aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@shadowen.org>2007-06-01 03:46:48 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-06-01 11:18:28 -0400
commit0a920b5b666d0be8141bd1ce620fffa7de96b81b (patch)
tree9de51d4073895f72201040d4c7913dcc83b9ed4e /scripts
parentbc913b1899ce0c15ec496d1aa121c36785e0528a (diff)
add a trivial patch style checker
We are seeing increasing levels of minor patch style violations in submissions to the mailing lists as well as making it into the tree. These detract from the quality of the submission and cause unnessary work for reviewers. As a first step package up the current state of the patch style checker and include it in the kernel tree. Add instructions suggesting running it on submissions. This adds version v0.01 of the checkpatch.pl script. Signed-off-by: Andy Whitcroft <apw@shadowen.org> Signed-off-by: Joel Schopp <jschopp@austin.ibm.com> Cc: Randy Dunlap <rdunlap@xenotime.net> Cc: Dave Jones <davej@codemonkey.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/checkpatch.pl595
1 files changed, 595 insertions, 0 deletions
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
new file mode 100644
index 000000000000..e216d49624b7
--- /dev/null
+++ b/scripts/checkpatch.pl
@@ -0,0 +1,595 @@
1#!/usr/bin/perl -w
2# (c) 2001, Dave Jones. <davej@codemonkey.org.uk> (the file handling bit)
3# (c) 2005, Joel Scohpp <jschopp@austin.ibm.com> (the ugly bit)
4# (c) 2007, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite, etc)
5# Licensed under the terms of the GNU GPL License version 2
6
7use strict;
8
9my $P = $0;
10
11my $V = '0.01';
12
13use Getopt::Long qw(:config no_auto_abbrev);
14
15my $quiet = 0;
16my $tree = 1;
17my $chk_signoff = 1;
18my $chk_patch = 1;
19GetOptions(
20 'q|quiet' => \$quiet,
21 'tree!' => \$tree,
22 'signoff!' => \$chk_signoff,
23 'patch!' => \$chk_patch,
24) or exit;
25
26my $exit = 0;
27
28if ($#ARGV < 0) {
29 print "usage: patchstylecheckemail.pl [options] patchfile\n";
30 print "version: $V\n";
31 print "options: -q => quiet\n";
32 print " --no-tree => run without a kernel tree\n";
33 exit(1);
34}
35
36if ($tree && !top_of_kernel_tree()) {
37 print "Must be run from the top-level dir. of a kernel tree\n";
38 exit(2);
39}
40
41my @deprecated = ();
42my $removal = 'Documentation/feature-removal-schedule.txt';
43if ($tree && -f $removal) {
44 open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n";
45 while (<REMOVE>) {
46 if (/^Files:\s+(.*\S)/) {
47 for my $file (split(/[, ]+/, $1)) {
48 if ($file =~ m@include/(.*)@) {
49 push(@deprecated, $1);
50 }
51 }
52 }
53 }
54}
55
56my @lines = ();
57while (<>) {
58 chomp;
59 push(@lines, $_);
60 if (eof(ARGV)) {
61 if (!process($ARGV, @lines)) {
62 $exit = 1;
63 }
64 @lines = ();
65 }
66}
67
68exit($exit);
69
70sub top_of_kernel_tree {
71 if ((-f "COPYING") && (-f "CREDITS") && (-f "Kbuild") &&
72 (-f "MAINTAINERS") && (-f "Makefile") && (-f "README") &&
73 (-d "Documentation") && (-d "arch") && (-d "include") &&
74 (-d "drivers") && (-d "fs") && (-d "init") && (-d "ipc") &&
75 (-d "kernel") && (-d "lib") && (-d "scripts")) {
76 return 1;
77 }
78 return 0;
79}
80
81sub expand_tabs {
82 my ($str) = @_;
83
84 my $res = '';
85 my $n = 0;
86 for my $c (split(//, $str)) {
87 if ($c eq "\t") {
88 $res .= ' ';
89 $n++;
90 for (; ($n % 8) != 0; $n++) {
91 $res .= ' ';
92 }
93 next;
94 }
95 $res .= $c;
96 $n++;
97 }
98
99 return $res;
100}
101
102sub cat_vet {
103 my ($vet) = @_;
104
105 $vet =~ s/\t/^I/;
106 $vet =~ s/$/\$/;
107
108 return $vet;
109}
110
111sub process {
112 my $filename = shift;
113 my @lines = @_;
114
115 my $linenr=0;
116 my $prevline="";
117 my $stashline="";
118
119 my $lineforcounting='';
120 my $indent;
121 my $previndent=0;
122 my $stashindent=0;
123
124 my $clean = 1;
125 my $signoff = 0;
126 my $is_patch = 0;
127
128 # Trace the real file/line as we go.
129 my $realfile = '';
130 my $realline = 0;
131 my $realcnt = 0;
132 my $here = '';
133 my $in_comment = 0;
134 my $first_line = 0;
135
136 foreach my $line (@lines) {
137 $linenr++;
138
139#extract the filename as it passes
140 if ($line=~/^\+\+\+\s+(\S+)/) {
141 $realfile=$1;
142 $in_comment = 0;
143 next;
144 }
145#extract the line range in the file after the patch is applied
146 if ($line=~/^\@\@ -\d+,\d+ \+(\d+)(,(\d+))? \@\@/) {
147 $is_patch = 1;
148 $first_line = 1;
149 $in_comment = 0;
150 $realline=$1-1;
151 if (defined $2) {
152 $realcnt=$3+1;
153 } else {
154 $realcnt=1+1;
155 }
156 next;
157 }
158
159#track the line number as we move through the hunk
160 if ($line=~/^[ \+]/) {
161 $realline++;
162 $realcnt-- if ($realcnt != 0);
163
164 # track any sort of multi-line comment. Obviously if
165 # the added text or context do not include the whole
166 # comment we will not see it. Such is life.
167 #
168 # Guestimate if this is a continuing comment. If this
169 # is the start of a diff block and this line starts
170 # ' *' then it is very likely a comment.
171 if ($first_line and $line =~ m@^.\s*\*@) {
172 $in_comment = 1;
173 }
174 if ($line =~ m@/\*@) {
175 $in_comment = 1;
176 }
177 if ($line =~ m@\*/@) {
178 $in_comment = 0;
179 }
180
181 $lineforcounting = $line;
182 $lineforcounting =~ s/^\+//;
183 $lineforcounting = expand_tabs($lineforcounting);
184
185 my ($white) = ($lineforcounting =~ /^(\s*)/);
186 $indent = length($white);
187
188 # Track the previous line.
189 ($prevline, $stashline) = ($stashline, $line);
190 ($previndent, $stashindent) = ($stashindent, $indent);
191 $first_line = 0;
192 }
193
194#make up the handle for any error we report on this line
195 $here = "PATCH: $ARGV:$linenr:";
196 $here .= "\nFILE: $realfile:$realline:" if ($realcnt != 0);
197
198 my $herecurr = "$here\n$line\n\n";
199 my $hereprev = "$here\n$prevline\n$line\n\n";
200
201#check the patch for a signoff:
202 if ($line =~ /^\s*Signed-off-by:\s/) {
203 $signoff++;
204
205 } elsif ($line =~ /^\s*signed-off-by:/i) {
206 if (!($line =~ /^\s*Signed-off-by:/)) {
207 print "use Signed-off-by:\n";
208 print "$herecurr";
209 $clean = 0;
210 }
211 if ($line =~ /^\s*signed-off-by:\S/i) {
212 print "need space after Signed-off-by:\n";
213 print "$herecurr";
214 $clean = 0;
215 }
216 }
217
218#ignore lines not being added
219 if ($line=~/^[^\+]/) {next;}
220
221# check we are in a valid source file *.[hcsS] if not then ignore this hunk
222 next if ($realfile !~ /\.[hcsS]$/);
223
224#trailing whitespace
225 if ($line=~/\S\s+$/) {
226 my $herevet = "$here\n" . cat_vet($line) . "\n\n";
227 print "trailing whitespace\n";
228 print "$herevet";
229 $clean = 0;
230 }
231#80 column limit
232 if (!($prevline=~/\/\*\*/) && length($lineforcounting) > 80) {
233 print "line over 80 characters\n";
234 print "$herecurr";
235 $clean = 0;
236 }
237
238# check we are in a valid source file *.[hc] if not then ignore this hunk
239 next if ($realfile !~ /\.[hc]$/);
240
241# at the beginning of a line any tabs must come first and anything
242# more than 8 must use tabs.
243 if ($line=~/^\+\s* \t\s*\S/ or $line=~/^\+\s* \s*/) {
244 my $herevet = "$here\n" . cat_vet($line) . "\n\n";
245 print "use tabs not spaces\n";
246 print "$herevet";
247 $clean = 0;
248 }
249
250 #
251 # The rest of our checks refer specifically to C style
252 # only apply those _outside_ comments.
253 #
254 next if ($in_comment);
255
256# no C99 // comments
257 if ($line =~ m@//@ and !($line =~ m@\".*//.*\"@)) {
258 print "do not use C99 // comments\n";
259 print "$herecurr";
260 $clean = 0;
261 }
262
263 # Remove comments from the line before processing.
264 $line =~ s@/\*.*\*/@@g;
265 $line =~ s@/\*.*@@;
266 $line =~ s@.*\*/@@;
267 $line =~ s@//.*@@;
268
269#EXPORT_SYMBOL should immediately follow its function closing }.
270 if (($line =~ /EXPORT_SYMBOL.*\(.*\)/) ||
271 ($line =~ /EXPORT_UNUSED_SYMBOL.*\(.*\)/)) {
272 if (($prevline !~ /^}/) &&
273 ($prevline !~ /^\+}/) &&
274 ($prevline !~ /^ }/)) {
275 print "EXPORT_SYMBOL(func); should immediately follow its function\n";
276 print "$herecurr";
277 $clean = 0;
278 }
279 }
280
281 # check for static initialisers.
282 if ($line=~/\s*static\s.*=\s+(0|NULL);/) {
283 print "do not initialise statics to 0 or NULL\n";
284 print "$herecurr";
285 $clean = 0;
286 }
287
288 # check for new typedefs.
289 if ($line=~/\s*typedef\s/) {
290 print "do not add new typedefs\n";
291 print "$herecurr";
292 $clean = 0;
293 }
294
295# * goes on variable not on type
296 if ($line=~/[A-Za-z\d_]+\* [A-Za-z\d_]+/) {
297 print "\"foo* bar\" should be \"foo *bar\"\n";
298 print "$herecurr";
299 $clean = 0;
300 }
301
302# # no BUG() or BUG_ON()
303# if ($line =~ /\b(BUG|BUG_ON)\b/) {
304# print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
305# print "$herecurr";
306# $clean = 0;
307# }
308
309# printk should use KERN_* levels
310 if ($line =~ /\bprintk\((?!KERN_)/) {
311 print "printk() should include KERN_ facility level\n";
312 print "$herecurr";
313 $clean = 0;
314 }
315
316#function brace can't be on same line, except for #defines of do while, or if closed on same line
317 if (($line=~/[A-Za-z\d_]+\**\s+\**[A-Za-z\d_]+\(.*\).* {/) and
318 !($line=~/\#define.*do\s{/) and !($line=~/}/)) {
319 print "braces following function declarations go on the next line\n";
320 print "$herecurr";
321 $clean = 0;
322 }
323 my $opline = $line;
324 $opline =~ s/^.//;
325 if (!($line=~/\#\s*include/)) {
326 # Check operator spacing.
327 my @elements = split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/, $opline);
328 for (my $n = 0; $n < $#elements; $n += 2) {
329 # $wN says we have white-space before or after
330 # $sN says we have a separator before or after
331 # $oN says we have another operator before or after
332 my $w1 = $elements[$n] =~ /\s$/;
333 my $s1 = $elements[$n] =~ /(\[|\(|\s)$/;
334 my $o1 = $elements[$n] eq '';
335 my $op = $elements[$n + 1];
336 my $w2 = 1;
337 my $s2 = 1;
338 my $o2 = 0;
339 # If we have something after the operator handle it.
340 if (defined $elements[$n + 2]) {
341 $w2 = $elements[$n + 2] =~ /^\s/;
342 $s2 = $elements[$n + 2] =~ /^(\s|\)|\]|;)/;
343 $o2 = $elements[$n + 2] eq '';
344 }
345
346 # Generate the context.
347 my $at = "here: ";
348 for (my $m = $n; $m >= 0; $m--) {
349 if ($elements[$m] ne '') {
350 $at .= $elements[$m];
351 last;
352 }
353 }
354 $at .= $op;
355 for (my $m = $n + 2; defined $elements[$m]; $m++) {
356 if ($elements[$m] ne '') {
357 $at .= $elements[$m];
358 last;
359 }
360 }
361
362 ##print "<$s1:$op:$s2> <$elements[$n]:$elements[$n + 1]:$elements[$n + 2]>\n";
363 # Skip things apparently in quotes.
364 next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
365
366 # We need ; as an operator. // is a comment.
367 if ($op eq ';' or $op eq '//') {
368
369 # -> should have no spaces
370 } elsif ($op eq '->') {
371 if ($s1 or $s2) {
372 print "no spaces around that '$op' $at\n";
373 print "$herecurr";
374 $clean = 0;
375 }
376
377 # , must have a space on the right.
378 } elsif ($op eq ',') {
379 if (!$s2) {
380 print "need space after that '$op' $at\n";
381 print "$herecurr";
382 $clean = 0;
383 }
384
385 # unary ! and unary ~ are allowed no space on the right
386 } elsif ($op eq '!' or $op eq '~') {
387 if (!$s1 && !$o1) {
388 print "need space before that '$op' $at\n";
389 print "$herecurr";
390 $clean = 0;
391 }
392 if ($s2) {
393 print "no space after that '$op' $at\n";
394 print "$herecurr";
395 $clean = 0;
396 }
397
398 # unary ++ and unary -- are allowed no space on one side.
399 } elsif ($op eq '++' or $op eq '--') {
400 if (($s1 && $s2) || ((!$s1 && !$o1) && (!$s2 && !$o2))) {
401 print "need space one side of that '$op' $at\n";
402 print "$herecurr";
403 $clean = 0;
404 }
405
406 # & is both unary and binary
407 # unary:
408 # a &b
409 # binary (consistent spacing):
410 # a&b OK
411 # a & b OK
412 #
413 # boiling down to: if there is a space on the right then there
414 # should be one on the left.
415 #
416 # - is the same
417 #
418 # * is the same only adding:
419 # type:
420 # (foo *)
421 # (foo **)
422 #
423 } elsif ($op eq '&' or $op eq '-' or $op eq '*') {
424 if ($w2 and !$w1) {
425 print "need space before that '$op' $at\n";
426 print "$herecurr";
427 $clean = 0;
428 }
429
430 # << and >> may either have or not have spaces both sides
431 } elsif ($op eq '<<' or $op eq '>>' or $op eq '+' or $op eq '/' or
432 $op eq '^' or $op eq '|')
433 {
434 if ($s1 != $s2) {
435 print "need consistent spacing around '$op' $at\n";
436 print "$herecurr";
437 $clean = 0;
438 }
439
440 # All the others need spaces both sides.
441 } elsif (!$s1 or !$s2) {
442 print "need spaces around that '$op' $at\n";
443 print "$herecurr";
444 $clean = 0;
445 }
446 }
447 }
448
449#need space before brace following if, while, etc
450 if ($line=~/\(.*\){/) {
451 print "need a space before the brace\n";
452 print "$herecurr";
453 $clean = 0;
454 }
455
456#goto labels aren't indented, allow a single space however
457 if ($line=~/^.\s+[A-Za-z\d_]+:/ and
458 !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
459 print "labels should not be indented\n";
460 print "$herecurr";
461 $clean = 0;
462 }
463
464# Need a space before open parenthesis after if, while etc
465 if ($line=~/(if|while|for|switch)\(/) {
466 print "need a space before the open parenthesis\n";
467 print "$herecurr";
468 $clean = 0;
469 }
470
471# Check for illegal assignment in if conditional.
472 if ($line=~/(if|while)\s*\(.*[^<>!=]=[^=].*\)/) {
473 print "do not use assignment in if condition\n";
474 print "$herecurr";
475 $clean = 0;
476 }
477
478 # Check for }<nl>else {, these must be at the same
479 # indent level to be relevant to each other.
480 if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
481 $previndent == $indent) {
482 print "else should follow close brace\n";
483 print "$hereprev";
484 $clean = 0;
485 }
486
487 # Check for switch () {<nl>case, these must be at the
488 # same indent. We will only catch the first one, as our
489 # context is very small but people tend to be consistent
490 # so we will catch them out more often than not.
491 if ($prevline=~/\s*switch\s*\(.*\)/ and $line=~/\s*case\s+/
492 and $previndent != $indent) {
493 print "switch and case should be at the same indent\n";
494 print "$hereprev";
495 $clean = 0;
496 }
497
498#studly caps, commented out until figure out how to distinguish between use of existing and adding new
499# if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
500# print "No studly caps, use _\n";
501# print "$herecurr";
502# $clean = 0;
503# }
504
505#no spaces allowed after \ in define
506 if ($line=~/\#define.*\\\s$/) {
507 print("Whitepspace after \\ makes next lines useless\n");
508 print "$herecurr";
509 $clean = 0;
510 }
511
512#warn if <asm/foo.h> is #included and <linux/foo.h> is available.
513 if ($tree && $line =~ qr|\s*\#\s*include\s*\<asm\/(.*)\.h\>|) {
514 my $checkfile = "include/linux/$1.h";
515 if (-f $checkfile) {
516 print "Use #include <linux/$1.h> instead of <asm/$1.h>\n";
517 print $herecurr;
518 $clean = 0;
519 }
520 }
521
522#if/while/etc brace do not go on next line, unless #defining a do while loop, or if that brace on the next line is for something else
523 if ($prevline=~/(if|while|for|switch)\s*\(/) {
524 my @opened = $prevline=~/\(/g;
525 my @closed = $prevline=~/\)/g;
526 my $nr_line = $linenr;
527 my $remaining = $realcnt;
528 my $next_line = $line;
529 my $extra_lines = 0;
530 my $display_segment = $prevline;
531
532 while ($remaining > 0 && scalar @opened > scalar @closed) {
533 $prevline .= $next_line;
534 $display_segment .= "\n" . $next_line;
535 $next_line = $lines[$nr_line];
536 $nr_line++;
537 $remaining--;
538
539 @opened = $prevline=~/\(/g;
540 @closed = $prevline=~/\)/g;
541 }
542
543 if (($prevline=~/(if|while|for|switch)\s*\(.*\)\s*$/) and ($next_line=~/{/) and
544 !($next_line=~/(if|while|for)/) and !($next_line=~/\#define.*do.*while/)) {
545 print "That { should be on the previous line\n";
546 print "$display_segment\n$next_line\n\n";
547 $clean = 0;
548 }
549 }
550
551#multiline macros should be enclosed in a do while loop
552 if (($prevline=~/\#define.*\\/) and !($prevline=~/do\s+{/) and
553 !($prevline=~/\(\{/) and ($line=~/;\s*\\/) and
554 !($line=~/do.*{/) and !($line=~/\(\{/)) {
555 print "Macros with multiple statements should be enclosed in a do - while loop\n";
556 print "$hereprev";
557 $clean = 0;
558 }
559
560# don't include deprecated include files
561 for my $inc (@deprecated) {
562 if ($line =~ m@\#\s*include\s*\<$inc>@) {
563 print "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n";
564 print "$herecurr";
565 $clean = 0;
566 }
567 }
568
569# don't use kernel_thread()
570 if ($line =~ /\bkernel_thread\b/) {
571 print "Don't use kernel_thread(), use kthread(): see Documentation/feature-removal-schedule.txt\n";
572 print "$herecurr";
573 $clean = 0;
574 }
575 }
576
577 if ($chk_patch && !$is_patch) {
578 $clean = 0;
579 print "Does not appear to be a unified-diff format patch\n";
580 }
581 if ($is_patch && $chk_signoff && $signoff == 0) {
582 $clean = 0;
583 print "Missing Signed-off-by: line(s)\n";
584 }
585
586 if ($clean == 1 && $quiet == 0) {
587 print "Your patch has no obvious style problems and is ready for submission.\n"
588 }
589 if ($clean == 0 && $quiet == 0) {
590 print "Your patch has style problems, please review. If any of these errors\n";
591 print "are false positives report them to the maintainer, see\n";
592 print "CHECKPATCH in MAINTAINERS.\n";
593 }
594 return $clean;
595}