1#!/usr/bin/perl -w
2#
3# CDDL HEADER START
4#
5# This file and its contents are supplied under the terms of the
6# Common Development and Distribution License ("CDDL"), version 1.0.
7# You may use this file only in accordance with the terms of version
8# 1.0 of the CDDL.
9#
10# A full copy of the text of the CDDL should have accompanied this
11# source.  A copy of the CDDL is also available via the Internet at
12# http://www.opensource.org/licenses/cddl1.txt
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22#
23# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26# Copyright 2004-2018 J. Schilling. All rights reserved.
27#
28# @(#)cstyle.pl	1.19 18/03/15 J. Schilling
29#
30#
31# @(#)cstyle 1.58 98/09/09 (from shannon)
32#ident	"@(#)cstyle.pl	1.8	08/07/11 SMI"
33#
34# cstyle - check for some common stylistic errors.
35#
36#	cstyle is a sort of "lint" for C coding style.
37#	It attempts to check for the style used in the
38#	kernel, sometimes known as "Bill Joy Normal Form".
39#
40#	There's a lot this can't check for, like proper indentation
41#	of code blocks.  There's also a lot more this could check for.
42#
43#	A note to the non perl literate:
44#
45#		perl regular expressions are pretty much like egrep
46#		regular expressions, with the following special symbols
47#
48#		\s	any space character
49#		\S	any non-space character
50#		\w	any "word" character [a-zA-Z0-9_]
51#		\W	any non-word character
52#		\d	a digit [0-9]
53#		\D	a non-digit
54#		\b	word boundary (between \w and \W)
55#		\B	non-word boundary
56#
57
58require 5.0;
59use IO::File;
60use Getopt::Std;
61use strict;
62
63my $usage =
64"usage: cstyle [-chpvCPbKB] [-o constructs] [-l #] file ...
65	-c	check continuation indentation inside functions
66	-h	perform heuristic checks that are sometimes wrong
67	-p	perform some of the more picky checks
68	-v	verbose
69	-C	don't check anything in header block comments
70	-P	check for use of non-POSIX types
71	-o constructs
72		allow a comma-seperated list of optional constructs:
73		    doxygen	allow doxygen-style block comments (/** /*!)
74		    splint	allow splint-style lint comments (/*@ ... @*/)
75	-l #	set maxline length (default is 80)
76	-b	do not check for blank after cpp #
77	-K	do not check for blank at /* */ comment bounds
78	-B	allow /*------- box comments
79";
80
81my %opts;
82
83if (!getopts("cho:pvCPl:bKB", \%opts)) {
84	print $usage;
85	exit 2;
86}
87
88my $check_continuation = $opts{'c'};
89my $heuristic = $opts{'h'};
90my $picky = $opts{'p'};
91my $verbose = $opts{'v'};
92my $ignore_hdr_comment = $opts{'C'};
93my $check_posix_types = $opts{'P'};
94my $maxlinelen = $opts{'l'};
95my $blank_after_cpp = $opts{'b'};
96my $Kommentar = $opts{'K'};
97my $Boxcomment = $opts{'B'};
98
99if (!$maxlinelen) {
100	$maxlinelen = 80;
101}
102# printf "linelen %d\n", $maxlinelen;
103
104# my $toolong = sprintf("line(len %d) > %d characters", length($eline), $maxlinelen);
105# printf "%s\n", $toolong;
106
107my $doxygen_comments = 0;
108my $splint_comments = 0;
109
110if (defined($opts{'o'})) {
111	for my $x (split /,/, $opts{'o'}) {
112		if ($x eq "doxygen") {
113			$doxygen_comments = 1;
114		} elsif ($x eq "splint") {
115			$splint_comments = 1;
116		} else {
117			print "cstyle: unrecognized construct \"$x\"\n";
118			print $usage;
119			exit 2;
120		}
121	}
122}
123
124my ($filename, $line, $prev);		# shared globals
125
126my $fmt;
127my $hdr_comment_start;
128
129if ($verbose) {
130	$fmt = "%s: %d: %s\n%s\n";
131} else {
132	$fmt = "%s: %d: %s\n";
133}
134
135if ($doxygen_comments) {
136	# doxygen comments look like "/*!" or "/**"; allow them.
137	$hdr_comment_start = qr/^\s*\/\*[\!\*]?$/;
138} else {
139	$hdr_comment_start = qr/^\s*\/\*$/;
140}
141
142# Note, following must be in single quotes so that \s and \w work right.
143my $typename = '(int|char|short|long|unsigned|float|double' .
144    '|\w+_t|struct\s+\w+|union\s+\w+|FILE)';
145
146# mapping of old types to POSIX compatible types
147my %old2posix = (
148	'unchar' => 'uchar_t',
149	'ushort' => 'ushort_t',
150	'uint' => 'uint_t',
151	'ulong' => 'ulong_t',
152	'u_int' => 'uint_t',
153	'u_short' => 'ushort_t',
154	'u_long' => 'ulong_t',
155	'u_char' => 'uchar_t',
156	'quad' => 'quad_t'
157);
158
159my $lint_re = qr/\/\*(?:
160	ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*|
161	CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|
162	FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*|
163	PROTOLIB[0-9]*|SCANFLIKE[0-9]*|CSTYLED.*?
164    )\*\//x;
165
166my $splint_re = qr/\/\*@.*?@\*\//x;
167
168my $warlock_re = qr/\/\*\s*(?:
169	VARIABLES\ PROTECTED\ BY|
170	MEMBERS\ PROTECTED\ BY|
171	ALL\ MEMBERS\ PROTECTED\ BY|
172	READ-ONLY\ VARIABLES:|
173	READ-ONLY\ MEMBERS:|
174	VARIABLES\ READABLE\ WITHOUT\ LOCK:|
175	MEMBERS\ READABLE\ WITHOUT\ LOCK:|
176	LOCKS\ COVERED\ BY|
177	LOCK\ UNNEEDED\ BECAUSE|
178	LOCK\ NEEDED:|
179	LOCK\ HELD\ ON\ ENTRY:|
180	READ\ LOCK\ HELD\ ON\ ENTRY:|
181	WRITE\ LOCK\ HELD\ ON\ ENTRY:|
182	LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:|
183	READ\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:|
184	WRITE\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:|
185	LOCK\ RELEASED\ AS\ SIDE\ EFFECT:|
186	LOCK\ UPGRADED\ AS\ SIDE\ EFFECT:|
187	LOCK\ DOWNGRADED\ AS\ SIDE\ EFFECT:|
188	FUNCTIONS\ CALLED\ THROUGH\ POINTER|
189	FUNCTIONS\ CALLED\ THROUGH\ MEMBER|
190	LOCK\ ORDER:
191    )/x;
192
193my $err_stat = 0;		# exit status
194
195if ($#ARGV >= 0) {
196	foreach my $arg (@ARGV) {
197		my $fh = new IO::File $arg, "r";
198		if (!defined($fh)) {
199			printf "%s: can not open\n", $arg;
200		} else {
201			&cstyle($arg, $fh);
202			close $fh;
203		}
204	}
205} else {
206	&cstyle("<stdin>", *STDIN);
207}
208exit $err_stat;
209
210my $no_errs = 0;		# set for CSTYLED-protected lines
211
212sub err($) {
213	my ($error) = @_;
214	unless ($no_errs) {
215		if ($verbose) {
216			printf $fmt, $filename, $., $error, $line;
217		} else {
218			printf $fmt, $filename, $., $error;
219		}
220		$err_stat = 1;
221	}
222}
223
224sub err_prefix($$) {
225	my ($prevline, $error) = @_;
226	my $out = $prevline."\n".$line;
227	unless ($no_errs) {
228		if ($verbose) {
229			printf $fmt, $filename, $., $error, $out;
230		} else {
231			printf $fmt, $filename, $., $error;
232		}
233		$err_stat = 1;
234	}
235}
236
237sub err_prev($) {
238	my ($error) = @_;
239	unless ($no_errs) {
240		if ($verbose) {
241			printf $fmt, $filename, $. - 1, $error, $prev;
242		} else {
243			printf $fmt, $filename, $. - 1, $error;
244		}
245		$err_stat = 1;
246	}
247}
248
249sub cstyle($$) {
250
251my ($fn, $filehandle) = @_;
252$filename = $fn;			# share it globally
253
254my $in_cpp = 0;
255my $next_in_cpp = 0;
256
257my $in_comment = 0;
258my $in_header_comment = 0;
259my $comment_done = 0;
260my $in_warlock_comment = 0;
261my $in_function = 0;
262my $in_function_header = 0;
263my $in_declaration = 0;
264my $note_level = 0;
265my $nextok = 0;
266my $nocheck = 0;
267
268my $in_string = 0;
269
270my ($okmsg, $comment_prefix);
271
272$line = '';
273$prev = '';
274reset_indent();
275
276line: while (<$filehandle>) {
277	if (eof) {
278		if (! /\n$/) {
279			err("newline not last character in file");
280		}
281	}
282	s/\r?\n$//;	# strip return and newline
283
284	# save the original line, then remove all text from within
285	# double or single quotes, we do not want to check such text.
286
287	$line = $_;
288
289	#
290	# C allows strings to be continued with a backslash at the end of
291	# the line.  We translate that into a quoted string on the previous
292	# line followed by an initial quote on the next line.
293	#
294	# (we assume that no-one will use backslash-continuation with character
295	# constants)
296	#
297	$_ = '"' . $_		if ($in_string && !$nocheck && !$in_comment);
298
299	#
300	# normal strings and characters
301	#
302	s/'([^\\']|\\[^xX0]|\\0[0-9]*|\\[xX][0-9a-fA-F]*)'/''/g;
303	s/"([^\\"]|\\.)*"/\"\"/g;
304
305	#
306	# detect string continuation
307	#
308	if ($nocheck || $in_comment) {
309		$in_string = 0;
310	} else {
311		#
312		# Now that all full strings are replaced with "", we check
313		# for unfinished strings continuing onto the next line.
314		#
315		$in_string =
316		    (s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ ||
317		    s/^("")*"([^\\"]|\\.)*\\$/""/);
318	}
319
320	#
321	# figure out if we are in a cpp directive
322	#
323	$in_cpp = $next_in_cpp || /^\s*#/;	# continued or started
324	$next_in_cpp = $in_cpp && /\\$/;	# only if continued
325
326	# strip off trailing backslashes, which appear in long macros
327	s/\s*\\$//;
328
329	# an /* END CSTYLED */ comment ends a no-check block.
330	if ($nocheck) {
331		if (/\/\* *END *CSTYLED *\*\//) {
332			$nocheck = 0;
333		} else {
334			reset_indent();
335			next line;
336		}
337	}
338
339	# a /*CSTYLED*/ comment indicates that the next line is ok.
340	if ($nextok) {
341		if ($okmsg) {
342			err($okmsg);
343		}
344		$nextok = 0;
345		$okmsg = 0;
346		if (/\/\* *CSTYLED.*\*\//) {
347			/^.*\/\* *CSTYLED *(.*) *\*\/.*$/;
348			$okmsg = $1;
349			$nextok = 1;
350		}
351		$no_errs = 1;
352	} elsif ($no_errs) {
353		$no_errs = 0;
354	}
355
356	# check length of line.
357	# first, a quick check to see if there is any chance of being too long.
358	if (($line =~ tr/\t/\t/) * 7 + length($line) > $maxlinelen) {
359		# yes, there is a chance.
360		# replace tabs with spaces and check again.
361		my $eline = $line;
362		1 while $eline =~
363		    s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
364		if (length($eline) > $maxlinelen) {
365			my $toolong = sprintf("line (len %3d) > %d characters",
366						length($eline), $maxlinelen);
367			err($toolong);
368		}
369	}
370
371	# ignore NOTE(...) annotations (assumes NOTE is on lines by itself).
372	if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE
373		s/[^()]//g;			  # eliminate all non-parens
374		$note_level += s/\(//g - length;  # update paren nest level
375		next;
376	}
377
378	# a /* BEGIN CSTYLED */ comment starts a no-check block.
379	if (/\/\* *BEGIN *CSTYLED *\*\//) {
380		$nocheck = 1;
381	}
382
383	# a /*CSTYLED*/ comment indicates that the next line is ok.
384	if (/\/\* *CSTYLED.*\*\//) {
385		/^.*\/\* *CSTYLED *(.*) *\*\/.*$/;
386		$okmsg = $1;
387		$nextok = 1;
388	}
389	if (/\/\/ *CSTYLED/) {
390		/^.*\/\/ *CSTYLED *(.*)$/;
391		$okmsg = $1;
392		$nextok = 1;
393	}
394
395	# universal checks; apply to everything
396	if (/\t +\t/) {
397		err("spaces between tabs");
398	}
399	if (/ \t+ /) {
400		err("tabs between spaces");
401	}
402	if (/\s$/) {
403		err("space or tab at end of line");
404	}
405	if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) {
406		err("comment preceded by non-blank");
407	}
408
409	# is this the beginning or ending of a function?
410	# (not if "struct foo\n{\n")
411	if (/^{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) {
412		$in_function = 1;
413		$in_declaration = 1;
414		$in_function_header = 0;
415		$prev = $line;
416		next line;
417	}
418	if (/^}\s*(\/\*.*\*\/\s*)*$/) {
419		if ($prev =~ /^\s*return\s*;/) {
420			err_prev("unneeded return at end of function");
421		}
422		$in_function = 0;
423		reset_indent();		# we don't check between functions
424		$prev = $line;
425		next line;
426	}
427	if (/^\w*\($/) {
428		$in_function_header = 1;
429	}
430
431	if ($in_warlock_comment && /\*\//) {
432		$in_warlock_comment = 0;
433		$prev = $line;
434		next line;
435	}
436
437	# a blank line terminates the declarations within a function.
438	# XXX - but still a problem in sub-blocks.
439	if ($in_declaration && /^$/) {
440		$in_declaration = 0;
441	}
442
443	if ($comment_done) {
444		$in_comment = 0;
445		$in_header_comment = 0;
446		$comment_done = 0;
447	}
448	# does this looks like the start of a block comment?
449	if (/$hdr_comment_start/) {
450		if (!/^\t*\/\*/) {
451			err("block comment not indented by tabs");
452		}
453		$in_comment = 1;
454		/^(\s*)\//;
455		$comment_prefix = $1;
456		if ($comment_prefix eq "") {
457			$in_header_comment = 1;
458		}
459		$prev = $line;
460		next line;
461	}
462	# are we still in the block comment?
463	if ($in_comment) {
464		if (/^$comment_prefix \*\/$/) {
465			$comment_done = 1;
466		} elsif (/\*\//) {
467			$comment_done = 1;
468			err("improper block comment close")
469			    unless ($ignore_hdr_comment && $in_header_comment);
470		} elsif (!/^$comment_prefix \*[ \t]/ &&
471		    !/^$comment_prefix \*$/) {
472			err("improper block comment")
473			    unless ($ignore_hdr_comment && $in_header_comment);
474		}
475	}
476
477	if ($in_header_comment && $ignore_hdr_comment) {
478		$prev = $line;
479		next line;
480	}
481
482	# check for errors that might occur in comments and in code.
483
484	# allow spaces to be used to draw pictures in header comments.
485	if (/[^ ]     / && !/".*     .*"/ && !$in_header_comment) {
486		err("spaces instead of tabs");
487	}
488	if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ &&
489	    (!/^    \w/ || $in_function != 0)) {
490		err("indent by spaces instead of tabs");
491	}
492	if (/^\t+ [^ \t\*]/ || /^\t+  \S/ || /^\t+   \S/) {
493		err("continuation line not indented by 4 spaces");
494	}
495	if (/$warlock_re/ && !/\*\//) {
496		$in_warlock_comment = 1;
497		$prev = $line;
498		next line;
499	}
500	if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) {
501		if (!$Boxcomment ||
502		    !/^\s*\/\*----------------------------------------------------------------------/) {
503			err("improper first line of block comment");
504		}
505	}
506
507	if ($in_comment) {	# still in comment, don't do further checks
508		$prev = $line;
509		next line;
510	}
511
512	if ((/[^(]\/\*\S/ || /^\/\*\S/) &&
513	    !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
514		if (!$Kommentar) {
515			err("missing blank after open comment");
516		}
517	}
518	if (/\S\*\/[^)]|\S\*\/$/ &&
519	    !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
520		if (!$Kommentar) {
521			err("missing blank before close comment");
522		}
523	}
524	# check for unterminated single line comments, but allow them when
525	# they are used to comment out the argument list of a function
526	# declaration.
527	if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) {
528		err("unterminated single line comment");
529	}
530
531	if (/^(#else|#endif|#include)(.*)$/) {
532		$prev = $line;
533		if ($picky) {
534			my $directive = $1;
535			my $clause = $2;
536			# Enforce ANSI rules for #else and #endif: no noncomment
537			# identifiers are allowed after #endif or #else.  Allow
538			# C++ comments since they seem to be a fact of life.
539			if ((($1 eq "#endif") || ($1 eq "#else")) &&
540			    ($clause ne "") &&
541			    (!($clause =~ /^\s+\/\*.*\*\/$/)) &&
542			    (!($clause =~ /^\s+\/\/.*$/))) {
543				err("non-comment text following " .
544				    "$directive (or malformed $directive " .
545				    "directive)");
546			}
547		}
548		next line;
549	}
550
551	if ($blank_after_cpp) {
552		if (/^#[ 	]*(else|endif|include)/) {
553			$prev = $line;
554			next line;
555		}
556	}
557
558	#
559	# delete any comments and check everything else.  Note that
560	# ".*?" is a non-greedy match, so that we don't get confused by
561	# multiple comments on the same line.
562	#
563	s/\/\*.*?\*\///g;
564
565	if (/\/\/\S/) {		# C++ comments
566		err("missing blank after start comment");
567	}
568
569	s/\/\/.*$//;		# C++ comments
570
571	# delete any trailing whitespace; we have already checked for that.
572	s/\s*$//;
573
574	# following checks do not apply to text in comments.
575
576	if (/[^<>\s][!<>=]=/ || /[^<>][!<>=]=[^\s,]/ ||
577	    (/[^->]>[^,=>\s]/ && !/[^->]>$/) ||
578	    (/[^<]<[^,=<\s]/ && !/[^<]<$/) ||
579	    /[^<\s]<[^<]/ || /[^->\s]>[^>]/) {
580		err("missing space around relational operator");
581	}
582	if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ ||
583	    (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) ||
584	    (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) {
585		# XXX - should only check this for C++ code
586		# XXX - there are probably other forms that should be allowed
587		if (!/\soperator=/) {
588			err("missing space around assignment operator");
589		}
590	}
591	if (/[,;]\S/ && !/\bfor \(;;\)/) {
592		err("comma or semicolon followed by non-blank");
593	}
594	# allow "for" statements to have empty "while" clauses
595	if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) {
596		err("comma or semicolon preceded by blank");
597	}
598	if (/^\s*(&&|\|\|)/) {
599		err("improper boolean continuation");
600	}
601	if (/\S   *(&&|\|\|)/ || /(&&|\|\|)   *\S/) {
602		err("more than one space around boolean operator");
603	}
604	if (/\b(for|if|while|switch|sizeof|return|case)\(/) {
605		err("missing space between keyword and paren");
606	}
607	if (/(\b(for|if|while|switch|return)\b.*){2,}/ && !/^#define/) {
608		# multiple "case" and "sizeof" allowed
609		err("more than one keyword on line");
610	}
611	if (/\b(for|if|while|switch|sizeof|return|case)\s\s+\(/ &&
612	    !/^#if\s+\(/) {
613		err("extra space between keyword and paren");
614	}
615	# try to detect "func (x)" but not "if (x)" or
616	# "#define foo (x)" or "int (*func)();"
617	if (/\w\s\(/) {
618		my $s = $_;
619		# strip off all keywords on the line
620		s/\b(for|if|while|switch|return|case|sizeof)\s\(/XXX(/g;
621		s/#elif\s\(/XXX(/g;
622		s/^#define\s+\w+\s+\(/XXX(/;
623		# do not match things like "void (*f)();"
624		# or "typedef void (func_t)();"
625		s/\w\s\(+\*/XXX(*/g;
626		s/\b($typename|void)\s+\(+/XXX(/og;
627		if (/\w\s\(/) {
628			err("extra space between function name and left paren");
629		}
630		$_ = $s;
631	}
632	# try to detect "int foo(x)", but not "extern int foo(x);"
633	# XXX - this still trips over too many legitimate things,
634	# like "int foo(x,\n\ty);"
635#		if (/^(\w+(\s|\*)+)+\w+\(/ && !/\)[;,](\s|)*$/ &&
636#		    !/^(extern|static)\b/) {
637#			err("return type of function not on separate line");
638#		}
639	# this is a close approximation
640	if (/^(\w+(\s|\*)+)+\w+\(.*\)(\s|)*$/ &&
641	    !/^(extern|static)\b.*\(/) {
642		#
643		# We unfortunately cannot flag a function implementation like
644		# extern int func()
645		# { ...
646		# as we need to permit a prototype "extern int func(..."
647		# where some of the parameters from the prototype are on a
648		# different line.
649		#
650		err("return type of function not on separate line");
651	}
652	if (/^#define /) {
653		err("#define followed by space instead of tab");
654	}
655	if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) {
656		err("unparenthesized return expression");
657	}
658	if (/\bsizeof\b/ && !/\bsizeof\s*\(.*\)/) {
659		err("unparenthesized sizeof expression");
660	}
661	if (/\(\s/) {
662		err("whitespace after left paren");
663	}
664	# allow "for" statements to have empty "continue" clauses
665	if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) {
666		err("whitespace before right paren");
667	}
668	if (/^\s*\(void\)[^ ]/) {
669		err("missing space after (void) cast");
670	}
671	if (/\S\{/ && !/\{\{/) {
672		err("missing space before left brace");
673	}
674	if ($in_function && /^\s+{/ &&
675	    ($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) {
676		err("left brace starting a line");
677	}
678	if (/}(else|while)/) {
679		err("missing space after right brace");
680	}
681	if (/}\s\s+(else|while)/) {
682		err("extra space after right brace");
683	}
684	if (/\b_VOID\b|\bVOID\b|\bSTATIC\b/) {
685		err("obsolete use of VOID or STATIC");
686	}
687	if (/\b$typename\*/o) {
688		err("missing space between type name and *");
689	}
690	if (/^\s+#/) {
691		err("preprocessor statement not in column 1");
692	}
693	if (/^#\s/) {
694		if (!$blank_after_cpp) {
695			err("blank after preprocessor #");
696		}
697	}
698	if (/!\s*(strcmp|strncmp|bcmp)\s*\(/) {
699		err("don't use boolean ! with comparison functions");
700	}
701
702	#
703	# We completely ignore, for purposes of indentation:
704	#  * lines outside of functions
705	#  * preprocessor lines
706	#
707	if ($check_continuation && $in_function && !$in_cpp) {
708		process_indent($_);
709	}
710	if ($picky) {
711		# try to detect spaces after casts, but allow (e.g.)
712		# "sizeof (int) + 1", "void (*funcptr)(int) = foo;", and
713		# "int foo(int) __NORETURN;"
714		if ((/^\($typename( \*+)?\)\s/o ||
715		    /\W\($typename( \*+)?\)\s/o) &&
716		    !/sizeof\s*\($typename( \*)?\)\s/o &&
717		    !/\($typename( \*+)?\)\s+=[^=]/o) {
718			err("space after cast");
719		}
720		if (/\b$typename\s*\*\s/o &&
721		    !/\b$typename\s*\*\s+const\b/o) {
722			err("unary * followed by space");
723		}
724	}
725	if ($check_posix_types) {
726		# try to detect old non-POSIX types.
727		# POSIX requires all non-standard typedefs to end in _t,
728		# but historically these have been used.
729		if (/\b(unchar|ushort|uint|ulong|u_int|u_short|u_long|u_char|quad)\b/) {
730			err("non-POSIX typedef $1 used: use $old2posix{$1} instead");
731		}
732	}
733	if ($heuristic) {
734		# cannot check this everywhere due to "struct {\n...\n} foo;"
735		if ($in_function && !$in_declaration &&
736		    /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ &&
737		    !/} (else|while)/ && !/}}/) {
738			err("possible bad text following right brace");
739		}
740		# cannot check this because sub-blocks in
741		# the middle of code are ok
742		if ($in_function && /^\s+{/) {
743			err("possible left brace starting a line");
744		}
745	}
746	if (/^\s*else\W/) {
747		if ($prev =~ /^\s*}$/) {
748			err_prefix($prev,
749			    "else and right brace should be on same line");
750		}
751	}
752	$prev = $line;
753}
754
755if ($prev eq "") {
756	err("last line in file is blank");
757}
758
759}
760
761#
762# Continuation-line checking
763#
764# The rest of this file contains the code for the continuation checking
765# engine.  It's a pretty simple state machine which tracks the expression
766# depth (unmatched '('s and '['s).
767#
768# Keep in mind that the argument to process_indent() has already been heavily
769# processed; all comments have been replaced by control-A, and the contents of
770# strings and character constants have been elided.
771#
772
773my $cont_in;		# currently inside of a continuation
774my $cont_off;		# skipping an initializer or definition
775my $cont_noerr;		# suppress cascading errors
776my $cont_start;		# the line being continued
777my $cont_base;		# the base indentation
778my $cont_first;		# this is the first line of a statement
779my $cont_multiseg;	# this continuation has multiple segments
780
781my $cont_special;	# this is a C statement (if, for, etc.)
782my $cont_macro;		# this is a macro
783my $cont_case;		# this is a multi-line case
784
785my @cont_paren;		# the stack of unmatched ( and [s we've seen
786
787sub
788reset_indent()
789{
790	$cont_in = 0;
791	$cont_off = 0;
792}
793
794sub
795delabel($)
796{
797	#
798	# replace labels with tabs.  Note that there may be multiple
799	# labels on a line.
800	#
801	local $_ = $_[0];
802
803	while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) {
804		my ($pre_tabs, $label, $rest) = ($1, $2, $3);
805		$_ = $pre_tabs;
806		while ($label =~ s/^([^\t]*)(\t+)//) {
807			$_ .= "\t" x (length($2) + length($1) / 8);
808		}
809		$_ .= ("\t" x (length($label) / 8)).$rest;
810	}
811
812	return ($_);
813}
814
815sub
816process_indent($)
817{
818	require strict;
819	local $_ = $_[0];			# preserve the global $_
820
821	s///g;	# No comments
822	s/\s+$//;	# Strip trailing whitespace
823
824	return			if (/^$/);	# skip empty lines
825
826	# regexps used below; keywords taking (), macros, and continued cases
827	my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b';
828	my $macro = '[A-Z_][A-Z_0-9]*\(';
829	my $case = 'case\b[^:]*$';
830
831	# skip over enumerations, array definitions, initializers, etc.
832	if ($cont_off <= 0 && !/^\s*$special/ &&
833	    (/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*)){/ ||
834	    (/^\s*{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) {
835		$cont_in = 0;
836		$cont_off = tr/{/{/ - tr/}/}/;
837		return;
838	}
839	if ($cont_off) {
840		$cont_off += tr/{/{/ - tr/}/}/;
841		return;
842	}
843
844	if (!$cont_in) {
845		$cont_start = $line;
846
847		if (/^\t* /) {
848			err("non-continuation indented 4 spaces");
849			$cont_noerr = 1;		# stop reporting
850		}
851		$_ = delabel($_);	# replace labels with tabs
852
853		# check if the statement is complete
854		return		if (/^\s*\}?$/);
855		return		if (/^\s*\}?\s*else\s*\{?$/);
856		return		if (/^\s*do\s*\{?$/);
857		return		if (/{$/);
858		return		if (/}[,;]?$/);
859
860		# Allow macros on their own lines
861		return		if (/^\s*[A-Z_][A-Z_0-9]*$/);
862
863		# cases we don't deal with, generally non-kosher
864		if (/{/) {
865			err("stuff after {");
866			return;
867		}
868
869		# Get the base line, and set up the state machine
870		/^(\t*)/;
871		$cont_base = $1;
872		$cont_in = 1;
873		@cont_paren = ();
874		$cont_first = 1;
875		$cont_multiseg = 0;
876
877		# certain things need special processing
878		$cont_special = /^\s*$special/? 1 : 0;
879		$cont_macro = /^\s*$macro/? 1 : 0;
880		$cont_case = /^\s*$case/? 1 : 0;
881	} else {
882		$cont_first = 0;
883
884		# Strings may be pulled back to an earlier (half-)tabstop
885		unless ($cont_noerr || /^$cont_base    / ||
886		    (/^\t*(?:    )?(?:gettext\()?\"/ && !/^$cont_base\t/)) {
887			err_prefix($cont_start,
888			    "continuation should be indented 4 spaces");
889		}
890	}
891
892	my $rest = $_;			# keeps the remainder of the line
893
894	#
895	# The split matches 0 characters, so that each 'special' character
896	# is processed separately.  Parens and brackets are pushed and
897	# popped off the @cont_paren stack.  For normal processing, we wait
898	# until a ; or { terminates the statement.  "special" processing
899	# (if/for/while/switch) is allowed to stop when the stack empties,
900	# as is macro processing.  Case statements are terminated with a :
901	# and an empty paren stack.
902	#
903	foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) {
904		next		if (length($_) == 0);
905
906		# rest contains the remainder of the line
907		my $rxp = "[^\Q$_\E]*\Q$_\E";
908		$rest =~ s/^$rxp//;
909
910		if (/\(/ || /\[/) {
911			push @cont_paren, $_;
912		} elsif (/\)/ || /\]/) {
913			my $cur = $_;
914			tr/\)\]/\(\[/;
915
916			my $old = (pop @cont_paren);
917			if (!defined($old)) {
918				err("unexpected '$cur'");
919				$cont_in = 0;
920				last;
921			} elsif ($old ne $_) {
922				err("'$cur' mismatched with '$old'");
923				$cont_in = 0;
924				last;
925			}
926
927			#
928			# If the stack is now empty, do special processing
929			# for if/for/while/switch and macro statements.
930			#
931			next		if (@cont_paren != 0);
932			if ($cont_special) {
933				if ($rest =~ /^\s*{?$/) {
934					$cont_in = 0;
935					last;
936				}
937				if ($rest =~ /^\s*;$/) {
938					err("empty if/for/while body ".
939					    "not on its own line");
940					$cont_in = 0;
941					last;
942				}
943				if (!$cont_first && $cont_multiseg == 1) {
944					err_prefix($cont_start,
945					    "multiple statements continued ".
946					    "over multiple lines");
947					$cont_multiseg = 2;
948				} elsif ($cont_multiseg == 0) {
949					$cont_multiseg = 1;
950				}
951				# We've finished this section, start
952				# processing the next.
953				goto section_ended;
954			}
955			if ($cont_macro) {
956				if ($rest =~ /^$/) {
957					$cont_in = 0;
958					last;
959				}
960			}
961		} elsif (/\;/) {
962			if ($cont_case) {
963				err("unexpected ;");
964			} elsif (!$cont_special) {
965				err("unexpected ;")	if (@cont_paren != 0);
966				if (!$cont_first && $cont_multiseg == 1) {
967					err_prefix($cont_start,
968					    "multiple statements continued ".
969					    "over multiple lines");
970					$cont_multiseg = 2;
971				} elsif ($cont_multiseg == 0) {
972					$cont_multiseg = 1;
973				}
974				if ($rest =~ /^$/) {
975					$cont_in = 0;
976					last;
977				}
978				if ($rest =~ /^\s*special/) {
979					err("if/for/while/switch not started ".
980					    "on its own line");
981				}
982				goto section_ended;
983			}
984		} elsif (/\{/) {
985			err("{ while in parens/brackets") if (@cont_paren != 0);
986			err("stuff after {")		if ($rest =~ /[^\s}]/);
987			$cont_in = 0;
988			last;
989		} elsif (/\}/) {
990			err("} while in parens/brackets") if (@cont_paren != 0);
991			if (!$cont_special && $rest !~ /^\s*(while|else)\b/) {
992				if ($rest =~ /^$/) {
993					err("unexpected }");
994				} else {
995					err("stuff after }");
996				}
997				$cont_in = 0;
998				last;
999			}
1000		} elsif (/\:/ && $cont_case && @cont_paren == 0) {
1001			err("stuff after multi-line case") if ($rest !~ /$^/);
1002			$cont_in = 0;
1003			last;
1004		}
1005		next;
1006section_ended:
1007		# End of a statement or if/while/for loop.  Reset
1008		# cont_special and cont_macro based on the rest of the
1009		# line.
1010		$cont_special = ($rest =~ /^\s*$special/)? 1 : 0;
1011		$cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0;
1012		$cont_case = 0;
1013		next;
1014	}
1015	$cont_noerr = 0			if (!$cont_in);
1016}
1017