mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 09:46:37 +03:00
scripts/checkpatch.pl: Resync with v6.17
This resyncs us with the version found in v6.17 of the Linux kernel with the following exceptions: - Keep our u-boot specific tests / code area. - Keep the location of our checkpatch.rst - Change the "use strscpy" test as we don't have that to strlcpy - Keep debug/printf in the list for $logFunctions - Keep checks to "env" files - Keep our tests for strncpy/strncat This also syncs the spdxcheck.py tool and all the associated documentation. Signed-off-by: Kory Maincent <kory.maincent@bootlin.com> [trini: Keep our strlcpy/cat check] Signed-off-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
@@ -168,7 +168,7 @@ Available options:
|
|||||||
|
|
||||||
- --fix
|
- --fix
|
||||||
|
|
||||||
This is an EXPERIMENTAL feature. If correctable errors exists, a file
|
This is an EXPERIMENTAL feature. If correctable errors exist, a file
|
||||||
<inputfile>.EXPERIMENTAL-checkpatch-fixes is created which has the
|
<inputfile>.EXPERIMENTAL-checkpatch-fixes is created which has the
|
||||||
automatically fixable errors corrected.
|
automatically fixable errors corrected.
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ Available options:
|
|||||||
|
|
||||||
- --ignore-perl-version
|
- --ignore-perl-version
|
||||||
|
|
||||||
Override checking of perl version. Runtime errors maybe encountered after
|
Override checking of perl version. Runtime errors may be encountered after
|
||||||
enabling this flag if the perl version does not meet the minimum specified.
|
enabling this flag if the perl version does not meet the minimum specified.
|
||||||
|
|
||||||
- --codespell
|
- --codespell
|
||||||
@@ -342,24 +342,6 @@ API usage
|
|||||||
|
|
||||||
See: https://www.kernel.org/doc/html/latest/RCU/whatisRCU.html#full-list-of-rcu-apis
|
See: https://www.kernel.org/doc/html/latest/RCU/whatisRCU.html#full-list-of-rcu-apis
|
||||||
|
|
||||||
**DEPRECATED_VARIABLE**
|
|
||||||
EXTRA_{A,C,CPP,LD}FLAGS are deprecated and should be replaced by the new
|
|
||||||
flags added via commit f77bf01425b1 ("kbuild: introduce ccflags-y,
|
|
||||||
asflags-y and ldflags-y").
|
|
||||||
|
|
||||||
The following conversion scheme maybe used::
|
|
||||||
|
|
||||||
EXTRA_AFLAGS -> asflags-y
|
|
||||||
EXTRA_CFLAGS -> ccflags-y
|
|
||||||
EXTRA_CPPFLAGS -> cppflags-y
|
|
||||||
EXTRA_LDFLAGS -> ldflags-y
|
|
||||||
|
|
||||||
See:
|
|
||||||
|
|
||||||
1. https://lore.kernel.org/lkml/20070930191054.GA15876@uranus.ravnborg.org/
|
|
||||||
2. https://lore.kernel.org/lkml/1313384834-24433-12-git-send-email-lacombar@gmail.com/
|
|
||||||
3. https://www.kernel.org/doc/html/latest/kbuild/makefiles.html#compilation-flags
|
|
||||||
|
|
||||||
**DEVICE_ATTR_FUNCTIONS**
|
**DEVICE_ATTR_FUNCTIONS**
|
||||||
The function names used in DEVICE_ATTR is unusual.
|
The function names used in DEVICE_ATTR is unusual.
|
||||||
Typically, the store and show functions are used with <attr>_store and
|
Typically, the store and show functions are used with <attr>_store and
|
||||||
@@ -470,8 +452,6 @@ API usage
|
|||||||
usleep_range() should be preferred over udelay(). The proper way of
|
usleep_range() should be preferred over udelay(). The proper way of
|
||||||
using usleep_range() is mentioned in the kernel docs.
|
using usleep_range() is mentioned in the kernel docs.
|
||||||
|
|
||||||
See: https://www.kernel.org/doc/html/latest/timers/timers-howto.html#delays-information-on-the-various-kernel-delay-sleep-mechanisms
|
|
||||||
|
|
||||||
|
|
||||||
Comments
|
Comments
|
||||||
--------
|
--------
|
||||||
@@ -515,6 +495,15 @@ Comments
|
|||||||
|
|
||||||
See: https://lore.kernel.org/lkml/20131006222342.GT19510@leaf/
|
See: https://lore.kernel.org/lkml/20131006222342.GT19510@leaf/
|
||||||
|
|
||||||
|
**UNCOMMENTED_RGMII_MODE**
|
||||||
|
Historically, the RGMII PHY modes specified in Device Trees have been
|
||||||
|
used inconsistently, often referring to the usage of delays on the PHY
|
||||||
|
side rather than describing the board.
|
||||||
|
|
||||||
|
PHY modes "rgmii", "rgmii-rxid" and "rgmii-txid" modes require the clock
|
||||||
|
signal to be delayed on the PCB; this unusual configuration should be
|
||||||
|
described in a comment. If they are not (meaning that the delay is realized
|
||||||
|
internally in the MAC or PHY), "rgmii-id" is the correct PHY mode.
|
||||||
|
|
||||||
Commit message
|
Commit message
|
||||||
--------------
|
--------------
|
||||||
@@ -612,6 +601,13 @@ Commit message
|
|||||||
|
|
||||||
See: https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes
|
See: https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes
|
||||||
|
|
||||||
|
**BAD_FIXES_TAG**
|
||||||
|
The Fixes: tag is malformed or does not follow the community conventions.
|
||||||
|
This can occur if the tag have been split into multiple lines (e.g., when
|
||||||
|
pasted in an email program with word wrapping enabled).
|
||||||
|
|
||||||
|
See: https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes
|
||||||
|
|
||||||
|
|
||||||
Comparison style
|
Comparison style
|
||||||
----------------
|
----------------
|
||||||
@@ -899,6 +895,20 @@ Macros, Attributes and Symbols
|
|||||||
|
|
||||||
See: https://lore.kernel.org/lkml/1399671106.2912.21.camel@joe-AO725/
|
See: https://lore.kernel.org/lkml/1399671106.2912.21.camel@joe-AO725/
|
||||||
|
|
||||||
|
**MACRO_ARG_UNUSED**
|
||||||
|
If function-like macros do not utilize a parameter, it might result
|
||||||
|
in a build warning. We advocate for utilizing static inline functions
|
||||||
|
to replace such macros.
|
||||||
|
For example, for a macro such as the one below::
|
||||||
|
|
||||||
|
#define test(a) do { } while (0)
|
||||||
|
|
||||||
|
there would be a warning like below::
|
||||||
|
|
||||||
|
WARNING: Argument 'a' is not used in function-like macro.
|
||||||
|
|
||||||
|
See: https://www.kernel.org/doc/html/latest/process/coding-style.html#macros-enums-and-rtl
|
||||||
|
|
||||||
**SINGLE_STATEMENT_DO_WHILE_MACRO**
|
**SINGLE_STATEMENT_DO_WHILE_MACRO**
|
||||||
For the multi-statement macros, it is necessary to use the do-while
|
For the multi-statement macros, it is necessary to use the do-while
|
||||||
loop to avoid unpredictable code paths. The do-while loop helps to
|
loop to avoid unpredictable code paths. The do-while loop helps to
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ my %verbose_messages = ();
|
|||||||
my %verbose_emitted = ();
|
my %verbose_emitted = ();
|
||||||
my $tree = 1;
|
my $tree = 1;
|
||||||
my $chk_signoff = 1;
|
my $chk_signoff = 1;
|
||||||
|
my $chk_fixes_tag = 1;
|
||||||
my $chk_patch = 1;
|
my $chk_patch = 1;
|
||||||
my $tst_only;
|
my $tst_only;
|
||||||
my $emacs = 0;
|
my $emacs = 0;
|
||||||
@@ -75,6 +76,8 @@ my $git_command ='export LANGUAGE=en_US.UTF-8; git';
|
|||||||
my $tabsize = 8;
|
my $tabsize = 8;
|
||||||
my ${CONFIG_} = "CONFIG_";
|
my ${CONFIG_} = "CONFIG_";
|
||||||
|
|
||||||
|
my %maybe_linker_symbol; # for externs in c exceptions, when seen in *vmlinux.lds.h
|
||||||
|
|
||||||
sub help {
|
sub help {
|
||||||
my ($exitcode) = @_;
|
my ($exitcode) = @_;
|
||||||
|
|
||||||
@@ -87,6 +90,7 @@ Options:
|
|||||||
-v, --verbose verbose mode
|
-v, --verbose verbose mode
|
||||||
--no-tree run without a kernel tree
|
--no-tree run without a kernel tree
|
||||||
--no-signoff do not check for 'Signed-off-by' line
|
--no-signoff do not check for 'Signed-off-by' line
|
||||||
|
--no-fixes-tag do not check for 'Fixes:' tag
|
||||||
--patch treat FILE as patchfile (default)
|
--patch treat FILE as patchfile (default)
|
||||||
--emacs emacs compile window format
|
--emacs emacs compile window format
|
||||||
--terse one line per report
|
--terse one line per report
|
||||||
@@ -110,7 +114,8 @@ Options:
|
|||||||
--max-line-length=n set the maximum line length, (default $max_line_length)
|
--max-line-length=n set the maximum line length, (default $max_line_length)
|
||||||
if exceeded, warn on patches
|
if exceeded, warn on patches
|
||||||
requires --strict for use with --file
|
requires --strict for use with --file
|
||||||
--min-conf-desc-length=n set the min description length, if shorter, warn
|
--min-conf-desc-length=n set the minimum description length for config symbols
|
||||||
|
in lines, if shorter, warn (default $min_conf_desc_length)
|
||||||
--tab-size=n set the number of spaces for tab (default $tabsize)
|
--tab-size=n set the number of spaces for tab (default $tabsize)
|
||||||
--root=PATH PATH to the kernel tree root
|
--root=PATH PATH to the kernel tree root
|
||||||
--no-summary suppress the per-file summary
|
--no-summary suppress the per-file summary
|
||||||
@@ -148,6 +153,24 @@ EOM
|
|||||||
exit($exitcode);
|
exit($exitcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $DO_WHILE_0_ADVICE = q{
|
||||||
|
do {} while (0) advice is over-stated in a few situations:
|
||||||
|
|
||||||
|
The more obvious case is macros, like MODULE_PARM_DESC, invoked at
|
||||||
|
file-scope, where C disallows code (it must be in functions). See
|
||||||
|
$exceptions if you have one to add by name.
|
||||||
|
|
||||||
|
More troublesome is declarative macros used at top of new scope,
|
||||||
|
like DECLARE_PER_CPU. These might just compile with a do-while-0
|
||||||
|
wrapper, but would be incorrect. Most of these are handled by
|
||||||
|
detecting struct,union,etc declaration primitives in $exceptions.
|
||||||
|
|
||||||
|
Theres also macros called inside an if (block), which "return" an
|
||||||
|
expression. These cannot do-while, and need a ({}) wrapper.
|
||||||
|
|
||||||
|
Enjoy this qualification while we work to improve our heuristics.
|
||||||
|
};
|
||||||
|
|
||||||
sub uniq {
|
sub uniq {
|
||||||
my %seen;
|
my %seen;
|
||||||
return grep { !$seen{$_}++ } @_;
|
return grep { !$seen{$_}++ } @_;
|
||||||
@@ -295,6 +318,7 @@ GetOptions(
|
|||||||
'v|verbose!' => \$verbose,
|
'v|verbose!' => \$verbose,
|
||||||
'tree!' => \$tree,
|
'tree!' => \$tree,
|
||||||
'signoff!' => \$chk_signoff,
|
'signoff!' => \$chk_signoff,
|
||||||
|
'fixes-tag!' => \$chk_fixes_tag,
|
||||||
'patch!' => \$chk_patch,
|
'patch!' => \$chk_patch,
|
||||||
'emacs!' => \$emacs,
|
'emacs!' => \$emacs,
|
||||||
'terse!' => \$terse,
|
'terse!' => \$terse,
|
||||||
@@ -337,7 +361,7 @@ if ($user_codespellfile) {
|
|||||||
} elsif (!(-f $codespellfile)) {
|
} elsif (!(-f $codespellfile)) {
|
||||||
# If /usr/share/codespell/dictionary.txt is not present, try to find it
|
# If /usr/share/codespell/dictionary.txt is not present, try to find it
|
||||||
# under codespell's install directory: <codespell_root>/data/dictionary.txt
|
# under codespell's install directory: <codespell_root>/data/dictionary.txt
|
||||||
if (($codespell || $help) && which("codespell") ne "" && which("python") ne "") {
|
if (($codespell || $help) && which("python3") ne "") {
|
||||||
my $python_codespell_dict = << "EOF";
|
my $python_codespell_dict = << "EOF";
|
||||||
|
|
||||||
import os.path as op
|
import os.path as op
|
||||||
@@ -347,7 +371,7 @@ codespell_file = op.join(codespell_dir, 'data', 'dictionary.txt')
|
|||||||
print(codespell_file, end='')
|
print(codespell_file, end='')
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
my $codespell_dict = `python -c "$python_codespell_dict" 2> /dev/null`;
|
my $codespell_dict = `python3 -c "$python_codespell_dict" 2> /dev/null`;
|
||||||
$codespellfile = $codespell_dict if (-f $codespell_dict);
|
$codespellfile = $codespell_dict if (-f $codespell_dict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -513,6 +537,7 @@ our $Attribute = qr{
|
|||||||
__ro_after_init|
|
__ro_after_init|
|
||||||
__kprobes|
|
__kprobes|
|
||||||
$InitAttribute|
|
$InitAttribute|
|
||||||
|
__aligned\s*\(.*\)|
|
||||||
____cacheline_aligned|
|
____cacheline_aligned|
|
||||||
____cacheline_aligned_in_smp|
|
____cacheline_aligned_in_smp|
|
||||||
____cacheline_internodealigned_in_smp|
|
____cacheline_internodealigned_in_smp|
|
||||||
@@ -579,10 +604,14 @@ our $typeKernelTypedefs = qr{(?x:
|
|||||||
(?:__)?(?:u|s|be|le)(?:8|16|32|64)|
|
(?:__)?(?:u|s|be|le)(?:8|16|32|64)|
|
||||||
atomic_t
|
atomic_t
|
||||||
)};
|
)};
|
||||||
|
our $typeStdioTypedefs = qr{(?x:
|
||||||
|
FILE
|
||||||
|
)};
|
||||||
our $typeTypedefs = qr{(?x:
|
our $typeTypedefs = qr{(?x:
|
||||||
$typeC99Typedefs\b|
|
$typeC99Typedefs\b|
|
||||||
$typeOtherOSTypedefs\b|
|
$typeOtherOSTypedefs\b|
|
||||||
$typeKernelTypedefs\b
|
$typeKernelTypedefs\b|
|
||||||
|
$typeStdioTypedefs\b
|
||||||
)};
|
)};
|
||||||
|
|
||||||
our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
|
our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
|
||||||
@@ -621,6 +650,22 @@ our $signature_tags = qr{(?xi:
|
|||||||
Cc:
|
Cc:
|
||||||
)};
|
)};
|
||||||
|
|
||||||
|
our @link_tags = qw(Link Closes);
|
||||||
|
|
||||||
|
#Create a search and print patterns for all these strings to be used directly below
|
||||||
|
our $link_tags_search = "";
|
||||||
|
our $link_tags_print = "";
|
||||||
|
foreach my $entry (@link_tags) {
|
||||||
|
if ($link_tags_search ne "") {
|
||||||
|
$link_tags_search .= '|';
|
||||||
|
$link_tags_print .= ' or ';
|
||||||
|
}
|
||||||
|
$entry .= ':';
|
||||||
|
$link_tags_search .= $entry;
|
||||||
|
$link_tags_print .= "'$entry'";
|
||||||
|
}
|
||||||
|
$link_tags_search = "(?:${link_tags_search})";
|
||||||
|
|
||||||
our $tracing_logging_tags = qr{(?xi:
|
our $tracing_logging_tags = qr{(?xi:
|
||||||
[=-]*> |
|
[=-]*> |
|
||||||
<[=-]* |
|
<[=-]* |
|
||||||
@@ -645,6 +690,9 @@ our $tracing_logging_tags = qr{(?xi:
|
|||||||
[\.\!:\s]*
|
[\.\!:\s]*
|
||||||
)};
|
)};
|
||||||
|
|
||||||
|
# Device ID types like found in include/linux/mod_devicetable.h.
|
||||||
|
our $dev_id_types = qr{\b[a-z]\w*_device_id\b};
|
||||||
|
|
||||||
sub edit_distance_min {
|
sub edit_distance_min {
|
||||||
my (@arr) = @_;
|
my (@arr) = @_;
|
||||||
my $len = scalar @arr;
|
my $len = scalar @arr;
|
||||||
@@ -703,6 +751,17 @@ sub find_standard_signature {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
our $obsolete_archives = qr{(?xi:
|
||||||
|
\Qfreedesktop.org/archives/dri-devel\E |
|
||||||
|
\Qlists.infradead.org\E |
|
||||||
|
\Qlkml.org\E |
|
||||||
|
\Qmail-archive.com\E |
|
||||||
|
\Qmailman.alsa-project.org/pipermail\E |
|
||||||
|
\Qmarc.info\E |
|
||||||
|
\Qozlabs.org/pipermail\E |
|
||||||
|
\Qspinics.net\E
|
||||||
|
)};
|
||||||
|
|
||||||
our @typeListMisordered = (
|
our @typeListMisordered = (
|
||||||
qr{char\s+(?:un)?signed},
|
qr{char\s+(?:un)?signed},
|
||||||
qr{int\s+(?:(?:un)?signed\s+)?short\s},
|
qr{int\s+(?:(?:un)?signed\s+)?short\s},
|
||||||
@@ -802,16 +861,10 @@ foreach my $entry (@mode_permission_funcs) {
|
|||||||
$mode_perms_search = "(?:${mode_perms_search})";
|
$mode_perms_search = "(?:${mode_perms_search})";
|
||||||
|
|
||||||
our %deprecated_apis = (
|
our %deprecated_apis = (
|
||||||
"synchronize_rcu_bh" => "synchronize_rcu",
|
"kmap" => "kmap_local_page",
|
||||||
"synchronize_rcu_bh_expedited" => "synchronize_rcu_expedited",
|
"kunmap" => "kunmap_local",
|
||||||
"call_rcu_bh" => "call_rcu",
|
"kmap_atomic" => "kmap_local_page",
|
||||||
"rcu_barrier_bh" => "rcu_barrier",
|
"kunmap_atomic" => "kunmap_local",
|
||||||
"synchronize_sched" => "synchronize_rcu",
|
|
||||||
"synchronize_sched_expedited" => "synchronize_rcu_expedited",
|
|
||||||
"call_rcu_sched" => "call_rcu",
|
|
||||||
"rcu_barrier_sched" => "rcu_barrier",
|
|
||||||
"get_state_synchronize_sched" => "get_state_synchronize_rcu",
|
|
||||||
"cond_synchronize_sched" => "cond_synchronize_rcu",
|
|
||||||
);
|
);
|
||||||
|
|
||||||
#Create a search pattern for all these strings to speed up a loop below
|
#Create a search pattern for all these strings to speed up a loop below
|
||||||
@@ -1047,7 +1100,8 @@ our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)};
|
|||||||
our $declaration_macros = qr{(?x:
|
our $declaration_macros = qr{(?x:
|
||||||
(?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(|
|
(?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(|
|
||||||
(?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(|
|
(?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(|
|
||||||
(?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
|
(?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(|
|
||||||
|
(?:$Storage\s+)?(?:XA_STATE|XA_STATE_ORDER)\s*\(
|
||||||
)};
|
)};
|
||||||
|
|
||||||
our %allow_repeated_words = (
|
our %allow_repeated_words = (
|
||||||
@@ -1223,6 +1277,7 @@ sub git_commit_info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$chk_signoff = 0 if ($file);
|
$chk_signoff = 0 if ($file);
|
||||||
|
$chk_fixes_tag = 0 if ($file);
|
||||||
|
|
||||||
my @rawlines = ();
|
my @rawlines = ();
|
||||||
my @lines = ();
|
my @lines = ();
|
||||||
@@ -2725,6 +2780,9 @@ sub process {
|
|||||||
|
|
||||||
our $clean = 1;
|
our $clean = 1;
|
||||||
my $signoff = 0;
|
my $signoff = 0;
|
||||||
|
my $fixes_tag = 0;
|
||||||
|
my $is_revert = 0;
|
||||||
|
my $needs_fixes_tag = "";
|
||||||
my $author = '';
|
my $author = '';
|
||||||
my $authorsignoff = 0;
|
my $authorsignoff = 0;
|
||||||
my $author_sob = '';
|
my $author_sob = '';
|
||||||
@@ -2957,7 +3015,7 @@ sub process {
|
|||||||
|
|
||||||
if ($realfile =~ m@^include/asm/@) {
|
if ($realfile =~ m@^include/asm/@) {
|
||||||
ERROR("MODIFIED_INCLUDE_ASM",
|
ERROR("MODIFIED_INCLUDE_ASM",
|
||||||
"do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
|
"do not modify files in include/asm, change architecture specific files in arch/<architecture>/include/asm\n" . "$here$rawline\n");
|
||||||
}
|
}
|
||||||
$found_file = 1;
|
$found_file = 1;
|
||||||
}
|
}
|
||||||
@@ -3252,17 +3310,79 @@ sub process {
|
|||||||
if ($sign_off =~ /^co-developed-by:$/i) {
|
if ($sign_off =~ /^co-developed-by:$/i) {
|
||||||
if ($email eq $author) {
|
if ($email eq $author) {
|
||||||
WARN("BAD_SIGN_OFF",
|
WARN("BAD_SIGN_OFF",
|
||||||
"Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline);
|
"Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . $herecurr);
|
||||||
}
|
}
|
||||||
if (!defined $lines[$linenr]) {
|
if (!defined $lines[$linenr]) {
|
||||||
WARN("BAD_SIGN_OFF",
|
WARN("BAD_SIGN_OFF",
|
||||||
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
|
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . $herecurr);
|
||||||
} elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
|
} elsif ($rawlines[$linenr] !~ /^signed-off-by:\s*(.*)/i) {
|
||||||
WARN("BAD_SIGN_OFF",
|
WARN("BAD_SIGN_OFF",
|
||||||
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
|
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . $herecurr . $rawlines[$linenr] . "\n");
|
||||||
} elsif ($1 ne $email) {
|
} elsif ($1 ne $email) {
|
||||||
WARN("BAD_SIGN_OFF",
|
WARN("BAD_SIGN_OFF",
|
||||||
"Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
|
"Co-developed-by and Signed-off-by: name/email do not match\n" . $herecurr . $rawlines[$linenr] . "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# check if Reported-by: is followed by a Closes: tag
|
||||||
|
if ($sign_off =~ /^reported(?:|-and-tested)-by:$/i) {
|
||||||
|
if (!defined $lines[$linenr]) {
|
||||||
|
WARN("BAD_REPORTED_BY_LINK",
|
||||||
|
"Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . "\n");
|
||||||
|
} elsif ($rawlines[$linenr] !~ /^closes:\s*/i) {
|
||||||
|
WARN("BAD_REPORTED_BY_LINK",
|
||||||
|
"Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . $rawlines[$linenr] . "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# These indicate a bug fix
|
||||||
|
if (!$in_header_lines && !$is_patch &&
|
||||||
|
$line =~ /^This reverts commit/) {
|
||||||
|
$is_revert = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$in_header_lines && !$is_patch &&
|
||||||
|
$line =~ /((?:(?:BUG: K.|UB)SAN: |Call Trace:|stable\@|syzkaller))/) {
|
||||||
|
$needs_fixes_tag = $1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check Fixes: styles is correct
|
||||||
|
if (!$in_header_lines &&
|
||||||
|
$line =~ /^\s*(fixes:?)\s*(?:commit\s*)?([0-9a-f]{5,40})(?:\s*($balanced_parens))?/i) {
|
||||||
|
my $tag = $1;
|
||||||
|
my $orig_commit = $2;
|
||||||
|
my $title;
|
||||||
|
my $title_has_quotes = 0;
|
||||||
|
$fixes_tag = 1;
|
||||||
|
if (defined $3) {
|
||||||
|
# Always strip leading/trailing parens then double quotes if existing
|
||||||
|
$title = substr($3, 1, -1);
|
||||||
|
if ($title =~ /^".*"$/) {
|
||||||
|
$title = substr($title, 1, -1);
|
||||||
|
$title_has_quotes = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$title = "commit title"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
my $tag_case = not ($tag eq "Fixes:");
|
||||||
|
my $tag_space = not ($line =~ /^fixes:? [0-9a-f]{5,40} ($balanced_parens)/i);
|
||||||
|
|
||||||
|
my $id_length = not ($orig_commit =~ /^[0-9a-f]{12,40}$/i);
|
||||||
|
my $id_case = not ($orig_commit !~ /[A-F]/);
|
||||||
|
|
||||||
|
my $id = "0123456789ab";
|
||||||
|
my ($cid, $ctitle) = git_commit_info($orig_commit, $id,
|
||||||
|
$title);
|
||||||
|
|
||||||
|
if (defined($cid) && ($ctitle ne $title || $tag_case || $tag_space || $id_length || $id_case || !$title_has_quotes)) {
|
||||||
|
my $fixed = "Fixes: $cid (\"$ctitle\")";
|
||||||
|
if (WARN("BAD_FIXES_TAG",
|
||||||
|
"Please use correct Fixes: style 'Fixes: <12+ chars of sha1> (\"<title line>\")' - ie: '$fixed'\n" . $herecurr) &&
|
||||||
|
$fix) {
|
||||||
|
$fixed[$fixlinenr] = $fixed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3300,13 +3420,13 @@ sub process {
|
|||||||
length($line) > 75 &&
|
length($line) > 75 &&
|
||||||
!($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ ||
|
!($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ ||
|
||||||
# file delta changes
|
# file delta changes
|
||||||
$line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
|
$line =~ /^\s*(?:[\w\.\-\+]*\/)++[\w\.\-\+]+:/ ||
|
||||||
# filename then :
|
# filename then :
|
||||||
$line =~ /^\s*(?:Fixes:|Link:|$signature_tags)/i ||
|
$line =~ /^\s*(?:Fixes:|$link_tags_search|$signature_tags)/i ||
|
||||||
# A Fixes: or Link: line or signature tag line
|
# A Fixes:, link or signature tag line
|
||||||
$commit_log_possible_stack_dump)) {
|
$commit_log_possible_stack_dump)) {
|
||||||
WARN("COMMIT_LOG_LONG_LINE",
|
WARN("COMMIT_LOG_LONG_LINE",
|
||||||
"Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
|
"Prefer a maximum 75 chars per line (possible unwrapped commit description?)\n" . $herecurr);
|
||||||
$commit_log_long_line = 1;
|
$commit_log_long_line = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3316,6 +3436,29 @@ sub process {
|
|||||||
$commit_log_possible_stack_dump = 0;
|
$commit_log_possible_stack_dump = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check for odd tags before a URI/URL
|
||||||
|
if ($in_commit_log &&
|
||||||
|
$line =~ /^\s*(\w+:)\s*http/ && $1 !~ /^$link_tags_search$/) {
|
||||||
|
if ($1 =~ /^v(?:ersion)?\d+/i) {
|
||||||
|
WARN("COMMIT_LOG_VERSIONING",
|
||||||
|
"Patch version information should be after the --- line\n" . $herecurr);
|
||||||
|
} else {
|
||||||
|
WARN("COMMIT_LOG_USE_LINK",
|
||||||
|
"Unknown link reference '$1', use $link_tags_print instead\n" . $herecurr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for misuse of the link tags
|
||||||
|
if ($in_commit_log &&
|
||||||
|
$line =~ /^\s*(\w+:)\s*(\S+)/) {
|
||||||
|
my $tag = $1;
|
||||||
|
my $value = $2;
|
||||||
|
if ($tag =~ /^$link_tags_search$/ && $value !~ m{^https?://}) {
|
||||||
|
WARN("COMMIT_LOG_WRONG_LINK",
|
||||||
|
"'$tag' should be followed by a public http(s) link\n" . $herecurr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Check for lines starting with a #
|
# Check for lines starting with a #
|
||||||
if ($in_commit_log && $line =~ /^#/) {
|
if ($in_commit_log && $line =~ /^#/) {
|
||||||
if (WARN("COMMIT_COMMENT_SYMBOL",
|
if (WARN("COMMIT_COMMENT_SYMBOL",
|
||||||
@@ -3401,6 +3544,12 @@ sub process {
|
|||||||
$last_git_commit_id_linenr = $linenr if ($line =~ /\bcommit\s*$/i);
|
$last_git_commit_id_linenr = $linenr if ($line =~ /\bcommit\s*$/i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check for mailing list archives other than lore.kernel.org
|
||||||
|
if ($rawline =~ m{http.*\b$obsolete_archives}) {
|
||||||
|
WARN("PREFER_LORE_ARCHIVE",
|
||||||
|
"Use lore.kernel.org archive links when possible - see https://lore.kernel.org/lists.html\n" . $herecurr);
|
||||||
|
}
|
||||||
|
|
||||||
# Check for added, moved or deleted files
|
# Check for added, moved or deleted files
|
||||||
if (!$reported_maintainer_file && !$in_commit_log &&
|
if (!$reported_maintainer_file && !$in_commit_log &&
|
||||||
($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
|
($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
|
||||||
@@ -3482,9 +3631,10 @@ sub process {
|
|||||||
# Check for various typo / spelling mistakes
|
# Check for various typo / spelling mistakes
|
||||||
if (defined($misspellings) &&
|
if (defined($misspellings) &&
|
||||||
($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
|
($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
|
||||||
while ($rawline =~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi) {
|
my $rawline_utf8 = decode("utf8", $rawline);
|
||||||
|
while ($rawline_utf8 =~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi) {
|
||||||
my $typo = $1;
|
my $typo = $1;
|
||||||
my $blank = copy_spacing($rawline);
|
my $blank = copy_spacing($rawline_utf8);
|
||||||
my $ptr = substr($blank, 0, $-[1]) . "^" x length($typo);
|
my $ptr = substr($blank, 0, $-[1]) . "^" x length($typo);
|
||||||
my $hereptr = "$hereline$ptr\n";
|
my $hereptr = "$hereline$ptr\n";
|
||||||
my $typo_fix = $spelling_fix{lc($typo)};
|
my $typo_fix = $spelling_fix{lc($typo)};
|
||||||
@@ -3607,47 +3757,47 @@ sub process {
|
|||||||
# Kconfig supports named choices), so use a word boundary
|
# Kconfig supports named choices), so use a word boundary
|
||||||
# (\b) rather than a whitespace character (\s)
|
# (\b) rather than a whitespace character (\s)
|
||||||
$line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
|
$line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
|
||||||
my $length = 0;
|
my $ln = $linenr;
|
||||||
my $cnt = $realcnt;
|
my $needs_help = 0;
|
||||||
my $ln = $linenr + 1;
|
my $has_help = 0;
|
||||||
my $f;
|
my $help_length = 0;
|
||||||
my $is_start = 0;
|
while (defined $lines[$ln]) {
|
||||||
my $is_end = 0;
|
my $f = $lines[$ln++];
|
||||||
for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) {
|
|
||||||
$f = $lines[$ln - 1];
|
|
||||||
$cnt-- if ($lines[$ln - 1] !~ /^-/);
|
|
||||||
$is_end = $lines[$ln - 1] =~ /^\+/;
|
|
||||||
|
|
||||||
next if ($f =~ /^-/);
|
next if ($f =~ /^-/);
|
||||||
last if (!$file && $f =~ /^\@\@/);
|
last if ($f !~ /^[\+ ]/); # !patch context
|
||||||
|
|
||||||
if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
|
if ($f =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
|
||||||
$is_start = 1;
|
$needs_help = 1;
|
||||||
} elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
|
next;
|
||||||
$length = -1;
|
}
|
||||||
|
if ($f =~ /^\+\s*help\s*$/) {
|
||||||
|
$has_help = 1;
|
||||||
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
$f =~ s/^.//;
|
$f =~ s/^.//; # strip patch context [+ ]
|
||||||
$f =~ s/#.*//;
|
$f =~ s/#.*//; # strip # directives
|
||||||
$f =~ s/^\s+//;
|
$f =~ s/^\s+//; # strip leading blanks
|
||||||
next if ($f =~ /^$/);
|
next if ($f =~ /^$/); # skip blank lines
|
||||||
|
|
||||||
|
# At the end of this Kconfig block:
|
||||||
# This only checks context lines in the patch
|
# This only checks context lines in the patch
|
||||||
# and so hopefully shouldn't trigger false
|
# and so hopefully shouldn't trigger false
|
||||||
# positives, even though some of these are
|
# positives, even though some of these are
|
||||||
# common words in help texts
|
# common words in help texts
|
||||||
if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice|
|
if ($f =~ /^(?:config|menuconfig|choice|endchoice|
|
||||||
if|endif|menu|endmenu|source)\b/x) {
|
if|endif|menu|endmenu|source)\b/x) {
|
||||||
$is_end = 1;
|
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
$length++;
|
$help_length++ if ($has_help);
|
||||||
}
|
}
|
||||||
if ($is_start && $is_end && $length < $min_conf_desc_length) {
|
if ($needs_help &&
|
||||||
|
$help_length < $min_conf_desc_length) {
|
||||||
|
my $stat_real = get_stat_real($linenr, $ln - 1);
|
||||||
WARN("CONFIG_DESCRIPTION",
|
WARN("CONFIG_DESCRIPTION",
|
||||||
"please write a paragraph that describes the config symbol fully\n" . $herecurr);
|
"please write a help paragraph that fully describes the config symbol with at least $min_conf_desc_length lines\n" . "$here\n$stat_real\n");
|
||||||
}
|
}
|
||||||
#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# check MAINTAINERS entries
|
# check MAINTAINERS entries
|
||||||
@@ -3690,20 +3840,6 @@ sub process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) &&
|
|
||||||
($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) {
|
|
||||||
my $flag = $1;
|
|
||||||
my $replacement = {
|
|
||||||
'EXTRA_AFLAGS' => 'asflags-y',
|
|
||||||
'EXTRA_CFLAGS' => 'ccflags-y',
|
|
||||||
'EXTRA_CPPFLAGS' => 'cppflags-y',
|
|
||||||
'EXTRA_LDFLAGS' => 'ldflags-y',
|
|
||||||
};
|
|
||||||
|
|
||||||
WARN("DEPRECATED_VARIABLE",
|
|
||||||
"Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag});
|
|
||||||
}
|
|
||||||
|
|
||||||
# check for DT compatible documentation
|
# check for DT compatible documentation
|
||||||
if (defined $root &&
|
if (defined $root &&
|
||||||
(($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) ||
|
(($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) ||
|
||||||
@@ -3735,6 +3871,18 @@ sub process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check for RGMII phy-mode with delay on PCB
|
||||||
|
if ($realfile =~ /\.(dts|dtsi|dtso)$/ &&
|
||||||
|
$line =~ /^\+\s*(phy-mode|phy-connection-type)\s*=\s*"/ &&
|
||||||
|
!ctx_has_comment($first_line, $linenr)) {
|
||||||
|
my $prop = $1;
|
||||||
|
my $mode = get_quoted_string($line, $rawline);
|
||||||
|
if ($mode =~ /^"rgmii(?:|-rxid|-txid)"$/) {
|
||||||
|
WARN("UNCOMMENTED_RGMII_MODE",
|
||||||
|
"$prop $mode without comment -- delays on the PCB should be described, otherwise use \"rgmii-id\"\n" . $herecurr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# check for using SPDX license tag at beginning of files
|
# check for using SPDX license tag at beginning of files
|
||||||
if ($realline == $checklicenseline) {
|
if ($realline == $checklicenseline) {
|
||||||
if ($rawline =~ /^[ \+]\s*\#\!\s*\//) {
|
if ($rawline =~ /^[ \+]\s*\#\!\s*\//) {
|
||||||
@@ -3743,7 +3891,7 @@ sub process {
|
|||||||
my $comment = "";
|
my $comment = "";
|
||||||
if ($realfile =~ /\.(h|s|S)$/) {
|
if ($realfile =~ /\.(h|s|S)$/) {
|
||||||
$comment = '/*';
|
$comment = '/*';
|
||||||
} elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
|
} elsif ($realfile =~ /\.(c|rs|dts|dtsi)$/) {
|
||||||
$comment = '//';
|
$comment = '//';
|
||||||
} elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) {
|
} elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) {
|
||||||
$comment = '#';
|
$comment = '#';
|
||||||
@@ -3770,7 +3918,7 @@ sub process {
|
|||||||
"'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
|
"'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
|
||||||
}
|
}
|
||||||
if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
|
if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
|
||||||
not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) {
|
$spdx_license !~ /GPL-2\.0(?:-only)? OR BSD-2-Clause/) {
|
||||||
my $msg_level = \&WARN;
|
my $msg_level = \&WARN;
|
||||||
$msg_level = \&CHK if ($file);
|
$msg_level = \&CHK if ($file);
|
||||||
if (&{$msg_level}("SPDX_LICENSE_TAG",
|
if (&{$msg_level}("SPDX_LICENSE_TAG",
|
||||||
@@ -3780,18 +3928,23 @@ sub process {
|
|||||||
$fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
|
$fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($realfile =~ m@^include/dt-bindings/@ &&
|
||||||
|
$spdx_license !~ /GPL-2\.0(?:-only)? OR \S+/) {
|
||||||
|
WARN("SPDX_LICENSE_TAG",
|
||||||
|
"DT binding headers should be licensed (GPL-2.0-only OR .*)\n" . $herecurr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# check for embedded filenames
|
# check for embedded filenames
|
||||||
if ($rawline =~ /^\+.*\Q$realfile\E/) {
|
if ($rawline =~ /^\+.*\b\Q$realfile\E\b/) {
|
||||||
WARN("EMBEDDED_FILENAME",
|
WARN("EMBEDDED_FILENAME",
|
||||||
"It's generally not useful to have the filename in the file\n" . $herecurr);
|
"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
|
# check we are in a valid source file if not then ignore this hunk
|
||||||
next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts|env)$/);
|
next if ($realfile !~ /\.(h|c|rs|s|S|sh|dtsi|dts|env)$/);
|
||||||
|
|
||||||
# check for using SPDX-License-Identifier on the wrong line number
|
# check for using SPDX-License-Identifier on the wrong line number
|
||||||
if ($realline != $checklicenseline &&
|
if ($realline != $checklicenseline &&
|
||||||
@@ -3857,7 +4010,7 @@ sub process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($msg_type ne "" &&
|
if ($msg_type ne "" &&
|
||||||
(show_type("LONG_LINE") || show_type($msg_type))) {
|
show_type("LONG_LINE") && show_type($msg_type)) {
|
||||||
my $msg_level = \&WARN;
|
my $msg_level = \&WARN;
|
||||||
$msg_level = \&CHK if ($file);
|
$msg_level = \&CHK if ($file);
|
||||||
&{$msg_level}($msg_type,
|
&{$msg_level}($msg_type,
|
||||||
@@ -3878,7 +4031,7 @@ sub process {
|
|||||||
if ($realfile =~ /\.S$/ &&
|
if ($realfile =~ /\.S$/ &&
|
||||||
$line =~ /^\+\s*(?:[A-Z]+_)?SYM_[A-Z]+_(?:START|END)(?:_[A-Z_]+)?\s*\(\s*\.L/) {
|
$line =~ /^\+\s*(?:[A-Z]+_)?SYM_[A-Z]+_(?:START|END)(?:_[A-Z_]+)?\s*\(\s*\.L/) {
|
||||||
WARN("AVOID_L_PREFIX",
|
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-annotations.rst\n" . $herecurr);
|
"Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/core-api/asm-annotations.rst\n" . $herecurr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($u_boot) {
|
if ($u_boot) {
|
||||||
@@ -4000,16 +4153,6 @@ sub process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Block comment styles
|
|
||||||
# Networking with an initial /*
|
|
||||||
if ($realfile =~ m@^(drivers/net/|net/)@ &&
|
|
||||||
$prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
|
|
||||||
$rawline =~ /^\+[ \t]*\*/ &&
|
|
||||||
$realline > 3) { # Do not warn about the initial copyright comment block after SPDX-License-Identifier
|
|
||||||
WARN("NETWORKING_BLOCK_COMMENT_STYLE",
|
|
||||||
"networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Block comments use * on subsequent lines
|
# Block comments use * on subsequent lines
|
||||||
if ($prevline =~ /$;[ \t]*$/ && #ends in comment
|
if ($prevline =~ /$;[ \t]*$/ && #ends in comment
|
||||||
$prevrawline =~ /^\+.*?\/\*/ && #starting /*
|
$prevrawline =~ /^\+.*?\/\*/ && #starting /*
|
||||||
@@ -4058,7 +4201,7 @@ sub process {
|
|||||||
if ($prevline =~ /^[\+ ]};?\s*$/ &&
|
if ($prevline =~ /^[\+ ]};?\s*$/ &&
|
||||||
$line =~ /^\+/ &&
|
$line =~ /^\+/ &&
|
||||||
!($line =~ /^\+\s*$/ ||
|
!($line =~ /^\+\s*$/ ||
|
||||||
$line =~ /^\+\s*EXPORT_SYMBOL/ ||
|
$line =~ /^\+\s*(?:EXPORT_SYMBOL|early_param|ALLOW_ERROR_INJECTION)/ ||
|
||||||
$line =~ /^\+\s*MODULE_/i ||
|
$line =~ /^\+\s*MODULE_/i ||
|
||||||
$line =~ /^\+\s*\#\s*(?:end|elif|else)/ ||
|
$line =~ /^\+\s*\#\s*(?:end|elif|else)/ ||
|
||||||
$line =~ /^\+[a-z_]*init/ ||
|
$line =~ /^\+[a-z_]*init/ ||
|
||||||
@@ -4826,12 +4969,12 @@ sub process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# avoid BUG() or BUG_ON()
|
# do not use BUG() or variants
|
||||||
if ($line =~ /\b(?:BUG|BUG_ON)\b/) {
|
if ($line =~ /\b(?!AA_|BUILD_|IDA_|KVM_|RWLOCK_|snd_|SPIN_)(?:[a-zA-Z_]*_)?BUG(?:_ON)?(?:_[A-Z_]+)?\s*\(/) {
|
||||||
my $msg_level = \&WARN;
|
my $msg_level = \&WARN;
|
||||||
$msg_level = \&CHK if ($file);
|
$msg_level = \&CHK if ($file);
|
||||||
&{$msg_level}("AVOID_BUG",
|
&{$msg_level}("AVOID_BUG",
|
||||||
"Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
|
"Do not crash the kernel unless it is absolutely unavoidable--use WARN_ON_ONCE() plus recovery code (if feasible) instead of BUG() or variants\n" . $herecurr);
|
||||||
}
|
}
|
||||||
|
|
||||||
# avoid LINUX_VERSION_CODE
|
# avoid LINUX_VERSION_CODE
|
||||||
@@ -5052,7 +5195,7 @@ sub process {
|
|||||||
if|for|while|switch|return|case|
|
if|for|while|switch|return|case|
|
||||||
volatile|__volatile__|
|
volatile|__volatile__|
|
||||||
__attribute__|format|__extension__|
|
__attribute__|format|__extension__|
|
||||||
asm|__asm__)$/x)
|
asm|__asm__|scoped_guard)$/x)
|
||||||
{
|
{
|
||||||
# cpp #define statements have non-optional spaces, ie
|
# cpp #define statements have non-optional spaces, ie
|
||||||
# if there is a space between the name and the open
|
# if there is a space between the name and the open
|
||||||
@@ -5513,9 +5656,9 @@ sub process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# check for unnecessary parentheses around comparisons in if uses
|
# check for unnecessary parentheses around comparisons
|
||||||
# when !drivers/staging or command-line uses --strict
|
# except in drivers/staging
|
||||||
if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) &&
|
if (($realfile !~ m@^(?:drivers/staging/)@) &&
|
||||||
$perl_version_ok && defined($stat) &&
|
$perl_version_ok && defined($stat) &&
|
||||||
$stat =~ /(^.\s*if\s*($balanced_parens))/) {
|
$stat =~ /(^.\s*if\s*($balanced_parens))/) {
|
||||||
my $if_stat = $1;
|
my $if_stat = $1;
|
||||||
@@ -5683,6 +5826,7 @@ sub process {
|
|||||||
defined($stat) && defined($cond) &&
|
defined($stat) && defined($cond) &&
|
||||||
$line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
|
$line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
|
||||||
my ($s, $c) = ($stat, $cond);
|
my ($s, $c) = ($stat, $cond);
|
||||||
|
my $fixed_assign_in_if = 0;
|
||||||
|
|
||||||
if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
|
if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
|
||||||
if (ERROR("ASSIGN_IN_IF",
|
if (ERROR("ASSIGN_IN_IF",
|
||||||
@@ -5707,6 +5851,7 @@ sub process {
|
|||||||
$newline .= ')';
|
$newline .= ')';
|
||||||
$newline .= " {" if (defined($brace));
|
$newline .= " {" if (defined($brace));
|
||||||
fix_insert_line($fixlinenr + 1, $newline);
|
fix_insert_line($fixlinenr + 1, $newline);
|
||||||
|
$fixed_assign_in_if = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5730,8 +5875,20 @@ sub process {
|
|||||||
$stat_real = "[...]\n$stat_real";
|
$stat_real = "[...]\n$stat_real";
|
||||||
}
|
}
|
||||||
|
|
||||||
ERROR("TRAILING_STATEMENTS",
|
if (ERROR("TRAILING_STATEMENTS",
|
||||||
"trailing statements should be on next line\n" . $herecurr . $stat_real);
|
"trailing statements should be on next line\n" . $herecurr . $stat_real) &&
|
||||||
|
!$fixed_assign_in_if &&
|
||||||
|
$cond_lines == 0 &&
|
||||||
|
$fix && $perl_version_ok &&
|
||||||
|
$fixed[$fixlinenr] =~ /^\+(\s*)((?:if|while|for)\s*$balanced_parens)\s*(.*)$/) {
|
||||||
|
my $indent = $1;
|
||||||
|
my $test = $2;
|
||||||
|
my $rest = rtrim($4);
|
||||||
|
if ($rest =~ /;$/) {
|
||||||
|
$fixed[$fixlinenr] = "\+$indent$test";
|
||||||
|
fix_insert_line($fixlinenr + 1, "$indent\t$rest");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5829,16 +5986,20 @@ sub process {
|
|||||||
#CamelCase
|
#CamelCase
|
||||||
if ($var !~ /^$Constant$/ &&
|
if ($var !~ /^$Constant$/ &&
|
||||||
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
|
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
|
||||||
|
#Ignore C keywords
|
||||||
|
$var !~ /^_Generic$/ &&
|
||||||
#Ignore some autogenerated defines and enum values
|
#Ignore some autogenerated defines and enum values
|
||||||
$var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ &&
|
$var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ &&
|
||||||
#Ignore Page<foo> variants
|
#Ignore Page<foo> variants
|
||||||
$var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
|
$var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
|
||||||
|
#Ignore ETHTOOL_LINK_MODE_<foo> variants
|
||||||
|
$var !~ /^ETHTOOL_LINK_MODE_/ &&
|
||||||
#Ignore SI style variants like nS, mV and dB
|
#Ignore SI style variants like nS, mV and dB
|
||||||
#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
|
#(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_]+)?$/ &&
|
$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
|
#Ignore some three character SI units explicitly, like MiB and KHz
|
||||||
$var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
|
$var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
|
||||||
while ($var =~ m{($Ident)}g) {
|
while ($var =~ m{\b($Ident)}g) {
|
||||||
my $word = $1;
|
my $word = $1;
|
||||||
next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
|
next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
|
||||||
if ($check) {
|
if ($check) {
|
||||||
@@ -5888,9 +6049,9 @@ sub process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# multi-statement macros should be enclosed in a do while loop, grab the
|
# Usually multi-statement macros should be enclosed in a do {} while
|
||||||
# first statement and ensure its the whole macro if its not enclosed
|
# (0) loop. Grab the first statement and ensure its the whole macro
|
||||||
# in a known good container
|
# if its not enclosed in a known good container
|
||||||
if ($realfile !~ m@/vmlinux.lds.h$@ &&
|
if ($realfile !~ m@/vmlinux.lds.h$@ &&
|
||||||
$line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
|
$line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
|
||||||
my $ln = $linenr;
|
my $ln = $linenr;
|
||||||
@@ -5943,10 +6104,13 @@ sub process {
|
|||||||
|
|
||||||
my $exceptions = qr{
|
my $exceptions = qr{
|
||||||
$Declare|
|
$Declare|
|
||||||
|
# named exceptions
|
||||||
module_param_named|
|
module_param_named|
|
||||||
MODULE_PARM_DESC|
|
MODULE_PARM_DESC|
|
||||||
DECLARE_PER_CPU|
|
DECLARE_PER_CPU|
|
||||||
DEFINE_PER_CPU|
|
DEFINE_PER_CPU|
|
||||||
|
static_assert|
|
||||||
|
# declaration primitives
|
||||||
__typeof__\(|
|
__typeof__\(|
|
||||||
union|
|
union|
|
||||||
struct|
|
struct|
|
||||||
@@ -5968,6 +6132,7 @@ sub process {
|
|||||||
$dstat !~ /$exceptions/ &&
|
$dstat !~ /$exceptions/ &&
|
||||||
$dstat !~ /^\.$Ident\s*=/ && # .foo =
|
$dstat !~ /^\.$Ident\s*=/ && # .foo =
|
||||||
$dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo
|
$dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo
|
||||||
|
$dstat !~ /^case\b/ && # case ...
|
||||||
$dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...)
|
$dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...)
|
||||||
$dstat !~ /^while\s*$Constant\s*$Constant\s*$/ && # while (...) {...}
|
$dstat !~ /^while\s*$Constant\s*$Constant\s*$/ && # while (...) {...}
|
||||||
$dstat !~ /^for\s*$Constant$/ && # for (...)
|
$dstat !~ /^for\s*$Constant$/ && # for (...)
|
||||||
@@ -5980,11 +6145,11 @@ sub process {
|
|||||||
ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
|
ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
|
||||||
"Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");
|
"Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");
|
||||||
} elsif ($dstat =~ /;/) {
|
} elsif ($dstat =~ /;/) {
|
||||||
ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
|
WARN("MULTISTATEMENT_MACRO_USE_DO_WHILE",
|
||||||
"Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
|
"Non-declarative macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx\nBUT SEE:\n$DO_WHILE_0_ADVICE");
|
||||||
} else {
|
} else {
|
||||||
ERROR("COMPLEX_MACRO",
|
ERROR("COMPLEX_MACRO",
|
||||||
"Macros with complex values should be enclosed in parentheses\n" . "$herectx");
|
"Macros with complex values should be enclosed in parentheses\n" . "$herectx\nBUT SEE:\n$DO_WHILE_0_ADVICE");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6026,6 +6191,12 @@ sub process {
|
|||||||
CHK("MACRO_ARG_PRECEDENCE",
|
CHK("MACRO_ARG_PRECEDENCE",
|
||||||
"Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");
|
"Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check if this is an unused argument
|
||||||
|
if ($define_stmt !~ /\b$arg\b/ && $define_stmt) {
|
||||||
|
WARN("MACRO_ARG_UNUSED",
|
||||||
|
"Argument '$arg' is not used in function-like macro\n" . "$herectx");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# check for macros with flow control, but without ## concatenation
|
# check for macros with flow control, but without ## concatenation
|
||||||
@@ -6040,6 +6211,9 @@ sub process {
|
|||||||
|
|
||||||
# check for line continuations outside of #defines, preprocessor #, and asm
|
# check for line continuations outside of #defines, preprocessor #, and asm
|
||||||
|
|
||||||
|
} elsif ($realfile =~ m@/vmlinux.lds.h$@) {
|
||||||
|
$line =~ s/(\w+)/$maybe_linker_symbol{$1}++/ge;
|
||||||
|
#print "REAL: $realfile\nln: $line\nkeys:", sort keys %maybe_linker_symbol;
|
||||||
} else {
|
} else {
|
||||||
if ($prevline !~ /^..*\\$/ &&
|
if ($prevline !~ /^..*\\$/ &&
|
||||||
$line !~ /^\+\s*\#.*\\$/ && # preprocessor
|
$line !~ /^\+\s*\#.*\\$/ && # preprocessor
|
||||||
@@ -6566,11 +6740,11 @@ sub process {
|
|||||||
# ignore udelay's < 10, however
|
# ignore udelay's < 10, however
|
||||||
if (! ($delay < 10) ) {
|
if (! ($delay < 10) ) {
|
||||||
CHK("USLEEP_RANGE",
|
CHK("USLEEP_RANGE",
|
||||||
"usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
|
"usleep_range is preferred over udelay; see function description of usleep_range() and udelay().\n" . $herecurr);
|
||||||
}
|
}
|
||||||
if ($delay > 2000) {
|
if ($delay > 2000) {
|
||||||
WARN("LONG_UDELAY",
|
WARN("LONG_UDELAY",
|
||||||
"long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr);
|
"long udelay - prefer mdelay; see function description of mdelay().\n" . $herecurr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6578,7 +6752,7 @@ sub process {
|
|||||||
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
|
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
|
||||||
if ($1 < 20) {
|
if ($1 < 20) {
|
||||||
WARN("MSLEEP",
|
WARN("MSLEEP",
|
||||||
"msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
|
"msleep < 20ms can sleep for up to 20ms; see function description of msleep().\n" . $herecurr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6886,7 +7060,7 @@ sub process {
|
|||||||
($extension eq "f" &&
|
($extension eq "f" &&
|
||||||
defined $qualifier && $qualifier !~ /^w/) ||
|
defined $qualifier && $qualifier !~ /^w/) ||
|
||||||
($extension eq "4" &&
|
($extension eq "4" &&
|
||||||
defined $qualifier && $qualifier !~ /^cc/)) {
|
defined $qualifier && $qualifier !~ /^c(?:[hlbc]|hR)$/)) {
|
||||||
$bad_specifier = $specifier;
|
$bad_specifier = $specifier;
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
@@ -6900,15 +7074,19 @@ sub process {
|
|||||||
}
|
}
|
||||||
if ($bad_specifier ne "") {
|
if ($bad_specifier ne "") {
|
||||||
my $stat_real = get_stat_real($linenr, $lc);
|
my $stat_real = get_stat_real($linenr, $lc);
|
||||||
|
my $msg_level = \&WARN;
|
||||||
my $ext_type = "Invalid";
|
my $ext_type = "Invalid";
|
||||||
my $use = "";
|
my $use = "";
|
||||||
if ($bad_specifier =~ /p[Ff]/) {
|
if ($bad_specifier =~ /p[Ff]/) {
|
||||||
$use = " - use %pS instead";
|
$use = " - use %pS instead";
|
||||||
$use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
|
$use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
|
||||||
|
} elsif ($bad_specifier =~ /pA/) {
|
||||||
|
$use = " - '%pA' is only intended to be used from Rust code";
|
||||||
|
$msg_level = \&ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
WARN("VSPRINTF_POINTER_EXTENSION",
|
&{$msg_level}("VSPRINTF_POINTER_EXTENSION",
|
||||||
"$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
|
"$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6973,6 +7151,25 @@ sub process {
|
|||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
|
|
||||||
|
# ethtool_sprintf uses that should likely be ethtool_puts
|
||||||
|
if ($line =~ /\bethtool_sprintf\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
|
||||||
|
if (WARN("PREFER_ETHTOOL_PUTS",
|
||||||
|
"Prefer ethtool_puts over ethtool_sprintf with only two arguments\n" . $herecurr) &&
|
||||||
|
$fix) {
|
||||||
|
$fixed[$fixlinenr] =~ s/\bethtool_sprintf\s*\(\s*($FuncArg)\s*,\s*($FuncArg)/ethtool_puts($1, $7)/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# use $rawline because $line loses %s via sanitization and thus we can't match against it.
|
||||||
|
if ($rawline =~ /\bethtool_sprintf\s*\(\s*$FuncArg\s*,\s*\"\%s\"\s*,\s*$FuncArg\s*\)/) {
|
||||||
|
if (WARN("PREFER_ETHTOOL_PUTS",
|
||||||
|
"Prefer ethtool_puts over ethtool_sprintf with standalone \"%s\" specifier\n" . $herecurr) &&
|
||||||
|
$fix) {
|
||||||
|
$fixed[$fixlinenr] =~ s/\bethtool_sprintf\s*\(\s*($FuncArg)\s*,\s*"\%s"\s*,\s*($FuncArg)/ethtool_puts($1, $7)/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# typecasts on min/max could be min_t/max_t
|
# typecasts on min/max could be min_t/max_t
|
||||||
if ($perl_version_ok &&
|
if ($perl_version_ok &&
|
||||||
defined $stat &&
|
defined $stat &&
|
||||||
@@ -7005,11 +7202,11 @@ sub process {
|
|||||||
my $max = $7;
|
my $max = $7;
|
||||||
if ($min eq $max) {
|
if ($min eq $max) {
|
||||||
WARN("USLEEP_RANGE",
|
WARN("USLEEP_RANGE",
|
||||||
"usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
|
"usleep_range should not use min == max args; see function description of usleep_range().\n" . "$here\n$stat\n");
|
||||||
} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
|
} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
|
||||||
$min > $max) {
|
$min > $max) {
|
||||||
WARN("USLEEP_RANGE",
|
WARN("USLEEP_RANGE",
|
||||||
"usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
|
"usleep_range args reversed, use min then max; see function description of usleep_range().\n" . "$here\n$stat\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7077,6 +7274,21 @@ sub process {
|
|||||||
"arguments for function declarations should follow identifier\n" . $herecurr);
|
"arguments for function declarations should follow identifier\n" . $herecurr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} elsif ($realfile =~ /\.c$/ && defined $stat &&
|
||||||
|
$stat =~ /^\+extern struct\s+(\w+)\s+(\w+)\[\];/)
|
||||||
|
{
|
||||||
|
my ($st_type, $st_name) = ($1, $2);
|
||||||
|
|
||||||
|
for my $s (keys %maybe_linker_symbol) {
|
||||||
|
#print "Linker symbol? $st_name : $s\n";
|
||||||
|
goto LIKELY_LINKER_SYMBOL
|
||||||
|
if $st_name =~ /$s/;
|
||||||
|
}
|
||||||
|
WARN("AVOID_EXTERNS",
|
||||||
|
"found a file-scoped extern type:$st_type name:$st_name in .c file\n"
|
||||||
|
. "is this a linker symbol ?\n" . $herecurr);
|
||||||
|
LIKELY_LINKER_SYMBOL:
|
||||||
|
|
||||||
} elsif ($realfile =~ /\.c$/ && defined $stat &&
|
} elsif ($realfile =~ /\.c$/ && defined $stat &&
|
||||||
$stat =~ /^.\s*extern\s+/)
|
$stat =~ /^.\s*extern\s+/)
|
||||||
{
|
{
|
||||||
@@ -7145,14 +7357,16 @@ sub process {
|
|||||||
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
|
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
|
||||||
}
|
}
|
||||||
|
|
||||||
# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
|
# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_array/kvmalloc_array/kvcalloc/kcalloc
|
||||||
if ($perl_version_ok &&
|
if ($perl_version_ok &&
|
||||||
defined $stat &&
|
defined $stat &&
|
||||||
$stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
|
$stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
|
||||||
my $oldfunc = $3;
|
my $oldfunc = $3;
|
||||||
my $a1 = $4;
|
my $a1 = $4;
|
||||||
my $a2 = $10;
|
my $a2 = $10;
|
||||||
my $newfunc = "kmalloc_array";
|
my $newfunc = "kmalloc_array";
|
||||||
|
$newfunc = "kvmalloc_array" if ($oldfunc eq "kvmalloc");
|
||||||
|
$newfunc = "kvcalloc" if ($oldfunc eq "kvzalloc");
|
||||||
$newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
|
$newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
|
||||||
my $r1 = $a1;
|
my $r1 = $a1;
|
||||||
my $r2 = $a2;
|
my $r2 = $a2;
|
||||||
@@ -7169,7 +7383,7 @@ sub process {
|
|||||||
"Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
|
"Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
|
||||||
$cnt == 1 &&
|
$cnt == 1 &&
|
||||||
$fix) {
|
$fix) {
|
||||||
$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
|
$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7183,7 +7397,7 @@ sub process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# check for alloc argument mismatch
|
# check for alloc argument mismatch
|
||||||
if ($line =~ /\b((?:devm_)?(?:kcalloc|kmalloc_array))\s*\(\s*sizeof\b/) {
|
if ($line =~ /\b((?:devm_)?((?:k|kv)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/) {
|
||||||
WARN("ALLOC_ARRAY_ARGS",
|
WARN("ALLOC_ARRAY_ARGS",
|
||||||
"$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
|
"$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
|
||||||
}
|
}
|
||||||
@@ -7211,8 +7425,8 @@ sub process {
|
|||||||
|
|
||||||
# check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too)
|
# check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too)
|
||||||
if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) {
|
if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) {
|
||||||
ERROR("IS_ENABLED_CONFIG",
|
WARN("IS_ENABLED_CONFIG",
|
||||||
"IS_ENABLED($1) must be used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr);
|
"IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr);
|
||||||
}
|
}
|
||||||
|
|
||||||
# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
|
# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
|
||||||
@@ -7386,6 +7600,16 @@ sub process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check for array definition/declarations that should use flexible arrays instead
|
||||||
|
if ($sline =~ /^[\+ ]\s*\}(?:\s*__packed)?\s*;\s*$/ &&
|
||||||
|
$prevline =~ /^\+\s*(?:\}(?:\s*__packed\s*)?|$Type)\s*$Ident\s*\[\s*(0|1)\s*\]\s*;\s*$/) {
|
||||||
|
if (ERROR("FLEXIBLE_ARRAY",
|
||||||
|
"Use C99 flexible arrays - see https://docs.kernel.org/process/deprecated.html#zero-length-and-one-element-arrays\n" . $hereprev) &&
|
||||||
|
$1 == '0' && $fix) {
|
||||||
|
$fixed[$fixlinenr - 1] =~ s/\[\s*0\s*\]/[]/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# nested likely/unlikely calls
|
# nested likely/unlikely calls
|
||||||
if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
|
if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
|
||||||
WARN("LIKELY_MISUSE",
|
WARN("LIKELY_MISUSE",
|
||||||
@@ -7403,6 +7627,30 @@ sub process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Complain about RCU Tasks Trace used outside of BPF (and of course, RCU).
|
||||||
|
our $rcu_trace_funcs = qr{(?x:
|
||||||
|
rcu_read_lock_trace |
|
||||||
|
rcu_read_lock_trace_held |
|
||||||
|
rcu_read_unlock_trace |
|
||||||
|
call_rcu_tasks_trace |
|
||||||
|
synchronize_rcu_tasks_trace |
|
||||||
|
rcu_barrier_tasks_trace |
|
||||||
|
rcu_request_urgent_qs_task
|
||||||
|
)};
|
||||||
|
our $rcu_trace_paths = qr{(?x:
|
||||||
|
kernel/bpf/ |
|
||||||
|
include/linux/bpf |
|
||||||
|
net/bpf/ |
|
||||||
|
kernel/rcu/ |
|
||||||
|
include/linux/rcu
|
||||||
|
)};
|
||||||
|
if ($line =~ /\b($rcu_trace_funcs)\s*\(/) {
|
||||||
|
if ($realfile !~ m{^$rcu_trace_paths}) {
|
||||||
|
WARN("RCU_TASKS_TRACE",
|
||||||
|
"use of RCU tasks trace is incorrect outside BPF or core RCU code\n" . $herecurr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# check for lockdep_set_novalidate_class
|
# check for lockdep_set_novalidate_class
|
||||||
if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
|
if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
|
||||||
$line =~ /__lockdep_no_validate__\s*\)/ ) {
|
$line =~ /__lockdep_no_validate__\s*\)/ ) {
|
||||||
@@ -7544,6 +7792,13 @@ sub process {
|
|||||||
WARN("MODULE_LICENSE",
|
WARN("MODULE_LICENSE",
|
||||||
"unknown module license " . $extracted_string . "\n" . $herecurr);
|
"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 (\"module: Cure the MODULE_LICENSE \"GPL\" vs. \"GPL v2\" bogosity\")\n" . $herecurr) &&
|
||||||
|
$fix) {
|
||||||
|
$fixed[$fixlinenr] =~ s/\bMODULE_LICENSE\s*\(\s*"GPL v2"\s*\)/MODULE_LICENSE("GPL")/;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# check for sysctl duplicate constants
|
# check for sysctl duplicate constants
|
||||||
@@ -7551,6 +7806,31 @@ sub process {
|
|||||||
WARN("DUPLICATED_SYSCTL_CONST",
|
WARN("DUPLICATED_SYSCTL_CONST",
|
||||||
"duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
|
"duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check that *_device_id tables have sentinel entries.
|
||||||
|
if (defined $stat && $line =~ /struct\s+$dev_id_types\s+\w+\s*\[\s*\]\s*=\s*\{/) {
|
||||||
|
my $stripped = $stat;
|
||||||
|
|
||||||
|
# Strip diff line prefixes.
|
||||||
|
$stripped =~ s/(^|\n)./$1/g;
|
||||||
|
# Line continuations.
|
||||||
|
$stripped =~ s/\\\n/\n/g;
|
||||||
|
# Strip whitespace, empty strings, zeroes, and commas.
|
||||||
|
$stripped =~ s/""//g;
|
||||||
|
$stripped =~ s/0x0//g;
|
||||||
|
$stripped =~ s/[\s$;,0]//g;
|
||||||
|
# Strip field assignments.
|
||||||
|
$stripped =~ s/\.$Ident=//g;
|
||||||
|
|
||||||
|
if (!(substr($stripped, -4) eq "{}};" ||
|
||||||
|
substr($stripped, -6) eq "{{}}};" ||
|
||||||
|
$stripped =~ /ISAPNP_DEVICE_SINGLE_END}};$/ ||
|
||||||
|
$stripped =~ /ISAPNP_CARD_END}};$/ ||
|
||||||
|
$stripped =~ /NULL};$/ ||
|
||||||
|
$stripped =~ /PCMCIA_DEVICE_NULL};$/)) {
|
||||||
|
ERROR("MISSING_SENTINEL", "missing sentinel in ID array\n" . "$here\n$stat\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# If we have no input at all, then there is nothing to report on
|
# If we have no input at all, then there is nothing to report on
|
||||||
@@ -7575,6 +7855,12 @@ sub process {
|
|||||||
ERROR("NOT_UNIFIED_DIFF",
|
ERROR("NOT_UNIFIED_DIFF",
|
||||||
"Does not appear to be a unified-diff format patch\n");
|
"Does not appear to be a unified-diff format patch\n");
|
||||||
}
|
}
|
||||||
|
if ($is_patch && $has_commit_log && $chk_fixes_tag) {
|
||||||
|
if ($needs_fixes_tag ne "" && !$is_revert && !$fixes_tag) {
|
||||||
|
WARN("MISSING_FIXES_TAG",
|
||||||
|
"The commit message has '$needs_fixes_tag', perhaps it also needs a 'Fixes:' tag?\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
if ($is_patch && $has_commit_log && $chk_signoff) {
|
if ($is_patch && $has_commit_log && $chk_signoff) {
|
||||||
if ($signoff == 0) {
|
if ($signoff == 0) {
|
||||||
ERROR("MISSING_SIGN_OFF",
|
ERROR("MISSING_SIGN_OFF",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from argparse import ArgumentParser
|
|||||||
from ply import lex, yacc
|
from ply import lex, yacc
|
||||||
import locale
|
import locale
|
||||||
import traceback
|
import traceback
|
||||||
|
import fnmatch
|
||||||
import sys
|
import sys
|
||||||
import git
|
import git
|
||||||
import re
|
import re
|
||||||
@@ -28,6 +29,21 @@ class SPDXdata(object):
|
|||||||
self.licenses = [ ]
|
self.licenses = [ ]
|
||||||
self.exceptions = { }
|
self.exceptions = { }
|
||||||
|
|
||||||
|
class dirinfo(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.missing = 0
|
||||||
|
self.total = 0
|
||||||
|
self.files = []
|
||||||
|
|
||||||
|
def update(self, fname, basedir, miss):
|
||||||
|
self.total += 1
|
||||||
|
self.missing += miss
|
||||||
|
if miss:
|
||||||
|
fname = './' + fname
|
||||||
|
bdir = os.path.dirname(fname)
|
||||||
|
if bdir == basedir.rstrip('/'):
|
||||||
|
self.files.append(fname)
|
||||||
|
|
||||||
# Read the spdx data from the LICENSES directory
|
# Read the spdx data from the LICENSES directory
|
||||||
def read_spdxdata(repo):
|
def read_spdxdata(repo):
|
||||||
|
|
||||||
@@ -91,11 +107,25 @@ class id_parser(object):
|
|||||||
self.parser = yacc.yacc(module = self, write_tables = False, debug = False)
|
self.parser = yacc.yacc(module = self, write_tables = False, debug = False)
|
||||||
self.lines_checked = 0
|
self.lines_checked = 0
|
||||||
self.checked = 0
|
self.checked = 0
|
||||||
|
self.excluded = 0
|
||||||
self.spdx_valid = 0
|
self.spdx_valid = 0
|
||||||
self.spdx_errors = 0
|
self.spdx_errors = 0
|
||||||
|
self.spdx_dirs = {}
|
||||||
|
self.dirdepth = -1
|
||||||
|
self.basedir = '.'
|
||||||
self.curline = 0
|
self.curline = 0
|
||||||
self.deepest = 0
|
self.deepest = 0
|
||||||
|
|
||||||
|
def set_dirinfo(self, basedir, dirdepth):
|
||||||
|
if dirdepth >= 0:
|
||||||
|
self.basedir = basedir
|
||||||
|
bdir = basedir.lstrip('./').rstrip('/')
|
||||||
|
if bdir != '':
|
||||||
|
parts = bdir.split('/')
|
||||||
|
else:
|
||||||
|
parts = []
|
||||||
|
self.dirdepth = dirdepth + len(parts)
|
||||||
|
|
||||||
# Validate License and Exception IDs
|
# Validate License and Exception IDs
|
||||||
def validate(self, tok):
|
def validate(self, tok):
|
||||||
id = tok.value.upper()
|
id = tok.value.upper()
|
||||||
@@ -167,6 +197,7 @@ class id_parser(object):
|
|||||||
def parse_lines(self, fd, maxlines, fname):
|
def parse_lines(self, fd, maxlines, fname):
|
||||||
self.checked += 1
|
self.checked += 1
|
||||||
self.curline = 0
|
self.curline = 0
|
||||||
|
fail = 1
|
||||||
try:
|
try:
|
||||||
for line in fd:
|
for line in fd:
|
||||||
line = line.decode(locale.getpreferredencoding(False), errors='ignore')
|
line = line.decode(locale.getpreferredencoding(False), errors='ignore')
|
||||||
@@ -183,15 +214,22 @@ class id_parser(object):
|
|||||||
# Remove trailing xml comment closure
|
# Remove trailing xml comment closure
|
||||||
if line.strip().endswith('-->'):
|
if line.strip().endswith('-->'):
|
||||||
expr = expr.rstrip('-->').strip()
|
expr = expr.rstrip('-->').strip()
|
||||||
|
# Remove trailing Jinja2 comment closure
|
||||||
|
if line.strip().endswith('#}'):
|
||||||
|
expr = expr.rstrip('#}').strip()
|
||||||
# Special case for SH magic boot code files
|
# Special case for SH magic boot code files
|
||||||
if line.startswith('LIST \"'):
|
if line.startswith('LIST \"'):
|
||||||
expr = expr.rstrip('\"').strip()
|
expr = expr.rstrip('\"').strip()
|
||||||
|
# Remove j2 comment closure
|
||||||
|
if line.startswith('{#'):
|
||||||
|
expr = expr.rstrip('#}').strip()
|
||||||
self.parse(expr)
|
self.parse(expr)
|
||||||
self.spdx_valid += 1
|
self.spdx_valid += 1
|
||||||
#
|
#
|
||||||
# Should we check for more SPDX ids in the same file and
|
# Should we check for more SPDX ids in the same file and
|
||||||
# complain if there are any?
|
# complain if there are any?
|
||||||
#
|
#
|
||||||
|
fail = 0
|
||||||
break
|
break
|
||||||
|
|
||||||
except ParserException as pe:
|
except ParserException as pe:
|
||||||
@@ -200,31 +238,105 @@ class id_parser(object):
|
|||||||
tok = pe.tok.value
|
tok = pe.tok.value
|
||||||
sys.stdout.write('%s: %d:%d %s: %s\n' %(fname, self.curline, col, pe.txt, tok))
|
sys.stdout.write('%s: %d:%d %s: %s\n' %(fname, self.curline, col, pe.txt, tok))
|
||||||
else:
|
else:
|
||||||
sys.stdout.write('%s: %d:0 %s\n' %(fname, self.curline, col, pe.txt))
|
sys.stdout.write('%s: %d:0 %s\n' %(fname, self.curline, pe.txt))
|
||||||
self.spdx_errors += 1
|
self.spdx_errors += 1
|
||||||
|
|
||||||
def scan_git_tree(tree):
|
if fname == '-':
|
||||||
|
return
|
||||||
|
|
||||||
|
base = os.path.dirname(fname)
|
||||||
|
if self.dirdepth > 0:
|
||||||
|
parts = base.split('/')
|
||||||
|
i = 0
|
||||||
|
base = '.'
|
||||||
|
while i < self.dirdepth and i < len(parts) and len(parts[i]):
|
||||||
|
base += '/' + parts[i]
|
||||||
|
i += 1
|
||||||
|
elif self.dirdepth == 0:
|
||||||
|
base = self.basedir
|
||||||
|
else:
|
||||||
|
base = './' + base.rstrip('/')
|
||||||
|
base += '/'
|
||||||
|
|
||||||
|
di = self.spdx_dirs.get(base, dirinfo())
|
||||||
|
di.update(fname, base, fail)
|
||||||
|
self.spdx_dirs[base] = di
|
||||||
|
|
||||||
|
class pattern(object):
|
||||||
|
def __init__(self, line):
|
||||||
|
self.pattern = line
|
||||||
|
self.match = self.match_file
|
||||||
|
if line == '.*':
|
||||||
|
self.match = self.match_dot
|
||||||
|
elif line.endswith('/'):
|
||||||
|
self.pattern = line[:-1]
|
||||||
|
self.match = self.match_dir
|
||||||
|
elif line.startswith('/'):
|
||||||
|
self.pattern = line[1:]
|
||||||
|
self.match = self.match_fn
|
||||||
|
|
||||||
|
def match_dot(self, fpath):
|
||||||
|
return os.path.basename(fpath).startswith('.')
|
||||||
|
|
||||||
|
def match_file(self, fpath):
|
||||||
|
return os.path.basename(fpath) == self.pattern
|
||||||
|
|
||||||
|
def match_fn(self, fpath):
|
||||||
|
return fnmatch.fnmatchcase(fpath, self.pattern)
|
||||||
|
|
||||||
|
def match_dir(self, fpath):
|
||||||
|
if self.match_fn(os.path.dirname(fpath)):
|
||||||
|
return True
|
||||||
|
return fpath.startswith(self.pattern)
|
||||||
|
|
||||||
|
def exclude_file(fpath):
|
||||||
|
for rule in exclude_rules:
|
||||||
|
if rule.match(fpath):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def scan_git_tree(tree, basedir, dirdepth):
|
||||||
|
parser.set_dirinfo(basedir, dirdepth)
|
||||||
for el in tree.traverse():
|
for el in tree.traverse():
|
||||||
# Exclude stuff which would make pointless noise
|
|
||||||
# FIXME: Put this somewhere more sensible
|
|
||||||
if el.path.startswith("LICENSES"):
|
|
||||||
continue
|
|
||||||
if el.path.find("license-rules.rst") >= 0:
|
|
||||||
continue
|
|
||||||
if not os.path.isfile(el.path):
|
if not os.path.isfile(el.path):
|
||||||
continue
|
continue
|
||||||
|
if exclude_file(el.path):
|
||||||
|
parser.excluded += 1
|
||||||
|
continue
|
||||||
with open(el.path, 'rb') as fd:
|
with open(el.path, 'rb') as fd:
|
||||||
parser.parse_lines(fd, args.maxlines, el.path)
|
parser.parse_lines(fd, args.maxlines, el.path)
|
||||||
|
|
||||||
def scan_git_subtree(tree, path):
|
def scan_git_subtree(tree, path, dirdepth):
|
||||||
for p in path.strip('/').split('/'):
|
for p in path.strip('/').split('/'):
|
||||||
tree = tree[p]
|
tree = tree[p]
|
||||||
scan_git_tree(tree)
|
scan_git_tree(tree, path.strip('/'), dirdepth)
|
||||||
|
|
||||||
|
def read_exclude_file(fname):
|
||||||
|
rules = []
|
||||||
|
if not fname:
|
||||||
|
return rules
|
||||||
|
with open(fname) as fd:
|
||||||
|
for line in fd:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith('#'):
|
||||||
|
continue
|
||||||
|
if not len(line):
|
||||||
|
continue
|
||||||
|
rules.append(pattern(line))
|
||||||
|
return rules
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
ap = ArgumentParser(description='SPDX expression checker')
|
ap = ArgumentParser(description='SPDX expression checker')
|
||||||
ap.add_argument('path', nargs='*', help='Check path or file. If not given full git tree scan. For stdin use "-"')
|
ap.add_argument('path', nargs='*', help='Check path or file. If not given full git tree scan. For stdin use "-"')
|
||||||
|
ap.add_argument('-d', '--dirs', action='store_true',
|
||||||
|
help='Show [sub]directory statistics.')
|
||||||
|
ap.add_argument('-D', '--depth', type=int, default=-1,
|
||||||
|
help='Directory depth for -d statistics. Default: unlimited')
|
||||||
|
ap.add_argument('-e', '--exclude',
|
||||||
|
help='File containing file patterns to exclude. Default: scripts/spdxexclude')
|
||||||
|
ap.add_argument('-f', '--files', action='store_true',
|
||||||
|
help='Show files without SPDX.')
|
||||||
ap.add_argument('-m', '--maxlines', type=int, default=15,
|
ap.add_argument('-m', '--maxlines', type=int, default=15,
|
||||||
help='Maximum number of lines to scan in a file. Default 15')
|
help='Maximum number of lines to scan in a file. Default 15')
|
||||||
ap.add_argument('-v', '--verbose', action='store_true', help='Verbose statistics output')
|
ap.add_argument('-v', '--verbose', action='store_true', help='Verbose statistics output')
|
||||||
@@ -258,6 +370,15 @@ if __name__ == '__main__':
|
|||||||
sys.stderr.write('%s\n' %traceback.format_exc())
|
sys.stderr.write('%s\n' %traceback.format_exc())
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
fname = args.exclude
|
||||||
|
if not fname:
|
||||||
|
fname = os.path.join(os.path.dirname(__file__), 'spdxexclude')
|
||||||
|
exclude_rules = read_exclude_file(fname)
|
||||||
|
except Exception as ex:
|
||||||
|
sys.stderr.write('FAIL: Reading exclude file %s: %s\n' %(fname, ex))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if len(args.path) and args.path[0] == '-':
|
if len(args.path) and args.path[0] == '-':
|
||||||
stdin = os.fdopen(sys.stdin.fileno(), 'rb')
|
stdin = os.fdopen(sys.stdin.fileno(), 'rb')
|
||||||
@@ -268,13 +389,21 @@ if __name__ == '__main__':
|
|||||||
if os.path.isfile(p):
|
if os.path.isfile(p):
|
||||||
parser.parse_lines(open(p, 'rb'), args.maxlines, p)
|
parser.parse_lines(open(p, 'rb'), args.maxlines, p)
|
||||||
elif os.path.isdir(p):
|
elif os.path.isdir(p):
|
||||||
scan_git_subtree(repo.head.reference.commit.tree, p)
|
scan_git_subtree(repo.head.reference.commit.tree, p,
|
||||||
|
args.depth)
|
||||||
else:
|
else:
|
||||||
sys.stderr.write('path %s does not exist\n' %p)
|
sys.stderr.write('path %s does not exist\n' %p)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
# Full git tree scan
|
# Full git tree scan
|
||||||
scan_git_tree(repo.head.commit.tree)
|
scan_git_tree(repo.head.commit.tree, '.', args.depth)
|
||||||
|
|
||||||
|
ndirs = len(parser.spdx_dirs)
|
||||||
|
dirsok = 0
|
||||||
|
if ndirs:
|
||||||
|
for di in parser.spdx_dirs.values():
|
||||||
|
if not di.missing:
|
||||||
|
dirsok += 1
|
||||||
|
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
sys.stderr.write('\n')
|
sys.stderr.write('\n')
|
||||||
@@ -283,10 +412,41 @@ if __name__ == '__main__':
|
|||||||
sys.stderr.write('License IDs %12d\n' %len(spdx.licenses))
|
sys.stderr.write('License IDs %12d\n' %len(spdx.licenses))
|
||||||
sys.stderr.write('Exception IDs %12d\n' %len(spdx.exceptions))
|
sys.stderr.write('Exception IDs %12d\n' %len(spdx.exceptions))
|
||||||
sys.stderr.write('\n')
|
sys.stderr.write('\n')
|
||||||
|
sys.stderr.write('Files excluded: %12d\n' %parser.excluded)
|
||||||
sys.stderr.write('Files checked: %12d\n' %parser.checked)
|
sys.stderr.write('Files checked: %12d\n' %parser.checked)
|
||||||
sys.stderr.write('Lines checked: %12d\n' %parser.lines_checked)
|
sys.stderr.write('Lines checked: %12d\n' %parser.lines_checked)
|
||||||
sys.stderr.write('Files with SPDX: %12d\n' %parser.spdx_valid)
|
if parser.checked:
|
||||||
|
pc = int(100 * parser.spdx_valid / parser.checked)
|
||||||
|
sys.stderr.write('Files with SPDX: %12d %3d%%\n' %(parser.spdx_valid, pc))
|
||||||
|
missing = parser.checked - parser.spdx_valid
|
||||||
|
mpc = int(100 * missing / parser.checked)
|
||||||
|
sys.stderr.write('Files without SPDX:%12d %3d%%\n' %(missing, mpc))
|
||||||
sys.stderr.write('Files with errors: %12d\n' %parser.spdx_errors)
|
sys.stderr.write('Files with errors: %12d\n' %parser.spdx_errors)
|
||||||
|
if ndirs:
|
||||||
|
sys.stderr.write('\n')
|
||||||
|
sys.stderr.write('Directories accounted: %8d\n' %ndirs)
|
||||||
|
pc = int(100 * dirsok / ndirs)
|
||||||
|
sys.stderr.write('Directories complete: %8d %3d%%\n' %(dirsok, pc))
|
||||||
|
|
||||||
|
if ndirs and ndirs != dirsok and args.dirs:
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write('\n')
|
||||||
|
sys.stderr.write('Incomplete directories: SPDX in Files\n')
|
||||||
|
for f in sorted(parser.spdx_dirs.keys()):
|
||||||
|
di = parser.spdx_dirs[f]
|
||||||
|
if di.missing:
|
||||||
|
valid = di.total - di.missing
|
||||||
|
pc = int(100 * valid / di.total)
|
||||||
|
sys.stderr.write(' %-80s: %5d of %5d %3d%%\n' %(f, valid, di.total, pc))
|
||||||
|
|
||||||
|
if ndirs and ndirs != dirsok and args.files:
|
||||||
|
if args.verbose or args.dirs:
|
||||||
|
sys.stderr.write('\n')
|
||||||
|
sys.stderr.write('Files without SPDX:\n')
|
||||||
|
for f in sorted(parser.spdx_dirs.keys()):
|
||||||
|
di = parser.spdx_dirs[f]
|
||||||
|
for f in sorted(di.files):
|
||||||
|
sys.stderr.write(' %s\n' %f)
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user