From nobody Mon Apr 13 10:36:44 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55F95C25B0E for ; Wed, 17 Aug 2022 02:09:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238230AbiHQCJT (ORCPT ); Tue, 16 Aug 2022 22:09:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235578AbiHQCJR (ORCPT ); Tue, 16 Aug 2022 22:09:17 -0400 Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E81A72EFE for ; Tue, 16 Aug 2022 19:09:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:In-Reply-To:Content-Type: MIME-Version:References:Message-ID:Subject:Cc:To:From:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=UqfDOtFL88O/ngk18Gb6f26efe0b8kcOH2WagPc1jmg=; b=gr+V9x0u5FZQuJegT+Uz+F/KmH MT+a6QHLfb1RRTlCxJX7AjTGT6kSiKOHgCbFMEhzL1IqAj3ENan3kbn8xMBZNZ7kbcw37+R6ugJuy KC+6KuZGhyv+oYKLsqwlCOIw5WKTi1wVgki9o+GQhJYFEyF1LUJwADTCIAsMiOTK+kN2vsiNyZG9+ WSqIwittIqJeqwWmvdW69muxTjzAQpPawL8lBNbdgtz+OOftmh/Z45ZNsO8++bf6AoFSrQVuhBuhL ZdAI6yLaCD44EhBuCHHVUG8UnWX+RSD5EODFgtKr+fIa8blOotru1B6G67UvRol+oIyKmJ3rTE6Ux gyWrhuTQ==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.95 #2 (Red Hat Linux)) id 1oO8UQ-005EN3-Vr; Wed, 17 Aug 2022 02:09:03 +0000 Date: Wed, 17 Aug 2022 03:09:02 +0100 From: Al Viro To: Paul Lemmermann Cc: arnd@arndb.de, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org Subject: [PATCH] improve the kernel quality and reduce the amount of BS patches Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Sender: Al Viro Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" this idiocy has gone too far =20 Signed-off-by: Al Viro --- diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl deleted file mode 100755 index 79e759aac543..000000000000 --- a/scripts/checkpatch.pl +++ /dev/null @@ -1,7587 +0,0 @@ -#!/usr/bin/env perl -# SPDX-License-Identifier: GPL-2.0 -# -# (c) 2001, Dave Jones. (the file handling bit) -# (c) 2005, Joel Schopp (the ugly bit) -# (c) 2007,2008, Andy Whitcroft (new conditions, test sui= te) -# (c) 2008-2010 Andy Whitcroft -# (c) 2010-2018 Joe Perches - -use strict; -use warnings; -use POSIX; -use File::Basename; -use Cwd 'abs_path'; -use Term::ANSIColor qw(:constants); -use Encode qw(decode encode); - -my $P =3D $0; -my $D =3D dirname(abs_path($P)); - -my $V =3D '0.32'; - -use Getopt::Long qw(:config no_auto_abbrev); - -my $quiet =3D 0; -my $verbose =3D 0; -my %verbose_messages =3D (); -my %verbose_emitted =3D (); -my $tree =3D 1; -my $chk_signoff =3D 1; -my $chk_patch =3D 1; -my $tst_only; -my $emacs =3D 0; -my $terse =3D 0; -my $showfile =3D 0; -my $file =3D 0; -my $git =3D 0; -my %git_commits =3D (); -my $check =3D 0; -my $check_orig =3D 0; -my $summary =3D 1; -my $mailback =3D 0; -my $summary_file =3D 0; -my $show_types =3D 0; -my $list_types =3D 0; -my $fix =3D 0; -my $fix_inplace =3D 0; -my $root; -my $gitroot =3D $ENV{'GIT_DIR'}; -$gitroot =3D ".git" if !defined($gitroot); -my %debug; -my %camelcase =3D (); -my %use_type =3D (); -my @use =3D (); -my %ignore_type =3D (); -my @ignore =3D (); -my $help =3D 0; -my $configuration_file =3D ".checkpatch.conf"; -my $max_line_length =3D 100; -my $ignore_perl_version =3D 0; -my $minimum_perl_version =3D 5.10.0; -my $min_conf_desc_length =3D 4; -my $spelling_file =3D "$D/spelling.txt"; -my $codespell =3D 0; -my $codespellfile =3D "/usr/share/codespell/dictionary.txt"; -my $user_codespellfile =3D ""; -my $conststructsfile =3D "$D/const_structs.checkpatch"; -my $docsfile =3D "$D/../Documentation/dev-tools/checkpatch.rst"; -my $typedefsfile; -my $color =3D "auto"; -my $allow_c99_comments =3D 1; # Can be overridden by --ignore C99_COMMENT_= TOLERANCE -# git output parsing needs US English output, so first set backtick child = process LANGUAGE -my $git_command =3D'export LANGUAGE=3Den_US.UTF-8; git'; -my $tabsize =3D 8; -my ${CONFIG_} =3D "CONFIG_"; - -sub help { - my ($exitcode) =3D @_; - - print << "EOM"; -Usage: $P [OPTION]... [FILE]... -Version: $V - -Options: - -q, --quiet quiet - -v, --verbose verbose mode - --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 - --showfile emit diffed file position, not input file pos= ition - -g, --git treat FILE as a single commit or git revision= range - single git commit with: - - ^ - ~n - multiple git commits with: - .. - ... - - - git merges are ignored - -f, --file treat FILE as regular source file - --subjective, --strict enable more subjective tests - --list-types list the possible message types - --types TYPE(,TYPE2...) show only these comma separated message types - --ignore TYPE(,TYPE2...) ignore various comma separated message types - --show-types show the specific message type in the output - --max-line-length=3Dn set the maximum line length, (default $max_= line_length) - if exceeded, warn on patches - requires --strict for use with --file - --min-conf-desc-length=3Dn set the min description length, if shorter,= warn - --tab-size=3Dn set the number of spaces for tab (default $= tabsize) - --root=3DPATH PATH to the kernel tree root - --no-summary suppress the per-file summary - --mailback only produce a report in case of warnings/err= ors - --summary-file include the filename in summary - --debug KEY=3D[0|1] turn on/off debugging of KEY, where KEY is = one of - 'values', 'possible', 'type', and 'attr' (def= ault - is all off) - --test-only=3DWORD report only warnings/errors containing WORD - literally - --fix EXPERIMENTAL - may create horrible results - If correctable single-line errors exist, crea= te - ".EXPERIMENTAL-checkpatch-fixes" - with potential errors corrected to the prefer= red - checkpatch style - --fix-inplace EXPERIMENTAL - may create horrible results - Is the same as --fix, but overwrites the input - file. It's your fault if there's no backup o= r git - --ignore-perl-version override checking of perl version. expect - runtime errors. - --codespell Use the codespell dictionary for spelling/typ= os - (default:$codespellfile) - --codespellfile Use this codespell dictionary - --typedefsfile Read additional types from this file - --color[=3DWHEN] Use colors 'always', 'never', or only when = output - is a terminal ('auto'). Default is 'auto'. - --kconfig-prefix=3DWORD use WORD as a prefix for Kconfig symbols (d= efault - ${CONFIG_}) - -h, --help, --version display this help and exit - -When FILE is - read standard input. -EOM - - exit($exitcode); -} - -sub uniq { - my %seen; - return grep { !$seen{$_}++ } @_; -} - -sub list_types { - my ($exitcode) =3D @_; - - my $count =3D 0; - - local $/ =3D undef; - - open(my $script, '<', abs_path($P)) or - die "$P: Can't read '$P' $!\n"; - - my $text =3D <$script>; - close($script); - - my %types =3D (); - # Also catch when type or level is passed through a variable - while ($text =3D~ /(?:(\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_t= ype\s*=3D)\s*"([^"]+)"/g) { - if (defined($1)) { - if (exists($types{$2})) { - $types{$2} .=3D ",$1" if ($types{$2} ne $1); - } else { - $types{$2} =3D $1; - } - } else { - $types{$2} =3D "UNDETERMINED"; - } - } - - print("#\tMessage type\n\n"); - if ($color) { - print(" ( Color coding: "); - print(RED . "ERROR" . RESET); - print(" | "); - print(YELLOW . "WARNING" . RESET); - print(" | "); - print(GREEN . "CHECK" . RESET); - print(" | "); - print("Multiple levels / Undetermined"); - print(" )\n\n"); - } - - foreach my $type (sort keys %types) { - my $orig_type =3D $type; - if ($color) { - my $level =3D $types{$type}; - if ($level eq "ERROR") { - $type =3D RED . $type . RESET; - } elsif ($level eq "WARN") { - $type =3D YELLOW . $type . RESET; - } elsif ($level eq "CHK") { - $type =3D GREEN . $type . RESET; - } - } - print(++$count . "\t" . $type . "\n"); - if ($verbose && exists($verbose_messages{$orig_type})) { - my $message =3D $verbose_messages{$orig_type}; - $message =3D~ s/\n/\n\t/g; - print("\t" . $message . "\n\n"); - } - } - - exit($exitcode); -} - -my $conf =3D which_conf($configuration_file); -if (-f $conf) { - my @conf_args; - open(my $conffile, '<', "$conf") - or warn "$P: Can't find a readable $configuration_file file $!\n"; - - while (<$conffile>) { - my $line =3D $_; - - $line =3D~ s/\s*\n?$//g; - $line =3D~ s/^\s*//g; - $line =3D~ s/\s+/ /g; - - next if ($line =3D~ m/^\s*#/); - next if ($line =3D~ m/^\s*$/); - - my @words =3D split(" ", $line); - foreach my $word (@words) { - last if ($word =3D~ m/^#/); - push (@conf_args, $word); - } - } - close($conffile); - unshift(@ARGV, @conf_args) if @conf_args; -} - -sub load_docs { - open(my $docs, '<', "$docsfile") - or warn "$P: Can't read the documentation file $docsfile $!\n"; - - my $type =3D ''; - my $desc =3D ''; - my $in_desc =3D 0; - - while (<$docs>) { - chomp; - my $line =3D $_; - $line =3D~ s/\s+$//; - - if ($line =3D~ /^\s*\*\*(.+)\*\*$/) { - if ($desc ne '') { - $verbose_messages{$type} =3D trim($desc); - } - $type =3D $1; - $desc =3D ''; - $in_desc =3D 1; - } elsif ($in_desc) { - if ($line =3D~ /^(?:\s{4,}|$)/) { - $line =3D~ s/^\s{4}//; - $desc .=3D $line; - $desc .=3D "\n"; - } else { - $verbose_messages{$type} =3D trim($desc); - $type =3D ''; - $desc =3D ''; - $in_desc =3D 0; - } - } - } - - if ($desc ne '') { - $verbose_messages{$type} =3D trim($desc); - } - close($docs); -} - -# Perl's Getopt::Long allows options to take optional arguments after a sp= ace. -# Prevent --color by itself from consuming other arguments -foreach (@ARGV) { - if ($_ eq "--color" || $_ eq "-color") { - $_ =3D "--color=3D$color"; - } -} - -GetOptions( - 'q|quiet+' =3D> \$quiet, - 'v|verbose!' =3D> \$verbose, - 'tree!' =3D> \$tree, - 'signoff!' =3D> \$chk_signoff, - 'patch!' =3D> \$chk_patch, - 'emacs!' =3D> \$emacs, - 'terse!' =3D> \$terse, - 'showfile!' =3D> \$showfile, - 'f|file!' =3D> \$file, - 'g|git!' =3D> \$git, - 'subjective!' =3D> \$check, - 'strict!' =3D> \$check, - 'ignore=3Ds' =3D> \@ignore, - 'types=3Ds' =3D> \@use, - 'show-types!' =3D> \$show_types, - 'list-types!' =3D> \$list_types, - 'max-line-length=3Di' =3D> \$max_line_length, - 'min-conf-desc-length=3Di' =3D> \$min_conf_desc_length, - 'tab-size=3Di' =3D> \$tabsize, - 'root=3Ds' =3D> \$root, - 'summary!' =3D> \$summary, - 'mailback!' =3D> \$mailback, - 'summary-file!' =3D> \$summary_file, - 'fix!' =3D> \$fix, - 'fix-inplace!' =3D> \$fix_inplace, - 'ignore-perl-version!' =3D> \$ignore_perl_version, - 'debug=3Ds' =3D> \%debug, - 'test-only=3Ds' =3D> \$tst_only, - 'codespell!' =3D> \$codespell, - 'codespellfile=3Ds' =3D> \$user_codespellfile, - 'typedefsfile=3Ds' =3D> \$typedefsfile, - 'color=3Ds' =3D> \$color, - 'no-color' =3D> \$color, #keep old behaviors of -nocolor - 'nocolor' =3D> \$color, #keep old behaviors of -nocolor - 'kconfig-prefix=3Ds' =3D> \${CONFIG_}, - 'h|help' =3D> \$help, - 'version' =3D> \$help -) or $help =3D 2; - -if ($user_codespellfile) { - # Use the user provided codespell file unconditionally - $codespellfile =3D $user_codespellfile; -} elsif (!(-f $codespellfile)) { - # If /usr/share/codespell/dictionary.txt is not present, try to find it - # under codespell's install directory: /data/dictionary.t= xt - if (($codespell || $help) && which("python3") ne "") { - my $python_codespell_dict =3D << "EOF"; - -import os.path as op -import codespell_lib -codespell_dir =3D op.dirname(codespell_lib.__file__) -codespell_file =3D op.join(codespell_dir, 'data', 'dictionary.txt') -print(codespell_file, end=3D'') -EOF - - my $codespell_dict =3D `python3 -c "$python_codespell_dict" 2> /dev/null= `; - $codespellfile =3D $codespell_dict if (-f $codespell_dict); - } -} - -# $help is 1 if either -h, --help or --version is passed as option - exitc= ode: 0 -# $help is 2 if invalid option is passed - exitcode: 1 -help($help - 1) if ($help); - -die "$P: --git cannot be used with --file or --fix\n" if ($git && ($file |= | $fix)); -die "$P: --verbose cannot be used with --terse\n" if ($verbose && $terse); - -if ($color =3D~ /^[01]$/) { - $color =3D !$color; -} elsif ($color =3D~ /^always$/i) { - $color =3D 1; -} elsif ($color =3D~ /^never$/i) { - $color =3D 0; -} elsif ($color =3D~ /^auto$/i) { - $color =3D (-t STDOUT); -} else { - die "$P: Invalid color mode: $color\n"; -} - -load_docs() if ($verbose); -list_types(0) if ($list_types); - -$fix =3D 1 if ($fix_inplace); -$check_orig =3D $check; - -my $exit =3D 0; - -my $perl_version_ok =3D 1; -if ($^V && $^V lt $minimum_perl_version) { - $perl_version_ok =3D 0; - printf "$P: requires at least perl version %vd\n", $minimum_perl_version; - exit(1) if (!$ignore_perl_version); -} - -#if no filenames are given, push '-' to read patch from stdin -if ($#ARGV < 0) { - push(@ARGV, '-'); -} - -# skip TAB size 1 to avoid additional checks on $tabsize - 1 -die "$P: Invalid TAB size: $tabsize\n" if ($tabsize < 2); - -sub hash_save_array_words { - my ($hashRef, $arrayRef) =3D @_; - - my @array =3D split(/,/, join(',', @$arrayRef)); - foreach my $word (@array) { - $word =3D~ s/\s*\n?$//g; - $word =3D~ s/^\s*//g; - $word =3D~ s/\s+/ /g; - $word =3D~ tr/[a-z]/[A-Z]/; - - next if ($word =3D~ m/^\s*#/); - next if ($word =3D~ m/^\s*$/); - - $hashRef->{$word}++; - } -} - -sub hash_show_words { - my ($hashRef, $prefix) =3D @_; - - if (keys %$hashRef) { - print "\nNOTE: $prefix message types:"; - foreach my $word (sort keys %$hashRef) { - print " $word"; - } - print "\n"; - } -} - -hash_save_array_words(\%ignore_type, \@ignore); -hash_save_array_words(\%use_type, \@use); - -my $dbg_values =3D 0; -my $dbg_possible =3D 0; -my $dbg_type =3D 0; -my $dbg_attr =3D 0; -for my $key (keys %debug) { - ## no critic - eval "\${dbg_$key} =3D '$debug{$key}';"; - die "$@" if ($@); -} - -my $rpt_cleaners =3D 0; - -if ($terse) { - $emacs =3D 1; - $quiet++; -} - -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 =3D '.'; - } elsif ($0 =3D~ m@(.*)/scripts/[^/]*$@ && - top_of_kernel_tree($1)) { - $root =3D $1; - } - } - - if (!defined $root) { - print "Must be run from the top-level dir. of a kernel tree\n"; - exit(2); - } -} - -my $emitted_corrupt =3D 0; - -our $Ident =3D qr{ - [A-Za-z_][A-Za-z\d_]* - (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* - }x; -our $Storage =3D qr{extern|static|asmlinkage}; -our $Sparse =3D qr{ - __user| - __kernel| - __force| - __iomem| - __must_check| - __kprobes| - __ref| - __refconst| - __refdata| - __rcu| - __private - }x; -our $InitAttributePrefix =3D qr{__(?:mem|cpu|dev|net_|)}; -our $InitAttributeData =3D qr{$InitAttributePrefix(?:initdata\b)}; -our $InitAttributeConst =3D qr{$InitAttributePrefix(?:initconst\b)}; -our $InitAttributeInit =3D qr{$InitAttributePrefix(?:init\b)}; -our $InitAttribute =3D qr{$InitAttributeData|$InitAttributeConst|$InitAttr= ibuteInit}; - -# Notes to $Attribute: -# We need \b after 'init' otherwise 'initconst' will cause a false positiv= e in a check -our $Attribute =3D qr{ - const| - volatile| - __percpu| - __nocast| - __safe| - __bitwise| - __packed__| - __packed2__| - __naked| - __maybe_unused| - __always_unused| - __noreturn| - __used| - __cold| - __pure| - __noclone| - __deprecated| - __read_mostly| - __ro_after_init| - __kprobes| - $InitAttribute| - ____cacheline_aligned| - ____cacheline_aligned_in_smp| - ____cacheline_internodealigned_in_smp| - __weak| - __alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) - }x; -our $Modifier; -our $Inline =3D qr{inline|__always_inline|noinline|__inline|__inline__}; -our $Member =3D qr{->$Ident|\.$Ident|\[[^]]*\]}; -our $Lval =3D qr{$Ident(?:$Member)*}; - -our $Int_type =3D qr{(?i)llu|ull|ll|lu|ul|l|u}; -our $Binary =3D qr{(?i)0b[01]+$Int_type?}; -our $Hex =3D qr{(?i)0x[0-9a-f]+$Int_type?}; -our $Int =3D qr{[0-9]+$Int_type?}; -our $Octal =3D qr{0[0-7]+$Int_type?}; -our $String =3D qr{(?:\b[Lu])?"[X\t]*"}; -our $Float_hex =3D qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; -our $Float_dec =3D qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[= fl]?}; -our $Float_int =3D qr{(?i)[0-9]+e-?[0-9]+[fl]?}; -our $Float =3D qr{$Float_hex|$Float_dec|$Float_int}; -our $Constant =3D qr{$Float|$Binary|$Octal|$Hex|$Int}; -our $Assignment =3D qr{\*\=3D|/=3D|%=3D|\+=3D|-=3D|<<=3D|>>=3D|&=3D|\^=3D|= \|=3D|=3D}; -our $Compare =3D qr{<=3D|>=3D|=3D=3D|!=3D|<|(?}; -our $Arithmetic =3D qr{\+|-|\*|\/|%}; -our $Operators =3D qr{ - <=3D|>=3D|=3D=3D|!=3D| - =3D>|->|<<|>>|<|>|!|~| - &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic - }x; - -our $c90_Keywords =3D qr{do|for|while|if|else|return|goto|continue|switch|= default|case|break}x; - -our $BasicType; -our $NonptrType; -our $NonptrTypeMisordered; -our $NonptrTypeWithAttr; -our $Type; -our $TypeMisordered; -our $Declare; -our $DeclareMisordered; - -our $NON_ASCII_UTF8 =3D qr{ - [\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; - -our $UTF8 =3D qr{ - [\x09\x0A\x0D\x20-\x7E] # ASCII - | $NON_ASCII_UTF8 -}x; - -our $typeC99Typedefs =3D qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t}; -our $typeOtherOSTypedefs =3D qr{(?x: - u_(?:char|short|int|long) | # bsd - u(?:nchar|short|int|long) # sysv -)}; -our $typeKernelTypedefs =3D qr{(?x: - (?:__)?(?:u|s|be|le)(?:8|16|32|64)| - atomic_t -)}; -our $typeTypedefs =3D qr{(?x: - $typeC99Typedefs\b| - $typeOtherOSTypedefs\b| - $typeKernelTypedefs\b -)}; - -our $zero_initializer =3D qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b}; - -our $logFunctions =3D qr{(?x: - printk(?:_ratelimited|_once|_deferred_once|_deferred|)| - (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|inf= o|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| - TP_printk| - WARN(?:_RATELIMIT|_ONCE|)| - panic| - MODULE_[A-Z_]+| - seq_vprintf|seq_printf|seq_puts -)}; - -our $allocFunctions =3D qr{(?x: - (?:(?:devm_)? - (?:kv|k|v)[czm]alloc(?:_array)?(?:_node)? | - kstrdup(?:_const)? | - kmemdup(?:_nul)?) | - (?:\w+)?alloc_skb(?:_ip_align)? | - # dev_alloc_skb/netdev_alloc_skb, et al - dma_alloc_coherent -)}; - -our $signature_tags =3D qr{(?xi: - Signed-off-by:| - Co-developed-by:| - Acked-by:| - Tested-by:| - Reviewed-by:| - Reported-by:| - Suggested-by:| - To:| - Cc: -)}; - -our $tracing_logging_tags =3D qr{(?xi: - [=3D-]*> | - <[=3D-]* | - \[ | - \] | - start | - called | - entered | - entry | - enter | - in | - inside | - here | - begin | - exit | - end | - done | - leave | - completed | - out | - return | - [\.\!:\s]* -)}; - -sub edit_distance_min { - my (@arr) =3D @_; - my $len =3D scalar @arr; - if ((scalar @arr) < 1) { - # if underflow, return - return; - } - my $min =3D $arr[0]; - for my $i (0 .. ($len-1)) { - if ($arr[$i] < $min) { - $min =3D $arr[$i]; - } - } - return $min; -} - -sub get_edit_distance { - my ($str1, $str2) =3D @_; - $str1 =3D lc($str1); - $str2 =3D lc($str2); - $str1 =3D~ s/-//g; - $str2 =3D~ s/-//g; - my $len1 =3D length($str1); - my $len2 =3D length($str2); - # two dimensional array storing minimum edit distance - my @distance; - for my $i (0 .. $len1) { - for my $j (0 .. $len2) { - if ($i =3D=3D 0) { - $distance[$i][$j] =3D $j; - } elsif ($j =3D=3D 0) { - $distance[$i][$j] =3D $i; - } elsif (substr($str1, $i-1, 1) eq substr($str2, $j-1, 1)) { - $distance[$i][$j] =3D $distance[$i - 1][$j - 1]; - } else { - my $dist1 =3D $distance[$i][$j - 1]; #insert distance - my $dist2 =3D $distance[$i - 1][$j]; # remove - my $dist3 =3D $distance[$i - 1][$j - 1]; #replace - $distance[$i][$j] =3D 1 + edit_distance_min($dist1, $dist2, $dist3); - } - } - } - return $distance[$len1][$len2]; -} - -sub find_standard_signature { - my ($sign_off) =3D @_; - my @standard_signature_tags =3D ( - 'Signed-off-by:', 'Co-developed-by:', 'Acked-by:', 'Tested-by:', - 'Reviewed-by:', 'Reported-by:', 'Suggested-by:' - ); - foreach my $signature (@standard_signature_tags) { - return $signature if (get_edit_distance($sign_off, $signature) <=3D 2); - } - - return ""; -} - -our @typeListMisordered =3D ( - qr{char\s+(?:un)?signed}, - qr{int\s+(?:(?:un)?signed\s+)?short\s}, - qr{int\s+short(?:\s+(?:un)?signed)}, - qr{short\s+int(?:\s+(?:un)?signed)}, - qr{(?:un)?signed\s+int\s+short}, - qr{short\s+(?:un)?signed}, - qr{long\s+int\s+(?:un)?signed}, - qr{int\s+long\s+(?:un)?signed}, - qr{long\s+(?:un)?signed\s+int}, - qr{int\s+(?:un)?signed\s+long}, - qr{int\s+(?:un)?signed}, - qr{int\s+long\s+long\s+(?:un)?signed}, - qr{long\s+long\s+int\s+(?:un)?signed}, - qr{long\s+long\s+(?:un)?signed\s+int}, - qr{long\s+long\s+(?:un)?signed}, - qr{long\s+(?:un)?signed}, -); - -our @typeList =3D ( - qr{void}, - qr{(?:(?:un)?signed\s+)?char}, - qr{(?:(?:un)?signed\s+)?short\s+int}, - qr{(?:(?:un)?signed\s+)?short}, - qr{(?:(?:un)?signed\s+)?int}, - qr{(?:(?:un)?signed\s+)?long\s+int}, - qr{(?:(?:un)?signed\s+)?long\s+long\s+int}, - qr{(?:(?:un)?signed\s+)?long\s+long}, - qr{(?:(?:un)?signed\s+)?long}, - qr{(?:un)?signed}, - 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}, - @typeListMisordered, -); - -our $C90_int_types =3D qr{(?x: - long\s+long\s+int\s+(?:un)?signed| - long\s+long\s+(?:un)?signed\s+int| - long\s+long\s+(?:un)?signed| - (?:(?:un)?signed\s+)?long\s+long\s+int| - (?:(?:un)?signed\s+)?long\s+long| - int\s+long\s+long\s+(?:un)?signed| - int\s+(?:(?:un)?signed\s+)?long\s+long| - - long\s+int\s+(?:un)?signed| - long\s+(?:un)?signed\s+int| - long\s+(?:un)?signed| - (?:(?:un)?signed\s+)?long\s+int| - (?:(?:un)?signed\s+)?long| - int\s+long\s+(?:un)?signed| - int\s+(?:(?:un)?signed\s+)?long| - - int\s+(?:un)?signed| - (?:(?:un)?signed\s+)?int -)}; - -our @typeListFile =3D (); -our @typeListWithAttr =3D ( - @typeList, - qr{struct\s+$InitAttribute\s+$Ident}, - qr{union\s+$InitAttribute\s+$Ident}, -); - -our @modifierList =3D ( - qr{fastcall}, -); -our @modifierListFile =3D (); - -our @mode_permission_funcs =3D ( - ["module_param", 3], - ["module_param_(?:array|named|string)", 4], - ["module_param_array_named", 5], - ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bo= ol|blob|regset32|u32_array)", 2], - ["proc_create(?:_data|)", 2], - ["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2], - ["IIO_DEV_ATTR_[A-Z_]+", 1], - ["SENSOR_(?:DEVICE_|)ATTR_2", 2], - ["SENSOR_TEMPLATE(?:_2|)", 3], - ["__ATTR", 2], -); - -my $word_pattern =3D '\b[A-Z]?[a-z]{2,}\b'; - -#Create a search pattern for all these functions to speed up a loop below -our $mode_perms_search =3D ""; -foreach my $entry (@mode_permission_funcs) { - $mode_perms_search .=3D '|' if ($mode_perms_search ne ""); - $mode_perms_search .=3D $entry->[0]; -} -$mode_perms_search =3D "(?:${mode_perms_search})"; - -our %deprecated_apis =3D ( - "synchronize_rcu_bh" =3D> "synchronize_rcu", - "synchronize_rcu_bh_expedited" =3D> "synchronize_rcu_expedited", - "call_rcu_bh" =3D> "call_rcu", - "rcu_barrier_bh" =3D> "rcu_barrier", - "synchronize_sched" =3D> "synchronize_rcu", - "synchronize_sched_expedited" =3D> "synchronize_rcu_expedited", - "call_rcu_sched" =3D> "call_rcu", - "rcu_barrier_sched" =3D> "rcu_barrier", - "get_state_synchronize_sched" =3D> "get_state_synchronize_rcu", - "cond_synchronize_sched" =3D> "cond_synchronize_rcu", -); - -#Create a search pattern for all these strings to speed up a loop below -our $deprecated_apis_search =3D ""; -foreach my $entry (keys %deprecated_apis) { - $deprecated_apis_search .=3D '|' if ($deprecated_apis_search ne ""); - $deprecated_apis_search .=3D $entry; -} -$deprecated_apis_search =3D "(?:${deprecated_apis_search})"; - -our $mode_perms_world_writable =3D qr{ - S_IWUGO | - S_IWOTH | - S_IRWXUGO | - S_IALLUGO | - 0[0-7][0-7][2367] -}x; - -our %mode_permission_string_types =3D ( - "S_IRWXU" =3D> 0700, - "S_IRUSR" =3D> 0400, - "S_IWUSR" =3D> 0200, - "S_IXUSR" =3D> 0100, - "S_IRWXG" =3D> 0070, - "S_IRGRP" =3D> 0040, - "S_IWGRP" =3D> 0020, - "S_IXGRP" =3D> 0010, - "S_IRWXO" =3D> 0007, - "S_IROTH" =3D> 0004, - "S_IWOTH" =3D> 0002, - "S_IXOTH" =3D> 0001, - "S_IRWXUGO" =3D> 0777, - "S_IRUGO" =3D> 0444, - "S_IWUGO" =3D> 0222, - "S_IXUGO" =3D> 0111, -); - -#Create a search pattern for all these strings to speed up a loop below -our $mode_perms_string_search =3D ""; -foreach my $entry (keys %mode_permission_string_types) { - $mode_perms_string_search .=3D '|' if ($mode_perms_string_search ne ""); - $mode_perms_string_search .=3D $entry; -} -our $single_mode_perms_string_search =3D "(?:${mode_perms_string_search})"; -our $multi_mode_perms_string_search =3D qr{ - ${single_mode_perms_string_search} - (?:\s*\|\s*${single_mode_perms_string_search})* -}x; - -sub perms_to_octal { - my ($string) =3D @_; - - return trim($string) if ($string =3D~ /^\s*0[0-7]{3,3}\s*$/); - - my $val =3D ""; - my $oval =3D ""; - my $to =3D 0; - my $curpos =3D 0; - my $lastpos =3D 0; - while ($string =3D~ /\b(($single_mode_perms_string_search)\b(?:\s*\|\s*)?= \s*)/g) { - $curpos =3D pos($string); - my $match =3D $2; - my $omatch =3D $1; - last if ($lastpos > 0 && ($curpos - length($omatch) !=3D $lastpos)); - $lastpos =3D $curpos; - $to |=3D $mode_permission_string_types{$match}; - $val .=3D '\s*\|\s*' if ($val ne ""); - $val .=3D $match; - $oval .=3D $omatch; - } - $oval =3D~ s/^\s*\|\s*//; - $oval =3D~ s/\s*\|\s*$//; - return sprintf("%04o", $to); -} - -our $allowed_asm_includes =3D qr{(?x: - irq| - memory| - time| - reboot -)}; -# memory.h: ARM has a custom one - -# Load common spelling mistakes and build regular expression list. -my $misspellings; -my %spelling_fix; - -if (open(my $spelling, '<', $spelling_file)) { - while (<$spelling>) { - my $line =3D $_; - - $line =3D~ s/\s*\n?$//g; - $line =3D~ s/^\s*//g; - - next if ($line =3D~ m/^\s*#/); - next if ($line =3D~ m/^\s*$/); - - my ($suspect, $fix) =3D split(/\|\|/, $line); - - $spelling_fix{$suspect} =3D $fix; - } - close($spelling); -} else { - warn "No typos will be found - file '$spelling_file': $!\n"; -} - -if ($codespell) { - if (open(my $spelling, '<', $codespellfile)) { - while (<$spelling>) { - my $line =3D $_; - - $line =3D~ s/\s*\n?$//g; - $line =3D~ s/^\s*//g; - - next if ($line =3D~ m/^\s*#/); - next if ($line =3D~ m/^\s*$/); - next if ($line =3D~ m/, disabled/i); - - $line =3D~ s/,.*$//; - - my ($suspect, $fix) =3D split(/->/, $line); - - $spelling_fix{$suspect} =3D $fix; - } - close($spelling); - } else { - warn "No codespell typos will be found - file '$codespellfile': $!\n"; - } -} - -$misspellings =3D join("|", sort keys %spelling_fix) if keys %spelling_fix; - -sub read_words { - my ($wordsRef, $file) =3D @_; - - if (open(my $words, '<', $file)) { - while (<$words>) { - my $line =3D $_; - - $line =3D~ s/\s*\n?$//g; - $line =3D~ s/^\s*//g; - - next if ($line =3D~ m/^\s*#/); - next if ($line =3D~ m/^\s*$/); - if ($line =3D~ /\s/) { - print("$file: '$line' invalid - ignored\n"); - next; - } - - $$wordsRef .=3D '|' if (defined $$wordsRef); - $$wordsRef .=3D $line; - } - close($file); - return 1; - } - - return 0; -} - -my $const_structs; -if (show_type("CONST_STRUCT")) { - read_words(\$const_structs, $conststructsfile) - or warn "No structs that should be const will be found - file '$const= structsfile': $!\n"; -} - -if (defined($typedefsfile)) { - my $typeOtherTypedefs; - read_words(\$typeOtherTypedefs, $typedefsfile) - or warn "No additional types will be considered - file '$typedefsfile= ': $!\n"; - $typeTypedefs .=3D '|' . $typeOtherTypedefs if (defined $typeOtherTypedef= s); -} - -sub build_types { - my $mods =3D "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile= )) . "\n)"; - my $all =3D "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)= "; - my $Misordered =3D "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)= "; - my $allWithAttr =3D "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; - $Modifier =3D qr{(?:$Attribute|$Sparse|$mods)}; - $BasicType =3D qr{ - (?:$typeTypedefs\b)| - (?:${all}\b) - }x; - $NonptrType =3D qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:typeof|__typeof__)\s*\([^\)]*\)| - (?:$typeTypedefs\b)| - (?:${all}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $NonptrTypeMisordered =3D qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:${Misordered}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $NonptrTypeWithAttr =3D qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:typeof|__typeof__)\s*\([^\)]*\)| - (?:$typeTypedefs\b)| - (?:${allWithAttr}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $Type =3D qr{ - $NonptrType - (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\= ])+){0,4} - (?:\s+$Inline|\s+$Modifier)* - }x; - $TypeMisordered =3D qr{ - $NonptrTypeMisordered - (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\= ])+){0,4} - (?:\s+$Inline|\s+$Modifier)* - }x; - $Declare =3D qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; - $DeclareMisordered =3D qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered}; -} -build_types(); - -our $Typecast =3D qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; - -# Using $balanced_parens, $LvalOrFunc, or $FuncArg -# requires at least perl version v5.10.0 -# Any use must be runtime checked with $^V - -our $balanced_parens =3D qr/(\((?:[^\(\)]++|(?-1))*\))/; -our $LvalOrFunc =3D qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; -our $FuncArg =3D qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)}; - -our $declaration_macros =3D qr{(?x: - (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+)= {1,6}\s*\(| - (?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(| - (?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(| - (?:$Storage\s+)?(?:XA_STATE|XA_STATE_ORDER)\s*\( -)}; - -our %allow_repeated_words =3D ( - add =3D> '', - added =3D> '', - bad =3D> '', - be =3D> '', -); - -sub deparenthesize { - my ($string) =3D @_; - return "" if (!defined($string)); - - while ($string =3D~ /^\s*\(.*\)\s*$/) { - $string =3D~ s@^\s*\(\s*@@; - $string =3D~ s@\s*\)\s*$@@; - } - - $string =3D~ s@\s+@ @g; - - return $string; -} - -sub seed_camelcase_file { - my ($file) =3D @_; - - return if (!(-f $file)); - - local $/; - - open(my $include_file, '<', "$file") - or warn "$P: Can't read '$file' $!\n"; - my $text =3D <$include_file>; - close($include_file); - - my @lines =3D split('\n', $text); - - foreach my $line (@lines) { - next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/); - if ($line =3D~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][= a-z]|[a-z][A-Z])\w*)/) { - $camelcase{$1} =3D 1; - } elsif ($line =3D~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*= [\(\[,;]/) { - $camelcase{$1} =3D 1; - } elsif ($line =3D~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z]= [A-Z])\w*)\s*[;\{]/) { - $camelcase{$1} =3D 1; - } - } -} - -our %maintained_status =3D (); - -sub is_maintained_obsolete { - my ($filename) =3D @_; - - return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl")); - - if (!exists($maintained_status{$filename})) { - $maintained_status{$filename} =3D `perl $root/scripts/get_maintainer.pl = --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`; - } - - return $maintained_status{$filename} =3D~ /obsolete/i; -} - -sub is_SPDX_License_valid { - my ($license) =3D @_; - - return 1 if (!$tree || which("python3") eq "" || !(-x "$root/scripts/spdx= check.py") || !(-e "$gitroot")); - - my $root_path =3D abs_path($root); - my $status =3D `cd "$root_path"; echo "$license" | scripts/spdxcheck.py -= `; - return 0 if ($status ne ""); - return 1; -} - -my $camelcase_seeded =3D 0; -sub seed_camelcase_includes { - return if ($camelcase_seeded); - - my $files; - my $camelcase_cache =3D ""; - my @include_files =3D (); - - $camelcase_seeded =3D 1; - - if (-e "$gitroot") { - my $git_last_include_commit =3D `${git_command} log --no-merges --pretty= =3Dformat:"%h%n" -1 -- include`; - chomp $git_last_include_commit; - $camelcase_cache =3D ".checkpatch-camelcase.git.$git_last_include_commit= "; - } else { - my $last_mod_date =3D 0; - $files =3D `find $root/include -name "*.h"`; - @include_files =3D split('\n', $files); - foreach my $file (@include_files) { - my $date =3D POSIX::strftime("%Y%m%d%H%M", - localtime((stat $file)[9])); - $last_mod_date =3D $date if ($last_mod_date < $date); - } - $camelcase_cache =3D ".checkpatch-camelcase.date.$last_mod_date"; - } - - if ($camelcase_cache ne "" && -f $camelcase_cache) { - open(my $camelcase_file, '<', "$camelcase_cache") - or warn "$P: Can't read '$camelcase_cache' $!\n"; - while (<$camelcase_file>) { - chomp; - $camelcase{$_} =3D 1; - } - close($camelcase_file); - - return; - } - - if (-e "$gitroot") { - $files =3D `${git_command} ls-files "include/*.h"`; - @include_files =3D split('\n', $files); - } - - foreach my $file (@include_files) { - seed_camelcase_file($file); - } - - if ($camelcase_cache ne "") { - unlink glob ".checkpatch-camelcase.*"; - open(my $camelcase_file, '>', "$camelcase_cache") - or warn "$P: Can't write '$camelcase_cache' $!\n"; - foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) { - print $camelcase_file ("$_\n"); - } - close($camelcase_file); - } -} - -sub git_is_single_file { - my ($filename) =3D @_; - - return 0 if ((which("git") eq "") || !(-e "$gitroot")); - - my $output =3D `${git_command} ls-files -- $filename 2>/dev/null`; - my $count =3D $output =3D~ tr/\n//; - return $count eq 1 && $output =3D~ m{^${filename}$}; -} - -sub git_commit_info { - my ($commit, $id, $desc) =3D @_; - - return ($id, $desc) if ((which("git") eq "") || !(-e "$gitroot")); - - my $output =3D `${git_command} log --no-color --format=3D'%H %s' -1 $comm= it 2>&1`; - $output =3D~ s/^\s*//gm; - my @lines =3D split("\n", $output); - - return ($id, $desc) if ($#lines < 0); - - if ($lines[0] =3D~ /^error: short SHA1 $commit is ambiguous/) { -# Maybe one day convert this block of bash into something that returns -# all matching commit ids, but it's very slow... -# -# echo "checking commits $1..." -# git rev-list --remotes | grep -i "^$1" | -# while read line ; do -# git log --format=3D'%H %s' -1 $line | -# echo "commit $(cut -c 1-12,41-)" -# done - } elsif ($lines[0] =3D~ /^fatal: ambiguous argument '$commit': unknown re= vision or path not in the working tree\./ || - $lines[0] =3D~ /^fatal: bad object $commit/) { - $id =3D undef; - } else { - $id =3D substr($lines[0], 0, 12); - $desc =3D substr($lines[0], 41); - } - - return ($id, $desc); -} - -$chk_signoff =3D 0 if ($file); - -my @rawlines =3D (); -my @lines =3D (); -my @fixed =3D (); -my @fixed_inserted =3D (); -my @fixed_deleted =3D (); -my $fixlinenr =3D -1; - -# If input is git commits, extract all commits from the commit expressions. -# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'. -die "$P: No git repository found\n" if ($git && !-e "$gitroot"); - -if ($git) { - my @commits =3D (); - foreach my $commit_expr (@ARGV) { - my $git_range; - if ($commit_expr =3D~ m/^(.*)-(\d+)$/) { - $git_range =3D "-$2 $1"; - } elsif ($commit_expr =3D~ m/\.\./) { - $git_range =3D "$commit_expr"; - } else { - $git_range =3D "-1 $commit_expr"; - } - my $lines =3D `${git_command} log --no-color --no-merges --pretty=3Dform= at:'%H %s' $git_range`; - foreach my $line (split(/\n/, $lines)) { - $line =3D~ /^([0-9a-fA-F]{40,40}) (.*)$/; - next if (!defined($1) || !defined($2)); - my $sha1 =3D $1; - my $subject =3D $2; - unshift(@commits, $sha1); - $git_commits{$sha1} =3D $subject; - } - } - die "$P: no git commits after extraction!\n" if (@commits =3D=3D 0); - @ARGV =3D @commits; -} - -my $vname; -$allow_c99_comments =3D !defined $ignore_type{"C99_COMMENT_TOLERANCE"}; -for my $filename (@ARGV) { - my $FILE; - my $is_git_file =3D git_is_single_file($filename); - my $oldfile =3D $file; - $file =3D 1 if ($is_git_file); - if ($git) { - open($FILE, '-|', "git format-patch -M --stdout -1 $filename") || - die "$P: $filename: git format-patch failed - $!\n"; - } elsif ($file) { - open($FILE, '-|', "diff -u /dev/null $filename") || - die "$P: $filename: diff failed - $!\n"; - } elsif ($filename eq '-') { - open($FILE, '<&STDIN'); - } else { - open($FILE, '<', "$filename") || - die "$P: $filename: open failed - $!\n"; - } - if ($filename eq '-') { - $vname =3D 'Your patch'; - } elsif ($git) { - $vname =3D "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$= filename} . '")'; - } else { - $vname =3D $filename; - } - while (<$FILE>) { - chomp; - push(@rawlines, $_); - $vname =3D qq("$1") if ($filename eq '-' && $_ =3D~ m/^Subject:\s+(.+)/i= ); - } - close($FILE); - - if ($#ARGV > 0 && $quiet =3D=3D 0) { - print '-' x length($vname) . "\n"; - print "$vname\n"; - print '-' x length($vname) . "\n"; - } - - if (!process($filename)) { - $exit =3D 1; - } - @rawlines =3D (); - @lines =3D (); - @fixed =3D (); - @fixed_inserted =3D (); - @fixed_deleted =3D (); - $fixlinenr =3D -1; - @modifierListFile =3D (); - @typeListFile =3D (); - build_types(); - $file =3D $oldfile if ($is_git_file); -} - -if (!$quiet) { - hash_show_words(\%use_type, "Used"); - hash_show_words(\%ignore_type, "Ignored"); - - if (!$perl_version_ok) { - print << "EOM" - -NOTE: perl $^V is not modern enough to detect all possible issues. - An upgrade to at least perl $minimum_perl_version is suggested. -EOM - } - if ($exit) { - print << "EOM" - -NOTE: If any of the errors are false positives, please report - them to the maintainer, see CHECKPATCH in MAINTAINERS. -EOM - } -} - -exit($exit); - -sub top_of_kernel_tree { - my ($root) =3D @_; - - my @tree_check =3D ( - "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; - } - } - return 1; -} - -sub parse_email { - my ($formatted_email) =3D @_; - - my $name =3D ""; - my $quoted =3D ""; - my $name_comment =3D ""; - my $address =3D ""; - my $comment =3D ""; - - if ($formatted_email =3D~ /^(.*)<(\S+\@\S+)>(.*)$/) { - $name =3D $1; - $address =3D $2; - $comment =3D $3 if defined $3; - } elsif ($formatted_email =3D~ /^\s*<(\S+\@\S+)>(.*)$/) { - $address =3D $1; - $comment =3D $2 if defined $2; - } elsif ($formatted_email =3D~ /(\S+\@\S+)(.*)$/) { - $address =3D $1; - $comment =3D $2 if defined $2; - $formatted_email =3D~ s/\Q$address\E.*$//; - $name =3D $formatted_email; - $name =3D trim($name); - $name =3D~ s/^\"|\"$//g; - # If there's a name left after stripping spaces and - # leading quotes, and the address doesn't have both - # leading and trailing angle brackets, the address - # is invalid. ie: - # "joe smith joe@smith.com" bad - # "joe smith ]+>$/) { - $name =3D ""; - $address =3D ""; - $comment =3D ""; - } - } - - # Extract comments from names excluding quoted parts - # "John D. (Doe)" - Do not extract - if ($name =3D~ s/\"(.+)\"//) { - $quoted =3D $1; - } - while ($name =3D~ s/\s*($balanced_parens)\s*/ /) { - $name_comment .=3D trim($1); - } - $name =3D~ s/^[ \"]+|[ \"]+$//g; - $name =3D trim("$quoted $name"); - - $address =3D trim($address); - $address =3D~ s/^\<|\>$//g; - $comment =3D trim($comment); - - if ($name =3D~ /[^\w \-]/i) { ##has "must quote" chars - $name =3D~ s/(?"; - } - $formatted_email .=3D "$comment"; - return $formatted_email; -} - -sub reformat_email { - my ($email) =3D @_; - - my ($email_name, $name_comment, $email_address, $comment) =3D parse_email= ($email); - return format_email($email_name, $name_comment, $email_address, $comment); -} - -sub same_email_addresses { - my ($email1, $email2) =3D @_; - - my ($email1_name, $name1_comment, $email1_address, $comment1) =3D parse_e= mail($email1); - my ($email2_name, $name2_comment, $email2_address, $comment2) =3D parse_e= mail($email2); - - return $email1_name eq $email2_name && - $email1_address eq $email2_address && - $name1_comment eq $name2_comment && - $comment1 eq $comment2; -} - -sub which { - my ($bin) =3D @_; - - foreach my $path (split(/:/, $ENV{PATH})) { - if (-e "$path/$bin") { - return "$path/$bin"; - } - } - - return ""; -} - -sub which_conf { - my ($conf) =3D @_; - - foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { - if (-e "$path/$conf") { - return "$path/$conf"; - } - } - - return ""; -} - -sub expand_tabs { - my ($str) =3D @_; - - my $res =3D ''; - my $n =3D 0; - for my $c (split(//, $str)) { - if ($c eq "\t") { - $res .=3D ' '; - $n++; - for (; ($n % $tabsize) !=3D 0; $n++) { - $res .=3D ' '; - } - next; - } - $res .=3D $c; - $n++; - } - - return $res; -} -sub copy_spacing { - (my $res =3D shift) =3D~ tr/\t/ /c; - return $res; -} - -sub line_stats { - my ($line) =3D @_; - - # Drop the diff line leader and expand tabs - $line =3D~ s/^.//; - $line =3D expand_tabs($line); - - # Pick the indent from the front of the line. - my ($white) =3D ($line =3D~ /^(\s*)/); - - return (length($line), length($white)); -} - -my $sanitise_quote =3D ''; - -sub sanitise_line_reset { - my ($in_comment) =3D @_; - - if ($in_comment) { - $sanitise_quote =3D '*/'; - } else { - $sanitise_quote =3D ''; - } -} -sub sanitise_line { - my ($line) =3D @_; - - my $res =3D ''; - my $l =3D ''; - - my $qlen =3D 0; - my $off =3D 0; - my $c; - - # Always copy over the diff marker. - $res =3D substr($line, 0, 1); - - for ($off =3D 1; $off < length($line); $off++) { - $c =3D substr($line, $off, 1); - - # Comments we are whacking completely including the begin - # and end, all to $;. - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') { - $sanitise_quote =3D '*/'; - - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') { - $sanitise_quote =3D ''; - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') { - $sanitise_quote =3D '//'; - - substr($res, $off, 2, $sanitise_quote); - $off++; - next; - } - - # A \ in a string means ignore the next character. - if (($sanitise_quote eq "'" || $sanitise_quote eq '"') && - $c eq "\\") { - substr($res, $off, 2, 'XX'); - $off++; - next; - } - # Regular quotes. - if ($c eq "'" || $c eq '"') { - if ($sanitise_quote eq '') { - $sanitise_quote =3D $c; - - substr($res, $off, 1, $c); - next; - } elsif ($sanitise_quote eq $c) { - $sanitise_quote =3D ''; - } - } - - #print "c<$c> SQ<$sanitise_quote>\n"; - if ($off !=3D 0 && $sanitise_quote eq '*/' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off !=3D 0 && $sanitise_quote eq '//' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off !=3D 0 && $sanitise_quote && $c ne "\t") { - substr($res, $off, 1, 'X'); - } else { - substr($res, $off, 1, $c); - } - } - - if ($sanitise_quote eq '//') { - $sanitise_quote =3D ''; - } - - # The pathname on a #include may be surrounded by '<' and '>'. - if ($res =3D~ /^.\s*\#\s*include\s+\<(.*)\>/) { - my $clean =3D 'X' x length($1); - $res =3D~ s@\<.*\>@<$clean>@; - - # The whole of a #error is a string. - } elsif ($res =3D~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) { - my $clean =3D 'X' x length($1); - $res =3D~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@; - } - - if ($allow_c99_comments && $res =3D~ m@(//.*$)@) { - my $match =3D $1; - $res =3D~ s/\Q$match\E/"$;" x length($match)/e; - } - - return $res; -} - -sub get_quoted_string { - my ($line, $rawline) =3D @_; - - return "" if (!defined($line) || !defined($rawline)); - return "" if ($line !~ m/($String)/g); - return substr($rawline, $-[0], $+[0] - $-[0]); -} - -sub ctx_statement_block { - my ($linenr, $remain, $off) =3D @_; - my $line =3D $linenr - 1; - my $blk =3D ''; - my $soff =3D $off; - my $coff =3D $off - 1; - my $coff_set =3D 0; - - my $loff =3D 0; - - my $type =3D ''; - my $level =3D 0; - my @stack =3D (); - my $p; - my $c; - my $len =3D 0; - - my $remainder; - while (1) { - @stack =3D (['', 0]) if ($#stack =3D=3D -1); - - #warn "CSB: blk<$blk> remain<$remain>\n"; - # If we are about to drop off the end, pull in more - # context. - if ($off >=3D $len) { - for (; $remain > 0; $line++) { - last if (!defined $lines[$line]); - next if ($lines[$line] =3D~ /^-/); - $remain--; - $loff =3D $len; - $blk .=3D $lines[$line] . "\n"; - $len =3D length($blk); - $line++; - last; - } - # Bail if there is no further context. - #warn "CSB: blk<$blk> off<$off> len<$len>\n"; - if ($off >=3D $len) { - last; - } - if ($level =3D=3D 0 && substr($blk, $off) =3D~ /^.\s*#\s*define/) { - $level++; - $type =3D '#'; - } - } - $p =3D $c; - $c =3D substr($blk, $off, 1); - $remainder =3D substr($blk, $off); - - #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_s= et<$coff_set>\n"; - - # Handle nested #if/#else. - if ($remainder =3D~ /^#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, [ $type, $level ]); - } elsif ($remainder =3D~ /^#\s*(?:else|elif)\b/) { - ($type, $level) =3D @{$stack[$#stack - 1]}; - } elsif ($remainder =3D~ /^#\s*endif\b/) { - ($type, $level) =3D @{pop(@stack)}; - } - - # Statement ends at the ';' or a close '}' at the - # outermost level. - if ($level =3D=3D 0 && $c eq ';') { - last; - } - - # An else is really a conditional as long as its not else if - if ($level =3D=3D 0 && $coff_set =3D=3D 0 && - (!defined($p) || $p =3D~ /(?:\s|\}|\+)/) && - $remainder =3D~ /^(else)(?:\s|{)/ && - $remainder !~ /^else\s+if\b/) { - $coff =3D $off + length($1) - 1; - $coff_set =3D 1; - #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n"; - #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n"; - } - - if (($type eq '' || $type eq '(') && $c eq '(') { - $level++; - $type =3D '('; - } - if ($type eq '(' && $c eq ')') { - $level--; - $type =3D ($level !=3D 0)? '(' : ''; - - if ($level =3D=3D 0 && $coff < $soff) { - $coff =3D $off; - $coff_set =3D 1; - #warn "CSB: mark coff<$coff>\n"; - } - } - if (($type eq '' || $type eq '{') && $c eq '{') { - $level++; - $type =3D '{'; - } - if ($type eq '{' && $c eq '}') { - $level--; - $type =3D ($level !=3D 0)? '{' : ''; - - if ($level =3D=3D 0) { - if (substr($blk, $off + 1, 1) eq ';') { - $off++; - } - last; - } - } - # Preprocessor commands end at the newline unless escaped. - if ($type eq '#' && $c eq "\n" && $p ne "\\") { - $level--; - $type =3D ''; - $off++; - last; - } - $off++; - } - # We are truly at the end, so shuffle to the next line. - if ($off =3D=3D $len) { - $loff =3D $len + 1; - $line++; - $remain--; - } - - my $statement =3D substr($blk, $soff, $off - $soff + 1); - my $condition =3D substr($blk, $soff, $coff - $soff + 1); - - #warn "STATEMENT<$statement>\n"; - #warn "CONDITION<$condition>\n"; - - #print "coff<$coff> soff<$off> loff<$loff>\n"; - - return ($statement, $condition, - $line, $remain + 1, $off - $loff + 1, $level); -} - -sub statement_lines { - my ($stmt) =3D @_; - - # Strip the diff line prefixes and rip blank lines at start and end. - $stmt =3D~ s/(^|\n)./$1/g; - $stmt =3D~ s/^\s*//; - $stmt =3D~ s/\s*$//; - - my @stmt_lines =3D ($stmt =3D~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_rawlines { - my ($stmt) =3D @_; - - my @stmt_lines =3D ($stmt =3D~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_block_size { - my ($stmt) =3D @_; - - $stmt =3D~ s/(^|\n)./$1/g; - $stmt =3D~ s/^\s*{//; - $stmt =3D~ s/}\s*$//; - $stmt =3D~ s/^\s*//; - $stmt =3D~ s/\s*$//; - - my @stmt_lines =3D ($stmt =3D~ /\n/g); - my @stmt_statements =3D ($stmt =3D~ /;/g); - - my $stmt_lines =3D $#stmt_lines + 2; - my $stmt_statements =3D $#stmt_statements + 1; - - if ($stmt_lines > $stmt_statements) { - return $stmt_lines; - } else { - return $stmt_statements; - } -} - -sub ctx_statement_full { - my ($linenr, $remain, $off) =3D @_; - my ($statement, $condition, $level); - - my (@chunks); - - # Grab the first conditional/block pair. - ($statement, $condition, $linenr, $remain, $off, $level) =3D - ctx_statement_block($linenr, $remain, $off); - #print "F: c<$condition> s<$statement> remain<$remain>\n"; - push(@chunks, [ $condition, $statement ]); - if (!($remain > 0 && $condition =3D~ /^\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. - for (;;) { - ($statement, $condition, $linenr, $remain, $off, $level) =3D - ctx_statement_block($linenr, $remain, $off); - #print "C: c<$condition> s<$statement> remain<$remain>\n"; - last if (!($remain > 0 && $condition =3D~ /^(?:\s*\n[+-])*\s*(?:else|do)= \b/s)); - #print "C: push\n"; - push(@chunks, [ $condition, $statement ]); - } - - return ($level, $linenr, @chunks); -} - -sub ctx_block_get { - my ($linenr, $remain, $outer, $open, $close, $off) =3D @_; - my $line; - my $start =3D $linenr - 1; - my $blk =3D ''; - my @o; - my @c; - my @res =3D (); - - my $level =3D 0; - my @stack =3D ($level); - for ($line =3D $start; $remain > 0; $line++) { - next if ($rawlines[$line] =3D~ /^-/); - $remain--; - - $blk .=3D $rawlines[$line]; - - # Handle nested #if/#else. - if ($lines[$line] =3D~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, $level); - } elsif ($lines[$line] =3D~ /^.\s*#\s*(?:else|elif)\b/) { - $level =3D $stack[$#stack - 1]; - } elsif ($lines[$line] =3D~ /^.\s*#\s*endif\b/) { - $level =3D pop(@stack); - } - - foreach my $c (split(//, $lines[$line])) { - ##print "C<$c>L<$level><$open$close>O<$off>\n"; - if ($off > 0) { - $off--; - next; - } - - if ($c eq $close && $level > 0) { - $level--; - last if ($level =3D=3D 0); - } elsif ($c eq $open) { - $level++; - } - } - - if (!$outer || $level <=3D 1) { - push(@res, $rawlines[$line]); - } - - last if ($level =3D=3D 0); - } - - return ($level, @res); -} -sub ctx_block_outer { - my ($linenr, $remain) =3D @_; - - my ($level, @r) =3D ctx_block_get($linenr, $remain, 1, '{', '}', 0); - return @r; -} -sub ctx_block { - my ($linenr, $remain) =3D @_; - - my ($level, @r) =3D ctx_block_get($linenr, $remain, 0, '{', '}', 0); - return @r; -} -sub ctx_statement { - my ($linenr, $remain, $off) =3D @_; - - my ($level, @r) =3D ctx_block_get($linenr, $remain, 0, '(', ')', $off); - return @r; -} -sub ctx_block_level { - my ($linenr, $remain) =3D @_; - - return ctx_block_get($linenr, $remain, 0, '{', '}', 0); -} -sub ctx_statement_level { - my ($linenr, $remain, $off) =3D @_; - - return ctx_block_get($linenr, $remain, 0, '(', ')', $off); -} - -sub ctx_locate_comment { - my ($first_line, $end_line) =3D @_; - - # If c99 comment on the current line, or the line before or after - my ($current_comment) =3D ($rawlines[$end_line - 1] =3D~ m@^\+.*(//.*$)@); - return $current_comment if (defined $current_comment); - ($current_comment) =3D ($rawlines[$end_line - 2] =3D~ m@^[\+ ].*(//.*$)@); - return $current_comment if (defined $current_comment); - ($current_comment) =3D ($rawlines[$end_line] =3D~ m@^[\+ ].*(//.*$)@); - return $current_comment if (defined $current_comment); - - # Catch a comment on the end of the line itself. - ($current_comment) =3D ($rawlines[$end_line - 1] =3D~ m@.*(/\*.*\*/)\s*(?= :\\\s*)?$@); - return $current_comment if (defined $current_comment); - - # Look through the context and try and figure out if there is a - # comment. - my $in_comment =3D 0; - $current_comment =3D ''; - for (my $linenr =3D $first_line; $linenr < $end_line; $linenr++) { - my $line =3D $rawlines[$linenr - 1]; - #warn " $line\n"; - if ($linenr =3D=3D $first_line and $line =3D~ m@^.\s*\*@) { - $in_comment =3D 1; - } - if ($line =3D~ m@/\*@) { - $in_comment =3D 1; - } - if (!$in_comment && $current_comment ne '') { - $current_comment =3D ''; - } - $current_comment .=3D $line . "\n" if ($in_comment); - if ($line =3D~ m@\*/@) { - $in_comment =3D 0; - } - } - - chomp($current_comment); - return($current_comment); -} -sub ctx_has_comment { - my ($first_line, $end_line) =3D @_; - my $cmt =3D ctx_locate_comment($first_line, $end_line); - - ##print "LINE: $rawlines[$end_line - 1 ]\n"; - ##print "CMMT: $cmt\n"; - - return ($cmt ne ''); -} - -sub raw_line { - my ($linenr, $cnt) =3D @_; - - my $offset =3D $linenr - 1; - $cnt++; - - my $line; - while ($cnt) { - $line =3D $rawlines[$offset++]; - next if (defined($line) && $line =3D~ /^-/); - $cnt--; - } - - return $line; -} - -sub get_stat_real { - my ($linenr, $lc) =3D @_; - - my $stat_real =3D raw_line($linenr, 0); - for (my $count =3D $linenr + 1; $count <=3D $lc; $count++) { - $stat_real =3D $stat_real . "\n" . raw_line($count, 0); - } - - return $stat_real; -} - -sub get_stat_here { - my ($linenr, $cnt, $here) =3D @_; - - my $herectx =3D $here . "\n"; - for (my $n =3D 0; $n < $cnt; $n++) { - $herectx .=3D raw_line($linenr, $n) . "\n"; - } - - return $herectx; -} - -sub cat_vet { - my ($vet) =3D @_; - my ($res, $coded); - - $res =3D ''; - while ($vet =3D~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) { - $res .=3D $1; - if ($2 ne '') { - $coded =3D sprintf("^%c", unpack('C', $2) + 64); - $res .=3D $coded; - } - } - $res =3D~ s/$/\$/; - - return $res; -} - -my $av_preprocessor =3D 0; -my $av_pending; -my @av_paren_type; -my $av_pend_colon; - -sub annotate_reset { - $av_preprocessor =3D 0; - $av_pending =3D '_'; - @av_paren_type =3D ('E'); - $av_pend_colon =3D 'O'; -} - -sub annotate_values { - my ($stream, $type) =3D @_; - - my $res; - my $var =3D '_' x length($stream); - my $cur =3D $stream; - - print "$stream\n" if ($dbg_values > 1); - - while (length($cur)) { - @av_paren_type =3D ('E') if ($#av_paren_type < 0); - print " <" . join('', @av_paren_type) . - "> <$type> <$av_pending>" if ($dbg_values > 1); - if ($cur =3D~ /^(\s+)/o) { - print "WS($1)\n" if ($dbg_values > 1); - if ($1 =3D~ /\n/ && $av_preprocessor) { - $type =3D pop(@av_paren_type); - $av_preprocessor =3D 0; - } - - } elsif ($cur =3D~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { - print "CAST($1)\n" if ($dbg_values > 1); - push(@av_paren_type, $type); - $type =3D 'c'; - - } elsif ($cur =3D~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { - print "DECLARE($1)\n" if ($dbg_values > 1); - $type =3D 'T'; - - } elsif ($cur =3D~ /^($Modifier)\s*/) { - print "MODIFIER($1)\n" if ($dbg_values > 1); - $type =3D 'T'; - - } elsif ($cur =3D~ /^(\#\s*define\s*$Ident)(\(?)/o) { - print "DEFINE($1,$2)\n" if ($dbg_values > 1); - $av_preprocessor =3D 1; - push(@av_paren_type, $type); - if ($2 ne '') { - $av_pending =3D 'N'; - } - $type =3D 'E'; - - } elsif ($cur =3D~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) { - print "UNDEF($1)\n" if ($dbg_values > 1); - $av_preprocessor =3D 1; - push(@av_paren_type, $type); - - } elsif ($cur =3D~ /^(\#\s*(?:ifdef|ifndef|if))/o) { - print "PRE_START($1)\n" if ($dbg_values > 1); - $av_preprocessor =3D 1; - - push(@av_paren_type, $type); - push(@av_paren_type, $type); - $type =3D 'E'; - - } elsif ($cur =3D~ /^(\#\s*(?:else|elif))/o) { - print "PRE_RESTART($1)\n" if ($dbg_values > 1); - $av_preprocessor =3D 1; - - push(@av_paren_type, $av_paren_type[$#av_paren_type]); - - $type =3D 'E'; - - } elsif ($cur =3D~ /^(\#\s*(?:endif))/o) { - print "PRE_END($1)\n" if ($dbg_values > 1); - - $av_preprocessor =3D 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); - $type =3D 'E'; - - } elsif ($cur =3D~ /^(\\\n)/o) { - print "PRECONT($1)\n" if ($dbg_values > 1); - - } elsif ($cur =3D~ /^(__attribute__)\s*\(?/o) { - print "ATTR($1)\n" if ($dbg_values > 1); - $av_pending =3D $type; - $type =3D 'N'; - - } elsif ($cur =3D~ /^(sizeof)\s*(\()?/o) { - print "SIZEOF($1)\n" if ($dbg_values > 1); - if (defined $2) { - $av_pending =3D 'V'; - } - $type =3D 'N'; - - } elsif ($cur =3D~ /^(if|while|for)\b/o) { - print "COND($1)\n" if ($dbg_values > 1); - $av_pending =3D 'E'; - $type =3D 'N'; - - } elsif ($cur =3D~/^(case)/o) { - print "CASE($1)\n" if ($dbg_values > 1); - $av_pend_colon =3D 'C'; - $type =3D 'N'; - - } elsif ($cur =3D~/^(return|else|goto|typeof|__typeof__)\b/o) { - print "KEYWORD($1)\n" if ($dbg_values > 1); - $type =3D 'N'; - - } elsif ($cur =3D~ /^(\()/o) { - print "PAREN('$1')\n" if ($dbg_values > 1); - push(@av_paren_type, $av_pending); - $av_pending =3D '_'; - $type =3D 'N'; - - } elsif ($cur =3D~ /^(\))/o) { - my $new_type =3D pop(@av_paren_type); - if ($new_type ne '_') { - $type =3D $new_type; - print "PAREN('$1') -> $type\n" - if ($dbg_values > 1); - } else { - print "PAREN('$1')\n" if ($dbg_values > 1); - } - - } elsif ($cur =3D~ /^($Ident)\s*\(/o) { - print "FUNC($1)\n" if ($dbg_values > 1); - $type =3D 'V'; - $av_pending =3D 'V'; - - } elsif ($cur =3D~ /^($Ident\s*):(?:\s*\d+\s*(,|=3D|;))?/) { - if (defined $2 && $type eq 'C' || $type eq 'T') { - $av_pend_colon =3D 'B'; - } elsif ($type eq 'E') { - $av_pend_colon =3D 'L'; - } - print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1); - $type =3D 'V'; - - } elsif ($cur =3D~ /^($Ident|$Constant)/o) { - print "IDENT($1)\n" if ($dbg_values > 1); - $type =3D 'V'; - - } elsif ($cur =3D~ /^($Assignment)/o) { - print "ASSIGN($1)\n" if ($dbg_values > 1); - $type =3D 'N'; - - } elsif ($cur =3D~/^(;|{|})/) { - print "END($1)\n" if ($dbg_values > 1); - $type =3D 'E'; - $av_pend_colon =3D 'O'; - - } elsif ($cur =3D~/^(,)/) { - print "COMMA($1)\n" if ($dbg_values > 1); - $type =3D 'C'; - - } elsif ($cur =3D~ /^(\?)/o) { - print "QUESTION($1)\n" if ($dbg_values > 1); - $type =3D 'N'; - - } elsif ($cur =3D~ /^(:)/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 =3D 'E'; - } else { - $type =3D 'N'; - } - $av_pend_colon =3D 'O'; - - } elsif ($cur =3D~ /^(\[)/o) { - print "CLOSE($1)\n" if ($dbg_values > 1); - $type =3D 'N'; - - } elsif ($cur =3D~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) { - my $variant; - - print "OPV($1)\n" if ($dbg_values > 1); - if ($type eq 'V') { - $variant =3D 'B'; - } else { - $variant =3D 'U'; - } - - substr($var, length($res), 1, $variant); - $type =3D 'N'; - - } elsif ($cur =3D~ /^($Operators)/o) { - print "OP($1)\n" if ($dbg_values > 1); - if ($1 ne '++' && $1 ne '--') { - $type =3D 'N'; - } - - } elsif ($cur =3D~ /(^.)/o) { - print "C($1)\n" if ($dbg_values > 1); - } - if (defined $1) { - $cur =3D substr($cur, length($1)); - $res .=3D $type x length($1); - } - } - - return ($res, $var); -} - -sub possible { - my ($possible, $line) =3D @_; - my $notPermitted =3D qr{(?: - ^(?: - $Modifier| - $Storage| - $Type| - DEFINE_\S+ - )$| - ^(?: - goto| - return| - case| - else| - asm|__asm__| - do| - \#| - \#\#| - )(?:\s|$)| - ^(?:typedef|struct|enum)\b - )}x; - warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2); - if ($possible !~ $notPermitted) { - # Check for modifiers. - $possible =3D~ s/\s*$Storage\s*//g; - $possible =3D~ s/\s*$Sparse\s*//g; - if ($possible =3D~ /^\s*$/) { - - } elsif ($possible =3D~ /\s/) { - $possible =3D~ s/\s*$Type\s*//g; - for my $modifier (split(' ', $possible)) { - if ($modifier !~ $notPermitted) { - warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible); - push(@modifierListFile, $modifier); - } - } - - } else { - warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); - push(@typeListFile, $possible); - } - build_types(); - } else { - warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1); - } -} - -my $prefix =3D ''; - -sub show_type { - my ($type) =3D @_; - - $type =3D~ tr/[a-z]/[A-Z]/; - - return defined $use_type{$type} if (scalar keys %use_type > 0); - - return !defined $ignore_type{$type}; -} - -sub report { - my ($level, $type, $msg) =3D @_; - - if (!show_type($type) || - (defined $tst_only && $msg !~ /\Q$tst_only\E/)) { - return 0; - } - my $output =3D ''; - if ($color) { - if ($level eq 'ERROR') { - $output .=3D RED; - } elsif ($level eq 'WARNING') { - $output .=3D YELLOW; - } else { - $output .=3D GREEN; - } - } - $output .=3D $prefix . $level . ':'; - if ($show_types) { - $output .=3D BLUE if ($color); - $output .=3D "$type:"; - } - $output .=3D RESET if ($color); - $output .=3D ' ' . $msg . "\n"; - - if ($showfile) { - my @lines =3D split("\n", $output, -1); - splice(@lines, 1, 1); - $output =3D join("\n", @lines); - } - - if ($terse) { - $output =3D (split('\n', $output))[0] . "\n"; - } - - if ($verbose && exists($verbose_messages{$type}) && - !exists($verbose_emitted{$type})) { - $output .=3D $verbose_messages{$type} . "\n\n"; - $verbose_emitted{$type} =3D 1; - } - - push(our @report, $output); - - return 1; -} - -sub report_dump { - our @report; -} - -sub fixup_current_range { - my ($lineRef, $offset, $length) =3D @_; - - if ($$lineRef =3D~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) { - my $o =3D $1; - my $l =3D $2; - my $no =3D $o + $offset; - my $nl =3D $l + $length; - $$lineRef =3D~ s/\+$o,$l \@\@/\+$no,$nl \@\@/; - } -} - -sub fix_inserted_deleted_lines { - my ($linesRef, $insertedRef, $deletedRef) =3D @_; - - my $range_last_linenr =3D 0; - my $delta_offset =3D 0; - - my $old_linenr =3D 0; - my $new_linenr =3D 0; - - my $next_insert =3D 0; - my $next_delete =3D 0; - - my @lines =3D (); - - my $inserted =3D @{$insertedRef}[$next_insert++]; - my $deleted =3D @{$deletedRef}[$next_delete++]; - - foreach my $old_line (@{$linesRef}) { - my $save_line =3D 1; - my $line =3D $old_line; #don't modify the array - if ($line =3D~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename - $delta_offset =3D 0; - } elsif ($line =3D~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk - $range_last_linenr =3D $new_linenr; - fixup_current_range(\$line, $delta_offset, 0); - } - - while (defined($deleted) && ${$deleted}{'LINENR'} =3D=3D $old_linenr) { - $deleted =3D @{$deletedRef}[$next_delete++]; - $save_line =3D 0; - fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1); - } - - while (defined($inserted) && ${$inserted}{'LINENR'} =3D=3D $old_linenr) { - push(@lines, ${$inserted}{'LINE'}); - $inserted =3D @{$insertedRef}[$next_insert++]; - $new_linenr++; - fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1); - } - - if ($save_line) { - push(@lines, $line); - $new_linenr++; - } - - $old_linenr++; - } - - return @lines; -} - -sub fix_insert_line { - my ($linenr, $line) =3D @_; - - my $inserted =3D { - LINENR =3D> $linenr, - LINE =3D> $line, - }; - push(@fixed_inserted, $inserted); -} - -sub fix_delete_line { - my ($linenr, $line) =3D @_; - - my $deleted =3D { - LINENR =3D> $linenr, - LINE =3D> $line, - }; - - push(@fixed_deleted, $deleted); -} - -sub ERROR { - my ($type, $msg) =3D @_; - - if (report("ERROR", $type, $msg)) { - our $clean =3D 0; - our $cnt_error++; - return 1; - } - return 0; -} -sub WARN { - my ($type, $msg) =3D @_; - - if (report("WARNING", $type, $msg)) { - our $clean =3D 0; - our $cnt_warn++; - return 1; - } - return 0; -} -sub CHK { - my ($type, $msg) =3D @_; - - if ($check && report("CHECK", $type, $msg)) { - our $clean =3D 0; - our $cnt_chk++; - return 1; - } - return 0; -} - -sub check_absolute_file { - my ($absolute, $herecurr) =3D @_; - my $file =3D $absolute; - - ##print "absolute<$absolute>\n"; - - # See if any suffix of this path is a path within the tree. - while ($file =3D~ 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 =3D $absolute; - substr($prefix, -length($file)) =3D ''; - - ##print "prefix<$prefix>\n"; - if ($prefix ne ".../") { - WARN("USE_RELATIVE_PATH", - "use relative pathname instead of absolute in changelog text\n" . $= herecurr); - } -} - -sub trim { - my ($string) =3D @_; - - $string =3D~ s/^\s+|\s+$//g; - - return $string; -} - -sub ltrim { - my ($string) =3D @_; - - $string =3D~ s/^\s+//; - - return $string; -} - -sub rtrim { - my ($string) =3D @_; - - $string =3D~ s/\s+$//; - - return $string; -} - -sub string_find_replace { - my ($string, $find, $replace) =3D @_; - - $string =3D~ s/$find/$replace/g; - - return $string; -} - -sub tabify { - my ($leading) =3D @_; - - my $source_indent =3D $tabsize; - my $max_spaces_before_tab =3D $source_indent - 1; - my $spaces_to_tab =3D " " x $source_indent; - - #convert leading spaces to tabs - 1 while $leading =3D~ s@^([\t]*)$spaces_to_tab@$1\t@g; - #Remove spaces before a tab - 1 while $leading =3D~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g; - - return "$leading"; -} - -sub pos_last_openparen { - my ($line) =3D @_; - - my $pos =3D 0; - - my $opens =3D $line =3D~ tr/\(/\(/; - my $closes =3D $line =3D~ tr/\)/\)/; - - my $last_openparen =3D 0; - - if (($opens =3D=3D 0) || ($closes >=3D $opens)) { - return -1; - } - - my $len =3D length($line); - - for ($pos =3D 0; $pos < $len; $pos++) { - my $string =3D substr($line, $pos); - if ($string =3D~ /^($FuncArg|$balanced_parens)/) { - $pos +=3D length($1) - 1; - } elsif (substr($line, $pos, 1) eq '(') { - $last_openparen =3D $pos; - } elsif (index($string, '(') =3D=3D -1) { - last; - } - } - - return length(expand_tabs(substr($line, 0, $last_openparen))) + 1; -} - -sub get_raw_comment { - my ($line, $rawline) =3D @_; - my $comment =3D ''; - - for my $i (0 .. (length($line) - 1)) { - if (substr($line, $i, 1) eq "$;") { - $comment .=3D substr($rawline, $i, 1); - } - } - - return $comment; -} - -sub exclude_global_initialisers { - my ($realfile) =3D @_; - - # Do not check for BPF programs (tools/testing/selftests/bpf/progs/*.c, s= amples/bpf/*_kern.c, *.bpf.c). - return $realfile =3D~ m@^tools/testing/selftests/bpf/progs/.*\.c$@ || - $realfile =3D~ m@^samples/bpf/.*_kern\.c$@ || - $realfile =3D~ m@/bpf/.*\.bpf\.c$@; -} - -sub process { - my $filename =3D shift; - - my $linenr=3D0; - my $prevline=3D""; - my $prevrawline=3D""; - my $stashline=3D""; - my $stashrawline=3D""; - - my $length; - my $indent; - my $previndent=3D0; - my $stashindent=3D0; - - our $clean =3D 1; - my $signoff =3D 0; - my $author =3D ''; - my $authorsignoff =3D 0; - my $author_sob =3D ''; - my $is_patch =3D 0; - my $is_binding_patch =3D -1; - my $in_header_lines =3D $file ? 0 : 1; - my $in_commit_log =3D 0; #Scanning lines before patch - my $has_patch_separator =3D 0; #Found a --- line - my $has_commit_log =3D 0; #Encountered lines before patch - my $commit_log_lines =3D 0; #Number of commit log lines - my $commit_log_possible_stack_dump =3D 0; - my $commit_log_long_line =3D 0; - my $commit_log_has_diff =3D 0; - my $reported_maintainer_file =3D 0; - my $non_utf8_charset =3D 0; - - my $last_git_commit_id_linenr =3D -1; - - my $last_blank_line =3D 0; - my $last_coalesced_string_linenr =3D -1; - - our @report =3D (); - our $cnt_lines =3D 0; - our $cnt_error =3D 0; - our $cnt_warn =3D 0; - our $cnt_chk =3D 0; - - # Trace the real file/line as we go. - my $realfile =3D ''; - my $realline =3D 0; - my $realcnt =3D 0; - my $here =3D ''; - my $context_function; #undef'd unless there's a known function - my $in_comment =3D 0; - my $comment_edge =3D 0; - my $first_line =3D 0; - my $p1_prefix =3D ''; - - my $prev_values =3D 'E'; - - # suppression flags - my %suppress_ifbraces; - my %suppress_whiletrailers; - my %suppress_export; - my $suppress_statement =3D 0; - - my %signatures =3D (); - - # Pre-scan the patch sanitizing the lines. - # Pre-scan the patch looking for any __setup documentation. - # - my @setup_docs =3D (); - my $setup_docs =3D 0; - - my $camelcase_file_seeded =3D 0; - - my $checklicenseline =3D 1; - - sanitise_line_reset(); - my $line; - foreach my $rawline (@rawlines) { - $linenr++; - $line =3D $rawline; - - push(@fixed, $rawline) if ($fix); - - if ($rawline=3D~/^\+\+\+\s+(\S+)/) { - $setup_docs =3D 0; - if ($1 =3D~ m@Documentation/admin-guide/kernel-parameters.txt$@) { - $setup_docs =3D 1; - } - #next; - } - if ($rawline =3D~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { - $realline=3D$1-1; - if (defined $2) { - $realcnt=3D$3+1; - } else { - $realcnt=3D1+1; - } - $in_comment =3D 0; - - # 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; - my $cnt =3D $realcnt; - for (my $ln =3D $linenr + 1; $cnt > 0; $ln++) { - next if (defined $rawlines[$ln - 1] && - $rawlines[$ln - 1] =3D~ /^-/); - $cnt--; - #print "RAW<$rawlines[$ln - 1]>\n"; - last if (!defined $rawlines[$ln - 1]); - if ($rawlines[$ln - 1] =3D~ m@(/\*|\*/)@ && - $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) { - ($edge) =3D $1; - last; - } - } - if (defined $edge && $edge eq '*/') { - $in_comment =3D 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 && - $rawlines[$linenr] =3D~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@) - { - $in_comment =3D 1; - } - - ##print "COMMENT:$in_comment edge<$edge> $rawline\n"; - sanitise_line_reset($in_comment); - - } elsif ($realcnt && $rawline =3D~ /^(?:\+| |$)/) { - # Standardise the strings and chars within the input to - # simplify matching -- only bother with positive lines. - $line =3D sanitise_line($rawline); - } - push(@lines, $line); - - if ($realcnt > 1) { - $realcnt-- if ($line =3D~ /^(?:\+| |$)/); - } else { - $realcnt =3D 0; - } - - #print "=3D=3D>$rawline\n"; - #print "-->$line\n"; - - if ($setup_docs && $line =3D~ /^\+/) { - push(@setup_docs, $line); - } - } - - $prefix =3D ''; - - $realcnt =3D 0; - $linenr =3D 0; - $fixlinenr =3D -1; - foreach my $line (@lines) { - $linenr++; - $fixlinenr++; - my $sline =3D $line; #copy of $line - $sline =3D~ s/$;/ /g; #with comments as spaces - - my $rawline =3D $rawlines[$linenr - 1]; - my $raw_comment =3D get_raw_comment($line, $rawline); - -# check if it's a mode change, rename or start of a patch - if (!$in_commit_log && - ($line =3D~ /^ mode change [0-7]+ =3D> [0-7]+ \S+\s*$/ || - ($line =3D~ /^rename (?:from|to) \S+\s*$/ || - $line =3D~ /^diff --git a\/[\w\/\.\_\-]+ b\/\S+\s*$/))) { - $is_patch =3D 1; - } - -#extract the line range in the file after the patch is applied - if (!$in_commit_log && - $line =3D~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) { - my $context =3D $4; - $is_patch =3D 1; - $first_line =3D $linenr + 1; - $realline=3D$1-1; - if (defined $2) { - $realcnt=3D$3+1; - } else { - $realcnt=3D1+1; - } - annotate_reset(); - $prev_values =3D 'E'; - - %suppress_ifbraces =3D (); - %suppress_whiletrailers =3D (); - %suppress_export =3D (); - $suppress_statement =3D 0; - if ($context =3D~ /\b(\w+)\s*\(/) { - $context_function =3D $1; - } else { - undef $context_function; - } - next; - -# 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. - } elsif ($line =3D~ /^( |\+|$)/) { - $realline++; - $realcnt-- if ($realcnt !=3D 0); - - # Measure the line length and indent. - ($length, $indent) =3D line_stats($rawline); - - # Track the previous line. - ($prevline, $stashline) =3D ($stashline, $line); - ($previndent, $stashindent) =3D ($stashindent, $indent); - ($prevrawline, $stashrawline) =3D ($stashrawline, $rawline); - - #warn "line<$line>\n"; - - } elsif ($realcnt =3D=3D 1) { - $realcnt--; - } - - my $hunk_line =3D ($realcnt !=3D 0); - - $here =3D "#$linenr: " if (!$file); - $here =3D "#$realline: " if ($file); - - my $found_file =3D 0; - # extract the filename as it passes - if ($line =3D~ /^diff --git.*?(\S+)$/) { - $realfile =3D $1; - $realfile =3D~ s@^([^/]*)/@@ if (!$file); - $in_commit_log =3D 0; - $found_file =3D 1; - } elsif ($line =3D~ /^\+\+\+\s+(\S+)/) { - $realfile =3D $1; - $realfile =3D~ s@^([^/]*)/@@ if (!$file); - $in_commit_log =3D 0; - - $p1_prefix =3D $1; - if (!$file && $tree && $p1_prefix ne '' && - -e "$root/$p1_prefix") { - WARN("PATCH_PREFIX", - "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); - } - - if ($realfile =3D~ m@^include/asm/@) { - ERROR("MODIFIED_INCLUDE_ASM", - "do not modify files in include/asm, change architecture specifi= c files in include/asm-\n" . "$here$rawline\n"); - } - $found_file =3D 1; - } - -#make up the handle for any error we report on this line - if ($showfile) { - $prefix =3D "$realfile:$realline: " - } elsif ($emacs) { - if ($file) { - $prefix =3D "$filename:$realline: "; - } else { - $prefix =3D "$filename:$linenr: "; - } - } - - if ($found_file) { - if (is_maintained_obsolete($realfile)) { - WARN("OBSOLETE", - "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy. = No unnecessary modifications please.\n"); - } - if ($realfile =3D~ m@^(?:drivers/net/|net/|drivers/staging/)@) { - $check =3D 1; - } else { - $check =3D $check_orig; - } - $checklicenseline =3D 1; - - if ($realfile !~ /^MAINTAINERS/) { - my $last_binding_patch =3D $is_binding_patch; - - $is_binding_patch =3D () =3D $realfile =3D~ m@^(?:Documentation/device= tree/|include/dt-bindings/)@; - - if (($last_binding_patch !=3D -1) && - ($last_binding_patch ^ $is_binding_patch)) { - WARN("DT_SPLIT_BINDING_PATCH", - "DT binding docs and includes should be a separate patch. See: D= ocumentation/devicetree/bindings/submitting-patches.rst\n"); - } - } - - next; - } - - $here .=3D "FILE: $realfile:$realline:" if ($realcnt !=3D 0); - - my $hereline =3D "$here\n$rawline\n"; - my $herecurr =3D "$here\n$rawline\n"; - my $hereprev =3D "$here\n$prevrawline\n$rawline\n"; - - $cnt_lines++ if ($realcnt !=3D 0); - -# Verify the existence of a commit log if appropriate -# 2 is used because a $signature is counted in $commit_log_lines - if ($in_commit_log) { - if ($line !~ /^\s*$/) { - $commit_log_lines++; #could be a $signature - } - } elsif ($has_commit_log && $commit_log_lines < 2) { - WARN("COMMIT_MESSAGE", - "Missing commit description - Add an appropriate one\n"); - $commit_log_lines =3D 2; #warn only once - } - -# Check if the commit log has what seems like a diff which can confuse pat= ch - if ($in_commit_log && !$commit_log_has_diff && - (($line =3D~ m@^\s+diff\b.*a/([\w/]+)@ && - $line =3D~ m@^\s+diff\b.*a/[\w/]+\s+b/$1\b@) || - $line =3D~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ || - $line =3D~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) { - ERROR("DIFF_IN_COMMIT_MSG", - "Avoid using diff content in the commit message - patch(1) might = not work\n" . $herecurr); - $commit_log_has_diff =3D 1; - } - -# Check for incorrect file permissions - if ($line =3D~ /^new (file )?mode.*[7531]\d{0,2}$/) { - my $permhere =3D $here . "FILE: $realfile\n"; - if ($realfile !~ m@scripts/@ && - $realfile !~ /\.(py|pl|awk|sh)$/) { - ERROR("EXECUTE_PERMISSIONS", - "do not set execute permissions for source files\n" . $permhere); - } - } - -# Check the patch for a From: - if (decode("MIME-Header", $line) =3D~ /^From:\s*(.*)/) { - $author =3D $1; - my $curline =3D $linenr; - while(defined($rawlines[$curline]) && ($rawlines[$curline++] =3D~ /^[ \= t]\s*(.*)/)) { - $author .=3D $1; - } - $author =3D encode("utf8", $author) if ($line =3D~ /=3D\?utf-8\?/i); - $author =3D~ s/"//g; - $author =3D reformat_email($author); - } - -# Check the patch for a signoff: - if ($line =3D~ /^\s*signed-off-by:\s*(.*)/i) { - $signoff++; - $in_commit_log =3D 0; - if ($author ne '' && $authorsignoff !=3D 1) { - if (same_email_addresses($1, $author)) { - $authorsignoff =3D 1; - } else { - my $ctx =3D $1; - my ($email_name, $email_comment, $email_address, $comment1) =3D parse= _email($ctx); - my ($author_name, $author_comment, $author_address, $comment2) =3D pa= rse_email($author); - - if (lc $email_address eq lc $author_address && $email_name eq $author= _name) { - $author_sob =3D $ctx; - $authorsignoff =3D 2; - } elsif (lc $email_address eq lc $author_address) { - $author_sob =3D $ctx; - $authorsignoff =3D 3; - } elsif ($email_name eq $author_name) { - $author_sob =3D $ctx; - $authorsignoff =3D 4; - - my $address1 =3D $email_address; - my $address2 =3D $author_address; - - if ($address1 =3D~ /(\S+)\+\S+(\@.*)/) { - $address1 =3D "$1$2"; - } - if ($address2 =3D~ /(\S+)\+\S+(\@.*)/) { - $address2 =3D "$1$2"; - } - if ($address1 eq $address2) { - $authorsignoff =3D 5; - } - } - } - } - } - -# Check for patch separator - if ($line =3D~ /^---$/) { - $has_patch_separator =3D 1; - $in_commit_log =3D 0; - } - -# Check if MAINTAINERS is being updated. If so, there's probably no need = to -# emit the "does MAINTAINERS need updating?" message on file add/move/dele= te - if ($line =3D~ /^\s*MAINTAINERS\s*\|/) { - $reported_maintainer_file =3D 1; - } - -# Check signature styles - if (!$in_header_lines && - $line =3D~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) { - my $space_before =3D $1; - my $sign_off =3D $2; - my $space_after =3D $3; - my $email =3D $4; - my $ucfirst_sign_off =3D ucfirst(lc($sign_off)); - - if ($sign_off !~ /$signature_tags/) { - my $suggested_signature =3D find_standard_signature($sign_off); - if ($suggested_signature eq "") { - WARN("BAD_SIGN_OFF", - "Non-standard signature: $sign_off\n" . $herecurr); - } else { - if (WARN("BAD_SIGN_OFF", - "Non-standard signature: '$sign_off' - perhaps '$suggested_signatur= e'?\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/$sign_off/$suggested_signature/; - } - } - } - if (defined $space_before && $space_before ne "") { - if (WARN("BAD_SIGN_OFF", - "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D - "$ucfirst_sign_off $email"; - } - } - if ($sign_off =3D~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { - if (WARN("BAD_SIGN_OFF", - "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr)= && - $fix) { - $fixed[$fixlinenr] =3D - "$ucfirst_sign_off $email"; - } - - } - if (!defined $space_after || $space_after ne " ") { - if (WARN("BAD_SIGN_OFF", - "Use a single space after $ucfirst_sign_off\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D - "$ucfirst_sign_off $email"; - } - } - - my ($email_name, $name_comment, $email_address, $comment) =3D parse_ema= il($email); - my $suggested_email =3D format_email(($email_name, $name_comment, $emai= l_address, $comment)); - if ($suggested_email eq "") { - ERROR("BAD_SIGN_OFF", - "Unrecognized email address: '$email'\n" . $herecurr); - } else { - my $dequoted =3D $suggested_email; - $dequoted =3D~ s/^"//; - $dequoted =3D~ s/" 1) { - WARN("BAD_SIGN_OFF", - "Use a single name comment in email: '$email'\n" . $herecurr); - } - - - # stable@vger.kernel.org or stable@kernel.org shouldn't - # have an email name. In addition comments should strictly - # begin with a # - if ($email =3D~ /^.*stable\@(?:vger\.)?kernel\.org/i) { - if (($comment ne "" && $comment !~ /^#.+/) || - ($email_name ne "")) { - my $cur_name =3D $email_name; - my $new_comment =3D $comment; - $cur_name =3D~ s/[a-zA-Z\s\-\"]+//g; - - # Remove brackets enclosing comment text - # and # from start of comments to get comment text - $new_comment =3D~ s/^\((.*)\)$/$1/; - $new_comment =3D~ s/^\[(.*)\]$/$1/; - $new_comment =3D~ s/^[\s\#]+|\s+$//g; - - $new_comment =3D trim("$new_comment $cur_name") if ($cur_name ne $ne= w_comment); - $new_comment =3D " # $new_comment" if ($new_comment ne ""); - my $new_email =3D "$email_address$new_comment"; - - if (WARN("BAD_STABLE_ADDRESS_STYLE", - "Invalid email format for stable: '$email', prefer '$new_email'\n"= . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\Q$email\E/$new_email/; - } - } - } elsif ($comment ne "" && $comment !~ /^(?:#.+|\(.+\))$/) { - my $new_comment =3D $comment; - - # Extract comment text from within brackets or - # c89 style /*...*/ comments - $new_comment =3D~ s/^\[(.*)\]$/$1/; - $new_comment =3D~ s/^\/\*(.*)\*\/$/$1/; - - $new_comment =3D trim($new_comment); - $new_comment =3D~ s/^[^\w]$//; # Single lettered comment with non wor= d character is usually a typo - $new_comment =3D "($new_comment)" if ($new_comment ne ""); - my $new_email =3D format_email($email_name, $name_comment, $email_add= ress, $new_comment); - - if (WARN("BAD_SIGN_OFF", - "Unexpected content after email: '$email', should be: '$new_email'\= n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\Q$email\E/$new_email/; - } - } - } - -# Check for duplicate signatures - my $sig_nospace =3D $line; - $sig_nospace =3D~ s/\s//g; - $sig_nospace =3D lc($sig_nospace); - if (defined $signatures{$sig_nospace}) { - WARN("BAD_SIGN_OFF", - "Duplicate signature\n" . $herecurr); - } else { - $signatures{$sig_nospace} =3D 1; - } - -# Check Co-developed-by: immediately followed by Signed-off-by: with same = name and email - if ($sign_off =3D~ /^co-developed-by:$/i) { - if ($email eq $author) { - WARN("BAD_SIGN_OFF", - "Co-developed-by: should not be used to attribute nominal patch= author '$author'\n" . "$here\n" . $rawline); - } - if (!defined $lines[$linenr]) { - WARN("BAD_SIGN_OFF", - "Co-developed-by: must be immediately followed by Signed-off-by:= \n" . "$here\n" . $rawline); - } elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) { - WARN("BAD_SIGN_OFF", - "Co-developed-by: must be immediately followed by Signed-off-by:= \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); - } elsif ($1 ne $email) { - WARN("BAD_SIGN_OFF", - "Co-developed-by and Signed-off-by: name/email do not match \n" = . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); - } - } - } - -# Check email subject for common tools that don't need to be mentioned - if ($in_header_lines && - $line =3D~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) { - WARN("EMAIL_SUBJECT", - "A patch subject line should describe the change not the tool that= found it\n" . $herecurr); - } - -# Check for Gerrit Change-Ids not in any patch context - if ($realfile eq '' && !$has_patch_separator && $line =3D~ /^\s*change-i= d:/i) { - if (ERROR("GERRIT_CHANGE_ID", - "Remove Gerrit Change-Id's before submitting upstream\n" . $h= erecurr) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - } - -# Check if the commit log is in a possible stack dump - if ($in_commit_log && !$commit_log_possible_stack_dump && - ($line =3D~ /^\s*(?:WARNING:|BUG:)/ || - $line =3D~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ || - # timestamp - $line =3D~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) || - $line =3D~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ || - $line =3D~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) { - # stack dump address styles - $commit_log_possible_stack_dump =3D 1; - } - -# Check for line lengths > 75 in commit log, warn once - if ($in_commit_log && !$commit_log_long_line && - length($line) > 75 && - !($line =3D~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ || - # file delta changes - $line =3D~ /^\s*(?:[\w\.\-\+]*\/)++[\w\.\-\+]+:/ || - # filename then : - $line =3D~ /^\s*(?:Fixes:|Link:|$signature_tags)/i || - # A Fixes: or Link: line or signature tag line - $commit_log_possible_stack_dump)) { - WARN("COMMIT_LOG_LONG_LINE", - "Possible unwrapped commit description (prefer a maximum 75 chars = per line)\n" . $herecurr); - $commit_log_long_line =3D 1; - } - -# Reset possible stack dump if a blank line is found - if ($in_commit_log && $commit_log_possible_stack_dump && - $line =3D~ /^\s*$/) { - $commit_log_possible_stack_dump =3D 0; - } - -# Check for lines starting with a # - if ($in_commit_log && $line =3D~ /^#/) { - if (WARN("COMMIT_COMMENT_SYMBOL", - "Commit log lines starting with '#' are dropped by git as comments\n"= . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/^/ /; - } - } - -# Check for git id commit length and improperly formed commit descriptions -# A correctly formed commit description is: -# commit ("Complete commit subject") -# with the commit subject '("' prefix and '")' suffix -# This is a fairly compilicated block as it tests for what appears to be -# bare SHA-1 hash with minimum length of 5. It also avoids several types= of -# possible SHA-1 matches. -# A commit match can span multiple lines so this block attempts to find a -# complete typical commit on a maximum of 3 lines - if ($perl_version_ok && - $in_commit_log && !$commit_log_possible_stack_dump && - $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i && - $line !~ /^This reverts commit [0-9a-f]{7,40}/ && - (($line =3D~ /\bcommit\s+[0-9a-f]{5,}\b/i || - ($line =3D~ /\bcommit\s*$/i && defined($rawlines[$linenr]) && $raw= lines[$linenr] =3D~ /^\s*[0-9a-f]{5,}\b/i)) || - ($line =3D~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i && - $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && - $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { - my $init_char =3D "c"; - my $orig_commit =3D ""; - my $short =3D 1; - my $long =3D 0; - my $case =3D 1; - my $space =3D 1; - my $id =3D '0123456789ab'; - my $orig_desc =3D "commit description"; - my $description =3D ""; - my $herectx =3D $herecurr; - my $has_parens =3D 0; - my $has_quotes =3D 0; - - my $input =3D $line; - if ($line =3D~ /(?:\bcommit\s+[0-9a-f]{5,}|\bcommit\s*$)/i) { - for (my $n =3D 0; $n < 2; $n++) { - if ($input =3D~ /\bcommit\s+[0-9a-f]{5,}\s*($balanced_parens)/i) { - $orig_desc =3D $1; - $has_parens =3D 1; - # Always strip leading/trailing parens then double quotes if existing - $orig_desc =3D substr($orig_desc, 1, -1); - if ($orig_desc =3D~ /^".*"$/) { - $orig_desc =3D substr($orig_desc, 1, -1); - $has_quotes =3D 1; - } - last; - } - last if ($#lines < $linenr + $n); - $input .=3D " " . trim($rawlines[$linenr + $n]); - $herectx .=3D "$rawlines[$linenr + $n]\n"; - } - $herectx =3D $herecurr if (!$has_parens); - } - - if ($input =3D~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { - $init_char =3D $1; - $orig_commit =3D lc($2); - $short =3D 0 if ($input =3D~ /\bcommit\s+[0-9a-f]{12,40}/i); - $long =3D 1 if ($input =3D~ /\bcommit\s+[0-9a-f]{41,}/i); - $space =3D 0 if ($input =3D~ /\bcommit [0-9a-f]/i); - $case =3D 0 if ($input =3D~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); - } elsif ($input =3D~ /\b([0-9a-f]{12,40})\b/i) { - $orig_commit =3D lc($1); - } - - ($id, $description) =3D git_commit_info($orig_commit, - $id, $orig_desc); - - if (defined($id) && - ($short || $long || $space || $case || ($orig_desc ne $description)= || !$has_quotes) && - $last_git_commit_id_linenr !=3D $linenr - 1) { - ERROR("GIT_COMMIT_ID", - "Please use git commit description style 'commit <12+ chars of s= ha1> (\"\")' - ie: '${init_char}ommit $id (\"$description\")'\n= " . $herectx); - } - #don't report the next line if this line ends in commit and the sha1 ha= sh is the next line - $last_git_commit_id_linenr =3D $linenr if ($line =3D~ /\bcommit\s*$/i); - } - -# Check for added, moved or deleted files - if (!$reported_maintainer_file && !$in_commit_log && - ($line =3D~ /^(?:new|deleted) file mode\s*\d+\s*$/ || - $line =3D~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || - ($line =3D~ /\{\s*([\w\/\.\-]*)\s*\=3D\>\s*([\w\/\.\-]*)\s*\}/ && - (defined($1) || defined($2))))) { - $is_patch =3D 1; - $reported_maintainer_file =3D 1; - WARN("FILE_PATH_CHANGES", - "added, moved or deleted file(s), does MAINTAINERS need updating?\= n" . $herecurr); - } - -# Check for adding new DT bindings not in schema format - if (!$in_commit_log && - ($line =3D~ /^new file mode\s*\d+\s*$/) && - ($realfile =3D~ m@^Documentation/devicetree/bindings/.*\.txt$@)) { - WARN("DT_SCHEMA_BINDING_PATCH", - "DT bindings should be in DT schema format. See: Documentation/dev= icetree/bindings/writing-schema.rst\n"); - } - -# Check for wrappage within a valid hunk of the file - if ($realcnt !=3D 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { - ERROR("CORRUPTED_PATCH", - "patch seems to be corrupt (line wrapped?)\n" . - $herecurr) if (!$emitted_corrupt++); - } - -# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-= utf-8.en.php - if (($realfile =3D~ /^$/ || $line =3D~ /^\+/) && - $rawline !~ m/^$UTF8*$/) { - my ($utf8_prefix) =3D ($rawline =3D~ /^($UTF8*)/); - - my $blank =3D copy_spacing($rawline); - my $ptr =3D substr($blank, 0, length($utf8_prefix)) . "^"; - my $hereptr =3D "$hereline$ptr\n"; - - CHK("INVALID_UTF8", - "Invalid UTF-8, patch and commit message should be encoded in UTF-8= \n" . $hereptr); - } - -# Check if it's the start of a commit log -# (not a header line and we haven't seen the patch filename) - if ($in_header_lines && $realfile =3D~ /^$/ && - !($rawline =3D~ /^\s+(?:\S|$)/ || - $rawline =3D~ /^(?:commit\b|from\b|[\w-]+:)/i)) { - $in_header_lines =3D 0; - $in_commit_log =3D 1; - $has_commit_log =3D 1; - } - -# Check if there is UTF-8 in a commit log when a mail header has explicitly -# declined it, i.e defined some charset where it is missing. - if ($in_header_lines && - $rawline =3D~ /^Content-Type:.+charset=3D"(.+)".*$/ && - $1 !~ /utf-8/i) { - $non_utf8_charset =3D 1; - } - - if ($in_commit_log && $non_utf8_charset && $realfile =3D~ /^$/ && - $rawline =3D~ /$NON_ASCII_UTF8/) { - WARN("UTF8_BEFORE_PATCH", - "8-bit UTF-8 used in possible commit log\n" . $herecurr); - } - -# Check for absolute kernel paths in commit message - if ($tree && $in_commit_log) { - while ($line =3D~ m{(?:^|\s)(/\S*)}g) { - my $file =3D $1; - - if ($file =3D~ m{^(.*?)(?::\d+)+:?$} && - check_absolute_file($1, $herecurr)) { - # - } else { - check_absolute_file($file, $herecurr); - } - } - } - -# Check for various typo / spelling mistakes - if (defined($misspellings) && - ($in_commit_log || $line =3D~ /^(?:\+|Subject:)/i)) { - while ($rawline =3D~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi)= { - my $typo =3D $1; - my $blank =3D copy_spacing($rawline); - my $ptr =3D substr($blank, 0, $-[1]) . "^" x length($typo); - my $hereptr =3D "$hereline$ptr\n"; - my $typo_fix =3D $spelling_fix{lc($typo)}; - $typo_fix =3D ucfirst($typo_fix) if ($typo =3D~ /^[A-Z]/); - $typo_fix =3D uc($typo_fix) if ($typo =3D~ /^[A-Z]+$/); - my $msg_level =3D \&WARN; - $msg_level =3D \&CHK if ($file); - if (&{$msg_level}("TYPO_SPELLING", - "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $hereptr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo= _fix$3/; - } - } - } - -# check for invalid commit id - if ($in_commit_log && $line =3D~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\= b/i) { - my $id; - my $description; - ($id, $description) =3D git_commit_info($2, undef, undef); - if (!defined($id)) { - WARN("UNKNOWN_COMMIT_ID", - "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herec= urr); - } - } - -# check for repeated words separated by a single space -# avoid false positive from list command eg, '-rw-r--r-- 1 root root' - if (($rawline =3D~ /^\+/ || $in_commit_log) && - $rawline !~ /[bcCdDlMnpPs\?-][rwxsStT-]{9}/) { - pos($rawline) =3D 1 if (!$in_commit_log); - while ($rawline =3D~ /\b($word_pattern) (?=3D($word_pattern))/g) { - - my $first =3D $1; - my $second =3D $2; - my $start_pos =3D $-[1]; - my $end_pos =3D $+[2]; - if ($first =3D~ /(?:struct|union|enum)/) { - pos($rawline) +=3D length($first) + length($second) + 1; - next; - } - - next if (lc($first) ne lc($second)); - next if ($first eq 'long'); - - # check for character before and after the word matches - my $start_char =3D ''; - my $end_char =3D ''; - $start_char =3D substr($rawline, $start_pos - 1, 1) if ($start_pos > (= $in_commit_log ? 0 : 1)); - $end_char =3D substr($rawline, $end_pos, 1) if ($end_pos < length($raw= line)); - - next if ($start_char =3D~ /^\S$/); - next if (index(" \t.,;?!", $end_char) =3D=3D -1); - - # avoid repeating hex occurrences like 'ff ff fe 09 ...' - if ($first =3D~ /\b[0-9a-f]{2,}\b/i) { - next if (!exists($allow_repeated_words{lc($first)})); - } - - if (WARN("REPEATED_WORD", - "Possible repeated word: '$first'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\b$first $second\b/$first/; - } - } - - # if it's a repeated word on consecutive lines in a comment block - if ($prevline =3D~ /$;+\s*$/ && - $prevrawline =3D~ /($word_pattern)\s*$/) { - my $last_word =3D $1; - if ($rawline =3D~ /^\+\s*\*\s*$last_word /) { - if (WARN("REPEATED_WORD", - "Possible repeated word: '$last_word'\n" . $hereprev) && - $fix) { - $fixed[$fixlinenr] =3D~ s/(\+\s*\*\s*)$last_word /$1/; - } - } - } - } - -# ignore non-hunk lines and lines being removed - next if (!$hunk_line || $line =3D~ /^-/); - -#trailing whitespace - if ($line =3D~ /^\+.*\015/) { - my $herevet =3D "$here\n" . cat_vet($rawline) . "\n"; - if (ERROR("DOS_LINE_ENDINGS", - "DOS line endings\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =3D~ s/[\s\015]+$//; - } - } elsif ($rawline =3D~ /^\+.*\S\s+$/ || $rawline =3D~ /^\+\s+$/) { - my $herevet =3D "$here\n" . cat_vet($rawline) . "\n"; - if (ERROR("TRAILING_WHITESPACE", - "trailing whitespace\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\s+$//; - } - - $rpt_cleaners =3D 1; - } - -# Check for FSF mailing addresses. - if ($rawline =3D~ /\bwrite to the Free/i || - $rawline =3D~ /\b675\s+Mass\s+Ave/i || - $rawline =3D~ /\b59\s+Temple\s+Pl/i || - $rawline =3D~ /\b51\s+Franklin\s+St/i) { - my $herevet =3D "$here\n" . cat_vet($rawline) . "\n"; - my $msg_level =3D \&ERROR; - $msg_level =3D \&CHK if ($file); - &{$msg_level}("FSF_MAILING_ADDRESS", - "Do not include the paragraph about writing to the Free Software= Foundation's mailing address from the sample GPL notice. The FSF has chang= ed addresses in the past, and may do so again. Linux already includes a cop= y of the GPL.\n" . $herevet) - } - -# check for Kconfig help text having a real description -# Only applies when adding the entry originally, after that we do not have -# sufficient context to determine whether it is indeed long enough. - if ($realfile =3D~ /Kconfig/ && - # 'choice' is usually the last thing on the line (though - # Kconfig supports named choices), so use a word boundary - # (\b) rather than a whitespace character (\s) - $line =3D~ /^\+\s*(?:config|menuconfig|choice)\b/) { - my $ln =3D $linenr; - my $needs_help =3D 0; - my $has_help =3D 0; - my $help_length =3D 0; - while (defined $lines[$ln]) { - my $f =3D $lines[$ln++]; - - next if ($f =3D~ /^-/); - last if ($f !~ /^[\+ ]/); # !patch context - - if ($f =3D~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) { - $needs_help =3D 1; - next; - } - if ($f =3D~ /^\+\s*help\s*$/) { - $has_help =3D 1; - next; - } - - $f =3D~ s/^.//; # strip patch context [+ ] - $f =3D~ s/#.*//; # strip # directives - $f =3D~ s/^\s+//; # strip leading blanks - next if ($f =3D~ /^$/); # skip blank lines - - # At the end of this Kconfig block: - # This only checks context lines in the patch - # and so hopefully shouldn't trigger false - # positives, even though some of these are - # common words in help texts - if ($f =3D~ /^(?:config|menuconfig|choice|endchoice| - if|endif|menu|endmenu|source)\b/x) { - last; - } - $help_length++ if ($has_help); - } - if ($needs_help && - $help_length < $min_conf_desc_length) { - my $stat_real =3D get_stat_real($linenr, $ln - 1); - WARN("CONFIG_DESCRIPTION", - "please write a help paragraph that fully describes the config sy= mbol\n" . "$here\n$stat_real\n"); - } - } - -# check MAINTAINERS entries - if ($realfile =3D~ /^MAINTAINERS$/) { -# check MAINTAINERS entries for the right form - if ($rawline =3D~ /^\+[A-Z]:/ && - $rawline !~ /^\+[A-Z]:\t\S/) { - if (WARN("MAINTAINERS_STYLE", - "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/^(\+[A-Z]):\s*/$1:\t/; - } - } -# check MAINTAINERS entries for the right ordering too - my $preferred_order =3D 'MRLSWQBCPTFXNK'; - if ($rawline =3D~ /^\+[A-Z]:/ && - $prevrawline =3D~ /^[\+ ][A-Z]:/) { - $rawline =3D~ /^\+([A-Z]):\s*(.*)/; - my $cur =3D $1; - my $curval =3D $2; - $prevrawline =3D~ /^[\+ ]([A-Z]):\s*(.*)/; - my $prev =3D $1; - my $prevval =3D $2; - my $curindex =3D index($preferred_order, $cur); - my $previndex =3D index($preferred_order, $prev); - if ($curindex < 0) { - WARN("MAINTAINERS_STYLE", - "Unknown MAINTAINERS entry type: '$cur'\n" . $herecurr); - } else { - if ($previndex >=3D 0 && $curindex < $previndex) { - WARN("MAINTAINERS_STYLE", - "Misordered MAINTAINERS entry - list '$cur:' before '$prev:'\n"= . $hereprev); - } elsif ((($prev eq 'F' && $cur eq 'F') || - ($prev eq 'X' && $cur eq 'X')) && - ($prevval cmp $curval) > 0) { - WARN("MAINTAINERS_STYLE", - "Misordered MAINTAINERS entry - list file patterns in alphabeti= c order\n" . $hereprev); - } - } - } - } - - if (($realfile =3D~ /Makefile.*/ || $realfile =3D~ /Kbuild.*/) && - ($line =3D~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { - my $flag =3D $1; - my $replacement =3D { - 'EXTRA_AFLAGS' =3D> 'asflags-y', - 'EXTRA_CFLAGS' =3D> 'ccflags-y', - 'EXTRA_CPPFLAGS' =3D> 'cppflags-y', - 'EXTRA_LDFLAGS' =3D> 'ldflags-y', - }; - - WARN("DEPRECATED_VARIABLE", - "Use of $flag is deprecated, please use \`$replacement->{$flag} in= stead.\n" . $herecurr) if ($replacement->{$flag}); - } - -# check for DT compatible documentation - if (defined $root && - (($realfile =3D~ /\.dtsi?$/ && $line =3D~ /^\+\s*compatible\s*=3D\s*\"/= ) || - ($realfile =3D~ /\.[ch]$/ && $line =3D~ /^\+.*\.compatible\s*=3D\s*\"/= ))) { - - my @compats =3D $rawline =3D~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; - - my $dt_path =3D $root . "/Documentation/devicetree/bindings/"; - my $vp_file =3D $dt_path . "vendor-prefixes.yaml"; - - foreach my $compat (@compats) { - my $compat2 =3D $compat; - $compat2 =3D~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; - my $compat3 =3D $compat; - $compat3 =3D~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/; - `grep -Erq "$compat|$compat2|$compat3" $dt_path`; - if ( $? >> 8 ) { - WARN("UNDOCUMENTED_DT_STRING", - "DT compatible string \"$compat\" appears un-documented -- check= $dt_path\n" . $herecurr); - } - - next if $compat !~ /^([a-zA-Z0-9\-]+)\,/; - my $vendor =3D $1; - `grep -Eq "\\"\\^\Q$vendor\E,\\.\\*\\":" $vp_file`; - if ( $? >> 8 ) { - WARN("UNDOCUMENTED_DT_STRING", - "DT compatible string vendor \"$vendor\" appears un-documented -= - check $vp_file\n" . $herecurr); - } - } - } - -# check for using SPDX license tag at beginning of files - if ($realline =3D=3D $checklicenseline) { - if ($rawline =3D~ /^[ \+]\s*\#\!\s*\//) { - $checklicenseline =3D 2; - } elsif ($rawline =3D~ /^\+/) { - my $comment =3D ""; - if ($realfile =3D~ /\.(h|s|S)$/) { - $comment =3D '/*'; - } elsif ($realfile =3D~ /\.(c|dts|dtsi)$/) { - $comment =3D '//'; - } elsif (($checklicenseline =3D=3D 2) || $realfile =3D~ /\.(sh|pl|py|a= wk|tc|yaml)$/) { - $comment =3D '#'; - } elsif ($realfile =3D~ /\.rst$/) { - $comment =3D '..'; - } - -# check SPDX comment style for .[chsS] files - if ($realfile =3D~ /\.[chsS]$/ && - $rawline =3D~ /SPDX-License-Identifier:/ && - $rawline !~ m@^\+\s*\Q$comment\E\s*@) { - WARN("SPDX_LICENSE_TAG", - "Improper SPDX comment style for '$realfile', please use '$comme= nt' instead\n" . $herecurr); - } - - if ($comment !~ /^$/ && - $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) { - WARN("SPDX_LICENSE_TAG", - "Missing or malformed SPDX-License-Identifier tag in line $check= licenseline\n" . $herecurr); - } elsif ($rawline =3D~ /(SPDX-License-Identifier: .*)/) { - my $spdx_license =3D $1; - if (!is_SPDX_License_valid($spdx_license)) { - WARN("SPDX_LICENSE_TAG", - "'$spdx_license' is not supported in LICENSES/...\n" . $herecur= r); - } - if ($realfile =3D~ m@^Documentation/devicetree/bindings/@ && - not $spdx_license =3D~ /GPL-2\.0.*BSD-2-Clause/) { - my $msg_level =3D \&WARN; - $msg_level =3D \&CHK if ($file); - if (&{$msg_level}("SPDX_LICENSE_TAG", - - "DT binding documents should be licensed (GPL-2.0-only OR BSD-2-= Clause)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/SPDX-License-Identifier: .*/SPDX-License-= Identifier: (GPL-2.0-only OR BSD-2-Clause)/; - } - } - } - } - } - -# check for embedded filenames - if ($rawline =3D~ /^\+.*\Q$realfile\E/) { - WARN("EMBEDDED_FILENAME", - "It's generally not useful to have the filename in the file\n" . $= herecurr); - } - -# check we are in a valid source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/); - -# check for using SPDX-License-Identifier on the wrong line number - if ($realline !=3D $checklicenseline && - $rawline =3D~ /\bSPDX-License-Identifier:/ && - substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) { - WARN("SPDX_LICENSE_TAG", - "Misplaced SPDX-License-Identifier tag - use line $checklicenselin= e instead\n" . $herecurr); - } - -# line length limit (with some exclusions) -# -# There are a few types of lines that may extend beyond $max_line_length: -# logging functions like pr_info that end in a string -# lines with a single string -# #defines that are a single string -# lines with an RFC3986 like URL -# -# There are 3 different line length message types: -# LONG_LINE_COMMENT a comment starts before but extends beyond $max_line_l= ength -# LONG_LINE_STRING a string starts before but extends beyond $max_line_len= gth -# LONG_LINE all other lines longer than $max_line_length -# -# if LONG_LINE is ignored, the other 2 types are also ignored -# - - if ($line =3D~ /^\+/ && $length > $max_line_length) { - my $msg_type =3D "LONG_LINE"; - - # Check the allowed long line types first - - # logging functions that end in a string that starts - # before $max_line_length - if ($line =3D~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($= String\s*(?:|,|\)\s*;)\s*)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1)= )) <=3D $max_line_length) { - $msg_type =3D ""; - - # lines with only strings (w/ possible termination) - # #defines with only strings - } elsif ($line =3D~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || - $line =3D~ /^\+\s*#\s*define\s+\w+\s+$String$/) { - $msg_type =3D ""; - - # More special cases - } elsif ($line =3D~ /^\+.*\bEFI_GUID\s*\(/ || - $line =3D~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) { - $msg_type =3D ""; - - # URL ($rawline is used in case the URL is in a comment) - } elsif ($rawline =3D~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) { - $msg_type =3D ""; - - # Otherwise set the alternate message types - - # a comment starts before $max_line_length - } elsif ($line =3D~ /($;[\s$;]*)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1)))= <=3D $max_line_length) { - $msg_type =3D "LONG_LINE_COMMENT" - - # a quoted string starts before $max_line_length - } elsif ($sline =3D~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1)))= <=3D $max_line_length) { - $msg_type =3D "LONG_LINE_STRING" - } - - if ($msg_type ne "" && - (show_type("LONG_LINE") || show_type($msg_type))) { - my $msg_level =3D \&WARN; - $msg_level =3D \&CHK if ($file); - &{$msg_level}($msg_type, - "line length of $length exceeds $max_line_length columns\n" . $= herecurr); - } - } - -# check for adding lines without a newline. - if ($line =3D~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =3D~ = /^\\ No newline at end of file/) { - if (WARN("MISSING_EOF_NEWLINE", - "adding a line without newline at end of file\n" . $herecurr) = && - $fix) { - fix_delete_line($fixlinenr+1, "No newline at end of file"); - } - } - -# check for .L prefix local symbols in .S files - if ($realfile =3D~ /\.S$/ && - $line =3D~ /^\+\s*(?:[A-Z]+_)?SYM_[A-Z]+_(?:START|END)(?:_[A-Z_]+)?\= s*\(\s*\.L/) { - WARN("AVOID_L_PREFIX", - "Avoid using '.L' prefixed local symbol names for denoting a range= of code via 'SYM_*_START/END' annotations; see Documentation/asm-annotatio= ns.rst\n" . $herecurr); - } - -# check we are in a valid source file C or perl if not then ignore this hu= nk - next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); - -# at the beginning of a line any tabs must come first and anything -# more than $tabsize must use tabs. - if ($rawline =3D~ /^\+\s* \t\s*\S/ || - $rawline =3D~ /^\+\s* \s*/) { - my $herevet =3D "$here\n" . cat_vet($rawline) . "\n"; - $rpt_cleaners =3D 1; - if (ERROR("CODE_INDENT", - "code indent should use tabs where possible\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =3D~ s/^\+([ \t]+)/"\+" . tabify($1)/e; - } - } - -# check for space before tabs. - if ($rawline =3D~ /^\+/ && $rawline =3D~ / \t/) { - my $herevet =3D "$here\n" . cat_vet($rawline) . "\n"; - if (WARN("SPACE_BEFORE_TAB", - "please, no space before tabs\n" . $herevet) && - $fix) { - while ($fixed[$fixlinenr] =3D~ - s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {} - while ($fixed[$fixlinenr] =3D~ - s/(^\+.*) +\t/$1\t/) {} - } - } - -# check for assignments on the start of a line - if ($sline =3D~ /^\+\s+($Assignment)[^=3D]/) { - my $operator =3D $1; - if (CHK("ASSIGNMENT_CONTINUATIONS", - "Assignment operator '$1' should be on the previous line\n" . $herepre= v) && - $fix && $prevrawline =3D~ /^\+/) { - # add assignment operator to the previous line, remove from current li= ne - $fixed[$fixlinenr - 1] .=3D " $operator"; - $fixed[$fixlinenr] =3D~ s/\Q$operator\E\s*//; - } - } - -# check for && or || at the start of a line - if ($rawline =3D~ /^\+\s*(&&|\|\|)/) { - my $operator =3D $1; - if (CHK("LOGICAL_CONTINUATIONS", - "Logical continuations should be on the previous line\n" . $hereprev) = && - $fix && $prevrawline =3D~ /^\+/) { - # insert logical operator at last non-comment, non-whitepsace char on = previous line - $prevline =3D~ /[\s$;]*$/; - my $line_end =3D substr($prevrawline, $-[0]); - $fixed[$fixlinenr - 1] =3D~ s/\Q$line_end\E$/ $operator$line_end/; - $fixed[$fixlinenr] =3D~ s/\Q$operator\E\s*//; - } - } - -# check indentation starts on a tab stop - if ($perl_version_ok && - $sline =3D~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|whil= e\b|\s*$)|$Declare\s*$Ident\s*[;=3D])/) { - my $indent =3D length($1); - if ($indent % $tabsize) { - if (WARN("TABSTOP", - "Statements should start on a tabstop\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e; - } - } - } - -# check multi-line statement indentation matches previous line - if ($perl_version_ok && - $prevline =3D~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declar= e\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=3D\s*$Ident\s*= )\(.*(\&\&|\|\||,)\s*$/) { - $prevline =3D~ /^\+(\t*)(.*)$/; - my $oldindent =3D $1; - my $rest =3D $2; - - my $pos =3D pos_last_openparen($rest); - if ($pos >=3D 0) { - $line =3D~ /^(\+| )([ \t]*)/; - my $newindent =3D $2; - - my $goodtabindent =3D $oldindent . - "\t" x ($pos / $tabsize) . - " " x ($pos % $tabsize); - my $goodspaceindent =3D $oldindent . " " x $pos; - - if ($newindent ne $goodtabindent && - $newindent ne $goodspaceindent) { - - if (CHK("PARENTHESIS_ALIGNMENT", - "Alignment should match open parenthesis\n" . $hereprev) && - $fix && $line =3D~ /^\+/) { - $fixed[$fixlinenr] =3D~ - s/^\+[ \t]*/\+$goodtabindent/; - } - } - } - } - -# check for space after cast like "(int) foo" or "(struct foo) bar" -# avoid checking a few false positives: -# "sizeof(<type>)" or "__alignof__(<type>)" -# function pointer declarations like "(*foo)(int) =3D bar;" -# structure definitions like "(struct foo) { 0 };" -# multiline macros that define functions -# known attributes or the __attribute__ keyword - if ($line =3D~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![=3D{]|\\$|$Attribute= |__attribute__))/ && - (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { - if (CHK("SPACING", - "No space is necessary after a cast\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/(\(\s*$Type\s*\))[ \t]+/$1/; - } - } - -# Block comment styles -# Networking with an initial /* - if ($realfile =3D~ m@^(drivers/net/|net/)@ && - $prevrawline =3D~ /^\+[ \t]*\/\*[ \t]*$/ && - $rawline =3D~ /^\+[ \t]*\*/ && - $realline > 3) { # Do not warn about the initial copyright comment b= lock after SPDX-License-Identifier - WARN("NETWORKING_BLOCK_COMMENT_STYLE", - "networking block comments don't use an empty /* line, use /* Comm= ent...\n" . $hereprev); - } - -# Block comments use * on subsequent lines - if ($prevline =3D~ /$;[ \t]*$/ && #ends in comment - $prevrawline =3D~ /^\+.*?\/\*/ && #starting /* - $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ - $rawline =3D~ /^\+/ && #line is new - $rawline !~ /^\+[ \t]*\*/) { #no leading * - WARN("BLOCK_COMMENT_STYLE", - "Block comments use * on subsequent lines\n" . $hereprev); - } - -# Block comments use */ on trailing lines - if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */ - $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/ - $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/ - $rawline =3D~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ - WARN("BLOCK_COMMENT_STYLE", - "Block comments use a trailing */ on a separate line\n" . $herecur= r); - } - -# Block comment * alignment - if ($prevline =3D~ /$;[ \t]*$/ && #ends in comment - $line =3D~ /^\+[ \t]*$;/ && #leading comment - $rawline =3D~ /^\+[ \t]*\*/ && #leading * - (($prevrawline =3D~ /^\+.*?\/\*/ && #leading /* - $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */ - $prevrawline =3D~ /^\+[ \t]*\*/)) { #leading * - my $oldindent; - $prevrawline =3D~ m@^\+([ \t]*/?)\*@; - if (defined($1)) { - $oldindent =3D expand_tabs($1); - } else { - $prevrawline =3D~ m@^\+(.*/?)\*@; - $oldindent =3D expand_tabs($1); - } - $rawline =3D~ m@^\+([ \t]*)\*@; - my $newindent =3D $1; - $newindent =3D expand_tabs($newindent); - if (length($oldindent) ne length($newindent)) { - WARN("BLOCK_COMMENT_STYLE", - "Block comments should align the * on each line\n" . $hereprev); - } - } - -# check for missing blank lines after struct/union declarations -# with exceptions for various attributes and macros - if ($prevline =3D~ /^[\+ ]};?\s*$/ && - $line =3D~ /^\+/ && - !($line =3D~ /^\+\s*$/ || - $line =3D~ /^\+\s*(?:EXPORT_SYMBOL|early_param)/ || - $line =3D~ /^\+\s*MODULE_/i || - $line =3D~ /^\+\s*\#\s*(?:end|elif|else)/ || - $line =3D~ /^\+[a-z_]*init/ || - $line =3D~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || - $line =3D~ /^\+\s*DECLARE/ || - $line =3D~ /^\+\s*builtin_[\w_]*driver/ || - $line =3D~ /^\+\s*__setup/)) { - if (CHK("LINE_SPACING", - "Please use a blank line after function/struct/union/enum declarations= \n" . $hereprev) && - $fix) { - fix_insert_line($fixlinenr, "\+"); - } - } - -# check for multiple consecutive blank lines - if ($prevline =3D~ /^[\+ ]\s*$/ && - $line =3D~ /^\+\s*$/ && - $last_blank_line !=3D ($linenr - 1)) { - if (CHK("LINE_SPACING", - "Please don't use multiple blank lines\n" . $hereprev) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - - $last_blank_line =3D $linenr; - } - -# check for missing blank lines after declarations -# (declarations must have the same indentation and not be at the start of = line) - if (($prevline =3D~ /\+(\s+)\S/) && $sline =3D~ /^\+$1\S/) { - # use temporaries - my $sl =3D $sline; - my $pl =3D $prevline; - # remove $Attribute/$Sparse uses to simplify comparisons - $sl =3D~ s/\b(?:$Attribute|$Sparse)\b//g; - $pl =3D~ s/\b(?:$Attribute|$Sparse)\b//g; - if (($pl =3D~ /^\+\s+$Declare\s*$Ident\s*[=3D,;:\[]/ || - # function pointer declarations - $pl =3D~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=3D,;:\[\(]/ || - # foo bar; where foo is some local typedef or #define - $pl =3D~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=3D,;\[]/ || - # known declaration macros - $pl =3D~ /^\+\s+$declaration_macros/) && - # for "else if" which can look like "$Ident $Ident" - !($pl =3D~ /^\+\s+$c90_Keywords\b/ || - # other possible extensions of declaration lines - $pl =3D~ /(?:$Compare|$Assignment|$Operators)\s*$/ || - # not starting a section or a macro "\" extended line - $pl =3D~ /(?:\{\s*|\\)$/) && - # looks like a declaration - !($sl =3D~ /^\+\s+$Declare\s*$Ident\s*[=3D,;:\[]/ || - # function pointer declarations - $sl =3D~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=3D,;:\[\(]/ = || - # foo bar; where foo is some local typedef or #define - $sl =3D~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=3D,;\[]/ || - # known declaration macros - $sl =3D~ /^\+\s+$declaration_macros/ || - # start of struct or union or enum - $sl =3D~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|t= ypedef)\b/ || - # start or end of block or continuation of declaration - $sl =3D~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || - # bitfield continuation - $sl =3D~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || - # other possible extensions of declaration lines - $sl =3D~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/)) { - if (WARN("LINE_SPACING", - "Missing a blank line after declarations\n" . $hereprev) && - $fix) { - fix_insert_line($fixlinenr, "\+"); - } - } - } - -# check for spaces at the beginning of a line. -# Exceptions: -# 1) within comments -# 2) indented preprocessor commands -# 3) hanging labels - if ($rawline =3D~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/) { - my $herevet =3D "$here\n" . cat_vet($rawline) . "\n"; - if (WARN("LEADING_SPACE", - "please, no spaces at the start of a line\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =3D~ s/^\+([ \t]+)/"\+" . tabify($1)/e; - } - } - -# check we are in a valid C source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c)$/); - -# check for unusual line ending [ or ( - if ($line =3D~ /^\+.*([\[\(])\s*$/) { - CHK("OPEN_ENDED_LINE", - "Lines should not end with a '$1'\n" . $herecurr); - } - -# check if this appears to be the start function declaration, save the name - if ($sline =3D~ /^\+\{\s*$/ && - $prevline =3D~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ide= nt)\(/) { - $context_function =3D $1; - } - -# check if this appears to be the end of function declaration - if ($sline =3D~ /^\+\}\s*$/) { - undef $context_function; - } - -# check indentation of any line with a bare else -# (but not if it is a multiple line "if (foo) return bar; else return baz;= ") -# if the previous line is a break or return and is indented 1 tab more... - if ($sline =3D~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) { - my $tabs =3D length($1) + 1; - if ($prevline =3D~ /^\+\t{$tabs,$tabs}break\b/ || - ($prevline =3D~ /^\+\t{$tabs,$tabs}return\b/ && - defined $lines[$linenr] && - $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) { - WARN("UNNECESSARY_ELSE", - "else is not generally useful after a break or return\n" . $herep= rev); - } - } - -# check indentation of a line with a break; -# if the previous line is a goto, return or break -# and is indented the same # of tabs - if ($sline =3D~ /^\+([\t]+)break\s*;\s*$/) { - my $tabs =3D $1; - if ($prevline =3D~ /^\+$tabs(goto|return|break)\b/) { - if (WARN("UNNECESSARY_BREAK", - "break is not useful after a $1\n" . $hereprev) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - } - } - -# check for RCS/CVS revision markers - if ($rawline =3D~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { - WARN("CVS_KEYWORD", - "CVS style keyword markers, these will _not_ be updated\n". $herec= urr); - } - -# check for old HOTPLUG __dev<foo> section markings - if ($line =3D~ /\b(__dev(init|exit)(data|const|))\b/) { - WARN("HOTPLUG_SECTION", - "Using $1 is unnecessary\n" . $herecurr); - } - -# Check for potential 'bare' types - my ($stat, $cond, $line_nr_next, $remain_next, $off_next, - $realline_next); -#print "LINE<$line>\n"; - if ($linenr > $suppress_statement && - $realcnt && $sline =3D~ /.\s*\S/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) =3D - ctx_statement_block($linenr, $realcnt, 0); - $stat =3D~ s/\n./\n /g; - $cond =3D~ s/\n./\n /g; - -#print "linenr<$linenr> <$stat>\n"; - # If this statement has no statement boundaries within - # it there is no point in retrying a statement scan - # until we hit end of it. - my $frag =3D $stat; $frag =3D~ s/;+\s*$//; - if ($frag !~ /(?:{|;)/) { -#print "skip<$line_nr_next>\n"; - $suppress_statement =3D $line_nr_next; - } - - # Find the real next line. - $realline_next =3D $line_nr_next; - if (defined $realline_next && - (!defined $lines[$realline_next - 1] || - substr($lines[$realline_next - 1], $off_next) =3D~ /^\s*$/)) { - $realline_next++; - } - - my $s =3D $stat; - $s =3D~ s/{.*$//s; - - # Ignore goto labels. - if ($s =3D~ /$Ident:\*$/s) { - - # Ignore functions being called - } elsif ($s =3D~ /^.\s*$Ident\s*\(/s) { - - } elsif ($s =3D~ /^.\s*else\b/s) { - - # declarations always start with types - } elsif ($prev_values eq 'E' && $s =3D~ /^.\s*(?:$Storage\s+)?(?:$Inlin= e\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\= *[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=3D|,|\()/s) { - my $type =3D $1; - $type =3D~ s/\s+/ /g; - possible($type, "A:" . $s); - - # definitions in global scope can only start with types - } elsif ($s =3D~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident= )\b\s*(?!:)/s) { - possible($1, "B:" . $s); - } - - # any (foo ... *) is a pointer cast, and foo is a type - while ($s =3D~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) { - possible($1, "C:" . $s); - } - - # Check for any sort of function declaration. - # int foo(something bar, other baz); - # void (*store_gdt)(x86_descr_ptr *); - if ($prev_values eq 'E' && $s =3D~ /^(.(?:typedef\s*)?(?:(?:$Storage|$I= nline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) { - my ($name_len) =3D length($1); - - my $ctx =3D $s; - substr($ctx, 0, $name_len + 1, ''); - $ctx =3D~ s/\)[^\)]*$//; - - for my $arg (split(/\s*,\s*/, $ctx)) { - if ($arg =3D~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Id= ent)?$/s || $arg =3D~ /^($Ident)$/s) { - - possible($1, "D:" . $s); - } - } - } - - } - -# -# Checks which may be anchored in the context. -# - -# Check for switch () and associated case and default -# statements should be at the same indent. - if ($line=3D~/\bswitch\s*\(.*\)/) { - my $err =3D ''; - my $sep =3D ''; - my @ctx =3D ctx_block_outer($linenr, $realcnt); - shift(@ctx); - for my $ctx (@ctx) { - my ($clen, $cindent) =3D line_stats($ctx); - if ($ctx =3D~ /^\+\s*(case\s+|default:)/ && - $indent !=3D $cindent) { - $err .=3D "$sep$ctx\n"; - $sep =3D ''; - } else { - $sep =3D "[...]\n"; - } - } - if ($err ne '') { - ERROR("SWITCH_CASE_INDENT_LEVEL", - "switch and case should be at the same indent\n$hereline$err"); - } - } - -# if/while/etc brace do not go on next line, unless defining a do while lo= op, -# or if that brace on the next line is for something else - if ($line =3D~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]= +)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { - my $pre_ctx =3D "$1$2"; - - my ($level, @ctx) =3D ctx_statement_level($linenr, $realcnt, 0); - - if ($line =3D~ /^\+\t{6,}/) { - WARN("DEEP_INDENTATION", - "Too many leading tabs - consider code refactoring\n" . $herecurr= ); - } - - my $ctx_cnt =3D $realcnt - $#ctx - 1; - my $ctx =3D join("\n", @ctx); - - my $ctx_ln =3D $linenr; - my $ctx_skip =3D $realcnt; - - while ($ctx_skip > $ctx_cnt || ($ctx_skip =3D=3D $ctx_cnt && - defined $lines[$ctx_ln - 1] && - $lines[$ctx_ln - 1] =3D~ /^-/)) { - ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n"; - $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~= /^-/); - $ctx_ln++; - } - - #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; - #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]= >\n"; - - if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - = 1] =3D~ /^\+\s*{/) { - ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - if ($level =3D=3D 0 && $pre_ctx !~ /}\s*while\s*\($/ && - $ctx =3D~ /\)\s*\;\s*$/ && - defined $lines[$ctx_ln - 1]) - { - my ($nlength, $nindent) =3D line_stats($lines[$ctx_ln - 1]); - if ($nindent > $indent) { - WARN("TRAILING_SEMICOLON", - "trailing semicolon indicates no statements, indent implies othe= rwise\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - } - } - -# Check relative indent for conditionals and blocks. - if ($line =3D~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|(= ?:do|else)\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) =3D - ctx_statement_block($linenr, $realcnt, 0) - if (!defined $stat); - my ($s, $c) =3D ($stat, $cond); - - substr($s, 0, length($c), ''); - - # remove inline comments - $s =3D~ s/$;/ /g; - $c =3D~ s/$;/ /g; - - # Find out how long the conditional actually is. - my @newlines =3D ($c =3D~ /\n/gs); - my $cond_lines =3D 1 + $#newlines; - - # Make sure we remove the line prefixes as we have - # none on the first line, and are going to readd them - # where necessary. - $s =3D~ s/\n./\n/gs; - while ($s =3D~ /\n\s+\\\n/) { - $cond_lines +=3D $s =3D~ s/\n\s+\\\n/\n/g; - } - - # 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 =3D 0; - my $check =3D 0; - $s =3D~ s/^.*\bdo\b//; - $s =3D~ s/^\s*{//; - if ($s =3D~ s/^\s*\\//) { - $continuation =3D 1; - } - if ($s =3D~ s/^\s*?\n//) { - $check =3D 1; - $cond_lines++; - } - - # Also ignore a loop construct at the end of a - # preprocessor statement. - if (($prevline =3D~ /^.\s*#\s*define\s/ || - $prevline =3D~ /\\\s*$/) && $continuation =3D=3D 0) { - $check =3D 0; - } - - my $cond_ptr =3D -1; - $continuation =3D 0; - while ($cond_ptr !=3D $cond_lines) { - $cond_ptr =3D $cond_lines; - - # If we see an #else/#elif then the code - # is not linear. - if ($s =3D~ /^\s*\#\s*(?:else|elif)/) { - $check =3D 0; - } - - # Ignore: - # 1) blank lines, they should be at 0, - # 2) preprocessor lines, and - # 3) labels. - if ($continuation || - $s =3D~ /^\s*?\n/ || - $s =3D~ /^\s*#\s*?/ || - $s =3D~ /^\s*$Ident\s*:/) { - $continuation =3D ($s =3D~ /^.*?\\\n/) ? 1 : 0; - if ($s =3D~ s/^.*?\n//) { - $cond_lines++; - } - } - } - - my (undef, $sindent) =3D line_stats("+" . $s); - my $stat_real =3D 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 =3D 0; - } - if (defined($stat_real) && $cond_lines > 1) { - $stat_real =3D "[...]\n$stat_real"; - } - - #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sinden= t> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> = stat_real<$stat_real> stat<$stat>\n"; - - if ($check && $s ne '' && - (($sindent % $tabsize) !=3D 0 || - ($sindent < $indent) || - ($sindent =3D=3D $indent && - ($s !~ /^\s*(?:\}|\{|else\b)/)) || - ($sindent > $indent + $tabsize))) { - WARN("SUSPECT_CODE_INDENT", - "suspect code indent for conditional statements ($indent, $sinden= t)\n" . $herecurr . "$stat_real\n"); - } - } - - # Track the 'values' across context and added lines. - my $opline =3D $line; $opline =3D~ s/^./ /; - my ($curr_values, $curr_vars) =3D - annotate_values($opline . "\n", $prev_values); - $curr_values =3D $prev_values . $curr_values; - if ($dbg_values) { - my $outline =3D $opline; $outline =3D~ s/\t/ /g; - print "$linenr > .$outline\n"; - print "$linenr > $curr_values\n"; - print "$linenr > $curr_vars\n"; - } - $prev_values =3D substr($curr_values, -1); - -#ignore lines not being added - next if ($line =3D~ /^[^\+]/); - -# check for self assignments used to avoid compiler warnings -# e.g.: int foo =3D foo, *bar =3D NULL; -# struct foo bar =3D *(&(bar)); - if ($line =3D~ /^\+\s*(?:$Declare)?([A-Za-z_][A-Za-z\d_]*)\s*=3D/) { - my $var =3D $1; - if ($line =3D~ /^\+\s*(?:$Declare)?$var\s*=3D\s*(?:$var|\*\s*\(?\s*&\s*= \(?\s*$var\s*\)?\s*\)?)\s*[;,]/) { - WARN("SELF_ASSIGNMENT", - "Do not use self-assignments to avoid compiler warnings\n" . $her= ecurr); - } - } - -# check for dereferences that span multiple lines - if ($prevline =3D~ /^\+.*$Lval\s*(?:\.|->)\s*$/ && - $line =3D~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) { - $prevline =3D~ /($Lval\s*(?:\.|->))\s*$/; - my $ref =3D $1; - $line =3D~ /^.\s*($Lval)/; - $ref .=3D $1; - $ref =3D~ s/\s//g; - WARN("MULTILINE_DEREFERENCE", - "Avoid multiple line dereference - prefer '$ref'\n" . $hereprev); - } - -# check for declarations of signed or unsigned without int - while ($line =3D~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($I= dent)?\s*[=3D,;\[\)\(]}g) { - my $type =3D $1; - my $var =3D $2; - $var =3D "" if (!defined $var); - if ($type =3D~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)= ((?:\s*\*)*)\s*$/) { - my $sign =3D $1; - my $pointer =3D $2; - - $pointer =3D "" if (!defined $pointer); - - if (WARN("UNSPECIFIED_INT", - "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use= of '$sign" . rtrim($pointer) . "'\n" . $herecurr) && - $fix) { - my $decl =3D trim($sign) . " int "; - my $comp_pointer =3D $pointer; - $comp_pointer =3D~ s/\s//g; - $decl .=3D $comp_pointer; - $decl =3D rtrim($decl) if ($var eq ""); - $fixed[$fixlinenr] =3D~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@; - } - } - } - -# TEST: allow direct testing of the type matcher. - if ($dbg_type) { - if ($line =3D~ /^.\s*$Declare\s*$/) { - ERROR("TEST_TYPE", - "TEST: is type\n" . $herecurr); - } elsif ($dbg_type > 1 && $line =3D~ /^.+($Declare)/) { - ERROR("TEST_NOT_TYPE", - "TEST: is not type ($1 is)\n". $herecurr); - } - next; - } -# TEST: allow direct testing of the attribute matcher. - if ($dbg_attr) { - if ($line =3D~ /^.\s*$Modifier\s*$/) { - ERROR("TEST_ATTR", - "TEST: is attr\n" . $herecurr); - } elsif ($dbg_attr > 1 && $line =3D~ /^.+($Modifier)/) { - ERROR("TEST_NOT_ATTR", - "TEST: is not attr ($1 is)\n". $herecurr); - } - next; - } - -# check for initialisation to aggregates open brace on the next line - if ($line =3D~ /^.\s*{/ && - $prevline =3D~ /(?:^|[^=3D])=3D\s*$/) { - if (ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . $hereprev) && - $fix && $prevline =3D~ /^\+/ && $line =3D~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline =3D $prevrawline; - $fixedline =3D~ s/\s*=3D\s*$/ =3D {/; - fix_insert_line($fixlinenr, $fixedline); - $fixedline =3D $line; - $fixedline =3D~ s/^(.\s*)\{\s*/$1/; - fix_insert_line($fixlinenr, $fixedline); - } - } - -# -# Checks which are anchored on the added line. -# - -# check for malformed paths in #include statements (uses RAW line) - if ($rawline =3D~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { - my $path =3D $1; - if ($path =3D~ m{//}) { - ERROR("MALFORMED_INCLUDE", - "malformed #include filename\n" . $herecurr); - } - if ($path =3D~ "^uapi/" && $realfile =3D~ m@\binclude/uapi/@) { - ERROR("UAPI_INCLUDE", - "No #include in ...include/uapi/... should use a uapi/ path pref= ix\n" . $herecurr); - } - } - -# no C99 // comments - if ($line =3D~ m{//}) { - if (ERROR("C99_COMMENTS", - "do not use C99 // comments\n" . $herecurr) && - $fix) { - my $line =3D $fixed[$fixlinenr]; - if ($line =3D~ /\/\/(.*)$/) { - my $comment =3D trim($1); - $fixed[$fixlinenr] =3D~ s@\/\/(.*)$@/\* $comment \*/@; - } - } - } - # Remove C99 comments. - $line =3D~ s@//.*@@; - $opline =3D~ s@//.*@@; - -# EXPORT_SYMBOL should immediately follow the thing it is exporting, consi= der -# 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] =3D~ /EXPORT_SYMBOL.*\((.*)\)/)) { - # Handle definitions which produce identifiers with - # a prefix: - # XXX(foo); - # EXPORT_SYMBOL(something_foo); - my $name =3D $1; - $name =3D~ s/^\s*($Ident).*/$1/; - if ($stat =3D~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && - $name =3D~ /^${Ident}_$2/) { -#print "FOO C name<$name>\n"; - $suppress_export{$realline_next} =3D 1; - - } elsif ($stat !~ /(?: - \n.}\s*$| - ^.DEFINE_$Ident\(\Q$name\E\)| - ^.DECLARE_$Ident\(\Q$name\E\)| - ^.LIST_HEAD\(\Q$name\E\)| - ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(| - \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=3D|\[|\() - )/x) { -#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n"; - $suppress_export{$realline_next} =3D 2; - } else { - $suppress_export{$realline_next} =3D 1; - } - } - if (!defined $suppress_export{$linenr} && - $prevline =3D~ /^.\s*$/ && - ($line =3D~ /EXPORT_SYMBOL.*\((.*)\)/)) { -#print "FOO B <$lines[$linenr - 1]>\n"; - $suppress_export{$linenr} =3D 2; - } - if (defined $suppress_export{$linenr} && - $suppress_export{$linenr} =3D=3D 2) { - WARN("EXPORT_SYMBOL", - "EXPORT_SYMBOL(foo); should immediately follow its function/variab= le\n" . $herecurr); - } - -# check for global initialisers. - if ($line =3D~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=3D\s*($zero_initia= lizer)\s*;/ && - !exclude_global_initialisers($realfile)) { - if (ERROR("GLOBAL_INITIALISERS", - "do not initialise globals to $1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=3D\s*= $zero_initializer\s*;/$1;/; - } - } -# check for static initialisers. - if ($line =3D~ /^\+.*\bstatic\s.*=3D\s*($zero_initializer)\s*;/) { - if (ERROR("INITIALISED_STATIC", - "do not initialise statics to $1\n" . - $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/(\bstatic\s.*?)\s*=3D\s*$zero_initializer\s*= ;/$1;/; - } - } - -# check for misordered declarations of char/short/int/long with signed/uns= igned - while ($sline =3D~ m{(\b$TypeMisordered\b)}g) { - my $tmp =3D trim($1); - WARN("MISORDERED_TYPE", - "type '$tmp' should be specified in [[un]signed] [short|int|long|l= ong long] order\n" . $herecurr); - } - -# check for unnecessary <signed> int declarations of short/long/long long - while ($sline =3D~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) { - my $type =3D trim($1); - next if ($type !~ /\bint\b/); - next if ($type !~ /\b(?:short|long\s+long|long)\b/); - my $new_type =3D $type; - $new_type =3D~ s/\b\s*int\s*\b/ /; - $new_type =3D~ s/\b\s*(?:un)?signed\b\s*/ /; - $new_type =3D~ s/^const\s+//; - $new_type =3D "unsigned $new_type" if ($type =3D~ /\bunsigned\b/); - $new_type =3D "const $new_type" if ($type =3D~ /^const\b/); - $new_type =3D~ s/\s+/ /g; - $new_type =3D trim($new_type); - if (WARN("UNNECESSARY_INT", - "Prefer '$new_type' over '$type' as the int is unnecessary\n" . $here= curr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\b\Q$type\E\b/$new_type/; - } - } - -# check for static const char * arrays. - if ($line =3D~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=3D\s*/= ) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static const char * array should probably be static const char * = const\n" . - $herecurr); - } - -# check for initialized const char arrays that should be static const - if ($line =3D~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_= t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=3D\s*"/) { - if (WARN("STATIC_CONST_CHAR_ARRAY", - "const array should probably be static const\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/(^.\s*)const\b/${1}static const/; - } - } - -# check for static char foo[] =3D "bar" declarations. - if ($line =3D~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=3D\s*"/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static char array declaration should probably be static const cha= r\n" . - $herecurr); - } - -# check for const <foo> const where <foo> is not a pointer or array type - if ($sline =3D~ /\bconst\s+($BasicType)\s+const\b/) { - my $found =3D $1; - if ($sline =3D~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) { - WARN("CONST_CONST", - "'const $found const *' should probably be 'const $found * const'= \n" . $herecurr); - } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) { - WARN("CONST_CONST", - "'const $found const' should probably be 'const $found'\n" . $her= ecurr); - } - } - -# check for const static or static <non ptr type> const declarations -# prefer 'static const <foo>' over 'const static <foo>' and 'static <foo> = const' - if ($sline =3D~ /^\+\s*const\s+static\s+($Type)\b/ || - $sline =3D~ /^\+\s*static\s+($BasicType)\s+const\b/) { - if (WARN("STATIC_CONST", - "Move const after static - use 'static const $1'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\bconst\s+static\b/static const/; - $fixed[$fixlinenr] =3D~ s/\bstatic\s+($BasicType)\s+const\b/static con= st $1/; - } - } - -# check for non-global char *foo[] =3D {"bar", ...} declarations. - if ($line =3D~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*= =3D\s*\{/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "char * array declaration might be better as static const\n" . - $herecurr); - } - -# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) - if ($line =3D~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { - my $array =3D $1; - if ($line =3D~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\= Q$array\E\s*\[\s*0\s*\]\s*\))@) { - my $array_div =3D $1; - if (WARN("ARRAY_SIZE", - "Prefer ARRAY_SIZE($array)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\Q$array_div\E/ARRAY_SIZE($array)/; - } - } - } - -# check for function declarations without arguments like "int foo()" - if ($line =3D~ /(\b$Type\s*$Ident)\s*\(\s*\)/) { - if (ERROR("FUNCTION_WITHOUT_ARGS", - "Bad function definition - $1() should probably be $1(void)\n" . $he= recurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)= /; - } - } - -# check for new typedefs, only function parameters and sparse annotations -# make sense. - if ($line =3D~ /\btypedef\s/ && - $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && - $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && - $line !~ /\b$typeTypedefs\b/ && - $line !~ /\b__bitwise\b/) { - WARN("NEW_TYPEDEFS", - "do not add new typedefs\n" . $herecurr); - } - -# * goes on variable not on type - # (char*[ const]) - while ($line =3D~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) { - #print "AA<$1>\n"; - my ($ident, $from, $to) =3D ($1, $2, $2); - - # Should start with a space. - $to =3D~ s/^(\S)/ $1/; - # Should not end with a space. - $to =3D~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =3D~ s/\*\s+\*/\*\*/) { - } - -## print "1: from<$from> to<$to> ident<$ident>\n"; - if ($from ne $to) { - if (ERROR("POINTER_LOCATION", - "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) && - $fix) { - my $sub_from =3D $ident; - my $sub_to =3D $ident; - $sub_to =3D~ s/\Q$from\E/$to/; - $fixed[$fixlinenr] =3D~ - s@\Q$sub_from\E@$sub_to@; - } - } - } - while ($line =3D~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)= )}g) { - #print "BB<$1>\n"; - my ($match, $from, $to, $ident) =3D ($1, $2, $2, $3); - - # Should start with a space. - $to =3D~ s/^(\S)/ $1/; - # Should not end with a space. - $to =3D~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =3D~ s/\*\s+\*/\*\*/) { - } - # Modifiers should have spaces. - $to =3D~ s/(\b$Modifier$)/$1 /; - -## print "2: from<$from> to<$to> ident<$ident>\n"; - if ($from ne $to && $ident !~ /^$Modifier$/) { - if (ERROR("POINTER_LOCATION", - "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) && - $fix) { - - my $sub_from =3D $match; - my $sub_to =3D $match; - $sub_to =3D~ s/\Q$from\E/$to/; - $fixed[$fixlinenr] =3D~ - s@\Q$sub_from\E@$sub_to@; - } - } - } - -# avoid BUG() or BUG_ON() - if ($line =3D~ /\b(?:BUG|BUG_ON)\b/) { - my $msg_level =3D \&WARN; - $msg_level =3D \&CHK if ($file); - &{$msg_level}("AVOID_BUG", - "Avoid crashing the kernel - try using WARN_ON & recovery code r= ather than BUG() or BUG_ON()\n" . $herecurr); - } - -# avoid LINUX_VERSION_CODE - if ($line =3D~ /\bLINUX_VERSION_CODE\b/) { - WARN("LINUX_VERSION_CODE", - "LINUX_VERSION_CODE should be avoided, code should be for the vers= ion to which it is merged\n" . $herecurr); - } - -# check for uses of printk_ratelimit - if ($line =3D~ /\bprintk_ratelimit\s*\(/) { - WARN("PRINTK_RATELIMITED", - "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_rat= elimit\n" . $herecurr); - } - -# printk should use KERN_* levels - if ($line =3D~ /\bprintk\s*\(\s*(?!KERN_[A-Z]+\b)/) { - WARN("PRINTK_WITHOUT_KERN_LEVEL", - "printk() should include KERN_<LEVEL> facility level\n" . $herecur= r); - } - -# prefer variants of (subsystem|netdev|dev|pr)_<level> to printk(KERN_<LEV= EL> - if ($line =3D~ /\b(printk(_once|_ratelimited)?)\s*\(\s*KERN_([A-Z]+)/) { - my $printk =3D $1; - my $modifier =3D $2; - my $orig =3D $3; - $modifier =3D "" if (!defined($modifier)); - my $level =3D lc($orig); - $level =3D "warn" if ($level eq "warning"); - my $level2 =3D $level; - $level2 =3D "dbg" if ($level eq "debug"); - $level .=3D $modifier; - $level2 .=3D $modifier; - WARN("PREFER_PR_LEVEL", - "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then de= v_$level2(dev, ... then pr_$level(... to $printk(KERN_$orig ...\n" . $here= curr); - } - -# prefer dev_<level> to dev_printk(KERN_<LEVEL> - if ($line =3D~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) { - my $orig =3D $1; - my $level =3D lc($orig); - $level =3D "warn" if ($level eq "warning"); - $level =3D "dbg" if ($level eq "debug"); - WARN("PREFER_DEV_LEVEL", - "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecur= r); - } - -# trace_printk should not be used in production code. - if ($line =3D~ /\b(trace_printk|trace_puts|ftrace_vprintk)\s*\(/) { - WARN("TRACE_PRINTK", - "Do not use $1() in production code (this can be ignored if built = only with a debug config option)\n" . $herecurr); - } - -# ENOSYS means "bad syscall nr" and nothing else. This will have a small -# number of false positives, but assembly files are not checked, so at -# least the arch entry code will not trigger this warning. - if ($line =3D~ /\bENOSYS\b/) { - WARN("ENOSYS", - "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr= ); - } - -# ENOTSUPP is not a standard error code and should be avoided in new patch= es. -# Folks usually mean EOPNOTSUPP (also called ENOTSUP), when they type ENOT= SUPP. -# Similarly to ENOSYS warning a small number of false positives is expecte= d. - if (!$file && $line =3D~ /\bENOTSUPP\b/) { - if (WARN("ENOTSUPP", - "ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP\n" . $herecurr= ) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\bENOTSUPP\b/EOPNOTSUPP/; - } - } - -# function brace can't be on same line, except for #defines of do while, -# or if closed on same line - if ($perl_version_ok && - $sline =3D~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ && - $sline !~ /\#\s*define\b.*do\s*\{/ && - $sline !~ /}/) { - if (ERROR("OPEN_BRACE", - "open brace '{' following function definitions go on the next line\n= " . $herecurr) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - my $fixed_line =3D $rawline; - $fixed_line =3D~ /(^..*$Type\s*$Ident\(.*\)\s*)\{(.*)$/; - my $line1 =3D $1; - my $line2 =3D $2; - fix_insert_line($fixlinenr, ltrim($line1)); - fix_insert_line($fixlinenr, "\+{"); - if ($line2 !~ /^\s*$/) { - fix_insert_line($fixlinenr, "\+\t" . trim($line2)); - } - } - } - -# open braces for enum, union and struct go on the same line. - if ($line =3D~ /^.\s*{/ && - $prevline =3D~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)= ?\s*$/) { - if (ERROR("OPEN_BRACE", - "open brace '{' following $1 go on the same line\n" . $hereprev) && - $fix && $prevline =3D~ /^\+/ && $line =3D~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline =3D rtrim($prevrawline) . " {"; - fix_insert_line($fixlinenr, $fixedline); - $fixedline =3D $rawline; - $fixedline =3D~ s/^(.\s*)\{\s*/$1\t/; - if ($fixedline !~ /^\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - } - } - -# missing space after union, struct or enum definition - if ($line =3D~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2= }[=3D\{]/) { - if (WARN("SPACING", - "missing space after $1 definition\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([= =3D\{])/$1 $2/; - } - } - -# Function pointer declarations -# check spacing between type, funcptr, and args -# canonical declaration is "type (*funcptr)(args...)" - if ($line =3D~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) { - my $declare =3D $1; - my $pre_pointer_space =3D $2; - my $post_pointer_space =3D $3; - my $funcname =3D $4; - my $post_funcname_space =3D $5; - my $pre_args_space =3D $6; - -# the $Declare variable will capture all spaces after the type -# so check it for a missing trailing missing space but pointer return types -# don't need a space so don't warn for those. - my $post_declare_space =3D ""; - if ($declare =3D~ /(\s+)$/) { - $post_declare_space =3D $1; - $declare =3D rtrim($declare); - } - if ($declare !~ /\*$/ && $post_declare_space =3D~ /^$/) { - WARN("SPACING", - "missing space after return type\n" . $herecurr); - $post_declare_space =3D " "; - } - -# unnecessary space "type (*funcptr)(args...)" -# This test is not currently implemented because these declarations are -# equivalent to -# int foo(int bar, ...) -# and this is form shouldn't/doesn't generate a checkpatch warning. -# -# elsif ($declare =3D~ /\s{2,}$/) { -# WARN("SPACING", -# "Multiple spaces after return type\n" . $herecurr); -# } - -# unnecessary space "type ( *funcptr)(args...)" - if (defined $pre_pointer_space && - $pre_pointer_space =3D~ /^\s/) { - WARN("SPACING", - "Unnecessary space after function pointer open parenthesis\n" . $= herecurr); - } - -# unnecessary space "type (* funcptr)(args...)" - if (defined $post_pointer_space && - $post_pointer_space =3D~ /^\s/) { - WARN("SPACING", - "Unnecessary space before function pointer name\n" . $herecurr); - } - -# unnecessary space "type (*funcptr )(args...)" - if (defined $post_funcname_space && - $post_funcname_space =3D~ /^\s/) { - WARN("SPACING", - "Unnecessary space after function pointer name\n" . $herecurr); - } - -# unnecessary space "type (*funcptr) (args...)" - if (defined $pre_args_space && - $pre_args_space =3D~ /^\s/) { - WARN("SPACING", - "Unnecessary space before function pointer arguments\n" . $herecu= rr); - } - - if (show_type("SPACING") && $fix) { - $fixed[$fixlinenr] =3D~ - s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $po= st_declare_space . '(*' . $funcname . ')('/ex; - } - } - -# check for spacing round square brackets; allowed: -# 1. with a type on the left -- int [] a; -# 2. at the beginning of a line for slice initialisers -- [0...10] =3D 5, -# 3. inside a curly brace -- =3D { [0...10] =3D 5 } - while ($line =3D~ /(.*?\s)\[/g) { - my ($where, $prefix) =3D ($-[1], $1); - if ($prefix !~ /$Type\s+$/ && - ($where !=3D 0 || $prefix !~ /^.\s+$/) && - $prefix !~ /[{,:]\s+$/) { - if (ERROR("BRACKET_SPACE", - "space prohibited before open square bracket '['\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/^(\+.*?)\s+\[/$1\[/; - } - } - } - -# check for spaces between functions and their parentheses. - while ($line =3D~ /($Ident)\s+\(/g) { - my $name =3D $1; - my $ctx_before =3D substr($line, 0, $-[1]); - my $ctx =3D "$ctx_before$name"; - - # Ignore those directives where spaces _are_ permitted. - if ($name =3D~ /^(?: - if|for|while|switch|return|case| - volatile|__volatile__| - __attribute__|format|__extension__| - asm|__asm__)$/x) - { - # 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. - } elsif ($ctx_before =3D~ /^.\s*\#\s*define\s*$/) { - - # cpp #elif statement condition may start with a ( - } elsif ($ctx =3D~ /^.\s*\#\s*elif\s*$/) { - - # If this whole things ends with a type its most - # likely a typedef for a function. - } elsif ($ctx =3D~ /$Type$/) { - - } else { - if (WARN("SPACING", - "space prohibited between function name and open parenthesis '('\n" = . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/\b$name\s+\(/$name\(/; - } - } - } - -# Check operator spacing. - if (!($line=3D~/\#\s*include/)) { - my $fixed_line =3D ""; - my $line_fixed =3D 0; - - my $ops =3D qr{ - <<=3D|>>=3D|<=3D|>=3D|=3D=3D|!=3D| - \+=3D|-=3D|\*=3D|\/=3D|%=3D|\^=3D|\|=3D|&=3D| - =3D>|->|<<|>>|<|>|=3D|!|~| - &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| - \?:|\?|: - }x; - my @elements =3D split(/($ops|;)/, $opline); - -## print("element count: <" . $#elements . ">\n"); -## foreach my $el (@elements) { -## print("el: <$el>\n"); -## } - - my @fix_elements =3D (); - my $off =3D 0; - - foreach my $el (@elements) { - push(@fix_elements, substr($rawline, $off, length($el))); - $off +=3D length($el); - } - - $off =3D 0; - - my $blank =3D copy_spacing($opline); - my $last_after =3D -1; - - for (my $n =3D 0; $n < $#elements; $n +=3D 2) { - - my $good =3D $fix_elements[$n] . $fix_elements[$n + 1]; - -## print("n: <$n> good: <$good>\n"); - - $off +=3D length($elements[$n]); - - # Pick up the preceding and succeeding characters. - my $ca =3D substr($opline, 0, $off); - my $cc =3D ''; - if (length($opline) >=3D ($off + length($elements[$n + 1]))) { - $cc =3D substr($opline, $off + length($elements[$n + 1])); - } - my $cb =3D "$ca$;$cc"; - - my $a =3D ''; - $a =3D 'V' if ($elements[$n] ne ''); - $a =3D 'W' if ($elements[$n] =3D~ /\s$/); - $a =3D 'C' if ($elements[$n] =3D~ /$;$/); - $a =3D 'B' if ($elements[$n] =3D~ /(\[|\()$/); - $a =3D 'O' if ($elements[$n] eq ''); - $a =3D 'E' if ($ca =3D~ /^\s*$/); - - my $op =3D $elements[$n + 1]; - - my $c =3D ''; - if (defined $elements[$n + 2]) { - $c =3D 'V' if ($elements[$n + 2] ne ''); - $c =3D 'W' if ($elements[$n + 2] =3D~ /^\s/); - $c =3D 'C' if ($elements[$n + 2] =3D~ /^$;/); - $c =3D 'B' if ($elements[$n + 2] =3D~ /^(\)|\]|;)/); - $c =3D 'O' if ($elements[$n + 2] eq ''); - $c =3D 'E' if ($elements[$n + 2] =3D~ /^\s*\\$/); - } else { - $c =3D 'E'; - } - - my $ctx =3D "${a}x${c}"; - - my $at =3D "(ctx:$ctx)"; - - my $ptr =3D substr($blank, 0, $off) . "^"; - my $hereptr =3D "$hereline$ptr\n"; - - # Pull out the value of this operator. - my $op_type =3D substr($curr_values, $off + 1, 1); - - # Get the full operator variant. - my $opv =3D $op . substr($curr_vars, $off, 1); - - # Ignore operators passed as parameters. - if ($op_type ne 'V' && - $ca =3D~ /\s$/ && $cc =3D~ /^\s*[,\)]/) { - -# # Ignore comments -# } elsif ($op =3D~ /^$;+$/) { - - # ; should have either the end of line or a space or \ after it - } elsif ($op eq ';') { - if ($ctx !~ /.x[WEBC]/ && - $cc !~ /^\\/ && $cc !~ /^;/) { - if (ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr)) { - $good =3D $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; - $line_fixed =3D 1; - } - } - - # // is a comment - } elsif ($op eq '//') { - - # : when part of a bitfield - } elsif ($opv eq ':B') { - # skip the bitfield test for now - - # No spaces for: - # -> - } elsif ($op eq '->') { - if ($ctx =3D~ /Wx.|.xW/) { - if (ERROR("SPACING", - "spaces prohibited around that '$op' $at\n" . $hereptr)) { - $good =3D rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =3D~ s/^\s+//; - } - $line_fixed =3D 1; - } - } - - # , must not have a space before and must have a space on the right. - } elsif ($op eq ',') { - my $rtrim_before =3D 0; - my $space_after =3D 0; - if ($ctx =3D~ /Wx./) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $line_fixed =3D 1; - $rtrim_before =3D 1; - } - } - if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { - if (ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr)) { - $line_fixed =3D 1; - $last_after =3D $n; - $space_after =3D 1; - } - } - if ($rtrim_before || $space_after) { - if ($rtrim_before) { - $good =3D rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - } else { - $good =3D $fix_elements[$n] . trim($fix_elements[$n + 1]); - } - if ($space_after) { - $good .=3D " "; - } - } - - # '*' as part of a type definition -- reported already. - } elsif ($opv eq '*_') { - #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 '~' || - $opv eq '*U' || $opv eq '-U' || - $opv eq '&U' || $opv eq '&&U') { - if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$= /) { - if (ERROR("SPACING", - "space required before that '$op' $at\n" . $hereptr)) { - if ($n !=3D $last_after + 2) { - $good =3D $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]); - $line_fixed =3D 1; - } - } - } - if ($op eq '*' && $cc =3D~/\s*$Modifier\b/) { - # A unary '*' may be const - - } elsif ($ctx =3D~ /.xW/) { - if (ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr)) { - $good =3D $fix_elements[$n] . rtrim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =3D~ s/^\s+//; - } - $line_fixed =3D 1; - } - } - - # unary ++ and unary -- are allowed no space on one side. - } elsif ($op eq '++' or $op eq '--') { - if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { - if (ERROR("SPACING", - "space required one side of that '$op' $at\n" . $hereptr)) { - $good =3D $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; - $line_fixed =3D 1; - } - } - if ($ctx =3D~ /Wx[BE]/ || - ($ctx =3D~ /Wx./ && $cc =3D~ /^;/)) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $good =3D rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - $line_fixed =3D 1; - } - } - if ($ctx =3D~ /ExW/) { - if (ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr)) { - $good =3D $fix_elements[$n] . trim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =3D~ s/^\s+//; - } - $line_fixed =3D 1; - } - } - - # << and >> may either have or not have spaces both sides - } elsif ($op eq '<<' or $op eq '>>' or - $op eq '&' or $op eq '^' or $op eq '|' or - $op eq '+' or $op eq '-' or - $op eq '*' or $op eq '/' or - $op eq '%') - { - if ($check) { - if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) { - if (CHK("SPACING", - "spaces preferred around that '$op' $at\n" . $hereptr)) { - $good =3D rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n += 1]) . " "; - $fix_elements[$n + 2] =3D~ s/^\s+//; - $line_fixed =3D 1; - } - } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) { - if (CHK("SPACING", - "space preferred before that '$op' $at\n" . $hereptr)) { - $good =3D rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n += 1]); - $line_fixed =3D 1; - } - } - } elsif ($ctx =3D~ /Wx[^WCE]|[^WCE]xW/) { - if (ERROR("SPACING", - "need consistent spacing around '$op' $at\n" . $hereptr)) { - $good =3D rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + = 1]) . " "; - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =3D~ s/^\s+//; - } - $line_fixed =3D 1; - } - } - - # 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 =3D~ /Wx./ and $realfile !~ m@.*\.lds\.h$@) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $good =3D rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - $line_fixed =3D 1; - } - } - - # All the others need spaces both sides. - } elsif ($ctx !~ /[EWC]x[CWE]/) { - my $ok =3D 0; - - # Ignore email addresses <foo@bar> - if (($op eq '<' && - $cc =3D~ /^\S+\@\S+>/) || - ($op eq '>' && - $ca =3D~ /<\S+\@\S+$/)) - { - $ok =3D 1; - } - - # for asm volatile statements - # ignore a colon with another - # colon immediately before or after - if (($op eq ':') && - ($ca =3D~ /:$/ || $cc =3D~ /^:/)) { - $ok =3D 1; - } - - # messages are ERROR, but ?: are CHK - if ($ok =3D=3D 0) { - my $msg_level =3D \&ERROR; - $msg_level =3D \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') &= & $ctx =3D~ /VxV/); - - if (&{$msg_level}("SPACING", - "spaces required around that '$op' $at\n" . $hereptr)) { - $good =3D rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + = 1]) . " "; - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =3D~ s/^\s+//; - } - $line_fixed =3D 1; - } - } - } - $off +=3D length($elements[$n + 1]); - -## print("n: <$n> GOOD: <$good>\n"); - - $fixed_line =3D $fixed_line . $good; - } - - if (($#elements % 2) =3D=3D 0) { - $fixed_line =3D $fixed_line . $fix_elements[$#elements]; - } - - if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) { - $fixed[$fixlinenr] =3D $fixed_line; - } - - - } - -# check for whitespace before a non-naked semicolon - if ($line =3D~ /^\+.*\S\s+;\s*$/) { - if (WARN("SPACING", - "space prohibited before semicolon\n" . $herecurr) && - $fix) { - 1 while $fixed[$fixlinenr] =3D~ - s/^(\+.*\S)\s+;/$1;/; - } - } - -# check for multiple assignments - if ($line =3D~ /^.\s*$Lval\s*=3D\s*$Lval\s*=3D(?!=3D)/) { - CHK("MULTIPLE_ASSIGNMENTS", - "multiple assignments should be avoided\n" . $herecurr); - } - -## # check for multiple declarations, allowing for a function declaration -## # continuation. -## if ($line =3D~ /^.\s*$Type\s+$Ident(?:\s*=3D[^,{]*)?\s*,\s*$Ident.*/ = && -## $line !~ /^.\s*$Type\s+$Ident(?:\s*=3D[^,{]*)?\s*,\s*$Type\s*$Ide= nt.*/) { -## -## # Remove any bracketed sections to ensure we do not -## # falsely report the parameters of functions. -## my $ln =3D $line; -## while ($ln =3D~ s/\([^\(\)]*\)//g) { -## } -## if ($ln =3D~ /,/) { -## WARN("MULTIPLE_DECLARATION", -## "declaring multiple variables together should be avoided\n" . $= herecurr); -## } -## } - -#need space before brace following if, while, etc - if (($line =3D~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) || - $line =3D~ /\b(?:else|do)\{/) { - if (ERROR("SPACING", - "space required before the open brace '{'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/^(\+.*(?:do|else|\)))\{/$1 {/; - } - } - -## # check for blank lines before declarations -## if ($line =3D~ /^.\t+$Type\s+$Ident(?:\s*=3D.*)?;/ && -## $prevrawline =3D~ /^.\s*$/) { -## WARN("SPACING", -## "No blank lines before declarations\n" . $hereprev); -## } -## - -# closing brace should have a space following it when it has anything -# on the line - if ($line =3D~ /}(?!(?:,|;|\)|\}))\S/) { - if (ERROR("SPACING", - "space required after that close brace '}'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/}((?!(?:,|;|\)))\S)/} $1/; - } - } - -# check spacing on square brackets - if ($line =3D~ /\[\s/ && $line !~ /\[\s*$/) { - if (ERROR("SPACING", - "space prohibited after that open square bracket '['\n" . $herecurr)= && - $fix) { - $fixed[$fixlinenr] =3D~ - s/\[\s+/\[/; - } - } - if ($line =3D~ /\s\]/) { - if (ERROR("SPACING", - "space prohibited before that close square bracket ']'\n" . $herecur= r) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/\s+\]/\]/; - } - } - -# check spacing on parentheses - if ($line =3D~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && - $line !~ /for\s*\(\s+;/) { - if (ERROR("SPACING", - "space prohibited after that open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/\(\s+/\(/; - } - } - if ($line =3D~ /(\s+)\)/ && $line !~ /^.\s*\)/ && - $line !~ /for\s*\(.*;\s+\)/ && - $line !~ /:\s+\)/) { - if (ERROR("SPACING", - "space prohibited before that close parenthesis ')'\n" . $herecurr) = && - $fix) { - $fixed[$fixlinenr] =3D~ - s/\s+\)/\)/; - } - } - -# check unnecessary parentheses around addressof/dereference single $Lvals -# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar - - while ($line =3D~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g= ) { - my $var =3D $1; - if (CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around $var\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\(\s*\Q$var\E\s*\)/$var/; - } - } - -# check for unnecessary parentheses around function pointer uses -# ie: (foo->bar)(); should be foo->bar(); -# but not "if (foo->bar) (" to avoid some false positives - if ($line =3D~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && = $1 !~ /^if/) { - my $var =3D $2; - if (CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around function pointer $var\n" . $herecurr) = && - $fix) { - my $var2 =3D deparenthesize($var); - $var2 =3D~ s/\s//g; - $fixed[$fixlinenr] =3D~ s/\Q$var\E/$var2/; - } - } - -# check for unnecessary parentheses around comparisons in if uses -# when !drivers/staging or command-line uses --strict - if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) && - $perl_version_ok && defined($stat) && - $stat =3D~ /(^.\s*if\s*($balanced_parens))/) { - my $if_stat =3D $1; - my $test =3D substr($2, 1, -1); - my $herectx; - while ($test =3D~ /(?:^|[^\w\&\!\~])+\s*\(\s*([\&\!\~]?\s*$Lval\s*(?:$C= ompare\s*$FuncArg)?)\s*\)/g) { - my $match =3D $1; - # avoid parentheses around potential macro args - next if ($match =3D~ /^\s*\w+\s*$/); - if (!defined($herectx)) { - $herectx =3D $here . "\n"; - my $cnt =3D statement_rawlines($if_stat); - for (my $n =3D 0; $n < $cnt; $n++) { - my $rl =3D raw_line($linenr, $n); - $herectx .=3D $rl . "\n"; - last if $rl =3D~ /^[ \+].*\{/; - } - } - CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around '$match'\n" . $herectx); - } - } - -# check that goto labels aren't indented (allow a single space indentation) -# and ignore bitfield definitions like foo:1 -# Strictly, labels can have whitespace after the identifier and before the= : -# but this is not allowed here as many ?: uses would appear to be labels - if ($sline =3D~ /^.\s+[A-Za-z_][A-Za-z\d_]*:(?!\s*\d+)/ && - $sline !~ /^. [A-Za-z\d_][A-Za-z\d_]*:/ && - $sline !~ /^.\s+default:/) { - if (WARN("INDENTED_LABEL", - "labels should not be indented\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/^(.)\s+/$1/; - } - } - -# check if a statement with a comma should be two statements like: -# foo =3D bar(), /* comma should be semicolon */ -# bar =3D baz(); - if (defined($stat) && - $stat =3D~ /^\+\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*,\s*(?:$Lval= \s*$Assignment\s*)?$FuncArg\s*;\s*$/) { - my $cnt =3D statement_rawlines($stat); - my $herectx =3D get_stat_here($linenr, $cnt, $here); - WARN("SUSPECT_COMMA_SEMICOLON", - "Possible comma where semicolon could be used\n" . $herectx); - } - -# return is not a function - if (defined($stat) && $stat =3D~ /^.\s*return(\s*)\(/s) { - my $spacing =3D $1; - if ($perl_version_ok && - $stat =3D~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) { - my $value =3D $1; - $value =3D deparenthesize($value); - if ($value =3D~ m/^\s*$FuncArg\s*(?:\?|$)/) { - ERROR("RETURN_PARENTHESES", - "return is not a function, parentheses are not required\n" . $h= erecurr); - } - } elsif ($spacing !~ /\s+/) { - ERROR("SPACING", - "space required before the open parenthesis '('\n" . $herecurr); - } - } - -# unnecessary return in a void function -# at end-of-function, with the previous line a single leading tab, then re= turn; -# and the line before that not a goto label target like "out:" - if ($sline =3D~ /^[ \+]}\s*$/ && - $prevline =3D~ /^\+\treturn\s*;\s*$/ && - $linenr >=3D 3 && - $lines[$linenr - 3] =3D~ /^[ +]/ && - $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) { - WARN("RETURN_VOID", - "void function return statements are not generally useful\n" . $he= reprev); - } - -# if statements using unnecessary parentheses - ie: if ((foo =3D=3D bar)) - if ($perl_version_ok && - $line =3D~ /\bif\s*((?:\(\s*){2,})/) { - my $openparens =3D $1; - my $count =3D $openparens =3D~ tr@\(@\(@; - my $msg =3D ""; - if ($line =3D~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)= \s*$LvalOrFunc(?:\s*\)){$count,$count}/) { - my $comp =3D $4; #Not $1 because of $LvalOrFunc - $msg =3D " - maybe =3D=3D should be =3D ?" if ($comp eq "=3D=3D"); - WARN("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses$msg\n" . $herecurr); - } - } - -# comparisons with a constant or upper case identifier on the left -# avoid cases like "foo + BAR < baz" -# only fix matches surrounded by parentheses to avoid incorrect -# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5" - if ($perl_version_ok && - $line =3D~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($L= valOrFunc)/) { - my $lead =3D $1; - my $const =3D $2; - my $comp =3D $3; - my $to =3D $4; - my $newcomp =3D $comp; - if ($lead !~ /(?:$Operators|\.)\s*$/ && - $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ && - WARN("CONSTANT_COMPARISON", - "Comparisons should place the constant on the right side of the test\= n" . $herecurr) && - $fix) { - if ($comp eq "<") { - $newcomp =3D ">"; - } elsif ($comp eq "<=3D") { - $newcomp =3D ">=3D"; - } elsif ($comp eq ">") { - $newcomp =3D "<"; - } elsif ($comp eq ">=3D") { - $newcomp =3D "<=3D"; - } - $fixed[$fixlinenr] =3D~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($= to $newcomp $const)/; - } - } - -# Return of what appears to be an errno should normally be negative - if ($sline =3D~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,= ]/) { - my $name =3D $1; - if ($name ne 'EOF' && $name ne 'ERROR' && $name !~ /^EPOLL/) { - WARN("USE_NEGATIVE_ERRNO", - "return of an errno should typically be negative (ie: return -$1)= \n" . $herecurr); - } - } - -# Need a space before open parenthesis after if, while etc - if ($line =3D~ /\b(if|while|for|switch)\(/) { - if (ERROR("SPACING", - "space required before the open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/\b(if|while|for|switch)\(/$1 \(/; - } - } - -# Check for illegal assignment in if conditional -- and check for trailing -# statements after the conditional. - if ($line =3D~ /do\s*(?!{)/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) =3D - ctx_statement_block($linenr, $realcnt, 0) - if (!defined $stat); - my ($stat_next) =3D ctx_statement_block($line_nr_next, - $remain_next, $off_next); - $stat_next =3D~ s/\n./\n /g; - ##print "stat<$stat> stat_next<$stat_next>\n"; - - if ($stat_next =3D~ /^\s*while\b/) { - # If the statement carries leading newlines, - # then count those as offsets. - my ($whitespace) =3D - ($stat_next =3D~ /^((?:\s*\n[+-])*\s*)/s); - my $offset =3D - statement_rawlines($whitespace) - 1; - - $suppress_whiletrailers{$line_nr_next + - $offset} =3D 1; - } - } - if (!defined $suppress_whiletrailers{$linenr} && - defined($stat) && defined($cond) && - $line =3D~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { - my ($s, $c) =3D ($stat, $cond); - my $fixed_assign_in_if =3D 0; - - if ($c =3D~ /\bif\s*\(.*[^<>!=3D]=3D[^=3D].*/s) { - if (ERROR("ASSIGN_IN_IF", - "do not use assignment in if condition\n" . $herecurr) && - $fix && $perl_version_ok) { - if ($rawline =3D~ /^\+(\s+)if\s*\(\s*(\!)?\s*\(\s*(($Lval)\s*=3D\s*$L= valOrFunc)\s*\)\s*(?:($Compare)\s*($FuncArg))?\s*\)\s*(\{)?\s*$/) { - my $space =3D $1; - my $not =3D $2; - my $statement =3D $3; - my $assigned =3D $4; - my $test =3D $8; - my $against =3D $9; - my $brace =3D $15; - fix_delete_line($fixlinenr, $rawline); - fix_insert_line($fixlinenr, "$space$statement;"); - my $newline =3D "${space}if ("; - $newline .=3D '!' if defined($not); - $newline .=3D '(' if (defined $not && defined($test) && defined($aga= inst)); - $newline .=3D "$assigned"; - $newline .=3D " $test $against" if (defined($test) && defined($again= st)); - $newline .=3D ')' if (defined $not && defined($test) && defined($aga= inst)); - $newline .=3D ')'; - $newline .=3D " {" if (defined($brace)); - fix_insert_line($fixlinenr + 1, $newline); - $fixed_assign_in_if =3D 1; - } - } - } - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =3D~ s/\n.*//g; - $s =3D~ s/$;//g; # Remove any comments - if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ && - $c !~ /}\s*while\s*/) - { - # Find out how long the conditional actually is. - my @newlines =3D ($c =3D~ /\n/gs); - my $cond_lines =3D 1 + $#newlines; - my $stat_real =3D ''; - - $stat_real =3D raw_line($linenr, $cond_lines) - . "\n" if ($cond_lines); - if (defined($stat_real) && $cond_lines > 1) { - $stat_real =3D "[...]\n$stat_real"; - } - - if (ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr . $stat_= real) && - !$fixed_assign_in_if && - $cond_lines =3D=3D 0 && - $fix && $perl_version_ok && - $fixed[$fixlinenr] =3D~ /^\+(\s*)((?:if|while|for)\s*$balanced_par= ens)\s*(.*)$/) { - my $indent =3D $1; - my $test =3D $2; - my $rest =3D rtrim($4); - if ($rest =3D~ /;$/) { - $fixed[$fixlinenr] =3D "\+$indent$test"; - fix_insert_line($fixlinenr + 1, "$indent\t$rest"); - } - } - } - } - -# Check for bitwise tests written as boolean - if ($line =3D~ / - (?: - (?:\[|\(|\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\|) - | - (?:\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\||\)|\]) - )/x) - { - WARN("HEXADECIMAL_BOOLEAN_TEST", - "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $her= ecurr); - } - -# if and else should not have general statements after it - if ($line =3D~ /^.\s*(?:}\s*)?else\b(.*)/) { - my $s =3D $1; - $s =3D~ s/$;//g; # Remove any comments - if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - } -# if should not continue a brace - if ($line =3D~ /}\s*if\b/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line (or did you mean 'els= e if'?)\n" . - $herecurr); - } -# case and default should not have general statements after them - if ($line =3D~ /^.\s*(?:case\s*.*|default\s*):/g && - $line !~ /\G(?: - (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$| - \s*return\s+ - )/xg) - { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - - # Check for }<nl>else {, these must be at the same - # indent level to be relevant to each other. - if ($prevline=3D~/}\s*$/ and $line=3D~/^.\s*else\s*/ && - $previndent =3D=3D $indent) { - if (ERROR("ELSE_AFTER_BRACE", - "else should follow close brace '}'\n" . $hereprev) && - $fix && $prevline =3D~ /^\+/ && $line =3D~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline =3D $prevrawline; - $fixedline =3D~ s/}\s*$//; - if ($fixedline !~ /^\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - $fixedline =3D $rawline; - $fixedline =3D~ s/^(.\s*)else/$1} else/; - fix_insert_line($fixlinenr, $fixedline); - } - } - - if ($prevline=3D~/}\s*$/ and $line=3D~/^.\s*while\s*/ && - $previndent =3D=3D $indent) { - my ($s, $c) =3D ctx_statement_block($linenr, $realcnt, 0); - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =3D~ s/\n.*//g; - - if ($s =3D~ /^\s*;/) { - if (ERROR("WHILE_AFTER_BRACE", - "while should follow close brace '}'\n" . $hereprev) && - $fix && $prevline =3D~ /^\+/ && $line =3D~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline =3D $prevrawline; - my $trailing =3D $rawline; - $trailing =3D~ s/^\+//; - $trailing =3D trim($trailing); - $fixedline =3D~ s/}\s*$/} $trailing/; - fix_insert_line($fixlinenr, $fixedline); - } - } - } - -#Specific variable tests - while ($line =3D~ m{($Constant|$Lval)}g) { - my $var =3D $1; - -#CamelCase - if ($var !~ /^$Constant$/ && - $var =3D~ /[A-Z][a-z]|[a-z][A-Z]/ && -#Ignore some autogenerated defines and enum values - $var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ && -#Ignore Page<foo> variants - $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ && -#Ignore SI style variants like nS, mV and dB -#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE) - $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-= Z0-9_]+)?$/ && -#Ignore some three character SI units explicitly, like MiB and KHz - $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) { - while ($var =3D~ m{\b($Ident)}g) { - my $word =3D $1; - next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/); - if ($check) { - seed_camelcase_includes(); - if (!$file && !$camelcase_file_seeded) { - seed_camelcase_file($realfile); - $camelcase_file_seeded =3D 1; - } - } - if (!defined $camelcase{$word}) { - $camelcase{$word} =3D 1; - CHK("CAMELCASE", - "Avoid CamelCase: <$word>\n" . $herecurr); - } - } - } - } - -#no spaces allowed after \ in define - if ($line =3D~ /\#\s*define.*\\\s+$/) { - if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", - "Whitespace after \\ makes next lines useless\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\s+$//; - } - } - -# warn if <asm/foo.h> is #included and <linux/foo.h> is available and incl= udes -# itself <asm/foo.h> (uses RAW line) - if ($tree && $rawline =3D~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) { - my $file =3D "$1.h"; - my $checkfile =3D "include/linux/$file"; - if (-f "$root/$checkfile" && - $realfile ne $checkfile && - $1 !~ /$allowed_asm_includes/) - { - my $asminclude =3D `grep -Ec "#include\\s+<asm/$file>" $root/$checkfil= e`; - if ($asminclude > 0) { - if ($realfile =3D~ m{^arch/}) { - CHK("ARCH_INCLUDE_LINUX", - "Consider using #include <linux/$file> instead of <asm/$file>\n"= . $herecurr); - } else { - WARN("INCLUDE_LINUX", - "Use #include <linux/$file> instead of <asm/$file>\n" . $herecu= rr); - } - } - } - } - -# 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 -# in a known good container - if ($realfile !~ m@/vmlinux.lds.h$@ && - $line =3D~ /^.\s*\#\s*define\s*$Ident(\()?/) { - my $ln =3D $linenr; - my $cnt =3D $realcnt; - my ($off, $dstat, $dcond, $rest); - my $ctx =3D ''; - my $has_flow_statement =3D 0; - my $has_arg_concat =3D 0; - ($dstat, $dcond, $ln, $cnt, $off) =3D - ctx_statement_block($linenr, $realcnt, 0); - $ctx =3D $dstat; - #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; - #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; - - $has_flow_statement =3D 1 if ($ctx =3D~ /\b(goto|return)\b/); - $has_arg_concat =3D 1 if ($ctx =3D~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_A= RGS__|args)\b/); - - $dstat =3D~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//; - my $define_args =3D $1; - my $define_stmt =3D $dstat; - my @def_args =3D (); - - if (defined $define_args && $define_args ne "") { - $define_args =3D substr($define_args, 1, length($define_args) - 2); - $define_args =3D~ s/\s*//g; - $define_args =3D~ s/\\\+?//g; - @def_args =3D split(",", $define_args); - } - - $dstat =3D~ s/$;//g; - $dstat =3D~ s/\\\n.//g; - $dstat =3D~ s/^\s*//s; - $dstat =3D~ s/\s*$//s; - - # Flatten any parentheses and braces - while ($dstat =3D~ s/\([^\(\)]*\)/1u/ || - $dstat =3D~ s/\{[^\{\}]*\}/1u/ || - $dstat =3D~ s/.\[[^\[\]]*\]/1u/) - { - } - - # Flatten any obvious string concatenation. - while ($dstat =3D~ s/($String)\s*$Ident/$1/ || - $dstat =3D~ s/$Ident\s*($String)/$1/) - { - } - - # Make asm volatile uses seem like a generic function - $dstat =3D~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; - - my $exceptions =3D qr{ - $Declare| - module_param_named| - MODULE_PARM_DESC| - DECLARE_PER_CPU| - DEFINE_PER_CPU| - __typeof__\(| - union| - struct| - \.$Ident\s*=3D\s*| - ^\"|\"$| - ^\[ - }x; - #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; - - $ctx =3D~ s/\n*$//; - my $stmt_cnt =3D statement_rawlines($ctx); - my $herectx =3D get_stat_here($linenr, $stmt_cnt, $here); - - if ($dstat ne '' && - $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), - $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); - $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo /= / ~foo // -foo // foo->bar // foo.bar->baz - $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants - $dstat !~ /$exceptions/ && - $dstat !~ /^\.$Ident\s*=3D/ && # .foo =3D - $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringificati= on #foo - $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} wh= ile (...); // do {...} while (...) - $dstat !~ /^while\s*$Constant\s*$Constant\s*$/ && # while (...) {.= ..} - $dstat !~ /^for\s*$Constant$/ && # for (...) - $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (..= .) bar() - $dstat !~ /^do\s*{/ && # do {... - $dstat !~ /^\(\{/ && # ({... - $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PAT= H)\b/) - { - if ($dstat =3D~ /^\s*if\b/) { - ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", - "Macros starting with if should be enclosed by a do - while loo= p to avoid possible if/else logic defects\n" . "$herectx"); - } elsif ($dstat =3D~ /;/) { - ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", - "Macros with multiple statements should be enclosed in a do - w= hile loop\n" . "$herectx"); - } else { - ERROR("COMPLEX_MACRO", - "Macros with complex values should be enclosed in parentheses\n= " . "$herectx"); - } - - } - - # Make $define_stmt single line, comment-free, etc - my @stmt_array =3D split('\n', $define_stmt); - my $first =3D 1; - $define_stmt =3D ""; - foreach my $l (@stmt_array) { - $l =3D~ s/\\$//; - if ($first) { - $define_stmt =3D $l; - $first =3D 0; - } elsif ($l =3D~ /^[\+ ]/) { - $define_stmt .=3D substr($l, 1); - } - } - $define_stmt =3D~ s/$;//g; - $define_stmt =3D~ s/\s+/ /g; - $define_stmt =3D trim($define_stmt); - -# check if any macro arguments are reused (ignore '...' and 'type') - foreach my $arg (@def_args) { - next if ($arg =3D~ /\.\.\./); - next if ($arg =3D~ /^type$/i); - my $tmp_stmt =3D $define_stmt; - $tmp_stmt =3D~ s/\b(__must_be_array|offsetof|sizeof|sizeof_field|__str= ingify|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*= \s*$arg\s*\)*\b//g; - $tmp_stmt =3D~ s/\#+\s*$arg\b//g; - $tmp_stmt =3D~ s/\b$arg\s*\#\#//g; - my $use_cnt =3D () =3D $tmp_stmt =3D~ /\b$arg\b/g; - if ($use_cnt > 1) { - CHK("MACRO_ARG_REUSE", - "Macro argument reuse '$arg' - possible side-effects?\n" . "$here= ctx"); - } -# check if any macro arguments may have other precedence issues - if ($tmp_stmt =3D~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m && - ((defined($1) && $1 ne ',') || - (defined($2) && $2 ne ','))) { - CHK("MACRO_ARG_PRECEDENCE", - "Macro argument '$arg' may be better as '($arg)' to avoid precede= nce issues\n" . "$herectx"); - } - } - -# check for macros with flow control, but without ## concatenation -# ## concatenation is commonly a macro that defines a function so ignore t= hose - if ($has_flow_statement && !$has_arg_concat) { - my $cnt =3D statement_rawlines($ctx); - my $herectx =3D get_stat_here($linenr, $cnt, $here); - - WARN("MACRO_WITH_FLOW_CONTROL", - "Macros with flow control statements should be avoided\n" . "$her= ectx"); - } - -# check for line continuations outside of #defines, preprocessor #, and asm - - } else { - if ($prevline !~ /^..*\\$/ && - $line !~ /^\+\s*\#.*\\$/ && # preprocessor - $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm - $line =3D~ /^\+.*\\$/) { - WARN("LINE_CONTINUATIONS", - "Avoid unnecessary line continuations\n" . $herecurr); - } - } - -# do {} while (0) macro tests: -# single-statement macros do not need to be enclosed in do while (0) loop, -# macro should not end with a semicolon - if ($perl_version_ok && - $realfile !~ m@/vmlinux.lds.h$@ && - $line =3D~ /^.\s*\#\s*define\s+$Ident(\()?/) { - my $ln =3D $linenr; - my $cnt =3D $realcnt; - my ($off, $dstat, $dcond, $rest); - my $ctx =3D ''; - ($dstat, $dcond, $ln, $cnt, $off) =3D - ctx_statement_block($linenr, $realcnt, 0); - $ctx =3D $dstat; - - $dstat =3D~ s/\\\n.//g; - $dstat =3D~ s/$;/ /g; - - if ($dstat =3D~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*= {(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) { - my $stmts =3D $2; - my $semis =3D $3; - - $ctx =3D~ s/\n*$//; - my $cnt =3D statement_rawlines($ctx); - my $herectx =3D get_stat_here($linenr, $cnt, $here); - - if (($stmts =3D~ tr/;/;/) =3D=3D 1 && - $stmts !~ /^\s*(if|while|for|switch)\b/) { - WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", - "Single statement macros should not use a do {} while (0) loop\n= " . "$herectx"); - } - if (defined $semis && $semis ne "") { - WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON", - "do {} while (0) macros should not be semicolon terminated\n" . = "$herectx"); - } - } elsif ($dstat =3D~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) { - $ctx =3D~ s/\n*$//; - my $cnt =3D statement_rawlines($ctx); - my $herectx =3D get_stat_here($linenr, $cnt, $here); - - WARN("TRAILING_SEMICOLON", - "macros should not use a trailing semicolon\n" . "$herectx"); - } - } - -# check for redundant bracing round if etc - if ($line =3D~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { - my ($level, $endln, @chunks) =3D - ctx_statement_full($linenr, $realcnt, 1); - #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; - #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; - if ($#chunks > 0 && $level =3D=3D 0) { - my @allowed =3D (); - my $allow =3D 0; - my $seen =3D 0; - my $herectx =3D $here . "\n"; - my $ln =3D $linenr - 1; - for my $chunk (@chunks) { - my ($cond, $block) =3D @{$chunk}; - - # If the condition carries leading newlines, then count those as offs= ets. - my ($whitespace) =3D ($cond =3D~ /^((?:\s*\n[+-])*\s*)/s); - my $offset =3D statement_rawlines($whitespace) - 1; - - $allowed[$allow] =3D 0; - #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; - - # We have looked at and allowed this specific line. - $suppress_ifbraces{$ln + $offset} =3D 1; - - $herectx .=3D "$rawlines[$ln + $offset]\n[...]\n"; - $ln +=3D statement_rawlines($block) - 1; - - substr($block, 0, length($cond), ''); - - $seen++ if ($block =3D~ /^\s*{/); - - #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n"; - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed[$allow] =3D 1; - } - if ($block =3D~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed[$allow] =3D 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed[$allow] =3D 1; - } - $allow++; - } - if ($seen) { - my $sum_allowed =3D 0; - foreach (@allowed) { - $sum_allowed +=3D $_; - } - if ($sum_allowed =3D=3D 0) { - WARN("BRACES", - "braces {} are not necessary for any arm of this statement\n" .= $herectx); - } elsif ($sum_allowed !=3D $allow && - $seen !=3D $allow) { - CHK("BRACES", - "braces {} should be used on all arms of this statement\n" . $he= rectx); - } - } - } - } - if (!defined $suppress_ifbraces{$linenr - 1} && - $line =3D~ /\b(if|while|for|else)\b/) { - my $allowed =3D 0; - - # Check the pre-context. - if (substr($line, 0, $-[0]) =3D~ /(\}\s*)$/) { - #print "APW: ALLOWED: pre<$1>\n"; - $allowed =3D 1; - } - - my ($level, $endln, @chunks) =3D - ctx_statement_full($linenr, $realcnt, $-[0]); - - # Check the condition. - my ($cond, $block) =3D @{$chunks[0]}; - #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed =3D 1; - } - if ($block =3D~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed =3D 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed =3D 1; - } - # Check the post-context. - if (defined $chunks[1]) { - my ($cond, $block) =3D @{$chunks[1]}; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if ($block =3D~ /^\s*\{/) { - #print "APW: ALLOWED: chunk-1 block<$block>\n"; - $allowed =3D 1; - } - } - if ($level =3D=3D 0 && $block =3D~ /^\s*\{/ && !$allowed) { - my $cnt =3D statement_rawlines($block); - my $herectx =3D get_stat_here($linenr, $cnt, $here); - - WARN("BRACES", - "braces {} are not necessary for single statement blocks\n" . $he= rectx); - } - } - -# check for single line unbalanced braces - if ($sline =3D~ /^.\s*\}\s*else\s*$/ || - $sline =3D~ /^.\s*else\s*\{\s*$/) { - CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr); - } - -# check for unnecessary blank lines around braces - if (($line =3D~ /^.\s*}\s*$/ && $prevrawline =3D~ /^.\s*$/)) { - if (CHK("BRACES", - "Blank lines aren't necessary before a close brace '}'\n" . $hereprev)= && - $fix && $prevrawline =3D~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - } - } - if (($rawline =3D~ /^.\s*$/ && $prevline =3D~ /^..*{\s*$/)) { - if (CHK("BRACES", - "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) = && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - } - -# no volatiles please - my $asm_volatile =3D qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; - if ($line =3D~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { - WARN("VOLATILE", - "Use of volatile is usually wrong: see Documentation/process/volat= ile-considered-harmful.rst\n" . $herecurr); - } - -# Check for user-visible strings broken across lines, which breaks the abi= lity -# to grep for the string. Make exceptions when the previous string ends i= n a -# newline (multiple lines in one string constant) or '\t', '\r', ';', or '= {' -# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value - if ($line =3D~ /^\+\s*$String/ && - $prevline =3D~ /"\s*$/ && - $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{= \s*)"\s*$/) { - if (WARN("SPLIT_STRING", - "quoted string split across lines\n" . $hereprev) && - $fix && - $prevrawline =3D~ /^\+.*"\s*$/ && - $last_coalesced_string_linenr !=3D $linenr - 1) { - my $extracted_string =3D get_quoted_string($line, $rawline); - my $comma_close =3D ""; - if ($rawline =3D~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) { - $comma_close =3D $1; - } - - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline =3D $prevrawline; - $fixedline =3D~ s/"\s*$//; - $fixedline .=3D substr($extracted_string, 1) . trim($comma_close); - fix_insert_line($fixlinenr - 1, $fixedline); - $fixedline =3D $rawline; - $fixedline =3D~ s/\Q$extracted_string\E\Q$comma_close\E//; - if ($fixedline !~ /\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - $last_coalesced_string_linenr =3D $linenr; - } - } - -# check for missing a space in a string concatenation - if ($prevrawline =3D~ /[^\\]\w"$/ && $rawline =3D~ /^\+[\t ]+"\w/) { - WARN('MISSING_SPACE', - "break quoted strings at a space character\n" . $hereprev); - } - -# check for an embedded function name in a string when the function is kno= wn -# This does not work very well for -f --file checking as it depends on pat= ch -# context providing the function name or a single line form for in-file -# function declarations - if ($line =3D~ /^\+.*$String/ && - defined($context_function) && - get_quoted_string($line, $rawline) =3D~ /\b$context_function\b/ && - length(get_quoted_string($line, $rawline)) !=3D (length($context_fun= ction) + 2)) { - WARN("EMBEDDED_FUNCTION_NAME", - "Prefer using '\"%s...\", __func__' to using '$context_function', = this function's name, in a string\n" . $herecurr); - } - -# check for unnecessary function tracing like uses -# This does not use $logFunctions because there are many instances like -# 'dprintk(FOO, "%s()\n", __func__);' which do not match $logFunctions - if ($rawline =3D~ /^\+.*\([^"]*"$tracing_logging_tags{0,3}%s(?:\s*\(\s*\= )\s*)?$tracing_logging_tags{0,3}(?:\\n)?"\s*,\s*__func__\s*\)\s*;/) { - if (WARN("TRACING_LOGGING", - "Unnecessary ftrace-like logging - prefer using ftrace\n" . $herecurr= ) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - } - -# check for spaces before a quoted newline - if ($rawline =3D~ /^.*\".*\s\\n/) { - if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", - "unnecessary whitespace before a quoted newline\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/^(\+.*\".*)\s+\\n/$1\\n/; - } - - } - -# concatenated string without spaces between elements - if ($line =3D~ /$String[A-Z_]/ || - ($line =3D~ /([A-Za-z0-9_]+)$String/ && $1 !~ /^[Lu]$/)) { - if (CHK("CONCATENATED_STRING", - "Concatenated strings should use spaces between elements\n" . $herecur= r) && - $fix) { - while ($line =3D~ /($String)/g) { - my $extracted_string =3D substr($rawline, $-[0], $+[0] - $-[0]); - $fixed[$fixlinenr] =3D~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extrac= ted_string $1/; - $fixed[$fixlinenr] =3D~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $ext= racted_string/; - } - } - } - -# uncoalesced string fragments - if ($line =3D~ /$String\s*[Lu]?"/) { - if (WARN("STRING_FRAGMENTS", - "Consecutive strings are generally better as a single string\n" . $he= recurr) && - $fix) { - while ($line =3D~ /($String)(?=3D\s*")/g) { - my $extracted_string =3D substr($rawline, $-[0], $+[0] - $-[0]); - $fixed[$fixlinenr] =3D~ s/\Q$extracted_string\E\s*"/substr($extracted= _string, 0, -1)/e; - } - } - } - -# check for non-standard and hex prefixed decimal printf formats - my $show_L =3D 1; #don't show the same defect twice - my $show_Z =3D 1; - while ($line =3D~ /(?:^|")([X\t]*)(?:"|$)/g) { - my $string =3D substr($rawline, $-[1], $+[1] - $-[1]); - $string =3D~ s/%%/__/g; - # check for %L - if ($show_L && $string =3D~ /%[\*\d\.\$]*L([diouxX])/) { - WARN("PRINTF_L", - "\%L$1 is non-standard C, use %ll$1\n" . $herecurr); - $show_L =3D 0; - } - # check for %Z - if ($show_Z && $string =3D~ /%[\*\d\.\$]*Z([diouxX])/) { - WARN("PRINTF_Z", - "%Z$1 is non-standard C, use %z$1\n" . $herecurr); - $show_Z =3D 0; - } - # check for 0x<decimal> - if ($string =3D~ /0x%[\*\d\.\$\Llzth]*[diou]/) { - ERROR("PRINTF_0XDECIMAL", - "Prefixing 0x with decimal output is defective\n" . $herecurr); - } - } - -# check for line continuations in quoted strings with odd counts of " - if ($rawline =3D~ /\\$/ && $sline =3D~ tr/"/"/ % 2) { - WARN("LINE_CONTINUATIONS", - "Avoid line continuations in quoted strings\n" . $herecurr); - } - -# warn about #if 0 - if ($line =3D~ /^.\s*\#\s*if\s+0\b/) { - WARN("IF_0", - "Consider removing the code enclosed by this #if 0 and its #endif\= n" . $herecurr); - } - -# warn about #if 1 - if ($line =3D~ /^.\s*\#\s*if\s+1\b/) { - WARN("IF_1", - "Consider removing the #if 1 and its #endif\n" . $herecurr); - } - -# check for needless "if (<foo>) fn(<foo>)" uses - if ($prevline =3D~ /\bif\s*\(\s*($Lval)\s*\)/) { - my $tested =3D quotemeta($1); - my $expr =3D '\s*\(\s*' . $tested . '\s*\)\s*;'; - if ($line =3D~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:= kmem_cache|mempool|dma_pool)_destroy)$expr/) { - my $func =3D $1; - if (WARN('NEEDLESS_IF', - "$func(NULL) is safe and this check is probably not required\n" . $h= ereprev) && - $fix) { - my $do_fix =3D 1; - my $leading_tabs =3D ""; - my $new_leading_tabs =3D ""; - if ($lines[$linenr - 2] =3D~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) { - $leading_tabs =3D $1; - } else { - $do_fix =3D 0; - } - if ($lines[$linenr - 1] =3D~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s= *$/) { - $new_leading_tabs =3D $1; - if (length($leading_tabs) + 1 ne length($new_leading_tabs)) { - $do_fix =3D 0; - } - } else { - $do_fix =3D 0; - } - if ($do_fix) { - fix_delete_line($fixlinenr - 1, $prevrawline); - $fixed[$fixlinenr] =3D~ s/^\+$new_leading_tabs/\+$leading_tabs/; - } - } - } - } - -# check for unnecessary "Out of Memory" messages - if ($line =3D~ /^\+.*\b$logFunctions\s*\(/ && - $prevline =3D~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*=3D=3D\s*)?($Lval)(= \s*=3D=3D\s*NULL\s*)?\s*\)/ && - (defined $1 || defined $3) && - $linenr > 3) { - my $testval =3D $2; - my $testline =3D $lines[$linenr - 3]; - - my ($s, $c) =3D ctx_statement_block($linenr - 3, $realcnt, 0); -# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n"); - - if ($s =3D~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=3D\s*(?:\([^\= )]*\)\s*)?\s*$allocFunctions\s*\(/ && - $s !~ /\b__GFP_NOWARN\b/ ) { - WARN("OOM_MESSAGE", - "Possible unnecessary 'out of memory' message\n" . $hereprev); - } - } - -# check for logging functions with KERN_<LEVEL> - if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ && - $line =3D~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) { - my $level =3D $1; - if (WARN("UNNECESSARY_KERN_LEVEL", - "Possible unnecessary $level\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\s*$level\s*//; - } - } - -# check for logging continuations - if ($line =3D~ /\bprintk\s*\(\s*KERN_CONT\b|\bpr_cont\s*\(/) { - WARN("LOGGING_CONTINUATION", - "Avoid logging continuation uses where feasible\n" . $herecurr); - } - -# check for unnecessary use of %h[xudi] and %hh[xudi] in logging functions - if (defined $stat && - $line =3D~ /\b$logFunctions\s*\(/ && - index($stat, '"') >=3D 0) { - my $lc =3D $stat =3D~ tr@\n@@; - $lc =3D $lc + $linenr; - my $stat_real =3D get_stat_real($linenr, $lc); - pos($stat_real) =3D index($stat_real, '"'); - while ($stat_real =3D~ /[^\"%]*(%[\#\d\.\*\-]*(h+)[idux])/g) { - my $pspec =3D $1; - my $h =3D $2; - my $lineoff =3D substr($stat_real, 0, $-[1]) =3D~ tr@\n@@; - if (WARN("UNNECESSARY_MODIFIER", - "Integer promotion: Using '$h' in '$pspec' is unnecessary\n" . "$her= e\n$stat_real\n") && - $fix && $fixed[$fixlinenr + $lineoff] =3D~ /^\+/) { - my $nspec =3D $pspec; - $nspec =3D~ s/h//g; - $fixed[$fixlinenr + $lineoff] =3D~ s/\Q$pspec\E/$nspec/; - } - } - } - -# check for mask then right shift without a parentheses - if ($perl_version_ok && - $line =3D~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ && - $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so - WARN("MASK_THEN_SHIFT", - "Possible precedence defect with mask then right shift - may need = parentheses\n" . $herecurr); - } - -# check for pointer comparisons to NULL - if ($perl_version_ok) { - while ($line =3D~ /\b$LvalOrFunc\s*(=3D=3D|\!=3D)\s*NULL\b/g) { - my $val =3D $1; - my $equal =3D "!"; - $equal =3D "" if ($4 eq "!=3D"); - if (CHK("COMPARISON_TO_NULL", - "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecur= r) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\b\Q$val\E\s*(?:=3D=3D|\!=3D)\s*NULL\b/$equ= al$val/; - } - } - } - -# check for bad placement of section $InitAttribute (e.g.: __initdata) - if ($line =3D~ /(\b$InitAttribute\b)/) { - my $attr =3D $1; - if ($line =3D~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWi= thAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=3D;]/) { - my $ptr =3D $1; - my $var =3D $2; - if ((($ptr =3D~ /\b(union|struct)\s+$attr\b/ && - ERROR("MISPLACED_INIT", - "$attr should be placed after $var\n" . $herecurr)) || - ($ptr !~ /\b(union|struct)\s+$attr\b/ && - WARN("MISPLACED_INIT", - "$attr should be placed after $var\n" . $herecurr))) && - $fix) { - $fixed[$fixlinenr] =3D~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($No= nptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=3D;])\s*/"$1" = . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_f= ind_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = =3D ")/e; - } - } - } - -# check for $InitAttributeData (ie: __initdata) with const - if ($line =3D~ /\bconst\b/ && $line =3D~ /($InitAttributeData)/) { - my $attr =3D $1; - $attr =3D~ /($InitAttributePrefix)(.*)/; - my $attr_prefix =3D $1; - my $attr_type =3D $2; - if (ERROR("INIT_ATTRIBUTE", - "Use of const init definition must use ${attr_prefix}initconst\n" . = $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/$InitAttributeData/${attr_prefix}initconst/; - } - } - -# check for $InitAttributeConst (ie: __initconst) without const - if ($line !~ /\bconst\b/ && $line =3D~ /($InitAttributeConst)/) { - my $attr =3D $1; - if (ERROR("INIT_ATTRIBUTE", - "Use of $attr requires a separate use of const\n" . $herecurr) && - $fix) { - my $lead =3D $fixed[$fixlinenr] =3D~ - /(^\+\s*(?:static\s+))/; - $lead =3D rtrim($1); - $lead =3D "$lead " if ($lead !~ /^\+$/); - $lead =3D "${lead}const "; - $fixed[$fixlinenr] =3D~ s/(^\+\s*(?:static\s+))/$lead/; - } - } - -# check for __read_mostly with const non-pointer (should just be const) - if ($line =3D~ /\b__read_mostly\b/ && - $line =3D~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =3D~ /\bconst\= b/) { - if (ERROR("CONST_READ_MOSTLY", - "Invalid use of __read_mostly with const type\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\s+__read_mostly\b//; - } - } - -# don't use __constant_<foo> functions outside of include/uapi/ - if ($realfile !~ m@^include/uapi/@ && - $line =3D~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_= to_[bl]e(?:16|32|64)))\s*\(/) { - my $constant_func =3D $1; - my $func =3D $constant_func; - $func =3D~ s/^__constant_//; - if (WARN("CONSTANT_CONVERSION", - "$constant_func should be $func\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\b$constant_func\b/$func/g; - } - } - -# prefer usleep_range over udelay - if ($line =3D~ /\budelay\s*\(\s*(\d+)\s*\)/) { - my $delay =3D $1; - # ignore udelay's < 10, however - if (! ($delay < 10) ) { - CHK("USLEEP_RANGE", - "usleep_range is preferred over udelay; see Documentation/timers/t= imers-howto.rst\n" . $herecurr); - } - if ($delay > 2000) { - WARN("LONG_UDELAY", - "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n"= . $herecurr); - } - } - -# warn about unexpectedly long msleep's - if ($line =3D~ /\bmsleep\s*\((\d+)\);/) { - if ($1 < 20) { - WARN("MSLEEP", - "msleep < 20ms can sleep for up to 20ms; see Documentation/timers= /timers-howto.rst\n" . $herecurr); - } - } - -# check for comparisons of jiffies - if ($line =3D~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) { - WARN("JIFFIES_COMPARISON", - "Comparing jiffies is almost always wrong; prefer time_after, time= _before and friends\n" . $herecurr); - } - -# check for comparisons of get_jiffies_64() - if ($line =3D~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jif= fies_64\s*\(\s*\)/) { - WARN("JIFFIES_COMPARISON", - "Comparing get_jiffies_64() is almost always wrong; prefer time_af= ter64, time_before64 and friends\n" . $herecurr); - } - -# warn about #ifdefs in C files -# if ($line =3D~ /^.\s*\#\s*if(|n)def/ && ($realfile =3D~ /\.c$/)) { -# print "#ifdef in C files should be avoided\n"; -# print "$herecurr"; -# $clean =3D 0; -# } - -# warn about spacing in #ifdefs - if ($line =3D~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { - if (ERROR("SPACING", - "exactly one space required after that #$1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ - s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; - } - - } - -# check for spinlock_t definitions without a comment. - if ($line =3D~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ || - $line =3D~ /^.\s*(DEFINE_MUTEX)\s*\(/) { - my $which =3D $1; - if (!ctx_has_comment($first_line, $linenr)) { - CHK("UNCOMMENTED_DEFINITION", - "$1 definition without comment\n" . $herecurr); - } - } -# check for memory barriers without a comment. - - my $barriers =3D qr{ - mb| - rmb| - wmb - }x; - my $barrier_stems =3D qr{ - mb__before_atomic| - mb__after_atomic| - store_release| - load_acquire| - store_mb| - (?:$barriers) - }x; - my $all_barriers =3D qr{ - (?:$barriers)| - smp_(?:$barrier_stems)| - virt_(?:$barrier_stems) - }x; - - if ($line =3D~ /\b(?:$all_barriers)\s*\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - WARN("MEMORY_BARRIER", - "memory barrier without comment\n" . $herecurr); - } - } - - my $underscore_smp_barriers =3D qr{__smp_(?:$barrier_stems)}x; - - if ($realfile !~ m@^include/asm-generic/@ && - $realfile !~ m@/barrier\.h$@ && - $line =3D~ m/\b(?:$underscore_smp_barriers)\s*\(/ && - $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { - WARN("MEMORY_BARRIER", - "__smp memory barriers shouldn't be used outside barrier.h and asm= -generic\n" . $herecurr); - } - -# check for waitqueue_active without a comment. - if ($line =3D~ /\bwaitqueue_active\s*\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - WARN("WAITQUEUE_ACTIVE", - "waitqueue_active without comment\n" . $herecurr); - } - } - -# check for data_race without a comment. - if ($line =3D~ /\bdata_race\s*\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - WARN("DATA_RACE", - "data_race without comment\n" . $herecurr); - } - } - -# check of hardware specific defines - if ($line =3D~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x= __)\b@ && $realfile !~ m@include/asm-@) { - CHK("ARCH_DEFINES", - "architecture specific defines should be avoided\n" . $herecurr); - } - -# check that the storage class is not after a type - if ($line =3D~ /\b($Type)\s+($Storage)\b/) { - WARN("STORAGE_CLASS", - "storage class '$2' should be located before type '$1'\n" . $herec= urr); - } -# Check that the storage class is at the beginning of a declaration - if ($line =3D~ /\b$Storage\b/ && - $line !~ /^.\s*$Storage/ && - $line =3D~ /^.\s*(.+?)\$Storage\s/ && - $1 !~ /[\,\)]\s*$/) { - WARN("STORAGE_CLASS", - "storage class should be at the beginning of the declaration\n" . = $herecurr); - } - -# check the location of the inline attribute, that it is between -# storage class and type. - if ($line =3D~ /\b$Type\s+$Inline\b/ || - $line =3D~ /\b$Inline\s+$Storage\b/) { - ERROR("INLINE_LOCATION", - "inline keyword should sit between storage class and type\n" . $h= erecurr); - } - -# Check for __inline__ and __inline, prefer inline - if ($realfile !~ m@\binclude/uapi/@ && - $line =3D~ /\b(__inline__|__inline)\b/) { - if (WARN("INLINE", - "plain inline is preferred over $1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\b(__inline__|__inline)\b/inline/; - - } - } - -# Check for compiler attributes - if ($realfile !~ m@\binclude/uapi/@ && - $rawline =3D~ /\b__attribute__\s*\(\s*($balanced_parens)\s*\)/) { - my $attr =3D $1; - $attr =3D~ s/\s*\(\s*(.*)\)\s*/$1/; - - my %attr_list =3D ( - "alias" =3D> "__alias", - "aligned" =3D> "__aligned", - "always_inline" =3D> "__always_inline", - "assume_aligned" =3D> "__assume_aligned", - "cold" =3D> "__cold", - "const" =3D> "__attribute_const__", - "copy" =3D> "__copy", - "designated_init" =3D> "__designated_init", - "externally_visible" =3D> "__visible", - "format" =3D> "printf|scanf", - "gnu_inline" =3D> "__gnu_inline", - "malloc" =3D> "__malloc", - "mode" =3D> "__mode", - "no_caller_saved_registers" =3D> "__no_caller_saved_registers", - "noclone" =3D> "__noclone", - "noinline" =3D> "noinline", - "nonstring" =3D> "__nonstring", - "noreturn" =3D> "__noreturn", - "packed" =3D> "__packed", - "pure" =3D> "__pure", - "section" =3D> "__section", - "used" =3D> "__used", - "weak" =3D> "__weak" - ); - - while ($attr =3D~ /\s*(\w+)\s*(${balanced_parens})?/g) { - my $orig_attr =3D $1; - my $params =3D ''; - $params =3D $2 if defined($2); - my $curr_attr =3D $orig_attr; - $curr_attr =3D~ s/^[\s_]+|[\s_]+$//g; - if (exists($attr_list{$curr_attr})) { - my $new =3D $attr_list{$curr_attr}; - if ($curr_attr eq "format" && $params) { - $params =3D~ /^\s*\(\s*(\w+)\s*,\s*(.*)/; - $new =3D "__$1\($2"; - } else { - $new =3D "$new$params"; - } - if (WARN("PREFER_DEFINED_ATTRIBUTE_MACRO", - "Prefer $new over __attribute__(($orig_attr$params))\n" . $herecurr= ) && - $fix) { - my $remove =3D "\Q$orig_attr\E" . '\s*' . "\Q$params\E" . '(?:\s*,\s= *)?'; - $fixed[$fixlinenr] =3D~ s/$remove//; - $fixed[$fixlinenr] =3D~ s/\b__attribute__/$new __attribute__/; - $fixed[$fixlinenr] =3D~ s/\}\Q$new\E/} $new/; - $fixed[$fixlinenr] =3D~ s/ __attribute__\s*\(\s*\(\s*\)\s*\)//; - } - } - } - - # Check for __attribute__ unused, prefer __always_unused or __maybe_unu= sed - if ($attr =3D~ /^_*unused/) { - WARN("PREFER_DEFINED_ATTRIBUTE_MACRO", - "__always_unused or __maybe_unused is preferred over __attribute_= _((__unused__))\n" . $herecurr); - } - } - -# Check for __attribute__ weak, or __weak declarations (may have link issu= es) - if ($perl_version_ok && - $line =3D~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_par= ens\s*(?:$Attribute)?\s*;/ && - ($line =3D~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ || - $line =3D~ /\b__weak\b/)) { - ERROR("WEAK_DECLARATION", - "Using weak declarations can have unintended link defects\n" . $h= erecurr); - } - -# check for c99 types like uint8_t used outside of uapi/ and tools/ - if ($realfile !~ m@\binclude/uapi/@ && - $realfile !~ m@\btools/@ && - $line =3D~ /\b($Declare)\s*$Ident\s*[=3D;,\[]/) { - my $type =3D $1; - if ($type =3D~ /\b($typeC99Typedefs)\b/) { - $type =3D $1; - my $kernel_type =3D 'u'; - $kernel_type =3D 's' if ($type =3D~ /^_*[si]/); - $type =3D~ /(\d+)/; - $kernel_type .=3D $1; - if (CHK("PREFER_KERNEL_TYPES", - "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\b$type\b/$kernel_type/; - } - } - } - -# check for cast of C90 native int or longer types constants - if ($line =3D~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { - my $cast =3D $1; - my $const =3D $2; - my $suffix =3D ""; - my $newconst =3D $const; - $newconst =3D~ s/${Int_type}$//; - $suffix .=3D 'U' if ($cast =3D~ /\bunsigned\b/); - if ($cast =3D~ /\blong\s+long\b/) { - $suffix .=3D 'LL'; - } elsif ($cast =3D~ /\blong\b/) { - $suffix .=3D 'L'; - } - if (WARN("TYPECAST_INT_CONSTANT", - "Unnecessary typecast of c90 int constant - '$cast$const' could be '$= const$suffix'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\Q$cast\E$const\b/$newconst$suffix/; - } - } - -# check for sizeof(&) - if ($line =3D~ /\bsizeof\s*\(\s*\&/) { - WARN("SIZEOF_ADDRESS", - "sizeof(& should be avoided\n" . $herecurr); - } - -# check for sizeof without parenthesis - if ($line =3D~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) { - if (WARN("SIZEOF_PARENTHESIS", - "sizeof $1 should be sizeof($1)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval= |))/"sizeof(" . trim($1) . ")"/ex; - } - } - -# check for struct spinlock declarations - if ($line =3D~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) { - WARN("USE_SPINLOCK_T", - "struct spinlock should be spinlock_t\n" . $herecurr); - } - -# check for seq_printf uses that could be seq_puts - if ($sline =3D~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) { - my $fmt =3D get_quoted_string($line, $rawline); - $fmt =3D~ s/%%//g; - if ($fmt !~ /%/) { - if (WARN("PREFER_SEQ_PUTS", - "Prefer seq_puts to seq_printf\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\bseq_printf\b/seq_puts/; - } - } - } - -# check for vsprintf extension %p<foo> misuses - if ($perl_version_ok && - defined $stat && - $stat =3D~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s && - $1 !~ /^_*volatile_*$/) { - my $stat_real; - - my $lc =3D $stat =3D~ tr@\n@@; - $lc =3D $lc + $linenr; - for (my $count =3D $linenr; $count <=3D $lc; $count++) { - my $specifier; - my $extension; - my $qualifier; - my $bad_specifier =3D ""; - my $fmt =3D get_quoted_string($lines[$count - 1], raw_line($count, 0)); - $fmt =3D~ s/%%//g; - - while ($fmt =3D~ /(\%[\*\d\.]*p(\w)(\w*))/g) { - $specifier =3D $1; - $extension =3D $2; - $qualifier =3D $3; - if ($extension !~ /[4SsBKRraEehMmIiUDdgVCbGNOxtf]/ || - ($extension eq "f" && - defined $qualifier && $qualifier !~ /^w/) || - ($extension eq "4" && - defined $qualifier && $qualifier !~ /^cc/)) { - $bad_specifier =3D $specifier; - last; - } - if ($extension eq "x" && !defined($stat_real)) { - if (!defined($stat_real)) { - $stat_real =3D get_stat_real($linenr, $lc); - } - WARN("VSPRINTF_SPECIFIER_PX", - "Using vsprintf specifier '\%px' potentially exposes the kernel= memory layout, if you don't really need the address please consider using = '\%p'.\n" . "$here\n$stat_real\n"); - } - } - if ($bad_specifier ne "") { - my $stat_real =3D get_stat_real($linenr, $lc); - my $ext_type =3D "Invalid"; - my $use =3D ""; - if ($bad_specifier =3D~ /p[Ff]/) { - $use =3D " - use %pS instead"; - $use =3D~ s/pS/ps/ if ($bad_specifier =3D~ /pf/); - } - - WARN("VSPRINTF_POINTER_EXTENSION", - "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . = "$here\n$stat_real\n"); - } - } - } - -# Check for misused memsets - if ($perl_version_ok && - defined $stat && - $stat =3D~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s= *$FuncArg\s*\)/) { - - my $ms_addr =3D $2; - my $ms_val =3D $7; - my $ms_size =3D $12; - - if ($ms_size =3D~ /^(0x|)0$/i) { - ERROR("MEMSET", - "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$he= re\n$stat\n"); - } elsif ($ms_size =3D~ /^(0x|)1$/i) { - WARN("MEMSET", - "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" .= "$here\n$stat\n"); - } - } - -# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, = bar) -# if ($perl_version_ok && -# defined $stat && -# $stat =3D~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\= s*ETH_ALEN\s*\)/) { -# if (WARN("PREFER_ETHER_ADDR_COPY", -# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses ar= e __aligned(2)\n" . "$here\n$stat\n") && -# $fix) { -# $fixed[$fixlinenr] =3D~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\= ,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; -# } -# } - -# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo= , bar) -# if ($perl_version_ok && -# defined $stat && -# $stat =3D~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\= s*ETH_ALEN\s*\)/) { -# WARN("PREFER_ETHER_ADDR_EQUAL", -# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over m= emcmp()\n" . "$here\n$stat\n") -# } - -# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr -# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr -# if ($perl_version_ok && -# defined $stat && -# $stat =3D~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\= s*ETH_ALEN\s*\)/) { -# -# my $ms_val =3D $7; -# -# if ($ms_val =3D~ /^(?:0x|)0+$/i) { -# if (WARN("PREFER_ETH_ZERO_ADDR", -# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && -# $fix) { -# $fixed[$fixlinenr] =3D~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*= ,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; -# } -# } elsif ($ms_val =3D~ /^(?:0xff|255)$/i) { -# if (WARN("PREFER_ETH_BROADCAST_ADDR", -# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && -# $fix) { -# $fixed[$fixlinenr] =3D~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*= ,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; -# } -# } -# } - -# strlcpy uses that should likely be strscpy - if ($line =3D~ /\bstrlcpy\s*\(/) { - WARN("STRLCPY", - "Prefer strscpy over strlcpy - see: https://lore.kernel.org/r/CAHk= -=3DwgfRnXz0W3D37d01q3JFkr_i_uTL=3DV6A6G1oUZcprmknw\@mail.gmail.com/\n" . $= herecurr); - } - -# typecasts on min/max could be min_t/max_t - if ($perl_version_ok && - defined $stat && - $stat =3D~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\= )/) { - if (defined $2 || defined $7) { - my $call =3D $1; - my $cast1 =3D deparenthesize($2); - my $arg1 =3D $3; - my $cast2 =3D deparenthesize($7); - my $arg2 =3D $8; - my $cast; - - if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) { - $cast =3D "$cast1 or $cast2"; - } elsif ($cast1 ne "") { - $cast =3D $cast1; - } else { - $cast =3D $cast2; - } - WARN("MINMAX", - "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "= $here\n$stat\n"); - } - } - -# check usleep_range arguments - if ($perl_version_ok && - defined $stat && - $stat =3D~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncA= rg)\s*\)/) { - my $min =3D $1; - my $max =3D $7; - if ($min eq $max) { - WARN("USLEEP_RANGE", - "usleep_range should not use min =3D=3D max args; see Documentati= on/timers/timers-howto.rst\n" . "$here\n$stat\n"); - } elsif ($min =3D~ /^\d+$/ && $max =3D~ /^\d+$/ && - $min > $max) { - WARN("USLEEP_RANGE", - "usleep_range args reversed, use min then max; see Documentation/= timers/timers-howto.rst\n" . "$here\n$stat\n"); - } - } - -# check for naked sscanf - if ($perl_version_ok && - defined $stat && - $line =3D~ /\bsscanf\b/ && - ($stat !~ /$Ident\s*=3D\s*sscanf\s*$balanced_parens/ && - $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ && - $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) { - my $lc =3D $stat =3D~ tr@\n@@; - $lc =3D $lc + $linenr; - my $stat_real =3D get_stat_real($linenr, $lc); - WARN("NAKED_SSCANF", - "unchecked sscanf return value\n" . "$here\n$stat_real\n"); - } - -# check for simple sscanf that should be kstrto<foo> - if ($perl_version_ok && - defined $stat && - $line =3D~ /\bsscanf\b/) { - my $lc =3D $stat =3D~ tr@\n@@; - $lc =3D $lc + $linenr; - my $stat_real =3D get_stat_real($linenr, $lc); - if ($stat_real =3D~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) { - my $format =3D $6; - my $count =3D $format =3D~ tr@%@%@; - if ($count =3D=3D 1 && - $format =3D~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]= h?|[hl]h?|[udxi])"$/) { - WARN("SSCANF_TO_KSTRTO", - "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$sta= t_real\n"); - } - } - } - -# check for new externs in .h files. - if ($realfile =3D~ /\.h$/ && - $line =3D~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) { - if (CHK("AVOID_EXTERNS", - "extern prototypes should be avoided in .h files\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/(.*)\bextern\b\s*(.*)/$1$2/; - } - } - -# check for new externs in .c files. - if ($realfile =3D~ /\.c$/ && defined $stat && - $stat =3D~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) - { - my $function_name =3D $1; - my $paren_space =3D $2; - - my $s =3D $stat; - if (defined $cond) { - substr($s, 0, length($cond), ''); - } - if ($s =3D~ /^\s*;/) - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - - if ($paren_space =3D~ /\n/) { - WARN("FUNCTION_ARGUMENTS", - "arguments for function declarations should follow identifier\n" = . $herecurr); - } - - } elsif ($realfile =3D~ /\.c$/ && defined $stat && - $stat =3D~ /^.\s*extern\s+/) - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - -# check for function declarations that have arguments without identifier n= ames - if (defined $stat && - $stat =3D~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*= \))\s*\(\s*([^{]+)\s*\)\s*;/s && - $1 ne "void") { - my $args =3D trim($1); - while ($args =3D~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$bal= anced_parens)?)/g) { - my $arg =3D trim($1); - if ($arg =3D~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) { - WARN("FUNCTION_ARGUMENTS", - "function definition argument '$arg' should also have an identif= ier name\n" . $herecurr); - } - } - } - -# check for function definitions - if ($perl_version_ok && - defined $stat && - $stat =3D~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens= \s*{/s) { - $context_function =3D $1; - -# check for multiline function definition with misplaced open brace - my $ok =3D 0; - my $cnt =3D statement_rawlines($stat); - my $herectx =3D $here . "\n"; - for (my $n =3D 0; $n < $cnt; $n++) { - my $rl =3D raw_line($linenr, $n); - $herectx .=3D $rl . "\n"; - $ok =3D 1 if ($rl =3D~ /^[ \+]\{/); - $ok =3D 1 if ($rl =3D~ /\{/ && $n =3D=3D 0); - last if $rl =3D~ /^[ \+].*\{/; - } - if (!$ok) { - ERROR("OPEN_BRACE", - "open brace '{' following function definitions go on the next li= ne\n" . $herectx); - } - } - -# checks for new __setup's - if ($rawline =3D~ /\b__setup\("([^"]*)"/) { - my $name =3D $1; - - if (!grep(/$name/, @setup_docs)) { - CHK("UNDOCUMENTED_SETUP", - "__setup appears un-documented -- check Documentation/admin-guide/= kernel-parameters.txt\n" . $herecurr); - } - } - -# check for pointless casting of alloc functions - if ($line =3D~ /\*\s*\)\s*$allocFunctions\b/) { - WARN("UNNECESSARY_CASTS", - "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallo= cnocast.html\n" . $herecurr); - } - -# alloc style -# p =3D alloc(sizeof(struct foo), ...) should be p =3D alloc(sizeof(*p), .= ..) - if ($perl_version_ok && - $line =3D~ /\b($Lval)\s*\=3D\s*(?:$balanced_parens)?\s*((?:kv|k|v)[m= z]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) { - CHK("ALLOC_SIZEOF_STRUCT", - "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); - } - -# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_array/kv= malloc_array/kvcalloc/kcalloc - if ($perl_version_ok && - defined $stat && - $stat =3D~ /^\+\s*($Lval)\s*\=3D\s*(?:$balanced_parens)?\s*((?:kv|k)= [mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { - my $oldfunc =3D $3; - my $a1 =3D $4; - my $a2 =3D $10; - my $newfunc =3D "kmalloc_array"; - $newfunc =3D "kvmalloc_array" if ($oldfunc eq "kvmalloc"); - $newfunc =3D "kvcalloc" if ($oldfunc eq "kvzalloc"); - $newfunc =3D "kcalloc" if ($oldfunc eq "kzalloc"); - my $r1 =3D $a1; - my $r2 =3D $a2; - if ($a1 =3D~ /^sizeof\s*\S/) { - $r1 =3D $a2; - $r2 =3D $a1; - } - if ($r1 !~ /^sizeof\b/ && $r2 =3D~ /^sizeof\s*\S/ && - !($r1 =3D~ /^$Constant$/ || $r1 =3D~ /^[A-Z_][A-Z0-9_]*$/)) { - my $cnt =3D statement_rawlines($stat); - my $herectx =3D get_stat_here($linenr, $cnt, $here); - - if (WARN("ALLOC_WITH_MULTIPLY", - "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) && - $cnt =3D=3D 1 && - $fix) { - $fixed[$fixlinenr] =3D~ s/\b($Lval)\s*\=3D\s*(?:$balanced_parens)?\s*= ((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' =3D ' . "$ne= wfunc(" . trim($r1) . ', ' . trim($r2)/e; - } - } - } - -# check for krealloc arg reuse - if ($perl_version_ok && - $line =3D~ /\b($Lval)\s*\=3D\s*(?:$balanced_parens)?\s*krealloc\s*\(= \s*($Lval)\s*,/ && - $1 eq $3) { - WARN("KREALLOC_ARG_REUSE", - "Reusing the krealloc arg is almost always a bug\n" . $herecurr); - } - -# check for alloc argument mismatch - if ($line =3D~ /\b((?:devm_)?(?:kcalloc|kmalloc_array))\s*\(\s*sizeof\b/= ) { - WARN("ALLOC_ARRAY_ARGS", - "$1 uses number as first arg, sizeof is generally wrong\n" . $here= curr); - } - -# check for multiple semicolons - if ($line =3D~ /;\s*;\s*$/) { - if (WARN("ONE_SEMICOLON", - "Statements terminations use 1 semicolon\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/(\s*;\s*){2,}$/;/g; - } - } - -# check for #defines like: 1 << <digit> that could be BIT(digit), it is no= t exported to uapi - if ($realfile !~ m@^include/uapi/@ && - $line =3D~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$= Ident)\s*\)?/) { - my $ull =3D ""; - $ull =3D "_ULL" if (defined($1) && $1 =3D~ /ll/i); - if (CHK("BIT_MACRO", - "Prefer using the BIT$ull macro\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/= BIT${ull}($1)/; - } - } - -# check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too) - if ($rawline =3D~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}= /) { - WARN("IS_ENABLED_CONFIG", - "IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . = $herecurr); - } - -# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE - if ($line =3D~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(${CONFIG_}[A-Z_]= +)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) { - my $config =3D $1; - if (WARN("PREFER_IS_ENABLED", - "Prefer IS_ENABLED(<FOO>) to ${CONFIG_}<FOO> || ${CONFIG_}<FOO>_MODUL= E\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D "\+#if IS_ENABLED($config)"; - } - } - -# check for /* fallthrough */ like comment, prefer fallthrough; - my @fallthroughs =3D ( - 'fallthrough', - '@fallthrough@', - 'lint -fallthrough[ \t]*', - 'intentional(?:ly)?[ \t]*fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)', - '(?:else,?\s*)?FALL(?:S | |-)?THR(?:OUGH|U|EW)[ \t.!]*(?:-[^\n\r]*)?', - 'Fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?', - 'fall(?:s | |-)?thr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?', - ); - if ($raw_comment ne '') { - foreach my $ft (@fallthroughs) { - if ($raw_comment =3D~ /$ft/) { - my $msg_level =3D \&WARN; - $msg_level =3D \&CHK if ($file); - &{$msg_level}("PREFER_FALLTHROUGH", - "Prefer 'fallthrough;' over fallthrough comment\n" . $herecurr= ); - last; - } - } - } - -# check for switch/default statements without a break; - if ($perl_version_ok && - defined $stat && - $stat =3D~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bde= fault[$;\s]*:[$;\s]*;/g) { - my $cnt =3D statement_rawlines($stat); - my $herectx =3D get_stat_here($linenr, $cnt, $here); - - WARN("DEFAULT_NO_BREAK", - "switch default: should use break\n" . $herectx); - } - -# check for gcc specific __FUNCTION__ - if ($line =3D~ /\b__FUNCTION__\b/) { - if (WARN("USE_FUNC", - "__func__ should be used instead of gcc specific __FUNCTION__\n" . $= herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\b__FUNCTION__\b/__func__/g; - } - } - -# check for uses of __DATE__, __TIME__, __TIMESTAMP__ - while ($line =3D~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) { - ERROR("DATE_TIME", - "Use of the '$1' macro makes the build non-deterministic\n" . $he= recurr); - } - -# check for use of yield() - if ($line =3D~ /\byield\s*\(\s*\)/) { - WARN("YIELD", - "Using yield() is generally wrong. See yield() kernel-doc (sched/c= ore.c)\n" . $herecurr); - } - -# check for comparisons against true and false - if ($line =3D~ /\+\s*(.*?)\b(true|false|$Lval)\s*(=3D=3D|\!=3D)\s*(true|= false|$Lval)\b(.*)$/i) { - my $lead =3D $1; - my $arg =3D $2; - my $test =3D $3; - my $otype =3D $4; - my $trail =3D $5; - my $op =3D "!"; - - ($arg, $otype) =3D ($otype, $arg) if ($arg =3D~ /^(?:true|false)$/i); - - my $type =3D lc($otype); - if ($type =3D~ /^(?:true|false)$/) { - if (("$test" eq "=3D=3D" && "$type" eq "true") || - ("$test" eq "!=3D" && "$type" eq "false")) { - $op =3D ""; - } - - CHK("BOOL_COMPARISON", - "Using comparison to $otype is error prone\n" . $herecurr); - -## maybe suggesting a correct construct would better -## "Using comparison to $otype is error prone. Perhaps use '${lead= }${op}${arg}${trail}'\n" . $herecurr); - - } - } - -# check for semaphores initialized locked - if ($line =3D~ /^.\s*sema_init.+,\W?0\W?\)/) { - WARN("CONSIDER_COMPLETION", - "consider using a completion\n" . $herecurr); - } - -# recommend kstrto* over simple_strto* and strict_strto* - if ($line =3D~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) { - WARN("CONSIDER_KSTRTO", - "$1 is obsolete, use k$3 instead\n" . $herecurr); - } - -# check for __initcall(), use device_initcall() explicitly or more appropr= iate function please - if ($line =3D~ /^.\s*__initcall\s*\(/) { - WARN("USE_DEVICE_INITCALL", - "please use device_initcall() or more appropriate function instead= of __initcall() (see include/linux/init.h)\n" . $herecurr); - } - -# check for spin_is_locked(), suggest lockdep instead - if ($line =3D~ /\bspin_is_locked\(/) { - WARN("USE_LOCKDEP", - "Where possible, use lockdep_assert_held instead of assertions bas= ed on spin_is_locked\n" . $herecurr); - } - -# check for deprecated apis - if ($line =3D~ /\b($deprecated_apis_search)\b\s*\(/) { - my $deprecated_api =3D $1; - my $new_api =3D $deprecated_apis{$deprecated_api}; - WARN("DEPRECATED_API", - "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n"= . $herecurr); - } - -# check for various structs that are normally const (ops, kgdb, device_tre= e) -# and avoid what seem like struct definitions 'struct foo {' - if (defined($const_structs) && - $line !~ /\bconst\b/ && - $line =3D~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) { - WARN("CONST_STRUCT", - "struct $1 should normally be const\n" . $herecurr); - } - -# use of NR_CPUS is usually wrong -# ignore definitions of NR_CPUS and usage to define arrays as likely right -# ignore designated initializers using NR_CPUS - if ($line =3D~ /\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/ && - $line !~ /^.\s*\.\w+\s*=3D\s*.*\bNR_CPUS\b/) - { - WARN("NR_CPUS", - "usage of NR_CPUS is often wrong - consider using cpu_possible(), = num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); - } - -# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong. - if ($line =3D~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) { - ERROR("DEFINE_ARCH_HAS", - "#define of '$1' is wrong - use Kconfig variables or standard gua= rds instead\n" . $herecurr); - } - -# likely/unlikely comparisons similar to "(likely(foo) > 0)" - if ($perl_version_ok && - $line =3D~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) { - WARN("LIKELY_MISUSE", - "Using $1 should generally have parentheses around the comparison\= n" . $herecurr); - } - -# return sysfs_emit(foo, fmt, ...) fmt without newline - if ($line =3D~ /\breturn\s+sysfs_emit\s*\(\s*$FuncArg\s*,\s*($String)/ && - substr($rawline, $-[6], $+[6] - $-[6]) !~ /\\n"$/) { - my $offset =3D $+[6] - 1; - if (WARN("SYSFS_EMIT", - "return sysfs_emit(...) formats should include a terminating newline\= n" . $herecurr) && - $fix) { - substr($fixed[$fixlinenr], $offset, 0) =3D '\\n'; - } - } - -# nested likely/unlikely calls - if ($line =3D~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALU= E)?|WARN)/) { - WARN("LIKELY_MISUSE", - "nested (un)?likely() calls, $1 already uses unlikely() internally= \n" . $herecurr); - } - -# whine mightly about in_atomic - if ($line =3D~ /\bin_atomic\s*\(/) { - if ($realfile =3D~ m@^drivers/@) { - ERROR("IN_ATOMIC", - "do not use in_atomic in drivers\n" . $herecurr); - } elsif ($realfile !~ m@^kernel/@) { - WARN("IN_ATOMIC", - "use of in_atomic() is incorrect outside core kernel code\n" . $h= erecurr); - } - } - -# check for lockdep_set_novalidate_class - if ($line =3D~ /^.\s*lockdep_set_novalidate_class\s*\(/ || - $line =3D~ /__lockdep_no_validate__\s*\)/ ) { - if ($realfile !~ m@^kernel/lockdep@ && - $realfile !~ m@^include/linux/lockdep@ && - $realfile !~ m@^drivers/base/core@) { - ERROR("LOCKDEP", - "lockdep_no_validate class is reserved for device->mutex.\n" . $= herecurr); - } - } - - if ($line =3D~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ || - $line =3D~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) { - WARN("EXPORTED_WORLD_WRITABLE", - "Exporting world writable files is usually an error. Consider more= restrictive permissions.\n" . $herecurr); - } - -# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO> -# and whether or not function naming is typical and if -# DEVICE_ATTR permissions uses are unusual too - if ($perl_version_ok && - defined $stat && - $stat =3D~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mo= de_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)= /) { - my $var =3D $1; - my $perms =3D $2; - my $show =3D $3; - my $store =3D $4; - my $octal_perms =3D perms_to_octal($perms); - if ($show =3D~ /^${var}_show$/ && - $store =3D~ /^${var}_store$/ && - $octal_perms eq "0644") { - if (WARN("DEVICE_ATTR_RW", - "Use DEVICE_ATTR_RW\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\= s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/; - } - } elsif ($show =3D~ /^${var}_show$/ && - $store =3D~ /^NULL$/ && - $octal_perms eq "0444") { - if (WARN("DEVICE_ATTR_RO", - "Use DEVICE_ATTR_RO\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\= s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/; - } - } elsif ($show =3D~ /^NULL$/ && - $store =3D~ /^${var}_store$/ && - $octal_perms eq "0200") { - if (WARN("DEVICE_ATTR_WO", - "Use DEVICE_ATTR_WO\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\= s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/; - } - } elsif ($octal_perms eq "0644" || - $octal_perms eq "0444" || - $octal_perms eq "0200") { - my $newshow =3D "$show"; - $newshow =3D "${var}_show" if ($show ne "NULL" && $show ne "${var}_sho= w"); - my $newstore =3D $store; - $newstore =3D "${var}_store" if ($store ne "NULL" && $store ne "${var}= _store"); - my $rename =3D ""; - if ($show ne $newshow) { - $rename .=3D " '$show' to '$newshow'"; - } - if ($store ne $newstore) { - $rename .=3D " '$store' to '$newstore'"; - } - WARN("DEVICE_ATTR_FUNCTIONS", - "Consider renaming function(s)$rename\n" . $herecurr); - } else { - WARN("DEVICE_ATTR_PERMS", - "DEVICE_ATTR unusual permissions '$perms' used\n" . $herecurr); - } - } - -# Mode permission misuses where it seems decimal should be octal -# This uses a shortcut match to avoid unnecessary uses of a slow foreach l= oop -# o Ignore module_param*(...) uses with a decimal 0 permission as that has= a -# specific definition of not visible in sysfs. -# o Ignore proc_create*(...) uses with a decimal 0 permission as that means -# use the default permissions - if ($perl_version_ok && - defined $stat && - $line =3D~ /$mode_perms_search/) { - foreach my $entry (@mode_permission_funcs) { - my $func =3D $entry->[0]; - my $arg_pos =3D $entry->[1]; - - my $lc =3D $stat =3D~ tr@\n@@; - $lc =3D $lc + $linenr; - my $stat_real =3D get_stat_real($linenr, $lc); - - my $skip_args =3D ""; - if ($arg_pos > 1) { - $arg_pos--; - $skip_args =3D "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; - } - my $test =3D "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*= )\\s*[,\\)]"; - if ($stat =3D~ /$test/) { - my $val =3D $1; - $val =3D $6 if ($skip_args ne ""); - if (!($func =3D~ /^(?:module_param|proc_create)/ && $val eq "0") && - (($val =3D~ /^$Int$/ && $val !~ /^$Octal$/) || - ($val =3D~ /^$Octal$/ && length($val) ne 4))) { - ERROR("NON_OCTAL_PERMISSIONS", - "Use 4 digit octal (0777) not decimal permissions\n" . "$here\= n" . $stat_real); - } - if ($val =3D~ /^$Octal$/ && (oct($val) & 02)) { - ERROR("EXPORTED_WORLD_WRITABLE", - "Exporting writable files is usually an error. Consider more r= estrictive permissions.\n" . "$here\n" . $stat_real); - } - } - } - } - -# check for uses of S_<PERMS> that could be octal for readability - while ($line =3D~ m{\b($multi_mode_perms_string_search)\b}g) { - my $oval =3D $1; - my $octal =3D perms_to_octal($oval); - if (WARN("SYMBOLIC_PERMS", - "Symbolic permissions '$oval' are not preferred. Consider using octal= permissions '$octal'.\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\Q$oval\E/$octal/; - } - } - -# validate content of MODULE_LICENSE against list from include/linux/modul= e.h - if ($line =3D~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { - my $extracted_string =3D get_quoted_string($line, $rawline); - my $valid_licenses =3D qr{ - GPL| - GPL\ v2| - GPL\ and\ additional\ rights| - Dual\ BSD/GPL| - Dual\ MIT/GPL| - Dual\ MPL/GPL| - Proprietary - }x; - if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) { - WARN("MODULE_LICENSE", - "unknown module license " . $extracted_string . "\n" . $herecurr); - } - if (!$file && $extracted_string eq '"GPL v2"') { - if (WARN("MODULE_LICENSE", - "Prefer \"GPL\" over \"GPL v2\" - see commit bf7fbeeae6db (\"modu= le: Cure the MODULE_LICENSE \"GPL\" vs. \"GPL v2\" bogosity\")\n" . $herecu= rr) && - $fix) { - $fixed[$fixlinenr] =3D~ s/\bMODULE_LICENSE\s*\(\s*"GPL v2"\s*\)/MODUL= E_LICENSE("GPL")/; - } - } - } - -# check for sysctl duplicate constants - if ($line =3D~ /\.extra[12]\s*=3D\s*&(zero|one|int_max)\b/) { - WARN("DUPLICATED_SYSCTL_CONST", - "duplicated sysctl range checking value '$1', consider using the share= d one in include/linux/sysctl.h\n" . $herecurr); - } - } - - # If we have no input at all, then there is nothing to report on - # so just keep quiet. - if ($#rawlines =3D=3D -1) { - exit(0); - } - - # In mailback mode only produce a report in the negative, for - # things that appear to be patches. - if ($mailback && ($clean =3D=3D 1 || !$is_patch)) { - exit(0); - } - - # This is not a patch, and we are in 'no-patch' mode so - # just keep quiet. - if (!$chk_patch && !$is_patch) { - exit(0); - } - - if (!$is_patch && $filename !~ /cover-letter\.patch$/) { - ERROR("NOT_UNIFIED_DIFF", - "Does not appear to be a unified-diff format patch\n"); - } - if ($is_patch && $has_commit_log && $chk_signoff) { - if ($signoff =3D=3D 0) { - ERROR("MISSING_SIGN_OFF", - "Missing Signed-off-by: line(s)\n"); - } elsif ($authorsignoff !=3D 1) { - # authorsignoff values: - # 0 -> missing sign off - # 1 -> sign off identical - # 2 -> names and addresses match, comments mismatch - # 3 -> addresses match, names different - # 4 -> names match, addresses different - # 5 -> names match, addresses excluding subaddress details (refer RFC 5= 233) match - - my $sob_msg =3D "'From: $author' !=3D 'Signed-off-by: $author_sob'"; - - if ($authorsignoff =3D=3D 0) { - ERROR("NO_AUTHOR_SIGN_OFF", - "Missing Signed-off-by: line by nominal patch author '$author'\n= "); - } elsif ($authorsignoff =3D=3D 2) { - CHK("FROM_SIGN_OFF_MISMATCH", - "From:/Signed-off-by: email comments mismatch: $sob_msg\n"); - } elsif ($authorsignoff =3D=3D 3) { - WARN("FROM_SIGN_OFF_MISMATCH", - "From:/Signed-off-by: email name mismatch: $sob_msg\n"); - } elsif ($authorsignoff =3D=3D 4) { - WARN("FROM_SIGN_OFF_MISMATCH", - "From:/Signed-off-by: email address mismatch: $sob_msg\n"); - } elsif ($authorsignoff =3D=3D 5) { - WARN("FROM_SIGN_OFF_MISMATCH", - "From:/Signed-off-by: email subaddress mismatch: $sob_msg\n"); - } - } - } - - print report_dump(); - if ($summary && !($clean =3D=3D 1 && $quiet =3D=3D 1)) { - print "$filename " if ($summary_file); - print "total: $cnt_error errors, $cnt_warn warnings, " . - (($check)? "$cnt_chk checks, " : "") . - "$cnt_lines lines checked\n"; - } - - if ($quiet =3D=3D 0) { - # If there were any defects found and not already fixing them - if (!$clean and !$fix) { - print << "EOM" - -NOTE: For some of the reported defects, checkpatch may be able to - mechanically convert to the typical style using --fix or --fix-inpla= ce. -EOM - } - # If there were whitespace errors which cleanpatch can fix - # then suggest that. - if ($rpt_cleaners) { - $rpt_cleaners =3D 0; - print << "EOM" - -NOTE: Whitespace errors detected. - You may wish to use scripts/cleanpatch or scripts/cleanfile -EOM - } - } - - if ($clean =3D=3D 0 && $fix && - ("@rawlines" ne "@fixed" || - $#fixed_inserted >=3D 0 || $#fixed_deleted >=3D 0)) { - my $newfile =3D $filename; - $newfile .=3D ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); - my $linecount =3D 0; - my $f; - - @fixed =3D fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed= _deleted); - - open($f, '>', $newfile) - or die "$P: Can't open $newfile for write\n"; - foreach my $fixed_line (@fixed) { - $linecount++; - if ($file) { - if ($linecount > 3) { - $fixed_line =3D~ s/^\+//; - print $f $fixed_line . "\n"; - } - } else { - print $f $fixed_line . "\n"; - } - } - close($f); - - if (!$quiet) { - print << "EOM"; - -Wrote EXPERIMENTAL --fix correction(s) to '$newfile' - -Do _NOT_ trust the results written to this file. -Do _NOT_ submit these changes without inspecting them for correctness. - -This EXPERIMENTAL file is simply a convenience to help rewrite patches. -No warranties, expressed or implied... -EOM - } - } - - if ($quiet =3D=3D 0) { - print "\n"; - if ($clean =3D=3D 1) { - print "$vname has no obvious style problems and is ready for submission= .\n"; - } else { - print "$vname has style problems, please review.\n"; - } - } - return $clean; -}