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