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