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