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