2007-06-01 11:46:48 +04:00
#!/usr/bin/perl -w
2010-01-13 00:59:52 +03:00
# (c) 2001, Dave Jones. (the file handling bit)
2007-06-09 00:47:06 +04:00
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
2009-01-07 01:41:23 +03:00
# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
2010-10-27 01:23:17 +04:00
# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
2007-06-01 11:46:48 +04:00
# Licensed under the terms of the GNU GPL License version 2
use strict ;
my $ P = $ 0 ;
2007-06-09 00:47:06 +04:00
$ P =~ s@.*/@@g ;
2007-06-01 11:46:48 +04:00
2011-07-26 04:13:25 +04:00
my $ V = '0.32' ;
2007-06-01 11:46:48 +04:00
use Getopt::Long qw( :config no_auto_abbrev ) ;
my $ quiet = 0 ;
my $ tree = 1 ;
my $ chk_signoff = 1 ;
my $ chk_patch = 1 ;
2008-03-29 00:15:58 +03:00
my $ tst_only ;
2007-10-18 14:05:08 +04:00
my $ emacs = 0 ;
2007-11-29 03:21:06 +03:00
my $ terse = 0 ;
2007-10-18 14:05:08 +04:00
my $ file = 0 ;
my $ check = 0 ;
2007-11-29 03:21:06 +03:00
my $ summary = 1 ;
my $ mailback = 0 ;
2008-02-08 15:22:03 +03:00
my $ summary_file = 0 ;
2011-07-26 04:13:25 +04:00
my $ show_types = 0 ;
2007-10-18 14:05:08 +04:00
my $ root ;
2008-02-08 15:20:54 +03:00
my % debug ;
2011-07-26 04:13:25 +04:00
my % ignore_type = ( ) ;
my @ ignore = ( ) ;
2009-09-22 04:04:37 +04:00
my $ help = 0 ;
2011-07-26 04:13:25 +04:00
my $ configuration_file = ".checkpatch.conf" ;
2012-12-18 04:01:54 +04:00
my $ max_line_length = 80 ;
2009-09-22 04:04:37 +04:00
sub help {
my ( $ exitcode ) = @ _ ;
print << "EOM" ;
Usage: $ P [ OPTION ] ... [ FILE ] ...
Version: $ V
Options:
- q , - - quiet quiet
- - no - tree run without a kernel tree
- - no - signoff do not check for 'Signed-off-by' line
- - patch treat FILE as patchfile ( default )
- - emacs emacs compile window format
- - terse one line per report
- f , - - file treat FILE as regular source file
- - subjective , - - strict enable more subjective tests
2011-07-26 04:13:25 +04:00
- - ignore TYPE ( , TYPE2 ... ) ignore various comma separated message types
2012-12-18 04:01:54 +04:00
- - max - line - length = n set the maximum line length , if exceeded , warn
2011-07-26 04:13:25 +04:00
- - show - types show the message "types" in the output
2009-09-22 04:04:37 +04:00
- - root = PATH PATH to the kernel tree root
- - no - summary suppress the per - file summary
- - mailback only produce a report in case of warnings / errors
- - summary - file include the filename in summary
- - debug KEY = [ 0 | 1 ] turn on / off debugging of KEY , where KEY is one of
'values' , 'possible' , 'type' , and 'attr' ( default
is all off )
- - test - only = WORD report only warnings / errors containing WORD
literally
- h , - - help , - - version display this help and exit
When FILE is - read standard input .
EOM
exit ( $ exitcode ) ;
}
2011-07-26 04:13:25 +04:00
my $ conf = which_conf ( $ configuration_file ) ;
if ( - f $ conf ) {
my @ conf_args ;
open ( my $ conffile , '<' , "$conf" )
or warn "$P: Can't find a readable $configuration_file file $!\n" ;
while ( <$conffile> ) {
my $ line = $ _ ;
$ line =~ s/\s*\n?$//g ;
$ line =~ s/^\s*//g ;
$ line =~ s/\s+/ /g ;
next if ( $ line =~ m/^\s*#/ ) ;
next if ( $ line =~ m/^\s*$/ ) ;
my @ words = split ( " " , $ line ) ;
foreach my $ word ( @ words ) {
last if ( $ word =~ m/^#/ ) ;
push ( @ conf_args , $ word ) ;
}
}
close ( $ conffile ) ;
unshift ( @ ARGV , @ conf_args ) if @ conf_args ;
}
2007-06-01 11:46:48 +04:00
GetOptions (
2007-10-18 14:05:08 +04:00
'q|quiet+' = > \ $ quiet ,
2007-06-01 11:46:48 +04:00
'tree!' = > \ $ tree ,
'signoff!' = > \ $ chk_signoff ,
'patch!' = > \ $ chk_patch ,
2007-10-18 14:05:08 +04:00
'emacs!' = > \ $ emacs ,
2007-11-29 03:21:06 +03:00
'terse!' = > \ $ terse ,
2009-09-22 04:04:37 +04:00
'f|file!' = > \ $ file ,
2007-10-18 14:05:08 +04:00
'subjective!' = > \ $ check ,
'strict!' = > \ $ check ,
2011-07-26 04:13:25 +04:00
'ignore=s' = > \ @ ignore ,
'show-types!' = > \ $ show_types ,
2012-12-18 04:01:54 +04:00
'max-line-length=i' = > \ $ max_line_length ,
2007-10-18 14:05:08 +04:00
'root=s' = > \ $ root ,
2007-11-29 03:21:06 +03:00
'summary!' = > \ $ summary ,
'mailback!' = > \ $ mailback ,
2008-02-08 15:22:03 +03:00
'summary-file!' = > \ $ summary_file ,
2008-02-08 15:20:54 +03:00
'debug=s' = > \ % debug ,
2008-03-29 00:15:58 +03:00
'test-only=s' = > \ $ tst_only ,
2009-09-22 04:04:37 +04:00
'h|help' = > \ $ help ,
'version' = > \ $ help
) or help ( 1 ) ;
help ( 0 ) if ( $ help ) ;
2007-06-01 11:46:48 +04:00
my $ exit = 0 ;
if ( $# ARGV < 0 ) {
2009-09-22 04:04:37 +04:00
print "$P: no input files\n" ;
2007-06-01 11:46:48 +04:00
exit ( 1 ) ;
}
2011-07-26 04:13:25 +04:00
@ ignore = split ( /,/ , join ( ',' , @ ignore ) ) ;
foreach my $ word ( @ ignore ) {
$ word =~ s/\s*\n?$//g ;
$ word =~ s/^\s*//g ;
$ word =~ s/\s+/ /g ;
$ word =~ tr /[a-z]/ [ A - Z ] / ;
next if ( $ word =~ m/^\s*#/ ) ;
next if ( $ word =~ m/^\s*$/ ) ;
$ ignore_type { $ word } + + ;
}
2008-02-08 15:20:54 +03:00
my $ dbg_values = 0 ;
my $ dbg_possible = 0 ;
2008-07-24 08:29:06 +04:00
my $ dbg_type = 0 ;
2008-10-16 09:02:17 +04:00
my $ dbg_attr = 0 ;
2008-02-08 15:20:54 +03:00
for my $ key ( keys % debug ) {
2009-01-07 01:41:30 +03:00
## no critic
eval "\${dbg_$key} = '$debug{$key}';" ;
die "$@" if ( $@ ) ;
2008-02-08 15:20:54 +03:00
}
2010-10-27 01:23:12 +04:00
my $ rpt_cleaners = 0 ;
2007-11-29 03:21:06 +03:00
if ( $ terse ) {
$ emacs = 1 ;
$ quiet + + ;
}
2007-10-18 14:05:08 +04:00
if ( $ tree ) {
if ( defined $ root ) {
if ( ! top_of_kernel_tree ( $ root ) ) {
die "$P: $root: --root does not point at a valid tree\n" ;
}
} else {
if ( top_of_kernel_tree ( '.' ) ) {
$ root = '.' ;
} elsif ( $ 0 =~ m @(.*)/scripts/[^/]*$@ &&
top_of_kernel_tree ( $ 1 ) ) {
$ root = $ 1 ;
}
}
if ( ! defined $ root ) {
print "Must be run from the top-level dir. of a kernel tree\n" ;
exit ( 2 ) ;
}
2007-06-01 11:46:48 +04:00
}
2007-10-18 14:05:08 +04:00
my $ emitted_corrupt = 0 ;
2009-10-27 02:50:14 +03:00
our $ Ident = qr{
[ A - Za - z_ ] [ A - Za - z \ d_ ] *
( ? : \ s * \ #\#\s*[A-Za-z_][A-Za-z\d_]*)*
} x ;
2007-10-18 14:05:08 +04:00
our $ Storage = qr{ extern|static|asmlinkage } ;
our $ Sparse = qr{
__user |
__kernel |
__force |
__iomem |
__must_check |
__init_refok |
2009-02-28 01:03:08 +03:00
__kprobes |
2011-07-26 04:13:23 +04:00
__ref |
__rcu
2007-10-18 14:05:08 +04:00
} x ;
2010-03-06 00:43:51 +03:00
# Notes to $Attribute:
# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
2007-10-18 14:05:08 +04:00
our $ Attribute = qr{
const |
2010-10-27 01:23:16 +04:00
__percpu |
__nocast |
__safe |
__bitwise__ |
__packed__ |
__packed2__ |
__naked |
__maybe_unused |
__always_unused |
__noreturn |
__used |
__cold |
__noclone |
__deprecated |
2007-10-18 14:05:08 +04:00
__read_mostly |
__kprobes |
2010-03-06 00:43:51 +03:00
__ ( ? : mem | cpu | dev | ) ( ? : initdata | initconst | init \ b ) |
2008-10-16 09:02:18 +04:00
____cacheline_aligned |
____cacheline_aligned_in_smp |
2009-01-07 01:41:18 +03:00
____cacheline_internodealigned_in_smp |
__weak
2007-10-18 14:05:08 +04:00
} x ;
2008-06-06 09:46:01 +04:00
our $ Modifier ;
2007-10-18 14:05:08 +04:00
our $ Inline = qr{ inline|__always_inline|noinline } ;
our $ Member = qr{ ->$Ident| \ .$Ident| \ [[^]]* \ ] } ;
our $ Lval = qr{ $Ident(?:$Member)* } ;
2013-02-05 02:28:51 +04:00
our $ Float_hex = qr{ (?i)0x[0-9a-f]+p-?[0-9]+[fl]? } ;
our $ Float_dec = qr{ (?i)(?:[0-9]+ \ .[0-9]*|[0-9]* \ .[0-9]+)(?:e-?[0-9]+)?[fl]? } ;
our $ Float_int = qr{ (?i)[0-9]+e-?[0-9]+[fl]? } ;
2012-12-18 04:02:05 +04:00
our $ Float = qr{ $Float_hex|$Float_dec|$Float_int } ;
2013-02-05 02:28:51 +04:00
our $ Constant = qr{ $Float|(?i)(?:0x[0-9a-f]+|[0-9]+)[ul]* } ;
our $ Assignment = qr{ \ * \ =|/=|%=| \ +=|-=|<<=|>>=|&=| \ ^=| \ |=|= } ;
2009-01-07 01:41:24 +03:00
our $ Compare = qr{ <=|>=|==|!=|<|> } ;
2007-10-18 14:05:08 +04:00
our $ Operators = qr{
<=|> = |= = | != |
= > | - > | <<|> > | <|> | ! | ~ |
2008-02-08 15:20:54 +03:00
&& | \ | \ || , | \ ^ | \ + \ + | - - | & | \ || \ + | - | \ * | \ / | %
2007-10-18 14:05:08 +04:00
} x ;
2007-11-29 03:21:06 +03:00
our $ NonptrType ;
our $ Type ;
our $ Declare ;
2011-11-01 04:13:12 +04:00
our $ NON_ASCII_UTF8 = qr{
[ \ xC2 - \ xDF ] [ \ x80 - \ xBF ] # non-overlong 2-byte
2008-04-29 11:59:32 +04:00
| \ xE0 [ \ xA0 - \ xBF ] [ \ x80 - \ xBF ] # excluding overlongs
| [ \ xE1 - \ xEC \ xEE \ xEF ] [ \ x80 - \ xBF ] { 2 } # straight 3-byte
| \ xED [ \ x80 - \ x9F ] [ \ x80 - \ xBF ] # excluding surrogates
| \ xF0 [ \ x90 - \ xBF ] [ \ x80 - \ xBF ] { 2 } # planes 1-3
| [ \ xF1 - \ xF3 ] [ \ x80 - \ xBF ] { 3 } # planes 4-15
| \ xF4 [ \ x80 - \ x8F ] [ \ x80 - \ xBF ] { 2 } # plane 16
} x ;
2011-11-01 04:13:12 +04:00
our $ UTF8 = qr{
[ \ x09 \ x0A \ x0D \ x20 - \ x7E ] # ASCII
| $ NON_ASCII_UTF8
} x ;
2008-10-16 09:02:32 +04:00
our $ typeTypedefs = qr{ (?x:
2009-09-22 04:04:38 +04:00
( ? : __ ) ? ( ? : u | s | be | le ) ( ? : 8 | 16 | 32 | 64 ) |
2008-10-16 09:02:32 +04:00
atomic_t
) } ;
2010-03-06 00:43:51 +03:00
our $ logFunctions = qr{ (?x:
2011-07-26 04:13:27 +04:00
printk ( ? : _ratelimited | _once | ) |
[ a - z0 - 9 ] + _ ( ? : printk | emerg | alert | crit | err | warning | warn | notice | info | debug | dbg | vdbg | devel | cont | WARN ) ( ? : _ratelimited | _once | ) |
WARN ( ? : _RATELIMIT | _ONCE | ) |
2011-05-25 04:13:40 +04:00
panic |
MODULE_ [ A - Z_ ] +
2010-03-06 00:43:51 +03:00
) } ;
2011-07-26 04:13:23 +04:00
our $ signature_tags = qr{ (?xi:
Signed - off - by: |
Acked - by: |
Tested - by: |
Reviewed - by: |
Reported - by: |
To: |
Cc:
) } ;
2007-11-29 03:21:06 +03:00
our @ typeList = (
qr{ void } ,
2008-06-06 09:46:01 +04:00
qr{ (?:unsigned \ s+)?char } ,
qr{ (?:unsigned \ s+)?short } ,
qr{ (?:unsigned \ s+)?int } ,
qr{ (?:unsigned \ s+)?long } ,
qr{ (?:unsigned \ s+)?long \ s+int } ,
qr{ (?:unsigned \ s+)?long \ s+long } ,
qr{ (?:unsigned \ s+)?long \ s+long \ s+int } ,
2007-11-29 03:21:06 +03:00
qr{ unsigned } ,
qr{ float } ,
qr{ double } ,
qr{ bool } ,
qr{ struct \ s+$Ident } ,
qr{ union \ s+$Ident } ,
qr{ enum \ s+$Ident } ,
qr{ $ { Ident } _t } ,
qr{ $ { Ident } _handler } ,
qr{ $ { Ident } _handler_fn } ,
) ;
2008-06-06 09:46:01 +04:00
our @ modifierList = (
qr{ fastcall } ,
) ;
2007-11-29 03:21:06 +03:00
2010-08-10 04:20:57 +04:00
our $ allowed_asm_includes = qr{ (?x:
irq |
memory
) } ;
# memory.h: ARM has a custom one
2007-11-29 03:21:06 +03:00
sub build_types {
2008-07-24 08:29:07 +04:00
my $ mods = "(?x: \n" . join ( "|\n " , @ modifierList ) . "\n)" ;
my $ all = "(?x: \n" . join ( "|\n " , @ typeList ) . "\n)" ;
2008-07-24 08:28:57 +04:00
$ Modifier = qr{ (?:$Attribute|$Sparse|$mods) } ;
2007-11-29 03:21:06 +03:00
$ NonptrType = qr{
2008-07-24 08:29:07 +04:00
( ? : $ Modifier \ s + | const \ s + ) *
2008-03-05 01:28:20 +03:00
( ? :
2012-01-11 03:10:13 +04:00
( ? : typeof | __typeof__ ) \ s * \ ( [ ^ \ ) ] * \ ) |
2008-10-16 09:02:32 +04:00
( ? : $ typeTypedefs \ b ) |
2008-06-06 09:46:01 +04:00
( ? : $ { all } \ b )
2008-03-05 01:28:20 +03:00
)
2008-07-24 08:28:57 +04:00
( ? : \ s + $ Modifier | \ s + const ) *
2007-11-29 03:21:06 +03:00
} x ;
$ Type = qr{
2008-06-06 09:46:01 +04:00
$ NonptrType
2012-03-24 02:02:18 +04:00
( ? : ( ? : \ s | \ * | \ [ \ ] ) + \ s * const | ( ? : \ s | \ * | \ [ \ ] ) + | ( ? : \ s * \ [ \ s * \ ] ) + ) ?
2008-07-24 08:28:57 +04:00
( ? : \ s + $ Inline | \ s + $ Modifier ) *
2007-11-29 03:21:06 +03:00
} x ;
$ Declare = qr{ (?:$Storage \ s+)?$Type } ;
}
build_types ( ) ;
2007-10-18 14:05:08 +04:00
2011-07-26 04:13:22 +04:00
our $ Typecast = qr{ \ s*( \ ( \ s*$NonptrType \ s* \ )) { 0,1 } \ s* } ;
2012-03-24 02:02:16 +04:00
# Using $balanced_parens, $LvalOrFunc, or $FuncArg
# requires at least perl version v5.10.0
# Any use must be runtime checked with $^V
our $ balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/ ;
our $ LvalOrFunc = qr{ ($Lval) \ s*($balanced_parens { 0,1 } ) \ s* } ;
2012-01-11 03:09:58 +04:00
our $ FuncArg = qr{ $Typecast { 0,1 } ($LvalOrFunc|$Constant) } ;
2011-07-26 04:13:22 +04:00
sub deparenthesize {
my ( $ string ) = @ _ ;
return "" if ( ! defined ( $ string ) ) ;
$ string =~ s@^\s*\(\s*@@g ;
$ string =~ s@\s*\)\s*$@@g ;
$ string =~ s@\s+@ @g ;
return $ string ;
}
2007-10-18 14:05:08 +04:00
$ chk_signoff = 0 if ( $ file ) ;
2007-06-09 00:47:06 +04:00
my @ rawlines = ( ) ;
2008-02-08 15:20:54 +03:00
my @ lines = ( ) ;
my $ vname ;
2007-10-18 14:05:08 +04:00
for my $ filename ( @ ARGV ) {
2009-01-07 01:41:30 +03:00
my $ FILE ;
2007-10-18 14:05:08 +04:00
if ( $ file ) {
2009-01-07 01:41:30 +03:00
open ( $ FILE , '-|' , "diff -u /dev/null $filename" ) ||
2007-10-18 14:05:08 +04:00
die "$P: $filename: diff failed - $!\n" ;
2009-01-07 01:41:30 +03:00
} elsif ( $ filename eq '-' ) {
open ( $ FILE , '<&STDIN' ) ;
2007-10-18 14:05:08 +04:00
} else {
2009-01-07 01:41:30 +03:00
open ( $ FILE , '<' , "$filename" ) ||
2007-10-18 14:05:08 +04:00
die "$P: $filename: open failed - $!\n" ;
2007-06-01 11:46:48 +04:00
}
2008-02-08 15:20:54 +03:00
if ( $ filename eq '-' ) {
$ vname = 'Your patch' ;
} else {
$ vname = $ filename ;
}
2009-01-07 01:41:30 +03:00
while ( <$FILE> ) {
2007-10-18 14:05:08 +04:00
chomp ;
push ( @ rawlines , $ _ ) ;
}
2009-01-07 01:41:30 +03:00
close ( $ FILE ) ;
2008-02-08 15:20:54 +03:00
if ( ! process ( $ filename ) ) {
2007-10-18 14:05:08 +04:00
$ exit = 1 ;
}
@ rawlines = ( ) ;
2008-02-08 15:22:03 +03:00
@ lines = ( ) ;
2007-06-01 11:46:48 +04:00
}
exit ( $ exit ) ;
sub top_of_kernel_tree {
2007-10-18 14:05:08 +04:00
my ( $ root ) = @ _ ;
my @ tree_check = (
"COPYING" , "CREDITS" , "Kbuild" , "MAINTAINERS" , "Makefile" ,
"README" , "Documentation" , "arch" , "include" , "drivers" ,
"fs" , "init" , "ipc" , "kernel" , "lib" , "scripts" ,
) ;
foreach my $ check ( @ tree_check ) {
if ( ! - e $ root . '/' . $ check ) {
return 0 ;
}
2007-06-01 11:46:48 +04:00
}
2007-10-18 14:05:08 +04:00
return 1 ;
2012-10-05 04:13:32 +04:00
}
2007-06-01 11:46:48 +04:00
2011-07-26 04:13:23 +04:00
sub parse_email {
my ( $ formatted_email ) = @ _ ;
my $ name = "" ;
my $ address = "" ;
my $ comment = "" ;
if ( $ formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/ ) {
$ name = $ 1 ;
$ address = $ 2 ;
$ comment = $ 3 if defined $ 3 ;
} elsif ( $ formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/ ) {
$ address = $ 1 ;
$ comment = $ 2 if defined $ 2 ;
} elsif ( $ formatted_email =~ /(\S+\@\S+)(.*)$/ ) {
$ address = $ 1 ;
$ comment = $ 2 if defined $ 2 ;
$ formatted_email =~ s/$address.*$// ;
$ name = $ formatted_email ;
$ name =~ s/^\s+|\s+$//g ;
$ name =~ s/^\"|\"$//g ;
# If there's a name left after stripping spaces and
# leading quotes, and the address doesn't have both
# leading and trailing angle brackets, the address
# is invalid. ie:
# "joe smith joe@smith.com" bad
# "joe smith <joe@smith.com" bad
if ( $ name ne "" && $ address !~ /^<[^>]+>$/ ) {
$ name = "" ;
$ address = "" ;
$ comment = "" ;
}
}
$ name =~ s/^\s+|\s+$//g ;
$ name =~ s/^\"|\"$//g ;
$ address =~ s/^\s+|\s+$//g ;
$ address =~ s/^\<|\>$//g ;
if ( $ name =~ /[^\w \-]/i ) { ##has "must quote" chars
$ name =~ s/(?<!\\)"/\\"/g ; ##escape quotes
$ name = "\"$name\"" ;
}
return ( $ name , $ address , $ comment ) ;
}
sub format_email {
my ( $ name , $ address ) = @ _ ;
my $ formatted_email ;
$ name =~ s/^\s+|\s+$//g ;
$ name =~ s/^\"|\"$//g ;
$ address =~ s/^\s+|\s+$//g ;
if ( $ name =~ /[^\w \-]/i ) { ##has "must quote" chars
$ name =~ s/(?<!\\)"/\\"/g ; ##escape quotes
$ name = "\"$name\"" ;
}
if ( "$name" eq "" ) {
$ formatted_email = "$address" ;
} else {
$ formatted_email = "$name <$address>" ;
}
return $ formatted_email ;
}
2011-07-26 04:13:25 +04:00
sub which_conf {
my ( $ conf ) = @ _ ;
foreach my $ path ( split ( /:/ , ".:$ENV{HOME}:.scripts" ) ) {
if ( - e "$path/$conf" ) {
return "$path/$conf" ;
}
}
return "" ;
}
2007-06-01 11:46:48 +04:00
sub expand_tabs {
my ( $ str ) = @ _ ;
my $ res = '' ;
my $ n = 0 ;
for my $ c ( split ( // , $ str ) ) {
if ( $ c eq "\t" ) {
$ res . = ' ' ;
$ n + + ;
for ( ; ( $ n % 8 ) != 0 ; $ n + + ) {
$ res . = ' ' ;
}
next ;
}
$ res . = $ c ;
$ n + + ;
}
return $ res ;
}
2007-10-18 14:05:08 +04:00
sub copy_spacing {
2008-03-29 00:15:58 +03:00
( my $ res = shift ) =~ tr /\t/ / c ;
2007-10-18 14:05:08 +04:00
return $ res ;
}
2007-06-01 11:46:48 +04:00
2007-06-09 00:46:39 +04:00
sub line_stats {
my ( $ line ) = @ _ ;
# Drop the diff line leader and expand tabs
$ line =~ s/^.// ;
$ line = expand_tabs ( $ line ) ;
# Pick the indent from the front of the line.
my ( $ white ) = ( $ line =~ /^(\s*)/ ) ;
return ( length ( $ line ) , length ( $ white ) ) ;
}
2008-03-29 00:15:58 +03:00
my $ sanitise_quote = '' ;
sub sanitise_line_reset {
my ( $ in_comment ) = @ _ ;
if ( $ in_comment ) {
$ sanitise_quote = '*/' ;
} else {
$ sanitise_quote = '' ;
}
}
2007-06-09 00:47:06 +04:00
sub sanitise_line {
my ( $ line ) = @ _ ;
my $ res = '' ;
my $ l = '' ;
2008-02-08 15:20:54 +03:00
my $ qlen = 0 ;
2008-03-29 00:15:58 +03:00
my $ off = 0 ;
my $ c ;
2007-06-09 00:47:06 +04:00
2008-03-29 00:15:58 +03:00
# Always copy over the diff marker.
$ res = substr ( $ line , 0 , 1 ) ;
for ( $ off = 1 ; $ off < length ( $ line ) ; $ off + + ) {
$ c = substr ( $ line , $ off , 1 ) ;
# Comments we are wacking completly including the begin
# and end, all to $;.
if ( $ sanitise_quote eq '' && substr ( $ line , $ off , 2 ) eq '/*' ) {
$ sanitise_quote = '*/' ;
substr ( $ res , $ off , 2 , "$;$;" ) ;
$ off + + ;
next ;
2007-06-09 00:47:06 +04:00
}
2008-10-16 09:02:26 +04:00
if ( $ sanitise_quote eq '*/' && substr ( $ line , $ off , 2 ) eq '*/' ) {
2008-03-29 00:15:58 +03:00
$ sanitise_quote = '' ;
substr ( $ res , $ off , 2 , "$;$;" ) ;
$ off + + ;
next ;
2008-02-08 15:20:54 +03:00
}
2009-09-22 04:04:35 +04:00
if ( $ sanitise_quote eq '' && substr ( $ line , $ off , 2 ) eq '//' ) {
$ sanitise_quote = '//' ;
substr ( $ res , $ off , 2 , $ sanitise_quote ) ;
$ off + + ;
next ;
}
2008-03-29 00:15:58 +03:00
# A \ in a string means ignore the next character.
if ( ( $ sanitise_quote eq "'" || $ sanitise_quote eq '"' ) &&
$ c eq "\\" ) {
substr ( $ res , $ off , 2 , 'XX' ) ;
$ off + + ;
next ;
2007-06-09 00:47:06 +04:00
}
2008-03-29 00:15:58 +03:00
# Regular quotes.
if ( $ c eq "'" || $ c eq '"' ) {
if ( $ sanitise_quote eq '' ) {
$ sanitise_quote = $ c ;
2007-06-09 00:47:06 +04:00
2008-03-29 00:15:58 +03:00
substr ( $ res , $ off , 1 , $ c ) ;
next ;
} elsif ( $ sanitise_quote eq $ c ) {
$ sanitise_quote = '' ;
}
}
2007-06-09 00:47:06 +04:00
2009-01-07 01:41:20 +03:00
#print "c<$c> SQ<$sanitise_quote>\n";
2008-03-29 00:15:58 +03:00
if ( $ off != 0 && $ sanitise_quote eq '*/' && $ c ne "\t" ) {
substr ( $ res , $ off , 1 , $; ) ;
2009-09-22 04:04:35 +04:00
} elsif ( $ off != 0 && $ sanitise_quote eq '//' && $ c ne "\t" ) {
substr ( $ res , $ off , 1 , $; ) ;
2008-03-29 00:15:58 +03:00
} elsif ( $ off != 0 && $ sanitise_quote && $ c ne "\t" ) {
substr ( $ res , $ off , 1 , 'X' ) ;
} else {
substr ( $ res , $ off , 1 , $ c ) ;
}
2008-02-08 15:20:54 +03:00
}
2009-09-22 04:04:35 +04:00
if ( $ sanitise_quote eq '//' ) {
$ sanitise_quote = '' ;
}
2008-02-08 15:20:54 +03:00
# The pathname on a #include may be surrounded by '<' and '>'.
2008-06-06 09:46:01 +04:00
if ( $ res =~ /^.\s*\#\s*include\s+\<(.*)\>/ ) {
2008-02-08 15:20:54 +03:00
my $ clean = 'X' x length ( $ 1 ) ;
$ res =~ s@\<.*\>@<$clean>@ ;
# The whole of a #error is a string.
2008-06-06 09:46:01 +04:00
} elsif ( $ res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/ ) {
2008-02-08 15:20:54 +03:00
my $ clean = 'X' x length ( $ 1 ) ;
2008-06-06 09:46:01 +04:00
$ res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@ ;
2008-02-08 15:20:54 +03:00
}
2007-06-09 00:47:06 +04:00
return $ res ;
}
2007-11-29 03:21:06 +03:00
sub ctx_statement_block {
my ( $ linenr , $ remain , $ off ) = @ _ ;
my $ line = $ linenr - 1 ;
my $ blk = '' ;
my $ soff = $ off ;
my $ coff = $ off - 1 ;
2008-03-29 00:15:58 +03:00
my $ coff_set = 0 ;
2007-11-29 03:21:06 +03:00
2008-02-08 15:22:03 +03:00
my $ loff = 0 ;
2007-11-29 03:21:06 +03:00
my $ type = '' ;
my $ level = 0 ;
2009-01-16 00:51:04 +03:00
my @ stack = ( ) ;
2008-03-05 01:28:20 +03:00
my $ p ;
2007-11-29 03:21:06 +03:00
my $ c ;
my $ len = 0 ;
2008-02-08 15:22:03 +03:00
my $ remainder ;
2007-11-29 03:21:06 +03:00
while ( 1 ) {
2009-01-16 00:51:04 +03:00
@ stack = ( [ '' , 0 ] ) if ( $# stack == - 1 ) ;
2008-03-29 00:15:58 +03:00
#warn "CSB: blk<$blk> remain<$remain>\n";
2007-11-29 03:21:06 +03:00
# If we are about to drop off the end, pull in more
# context.
if ( $ off >= $ len ) {
for ( ; $ remain > 0 ; $ line + + ) {
2008-10-16 09:02:25 +04:00
last if ( ! defined $ lines [ $ line ] ) ;
2008-02-08 15:20:54 +03:00
next if ( $ lines [ $ line ] =~ /^-/ ) ;
2007-11-29 03:21:06 +03:00
$ remain - - ;
2008-02-08 15:22:03 +03:00
$ loff = $ len ;
2008-02-08 15:20:54 +03:00
$ blk . = $ lines [ $ line ] . "\n" ;
2007-11-29 03:21:06 +03:00
$ len = length ( $ blk ) ;
$ line + + ;
last ;
}
# Bail if there is no further context.
#warn "CSB: blk<$blk> off<$off> len<$len>\n";
2008-02-08 15:22:03 +03:00
if ( $ off >= $ len ) {
2007-11-29 03:21:06 +03:00
last ;
}
2012-01-11 03:09:54 +04:00
if ( $ level == 0 && substr ( $ blk , $ off ) =~ /^.\s*#\s*define/ ) {
$ level + + ;
$ type = '#' ;
}
2007-11-29 03:21:06 +03:00
}
2008-03-05 01:28:20 +03:00
$ p = $ c ;
2007-11-29 03:21:06 +03:00
$ c = substr ( $ blk , $ off , 1 ) ;
2008-02-08 15:22:03 +03:00
$ remainder = substr ( $ blk , $ off ) ;
2007-11-29 03:21:06 +03:00
2008-03-29 00:15:58 +03:00
#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
2009-01-07 01:41:27 +03:00
# Handle nested #if/#else.
if ( $ remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/ ) {
push ( @ stack , [ $ type , $ level ] ) ;
} elsif ( $ remainder =~ /^#\s*(?:else|elif)\b/ ) {
( $ type , $ level ) = @ { $ stack [ $# stack - 1 ] } ;
} elsif ( $ remainder =~ /^#\s*endif\b/ ) {
( $ type , $ level ) = @ { pop ( @ stack ) } ;
}
2007-11-29 03:21:06 +03:00
# Statement ends at the ';' or a close '}' at the
# outermost level.
if ( $ level == 0 && $ c eq ';' ) {
last ;
}
2008-02-08 15:22:03 +03:00
# An else is really a conditional as long as its not else if
2008-03-29 00:15:58 +03:00
if ( $ level == 0 && $ coff_set == 0 &&
( ! defined ( $ p ) || $ p =~ /(?:\s|\}|\+)/ ) &&
$ remainder =~ /^(else)(?:\s|{)/ &&
$ remainder !~ /^else\s+if\b/ ) {
$ coff = $ off + length ( $ 1 ) - 1 ;
$ coff_set = 1 ;
#warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
#warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
2008-02-08 15:22:03 +03:00
}
2007-11-29 03:21:06 +03:00
if ( ( $ type eq '' || $ type eq '(' ) && $ c eq '(' ) {
$ level + + ;
$ type = '(' ;
}
if ( $ type eq '(' && $ c eq ')' ) {
$ level - - ;
$ type = ( $ level != 0 ) ? '(' : '' ;
if ( $ level == 0 && $ coff < $ soff ) {
$ coff = $ off ;
2008-03-29 00:15:58 +03:00
$ coff_set = 1 ;
#warn "CSB: mark coff<$coff>\n";
2007-11-29 03:21:06 +03:00
}
}
if ( ( $ type eq '' || $ type eq '{' ) && $ c eq '{' ) {
$ level + + ;
$ type = '{' ;
}
if ( $ type eq '{' && $ c eq '}' ) {
$ level - - ;
$ type = ( $ level != 0 ) ? '{' : '' ;
if ( $ level == 0 ) {
2010-08-10 04:21:03 +04:00
if ( substr ( $ blk , $ off + 1 , 1 ) eq ';' ) {
$ off + + ;
}
2007-11-29 03:21:06 +03:00
last ;
}
}
2012-01-11 03:09:54 +04:00
# Preprocessor commands end at the newline unless escaped.
if ( $ type eq '#' && $ c eq "\n" && $ p ne "\\" ) {
$ level - - ;
$ type = '' ;
$ off + + ;
last ;
}
2007-11-29 03:21:06 +03:00
$ off + + ;
}
2008-07-24 08:29:00 +04:00
# We are truly at the end, so shuffle to the next line.
2008-02-08 15:22:03 +03:00
if ( $ off == $ len ) {
2008-07-24 08:29:00 +04:00
$ loff = $ len + 1 ;
2008-02-08 15:22:03 +03:00
$ line + + ;
$ remain - - ;
}
2007-11-29 03:21:06 +03:00
my $ statement = substr ( $ blk , $ soff , $ off - $ soff + 1 ) ;
my $ condition = substr ( $ blk , $ soff , $ coff - $ soff + 1 ) ;
#warn "STATEMENT<$statement>\n";
#warn "CONDITION<$condition>\n";
2008-03-29 00:15:58 +03:00
#print "coff<$coff> soff<$off> loff<$loff>\n";
2008-02-08 15:22:03 +03:00
return ( $ statement , $ condition ,
$ line , $ remain + 1 , $ off - $ loff + 1 , $ level ) ;
}
2008-03-05 01:28:20 +03:00
sub statement_lines {
my ( $ stmt ) = @ _ ;
# Strip the diff line prefixes and rip blank lines at start and end.
$ stmt =~ s/(^|\n)./$1/g ;
$ stmt =~ s/^\s*// ;
$ stmt =~ s/\s*$// ;
my @ stmt_lines = ( $ stmt =~ /\n/g ) ;
return $# stmt_lines + 2 ;
}
sub statement_rawlines {
my ( $ stmt ) = @ _ ;
my @ stmt_lines = ( $ stmt =~ /\n/g ) ;
return $# stmt_lines + 2 ;
}
sub statement_block_size {
my ( $ stmt ) = @ _ ;
$ stmt =~ s/(^|\n)./$1/g ;
$ stmt =~ s/^\s*{// ;
$ stmt =~ s/}\s*$// ;
$ stmt =~ s/^\s*// ;
$ stmt =~ s/\s*$// ;
my @ stmt_lines = ( $ stmt =~ /\n/g ) ;
my @ stmt_statements = ( $ stmt =~ /;/g ) ;
my $ stmt_lines = $# stmt_lines + 2 ;
my $ stmt_statements = $# stmt_statements + 1 ;
if ( $ stmt_lines > $ stmt_statements ) {
return $ stmt_lines ;
} else {
return $ stmt_statements ;
}
}
2008-02-08 15:22:03 +03:00
sub ctx_statement_full {
my ( $ linenr , $ remain , $ off ) = @ _ ;
my ( $ statement , $ condition , $ level ) ;
my ( @ chunks ) ;
2008-03-05 01:28:20 +03:00
# Grab the first conditional/block pair.
2008-02-08 15:22:03 +03:00
( $ statement , $ condition , $ linenr , $ remain , $ off , $ level ) =
ctx_statement_block ( $ linenr , $ remain , $ off ) ;
2008-03-29 00:15:58 +03:00
#print "F: c<$condition> s<$statement> remain<$remain>\n";
2008-03-05 01:28:20 +03:00
push ( @ chunks , [ $ condition , $ statement ] ) ;
if ( ! ( $ remain > 0 && $ condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s ) ) {
return ( $ level , $ linenr , @ chunks ) ;
}
# Pull in the following conditional/block pairs and see if they
# could continue the statement.
2008-02-08 15:22:03 +03:00
for ( ; ; ) {
( $ statement , $ condition , $ linenr , $ remain , $ off , $ level ) =
ctx_statement_block ( $ linenr , $ remain , $ off ) ;
2008-03-05 01:28:20 +03:00
#print "C: c<$condition> s<$statement> remain<$remain>\n";
2008-03-29 00:15:58 +03:00
last if ( ! ( $ remain > 0 && $ condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s ) ) ;
2008-03-05 01:28:20 +03:00
#print "C: push\n";
push ( @ chunks , [ $ condition , $ statement ] ) ;
2008-02-08 15:22:03 +03:00
}
return ( $ level , $ linenr , @ chunks ) ;
2007-11-29 03:21:06 +03:00
}
2007-06-09 00:46:39 +04:00
sub ctx_block_get {
2007-07-19 12:48:34 +04:00
my ( $ linenr , $ remain , $ outer , $ open , $ close , $ off ) = @ _ ;
2007-06-09 00:46:39 +04:00
my $ line ;
my $ start = $ linenr - 1 ;
my $ blk = '' ;
my @ o ;
my @ c ;
my @ res = ( ) ;
2007-07-19 12:48:34 +04:00
my $ level = 0 ;
2009-01-07 01:41:27 +03:00
my @ stack = ( $ level ) ;
2007-06-09 00:47:06 +04:00
for ( $ line = $ start ; $ remain > 0 ; $ line + + ) {
next if ( $ rawlines [ $ line ] =~ /^-/ ) ;
$ remain - - ;
$ blk . = $ rawlines [ $ line ] ;
2009-01-07 01:41:27 +03:00
# Handle nested #if/#else.
2010-10-27 01:23:19 +04:00
if ( $ lines [ $ line ] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/ ) {
2009-01-07 01:41:27 +03:00
push ( @ stack , $ level ) ;
2010-10-27 01:23:19 +04:00
} elsif ( $ lines [ $ line ] =~ /^.\s*#\s*(?:else|elif)\b/ ) {
2009-01-07 01:41:27 +03:00
$ level = $ stack [ $# stack - 1 ] ;
2010-10-27 01:23:19 +04:00
} elsif ( $ lines [ $ line ] =~ /^.\s*#\s*endif\b/ ) {
2009-01-07 01:41:27 +03:00
$ level = pop ( @ stack ) ;
}
2010-10-27 01:23:19 +04:00
foreach my $ c ( split ( // , $ lines [ $ line ] ) ) {
2007-07-19 12:48:34 +04:00
##print "C<$c>L<$level><$open$close>O<$off>\n";
if ( $ off > 0 ) {
$ off - - ;
next ;
}
2007-06-09 00:46:39 +04:00
2007-07-19 12:48:34 +04:00
if ( $ c eq $ close && $ level > 0 ) {
$ level - - ;
last if ( $ level == 0 ) ;
} elsif ( $ c eq $ open ) {
$ level + + ;
}
}
2007-06-09 00:46:39 +04:00
2007-07-19 12:48:34 +04:00
if ( ! $ outer || $ level <= 1 ) {
2007-06-09 00:47:06 +04:00
push ( @ res , $ rawlines [ $ line ] ) ;
2007-06-09 00:46:39 +04:00
}
2007-07-19 12:48:34 +04:00
last if ( $ level == 0 ) ;
2007-06-09 00:46:39 +04:00
}
2007-07-19 12:48:34 +04:00
return ( $ level , @ res ) ;
2007-06-09 00:46:39 +04:00
}
sub ctx_block_outer {
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 12:48:34 +04:00
my ( $ level , @ r ) = ctx_block_get ( $ linenr , $ remain , 1 , '{' , '}' , 0 ) ;
return @ r ;
2007-06-09 00:46:39 +04:00
}
sub ctx_block {
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 12:48:34 +04:00
my ( $ level , @ r ) = ctx_block_get ( $ linenr , $ remain , 0 , '{' , '}' , 0 ) ;
return @ r ;
2007-06-24 04:16:34 +04:00
}
sub ctx_statement {
2007-07-19 12:48:34 +04:00
my ( $ linenr , $ remain , $ off ) = @ _ ;
my ( $ level , @ r ) = ctx_block_get ( $ linenr , $ remain , 0 , '(' , ')' , $ off ) ;
return @ r ;
}
sub ctx_block_level {
2007-06-24 04:16:34 +04:00
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 12:48:34 +04:00
return ctx_block_get ( $ linenr , $ remain , 0 , '{' , '}' , 0 ) ;
2007-06-09 00:46:39 +04:00
}
2007-10-17 10:29:38 +04:00
sub ctx_statement_level {
my ( $ linenr , $ remain , $ off ) = @ _ ;
return ctx_block_get ( $ linenr , $ remain , 0 , '(' , ')' , $ off ) ;
}
2007-06-09 00:46:39 +04:00
sub ctx_locate_comment {
my ( $ first_line , $ end_line ) = @ _ ;
# Catch a comment on the end of the line itself.
2008-07-24 08:28:59 +04:00
my ( $ current_comment ) = ( $ rawlines [ $ end_line - 1 ] =~ m @.*(/\*.*\*/)\s*(?:\\\s*)?$@ ) ;
2007-06-09 00:46:39 +04:00
return $ current_comment if ( defined $ current_comment ) ;
# Look through the context and try and figure out if there is a
# comment.
my $ in_comment = 0 ;
$ current_comment = '' ;
for ( my $ linenr = $ first_line ; $ linenr < $ end_line ; $ linenr + + ) {
2007-06-09 00:47:06 +04:00
my $ line = $ rawlines [ $ linenr - 1 ] ;
#warn " $line\n";
2007-06-09 00:46:39 +04:00
if ( $ linenr == $ first_line and $ line =~ m @^.\s*\*@ ) {
$ in_comment = 1 ;
}
if ( $ line =~ m @/\*@ ) {
$ in_comment = 1 ;
}
if ( ! $ in_comment && $ current_comment ne '' ) {
$ current_comment = '' ;
}
$ current_comment . = $ line . "\n" if ( $ in_comment ) ;
if ( $ line =~ m @\*/@ ) {
$ in_comment = 0 ;
}
}
chomp ( $ current_comment ) ;
return ( $ current_comment ) ;
}
sub ctx_has_comment {
my ( $ first_line , $ end_line ) = @ _ ;
my $ cmt = ctx_locate_comment ( $ first_line , $ end_line ) ;
2007-06-09 00:47:06 +04:00
##print "LINE: $rawlines[$end_line - 1 ]\n";
2007-06-09 00:46:39 +04:00
##print "CMMT: $cmt\n";
return ( $ cmt ne '' ) ;
}
2008-10-16 09:02:21 +04:00
sub raw_line {
my ( $ linenr , $ cnt ) = @ _ ;
my $ offset = $ linenr - 1 ;
$ cnt + + ;
my $ line ;
while ( $ cnt ) {
$ line = $ rawlines [ $ offset + + ] ;
next if ( defined ( $ line ) && $ line =~ /^-/ ) ;
$ cnt - - ;
}
return $ line ;
}
2007-10-18 14:05:08 +04:00
sub cat_vet {
my ( $ vet ) = @ _ ;
my ( $ res , $ coded ) ;
2007-10-17 10:29:38 +04:00
2007-10-18 14:05:08 +04:00
$ res = '' ;
while ( $ vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g ) {
$ res . = $ 1 ;
if ( $ 2 ne '' ) {
$ coded = sprintf ( "^%c" , unpack ( 'C' , $ 2 ) + 64 ) ;
$ res . = $ coded ;
2007-10-17 10:29:38 +04:00
}
}
2007-10-18 14:05:08 +04:00
$ res =~ s/$/\$/ ;
2007-10-17 10:29:38 +04:00
2007-10-18 14:05:08 +04:00
return $ res ;
2007-10-17 10:29:38 +04:00
}
2008-02-08 15:20:54 +03:00
my $ av_preprocessor = 0 ;
2008-03-05 01:28:20 +03:00
my $ av_pending ;
2008-02-08 15:20:54 +03:00
my @ av_paren_type ;
2008-07-24 08:29:10 +04:00
my $ av_pend_colon ;
2008-02-08 15:20:54 +03:00
sub annotate_reset {
$ av_preprocessor = 0 ;
2008-03-05 01:28:20 +03:00
$ av_pending = '_' ;
@ av_paren_type = ( 'E' ) ;
2008-07-24 08:29:10 +04:00
$ av_pend_colon = 'O' ;
2008-02-08 15:20:54 +03:00
}
2007-10-18 14:05:08 +04:00
sub annotate_values {
my ( $ stream , $ type ) = @ _ ;
2007-06-01 11:46:48 +04:00
2007-10-18 14:05:08 +04:00
my $ res ;
2008-07-24 08:29:10 +04:00
my $ var = '_' x length ( $ stream ) ;
2007-10-18 14:05:08 +04:00
my $ cur = $ stream ;
2008-02-08 15:20:54 +03:00
print "$stream\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
while ( length ( $ cur ) ) {
2008-03-29 00:15:58 +03:00
@ av_paren_type = ( 'E' ) if ( $# av_paren_type < 0 ) ;
2008-03-05 01:28:20 +03:00
print " <" . join ( '' , @ av_paren_type ) .
2008-04-29 11:59:32 +04:00
"> <$type> <$av_pending>" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
if ( $ cur =~ /^(\s+)/o ) {
2008-02-08 15:20:54 +03:00
print "WS($1)\n" if ( $ dbg_values > 1 ) ;
if ( $ 1 =~ /\n/ && $ av_preprocessor ) {
2008-03-05 01:28:20 +03:00
$ type = pop ( @ av_paren_type ) ;
2008-02-08 15:20:54 +03:00
$ av_preprocessor = 0 ;
2007-10-18 14:05:08 +04:00
}
2011-01-13 03:59:58 +03:00
} elsif ( $ cur =~ /^(\(\s*$Type\s*)\)/ && $ av_pending eq '_' ) {
2010-10-27 01:23:13 +04:00
print "CAST($1)\n" if ( $ dbg_values > 1 ) ;
push ( @ av_paren_type , $ type ) ;
2012-01-11 03:10:11 +04:00
$ type = 'c' ;
2010-10-27 01:23:13 +04:00
2010-10-27 01:23:11 +04:00
} elsif ( $ cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/ ) {
2008-02-08 15:20:54 +03:00
print "DECLARE($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'T' ;
2008-07-24 08:29:05 +04:00
} elsif ( $ cur =~ /^($Modifier)\s*/ ) {
print "MODIFIER($1)\n" if ( $ dbg_values > 1 ) ;
$ type = 'T' ;
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*define\s*$Ident)(\(?)/o ) {
2008-04-29 11:59:32 +04:00
print "DEFINE($1,$2)\n" if ( $ dbg_values > 1 ) ;
2008-02-08 15:20:54 +03:00
$ av_preprocessor = 1 ;
2008-04-29 11:59:32 +04:00
push ( @ av_paren_type , $ type ) ;
if ( $ 2 ne '' ) {
$ av_pending = 'N' ;
}
$ type = 'E' ;
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o ) {
2008-04-29 11:59:32 +04:00
print "UNDEF($1)\n" if ( $ dbg_values > 1 ) ;
$ av_preprocessor = 1 ;
push ( @ av_paren_type , $ type ) ;
2007-10-18 14:05:08 +04:00
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o ) {
2008-03-05 01:28:20 +03:00
print "PRE_START($1)\n" if ( $ dbg_values > 1 ) ;
2008-02-08 15:20:54 +03:00
$ av_preprocessor = 1 ;
2008-03-05 01:28:20 +03:00
push ( @ av_paren_type , $ type ) ;
push ( @ av_paren_type , $ type ) ;
2008-04-29 11:59:32 +04:00
$ type = 'E' ;
2008-03-05 01:28:20 +03:00
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*(?:else|elif))/o ) {
2008-03-05 01:28:20 +03:00
print "PRE_RESTART($1)\n" if ( $ dbg_values > 1 ) ;
$ av_preprocessor = 1 ;
push ( @ av_paren_type , $ av_paren_type [ $# av_paren_type ] ) ;
2008-04-29 11:59:32 +04:00
$ type = 'E' ;
2008-03-05 01:28:20 +03:00
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*(?:endif))/o ) {
2008-03-05 01:28:20 +03:00
print "PRE_END($1)\n" if ( $ dbg_values > 1 ) ;
$ av_preprocessor = 1 ;
# Assume all arms of the conditional end as this
# one does, and continue as if the #endif was not here.
pop ( @ av_paren_type ) ;
push ( @ av_paren_type , $ type ) ;
2008-04-29 11:59:32 +04:00
$ type = 'E' ;
2007-10-18 14:05:08 +04:00
} elsif ( $ cur =~ /^(\\\n)/o ) {
2008-02-08 15:20:54 +03:00
print "PRECONT($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
2008-04-29 11:59:32 +04:00
} elsif ( $ cur =~ /^(__attribute__)\s*\(?/o ) {
print "ATTR($1)\n" if ( $ dbg_values > 1 ) ;
$ av_pending = $ type ;
$ type = 'N' ;
2007-10-18 14:05:08 +04:00
} elsif ( $ cur =~ /^(sizeof)\s*(\()?/o ) {
2008-02-08 15:20:54 +03:00
print "SIZEOF($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
if ( defined $ 2 ) {
2008-03-05 01:28:20 +03:00
$ av_pending = 'V' ;
2007-10-18 14:05:08 +04:00
}
$ type = 'N' ;
2008-10-16 09:02:16 +04:00
} elsif ( $ cur =~ /^(if|while|for)\b/o ) {
2008-02-08 15:20:54 +03:00
print "COND($1)\n" if ( $ dbg_values > 1 ) ;
2008-10-16 09:02:16 +04:00
$ av_pending = 'E' ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
2008-07-24 08:29:10 +04:00
} elsif ( $ cur =~ /^(case)/o ) {
print "CASE($1)\n" if ( $ dbg_values > 1 ) ;
$ av_pend_colon = 'C' ;
$ type = 'N' ;
2008-10-16 09:02:16 +04:00
} elsif ( $ cur =~ /^(return|else|goto|typeof|__typeof__)\b/o ) {
2008-02-08 15:20:54 +03:00
print "KEYWORD($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
} elsif ( $ cur =~ /^(\()/o ) {
2008-02-08 15:20:54 +03:00
print "PAREN('$1')\n" if ( $ dbg_values > 1 ) ;
2008-03-05 01:28:20 +03:00
push ( @ av_paren_type , $ av_pending ) ;
$ av_pending = '_' ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
} elsif ( $ cur =~ /^(\))/o ) {
2008-03-05 01:28:20 +03:00
my $ new_type = pop ( @ av_paren_type ) ;
if ( $ new_type ne '_' ) {
$ type = $ new_type ;
2008-02-08 15:20:54 +03:00
print "PAREN('$1') -> $type\n"
if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
} else {
2008-02-08 15:20:54 +03:00
print "PAREN('$1')\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
}
2008-07-24 08:28:57 +04:00
} elsif ( $ cur =~ /^($Ident)\s*\(/o ) {
2008-02-08 15:20:54 +03:00
print "FUNC($1)\n" if ( $ dbg_values > 1 ) ;
2008-07-24 08:28:57 +04:00
$ type = 'V' ;
2008-03-05 01:28:20 +03:00
$ av_pending = 'V' ;
2007-10-18 14:05:08 +04:00
2009-01-07 01:41:19 +03:00
} elsif ( $ cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/ ) {
if ( defined $ 2 && $ type eq 'C' || $ type eq 'T' ) {
2008-07-24 08:29:10 +04:00
$ av_pend_colon = 'B' ;
2009-01-07 01:41:19 +03:00
} elsif ( $ type eq 'E' ) {
$ av_pend_colon = 'L' ;
2008-07-24 08:29:10 +04:00
}
print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ( $ dbg_values > 1 ) ;
$ type = 'V' ;
2007-10-18 14:05:08 +04:00
} elsif ( $ cur =~ /^($Ident|$Constant)/o ) {
2008-02-08 15:20:54 +03:00
print "IDENT($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'V' ;
} elsif ( $ cur =~ /^($Assignment)/o ) {
2008-02-08 15:20:54 +03:00
print "ASSIGN($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
2008-03-05 01:28:20 +03:00
} elsif ( $ cur =~ /^(;|{|})/ ) {
2008-02-08 15:20:54 +03:00
print "END($1)\n" if ( $ dbg_values > 1 ) ;
2008-02-08 15:22:03 +03:00
$ type = 'E' ;
2008-07-24 08:29:10 +04:00
$ av_pend_colon = 'O' ;
2009-01-07 01:41:19 +03:00
} elsif ( $ cur =~ /^(,)/ ) {
print "COMMA($1)\n" if ( $ dbg_values > 1 ) ;
$ type = 'C' ;
2008-07-24 08:29:10 +04:00
} elsif ( $ cur =~ /^(\?)/o ) {
print "QUESTION($1)\n" if ( $ dbg_values > 1 ) ;
$ type = 'N' ;
} elsif ( $ cur =~ /^(:)/o ) {
print "COLON($1,$av_pend_colon)\n" if ( $ dbg_values > 1 ) ;
substr ( $ var , length ( $ res ) , 1 , $ av_pend_colon ) ;
if ( $ av_pend_colon eq 'C' || $ av_pend_colon eq 'L' ) {
$ type = 'E' ;
} else {
$ type = 'N' ;
}
$ av_pend_colon = 'O' ;
2008-02-08 15:22:03 +03:00
2009-01-07 01:41:19 +03:00
} elsif ( $ cur =~ /^(\[)/o ) {
2008-02-08 15:22:03 +03:00
print "CLOSE($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
2008-10-16 09:02:16 +04:00
} elsif ( $ cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o ) {
2008-07-24 08:29:10 +04:00
my $ variant ;
print "OPV($1)\n" if ( $ dbg_values > 1 ) ;
if ( $ type eq 'V' ) {
$ variant = 'B' ;
} else {
$ variant = 'U' ;
}
substr ( $ var , length ( $ res ) , 1 , $ variant ) ;
$ type = 'N' ;
2007-10-18 14:05:08 +04:00
} elsif ( $ cur =~ /^($Operators)/o ) {
2008-02-08 15:20:54 +03:00
print "OP($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
if ( $ 1 ne '++' && $ 1 ne '--' ) {
$ type = 'N' ;
}
} elsif ( $ cur =~ /(^.)/o ) {
2008-02-08 15:20:54 +03:00
print "C($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
}
if ( defined $ 1 ) {
$ cur = substr ( $ cur , length ( $ 1 ) ) ;
$ res . = $ type x length ( $ 1 ) ;
}
2007-10-17 10:29:38 +04:00
}
2007-06-01 11:46:48 +04:00
2008-07-24 08:29:10 +04:00
return ( $ res , $ var ) ;
2007-06-01 11:46:48 +04:00
}
2007-11-29 03:21:06 +03:00
sub possible {
2008-02-08 15:22:03 +03:00
my ( $ possible , $ line ) = @ _ ;
2009-10-27 02:50:12 +03:00
my $ notPermitted = qr{ (?:
2008-10-16 09:02:29 +04:00
^ ( ? :
$ Modifier |
$ Storage |
$ Type |
2009-10-27 02:50:12 +03:00
DEFINE_ \ S +
) $|
^ ( ? :
2008-10-16 09:02:29 +04:00
goto |
return |
case |
else |
asm | __asm__ |
2012-01-11 03:10:00 +04:00
do |
\ #|
\ #\#|
2009-10-27 02:50:12 +03:00
) ( ? : \ s | $ ) |
2008-10-16 09:02:29 +04:00
^ ( ? : typedef | struct | enum ) \ b
2009-10-27 02:50:12 +03:00
) } x ;
warn "CHECK<$possible> ($line)\n" if ( $ dbg_possible > 2 ) ;
if ( $ possible !~ $ notPermitted ) {
2008-06-06 09:46:01 +04:00
# Check for modifiers.
$ possible =~ s/\s*$Storage\s*//g ;
$ possible =~ s/\s*$Sparse\s*//g ;
if ( $ possible =~ /^\s*$/ ) {
} elsif ( $ possible =~ /\s/ ) {
$ possible =~ s/\s*$Type\s*//g ;
2008-07-24 08:29:09 +04:00
for my $ modifier ( split ( ' ' , $ possible ) ) {
2009-10-27 02:50:12 +03:00
if ( $ modifier !~ $ notPermitted ) {
warn "MODIFIER: $modifier ($possible) ($line)\n" if ( $ dbg_possible ) ;
push ( @ modifierList , $ modifier ) ;
}
2008-07-24 08:29:09 +04:00
}
2008-06-06 09:46:01 +04:00
} else {
warn "POSSIBLE: $possible ($line)\n" if ( $ dbg_possible ) ;
push ( @ typeList , $ possible ) ;
}
2007-11-29 03:21:06 +03:00
build_types ( ) ;
2008-10-16 09:02:29 +04:00
} else {
warn "NOTPOSS: $possible ($line)\n" if ( $ dbg_possible > 1 ) ;
2007-11-29 03:21:06 +03:00
}
}
2007-10-18 14:05:08 +04:00
my $ prefix = '' ;
2011-07-26 04:13:25 +04:00
sub show_type {
return ! defined $ ignore_type { $ _ [ 0 ] } ;
}
2007-07-19 12:48:34 +04:00
sub report {
2011-07-26 04:13:25 +04:00
if ( ! show_type ( $ _ [ 1 ] ) ||
( defined $ tst_only && $ _ [ 2 ] !~ /\Q$tst_only\E/ ) ) {
2008-03-29 00:15:58 +03:00
return 0 ;
}
2011-07-26 04:13:25 +04:00
my $ line ;
if ( $ show_types ) {
$ line = "$prefix$_[0]:$_[1]: $_[2]\n" ;
} else {
$ line = "$prefix$_[0]: $_[2]\n" ;
}
2007-11-29 03:21:06 +03:00
$ line = ( split ( '\n' , $ line ) ) [ 0 ] . "\n" if ( $ terse ) ;
2008-02-08 15:22:03 +03:00
push ( our @ report , $ line ) ;
2008-03-29 00:15:58 +03:00
return 1 ;
2007-07-19 12:48:34 +04:00
}
sub report_dump {
2008-02-08 15:22:03 +03:00
our @ report ;
2007-07-19 12:48:34 +04:00
}
2011-07-26 04:13:25 +04:00
2007-07-16 10:37:22 +04:00
sub ERROR {
2011-07-26 04:13:25 +04:00
if ( report ( "ERROR" , $ _ [ 0 ] , $ _ [ 1 ] ) ) {
2008-03-29 00:15:58 +03:00
our $ clean = 0 ;
our $ cnt_error + + ;
}
2007-07-16 10:37:22 +04:00
}
sub WARN {
2011-07-26 04:13:25 +04:00
if ( report ( "WARNING" , $ _ [ 0 ] , $ _ [ 1 ] ) ) {
2008-03-29 00:15:58 +03:00
our $ clean = 0 ;
our $ cnt_warn + + ;
}
2007-07-16 10:37:22 +04:00
}
sub CHK {
2011-07-26 04:13:25 +04:00
if ( $ check && report ( "CHECK" , $ _ [ 0 ] , $ _ [ 1 ] ) ) {
2007-10-18 14:05:08 +04:00
our $ clean = 0 ;
our $ cnt_chk + + ;
}
2007-07-16 10:37:22 +04:00
}
2008-10-16 09:02:21 +04:00
sub check_absolute_file {
my ( $ absolute , $ herecurr ) = @ _ ;
my $ file = $ absolute ;
##print "absolute<$absolute>\n";
# See if any suffix of this path is a path within the tree.
while ( $ file =~ s@^[^/]*/@@ ) {
if ( - f "$root/$file" ) {
##print "file<$file>\n";
last ;
}
}
if ( ! - f _ ) {
return 0 ;
}
# It is, so see if the prefix is acceptable.
my $ prefix = $ absolute ;
substr ( $ prefix , - length ( $ file ) ) = '' ;
##print "prefix<$prefix>\n";
if ( $ prefix ne ".../" ) {
2011-07-26 04:13:25 +04:00
WARN ( "USE_RELATIVE_PATH" ,
"use relative pathname instead of absolute in changelog text\n" . $ herecurr ) ;
2008-10-16 09:02:21 +04:00
}
}
2012-03-24 02:02:16 +04:00
sub pos_last_openparen {
my ( $ line ) = @ _ ;
my $ pos = 0 ;
my $ opens = $ line =~ tr /\(/ \ ( / ;
my $ closes = $ line =~ tr /\)/ \ ) / ;
my $ last_openparen = 0 ;
if ( ( $ opens == 0 ) || ( $ closes >= $ opens ) ) {
return - 1 ;
}
my $ len = length ( $ line ) ;
for ( $ pos = 0 ; $ pos < $ len ; $ pos + + ) {
my $ string = substr ( $ line , $ pos ) ;
if ( $ string =~ /^($FuncArg|$balanced_parens)/ ) {
$ pos += length ( $ 1 ) - 1 ;
} elsif ( substr ( $ line , $ pos , 1 ) eq '(' ) {
$ last_openparen = $ pos ;
} elsif ( index ( $ string , '(' ) == - 1 ) {
last ;
}
}
return $ last_openparen + 1 ;
}
2007-06-01 11:46:48 +04:00
sub process {
my $ filename = shift ;
my $ linenr = 0 ;
my $ prevline = "" ;
2008-02-08 15:20:54 +03:00
my $ prevrawline = "" ;
2007-06-01 11:46:48 +04:00
my $ stashline = "" ;
2008-02-08 15:20:54 +03:00
my $ stashrawline = "" ;
2007-06-01 11:46:48 +04:00
2007-06-09 00:46:39 +04:00
my $ length ;
2007-06-01 11:46:48 +04:00
my $ indent ;
my $ previndent = 0 ;
my $ stashindent = 0 ;
2007-07-16 10:37:22 +04:00
our $ clean = 1 ;
2007-06-01 11:46:48 +04:00
my $ signoff = 0 ;
my $ is_patch = 0 ;
2011-11-01 04:13:12 +04:00
my $ in_header_lines = 1 ;
my $ in_commit_log = 0 ; #Scanning lines before patch
2012-10-05 04:13:29 +04:00
my $ non_utf8_charset = 0 ;
2008-02-08 15:22:03 +03:00
our @ report = ( ) ;
2007-10-18 14:05:08 +04:00
our $ cnt_lines = 0 ;
our $ cnt_error = 0 ;
our $ cnt_warn = 0 ;
our $ cnt_chk = 0 ;
2007-06-01 11:46:48 +04:00
# Trace the real file/line as we go.
my $ realfile = '' ;
my $ realline = 0 ;
my $ realcnt = 0 ;
my $ here = '' ;
my $ in_comment = 0 ;
2008-02-08 15:20:54 +03:00
my $ comment_edge = 0 ;
2007-06-01 11:46:48 +04:00
my $ first_line = 0 ;
2009-01-07 01:41:24 +03:00
my $ p1_prefix = '' ;
2007-06-01 11:46:48 +04:00
2008-02-08 15:22:03 +03:00
my $ prev_values = 'E' ;
# suppression flags
2008-03-29 00:15:58 +03:00
my % suppress_ifbraces ;
2008-10-16 09:02:30 +04:00
my % suppress_whiletrailers ;
2009-10-27 02:50:16 +03:00
my % suppress_export ;
2012-01-11 03:10:01 +04:00
my $ suppress_statement = 0 ;
2007-06-24 04:16:34 +04:00
2012-12-18 04:02:07 +04:00
my % camelcase = ( ) ;
2008-02-08 15:20:54 +03:00
# Pre-scan the patch sanitizing the lines.
2007-07-16 10:37:22 +04:00
# Pre-scan the patch looking for any __setup documentation.
2008-02-08 15:20:54 +03:00
#
2007-07-16 10:37:22 +04:00
my @ setup_docs = ( ) ;
my $ setup_docs = 0 ;
2008-03-29 00:15:58 +03:00
sanitise_line_reset ( ) ;
2008-02-08 15:20:54 +03:00
my $ line ;
foreach my $ rawline ( @ rawlines ) {
2008-03-29 00:15:58 +03:00
$ linenr + + ;
$ line = $ rawline ;
2008-02-08 15:20:54 +03:00
2008-03-29 00:15:58 +03:00
if ( $ rawline =~ /^\+\+\+\s+(\S+)/ ) {
2007-07-16 10:37:22 +04:00
$ setup_docs = 0 ;
if ( $ 1 =~ m @Documentation/kernel-parameters.txt$@ ) {
$ setup_docs = 1 ;
}
2008-03-29 00:15:58 +03:00
#next;
}
if ( $ rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/ ) {
$ realline = $ 1 - 1 ;
if ( defined $ 2 ) {
$ realcnt = $ 3 + 1 ;
} else {
$ realcnt = 1 + 1 ;
}
2008-06-06 09:46:01 +04:00
$ in_comment = 0 ;
2008-03-29 00:15:58 +03:00
# Guestimate if this is a continuing comment. Run
# the context looking for a comment "edge". If this
# edge is a close comment then we must be in a comment
# at context start.
my $ edge ;
2008-10-16 09:02:19 +04:00
my $ cnt = $ realcnt ;
for ( my $ ln = $ linenr + 1 ; $ cnt > 0 ; $ ln + + ) {
next if ( defined $ rawlines [ $ ln - 1 ] &&
$ rawlines [ $ ln - 1 ] =~ /^-/ ) ;
$ cnt - - ;
#print "RAW<$rawlines[$ln - 1]>\n";
2009-01-07 01:41:16 +03:00
last if ( ! defined $ rawlines [ $ ln - 1 ] ) ;
2009-01-07 01:41:20 +03:00
if ( $ rawlines [ $ ln - 1 ] =~ m @(/\*|\*/)@ &&
$ rawlines [ $ ln - 1 ] !~ m @"[^"]*(?:/\*|\*/)[^"]*"@ ) {
( $ edge ) = $ 1 ;
last ;
}
2008-03-29 00:15:58 +03:00
}
if ( defined $ edge && $ edge eq '*/' ) {
$ in_comment = 1 ;
}
# Guestimate if this is a continuing comment. If this
# is the start of a diff block and this line starts
# ' *' then it is very likely a comment.
if ( ! defined $ edge &&
2009-01-07 01:41:17 +03:00
$ rawlines [ $ linenr ] =~ m @^.\s*(?:\*\*+| \*)(?:\s|$)@ )
2008-03-29 00:15:58 +03:00
{
$ in_comment = 1 ;
}
##print "COMMENT:$in_comment edge<$edge> $rawline\n";
sanitise_line_reset ( $ in_comment ) ;
2008-04-29 11:59:32 +04:00
} elsif ( $ realcnt && $ rawline =~ /^(?:\+| |$)/ ) {
2008-03-29 00:15:58 +03:00
# Standardise the strings and chars within the input to
2008-04-29 11:59:32 +04:00
# simplify matching -- only bother with positive lines.
2008-03-29 00:15:58 +03:00
$ line = sanitise_line ( $ rawline ) ;
2007-07-16 10:37:22 +04:00
}
2008-03-29 00:15:58 +03:00
push ( @ lines , $ line ) ;
if ( $ realcnt > 1 ) {
$ realcnt - - if ( $ line =~ /^(?:\+| |$)/ ) ;
} else {
$ realcnt = 0 ;
}
#print "==>$rawline\n";
#print "-->$line\n";
2007-07-16 10:37:22 +04:00
if ( $ setup_docs && $ line =~ /^\+/ ) {
push ( @ setup_docs , $ line ) ;
}
}
2007-10-18 14:05:08 +04:00
$ prefix = '' ;
2008-03-29 00:15:58 +03:00
$ realcnt = 0 ;
$ linenr = 0 ;
2007-06-01 11:46:48 +04:00
foreach my $ line ( @ lines ) {
$ linenr + + ;
2008-02-08 15:20:54 +03:00
my $ rawline = $ rawlines [ $ linenr - 1 ] ;
2007-10-18 14:05:08 +04:00
2007-06-01 11:46:48 +04:00
#extract the line range in the file after the patch is applied
2007-10-18 14:05:08 +04:00
if ( $ line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/ ) {
2007-06-01 11:46:48 +04:00
$ is_patch = 1 ;
2007-06-09 00:46:39 +04:00
$ first_line = $ linenr + 1 ;
2007-06-01 11:46:48 +04:00
$ realline = $ 1 - 1 ;
if ( defined $ 2 ) {
$ realcnt = $ 3 + 1 ;
} else {
$ realcnt = 1 + 1 ;
}
2008-02-08 15:20:54 +03:00
annotate_reset ( ) ;
2008-02-08 15:22:03 +03:00
$ prev_values = 'E' ;
2008-03-29 00:15:58 +03:00
% suppress_ifbraces = ( ) ;
2008-10-16 09:02:30 +04:00
% suppress_whiletrailers = ( ) ;
2009-10-27 02:50:16 +03:00
% suppress_export = ( ) ;
2012-01-11 03:10:01 +04:00
$ suppress_statement = 0 ;
2007-06-01 11:46:48 +04:00
next ;
2007-06-09 00:46:39 +04:00
# track the line number as we move through the hunk, note that
# new versions of GNU diff omit the leading space on completely
# blank context lines so we need to count that too.
2008-03-29 00:15:58 +03:00
} elsif ( $ line =~ /^( |\+|$)/ ) {
2007-06-01 11:46:48 +04:00
$ realline + + ;
2007-06-24 04:16:44 +04:00
$ realcnt - - if ( $ realcnt != 0 ) ;
2007-06-01 11:46:48 +04:00
2007-06-09 00:46:39 +04:00
# Measure the line length and indent.
2008-02-08 15:20:54 +03:00
( $ length , $ indent ) = line_stats ( $ rawline ) ;
2007-06-01 11:46:48 +04:00
# Track the previous line.
( $ prevline , $ stashline ) = ( $ stashline , $ line ) ;
( $ previndent , $ stashindent ) = ( $ stashindent , $ indent ) ;
2008-02-08 15:20:54 +03:00
( $ prevrawline , $ stashrawline ) = ( $ stashrawline , $ rawline ) ;
2008-03-29 00:15:58 +03:00
#warn "line<$line>\n";
2007-10-18 14:05:08 +04:00
2007-06-24 04:16:44 +04:00
} elsif ( $ realcnt == 1 ) {
$ realcnt - - ;
2007-06-01 11:46:48 +04:00
}
2009-10-27 02:50:13 +03:00
my $ hunk_line = ( $ realcnt != 0 ) ;
2007-06-01 11:46:48 +04:00
#make up the handle for any error we report on this line
2008-03-29 00:15:58 +03:00
$ prefix = "$filename:$realline: " if ( $ emacs && $ file ) ;
$ prefix = "$filename:$linenr: " if ( $ emacs && ! $ file ) ;
2007-10-18 14:05:08 +04:00
$ here = "#$linenr: " if ( ! $ file ) ;
$ here = "#$realline: " if ( $ file ) ;
2008-03-29 00:15:58 +03:00
# extract the filename as it passes
2010-10-27 01:23:16 +04:00
if ( $ line =~ /^diff --git.*?(\S+)$/ ) {
$ realfile = $ 1 ;
$ realfile =~ s@^([^/]*)/@@ ;
2012-01-11 03:09:50 +04:00
$ in_commit_log = 0 ;
2010-10-27 01:23:16 +04:00
} elsif ( $ line =~ /^\+\+\+\s+(\S+)/ ) {
2008-03-29 00:15:58 +03:00
$ realfile = $ 1 ;
2009-01-07 01:41:24 +03:00
$ realfile =~ s@^([^/]*)/@@ ;
2012-01-11 03:09:50 +04:00
$ in_commit_log = 0 ;
2009-01-07 01:41:24 +03:00
$ p1_prefix = $ 1 ;
2009-02-28 01:03:06 +03:00
if ( ! $ file && $ tree && $ p1_prefix ne '' &&
- e "$root/$p1_prefix" ) {
2011-07-26 04:13:25 +04:00
WARN ( "PATCH_PREFIX" ,
"patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n" ) ;
2009-01-07 01:41:24 +03:00
}
2008-03-29 00:15:58 +03:00
2008-10-16 09:02:20 +04:00
if ( $ realfile =~ m @^include/asm/@ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "MODIFIED_INCLUDE_ASM" ,
"do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n" ) ;
2008-03-29 00:15:58 +03:00
}
next ;
}
2007-06-09 00:47:03 +04:00
$ here . = "FILE: $realfile:$realline:" if ( $ realcnt != 0 ) ;
2007-06-01 11:46:48 +04:00
2008-02-08 15:20:54 +03:00
my $ hereline = "$here\n$rawline\n" ;
my $ herecurr = "$here\n$rawline\n" ;
my $ hereprev = "$here\n$prevrawline\n$rawline\n" ;
2007-06-01 11:46:48 +04:00
2007-10-18 14:05:08 +04:00
$ cnt_lines + + if ( $ realcnt != 0 ) ;
2010-10-27 01:23:16 +04:00
# Check for incorrect file permissions
if ( $ line =~ /^new (file )?mode.*[7531]\d{0,2}$/ ) {
my $ permhere = $ here . "FILE: $realfile\n" ;
if ( $ realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "EXECUTE_PERMISSIONS" ,
"do not set execute permissions for source files\n" . $ permhere ) ;
2010-10-27 01:23:16 +04:00
}
}
2011-07-26 04:13:23 +04:00
# Check the patch for a signoff:
2007-06-24 04:16:44 +04:00
if ( $ line =~ /^\s*signed-off-by:/i ) {
2007-06-09 00:46:39 +04:00
$ signoff + + ;
2011-11-01 04:13:12 +04:00
$ in_commit_log = 0 ;
2011-07-26 04:13:23 +04:00
}
# Check signature styles
2012-01-11 03:09:50 +04:00
if ( ! $ in_header_lines &&
2012-07-31 01:41:18 +04:00
$ line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i ) {
2011-07-26 04:13:23 +04:00
my $ space_before = $ 1 ;
my $ sign_off = $ 2 ;
my $ space_after = $ 3 ;
my $ email = $ 4 ;
my $ ucfirst_sign_off = ucfirst ( lc ( $ sign_off ) ) ;
2012-07-31 01:41:18 +04:00
if ( $ sign_off !~ /$signature_tags/ ) {
WARN ( "BAD_SIGN_OFF" ,
"Non-standard signature: $sign_off\n" . $ herecurr ) ;
}
2011-07-26 04:13:23 +04:00
if ( defined $ space_before && $ space_before ne "" ) {
2011-07-26 04:13:25 +04:00
WARN ( "BAD_SIGN_OFF" ,
"Do not use whitespace before $ucfirst_sign_off\n" . $ herecurr ) ;
2011-07-26 04:13:23 +04:00
}
if ( $ sign_off =~ /-by:$/i && $ sign_off ne $ ucfirst_sign_off ) {
2011-07-26 04:13:25 +04:00
WARN ( "BAD_SIGN_OFF" ,
"'$ucfirst_sign_off' is the preferred signature form\n" . $ herecurr ) ;
2011-07-26 04:13:23 +04:00
}
if ( ! defined $ space_after || $ space_after ne " " ) {
2011-07-26 04:13:25 +04:00
WARN ( "BAD_SIGN_OFF" ,
"Use a single space after $ucfirst_sign_off\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2011-07-26 04:13:23 +04:00
my ( $ email_name , $ email_address , $ comment ) = parse_email ( $ email ) ;
my $ suggested_email = format_email ( ( $ email_name , $ email_address ) ) ;
if ( $ suggested_email eq "" ) {
2011-07-26 04:13:25 +04:00
ERROR ( "BAD_SIGN_OFF" ,
"Unrecognized email address: '$email'\n" . $ herecurr ) ;
2011-07-26 04:13:23 +04:00
} else {
my $ dequoted = $ suggested_email ;
$ dequoted =~ s/^"// ;
$ dequoted =~ s/" </ </ ;
# Don't force email to have quotes
# Allow just an angle bracketed address
if ( "$dequoted$comment" ne $ email &&
"<$email_address>$comment" ne $ email &&
"$suggested_email$comment" ne $ email ) {
2011-07-26 04:13:25 +04:00
WARN ( "BAD_SIGN_OFF" ,
"email address '$email' might be better as '$suggested_email$comment'\n" . $ herecurr ) ;
2011-07-26 04:13:23 +04:00
}
2007-06-01 11:46:48 +04:00
}
}
2007-06-09 00:47:06 +04:00
# Check for wrappage within a valid hunk of the file
2007-11-29 03:21:06 +03:00
if ( $ realcnt != 0 && $ line !~ m {^(?:\+|-| |\\ No newline|$)} ) {
2011-07-26 04:13:25 +04:00
ERROR ( "CORRUPTED_PATCH" ,
"patch seems to be corrupt (line wrapped?)\n" .
2007-10-18 14:05:08 +04:00
$ herecurr ) if ( ! $ emitted_corrupt + + ) ;
2007-07-16 10:37:22 +04:00
}
2008-10-16 09:02:21 +04:00
# Check for absolute kernel paths.
if ( $ tree ) {
while ( $ line =~ m {(?:^|\s)(/\S*)}g ) {
my $ file = $ 1 ;
if ( $ file =~ m {^(.*?)(?::\d+)+:?$} &&
check_absolute_file ( $ 1 , $ herecurr ) ) {
#
} else {
check_absolute_file ( $ file , $ herecurr ) ;
}
}
}
2007-07-16 10:37:22 +04:00
# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
if ( ( $ realfile =~ /^$/ || $ line =~ /^\+/ ) &&
2008-04-29 11:59:32 +04:00
$ rawline !~ m/^$UTF8*$/ ) {
my ( $ utf8_prefix ) = ( $ rawline =~ /^($UTF8*)/ ) ;
my $ blank = copy_spacing ( $ rawline ) ;
my $ ptr = substr ( $ blank , 0 , length ( $ utf8_prefix ) ) . "^" ;
my $ hereptr = "$hereline$ptr\n" ;
2011-07-26 04:13:26 +04:00
CHK ( "INVALID_UTF8" ,
"Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $ hereptr ) ;
2007-06-09 00:47:06 +04:00
}
2011-11-01 04:13:12 +04:00
# Check if it's the start of a commit log
# (not a header line and we haven't seen the patch filename)
if ( $ in_header_lines && $ realfile =~ /^$/ &&
2012-01-11 03:09:50 +04:00
$ rawline !~ /^(commit\b|from\b|[\w-]+:).+$/i ) {
2011-11-01 04:13:12 +04:00
$ in_header_lines = 0 ;
$ in_commit_log = 1 ;
}
2012-10-05 04:13:29 +04:00
# Check if there is UTF-8 in a commit log when a mail header has explicitly
# declined it, i.e defined some charset where it is missing.
if ( $ in_header_lines &&
$ rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
$ 1 !~ /utf-8/i ) {
$ non_utf8_charset = 1 ;
}
if ( $ in_commit_log && $ non_utf8_charset && $ realfile =~ /^$/ &&
2011-11-01 04:13:12 +04:00
$ rawline =~ /$NON_ASCII_UTF8/ ) {
2012-10-05 04:13:29 +04:00
WARN ( "UTF8_BEFORE_PATCH" ,
2011-11-01 04:13:12 +04:00
"8-bit UTF-8 used in possible commit log\n" . $ herecurr ) ;
}
2008-10-16 09:02:28 +04:00
# ignore non-hunk lines and lines being removed
next if ( ! $ hunk_line || $ line =~ /^-/ ) ;
2007-06-01 11:46:48 +04:00
#trailing whitespace
2007-10-17 10:29:38 +04:00
if ( $ line =~ /^\+.*\015/ ) {
2008-02-08 15:20:54 +03:00
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2011-07-26 04:13:25 +04:00
ERROR ( "DOS_LINE_ENDINGS" ,
"DOS line endings\n" . $ herevet ) ;
2007-10-17 10:29:38 +04:00
2008-02-08 15:20:54 +03:00
} elsif ( $ rawline =~ /^\+.*\S\s+$/ || $ rawline =~ /^\+\s+$/ ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2011-07-26 04:13:25 +04:00
ERROR ( "TRAILING_WHITESPACE" ,
"trailing whitespace\n" . $ herevet ) ;
2010-10-27 01:23:12 +04:00
$ rpt_cleaners = 1 ;
2007-06-01 11:46:48 +04:00
}
2008-10-16 09:02:27 +04:00
2010-05-25 01:33:29 +04:00
# check for Kconfig help text having a real description
2010-10-27 01:23:15 +04:00
# Only applies when adding the entry originally, after that we do not have
# sufficient context to determine whether it is indeed long enough.
2010-05-25 01:33:29 +04:00
if ( $ realfile =~ /Kconfig/ &&
2012-01-11 03:10:03 +04:00
$ line =~ /.\s*config\s+/ ) {
2010-05-25 01:33:29 +04:00
my $ length = 0 ;
2010-10-27 01:23:15 +04:00
my $ cnt = $ realcnt ;
my $ ln = $ linenr + 1 ;
my $ f ;
2012-01-11 03:10:03 +04:00
my $ is_start = 0 ;
2010-10-27 01:23:15 +04:00
my $ is_end = 0 ;
2012-01-11 03:10:03 +04:00
for ( ; $ cnt > 0 && defined $ lines [ $ ln - 1 ] ; $ ln + + ) {
2010-10-27 01:23:15 +04:00
$ f = $ lines [ $ ln - 1 ] ;
$ cnt - - if ( $ lines [ $ ln - 1 ] !~ /^-/ ) ;
$ is_end = $ lines [ $ ln - 1 ] =~ /^\+/ ;
next if ( $ f =~ /^-/ ) ;
2012-01-11 03:10:03 +04:00
if ( $ lines [ $ ln - 1 ] =~ /.\s*(?:bool|tristate)\s*\"/ ) {
$ is_start = 1 ;
} elsif ( $ lines [ $ ln - 1 ] =~ /.\s*(?:---)?help(?:---)?$/ ) {
$ length = - 1 ;
}
2010-10-27 01:23:15 +04:00
$ f =~ s/^.// ;
2010-05-25 01:33:29 +04:00
$ f =~ s/#.*// ;
$ f =~ s/^\s+// ;
next if ( $ f =~ /^$/ ) ;
2010-10-27 01:23:15 +04:00
if ( $ f =~ /^\s*config\s/ ) {
$ is_end = 1 ;
last ;
}
2010-05-25 01:33:29 +04:00
$ length + + ;
}
2011-07-26 04:13:25 +04:00
WARN ( "CONFIG_DESCRIPTION" ,
2012-01-11 03:10:03 +04:00
"please write a paragraph that describes the config symbol fully\n" . $ herecurr ) if ( $ is_start && $ is_end && $ length < 4 ) ;
#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
2010-05-25 01:33:29 +04:00
}
2012-12-18 04:01:48 +04:00
# discourage the addition of CONFIG_EXPERIMENTAL in Kconfig.
if ( $ realfile =~ /Kconfig/ &&
$ line =~ /.\s*depends on\s+.*\bEXPERIMENTAL\b/ ) {
WARN ( "CONFIG_EXPERIMENTAL" ,
"Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n" ) ;
}
2011-08-15 09:07:14 +04:00
if ( ( $ realfile =~ /Makefile.*/ || $ realfile =~ /Kbuild.*/ ) &&
( $ line =~ /\+(EXTRA_[A-Z]+FLAGS).*/ ) ) {
my $ flag = $ 1 ;
my $ replacement = {
'EXTRA_AFLAGS' = > 'asflags-y' ,
'EXTRA_CFLAGS' = > 'ccflags-y' ,
'EXTRA_CPPFLAGS' = > 'cppflags-y' ,
'EXTRA_LDFLAGS' = > 'ldflags-y' ,
} ;
WARN ( "DEPRECATED_VARIABLE" ,
"Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $ herecurr ) if ( $ replacement - > { $ flag } ) ;
}
2008-10-16 09:02:27 +04:00
# check we are in a valid source file if not then ignore this hunk
next if ( $ realfile !~ /\.(h|c|s|S|pl|sh)$/ ) ;
2012-12-18 04:01:54 +04:00
#line length limit
2008-06-06 09:46:01 +04:00
if ( $ line =~ /^\+/ && $ prevrawline !~ /\/\*\*/ &&
2008-07-24 08:29:01 +04:00
$ rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
2011-05-25 04:13:41 +04:00
! ( $ line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:|,|\)\s*;)\s*$/ ||
2010-08-10 04:21:01 +04:00
$ line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/ ) &&
2012-12-18 04:01:54 +04:00
$ length > $ max_line_length )
2008-06-06 09:46:01 +04:00
{
2011-07-26 04:13:25 +04:00
WARN ( "LONG_LINE" ,
2012-12-18 04:01:54 +04:00
"line over $max_line_length characters\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2012-03-24 02:02:21 +04:00
# Check for user-visible strings broken across lines, which breaks the ability
# to grep for the string. Limited to strings used as parameters (those
# following an open parenthesis), which almost completely eliminates false
# positives, as well as warning only once per parameter rather than once per
# line of the string. Make an exception when the previous string ends in a
# newline (multiple lines in one string constant) or \n\t (common in inline
# assembly to indent the instruction on the following line).
if ( $ line =~ /^\+\s*"/ &&
$ prevline =~ /"\s*$/ &&
$ prevline =~ /\(/ &&
$ prevrawline !~ /\\n(?:\\t)*"\s*$/ ) {
WARN ( "SPLIT_STRING" ,
"quoted string split across lines\n" . $ hereprev ) ;
}
2010-03-06 00:43:55 +03:00
# check for spaces before a quoted newline
if ( $ rawline =~ /^.*\".*\s\\n/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "QUOTED_WHITESPACE_BEFORE_NEWLINE" ,
"unnecessary whitespace before a quoted newline\n" . $ herecurr ) ;
2010-03-06 00:43:55 +03:00
}
2007-11-29 03:21:06 +03:00
# check for adding lines without a newline.
if ( $ line =~ /^\+/ && defined $ lines [ $ linenr ] && $ lines [ $ linenr ] =~ /^\\ No newline at end of file/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "MISSING_EOF_NEWLINE" ,
"adding a line without newline at end of file\n" . $ herecurr ) ;
2007-11-29 03:21:06 +03:00
}
2009-09-22 04:04:40 +04:00
# Blackfin: use hi/lo macros
if ( $ realfile =~ m @arch/blackfin/.*\.S$@ ) {
if ( $ line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/ ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
2011-07-26 04:13:25 +04:00
ERROR ( "LO_MACRO" ,
"use the LO() macro, not (... & 0xFFFF)\n" . $ herevet ) ;
2009-09-22 04:04:40 +04:00
}
if ( $ line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/ ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
2011-07-26 04:13:25 +04:00
ERROR ( "HI_MACRO" ,
"use the HI() macro, not (... >> 16)\n" . $ herevet ) ;
2009-09-22 04:04:40 +04:00
}
}
2008-10-16 09:02:24 +04:00
# check we are in a valid source file C or perl if not then ignore this hunk
next if ( $ realfile !~ /\.(h|c|pl)$/ ) ;
2007-06-01 11:46:48 +04:00
# at the beginning of a line any tabs must come first and anything
# more than 8 must use tabs.
2008-02-08 15:20:54 +03:00
if ( $ rawline =~ /^\+\s* \t\s*\S/ ||
$ rawline =~ /^\+\s* \s*/ ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2011-07-26 04:13:25 +04:00
ERROR ( "CODE_INDENT" ,
"code indent should use tabs where possible\n" . $ herevet ) ;
2010-10-27 01:23:12 +04:00
$ rpt_cleaners = 1 ;
2007-06-01 11:46:48 +04:00
}
2010-03-06 00:43:54 +03:00
# check for space before tabs.
if ( $ rawline =~ /^\+/ && $ rawline =~ / \t/ ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2011-07-26 04:13:25 +04:00
WARN ( "SPACE_BEFORE_TAB" ,
"please, no space before tabs\n" . $ herevet ) ;
2010-03-06 00:43:54 +03:00
}
2012-03-24 02:02:16 +04:00
# check for && or || at the start of a line
if ( $ rawline =~ /^\+\s*(&&|\|\|)/ ) {
CHK ( "LOGICAL_CONTINUATIONS" ,
"Logical continuations should be on the previous line\n" . $ hereprev ) ;
}
# check multi-line statement indentation matches previous line
if ( $ ^ V && $ ^ V ge 5.10 .0 &&
$ prevline =~ /^\+(\t*)(if \(|$Ident\().*(\&\&|\|\||,)\s*$/ ) {
$ prevline =~ /^\+(\t*)(.*)$/ ;
my $ oldindent = $ 1 ;
my $ rest = $ 2 ;
my $ pos = pos_last_openparen ( $ rest ) ;
if ( $ pos >= 0 ) {
2012-07-31 01:41:16 +04:00
$ line =~ /^(\+| )([ \t]*)/ ;
my $ newindent = $ 2 ;
2012-03-24 02:02:16 +04:00
my $ goodtabindent = $ oldindent .
"\t" x ( $ pos / 8 ) .
" " x ( $ pos % 8 ) ;
my $ goodspaceindent = $ oldindent . " " x $ pos ;
if ( $ newindent ne $ goodtabindent &&
$ newindent ne $ goodspaceindent ) {
CHK ( "PARENTHESIS_ALIGNMENT" ,
"Alignment should match open parenthesis\n" . $ hereprev ) ;
}
}
}
2012-03-24 02:02:19 +04:00
if ( $ line =~ /^\+.*\*[ \t]*\)[ \t]+/ ) {
CHK ( "SPACING" ,
"No space is necessary after a cast\n" . $ hereprev ) ;
}
2012-10-05 04:13:35 +04:00
if ( $ realfile =~ m @^(drivers/net/|net/)@ &&
$ rawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
$ prevrawline =~ /^\+[ \t]*$/ ) {
WARN ( "NETWORKING_BLOCK_COMMENT_STYLE" ,
"networking block comments don't use an empty /* line, use /* Comment...\n" . $ hereprev ) ;
}
if ( $ realfile =~ m @^(drivers/net/|net/)@ &&
2012-11-09 03:53:29 +04:00
$ rawline !~ m @^\+[ \t]*\*/[ \t]*$@ && #trailing */
$ rawline !~ m @^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/
$ rawline !~ m @^\+.*\*{2,}/[ \t]*$@ && #trailing **/
$ rawline =~ m @^\+[ \t]*.+\*\/[ \t]*$@ ) { #non blank */
2012-10-05 04:13:35 +04:00
WARN ( "NETWORKING_BLOCK_COMMENT_STYLE" ,
"networking block comments put the trailing */ on a separate line\n" . $ herecurr ) ;
}
checkpatch: fix handling of leading spaces
I've got a false positive when spaces are present at the beginning of a
line.
So I add this check, obviously excluding to check the lines in the middle of
comments.
For instance this code passes the checkpatch test:
+struct davinci_mcbsp_data {
+ unsigned int fmt;
+ int clk_div;
+};
+
+static struct davinci_mcbsp_data mcbsp_data;
Where, before the string "int clk_div", I have 4 spaces (\040
ascii character).
With v2.6.34 scripts/checkpatch.pl script I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
total: 0 errors, 0 warnings, 201 lines checked
0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch has no obvious style
problems and is ready for submission.
That is not correct. Instead with the proposed patch I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
WARNING: please, no space for starting a line,
excluding comments
#63: FILE: sound/soc/davinci/davinci-i2s.c:165:
+ int clk_div;$
WARNING: please, no space for starting a line,
excluding comments
#95: FILE: sound/soc/davinci/davinci-i2s.c:406:
+ return 0;$
total: 0 errors, 2 warnings, 201 lines checked
That is correct.
Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-08-10 04:20:59 +04:00
# check for spaces at the beginning of a line.
2010-10-27 01:23:11 +04:00
# Exceptions:
# 1) within comments
# 2) indented preprocessor commands
# 3) hanging labels
if ( $ rawline =~ /^\+ / && $ line !~ /\+ *(?:$;|#|$Ident:)/ ) {
checkpatch: fix handling of leading spaces
I've got a false positive when spaces are present at the beginning of a
line.
So I add this check, obviously excluding to check the lines in the middle of
comments.
For instance this code passes the checkpatch test:
+struct davinci_mcbsp_data {
+ unsigned int fmt;
+ int clk_div;
+};
+
+static struct davinci_mcbsp_data mcbsp_data;
Where, before the string "int clk_div", I have 4 spaces (\040
ascii character).
With v2.6.34 scripts/checkpatch.pl script I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
total: 0 errors, 0 warnings, 201 lines checked
0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch has no obvious style
problems and is ready for submission.
That is not correct. Instead with the proposed patch I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
WARNING: please, no space for starting a line,
excluding comments
#63: FILE: sound/soc/davinci/davinci-i2s.c:165:
+ int clk_div;$
WARNING: please, no space for starting a line,
excluding comments
#95: FILE: sound/soc/davinci/davinci-i2s.c:406:
+ return 0;$
total: 0 errors, 2 warnings, 201 lines checked
That is correct.
Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-08-10 04:20:59 +04:00
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2011-07-26 04:13:25 +04:00
WARN ( "LEADING_SPACE" ,
"please, no spaces at the start of a line\n" . $ herevet ) ;
checkpatch: fix handling of leading spaces
I've got a false positive when spaces are present at the beginning of a
line.
So I add this check, obviously excluding to check the lines in the middle of
comments.
For instance this code passes the checkpatch test:
+struct davinci_mcbsp_data {
+ unsigned int fmt;
+ int clk_div;
+};
+
+static struct davinci_mcbsp_data mcbsp_data;
Where, before the string "int clk_div", I have 4 spaces (\040
ascii character).
With v2.6.34 scripts/checkpatch.pl script I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
total: 0 errors, 0 warnings, 201 lines checked
0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch has no obvious style
problems and is ready for submission.
That is not correct. Instead with the proposed patch I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
WARNING: please, no space for starting a line,
excluding comments
#63: FILE: sound/soc/davinci/davinci-i2s.c:165:
+ int clk_div;$
WARNING: please, no space for starting a line,
excluding comments
#95: FILE: sound/soc/davinci/davinci-i2s.c:406:
+ return 0;$
total: 0 errors, 2 warnings, 201 lines checked
That is correct.
Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-08-10 04:20:59 +04:00
}
2008-10-16 09:02:24 +04:00
# check we are in a valid C source file if not then ignore this hunk
next if ( $ realfile !~ /\.(h|c)$/ ) ;
2012-12-18 04:01:48 +04:00
# discourage the addition of CONFIG_EXPERIMENTAL in #if(def).
if ( $ line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/ ) {
WARN ( "CONFIG_EXPERIMENTAL" ,
"Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n" ) ;
}
2008-02-08 15:20:54 +03:00
# check for RCS/CVS revision markers
2008-03-05 01:28:20 +03:00
if ( $ rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "CVS_KEYWORD" ,
"CVS style keyword markers, these will _not_ be updated\n" . $ herecurr ) ;
2008-02-08 15:20:54 +03:00
}
2007-08-11 00:01:03 +04:00
2009-09-22 04:04:40 +04:00
# Blackfin: don't use __builtin_bfin_[cs]sync
if ( $ line =~ /__builtin_bfin_csync/ ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
2011-07-26 04:13:25 +04:00
ERROR ( "CSYNC" ,
"use the CSYNC() macro in asm/blackfin.h\n" . $ herevet ) ;
2009-09-22 04:04:40 +04:00
}
if ( $ line =~ /__builtin_bfin_ssync/ ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
2011-07-26 04:13:25 +04:00
ERROR ( "SSYNC" ,
"use the SSYNC() macro in asm/blackfin.h\n" . $ herevet ) ;
2009-09-22 04:04:40 +04:00
}
2013-02-22 04:44:14 +04:00
# check for old HOTPLUG __dev<foo> section markings
if ( $ line =~ /\b(__dev(init|exit)(data|const|))\b/ ) {
WARN ( "HOTPLUG_SECTION" ,
"Using $1 is unnecessary\n" . $ herecurr ) ;
}
2007-10-17 10:29:38 +04:00
# Check for potential 'bare' types
2009-10-27 02:50:16 +03:00
my ( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ,
$ realline_next ) ;
2012-01-11 03:10:01 +04:00
#print "LINE<$line>\n";
if ( $ linenr >= $ suppress_statement &&
$ realcnt && $ line =~ /.\s*\S/ ) {
2008-10-16 09:02:30 +04:00
( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ) =
2008-07-24 08:29:03 +04:00
ctx_statement_block ( $ linenr , $ realcnt , 0 ) ;
2008-04-29 11:59:32 +04:00
$ stat =~ s/\n./\n /g ;
$ cond =~ s/\n./\n /g ;
2012-01-11 03:10:01 +04:00
#print "linenr<$linenr> <$stat>\n";
# If this statement has no statement boundaries within
# it there is no point in retrying a statement scan
# until we hit end of it.
my $ frag = $ stat ; $ frag =~ s/;+\s*$// ;
if ( $ frag !~ /(?:{|;)/ ) {
#print "skip<$line_nr_next>\n";
$ suppress_statement = $ line_nr_next ;
}
2012-01-11 03:09:54 +04:00
2009-10-27 02:50:16 +03:00
# Find the real next line.
$ realline_next = $ line_nr_next ;
if ( defined $ realline_next &&
( ! defined $ lines [ $ realline_next - 1 ] ||
substr ( $ lines [ $ realline_next - 1 ] , $ off_next ) =~ /^\s*$/ ) ) {
$ realline_next + + ;
}
2008-04-29 11:59:32 +04:00
my $ s = $ stat ;
$ s =~ s/{.*$//s ;
2008-03-05 01:28:20 +03:00
2008-02-08 15:20:54 +03:00
# Ignore goto labels.
2008-04-29 11:59:32 +04:00
if ( $ s =~ /$Ident:\*$/s ) {
2008-02-08 15:20:54 +03:00
# Ignore functions being called
2008-04-29 11:59:32 +04:00
} elsif ( $ s =~ /^.\s*$Ident\s*\(/s ) {
2008-02-08 15:20:54 +03:00
2009-09-22 04:04:34 +04:00
} elsif ( $ s =~ /^.\s*else\b/s ) {
2008-06-06 09:46:01 +04:00
# declarations always start with types
2008-07-24 08:29:09 +04:00
} elsif ( $ prev_values eq 'E' && $ s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s ) {
2008-06-06 09:46:01 +04:00
my $ type = $ 1 ;
$ type =~ s/\s+/ /g ;
possible ( $ type , "A:" . $ s ) ;
2007-11-29 03:21:06 +03:00
# definitions in global scope can only start with types
2008-10-16 09:02:30 +04:00
} elsif ( $ s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s ) {
2008-06-06 09:46:01 +04:00
possible ( $ 1 , "B:" . $ s ) ;
2008-02-08 15:20:54 +03:00
}
2007-11-29 03:21:06 +03:00
# any (foo ... *) is a pointer cast, and foo is a type
2009-01-07 01:41:21 +03:00
while ( $ s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg ) {
2008-06-06 09:46:01 +04:00
possible ( $ 1 , "C:" . $ s ) ;
2007-11-29 03:21:06 +03:00
}
# Check for any sort of function declaration.
# int foo(something bar, other baz);
# void (*store_gdt)(x86_descr_ptr *);
2008-04-29 11:59:32 +04:00
if ( $ prev_values eq 'E' && $ s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s ) {
2007-11-29 03:21:06 +03:00
my ( $ name_len ) = length ( $ 1 ) ;
2008-03-05 01:28:20 +03:00
my $ ctx = $ s ;
2008-03-29 00:15:58 +03:00
substr ( $ ctx , 0 , $ name_len + 1 , '' ) ;
2007-11-29 03:21:06 +03:00
$ ctx =~ s/\)[^\)]*$// ;
2008-03-05 01:28:20 +03:00
2007-11-29 03:21:06 +03:00
for my $ arg ( split ( /\s*,\s*/ , $ ctx ) ) {
2008-06-06 09:46:01 +04:00
if ( $ arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $ arg =~ /^($Ident)$/s ) {
2007-11-29 03:21:06 +03:00
2008-06-06 09:46:01 +04:00
possible ( $ 1 , "D:" . $ s ) ;
2007-11-29 03:21:06 +03:00
}
}
2007-10-17 10:29:38 +04:00
}
2007-11-29 03:21:06 +03:00
2007-10-17 10:29:38 +04:00
}
2007-06-24 04:16:34 +04:00
#
# Checks which may be anchored in the context.
#
2007-06-09 00:47:06 +04:00
2007-06-24 04:16:34 +04:00
# Check for switch () and associated case and default
# statements should be at the same indent.
2007-06-09 00:47:06 +04:00
if ( $ line =~ /\bswitch\s*\(.*\)/ ) {
my $ err = '' ;
my $ sep = '' ;
my @ ctx = ctx_block_outer ( $ linenr , $ realcnt ) ;
shift ( @ ctx ) ;
for my $ ctx ( @ ctx ) {
my ( $ clen , $ cindent ) = line_stats ( $ ctx ) ;
if ( $ ctx =~ /^\+\s*(case\s+|default:)/ &&
$ indent != $ cindent ) {
$ err . = "$sep$ctx\n" ;
$ sep = '' ;
} else {
$ sep = "[...]\n" ;
}
}
if ( $ err ne '' ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SWITCH_CASE_INDENT_LEVEL" ,
"switch and case should be at the same indent\n$hereline$err" ) ;
2007-07-16 10:37:22 +04:00
}
}
# 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
2008-06-06 09:46:01 +04:00
if ( $ line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $ line !~ /^.\s*\#/ ) {
2008-03-29 00:15:58 +03:00
my $ pre_ctx = "$1$2" ;
2007-10-17 10:29:38 +04:00
my ( $ level , @ ctx ) = ctx_statement_level ( $ linenr , $ realcnt , 0 ) ;
2012-02-04 03:20:39 +04:00
if ( $ line =~ /^\+\t{6,}/ ) {
WARN ( "DEEP_INDENTATION" ,
"Too many leading tabs - consider code refactoring\n" . $ herecurr ) ;
}
2007-07-16 10:37:22 +04:00
my $ ctx_cnt = $ realcnt - $# ctx - 1 ;
my $ ctx = join ( "\n" , @ ctx ) ;
2008-07-24 08:29:01 +04:00
my $ ctx_ln = $ linenr ;
my $ ctx_skip = $ realcnt ;
2008-03-29 00:15:58 +03:00
2008-07-24 08:29:01 +04:00
while ( $ ctx_skip > $ ctx_cnt || ( $ ctx_skip == $ ctx_cnt &&
defined $ lines [ $ ctx_ln - 1 ] &&
$ lines [ $ ctx_ln - 1 ] =~ /^-/ ) ) {
##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
$ ctx_skip - - if ( ! defined $ lines [ $ ctx_ln - 1 ] || $ lines [ $ ctx_ln - 1 ] !~ /^-/ ) ;
2007-07-16 10:37:22 +04:00
$ ctx_ln + + ;
}
2008-07-24 08:29:01 +04:00
2008-07-24 08:29:03 +04:00
#print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
#print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
2007-07-16 10:37:22 +04:00
2008-03-29 00:15:58 +03:00
if ( $ ctx !~ /{\s*/ && defined ( $ lines [ $ ctx_ln - 1 ] ) && $ lines [ $ ctx_ln - 1 ] =~ /^\+\s*{/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "OPEN_BRACE" ,
"that open brace { should be on the previous line\n" .
2010-10-27 01:23:19 +04:00
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n" ) ;
2007-06-09 00:47:06 +04:00
}
2008-03-29 00:15:58 +03:00
if ( $ level == 0 && $ pre_ctx !~ /}\s*while\s*\($/ &&
$ ctx =~ /\)\s*\;\s*$/ &&
defined $ lines [ $ ctx_ln - 1 ] )
{
2007-10-17 10:29:38 +04:00
my ( $ nlength , $ nindent ) = line_stats ( $ lines [ $ ctx_ln - 1 ] ) ;
if ( $ nindent > $ indent ) {
2011-07-26 04:13:25 +04:00
WARN ( "TRAILING_SEMICOLON" ,
"trailing semicolon indicates no statements, indent implies otherwise\n" .
2010-10-27 01:23:19 +04:00
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n" ) ;
2007-10-17 10:29:38 +04:00
}
}
2007-06-09 00:47:06 +04:00
}
2008-10-16 09:02:21 +04:00
# Check relative indent for conditionals and blocks.
if ( $ line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $ line !~ /^.\s*#/ && $ line !~ /\}\s*while\s*/ ) {
2012-01-11 03:10:01 +04:00
( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ) =
ctx_statement_block ( $ linenr , $ realcnt , 0 )
if ( ! defined $ stat ) ;
2008-10-16 09:02:21 +04:00
my ( $ s , $ c ) = ( $ stat , $ cond ) ;
substr ( $ s , 0 , length ( $ c ) , '' ) ;
# Make sure we remove the line prefixes as we have
# none on the first line, and are going to readd them
# where necessary.
$ s =~ s/\n./\n/gs ;
# Find out how long the conditional actually is.
2008-10-16 09:02:27 +04:00
my @ newlines = ( $ c =~ /\n/gs ) ;
my $ cond_lines = 1 + $# newlines ;
2008-10-16 09:02:21 +04:00
# We want to check the first line inside the block
# starting at the end of the conditional, so remove:
# 1) any blank line termination
# 2) any opening brace { on end of the line
# 3) any do (...) {
my $ continuation = 0 ;
my $ check = 0 ;
$ s =~ s/^.*\bdo\b// ;
$ s =~ s/^\s*{// ;
if ( $ s =~ s/^\s*\\// ) {
$ continuation = 1 ;
}
2008-10-16 09:02:22 +04:00
if ( $ s =~ s/^\s*?\n// ) {
2008-10-16 09:02:21 +04:00
$ check = 1 ;
$ cond_lines + + ;
}
# Also ignore a loop construct at the end of a
# preprocessor statement.
if ( ( $ prevline =~ /^.\s*#\s*define\s/ ||
$ prevline =~ /\\\s*$/ ) && $ continuation == 0 ) {
$ check = 0 ;
}
2008-10-16 09:02:22 +04:00
my $ cond_ptr = - 1 ;
2008-10-16 09:02:35 +04:00
$ continuation = 0 ;
2008-10-16 09:02:22 +04:00
while ( $ cond_ptr != $ cond_lines ) {
$ cond_ptr = $ cond_lines ;
2008-10-16 09:02:32 +04:00
# If we see an #else/#elif then the code
# is not linear.
if ( $ s =~ /^\s*\#\s*(?:else|elif)/ ) {
$ check = 0 ;
}
2008-10-16 09:02:22 +04:00
# Ignore:
# 1) blank lines, they should be at 0,
# 2) preprocessor lines, and
# 3) labels.
2008-10-16 09:02:35 +04:00
if ( $ continuation ||
$ s =~ /^\s*?\n/ ||
2008-10-16 09:02:22 +04:00
$ s =~ /^\s*#\s*?/ ||
$ s =~ /^\s*$Ident\s*:/ ) {
2008-10-16 09:02:35 +04:00
$ continuation = ( $ s =~ /^.*?\\\n/ ) ? 1 : 0 ;
2009-09-22 04:04:36 +04:00
if ( $ s =~ s/^.*?\n// ) {
$ cond_lines + + ;
}
2008-10-16 09:02:22 +04:00
}
2008-10-16 09:02:21 +04:00
}
my ( undef , $ sindent ) = line_stats ( "+" . $ s ) ;
my $ stat_real = raw_line ( $ linenr , $ cond_lines ) ;
# Check if either of these lines are modified, else
# this is not this patch's fault.
if ( ! defined ( $ stat_real ) ||
$ stat !~ /^\+/ && $ stat_real !~ /^\+/ ) {
$ check = 0 ;
}
if ( defined ( $ stat_real ) && $ cond_lines > 1 ) {
$ stat_real = "[...]\n$stat_real" ;
}
2008-10-16 09:02:22 +04:00
#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
2008-10-16 09:02:21 +04:00
if ( $ check && ( ( $ sindent % 8 ) != 0 ||
( $ sindent <= $ indent && $ s ne '' ) ) ) {
2011-07-26 04:13:25 +04:00
WARN ( "SUSPECT_CODE_INDENT" ,
"suspect code indent for conditional statements ($indent, $sindent)\n" . $ herecurr . "$stat_real\n" ) ;
2008-10-16 09:02:21 +04:00
}
}
2007-10-18 14:05:08 +04:00
# Track the 'values' across context and added lines.
my $ opline = $ line ; $ opline =~ s/^./ / ;
2008-07-24 08:29:10 +04:00
my ( $ curr_values , $ curr_vars ) =
annotate_values ( $ opline . "\n" , $ prev_values ) ;
2007-10-18 14:05:08 +04:00
$ curr_values = $ prev_values . $ curr_values ;
2008-02-08 15:20:54 +03:00
if ( $ dbg_values ) {
my $ outline = $ opline ; $ outline =~ s/\t/ /g ;
2008-03-05 01:28:20 +03:00
print "$linenr > .$outline\n" ;
print "$linenr > $curr_values\n" ;
2008-07-24 08:29:10 +04:00
print "$linenr > $curr_vars\n" ;
2008-02-08 15:20:54 +03:00
}
2007-10-18 14:05:08 +04:00
$ prev_values = substr ( $ curr_values , - 1 ) ;
2007-06-09 00:47:06 +04:00
#ignore lines not being added
if ( $ line =~ /^[^\+]/ ) { next ; }
2007-06-24 04:16:34 +04:00
# TEST: allow direct testing of the type matcher.
2008-07-24 08:29:06 +04:00
if ( $ dbg_type ) {
if ( $ line =~ /^.\s*$Declare\s*$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "TEST_TYPE" ,
"TEST: is type\n" . $ herecurr ) ;
2008-07-24 08:29:06 +04:00
} elsif ( $ dbg_type > 1 && $ line =~ /^.+($Declare)/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "TEST_NOT_TYPE" ,
"TEST: is not type ($1 is)\n" . $ herecurr ) ;
2008-07-24 08:29:06 +04:00
}
2007-06-24 04:16:34 +04:00
next ;
}
2008-10-16 09:02:17 +04:00
# TEST: allow direct testing of the attribute matcher.
if ( $ dbg_attr ) {
2009-02-28 01:03:08 +03:00
if ( $ line =~ /^.\s*$Modifier\s*$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "TEST_ATTR" ,
"TEST: is attr\n" . $ herecurr ) ;
2009-02-28 01:03:08 +03:00
} elsif ( $ dbg_attr > 1 && $ line =~ /^.+($Modifier)/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "TEST_NOT_ATTR" ,
"TEST: is not attr ($1 is)\n" . $ herecurr ) ;
2008-10-16 09:02:17 +04:00
}
next ;
}
2007-06-24 04:16:34 +04:00
2007-07-19 12:48:34 +04:00
# check for initialisation to aggregates open brace on the next line
2009-10-27 02:50:15 +03:00
if ( $ line =~ /^.\s*{/ &&
$ prevline =~ /(?:^|[^=])=\s*$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "OPEN_BRACE" ,
"that open brace { should be on the previous line\n" . $ hereprev ) ;
2007-07-19 12:48:34 +04:00
}
2007-06-24 04:16:34 +04:00
#
# Checks which are anchored on the added line.
#
# check for malformed paths in #include statements (uses RAW line)
2008-06-06 09:46:01 +04:00
if ( $ rawline =~ m {^.\s*\#\s*include\s+[<"](.*)[">]} ) {
2007-06-24 04:16:34 +04:00
my $ path = $ 1 ;
if ( $ path =~ m {//} ) {
2011-07-26 04:13:25 +04:00
ERROR ( "MALFORMED_INCLUDE" ,
2012-12-21 03:05:37 +04:00
"malformed #include filename\n" . $ herecurr ) ;
}
if ( $ path =~ "^uapi/" && $ realfile =~ m @\binclude/uapi/@ ) {
ERROR ( "UAPI_INCLUDE" ,
"No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $ herecurr ) ;
2007-06-24 04:16:34 +04:00
}
}
2007-06-09 00:47:06 +04:00
2007-06-01 11:46:48 +04:00
# no C99 // comments
2007-06-09 00:47:06 +04:00
if ( $ line =~ m {//} ) {
2011-07-26 04:13:25 +04:00
ERROR ( "C99_COMMENTS" ,
"do not use C99 // comments\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-06-09 00:47:06 +04:00
# Remove C99 comments.
2007-06-01 11:46:48 +04:00
$ line =~ s@//.*@@ ;
2007-10-18 14:05:08 +04:00
$ opline =~ s@//.*@@ ;
2007-06-01 11:46:48 +04:00
2009-10-27 02:50:16 +03:00
# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
# the whole statement.
#print "APW <$lines[$realline_next - 1]>\n";
if ( defined $ realline_next &&
exists $ lines [ $ realline_next - 1 ] &&
! defined $ suppress_export { $ realline_next } &&
( $ lines [ $ realline_next - 1 ] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
$ lines [ $ realline_next - 1 ] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/ ) ) {
2010-10-27 01:23:18 +04:00
# Handle definitions which produce identifiers with
# a prefix:
# XXX(foo);
# EXPORT_SYMBOL(something_foo);
2007-06-24 04:16:34 +04:00
my $ name = $ 1 ;
2012-01-11 03:10:04 +04:00
if ( $ stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ &&
2010-10-27 01:23:18 +04:00
$ name =~ /^${Ident}_$2/ ) {
#print "FOO C name<$name>\n";
$ suppress_export { $ realline_next } = 1 ;
} elsif ( $ stat !~ / ( ? :
2009-10-27 02:50:16 +03:00
\ n . } \ s * $|
2008-10-16 09:02:34 +04:00
^ . DEFINE_ $ Ident \ ( \ Q $ name \ E \ ) |
^ . DECLARE_ $ Ident \ ( \ Q $ name \ E \ ) |
^ . LIST_HEAD \ ( \ Q $ name \ E \ ) |
2009-10-27 02:50:16 +03:00
^ . ( ? : $ Storage \ s + ) ? $ Type \ s * \ ( \ s * \ * \ s * \ Q $ name \ E \ s * \ ) \ s * \ ( |
\ b \ Q $ name \ E ( ? : \ s + $ Attribute ) * \ s * ( ? : ; |= | \ [ | \ ( )
2008-10-16 09:02:34 +04:00
) / x ) {
2009-10-27 02:50:16 +03:00
#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
$ suppress_export { $ realline_next } = 2 ;
} else {
$ suppress_export { $ realline_next } = 1 ;
2007-06-01 11:46:48 +04:00
}
}
2009-10-27 02:50:16 +03:00
if ( ! defined $ suppress_export { $ linenr } &&
$ prevline =~ /^.\s*$/ &&
( $ line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
$ line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/ ) ) {
#print "FOO B <$lines[$linenr - 1]>\n";
$ suppress_export { $ linenr } = 2 ;
}
if ( defined $ suppress_export { $ linenr } &&
$ suppress_export { $ linenr } == 2 ) {
2011-07-26 04:13:25 +04:00
WARN ( "EXPORT_SYMBOL" ,
"EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $ herecurr ) ;
2009-10-27 02:50:16 +03:00
}
2007-06-01 11:46:48 +04:00
2010-08-10 04:21:00 +04:00
# check for global initialisers.
2008-06-06 09:46:01 +04:00
if ( $ line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "GLOBAL_INITIALISERS" ,
"do not initialise globals to 0 or NULL\n" .
2007-07-19 12:48:34 +04:00
$ herecurr ) ;
}
2007-06-24 04:16:34 +04:00
# check for static initialisers.
2009-01-07 01:41:28 +03:00
if ( $ line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "INITIALISED_STATIC" ,
"do not initialise statics to 0 or NULL\n" .
2007-07-16 10:37:22 +04:00
$ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2010-10-27 01:23:20 +04:00
# check for static const char * arrays.
if ( $ line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "STATIC_CONST_CHAR_ARRAY" ,
"static const char * array should probably be static const char * const\n" .
2010-10-27 01:23:20 +04:00
$ herecurr ) ;
}
# check for static char foo[] = "bar" declarations.
if ( $ line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "STATIC_CONST_CHAR_ARRAY" ,
"static char array declaration should probably be static const char\n" .
2010-10-27 01:23:20 +04:00
$ herecurr ) ;
}
2010-10-27 01:23:21 +04:00
# check for declarations of struct pci_device_id
if ( $ line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "DEFINE_PCI_DEVICE_TABLE" ,
"Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $ herecurr ) ;
2010-10-27 01:23:21 +04:00
}
2007-06-24 04:16:34 +04:00
# check for new typedefs, only function parameters and sparse annotations
# make sense.
if ( $ line =~ /\btypedef\s/ &&
2009-01-07 01:41:26 +03:00
$ line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
2008-06-06 09:46:01 +04:00
$ line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
2008-10-16 09:02:32 +04:00
$ line !~ /\b$typeTypedefs\b/ &&
2007-06-24 04:16:34 +04:00
$ line !~ /\b__bitwise(?:__|)\b/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "NEW_TYPEDEFS" ,
"do not add new typedefs\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
# * goes on variable not on type
2009-01-07 01:41:21 +03:00
# (char*[ const])
2012-01-11 03:10:15 +04:00
while ( $ line =~ m {(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g ) {
#print "AA<$1>\n";
my ( $ from , $ to ) = ( $ 2 , $ 2 ) ;
2009-01-07 01:41:21 +03:00
# Should start with a space.
$ to =~ s/^(\S)/ $1/ ;
# Should not end with a space.
$ to =~ s/\s+$// ;
# '*'s should not have spaces between.
2009-01-16 00:51:05 +03:00
while ( $ to =~ s/\*\s+\*/\*\*/ ) {
2009-01-07 01:41:21 +03:00
}
2007-06-24 04:16:44 +04:00
2009-01-07 01:41:21 +03:00
#print "from<$from> to<$to>\n";
if ( $ from ne $ to ) {
2011-07-26 04:13:25 +04:00
ERROR ( "POINTER_LOCATION" ,
"\"(foo$from)\" should be \"(foo$to)\"\n" . $ herecurr ) ;
2009-01-07 01:41:21 +03:00
}
2012-01-11 03:10:15 +04:00
}
while ( $ line =~ m {(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g ) {
#print "BB<$1>\n";
my ( $ from , $ to , $ ident ) = ( $ 2 , $ 2 , $ 3 ) ;
2009-01-07 01:41:21 +03:00
# Should start with a space.
$ to =~ s/^(\S)/ $1/ ;
# Should not end with a space.
$ to =~ s/\s+$// ;
# '*'s should not have spaces between.
2009-01-16 00:51:05 +03:00
while ( $ to =~ s/\*\s+\*/\*\*/ ) {
2009-01-07 01:41:21 +03:00
}
# Modifiers should have spaces.
$ to =~ s/(\b$Modifier$)/$1 / ;
2007-06-24 04:16:44 +04:00
2009-02-28 01:03:08 +03:00
#print "from<$from> to<$to> ident<$ident>\n";
if ( $ from ne $ to && $ ident !~ /^$Modifier$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "POINTER_LOCATION" ,
"\"foo${from}bar\" should be \"foo${to}bar\"\n" . $ herecurr ) ;
2009-01-07 01:41:21 +03:00
}
2007-06-01 11:46:48 +04:00
}
# # no BUG() or BUG_ON()
# if ($line =~ /\b(BUG|BUG_ON)\b/) {
# print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
# print "$herecurr";
# $clean = 0;
# }
2007-11-29 03:21:06 +03:00
if ( $ line =~ /\bLINUX_VERSION_CODE\b/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "LINUX_VERSION_CODE" ,
"LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $ herecurr ) ;
2007-11-29 03:21:06 +03:00
}
2011-06-16 02:08:17 +04:00
# check for uses of printk_ratelimit
if ( $ line =~ /\bprintk_ratelimit\s*\(/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "PRINTK_RATELIMITED" ,
"Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $ herecurr ) ;
2011-06-16 02:08:17 +04:00
}
2007-06-09 00:47:06 +04:00
# printk should use KERN_* levels. Note that follow on printk's on the
# same line do not need a level, so we use the current block context
# to try and find and validate the current printk. In summary the current
2011-03-31 05:57:33 +04:00
# printk includes all preceding printk's which have no newline on the end.
2007-06-09 00:47:06 +04:00
# we assume the first bad printk is the one to report.
2007-07-19 12:48:34 +04:00
if ( $ line =~ /\bprintk\((?!KERN_)\s*"/ ) {
2007-06-09 00:47:06 +04:00
my $ ok = 0 ;
for ( my $ ln = $ linenr - 1 ; $ ln >= $ first_line ; $ ln - - ) {
#print "CHECK<$lines[$ln - 1]\n";
2011-03-31 05:57:33 +04:00
# we have a preceding printk if it ends
2007-06-09 00:47:06 +04:00
# with "\n" ignore it, else it is to blame
if ( $ lines [ $ ln - 1 ] =~ m {\bprintk\(} ) {
if ( $ rawlines [ $ ln - 1 ] !~ m {\\n"} ) {
$ ok = 1 ;
}
last ;
}
}
if ( $ ok == 0 ) {
2011-07-26 04:13:25 +04:00
WARN ( "PRINTK_WITHOUT_KERN_LEVEL" ,
"printk() should include KERN_ facility level\n" . $ herecurr ) ;
2007-06-09 00:47:06 +04:00
}
2007-06-01 11:46:48 +04:00
}
2012-06-01 03:26:09 +04:00
if ( $ line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/ ) {
my $ orig = $ 1 ;
my $ level = lc ( $ orig ) ;
$ level = "warn" if ( $ level eq "warning" ) ;
2012-10-05 04:13:32 +04:00
my $ level2 = $ level ;
$ level2 = "dbg" if ( $ level eq "debug" ) ;
2012-06-01 03:26:09 +04:00
WARN ( "PREFER_PR_LEVEL" ,
2012-10-05 04:13:32 +04:00
"Prefer netdev_$level2(netdev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $ herecurr ) ;
2012-06-01 03:26:09 +04:00
}
if ( $ line =~ /\bpr_warning\s*\(/ ) {
WARN ( "PREFER_PR_LEVEL" ,
"Prefer pr_warn(... to pr_warning(...\n" . $ herecurr ) ;
}
2013-02-22 04:44:13 +04:00
if ( $ line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/ ) {
my $ orig = $ 1 ;
my $ level = lc ( $ orig ) ;
$ level = "warn" if ( $ level eq "warning" ) ;
$ level = "dbg" if ( $ level eq "debug" ) ;
WARN ( "PREFER_DEV_LEVEL" ,
"Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $ herecurr ) ;
}
2007-06-24 04:16:34 +04:00
# function brace can't be on same line, except for #defines of do while,
# or if closed on same line
2008-06-06 09:46:01 +04:00
if ( ( $ line =~ /$Type\s*$Ident\(.*\).*\s{/ ) and
! ( $ line =~ /\#\s*define.*do\s{/ ) and ! ( $ line =~ /}/ ) ) {
2011-07-26 04:13:25 +04:00
ERROR ( "OPEN_BRACE" ,
"open brace '{' following function declarations go on the next line\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-06-24 04:16:34 +04:00
2007-11-29 03:21:06 +03:00
# open braces for enum, union and struct go on the same line.
if ( $ line =~ /^.\s*{/ &&
$ prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "OPEN_BRACE" ,
"open brace '{' following $1 go on the same line\n" . $ hereprev ) ;
2007-11-29 03:21:06 +03:00
}
2010-10-27 01:23:15 +04:00
# missing space after union, struct or enum definition
if ( $ line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "SPACING" ,
"missing space after $1 definition\n" . $ herecurr ) ;
2010-10-27 01:23:15 +04:00
}
2008-07-24 08:29:02 +04:00
# check for spacing round square brackets; allowed:
# 1. with a type on the left -- int [] a;
2008-10-16 09:02:15 +04:00
# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
# 3. inside a curly brace -- = { [0...10] = 5 }
2008-07-24 08:29:02 +04:00
while ( $ line =~ /(.*?\s)\[/g ) {
my ( $ where , $ prefix ) = ( $- [ 1 ] , $ 1 ) ;
if ( $ prefix !~ /$Type\s+$/ &&
2008-10-16 09:02:15 +04:00
( $ where != 0 || $ prefix !~ /^.\s+$/ ) &&
checkpatch: catch [ ... ] usage when not at the beginning of definition
Handle the [ A ... B ] form deeper into a definition, for example:
static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = {
{0, 0, 0, 0, 0, 0, 0, 27, 27, [9 ... PCI_MAX_DEVICES - 1] = 0 },
{0, 0, 0, 0, 0, 0, 0, 29, 29, [9 ... PCI_MAX_DEVICES - 1] = 0 },
};
Reported-by: Marek Vasut <marek.vasut@gmail.com>
Signed-off-by: Andy Whitcroft <apw@canonical.com>
Cc: Joe Perches <joe@perches.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-03-24 02:02:17 +04:00
$ prefix !~ /[{,]\s+$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "BRACKET_SPACE" ,
"space prohibited before open square bracket '['\n" . $ herecurr ) ;
2008-07-24 08:29:02 +04:00
}
}
2007-07-19 12:48:34 +04:00
# check for spaces between functions and their parentheses.
2007-10-18 14:05:08 +04:00
while ( $ line =~ /($Ident)\s+\(/g ) {
2008-02-08 15:20:54 +03:00
my $ name = $ 1 ;
2008-03-29 00:15:58 +03:00
my $ ctx_before = substr ( $ line , 0 , $- [ 1 ] ) ;
my $ ctx = "$ctx_before$name" ;
2008-02-08 15:20:54 +03:00
# Ignore those directives where spaces _are_ permitted.
2008-03-29 00:15:58 +03:00
if ( $ name =~ / ^ ( ? :
if | for | while | switch | return | case |
volatile | __volatile__ |
__attribute__ | format | __extension__ |
asm | __asm__ ) $ / x )
{
2008-02-08 15:20:54 +03:00
# cpp #define statements have non-optional spaces, ie
# if there is a space between the name and the open
# parenthesis it is simply not a parameter group.
2008-06-06 09:46:01 +04:00
} elsif ( $ ctx_before =~ /^.\s*\#\s*define\s*$/ ) {
2008-03-29 00:15:58 +03:00
# cpp #elif statement condition may start with a (
2008-06-06 09:46:01 +04:00
} elsif ( $ ctx =~ /^.\s*\#\s*elif\s*$/ ) {
2008-02-08 15:20:54 +03:00
# If this whole things ends with a type its most
# likely a typedef for a function.
2008-03-29 00:15:58 +03:00
} elsif ( $ ctx =~ /$Type$/ ) {
2008-02-08 15:20:54 +03:00
} else {
2011-07-26 04:13:25 +04:00
WARN ( "SPACING" ,
"space prohibited between function name and open parenthesis '('\n" . $ herecurr ) ;
2007-10-18 14:05:08 +04:00
}
2007-07-19 12:48:34 +04:00
}
2012-06-01 03:26:09 +04:00
# check for whitespace before a non-naked semicolon
if ( $ line =~ /^\+.*\S\s+;/ ) {
CHK ( "SPACING" ,
"space prohibited before semicolon\n" . $ herecurr ) ;
}
2007-06-24 04:16:34 +04:00
# Check operator spacing.
2007-06-01 11:46:48 +04:00
if ( ! ( $ line =~ /\#\s*include/ ) ) {
2007-10-17 10:29:38 +04:00
my $ ops = qr{
<<=|> >= | <=|> = |= = | != |
\ += | -= | \ *= | \ /= | % = | \ ^ = | \ | = | & = |
= > | - > | <<|> > | <|> |= | ! | ~ |
2008-07-24 08:29:10 +04:00
&& | \ | \ || , | \ ^ | \ + \ + | - - | & | \ || \ + | - | \ * | \ / | % |
\ ? | :
2007-10-17 10:29:38 +04:00
} x ;
2008-03-05 01:28:20 +03:00
my @ elements = split ( /($ops|;)/ , $ opline ) ;
2007-06-09 00:47:06 +04:00
my $ off = 0 ;
2007-10-18 14:05:08 +04:00
my $ blank = copy_spacing ( $ opline ) ;
2007-06-01 11:46:48 +04:00
for ( my $ n = 0 ; $ n < $# elements ; $ n += 2 ) {
2007-06-09 00:46:39 +04:00
$ off += length ( $ elements [ $ n ] ) ;
2011-03-31 05:57:33 +04:00
# Pick up the preceding and succeeding characters.
2008-03-29 00:15:58 +03:00
my $ ca = substr ( $ opline , 0 , $ off ) ;
my $ cc = '' ;
if ( length ( $ opline ) >= ( $ off + length ( $ elements [ $ n + 1 ] ) ) ) {
$ cc = substr ( $ opline , $ off + length ( $ elements [ $ n + 1 ] ) ) ;
}
my $ cb = "$ca$;$cc" ;
2007-06-09 00:46:39 +04:00
my $ a = '' ;
$ a = 'V' if ( $ elements [ $ n ] ne '' ) ;
$ a = 'W' if ( $ elements [ $ n ] =~ /\s$/ ) ;
2008-03-05 01:28:20 +03:00
$ a = 'C' if ( $ elements [ $ n ] =~ /$;$/ ) ;
2007-06-09 00:46:39 +04:00
$ a = 'B' if ( $ elements [ $ n ] =~ /(\[|\()$/ ) ;
$ a = 'O' if ( $ elements [ $ n ] eq '' ) ;
2008-03-29 00:15:58 +03:00
$ a = 'E' if ( $ ca =~ /^\s*$/ ) ;
2007-06-09 00:46:39 +04:00
2007-06-01 11:46:48 +04:00
my $ op = $ elements [ $ n + 1 ] ;
2007-06-09 00:46:39 +04:00
my $ c = '' ;
2007-06-01 11:46:48 +04:00
if ( defined $ elements [ $ n + 2 ] ) {
2007-06-09 00:46:39 +04:00
$ c = 'V' if ( $ elements [ $ n + 2 ] ne '' ) ;
$ c = 'W' if ( $ elements [ $ n + 2 ] =~ /^\s/ ) ;
2008-03-05 01:28:20 +03:00
$ c = 'C' if ( $ elements [ $ n + 2 ] =~ /^$;/ ) ;
2007-06-09 00:46:39 +04:00
$ c = 'B' if ( $ elements [ $ n + 2 ] =~ /^(\)|\]|;)/ ) ;
$ c = 'O' if ( $ elements [ $ n + 2 ] eq '' ) ;
2009-01-07 01:41:27 +03:00
$ c = 'E' if ( $ elements [ $ n + 2 ] =~ /^\s*\\$/ ) ;
2007-06-09 00:46:39 +04:00
} else {
$ c = 'E' ;
2007-06-01 11:46:48 +04:00
}
2007-06-09 00:46:39 +04:00
my $ ctx = "${a}x${c}" ;
my $ at = "(ctx:$ctx)" ;
2007-10-18 14:05:08 +04:00
my $ ptr = substr ( $ blank , 0 , $ off ) . "^" ;
2007-07-16 10:37:22 +04:00
my $ hereptr = "$hereline$ptr\n" ;
2007-06-01 11:46:48 +04:00
2008-07-24 08:29:10 +04:00
# Pull out the value of this operator.
2007-10-18 14:05:08 +04:00
my $ op_type = substr ( $ curr_values , $ off + 1 , 1 ) ;
2007-06-01 11:46:48 +04:00
2008-07-24 08:29:10 +04:00
# Get the full operator variant.
my $ opv = $ op . substr ( $ curr_vars , $ off , 1 ) ;
2008-02-08 15:22:03 +03:00
# Ignore operators passed as parameters.
if ( $ op_type ne 'V' &&
$ ca =~ /\s$/ && $ cc =~ /^\s*,/ ) {
2008-03-05 01:28:20 +03:00
# # Ignore comments
# } elsif ($op =~ /^$;+$/) {
2008-02-08 15:22:03 +03:00
2007-06-24 04:16:44 +04:00
# ; should have either the end of line or a space or \ after it
2008-02-08 15:22:03 +03:00
} elsif ( $ op eq ';' ) {
2008-03-05 01:28:20 +03:00
if ( $ ctx !~ /.x[WEBC]/ &&
$ cc !~ /^\\/ && $ cc !~ /^;/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space required after that '$op' $at\n" . $ hereptr ) ;
2007-06-24 04:16:44 +04:00
}
# // is a comment
} elsif ( $ op eq '//' ) {
2007-06-01 11:46:48 +04:00
2008-07-24 08:29:10 +04:00
# No spaces for:
# ->
# : when part of a bitfield
} elsif ( $ op eq '->' || $ opv eq ':B' ) {
2007-06-09 00:46:39 +04:00
if ( $ ctx =~ /Wx.|.xW/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"spaces prohibited around that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
# , must have a space on the right.
} elsif ( $ op eq ',' ) {
2008-03-05 01:28:20 +03:00
if ( $ ctx !~ /.x[WEC]/ && $ cc !~ /^}/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space required after that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
2007-10-17 10:29:38 +04:00
# '*' as part of a type definition -- reported already.
2008-07-24 08:29:10 +04:00
} elsif ( $ opv eq '*_' ) {
2007-10-17 10:29:38 +04:00
#warn "'*' is part of type\n";
# unary operators should have a space before and
# none after. May be left adjacent to another
# unary operator, or a cast
} elsif ( $ op eq '!' || $ op eq '~' ||
2008-07-24 08:29:10 +04:00
$ opv eq '*U' || $ opv eq '-U' ||
2008-10-16 09:02:16 +04:00
$ opv eq '&U' || $ opv eq '&&U' ) {
2008-03-05 01:28:20 +03:00
if ( $ ctx !~ /[WEBC]x./ && $ ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space required before that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
2009-02-28 01:03:07 +03:00
if ( $ op eq '*' && $ cc =~ /\s*$Modifier\b/ ) {
2008-04-29 11:59:32 +04:00
# A unary '*' may be const
} elsif ( $ ctx =~ /.xW/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space prohibited after that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
# unary ++ and unary -- are allowed no space on one side.
} elsif ( $ op eq '++' or $ op eq '--' ) {
2008-03-29 00:15:58 +03:00
if ( $ ctx !~ /[WEOBC]x[^W]/ && $ ctx !~ /[^W]x[WOBEC]/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space required one side of that '$op' $at\n" . $ hereptr ) ;
2008-03-29 00:15:58 +03:00
}
if ( $ ctx =~ /Wx[BE]/ ||
( $ ctx =~ /Wx./ && $ cc =~ /^;/ ) ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space prohibited before that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
2008-03-29 00:15:58 +03:00
if ( $ ctx =~ /ExW/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space prohibited after that '$op' $at\n" . $ hereptr ) ;
2007-06-24 04:16:34 +04:00
}
2007-06-01 11:46:48 +04:00
2008-03-29 00:15:58 +03:00
2007-06-01 11:46:48 +04:00
# << and >> may either have or not have spaces both sides
2007-10-17 10:29:38 +04:00
} elsif ( $ op eq '<<' or $ op eq '>>' or
$ op eq '&' or $ op eq '^' or $ op eq '|' or
$ op eq '+' or $ op eq '-' or
2008-02-08 15:20:54 +03:00
$ op eq '*' or $ op eq '/' or
$ op eq '%' )
2007-06-01 11:46:48 +04:00
{
2008-03-29 00:15:58 +03:00
if ( $ ctx =~ /Wx[^WCE]|[^WCE]xW/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"need consistent spacing around '$op' $at\n" .
2007-07-16 10:37:22 +04:00
$ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
2008-07-24 08:29:10 +04:00
# A colon needs no spaces before when it is
# terminating a case value or a label.
} elsif ( $ opv eq ':C' || $ opv eq ':L' ) {
if ( $ ctx =~ /Wx./ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space prohibited before that '$op' $at\n" . $ hereptr ) ;
2008-07-24 08:29:10 +04:00
}
2007-06-01 11:46:48 +04:00
# All the others need spaces both sides.
2008-03-05 01:28:20 +03:00
} elsif ( $ ctx !~ /[EWC]x[CWE]/ ) {
2008-07-24 08:29:10 +04:00
my $ ok = 0 ;
2007-08-11 00:01:03 +04:00
# Ignore email addresses <foo@bar>
2008-07-24 08:29:10 +04:00
if ( ( $ op eq '<' &&
$ cc =~ /^\S+\@\S+>/ ) ||
( $ op eq '>' &&
$ ca =~ /<\S+\@\S+$/ ) )
{
$ ok = 1 ;
}
# Ignore ?:
if ( ( $ opv eq ':O' && $ ca =~ /\?$/ ) ||
( $ op eq '?' && $ cc =~ /^:/ ) ) {
$ ok = 1 ;
}
if ( $ ok == 0 ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"spaces required around that '$op' $at\n" . $ hereptr ) ;
2007-08-11 00:01:03 +04:00
}
2007-06-01 11:46:48 +04:00
}
2007-06-09 00:46:39 +04:00
$ off += length ( $ elements [ $ n + 1 ] ) ;
2007-06-01 11:46:48 +04:00
}
}
2007-07-19 12:48:34 +04:00
# check for multiple assignments
if ( $ line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/ ) {
2011-07-26 04:13:25 +04:00
CHK ( "MULTIPLE_ASSIGNMENTS" ,
"multiple assignments should be avoided\n" . $ herecurr ) ;
2007-07-19 12:48:34 +04:00
}
2007-08-11 00:01:03 +04:00
## # check for multiple declarations, allowing for a function declaration
## # continuation.
## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
##
## # Remove any bracketed sections to ensure we do not
## # falsly report the parameters of functions.
## my $ln = $line;
## while ($ln =~ s/\([^\(\)]*\)//g) {
## }
## if ($ln =~ /,/) {
2011-07-26 04:13:25 +04:00
## WARN("MULTIPLE_DECLARATION",
## "declaring multiple variables together should be avoided\n" . $herecurr);
2007-08-11 00:01:03 +04:00
## }
## }
2007-07-19 12:48:34 +04:00
2007-06-01 11:46:48 +04:00
#need space before brace following if, while, etc
2007-08-11 00:01:03 +04:00
if ( ( $ line =~ /\(.*\){/ && $ line !~ /\($Type\){/ ) ||
$ line =~ /do{/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space required before the open brace '{'\n" . $ herecurr ) ;
2007-07-16 10:37:22 +04:00
}
# closing brace should have a space following it when it has anything
# on the line
if ( $ line =~ /}(?!(?:,|;|\)))\S/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space required after that close brace '}'\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-08-11 00:01:03 +04:00
# check spacing on square brackets
if ( $ line =~ /\[\s/ && $ line !~ /\[\s*$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space prohibited after that open square bracket '['\n" . $ herecurr ) ;
2007-08-11 00:01:03 +04:00
}
if ( $ line =~ /\s\]/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space prohibited before that close square bracket ']'\n" . $ herecurr ) ;
2007-08-11 00:01:03 +04:00
}
2008-06-06 09:46:01 +04:00
# check spacing on parentheses
2007-10-17 10:29:38 +04:00
if ( $ line =~ /\(\s/ && $ line !~ /\(\s*(?:\\)?$/ &&
$ line !~ /for\s*\(\s+;/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space prohibited after that open parenthesis '('\n" . $ herecurr ) ;
2007-08-11 00:01:03 +04:00
}
2008-02-08 15:22:03 +03:00
if ( $ line =~ /(\s+)\)/ && $ line !~ /^.\s*\)/ &&
2008-06-06 09:46:01 +04:00
$ line !~ /for\s*\(.*;\s+\)/ &&
$ line !~ /:\s+\)/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space prohibited before that close parenthesis ')'\n" . $ herecurr ) ;
2007-08-11 00:01:03 +04:00
}
2007-06-01 11:46:48 +04:00
#goto labels aren't indented, allow a single space however
2007-06-09 00:46:39 +04:00
if ( $ line =~ /^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
2007-06-01 11:46:48 +04:00
! ( $ line =~ /^. [A-Za-z\d_]+:/ ) and ! ( $ line =~ /^.\s+default:/ ) ) {
2011-07-26 04:13:25 +04:00
WARN ( "INDENTED_LABEL" ,
"labels should not be indented\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2008-06-06 09:46:01 +04:00
# Return is not a function.
if ( defined ( $ stat ) && $ stat =~ /^.\s*return(\s*)(\(.*);/s ) {
my $ spacing = $ 1 ;
my $ value = $ 2 ;
2009-01-07 01:41:24 +03:00
# Flatten any parentheses
2010-10-27 01:23:12 +04:00
$ value =~ s/\(/ \(/g ;
$ value =~ s/\)/\) /g ;
2012-01-11 03:10:08 +04:00
while ( $ value =~ s/\[[^\[\]]*\]/1/ ||
2009-01-16 00:51:06 +03:00
$ value !~ / ( ? : $ Ident | - ? $ Constant ) \ s *
$ Compare \ s *
( ? : $ Ident | - ? $ Constant ) / x &&
$ value =~ s/\([^\(\)]*\)/1/ ) {
2008-06-06 09:46:01 +04:00
}
2010-10-27 01:23:12 +04:00
#print "value<$value>\n";
if ( $ value =~ /^\s*(?:$Ident|-?$Constant)\s*$/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "RETURN_PARENTHESES" ,
"return is not a function, parentheses are not required\n" . $ herecurr ) ;
2008-06-06 09:46:01 +04:00
} elsif ( $ spacing !~ /\s+/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"space required before the open parenthesis '('\n" . $ herecurr ) ;
2008-06-06 09:46:01 +04:00
}
}
2010-10-27 01:23:14 +04:00
# Return of what appears to be an errno should normally be -'ve
if ( $ line =~ /^.\s*return\s*(E[A-Z]*)\s*;/ ) {
my $ name = $ 1 ;
if ( $ name ne 'EOF' && $ name ne 'ERROR' ) {
2011-07-26 04:13:25 +04:00
WARN ( "USE_NEGATIVE_ERRNO" ,
"return of an errno should typically be -ve (return -$1)\n" . $ herecurr ) ;
2010-10-27 01:23:14 +04:00
}
}
2008-06-06 09:46:01 +04:00
2007-06-01 11:46:48 +04:00
# Need a space before open parenthesis after if, while etc
2007-06-09 00:46:39 +04:00
if ( $ line =~ /\b(if|while|for|switch)\(/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" , "space required before the open parenthesis '('\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2008-07-24 08:29:03 +04:00
# Check for illegal assignment in if conditional -- and check for trailing
# statements after the conditional.
2008-10-16 09:02:30 +04:00
if ( $ line =~ /do\s*(?!{)/ ) {
2012-01-11 03:10:01 +04:00
( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ) =
ctx_statement_block ( $ linenr , $ realcnt , 0 )
if ( ! defined $ stat ) ;
2008-10-16 09:02:30 +04:00
my ( $ stat_next ) = ctx_statement_block ( $ line_nr_next ,
$ remain_next , $ off_next ) ;
$ stat_next =~ s/\n./\n /g ;
##print "stat<$stat> stat_next<$stat_next>\n";
if ( $ stat_next =~ /^\s*while\b/ ) {
# If the statement carries leading newlines,
# then count those as offsets.
my ( $ whitespace ) =
( $ stat_next =~ /^((?:\s*\n[+-])*\s*)/s ) ;
my $ offset =
statement_rawlines ( $ whitespace ) - 1 ;
$ suppress_whiletrailers { $ line_nr_next +
$ offset } = 1 ;
}
}
if ( ! defined $ suppress_whiletrailers { $ linenr } &&
$ line =~ /\b(?:if|while|for)\s*\(/ && $ line !~ /^.\s*#/ ) {
2008-04-29 11:59:32 +04:00
my ( $ s , $ c ) = ( $ stat , $ cond ) ;
2007-11-29 03:21:06 +03:00
2009-01-07 01:41:29 +03:00
if ( $ c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s ) {
2011-07-26 04:13:25 +04:00
ERROR ( "ASSIGN_IN_IF" ,
"do not use assignment in if condition\n" . $ herecurr ) ;
2007-11-29 03:21:06 +03:00
}
# Find out what is on the end of the line after the
# conditional.
2008-03-29 00:15:58 +03:00
substr ( $ s , 0 , length ( $ c ) , '' ) ;
2007-11-29 03:21:06 +03:00
$ s =~ s/\n.*//g ;
2008-02-08 15:22:03 +03:00
$ s =~ s/$;//g ; # Remove any comments
2008-07-24 08:29:03 +04:00
if ( length ( $ c ) && $ s !~ /^\s*{?\s*\\*\s*$/ &&
$ c !~ /}\s*while\s*/ )
2008-03-29 00:15:58 +03:00
{
2008-10-16 09:02:34 +04:00
# Find out how long the conditional actually is.
my @ newlines = ( $ c =~ /\n/gs ) ;
my $ cond_lines = 1 + $# newlines ;
2010-03-06 00:43:50 +03:00
my $ stat_real = '' ;
2008-10-16 09:02:34 +04:00
2010-03-06 00:43:50 +03:00
$ stat_real = raw_line ( $ linenr , $ cond_lines )
. "\n" if ( $ cond_lines ) ;
2008-10-16 09:02:34 +04:00
if ( defined ( $ stat_real ) && $ cond_lines > 1 ) {
$ stat_real = "[...]\n$stat_real" ;
}
2011-07-26 04:13:25 +04:00
ERROR ( "TRAILING_STATEMENTS" ,
"trailing statements should be on next line\n" . $ herecurr . $ stat_real ) ;
2007-11-29 03:21:06 +03:00
}
}
2008-02-08 15:22:03 +03:00
# Check for bitwise tests written as boolean
if ( $ line =~ /
( ? :
( ? : \ [ | \ ( | \ & \ & | \ | \ | )
\ s * 0 [ xX ] [ 0 - 9 ] + \ s *
( ? : \ & \ & | \ | \ | )
|
( ? : \ & \ & | \ | \ | )
\ s * 0 [ xX ] [ 0 - 9 ] + \ s *
( ? : \ & \ & | \ | \ || \ ) | \ ] )
) / x )
{
2011-07-26 04:13:25 +04:00
WARN ( "HEXADECIMAL_BOOLEAN_TEST" ,
"boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $ herecurr ) ;
2008-02-08 15:22:03 +03:00
}
2007-11-29 03:21:06 +03:00
# if and else should not have general statements after it
2008-02-08 15:22:03 +03:00
if ( $ line =~ /^.\s*(?:}\s*)?else\b(.*)/ ) {
my $ s = $ 1 ;
$ s =~ s/$;//g ; # Remove any comments
if ( $ s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "TRAILING_STATEMENTS" ,
"trailing statements should be on next line\n" . $ herecurr ) ;
2008-02-08 15:22:03 +03:00
}
2007-06-01 11:46:48 +04:00
}
2009-01-16 00:51:06 +03:00
# if should not continue a brace
if ( $ line =~ /}\s*if\b/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "TRAILING_STATEMENTS" ,
"trailing statements should be on next line\n" .
2009-01-16 00:51:06 +03:00
$ herecurr ) ;
}
2008-10-16 09:02:25 +04:00
# case and default should not have general statements after them
if ( $ line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
$ line !~ / \ G ( ? :
2008-10-16 09:02:36 +04:00
( ? : \ s * $; * ) ( ? : \ s * { ) ? ( ? : \ s * $; * ) ( ? : \ s * \ \ ) ? \ s * $|
2008-10-16 09:02:25 +04:00
\ s * return \ s +
) / xg )
{
2011-07-26 04:13:25 +04:00
ERROR ( "TRAILING_STATEMENTS" ,
"trailing statements should be on next line\n" . $ herecurr ) ;
2008-10-16 09:02:25 +04:00
}
2007-06-01 11:46:48 +04:00
# Check for }<nl>else {, these must be at the same
# indent level to be relevant to each other.
if ( $ prevline =~ /}\s*$/ and $ line =~ /^.\s*else\s*/ and
$ previndent == $ indent ) {
2011-07-26 04:13:25 +04:00
ERROR ( "ELSE_AFTER_BRACE" ,
"else should follow close brace '}'\n" . $ hereprev ) ;
2007-06-01 11:46:48 +04:00
}
2008-02-08 15:20:54 +03:00
if ( $ prevline =~ /}\s*$/ and $ line =~ /^.\s*while\s*/ and
$ previndent == $ indent ) {
my ( $ s , $ c ) = ctx_statement_block ( $ linenr , $ realcnt , 0 ) ;
# Find out what is on the end of the line after the
# conditional.
2008-03-29 00:15:58 +03:00
substr ( $ s , 0 , length ( $ c ) , '' ) ;
2008-02-08 15:20:54 +03:00
$ s =~ s/\n.*//g ;
if ( $ s =~ /^\s*;/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "WHILE_AFTER_BRACE" ,
"while should follow close brace '}'\n" . $ hereprev ) ;
2008-02-08 15:20:54 +03:00
}
}
2012-12-18 04:02:07 +04:00
#CamelCase
while ( $ line =~ m {($Constant|$Lval)}g ) {
my $ var = $ 1 ;
if ( $ var !~ /$Constant/ &&
$ var =~ /[A-Z]\w*[a-z]|[a-z]\w*[A-Z]/ &&
2013-02-22 04:44:17 +04:00
$ var !~ /^Page[A-Z]/ &&
2012-12-18 04:02:07 +04:00
! defined $ camelcase { $ var } ) {
$ camelcase { $ var } = 1 ;
WARN ( "CAMELCASE" ,
"Avoid CamelCase: <$var>\n" . $ herecurr ) ;
}
}
2007-06-01 11:46:48 +04:00
#no spaces allowed after \ in define
2008-06-06 09:46:01 +04:00
if ( $ line =~ /\#\s*define.*\\\s$/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "WHITESPACE_AFTER_LINE_CONTINUATION" ,
"Whitepspace after \\ makes next lines useless\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-06-24 04:16:34 +04:00
#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
2008-06-06 09:46:01 +04:00
if ( $ tree && $ rawline =~ m {^.\s*\#\s*include\s*\<asm\/(.*)\.h\>} ) {
2008-10-16 09:02:20 +04:00
my $ file = "$1.h" ;
my $ checkfile = "include/linux/$file" ;
if ( - f "$root/$checkfile" &&
$ realfile ne $ checkfile &&
2010-08-10 04:20:57 +04:00
$ 1 !~ /$allowed_asm_includes/ )
2008-06-06 09:46:01 +04:00
{
2008-10-16 09:02:20 +04:00
if ( $ realfile =~ m {^arch/} ) {
2011-07-26 04:13:25 +04:00
CHK ( "ARCH_INCLUDE_LINUX" ,
"Consider using #include <linux/$file> instead of <asm/$file>\n" . $ herecurr ) ;
2008-10-16 09:02:20 +04:00
} else {
2011-07-26 04:13:25 +04:00
WARN ( "INCLUDE_LINUX" ,
"Use #include <linux/$file> instead of <asm/$file>\n" . $ herecurr ) ;
2008-10-16 09:02:20 +04:00
}
2007-06-01 11:46:48 +04:00
}
}
2007-06-24 04:16:34 +04:00
# multi-statement macros should be enclosed in a do while loop, grab the
# first statement and ensure its the whole macro if its not enclosed
2008-03-05 01:28:20 +03:00
# in a known good container
2008-07-24 08:29:07 +04:00
if ( $ realfile !~ m @/vmlinux.lds.h$@ &&
$ line =~ /^.\s*\#\s*define\s*$Ident(\()?/ ) {
2007-06-24 04:16:44 +04:00
my $ ln = $ linenr ;
my $ cnt = $ realcnt ;
2008-06-06 09:46:01 +04:00
my ( $ off , $ dstat , $ dcond , $ rest ) ;
my $ ctx = '' ;
( $ dstat , $ dcond , $ ln , $ cnt , $ off ) =
2012-01-11 03:09:54 +04:00
ctx_statement_block ( $ linenr , $ realcnt , 0 ) ;
$ ctx = $ dstat ;
2008-06-06 09:46:01 +04:00
#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
2008-07-24 08:29:00 +04:00
#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
2008-06-06 09:46:01 +04:00
2012-01-11 03:09:54 +04:00
$ dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*// ;
2008-07-24 08:29:11 +04:00
$ dstat =~ s/$;//g ;
2008-06-06 09:46:01 +04:00
$ dstat =~ s/\\\n.//g ;
$ dstat =~ s/^\s*//s ;
$ dstat =~ s/\s*$//s ;
2007-07-16 10:37:22 +04:00
2008-06-06 09:46:01 +04:00
# Flatten any parentheses and braces
2008-10-16 09:02:33 +04:00
while ( $ dstat =~ s/\([^\(\)]*\)/1/ ||
$ dstat =~ s/\{[^\{\}]*\}/1/ ||
2012-01-11 03:10:10 +04:00
$ dstat =~ s/\[[^\[\]]*\]/1/ )
2008-10-16 09:02:33 +04:00
{
2007-07-16 10:37:22 +04:00
}
2007-06-24 04:16:44 +04:00
2012-03-24 02:02:18 +04:00
# Flatten any obvious string concatentation.
while ( $ dstat =~ s/("X*")\s*$Ident/$1/ ||
$ dstat =~ s/$Ident\s*("X*")/$1/ )
{
}
2008-06-06 09:46:01 +04:00
my $ exceptions = qr{
$ Declare |
module_param_named |
2012-10-05 04:13:38 +04:00
MODULE_PARM_DESC |
2008-06-06 09:46:01 +04:00
DECLARE_PER_CPU |
DEFINE_PER_CPU |
2009-01-07 01:41:18 +03:00
__typeof__ \ ( |
2010-03-06 00:43:52 +03:00
union |
struct |
2009-09-22 04:04:38 +04:00
\ . $ Ident \ s *= \ s * |
^ \ " | \ " $
2008-06-06 09:46:01 +04:00
} x ;
2010-10-27 01:23:18 +04:00
#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
2012-01-11 03:09:54 +04:00
if ( $ dstat ne '' &&
$ dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
$ dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo();
2012-03-24 02:02:18 +04:00
$ dstat !~ /^[!~-]?(?:$Ident|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo
2012-03-24 02:02:17 +04:00
$ dstat !~ /^'X'$/ && # character constants
2012-01-11 03:09:54 +04:00
$ dstat !~ /$exceptions/ &&
$ dstat !~ /^\.$Ident\s*=/ && # .foo =
2012-01-11 03:10:06 +04:00
$ dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...)
2012-01-11 03:09:54 +04:00
$ dstat !~ /^for\s*$Constant$/ && # for (...)
$ dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar()
$ dstat !~ /^do\s*{/ && # do {...
$ dstat !~ /^\({/ ) # ({...
{
$ ctx =~ s/\n*$// ;
my $ herectx = $ here . "\n" ;
my $ cnt = statement_rawlines ( $ ctx ) ;
for ( my $ n = 0 ; $ n < $ cnt ; $ n + + ) {
$ herectx . = raw_line ( $ linenr , $ n ) . "\n" ;
2008-06-06 09:46:01 +04:00
}
2012-01-11 03:09:54 +04:00
if ( $ dstat =~ /;/ ) {
ERROR ( "MULTISTATEMENT_MACRO_USE_DO_WHILE" ,
"Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx" ) ;
} else {
2011-07-26 04:13:25 +04:00
ERROR ( "COMPLEX_MACRO" ,
2012-01-11 03:09:54 +04:00
"Macros with complex values should be enclosed in parenthesis\n" . "$herectx" ) ;
2007-06-24 04:16:44 +04:00
}
2007-06-24 04:16:34 +04:00
}
2012-12-18 04:01:47 +04:00
2012-12-18 04:01:56 +04:00
# check for line continuations outside of #defines, preprocessor #, and asm
2012-12-18 04:01:47 +04:00
} else {
if ( $ prevline !~ /^..*\\$/ &&
2012-12-18 04:01:56 +04:00
$ line !~ /^\+\s*\#.*\\$/ && # preprocessor
$ line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm
2012-12-18 04:01:47 +04:00
$ line =~ /^\+.*\\$/ ) {
WARN ( "LINE_CONTINUATIONS" ,
"Avoid unnecessary line continuations\n" . $ herecurr ) ;
}
2007-06-01 11:46:48 +04:00
}
2012-07-31 01:41:24 +04:00
# do {} while (0) macro tests:
# single-statement macros do not need to be enclosed in do while (0) loop,
# macro should not end with a semicolon
if ( $ ^ V && $ ^ V ge 5.10 .0 &&
$ realfile !~ m @/vmlinux.lds.h$@ &&
$ line =~ /^.\s*\#\s*define\s+$Ident(\()?/ ) {
my $ ln = $ linenr ;
my $ cnt = $ realcnt ;
my ( $ off , $ dstat , $ dcond , $ rest ) ;
my $ ctx = '' ;
( $ dstat , $ dcond , $ ln , $ cnt , $ off ) =
ctx_statement_block ( $ linenr , $ realcnt , 0 ) ;
$ ctx = $ dstat ;
$ dstat =~ s/\\\n.//g ;
if ( $ dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/ ) {
my $ stmts = $ 2 ;
my $ semis = $ 3 ;
$ ctx =~ s/\n*$// ;
my $ cnt = statement_rawlines ( $ ctx ) ;
my $ herectx = $ here . "\n" ;
for ( my $ n = 0 ; $ n < $ cnt ; $ n + + ) {
$ herectx . = raw_line ( $ linenr , $ n ) . "\n" ;
}
2012-08-22 03:15:53 +04:00
if ( ( $ stmts =~ tr /;/ ; / ) == 1 &&
$ stmts !~ /^\s*(if|while|for|switch)\b/ ) {
2012-07-31 01:41:24 +04:00
WARN ( "SINGLE_STATEMENT_DO_WHILE_MACRO" ,
"Single statement macros should not use a do {} while (0) loop\n" . "$herectx" ) ;
}
if ( defined $ semis && $ semis ne "" ) {
WARN ( "DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON" ,
"do {} while (0) macros should not be semicolon terminated\n" . "$herectx" ) ;
}
}
}
2009-01-07 01:41:25 +03:00
# make sure symbols are always wrapped with VMLINUX_SYMBOL() ...
# all assignments may have only one of the following with an assignment:
# .
# ALIGN(...)
# VMLINUX_SYMBOL(...)
if ( $ realfile eq 'vmlinux.lds.h' && $ line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "MISSING_VMLINUX_SYMBOL" ,
"vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $ herecurr ) ;
2009-01-07 01:41:25 +03:00
}
2007-07-19 12:48:34 +04:00
# check for redundant bracing round if etc
2008-02-08 15:22:03 +03:00
if ( $ line =~ /(^.*)\bif\b/ && $ 1 !~ /else\s*$/ ) {
my ( $ level , $ endln , @ chunks ) =
2008-03-05 01:28:20 +03:00
ctx_statement_full ( $ linenr , $ realcnt , 1 ) ;
2008-02-08 15:22:03 +03:00
#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
2008-03-05 01:28:20 +03:00
#print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
if ( $# chunks > 0 && $ level == 0 ) {
2012-03-24 02:02:19 +04:00
my @ allowed = ( ) ;
my $ allow = 0 ;
2008-02-08 15:22:03 +03:00
my $ seen = 0 ;
2008-03-29 00:15:58 +03:00
my $ herectx = $ here . "\n" ;
2008-03-05 01:28:20 +03:00
my $ ln = $ linenr - 1 ;
2008-02-08 15:22:03 +03:00
for my $ chunk ( @ chunks ) {
my ( $ cond , $ block ) = @ { $ chunk } ;
2008-03-29 00:15:58 +03:00
# If the condition carries leading newlines, then count those as offsets.
my ( $ whitespace ) = ( $ cond =~ /^((?:\s*\n[+-])*\s*)/s ) ;
my $ offset = statement_rawlines ( $ whitespace ) - 1 ;
2012-03-24 02:02:19 +04:00
$ allowed [ $ allow ] = 0 ;
2008-03-29 00:15:58 +03:00
#print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
# We have looked at and allowed this specific line.
$ suppress_ifbraces { $ ln + $ offset } = 1 ;
$ herectx . = "$rawlines[$ln + $offset]\n[...]\n" ;
2008-03-05 01:28:20 +03:00
$ ln += statement_rawlines ( $ block ) - 1 ;
2008-03-29 00:15:58 +03:00
substr ( $ block , 0 , length ( $ cond ) , '' ) ;
2008-02-08 15:22:03 +03:00
$ seen + + if ( $ block =~ /^\s*{/ ) ;
2012-03-24 02:02:19 +04:00
#print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n";
2008-03-05 01:28:20 +03:00
if ( statement_lines ( $ cond ) > 1 ) {
#print "APW: ALLOWED: cond<$cond>\n";
2012-03-24 02:02:19 +04:00
$ allowed [ $ allow ] = 1 ;
2008-02-08 15:22:03 +03:00
}
if ( $ block =~ /\b(?:if|for|while)\b/ ) {
2008-03-05 01:28:20 +03:00
#print "APW: ALLOWED: block<$block>\n";
2012-03-24 02:02:19 +04:00
$ allowed [ $ allow ] = 1 ;
2008-02-08 15:22:03 +03:00
}
2008-03-05 01:28:20 +03:00
if ( statement_block_size ( $ block ) > 1 ) {
#print "APW: ALLOWED: lines block<$block>\n";
2012-03-24 02:02:19 +04:00
$ allowed [ $ allow ] = 1 ;
2008-02-08 15:22:03 +03:00
}
2012-03-24 02:02:19 +04:00
$ allow + + ;
2008-02-08 15:22:03 +03:00
}
2012-03-24 02:02:19 +04:00
if ( $ seen ) {
my $ sum_allowed = 0 ;
foreach ( @ allowed ) {
$ sum_allowed += $ _ ;
}
if ( $ sum_allowed == 0 ) {
WARN ( "BRACES" ,
"braces {} are not necessary for any arm of this statement\n" . $ herectx ) ;
} elsif ( $ sum_allowed != $ allow &&
$ seen != $ allow ) {
CHK ( "BRACES" ,
"braces {} should be used on all arms of this statement\n" . $ herectx ) ;
}
2008-02-08 15:22:03 +03:00
}
}
}
2008-03-29 00:15:58 +03:00
if ( ! defined $ suppress_ifbraces { $ linenr - 1 } &&
2008-02-08 15:22:03 +03:00
$ line =~ /\b(if|while|for|else)\b/ ) {
2008-03-05 01:28:20 +03:00
my $ allowed = 0 ;
# Check the pre-context.
if ( substr ( $ line , 0 , $- [ 0 ] ) =~ /(\}\s*)$/ ) {
#print "APW: ALLOWED: pre<$1>\n";
$ allowed = 1 ;
}
2008-03-29 00:15:58 +03:00
my ( $ level , $ endln , @ chunks ) =
ctx_statement_full ( $ linenr , $ realcnt , $- [ 0 ] ) ;
2008-03-05 01:28:20 +03:00
# Check the condition.
my ( $ cond , $ block ) = @ { $ chunks [ 0 ] } ;
2008-03-29 00:15:58 +03:00
#print "CHECKING<$linenr> cond<$cond> block<$block>\n";
2008-03-05 01:28:20 +03:00
if ( defined $ cond ) {
2008-03-29 00:15:58 +03:00
substr ( $ block , 0 , length ( $ cond ) , '' ) ;
2008-03-05 01:28:20 +03:00
}
if ( statement_lines ( $ cond ) > 1 ) {
#print "APW: ALLOWED: cond<$cond>\n";
$ allowed = 1 ;
}
if ( $ block =~ /\b(?:if|for|while)\b/ ) {
#print "APW: ALLOWED: block<$block>\n";
$ allowed = 1 ;
}
if ( statement_block_size ( $ block ) > 1 ) {
#print "APW: ALLOWED: lines block<$block>\n";
$ allowed = 1 ;
}
# Check the post-context.
if ( defined $ chunks [ 1 ] ) {
my ( $ cond , $ block ) = @ { $ chunks [ 1 ] } ;
if ( defined $ cond ) {
2008-03-29 00:15:58 +03:00
substr ( $ block , 0 , length ( $ cond ) , '' ) ;
2008-03-05 01:28:20 +03:00
}
if ( $ block =~ /^\s*\{/ ) {
#print "APW: ALLOWED: chunk-1 block<$block>\n";
$ allowed = 1 ;
}
}
if ( $ level == 0 && $ block =~ /^\s*\{/ && ! $ allowed ) {
2011-07-27 10:06:29 +04:00
my $ herectx = $ here . "\n" ;
2008-10-16 09:02:23 +04:00
my $ cnt = statement_rawlines ( $ block ) ;
2008-03-05 01:28:20 +03:00
2008-10-16 09:02:23 +04:00
for ( my $ n = 0 ; $ n < $ cnt ; $ n + + ) {
2011-07-27 10:06:29 +04:00
$ herectx . = raw_line ( $ linenr , $ n ) . "\n" ;
2007-07-19 12:48:34 +04:00
}
2008-03-05 01:28:20 +03:00
2011-07-26 04:13:25 +04:00
WARN ( "BRACES" ,
"braces {} are not necessary for single statement blocks\n" . $ herectx ) ;
2007-07-19 12:48:34 +04:00
}
}
2012-12-18 04:01:59 +04:00
# check for unnecessary blank lines around braces
if ( ( $ line =~ /^..*}\s*$/ && $ prevline =~ /^.\s*$/ ) ) {
CHK ( "BRACES" ,
"Blank lines aren't necessary before a close brace '}'\n" . $ hereprev ) ;
}
if ( ( $ line =~ /^.\s*$/ && $ prevline =~ /^..*{\s*$/ ) ) {
CHK ( "BRACES" ,
"Blank lines aren't necessary after an open brace '{'\n" . $ hereprev ) ;
}
2007-06-09 00:46:39 +04:00
# no volatiles please
2007-10-18 14:05:08 +04:00
my $ asm_volatile = qr{ \ b(__asm__|asm) \ s+(__volatile__|volatile) \ b } ;
if ( $ line =~ /\bvolatile\b/ && $ line !~ /$asm_volatile/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "VOLATILE" ,
"Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $ herecurr ) ;
2007-06-09 00:46:39 +04:00
}
2007-06-09 00:47:06 +04:00
# warn about #if 0
2008-06-06 09:46:01 +04:00
if ( $ line =~ /^.\s*\#\s*if\s+0\b/ ) {
2011-07-26 04:13:25 +04:00
CHK ( "REDUNDANT_CODE" ,
"if this code is redundant consider removing it\n" .
2007-07-16 10:37:22 +04:00
$ herecurr ) ;
2007-06-09 00:46:39 +04:00
}
2012-12-18 04:01:52 +04:00
# check for needless "if (<foo>) fn(<foo>)" uses
if ( $ prevline =~ /\bif\s*\(\s*($Lval)\s*\)/ ) {
my $ expr = '\s*\(\s*' . quotemeta ( $ 1 ) . '\s*\)\s*;' ;
if ( $ line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?)$expr/ ) {
WARN ( 'NEEDLESS_IF' ,
"$1(NULL) is safe this check is probably not required\n" . $ hereprev ) ;
2008-07-24 08:29:04 +04:00
}
}
2007-07-19 12:48:34 +04:00
2010-08-10 04:21:01 +04:00
# prefer usleep_range over udelay
2013-02-22 04:44:19 +04:00
if ( $ line =~ /\budelay\s*\(\s*(\d+)\s*\)/ ) {
2010-08-10 04:21:01 +04:00
# ignore udelay's < 10, however
2013-02-22 04:44:19 +04:00
if ( ! ( $ 1 < 10 ) ) {
2011-07-26 04:13:25 +04:00
CHK ( "USLEEP_RANGE" ,
"usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $ line ) ;
2010-08-10 04:21:01 +04:00
}
}
2010-08-10 04:21:02 +04:00
# warn about unexpectedly long msleep's
if ( $ line =~ /\bmsleep\s*\((\d+)\);/ ) {
if ( $ 1 < 20 ) {
2011-07-26 04:13:25 +04:00
WARN ( "MSLEEP" ,
"msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $ line ) ;
2010-08-10 04:21:02 +04:00
}
}
2007-06-09 00:47:06 +04:00
# warn about #ifdefs in C files
2008-06-06 09:46:01 +04:00
# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
2007-06-09 00:47:06 +04:00
# print "#ifdef in C files should be avoided\n";
# print "$herecurr";
# $clean = 0;
# }
2007-08-11 00:01:03 +04:00
# warn about spacing in #ifdefs
2008-06-06 09:46:01 +04:00
if ( $ line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "SPACING" ,
"exactly one space required after that #$1\n" . $ herecurr ) ;
2007-08-11 00:01:03 +04:00
}
2007-06-09 00:46:39 +04:00
# check for spinlock_t definitions without a comment.
2008-04-29 11:59:32 +04:00
if ( $ line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
$ line =~ /^.\s*(DEFINE_MUTEX)\s*\(/ ) {
2007-06-09 00:46:39 +04:00
my $ which = $ 1 ;
if ( ! ctx_has_comment ( $ first_line , $ linenr ) ) {
2011-07-26 04:13:25 +04:00
CHK ( "UNCOMMENTED_DEFINITION" ,
"$1 definition without comment\n" . $ herecurr ) ;
2007-06-09 00:46:39 +04:00
}
}
# check for memory barriers without a comment.
if ( $ line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/ ) {
if ( ! ctx_has_comment ( $ first_line , $ linenr ) ) {
2011-07-26 04:13:25 +04:00
CHK ( "MEMORY_BARRIER" ,
"memory barrier without comment\n" . $ herecurr ) ;
2007-06-09 00:46:39 +04:00
}
}
# check of hardware specific defines
2008-06-06 09:46:01 +04:00
if ( $ line =~ m @^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $ realfile !~ m @include/asm-@ ) {
2011-07-26 04:13:25 +04:00
CHK ( "ARCH_DEFINES" ,
"architecture specific defines should be avoided\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-06-24 04:16:34 +04:00
2010-05-25 01:33:30 +04:00
# Check that the storage class is at the beginning of a declaration
if ( $ line =~ /\b$Storage\b/ && $ line !~ /^.\s*$Storage\b/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "STORAGE_CLASS" ,
"storage class should be at the beginning of the declaration\n" . $ herecurr )
2010-05-25 01:33:30 +04:00
}
2007-07-16 10:37:22 +04:00
# check the location of the inline attribute, that it is between
# storage class and type.
2007-10-17 10:29:38 +04:00
if ( $ line =~ /\b$Type\s+$Inline\b/ ||
$ line =~ /\b$Inline\s+$Storage\b/ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "INLINE_LOCATION" ,
"inline keyword should sit between storage class and type\n" . $ herecurr ) ;
2007-07-16 10:37:22 +04:00
}
2007-11-29 03:21:06 +03:00
# Check for __inline__ and __inline, prefer inline
if ( $ line =~ /\b(__inline__|__inline)\b/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "INLINE" ,
"plain inline is preferred over $1\n" . $ herecurr ) ;
2007-11-29 03:21:06 +03:00
}
2011-01-13 04:00:00 +03:00
# Check for __attribute__ packed, prefer __packed
if ( $ line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "PREFER_PACKED" ,
"__packed is preferred over __attribute__((packed))\n" . $ herecurr ) ;
2011-01-13 04:00:00 +03:00
}
2011-07-26 04:13:24 +04:00
# Check for __attribute__ aligned, prefer __aligned
if ( $ line =~ /\b__attribute__\s*\(\s*\(.*aligned/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "PREFER_ALIGNED" ,
"__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $ herecurr ) ;
2011-07-26 04:13:24 +04:00
}
2012-01-11 03:09:52 +04:00
# Check for __attribute__ format(printf, prefer __printf
if ( $ line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/ ) {
WARN ( "PREFER_PRINTF" ,
"__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $ herecurr ) ;
}
2012-03-24 02:02:16 +04:00
# Check for __attribute__ format(scanf, prefer __scanf
if ( $ line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/ ) {
WARN ( "PREFER_SCANF" ,
"__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $ herecurr ) ;
}
2010-03-06 00:43:48 +03:00
# check for sizeof(&)
if ( $ line =~ /\bsizeof\s*\(\s*\&/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "SIZEOF_ADDRESS" ,
"sizeof(& should be avoided\n" . $ herecurr ) ;
2010-03-06 00:43:48 +03:00
}
2012-07-31 01:41:22 +04:00
# check for sizeof without parenthesis
if ( $ line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/ ) {
WARN ( "SIZEOF_PARENTHESIS" ,
"sizeof $1 should be sizeof($1)\n" . $ herecurr ) ;
}
2011-05-25 04:13:39 +04:00
# check for line continuations in quoted strings with odd counts of "
if ( $ rawline =~ /\\$/ && $ rawline =~ tr /"/ " / % 2 ) {
2011-07-26 04:13:25 +04:00
WARN ( "LINE_CONTINUATIONS" ,
"Avoid line continuations in quoted strings\n" . $ herecurr ) ;
2011-05-25 04:13:39 +04:00
}
2012-12-18 04:02:00 +04:00
# check for struct spinlock declarations
if ( $ line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/ ) {
WARN ( "USE_SPINLOCK_T" ,
"struct spinlock should be spinlock_t\n" . $ herecurr ) ;
}
2012-01-11 03:09:57 +04:00
# Check for misused memsets
2012-03-24 02:02:16 +04:00
if ( $ ^ V && $ ^ V ge 5.10 .0 &&
defined $ stat &&
2012-01-11 03:09:58 +04:00
$ stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/s ) {
my $ ms_addr = $ 2 ;
2012-03-24 02:02:16 +04:00
my $ ms_val = $ 7 ;
my $ ms_size = $ 12 ;
2012-01-11 03:09:57 +04:00
if ( $ ms_size =~ /^(0x|)0$/i ) {
ERROR ( "MEMSET" ,
2012-01-11 03:09:58 +04:00
"memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n" ) ;
2012-01-11 03:09:57 +04:00
} elsif ( $ ms_size =~ /^(0x|)1$/i ) {
WARN ( "MEMSET" ,
2012-01-11 03:09:58 +04:00
"single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n" ) ;
}
}
# typecasts on min/max could be min_t/max_t
2012-03-24 02:02:16 +04:00
if ( $ ^ V && $ ^ V ge 5.10 .0 &&
defined $ stat &&
2012-01-11 03:09:58 +04:00
$ stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/ ) {
2012-03-24 02:02:16 +04:00
if ( defined $ 2 || defined $ 7 ) {
2012-01-11 03:09:58 +04:00
my $ call = $ 1 ;
my $ cast1 = deparenthesize ( $ 2 ) ;
my $ arg1 = $ 3 ;
2012-03-24 02:02:16 +04:00
my $ cast2 = deparenthesize ( $ 7 ) ;
my $ arg2 = $ 8 ;
2012-01-11 03:09:58 +04:00
my $ cast ;
2012-03-24 02:02:16 +04:00
if ( $ cast1 ne "" && $ cast2 ne "" && $ cast1 ne $ cast2 ) {
2012-01-11 03:09:58 +04:00
$ cast = "$cast1 or $cast2" ;
} elsif ( $ cast1 ne "" ) {
$ cast = $ cast1 ;
} else {
$ cast = $ cast2 ;
}
WARN ( "MINMAX" ,
"$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n" ) ;
2012-01-11 03:09:57 +04:00
}
}
2012-07-31 01:41:20 +04:00
# check usleep_range arguments
if ( $ ^ V && $ ^ V ge 5.10 .0 &&
defined $ stat &&
$ stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/ ) {
my $ min = $ 1 ;
my $ max = $ 7 ;
if ( $ min eq $ max ) {
WARN ( "USLEEP_RANGE" ,
"usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n" ) ;
} elsif ( $ min =~ /^\d+$/ && $ max =~ /^\d+$/ &&
$ min > $ max ) {
WARN ( "USLEEP_RANGE" ,
"usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n" ) ;
}
}
2007-07-16 10:37:22 +04:00
# check for new externs in .c files.
2008-04-29 11:59:32 +04:00
if ( $ realfile =~ /\.c$/ && defined $ stat &&
2008-06-06 09:46:01 +04:00
$ stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s )
2008-04-29 11:59:32 +04:00
{
2008-06-06 09:46:01 +04:00
my $ function_name = $ 1 ;
my $ paren_space = $ 2 ;
2008-04-29 11:59:32 +04:00
my $ s = $ stat ;
if ( defined $ cond ) {
substr ( $ s , 0 , length ( $ cond ) , '' ) ;
}
2008-06-06 09:46:01 +04:00
if ( $ s =~ /^\s*;/ &&
$ function_name ne 'uninitialized_var' )
{
2011-07-26 04:13:25 +04:00
WARN ( "AVOID_EXTERNS" ,
"externs should be avoided in .c files\n" . $ herecurr ) ;
2008-04-29 11:59:32 +04:00
}
if ( $ paren_space =~ /\n/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "FUNCTION_ARGUMENTS" ,
"arguments for function declarations should follow identifier\n" . $ herecurr ) ;
2008-04-29 11:59:32 +04:00
}
2008-04-29 11:59:33 +04:00
} elsif ( $ realfile =~ /\.c$/ && defined $ stat &&
$ stat =~ /^.\s*extern\s+/ )
{
2011-07-26 04:13:25 +04:00
WARN ( "AVOID_EXTERNS" ,
"externs should be avoided in .c files\n" . $ herecurr ) ;
2007-07-16 10:37:22 +04:00
}
# checks for new __setup's
if ( $ rawline =~ /\b__setup\("([^"]*)"/ ) {
my $ name = $ 1 ;
if ( ! grep ( /$name/ , @ setup_docs ) ) {
2011-07-26 04:13:25 +04:00
CHK ( "UNDOCUMENTED_SETUP" ,
"__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $ herecurr ) ;
2007-07-16 10:37:22 +04:00
}
2007-06-24 04:16:34 +04:00
}
2007-10-17 10:29:38 +04:00
# check for pointless casting of kmalloc return
2011-01-13 03:59:56 +03:00
if ( $ line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "UNNECESSARY_CASTS" ,
"unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $ herecurr ) ;
2007-10-17 10:29:38 +04:00
}
2008-02-08 15:22:03 +03:00
2013-02-22 04:44:18 +04:00
# check for alloc argument mismatch
if ( $ line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/ ) {
WARN ( "ALLOC_ARRAY_ARGS" ,
"$1 uses number as first arg, sizeof is generally wrong\n" . $ herecurr ) ;
}
2011-01-13 03:59:56 +03:00
# check for multiple semicolons
if ( $ line =~ /;\s*;\s*$/ ) {
2012-12-18 04:02:01 +04:00
WARN ( "ONE_SEMICOLON" ,
"Statements terminations use 1 semicolon\n" . $ herecurr ) ;
}
# check for switch/default statements without a break;
if ( $ ^ V && $ ^ V ge 5.10 .0 &&
defined $ stat &&
$ stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g ) {
my $ ctx = '' ;
my $ herectx = $ here . "\n" ;
my $ cnt = statement_rawlines ( $ stat ) ;
for ( my $ n = 0 ; $ n < $ cnt ; $ n + + ) {
$ herectx . = raw_line ( $ linenr , $ n ) . "\n" ;
}
WARN ( "DEFAULT_NO_BREAK" ,
"switch default: should use break\n" . $ herectx ) ;
2011-01-13 03:59:56 +03:00
}
2008-02-08 15:22:03 +03:00
# check for gcc specific __FUNCTION__
if ( $ line =~ /__FUNCTION__/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "USE_FUNC" ,
"__func__ should be used instead of gcc specific __FUNCTION__\n" . $ herecurr ) ;
2008-02-08 15:22:03 +03:00
}
2008-03-29 00:15:58 +03:00
2012-03-24 02:02:20 +04:00
# check for use of yield()
if ( $ line =~ /\byield\s*\(\s*\)/ ) {
WARN ( "YIELD" ,
"Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $ herecurr ) ;
}
2010-09-07 18:34:01 +04:00
# check for semaphores initialized locked
if ( $ line =~ /^.\s*sema_init.+,\W?0\W?\)/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "CONSIDER_COMPLETION" ,
"consider using a completion\n" . $ herecurr ) ;
2008-03-29 00:15:58 +03:00
}
2012-03-24 02:02:20 +04:00
2011-11-01 04:13:10 +04:00
# recommend kstrto* over simple_strto* and strict_strto*
if ( $ line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "CONSIDER_KSTRTO" ,
2011-11-01 04:13:10 +04:00
"$1 is obsolete, use k$3 instead\n" . $ herecurr ) ;
2008-03-29 00:15:58 +03:00
}
2012-03-24 02:02:20 +04:00
2008-07-24 08:28:57 +04:00
# check for __initcall(), use device_initcall() explicitly please
if ( $ line =~ /^.\s*__initcall\s*\(/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "USE_DEVICE_INITCALL" ,
"please use device_initcall() instead of __initcall()\n" . $ herecurr ) ;
2008-07-24 08:28:57 +04:00
}
2012-03-24 02:02:20 +04:00
2010-03-06 00:43:53 +03:00
# check for various ops structs, ensure they are const.
my $ struct_ops = qr{ acpi_dock_ops|
address_space_operations |
backlight_ops |
block_device_operations |
dentry_operations |
dev_pm_ops |
dma_map_ops |
extent_io_ops |
file_lock_operations |
file_operations |
hv_ops |
ide_dma_ops |
intel_dvo_dev_ops |
item_operations |
iwl_ops |
kgdb_arch |
kgdb_io |
kset_uevent_ops |
lock_manager_operations |
microcode_ops |
mtrr_ops |
neigh_ops |
nlmsvc_binding |
pci_raw_ops |
pipe_buf_operations |
platform_hibernation_ops |
platform_suspend_ops |
proto_ops |
rpc_pipe_ops |
seq_operations |
snd_ac97_build_ops |
soc_pcmcia_socket_ops |
stacktrace_ops |
sysfs_ops |
tty_operations |
usb_mon_operations |
wd_ops } x ;
2009-01-16 00:51:07 +03:00
if ( $ line !~ /\bconst\b/ &&
2010-03-06 00:43:53 +03:00
$ line =~ /\bstruct\s+($struct_ops)\b/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "CONST_STRUCT" ,
"struct $1 should normally be const\n" .
2009-01-16 00:51:07 +03:00
$ herecurr ) ;
2009-01-07 01:41:29 +03:00
}
2008-03-29 00:15:58 +03:00
# use of NR_CPUS is usually wrong
# ignore definitions of NR_CPUS and usage to define arrays as likely right
if ( $ line =~ /\bNR_CPUS\b/ &&
2008-06-06 09:46:01 +04:00
$ line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
$ line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
2008-04-29 11:59:32 +04:00
$ line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
$ line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
$ line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/ )
2008-03-29 00:15:58 +03:00
{
2011-07-26 04:13:25 +04:00
WARN ( "NR_CPUS" ,
"usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $ herecurr ) ;
2008-03-29 00:15:58 +03:00
}
2008-04-29 11:59:33 +04:00
# check for %L{u,d,i} in strings
my $ string ;
while ( $ line =~ /(?:^|")([X\t]*)(?:"|$)/g ) {
$ string = substr ( $ rawline , $- [ 1 ] , $+ [ 1 ] - $- [ 1 ] ) ;
2008-10-16 09:02:23 +04:00
$ string =~ s/%%/__/g ;
2008-04-29 11:59:33 +04:00
if ( $ string =~ /(?<!%)%L[udi]/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "PRINTF_L" ,
"\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $ herecurr ) ;
2008-04-29 11:59:33 +04:00
last ;
}
}
2009-01-07 01:41:16 +03:00
# whine mightly about in_atomic
if ( $ line =~ /\bin_atomic\s*\(/ ) {
if ( $ realfile =~ m @^drivers/@ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "IN_ATOMIC" ,
"do not use in_atomic in drivers\n" . $ herecurr ) ;
2009-02-28 01:03:05 +03:00
} elsif ( $ realfile !~ m @^kernel/@ ) {
2011-07-26 04:13:25 +04:00
WARN ( "IN_ATOMIC" ,
"use of in_atomic() is incorrect outside core kernel code\n" . $ herecurr ) ;
2009-01-07 01:41:16 +03:00
}
}
2010-03-19 03:37:42 +03:00
# check for lockdep_set_novalidate_class
if ( $ line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
$ line =~ /__lockdep_no_validate__\s*\)/ ) {
if ( $ realfile !~ m @^kernel/lockdep@ &&
$ realfile !~ m @^include/linux/lockdep@ &&
$ realfile !~ m @^drivers/base/core@ ) {
2011-07-26 04:13:25 +04:00
ERROR ( "LOCKDEP" ,
"lockdep_no_validate class is reserved for device->mutex.\n" . $ herecurr ) ;
2010-03-19 03:37:42 +03:00
}
}
2011-01-13 03:59:59 +03:00
if ( $ line =~ /debugfs_create_file.*S_IWUGO/ ||
$ line =~ /DEVICE_ATTR.*S_IWUGO/ ) {
2011-07-26 04:13:25 +04:00
WARN ( "EXPORTED_WORLD_WRITABLE" ,
"Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $ herecurr ) ;
2011-01-13 03:59:59 +03:00
}
2008-02-08 15:22:03 +03:00
}
# If we have no input at all, then there is nothing to report on
# so just keep quiet.
if ( $# rawlines == - 1 ) {
exit ( 0 ) ;
2007-06-01 11:46:48 +04:00
}
2007-11-29 03:21:06 +03:00
# In mailback mode only produce a report in the negative, for
# things that appear to be patches.
if ( $ mailback && ( $ clean == 1 || ! $ is_patch ) ) {
exit ( 0 ) ;
}
# This is not a patch, and we are are in 'no-patch' mode so
# just keep quiet.
if ( ! $ chk_patch && ! $ is_patch ) {
exit ( 0 ) ;
}
if ( ! $ is_patch ) {
2011-07-26 04:13:25 +04:00
ERROR ( "NOT_UNIFIED_DIFF" ,
"Does not appear to be a unified-diff format patch\n" ) ;
2007-06-01 11:46:48 +04:00
}
if ( $ is_patch && $ chk_signoff && $ signoff == 0 ) {
2011-07-26 04:13:25 +04:00
ERROR ( "MISSING_SIGN_OFF" ,
"Missing Signed-off-by: line(s)\n" ) ;
2007-06-01 11:46:48 +04:00
}
2007-11-29 03:21:06 +03:00
print report_dump ( ) ;
2008-02-08 15:22:03 +03:00
if ( $ summary && ! ( $ clean == 1 && $ quiet == 1 ) ) {
print "$filename " if ( $ summary_file ) ;
2007-11-29 03:21:06 +03:00
print "total: $cnt_error errors, $cnt_warn warnings, " .
( ( $ check ) ? "$cnt_chk checks, " : "" ) .
"$cnt_lines lines checked\n" ;
print "\n" if ( $ quiet == 0 ) ;
2007-07-19 12:48:34 +04:00
}
2007-11-29 03:21:06 +03:00
2010-10-27 01:23:12 +04:00
if ( $ quiet == 0 ) {
2012-03-24 02:02:16 +04:00
if ( $ ^ V lt 5.10 .0 ) {
print ( "NOTE: perl $^V is not modern enough to detect all possible issues.\n" ) ;
print ( "An upgrade to at least perl v5.10.0 is suggested.\n\n" ) ;
}
2010-10-27 01:23:12 +04:00
# If there were whitespace errors which cleanpatch can fix
# then suggest that.
if ( $ rpt_cleaners ) {
print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n" ;
print " scripts/cleanfile\n\n" ;
2011-03-23 02:34:43 +03:00
$ rpt_cleaners = 0 ;
2010-10-27 01:23:12 +04:00
}
}
2012-03-24 02:02:17 +04:00
if ( $ quiet == 0 && keys % ignore_type ) {
2011-07-26 04:13:25 +04:00
print "NOTE: Ignored message types:" ;
foreach my $ ignore ( sort keys % ignore_type ) {
print " $ignore" ;
}
2012-03-24 02:02:17 +04:00
print "\n\n" ;
2011-07-26 04:13:25 +04:00
}
2007-06-01 11:46:48 +04:00
if ( $ clean == 1 && $ quiet == 0 ) {
2008-02-08 15:20:54 +03:00
print "$vname has no obvious style problems and is ready for submission.\n"
2007-06-01 11:46:48 +04:00
}
if ( $ clean == 0 && $ quiet == 0 ) {
2011-07-26 04:13:25 +04:00
print << "EOM" ;
$ vname has style problems , please review .
If any of these errors are false positives , please report
them to the maintainer , see CHECKPATCH in MAINTAINERS .
EOM
2007-06-01 11:46:48 +04:00
}
2008-02-08 15:22:03 +03:00
2007-06-01 11:46:48 +04:00
return $ clean ;
}