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