2007-06-01 00:46:48 -07:00
# ! / usr / bin / perl - w
2010-01-12 16:59:52 -05:00
# ( c ) 2001 , Dave Jones . ( the file handling bit )
2007-06-08 13:47:06 -07:00
# ( c ) 2005 , Joel Schopp < jschopp @ austin . ibm . com > ( the ugly bit )
2009-01-06 14:41:23 -08:00
# ( c ) 2007 , 2008 , Andy Whitcroft < apw @ uk . ibm . com > ( new conditions , test suite )
2010-10-26 14:23:17 -07:00
# ( c ) 2008 - 2010 Andy Whitcroft < apw @ canonical . com >
2007-06-01 00:46:48 -07:00
# Licensed under the terms of the GNU GPL License version 2
use strict ;
2013-07-08 16:00:43 -07:00
use POSIX ;
2007-06-01 00:46:48 -07:00
my $ P = $ 0 ;
2007-06-08 13:47:06 -07:00
$ P =~ s @.*/@@ g ;
2007-06-01 00:46:48 -07:00
2011-07-25 17:13:25 -07:00
my $ V = '0.32' ;
2007-06-01 00:46:48 -07: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-28 14:15:58 -07:00
my $ tst_only ;
2007-10-18 03:05:08 -07:00
my $ emacs = 0 ;
2007-11-28 16:21:06 -08:00
my $ terse = 0 ;
2007-10-18 03:05:08 -07:00
my $ file = 0 ;
my $ check = 0 ;
2007-11-28 16:21:06 -08:00
my $ summary = 1 ;
my $ mailback = 0 ;
2008-02-08 04:22:03 -08:00
my $ summary_file = 0 ;
2011-07-25 17:13:25 -07:00
my $ show_types = 0 ;
2013-07-03 15:05:31 -07:00
my $ fix = 0 ;
2014-01-23 15:54:44 -08:00
my $ fix_inplace = 0 ;
2007-10-18 03:05:08 -07:00
my $ root ;
2008-02-08 04:20:54 -08:00
my %debug;
2013-07-03 15:05:34 -07:00
my %camelcase = ();
2013-09-11 14:23:59 -07:00
my %use_type = ();
my @ use = ( ) ;
my %ignore_type = ();
2011-07-25 17:13:25 -07:00
my @ ignore = ( ) ;
2009-09-21 17:04:37 -07:00
my $ help = 0 ;
2011-07-25 17:13:25 -07:00
my $ configuration_file = ".checkpatch.conf" ;
2012-12-17 16:01:54 -08:00
my $ max_line_length = 80 ;
2013-09-11 14:23:56 -07:00
my $ ignore_perl_version = 0 ;
my $ minimum_perl_version = 5.10 .0 ;
2009-09-21 17:04:37 -07: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
2013-09-11 14:23:59 -07:00
-- types TYPE ( , TYPE2 . . . ) show only these comma separated message types
2011-07-25 17:13:25 -07:00
-- ignore TYPE ( , TYPE2 . . . ) ignore various comma separated message types
2012-12-17 16:01:54 -08:00
-- max - line - length = n set the maximum line length , if exceeded , warn
2011-07-25 17:13:25 -07:00
-- show - types show the message "types" in the output
2009-09-21 17:04:37 -07: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
2013-07-03 15:05:31 -07:00
-- fix EXPERIMENTAL - may create horrible results
If correctable single - line errors exist , create
"<inputfile>.EXPERIMENTAL-checkpatch-fixes"
with potential errors corrected to the preferred
checkpatch style
2014-01-23 15:54:44 -08:00
-- fix - inplace EXPERIMENTAL - may create horrible results
Is the same as -- fix , but overwrites the input
file . It 's your fault if there' s no backup or git
2013-09-11 14:23:56 -07:00
-- ignore - perl - version override checking of perl version . expect
runtime errors .
2009-09-21 17:04:37 -07:00
- h , -- help , -- version display this help and exit
When FILE is - read standard input .
EOM
exit ( $ exitcode ) ;
}
2011-07-25 17:13:25 -07: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 00:46:48 -07:00
GetOptions (
2007-10-18 03:05:08 -07:00
'q|quiet+' => \ $ quiet ,
2007-06-01 00:46:48 -07:00
'tree!' => \ $ tree ,
'signoff!' => \ $ chk_signoff ,
'patch!' => \ $ chk_patch ,
2007-10-18 03:05:08 -07:00
'emacs!' => \ $ emacs ,
2007-11-28 16:21:06 -08:00
'terse!' => \ $ terse ,
2009-09-21 17:04:37 -07:00
'f|file!' => \ $ file ,
2007-10-18 03:05:08 -07:00
'subjective!' => \ $ check ,
'strict!' => \ $ check ,
2011-07-25 17:13:25 -07:00
'ignore=s' => \@ ignore ,
2013-09-11 14:23:59 -07:00
'types=s' => \@ use ,
2011-07-25 17:13:25 -07:00
'show-types!' => \ $ show_types ,
2012-12-17 16:01:54 -08:00
'max-line-length=i' => \ $ max_line_length ,
2007-10-18 03:05:08 -07:00
'root=s' => \ $ root ,
2007-11-28 16:21:06 -08:00
'summary!' => \ $ summary ,
'mailback!' => \ $ mailback ,
2008-02-08 04:22:03 -08:00
'summary-file!' => \ $ summary_file ,
2013-07-03 15:05:31 -07:00
'fix!' => \ $ fix ,
2014-01-23 15:54:44 -08:00
'fix-inplace!' => \ $ fix_inplace ,
2013-09-11 14:23:56 -07:00
'ignore-perl-version!' => \ $ ignore_perl_version ,
2008-02-08 04:20:54 -08:00
'debug=s' => \ %debug,
2008-03-28 14:15:58 -07:00
'test-only=s' => \ $ tst_only ,
2009-09-21 17:04:37 -07:00
'h|help' => \ $ help ,
'version' => \ $ help
) or help ( 1 ) ;
help ( 0 ) if ( $ help ) ;
2007-06-01 00:46:48 -07:00
2014-01-23 15:54:44 -08:00
$ fix = 1 if ( $ fix_inplace ) ;
2007-06-01 00:46:48 -07:00
my $ exit = 0 ;
2013-09-11 14:23:56 -07:00
if ( $ ^ V && $ ^ V lt $ minimum_perl_version ) {
printf "$P: requires at least perl version %vd\n" , $ minimum_perl_version ;
if ( ! $ ignore_perl_version ) {
exit ( 1 ) ;
}
}
2007-06-01 00:46:48 -07:00
if ( $ # ARGV < 0 ) {
2009-09-21 17:04:37 -07:00
print "$P: no input files\n" ;
2007-06-01 00:46:48 -07:00
exit ( 1 ) ;
}
2013-09-11 14:23:59 -07:00
sub hash_save_array_words {
my ( $ hashRef , $ arrayRef ) = @ _ ;
2011-07-25 17:13:25 -07:00
2013-09-11 14:23:59 -07:00
my @ array = split ( / , / , join ( ',' , @ $ arrayRef ) ) ;
foreach my $ word ( @ array ) {
$ word =~ s /\ s *\ n ? $ // g ;
$ word =~ s /^\ s *// g ;
$ word =~ s /\ s +/ / g ;
$ word =~ tr / [ a - z ] / [ A - Z ] / ;
2011-07-25 17:13:25 -07:00
2013-09-11 14:23:59 -07:00
next if ( $ word =~ m /^\ s *#/ ) ;
next if ( $ word =~ m /^\ s * $ / ) ;
$ hashRef -> { $ word } ++ ;
}
2011-07-25 17:13:25 -07:00
}
2013-09-11 14:23:59 -07:00
sub hash_show_words {
my ( $ hashRef , $ prefix ) = @ _ ;
2013-09-11 14:24:04 -07:00
if ( $ quiet == 0 && keys %$hashRef) {
2013-09-11 14:23:59 -07:00
print "NOTE: $prefix message types:" ;
2013-09-11 14:24:04 -07:00
foreach my $ word ( sort keys %$hashRef) {
2013-09-11 14:23:59 -07:00
print " $word" ;
}
print "\n\n" ;
}
}
hash_save_array_words ( \ %ignore_type, \@ignore);
hash_save_array_words ( \ %use_type, \@use);
2008-02-08 04:20:54 -08:00
my $ dbg_values = 0 ;
my $ dbg_possible = 0 ;
2008-07-23 21:29:06 -07:00
my $ dbg_type = 0 ;
2008-10-15 22:02:17 -07:00
my $ dbg_attr = 0 ;
2008-02-08 04:20:54 -08:00
for my $ key ( keys %debug) {
2009-01-06 14:41:30 -08:00
## no critic
eval " \ $ { dbg_$key } = '$debug{$key}' ; ";
die " $ @ " if ($@);
2008-02-08 04:20:54 -08:00
}
2010-10-26 14:23:12 -07:00
my $rpt_cleaners = 0;
2007-11-28 16:21:06 -08:00
if ($terse) {
$emacs = 1;
$quiet++;
}
2007-10-18 03:05:08 -07: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 00:46:48 -07:00
}
2007-10-18 03:05:08 -07:00
my $ emitted_corrupt = 0 ;
2009-10-26 16:50:14 -07:00
our $ Ident = qr {
[ A - Za - z_ ] [ A - Za - z \ d_ ] *
( ?:\ s *\#\#\ s * [ A - Za - z_ ] [ A - Za - z \ d_ ] * ) *
} x ;
2007-10-18 03:05:08 -07:00
our $ Storage = qr { extern | static | asmlinkage } ;
our $ Sparse = qr {
_ _ user |
_ _ kernel |
_ _ force |
_ _ iomem |
_ _ must_check |
_ _ init_refok |
2009-02-27 14:03:08 -08:00
_ _ kprobes |
2011-07-25 17:13:23 -07:00
_ _ ref |
_ _ rcu
2007-10-18 03:05:08 -07:00
} x ;
2013-11-12 15:10:10 -08:00
our $ InitAttributePrefix = qr { _ _ ( ?: mem | cpu | dev | net_ | ) } ;
our $ InitAttributeData = qr { $ InitAttributePrefix ( ?: initdata \ b ) } ;
our $ InitAttributeConst = qr { $ InitAttributePrefix ( ?: initconst \ b ) } ;
our $ InitAttributeInit = qr { $ InitAttributePrefix ( ?: init \ b ) } ;
our $ InitAttribute = qr { $ InitAttributeData | $ InitAttributeConst | $ InitAttributeInit } ;
2013-09-11 14:24:05 -07:00
2010-03-05 13:43:51 -08:00
# Notes to $ Attribute :
# We need \ b after 'init' otherwise 'initconst' will cause a false positive in a check
2007-10-18 03:05:08 -07:00
our $ Attribute = qr {
const |
2010-10-26 14:23:16 -07:00
_ _ percpu |
_ _ nocast |
_ _ safe |
_ _ bitwise__ |
_ _ packed__ |
_ _ packed2__ |
_ _ naked |
_ _ maybe_unused |
_ _ always_unused |
_ _ noreturn |
_ _ used |
_ _ cold |
_ _ noclone |
_ _ deprecated |
2007-10-18 03:05:08 -07:00
_ _ read_mostly |
_ _ kprobes |
2013-09-11 14:24:05 -07:00
$ InitAttribute |
2008-10-15 22:02:18 -07:00
_ _ _ _ cacheline_aligned |
_ _ _ _ cacheline_aligned_in_smp |
2009-01-06 14:41:18 -08:00
_ _ _ _ cacheline_internodealigned_in_smp |
_ _ weak
2007-10-18 03:05:08 -07:00
} x ;
2008-06-05 22:46:01 -07:00
our $ Modifier ;
2007-10-18 03:05:08 -07:00
our $ Inline = qr { inline | _ _ always_inline | noinline } ;
our $ Member = qr { -> $ Ident | \. $ Ident | \ [ [ ^ ] ] *\ ] } ;
our $ Lval = qr { $ Ident ( ?: $ Member ) * } ;
2013-07-03 15:05:20 -07:00
our $ Int_type = qr { ( ? i ) llu | ull | ll | lu | ul | l | u } ;
our $ Binary = qr { ( ? i ) 0 b [ 01 ] + $ Int_type ? } ;
our $ Hex = qr { ( ? i ) 0 x [ 0 - 9 a - f ] + $ Int_type ? } ;
our $ Int = qr { [ 0 - 9 ] + $ Int_type ? } ;
2014-04-03 14:49:13 -07:00
our $ Octal = qr { 0 [ 0 - 7 ] + $ Int_type ? } ;
2013-02-04 14:28:51 -08:00
our $ Float_hex = qr { ( ? i ) 0 x [ 0 - 9 a - 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-17 16:02:05 -08:00
our $ Float = qr { $ Float_hex | $ Float_dec | $ Float_int } ;
2014-04-03 14:49:13 -07:00
our $ Constant = qr { $ Float | $ Binary | $ Octal | $ Hex | $ Int } ;
2013-02-04 14:28:51 -08:00
our $ Assignment = qr { \*\= | /= | %=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
2014-04-03 14:49:17 -07:00
our $ Compare = qr { <= | >= | == | ! = | < | ( ?< ! - ) > } ;
2013-07-03 15:05:31 -07:00
our $ Arithmetic = qr { \+ | - | \* | \/ | %};
2007-10-18 03:05:08 -07:00
our $ Operators = qr {
<= | >= | == | ! = |
=> | -> | << | >> | < | > | ! | ~ |
2013-07-03 15:05:31 -07:00
&& | \ | \ | | , | \^ | \+\+ | -- | & | \ | | $ Arithmetic
2007-10-18 03:05:08 -07:00
} x ;
2007-11-28 16:21:06 -08:00
our $ NonptrType ;
2013-09-11 14:24:05 -07:00
our $ NonptrTypeWithAttr ;
2007-11-28 16:21:06 -08:00
our $ Type ;
our $ Declare ;
2011-10-31 17:13:12 -07:00
our $ NON_ASCII_UTF8 = qr {
[ \ xC2 -\ xDF ] [ \ x80 -\ xBF ] # non - overlong 2 - byte
2008-04-29 00:59:32 -07: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-10-31 17:13:12 -07:00
our $ UTF8 = qr {
[ \ x09 \ x0A \ x0D \ x20 -\ x7E ] # ASCII
| $ NON_ASCII_UTF8
} x ;
2008-10-15 22:02:32 -07:00
our $ typeTypedefs = qr { ( ? x :
2009-09-21 17:04:38 -07:00
( ?: _ _ ) ? ( ?: u | s | be | le ) ( ?: 8 | 16 | 32 | 64 ) |
2008-10-15 22:02:32 -07:00
atomic_t
) } ;
2010-03-05 13:43:51 -08:00
our $ logFunctions = qr { ( ? x :
2011-07-25 17:13:27 -07:00
printk ( ?: _ ratelimited | _ once | ) |
2013-07-03 15:05:35 -07:00
( ?: [ a - z0 - 9 ] + _ ) { 1 , 2 } ( ?: printk | emerg | alert | crit | err | warning | warn | notice | info | debug | dbg | vdbg | devel | cont | WARN ) ( ?: _ ratelimited | _ once | ) |
2011-07-25 17:13:27 -07:00
WARN ( ?: _ RATELIMIT | _ ONCE | ) |
2011-05-24 17:13:40 -07:00
panic |
2013-11-12 15:10:07 -08:00
MODULE_ [ A - Z_ ] + |
seq_vprintf | seq_printf | seq_puts
2010-03-05 13:43:51 -08:00
) } ;
2011-07-25 17:13:23 -07:00
our $ signature_tags = qr { ( ? xi :
Signed - off - by : |
Acked - by : |
Tested - by : |
Reviewed - by : |
Reported - by : |
2013-04-29 16:18:17 -07:00
Suggested - by : |
2011-07-25 17:13:23 -07:00
To : |
Cc :
) } ;
2007-11-28 16:21:06 -08:00
our @ typeList = (
qr { void } ,
2008-06-05 22:46:01 -07: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-28 16:21:06 -08: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 } ,
) ;
2013-09-11 14:24:05 -07:00
our @ typeListWithAttr = (
@ typeList ,
qr { struct \ s + $ InitAttribute \ s + $ Ident } ,
qr { union \ s + $ InitAttribute \ s + $ Ident } ,
) ;
2008-06-05 22:46:01 -07:00
our @ modifierList = (
qr { fastcall } ,
) ;
2007-11-28 16:21:06 -08:00
2014-04-03 14:49:13 -07:00
our @ mode_permission_funcs = (
[ "module_param" , 3 ] ,
[ "module_param_(?:array|named|string)" , 4 ] ,
[ "module_param_array_named" , 5 ] ,
[ "debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)" , 2 ] ,
[ "proc_create(?:_data|)" , 2 ] ,
[ "(?:CLASS|DEVICE|SENSOR)_ATTR" , 2 ] ,
) ;
2014-04-03 14:49:24 -07:00
# Create a search pattern for all these functions to speed up a loop below
our $ mode_perms_search = "" ;
foreach my $ entry ( @ mode_permission_funcs ) {
$ mode_perms_search . = '|' if ( $ mode_perms_search ne "" ) ;
$ mode_perms_search . = $ entry -> [ 0 ] ;
}
2010-08-09 17:20:57 -07:00
our $ allowed_asm_includes = qr { ( ? x :
irq |
memory
) } ;
# memory . h : ARM has a custom one
2007-11-28 16:21:06 -08:00
sub build_types {
2008-07-23 21:29:07 -07:00
my $ mods = "(?x: \n" . join ( "|\n " , @ modifierList ) . "\n)" ;
my $ all = "(?x: \n" . join ( "|\n " , @ typeList ) . "\n)" ;
2013-09-11 14:24:05 -07:00
my $ allWithAttr = "(?x: \n" . join ( "|\n " , @ typeListWithAttr ) . "\n)" ;
2008-07-23 21:28:57 -07:00
$ Modifier = qr { ( ?: $ Attribute | $ Sparse | $ mods ) } ;
2007-11-28 16:21:06 -08:00
$ NonptrType = qr {
2008-07-23 21:29:07 -07:00
( ?: $ Modifier \ s + | const \ s + ) *
2008-03-04 14:28:20 -08:00
( ?:
2012-01-10 15:10:13 -08:00
( ?: typeof | _ _ typeof__ ) \ s *\ ( [ ^\ ) ] *\ ) |
2008-10-15 22:02:32 -07:00
( ?: $ typeTypedefs \ b ) |
2008-06-05 22:46:01 -07:00
( ?: $ { all } \ b )
2008-03-04 14:28:20 -08:00
)
2008-07-23 21:28:57 -07:00
( ?:\ s + $ Modifier | \ s + const ) *
2007-11-28 16:21:06 -08:00
} x ;
2013-09-11 14:24:05 -07:00
$ NonptrTypeWithAttr = qr {
( ?: $ Modifier \ s + | const \ s + ) *
( ?:
( ?: typeof | _ _ typeof__ ) \ s *\ ( [ ^\ ) ] *\ ) |
( ?: $ typeTypedefs \ b ) |
( ?: $ { allWithAttr } \ b )
)
( ?:\ s + $ Modifier | \ s + const ) *
} x ;
2007-11-28 16:21:06 -08:00
$ Type = qr {
2008-06-05 22:46:01 -07:00
$ NonptrType
2012-03-23 15:02:18 -07:00
( ?: ( ?:\ s | \* | \ [ \ ] ) +\ s * const | ( ?:\ s | \* | \ [ \ ] ) + | ( ?:\ s *\ [ \ s *\ ] ) + ) ?
2008-07-23 21:28:57 -07:00
( ?:\ s + $ Inline | \ s + $ Modifier ) *
2007-11-28 16:21:06 -08:00
} x ;
$ Declare = qr { ( ?: $ Storage \ s + ) ? $ Type } ;
}
build_types ( ) ;
2007-10-18 03:05:08 -07:00
2011-07-25 17:13:22 -07:00
our $ Typecast = qr { \ s * ( \ ( \ s * $ NonptrType \ s *\ ) ) { 0 , 1 } \ s * } ;
2012-03-23 15:02:16 -07: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 ) ) *\ ) ) / ;
2014-04-03 14:49:13 -07:00
our $ LvalOrFunc = qr { ( ( ?: [ \&\* ] \ s * ) ? $ Lval ) \ s * ( $ balanced_parens { 0 , 1 } ) \ s * } ;
2012-01-10 15:09:58 -08:00
our $ FuncArg = qr { $ Typecast { 0 , 1 } ( $ LvalOrFunc | $ Constant ) } ;
2011-07-25 17:13:22 -07:00
sub deparenthesize {
my ( $ string ) = @ _ ;
return "" if ( ! defined ( $ string ) ) ;
2014-04-03 14:49:21 -07:00
while ( $ string =~ /^\ s *\ ( . *\ ) \ s * $ / ) {
$ string =~ s @^\ s *\ ( \ s *@@ ;
$ string =~ s @\ s *\ ) \ s * $ @@ ;
}
2011-07-25 17:13:22 -07:00
$ string =~ s @\ s +@ @ g ;
2014-04-03 14:49:21 -07:00
2011-07-25 17:13:22 -07:00
return $ string ;
}
2013-07-03 15:05:34 -07:00
sub seed_camelcase_file {
my ( $ file ) = @ _ ;
return if ( ! ( - f $ file ) ) ;
local $ / ;
open ( my $ include_file , '<' , "$file" )
or warn "$P: Can't read '$file' $!\n" ;
my $ text = < $ include_file > ;
close ( $ include_file ) ;
my @ lines = split ( '\n' , $ text ) ;
foreach my $ line ( @ lines ) {
next if ( $ line ! ~ / ( ?: [ A - Z ] [ a - z ] | [ a - z ] [ A - Z ] ) / ) ;
if ( $ line =~ /^ [ \ t ] * ( ?:# [ \ t ] * define | typedef \ s + $ Type ) \ s + ( \ w * ( ?: [ A - Z ] [ a - z ] | [ a - z ] [ A - Z ] ) \ w * ) / ) {
$ camelcase { $ 1 } = 1 ;
2013-11-12 15:10:08 -08:00
} elsif ( $ line =~ /^\ s * $ Declare \ s + ( \ w * ( ?: [ A - Z ] [ a - z ] | [ a - z ] [ A - Z ] ) \ w * ) \ s * [ \ ( \ [ , ; ] / ) {
$ camelcase { $ 1 } = 1 ;
} elsif ( $ line =~ /^\ s * ( ?: union | struct | enum ) \ s + ( \ w * ( ?: [ A - Z ] [ a - z ] | [ a - z ] [ A - Z ] ) \ w * ) \ s * [ ; \ { ] / ) {
2013-07-03 15:05:34 -07:00
$ camelcase { $ 1 } = 1 ;
}
}
}
my $ camelcase_seeded = 0 ;
sub seed_camelcase_includes {
return if ( $ camelcase_seeded ) ;
my $ files ;
2013-07-08 16:00:43 -07:00
my $ camelcase_cache = "" ;
my @ include_files = ( ) ;
$ camelcase_seeded = 1 ;
2013-07-03 15:05:36 -07:00
2014-02-10 14:25:32 -08:00
if ( - e ".git" ) {
2013-07-03 15:05:36 -07:00
my $ git_last_include_commit = ` git log -- no - merges -- pretty = format : "%h%n" - 1 -- include ` ;
chomp $ git_last_include_commit ;
2013-07-08 16:00:43 -07:00
$ camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit" ;
2013-07-03 15:05:34 -07:00
} else {
2013-07-08 16:00:43 -07:00
my $ last_mod_date = 0 ;
2013-07-03 15:05:34 -07:00
$ files = ` find $ root / include - name "*.h" ` ;
2013-07-08 16:00:43 -07:00
@ include_files = split ( '\n' , $ files ) ;
foreach my $ file ( @ include_files ) {
my $ date = POSIX :: strftime ( "%Y%m%d%H%M" ,
localtime ( ( stat $ file ) [ 9 ] ) ) ;
$ last_mod_date = $ date if ( $ last_mod_date < $ date ) ;
}
$ camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date" ;
2013-07-03 15:05:34 -07:00
}
2013-07-08 16:00:43 -07:00
if ( $ camelcase_cache ne "" && - f $ camelcase_cache ) {
open ( my $ camelcase_file , '<' , "$camelcase_cache" )
or warn "$P: Can't read '$camelcase_cache' $!\n" ;
while ( < $ camelcase_file > ) {
chomp ;
$ camelcase { $ _ } = 1 ;
}
close ( $ camelcase_file ) ;
return ;
}
2014-02-10 14:25:32 -08:00
if ( - e ".git" ) {
2013-07-08 16:00:43 -07:00
$ files = ` git ls - files "include/*.h" ` ;
@ include_files = split ( '\n' , $ files ) ;
}
2013-07-03 15:05:34 -07:00
foreach my $ file ( @ include_files ) {
seed_camelcase_file ( $ file ) ;
}
2013-07-03 15:05:36 -07:00
2013-07-08 16:00:43 -07:00
if ( $ camelcase_cache ne "" ) {
2013-07-03 15:05:36 -07:00
unlink glob ".checkpatch-camelcase.*" ;
2013-07-08 16:00:43 -07:00
open ( my $ camelcase_file , '>' , "$camelcase_cache" )
or warn "$P: Can't write '$camelcase_cache' $!\n" ;
2013-07-03 15:05:36 -07:00
foreach ( sort { lc ( $ a ) cmp lc ( $ b ) } keys ( %camelcase)) {
print $ camelcase_file ( "$_\n" ) ;
}
close ( $ camelcase_file ) ;
}
2013-07-03 15:05:34 -07:00
}
2007-10-18 03:05:08 -07:00
$ chk_signoff = 0 if ( $ file ) ;
2007-06-08 13:47:06 -07:00
my @ rawlines = ( ) ;
2008-02-08 04:20:54 -08:00
my @ lines = ( ) ;
2013-07-03 15:05:31 -07:00
my @ fixed = ( ) ;
2008-02-08 04:20:54 -08:00
my $ vname ;
2007-10-18 03:05:08 -07:00
for my $ filename ( @ ARGV ) {
2009-01-06 14:41:30 -08:00
my $ FILE ;
2007-10-18 03:05:08 -07:00
if ( $ file ) {
2009-01-06 14:41:30 -08:00
open ( $ FILE , '-|' , "diff -u /dev/null $filename" ) | |
2007-10-18 03:05:08 -07:00
die "$P: $filename: diff failed - $!\n" ;
2009-01-06 14:41:30 -08:00
} elsif ( $ filename eq '-' ) {
open ( $ FILE , '<&STDIN' ) ;
2007-10-18 03:05:08 -07:00
} else {
2009-01-06 14:41:30 -08:00
open ( $ FILE , '<' , "$filename" ) | |
2007-10-18 03:05:08 -07:00
die "$P: $filename: open failed - $!\n" ;
2007-06-01 00:46:48 -07:00
}
2008-02-08 04:20:54 -08:00
if ( $ filename eq '-' ) {
$ vname = 'Your patch' ;
} else {
$ vname = $ filename ;
}
2009-01-06 14:41:30 -08:00
while ( < $ FILE > ) {
2007-10-18 03:05:08 -07:00
chomp ;
push ( @ rawlines , $ _ ) ;
}
2009-01-06 14:41:30 -08:00
close ( $ FILE ) ;
2008-02-08 04:20:54 -08:00
if ( ! process ( $ filename ) ) {
2007-10-18 03:05:08 -07:00
$ exit = 1 ;
}
@ rawlines = ( ) ;
2008-02-08 04:22:03 -08:00
@ lines = ( ) ;
2013-07-03 15:05:31 -07:00
@ fixed = ( ) ;
2007-06-01 00:46:48 -07:00
}
exit ( $ exit ) ;
sub top_of_kernel_tree {
2007-10-18 03:05:08 -07: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 00:46:48 -07:00
}
2007-10-18 03:05:08 -07:00
return 1 ;
2012-10-04 17:13:32 -07:00
}
2007-06-01 00:46:48 -07:00
2011-07-25 17:13:23 -07: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 ;
2013-07-03 15:05:31 -07:00
$ name = trim ( $ name ) ;
2011-07-25 17:13:23 -07:00
$ 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 = " " ;
}
}
2013-07-03 15:05:31 -07:00
$ name = trim ( $ name ) ;
2011-07-25 17:13:23 -07:00
$ name =~ s /^\ " | \ " $ // g ;
2013-07-03 15:05:31 -07:00
$ address = trim ( $ address ) ;
2011-07-25 17:13:23 -07:00
$ 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 ;
2013-07-03 15:05:31 -07:00
$ name = trim ( $ name ) ;
2011-07-25 17:13:23 -07:00
$ name =~ s /^\ " | \ " $ // g ;
2013-07-03 15:05:31 -07:00
$ address = trim ( $ address ) ;
2011-07-25 17:13:23 -07:00
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-25 17:13:25 -07:00
sub which_conf {
my ( $ conf ) = @ _ ;
foreach my $ path ( split ( /:/ , ".:$ENV{HOME}:.scripts" ) ) {
if ( - e "$path/$conf" ) {
return "$path/$conf" ;
}
}
return "" ;
}
2007-06-01 00:46:48 -07: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 03:05:08 -07:00
sub copy_spacing {
2008-03-28 14:15:58 -07:00
( my $ res = shift ) =~ tr /\ t / / c ;
2007-10-18 03:05:08 -07:00
return $ res ;
}
2007-06-01 00:46:48 -07:00
2007-06-08 13:46:39 -07: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-28 14:15:58 -07:00
my $ sanitise_quote = '' ;
sub sanitise_line_reset {
my ( $ in_comment ) = @ _ ;
if ( $ in_comment ) {
$ sanitise_quote = '*/' ;
} else {
$ sanitise_quote = '' ;
}
}
2007-06-08 13:47:06 -07:00
sub sanitise_line {
my ( $ line ) = @ _ ;
my $ res = '' ;
my $ l = '' ;
2008-02-08 04:20:54 -08:00
my $ qlen = 0 ;
2008-03-28 14:15:58 -07:00
my $ off = 0 ;
my $ c ;
2007-06-08 13:47:06 -07:00
2008-03-28 14:15:58 -07: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 ;
2008-02-08 04:20:54 -08:00
}
2008-10-15 22:02:26 -07:00
if ( $ sanitise_quote eq '*/' && substr ( $ line , $ off , 2 ) eq '*/' ) {
2008-03-28 14:15:58 -07:00
$ sanitise_quote = '' ;
substr ( $ res , $ off , 2 , "$;$;" ) ;
$ off ++ ;
next ;
}
2009-09-21 17:04:35 -07:00
if ( $ sanitise_quote eq '' && substr ( $ line , $ off , 2 ) eq '//' ) {
$ sanitise_quote = '//' ;
substr ( $ res , $ off , 2 , $ sanitise_quote ) ;
$ off ++ ;
next ;
}
2008-03-28 14:15:58 -07: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;
}
# Regular quotes.
if ($c eq " '" || $c eq ' "') {
if ($sanitise_quote eq '') {
$sanitise_quote = $c;
substr($res, $off, 1, $c);
2007-06-08 13:47:06 -07:00
next;
2008-03-28 14:15:58 -07:00
} elsif ($sanitise_quote eq $c) {
$sanitise_quote = '';
2007-06-08 13:47:06 -07:00
}
}
2008-03-28 14:15:58 -07:00
2009-01-06 14:41:20 -08:00
#print " c < $ c > SQ < $ sanitise_quote >\ n ";
2008-03-28 14:15:58 -07:00
if ($off != 0 && $sanitise_quote eq '*/' && $c ne " \ t ") {
substr($res, $off, 1, $;);
2009-09-21 17:04:35 -07:00
} elsif ($off != 0 && $sanitise_quote eq '//' && $c ne " \ t ") {
substr($res, $off, 1, $;);
2008-03-28 14:15:58 -07:00
} elsif ($off != 0 && $sanitise_quote && $c ne " \ t " ) {
substr ( $ res , $ off , 1 , 'X' ) ;
2007-06-08 13:47:06 -07:00
} else {
2008-03-28 14:15:58 -07:00
substr ( $ res , $ off , 1 , $ c ) ;
2007-06-08 13:47:06 -07:00
}
2008-02-08 04:20:54 -08:00
}
2009-09-21 17:04:35 -07:00
if ( $ sanitise_quote eq '//' ) {
$ sanitise_quote = '' ;
}
2008-02-08 04:20:54 -08:00
# The pathname on a # include may be surrounded by '<' and '>' .
2008-06-05 22:46:01 -07:00
if ( $ res =~ /^.\ s *\#\ s * include \ s +\< ( . * ) \>/ ) {
2008-02-08 04:20:54 -08:00
my $ clean = 'X' x length ( $ 1 ) ;
$ res =~ s @\<.*\>@< $ clean >@ ;
# The whole of a # error is a string .
2008-06-05 22:46:01 -07:00
} elsif ( $ res =~ /^.\ s *\#\ s * ( ?: error | warning ) \ s + ( . * ) \ b / ) {
2008-02-08 04:20:54 -08:00
my $ clean = 'X' x length ( $ 1 ) ;
2008-06-05 22:46:01 -07:00
$ res =~ s @ ( \#\ s * ( ?: error | warning ) \ s + ) . *@ $ 1 $ clean @ ;
2008-02-08 04:20:54 -08:00
}
2007-06-08 13:47:06 -07:00
return $ res ;
}
2013-04-29 16:18:13 -07:00
sub get_quoted_string {
my ( $ line , $ rawline ) = @ _ ;
return "" if ( $ line ! ~ m / ( \ "[X]+\")/g);
return substr($rawline, $-[0], $+[0] - $-[0]);
}
2007-11-28 16:21:06 -08:00
sub ctx_statement_block {
my ($linenr, $remain, $off) = @_;
my $line = $linenr - 1;
my $blk = '';
my $soff = $off;
my $coff = $off - 1;
2008-03-28 14:15:58 -07:00
my $coff_set = 0;
2007-11-28 16:21:06 -08:00
2008-02-08 04:22:03 -08:00
my $loff = 0;
2007-11-28 16:21:06 -08:00
my $type = '';
my $level = 0;
2009-01-15 13:51:04 -08:00
my @stack = ();
2008-03-04 14:28:20 -08:00
my $p;
2007-11-28 16:21:06 -08:00
my $c;
my $len = 0;
2008-02-08 04:22:03 -08:00
my $remainder;
2007-11-28 16:21:06 -08:00
while (1) {
2009-01-15 13:51:04 -08:00
@stack = (['', 0]) if ($#stack == -1);
2008-03-28 14:15:58 -07:00
#warn " CSB : blk < $ blk > remain < $ remain >\ n ";
2007-11-28 16:21:06 -08:00
# If we are about to drop off the end, pull in more
# context.
if ($off >= $len) {
for (; $remain > 0; $line++) {
2008-10-15 22:02:25 -07:00
last if (!defined $lines[$line]);
2008-02-08 04:20:54 -08:00
next if ($lines[$line] =~ /^-/);
2007-11-28 16:21:06 -08:00
$remain--;
2008-02-08 04:22:03 -08:00
$loff = $len;
2008-02-08 04:20:54 -08:00
$blk .= $lines[$line] . " \ n ";
2007-11-28 16:21:06 -08: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 04:22:03 -08:00
if ($off >= $len) {
2007-11-28 16:21:06 -08:00
last;
}
2012-01-10 15:09:54 -08:00
if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) {
$level++;
$type = '#';
}
2007-11-28 16:21:06 -08:00
}
2008-03-04 14:28:20 -08:00
$p = $c;
2007-11-28 16:21:06 -08:00
$c = substr($blk, $off, 1);
2008-02-08 04:22:03 -08:00
$remainder = substr($blk, $off);
2007-11-28 16:21:06 -08:00
2008-03-28 14:15:58 -07:00
#warn " CSB : c < $ c > type < $ type > level < $ level > remainder < $ remainder > coff_set < $ coff_set >\ n " ;
2009-01-06 14:41:27 -08: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-28 16:21:06 -08:00
# Statement ends at the ';' or a close '}' at the
# outermost level .
if ( $ level == 0 && $ c eq ';' ) {
last ;
}
2008-02-08 04:22:03 -08:00
# An else is really a conditional as long as its not else if
2008-03-28 14:15:58 -07: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 04:22:03 -08:00
}
2007-11-28 16:21:06 -08: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-28 14:15:58 -07:00
$ coff_set = 1 ;
# warn "CSB: mark coff<$coff>\n" ;
2007-11-28 16:21:06 -08:00
}
}
if ( ( $ type eq '' | | $ type eq '{' ) && $ c eq '{' ) {
$ level ++ ;
$ type = '{' ;
}
if ( $ type eq '{' && $ c eq '}' ) {
$ level -- ;
$ type = ( $ level ! = 0 ) ? '{' : '' ;
if ( $ level == 0 ) {
2010-08-09 17:21:03 -07:00
if ( substr ( $ blk , $ off + 1 , 1 ) eq ';' ) {
$ off ++ ;
}
2007-11-28 16:21:06 -08:00
last ;
}
}
2012-01-10 15:09:54 -08:00
# Preprocessor commands end at the newline unless escaped .
if ( $ type eq '#' && $ c eq "\n" && $ p ne " \\ ") {
$level--;
$type = '';
$off++;
last;
}
2007-11-28 16:21:06 -08:00
$off++;
}
2008-07-23 21:29:00 -07:00
# We are truly at the end, so shuffle to the next line.
2008-02-08 04:22:03 -08:00
if ($off == $len) {
2008-07-23 21:29:00 -07:00
$loff = $len + 1;
2008-02-08 04:22:03 -08:00
$line++;
$remain--;
}
2007-11-28 16:21:06 -08: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-28 14:15:58 -07:00
#print " coff < $ coff > soff < $ off > loff < $ loff >\ n ";
2008-02-08 04:22:03 -08:00
return ($statement, $condition,
$line, $remain + 1, $off - $loff + 1, $level);
}
2008-03-04 14:28:20 -08: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 04:22:03 -08:00
sub ctx_statement_full {
my ($linenr, $remain, $off) = @_;
my ($statement, $condition, $level);
my (@chunks);
2008-03-04 14:28:20 -08:00
# Grab the first conditional/block pair.
2008-02-08 04:22:03 -08:00
($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off);
2008-03-28 14:15:58 -07:00
#print " F : c < $ condition > s < $ statement > remain < $ remain >\ n ";
2008-03-04 14:28:20 -08: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 04:22:03 -08:00
for (;;) {
($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off);
2008-03-04 14:28:20 -08:00
#print " C : c < $ condition > s < $ statement > remain < $ remain >\ n ";
2008-03-28 14:15:58 -07:00
last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
2008-03-04 14:28:20 -08:00
#print " C : push \ n ";
push(@chunks, [ $condition, $statement ]);
2008-02-08 04:22:03 -08:00
}
return ($level, $linenr, @chunks);
2007-11-28 16:21:06 -08:00
}
2007-06-08 13:46:39 -07:00
sub ctx_block_get {
2007-07-19 01:48:34 -07:00
my ($linenr, $remain, $outer, $open, $close, $off) = @_;
2007-06-08 13:46:39 -07:00
my $line;
my $start = $linenr - 1;
my $blk = '';
my @o;
my @c;
my @res = ();
2007-07-19 01:48:34 -07:00
my $level = 0;
2009-01-06 14:41:27 -08:00
my @stack = ($level);
2007-06-08 13:47:06 -07:00
for ($line = $start; $remain > 0; $line++) {
next if ($rawlines[$line] =~ /^-/);
$remain--;
$blk .= $rawlines[$line];
2009-01-06 14:41:27 -08:00
# Handle nested #if/#else.
2010-10-26 14:23:19 -07:00
if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
2009-01-06 14:41:27 -08:00
push(@stack, $level);
2010-10-26 14:23:19 -07:00
} elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
2009-01-06 14:41:27 -08:00
$level = $stack[$#stack - 1];
2010-10-26 14:23:19 -07:00
} elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
2009-01-06 14:41:27 -08:00
$level = pop(@stack);
}
2010-10-26 14:23:19 -07:00
foreach my $c (split(//, $lines[$line])) {
2007-07-19 01:48:34 -07:00
##print " C < $ c > L < $ level >< $ open$close > O < $ off >\ n " ;
if ( $ off > 0 ) {
$ off -- ;
next ;
}
2007-06-08 13:46:39 -07:00
2007-07-19 01:48:34 -07:00
if ( $ c eq $ close && $ level > 0 ) {
$ level -- ;
last if ( $ level == 0 ) ;
} elsif ( $ c eq $ open ) {
$ level ++ ;
}
}
2007-06-08 13:46:39 -07:00
2007-07-19 01:48:34 -07:00
if ( ! $ outer | | $ level <= 1 ) {
2007-06-08 13:47:06 -07:00
push ( @ res , $ rawlines [ $ line ] ) ;
2007-06-08 13:46:39 -07:00
}
2007-07-19 01:48:34 -07:00
last if ( $ level == 0 ) ;
2007-06-08 13:46:39 -07:00
}
2007-07-19 01:48:34 -07:00
return ( $ level , @ res ) ;
2007-06-08 13:46:39 -07:00
}
sub ctx_block_outer {
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 01:48:34 -07:00
my ( $ level , @ r ) = ctx_block_get ( $ linenr , $ remain , 1 , '{' , '}' , 0 ) ;
return @ r ;
2007-06-08 13:46:39 -07:00
}
sub ctx_block {
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 01:48:34 -07:00
my ( $ level , @ r ) = ctx_block_get ( $ linenr , $ remain , 0 , '{' , '}' , 0 ) ;
return @ r ;
2007-06-23 17:16:34 -07:00
}
sub ctx_statement {
2007-07-19 01:48:34 -07:00
my ( $ linenr , $ remain , $ off ) = @ _ ;
my ( $ level , @ r ) = ctx_block_get ( $ linenr , $ remain , 0 , '(' , ')' , $ off ) ;
return @ r ;
}
sub ctx_block_level {
2007-06-23 17:16:34 -07:00
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 01:48:34 -07:00
return ctx_block_get ( $ linenr , $ remain , 0 , '{' , '}' , 0 ) ;
2007-06-08 13:46:39 -07:00
}
2007-10-16 23:29:38 -07:00
sub ctx_statement_level {
my ( $ linenr , $ remain , $ off ) = @ _ ;
return ctx_block_get ( $ linenr , $ remain , 0 , '(' , ')' , $ off ) ;
}
2007-06-08 13:46:39 -07:00
sub ctx_locate_comment {
my ( $ first_line , $ end_line ) = @ _ ;
# Catch a comment on the end of the line itself .
2008-07-23 21:28:59 -07:00
my ( $ current_comment ) = ( $ rawlines [ $ end_line - 1 ] =~ m @.* ( /\*.*\*/ ) \ s * ( ?:\\\ s * ) ? $ @ ) ;
2007-06-08 13:46:39 -07: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-08 13:47:06 -07:00
my $ line = $ rawlines [ $ linenr - 1 ] ;
# warn " $line\n" ;
2007-06-08 13:46:39 -07: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-08 13:47:06 -07:00
## print "LINE: $rawlines[$end_line - 1 ]\n" ;
2007-06-08 13:46:39 -07:00
## print "CMMT: $cmt\n" ;
return ( $ cmt ne '' ) ;
}
2008-10-15 22:02:21 -07: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-06-01 00:46:48 -07:00
sub cat_vet {
my ( $ vet ) = @ _ ;
2007-10-16 23:29:38 -07:00
my ( $ res , $ coded ) ;
2007-06-01 00:46:48 -07:00
2007-10-16 23:29:38 -07:00
$ res = '' ;
2007-10-18 03:05:08 -07:00
while ( $ vet =~ / ( [ ^ [ : cntrl : ] ] * ) ( [ [ : cntrl : ] ] | $ ) / g ) {
$ res . = $ 1 ;
if ( $ 2 ne '' ) {
$ coded = sprintf ( "^%c" , unpack ( 'C' , $ 2 ) + 64 ) ;
$ res . = $ coded ;
}
2007-10-16 23:29:38 -07:00
}
$ res =~ s / $ /\ $ / ;
2007-06-01 00:46:48 -07:00
2007-10-16 23:29:38 -07:00
return $ res ;
2007-06-01 00:46:48 -07:00
}
2008-02-08 04:20:54 -08:00
my $ av_preprocessor = 0 ;
2008-03-04 14:28:20 -08:00
my $ av_pending ;
2008-02-08 04:20:54 -08:00
my @ av_paren_type ;
2008-07-23 21:29:10 -07:00
my $ av_pend_colon ;
2008-02-08 04:20:54 -08:00
sub annotate_reset {
$ av_preprocessor = 0 ;
2008-03-04 14:28:20 -08:00
$ av_pending = '_' ;
@ av_paren_type = ( 'E' ) ;
2008-07-23 21:29:10 -07:00
$ av_pend_colon = 'O' ;
2008-02-08 04:20:54 -08:00
}
2007-10-18 03:05:08 -07:00
sub annotate_values {
my ( $ stream , $ type ) = @ _ ;
my $ res ;
2008-07-23 21:29:10 -07:00
my $ var = '_' x length ( $ stream ) ;
2007-10-18 03:05:08 -07:00
my $ cur = $ stream ;
2008-02-08 04:20:54 -08:00
print "$stream\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
while ( length ( $ cur ) ) {
2008-03-28 14:15:58 -07:00
@ av_paren_type = ( 'E' ) if ( $ # av_paren_type < 0 ) ;
2008-03-04 14:28:20 -08:00
print " <" . join ( '' , @ av_paren_type ) .
2008-04-29 00:59:32 -07:00
"> <$type> <$av_pending>" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
if ( $ cur =~ /^ ( \ s + ) / o ) {
2008-02-08 04:20:54 -08:00
print "WS($1)\n" if ( $ dbg_values > 1 ) ;
if ( $ 1 =~ /\ n / && $ av_preprocessor ) {
2008-03-04 14:28:20 -08:00
$ type = pop ( @ av_paren_type ) ;
2008-02-08 04:20:54 -08:00
$ av_preprocessor = 0 ;
2007-10-18 03:05:08 -07:00
}
2011-01-12 16:59:58 -08:00
} elsif ( $ cur =~ /^ ( \ ( \ s * $ Type \ s * ) \ ) / && $ av_pending eq '_' ) {
2010-10-26 14:23:13 -07:00
print "CAST($1)\n" if ( $ dbg_values > 1 ) ;
push ( @ av_paren_type , $ type ) ;
2012-01-10 15:10:11 -08:00
$ type = 'c' ;
2010-10-26 14:23:13 -07:00
2010-10-26 14:23:11 -07:00
} elsif ( $ cur =~ /^ ( $ Type ) \ s * ( ?: $ Ident | , | \ ) | \ ( | \ s * $ ) / ) {
2008-02-08 04:20:54 -08:00
print "DECLARE($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
$ type = 'T' ;
2008-07-23 21:29:05 -07:00
} elsif ( $ cur =~ /^ ( $ Modifier ) \ s */ ) {
print "MODIFIER($1)\n" if ( $ dbg_values > 1 ) ;
$ type = 'T' ;
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\ s * define \ s * $ Ident ) ( \ ( ? ) / o ) {
2008-04-29 00:59:32 -07:00
print "DEFINE($1,$2)\n" if ( $ dbg_values > 1 ) ;
2008-02-08 04:20:54 -08:00
$ av_preprocessor = 1 ;
2008-04-29 00:59:32 -07:00
push ( @ av_paren_type , $ type ) ;
if ( $ 2 ne '' ) {
$ av_pending = 'N' ;
}
$ type = 'E' ;
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\ s * ( ?: undef \ s * $ Ident | include \ b ) ) / o ) {
2008-04-29 00:59:32 -07:00
print "UNDEF($1)\n" if ( $ dbg_values > 1 ) ;
$ av_preprocessor = 1 ;
push ( @ av_paren_type , $ type ) ;
2007-10-18 03:05:08 -07:00
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\ s * ( ?: ifdef | ifndef | if ) ) / o ) {
2008-03-04 14:28:20 -08:00
print "PRE_START($1)\n" if ( $ dbg_values > 1 ) ;
2008-02-08 04:20:54 -08:00
$ av_preprocessor = 1 ;
2008-03-04 14:28:20 -08:00
push ( @ av_paren_type , $ type ) ;
push ( @ av_paren_type , $ type ) ;
2008-04-29 00:59:32 -07:00
$ type = 'E' ;
2008-03-04 14:28:20 -08:00
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\ s * ( ?: else | elif ) ) / o ) {
2008-03-04 14:28:20 -08: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 00:59:32 -07:00
$ type = 'E' ;
2008-03-04 14:28:20 -08:00
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\ s * ( ?: endif ) ) / o ) {
2008-03-04 14:28:20 -08: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 00:59:32 -07:00
$ type = 'E' ;
2007-10-18 03:05:08 -07:00
} elsif ( $ cur =~ /^ ( \\\ n ) / o ) {
2008-02-08 04:20:54 -08:00
print "PRECONT($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
2008-04-29 00:59:32 -07:00
} elsif ( $ cur =~ /^ ( _ _ attribute__ ) \ s *\ ( ?/ o ) {
print "ATTR($1)\n" if ( $ dbg_values > 1 ) ;
$ av_pending = $ type ;
$ type = 'N' ;
2007-10-18 03:05:08 -07:00
} elsif ( $ cur =~ /^ ( sizeof ) \ s * ( \ ( ) ?/ o ) {
2008-02-08 04:20:54 -08:00
print "SIZEOF($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
if ( defined $ 2 ) {
2008-03-04 14:28:20 -08:00
$ av_pending = 'V' ;
2007-10-18 03:05:08 -07:00
}
$ type = 'N' ;
2008-10-15 22:02:16 -07:00
} elsif ( $ cur =~ /^ ( if | while | for ) \ b / o ) {
2008-02-08 04:20:54 -08:00
print "COND($1)\n" if ( $ dbg_values > 1 ) ;
2008-10-15 22:02:16 -07:00
$ av_pending = 'E' ;
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
2008-07-23 21:29:10 -07:00
} elsif ( $ cur =~/^ ( case ) / o ) {
print "CASE($1)\n" if ( $ dbg_values > 1 ) ;
$ av_pend_colon = 'C' ;
$ type = 'N' ;
2008-10-15 22:02:16 -07:00
} elsif ( $ cur =~/^ ( return | else | goto | typeof | _ _ typeof__ ) \ b / o ) {
2008-02-08 04:20:54 -08:00
print "KEYWORD($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
} elsif ( $ cur =~ /^ ( \ ( ) / o ) {
2008-02-08 04:20:54 -08:00
print "PAREN('$1')\n" if ( $ dbg_values > 1 ) ;
2008-03-04 14:28:20 -08:00
push ( @ av_paren_type , $ av_pending ) ;
$ av_pending = '_' ;
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
} elsif ( $ cur =~ /^ ( \ ) ) / o ) {
2008-03-04 14:28:20 -08:00
my $ new_type = pop ( @ av_paren_type ) ;
if ( $ new_type ne '_' ) {
$ type = $ new_type ;
2008-02-08 04:20:54 -08:00
print "PAREN('$1') -> $type\n"
if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
} else {
2008-02-08 04:20:54 -08:00
print "PAREN('$1')\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
}
2008-07-23 21:28:57 -07:00
} elsif ( $ cur =~ /^ ( $ Ident ) \ s *\ ( / o ) {
2008-02-08 04:20:54 -08:00
print "FUNC($1)\n" if ( $ dbg_values > 1 ) ;
2008-07-23 21:28:57 -07:00
$ type = 'V' ;
2008-03-04 14:28:20 -08:00
$ av_pending = 'V' ;
2007-10-18 03:05:08 -07:00
2009-01-06 14:41:19 -08:00
} elsif ( $ cur =~ /^ ( $ Ident \ s * ) : ( ?:\ s *\ d +\ s * ( , | = | ; ) ) ?/ ) {
if ( defined $ 2 && $ type eq 'C' | | $ type eq 'T' ) {
2008-07-23 21:29:10 -07:00
$ av_pend_colon = 'B' ;
2009-01-06 14:41:19 -08:00
} elsif ( $ type eq 'E' ) {
$ av_pend_colon = 'L' ;
2008-07-23 21:29:10 -07:00
}
print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ( $ dbg_values > 1 ) ;
$ type = 'V' ;
2007-10-18 03:05:08 -07:00
} elsif ( $ cur =~ /^ ( $ Ident | $ Constant ) / o ) {
2008-02-08 04:20:54 -08:00
print "IDENT($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
$ type = 'V' ;
} elsif ( $ cur =~ /^ ( $ Assignment ) / o ) {
2008-02-08 04:20:54 -08:00
print "ASSIGN($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
2008-03-04 14:28:20 -08:00
} elsif ( $ cur =~/^ ( ; | { | } ) / ) {
2008-02-08 04:20:54 -08:00
print "END($1)\n" if ( $ dbg_values > 1 ) ;
2008-02-08 04:22:03 -08:00
$ type = 'E' ;
2008-07-23 21:29:10 -07:00
$ av_pend_colon = 'O' ;
2008-02-08 04:22:03 -08:00
2009-01-06 14:41:19 -08:00
} elsif ( $ cur =~/^ ( , ) / ) {
print "COMMA($1)\n" if ( $ dbg_values > 1 ) ;
$ type = 'C' ;
2008-07-23 21:29:10 -07: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' ;
2009-01-06 14:41:19 -08:00
} elsif ( $ cur =~ /^ ( \ [ ) / o ) {
2008-02-08 04:22:03 -08:00
print "CLOSE($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
2008-10-15 22:02:16 -07:00
} elsif ( $ cur =~ /^ ( - ( ? ! [ -> ] ) | \+ ( ? ! \+ ) | \* | \&\& | \& ) / o ) {
2008-07-23 21:29:10 -07: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 03:05:08 -07:00
} elsif ( $ cur =~ /^ ( $ Operators ) / o ) {
2008-02-08 04:20:54 -08:00
print "OP($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
if ( $ 1 ne '++' && $ 1 ne '--' ) {
$ type = 'N' ;
}
} elsif ( $ cur =~ / ( ^. ) / o ) {
2008-02-08 04:20:54 -08:00
print "C($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 03:05:08 -07:00
}
if ( defined $ 1 ) {
$ cur = substr ( $ cur , length ( $ 1 ) ) ;
$ res . = $ type x length ( $ 1 ) ;
}
}
2008-07-23 21:29:10 -07:00
return ( $ res , $ var ) ;
2007-10-18 03:05:08 -07:00
}
2007-11-28 16:21:06 -08:00
sub possible {
2008-02-08 04:22:03 -08:00
my ( $ possible , $ line ) = @ _ ;
2009-10-26 16:50:12 -07:00
my $ notPermitted = qr { ( ?:
2008-10-15 22:02:29 -07:00
^ ( ?:
$ Modifier |
$ Storage |
$ Type |
2009-10-26 16:50:12 -07:00
DEFINE_ \ S +
) $ |
^ ( ?:
2008-10-15 22:02:29 -07:00
goto |
return |
case |
else |
asm | _ _ asm__ |
2012-01-10 15:10:00 -08:00
do |
\# |
\#\# |
2009-10-26 16:50:12 -07:00
) ( ?:\ s | $ ) |
2008-10-15 22:02:29 -07:00
^ ( ?: typedef | struct | enum ) \ b
2009-10-26 16:50:12 -07:00
) } x ;
warn "CHECK<$possible> ($line)\n" if ( $ dbg_possible > 2 ) ;
if ( $ possible ! ~ $ notPermitted ) {
2008-06-05 22:46:01 -07: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-23 21:29:09 -07:00
for my $ modifier ( split ( ' ' , $ possible ) ) {
2009-10-26 16:50:12 -07:00
if ( $ modifier ! ~ $ notPermitted ) {
warn "MODIFIER: $modifier ($possible) ($line)\n" if ( $ dbg_possible ) ;
push ( @ modifierList , $ modifier ) ;
}
2008-07-23 21:29:09 -07:00
}
2008-06-05 22:46:01 -07:00
} else {
warn "POSSIBLE: $possible ($line)\n" if ( $ dbg_possible ) ;
push ( @ typeList , $ possible ) ;
}
2007-11-28 16:21:06 -08:00
build_types ( ) ;
2008-10-15 22:02:29 -07:00
} else {
warn "NOTPOSS: $possible ($line)\n" if ( $ dbg_possible > 1 ) ;
2007-11-28 16:21:06 -08:00
}
}
2007-10-18 03:05:08 -07:00
my $ prefix = '' ;
2011-07-25 17:13:25 -07:00
sub show_type {
2014-04-03 14:49:19 -07:00
my ( $ type ) = @ _ ;
2013-09-11 14:23:59 -07:00
2014-04-03 14:49:19 -07:00
return defined $ use_type { $ type } if ( scalar keys %use_type > 0);
return ! defined $ ignore_type { $ type } ;
2011-07-25 17:13:25 -07:00
}
2007-07-19 01:48:34 -07:00
sub report {
2014-04-03 14:49:19 -07:00
my ( $ level , $ type , $ msg ) = @ _ ;
if ( ! show_type ( $ type ) | |
( defined $ tst_only && $ msg ! ~ /\ Q $ tst_only \ E / ) ) {
2008-03-28 14:15:58 -07:00
return 0 ;
}
2011-07-25 17:13:25 -07:00
my $ line ;
if ( $ show_types ) {
2014-04-03 14:49:19 -07:00
$ line = "$prefix$level:$type: $msg\n" ;
2011-07-25 17:13:25 -07:00
} else {
2014-04-03 14:49:19 -07:00
$ line = "$prefix$level: $msg\n" ;
2011-07-25 17:13:25 -07:00
}
2007-11-28 16:21:06 -08:00
$ line = ( split ( '\n' , $ line ) ) [ 0 ] . "\n" if ( $ terse ) ;
2008-02-08 04:22:03 -08:00
push ( our @ report , $ line ) ;
2008-03-28 14:15:58 -07:00
return 1 ;
2007-07-19 01:48:34 -07:00
}
2014-04-03 14:49:19 -07:00
2007-07-19 01:48:34 -07:00
sub report_dump {
2008-02-08 04:22:03 -08:00
our @ report ;
2007-07-19 01:48:34 -07:00
}
2011-07-25 17:13:25 -07:00
2007-07-15 23:37:22 -07:00
sub ERROR {
2014-04-03 14:49:19 -07:00
my ( $ type , $ msg ) = @ _ ;
if ( report ( "ERROR" , $ type , $ msg ) ) {
2008-03-28 14:15:58 -07:00
our $ clean = 0 ;
our $ cnt_error ++ ;
2013-07-03 15:05:31 -07:00
return 1 ;
2008-03-28 14:15:58 -07:00
}
2013-07-03 15:05:31 -07:00
return 0 ;
2007-07-15 23:37:22 -07:00
}
sub WARN {
2014-04-03 14:49:19 -07:00
my ( $ type , $ msg ) = @ _ ;
if ( report ( "WARNING" , $ type , $ msg ) ) {
2008-03-28 14:15:58 -07:00
our $ clean = 0 ;
our $ cnt_warn ++ ;
2013-07-03 15:05:31 -07:00
return 1 ;
2008-03-28 14:15:58 -07:00
}
2013-07-03 15:05:31 -07:00
return 0 ;
2007-07-15 23:37:22 -07:00
}
sub CHK {
2014-04-03 14:49:19 -07:00
my ( $ type , $ msg ) = @ _ ;
if ( $ check && report ( "CHECK" , $ type , $ msg ) ) {
2007-10-18 03:05:08 -07:00
our $ clean = 0 ;
our $ cnt_chk ++ ;
2013-07-03 15:05:31 -07:00
return 1 ;
2007-10-18 03:05:08 -07:00
}
2013-07-03 15:05:31 -07:00
return 0 ;
2007-07-15 23:37:22 -07:00
}
2008-10-15 22:02:21 -07: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-25 17:13:25 -07:00
WARN ( "USE_RELATIVE_PATH" ,
"use relative pathname instead of absolute in changelog text\n" . $ herecurr ) ;
2008-10-15 22:02:21 -07:00
}
}
2013-07-03 15:05:31 -07:00
sub trim {
my ( $ string ) = @ _ ;
2013-09-11 14:24:01 -07:00
$ string =~ s /^\ s + | \ s + $ // g ;
return $ string ;
}
sub ltrim {
my ( $ string ) = @ _ ;
$ string =~ s /^\ s +// ;
return $ string ;
}
sub rtrim {
my ( $ string ) = @ _ ;
$ string =~ s /\ s + $ // ;
2013-07-03 15:05:31 -07:00
return $ string ;
}
2013-11-12 15:10:09 -08:00
sub string_find_replace {
my ( $ string , $ find , $ replace ) = @ _ ;
$ string =~ s / $ find / $ replace / g ;
return $ string ;
}
2013-07-03 15:05:31 -07:00
sub tabify {
my ( $ leading ) = @ _ ;
my $ source_indent = 8 ;
my $ max_spaces_before_tab = $ source_indent - 1 ;
my $ spaces_to_tab = " " x $ source_indent ;
# convert leading spaces to tabs
1 while $ leading =~ s @^ ( [ \ t ] * ) $ spaces_to_tab @ $ 1 \ t @ g ;
# Remove spaces before a tab
1 while $ leading =~ s @^ ( [ \ t ] * ) ( { 1 , $ max_spaces_before_tab } ) \ t @ $ 1 \ t @ g ;
return "$leading" ;
}
2012-03-23 15:02:16 -07: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 00:46:48 -07:00
sub process {
my $ filename = shift ;
my $ linenr = 0 ;
my $ prevline = "" ;
2008-02-08 04:20:54 -08:00
my $ prevrawline = "" ;
2007-06-01 00:46:48 -07:00
my $ stashline = "" ;
2008-02-08 04:20:54 -08:00
my $ stashrawline = "" ;
2007-06-01 00:46:48 -07:00
2007-06-08 13:46:39 -07:00
my $ length ;
2007-06-01 00:46:48 -07:00
my $ indent ;
my $ previndent = 0 ;
my $ stashindent = 0 ;
2007-07-15 23:37:22 -07:00
our $ clean = 1 ;
2007-06-01 00:46:48 -07:00
my $ signoff = 0 ;
my $ is_patch = 0 ;
2011-10-31 17:13:12 -07:00
my $ in_header_lines = 1 ;
my $ in_commit_log = 0 ; # Scanning lines before patch
2012-10-04 17:13:29 -07:00
my $ non_utf8_charset = 0 ;
2008-02-08 04:22:03 -08:00
our @ report = ( ) ;
2007-10-18 03:05:08 -07:00
our $ cnt_lines = 0 ;
our $ cnt_error = 0 ;
our $ cnt_warn = 0 ;
our $ cnt_chk = 0 ;
2007-06-01 00:46:48 -07: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 04:20:54 -08:00
my $ comment_edge = 0 ;
2007-06-01 00:46:48 -07:00
my $ first_line = 0 ;
2009-01-06 14:41:24 -08:00
my $ p1_prefix = '' ;
2007-06-01 00:46:48 -07:00
2008-02-08 04:22:03 -08:00
my $ prev_values = 'E' ;
# suppression flags
2008-03-28 14:15:58 -07:00
my %suppress_ifbraces;
2008-10-15 22:02:30 -07:00
my %suppress_whiletrailers;
2009-10-26 16:50:16 -07:00
my %suppress_export;
2012-01-10 15:10:01 -08:00
my $ suppress_statement = 0 ;
2007-06-23 17:16:34 -07:00
2013-09-11 14:23:57 -07:00
my %signatures = ();
2012-12-17 16:02:07 -08:00
2008-02-08 04:20:54 -08:00
# Pre - scan the patch sanitizing the lines .
2007-07-15 23:37:22 -07:00
# Pre - scan the patch looking for any _ _ setup documentation .
2008-02-08 04:20:54 -08:00
#
2007-07-15 23:37:22 -07:00
my @ setup_docs = ( ) ;
my $ setup_docs = 0 ;
2008-03-28 14:15:58 -07:00
2013-11-12 15:10:06 -08:00
my $ camelcase_file_seeded = 0 ;
2008-03-28 14:15:58 -07:00
sanitise_line_reset ( ) ;
2008-02-08 04:20:54 -08:00
my $ line ;
foreach my $ rawline ( @ rawlines ) {
2008-03-28 14:15:58 -07:00
$ linenr ++ ;
$ line = $ rawline ;
2008-02-08 04:20:54 -08:00
2013-07-03 15:05:31 -07:00
push ( @ fixed , $ rawline ) if ( $ fix ) ;
2008-03-28 14:15:58 -07:00
if ( $ rawline =~/^\+\+\+\ s + ( \ S + ) / ) {
2007-07-15 23:37:22 -07:00
$ setup_docs = 0 ;
if ( $ 1 =~ m @ Documentation / kernel - parameters . txt$ @ ) {
$ setup_docs = 1 ;
}
2008-03-28 14:15:58 -07:00
# next ;
2007-07-15 23:37:22 -07:00
}
2008-03-28 14:15:58 -07:00
if ( $ rawline =~/^\@\@ -\ d + ( ?: , \ d + ) ? \+ ( \ d + ) ( , ( \ d + ) ) ? \@\@/ ) {
$ realline = $ 1 - 1 ;
if ( defined $ 2 ) {
$ realcnt = $ 3 + 1 ;
} else {
$ realcnt = 1 + 1 ;
}
2008-06-05 22:46:01 -07:00
$ in_comment = 0 ;
2008-03-28 14:15:58 -07: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-15 22:02:19 -07: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-06 14:41:16 -08:00
last if ( ! defined $ rawlines [ $ ln - 1 ] ) ;
2009-01-06 14:41:20 -08:00
if ( $ rawlines [ $ ln - 1 ] =~ m @ ( /\* | \*/ ) @ &&
$ rawlines [ $ ln - 1 ] ! ~ m @ "[^" ] * ( ?:/\* | \*/ ) [ ^ "]*" @ ) {
( $ edge ) = $ 1 ;
last ;
}
2008-03-28 14:15:58 -07: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-06 14:41:17 -08:00
$ rawlines [ $ linenr ] =~ m @^.\ s * ( ?:\*\*+ | \* ) ( ?:\ s | $ ) @ )
2008-03-28 14:15:58 -07:00
{
$ in_comment = 1 ;
}
## print "COMMENT:$in_comment edge<$edge> $rawline\n" ;
sanitise_line_reset ( $ in_comment ) ;
2008-04-29 00:59:32 -07:00
} elsif ( $ realcnt && $ rawline =~ /^ ( ?:\+ | | $ ) / ) {
2008-03-28 14:15:58 -07:00
# Standardise the strings and chars within the input to
2008-04-29 00:59:32 -07:00
# simplify matching -- only bother with positive lines .
2008-03-28 14:15:58 -07:00
$ line = sanitise_line ( $ rawline ) ;
}
push ( @ lines , $ line ) ;
if ( $ realcnt > 1 ) {
$ realcnt -- if ( $ line =~ /^ ( ?:\+ | | $ ) / ) ;
} else {
$ realcnt = 0 ;
}
# print "==>$rawline\n" ;
# print "-->$line\n" ;
2007-07-15 23:37:22 -07:00
if ( $ setup_docs && $ line =~ /^\+/ ) {
push ( @ setup_docs , $ line ) ;
}
}
2007-10-18 03:05:08 -07:00
$ prefix = '' ;
2008-03-28 14:15:58 -07:00
$ realcnt = 0 ;
$ linenr = 0 ;
2007-06-01 00:46:48 -07:00
foreach my $ line ( @ lines ) {
$ linenr ++ ;
2013-09-11 14:24:03 -07:00
my $ sline = $ line ; # copy of $ line
$ sline =~ s / $ ; / / g ; # with comments as spaces
2007-06-01 00:46:48 -07:00
2008-02-08 04:20:54 -08:00
my $ rawline = $ rawlines [ $ linenr - 1 ] ;
2007-10-18 03:05:08 -07:00
2007-06-01 00:46:48 -07:00
# extract the line range in the file after the patch is applied
2007-10-18 03:05:08 -07:00
if ( $ line =~/^\@\@ -\ d + ( ?: , \ d + ) ? \+ ( \ d + ) ( , ( \ d + ) ) ? \@\@/ ) {
2007-06-01 00:46:48 -07:00
$ is_patch = 1 ;
2007-06-08 13:46:39 -07:00
$ first_line = $ linenr + 1 ;
2007-06-01 00:46:48 -07:00
$ realline = $ 1 - 1 ;
if ( defined $ 2 ) {
$ realcnt = $ 3 + 1 ;
} else {
$ realcnt = 1 + 1 ;
}
2008-02-08 04:20:54 -08:00
annotate_reset ( ) ;
2008-02-08 04:22:03 -08:00
$ prev_values = 'E' ;
2008-03-28 14:15:58 -07:00
%suppress_ifbraces = ();
2008-10-15 22:02:30 -07:00
%suppress_whiletrailers = ();
2009-10-26 16:50:16 -07:00
%suppress_export = ();
2012-01-10 15:10:01 -08:00
$ suppress_statement = 0 ;
2007-06-01 00:46:48 -07:00
next ;
2007-06-08 13:46:39 -07: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-28 14:15:58 -07:00
} elsif ( $ line =~ /^ ( | \+ | $ ) / ) {
2007-06-01 00:46:48 -07:00
$ realline ++ ;
2007-06-23 17:16:44 -07:00
$ realcnt -- if ( $ realcnt ! = 0 ) ;
2007-06-01 00:46:48 -07:00
2007-06-08 13:46:39 -07:00
# Measure the line length and indent .
2008-02-08 04:20:54 -08:00
( $ length , $ indent ) = line_stats ( $ rawline ) ;
2007-06-01 00:46:48 -07:00
# Track the previous line .
( $ prevline , $ stashline ) = ( $ stashline , $ line ) ;
( $ previndent , $ stashindent ) = ( $ stashindent , $ indent ) ;
2008-02-08 04:20:54 -08:00
( $ prevrawline , $ stashrawline ) = ( $ stashrawline , $ rawline ) ;
2008-03-28 14:15:58 -07:00
# warn "line<$line>\n" ;
2007-10-18 03:05:08 -07:00
2007-06-23 17:16:44 -07:00
} elsif ( $ realcnt == 1 ) {
$ realcnt -- ;
2007-06-01 00:46:48 -07:00
}
2009-10-26 16:50:13 -07:00
my $ hunk_line = ( $ realcnt ! = 0 ) ;
2007-06-01 00:46:48 -07:00
# make up the handle for any error we report on this line
2008-03-28 14:15:58 -07:00
$ prefix = "$filename:$realline: " if ( $ emacs && $ file ) ;
$ prefix = "$filename:$linenr: " if ( $ emacs && ! $ file ) ;
2007-10-18 03:05:08 -07:00
$ here = "#$linenr: " if ( ! $ file ) ;
$ here = "#$realline: " if ( $ file ) ;
2008-03-28 14:15:58 -07:00
# extract the filename as it passes
2010-10-26 14:23:16 -07:00
if ( $ line =~ /^ diff -- git . *? ( \ S + ) $ / ) {
$ realfile = $ 1 ;
2013-11-12 15:10:14 -08:00
$ realfile =~ s @^ ( [ ^/ ] * ) /@@ if ( ! $ file ) ;
2012-01-10 15:09:50 -08:00
$ in_commit_log = 0 ;
2010-10-26 14:23:16 -07:00
} elsif ( $ line =~ /^\+\+\+\ s + ( \ S + ) / ) {
2008-03-28 14:15:58 -07:00
$ realfile = $ 1 ;
2013-11-12 15:10:14 -08:00
$ realfile =~ s @^ ( [ ^/ ] * ) /@@ if ( ! $ file ) ;
2012-01-10 15:09:50 -08:00
$ in_commit_log = 0 ;
2009-01-06 14:41:24 -08:00
$ p1_prefix = $ 1 ;
2009-02-27 14:03:06 -08:00
if ( ! $ file && $ tree && $ p1_prefix ne '' &&
- e "$root/$p1_prefix" ) {
2011-07-25 17:13:25 -07:00
WARN ( "PATCH_PREFIX" ,
"patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n" ) ;
2009-01-06 14:41:24 -08:00
}
2008-03-28 14:15:58 -07:00
2008-10-15 22:02:20 -07:00
if ( $ realfile =~ m @^ include / asm /@ ) {
2011-07-25 17:13:25 -07: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-28 14:15:58 -07:00
}
next ;
}
2007-06-08 13:47:03 -07:00
$ here . = "FILE: $realfile:$realline:" if ( $ realcnt ! = 0 ) ;
2007-06-01 00:46:48 -07:00
2008-02-08 04:20:54 -08:00
my $ hereline = "$here\n$rawline\n" ;
my $ herecurr = "$here\n$rawline\n" ;
my $ hereprev = "$here\n$prevrawline\n$rawline\n" ;
2007-06-01 00:46:48 -07:00
2007-10-18 03:05:08 -07:00
$ cnt_lines ++ if ( $ realcnt ! = 0 ) ;
2010-10-26 14:23:16 -07:00
# Check for incorrect file permissions
if ( $ line =~ /^ new ( file ) ? mode . * [ 7531 ] \ d { 0 , 2 } $ / ) {
my $ permhere = $ here . "FILE: $realfile\n" ;
2013-04-29 16:18:14 -07:00
if ( $ realfile ! ~ m @ scripts /@ &&
$ realfile ! ~ /\. ( py | pl | awk | sh ) $ / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "EXECUTE_PERMISSIONS" ,
"do not set execute permissions for source files\n" . $ permhere ) ;
2010-10-26 14:23:16 -07:00
}
}
2011-07-25 17:13:23 -07:00
# Check the patch for a signoff :
2007-06-23 17:16:44 -07:00
if ( $ line =~ /^\ s * signed - off - by : / i ) {
2007-06-08 13:46:39 -07:00
$ signoff ++ ;
2011-10-31 17:13:12 -07:00
$ in_commit_log = 0 ;
2011-07-25 17:13:23 -07:00
}
# Check signature styles
2012-01-10 15:09:50 -08:00
if ( ! $ in_header_lines &&
2012-07-30 14:41:18 -07:00
$ line =~ /^ ( \ s * ) ( [ a - z0 - 9 _ - ] + by : | $ signature_tags ) ( \ s * ) ( . * ) / i ) {
2011-07-25 17:13:23 -07: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-30 14:41:18 -07:00
if ( $ sign_off ! ~ / $ signature_tags / ) {
WARN ( "BAD_SIGN_OFF" ,
"Non-standard signature: $sign_off\n" . $ herecurr ) ;
}
2011-07-25 17:13:23 -07:00
if ( defined $ space_before && $ space_before ne "" ) {
2013-07-03 15:05:31 -07:00
if ( WARN ( "BAD_SIGN_OFF" ,
"Do not use whitespace before $ucfirst_sign_off\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =
"$ucfirst_sign_off $email" ;
}
2007-06-01 00:46:48 -07:00
}
2011-07-25 17:13:23 -07:00
if ( $ sign_off =~ /- by : $ / i && $ sign_off ne $ ucfirst_sign_off ) {
2013-07-03 15:05:31 -07:00
if ( WARN ( "BAD_SIGN_OFF" ,
"'$ucfirst_sign_off' is the preferred signature form\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =
"$ucfirst_sign_off $email" ;
}
2011-07-25 17:13:23 -07:00
}
if ( ! defined $ space_after | | $ space_after ne " " ) {
2013-07-03 15:05:31 -07:00
if ( WARN ( "BAD_SIGN_OFF" ,
"Use a single space after $ucfirst_sign_off\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =
"$ucfirst_sign_off $email" ;
}
2011-07-25 17:13:23 -07: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-25 17:13:25 -07:00
ERROR ( "BAD_SIGN_OFF" ,
"Unrecognized email address: '$email'\n" . $ herecurr ) ;
2011-07-25 17:13:23 -07: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-25 17:13:25 -07:00
WARN("BAD_SIGN_OFF",
"email address ' $ email ' might be better as ' $ suggested_email$comment '\n" . $herecurr);
2011-07-25 17:13:23 -07:00
}
2007-06-01 00:46:48 -07:00
}
2013-09-11 14:23:57 -07:00
# Check for duplicate signatures
my $sig_nospace = $line;
$sig_nospace =~ s/\s//g;
$sig_nospace = lc($sig_nospace);
if (defined $signatures{$sig_nospace}) {
WARN("BAD_SIGN_OFF",
"Duplicate signature\n" . $herecurr);
} else {
$signatures{$sig_nospace} = 1;
}
2007-06-01 00:46:48 -07:00
}
2007-06-08 13:47:06 -07:00
# Check for wrappage within a valid hunk of the file
2007-11-28 16:21:06 -08:00
if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
2011-07-25 17:13:25 -07:00
ERROR("CORRUPTED_PATCH",
"patch seems to be corrupt (line wrapped?)\n" .
2007-10-18 03:05:08 -07:00
$herecurr) if (!$emitted_corrupt++);
2007-07-15 23:37:22 -07:00
}
2008-10-15 22:02:21 -07: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-15 23:37:22 -07:00
# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
if (($realfile =~ /^$/ || $line =~ /^\+/) &&
2008-04-29 00:59:32 -07: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-25 17:13:26 -07:00
CHK("INVALID_UTF8",
"Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
2007-06-08 13:47:06 -07:00
}
2007-06-01 00:46:48 -07:00
2011-10-31 17:13:12 -07: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-10 15:09:50 -08:00
$rawline !~ /^(commit\b|from\b|[\w-]+:).+$/i) {
2011-10-31 17:13:12 -07:00
$in_header_lines = 0;
$in_commit_log = 1;
}
2012-10-04 17:13:29 -07: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-10-31 17:13:12 -07:00
$rawline =~ /$NON_ASCII_UTF8/) {
2012-10-04 17:13:29 -07:00
WARN("UTF8_BEFORE_PATCH",
2011-10-31 17:13:12 -07:00
"8-bit UTF-8 used in possible commit log\n" . $herecurr);
}
2008-10-15 22:02:28 -07:00
# ignore non-hunk lines and lines being removed
next if (!$hunk_line || $line =~ /^-/);
2007-06-08 13:47:06 -07:00
2007-06-01 00:46:48 -07:00
#trailing whitespace
2007-10-16 23:29:38 -07:00
if ($line =~ /^\+.*\015/) {
2008-02-08 04:20:54 -08:00
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2013-09-11 14:23:54 -07:00
if (ERROR("DOS_LINE_ENDINGS",
"DOS line endings\n" . $herevet) &&
$fix) {
$fixed[$linenr - 1] =~ s/[\s\015]+$//;
}
2008-02-08 04:20:54 -08:00
} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2013-07-03 15:05:31 -07:00
if (ERROR("TRAILING_WHITESPACE",
"trailing whitespace\n" . $herevet) &&
$fix) {
2013-09-11 14:23:54 -07:00
$fixed[$linenr - 1] =~ s/\s+$//;
2013-07-03 15:05:31 -07:00
}
2010-10-26 14:23:12 -07:00
$rpt_cleaners = 1;
2007-06-01 00:46:48 -07:00
}
2008-10-15 22:02:27 -07:00
2013-11-12 15:10:12 -08:00
# Check for FSF mailing addresses.
2014-01-23 15:54:50 -08:00
if ($rawline =~ /\bwrite to the Free/i ||
2014-01-23 15:54:48 -08:00
$rawline =~ /\b59\s+Temple\s+Pl/i ||
$rawline =~ /\b51\s+Franklin\s+St/i) {
2013-11-12 15:10:12 -08:00
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
my $msg_type = \&ERROR;
$msg_type = \&CHK if ($file);
&{$msg_type}("FSF_MAILING_ADDRESS",
2014-01-23 15:54:48 -08:00
"Do not include the paragraph about writing to the Free Software Foundation' s mailing address from the sample GPL notice . The FSF has changed addresses in the past , and may do so again . Linux already includes a copy of the GPL . \ n " . $ herevet )
2013-11-12 15:10:12 -08:00
}
2010-05-24 14:33:29 -07:00
# check for Kconfig help text having a real description
2010-10-26 14:23:15 -07: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-24 14:33:29 -07:00
if ( $ realfile =~ / Kconfig / &&
2012-01-10 15:10:03 -08:00
$ line =~ /.\ s * config \ s +/ ) {
2010-05-24 14:33:29 -07:00
my $ length = 0 ;
2010-10-26 14:23:15 -07:00
my $ cnt = $ realcnt ;
my $ ln = $ linenr + 1 ;
my $ f ;
2012-01-10 15:10:03 -08:00
my $ is_start = 0 ;
2010-10-26 14:23:15 -07:00
my $ is_end = 0 ;
2012-01-10 15:10:03 -08:00
for ( ; $ cnt > 0 && defined $ lines [ $ ln - 1 ] ; $ ln ++ ) {
2010-10-26 14:23:15 -07:00
$ f = $ lines [ $ ln - 1 ] ;
$ cnt -- if ( $ lines [ $ ln - 1 ] ! ~ /^-/ ) ;
$ is_end = $ lines [ $ ln - 1 ] =~ /^\+/ ;
next if ( $ f =~ /^-/ ) ;
2012-01-10 15:10:03 -08:00
if ( $ lines [ $ ln - 1 ] =~ /.\ s * ( ?: bool | tristate ) \ s *\ "/) {
$is_start = 1;
} elsif ($lines[$ln - 1] =~ /.\s*(?:---)?help(?:---)?$/) {
$length = -1;
}
2010-10-26 14:23:15 -07:00
$f =~ s/^.//;
2010-05-24 14:33:29 -07:00
$f =~ s/#.*//;
$f =~ s/^\s+//;
next if ($f =~ /^$/);
2010-10-26 14:23:15 -07:00
if ($f =~ /^\s*config\s/) {
$is_end = 1;
last;
}
2010-05-24 14:33:29 -07:00
$length++;
}
2011-07-25 17:13:25 -07:00
WARN(" CONFIG_DESCRIPTION ",
2012-01-10 15:10:03 -08: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-24 14:33:29 -07:00
}
2012-12-17 16:01:48 -08: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 01: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 } ) ;
}
2014-01-23 15:54:51 -08:00
# check for DT compatible documentation
2014-04-03 14:49:26 -07:00
if ( defined $ root &&
( ( $ realfile =~ /\. dtsi ? $ / && $ line =~ /^\+\ s * compatible \ s *=\ s *\ " / ) | |
( $ realfile =~ /\. [ ch ] $ / && $ line =~ /^\+.*\. compatible \ s *=\ s *\ " / ) ) ) {
2014-01-23 15:54:51 -08:00
my @ compats = $ rawline =~ /\ " ( [ a - zA - Z0 - 9 \-\ , \.\+ _ ] + ) \ "/g;
2014-04-03 14:49:27 -07:00
my $dt_path = $root . " / Documentation / devicetree / bindings / ";
my $vp_file = $dt_path . " vendor - prefixes . txt " ;
2014-01-23 15:54:51 -08:00
foreach my $ compat ( @ compats ) {
my $ compat2 = $ compat ;
$ compat2 =~ s /\ , [ a - z ] *\-/\ , <\.\*>\-/ ;
` grep - Erq "$compat|$compat2" $ dt_path ` ;
if ( $ ? >> 8 ) {
WARN ( "UNDOCUMENTED_DT_STRING" ,
"DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $ herecurr ) ;
}
2014-04-03 14:49:25 -07:00
next if $ compat ! ~ /^ ( [ a - zA - Z0 - 9 \- ] + ) \ , / ;
my $ vendor = $ 1 ;
2014-04-03 14:49:27 -07:00
` grep - Eq " ^ $ vendor \\ b " $vp_file`;
2014-01-23 15:54:51 -08:00
if ( $? >> 8 ) {
WARN(" UNDOCUMENTED_DT_STRING ",
2014-04-03 14:49:27 -07:00
" DT compatible string vendor \ "$vendor\" appears un-documented -- check $vp_file\n" . $ herecurr ) ;
2014-01-23 15:54:51 -08:00
}
}
}
2008-10-15 22:02:27 -07: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-17 16:01:54 -08:00
# line length limit
2008-06-05 22:46:01 -07:00
if ( $ line =~ /^\+/ && $ prevrawline ! ~ /\/\*\*/ &&
2008-07-23 21:29:01 -07:00
$ rawline ! ~ /^.\ s *\*\ s *\@ $ Ident \ s / &&
2011-05-24 17:13:41 -07:00
! ( $ line =~ /^\+\ s * $ logFunctions \ s *\ ( \ s * ( ?: ( KERN_ \ S +\ s * | [ ^ "]*))?" [ X \ t ] * " \ s * ( ?: | , | \ ) \ s * ; ) \ s * $ / | |
2010-08-09 17:21:01 -07:00
$ line =~ /^\+\ s * "[^" ] * " \ s * ( ?:\ s * | , | \ ) \ s * ; ) \ s * $ / ) &&
2012-12-17 16:01:54 -08:00
$ length > $ max_line_length )
2008-06-05 22:46:01 -07:00
{
2011-07-25 17:13:25 -07:00
WARN ( "LONG_LINE" ,
2012-12-17 16:01:54 -08:00
"line over $max_line_length characters\n" . $ herecurr ) ;
2007-06-01 00:46:48 -07:00
}
2012-03-23 15:02:21 -07:00
# Check for user - visible strings broken across lines , which breaks the ability
2014-01-23 15:54:40 -08:00
# to grep for the string . Make exceptions when the previous string ends in a
# newline ( multiple lines in one string constant ) or '\t' , '\r' , ';' , or '{'
# ( common in inline assembly ) or is a octal \ 123 or hexadecimal \ xaf value
2012-03-23 15:02:21 -07:00
if ( $ line =~ /^\+\ s * "/ &&
$prevline =~ /" \ s * $ / &&
2014-01-23 15:54:40 -08:00
$ prevrawline ! ~ / ( ?:\\ ( ?: [ ntr ] | [ 0 - 7 ] { 1 , 3 } | x [ 0 - 9 a - fA - F ] { 1 , 2 } ) | ; \ s * | \ { \ s * ) "\s*$/) {
2012-03-23 15:02:21 -07:00
WARN(" SPLIT_STRING ",
" quoted string split across lines \ n " . $ hereprev ) ;
}
2010-03-05 13:43:55 -08:00
# check for spaces before a quoted newline
if ( $ rawline =~ /^.*\ " . *\ s \\ n / ) {
2013-07-03 15:05:31 -07:00
if ( WARN ( "QUOTED_WHITESPACE_BEFORE_NEWLINE" ,
"unnecessary whitespace before a quoted newline\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s /^ ( \+.*\ " . * ) \ s +\\ n / $ 1 \\ n / ;
}
2010-03-05 13:43:55 -08:00
}
2007-11-28 16:21:06 -08:00
# check for adding lines without a newline .
if ( $ line =~ /^\+/ && defined $ lines [ $ linenr ] && $ lines [ $ linenr ] =~ /^\\ No newline at end of file / ) {
2011-07-25 17:13:25 -07:00
WARN ( "MISSING_EOF_NEWLINE" ,
"adding a line without newline at end of file\n" . $ herecurr ) ;
2007-11-28 16:21:06 -08:00
}
2009-09-21 17:04:40 -07:00
# Blackfin : use hi / lo macros
if ( $ realfile =~ m @ arch / blackfin /.*\. S $ @ ) {
if ( $ line =~ /\. [ lL ] [ [ : space : ] ] *=.*& [ [ : space : ] ] * 0 x [ fF ] [ fF ] [ fF ] [ fF ] / ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
2011-07-25 17:13:25 -07:00
ERROR ( "LO_MACRO" ,
"use the LO() macro, not (... & 0xFFFF)\n" . $ herevet ) ;
2009-09-21 17:04:40 -07:00
}
if ( $ line =~ /\. [ hH ] [ [ : space : ] ] *=.*>> [ [ : space : ] ] * 16 / ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
2011-07-25 17:13:25 -07:00
ERROR ( "HI_MACRO" ,
"use the HI() macro, not (... >> 16)\n" . $ herevet ) ;
2009-09-21 17:04:40 -07:00
}
}
2008-10-15 22:02:24 -07: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 00:46:48 -07:00
# at the beginning of a line any tabs must come first and anything
# more than 8 must use tabs .
2008-02-08 04:20:54 -08:00
if ( $ rawline =~ /^\+\ s * \ t \ s *\ S / | |
$ rawline =~ /^\+\ s * \ s */ ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2010-10-26 14:23:12 -07:00
$ rpt_cleaners = 1 ;
2013-07-03 15:05:31 -07:00
if ( ERROR ( "CODE_INDENT" ,
"code indent should use tabs where possible\n" . $ herevet ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s /^\+ ( [ \ t ] + ) / " \+ " . tabify ( $ 1 ) / e ;
}
2007-06-01 00:46:48 -07:00
}
2010-03-05 13:43:54 -08:00
# check for space before tabs .
if ( $ rawline =~ /^\+/ && $ rawline =~ / \ t / ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2013-07-03 15:05:31 -07:00
if ( WARN ( "SPACE_BEFORE_TAB" ,
"please, no space before tabs\n" . $ herevet ) &&
$ fix ) {
2014-01-23 15:54:46 -08:00
while ( $ fixed [ $ linenr - 1 ] =~
s / ( ^\+.* ) { 8 , 8 } +\ t / $ 1 \ t \ t / ) { }
while ( $ fixed [ $ linenr - 1 ] =~
s / ( ^\+.* ) +\ t / $ 1 \ t / ) { }
2013-07-03 15:05:31 -07:00
}
2010-03-05 13:43:54 -08:00
}
2012-03-23 15:02:16 -07: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-30 14:41:16 -07:00
$ line =~ /^ ( \+ | ) ( [ \ t ] * ) / ;
my $ newindent = $ 2 ;
2012-03-23 15:02:16 -07:00
my $ goodtabindent = $ oldindent .
"\t" x ( $ pos / 8 ) .
" " x ( $ pos % 8);
my $ goodspaceindent = $ oldindent . " " x $ pos ;
if ( $ newindent ne $ goodtabindent &&
$ newindent ne $ goodspaceindent ) {
2013-07-03 15:05:31 -07:00
if ( CHK ( "PARENTHESIS_ALIGNMENT" ,
"Alignment should match open parenthesis\n" . $ hereprev ) &&
$ fix && $ line =~ /^\+/ ) {
$ fixed [ $ linenr - 1 ] =~
s /^\+ [ \ t ] */\+ $ goodtabindent / ;
}
2012-03-23 15:02:16 -07:00
}
}
}
2013-07-03 15:05:31 -07:00
if ( $ line =~ /^\+.*\* [ \ t ] *\ ) [ \ t ] + ( ? ! $ Assignment | $ Arithmetic ) / ) {
2013-07-03 15:05:31 -07:00
if ( CHK ( "SPACING" ,
"No space is necessary after a cast\n" . $ hereprev ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~
s /^ ( \+.*\* [ \ t ] *\ ) ) [ \ t ] +/ $ 1 / ;
}
2012-03-23 15:02:19 -07:00
}
2012-10-04 17:13:35 -07:00
if ( $ realfile =~ m @^ ( drivers / net / | net / ) @ &&
2013-07-03 15:05:23 -07:00
$ prevrawline =~ /^\+ [ \ t ] *\/\* [ \ t ] * $ / &&
2014-04-03 14:49:20 -07:00
$ rawline =~ /^\+ [ \ t ] *\*/ &&
$ realline > 2 ) {
2012-10-04 17:13:35 -07:00
WARN ( "NETWORKING_BLOCK_COMMENT_STYLE" ,
"networking block comments don't use an empty /* line, use /* Comment...\n" . $ hereprev ) ;
}
if ( $ realfile =~ m @^ ( drivers / net / | net / ) @ &&
2013-07-03 15:05:24 -07:00
$ prevrawline =~ /^\+ [ \ t ] *\/\*/ && # starting /*
$prevrawline !~ / \ * \ / [ \t] * $ / && #no trailing */
2013-09-11 14:23:59 -07:00
$ rawline =~ /^\+/ && # line is new
2013-07-03 15:05:24 -07:00
$ rawline ! ~ /^\+ [ \ t ] *\*/ ) { # no leading *
WARN ( "NETWORKING_BLOCK_COMMENT_STYLE" ,
"networking block comments start with * on subsequent lines\n" . $ hereprev ) ;
}
if ( $ realfile =~ m @^ ( drivers / net / | net / ) @ &&
2012-11-08 15:53:29 -08:00
$ rawline ! ~ m @^\+ [ \ t ] *\*/ [ \ t ] * $ @ && # trailing */
$ rawline ! ~ m @^\+.*/\*.*\*/ [ \ t ] * $ @ && # inline /* ... */
$ rawline ! ~ m @^\+.*\* { 2 , } / [ \ t ] * $ @ && # trailing **/
$ rawline =~ m @^\+ [ \ t ] *.+\*\/ [ \ t ] * $ @ ) { # non blank */
2012-10-04 17:13:35 -07:00
WARN ( "NETWORKING_BLOCK_COMMENT_STYLE" ,
"networking block comments put the trailing */ on a separate line\n" . $ herecurr ) ;
}
2010-08-09 17:20:59 -07:00
# check for spaces at the beginning of a line .
2010-10-26 14:23:11 -07:00
# Exceptions :
# 1 ) within comments
# 2 ) indented preprocessor commands
# 3 ) hanging labels
2013-07-03 15:05:31 -07:00
if ( $ rawline =~ /^\+ / && $ line ! ~ /^\+ * ( ?: $ ; | # | $ Ident : ) / ) {
2010-08-09 17:20:59 -07:00
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2013-07-03 15:05:31 -07:00
if ( WARN ( "LEADING_SPACE" ,
"please, no spaces at the start of a line\n" . $ herevet ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s /^\+ ( [ \ t ] + ) / " \+ " . tabify ( $ 1 ) / e ;
}
2010-08-09 17:20:59 -07:00
}
2008-10-15 22:02:24 -07:00
# check we are in a valid C source file if not then ignore this hunk
next if ( $ realfile ! ~ /\. ( h | c ) $ / ) ;
2012-12-17 16:01:48 -08: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 04:20:54 -08:00
# check for RCS / CVS revision markers
2008-03-04 14:28:20 -08:00
if ( $ rawline =~ /^\+.*\ $ ( Revision | Log | Id ) ( ?:\ $ | ) / ) {
2011-07-25 17:13:25 -07:00
WARN ( "CVS_KEYWORD" ,
"CVS style keyword markers, these will _not_ be updated\n" . $ herecurr ) ;
2008-02-08 04:20:54 -08:00
}
2007-08-10 13:01:03 -07:00
2009-09-21 17:04:40 -07:00
# Blackfin : don 't use __builtin_bfin_[cs]sync
if ($line =~ /__builtin_bfin_csync/) {
my $herevet = "$here\n" . cat_vet($line) . "\n";
2011-07-25 17:13:25 -07:00
ERROR("CSYNC",
"use the CSYNC() macro in asm/blackfin.h\n" . $herevet);
2009-09-21 17:04:40 -07:00
}
if ($line =~ /__builtin_bfin_ssync/) {
my $herevet = "$here\n" . cat_vet($line) . "\n";
2011-07-25 17:13:25 -07:00
ERROR("SSYNC",
"use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
2009-09-21 17:04:40 -07:00
}
2013-02-21 16:44:14 -08: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-16 23:29:38 -07:00
# Check for potential ' bare ' types
2009-10-26 16:50:16 -07:00
my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
$realline_next);
2012-01-10 15:10:01 -08:00
#print "LINE<$line>\n";
if ($linenr >= $suppress_statement &&
2013-09-11 14:24:03 -07:00
$realcnt && $sline =~ /.\s*\S/) {
2008-10-15 22:02:30 -07:00
($stat, $cond, $line_nr_next, $remain_next, $off_next) =
2008-07-23 21:29:03 -07:00
ctx_statement_block($linenr, $realcnt, 0);
2008-04-29 00:59:32 -07:00
$stat =~ s/\n./\n /g;
$cond =~ s/\n./\n /g;
2012-01-10 15:10:01 -08: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-10 15:09:54 -08:00
2009-10-26 16:50:16 -07: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 00:59:32 -07:00
my $s = $stat;
$s =~ s/{.*$//s;
2008-03-04 14:28:20 -08:00
2008-02-08 04:20:54 -08:00
# Ignore goto labels.
2008-04-29 00:59:32 -07:00
if ($s =~ /$Ident:\*$/s) {
2008-02-08 04:20:54 -08:00
# Ignore functions being called
2008-04-29 00:59:32 -07:00
} elsif ($s =~ /^.\s*$Ident\s*\(/s) {
2008-02-08 04:20:54 -08:00
2009-09-21 17:04:34 -07:00
} elsif ($s =~ /^.\s*else\b/s) {
2008-06-05 22:46:01 -07:00
# declarations always start with types
2008-07-23 21:29:09 -07: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-05 22:46:01 -07:00
my $type = $1;
$type =~ s/\s+/ /g;
possible($type, "A:" . $s);
2007-11-28 16:21:06 -08:00
# definitions in global scope can only start with types
2008-10-15 22:02:30 -07:00
} elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) {
2008-06-05 22:46:01 -07:00
possible($1, "B:" . $s);
2008-02-08 04:20:54 -08:00
}
2007-11-28 16:21:06 -08:00
# any (foo ... *) is a pointer cast, and foo is a type
2009-01-06 14:41:21 -08:00
while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) {
2008-06-05 22:46:01 -07:00
possible($1, "C:" . $s);
2007-10-16 23:29:38 -07:00
}
2007-11-28 16:21:06 -08:00
# Check for any sort of function declaration.
# int foo(something bar, other baz);
# void (*store_gdt)(x86_descr_ptr *);
2008-04-29 00:59:32 -07:00
if ($prev_values eq ' E ' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
2007-11-28 16:21:06 -08:00
my ($name_len) = length($1);
2008-03-04 14:28:20 -08:00
my $ctx = $s;
2008-03-28 14:15:58 -07:00
substr($ctx, 0, $name_len + 1, '');
2007-11-28 16:21:06 -08:00
$ctx =~ s/\)[^\)]*$//;
2008-03-04 14:28:20 -08:00
2007-11-28 16:21:06 -08:00
for my $arg (split(/\s*,\s*/, $ctx)) {
2008-06-05 22:46:01 -07:00
if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) {
2007-11-28 16:21:06 -08:00
2008-06-05 22:46:01 -07:00
possible($1, "D:" . $s);
2007-11-28 16:21:06 -08:00
}
}
}
2007-10-16 23:29:38 -07:00
}
2007-06-23 17:16:34 -07:00
#
# Checks which may be anchored in the context.
#
# Check for switch () and associated case and default
# statements should be at the same indent.
2007-06-08 13:47:06 -07: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-25 17:13:25 -07:00
ERROR("SWITCH_CASE_INDENT_LEVEL",
"switch and case should be at the same indent\n$hereline$err");
2007-07-15 23:37:22 -07: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-05 22:46:01 -07:00
if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
2008-03-28 14:15:58 -07:00
my $pre_ctx = "$1$2";
2007-10-16 23:29:38 -07:00
my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
2012-02-03 15:20:39 -08:00
if ($line =~ /^\+\t{6,}/) {
WARN("DEEP_INDENTATION",
"Too many leading tabs - consider code refactoring\n" . $herecurr);
}
2007-07-15 23:37:22 -07:00
my $ctx_cnt = $realcnt - $#ctx - 1;
my $ctx = join("\n", @ctx);
2008-07-23 21:29:01 -07:00
my $ctx_ln = $linenr;
my $ctx_skip = $realcnt;
2007-07-15 23:37:22 -07:00
2008-07-23 21:29:01 -07: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] !~ /^-/);
2008-03-28 14:15:58 -07:00
$ctx_ln++;
}
2008-07-23 21:29:01 -07:00
2008-07-23 21:29:03 -07:00
#print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
#print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
2008-03-28 14:15:58 -07:00
if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
2011-07-25 17:13:25 -07:00
ERROR("OPEN_BRACE",
"that open brace { should be on the previous line\n" .
2010-10-26 14:23:19 -07:00
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
2007-06-08 13:47:06 -07:00
}
2008-03-28 14:15:58 -07:00
if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
$ctx =~ /\)\s*\;\s*$/ &&
defined $lines[$ctx_ln - 1])
{
2007-10-16 23:29:38 -07:00
my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
if ($nindent > $indent) {
2011-07-25 17:13:25 -07:00
WARN("TRAILING_SEMICOLON",
"trailing semicolon indicates no statements, indent implies otherwise\n" .
2010-10-26 14:23:19 -07:00
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
2007-10-16 23:29:38 -07:00
}
}
2007-06-08 13:47:06 -07:00
}
2008-10-15 22:02:21 -07: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-10 15:10:01 -08:00
($stat, $cond, $line_nr_next, $remain_next, $off_next) =
ctx_statement_block($linenr, $realcnt, 0)
if (!defined $stat);
2008-10-15 22:02:21 -07: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-15 22:02:27 -07:00
my @newlines = ($c =~ /\n/gs);
my $cond_lines = 1 + $#newlines;
2008-10-15 22:02:21 -07: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-15 22:02:22 -07:00
if ($s =~ s/^\s*?\n//) {
2008-10-15 22:02:21 -07: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-15 22:02:22 -07:00
my $cond_ptr = -1;
2008-10-15 22:02:35 -07:00
$continuation = 0;
2008-10-15 22:02:22 -07:00
while ($cond_ptr != $cond_lines) {
$cond_ptr = $cond_lines;
2008-10-15 22:02:21 -07:00
2008-10-15 22:02:32 -07:00
# If we see an #else/#elif then the code
# is not linear.
if ($s =~ /^\s*\#\s*(?:else|elif)/) {
$check = 0;
}
2008-10-15 22:02:22 -07:00
# Ignore:
# 1) blank lines, they should be at 0,
# 2) preprocessor lines, and
# 3) labels.
2008-10-15 22:02:35 -07:00
if ($continuation ||
$s =~ /^\s*?\n/ ||
2008-10-15 22:02:22 -07:00
$s =~ /^\s*#\s*?/ ||
$s =~ /^\s*$Ident\s*:/) {
2008-10-15 22:02:35 -07:00
$continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
2009-09-21 17:04:36 -07:00
if ($s =~ s/^.*?\n//) {
$cond_lines++;
}
2008-10-15 22:02:22 -07:00
}
2008-10-15 22:02:21 -07: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-15 22:02:22 -07: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-15 22:02:21 -07:00
if ( $ check && ( ( $ sindent % 8) != 0 ||
( $ sindent <= $ indent && $ s ne '' ) ) ) {
2011-07-25 17:13:25 -07:00
WARN ( "SUSPECT_CODE_INDENT" ,
"suspect code indent for conditional statements ($indent, $sindent)\n" . $ herecurr . "$stat_real\n" ) ;
2008-10-15 22:02:21 -07:00
}
}
2007-10-18 03:05:08 -07:00
# Track the 'values' across context and added lines .
my $ opline = $ line ; $ opline =~ s /^./ / ;
2008-07-23 21:29:10 -07:00
my ( $ curr_values , $ curr_vars ) =
annotate_values ( $ opline . "\n" , $ prev_values ) ;
2007-10-18 03:05:08 -07:00
$ curr_values = $ prev_values . $ curr_values ;
2008-02-08 04:20:54 -08:00
if ( $ dbg_values ) {
my $ outline = $ opline ; $ outline =~ s /\ t / / g ;
2008-03-04 14:28:20 -08:00
print "$linenr > .$outline\n" ;
print "$linenr > $curr_values\n" ;
2008-07-23 21:29:10 -07:00
print "$linenr > $curr_vars\n" ;
2008-02-08 04:20:54 -08:00
}
2007-10-18 03:05:08 -07:00
$ prev_values = substr ( $ curr_values , - 1 ) ;
2007-06-08 13:47:06 -07:00
# ignore lines not being added
2013-07-03 15:05:31 -07:00
next if ( $ line =~ /^ [ ^\+ ] / ) ;
2007-06-08 13:47:06 -07:00
2007-06-23 17:16:34 -07:00
# TEST : allow direct testing of the type matcher .
2008-07-23 21:29:06 -07:00
if ( $ dbg_type ) {
if ( $ line =~ /^.\ s * $ Declare \ s * $ / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "TEST_TYPE" ,
"TEST: is type\n" . $ herecurr ) ;
2008-07-23 21:29:06 -07:00
} elsif ( $ dbg_type > 1 && $ line =~ /^.+ ( $ Declare ) / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "TEST_NOT_TYPE" ,
"TEST: is not type ($1 is)\n" . $ herecurr ) ;
2008-07-23 21:29:06 -07:00
}
2007-06-23 17:16:34 -07:00
next ;
}
2008-10-15 22:02:17 -07:00
# TEST : allow direct testing of the attribute matcher .
if ( $ dbg_attr ) {
2009-02-27 14:03:08 -08:00
if ( $ line =~ /^.\ s * $ Modifier \ s * $ / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "TEST_ATTR" ,
"TEST: is attr\n" . $ herecurr ) ;
2009-02-27 14:03:08 -08:00
} elsif ( $ dbg_attr > 1 && $ line =~ /^.+ ( $ Modifier ) / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "TEST_NOT_ATTR" ,
"TEST: is not attr ($1 is)\n" . $ herecurr ) ;
2008-10-15 22:02:17 -07:00
}
next ;
}
2007-06-23 17:16:34 -07:00
2007-07-19 01:48:34 -07:00
# check for initialisation to aggregates open brace on the next line
2009-10-26 16:50:15 -07:00
if ( $ line =~ /^.\ s * { / &&
$ prevline =~ / ( ?:^ | [ ^= ] ) =\ s * $ / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "OPEN_BRACE" ,
"that open brace { should be on the previous line\n" . $ hereprev ) ;
2007-07-19 01:48:34 -07:00
}
2007-06-23 17:16:34 -07:00
#
# Checks which are anchored on the added line .
#
# check for malformed paths in # include statements ( uses RAW line )
2008-06-05 22:46:01 -07:00
if ( $ rawline =~ m { ^.\ s *\#\ s * include \ s + [ < "](.*)[" > ] } ) {
2007-06-23 17:16:34 -07:00
my $ path = $ 1 ;
if ( $ path =~ m { // } ) {
2011-07-25 17:13:25 -07:00
ERROR ( "MALFORMED_INCLUDE" ,
2012-12-20 15:05:37 -08: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-23 17:16:34 -07:00
}
}
2007-06-08 13:47:06 -07:00
# no C99 // comments
if ( $ line =~ m { // } ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "C99_COMMENTS" ,
"do not use C99 // comments\n" . $ herecurr ) &&
$ fix ) {
my $ line = $ fixed [ $ linenr - 1 ] ;
if ( $ line =~ /\/\/ ( . * ) $ / ) {
my $ comment = trim ( $ 1 ) ;
$ fixed [ $ linenr - 1 ] =~ s @\/\/ ( . * ) $ @/\* $ comment \*/@ ;
}
}
2007-06-08 13:47:06 -07:00
}
# Remove C99 comments .
2007-06-01 00:46:48 -07:00
$ line =~ s @//.*@@ ;
2007-10-18 03:05:08 -07:00
$ opline =~ s @//.*@@ ;
2007-06-01 00:46:48 -07:00
2009-10-26 16:50:16 -07: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-26 14:23:18 -07:00
# Handle definitions which produce identifiers with
# a prefix :
# XXX ( foo ) ;
# EXPORT_SYMBOL ( something_foo ) ;
2007-06-23 17:16:34 -07:00
my $ name = $ 1 ;
2012-01-10 15:10:04 -08:00
if ( $ stat =~ /^ ( ?:.\ s * } \ s *\ n ) ?. ( [ A - Z_ ] + ) \ s *\ ( \ s * ( $ Ident ) / &&
2010-10-26 14:23:18 -07:00
$ name =~ /^ $ { Ident } _ $ 2 / ) {
# print "FOO C name<$name>\n" ;
$ suppress_export { $ realline_next } = 1 ;
} elsif ( $ stat ! ~ / ( ?:
2009-10-26 16:50:16 -07:00
\ n . } \ s * $ |
2008-10-15 22:02:34 -07:00
^. DEFINE_ $ Ident \ ( \ Q $ name \ E \ ) |
^. DECLARE_ $ Ident \ ( \ Q $ name \ E \ ) |
^. LIST_HEAD \ ( \ Q $ name \ E \ ) |
2009-10-26 16:50:16 -07:00
^. ( ?: $ Storage \ s + ) ? $ Type \ s *\ ( \ s *\*\ s *\ Q $ name \ E \ s *\ ) \ s *\ ( |
\ b \ Q $ name \ E ( ?:\ s + $ Attribute ) *\ s * ( ?: ; | = | \ [ | \ ( )
2008-10-15 22:02:34 -07:00
) / x ) {
2009-10-26 16:50:16 -07: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 00:46:48 -07:00
}
}
2009-10-26 16:50:16 -07: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-25 17:13:25 -07:00
WARN ( "EXPORT_SYMBOL" ,
"EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $ herecurr ) ;
2009-10-26 16:50:16 -07:00
}
2007-06-01 00:46:48 -07:00
2010-08-09 17:21:00 -07:00
# check for global initialisers .
2013-09-11 14:23:54 -07:00
if ( $ line =~ /^\+ ( \ s * $ Type \ s * $ Ident \ s * ( ?:\ s + $ Modifier ) ) *\ s *=\ s * ( 0 | NULL | false ) \ s * ; / ) {
if ( ERROR ( "GLOBAL_INITIALISERS" ,
"do not initialise globals to 0 or NULL\n" .
$ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s / ( $ Type \ s * $ Ident \ s * ( ?:\ s + $ Modifier ) ) *\ s *=\ s * ( 0 | NULL | false ) \ s * ; / $ 1 ; / ;
}
2007-07-19 01:48:34 -07:00
}
2007-06-23 17:16:34 -07:00
# check for static initialisers .
2013-09-11 14:23:54 -07:00
if ( $ line =~ /^\+.*\ bstatic \ s . *=\ s * ( 0 | NULL | false ) \ s * ; / ) {
if ( ERROR ( "INITIALISED_STATIC" ,
"do not initialise statics to 0 or NULL\n" .
$ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s / ( \ bstatic \ s . *? ) \ s *=\ s * ( 0 | NULL | false ) \ s * ; / $ 1 ; / ;
}
2007-06-01 00:46:48 -07:00
}
2010-10-26 14:23:20 -07:00
# check for static const char * arrays .
if ( $ line =~ /\ bstatic \ s + const \ s + char \ s *\*\ s * ( \ w + ) \ s *\ [ \ s *\ ] \ s *=\ s */ ) {
2011-07-25 17:13:25 -07:00
WARN ( "STATIC_CONST_CHAR_ARRAY" ,
"static const char * array should probably be static const char * const\n" .
2010-10-26 14:23:20 -07:00
$ herecurr ) ;
}
# check for static char foo [ ] = "bar" declarations .
if ( $ line =~ /\ bstatic \ s + char \ s + ( \ w + ) \ s *\ [ \ s *\ ] \ s *=\ s * "/) {
2011-07-25 17:13:25 -07:00
WARN(" STATIC_CONST_CHAR_ARRAY ",
" static char array declaration should probably be static const char \ n " .
2010-10-26 14:23:20 -07:00
$herecurr);
}
2014-04-03 14:49:18 -07:00
# check for non-global char *foo[] = {" bar " , . . . } declarations .
if ( $ line =~ /^.\ s + ( ?: static \ s + | const \ s + ) ? char \ s +\*\ s *\ w +\ s *\ [ \ s *\ ] \ s *=\ s *\ { / ) {
WARN ( "STATIC_CONST_CHAR_ARRAY" ,
"char * array declaration might be better as static const\n" .
$ herecurr ) ;
}
2014-01-27 17:07:18 -08:00
# check for function declarations without arguments like "int foo()"
if ( $ line =~ / ( \ b$Type \ s + $ Ident ) \ s *\ ( \ s *\ ) / ) {
if ( ERROR ( "FUNCTION_WITHOUT_ARGS" ,
"Bad function definition - $1() should probably be $1(void)\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s / ( \ b ( $ Type ) \ s + ( $ Ident ) ) \ s *\ ( \ s *\ ) / $ 2 $ 3 ( void ) / ;
}
}
2013-12-13 11:36:22 -07:00
# check for uses of DEFINE_PCI_DEVICE_TABLE
if ( $ line =~ /\ bDEFINE_PCI_DEVICE_TABLE \ s *\ ( \ s * ( \ w + ) \ s *\ ) \ s *=/ ) {
if ( WARN ( "DEFINE_PCI_DEVICE_TABLE" ,
"Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s /\ b ( ?: static \ s + | ) DEFINE_PCI_DEVICE_TABLE \ s *\ ( \ s * ( \ w + ) \ s *\ ) \ s *=\ s */ static const struct pci_device_id $ 1 \ [ \ ] = / ;
}
2010-10-26 14:23:21 -07:00
}
2007-06-23 17:16:34 -07:00
# check for new typedefs , only function parameters and sparse annotations
# make sense .
if ( $ line =~ /\ btypedef \ s / &&
2009-01-06 14:41:26 -08:00
$ line ! ~ /\ btypedef \ s + $ Type \ s *\ ( \ s *\*? $ Ident \ s *\ ) \ s *\ ( / &&
2008-06-05 22:46:01 -07:00
$ line ! ~ /\ btypedef \ s + $ Type \ s + $ Ident \ s *\ ( / &&
2008-10-15 22:02:32 -07:00
$ line ! ~ /\ b$typeTypedefs \ b / &&
2007-06-23 17:16:34 -07:00
$ line ! ~ /\ b__bitwise ( ?: _ _ | ) \ b / ) {
2011-07-25 17:13:25 -07:00
WARN ( "NEW_TYPEDEFS" ,
"do not add new typedefs\n" . $ herecurr ) ;
2007-06-01 00:46:48 -07:00
}
# * goes on variable not on type
2009-01-06 14:41:21 -08:00
# ( char * [ const ] )
2012-01-10 15:10:15 -08:00
while ( $ line =~ m { ( \ ( $ NonptrType ( \ s * ( ?: $ Modifier \ b \ s * | \*\ s * ) + ) \ ) ) } g ) {
# print "AA<$1>\n" ;
2013-07-03 15:05:31 -07:00
my ( $ ident , $ from , $ to ) = ( $ 1 , $ 2 , $ 2 ) ;
2007-06-23 17:16:44 -07:00
2009-01-06 14:41:21 -08: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-15 13:51:05 -08:00
while ( $ to =~ s /\*\ s +\*/\*\*/ ) {
2009-01-06 14:41:21 -08:00
}
2007-06-23 17:16:44 -07:00
2013-07-03 15:05:31 -07:00
## print "1: from<$from> to<$to> ident<$ident>\n" ;
2009-01-06 14:41:21 -08:00
if ( $ from ne $ to ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "POINTER_LOCATION" ,
"\"(foo$from)\" should be \"(foo$to)\"\n" . $ herecurr ) &&
$ fix ) {
my $ sub_from = $ ident ;
my $ sub_to = $ ident ;
$ sub_to =~ s /\ Q $ from \ E / $ to / ;
$ fixed [ $ linenr - 1 ] =~
s @\ Q $ sub_from \ E @ $ sub_to @ ;
}
2009-01-06 14:41:21 -08:00
}
2012-01-10 15:10:15 -08:00
}
while ( $ line =~ m { ( \ b$NonptrType ( \ s * ( ?: $ Modifier \ b \ s * | \*\ s * ) + ) ( $ Ident ) ) } g ) {
# print "BB<$1>\n" ;
2013-07-03 15:05:31 -07:00
my ( $ match , $ from , $ to , $ ident ) = ( $ 1 , $ 2 , $ 2 , $ 3 ) ;
2007-06-23 17:16:44 -07:00
2009-01-06 14:41:21 -08: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-15 13:51:05 -08:00
while ( $ to =~ s /\*\ s +\*/\*\*/ ) {
2009-01-06 14:41:21 -08:00
}
# Modifiers should have spaces .
$ to =~ s / ( \ b$Modifier$ ) / $ 1 / ;
2013-07-03 15:05:31 -07:00
## print "2: from<$from> to<$to> ident<$ident>\n" ;
2009-02-27 14:03:08 -08:00
if ( $ from ne $ to && $ ident ! ~ /^ $ Modifier $ / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "POINTER_LOCATION" ,
"\"foo${from}bar\" should be \"foo${to}bar\"\n" . $ herecurr ) &&
$ fix ) {
my $ sub_from = $ match ;
my $ sub_to = $ match ;
$ sub_to =~ s /\ Q $ from \ E / $ to / ;
$ fixed [ $ linenr - 1 ] =~
s @\ Q $ sub_from \ E @ $ sub_to @ ;
}
2009-01-06 14:41:21 -08:00
}
2007-06-01 00:46:48 -07: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-28 16:21:06 -08:00
if ( $ line =~ /\ bLINUX_VERSION_CODE \ b / ) {
2011-07-25 17:13:25 -07: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-28 16:21:06 -08:00
}
2011-06-15 15:08:17 -07:00
# check for uses of printk_ratelimit
if ( $ line =~ /\ bprintk_ratelimit \ s *\ ( / ) {
2011-07-25 17:13:25 -07:00
WARN ( "PRINTK_RATELIMITED" ,
"Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $ herecurr ) ;
2011-06-15 15:08:17 -07:00
}
2007-06-08 13:47:06 -07: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-30 22:57:33 -03:00
# printk includes all preceding printk' s which have no newline on the end .
2007-06-08 13:47:06 -07:00
# we assume the first bad printk is the one to report .
2007-07-19 01:48:34 -07:00
if ( $ line =~ /\ bprintk \ ( ( ? ! KERN_ ) \ s * "/) {
2007-06-08 13:47:06 -07:00
my $ok = 0;
for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
#print " CHECK < $ lines [ $ ln - 1 ] \ n ";
2011-03-30 22:57:33 -03:00
# we have a preceding printk if it ends
2007-06-08 13:47:06 -07: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-25 17:13:25 -07:00
WARN(" PRINTK_WITHOUT_KERN_LEVEL ",
" printk ( ) should include KERN_ facility level \ n " . $ herecurr ) ;
2007-06-08 13:47:06 -07:00
}
2007-06-01 00:46:48 -07:00
}
2012-05-31 16:26:09 -07:00
if ( $ line =~ /\ bprintk \ s *\ ( \ s * KERN_ ( [ A - Z ] + ) / ) {
my $ orig = $ 1 ;
my $ level = lc ( $ orig ) ;
$ level = "warn" if ( $ level eq "warning" ) ;
2012-10-04 17:13:32 -07:00
my $ level2 = $ level ;
$ level2 = "dbg" if ( $ level eq "debug" ) ;
2012-05-31 16:26:09 -07:00
WARN ( "PREFER_PR_LEVEL" ,
2014-04-03 14:49:23 -07:00
"Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $ herecurr ) ;
2012-05-31 16:26:09 -07:00
}
if ( $ line =~ /\ bpr_warning \ s *\ ( / ) {
2013-09-11 14:23:54 -07:00
if ( WARN ( "PREFER_PR_LEVEL" ,
"Prefer pr_warn(... to pr_warning(...\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~
s /\ bpr_warning \ b / pr_warn / ;
}
2012-05-31 16:26:09 -07:00
}
2013-02-21 16:44:13 -08: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-23 17:16:34 -07:00
# function brace can 't be on same line, except for #defines of do while,
# or if closed on same line
2008-06-05 22:46:01 -07:00
if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and
!($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) {
2011-07-25 17:13:25 -07:00
ERROR("OPEN_BRACE",
"open brace ' { ' following function declarations go on the next line\n" . $herecurr);
2007-06-01 00:46:48 -07:00
}
2007-06-23 17:16:34 -07:00
2007-11-28 16:21:06 -08: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-25 17:13:25 -07:00
ERROR("OPEN_BRACE",
"open brace ' { ' following $1 go on the same line\n" . $hereprev);
2007-11-28 16:21:06 -08:00
}
2010-10-26 14:23:15 -07:00
# missing space after union, struct or enum definition
2013-07-03 15:05:31 -07:00
if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) {
if (WARN("SPACING",
"missing space after $1 definition\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~
s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/;
}
2010-10-26 14:23:15 -07:00
}
2014-01-23 15:54:49 -08:00
# Function pointer declarations
# check spacing between type, funcptr, and args
# canonical declaration is "type (*funcptr)(args...)"
2014-04-03 14:49:12 -07:00
if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) {
2014-01-23 15:54:49 -08:00
my $declare = $1;
my $pre_pointer_space = $2;
my $post_pointer_space = $3;
my $funcname = $4;
my $post_funcname_space = $5;
my $pre_args_space = $6;
2014-04-03 14:49:12 -07:00
# the $Declare variable will capture all spaces after the type
# so check it for a missing trailing missing space but pointer return types
# don' t need a space so don 't warn for those.
my $post_declare_space = "";
if ($declare =~ /(\s+)$/) {
$post_declare_space = $1;
$declare = rtrim($declare);
}
if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) {
2014-01-23 15:54:49 -08:00
WARN("SPACING",
"missing space after return type\n" . $herecurr);
2014-04-03 14:49:12 -07:00
$post_declare_space = " ";
2014-01-23 15:54:49 -08:00
}
# unnecessary space "type (*funcptr)(args...)"
2014-04-03 14:49:12 -07:00
# This test is not currently implemented because these declarations are
# equivalent to
# int foo(int bar, ...)
# and this is form shouldn' t / doesn 't generate a checkpatch warning.
#
# elsif ($declare =~ /\s{2,}$/) {
# WARN("SPACING",
# "Multiple spaces after return type\n" . $herecurr);
# }
2014-01-23 15:54:49 -08:00
# unnecessary space "type ( *funcptr)(args...)"
if (defined $pre_pointer_space &&
$pre_pointer_space =~ /^\s/) {
WARN("SPACING",
"Unnecessary space after function pointer open parenthesis\n" . $herecurr);
}
# unnecessary space "type (* funcptr)(args...)"
if (defined $post_pointer_space &&
$post_pointer_space =~ /^\s/) {
WARN("SPACING",
"Unnecessary space before function pointer name\n" . $herecurr);
}
# unnecessary space "type (*funcptr )(args...)"
if (defined $post_funcname_space &&
$post_funcname_space =~ /^\s/) {
WARN("SPACING",
"Unnecessary space after function pointer name\n" . $herecurr);
}
# unnecessary space "type (*funcptr) (args...)"
if (defined $pre_args_space &&
$pre_args_space =~ /^\s/) {
WARN("SPACING",
"Unnecessary space before function pointer arguments\n" . $herecurr);
}
if (show_type("SPACING") && $fix) {
$fixed[$linenr - 1] =~
2014-04-03 14:49:12 -07:00
s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . ' ( * ' . $funcname . ' ) ( '/ex;
2014-01-23 15:54:49 -08:00
}
}
2008-07-23 21:29:02 -07:00
# check for spacing round square brackets; allowed:
# 1. with a type on the left -- int [] a;
2008-10-15 22:02:15 -07:00
# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
# 3. inside a curly brace -- = { [0...10] = 5 }
2008-07-23 21:29:02 -07:00
while ($line =~ /(.*?\s)\[/g) {
my ($where, $prefix) = ($-[1], $1);
if ($prefix !~ /$Type\s+$/ &&
2008-10-15 22:02:15 -07:00
($where != 0 || $prefix !~ /^.\s+$/) &&
2012-03-23 15:02:17 -07:00
$prefix !~ /[{,]\s+$/) {
2013-07-03 15:05:31 -07:00
if (ERROR("BRACKET_SPACE",
"space prohibited before open square bracket ' [ '\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~
s/^(\+.*?)\s+\[/$1\[/;
}
2008-07-23 21:29:02 -07:00
}
}
2007-07-19 01:48:34 -07:00
# check for spaces between functions and their parentheses.
2007-10-18 03:05:08 -07:00
while ($line =~ /($Ident)\s+\(/g) {
2008-02-08 04:20:54 -08:00
my $name = $1;
2008-03-28 14:15:58 -07:00
my $ctx_before = substr($line, 0, $-[1]);
my $ctx = "$ctx_before$name";
2008-02-08 04:20:54 -08:00
# Ignore those directives where spaces _are_ permitted.
2008-03-28 14:15:58 -07:00
if ($name =~ /^(?:
if|for|while|switch|return|case|
volatile|__volatile__|
__attribute__|format|__extension__|
asm|__asm__)$/x)
{
2008-02-08 04:20:54 -08: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-05 22:46:01 -07:00
} elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
2008-03-28 14:15:58 -07:00
# cpp #elif statement condition may start with a (
2008-06-05 22:46:01 -07:00
} elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
2008-02-08 04:20:54 -08:00
# If this whole things ends with a type its most
# likely a typedef for a function.
2008-03-28 14:15:58 -07:00
} elsif ($ctx =~ /$Type$/) {
2008-02-08 04:20:54 -08:00
} else {
2013-07-03 15:05:31 -07:00
if (WARN("SPACING",
"space prohibited between function name and open parenthesis ' ( '\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~
s/\b$name\s+\(/$name\(/;
}
2007-10-18 03:05:08 -07:00
}
2007-07-19 01:48:34 -07:00
}
2012-05-31 16:26:09 -07:00
2007-06-23 17:16:34 -07:00
# Check operator spacing.
2007-06-01 00:46:48 -07:00
if (!($line=~/\#\s*include/)) {
2013-07-03 15:05:31 -07:00
my $fixed_line = "";
my $line_fixed = 0;
2007-10-16 23:29:38 -07:00
my $ops = qr{
<<=|>>=|<=|>=|==|!=|
\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
=>|->|<<|>>|<|>|=|!|~|
2008-07-23 21:29:10 -07:00
&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
2013-11-12 15:10:05 -08:00
\?:|\?|:
2007-10-16 23:29:38 -07:00
}x;
2008-03-04 14:28:20 -08:00
my @elements = split(/($ops|;)/, $opline);
2013-07-03 15:05:31 -07:00
## print("element count: <" . $#elements . ">\n");
## foreach my $el (@elements) {
## print("el: <$el>\n");
## }
my @fix_elements = ();
2007-06-08 13:47:06 -07:00
my $off = 0;
2007-10-18 03:05:08 -07:00
2013-07-03 15:05:31 -07:00
foreach my $el (@elements) {
push(@fix_elements, substr($rawline, $off, length($el)));
$off += length($el);
}
$off = 0;
2007-10-18 03:05:08 -07:00
my $blank = copy_spacing($opline);
2013-09-11 14:24:01 -07:00
my $last_after = -1;
2007-10-18 03:05:08 -07:00
2007-06-01 00:46:48 -07:00
for (my $n = 0; $n < $#elements; $n += 2) {
2013-07-03 15:05:31 -07:00
my $good = $fix_elements[$n] . $fix_elements[$n + 1];
## print("n: <$n> good: <$good>\n");
2007-06-08 13:46:39 -07:00
$off += length($elements[$n]);
2011-03-30 22:57:33 -03:00
# Pick up the preceding and succeeding characters.
2008-03-28 14:15:58 -07: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-08 13:46:39 -07:00
my $a = '';
$a = ' V ' if ($elements[$n] ne '');
$a = ' W ' if ($elements[$n] =~ /\s$/);
2008-03-04 14:28:20 -08:00
$a = ' C ' if ($elements[$n] =~ /$;$/);
2007-06-08 13:46:39 -07:00
$a = ' B ' if ($elements[$n] =~ /(\[|\()$/);
$a = ' O ' if ($elements[$n] eq '');
2008-03-28 14:15:58 -07:00
$a = ' E ' if ($ca =~ /^\s*$/);
2007-06-08 13:46:39 -07:00
2007-06-01 00:46:48 -07:00
my $op = $elements[$n + 1];
2007-06-08 13:46:39 -07:00
my $c = '';
2007-06-01 00:46:48 -07:00
if (defined $elements[$n + 2]) {
2007-06-08 13:46:39 -07:00
$c = ' V ' if ($elements[$n + 2] ne '');
$c = ' W ' if ($elements[$n + 2] =~ /^\s/);
2008-03-04 14:28:20 -08:00
$c = ' C ' if ($elements[$n + 2] =~ /^$;/);
2007-06-08 13:46:39 -07:00
$c = ' B ' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
$c = ' O ' if ($elements[$n + 2] eq '');
2009-01-06 14:41:27 -08:00
$c = ' E ' if ($elements[$n + 2] =~ /^\s*\\$/);
2007-06-08 13:46:39 -07:00
} else {
$c = ' E ';
2007-06-01 00:46:48 -07:00
}
2007-06-08 13:46:39 -07:00
my $ctx = "${a}x${c}";
my $at = "(ctx:$ctx)";
2007-10-18 03:05:08 -07:00
my $ptr = substr($blank, 0, $off) . "^";
2007-07-15 23:37:22 -07:00
my $hereptr = "$hereline$ptr\n";
2007-06-01 00:46:48 -07:00
2008-07-23 21:29:10 -07:00
# Pull out the value of this operator.
2007-10-18 03:05:08 -07:00
my $op_type = substr($curr_values, $off + 1, 1);
2007-06-01 00:46:48 -07:00
2008-07-23 21:29:10 -07:00
# Get the full operator variant.
my $opv = $op . substr($curr_vars, $off, 1);
2008-02-08 04:22:03 -08:00
# Ignore operators passed as parameters.
if ($op_type ne ' V ' &&
$ca =~ /\s$/ && $cc =~ /^\s*,/) {
2008-03-04 14:28:20 -08:00
# # Ignore comments
# } elsif ($op =~ /^$;+$/) {
2008-02-08 04:22:03 -08:00
2007-06-23 17:16:44 -07:00
# ; should have either the end of line or a space or \ after it
2008-02-08 04:22:03 -08:00
} elsif ($op eq ' ; ') {
2008-03-04 14:28:20 -08:00
if ($ctx !~ /.x[WEBC]/ &&
$cc !~ /^\\/ && $cc !~ /^;/) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"space required after that ' $ op ' $at\n" . $hereptr)) {
2013-09-11 14:24:01 -07:00
$good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
2013-07-03 15:05:31 -07:00
$line_fixed = 1;
}
2007-06-23 17:16:44 -07:00
}
# // is a comment
} elsif ($op eq ' // ') {
2007-06-01 00:46:48 -07:00
2008-07-23 21:29:10 -07:00
# No spaces for:
# ->
# : when part of a bitfield
} elsif ($op eq ' -> ' || $opv eq ' : B ') {
2007-06-08 13:46:39 -07:00
if ($ctx =~ /Wx.|.xW/) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"spaces prohibited around that ' $ op ' $at\n" . $hereptr)) {
2013-09-11 14:24:01 -07:00
$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
2013-07-03 15:05:31 -07:00
if (defined $fix_elements[$n + 2]) {
$fix_elements[$n + 2] =~ s/^\s+//;
}
2013-09-11 14:24:01 -07:00
$line_fixed = 1;
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
# , must have a space on the right.
} elsif ($op eq ' , ') {
2008-03-04 14:28:20 -08:00
if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"space required after that ' $ op ' $at\n" . $hereptr)) {
2013-09-11 14:24:01 -07:00
$good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
2013-07-03 15:05:31 -07:00
$line_fixed = 1;
2013-09-11 14:24:01 -07:00
$last_after = $n;
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
2007-10-16 23:29:38 -07:00
# ' * ' as part of a type definition -- reported already.
2008-07-23 21:29:10 -07:00
} elsif ($opv eq ' * _ ') {
2007-10-16 23:29:38 -07: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-23 21:29:10 -07:00
$opv eq ' * U ' || $opv eq ' - U ' ||
2008-10-15 22:02:16 -07:00
$opv eq ' & U ' || $opv eq ' && U ') {
2008-03-04 14:28:20 -08:00
if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"space required before that ' $ op ' $at\n" . $hereptr)) {
2013-09-11 14:24:01 -07:00
if ($n != $last_after + 2) {
$good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]);
$line_fixed = 1;
}
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
2009-02-27 14:03:07 -08:00
if ($op eq ' * ' && $cc =~/\s*$Modifier\b/) {
2008-04-29 00:59:32 -07:00
# A unary ' * ' may be const
} elsif ($ctx =~ /.xW/) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"space prohibited after that ' $ op ' $at\n" . $hereptr)) {
2013-09-11 14:24:01 -07:00
$good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]);
2013-07-03 15:05:31 -07:00
if (defined $fix_elements[$n + 2]) {
$fix_elements[$n + 2] =~ s/^\s+//;
}
2013-09-11 14:24:01 -07:00
$line_fixed = 1;
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
# unary ++ and unary -- are allowed no space on one side.
} elsif ($op eq ' ++ ' or $op eq ' -- ') {
2008-03-28 14:15:58 -07:00
if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"space required one side of that ' $ op ' $at\n" . $hereptr)) {
2013-09-11 14:24:01 -07:00
$good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
2013-07-03 15:05:31 -07:00
$line_fixed = 1;
}
2007-06-01 00:46:48 -07:00
}
2008-03-28 14:15:58 -07:00
if ($ctx =~ /Wx[BE]/ ||
($ctx =~ /Wx./ && $cc =~ /^;/)) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"space prohibited before that ' $ op ' $at\n" . $hereptr)) {
2013-09-11 14:24:01 -07:00
$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
2013-07-03 15:05:31 -07:00
$line_fixed = 1;
}
2007-06-23 17:16:34 -07:00
}
2008-03-28 14:15:58 -07:00
if ($ctx =~ /ExW/) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"space prohibited after that ' $ op ' $at\n" . $hereptr)) {
2013-09-11 14:24:01 -07:00
$good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
2013-07-03 15:05:31 -07:00
if (defined $fix_elements[$n + 2]) {
$fix_elements[$n + 2] =~ s/^\s+//;
}
2013-09-11 14:24:01 -07:00
$line_fixed = 1;
2013-07-03 15:05:31 -07:00
}
2008-03-28 14:15:58 -07:00
}
2007-06-01 00:46:48 -07:00
# << and >> may either have or not have spaces both sides
2007-10-16 23:29:38 -07: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 04:20:54 -08:00
$op eq ' * ' or $op eq ' / ' or
$op eq ' %')
2007-06-01 00:46:48 -07:00
{
2008-03-28 14:15:58 -07:00
if ( $ ctx =~ / Wx [ ^ WCE ] | [ ^ WCE ] xW / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"need consistent spacing around '$op' $at\n" . $ hereptr ) ) {
2013-09-11 14:24:01 -07:00
$ good = rtrim ( $ fix_elements [ $ n ] ) . " " . trim ( $ fix_elements [ $ n + 1 ] ) . " " ;
if ( defined $ fix_elements [ $ n + 2 ] ) {
$ fix_elements [ $ n + 2 ] =~ s /^\ s +// ;
}
2013-07-03 15:05:31 -07:00
$ line_fixed = 1 ;
}
2007-06-01 00:46:48 -07:00
}
2008-07-23 21:29:10 -07: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 . / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited before that '$op' $at\n" . $ hereptr ) ) {
2013-09-11 14:24:01 -07:00
$ good = rtrim ( $ fix_elements [ $ n ] ) . trim ( $ fix_elements [ $ n + 1 ] ) ;
2013-07-03 15:05:31 -07:00
$ line_fixed = 1 ;
}
2008-07-23 21:29:10 -07:00
}
2007-06-01 00:46:48 -07:00
# All the others need spaces both sides .
2008-03-04 14:28:20 -08:00
} elsif ( $ ctx ! ~ / [ EWC ] x [ CWE ] / ) {
2008-07-23 21:29:10 -07:00
my $ ok = 0 ;
2007-08-10 13:01:03 -07:00
# Ignore email addresses < foo @ bar >
2008-07-23 21:29:10 -07:00
if ( ( $ op eq '<' &&
$ cc =~ /^\ S +\@\ S +>/ ) | |
( $ op eq '>' &&
$ ca =~ /<\ S +\@\ S + $ / ) )
{
$ ok = 1 ;
}
2013-11-12 15:10:05 -08:00
# messages are ERROR , but ?: are CHK
2008-07-23 21:29:10 -07:00
if ( $ ok == 0 ) {
2013-11-12 15:10:05 -08:00
my $ msg_type = \& ERROR ;
$ msg_type = \& CHK if ( ( $ op eq '?:' | | $ op eq '?' | | $ op eq ':' ) && $ ctx =~ / VxV / ) ;
if ( & { $ msg_type } ( "SPACING" ,
"spaces required around that '$op' $at\n" . $ hereptr ) ) {
2013-09-11 14:24:01 -07:00
$ good = rtrim ( $ fix_elements [ $ n ] ) . " " . trim ( $ fix_elements [ $ n + 1 ] ) . " " ;
if ( defined $ fix_elements [ $ n + 2 ] ) {
$ fix_elements [ $ n + 2 ] =~ s /^\ s +// ;
}
2013-07-03 15:05:31 -07:00
$ line_fixed = 1 ;
}
2007-08-10 13:01:03 -07:00
}
2007-06-01 00:46:48 -07:00
}
2007-06-08 13:46:39 -07:00
$ off += length ( $ elements [ $ n + 1 ] ) ;
2013-07-03 15:05:31 -07:00
## print ( "n: <$n> GOOD: <$good>\n" ) ;
$ fixed_line = $ fixed_line . $ good ;
2007-06-01 00:46:48 -07:00
}
2013-07-03 15:05:31 -07:00
if ( ( $ # elements % 2) == 0) {
$ fixed_line = $ fixed_line . $ fix_elements [ $ # elements ] ;
}
if ( $ fix && $ line_fixed && $ fixed_line ne $ fixed [ $ linenr - 1 ] ) {
$ fixed [ $ linenr - 1 ] = $ fixed_line ;
}
2007-06-01 00:46:48 -07:00
}
2013-07-03 15:05:32 -07:00
# check for whitespace before a non - naked semicolon
2014-01-23 15:54:41 -08:00
if ( $ line =~ /^\+.*\ S \ s + ; \ s * $ / ) {
2013-07-03 15:05:32 -07:00
if ( WARN ( "SPACING" ,
"space prohibited before semicolon\n" . $ herecurr ) &&
$ fix ) {
1 while $ fixed [ $ linenr - 1 ] =~
s /^ ( \+.*\ S ) \ s + ; / $ 1 ; / ;
}
}
2007-07-19 01:48:34 -07:00
# check for multiple assignments
if ( $ line =~ /^.\ s * $ Lval \ s *=\ s * $ Lval \ s *= ( ? ! = ) / ) {
2011-07-25 17:13:25 -07:00
CHK ( "MULTIPLE_ASSIGNMENTS" ,
"multiple assignments should be avoided\n" . $ herecurr ) ;
2007-07-19 01:48:34 -07:00
}
2007-08-10 13:01:03 -07: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-25 17:13:25 -07:00
## WARN ( "MULTIPLE_DECLARATION" ,
## "declaring multiple variables together should be avoided\n" . $ herecurr ) ;
2007-08-10 13:01:03 -07:00
## }
## }
2007-07-19 01:48:34 -07:00
2007-06-01 00:46:48 -07:00
# need space before brace following if , while , etc
2007-08-10 13:01:03 -07:00
if ( ( $ line =~ /\ ( . *\ ) { / && $ line ! ~ /\ ( $ Type \ ) { / ) | |
$ line =~ / do { / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space required before the open brace '{'\n" . $ herecurr ) &&
$ fix ) {
2013-09-11 14:23:54 -07:00
$ fixed [ $ linenr - 1 ] =~ s /^ ( \+.* ( ?: do | \ ) ) ) { / $ 1 { / ;
2013-07-03 15:05:31 -07:00
}
2007-07-15 23:37:22 -07:00
}
2013-07-03 15:05:28 -07:00
## # check for blank lines before declarations
## if ( $ line =~ /^.\ t + $ Type \ s + $ Ident ( ?:\ s *=.* ) ? ; / &&
## $ prevrawline =~ /^.\ s * $ / ) {
## WARN ( "SPACING" ,
## "No blank lines before declarations\n" . $ hereprev ) ;
## }
##
2007-07-15 23:37:22 -07:00
# closing brace should have a space following it when it has anything
# on the line
if ( $ line =~ / } ( ? ! ( ?: , | ; | \ ) ) ) \ S / ) {
2013-09-11 14:23:54 -07:00
if ( ERROR ( "SPACING" ,
"space required after that close brace '}'\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~
s / } ( ( ? ! ( ?: , | ; | \ ) ) ) \ S ) / } $ 1 / ;
}
2007-06-01 00:46:48 -07:00
}
2007-08-10 13:01:03 -07:00
# check spacing on square brackets
if ( $ line =~ /\ [ \ s / && $ line ! ~ /\ [ \ s * $ / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited after that open square bracket '['\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~
s /\ [ \ s +/\ [ / ;
}
2007-08-10 13:01:03 -07:00
}
if ( $ line =~ /\ s \ ] / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited before that close square bracket ']'\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~
s /\ s +\ ] /\ ] / ;
}
2007-08-10 13:01:03 -07:00
}
2008-06-05 22:46:01 -07:00
# check spacing on parentheses
2007-10-16 23:29:38 -07:00
if ( $ line =~ /\ ( \ s / && $ line ! ~ /\ ( \ s * ( ?:\\ ) ? $ / &&
$ line ! ~ / for \ s *\ ( \ s + ; / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited after that open parenthesis '('\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~
s /\ ( \ s +/\ ( / ;
}
2007-08-10 13:01:03 -07:00
}
2008-02-08 04:22:03 -08:00
if ( $ line =~ / ( \ s + ) \ ) / && $ line ! ~ /^.\ s *\ ) / &&
2008-06-05 22:46:01 -07:00
$ line ! ~ / for \ s *\ ( . * ; \ s +\ ) / &&
$ line ! ~ /:\ s +\ ) / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited before that close parenthesis ')'\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~
s /\ s +\ ) /\ ) / ;
}
2007-08-10 13:01:03 -07:00
}
2007-06-01 00:46:48 -07:00
# goto labels aren 't indented, allow a single space however
2007-06-08 13:46:39 -07:00
if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
2007-06-01 00:46:48 -07:00
!($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
2013-07-03 15:05:31 -07:00
if (WARN("INDENTED_LABEL",
"labels should not be indented\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~
s/^(.)\s+/$1/;
}
2007-06-01 00:46:48 -07:00
}
2014-04-03 14:49:21 -07:00
# return is not a function
2013-11-12 15:10:13 -08:00
if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
2008-06-05 22:46:01 -07:00
my $spacing = $1;
2013-11-12 15:10:13 -08:00
if ($^V && $^V ge 5.10.0 &&
2014-04-03 14:49:21 -07:00
$stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
my $value = $1;
$value = deparenthesize($value);
if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) {
ERROR("RETURN_PARENTHESES",
"return is not a function, parentheses are not required\n" . $herecurr);
}
2008-06-05 22:46:01 -07:00
} elsif ($spacing !~ /\s+/) {
2011-07-25 17:13:25 -07:00
ERROR("SPACING",
"space required before the open parenthesis ' ( '\n" . $herecurr);
2008-06-05 22:46:01 -07:00
}
}
2013-11-12 15:10:13 -08:00
2014-01-23 15:54:47 -08:00
# if statements using unnecessary parentheses - ie: if ((foo == bar))
if ($^V && $^V ge 5.10.0 &&
$line =~ /\bif\s*((?:\(\s*){2,})/) {
my $openparens = $1;
my $count = $openparens =~ tr@\(@\(@;
my $msg = "";
if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) {
my $comp = $4; #Not $1 because of $LvalOrFunc
$msg = " - maybe == should be = ?" if ($comp eq "==");
WARN("UNNECESSARY_PARENTHESES",
"Unnecessary parentheses$msg\n" . $herecurr);
}
}
2010-10-26 14:23:14 -07: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-25 17:13:25 -07:00
WARN ( "USE_NEGATIVE_ERRNO" ,
"return of an errno should typically be -ve (return -$1)\n" . $ herecurr ) ;
2010-10-26 14:23:14 -07:00
}
}
2008-06-05 22:46:01 -07:00
2007-06-01 00:46:48 -07:00
# Need a space before open parenthesis after if , while etc
2013-07-03 15:05:31 -07:00
if ( $ line =~ /\ b ( if | while | for | switch ) \ ( / ) {
if ( ERROR ( "SPACING" ,
"space required before the open parenthesis '('\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~
s /\ b ( if | while | for | switch ) \ ( / $ 1 \ ( / ;
}
2007-06-01 00:46:48 -07:00
}
2008-07-23 21:29:03 -07:00
# Check for illegal assignment in if conditional -- and check for trailing
# statements after the conditional .
2008-10-15 22:02:30 -07:00
if ( $ line =~ / do \ s * ( ? ! { ) / ) {
2012-01-10 15:10:01 -08:00
( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ) =
ctx_statement_block ( $ linenr , $ realcnt , 0 )
if ( ! defined $ stat ) ;
2008-10-15 22:02:30 -07: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 } &&
2013-11-21 14:31:57 -08:00
defined ( $ stat ) && defined ( $ cond ) &&
2008-10-15 22:02:30 -07:00
$ line =~ /\ b ( ?: if | while | for ) \ s *\ ( / && $ line ! ~ /^.\ s *#/ ) {
2008-04-29 00:59:32 -07:00
my ( $ s , $ c ) = ( $ stat , $ cond ) ;
2007-11-28 16:21:06 -08:00
2009-01-06 14:41:29 -08:00
if ( $ c =~ /\ bif \ s *\ ( . * [ ^<> ! = ] = [ ^= ] . */ s ) {
2011-07-25 17:13:25 -07:00
ERROR ( "ASSIGN_IN_IF" ,
"do not use assignment in if condition\n" . $ herecurr ) ;
2007-11-28 16:21:06 -08:00
}
# Find out what is on the end of the line after the
# conditional .
2008-03-28 14:15:58 -07:00
substr ( $ s , 0 , length ( $ c ) , '' ) ;
2007-11-28 16:21:06 -08:00
$ s =~ s /\ n . *// g ;
2008-02-08 04:22:03 -08:00
$ s =~ s / $ ; // g ; # Remove any comments
2008-07-23 21:29:03 -07:00
if ( length ( $ c ) && $ s ! ~ /^\ s * { ?\ s *\\*\ s * $ / &&
$ c ! ~ / } \ s * while \ s */ )
2008-03-28 14:15:58 -07:00
{
2008-10-15 22:02:34 -07:00
# Find out how long the conditional actually is .
my @ newlines = ( $ c =~ /\ n / gs ) ;
my $ cond_lines = 1 + $ # newlines ;
2010-03-05 13:43:50 -08:00
my $ stat_real = '' ;
2008-10-15 22:02:34 -07:00
2010-03-05 13:43:50 -08:00
$ stat_real = raw_line ( $ linenr , $ cond_lines )
. "\n" if ( $ cond_lines ) ;
2008-10-15 22:02:34 -07:00
if ( defined ( $ stat_real ) && $ cond_lines > 1 ) {
$ stat_real = "[...]\n$stat_real" ;
}
2011-07-25 17:13:25 -07:00
ERROR ( "TRAILING_STATEMENTS" ,
"trailing statements should be on next line\n" . $ herecurr . $ stat_real ) ;
2007-11-28 16:21:06 -08:00
}
}
2008-02-08 04:22:03 -08: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-25 17:13:25 -07:00
WARN ( "HEXADECIMAL_BOOLEAN_TEST" ,
" boolean test with hexadecimal , perhaps just 1 \& or \ | ?\ n " . $ herecurr ) ;
2008-02-08 04:22:03 -08:00
}
2007-11-28 16:21:06 -08:00
# if and else should not have general statements after it
2008-02-08 04:22:03 -08:00
if ( $ line =~ /^.\ s * ( ?: } \ s * ) ? else \ b ( . * ) / ) {
my $ s = $ 1 ;
$ s =~ s / $ ; // g ; # Remove any comments
if ( $ s ! ~ /^\ s * ( ?:\ sif | ( ?: { | ) \ s *\\?\ s * $ ) / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "TRAILING_STATEMENTS" ,
"trailing statements should be on next line\n" . $ herecurr ) ;
2008-02-08 04:22:03 -08:00
}
2007-06-01 00:46:48 -07:00
}
2009-01-15 13:51:06 -08:00
# if should not continue a brace
if ( $ line =~ / } \ s * if \ b / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "TRAILING_STATEMENTS" ,
"trailing statements should be on next line\n" .
2009-01-15 13:51:06 -08:00
$ herecurr ) ;
}
2008-10-15 22:02:25 -07:00
# case and default should not have general statements after them
if ( $ line =~ /^.\ s * ( ?: case \ s *.* | default \ s * ) :/ g &&
$ line ! ~ /\ G ( ?:
2008-10-15 22:02:36 -07:00
( ?:\ s * $ ; * ) ( ?:\ s * { ) ? ( ?:\ s * $ ; * ) ( ?:\ s *\\ ) ?\ s * $ |
2008-10-15 22:02:25 -07:00
\ s * return \ s +
) / xg )
{
2011-07-25 17:13:25 -07:00
ERROR ( "TRAILING_STATEMENTS" ,
"trailing statements should be on next line\n" . $ herecurr ) ;
2008-10-15 22:02:25 -07:00
}
2007-06-01 00:46:48 -07: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-25 17:13:25 -07:00
ERROR ( "ELSE_AFTER_BRACE" ,
"else should follow close brace '}'\n" . $ hereprev ) ;
2007-06-01 00:46:48 -07:00
}
2008-02-08 04:20:54 -08: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-28 14:15:58 -07:00
substr ( $ s , 0 , length ( $ c ) , '' ) ;
2008-02-08 04:20:54 -08:00
$ s =~ s /\ n . *// g ;
if ( $ s =~ /^\ s * ; / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "WHILE_AFTER_BRACE" ,
"while should follow close brace '}'\n" . $ hereprev ) ;
2008-02-08 04:20:54 -08:00
}
}
2013-07-03 15:05:20 -07:00
# Specific variable tests
2012-12-17 16:02:07 -08:00
while ( $ line =~ m { ( $ Constant | $ Lval ) } g ) {
my $ var = $ 1 ;
2013-07-03 15:05:20 -07:00
# gcc binary extension
if ( $ var =~ /^ $ Binary $ / ) {
2013-09-11 14:23:54 -07:00
if ( WARN ( "GCC_BINARY_CONSTANT" ,
"Avoid gcc v4.3+ binary constant extension: <$var>\n" . $ herecurr ) &&
$ fix ) {
my $ hexval = sprintf ( "0x%x" , oct ( $ var ) ) ;
$ fixed [ $ linenr - 1 ] =~
s /\ b$var \ b / $ hexval / ;
}
2013-07-03 15:05:20 -07:00
}
# CamelCase
2013-07-03 15:05:22 -07:00
if ( $ var ! ~ /^ $ Constant $ / &&
2013-07-03 15:05:20 -07:00
$ var =~ / [ A - Z ] [ a - z ] | [ a - z ] [ A - Z ] / &&
2013-07-03 15:05:33 -07:00
# Ignore Page < foo > variants
2013-07-03 15:05:22 -07:00
$ var ! ~ /^ ( ?: Clear | Set | TestClear | TestSet | ) Page [ A - Z ] / &&
2013-07-03 15:05:33 -07:00
# Ignore SI style variants like nS , mV and dB ( ie : max_uV , regulator_min_uA_show )
2013-07-03 15:05:34 -07:00
$ var ! ~ /^ ( ?: [ a - z_ ] *? ) _ ? [ a - z ] [ A - Z ] ( ?: _ [ a - z_ ] + ) ? $ / ) {
2013-09-11 14:23:55 -07:00
while ( $ var =~ m { ( $ Ident ) } g ) {
my $ word = $ 1 ;
next if ( $ word ! ~ / [ A - Z ] [ a - z ] | [ a - z ] [ A - Z ] / ) ;
2013-11-12 15:10:06 -08:00
if ( $ check ) {
seed_camelcase_includes ( ) ;
if ( ! $ file && ! $ camelcase_file_seeded ) {
seed_camelcase_file ( $ realfile ) ;
$ camelcase_file_seeded = 1 ;
}
}
2013-09-11 14:23:55 -07:00
if ( ! defined $ camelcase { $ word } ) {
$ camelcase { $ word } = 1 ;
CHK ( "CAMELCASE" ,
"Avoid CamelCase: <$word>\n" . $ herecurr ) ;
}
2013-07-03 15:05:34 -07:00
}
2012-12-17 16:02:07 -08:00
}
}
2007-06-01 00:46:48 -07:00
# no spaces allowed after \ in define
2013-09-11 14:23:54 -07:00
if ( $ line =~ /\#\ s * define . *\\\ s + $ / ) {
if ( WARN ( "WHITESPACE_AFTER_LINE_CONTINUATION" ,
" Whitespace after \\ makes next lines useless \ n " . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s /\ s + $ // ;
}
2007-06-01 00:46:48 -07:00
}
2007-06-23 17:16:34 -07:00
# warn if < asm / foo . h > is # included and < linux / foo . h > is available ( uses RAW line )
2008-06-05 22:46:01 -07:00
if ( $ tree && $ rawline =~ m { ^.\ s *\#\ s * include \ s *\< asm \/ ( . * ) \. h \> } ) {
2008-10-15 22:02:20 -07:00
my $ file = "$1.h" ;
my $ checkfile = "include/linux/$file" ;
if ( - f "$root/$checkfile" &&
$ realfile ne $ checkfile &&
2010-08-09 17:20:57 -07:00
$ 1 ! ~ / $ allowed_asm_includes / )
2008-06-05 22:46:01 -07:00
{
2008-10-15 22:02:20 -07:00
if ( $ realfile =~ m { ^ arch / } ) {
2011-07-25 17:13:25 -07:00
CHK ( "ARCH_INCLUDE_LINUX" ,
"Consider using #include <linux/$file> instead of <asm/$file>\n" . $ herecurr ) ;
2008-10-15 22:02:20 -07:00
} else {
2011-07-25 17:13:25 -07:00
WARN ( "INCLUDE_LINUX" ,
"Use #include <linux/$file> instead of <asm/$file>\n" . $ herecurr ) ;
2008-10-15 22:02:20 -07:00
}
2007-06-01 00:46:48 -07:00
}
}
2007-06-23 17:16:34 -07: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-04 14:28:20 -08:00
# in a known good container
2008-07-23 21:29:07 -07:00
if ( $ realfile ! ~ m @/ vmlinux . lds . h$ @ &&
$ line =~ /^.\ s *\#\ s * define \ s * $ Ident ( \ ( ) ?/ ) {
2007-06-23 17:16:44 -07:00
my $ ln = $ linenr ;
my $ cnt = $ realcnt ;
2008-06-05 22:46:01 -07:00
my ( $ off , $ dstat , $ dcond , $ rest ) ;
my $ ctx = '' ;
( $ dstat , $ dcond , $ ln , $ cnt , $ off ) =
2012-01-10 15:09:54 -08:00
ctx_statement_block ( $ linenr , $ realcnt , 0 ) ;
$ ctx = $ dstat ;
2008-06-05 22:46:01 -07:00
# print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n" ;
2008-07-23 21:29:00 -07:00
# print "LINE<$lines[$ln-1]> len<" . length ( $ lines [ $ ln - 1 ] ) . "\n" ;
2008-06-05 22:46:01 -07:00
2012-01-10 15:09:54 -08:00
$ dstat =~ s /^.\ s *\#\ s * define \ s + $ Ident ( ?:\ ( [ ^\ ) ] *\ ) ) ?\ s *// ;
2008-07-23 21:29:11 -07:00
$ dstat =~ s / $ ; // g ;
2008-06-05 22:46:01 -07:00
$ dstat =~ s /\\\ n . // g ;
$ dstat =~ s /^\ s *// s ;
$ dstat =~ s /\ s * $ // s ;
# Flatten any parentheses and braces
2008-10-15 22:02:33 -07:00
while ( $ dstat =~ s /\ ( [ ^\ ( \ ) ] *\ ) / 1 / | |
$ dstat =~ s /\ { [ ^\ { \ } ] *\ } / 1 / | |
2012-01-10 15:10:10 -08:00
$ dstat =~ s /\ [ [ ^\ [ \ ] ] *\ ] / 1 / )
2008-10-15 22:02:33 -07:00
{
2007-07-15 23:37:22 -07:00
}
2007-06-23 17:16:44 -07:00
2012-03-23 15:02:18 -07:00
# Flatten any obvious string concatentation .
while ( $ dstat =~ s / ( "X*" ) \ s * $ Ident / $ 1 / | |
$ dstat =~ s / $ Ident \ s * ( "X*" ) / $ 1 / )
{
}
2008-06-05 22:46:01 -07:00
my $ exceptions = qr {
$ Declare |
module_param_named |
2012-10-04 17:13:38 -07:00
MODULE_PARM_DESC |
2008-06-05 22:46:01 -07:00
DECLARE_PER_CPU |
DEFINE_PER_CPU |
2009-01-06 14:41:18 -08:00
_ _ typeof__ \ ( |
2010-03-05 13:43:52 -08:00
union |
struct |
2009-09-21 17:04:38 -07:00
\. $ Ident \ s *=\ s * |
^\ "|\"$
2008-06-05 22:46:01 -07:00
}x;
2010-10-26 14:23:18 -07:00
#print " REST < $ rest > dstat < $ dstat > ctx < $ ctx >\ n " ;
2012-01-10 15:09:54 -08:00
if ( $ dstat ne '' &&
$ dstat ! ~ /^ ( ?: $ Ident | -? $ Constant ) , $ / && # 10 , // foo ( ) ,
$ dstat ! ~ /^ ( ?: $ Ident | -? $ Constant ) ; $ / && # foo ( ) ;
2013-07-03 15:05:27 -07:00
$ dstat ! ~ /^ [ ! ~- ] ? ( ?: $ Lval | $ Constant ) $ / && # 10 // foo ( ) // ! foo // ~ foo // - foo // foo -> bar // foo . bar -> baz
2012-03-23 15:02:17 -07:00
$ dstat ! ~ /^ 'X' $ / && # character constants
2012-01-10 15:09:54 -08:00
$ dstat ! ~ / $ exceptions / &&
$ dstat ! ~ /^\. $ Ident \ s *=/ && # . foo =
2013-04-17 15:58:26 -07:00
$ dstat ! ~ /^ ( ?:\#\ s * $ Ident | \#\ s * $ Constant ) \ s * $ / && # stringification # foo
2012-01-10 15:10:06 -08:00
$ dstat ! ~ /^ do \ s * $ Constant \ s * while \ s * $ Constant ; ? $ / && # do { . . . } while ( . . . ) ; // do { . . . } while ( . . . )
2012-01-10 15:09:54 -08:00
$ dstat ! ~ /^ for \ s * $ Constant $ / && # for ( . . . )
$ dstat ! ~ /^ for \ s * $ Constant \ s + ( ?: $ Ident | -? $ Constant ) $ / && # for ( . . . ) bar ( )
$ dstat ! ~ /^ do \ s * { / && # do { . . .
2013-09-11 14:24:00 -07:00
$ dstat ! ~ /^\ ( { / && # ( { . . .
$ ctx ! ~ /^.\ s *#\ s * define \ s + TRACE_ ( ?: SYSTEM | INCLUDE_FILE | INCLUDE_PATH ) \ b / )
2012-01-10 15:09:54 -08:00
{
$ 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-05 22:46:01 -07:00
}
2012-01-10 15:09:54 -08: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-25 17:13:25 -07:00
ERROR ( "COMPLEX_MACRO" ,
2012-01-10 15:09:54 -08:00
"Macros with complex values should be enclosed in parenthesis\n" . "$herectx" ) ;
2007-06-23 17:16:44 -07:00
}
2007-06-23 17:16:34 -07:00
}
2012-12-17 16:01:47 -08:00
2012-12-17 16:01:56 -08:00
# check for line continuations outside of # defines , preprocessor # , and asm
2012-12-17 16:01:47 -08:00
} else {
if ( $ prevline ! ~ /^..*\\ $ / &&
2012-12-17 16:01:56 -08:00
$ line ! ~ /^\+\ s *\#.*\\ $ / && # preprocessor
$ line ! ~ /^\+.*\ b ( _ _ asm__ | asm ) \ b . *\\ $ / && # asm
2012-12-17 16:01:47 -08:00
$ line =~ /^\+.*\\ $ / ) {
WARN ( "LINE_CONTINUATIONS" ,
"Avoid unnecessary line continuations\n" . $ herecurr ) ;
}
2007-06-01 00:46:48 -07:00
}
2012-07-30 14:41:24 -07: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-21 16:15:53 -07:00
if ( ( $ stmts =~ tr / ; / ; / ) == 1 &&
$ stmts ! ~ /^\ s * ( if | while | for | switch ) \ b / ) {
2012-07-30 14:41:24 -07: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-06 14:41:25 -08: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-25 17:13:25 -07:00
WARN ( "MISSING_VMLINUX_SYMBOL" ,
"vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $ herecurr ) ;
2009-01-06 14:41:25 -08:00
}
2007-07-19 01:48:34 -07:00
# check for redundant bracing round if etc
2008-02-08 04:22:03 -08:00
if ( $ line =~ / ( ^.* ) \ bif \ b / && $ 1 ! ~ / else \ s * $ / ) {
my ( $ level , $ endln , @ chunks ) =
2008-03-04 14:28:20 -08:00
ctx_statement_full ( $ linenr , $ realcnt , 1 ) ;
2008-02-08 04:22:03 -08:00
# print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n" ;
2008-03-04 14:28:20 -08:00
# print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n" ;
if ( $ # chunks > 0 && $ level == 0 ) {
2012-03-23 15:02:19 -07:00
my @ allowed = ( ) ;
my $ allow = 0 ;
2008-02-08 04:22:03 -08:00
my $ seen = 0 ;
2008-03-28 14:15:58 -07:00
my $ herectx = $ here . "\n" ;
2008-03-04 14:28:20 -08:00
my $ ln = $ linenr - 1 ;
2008-02-08 04:22:03 -08:00
for my $ chunk ( @ chunks ) {
my ( $ cond , $ block ) = @ { $ chunk } ;
2008-03-28 14:15:58 -07: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-23 15:02:19 -07:00
$ allowed [ $ allow ] = 0 ;
2008-03-28 14:15:58 -07: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-04 14:28:20 -08:00
$ ln += statement_rawlines ( $ block ) - 1 ;
2008-03-28 14:15:58 -07:00
substr ( $ block , 0 , length ( $ cond ) , '' ) ;
2008-02-08 04:22:03 -08:00
$ seen ++ if ( $ block =~ /^\ s * { / ) ;
2012-03-23 15:02:19 -07:00
# print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n" ;
2008-03-04 14:28:20 -08:00
if ( statement_lines ( $ cond ) > 1 ) {
# print "APW: ALLOWED: cond<$cond>\n" ;
2012-03-23 15:02:19 -07:00
$ allowed [ $ allow ] = 1 ;
2008-02-08 04:22:03 -08:00
}
if ( $ block =~/\ b ( ?: if | for | while ) \ b / ) {
2008-03-04 14:28:20 -08:00
# print "APW: ALLOWED: block<$block>\n" ;
2012-03-23 15:02:19 -07:00
$ allowed [ $ allow ] = 1 ;
2008-02-08 04:22:03 -08:00
}
2008-03-04 14:28:20 -08:00
if ( statement_block_size ( $ block ) > 1 ) {
# print "APW: ALLOWED: lines block<$block>\n" ;
2012-03-23 15:02:19 -07:00
$ allowed [ $ allow ] = 1 ;
2008-02-08 04:22:03 -08:00
}
2012-03-23 15:02:19 -07:00
$ allow ++ ;
2008-02-08 04:22:03 -08:00
}
2012-03-23 15:02:19 -07: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 04:22:03 -08:00
}
}
}
2008-03-28 14:15:58 -07:00
if ( ! defined $ suppress_ifbraces { $ linenr - 1 } &&
2008-02-08 04:22:03 -08:00
$ line =~ /\ b ( if | while | for | else ) \ b / ) {
2008-03-04 14:28:20 -08:00
my $ allowed = 0 ;
2007-07-19 01:48:34 -07:00
2008-03-04 14:28:20 -08:00
# Check the pre - context .
if ( substr ( $ line , 0 , $ - [ 0 ] ) =~ / ( \ } \ s * ) $ / ) {
# print "APW: ALLOWED: pre<$1>\n" ;
$ allowed = 1 ;
}
2008-03-28 14:15:58 -07:00
my ( $ level , $ endln , @ chunks ) =
ctx_statement_full ( $ linenr , $ realcnt , $ - [ 0 ] ) ;
2008-03-04 14:28:20 -08:00
# Check the condition .
my ( $ cond , $ block ) = @ { $ chunks [ 0 ] } ;
2008-03-28 14:15:58 -07:00
# print "CHECKING<$linenr> cond<$cond> block<$block>\n" ;
2008-03-04 14:28:20 -08:00
if ( defined $ cond ) {
2008-03-28 14:15:58 -07:00
substr ( $ block , 0 , length ( $ cond ) , '' ) ;
2008-03-04 14:28:20 -08: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-28 14:15:58 -07:00
substr ( $ block , 0 , length ( $ cond ) , '' ) ;
2007-07-19 01:48:34 -07:00
}
2008-03-04 14:28:20 -08:00
if ( $ block =~ /^\ s *\ { / ) {
# print "APW: ALLOWED: chunk-1 block<$block>\n" ;
$ allowed = 1 ;
}
}
if ( $ level == 0 && $ block =~ /^\ s *\ { / && ! $ allowed ) {
2011-07-26 23:06:29 -07:00
my $ herectx = $ here . "\n" ;
2008-10-15 22:02:23 -07:00
my $ cnt = statement_rawlines ( $ block ) ;
2008-03-04 14:28:20 -08:00
2008-10-15 22:02:23 -07:00
for ( my $ n = 0 ; $ n < $ cnt ; $ n ++ ) {
2011-07-26 23:06:29 -07:00
$ herectx . = raw_line ( $ linenr , $ n ) . "\n" ;
2008-03-04 14:28:20 -08:00
}
2011-07-25 17:13:25 -07:00
WARN ( "BRACES" ,
"braces {} are not necessary for single statement blocks\n" . $ herectx ) ;
2007-07-19 01:48:34 -07:00
}
}
2012-12-17 16:01:59 -08:00
# check for unnecessary blank lines around braces
2013-07-03 15:05:29 -07:00
if ( ( $ line =~ /^.\ s * } \ s * $ / && $ prevrawline =~ /^.\ s * $ / ) ) {
2012-12-17 16:01:59 -08:00
CHK ( "BRACES" ,
"Blank lines aren't necessary before a close brace '}'\n" . $ hereprev ) ;
}
2013-07-03 15:05:29 -07:00
if ( ( $ rawline =~ /^.\ s * $ / && $ prevline =~ /^..* { \ s * $ / ) ) {
2012-12-17 16:01:59 -08:00
CHK ( "BRACES" ,
"Blank lines aren't necessary after an open brace '{'\n" . $ hereprev ) ;
}
2007-06-08 13:46:39 -07:00
# no volatiles please
2007-10-18 03:05:08 -07:00
my $ asm_volatile = qr { \ b ( _ _ asm__ | asm ) \ s + ( _ _ volatile__ | volatile ) \ b } ;
if ( $ line =~ /\ bvolatile \ b / && $ line ! ~ / $ asm_volatile / ) {
2011-07-25 17:13:25 -07:00
WARN ( "VOLATILE" ,
"Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $ herecurr ) ;
2007-06-08 13:46:39 -07:00
}
2007-06-08 13:47:06 -07:00
# warn about # if 0
2008-06-05 22:46:01 -07:00
if ( $ line =~ /^.\ s *\#\ s * if \ s + 0 \ b / ) {
2011-07-25 17:13:25 -07:00
CHK ( "REDUNDANT_CODE" ,
"if this code is redundant consider removing it\n" .
2007-07-15 23:37:22 -07:00
$ herecurr ) ;
2007-06-08 13:46:39 -07:00
}
2012-12-17 16:01:52 -08: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-23 21:29:04 -07:00
}
}
2007-07-19 01:48:34 -07:00
2013-09-11 14:24:05 -07:00
# check for bad placement of section $ InitAttribute ( e . g . : _ _ initdata )
if ( $ line =~ / ( \ b$InitAttribute \ b ) / ) {
my $ attr = $ 1 ;
if ( $ line =~ /^\+\ s * static \ s + ( ?: const \ s + ) ? ( ?: $ attr \ s + ) ? ( $ NonptrTypeWithAttr ) \ s + ( ?: $ attr \ s + ) ? ( $ Ident ( ?:\ [ [ ^ ] ] *\ ] ) ? ) \ s * [ = ; ] / ) {
my $ ptr = $ 1 ;
my $ var = $ 2 ;
if ( ( ( $ ptr =~ /\ b ( union | struct ) \ s + $ attr \ b / &&
ERROR ( "MISPLACED_INIT" ,
"$attr should be placed after $var\n" . $ herecurr ) ) | |
( $ ptr ! ~ /\ b ( union | struct ) \ s + $ attr \ b / &&
WARN ( "MISPLACED_INIT" ,
"$attr should be placed after $var\n" . $ herecurr ) ) ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s / ( \ bstatic \ s + ( ?: const \ s + ) ? ) ( ?: $ attr \ s + ) ? ( $ NonptrTypeWithAttr ) \ s + ( ?: $ attr \ s + ) ? ( $ Ident ( ?:\ [ [ ^ ] ] *\ ] ) ? ) \ s * ( [ = ; ] ) \ s */ "$1" . trim ( string_find_replace ( $ 2 , " \\ s * $ attr \\ s * ", " ")) . " " . trim(string_find_replace($3, " \\ s * $ attr \\ s * ", " ")) . " $ attr " . (" $ 4 " eq " ; " ? " ; " : " = ")/e;
}
}
}
2013-11-12 15:10:10 -08:00
# check for $InitAttributeData (ie: __initdata) with const
if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) {
my $attr = $1;
$attr =~ /($InitAttributePrefix)(.*)/;
my $attr_prefix = $1;
my $attr_type = $2;
if (ERROR(" INIT_ATTRIBUTE ",
" Use of const init definition must use $ { attr_prefix } initconst \ n " . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~
s/$InitAttributeData/${attr_prefix}initconst/;
}
}
# check for $InitAttributeConst (ie: __initconst) without const
if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) {
my $attr = $1;
if (ERROR(" INIT_ATTRIBUTE ",
" Use of $ attr requires a separate use of const \ n " . $ herecurr ) &&
$ fix ) {
my $ lead = $ fixed [ $ linenr - 1 ] =~
/ ( ^\+\ s * ( ?: static \ s + ) ) / ;
$ lead = rtrim ( $ 1 ) ;
$ lead = "$lead " if ( $ lead ! ~ /^\+ $ / ) ;
$ lead = "${lead}const " ;
$ fixed [ $ linenr - 1 ] =~ s / ( ^\+\ s * ( ?: static \ s + ) ) / $ lead / ;
}
}
2014-04-03 14:49:14 -07:00
# don 't use __constant_<foo> functions outside of include/uapi/
if ($realfile !~ m@^include/uapi/@ &&
$line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) {
my $constant_func = $1;
my $func = $constant_func;
$func =~ s/^__constant_//;
if (WARN("CONSTANT_CONVERSION",
"$constant_func should be $func\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~ s/\b$constant_func\b/$func/g;
}
}
2010-08-09 17:21:01 -07:00
# prefer usleep_range over udelay
2013-02-21 16:44:19 -08:00
if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
2014-04-03 14:49:11 -07:00
my $delay = $1;
2010-08-09 17:21:01 -07:00
# ignore udelay' s < 10 , however
2014-04-03 14:49:11 -07:00
if ( ! ( $ delay < 10 ) ) {
2011-07-25 17:13:25 -07:00
CHK ( "USLEEP_RANGE" ,
2014-04-03 14:49:11 -07:00
"usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $ herecurr ) ;
}
if ( $ delay > 2000 ) {
WARN ( "LONG_UDELAY" ,
"long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $ herecurr ) ;
2010-08-09 17:21:01 -07:00
}
}
2010-08-09 17:21:02 -07:00
# warn about unexpectedly long msleep 's
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
if ($1 < 20) {
2011-07-25 17:13:25 -07:00
WARN("MSLEEP",
2014-04-03 14:49:11 -07:00
"msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr);
2010-08-09 17:21:02 -07:00
}
}
2013-07-03 15:05:25 -07:00
# check for comparisons of jiffies
if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
WARN("JIFFIES_COMPARISON",
"Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr);
}
2013-07-03 15:05:26 -07:00
# check for comparisons of get_jiffies_64()
if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) {
WARN("JIFFIES_COMPARISON",
"Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr);
}
2007-06-08 13:47:06 -07:00
# warn about #ifdefs in C files
2008-06-05 22:46:01 -07:00
# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
2007-06-08 13:47:06 -07:00
# print "#ifdef in C files should be avoided\n";
# print "$herecurr";
# $clean = 0;
# }
2007-08-10 13:01:03 -07:00
# warn about spacing in #ifdefs
2008-06-05 22:46:01 -07:00
if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"exactly one space required after that #$1\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~
s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /;
}
2007-08-10 13:01:03 -07:00
}
2007-06-08 13:46:39 -07:00
# check for spinlock_t definitions without a comment.
2008-04-29 00:59:32 -07:00
if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
$line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
2007-06-08 13:46:39 -07:00
my $which = $1;
if (!ctx_has_comment($first_line, $linenr)) {
2011-07-25 17:13:25 -07:00
CHK("UNCOMMENTED_DEFINITION",
"$1 definition without comment\n" . $herecurr);
2007-06-08 13:46:39 -07: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)) {
2013-11-12 15:10:11 -08:00
WARN("MEMORY_BARRIER",
"memory barrier without comment\n" . $herecurr);
2007-06-08 13:46:39 -07:00
}
}
# check of hardware specific defines
2008-06-05 22:46:01 -07:00
if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
2011-07-25 17:13:25 -07:00
CHK("ARCH_DEFINES",
"architecture specific defines should be avoided\n" . $herecurr);
2007-06-01 00:46:48 -07:00
}
2007-06-23 17:16:34 -07:00
2010-05-24 14:33:30 -07:00
# Check that the storage class is at the beginning of a declaration
if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) {
2011-07-25 17:13:25 -07:00
WARN("STORAGE_CLASS",
"storage class should be at the beginning of the declaration\n" . $herecurr)
2010-05-24 14:33:30 -07:00
}
2007-07-15 23:37:22 -07:00
# check the location of the inline attribute, that it is between
# storage class and type.
2007-10-16 23:29:38 -07:00
if ($line =~ /\b$Type\s+$Inline\b/ ||
$line =~ /\b$Inline\s+$Storage\b/) {
2011-07-25 17:13:25 -07:00
ERROR("INLINE_LOCATION",
"inline keyword should sit between storage class and type\n" . $herecurr);
2007-07-15 23:37:22 -07:00
}
2007-11-28 16:21:06 -08:00
# Check for __inline__ and __inline, prefer inline
2013-11-12 15:10:14 -08:00
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b(__inline__|__inline)\b/) {
2013-09-11 14:23:54 -07:00
if (WARN("INLINE",
"plain inline is preferred over $1\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~ s/\b(__inline__|__inline)\b/inline/;
}
2007-11-28 16:21:06 -08:00
}
2011-01-12 17:00:00 -08:00
# Check for __attribute__ packed, prefer __packed
2013-11-12 15:10:14 -08:00
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
2011-07-25 17:13:25 -07:00
WARN("PREFER_PACKED",
"__packed is preferred over __attribute__((packed))\n" . $herecurr);
2011-01-12 17:00:00 -08:00
}
2011-07-25 17:13:24 -07:00
# Check for __attribute__ aligned, prefer __aligned
2013-11-12 15:10:14 -08:00
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
2011-07-25 17:13:25 -07:00
WARN("PREFER_ALIGNED",
"__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
2011-07-25 17:13:24 -07:00
}
2012-01-10 15:09:52 -08:00
# Check for __attribute__ format(printf, prefer __printf
2013-11-12 15:10:14 -08:00
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
2013-09-11 14:23:54 -07:00
if (WARN("PREFER_PRINTF",
"__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
}
2012-01-10 15:09:52 -08:00
}
2012-03-23 15:02:16 -07:00
# Check for __attribute__ format(scanf, prefer __scanf
2013-11-12 15:10:14 -08:00
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
2013-09-11 14:23:54 -07:00
if (WARN("PREFER_SCANF",
"__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
}
2012-03-23 15:02:16 -07:00
}
2010-03-05 13:43:48 -08:00
# check for sizeof(&)
if ($line =~ /\bsizeof\s*\(\s*\&/) {
2011-07-25 17:13:25 -07:00
WARN("SIZEOF_ADDRESS",
"sizeof(& should be avoided\n" . $herecurr);
2010-03-05 13:43:48 -08:00
}
2012-07-30 14:41:22 -07:00
# check for sizeof without parenthesis
if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) {
2013-09-11 14:23:54 -07:00
if (WARN("SIZEOF_PARENTHESIS",
"sizeof $1 should be sizeof($1)\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
}
2012-07-30 14:41:22 -07:00
}
2011-05-24 17:13:39 -07:00
# check for line continuations in quoted strings with odd counts of "
if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) {
2011-07-25 17:13:25 -07:00
WARN("LINE_CONTINUATIONS",
"Avoid line continuations in quoted strings\n" . $herecurr);
2011-05-24 17:13:39 -07:00
}
2012-12-17 16:02:00 -08: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);
}
2013-04-29 16:18:13 -07:00
# check for seq_printf uses that could be seq_puts
2013-11-12 15:10:07 -08:00
if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) {
2013-04-29 16:18:13 -07:00
my $fmt = get_quoted_string($line, $rawline);
2013-11-12 15:10:07 -08:00
if ($fmt ne "" && $fmt !~ /[^\\]\%/) {
2013-09-11 14:23:54 -07:00
if (WARN("PREFER_SEQ_PUTS",
"Prefer seq_puts to seq_printf\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~ s/\bseq_printf\b/seq_puts/;
}
2013-04-29 16:18:13 -07:00
}
}
2012-01-10 15:09:57 -08:00
# Check for misused memsets
2012-03-23 15:02:16 -07:00
if ($^V && $^V ge 5.10.0 &&
defined $stat &&
2012-01-10 15:09:58 -08:00
$stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/s) {
my $ms_addr = $2;
2012-03-23 15:02:16 -07:00
my $ms_val = $7;
my $ms_size = $12;
2012-01-10 15:09:57 -08:00
if ($ms_size =~ /^(0x|)0$/i) {
ERROR("MEMSET",
2012-01-10 15:09:58 -08:00
"memset to 0' s uses 0 as the 2 nd argument , not the 3 rd \ n " . " $ here \ n$stat \ n ");
2012-01-10 15:09:57 -08:00
} elsif ($ms_size =~ /^(0x|)1$/i) {
WARN(" MEMSET ",
2012-01-10 15:09:58 -08:00
" single byte memset is suspicious . Swapped 2 nd / 3 rd argument ?\ n " . " $ here \ n$stat \ n " ) ;
}
}
2014-01-23 15:54:52 -08:00
# Check for memcpy ( foo , bar , ETH_ALEN ) that could be ether_addr_copy ( foo , bar )
if ( $ ^ V && $ ^ V ge 5.10 .0 &&
$ line =~ /^\+ ( ?:.*? ) \ bmemcpy \ s *\ ( \ s * $ FuncArg \ s * , \ s * $ FuncArg \ s *\ , \ s * ETH_ALEN \ s *\ ) / s ) {
if ( WARN ( "PREFER_ETHER_ADDR_COPY" ,
"Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s /\ bmemcpy \ s *\ ( \ s * $ FuncArg \ s * , \ s * $ FuncArg \ s *\ , \ s * ETH_ALEN \ s *\ ) / ether_addr_copy ( $ 2 , $ 7 ) / ;
}
}
2012-01-10 15:09:58 -08:00
# typecasts on min / max could be min_t / max_t
2012-03-23 15:02:16 -07:00
if ( $ ^ V && $ ^ V ge 5.10 .0 &&
defined $ stat &&
2012-01-10 15:09:58 -08:00
$ stat =~ /^\+ ( ?:.*? ) \ b ( min | max ) \ s *\ ( \ s * $ FuncArg \ s * , \ s * $ FuncArg \ s *\ ) / ) {
2012-03-23 15:02:16 -07:00
if ( defined $ 2 | | defined $ 7 ) {
2012-01-10 15:09:58 -08:00
my $ call = $ 1 ;
my $ cast1 = deparenthesize ( $ 2 ) ;
my $ arg1 = $ 3 ;
2012-03-23 15:02:16 -07:00
my $ cast2 = deparenthesize ( $ 7 ) ;
my $ arg2 = $ 8 ;
2012-01-10 15:09:58 -08:00
my $ cast ;
2012-03-23 15:02:16 -07:00
if ( $ cast1 ne "" && $ cast2 ne "" && $ cast1 ne $ cast2 ) {
2012-01-10 15:09:58 -08: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-10 15:09:57 -08:00
}
}
2012-07-30 14:41:20 -07: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" ) ;
}
}
2013-11-12 15:10:15 -08:00
# check for naked sscanf
if ( $ ^ V && $ ^ V ge 5.10 .0 &&
defined $ stat &&
2014-04-03 14:49:16 -07:00
$ line =~ /\ bsscanf \ b / &&
2013-11-12 15:10:15 -08:00
( $ stat ! ~ / $ Ident \ s *=\ s * sscanf \ s * $ balanced_parens / &&
$ stat ! ~ /\ bsscanf \ s * $ balanced_parens \ s * ( ?: $ Compare ) / &&
$ stat ! ~ / ( ?: $ Compare ) \ s *\ bsscanf \ s * $ balanced_parens / ) ) {
my $ lc = $ stat =~ tr @\ n @@ ;
$ lc = $ lc + $ linenr ;
my $ stat_real = raw_line ( $ linenr , 0 ) ;
for ( my $ count = $ linenr + 1 ; $ count <= $ lc ; $ count ++ ) {
$ stat_real = $ stat_real . "\n" . raw_line ( $ count , 0 ) ;
}
WARN ( "NAKED_SSCANF" ,
"unchecked sscanf return value\n" . "$here\n$stat_real\n" ) ;
}
2013-09-11 14:23:58 -07:00
# check for new externs in . h files .
if ( $ realfile =~ /\. h$ / &&
$ line =~ /^\+\ s * ( extern \ s + ) $ Type \ s * $ Ident \ s *\ ( / s ) {
2013-09-24 15:27:46 -07:00
if ( CHK ( "AVOID_EXTERNS" ,
"extern prototypes should be avoided in .h files\n" . $ herecurr ) &&
2013-09-11 14:23:58 -07:00
$ fix ) {
$ fixed [ $ linenr - 1 ] =~ s / ( . * ) \ bextern \ b \ s * ( . * ) / $ 1 $ 2 / ;
}
}
2007-07-15 23:37:22 -07:00
# check for new externs in . c files .
2008-04-29 00:59:32 -07:00
if ( $ realfile =~ /\. c$ / && defined $ stat &&
2008-06-05 22:46:01 -07:00
$ stat =~ /^.\ s * ( ?: extern \ s + ) ? $ Type \ s + ( $ Ident ) ( \ s * ) \ ( / s )
2008-04-29 00:59:32 -07:00
{
2008-06-05 22:46:01 -07:00
my $ function_name = $ 1 ;
my $ paren_space = $ 2 ;
2008-04-29 00:59:32 -07:00
my $ s = $ stat ;
if ( defined $ cond ) {
substr ( $ s , 0 , length ( $ cond ) , '' ) ;
}
2008-06-05 22:46:01 -07:00
if ( $ s =~ /^\ s * ; / &&
$ function_name ne 'uninitialized_var' )
{
2011-07-25 17:13:25 -07:00
WARN ( "AVOID_EXTERNS" ,
"externs should be avoided in .c files\n" . $ herecurr ) ;
2008-04-29 00:59:32 -07:00
}
if ( $ paren_space =~ /\ n / ) {
2011-07-25 17:13:25 -07:00
WARN ( "FUNCTION_ARGUMENTS" ,
"arguments for function declarations should follow identifier\n" . $ herecurr ) ;
2008-04-29 00:59:32 -07:00
}
2008-04-29 00:59:33 -07:00
} elsif ( $ realfile =~ /\. c$ / && defined $ stat &&
$ stat =~ /^.\ s * extern \ s +/ )
{
2011-07-25 17:13:25 -07:00
WARN ( "AVOID_EXTERNS" ,
"externs should be avoided in .c files\n" . $ herecurr ) ;
2007-07-15 23:37:22 -07:00
}
# checks for new _ _ setup 's
if ($rawline =~ /\b__setup\("([^"]*)"/) {
my $name = $1;
if (!grep(/$name/, @setup_docs)) {
2011-07-25 17:13:25 -07:00
CHK("UNDOCUMENTED_SETUP",
"__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
2007-07-15 23:37:22 -07:00
}
2007-06-23 17:16:34 -07:00
}
2007-10-16 23:29:38 -07:00
# check for pointless casting of kmalloc return
2011-01-12 16:59:56 -08:00
if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) {
2011-07-25 17:13:25 -07:00
WARN("UNNECESSARY_CASTS",
"unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
2007-10-16 23:29:38 -07:00
}
2008-02-08 04:22:03 -08:00
2013-07-03 15:05:21 -07:00
# alloc style
# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
if ($^V && $^V ge 5.10.0 &&
$line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
CHK("ALLOC_SIZEOF_STRUCT",
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
}
2013-04-29 16:18:12 -07:00
# check for krealloc arg reuse
if ($^V && $^V ge 5.10.0 &&
$line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) {
WARN("KREALLOC_ARG_REUSE",
"Reusing the krealloc arg is almost always a bug\n" . $herecurr);
}
2013-02-21 16:44:18 -08: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);
}
2014-01-23 15:54:42 -08:00
# check for GFP_NOWAIT use
if ($line =~ /\b__GFP_NOFAIL\b/) {
WARN("__GFP_NOFAIL",
"Use of __GFP_NOFAIL is deprecated, no new users should be added\n" . $herecurr);
}
2011-01-12 16:59:56 -08:00
# check for multiple semicolons
if ($line =~ /;\s*;\s*$/) {
2013-09-11 14:23:54 -07:00
if (WARN("ONE_SEMICOLON",
"Statements terminations use 1 semicolon\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~ s/(\s*;\s*){2,}$/;/g;
}
2012-12-17 16:02:01 -08:00
}
2014-01-23 15:54:43 -08:00
# check for case / default statements not preceeded by break/fallthrough/switch
if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) {
my $has_break = 0;
my $has_statement = 0;
my $count = 0;
my $prevline = $linenr;
while ($prevline > 1 && $count < 3 && !$has_break) {
$prevline--;
my $rline = $rawlines[$prevline - 1];
my $fline = $lines[$prevline - 1];
last if ($fline =~ /^\@\@/);
next if ($fline =~ /^\-/);
next if ($fline =~ /^.(?:\s*(?:case\s+(?:$Ident|$Constant)[\s$;]*|default):[\s$;]*)*$/);
$has_break = 1 if ($rline =~ /fall[\s_-]*(through|thru)/i);
next if ($fline =~ /^.[\s$;]*$/);
$has_statement = 1;
$count++;
$has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|return\b|goto\b|continue\b)/);
}
if (!$has_break && $has_statement) {
WARN("MISSING_BREAK",
"Possible switch case/default not preceeded by break or fallthrough comment\n" . $herecurr);
}
}
2012-12-17 16:02:01 -08:00
# 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-12 16:59:56 -08:00
}
2008-02-08 04:22:03 -08:00
# check for gcc specific __FUNCTION__
2013-09-11 14:23:54 -07:00
if ($line =~ /\b__FUNCTION__\b/) {
if (WARN("USE_FUNC",
"__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) &&
$fix) {
$fixed[$linenr - 1] =~ s/\b__FUNCTION__\b/__func__/g;
}
2008-02-08 04:22:03 -08:00
}
2008-03-28 14:15:58 -07:00
2012-03-23 15:02:20 -07: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);
}
2013-07-03 15:05:30 -07:00
# check for comparisons against true and false
if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) {
my $lead = $1;
my $arg = $2;
my $test = $3;
my $otype = $4;
my $trail = $5;
my $op = "!";
($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i);
my $type = lc($otype);
if ($type =~ /^(?:true|false)$/) {
if (("$test" eq "==" && "$type" eq "true") ||
("$test" eq "!=" && "$type" eq "false")) {
$op = "";
}
CHK("BOOL_COMPARISON",
"Using comparison to $otype is error prone\n" . $herecurr);
## maybe suggesting a correct construct would better
## "Using comparison to $otype is error prone. Perhaps use ' $ { lead } $ { op } $ { arg } $ { trail } '\n" . $herecurr);
}
}
2010-09-07 14:34:01 +00:00
# check for semaphores initialized locked
if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
2011-07-25 17:13:25 -07:00
WARN("CONSIDER_COMPLETION",
"consider using a completion\n" . $herecurr);
2008-03-28 14:15:58 -07:00
}
2012-03-23 15:02:20 -07:00
2011-10-31 17:13:10 -07:00
# recommend kstrto* over simple_strto* and strict_strto*
if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) {
2011-07-25 17:13:25 -07:00
WARN("CONSIDER_KSTRTO",
2011-10-31 17:13:10 -07:00
"$1 is obsolete, use k$3 instead\n" . $herecurr);
2008-03-28 14:15:58 -07:00
}
2012-03-23 15:02:20 -07:00
2008-07-23 21:28:57 -07:00
# check for __initcall(), use device_initcall() explicitly please
if ($line =~ /^.\s*__initcall\s*\(/) {
2011-07-25 17:13:25 -07:00
WARN("USE_DEVICE_INITCALL",
"please use device_initcall() instead of __initcall()\n" . $herecurr);
2008-07-23 21:28:57 -07:00
}
2012-03-23 15:02:20 -07:00
2010-03-05 13:43:53 -08: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-15 13:51:07 -08:00
if ($line !~ /\bconst\b/ &&
2010-03-05 13:43:53 -08:00
$line =~ /\bstruct\s+($struct_ops)\b/) {
2011-07-25 17:13:25 -07:00
WARN("CONST_STRUCT",
"struct $1 should normally be const\n" .
2009-01-15 13:51:07 -08:00
$herecurr);
2009-01-06 14:41:29 -08:00
}
2008-03-28 14:15:58 -07: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-05 22:46:01 -07:00
$line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
$line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
2008-04-29 00:59:32 -07:00
$line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
$line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
$line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
2008-03-28 14:15:58 -07:00
{
2011-07-25 17:13:25 -07: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-28 14:15:58 -07:00
}
2008-04-29 00:59:33 -07:00
2013-11-12 15:10:09 -08:00
# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong.
if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) {
ERROR("DEFINE_ARCH_HAS",
"#define of ' $ 1 ' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr);
}
2008-04-29 00:59:33 -07:00
# check for %L{u,d,i} in strings
my $string;
while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
$string = substr($rawline, $-[1], $+[1] - $-[1]);
2008-10-15 22:02:23 -07:00
$string =~ s/%%/__/g;
2008-04-29 00:59:33 -07:00
if ($string =~ /(?<!%)%L[udi]/) {
2011-07-25 17:13:25 -07:00
WARN("PRINTF_L",
"\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
2008-04-29 00:59:33 -07:00
last;
}
}
2009-01-06 14:41:16 -08:00
# whine mightly about in_atomic
if ($line =~ /\bin_atomic\s*\(/) {
if ($realfile =~ m@^drivers/@) {
2011-07-25 17:13:25 -07:00
ERROR("IN_ATOMIC",
"do not use in_atomic in drivers\n" . $herecurr);
2009-02-27 14:03:05 -08:00
} elsif ($realfile !~ m@^kernel/@) {
2011-07-25 17:13:25 -07:00
WARN("IN_ATOMIC",
"use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
2009-01-06 14:41:16 -08:00
}
}
2010-03-19 01:37:42 +01: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-25 17:13:25 -07:00
ERROR("LOCKDEP",
"lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
2010-03-19 01:37:42 +01:00
}
}
2011-01-12 16:59:59 -08:00
if ($line =~ /debugfs_create_file.*S_IWUGO/ ||
$line =~ /DEVICE_ATTR.*S_IWUGO/ ) {
2011-07-25 17:13:25 -07:00
WARN("EXPORTED_WORLD_WRITABLE",
"Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
2011-01-12 16:59:59 -08:00
}
2014-04-03 14:49:13 -07:00
2014-04-03 14:49:24 -07:00
# Mode permission misuses where it seems decimal should be octal
# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
if ($^V && $^V ge 5.10.0 &&
$line =~ /$mode_perms_search/) {
foreach my $entry (@mode_permission_funcs) {
my $func = $entry->[0];
my $arg_pos = $entry->[1];
2014-04-03 14:49:13 -07:00
2014-04-03 14:49:24 -07:00
my $skip_args = "";
if ($arg_pos > 1) {
$arg_pos--;
$skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
}
my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]";
if ($line =~ /$test/) {
my $val = $1;
$val = $6 if ($skip_args ne "");
2014-04-03 14:49:13 -07:00
2014-04-03 14:49:24 -07:00
if ($val !~ /^0$/ &&
(($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
length($val) ne 4)) {
ERROR("NON_OCTAL_PERMISSIONS",
"Use 4 digit octal (0777) not decimal permissions\n" . $herecurr);
}
2014-04-03 14:49:13 -07:00
}
}
}
2008-02-08 04:22:03 -08: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 00:46:48 -07:00
}
2007-11-28 16:21:06 -08: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-25 17:13:25 -07:00
ERROR("NOT_UNIFIED_DIFF",
"Does not appear to be a unified-diff format patch\n");
2007-06-01 00:46:48 -07:00
}
if ($is_patch && $chk_signoff && $signoff == 0) {
2011-07-25 17:13:25 -07:00
ERROR("MISSING_SIGN_OFF",
"Missing Signed-off-by: line(s)\n");
2007-06-01 00:46:48 -07:00
}
2007-11-28 16:21:06 -08:00
print report_dump();
2008-02-08 04:22:03 -08:00
if ($summary && !($clean == 1 && $quiet == 1)) {
print "$filename " if ($summary_file);
2007-11-28 16:21:06 -08: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 01:48:34 -07:00
}
2007-11-28 16:21:06 -08:00
2010-10-26 14:23:12 -07:00
if ($quiet == 0) {
2012-03-23 15:02:16 -07: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-26 14:23:12 -07: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-22 16:34:43 -07:00
$rpt_cleaners = 0;
2010-10-26 14:23:12 -07:00
}
}
2013-09-11 14:23:59 -07:00
hash_show_words(\%use_type, "Used");
hash_show_words(\%ignore_type, "Ignored");
2011-07-25 17:13:25 -07:00
2013-07-03 15:05:31 -07:00
if ($clean == 0 && $fix && "@rawlines" ne "@fixed") {
2014-01-23 15:54:44 -08:00
my $newfile = $filename;
$newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace);
2013-07-03 15:05:31 -07:00
my $linecount = 0;
my $f;
open($f, ' > ', $newfile)
or die "$P: Can' t open $ newfile for write \ n " ;
foreach my $ fixed_line ( @ fixed ) {
$ linecount ++ ;
if ( $ file ) {
if ( $ linecount > 3 ) {
$ fixed_line =~ s /^\+// ;
print $ f $ fixed_line . "\n" ;
}
} else {
print $ f $ fixed_line . "\n" ;
}
}
close ( $ f ) ;
if ( ! $ quiet ) {
print << "EOM" ;
Wrote EXPERIMENTAL -- fix correction ( s ) to '$newfile'
Do _ NOT_ trust the results written to this file .
Do _ NOT_ submit these changes without inspecting them for correctness .
This EXPERIMENTAL file is simply a convenience to help rewrite patches .
No warranties , expressed or implied . . .
EOM
}
}
2007-06-01 00:46:48 -07:00
if ( $ clean == 1 && $ quiet == 0 ) {
2008-02-08 04:20:54 -08:00
print "$vname has no obvious style problems and is ready for submission.\n"
2007-06-01 00:46:48 -07:00
}
if ( $ clean == 0 && $ quiet == 0 ) {
2011-07-25 17:13:25 -07: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 00:46:48 -07:00
}
2008-02-08 04:22:03 -08:00
2007-06-01 00:46:48 -07:00
return $ clean ;
}