2007-06-01 11:46:48 +04:00
#!/usr/bin/perl -w
2010-01-13 00:59:52 +03:00
# (c) 2001, Dave Jones. (the file handling bit)
2007-06-09 00:47:06 +04:00
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
2009-01-07 01:41:23 +03:00
# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
2010-10-27 01:23:17 +04:00
# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
2007-06-01 11:46:48 +04:00
# Licensed under the terms of the GNU GPL License version 2
use strict ;
my $ P = $ 0 ;
2007-06-09 00:47:06 +04:00
$ P =~ s@.*/@@g ;
2007-06-01 11:46:48 +04:00
2010-10-27 01:23:19 +04:00
my $ V = '0.31' ;
2007-06-01 11:46:48 +04:00
use Getopt::Long qw( :config no_auto_abbrev ) ;
my $ quiet = 0 ;
my $ tree = 1 ;
my $ chk_signoff = 1 ;
my $ chk_patch = 1 ;
2008-03-29 00:15:58 +03:00
my $ tst_only ;
2007-10-18 14:05:08 +04:00
my $ emacs = 0 ;
2007-11-29 03:21:06 +03:00
my $ terse = 0 ;
2007-10-18 14:05:08 +04:00
my $ file = 0 ;
my $ check = 0 ;
2007-11-29 03:21:06 +03:00
my $ summary = 1 ;
my $ mailback = 0 ;
2008-02-08 15:22:03 +03:00
my $ summary_file = 0 ;
2007-10-18 14:05:08 +04:00
my $ root ;
2008-02-08 15:20:54 +03:00
my % debug ;
2009-09-22 04:04:37 +04:00
my $ help = 0 ;
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
- - root = PATH PATH to the kernel tree root
- - no - summary suppress the per - file summary
- - mailback only produce a report in case of warnings / errors
- - summary - file include the filename in summary
- - debug KEY = [ 0 | 1 ] turn on / off debugging of KEY , where KEY is one of
'values' , 'possible' , 'type' , and 'attr' ( default
is all off )
- - test - only = WORD report only warnings / errors containing WORD
literally
- h , - - help , - - version display this help and exit
When FILE is - read standard input .
EOM
exit ( $ exitcode ) ;
}
2007-06-01 11:46:48 +04:00
GetOptions (
2007-10-18 14:05:08 +04:00
'q|quiet+' = > \ $ quiet ,
2007-06-01 11:46:48 +04:00
'tree!' = > \ $ tree ,
'signoff!' = > \ $ chk_signoff ,
'patch!' = > \ $ chk_patch ,
2007-10-18 14:05:08 +04:00
'emacs!' = > \ $ emacs ,
2007-11-29 03:21:06 +03:00
'terse!' = > \ $ terse ,
2009-09-22 04:04:37 +04:00
'f|file!' = > \ $ file ,
2007-10-18 14:05:08 +04:00
'subjective!' = > \ $ check ,
'strict!' = > \ $ check ,
'root=s' = > \ $ root ,
2007-11-29 03:21:06 +03:00
'summary!' = > \ $ summary ,
'mailback!' = > \ $ mailback ,
2008-02-08 15:22:03 +03:00
'summary-file!' = > \ $ summary_file ,
2008-02-08 15:20:54 +03:00
'debug=s' = > \ % debug ,
2008-03-29 00:15:58 +03:00
'test-only=s' = > \ $ tst_only ,
2009-09-22 04:04:37 +04:00
'h|help' = > \ $ help ,
'version' = > \ $ help
) or help ( 1 ) ;
help ( 0 ) if ( $ help ) ;
2007-06-01 11:46:48 +04:00
my $ exit = 0 ;
if ( $# ARGV < 0 ) {
2009-09-22 04:04:37 +04:00
print "$P: no input files\n" ;
2007-06-01 11:46:48 +04:00
exit ( 1 ) ;
}
2008-02-08 15:20:54 +03:00
my $ dbg_values = 0 ;
my $ dbg_possible = 0 ;
2008-07-24 08:29:06 +04:00
my $ dbg_type = 0 ;
2008-10-16 09:02:17 +04:00
my $ dbg_attr = 0 ;
2008-02-08 15:20:54 +03:00
for my $ key ( keys % debug ) {
2009-01-07 01:41:30 +03:00
## no critic
eval "\${dbg_$key} = '$debug{$key}';" ;
die "$@" if ( $@ ) ;
2008-02-08 15:20:54 +03:00
}
2010-10-27 01:23:12 +04:00
my $ rpt_cleaners = 0 ;
2007-11-29 03:21:06 +03:00
if ( $ terse ) {
$ emacs = 1 ;
$ quiet + + ;
}
2007-10-18 14:05:08 +04:00
if ( $ tree ) {
if ( defined $ root ) {
if ( ! top_of_kernel_tree ( $ root ) ) {
die "$P: $root: --root does not point at a valid tree\n" ;
}
} else {
if ( top_of_kernel_tree ( '.' ) ) {
$ root = '.' ;
} elsif ( $ 0 =~ m @(.*)/scripts/[^/]*$@ &&
top_of_kernel_tree ( $ 1 ) ) {
$ root = $ 1 ;
}
}
if ( ! defined $ root ) {
print "Must be run from the top-level dir. of a kernel tree\n" ;
exit ( 2 ) ;
}
2007-06-01 11:46:48 +04:00
}
2007-10-18 14:05:08 +04:00
my $ emitted_corrupt = 0 ;
2009-10-27 02:50:14 +03:00
our $ Ident = qr{
[ A - Za - z_ ] [ A - Za - z \ d_ ] *
( ? : \ s * \ #\#\s*[A-Za-z_][A-Za-z\d_]*)*
} x ;
2007-10-18 14:05:08 +04:00
our $ Storage = qr{ extern|static|asmlinkage } ;
our $ Sparse = qr{
__user |
__kernel |
__force |
__iomem |
__must_check |
__init_refok |
2009-02-28 01:03:08 +03:00
__kprobes |
__ref
2007-10-18 14:05:08 +04:00
} x ;
2010-03-06 00:43:51 +03:00
# Notes to $Attribute:
# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
2007-10-18 14:05:08 +04:00
our $ Attribute = qr{
const |
2010-10-27 01:23:16 +04:00
__percpu |
__nocast |
__safe |
__bitwise__ |
__packed__ |
__packed2__ |
__naked |
__maybe_unused |
__always_unused |
__noreturn |
__used |
__cold |
__noclone |
__deprecated |
2007-10-18 14:05:08 +04:00
__read_mostly |
__kprobes |
2010-03-06 00:43:51 +03:00
__ ( ? : mem | cpu | dev | ) ( ? : initdata | initconst | init \ b ) |
2008-10-16 09:02:18 +04:00
____cacheline_aligned |
____cacheline_aligned_in_smp |
2009-01-07 01:41:18 +03:00
____cacheline_internodealigned_in_smp |
__weak
2007-10-18 14:05:08 +04:00
} x ;
2008-06-06 09:46:01 +04:00
our $ Modifier ;
2007-10-18 14:05:08 +04:00
our $ Inline = qr{ inline|__always_inline|noinline } ;
our $ Member = qr{ ->$Ident| \ .$Ident| \ [[^]]* \ ] } ;
our $ Lval = qr{ $Ident(?:$Member)* } ;
our $ Constant = qr{ (?:[0-9]+|0x[0-9a-fA-F]+)[UL]* } ;
our $ Assignment = qr{ (?: \ * \ =|/=|%=| \ +=|-=|<<=|>>=|&=| \ ^=| \ |=|=) } ;
2009-01-07 01:41:24 +03:00
our $ Compare = qr{ <=|>=|==|!=|<|> } ;
2007-10-18 14:05:08 +04:00
our $ Operators = qr{
<=|> = |= = | != |
= > | - > | <<|> > | <|> | ! | ~ |
2008-02-08 15:20:54 +03:00
&& | \ | \ || , | \ ^ | \ + \ + | - - | & | \ || \ + | - | \ * | \ / | %
2007-10-18 14:05:08 +04:00
} x ;
2007-11-29 03:21:06 +03:00
our $ NonptrType ;
our $ Type ;
our $ Declare ;
2008-04-29 11:59:32 +04:00
our $ UTF8 = qr {
[ \ x09 \ x0A \ x0D \ x20 - \ x7E ] # ASCII
| [ \ xC2 - \ xDF ] [ \ x80 - \ xBF ] # non-overlong 2-byte
| \ 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 ;
2008-10-16 09:02:32 +04:00
our $ typeTypedefs = qr{ (?x:
2009-09-22 04:04:38 +04:00
( ? : __ ) ? ( ? : u | s | be | le ) ( ? : 8 | 16 | 32 | 64 ) |
2008-10-16 09:02:32 +04:00
atomic_t
) } ;
2010-03-06 00:43:51 +03:00
our $ logFunctions = qr{ (?x:
printk |
pr_ ( debug | dbg | vdbg | devel | info | warning | err | notice | alert | crit | emerg | cont ) |
2010-08-10 04:21:01 +04:00
( dev | netdev | netif ) _ ( printk | dbg | vdbg | info | warn | err | notice | alert | crit | emerg | WARN ) |
2010-03-06 00:43:51 +03:00
WARN |
panic
) } ;
2007-11-29 03:21:06 +03:00
our @ typeList = (
qr{ void } ,
2008-06-06 09:46:01 +04:00
qr{ (?:unsigned \ s+)?char } ,
qr{ (?:unsigned \ s+)?short } ,
qr{ (?:unsigned \ s+)?int } ,
qr{ (?:unsigned \ s+)?long } ,
qr{ (?:unsigned \ s+)?long \ s+int } ,
qr{ (?:unsigned \ s+)?long \ s+long } ,
qr{ (?:unsigned \ s+)?long \ s+long \ s+int } ,
2007-11-29 03:21:06 +03:00
qr{ unsigned } ,
qr{ float } ,
qr{ double } ,
qr{ bool } ,
qr{ struct \ s+$Ident } ,
qr{ union \ s+$Ident } ,
qr{ enum \ s+$Ident } ,
qr{ $ { Ident } _t } ,
qr{ $ { Ident } _handler } ,
qr{ $ { Ident } _handler_fn } ,
) ;
2008-06-06 09:46:01 +04:00
our @ modifierList = (
qr{ fastcall } ,
) ;
2007-11-29 03:21:06 +03:00
2010-08-10 04:20:57 +04:00
our $ allowed_asm_includes = qr{ (?x:
irq |
memory
) } ;
# memory.h: ARM has a custom one
2007-11-29 03:21:06 +03:00
sub build_types {
2008-07-24 08:29:07 +04:00
my $ mods = "(?x: \n" . join ( "|\n " , @ modifierList ) . "\n)" ;
my $ all = "(?x: \n" . join ( "|\n " , @ typeList ) . "\n)" ;
2008-07-24 08:28:57 +04:00
$ Modifier = qr{ (?:$Attribute|$Sparse|$mods) } ;
2007-11-29 03:21:06 +03:00
$ NonptrType = qr{
2008-07-24 08:29:07 +04:00
( ? : $ Modifier \ s + | const \ s + ) *
2008-03-05 01:28:20 +03:00
( ? :
2008-06-06 09:46:01 +04:00
( ? : typeof | __typeof__ ) \ s * \ ( \ s * \ ** \ s * $ Ident \ s * \ ) |
2008-10-16 09:02:32 +04:00
( ? : $ typeTypedefs \ b ) |
2008-06-06 09:46:01 +04:00
( ? : $ { all } \ b )
2008-03-05 01:28:20 +03:00
)
2008-07-24 08:28:57 +04:00
( ? : \ s + $ Modifier | \ s + const ) *
2007-11-29 03:21:06 +03:00
} x ;
$ Type = qr{
2008-06-06 09:46:01 +04:00
$ NonptrType
2009-01-07 01:41:21 +03:00
( ? : [ \ s\*]+\s*const|[\s \ * ] + | ( ? : \ s * \ [ \ s * \ ] ) + ) ?
2008-07-24 08:28:57 +04:00
( ? : \ s + $ Inline | \ s + $ Modifier ) *
2007-11-29 03:21:06 +03:00
} x ;
$ Declare = qr{ (?:$Storage \ s+)?$Type } ;
}
build_types ( ) ;
2007-10-18 14:05:08 +04:00
$ chk_signoff = 0 if ( $ file ) ;
2007-06-09 00:46:39 +04:00
my @ dep_includes = ( ) ;
my @ dep_functions = ( ) ;
2007-10-18 14:05:08 +04:00
my $ removal = "Documentation/feature-removal-schedule.txt" ;
if ( $ tree && - f "$root/$removal" ) {
2009-01-07 01:41:30 +03:00
open ( my $ REMOVE , '<' , "$root/$removal" ) ||
2007-10-18 14:05:08 +04:00
die "$P: $removal: open failed - $!\n" ;
2009-01-07 01:41:30 +03:00
while ( <$REMOVE> ) {
2007-07-19 12:48:34 +04:00
if ( /^Check:\s+(.*\S)/ ) {
for my $ entry ( split ( /[, ]+/ , $ 1 ) ) {
if ( $ entry =~ m @include/(.*)@ ) {
2007-06-09 00:46:39 +04:00
push ( @ dep_includes , $ 1 ) ;
2007-07-19 12:48:34 +04:00
} elsif ( $ entry !~ m @/@ ) {
push ( @ dep_functions , $ entry ) ;
}
2007-06-09 00:46:39 +04:00
}
2007-06-01 11:46:48 +04:00
}
}
2009-01-07 01:41:30 +03:00
close ( $ REMOVE ) ;
2007-06-01 11:46:48 +04:00
}
2007-06-09 00:47:06 +04:00
my @ rawlines = ( ) ;
2008-02-08 15:20:54 +03:00
my @ lines = ( ) ;
my $ vname ;
2007-10-18 14:05:08 +04:00
for my $ filename ( @ ARGV ) {
2009-01-07 01:41:30 +03:00
my $ FILE ;
2007-10-18 14:05:08 +04:00
if ( $ file ) {
2009-01-07 01:41:30 +03:00
open ( $ FILE , '-|' , "diff -u /dev/null $filename" ) ||
2007-10-18 14:05:08 +04:00
die "$P: $filename: diff failed - $!\n" ;
2009-01-07 01:41:30 +03:00
} elsif ( $ filename eq '-' ) {
open ( $ FILE , '<&STDIN' ) ;
2007-10-18 14:05:08 +04:00
} else {
2009-01-07 01:41:30 +03:00
open ( $ FILE , '<' , "$filename" ) ||
2007-10-18 14:05:08 +04:00
die "$P: $filename: open failed - $!\n" ;
2007-06-01 11:46:48 +04:00
}
2008-02-08 15:20:54 +03:00
if ( $ filename eq '-' ) {
$ vname = 'Your patch' ;
} else {
$ vname = $ filename ;
}
2009-01-07 01:41:30 +03:00
while ( <$FILE> ) {
2007-10-18 14:05:08 +04:00
chomp ;
push ( @ rawlines , $ _ ) ;
}
2009-01-07 01:41:30 +03:00
close ( $ FILE ) ;
2008-02-08 15:20:54 +03:00
if ( ! process ( $ filename ) ) {
2007-10-18 14:05:08 +04:00
$ exit = 1 ;
}
@ rawlines = ( ) ;
2008-02-08 15:22:03 +03:00
@ lines = ( ) ;
2007-06-01 11:46:48 +04:00
}
exit ( $ exit ) ;
sub top_of_kernel_tree {
2007-10-18 14:05:08 +04:00
my ( $ root ) = @ _ ;
my @ tree_check = (
"COPYING" , "CREDITS" , "Kbuild" , "MAINTAINERS" , "Makefile" ,
"README" , "Documentation" , "arch" , "include" , "drivers" ,
"fs" , "init" , "ipc" , "kernel" , "lib" , "scripts" ,
) ;
foreach my $ check ( @ tree_check ) {
if ( ! - e $ root . '/' . $ check ) {
return 0 ;
}
2007-06-01 11:46:48 +04:00
}
2007-10-18 14:05:08 +04:00
return 1 ;
2007-06-01 11:46:48 +04:00
}
sub expand_tabs {
my ( $ str ) = @ _ ;
my $ res = '' ;
my $ n = 0 ;
for my $ c ( split ( // , $ str ) ) {
if ( $ c eq "\t" ) {
$ res . = ' ' ;
$ n + + ;
for ( ; ( $ n % 8 ) != 0 ; $ n + + ) {
$ res . = ' ' ;
}
next ;
}
$ res . = $ c ;
$ n + + ;
}
return $ res ;
}
2007-10-18 14:05:08 +04:00
sub copy_spacing {
2008-03-29 00:15:58 +03:00
( my $ res = shift ) =~ tr /\t/ / c ;
2007-10-18 14:05:08 +04:00
return $ res ;
}
2007-06-01 11:46:48 +04:00
2007-06-09 00:46:39 +04:00
sub line_stats {
my ( $ line ) = @ _ ;
# Drop the diff line leader and expand tabs
$ line =~ s/^.// ;
$ line = expand_tabs ( $ line ) ;
# Pick the indent from the front of the line.
my ( $ white ) = ( $ line =~ /^(\s*)/ ) ;
return ( length ( $ line ) , length ( $ white ) ) ;
}
2008-03-29 00:15:58 +03:00
my $ sanitise_quote = '' ;
sub sanitise_line_reset {
my ( $ in_comment ) = @ _ ;
if ( $ in_comment ) {
$ sanitise_quote = '*/' ;
} else {
$ sanitise_quote = '' ;
}
}
2007-06-09 00:47:06 +04:00
sub sanitise_line {
my ( $ line ) = @ _ ;
my $ res = '' ;
my $ l = '' ;
2008-02-08 15:20:54 +03:00
my $ qlen = 0 ;
2008-03-29 00:15:58 +03:00
my $ off = 0 ;
my $ c ;
2007-06-09 00:47:06 +04:00
2008-03-29 00:15:58 +03:00
# Always copy over the diff marker.
$ res = substr ( $ line , 0 , 1 ) ;
for ( $ off = 1 ; $ off < length ( $ line ) ; $ off + + ) {
$ c = substr ( $ line , $ off , 1 ) ;
# Comments we are wacking completly including the begin
# and end, all to $;.
if ( $ sanitise_quote eq '' && substr ( $ line , $ off , 2 ) eq '/*' ) {
$ sanitise_quote = '*/' ;
substr ( $ res , $ off , 2 , "$;$;" ) ;
$ off + + ;
next ;
2007-06-09 00:47:06 +04:00
}
2008-10-16 09:02:26 +04:00
if ( $ sanitise_quote eq '*/' && substr ( $ line , $ off , 2 ) eq '*/' ) {
2008-03-29 00:15:58 +03:00
$ sanitise_quote = '' ;
substr ( $ res , $ off , 2 , "$;$;" ) ;
$ off + + ;
next ;
2008-02-08 15:20:54 +03:00
}
2009-09-22 04:04:35 +04:00
if ( $ sanitise_quote eq '' && substr ( $ line , $ off , 2 ) eq '//' ) {
$ sanitise_quote = '//' ;
substr ( $ res , $ off , 2 , $ sanitise_quote ) ;
$ off + + ;
next ;
}
2008-03-29 00:15:58 +03:00
# A \ in a string means ignore the next character.
if ( ( $ sanitise_quote eq "'" || $ sanitise_quote eq '"' ) &&
$ c eq "\\" ) {
substr ( $ res , $ off , 2 , 'XX' ) ;
$ off + + ;
next ;
2007-06-09 00:47:06 +04:00
}
2008-03-29 00:15:58 +03:00
# Regular quotes.
if ( $ c eq "'" || $ c eq '"' ) {
if ( $ sanitise_quote eq '' ) {
$ sanitise_quote = $ c ;
2007-06-09 00:47:06 +04:00
2008-03-29 00:15:58 +03:00
substr ( $ res , $ off , 1 , $ c ) ;
next ;
} elsif ( $ sanitise_quote eq $ c ) {
$ sanitise_quote = '' ;
}
}
2007-06-09 00:47:06 +04:00
2009-01-07 01:41:20 +03:00
#print "c<$c> SQ<$sanitise_quote>\n";
2008-03-29 00:15:58 +03:00
if ( $ off != 0 && $ sanitise_quote eq '*/' && $ c ne "\t" ) {
substr ( $ res , $ off , 1 , $; ) ;
2009-09-22 04:04:35 +04:00
} elsif ( $ off != 0 && $ sanitise_quote eq '//' && $ c ne "\t" ) {
substr ( $ res , $ off , 1 , $; ) ;
2008-03-29 00:15:58 +03:00
} elsif ( $ off != 0 && $ sanitise_quote && $ c ne "\t" ) {
substr ( $ res , $ off , 1 , 'X' ) ;
} else {
substr ( $ res , $ off , 1 , $ c ) ;
}
2008-02-08 15:20:54 +03:00
}
2009-09-22 04:04:35 +04:00
if ( $ sanitise_quote eq '//' ) {
$ sanitise_quote = '' ;
}
2008-02-08 15:20:54 +03:00
# The pathname on a #include may be surrounded by '<' and '>'.
2008-06-06 09:46:01 +04:00
if ( $ res =~ /^.\s*\#\s*include\s+\<(.*)\>/ ) {
2008-02-08 15:20:54 +03:00
my $ clean = 'X' x length ( $ 1 ) ;
$ res =~ s@\<.*\>@<$clean>@ ;
# The whole of a #error is a string.
2008-06-06 09:46:01 +04:00
} elsif ( $ res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/ ) {
2008-02-08 15:20:54 +03:00
my $ clean = 'X' x length ( $ 1 ) ;
2008-06-06 09:46:01 +04:00
$ res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@ ;
2008-02-08 15:20:54 +03:00
}
2007-06-09 00:47:06 +04:00
return $ res ;
}
2007-11-29 03:21:06 +03:00
sub ctx_statement_block {
my ( $ linenr , $ remain , $ off ) = @ _ ;
my $ line = $ linenr - 1 ;
my $ blk = '' ;
my $ soff = $ off ;
my $ coff = $ off - 1 ;
2008-03-29 00:15:58 +03:00
my $ coff_set = 0 ;
2007-11-29 03:21:06 +03:00
2008-02-08 15:22:03 +03:00
my $ loff = 0 ;
2007-11-29 03:21:06 +03:00
my $ type = '' ;
my $ level = 0 ;
2009-01-16 00:51:04 +03:00
my @ stack = ( ) ;
2008-03-05 01:28:20 +03:00
my $ p ;
2007-11-29 03:21:06 +03:00
my $ c ;
my $ len = 0 ;
2008-02-08 15:22:03 +03:00
my $ remainder ;
2007-11-29 03:21:06 +03:00
while ( 1 ) {
2009-01-16 00:51:04 +03:00
@ stack = ( [ '' , 0 ] ) if ( $# stack == - 1 ) ;
2008-03-29 00:15:58 +03:00
#warn "CSB: blk<$blk> remain<$remain>\n";
2007-11-29 03:21:06 +03:00
# If we are about to drop off the end, pull in more
# context.
if ( $ off >= $ len ) {
for ( ; $ remain > 0 ; $ line + + ) {
2008-10-16 09:02:25 +04:00
last if ( ! defined $ lines [ $ line ] ) ;
2008-02-08 15:20:54 +03:00
next if ( $ lines [ $ line ] =~ /^-/ ) ;
2007-11-29 03:21:06 +03:00
$ remain - - ;
2008-02-08 15:22:03 +03:00
$ loff = $ len ;
2008-02-08 15:20:54 +03:00
$ blk . = $ lines [ $ line ] . "\n" ;
2007-11-29 03:21:06 +03:00
$ len = length ( $ blk ) ;
$ line + + ;
last ;
}
# Bail if there is no further context.
#warn "CSB: blk<$blk> off<$off> len<$len>\n";
2008-02-08 15:22:03 +03:00
if ( $ off >= $ len ) {
2007-11-29 03:21:06 +03:00
last ;
}
}
2008-03-05 01:28:20 +03:00
$ p = $ c ;
2007-11-29 03:21:06 +03:00
$ c = substr ( $ blk , $ off , 1 ) ;
2008-02-08 15:22:03 +03:00
$ remainder = substr ( $ blk , $ off ) ;
2007-11-29 03:21:06 +03:00
2008-03-29 00:15:58 +03:00
#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
2009-01-07 01:41:27 +03:00
# Handle nested #if/#else.
if ( $ remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/ ) {
push ( @ stack , [ $ type , $ level ] ) ;
} elsif ( $ remainder =~ /^#\s*(?:else|elif)\b/ ) {
( $ type , $ level ) = @ { $ stack [ $# stack - 1 ] } ;
} elsif ( $ remainder =~ /^#\s*endif\b/ ) {
( $ type , $ level ) = @ { pop ( @ stack ) } ;
}
2007-11-29 03:21:06 +03:00
# Statement ends at the ';' or a close '}' at the
# outermost level.
if ( $ level == 0 && $ c eq ';' ) {
last ;
}
2008-02-08 15:22:03 +03:00
# An else is really a conditional as long as its not else if
2008-03-29 00:15:58 +03:00
if ( $ level == 0 && $ coff_set == 0 &&
( ! defined ( $ p ) || $ p =~ /(?:\s|\}|\+)/ ) &&
$ remainder =~ /^(else)(?:\s|{)/ &&
$ remainder !~ /^else\s+if\b/ ) {
$ coff = $ off + length ( $ 1 ) - 1 ;
$ coff_set = 1 ;
#warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
#warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
2008-02-08 15:22:03 +03:00
}
2007-11-29 03:21:06 +03:00
if ( ( $ type eq '' || $ type eq '(' ) && $ c eq '(' ) {
$ level + + ;
$ type = '(' ;
}
if ( $ type eq '(' && $ c eq ')' ) {
$ level - - ;
$ type = ( $ level != 0 ) ? '(' : '' ;
if ( $ level == 0 && $ coff < $ soff ) {
$ coff = $ off ;
2008-03-29 00:15:58 +03:00
$ coff_set = 1 ;
#warn "CSB: mark coff<$coff>\n";
2007-11-29 03:21:06 +03:00
}
}
if ( ( $ type eq '' || $ type eq '{' ) && $ c eq '{' ) {
$ level + + ;
$ type = '{' ;
}
if ( $ type eq '{' && $ c eq '}' ) {
$ level - - ;
$ type = ( $ level != 0 ) ? '{' : '' ;
if ( $ level == 0 ) {
2010-08-10 04:21:03 +04:00
if ( substr ( $ blk , $ off + 1 , 1 ) eq ';' ) {
$ off + + ;
}
2007-11-29 03:21:06 +03:00
last ;
}
}
$ off + + ;
}
2008-07-24 08:29:00 +04:00
# We are truly at the end, so shuffle to the next line.
2008-02-08 15:22:03 +03:00
if ( $ off == $ len ) {
2008-07-24 08:29:00 +04:00
$ loff = $ len + 1 ;
2008-02-08 15:22:03 +03:00
$ line + + ;
$ remain - - ;
}
2007-11-29 03:21:06 +03:00
my $ statement = substr ( $ blk , $ soff , $ off - $ soff + 1 ) ;
my $ condition = substr ( $ blk , $ soff , $ coff - $ soff + 1 ) ;
#warn "STATEMENT<$statement>\n";
#warn "CONDITION<$condition>\n";
2008-03-29 00:15:58 +03:00
#print "coff<$coff> soff<$off> loff<$loff>\n";
2008-02-08 15:22:03 +03:00
return ( $ statement , $ condition ,
$ line , $ remain + 1 , $ off - $ loff + 1 , $ level ) ;
}
2008-03-05 01:28:20 +03:00
sub statement_lines {
my ( $ stmt ) = @ _ ;
# Strip the diff line prefixes and rip blank lines at start and end.
$ stmt =~ s/(^|\n)./$1/g ;
$ stmt =~ s/^\s*// ;
$ stmt =~ s/\s*$// ;
my @ stmt_lines = ( $ stmt =~ /\n/g ) ;
return $# stmt_lines + 2 ;
}
sub statement_rawlines {
my ( $ stmt ) = @ _ ;
my @ stmt_lines = ( $ stmt =~ /\n/g ) ;
return $# stmt_lines + 2 ;
}
sub statement_block_size {
my ( $ stmt ) = @ _ ;
$ stmt =~ s/(^|\n)./$1/g ;
$ stmt =~ s/^\s*{// ;
$ stmt =~ s/}\s*$// ;
$ stmt =~ s/^\s*// ;
$ stmt =~ s/\s*$// ;
my @ stmt_lines = ( $ stmt =~ /\n/g ) ;
my @ stmt_statements = ( $ stmt =~ /;/g ) ;
my $ stmt_lines = $# stmt_lines + 2 ;
my $ stmt_statements = $# stmt_statements + 1 ;
if ( $ stmt_lines > $ stmt_statements ) {
return $ stmt_lines ;
} else {
return $ stmt_statements ;
}
}
2008-02-08 15:22:03 +03:00
sub ctx_statement_full {
my ( $ linenr , $ remain , $ off ) = @ _ ;
my ( $ statement , $ condition , $ level ) ;
my ( @ chunks ) ;
2008-03-05 01:28:20 +03:00
# Grab the first conditional/block pair.
2008-02-08 15:22:03 +03:00
( $ statement , $ condition , $ linenr , $ remain , $ off , $ level ) =
ctx_statement_block ( $ linenr , $ remain , $ off ) ;
2008-03-29 00:15:58 +03:00
#print "F: c<$condition> s<$statement> remain<$remain>\n";
2008-03-05 01:28:20 +03:00
push ( @ chunks , [ $ condition , $ statement ] ) ;
if ( ! ( $ remain > 0 && $ condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s ) ) {
return ( $ level , $ linenr , @ chunks ) ;
}
# Pull in the following conditional/block pairs and see if they
# could continue the statement.
2008-02-08 15:22:03 +03:00
for ( ; ; ) {
( $ statement , $ condition , $ linenr , $ remain , $ off , $ level ) =
ctx_statement_block ( $ linenr , $ remain , $ off ) ;
2008-03-05 01:28:20 +03:00
#print "C: c<$condition> s<$statement> remain<$remain>\n";
2008-03-29 00:15:58 +03:00
last if ( ! ( $ remain > 0 && $ condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s ) ) ;
2008-03-05 01:28:20 +03:00
#print "C: push\n";
push ( @ chunks , [ $ condition , $ statement ] ) ;
2008-02-08 15:22:03 +03:00
}
return ( $ level , $ linenr , @ chunks ) ;
2007-11-29 03:21:06 +03:00
}
2007-06-09 00:46:39 +04:00
sub ctx_block_get {
2007-07-19 12:48:34 +04:00
my ( $ linenr , $ remain , $ outer , $ open , $ close , $ off ) = @ _ ;
2007-06-09 00:46:39 +04:00
my $ line ;
my $ start = $ linenr - 1 ;
my $ blk = '' ;
my @ o ;
my @ c ;
my @ res = ( ) ;
2007-07-19 12:48:34 +04:00
my $ level = 0 ;
2009-01-07 01:41:27 +03:00
my @ stack = ( $ level ) ;
2007-06-09 00:47:06 +04:00
for ( $ line = $ start ; $ remain > 0 ; $ line + + ) {
next if ( $ rawlines [ $ line ] =~ /^-/ ) ;
$ remain - - ;
$ blk . = $ rawlines [ $ line ] ;
2009-01-07 01:41:27 +03:00
# Handle nested #if/#else.
2010-10-27 01:23:19 +04:00
if ( $ lines [ $ line ] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/ ) {
2009-01-07 01:41:27 +03:00
push ( @ stack , $ level ) ;
2010-10-27 01:23:19 +04:00
} elsif ( $ lines [ $ line ] =~ /^.\s*#\s*(?:else|elif)\b/ ) {
2009-01-07 01:41:27 +03:00
$ level = $ stack [ $# stack - 1 ] ;
2010-10-27 01:23:19 +04:00
} elsif ( $ lines [ $ line ] =~ /^.\s*#\s*endif\b/ ) {
2009-01-07 01:41:27 +03:00
$ level = pop ( @ stack ) ;
}
2010-10-27 01:23:19 +04:00
foreach my $ c ( split ( // , $ lines [ $ line ] ) ) {
2007-07-19 12:48:34 +04:00
##print "C<$c>L<$level><$open$close>O<$off>\n";
if ( $ off > 0 ) {
$ off - - ;
next ;
}
2007-06-09 00:46:39 +04:00
2007-07-19 12:48:34 +04:00
if ( $ c eq $ close && $ level > 0 ) {
$ level - - ;
last if ( $ level == 0 ) ;
} elsif ( $ c eq $ open ) {
$ level + + ;
}
}
2007-06-09 00:46:39 +04:00
2007-07-19 12:48:34 +04:00
if ( ! $ outer || $ level <= 1 ) {
2007-06-09 00:47:06 +04:00
push ( @ res , $ rawlines [ $ line ] ) ;
2007-06-09 00:46:39 +04:00
}
2007-07-19 12:48:34 +04:00
last if ( $ level == 0 ) ;
2007-06-09 00:46:39 +04:00
}
2007-07-19 12:48:34 +04:00
return ( $ level , @ res ) ;
2007-06-09 00:46:39 +04:00
}
sub ctx_block_outer {
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 12:48:34 +04:00
my ( $ level , @ r ) = ctx_block_get ( $ linenr , $ remain , 1 , '{' , '}' , 0 ) ;
return @ r ;
2007-06-09 00:46:39 +04:00
}
sub ctx_block {
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 12:48:34 +04:00
my ( $ level , @ r ) = ctx_block_get ( $ linenr , $ remain , 0 , '{' , '}' , 0 ) ;
return @ r ;
2007-06-24 04:16:34 +04:00
}
sub ctx_statement {
2007-07-19 12:48:34 +04:00
my ( $ linenr , $ remain , $ off ) = @ _ ;
my ( $ level , @ r ) = ctx_block_get ( $ linenr , $ remain , 0 , '(' , ')' , $ off ) ;
return @ r ;
}
sub ctx_block_level {
2007-06-24 04:16:34 +04:00
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 12:48:34 +04:00
return ctx_block_get ( $ linenr , $ remain , 0 , '{' , '}' , 0 ) ;
2007-06-09 00:46:39 +04:00
}
2007-10-17 10:29:38 +04:00
sub ctx_statement_level {
my ( $ linenr , $ remain , $ off ) = @ _ ;
return ctx_block_get ( $ linenr , $ remain , 0 , '(' , ')' , $ off ) ;
}
2007-06-09 00:46:39 +04:00
sub ctx_locate_comment {
my ( $ first_line , $ end_line ) = @ _ ;
# Catch a comment on the end of the line itself.
2008-07-24 08:28:59 +04:00
my ( $ current_comment ) = ( $ rawlines [ $ end_line - 1 ] =~ m @.*(/\*.*\*/)\s*(?:\\\s*)?$@ ) ;
2007-06-09 00:46:39 +04:00
return $ current_comment if ( defined $ current_comment ) ;
# Look through the context and try and figure out if there is a
# comment.
my $ in_comment = 0 ;
$ current_comment = '' ;
for ( my $ linenr = $ first_line ; $ linenr < $ end_line ; $ linenr + + ) {
2007-06-09 00:47:06 +04:00
my $ line = $ rawlines [ $ linenr - 1 ] ;
#warn " $line\n";
2007-06-09 00:46:39 +04:00
if ( $ linenr == $ first_line and $ line =~ m @^.\s*\*@ ) {
$ in_comment = 1 ;
}
if ( $ line =~ m @/\*@ ) {
$ in_comment = 1 ;
}
if ( ! $ in_comment && $ current_comment ne '' ) {
$ current_comment = '' ;
}
$ current_comment . = $ line . "\n" if ( $ in_comment ) ;
if ( $ line =~ m @\*/@ ) {
$ in_comment = 0 ;
}
}
chomp ( $ current_comment ) ;
return ( $ current_comment ) ;
}
sub ctx_has_comment {
my ( $ first_line , $ end_line ) = @ _ ;
my $ cmt = ctx_locate_comment ( $ first_line , $ end_line ) ;
2007-06-09 00:47:06 +04:00
##print "LINE: $rawlines[$end_line - 1 ]\n";
2007-06-09 00:46:39 +04:00
##print "CMMT: $cmt\n";
return ( $ cmt ne '' ) ;
}
2008-10-16 09:02:21 +04:00
sub raw_line {
my ( $ linenr , $ cnt ) = @ _ ;
my $ offset = $ linenr - 1 ;
$ cnt + + ;
my $ line ;
while ( $ cnt ) {
$ line = $ rawlines [ $ offset + + ] ;
next if ( defined ( $ line ) && $ line =~ /^-/ ) ;
$ cnt - - ;
}
return $ line ;
}
2007-10-18 14:05:08 +04:00
sub cat_vet {
my ( $ vet ) = @ _ ;
my ( $ res , $ coded ) ;
2007-10-17 10:29:38 +04:00
2007-10-18 14:05:08 +04:00
$ res = '' ;
while ( $ vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g ) {
$ res . = $ 1 ;
if ( $ 2 ne '' ) {
$ coded = sprintf ( "^%c" , unpack ( 'C' , $ 2 ) + 64 ) ;
$ res . = $ coded ;
2007-10-17 10:29:38 +04:00
}
}
2007-10-18 14:05:08 +04:00
$ res =~ s/$/\$/ ;
2007-10-17 10:29:38 +04:00
2007-10-18 14:05:08 +04:00
return $ res ;
2007-10-17 10:29:38 +04:00
}
2008-02-08 15:20:54 +03:00
my $ av_preprocessor = 0 ;
2008-03-05 01:28:20 +03:00
my $ av_pending ;
2008-02-08 15:20:54 +03:00
my @ av_paren_type ;
2008-07-24 08:29:10 +04:00
my $ av_pend_colon ;
2008-02-08 15:20:54 +03:00
sub annotate_reset {
$ av_preprocessor = 0 ;
2008-03-05 01:28:20 +03:00
$ av_pending = '_' ;
@ av_paren_type = ( 'E' ) ;
2008-07-24 08:29:10 +04:00
$ av_pend_colon = 'O' ;
2008-02-08 15:20:54 +03:00
}
2007-10-18 14:05:08 +04:00
sub annotate_values {
my ( $ stream , $ type ) = @ _ ;
2007-06-01 11:46:48 +04:00
2007-10-18 14:05:08 +04:00
my $ res ;
2008-07-24 08:29:10 +04:00
my $ var = '_' x length ( $ stream ) ;
2007-10-18 14:05:08 +04:00
my $ cur = $ stream ;
2008-02-08 15:20:54 +03:00
print "$stream\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
while ( length ( $ cur ) ) {
2008-03-29 00:15:58 +03:00
@ av_paren_type = ( 'E' ) if ( $# av_paren_type < 0 ) ;
2008-03-05 01:28:20 +03:00
print " <" . join ( '' , @ av_paren_type ) .
2008-04-29 11:59:32 +04:00
"> <$type> <$av_pending>" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
if ( $ cur =~ /^(\s+)/o ) {
2008-02-08 15:20:54 +03:00
print "WS($1)\n" if ( $ dbg_values > 1 ) ;
if ( $ 1 =~ /\n/ && $ av_preprocessor ) {
2008-03-05 01:28:20 +03:00
$ type = pop ( @ av_paren_type ) ;
2008-02-08 15:20:54 +03:00
$ av_preprocessor = 0 ;
2007-10-18 14:05:08 +04:00
}
2011-01-13 03:59:58 +03:00
} elsif ( $ cur =~ /^(\(\s*$Type\s*)\)/ && $ av_pending eq '_' ) {
2010-10-27 01:23:13 +04:00
print "CAST($1)\n" if ( $ dbg_values > 1 ) ;
push ( @ av_paren_type , $ type ) ;
$ type = 'C' ;
2010-10-27 01:23:11 +04:00
} elsif ( $ cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/ ) {
2008-02-08 15:20:54 +03:00
print "DECLARE($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'T' ;
2008-07-24 08:29:05 +04:00
} elsif ( $ cur =~ /^($Modifier)\s*/ ) {
print "MODIFIER($1)\n" if ( $ dbg_values > 1 ) ;
$ type = 'T' ;
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*define\s*$Ident)(\(?)/o ) {
2008-04-29 11:59:32 +04:00
print "DEFINE($1,$2)\n" if ( $ dbg_values > 1 ) ;
2008-02-08 15:20:54 +03:00
$ av_preprocessor = 1 ;
2008-04-29 11:59:32 +04:00
push ( @ av_paren_type , $ type ) ;
if ( $ 2 ne '' ) {
$ av_pending = 'N' ;
}
$ type = 'E' ;
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o ) {
2008-04-29 11:59:32 +04:00
print "UNDEF($1)\n" if ( $ dbg_values > 1 ) ;
$ av_preprocessor = 1 ;
push ( @ av_paren_type , $ type ) ;
2007-10-18 14:05:08 +04:00
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o ) {
2008-03-05 01:28:20 +03:00
print "PRE_START($1)\n" if ( $ dbg_values > 1 ) ;
2008-02-08 15:20:54 +03:00
$ av_preprocessor = 1 ;
2008-03-05 01:28:20 +03:00
push ( @ av_paren_type , $ type ) ;
push ( @ av_paren_type , $ type ) ;
2008-04-29 11:59:32 +04:00
$ type = 'E' ;
2008-03-05 01:28:20 +03:00
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*(?:else|elif))/o ) {
2008-03-05 01:28:20 +03:00
print "PRE_RESTART($1)\n" if ( $ dbg_values > 1 ) ;
$ av_preprocessor = 1 ;
push ( @ av_paren_type , $ av_paren_type [ $# av_paren_type ] ) ;
2008-04-29 11:59:32 +04:00
$ type = 'E' ;
2008-03-05 01:28:20 +03:00
2008-06-06 09:46:01 +04:00
} elsif ( $ cur =~ /^(\#\s*(?:endif))/o ) {
2008-03-05 01:28:20 +03:00
print "PRE_END($1)\n" if ( $ dbg_values > 1 ) ;
$ av_preprocessor = 1 ;
# Assume all arms of the conditional end as this
# one does, and continue as if the #endif was not here.
pop ( @ av_paren_type ) ;
push ( @ av_paren_type , $ type ) ;
2008-04-29 11:59:32 +04:00
$ type = 'E' ;
2007-10-18 14:05:08 +04:00
} elsif ( $ cur =~ /^(\\\n)/o ) {
2008-02-08 15:20:54 +03:00
print "PRECONT($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
2008-04-29 11:59:32 +04:00
} elsif ( $ cur =~ /^(__attribute__)\s*\(?/o ) {
print "ATTR($1)\n" if ( $ dbg_values > 1 ) ;
$ av_pending = $ type ;
$ type = 'N' ;
2007-10-18 14:05:08 +04:00
} elsif ( $ cur =~ /^(sizeof)\s*(\()?/o ) {
2008-02-08 15:20:54 +03:00
print "SIZEOF($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
if ( defined $ 2 ) {
2008-03-05 01:28:20 +03:00
$ av_pending = 'V' ;
2007-10-18 14:05:08 +04:00
}
$ type = 'N' ;
2008-10-16 09:02:16 +04:00
} elsif ( $ cur =~ /^(if|while|for)\b/o ) {
2008-02-08 15:20:54 +03:00
print "COND($1)\n" if ( $ dbg_values > 1 ) ;
2008-10-16 09:02:16 +04:00
$ av_pending = 'E' ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
2008-07-24 08:29:10 +04:00
} elsif ( $ cur =~ /^(case)/o ) {
print "CASE($1)\n" if ( $ dbg_values > 1 ) ;
$ av_pend_colon = 'C' ;
$ type = 'N' ;
2008-10-16 09:02:16 +04:00
} elsif ( $ cur =~ /^(return|else|goto|typeof|__typeof__)\b/o ) {
2008-02-08 15:20:54 +03:00
print "KEYWORD($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
} elsif ( $ cur =~ /^(\()/o ) {
2008-02-08 15:20:54 +03:00
print "PAREN('$1')\n" if ( $ dbg_values > 1 ) ;
2008-03-05 01:28:20 +03:00
push ( @ av_paren_type , $ av_pending ) ;
$ av_pending = '_' ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
} elsif ( $ cur =~ /^(\))/o ) {
2008-03-05 01:28:20 +03:00
my $ new_type = pop ( @ av_paren_type ) ;
if ( $ new_type ne '_' ) {
$ type = $ new_type ;
2008-02-08 15:20:54 +03:00
print "PAREN('$1') -> $type\n"
if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
} else {
2008-02-08 15:20:54 +03:00
print "PAREN('$1')\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
}
2008-07-24 08:28:57 +04:00
} elsif ( $ cur =~ /^($Ident)\s*\(/o ) {
2008-02-08 15:20:54 +03:00
print "FUNC($1)\n" if ( $ dbg_values > 1 ) ;
2008-07-24 08:28:57 +04:00
$ type = 'V' ;
2008-03-05 01:28:20 +03:00
$ av_pending = 'V' ;
2007-10-18 14:05:08 +04:00
2009-01-07 01:41:19 +03:00
} elsif ( $ cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/ ) {
if ( defined $ 2 && $ type eq 'C' || $ type eq 'T' ) {
2008-07-24 08:29:10 +04:00
$ av_pend_colon = 'B' ;
2009-01-07 01:41:19 +03:00
} elsif ( $ type eq 'E' ) {
$ av_pend_colon = 'L' ;
2008-07-24 08:29:10 +04:00
}
print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ( $ dbg_values > 1 ) ;
$ type = 'V' ;
2007-10-18 14:05:08 +04:00
} elsif ( $ cur =~ /^($Ident|$Constant)/o ) {
2008-02-08 15:20:54 +03:00
print "IDENT($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'V' ;
} elsif ( $ cur =~ /^($Assignment)/o ) {
2008-02-08 15:20:54 +03:00
print "ASSIGN($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
2008-03-05 01:28:20 +03:00
} elsif ( $ cur =~ /^(;|{|})/ ) {
2008-02-08 15:20:54 +03:00
print "END($1)\n" if ( $ dbg_values > 1 ) ;
2008-02-08 15:22:03 +03:00
$ type = 'E' ;
2008-07-24 08:29:10 +04:00
$ av_pend_colon = 'O' ;
2009-01-07 01:41:19 +03:00
} elsif ( $ cur =~ /^(,)/ ) {
print "COMMA($1)\n" if ( $ dbg_values > 1 ) ;
$ type = 'C' ;
2008-07-24 08:29:10 +04:00
} elsif ( $ cur =~ /^(\?)/o ) {
print "QUESTION($1)\n" if ( $ dbg_values > 1 ) ;
$ type = 'N' ;
} elsif ( $ cur =~ /^(:)/o ) {
print "COLON($1,$av_pend_colon)\n" if ( $ dbg_values > 1 ) ;
substr ( $ var , length ( $ res ) , 1 , $ av_pend_colon ) ;
if ( $ av_pend_colon eq 'C' || $ av_pend_colon eq 'L' ) {
$ type = 'E' ;
} else {
$ type = 'N' ;
}
$ av_pend_colon = 'O' ;
2008-02-08 15:22:03 +03:00
2009-01-07 01:41:19 +03:00
} elsif ( $ cur =~ /^(\[)/o ) {
2008-02-08 15:22:03 +03:00
print "CLOSE($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
$ type = 'N' ;
2008-10-16 09:02:16 +04:00
} elsif ( $ cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o ) {
2008-07-24 08:29:10 +04:00
my $ variant ;
print "OPV($1)\n" if ( $ dbg_values > 1 ) ;
if ( $ type eq 'V' ) {
$ variant = 'B' ;
} else {
$ variant = 'U' ;
}
substr ( $ var , length ( $ res ) , 1 , $ variant ) ;
$ type = 'N' ;
2007-10-18 14:05:08 +04:00
} elsif ( $ cur =~ /^($Operators)/o ) {
2008-02-08 15:20:54 +03:00
print "OP($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
if ( $ 1 ne '++' && $ 1 ne '--' ) {
$ type = 'N' ;
}
} elsif ( $ cur =~ /(^.)/o ) {
2008-02-08 15:20:54 +03:00
print "C($1)\n" if ( $ dbg_values > 1 ) ;
2007-10-18 14:05:08 +04:00
}
if ( defined $ 1 ) {
$ cur = substr ( $ cur , length ( $ 1 ) ) ;
$ res . = $ type x length ( $ 1 ) ;
}
2007-10-17 10:29:38 +04:00
}
2007-06-01 11:46:48 +04:00
2008-07-24 08:29:10 +04:00
return ( $ res , $ var ) ;
2007-06-01 11:46:48 +04:00
}
2007-11-29 03:21:06 +03:00
sub possible {
2008-02-08 15:22:03 +03:00
my ( $ possible , $ line ) = @ _ ;
2009-10-27 02:50:12 +03:00
my $ notPermitted = qr{ (?:
2008-10-16 09:02:29 +04:00
^ ( ? :
$ Modifier |
$ Storage |
$ Type |
2009-10-27 02:50:12 +03:00
DEFINE_ \ S +
) $|
^ ( ? :
2008-10-16 09:02:29 +04:00
goto |
return |
case |
else |
asm | __asm__ |
do
2009-10-27 02:50:12 +03:00
) ( ? : \ s | $ ) |
2008-10-16 09:02:29 +04:00
^ ( ? : typedef | struct | enum ) \ b
2009-10-27 02:50:12 +03:00
) } x ;
warn "CHECK<$possible> ($line)\n" if ( $ dbg_possible > 2 ) ;
if ( $ possible !~ $ notPermitted ) {
2008-06-06 09:46:01 +04:00
# Check for modifiers.
$ possible =~ s/\s*$Storage\s*//g ;
$ possible =~ s/\s*$Sparse\s*//g ;
if ( $ possible =~ /^\s*$/ ) {
} elsif ( $ possible =~ /\s/ ) {
$ possible =~ s/\s*$Type\s*//g ;
2008-07-24 08:29:09 +04:00
for my $ modifier ( split ( ' ' , $ possible ) ) {
2009-10-27 02:50:12 +03:00
if ( $ modifier !~ $ notPermitted ) {
warn "MODIFIER: $modifier ($possible) ($line)\n" if ( $ dbg_possible ) ;
push ( @ modifierList , $ modifier ) ;
}
2008-07-24 08:29:09 +04:00
}
2008-06-06 09:46:01 +04:00
} else {
warn "POSSIBLE: $possible ($line)\n" if ( $ dbg_possible ) ;
push ( @ typeList , $ possible ) ;
}
2007-11-29 03:21:06 +03:00
build_types ( ) ;
2008-10-16 09:02:29 +04:00
} else {
warn "NOTPOSS: $possible ($line)\n" if ( $ dbg_possible > 1 ) ;
2007-11-29 03:21:06 +03:00
}
}
2007-10-18 14:05:08 +04:00
my $ prefix = '' ;
2007-07-19 12:48:34 +04:00
sub report {
2008-03-29 00:15:58 +03:00
if ( defined $ tst_only && $ _ [ 0 ] !~ /\Q$tst_only\E/ ) {
return 0 ;
}
2007-11-29 03:21:06 +03:00
my $ line = $ prefix . $ _ [ 0 ] ;
$ line = ( split ( '\n' , $ line ) ) [ 0 ] . "\n" if ( $ terse ) ;
2008-02-08 15:22:03 +03:00
push ( our @ report , $ line ) ;
2008-03-29 00:15:58 +03:00
return 1 ;
2007-07-19 12:48:34 +04:00
}
sub report_dump {
2008-02-08 15:22:03 +03:00
our @ report ;
2007-07-19 12:48:34 +04:00
}
2007-07-16 10:37:22 +04:00
sub ERROR {
2008-03-29 00:15:58 +03:00
if ( report ( "ERROR: $_[0]\n" ) ) {
our $ clean = 0 ;
our $ cnt_error + + ;
}
2007-07-16 10:37:22 +04:00
}
sub WARN {
2008-03-29 00:15:58 +03:00
if ( report ( "WARNING: $_[0]\n" ) ) {
our $ clean = 0 ;
our $ cnt_warn + + ;
}
2007-07-16 10:37:22 +04:00
}
sub CHK {
2008-03-29 00:15:58 +03:00
if ( $ check && report ( "CHECK: $_[0]\n" ) ) {
2007-10-18 14:05:08 +04:00
our $ clean = 0 ;
our $ cnt_chk + + ;
}
2007-07-16 10:37:22 +04:00
}
2008-10-16 09:02:21 +04:00
sub check_absolute_file {
my ( $ absolute , $ herecurr ) = @ _ ;
my $ file = $ absolute ;
##print "absolute<$absolute>\n";
# See if any suffix of this path is a path within the tree.
while ( $ file =~ s@^[^/]*/@@ ) {
if ( - f "$root/$file" ) {
##print "file<$file>\n";
last ;
}
}
if ( ! - f _ ) {
return 0 ;
}
# It is, so see if the prefix is acceptable.
my $ prefix = $ absolute ;
substr ( $ prefix , - length ( $ file ) ) = '' ;
##print "prefix<$prefix>\n";
if ( $ prefix ne ".../" ) {
WARN ( "use relative pathname instead of absolute in changelog text\n" . $ herecurr ) ;
}
}
2007-06-01 11:46:48 +04:00
sub process {
my $ filename = shift ;
my $ linenr = 0 ;
my $ prevline = "" ;
2008-02-08 15:20:54 +03:00
my $ prevrawline = "" ;
2007-06-01 11:46:48 +04:00
my $ stashline = "" ;
2008-02-08 15:20:54 +03:00
my $ stashrawline = "" ;
2007-06-01 11:46:48 +04:00
2007-06-09 00:46:39 +04:00
my $ length ;
2007-06-01 11:46:48 +04:00
my $ indent ;
my $ previndent = 0 ;
my $ stashindent = 0 ;
2007-07-16 10:37:22 +04:00
our $ clean = 1 ;
2007-06-01 11:46:48 +04:00
my $ signoff = 0 ;
my $ is_patch = 0 ;
2008-02-08 15:22:03 +03:00
our @ report = ( ) ;
2007-10-18 14:05:08 +04:00
our $ cnt_lines = 0 ;
our $ cnt_error = 0 ;
our $ cnt_warn = 0 ;
our $ cnt_chk = 0 ;
2007-06-01 11:46:48 +04:00
# Trace the real file/line as we go.
my $ realfile = '' ;
my $ realline = 0 ;
my $ realcnt = 0 ;
my $ here = '' ;
my $ in_comment = 0 ;
2008-02-08 15:20:54 +03:00
my $ comment_edge = 0 ;
2007-06-01 11:46:48 +04:00
my $ first_line = 0 ;
2009-01-07 01:41:24 +03:00
my $ p1_prefix = '' ;
2007-06-01 11:46:48 +04:00
2008-02-08 15:22:03 +03:00
my $ prev_values = 'E' ;
# suppression flags
2008-03-29 00:15:58 +03:00
my % suppress_ifbraces ;
2008-10-16 09:02:30 +04:00
my % suppress_whiletrailers ;
2009-10-27 02:50:16 +03:00
my % suppress_export ;
2007-06-24 04:16:34 +04:00
2008-02-08 15:20:54 +03:00
# Pre-scan the patch sanitizing the lines.
2007-07-16 10:37:22 +04:00
# Pre-scan the patch looking for any __setup documentation.
2008-02-08 15:20:54 +03:00
#
2007-07-16 10:37:22 +04:00
my @ setup_docs = ( ) ;
my $ setup_docs = 0 ;
2008-03-29 00:15:58 +03:00
sanitise_line_reset ( ) ;
2008-02-08 15:20:54 +03:00
my $ line ;
foreach my $ rawline ( @ rawlines ) {
2008-03-29 00:15:58 +03:00
$ linenr + + ;
$ line = $ rawline ;
2008-02-08 15:20:54 +03:00
2008-03-29 00:15:58 +03:00
if ( $ rawline =~ /^\+\+\+\s+(\S+)/ ) {
2007-07-16 10:37:22 +04:00
$ setup_docs = 0 ;
if ( $ 1 =~ m @Documentation/kernel-parameters.txt$@ ) {
$ setup_docs = 1 ;
}
2008-03-29 00:15:58 +03:00
#next;
}
if ( $ rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/ ) {
$ realline = $ 1 - 1 ;
if ( defined $ 2 ) {
$ realcnt = $ 3 + 1 ;
} else {
$ realcnt = 1 + 1 ;
}
2008-06-06 09:46:01 +04:00
$ in_comment = 0 ;
2008-03-29 00:15:58 +03:00
# Guestimate if this is a continuing comment. Run
# the context looking for a comment "edge". If this
# edge is a close comment then we must be in a comment
# at context start.
my $ edge ;
2008-10-16 09:02:19 +04:00
my $ cnt = $ realcnt ;
for ( my $ ln = $ linenr + 1 ; $ cnt > 0 ; $ ln + + ) {
next if ( defined $ rawlines [ $ ln - 1 ] &&
$ rawlines [ $ ln - 1 ] =~ /^-/ ) ;
$ cnt - - ;
#print "RAW<$rawlines[$ln - 1]>\n";
2009-01-07 01:41:16 +03:00
last if ( ! defined $ rawlines [ $ ln - 1 ] ) ;
2009-01-07 01:41:20 +03:00
if ( $ rawlines [ $ ln - 1 ] =~ m @(/\*|\*/)@ &&
$ rawlines [ $ ln - 1 ] !~ m @"[^"]*(?:/\*|\*/)[^"]*"@ ) {
( $ edge ) = $ 1 ;
last ;
}
2008-03-29 00:15:58 +03:00
}
if ( defined $ edge && $ edge eq '*/' ) {
$ in_comment = 1 ;
}
# Guestimate if this is a continuing comment. If this
# is the start of a diff block and this line starts
# ' *' then it is very likely a comment.
if ( ! defined $ edge &&
2009-01-07 01:41:17 +03:00
$ rawlines [ $ linenr ] =~ m @^.\s*(?:\*\*+| \*)(?:\s|$)@ )
2008-03-29 00:15:58 +03:00
{
$ in_comment = 1 ;
}
##print "COMMENT:$in_comment edge<$edge> $rawline\n";
sanitise_line_reset ( $ in_comment ) ;
2008-04-29 11:59:32 +04:00
} elsif ( $ realcnt && $ rawline =~ /^(?:\+| |$)/ ) {
2008-03-29 00:15:58 +03:00
# Standardise the strings and chars within the input to
2008-04-29 11:59:32 +04:00
# simplify matching -- only bother with positive lines.
2008-03-29 00:15:58 +03:00
$ line = sanitise_line ( $ rawline ) ;
2007-07-16 10:37:22 +04:00
}
2008-03-29 00:15:58 +03:00
push ( @ lines , $ line ) ;
if ( $ realcnt > 1 ) {
$ realcnt - - if ( $ line =~ /^(?:\+| |$)/ ) ;
} else {
$ realcnt = 0 ;
}
#print "==>$rawline\n";
#print "-->$line\n";
2007-07-16 10:37:22 +04:00
if ( $ setup_docs && $ line =~ /^\+/ ) {
push ( @ setup_docs , $ line ) ;
}
}
2007-10-18 14:05:08 +04:00
$ prefix = '' ;
2008-03-29 00:15:58 +03:00
$ realcnt = 0 ;
$ linenr = 0 ;
2007-06-01 11:46:48 +04:00
foreach my $ line ( @ lines ) {
$ linenr + + ;
2008-02-08 15:20:54 +03:00
my $ rawline = $ rawlines [ $ linenr - 1 ] ;
2007-10-18 14:05:08 +04:00
2007-06-01 11:46:48 +04:00
#extract the line range in the file after the patch is applied
2007-10-18 14:05:08 +04:00
if ( $ line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/ ) {
2007-06-01 11:46:48 +04:00
$ is_patch = 1 ;
2007-06-09 00:46:39 +04:00
$ first_line = $ linenr + 1 ;
2007-06-01 11:46:48 +04:00
$ realline = $ 1 - 1 ;
if ( defined $ 2 ) {
$ realcnt = $ 3 + 1 ;
} else {
$ realcnt = 1 + 1 ;
}
2008-02-08 15:20:54 +03:00
annotate_reset ( ) ;
2008-02-08 15:22:03 +03:00
$ prev_values = 'E' ;
2008-03-29 00:15:58 +03:00
% suppress_ifbraces = ( ) ;
2008-10-16 09:02:30 +04:00
% suppress_whiletrailers = ( ) ;
2009-10-27 02:50:16 +03:00
% suppress_export = ( ) ;
2007-06-01 11:46:48 +04:00
next ;
2007-06-09 00:46:39 +04:00
# track the line number as we move through the hunk, note that
# new versions of GNU diff omit the leading space on completely
# blank context lines so we need to count that too.
2008-03-29 00:15:58 +03:00
} elsif ( $ line =~ /^( |\+|$)/ ) {
2007-06-01 11:46:48 +04:00
$ realline + + ;
2007-06-24 04:16:44 +04:00
$ realcnt - - if ( $ realcnt != 0 ) ;
2007-06-01 11:46:48 +04:00
2007-06-09 00:46:39 +04:00
# Measure the line length and indent.
2008-02-08 15:20:54 +03:00
( $ length , $ indent ) = line_stats ( $ rawline ) ;
2007-06-01 11:46:48 +04:00
# Track the previous line.
( $ prevline , $ stashline ) = ( $ stashline , $ line ) ;
( $ previndent , $ stashindent ) = ( $ stashindent , $ indent ) ;
2008-02-08 15:20:54 +03:00
( $ prevrawline , $ stashrawline ) = ( $ stashrawline , $ rawline ) ;
2008-03-29 00:15:58 +03:00
#warn "line<$line>\n";
2007-10-18 14:05:08 +04:00
2007-06-24 04:16:44 +04:00
} elsif ( $ realcnt == 1 ) {
$ realcnt - - ;
2007-06-01 11:46:48 +04:00
}
2009-10-27 02:50:13 +03:00
my $ hunk_line = ( $ realcnt != 0 ) ;
2007-06-01 11:46:48 +04:00
#make up the handle for any error we report on this line
2008-03-29 00:15:58 +03:00
$ prefix = "$filename:$realline: " if ( $ emacs && $ file ) ;
$ prefix = "$filename:$linenr: " if ( $ emacs && ! $ file ) ;
2007-10-18 14:05:08 +04:00
$ here = "#$linenr: " if ( ! $ file ) ;
$ here = "#$realline: " if ( $ file ) ;
2008-03-29 00:15:58 +03:00
# extract the filename as it passes
2010-10-27 01:23:16 +04:00
if ( $ line =~ /^diff --git.*?(\S+)$/ ) {
$ realfile = $ 1 ;
$ realfile =~ s@^([^/]*)/@@ ;
} elsif ( $ line =~ /^\+\+\+\s+(\S+)/ ) {
2008-03-29 00:15:58 +03:00
$ realfile = $ 1 ;
2009-01-07 01:41:24 +03:00
$ realfile =~ s@^([^/]*)/@@ ;
$ p1_prefix = $ 1 ;
2009-02-28 01:03:06 +03:00
if ( ! $ file && $ tree && $ p1_prefix ne '' &&
- e "$root/$p1_prefix" ) {
2009-01-07 01:41:24 +03:00
WARN ( "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n" ) ;
}
2008-03-29 00:15:58 +03:00
2008-10-16 09:02:20 +04:00
if ( $ realfile =~ m @^include/asm/@ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n" ) ;
}
next ;
}
2007-06-09 00:47:03 +04:00
$ here . = "FILE: $realfile:$realline:" if ( $ realcnt != 0 ) ;
2007-06-01 11:46:48 +04:00
2008-02-08 15:20:54 +03:00
my $ hereline = "$here\n$rawline\n" ;
my $ herecurr = "$here\n$rawline\n" ;
my $ hereprev = "$here\n$prevrawline\n$rawline\n" ;
2007-06-01 11:46:48 +04:00
2007-10-18 14:05:08 +04:00
$ cnt_lines + + if ( $ realcnt != 0 ) ;
2010-10-27 01:23:16 +04:00
# Check for incorrect file permissions
if ( $ line =~ /^new (file )?mode.*[7531]\d{0,2}$/ ) {
my $ permhere = $ here . "FILE: $realfile\n" ;
if ( $ realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/ ) {
ERROR ( "do not set execute permissions for source files\n" . $ permhere ) ;
}
}
2007-06-01 11:46:48 +04:00
#check the patch for a signoff:
2007-06-24 04:16:44 +04:00
if ( $ line =~ /^\s*signed-off-by:/i ) {
2007-06-09 00:46:39 +04:00
# This is a signoff, if ugly, so do not double report.
$ signoff + + ;
2007-06-01 11:46:48 +04:00
if ( ! ( $ line =~ /^\s*Signed-off-by:/ ) ) {
2007-07-16 10:37:22 +04:00
WARN ( "Signed-off-by: is the preferred form\n" .
$ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
if ( $ line =~ /^\s*signed-off-by:\S/i ) {
2008-03-29 00:15:58 +03:00
WARN ( "space required after Signed-off-by:\n" .
2007-07-16 10:37:22 +04:00
$ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
}
2007-06-09 00:47:06 +04:00
# Check for wrappage within a valid hunk of the file
2007-11-29 03:21:06 +03:00
if ( $ realcnt != 0 && $ line !~ m {^(?:\+|-| |\\ No newline|$)} ) {
2007-07-16 10:37:22 +04:00
ERROR ( "patch seems to be corrupt (line wrapped?)\n" .
2007-10-18 14:05:08 +04:00
$ herecurr ) if ( ! $ emitted_corrupt + + ) ;
2007-07-16 10:37:22 +04:00
}
2008-10-16 09:02:21 +04:00
# Check for absolute kernel paths.
if ( $ tree ) {
while ( $ line =~ m {(?:^|\s)(/\S*)}g ) {
my $ file = $ 1 ;
if ( $ file =~ m {^(.*?)(?::\d+)+:?$} &&
check_absolute_file ( $ 1 , $ herecurr ) ) {
#
} else {
check_absolute_file ( $ file , $ herecurr ) ;
}
}
}
2007-07-16 10:37:22 +04:00
# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
if ( ( $ realfile =~ /^$/ || $ line =~ /^\+/ ) &&
2008-04-29 11:59:32 +04:00
$ rawline !~ m/^$UTF8*$/ ) {
my ( $ utf8_prefix ) = ( $ rawline =~ /^($UTF8*)/ ) ;
my $ blank = copy_spacing ( $ rawline ) ;
my $ ptr = substr ( $ blank , 0 , length ( $ utf8_prefix ) ) . "^" ;
my $ hereptr = "$hereline$ptr\n" ;
ERROR ( "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $ hereptr ) ;
2007-06-09 00:47:06 +04:00
}
2008-10-16 09:02:28 +04:00
# ignore non-hunk lines and lines being removed
next if ( ! $ hunk_line || $ line =~ /^-/ ) ;
2007-06-01 11:46:48 +04:00
#trailing whitespace
2007-10-17 10:29:38 +04:00
if ( $ line =~ /^\+.*\015/ ) {
2008-02-08 15:20:54 +03:00
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2007-10-17 10:29:38 +04:00
ERROR ( "DOS line endings\n" . $ herevet ) ;
2008-02-08 15:20:54 +03:00
} elsif ( $ rawline =~ /^\+.*\S\s+$/ || $ rawline =~ /^\+\s+$/ ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2007-07-16 10:37:22 +04:00
ERROR ( "trailing whitespace\n" . $ herevet ) ;
2010-10-27 01:23:12 +04:00
$ rpt_cleaners = 1 ;
2007-06-01 11:46:48 +04:00
}
2008-10-16 09:02:27 +04:00
2010-05-25 01:33:29 +04:00
# check for Kconfig help text having a real description
2010-10-27 01:23:15 +04:00
# Only applies when adding the entry originally, after that we do not have
# sufficient context to determine whether it is indeed long enough.
2010-05-25 01:33:29 +04:00
if ( $ realfile =~ /Kconfig/ &&
2010-10-27 01:23:15 +04:00
$ line =~ /\+\s*(?:---)?help(?:---)?$/ ) {
2010-05-25 01:33:29 +04:00
my $ length = 0 ;
2010-10-27 01:23:15 +04:00
my $ cnt = $ realcnt ;
my $ ln = $ linenr + 1 ;
my $ f ;
my $ is_end = 0 ;
while ( $ cnt > 0 && defined $ lines [ $ ln - 1 ] ) {
$ f = $ lines [ $ ln - 1 ] ;
$ cnt - - if ( $ lines [ $ ln - 1 ] !~ /^-/ ) ;
$ is_end = $ lines [ $ ln - 1 ] =~ /^\+/ ;
$ ln + + ;
next if ( $ f =~ /^-/ ) ;
$ f =~ s/^.// ;
2010-05-25 01:33:29 +04:00
$ f =~ s/#.*// ;
$ f =~ s/^\s+// ;
next if ( $ f =~ /^$/ ) ;
2010-10-27 01:23:15 +04:00
if ( $ f =~ /^\s*config\s/ ) {
$ is_end = 1 ;
last ;
}
2010-05-25 01:33:29 +04:00
$ length + + ;
}
2010-10-27 01:23:15 +04:00
WARN ( "please write a paragraph that describes the config symbol fully\n" . $ herecurr ) if ( $ is_end && $ length < 4 ) ;
#print "is_end<$is_end> length<$length>\n";
2010-05-25 01:33:29 +04:00
}
2008-10-16 09:02:27 +04:00
# check we are in a valid source file if not then ignore this hunk
next if ( $ realfile !~ /\.(h|c|s|S|pl|sh)$/ ) ;
2007-06-01 11:46:48 +04:00
#80 column limit
2008-06-06 09:46:01 +04:00
if ( $ line =~ /^\+/ && $ prevrawline !~ /\/\*\*/ &&
2008-07-24 08:29:01 +04:00
$ rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
2010-08-10 04:21:01 +04:00
! ( $ line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ ||
$ line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/ ) &&
2008-07-24 08:29:01 +04:00
$ length > 80 )
2008-06-06 09:46:01 +04:00
{
2007-07-16 10:37:22 +04:00
WARN ( "line over 80 characters\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2010-03-06 00:43:55 +03:00
# check for spaces before a quoted newline
if ( $ rawline =~ /^.*\".*\s\\n/ ) {
WARN ( "unnecessary whitespace before a quoted newline\n" . $ herecurr ) ;
}
2007-11-29 03:21:06 +03:00
# check for adding lines without a newline.
if ( $ line =~ /^\+/ && defined $ lines [ $ linenr ] && $ lines [ $ linenr ] =~ /^\\ No newline at end of file/ ) {
WARN ( "adding a line without newline at end of file\n" . $ herecurr ) ;
}
2009-09-22 04:04:40 +04:00
# Blackfin: use hi/lo macros
if ( $ realfile =~ m @arch/blackfin/.*\.S$@ ) {
if ( $ line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/ ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
ERROR ( "use the LO() macro, not (... & 0xFFFF)\n" . $ herevet ) ;
}
if ( $ line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/ ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
ERROR ( "use the HI() macro, not (... >> 16)\n" . $ herevet ) ;
}
}
2008-10-16 09:02:24 +04:00
# check we are in a valid source file C or perl if not then ignore this hunk
next if ( $ realfile !~ /\.(h|c|pl)$/ ) ;
2007-06-01 11:46:48 +04:00
# at the beginning of a line any tabs must come first and anything
# more than 8 must use tabs.
2008-02-08 15:20:54 +03:00
if ( $ rawline =~ /^\+\s* \t\s*\S/ ||
$ rawline =~ /^\+\s* \s*/ ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2008-04-29 11:59:32 +04:00
ERROR ( "code indent should use tabs where possible\n" . $ herevet ) ;
2010-10-27 01:23:12 +04:00
$ rpt_cleaners = 1 ;
2007-06-01 11:46:48 +04:00
}
2010-03-06 00:43:54 +03:00
# check for space before tabs.
if ( $ rawline =~ /^\+/ && $ rawline =~ / \t/ ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
WARN ( "please, no space before tabs\n" . $ herevet ) ;
}
checkpatch: fix handling of leading spaces
I've got a false positive when spaces are present at the beginning of a
line.
So I add this check, obviously excluding to check the lines in the middle of
comments.
For instance this code passes the checkpatch test:
+struct davinci_mcbsp_data {
+ unsigned int fmt;
+ int clk_div;
+};
+
+static struct davinci_mcbsp_data mcbsp_data;
Where, before the string "int clk_div", I have 4 spaces (\040
ascii character).
With v2.6.34 scripts/checkpatch.pl script I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
total: 0 errors, 0 warnings, 201 lines checked
0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch has no obvious style
problems and is ready for submission.
That is not correct. Instead with the proposed patch I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
WARNING: please, no space for starting a line,
excluding comments
#63: FILE: sound/soc/davinci/davinci-i2s.c:165:
+ int clk_div;$
WARNING: please, no space for starting a line,
excluding comments
#95: FILE: sound/soc/davinci/davinci-i2s.c:406:
+ return 0;$
total: 0 errors, 2 warnings, 201 lines checked
That is correct.
Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-08-10 04:20:59 +04:00
# check for spaces at the beginning of a line.
2010-10-27 01:23:11 +04:00
# Exceptions:
# 1) within comments
# 2) indented preprocessor commands
# 3) hanging labels
if ( $ rawline =~ /^\+ / && $ line !~ /\+ *(?:$;|#|$Ident:)/ ) {
checkpatch: fix handling of leading spaces
I've got a false positive when spaces are present at the beginning of a
line.
So I add this check, obviously excluding to check the lines in the middle of
comments.
For instance this code passes the checkpatch test:
+struct davinci_mcbsp_data {
+ unsigned int fmt;
+ int clk_div;
+};
+
+static struct davinci_mcbsp_data mcbsp_data;
Where, before the string "int clk_div", I have 4 spaces (\040
ascii character).
With v2.6.34 scripts/checkpatch.pl script I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
total: 0 errors, 0 warnings, 201 lines checked
0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch has no obvious style
problems and is ready for submission.
That is not correct. Instead with the proposed patch I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
WARNING: please, no space for starting a line,
excluding comments
#63: FILE: sound/soc/davinci/davinci-i2s.c:165:
+ int clk_div;$
WARNING: please, no space for starting a line,
excluding comments
#95: FILE: sound/soc/davinci/davinci-i2s.c:406:
+ return 0;$
total: 0 errors, 2 warnings, 201 lines checked
That is correct.
Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-08-10 04:20:59 +04:00
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2010-10-27 01:23:11 +04:00
WARN ( "please, no spaces at the start of a line\n" . $ herevet ) ;
checkpatch: fix handling of leading spaces
I've got a false positive when spaces are present at the beginning of a
line.
So I add this check, obviously excluding to check the lines in the middle of
comments.
For instance this code passes the checkpatch test:
+struct davinci_mcbsp_data {
+ unsigned int fmt;
+ int clk_div;
+};
+
+static struct davinci_mcbsp_data mcbsp_data;
Where, before the string "int clk_div", I have 4 spaces (\040
ascii character).
With v2.6.34 scripts/checkpatch.pl script I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
total: 0 errors, 0 warnings, 201 lines checked
0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch has no obvious style
problems and is ready for submission.
That is not correct. Instead with the proposed patch I get:
scripts/checkpatch.pl 0001-ASoC-DaVinci-Added-support-for-stereo-I2S.patch
WARNING: please, no space for starting a line,
excluding comments
#63: FILE: sound/soc/davinci/davinci-i2s.c:165:
+ int clk_div;$
WARNING: please, no space for starting a line,
excluding comments
#95: FILE: sound/soc/davinci/davinci-i2s.c:406:
+ return 0;$
total: 0 errors, 2 warnings, 201 lines checked
That is correct.
Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-08-10 04:20:59 +04:00
}
2008-10-16 09:02:24 +04:00
# check we are in a valid C source file if not then ignore this hunk
next if ( $ realfile !~ /\.(h|c)$/ ) ;
2008-02-08 15:20:54 +03:00
# check for RCS/CVS revision markers
2008-03-05 01:28:20 +03:00
if ( $ rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/ ) {
2008-02-08 15:20:54 +03:00
WARN ( "CVS style keyword markers, these will _not_ be updated\n" . $ herecurr ) ;
}
2007-08-11 00:01:03 +04:00
2009-09-22 04:04:40 +04:00
# Blackfin: don't use __builtin_bfin_[cs]sync
if ( $ line =~ /__builtin_bfin_csync/ ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
ERROR ( "use the CSYNC() macro in asm/blackfin.h\n" . $ herevet ) ;
}
if ( $ line =~ /__builtin_bfin_ssync/ ) {
my $ herevet = "$here\n" . cat_vet ( $ line ) . "\n" ;
ERROR ( "use the SSYNC() macro in asm/blackfin.h\n" . $ herevet ) ;
}
2007-10-17 10:29:38 +04:00
# Check for potential 'bare' types
2009-10-27 02:50:16 +03:00
my ( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ,
$ realline_next ) ;
2008-04-29 11:59:33 +04:00
if ( $ realcnt && $ line =~ /.\s*\S/ ) {
2008-10-16 09:02:30 +04:00
( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ) =
2008-07-24 08:29:03 +04:00
ctx_statement_block ( $ linenr , $ realcnt , 0 ) ;
2008-04-29 11:59:32 +04:00
$ stat =~ s/\n./\n /g ;
$ cond =~ s/\n./\n /g ;
2009-10-27 02:50:16 +03:00
# Find the real next line.
$ realline_next = $ line_nr_next ;
if ( defined $ realline_next &&
( ! defined $ lines [ $ realline_next - 1 ] ||
substr ( $ lines [ $ realline_next - 1 ] , $ off_next ) =~ /^\s*$/ ) ) {
$ realline_next + + ;
}
2008-04-29 11:59:32 +04:00
my $ s = $ stat ;
$ s =~ s/{.*$//s ;
2008-03-05 01:28:20 +03:00
2008-02-08 15:20:54 +03:00
# Ignore goto labels.
2008-04-29 11:59:32 +04:00
if ( $ s =~ /$Ident:\*$/s ) {
2008-02-08 15:20:54 +03:00
# Ignore functions being called
2008-04-29 11:59:32 +04:00
} elsif ( $ s =~ /^.\s*$Ident\s*\(/s ) {
2008-02-08 15:20:54 +03:00
2009-09-22 04:04:34 +04:00
} elsif ( $ s =~ /^.\s*else\b/s ) {
2008-06-06 09:46:01 +04:00
# declarations always start with types
2008-07-24 08:29:09 +04:00
} elsif ( $ prev_values eq 'E' && $ s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s ) {
2008-06-06 09:46:01 +04:00
my $ type = $ 1 ;
$ type =~ s/\s+/ /g ;
possible ( $ type , "A:" . $ s ) ;
2007-11-29 03:21:06 +03:00
# definitions in global scope can only start with types
2008-10-16 09:02:30 +04:00
} elsif ( $ s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s ) {
2008-06-06 09:46:01 +04:00
possible ( $ 1 , "B:" . $ s ) ;
2008-02-08 15:20:54 +03:00
}
2007-11-29 03:21:06 +03:00
# any (foo ... *) is a pointer cast, and foo is a type
2009-01-07 01:41:21 +03:00
while ( $ s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg ) {
2008-06-06 09:46:01 +04:00
possible ( $ 1 , "C:" . $ s ) ;
2007-11-29 03:21:06 +03:00
}
# Check for any sort of function declaration.
# int foo(something bar, other baz);
# void (*store_gdt)(x86_descr_ptr *);
2008-04-29 11:59:32 +04:00
if ( $ prev_values eq 'E' && $ s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s ) {
2007-11-29 03:21:06 +03:00
my ( $ name_len ) = length ( $ 1 ) ;
2008-03-05 01:28:20 +03:00
my $ ctx = $ s ;
2008-03-29 00:15:58 +03:00
substr ( $ ctx , 0 , $ name_len + 1 , '' ) ;
2007-11-29 03:21:06 +03:00
$ ctx =~ s/\)[^\)]*$// ;
2008-03-05 01:28:20 +03:00
2007-11-29 03:21:06 +03:00
for my $ arg ( split ( /\s*,\s*/ , $ ctx ) ) {
2008-06-06 09:46:01 +04:00
if ( $ arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $ arg =~ /^($Ident)$/s ) {
2007-11-29 03:21:06 +03:00
2008-06-06 09:46:01 +04:00
possible ( $ 1 , "D:" . $ s ) ;
2007-11-29 03:21:06 +03:00
}
}
2007-10-17 10:29:38 +04:00
}
2007-11-29 03:21:06 +03:00
2007-10-17 10:29:38 +04:00
}
2007-06-24 04:16:34 +04:00
#
# Checks which may be anchored in the context.
#
2007-06-09 00:47:06 +04:00
2007-06-24 04:16:34 +04:00
# Check for switch () and associated case and default
# statements should be at the same indent.
2007-06-09 00:47:06 +04:00
if ( $ line =~ /\bswitch\s*\(.*\)/ ) {
my $ err = '' ;
my $ sep = '' ;
my @ ctx = ctx_block_outer ( $ linenr , $ realcnt ) ;
shift ( @ ctx ) ;
for my $ ctx ( @ ctx ) {
my ( $ clen , $ cindent ) = line_stats ( $ ctx ) ;
if ( $ ctx =~ /^\+\s*(case\s+|default:)/ &&
$ indent != $ cindent ) {
$ err . = "$sep$ctx\n" ;
$ sep = '' ;
} else {
$ sep = "[...]\n" ;
}
}
if ( $ err ne '' ) {
2007-10-17 10:29:38 +04:00
ERROR ( "switch and case should be at the same indent\n$hereline$err" ) ;
2007-07-16 10:37:22 +04:00
}
}
# if/while/etc brace do not go on next line, unless defining a do while loop,
# or if that brace on the next line is for something else
2008-06-06 09:46:01 +04:00
if ( $ line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $ line !~ /^.\s*\#/ ) {
2008-03-29 00:15:58 +03:00
my $ pre_ctx = "$1$2" ;
2007-10-17 10:29:38 +04:00
my ( $ level , @ ctx ) = ctx_statement_level ( $ linenr , $ realcnt , 0 ) ;
2007-07-16 10:37:22 +04:00
my $ ctx_cnt = $ realcnt - $# ctx - 1 ;
my $ ctx = join ( "\n" , @ ctx ) ;
2008-07-24 08:29:01 +04:00
my $ ctx_ln = $ linenr ;
my $ ctx_skip = $ realcnt ;
2008-03-29 00:15:58 +03:00
2008-07-24 08:29:01 +04:00
while ( $ ctx_skip > $ ctx_cnt || ( $ ctx_skip == $ ctx_cnt &&
defined $ lines [ $ ctx_ln - 1 ] &&
$ lines [ $ ctx_ln - 1 ] =~ /^-/ ) ) {
##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
$ ctx_skip - - if ( ! defined $ lines [ $ ctx_ln - 1 ] || $ lines [ $ ctx_ln - 1 ] !~ /^-/ ) ;
2007-07-16 10:37:22 +04:00
$ ctx_ln + + ;
}
2008-07-24 08:29:01 +04:00
2008-07-24 08:29:03 +04:00
#print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
#print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
2007-07-16 10:37:22 +04:00
2008-03-29 00:15:58 +03:00
if ( $ ctx !~ /{\s*/ && defined ( $ lines [ $ ctx_ln - 1 ] ) && $ lines [ $ ctx_ln - 1 ] =~ /^\+\s*{/ ) {
ERROR ( "that open brace { should be on the previous line\n" .
2010-10-27 01:23:19 +04:00
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n" ) ;
2007-06-09 00:47:06 +04:00
}
2008-03-29 00:15:58 +03:00
if ( $ level == 0 && $ pre_ctx !~ /}\s*while\s*\($/ &&
$ ctx =~ /\)\s*\;\s*$/ &&
defined $ lines [ $ ctx_ln - 1 ] )
{
2007-10-17 10:29:38 +04:00
my ( $ nlength , $ nindent ) = line_stats ( $ lines [ $ ctx_ln - 1 ] ) ;
if ( $ nindent > $ indent ) {
2008-03-29 00:15:58 +03:00
WARN ( "trailing semicolon indicates no statements, indent implies otherwise\n" .
2010-10-27 01:23:19 +04:00
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n" ) ;
2007-10-17 10:29:38 +04:00
}
}
2007-06-09 00:47:06 +04:00
}
2008-10-16 09:02:21 +04:00
# Check relative indent for conditionals and blocks.
if ( $ line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $ line !~ /^.\s*#/ && $ line !~ /\}\s*while\s*/ ) {
my ( $ s , $ c ) = ( $ stat , $ cond ) ;
substr ( $ s , 0 , length ( $ c ) , '' ) ;
# Make sure we remove the line prefixes as we have
# none on the first line, and are going to readd them
# where necessary.
$ s =~ s/\n./\n/gs ;
# Find out how long the conditional actually is.
2008-10-16 09:02:27 +04:00
my @ newlines = ( $ c =~ /\n/gs ) ;
my $ cond_lines = 1 + $# newlines ;
2008-10-16 09:02:21 +04:00
# We want to check the first line inside the block
# starting at the end of the conditional, so remove:
# 1) any blank line termination
# 2) any opening brace { on end of the line
# 3) any do (...) {
my $ continuation = 0 ;
my $ check = 0 ;
$ s =~ s/^.*\bdo\b// ;
$ s =~ s/^\s*{// ;
if ( $ s =~ s/^\s*\\// ) {
$ continuation = 1 ;
}
2008-10-16 09:02:22 +04:00
if ( $ s =~ s/^\s*?\n// ) {
2008-10-16 09:02:21 +04:00
$ check = 1 ;
$ cond_lines + + ;
}
# Also ignore a loop construct at the end of a
# preprocessor statement.
if ( ( $ prevline =~ /^.\s*#\s*define\s/ ||
$ prevline =~ /\\\s*$/ ) && $ continuation == 0 ) {
$ check = 0 ;
}
2008-10-16 09:02:22 +04:00
my $ cond_ptr = - 1 ;
2008-10-16 09:02:35 +04:00
$ continuation = 0 ;
2008-10-16 09:02:22 +04:00
while ( $ cond_ptr != $ cond_lines ) {
$ cond_ptr = $ cond_lines ;
2008-10-16 09:02:32 +04:00
# If we see an #else/#elif then the code
# is not linear.
if ( $ s =~ /^\s*\#\s*(?:else|elif)/ ) {
$ check = 0 ;
}
2008-10-16 09:02:22 +04:00
# Ignore:
# 1) blank lines, they should be at 0,
# 2) preprocessor lines, and
# 3) labels.
2008-10-16 09:02:35 +04:00
if ( $ continuation ||
$ s =~ /^\s*?\n/ ||
2008-10-16 09:02:22 +04:00
$ s =~ /^\s*#\s*?/ ||
$ s =~ /^\s*$Ident\s*:/ ) {
2008-10-16 09:02:35 +04:00
$ continuation = ( $ s =~ /^.*?\\\n/ ) ? 1 : 0 ;
2009-09-22 04:04:36 +04:00
if ( $ s =~ s/^.*?\n// ) {
$ cond_lines + + ;
}
2008-10-16 09:02:22 +04:00
}
2008-10-16 09:02:21 +04:00
}
my ( undef , $ sindent ) = line_stats ( "+" . $ s ) ;
my $ stat_real = raw_line ( $ linenr , $ cond_lines ) ;
# Check if either of these lines are modified, else
# this is not this patch's fault.
if ( ! defined ( $ stat_real ) ||
$ stat !~ /^\+/ && $ stat_real !~ /^\+/ ) {
$ check = 0 ;
}
if ( defined ( $ stat_real ) && $ cond_lines > 1 ) {
$ stat_real = "[...]\n$stat_real" ;
}
2008-10-16 09:02:22 +04:00
#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
2008-10-16 09:02:21 +04:00
if ( $ check && ( ( $ sindent % 8 ) != 0 ||
( $ sindent <= $ indent && $ s ne '' ) ) ) {
WARN ( "suspect code indent for conditional statements ($indent, $sindent)\n" . $ herecurr . "$stat_real\n" ) ;
}
}
2007-10-18 14:05:08 +04:00
# Track the 'values' across context and added lines.
my $ opline = $ line ; $ opline =~ s/^./ / ;
2008-07-24 08:29:10 +04:00
my ( $ curr_values , $ curr_vars ) =
annotate_values ( $ opline . "\n" , $ prev_values ) ;
2007-10-18 14:05:08 +04:00
$ curr_values = $ prev_values . $ curr_values ;
2008-02-08 15:20:54 +03:00
if ( $ dbg_values ) {
my $ outline = $ opline ; $ outline =~ s/\t/ /g ;
2008-03-05 01:28:20 +03:00
print "$linenr > .$outline\n" ;
print "$linenr > $curr_values\n" ;
2008-07-24 08:29:10 +04:00
print "$linenr > $curr_vars\n" ;
2008-02-08 15:20:54 +03:00
}
2007-10-18 14:05:08 +04:00
$ prev_values = substr ( $ curr_values , - 1 ) ;
2007-06-09 00:47:06 +04:00
#ignore lines not being added
if ( $ line =~ /^[^\+]/ ) { next ; }
2007-06-24 04:16:34 +04:00
# TEST: allow direct testing of the type matcher.
2008-07-24 08:29:06 +04:00
if ( $ dbg_type ) {
if ( $ line =~ /^.\s*$Declare\s*$/ ) {
ERROR ( "TEST: is type\n" . $ herecurr ) ;
} elsif ( $ dbg_type > 1 && $ line =~ /^.+($Declare)/ ) {
ERROR ( "TEST: is not type ($1 is)\n" . $ herecurr ) ;
}
2007-06-24 04:16:34 +04:00
next ;
}
2008-10-16 09:02:17 +04:00
# TEST: allow direct testing of the attribute matcher.
if ( $ dbg_attr ) {
2009-02-28 01:03:08 +03:00
if ( $ line =~ /^.\s*$Modifier\s*$/ ) {
2008-10-16 09:02:17 +04:00
ERROR ( "TEST: is attr\n" . $ herecurr ) ;
2009-02-28 01:03:08 +03:00
} elsif ( $ dbg_attr > 1 && $ line =~ /^.+($Modifier)/ ) {
2008-10-16 09:02:17 +04:00
ERROR ( "TEST: is not attr ($1 is)\n" . $ herecurr ) ;
}
next ;
}
2007-06-24 04:16:34 +04:00
2007-07-19 12:48:34 +04:00
# check for initialisation to aggregates open brace on the next line
2009-10-27 02:50:15 +03:00
if ( $ line =~ /^.\s*{/ &&
$ prevline =~ /(?:^|[^=])=\s*$/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "that open brace { should be on the previous line\n" . $ hereprev ) ;
2007-07-19 12:48:34 +04:00
}
2007-06-24 04:16:34 +04:00
#
# Checks which are anchored on the added line.
#
# check for malformed paths in #include statements (uses RAW line)
2008-06-06 09:46:01 +04:00
if ( $ rawline =~ m {^.\s*\#\s*include\s+[<"](.*)[">]} ) {
2007-06-24 04:16:34 +04:00
my $ path = $ 1 ;
if ( $ path =~ m {//} ) {
2007-07-16 10:37:22 +04:00
ERROR ( "malformed #include filename\n" .
$ herecurr ) ;
2007-06-24 04:16:34 +04:00
}
}
2007-06-09 00:47:06 +04:00
2007-06-01 11:46:48 +04:00
# no C99 // comments
2007-06-09 00:47:06 +04:00
if ( $ line =~ m {//} ) {
2007-07-16 10:37:22 +04:00
ERROR ( "do not use C99 // comments\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-06-09 00:47:06 +04:00
# Remove C99 comments.
2007-06-01 11:46:48 +04:00
$ line =~ s@//.*@@ ;
2007-10-18 14:05:08 +04:00
$ opline =~ s@//.*@@ ;
2007-06-01 11:46:48 +04:00
2009-10-27 02:50:16 +03:00
# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
# the whole statement.
#print "APW <$lines[$realline_next - 1]>\n";
if ( defined $ realline_next &&
exists $ lines [ $ realline_next - 1 ] &&
! defined $ suppress_export { $ realline_next } &&
( $ lines [ $ realline_next - 1 ] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
$ lines [ $ realline_next - 1 ] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/ ) ) {
2010-10-27 01:23:18 +04:00
# Handle definitions which produce identifiers with
# a prefix:
# XXX(foo);
# EXPORT_SYMBOL(something_foo);
2007-06-24 04:16:34 +04:00
my $ name = $ 1 ;
2010-10-27 01:23:18 +04:00
if ( $ stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ &&
$ name =~ /^${Ident}_$2/ ) {
#print "FOO C name<$name>\n";
$ suppress_export { $ realline_next } = 1 ;
} elsif ( $ stat !~ / ( ? :
2009-10-27 02:50:16 +03:00
\ n . } \ s * $|
2008-10-16 09:02:34 +04:00
^ . DEFINE_ $ Ident \ ( \ Q $ name \ E \ ) |
^ . DECLARE_ $ Ident \ ( \ Q $ name \ E \ ) |
^ . LIST_HEAD \ ( \ Q $ name \ E \ ) |
2009-10-27 02:50:16 +03:00
^ . ( ? : $ Storage \ s + ) ? $ Type \ s * \ ( \ s * \ * \ s * \ Q $ name \ E \ s * \ ) \ s * \ ( |
\ b \ Q $ name \ E ( ? : \ s + $ Attribute ) * \ s * ( ? : ; |= | \ [ | \ ( )
2008-10-16 09:02:34 +04:00
) / x ) {
2009-10-27 02:50:16 +03:00
#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
$ suppress_export { $ realline_next } = 2 ;
} else {
$ suppress_export { $ realline_next } = 1 ;
2007-06-01 11:46:48 +04:00
}
}
2009-10-27 02:50:16 +03:00
if ( ! defined $ suppress_export { $ linenr } &&
$ prevline =~ /^.\s*$/ &&
( $ line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
$ line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/ ) ) {
#print "FOO B <$lines[$linenr - 1]>\n";
$ suppress_export { $ linenr } = 2 ;
}
if ( defined $ suppress_export { $ linenr } &&
$ suppress_export { $ linenr } == 2 ) {
WARN ( "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $ herecurr ) ;
}
2007-06-01 11:46:48 +04:00
2010-08-10 04:21:00 +04:00
# check for global initialisers.
2008-06-06 09:46:01 +04:00
if ( $ line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/ ) {
2010-08-10 04:21:00 +04:00
ERROR ( "do not initialise globals to 0 or NULL\n" .
2007-07-19 12:48:34 +04:00
$ herecurr ) ;
}
2007-06-24 04:16:34 +04:00
# check for static initialisers.
2009-01-07 01:41:28 +03:00
if ( $ line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/ ) {
2007-07-16 10:37:22 +04:00
ERROR ( "do not initialise statics to 0 or NULL\n" .
$ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2010-10-27 01:23:20 +04:00
# check for static const char * arrays.
if ( $ line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/ ) {
WARN ( "static const char * array should probably be static const char * const\n" .
$ herecurr ) ;
}
# check for static char foo[] = "bar" declarations.
if ( $ line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/ ) {
WARN ( "static char array declaration should probably be static const char\n" .
$ herecurr ) ;
}
2010-10-27 01:23:21 +04:00
# check for declarations of struct pci_device_id
if ( $ line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/ ) {
WARN ( "Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $ herecurr ) ;
}
2007-06-24 04:16:34 +04:00
# check for new typedefs, only function parameters and sparse annotations
# make sense.
if ( $ line =~ /\btypedef\s/ &&
2009-01-07 01:41:26 +03:00
$ line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
2008-06-06 09:46:01 +04:00
$ line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
2008-10-16 09:02:32 +04:00
$ line !~ /\b$typeTypedefs\b/ &&
2007-06-24 04:16:34 +04:00
$ line !~ /\b__bitwise(?:__|)\b/ ) {
2007-07-16 10:37:22 +04:00
WARN ( "do not add new typedefs\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
# * goes on variable not on type
2009-01-07 01:41:21 +03:00
# (char*[ const])
2009-02-28 01:03:07 +03:00
if ( $ line =~ m {\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)} ) {
2009-01-07 01:41:21 +03:00
my ( $ from , $ to ) = ( $ 1 , $ 1 ) ;
# Should start with a space.
$ to =~ s/^(\S)/ $1/ ;
# Should not end with a space.
$ to =~ s/\s+$// ;
# '*'s should not have spaces between.
2009-01-16 00:51:05 +03:00
while ( $ to =~ s/\*\s+\*/\*\*/ ) {
2009-01-07 01:41:21 +03:00
}
2007-06-24 04:16:44 +04:00
2009-01-07 01:41:21 +03:00
#print "from<$from> to<$to>\n";
if ( $ from ne $ to ) {
ERROR ( "\"(foo$from)\" should be \"(foo$to)\"\n" . $ herecurr ) ;
}
2009-02-28 01:03:07 +03:00
} elsif ( $ line =~ m {\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)} ) {
2009-01-07 01:41:21 +03:00
my ( $ from , $ to , $ ident ) = ( $ 1 , $ 1 , $ 2 ) ;
# Should start with a space.
$ to =~ s/^(\S)/ $1/ ;
# Should not end with a space.
$ to =~ s/\s+$// ;
# '*'s should not have spaces between.
2009-01-16 00:51:05 +03:00
while ( $ to =~ s/\*\s+\*/\*\*/ ) {
2009-01-07 01:41:21 +03:00
}
# Modifiers should have spaces.
$ to =~ s/(\b$Modifier$)/$1 / ;
2007-06-24 04:16:44 +04:00
2009-02-28 01:03:08 +03:00
#print "from<$from> to<$to> ident<$ident>\n";
if ( $ from ne $ to && $ ident !~ /^$Modifier$/ ) {
2009-01-07 01:41:21 +03:00
ERROR ( "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $ herecurr ) ;
}
2007-06-01 11:46:48 +04:00
}
# # no BUG() or BUG_ON()
# if ($line =~ /\b(BUG|BUG_ON)\b/) {
# print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
# print "$herecurr";
# $clean = 0;
# }
2007-11-29 03:21:06 +03:00
if ( $ line =~ /\bLINUX_VERSION_CODE\b/ ) {
2008-02-08 15:20:54 +03:00
WARN ( "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $ herecurr ) ;
2007-11-29 03:21:06 +03:00
}
2007-06-09 00:47:06 +04:00
# printk should use KERN_* levels. Note that follow on printk's on the
# same line do not need a level, so we use the current block context
# to try and find and validate the current printk. In summary the current
# printk includes all preceeding printk's which have no newline on the end.
# we assume the first bad printk is the one to report.
2007-07-19 12:48:34 +04:00
if ( $ line =~ /\bprintk\((?!KERN_)\s*"/ ) {
2007-06-09 00:47:06 +04:00
my $ ok = 0 ;
for ( my $ ln = $ linenr - 1 ; $ ln >= $ first_line ; $ ln - - ) {
#print "CHECK<$lines[$ln - 1]\n";
# we have a preceeding printk if it ends
# 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 ) {
2007-07-16 10:37:22 +04:00
WARN ( "printk() should include KERN_ facility level\n" . $ herecurr ) ;
2007-06-09 00:47:06 +04:00
}
2007-06-01 11:46:48 +04:00
}
2007-06-24 04:16:34 +04:00
# function brace can't be on same line, except for #defines of do while,
# or if closed on same line
2008-06-06 09:46:01 +04:00
if ( ( $ line =~ /$Type\s*$Ident\(.*\).*\s{/ ) and
! ( $ line =~ /\#\s*define.*do\s{/ ) and ! ( $ line =~ /}/ ) ) {
2007-07-16 10:37:22 +04:00
ERROR ( "open brace '{' following function declarations go on the next line\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-06-24 04:16:34 +04:00
2007-11-29 03:21:06 +03:00
# open braces for enum, union and struct go on the same line.
if ( $ line =~ /^.\s*{/ &&
$ prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/ ) {
ERROR ( "open brace '{' following $1 go on the same line\n" . $ hereprev ) ;
}
2010-10-27 01:23:15 +04:00
# missing space after union, struct or enum definition
if ( $ line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/ ) {
WARN ( "missing space after $1 definition\n" . $ herecurr ) ;
}
2008-07-24 08:29:02 +04:00
# check for spacing round square brackets; allowed:
# 1. with a type on the left -- int [] a;
2008-10-16 09:02:15 +04:00
# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
# 3. inside a curly brace -- = { [0...10] = 5 }
2008-07-24 08:29:02 +04:00
while ( $ line =~ /(.*?\s)\[/g ) {
my ( $ where , $ prefix ) = ( $- [ 1 ] , $ 1 ) ;
if ( $ prefix !~ /$Type\s+$/ &&
2008-10-16 09:02:15 +04:00
( $ where != 0 || $ prefix !~ /^.\s+$/ ) &&
$ prefix !~ /{\s+$/ ) {
2008-07-24 08:29:02 +04:00
ERROR ( "space prohibited before open square bracket '['\n" . $ herecurr ) ;
}
}
2007-07-19 12:48:34 +04:00
# check for spaces between functions and their parentheses.
2007-10-18 14:05:08 +04:00
while ( $ line =~ /($Ident)\s+\(/g ) {
2008-02-08 15:20:54 +03:00
my $ name = $ 1 ;
2008-03-29 00:15:58 +03:00
my $ ctx_before = substr ( $ line , 0 , $- [ 1 ] ) ;
my $ ctx = "$ctx_before$name" ;
2008-02-08 15:20:54 +03:00
# Ignore those directives where spaces _are_ permitted.
2008-03-29 00:15:58 +03:00
if ( $ name =~ / ^ ( ? :
if | for | while | switch | return | case |
volatile | __volatile__ |
__attribute__ | format | __extension__ |
asm | __asm__ ) $ / x )
{
2008-02-08 15:20:54 +03:00
# cpp #define statements have non-optional spaces, ie
# if there is a space between the name and the open
# parenthesis it is simply not a parameter group.
2008-06-06 09:46:01 +04:00
} elsif ( $ ctx_before =~ /^.\s*\#\s*define\s*$/ ) {
2008-03-29 00:15:58 +03:00
# cpp #elif statement condition may start with a (
2008-06-06 09:46:01 +04:00
} elsif ( $ ctx =~ /^.\s*\#\s*elif\s*$/ ) {
2008-02-08 15:20:54 +03:00
# If this whole things ends with a type its most
# likely a typedef for a function.
2008-03-29 00:15:58 +03:00
} elsif ( $ ctx =~ /$Type$/ ) {
2008-02-08 15:20:54 +03:00
} else {
2008-03-29 00:15:58 +03:00
WARN ( "space prohibited between function name and open parenthesis '('\n" . $ herecurr ) ;
2007-10-18 14:05:08 +04:00
}
2007-07-19 12:48:34 +04:00
}
2007-06-24 04:16:34 +04:00
# Check operator spacing.
2007-06-01 11:46:48 +04:00
if ( ! ( $ line =~ /\#\s*include/ ) ) {
2007-10-17 10:29:38 +04:00
my $ ops = qr{
<<=|> >= | <=|> = |= = | != |
\ += | -= | \ *= | \ /= | % = | \ ^ = | \ | = | & = |
= > | - > | <<|> > | <|> |= | ! | ~ |
2008-07-24 08:29:10 +04:00
&& | \ | \ || , | \ ^ | \ + \ + | - - | & | \ || \ + | - | \ * | \ / | % |
\ ? | :
2007-10-17 10:29:38 +04:00
} x ;
2008-03-05 01:28:20 +03:00
my @ elements = split ( /($ops|;)/ , $ opline ) ;
2007-06-09 00:47:06 +04:00
my $ off = 0 ;
2007-10-18 14:05:08 +04:00
my $ blank = copy_spacing ( $ opline ) ;
2007-06-01 11:46:48 +04:00
for ( my $ n = 0 ; $ n < $# elements ; $ n += 2 ) {
2007-06-09 00:46:39 +04:00
$ off += length ( $ elements [ $ n ] ) ;
2008-03-29 00:15:58 +03:00
# Pick up the preceeding and succeeding characters.
my $ ca = substr ( $ opline , 0 , $ off ) ;
my $ cc = '' ;
if ( length ( $ opline ) >= ( $ off + length ( $ elements [ $ n + 1 ] ) ) ) {
$ cc = substr ( $ opline , $ off + length ( $ elements [ $ n + 1 ] ) ) ;
}
my $ cb = "$ca$;$cc" ;
2007-06-09 00:46:39 +04:00
my $ a = '' ;
$ a = 'V' if ( $ elements [ $ n ] ne '' ) ;
$ a = 'W' if ( $ elements [ $ n ] =~ /\s$/ ) ;
2008-03-05 01:28:20 +03:00
$ a = 'C' if ( $ elements [ $ n ] =~ /$;$/ ) ;
2007-06-09 00:46:39 +04:00
$ a = 'B' if ( $ elements [ $ n ] =~ /(\[|\()$/ ) ;
$ a = 'O' if ( $ elements [ $ n ] eq '' ) ;
2008-03-29 00:15:58 +03:00
$ a = 'E' if ( $ ca =~ /^\s*$/ ) ;
2007-06-09 00:46:39 +04:00
2007-06-01 11:46:48 +04:00
my $ op = $ elements [ $ n + 1 ] ;
2007-06-09 00:46:39 +04:00
my $ c = '' ;
2007-06-01 11:46:48 +04:00
if ( defined $ elements [ $ n + 2 ] ) {
2007-06-09 00:46:39 +04:00
$ c = 'V' if ( $ elements [ $ n + 2 ] ne '' ) ;
$ c = 'W' if ( $ elements [ $ n + 2 ] =~ /^\s/ ) ;
2008-03-05 01:28:20 +03:00
$ c = 'C' if ( $ elements [ $ n + 2 ] =~ /^$;/ ) ;
2007-06-09 00:46:39 +04:00
$ c = 'B' if ( $ elements [ $ n + 2 ] =~ /^(\)|\]|;)/ ) ;
$ c = 'O' if ( $ elements [ $ n + 2 ] eq '' ) ;
2009-01-07 01:41:27 +03:00
$ c = 'E' if ( $ elements [ $ n + 2 ] =~ /^\s*\\$/ ) ;
2007-06-09 00:46:39 +04:00
} else {
$ c = 'E' ;
2007-06-01 11:46:48 +04:00
}
2007-06-09 00:46:39 +04:00
my $ ctx = "${a}x${c}" ;
my $ at = "(ctx:$ctx)" ;
2007-10-18 14:05:08 +04:00
my $ ptr = substr ( $ blank , 0 , $ off ) . "^" ;
2007-07-16 10:37:22 +04:00
my $ hereptr = "$hereline$ptr\n" ;
2007-06-01 11:46:48 +04:00
2008-07-24 08:29:10 +04:00
# Pull out the value of this operator.
2007-10-18 14:05:08 +04:00
my $ op_type = substr ( $ curr_values , $ off + 1 , 1 ) ;
2007-06-01 11:46:48 +04:00
2008-07-24 08:29:10 +04:00
# Get the full operator variant.
my $ opv = $ op . substr ( $ curr_vars , $ off , 1 ) ;
2008-02-08 15:22:03 +03:00
# Ignore operators passed as parameters.
if ( $ op_type ne 'V' &&
$ ca =~ /\s$/ && $ cc =~ /^\s*,/ ) {
2008-03-05 01:28:20 +03:00
# # Ignore comments
# } elsif ($op =~ /^$;+$/) {
2008-02-08 15:22:03 +03:00
2007-06-24 04:16:44 +04:00
# ; should have either the end of line or a space or \ after it
2008-02-08 15:22:03 +03:00
} elsif ( $ op eq ';' ) {
2008-03-05 01:28:20 +03:00
if ( $ ctx !~ /.x[WEBC]/ &&
$ cc !~ /^\\/ && $ cc !~ /^;/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space required after that '$op' $at\n" . $ hereptr ) ;
2007-06-24 04:16:44 +04:00
}
# // is a comment
} elsif ( $ op eq '//' ) {
2007-06-01 11:46:48 +04:00
2008-07-24 08:29:10 +04:00
# No spaces for:
# ->
# : when part of a bitfield
} elsif ( $ op eq '->' || $ opv eq ':B' ) {
2007-06-09 00:46:39 +04:00
if ( $ ctx =~ /Wx.|.xW/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "spaces prohibited around that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
# , must have a space on the right.
} elsif ( $ op eq ',' ) {
2008-03-05 01:28:20 +03:00
if ( $ ctx !~ /.x[WEC]/ && $ cc !~ /^}/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space required after that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
2007-10-17 10:29:38 +04:00
# '*' as part of a type definition -- reported already.
2008-07-24 08:29:10 +04:00
} elsif ( $ opv eq '*_' ) {
2007-10-17 10:29:38 +04:00
#warn "'*' is part of type\n";
# unary operators should have a space before and
# none after. May be left adjacent to another
# unary operator, or a cast
} elsif ( $ op eq '!' || $ op eq '~' ||
2008-07-24 08:29:10 +04:00
$ opv eq '*U' || $ opv eq '-U' ||
2008-10-16 09:02:16 +04:00
$ opv eq '&U' || $ opv eq '&&U' ) {
2008-03-05 01:28:20 +03:00
if ( $ ctx !~ /[WEBC]x./ && $ ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space required before that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
2009-02-28 01:03:07 +03:00
if ( $ op eq '*' && $ cc =~ /\s*$Modifier\b/ ) {
2008-04-29 11:59:32 +04:00
# A unary '*' may be const
} elsif ( $ ctx =~ /.xW/ ) {
2009-09-22 04:04:38 +04:00
ERROR ( "space prohibited after that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
# unary ++ and unary -- are allowed no space on one side.
} elsif ( $ op eq '++' or $ op eq '--' ) {
2008-03-29 00:15:58 +03:00
if ( $ ctx !~ /[WEOBC]x[^W]/ && $ ctx !~ /[^W]x[WOBEC]/ ) {
ERROR ( "space required one side of that '$op' $at\n" . $ hereptr ) ;
}
if ( $ ctx =~ /Wx[BE]/ ||
( $ ctx =~ /Wx./ && $ cc =~ /^;/ ) ) {
ERROR ( "space prohibited before that '$op' $at\n" . $ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
2008-03-29 00:15:58 +03:00
if ( $ ctx =~ /ExW/ ) {
ERROR ( "space prohibited after that '$op' $at\n" . $ hereptr ) ;
2007-06-24 04:16:34 +04:00
}
2007-06-01 11:46:48 +04:00
2008-03-29 00:15:58 +03:00
2007-06-01 11:46:48 +04:00
# << and >> may either have or not have spaces both sides
2007-10-17 10:29:38 +04:00
} elsif ( $ op eq '<<' or $ op eq '>>' or
$ op eq '&' or $ op eq '^' or $ op eq '|' or
$ op eq '+' or $ op eq '-' or
2008-02-08 15:20:54 +03:00
$ op eq '*' or $ op eq '/' or
$ op eq '%' )
2007-06-01 11:46:48 +04:00
{
2008-03-29 00:15:58 +03:00
if ( $ ctx =~ /Wx[^WCE]|[^WCE]xW/ ) {
2007-07-16 10:37:22 +04:00
ERROR ( "need consistent spacing around '$op' $at\n" .
$ hereptr ) ;
2007-06-01 11:46:48 +04:00
}
2008-07-24 08:29:10 +04:00
# A colon needs no spaces before when it is
# terminating a case value or a label.
} elsif ( $ opv eq ':C' || $ opv eq ':L' ) {
if ( $ ctx =~ /Wx./ ) {
ERROR ( "space prohibited before that '$op' $at\n" . $ hereptr ) ;
}
2007-06-01 11:46:48 +04:00
# All the others need spaces both sides.
2008-03-05 01:28:20 +03:00
} elsif ( $ ctx !~ /[EWC]x[CWE]/ ) {
2008-07-24 08:29:10 +04:00
my $ ok = 0 ;
2007-08-11 00:01:03 +04:00
# Ignore email addresses <foo@bar>
2008-07-24 08:29:10 +04:00
if ( ( $ op eq '<' &&
$ cc =~ /^\S+\@\S+>/ ) ||
( $ op eq '>' &&
$ ca =~ /<\S+\@\S+$/ ) )
{
$ ok = 1 ;
}
# Ignore ?:
if ( ( $ opv eq ':O' && $ ca =~ /\?$/ ) ||
( $ op eq '?' && $ cc =~ /^:/ ) ) {
$ ok = 1 ;
}
if ( $ ok == 0 ) {
2008-03-29 00:15:58 +03:00
ERROR ( "spaces required around that '$op' $at\n" . $ hereptr ) ;
2007-08-11 00:01:03 +04:00
}
2007-06-01 11:46:48 +04:00
}
2007-06-09 00:46:39 +04:00
$ off += length ( $ elements [ $ n + 1 ] ) ;
2007-06-01 11:46:48 +04:00
}
}
2007-07-19 12:48:34 +04:00
# check for multiple assignments
if ( $ line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/ ) {
2007-10-18 14:05:08 +04:00
CHK ( "multiple assignments should be avoided\n" . $ herecurr ) ;
2007-07-19 12:48:34 +04:00
}
2007-08-11 00:01:03 +04:00
## # check for multiple declarations, allowing for a function declaration
## # continuation.
## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
##
## # Remove any bracketed sections to ensure we do not
## # falsly report the parameters of functions.
## my $ln = $line;
## while ($ln =~ s/\([^\(\)]*\)//g) {
## }
## if ($ln =~ /,/) {
## WARN("declaring multiple variables together should be avoided\n" . $herecurr);
## }
## }
2007-07-19 12:48:34 +04:00
2007-06-01 11:46:48 +04:00
#need space before brace following if, while, etc
2007-08-11 00:01:03 +04:00
if ( ( $ line =~ /\(.*\){/ && $ line !~ /\($Type\){/ ) ||
$ line =~ /do{/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space required before the open brace '{'\n" . $ herecurr ) ;
2007-07-16 10:37:22 +04:00
}
# closing brace should have a space following it when it has anything
# on the line
if ( $ line =~ /}(?!(?:,|;|\)))\S/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space required after that close brace '}'\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-08-11 00:01:03 +04:00
# check spacing on square brackets
if ( $ line =~ /\[\s/ && $ line !~ /\[\s*$/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space prohibited after that open square bracket '['\n" . $ herecurr ) ;
2007-08-11 00:01:03 +04:00
}
if ( $ line =~ /\s\]/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space prohibited before that close square bracket ']'\n" . $ herecurr ) ;
2007-08-11 00:01:03 +04:00
}
2008-06-06 09:46:01 +04:00
# check spacing on parentheses
2007-10-17 10:29:38 +04:00
if ( $ line =~ /\(\s/ && $ line !~ /\(\s*(?:\\)?$/ &&
$ line !~ /for\s*\(\s+;/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space prohibited after that open parenthesis '('\n" . $ herecurr ) ;
2007-08-11 00:01:03 +04:00
}
2008-02-08 15:22:03 +03:00
if ( $ line =~ /(\s+)\)/ && $ line !~ /^.\s*\)/ &&
2008-06-06 09:46:01 +04:00
$ line !~ /for\s*\(.*;\s+\)/ &&
$ line !~ /:\s+\)/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space prohibited before that close parenthesis ')'\n" . $ herecurr ) ;
2007-08-11 00:01:03 +04:00
}
2007-06-01 11:46:48 +04:00
#goto labels aren't indented, allow a single space however
2007-06-09 00:46:39 +04:00
if ( $ line =~ /^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
2007-06-01 11:46:48 +04:00
! ( $ line =~ /^. [A-Za-z\d_]+:/ ) and ! ( $ line =~ /^.\s+default:/ ) ) {
2007-07-16 10:37:22 +04:00
WARN ( "labels should not be indented\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2008-06-06 09:46:01 +04:00
# Return is not a function.
if ( defined ( $ stat ) && $ stat =~ /^.\s*return(\s*)(\(.*);/s ) {
my $ spacing = $ 1 ;
my $ value = $ 2 ;
2009-01-07 01:41:24 +03:00
# Flatten any parentheses
2010-10-27 01:23:12 +04:00
$ value =~ s/\(/ \(/g ;
$ value =~ s/\)/\) /g ;
2009-01-16 00:51:06 +03:00
while ( $ value =~ s/\[[^\{\}]*\]/1/ ||
$ value !~ / ( ? : $ Ident | - ? $ Constant ) \ s *
$ Compare \ s *
( ? : $ Ident | - ? $ Constant ) / x &&
$ value =~ s/\([^\(\)]*\)/1/ ) {
2008-06-06 09:46:01 +04:00
}
2010-10-27 01:23:12 +04:00
#print "value<$value>\n";
if ( $ value =~ /^\s*(?:$Ident|-?$Constant)\s*$/ ) {
2008-06-06 09:46:01 +04:00
ERROR ( "return is not a function, parentheses are not required\n" . $ herecurr ) ;
} elsif ( $ spacing !~ /\s+/ ) {
ERROR ( "space required before the open parenthesis '('\n" . $ herecurr ) ;
}
}
2010-10-27 01:23:14 +04:00
# Return of what appears to be an errno should normally be -'ve
if ( $ line =~ /^.\s*return\s*(E[A-Z]*)\s*;/ ) {
my $ name = $ 1 ;
if ( $ name ne 'EOF' && $ name ne 'ERROR' ) {
WARN ( "return of an errno should typically be -ve (return -$1)\n" . $ herecurr ) ;
}
}
2008-06-06 09:46:01 +04:00
2007-06-01 11:46:48 +04:00
# Need a space before open parenthesis after if, while etc
2007-06-09 00:46:39 +04:00
if ( $ line =~ /\b(if|while|for|switch)\(/ ) {
2008-03-29 00:15:58 +03:00
ERROR ( "space required before the open parenthesis '('\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2008-07-24 08:29:03 +04:00
# Check for illegal assignment in if conditional -- and check for trailing
# statements after the conditional.
2008-10-16 09:02:30 +04:00
if ( $ line =~ /do\s*(?!{)/ ) {
my ( $ stat_next ) = ctx_statement_block ( $ line_nr_next ,
$ remain_next , $ off_next ) ;
$ stat_next =~ s/\n./\n /g ;
##print "stat<$stat> stat_next<$stat_next>\n";
if ( $ stat_next =~ /^\s*while\b/ ) {
# If the statement carries leading newlines,
# then count those as offsets.
my ( $ whitespace ) =
( $ stat_next =~ /^((?:\s*\n[+-])*\s*)/s ) ;
my $ offset =
statement_rawlines ( $ whitespace ) - 1 ;
$ suppress_whiletrailers { $ line_nr_next +
$ offset } = 1 ;
}
}
if ( ! defined $ suppress_whiletrailers { $ linenr } &&
$ line =~ /\b(?:if|while|for)\s*\(/ && $ line !~ /^.\s*#/ ) {
2008-04-29 11:59:32 +04:00
my ( $ s , $ c ) = ( $ stat , $ cond ) ;
2007-11-29 03:21:06 +03:00
2009-01-07 01:41:29 +03:00
if ( $ c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s ) {
2008-02-08 15:20:54 +03:00
ERROR ( "do not use assignment in if condition\n" . $ herecurr ) ;
2007-11-29 03:21:06 +03:00
}
# Find out what is on the end of the line after the
# conditional.
2008-03-29 00:15:58 +03:00
substr ( $ s , 0 , length ( $ c ) , '' ) ;
2007-11-29 03:21:06 +03:00
$ s =~ s/\n.*//g ;
2008-02-08 15:22:03 +03:00
$ s =~ s/$;//g ; # Remove any comments
2008-07-24 08:29:03 +04:00
if ( length ( $ c ) && $ s !~ /^\s*{?\s*\\*\s*$/ &&
$ c !~ /}\s*while\s*/ )
2008-03-29 00:15:58 +03:00
{
2008-10-16 09:02:34 +04:00
# Find out how long the conditional actually is.
my @ newlines = ( $ c =~ /\n/gs ) ;
my $ cond_lines = 1 + $# newlines ;
2010-03-06 00:43:50 +03:00
my $ stat_real = '' ;
2008-10-16 09:02:34 +04:00
2010-03-06 00:43:50 +03:00
$ stat_real = raw_line ( $ linenr , $ cond_lines )
. "\n" if ( $ cond_lines ) ;
2008-10-16 09:02:34 +04:00
if ( defined ( $ stat_real ) && $ cond_lines > 1 ) {
$ stat_real = "[...]\n$stat_real" ;
}
ERROR ( "trailing statements should be on next line\n" . $ herecurr . $ stat_real ) ;
2007-11-29 03:21:06 +03:00
}
}
2008-02-08 15:22:03 +03:00
# Check for bitwise tests written as boolean
if ( $ line =~ /
( ? :
( ? : \ [ | \ ( | \ & \ & | \ | \ | )
\ s * 0 [ xX ] [ 0 - 9 ] + \ s *
( ? : \ & \ & | \ | \ | )
|
( ? : \ & \ & | \ | \ | )
\ s * 0 [ xX ] [ 0 - 9 ] + \ s *
( ? : \ & \ & | \ | \ || \ ) | \ ] )
) / x )
{
WARN ( "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $ herecurr ) ;
}
2007-11-29 03:21:06 +03:00
# if and else should not have general statements after it
2008-02-08 15:22:03 +03:00
if ( $ line =~ /^.\s*(?:}\s*)?else\b(.*)/ ) {
my $ s = $ 1 ;
$ s =~ s/$;//g ; # Remove any comments
if ( $ s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/ ) {
ERROR ( "trailing statements should be on next line\n" . $ herecurr ) ;
}
2007-06-01 11:46:48 +04:00
}
2009-01-16 00:51:06 +03:00
# if should not continue a brace
if ( $ line =~ /}\s*if\b/ ) {
ERROR ( "trailing statements should be on next line\n" .
$ herecurr ) ;
}
2008-10-16 09:02:25 +04:00
# case and default should not have general statements after them
if ( $ line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
$ line !~ / \ G ( ? :
2008-10-16 09:02:36 +04:00
( ? : \ s * $; * ) ( ? : \ s * { ) ? ( ? : \ s * $; * ) ( ? : \ s * \ \ ) ? \ s * $|
2008-10-16 09:02:25 +04:00
\ s * return \ s +
) / xg )
{
ERROR ( "trailing statements should be on next line\n" . $ herecurr ) ;
}
2007-06-01 11:46:48 +04:00
# Check for }<nl>else {, these must be at the same
# indent level to be relevant to each other.
if ( $ prevline =~ /}\s*$/ and $ line =~ /^.\s*else\s*/ and
$ previndent == $ indent ) {
2007-07-16 10:37:22 +04:00
ERROR ( "else should follow close brace '}'\n" . $ hereprev ) ;
2007-06-01 11:46:48 +04:00
}
2008-02-08 15:20:54 +03:00
if ( $ prevline =~ /}\s*$/ and $ line =~ /^.\s*while\s*/ and
$ previndent == $ indent ) {
my ( $ s , $ c ) = ctx_statement_block ( $ linenr , $ realcnt , 0 ) ;
# Find out what is on the end of the line after the
# conditional.
2008-03-29 00:15:58 +03:00
substr ( $ s , 0 , length ( $ c ) , '' ) ;
2008-02-08 15:20:54 +03:00
$ s =~ s/\n.*//g ;
if ( $ s =~ /^\s*;/ ) {
ERROR ( "while should follow close brace '}'\n" . $ hereprev ) ;
}
}
2007-06-01 11:46:48 +04:00
#studly caps, commented out until figure out how to distinguish between use of existing and adding new
# if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
# print "No studly caps, use _\n";
# print "$herecurr";
# $clean = 0;
# }
#no spaces allowed after \ in define
2008-06-06 09:46:01 +04:00
if ( $ line =~ /\#\s*define.*\\\s$/ ) {
2007-07-16 10:37:22 +04:00
WARN ( "Whitepspace after \\ makes next lines useless\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-06-24 04:16:34 +04:00
#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
2008-06-06 09:46:01 +04:00
if ( $ tree && $ rawline =~ m {^.\s*\#\s*include\s*\<asm\/(.*)\.h\>} ) {
2008-10-16 09:02:20 +04:00
my $ file = "$1.h" ;
my $ checkfile = "include/linux/$file" ;
if ( - f "$root/$checkfile" &&
$ realfile ne $ checkfile &&
2010-08-10 04:20:57 +04:00
$ 1 !~ /$allowed_asm_includes/ )
2008-06-06 09:46:01 +04:00
{
2008-10-16 09:02:20 +04:00
if ( $ realfile =~ m {^arch/} ) {
CHK ( "Consider using #include <linux/$file> instead of <asm/$file>\n" . $ herecurr ) ;
} else {
WARN ( "Use #include <linux/$file> instead of <asm/$file>\n" . $ herecurr ) ;
}
2007-06-01 11:46:48 +04:00
}
}
2007-06-24 04:16:34 +04:00
# multi-statement macros should be enclosed in a do while loop, grab the
# first statement and ensure its the whole macro if its not enclosed
2008-03-05 01:28:20 +03:00
# in a known good container
2008-07-24 08:29:07 +04:00
if ( $ realfile !~ m @/vmlinux.lds.h$@ &&
$ line =~ /^.\s*\#\s*define\s*$Ident(\()?/ ) {
2007-06-24 04:16:44 +04:00
my $ ln = $ linenr ;
my $ cnt = $ realcnt ;
2008-06-06 09:46:01 +04:00
my ( $ off , $ dstat , $ dcond , $ rest ) ;
my $ ctx = '' ;
2007-06-24 04:16:34 +04:00
2008-06-06 09:46:01 +04:00
my $ args = defined ( $ 1 ) ;
# Find the end of the macro and limit our statement
# search to that.
while ( $ cnt > 0 && defined $ lines [ $ ln - 1 ] &&
$ lines [ $ ln - 1 ] =~ /^(?:-|..*\\$)/ )
{
$ ctx . = $ rawlines [ $ ln - 1 ] . "\n" ;
2008-07-24 08:29:00 +04:00
$ cnt - - if ( $ lines [ $ ln - 1 ] !~ /^-/ ) ;
2008-06-06 09:46:01 +04:00
$ ln + + ;
}
$ ctx . = $ rawlines [ $ ln - 1 ] ;
( $ dstat , $ dcond , $ ln , $ cnt , $ off ) =
ctx_statement_block ( $ linenr , $ ln - $ linenr + 1 , 0 ) ;
#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
2008-07-24 08:29:00 +04:00
#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
2008-06-06 09:46:01 +04:00
# Extract the remainder of the define (if any) and
# rip off surrounding spaces, and trailing \'s.
$ rest = '' ;
2008-10-16 09:02:18 +04:00
while ( $ off != 0 || ( $ cnt > 0 && $ rest =~ /\\\s*$/ ) ) {
#print "ADDING cnt<$cnt> $off <" . substr($lines[$ln - 1], $off) . "> rest<$rest>\n";
2008-07-24 08:29:00 +04:00
if ( $ off != 0 || $ lines [ $ ln - 1 ] !~ /^-/ ) {
$ rest . = substr ( $ lines [ $ ln - 1 ] , $ off ) . "\n" ;
$ cnt - - ;
}
2008-06-06 09:46:01 +04:00
$ ln + + ;
$ off = 0 ;
}
$ rest =~ s/\\\n.//g ;
$ rest =~ s/^\s*//s ;
$ rest =~ s/\s*$//s ;
# Clean up the original statement.
if ( $ args ) {
substr ( $ dstat , 0 , length ( $ dcond ) , '' ) ;
} else {
$ dstat =~ s/^.\s*\#\s*define\s+$Ident\s*// ;
2007-06-24 04:16:44 +04:00
}
2008-07-24 08:29:11 +04:00
$ dstat =~ s/$;//g ;
2008-06-06 09:46:01 +04:00
$ dstat =~ s/\\\n.//g ;
$ dstat =~ s/^\s*//s ;
$ dstat =~ s/\s*$//s ;
2007-07-16 10:37:22 +04:00
2008-06-06 09:46:01 +04:00
# Flatten any parentheses and braces
2008-10-16 09:02:33 +04:00
while ( $ dstat =~ s/\([^\(\)]*\)/1/ ||
$ dstat =~ s/\{[^\{\}]*\}/1/ ||
$ dstat =~ s/\[[^\{\}]*\]/1/ )
{
2007-07-16 10:37:22 +04:00
}
2007-06-24 04:16:44 +04:00
2008-06-06 09:46:01 +04:00
my $ exceptions = qr{
$ Declare |
module_param_named |
MODULE_PARAM_DESC |
DECLARE_PER_CPU |
DEFINE_PER_CPU |
2009-01-07 01:41:18 +03:00
__typeof__ \ ( |
2010-03-06 00:43:52 +03:00
union |
struct |
2009-09-22 04:04:38 +04:00
\ . $ Ident \ s *= \ s * |
^ \ " | \ " $
2008-06-06 09:46:01 +04:00
} x ;
2010-10-27 01:23:18 +04:00
#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
if ( $ rest ne '' && $ rest ne ',' ) {
2008-06-06 09:46:01 +04:00
if ( $ rest !~ /while\s*\(/ &&
$ dstat !~ /$exceptions/ )
{
2007-07-16 10:37:22 +04:00
ERROR ( "Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n" ) ;
2008-06-06 09:46:01 +04:00
}
} elsif ( $ ctx !~ /;/ ) {
if ( $ dstat ne '' &&
$ dstat !~ /^(?:$Ident|-?$Constant)$/ &&
$ dstat !~ /$exceptions/ &&
2008-10-16 09:02:31 +04:00
$ dstat !~ /^\.$Ident\s*=/ &&
2008-06-06 09:46:01 +04:00
$ dstat =~ /$Operators/ )
{
2007-07-16 10:37:22 +04:00
ERROR ( "Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n" ) ;
2007-06-24 04:16:44 +04:00
}
2007-06-24 04:16:34 +04:00
}
2007-06-01 11:46:48 +04:00
}
2009-01-07 01:41:25 +03:00
# make sure symbols are always wrapped with VMLINUX_SYMBOL() ...
# all assignments may have only one of the following with an assignment:
# .
# ALIGN(...)
# VMLINUX_SYMBOL(...)
if ( $ realfile eq 'vmlinux.lds.h' && $ line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/ ) {
WARN ( "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $ herecurr ) ;
}
2007-07-19 12:48:34 +04:00
# check for redundant bracing round if etc
2008-02-08 15:22:03 +03:00
if ( $ line =~ /(^.*)\bif\b/ && $ 1 !~ /else\s*$/ ) {
my ( $ level , $ endln , @ chunks ) =
2008-03-05 01:28:20 +03:00
ctx_statement_full ( $ linenr , $ realcnt , 1 ) ;
2008-02-08 15:22:03 +03:00
#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
2008-03-05 01:28:20 +03:00
#print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
if ( $# chunks > 0 && $ level == 0 ) {
2008-02-08 15:22:03 +03:00
my $ allowed = 0 ;
my $ seen = 0 ;
2008-03-29 00:15:58 +03:00
my $ herectx = $ here . "\n" ;
2008-03-05 01:28:20 +03:00
my $ ln = $ linenr - 1 ;
2008-02-08 15:22:03 +03:00
for my $ chunk ( @ chunks ) {
my ( $ cond , $ block ) = @ { $ chunk } ;
2008-03-29 00:15:58 +03:00
# If the condition carries leading newlines, then count those as offsets.
my ( $ whitespace ) = ( $ cond =~ /^((?:\s*\n[+-])*\s*)/s ) ;
my $ offset = statement_rawlines ( $ whitespace ) - 1 ;
#print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
# We have looked at and allowed this specific line.
$ suppress_ifbraces { $ ln + $ offset } = 1 ;
$ herectx . = "$rawlines[$ln + $offset]\n[...]\n" ;
2008-03-05 01:28:20 +03:00
$ ln += statement_rawlines ( $ block ) - 1 ;
2008-03-29 00:15:58 +03:00
substr ( $ block , 0 , length ( $ cond ) , '' ) ;
2008-02-08 15:22:03 +03:00
$ seen + + if ( $ block =~ /^\s*{/ ) ;
2008-03-05 01:28:20 +03:00
#print "cond<$cond> block<$block> allowed<$allowed>\n";
if ( statement_lines ( $ cond ) > 1 ) {
#print "APW: ALLOWED: cond<$cond>\n";
2008-02-08 15:22:03 +03:00
$ allowed = 1 ;
}
if ( $ block =~ /\b(?:if|for|while)\b/ ) {
2008-03-05 01:28:20 +03:00
#print "APW: ALLOWED: block<$block>\n";
2008-02-08 15:22:03 +03:00
$ allowed = 1 ;
}
2008-03-05 01:28:20 +03:00
if ( statement_block_size ( $ block ) > 1 ) {
#print "APW: ALLOWED: lines block<$block>\n";
2008-02-08 15:22:03 +03:00
$ allowed = 1 ;
}
}
if ( $ seen && ! $ allowed ) {
2008-03-05 01:28:20 +03:00
WARN ( "braces {} are not necessary for any arm of this statement\n" . $ herectx ) ;
2008-02-08 15:22:03 +03:00
}
}
}
2008-03-29 00:15:58 +03:00
if ( ! defined $ suppress_ifbraces { $ linenr - 1 } &&
2008-02-08 15:22:03 +03:00
$ line =~ /\b(if|while|for|else)\b/ ) {
2008-03-05 01:28:20 +03:00
my $ allowed = 0 ;
# Check the pre-context.
if ( substr ( $ line , 0 , $- [ 0 ] ) =~ /(\}\s*)$/ ) {
#print "APW: ALLOWED: pre<$1>\n";
$ allowed = 1 ;
}
2008-03-29 00:15:58 +03:00
my ( $ level , $ endln , @ chunks ) =
ctx_statement_full ( $ linenr , $ realcnt , $- [ 0 ] ) ;
2008-03-05 01:28:20 +03:00
# Check the condition.
my ( $ cond , $ block ) = @ { $ chunks [ 0 ] } ;
2008-03-29 00:15:58 +03:00
#print "CHECKING<$linenr> cond<$cond> block<$block>\n";
2008-03-05 01:28:20 +03:00
if ( defined $ cond ) {
2008-03-29 00:15:58 +03:00
substr ( $ block , 0 , length ( $ cond ) , '' ) ;
2008-03-05 01:28:20 +03:00
}
if ( statement_lines ( $ cond ) > 1 ) {
#print "APW: ALLOWED: cond<$cond>\n";
$ allowed = 1 ;
}
if ( $ block =~ /\b(?:if|for|while)\b/ ) {
#print "APW: ALLOWED: block<$block>\n";
$ allowed = 1 ;
}
if ( statement_block_size ( $ block ) > 1 ) {
#print "APW: ALLOWED: lines block<$block>\n";
$ allowed = 1 ;
}
# Check the post-context.
if ( defined $ chunks [ 1 ] ) {
my ( $ cond , $ block ) = @ { $ chunks [ 1 ] } ;
if ( defined $ cond ) {
2008-03-29 00:15:58 +03:00
substr ( $ block , 0 , length ( $ cond ) , '' ) ;
2008-03-05 01:28:20 +03:00
}
if ( $ block =~ /^\s*\{/ ) {
#print "APW: ALLOWED: chunk-1 block<$block>\n";
$ allowed = 1 ;
}
}
if ( $ level == 0 && $ block =~ /^\s*\{/ && ! $ allowed ) {
my $ herectx = $ here . "\n" ; ;
2008-10-16 09:02:23 +04:00
my $ cnt = statement_rawlines ( $ block ) ;
2008-03-05 01:28:20 +03:00
2008-10-16 09:02:23 +04:00
for ( my $ n = 0 ; $ n < $ cnt ; $ n + + ) {
$ herectx . = raw_line ( $ linenr , $ n ) . "\n" ; ;
2007-07-19 12:48:34 +04:00
}
2008-03-05 01:28:20 +03:00
WARN ( "braces {} are not necessary for single statement blocks\n" . $ herectx ) ;
2007-07-19 12:48:34 +04:00
}
}
2007-06-24 04:16:34 +04:00
# don't include deprecated include files (uses RAW line)
2007-06-09 00:46:39 +04:00
for my $ inc ( @ dep_includes ) {
2008-06-06 09:46:01 +04:00
if ( $ rawline =~ m @^.\s*\#\s*include\s*\<$inc>@ ) {
2007-07-16 10:37:22 +04:00
ERROR ( "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
}
2007-06-09 00:46:39 +04:00
# don't use deprecated functions
for my $ func ( @ dep_functions ) {
2007-06-09 00:47:06 +04:00
if ( $ line =~ /\b$func\b/ ) {
2007-07-16 10:37:22 +04:00
ERROR ( "Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $ herecurr ) ;
2007-06-09 00:46:39 +04:00
}
}
# no volatiles please
2007-10-18 14:05:08 +04:00
my $ asm_volatile = qr{ \ b(__asm__|asm) \ s+(__volatile__|volatile) \ b } ;
if ( $ line =~ /\bvolatile\b/ && $ line !~ /$asm_volatile/ ) {
2007-07-16 10:37:22 +04:00
WARN ( "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $ herecurr ) ;
2007-06-09 00:46:39 +04:00
}
2007-06-09 00:47:06 +04:00
# warn about #if 0
2008-06-06 09:46:01 +04:00
if ( $ line =~ /^.\s*\#\s*if\s+0\b/ ) {
2007-07-16 10:37:22 +04:00
CHK ( "if this code is redundant consider removing it\n" .
$ herecurr ) ;
2007-06-09 00:46:39 +04:00
}
2007-07-19 12:48:34 +04:00
# check for needless kfree() checks
if ( $ prevline =~ /\bif\s*\(([^\)]*)\)/ ) {
my $ expr = $ 1 ;
if ( $ line =~ /\bkfree\(\Q$expr\E\);/ ) {
2008-07-24 08:29:05 +04:00
WARN ( "kfree(NULL) is safe this check is probably not required\n" . $ hereprev ) ;
2007-07-19 12:48:34 +04:00
}
}
2008-07-24 08:29:04 +04:00
# check for needless usb_free_urb() checks
if ( $ prevline =~ /\bif\s*\(([^\)]*)\)/ ) {
my $ expr = $ 1 ;
if ( $ line =~ /\busb_free_urb\(\Q$expr\E\);/ ) {
WARN ( "usb_free_urb(NULL) is safe this check is probably not required\n" . $ hereprev ) ;
}
}
2007-07-19 12:48:34 +04:00
2010-08-10 04:21:01 +04:00
# prefer usleep_range over udelay
if ( $ line =~ /\budelay\s*\(\s*(\w+)\s*\)/ ) {
# ignore udelay's < 10, however
if ( ! ( ( $ 1 =~ /(\d+)/ ) && ( $ 1 < 10 ) ) ) {
CHK ( "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $ line ) ;
}
}
2010-08-10 04:21:02 +04:00
# warn about unexpectedly long msleep's
if ( $ line =~ /\bmsleep\s*\((\d+)\);/ ) {
if ( $ 1 < 20 ) {
WARN ( "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $ line ) ;
}
}
2007-06-09 00:47:06 +04:00
# warn about #ifdefs in C files
2008-06-06 09:46:01 +04:00
# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
2007-06-09 00:47:06 +04:00
# print "#ifdef in C files should be avoided\n";
# print "$herecurr";
# $clean = 0;
# }
2007-08-11 00:01:03 +04:00
# warn about spacing in #ifdefs
2008-06-06 09:46:01 +04:00
if ( $ line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/ ) {
2007-08-11 00:01:03 +04:00
ERROR ( "exactly one space required after that #$1\n" . $ herecurr ) ;
}
2007-06-09 00:46:39 +04:00
# check for spinlock_t definitions without a comment.
2008-04-29 11:59:32 +04:00
if ( $ line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
$ line =~ /^.\s*(DEFINE_MUTEX)\s*\(/ ) {
2007-06-09 00:46:39 +04:00
my $ which = $ 1 ;
if ( ! ctx_has_comment ( $ first_line , $ linenr ) ) {
2007-07-16 10:37:22 +04:00
CHK ( "$1 definition without comment\n" . $ herecurr ) ;
2007-06-09 00:46:39 +04:00
}
}
# check for memory barriers without a comment.
if ( $ line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/ ) {
if ( ! ctx_has_comment ( $ first_line , $ linenr ) ) {
2007-07-16 10:37:22 +04:00
CHK ( "memory barrier without comment\n" . $ herecurr ) ;
2007-06-09 00:46:39 +04:00
}
}
# check of hardware specific defines
2008-06-06 09:46:01 +04:00
if ( $ line =~ m @^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $ realfile !~ m @include/asm-@ ) {
2007-07-16 10:37:22 +04:00
CHK ( "architecture specific defines should be avoided\n" . $ herecurr ) ;
2007-06-01 11:46:48 +04:00
}
2007-06-24 04:16:34 +04:00
2010-05-25 01:33:30 +04:00
# Check that the storage class is at the beginning of a declaration
if ( $ line =~ /\b$Storage\b/ && $ line !~ /^.\s*$Storage\b/ ) {
WARN ( "storage class should be at the beginning of the declaration\n" . $ herecurr )
}
2007-07-16 10:37:22 +04:00
# check the location of the inline attribute, that it is between
# storage class and type.
2007-10-17 10:29:38 +04:00
if ( $ line =~ /\b$Type\s+$Inline\b/ ||
$ line =~ /\b$Inline\s+$Storage\b/ ) {
2007-07-16 10:37:22 +04:00
ERROR ( "inline keyword should sit between storage class and type\n" . $ herecurr ) ;
}
2007-11-29 03:21:06 +03:00
# Check for __inline__ and __inline, prefer inline
if ( $ line =~ /\b(__inline__|__inline)\b/ ) {
WARN ( "plain inline is preferred over $1\n" . $ herecurr ) ;
}
2011-01-13 04:00:00 +03:00
# Check for __attribute__ packed, prefer __packed
if ( $ line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/ ) {
WARN ( "__packed is preferred over __attribute__((packed))\n" . $ herecurr ) ;
}
2010-03-06 00:43:48 +03:00
# check for sizeof(&)
if ( $ line =~ /\bsizeof\s*\(\s*\&/ ) {
WARN ( "sizeof(& should be avoided\n" . $ herecurr ) ;
}
2007-07-16 10:37:22 +04:00
# check for new externs in .c files.
2008-04-29 11:59:32 +04:00
if ( $ realfile =~ /\.c$/ && defined $ stat &&
2008-06-06 09:46:01 +04:00
$ stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s )
2008-04-29 11:59:32 +04:00
{
2008-06-06 09:46:01 +04:00
my $ function_name = $ 1 ;
my $ paren_space = $ 2 ;
2008-04-29 11:59:32 +04:00
my $ s = $ stat ;
if ( defined $ cond ) {
substr ( $ s , 0 , length ( $ cond ) , '' ) ;
}
2008-06-06 09:46:01 +04:00
if ( $ s =~ /^\s*;/ &&
$ function_name ne 'uninitialized_var' )
{
2008-04-29 11:59:32 +04:00
WARN ( "externs should be avoided in .c files\n" . $ herecurr ) ;
}
if ( $ paren_space =~ /\n/ ) {
WARN ( "arguments for function declarations should follow identifier\n" . $ herecurr ) ;
}
2008-04-29 11:59:33 +04:00
} elsif ( $ realfile =~ /\.c$/ && defined $ stat &&
$ stat =~ /^.\s*extern\s+/ )
{
WARN ( "externs should be avoided in .c files\n" . $ herecurr ) ;
2007-07-16 10:37:22 +04:00
}
# checks for new __setup's
if ( $ rawline =~ /\b__setup\("([^"]*)"/ ) {
my $ name = $ 1 ;
if ( ! grep ( /$name/ , @ setup_docs ) ) {
CHK ( "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $ herecurr ) ;
}
2007-06-24 04:16:34 +04:00
}
2007-10-17 10:29:38 +04:00
# check for pointless casting of kmalloc return
2011-01-13 03:59:56 +03:00
if ( $ line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/ ) {
2007-10-17 10:29:38 +04:00
WARN ( "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $ herecurr ) ;
}
2008-02-08 15:22:03 +03:00
2011-01-13 03:59:56 +03:00
# check for multiple semicolons
if ( $ line =~ /;\s*;\s*$/ ) {
WARN ( "Statements terminations use 1 semicolon\n" . $ herecurr ) ;
}
2008-02-08 15:22:03 +03:00
# check for gcc specific __FUNCTION__
if ( $ line =~ /__FUNCTION__/ ) {
WARN ( "__func__ should be used instead of gcc specific __FUNCTION__\n" . $ herecurr ) ;
}
2008-03-29 00:15:58 +03:00
2010-09-07 18:34:01 +04:00
# check for semaphores initialized locked
if ( $ line =~ /^.\s*sema_init.+,\W?0\W?\)/ ) {
2008-03-29 00:15:58 +03:00
WARN ( "consider using a completion\n" . $ herecurr ) ;
2010-03-19 03:37:42 +03:00
2008-03-29 00:15:58 +03:00
}
2011-03-23 02:34:40 +03:00
# recommend kstrto* over simple_strto*
2008-03-29 00:15:58 +03:00
if ( $ line =~ /\bsimple_(strto.*?)\s*\(/ ) {
2011-03-23 02:34:40 +03:00
WARN ( "consider using kstrto* in preference to simple_$1\n" . $ herecurr ) ;
2008-03-29 00:15:58 +03:00
}
2008-07-24 08:28:57 +04:00
# check for __initcall(), use device_initcall() explicitly please
if ( $ line =~ /^.\s*__initcall\s*\(/ ) {
WARN ( "please use device_initcall() instead of __initcall()\n" . $ herecurr ) ;
}
2010-03-06 00:43:53 +03:00
# check for various ops structs, ensure they are const.
my $ struct_ops = qr{ acpi_dock_ops|
address_space_operations |
backlight_ops |
block_device_operations |
dentry_operations |
dev_pm_ops |
dma_map_ops |
extent_io_ops |
file_lock_operations |
file_operations |
hv_ops |
ide_dma_ops |
intel_dvo_dev_ops |
item_operations |
iwl_ops |
kgdb_arch |
kgdb_io |
kset_uevent_ops |
lock_manager_operations |
microcode_ops |
mtrr_ops |
neigh_ops |
nlmsvc_binding |
pci_raw_ops |
pipe_buf_operations |
platform_hibernation_ops |
platform_suspend_ops |
proto_ops |
rpc_pipe_ops |
seq_operations |
snd_ac97_build_ops |
soc_pcmcia_socket_ops |
stacktrace_ops |
sysfs_ops |
tty_operations |
usb_mon_operations |
wd_ops } x ;
2009-01-16 00:51:07 +03:00
if ( $ line !~ /\bconst\b/ &&
2010-03-06 00:43:53 +03:00
$ line =~ /\bstruct\s+($struct_ops)\b/ ) {
2009-01-16 00:51:07 +03:00
WARN ( "struct $1 should normally be const\n" .
$ herecurr ) ;
2009-01-07 01:41:29 +03:00
}
2008-03-29 00:15:58 +03:00
# use of NR_CPUS is usually wrong
# ignore definitions of NR_CPUS and usage to define arrays as likely right
if ( $ line =~ /\bNR_CPUS\b/ &&
2008-06-06 09:46:01 +04:00
$ line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
$ line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
2008-04-29 11:59:32 +04:00
$ line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
$ line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
$ line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/ )
2008-03-29 00:15:58 +03:00
{
WARN ( "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $ herecurr ) ;
}
2008-04-29 11:59:33 +04:00
# check for %L{u,d,i} in strings
my $ string ;
while ( $ line =~ /(?:^|")([X\t]*)(?:"|$)/g ) {
$ string = substr ( $ rawline , $- [ 1 ] , $+ [ 1 ] - $- [ 1 ] ) ;
2008-10-16 09:02:23 +04:00
$ string =~ s/%%/__/g ;
2008-04-29 11:59:33 +04:00
if ( $ string =~ /(?<!%)%L[udi]/ ) {
WARN ( "\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $ herecurr ) ;
last ;
}
}
2009-01-07 01:41:16 +03:00
# whine mightly about in_atomic
if ( $ line =~ /\bin_atomic\s*\(/ ) {
if ( $ realfile =~ m @^drivers/@ ) {
ERROR ( "do not use in_atomic in drivers\n" . $ herecurr ) ;
2009-02-28 01:03:05 +03:00
} elsif ( $ realfile !~ m @^kernel/@ ) {
2009-01-07 01:41:16 +03:00
WARN ( "use of in_atomic() is incorrect outside core kernel code\n" . $ herecurr ) ;
}
}
2010-03-19 03:37:42 +03:00
# check for lockdep_set_novalidate_class
if ( $ line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
$ line =~ /__lockdep_no_validate__\s*\)/ ) {
if ( $ realfile !~ m @^kernel/lockdep@ &&
$ realfile !~ m @^include/linux/lockdep@ &&
$ realfile !~ m @^drivers/base/core@ ) {
ERROR ( "lockdep_no_validate class is reserved for device->mutex.\n" . $ herecurr ) ;
}
}
2011-01-13 03:59:59 +03:00
if ( $ line =~ /debugfs_create_file.*S_IWUGO/ ||
$ line =~ /DEVICE_ATTR.*S_IWUGO/ ) {
WARN ( "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $ herecurr ) ;
}
2008-02-08 15:22:03 +03:00
}
# If we have no input at all, then there is nothing to report on
# so just keep quiet.
if ( $# rawlines == - 1 ) {
exit ( 0 ) ;
2007-06-01 11:46:48 +04:00
}
2007-11-29 03:21:06 +03:00
# In mailback mode only produce a report in the negative, for
# things that appear to be patches.
if ( $ mailback && ( $ clean == 1 || ! $ is_patch ) ) {
exit ( 0 ) ;
}
# This is not a patch, and we are are in 'no-patch' mode so
# just keep quiet.
if ( ! $ chk_patch && ! $ is_patch ) {
exit ( 0 ) ;
}
if ( ! $ is_patch ) {
2007-07-16 10:37:22 +04:00
ERROR ( "Does not appear to be a unified-diff format patch\n" ) ;
2007-06-01 11:46:48 +04:00
}
if ( $ is_patch && $ chk_signoff && $ signoff == 0 ) {
2007-07-16 10:37:22 +04:00
ERROR ( "Missing Signed-off-by: line(s)\n" ) ;
2007-06-01 11:46:48 +04:00
}
2007-11-29 03:21:06 +03:00
print report_dump ( ) ;
2008-02-08 15:22:03 +03:00
if ( $ summary && ! ( $ clean == 1 && $ quiet == 1 ) ) {
print "$filename " if ( $ summary_file ) ;
2007-11-29 03:21:06 +03:00
print "total: $cnt_error errors, $cnt_warn warnings, " .
( ( $ check ) ? "$cnt_chk checks, " : "" ) .
"$cnt_lines lines checked\n" ;
print "\n" if ( $ quiet == 0 ) ;
2007-07-19 12:48:34 +04:00
}
2007-11-29 03:21:06 +03:00
2010-10-27 01:23:12 +04:00
if ( $ quiet == 0 ) {
# If there were whitespace errors which cleanpatch can fix
# then suggest that.
if ( $ rpt_cleaners ) {
print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n" ;
print " scripts/cleanfile\n\n" ;
2011-03-23 02:34:43 +03:00
$ rpt_cleaners = 0 ;
2010-10-27 01:23:12 +04:00
}
}
2007-06-01 11:46:48 +04:00
if ( $ clean == 1 && $ quiet == 0 ) {
2008-02-08 15:20:54 +03:00
print "$vname has no obvious style problems and is ready for submission.\n"
2007-06-01 11:46:48 +04:00
}
if ( $ clean == 0 && $ quiet == 0 ) {
2008-02-08 15:20:54 +03:00
print "$vname has style problems, please review. If any of these errors\n" ;
2007-06-01 11:46:48 +04:00
print "are false positives report them to the maintainer, see\n" ;
print "CHECKPATCH in MAINTAINERS.\n" ;
}
2008-02-08 15:22:03 +03:00
2007-06-01 11:46:48 +04:00
return $ clean ;
}