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 { \*\= | /= | %=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
2009-01-06 14:41:24 -08: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 ],
);
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 ));
$ string =~ s@^\s*\ ( \s*@@g ;
$ string =~ s@\s*\ ) \s* $ @@g ;
$ string =~ s@\s+@ @g ;
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 {
2013-09-11 14:23:59 -07:00
return defined $ use_type { $ _ [ 0 ]} if ( scalar keys %use_type > 0);
return ! defined $ ignore_type { $ _ [ 0 ]};
2011-07-25 17:13:25 -07:00
}
2007-07-19 01:48:34 -07:00
sub report {
2011-07-25 17:13:25 -07:00
if (! show_type ( $ _ [ 1 ]) ||
( defined $ tst_only && $ _ [ 2 ] ! ~ /\ 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 ) {
$ line = "$prefix$_[0]:$_[1]: $_[2]\n" ;
} else {
$ line = "$prefix$_[0]: $_[2]\n" ;
}
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
}
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 {
2011-07-25 17:13:25 -07:00
if ( report ( "ERROR" , $ _ [ 0 ], $ _ [ 1 ])) {
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 {
2011-07-25 17:13:25 -07:00
if ( report ( "WARNING" , $ _ [ 0 ], $ _ [ 1 ])) {
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 {
2011-07-25 17:13:25 -07:00
if ( $ check && report ( "CHECK" , $ _ [ 0 ], $ _ [ 1 ])) {
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
if ( defined $ root && $ realfile =~ /\.dts / &&
$ rawline =~ /^\+\s * compatible\s*=/ ) {
my @compats = $ rawline =~ /\ " ([ a - zA - Z0 - 9 \-\ , \.\+ _ ] + ) \ "/g;
foreach my $compat (@compats) {
my $compat2 = $compat;
my $dt_path = $root . " / Documentation / devicetree / bindings/ " ;
$ 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 );
}
my $ vendor = $ compat ;
my $ vendor_path = $ dt_path . "vendor-prefixes.txt" ;
next if (! - f $ vendor_path );
$ vendor =~ s/^ ([ a - zA - Z0 - 9 ] + ) \ ,. */ $ 1 / ;
` grep - Eq "$vendor" $ vendor_path ` ;
if ( $ ? >> 8 ) {
WARN ( "UNDOCUMENTED_DT_STRING" ,
"DT compatible string vendor \"$vendor\" appears un-documented -- check $vendor_path\n" . $ herecurr );
}
}
}
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 ] * $ / &&
$ rawline =~ /^\+ [ \t ] *\*/ ) {
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-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" ,
2012-10-04 17:13:32 -07:00
"Prefer netdev_$level2(netdev, ... 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
}
2008-06-05 22:46:01 -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 &&
$stat =~ /^.\s*return\s*$balanced_parens\s*;\s*$/) {
2011-07-25 17:13:25 -07:00
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/ ;
}
}
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 =~ /^ ( 0 x |) 0 $ / i ) {
ERROR ( "MEMSET" ,
2012-01-10 15:09:58 -08:00
"memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n" );
2012-01-10 15:09:57 -08:00
} elsif ( $ ms_size =~ /^ ( 0 x |) 1 $ / i ) {
WARN ( "MEMSET" ,
2012-01-10 15:09:58 -08:00
"single byte memset is suspicious. Swapped 2nd/3rd 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 &&
$ stat =~ /\bsscanf\b / &&
( $ 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
foreach my $entry (@mode_permission_funcs) {
my $func = $entry->[0];
my $arg_pos = $entry->[1];
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 ($^V && $^V ge 5.10.0 &&
$line =~ /$test/) {
my $val = $1;
$val = $6 if ($skip_args ne "");
if ($val =~ /^$Int$/ && $val !~ /^$Octal$/) {
ERROR("NON_OCTAL_PERMISSIONS",
"Use octal not decimal permissions\n" . $herecurr);
}
}
}
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 ;
}