$f =~ s/^.//; # strip patch context [+ ] $f =~ s/#.*//; # strip # directives $f =~ s/^\s+//; # strip leading blanks next if ($f =~ /^$/); # 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 =~ /^(?: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 = get_stat_real($linenr, $ln - 1); WARN("CONFIG_DESCRIPTION", "please write a help paragraph that fully describes the config symbol\n" . "$here\n$stat_real\n"); } } # check MAINTAINERS entries if ($realfile =~ /^MAINTAINERS$/) {# check MAINTAINERS entries for the right form if ($rawline =~ /^\+[A-Z]:/ && $rawline !~ /^\+[A-Z]:\t\S/) { if (WARN("MAINTAINERS_STYLE", "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) && $fix) { $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/; } }# check MAINTAINERS entries for the right ordering too my $preferred_order = 'MRLSWQBCPTFXNK'; if ($rawline =~ /^\+[A-Z]:/ && $prevrawline =~ /^[\+ ][A-Z]:/) { $rawline =~ /^\+([A-Z]):\s*(.*)/; my $cur = $1; my $curval = $2; $prevrawline =~ /^[\+ ]([A-Z]):\s*(.*)/; my $prev = $1; my $prevval = $2; my $curindex = index($preferred_order, $cur); my $previndex = index($preferred_order, $prev); if ($curindex < 0) { WARN("MAINTAINERS_STYLE", "Unknown MAINTAINERS entry type: '$cur'\n" . $herecurr); } else { if ($previndex >= 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 alphabetic order\n" . $hereprev); } } } } 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 if (defined $root && (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) || ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) { my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; my $dt_path = $root . "/Documentation/devicetree/bindings/"; my $vp_file = $dt_path . "vendor-prefixes.yaml"; foreach my $compat (@compats) { my $compat2 = $compat; $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; my $compat3 = $compat; $compat3 =~ 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 = $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 == $checklicenseline) { if ($rawline =~ /^[ \+]\s*\#\!\s*\//) { $checklicenseline = 2; } elsif ($rawline =~ /^\+/) { my $comment = ""; if ($realfile =~ /\.(h|s|S)$/) { $comment = '/*'; } elsif ($realfile =~ /\.(c|dts|dtsi)$/) { $comment = '//'; } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) { $comment = '#'; } elsif ($realfile =~ /\.rst$/) { $comment = '..'; } # check SPDX comment style for .[chsS] files if ($realfile =~ /\.[chsS]$/ && $rawline =~ /SPDX-License-Identifier:/ && $rawline !~ m@^\+\s*\Q$comment\E\s*@) { WARN("SPDX_LICENSE_TAG", "Improper SPDX comment style for '$realfile', please use '$comment' 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 $checklicenseline\n" . $herecurr); } elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) { my $spdx_license = $1; if (!is_SPDX_License_valid($spdx_license)) { WARN("SPDX_LICENSE_TAG", "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr); } if ($realfile =~ m@^Documentation/devicetree/bindings/@ && not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) { my $msg_level = \&WARN; $msg_level = \&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] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/; } } } } } # check for embedded filenames if ($rawline =~ /^\+.*\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 != $checklicenseline && $rawline =~ /\bSPDX-License-Identifier:/ && substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) { WARN("SPDX_LICENSE_TAG", "Misplaced SPDX-License-Identifier tag - use line $checklicenseline 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_length# LONG_LINE_STRING a string starts before but extends beyond $max_line_length# LONG_LINE all other lines longer than $max_line_length## if LONG_LINE is ignored, the other 2 types are also ignored# if ($line =~ /^\+/ && $length > $max_line_length) { my $msg_type = "LONG_LINE"; # Check the allowed long line types first # logging functions that end in a string that starts # before $max_line_length if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ && length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { $msg_type = ""; # lines with only strings (w/ possible termination) # #defines with only strings } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) { $msg_type = ""; # More special cases } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ || $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) { $msg_type = ""; # URL ($rawline is used in case the URL is in a comment) } elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) { $msg_type = ""; # Otherwise set the alternate message types # a comment starts before $max_line_length } elsif ($line =~ /($;[\s$;]*)$/ && length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { $msg_type = "LONG_LINE_COMMENT" # a quoted string starts before $max_line_length } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { $msg_type = "LONG_LINE_STRING" } if ($msg_type ne "" && (show_type("LONG_LINE") || show_type($msg_type))) { my $msg_level = \&WARN; $msg_level = \&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 =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ 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 =~ /\.S$/ && $line =~ /^\+\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-annotations.rst\n" . $herecurr); } # check we are in a valid source file C or perl if not then ignore this hunk 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 =~ /^\+\s* \t\s*\S/ || $rawline =~ /^\+\s* \s*/) { my $herevet = "$here\n" . cat_vet($rawline) . "\n"; $rpt_cleaners = 1; if (ERROR("CODE_INDENT", "code indent should use tabs where possible\n" . $herevet) && $fix) { $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; } } # check for space before tabs. if ($rawline =~ /^\+/ && $rawline =~ / \t/) { my $herevet = "$here\n" . cat_vet($rawline) . "\n"; if (WARN("SPACE_BEFORE_TAB", "please, no space before tabs\n" . $herevet) && $fix) { while ($fixed[$fixlinenr] =~ s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {} while ($fixed[$fixlinenr] =~ s/(^\+.*) +\t/$1\t/) {} } } # check for assignments on the start of a line if ($sline =~ /^\+\s+($Assignment)[^=]/) { my $operator = $1; if (CHK("ASSIGNMENT_CONTINUATIONS", "Assignment operator '$1' should be on the previous line\n" . $hereprev) && $fix && $prevrawline =~ /^\+/) { # add assignment operator to the previous line, remove from current line $fixed[$fixlinenr - 1] .= " $operator"; $fixed[$fixlinenr] =~ s/\Q$operator\E\s*//; } } # check for && or || at the start of a line if ($rawline =~ /^\+\s*(&&|\|\|)/) { my $operator = $1; if (CHK("LOGICAL_CONTINUATIONS", "Logical continuations should be on the previous line\n" . $hereprev) && $fix && $prevrawline =~ /^\+/) { # insert logical operator at last non-comment, non-whitepsace char on previous line $prevline =~ /[\s$;]*$/; my $line_end = substr($prevrawline, $-[0]); $fixed[$fixlinenr - 1] =~ s/\Q$line_end\E$/ $operator$line_end/; $fixed[$fixlinenr] =~ s/\Q$operator\E\s*//; } } # check indentation starts on a tab stop if ($perl_version_ok && $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) { my $indent = length($1); if ($indent % $tabsize) { if (WARN("TABSTOP", "Statements should start on a tabstop\n" . $herecurr) && $fix) { $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e; } } } # check multi-line statement indentation matches previous line if ($perl_version_ok && $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { $prevline =~ /^\+(\t*)(.*)$/; my $oldindent = $1; my $rest = $2; my $pos = pos_last_openparen($rest); if ($pos >= 0) { $line =~ /^(\+| )([ \t]*)/; my $newindent = $2; my $goodtabindent = $oldindent . "\t" x ($pos / $tabsize) . " " x ($pos % $tabsize); my $goodspaceindent = $oldindent . " " x $pos; if ($newindent ne $goodtabindent && $newindent ne $goodspaceindent) { if (CHK("PARENTHESIS_ALIGNMENT", "Alignment should match open parenthesis\n" . $hereprev) && $fix && $line =~ /^\+/) { $fixed[$fixlinenr] =~ 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) = bar;"# structure definitions like "(struct foo) { 0 };"# multiline macros that define functions# known attributes or the __attribute__ keyword if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { if (CHK("SPACING", "No space is necessary after a cast\n" . $herecurr) && $fix) { $fixed[$fixlinenr] =~ s/(\(\s*$Type\s*\))[ \t]+/$1/; } } # 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 if ($prevline =~ /$;[ \t]*$/ && #ends in comment $prevrawline =~ /^\+.*?\/\*/ && #starting /* $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ $rawline =~ /^\+/ && #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 =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ WARN("BLOCK_COMMENT_STYLE", "Block comments use a trailing */ on a separate line\n" . $herecurr); } # Block comment * alignment if ($prevline =~ /$;[ \t]*$/ && #ends in comment $line =~ /^\+[ \t]*$;/ && #leading comment $rawline =~ /^\+[ \t]*\*/ && #leading * (($prevrawline =~ /^\+.*?\/\*/ && #leading /* $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */ $prevrawline =~ /^\+[ \t]*\*/)) { #leading * my $oldindent; $prevrawline =~ m@^\+([ \t]*/?)\*@; if (defined($1)) { $oldindent = expand_tabs($1); } else { $prevrawline =~ m@^\+(.*/?)\*@; $oldindent = expand_tabs($1); } $rawline =~ m@^\+([ \t]*)\*@; my $newindent = $1; $newindent = 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 =~ /^[\+ ]};?\s*$/ && $line =~ /^\+/ && !($line =~ /^\+\s*$/ || $line =~ /^\+\s*(?:EXPORT_SYMBOL|early_param)/ || $line =~ /^\+\s*MODULE_/i || $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || $line =~ /^\+[a-z_]*init/ || $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || $line =~ /^\+\s*DECLARE/ || $line =~ /^\+\s*builtin_[\w_]*driver/ || $line =~ /^\+\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 =~ /^[\+ ]\s*$/ && $line =~ /^\+\s*$/ && $last_blank_line != ($linenr - 1)) { if (CHK("LINE_SPACING", "Please don't use multiple blank lines\n" . $hereprev) && $fix) { fix_delete_line($fixlinenr, $rawline); } $last_blank_line = $linenr; } # check for missing blank lines after declarations# (declarations must have the same indentation and not be at the start of line) if (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/) { # use temporaries my $sl = $sline; my $pl = $prevline; # remove $Attribute/$Sparse uses to simplify comparisons $sl =~ s/\b(?:$Attribute|$Sparse)\b//g; $pl =~ s/\b(?:$Attribute|$Sparse)\b//g; if (($pl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || # function pointer declarations $pl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || # foo bar; where foo is some local typedef or #define $pl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || # known declaration macros $pl =~ /^\+\s+$declaration_macros/) && # for "else if" which can look like "$Ident $Ident" !($pl =~ /^\+\s+$c90_Keywords\b/ || # other possible extensions of declaration lines $pl =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || # not starting a section or a macro "\" extended line $pl =~ /(?:\{\s*|\\)$/) && # looks like a declaration !($sl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || # function pointer declarations $sl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || # foo bar; where foo is some local typedef or #define $sl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || # known declaration macros $sl =~ /^\+\s+$declaration_macros/ || # start of struct or union or enum $sl =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ || # start or end of block or continuation of declaration $sl =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || # bitfield continuation $sl =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || # other possible extensions of declaration lines $sl =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/)) { if (WARN("LINE_SPACING", "Missing a blank line after declarations\n" . $hereprev) && $fix) { fix_insert_line($fixlinenr, "\+"); } }Lines 3501–4000 of 7586. Previous lines Load more
$f =~ s/^.//; # strip patch context [+ ] $f =~ s/#.*//; # strip # directives $f =~ s/^\s+//; # strip leading blanks next if ($f =~ /^$/); # 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 =~ /^(?: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 = get_stat_real($linenr, $ln - 1); WARN("CONFIG_DESCRIPTION", "please write a help paragraph that fully describes the config symbol\n" . "$here\n$stat_real\n"); } } # check MAINTAINERS entries if ($realfile =~ /^MAINTAINERS$/) { # check MAINTAINERS entries for the right form if ($rawline =~ /^\+[A-Z]:/ && $rawline !~ /^\+[A-Z]:\t\S/) { if (WARN("MAINTAINERS_STYLE", "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) && $fix) { $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/; } } # check MAINTAINERS entries for the right ordering too my $preferred_order = 'MRLSWQBCPTFXNK'; if ($rawline =~ /^\+[A-Z]:/ && $prevrawline =~ /^[\+ ][A-Z]:/) { $rawline =~ /^\+([A-Z]):\s*(.*)/; my $cur = $1; my $curval = $2; $prevrawline =~ /^[\+ ]([A-Z]):\s*(.*)/; my $prev = $1; my $prevval = $2; my $curindex = index($preferred_order, $cur); my $previndex = index($preferred_order, $prev); if ($curindex < 0) { WARN("MAINTAINERS_STYLE", "Unknown MAINTAINERS entry type: '$cur'\n" . $herecurr); } else { if ($previndex >= 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 alphabetic order\n" . $hereprev); } } } } 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 if (defined $root && (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) || ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) { my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; my $dt_path = $root . "/Documentation/devicetree/bindings/"; my $vp_file = $dt_path . "vendor-prefixes.yaml"; foreach my $compat (@compats) { my $compat2 = $compat; $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; my $compat3 = $compat; $compat3 =~ 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 = $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 == $checklicenseline) { if ($rawline =~ /^[ \+]\s*\#\!\s*\//) { $checklicenseline = 2; } elsif ($rawline =~ /^\+/) { my $comment = ""; if ($realfile =~ /\.(h|s|S)$/) { $comment = '/*'; } elsif ($realfile =~ /\.(c|dts|dtsi)$/) { $comment = '//'; } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) { $comment = '#'; } elsif ($realfile =~ /\.rst$/) { $comment = '..'; } # check SPDX comment style for .[chsS] files if ($realfile =~ /\.[chsS]$/ && $rawline =~ /SPDX-License-Identifier:/ && $rawline !~ m@^\+\s*\Q$comment\E\s*@) { WARN("SPDX_LICENSE_TAG", "Improper SPDX comment style for '$realfile', please use '$comment' 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 $checklicenseline\n" . $herecurr); } elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) { my $spdx_license = $1; if (!is_SPDX_License_valid($spdx_license)) { WARN("SPDX_LICENSE_TAG", "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr); } if ($realfile =~ m@^Documentation/devicetree/bindings/@ && not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) { my $msg_level = \&WARN; $msg_level = \&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] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/; } } } } } # check for embedded filenames if ($rawline =~ /^\+.*\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 != $checklicenseline && $rawline =~ /\bSPDX-License-Identifier:/ && substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) { WARN("SPDX_LICENSE_TAG", "Misplaced SPDX-License-Identifier tag - use line $checklicenseline 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_length # LONG_LINE_STRING a string starts before but extends beyond $max_line_length # LONG_LINE all other lines longer than $max_line_length # # if LONG_LINE is ignored, the other 2 types are also ignored # if ($line =~ /^\+/ && $length > $max_line_length) { my $msg_type = "LONG_LINE"; # Check the allowed long line types first # logging functions that end in a string that starts # before $max_line_length if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ && length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { $msg_type = ""; # lines with only strings (w/ possible termination) # #defines with only strings } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) { $msg_type = ""; # More special cases } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ || $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) { $msg_type = ""; # URL ($rawline is used in case the URL is in a comment) } elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) { $msg_type = ""; # Otherwise set the alternate message types # a comment starts before $max_line_length } elsif ($line =~ /($;[\s$;]*)$/ && length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { $msg_type = "LONG_LINE_COMMENT" # a quoted string starts before $max_line_length } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { $msg_type = "LONG_LINE_STRING" } if ($msg_type ne "" && (show_type("LONG_LINE") || show_type($msg_type))) { my $msg_level = \&WARN; $msg_level = \&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 =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ 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 =~ /\.S$/ && $line =~ /^\+\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-annotations.rst\n" . $herecurr); } # check we are in a valid source file C or perl if not then ignore this hunk 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 =~ /^\+\s* \t\s*\S/ || $rawline =~ /^\+\s* \s*/) { my $herevet = "$here\n" . cat_vet($rawline) . "\n"; $rpt_cleaners = 1; if (ERROR("CODE_INDENT", "code indent should use tabs where possible\n" . $herevet) && $fix) { $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; } } # check for space before tabs. if ($rawline =~ /^\+/ && $rawline =~ / \t/) { my $herevet = "$here\n" . cat_vet($rawline) . "\n"; if (WARN("SPACE_BEFORE_TAB", "please, no space before tabs\n" . $herevet) && $fix) { while ($fixed[$fixlinenr] =~ s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {} while ($fixed[$fixlinenr] =~ s/(^\+.*) +\t/$1\t/) {} } } # check for assignments on the start of a line if ($sline =~ /^\+\s+($Assignment)[^=]/) { my $operator = $1; if (CHK("ASSIGNMENT_CONTINUATIONS", "Assignment operator '$1' should be on the previous line\n" . $hereprev) && $fix && $prevrawline =~ /^\+/) { # add assignment operator to the previous line, remove from current line $fixed[$fixlinenr - 1] .= " $operator"; $fixed[$fixlinenr] =~ s/\Q$operator\E\s*//; } } # check for && or || at the start of a line if ($rawline =~ /^\+\s*(&&|\|\|)/) { my $operator = $1; if (CHK("LOGICAL_CONTINUATIONS", "Logical continuations should be on the previous line\n" . $hereprev) && $fix && $prevrawline =~ /^\+/) { # insert logical operator at last non-comment, non-whitepsace char on previous line $prevline =~ /[\s$;]*$/; my $line_end = substr($prevrawline, $-[0]); $fixed[$fixlinenr - 1] =~ s/\Q$line_end\E$/ $operator$line_end/; $fixed[$fixlinenr] =~ s/\Q$operator\E\s*//; } } # check indentation starts on a tab stop if ($perl_version_ok && $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) { my $indent = length($1); if ($indent % $tabsize) { if (WARN("TABSTOP", "Statements should start on a tabstop\n" . $herecurr) && $fix) { $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e; } } } # check multi-line statement indentation matches previous line if ($perl_version_ok && $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { $prevline =~ /^\+(\t*)(.*)$/; my $oldindent = $1; my $rest = $2; my $pos = pos_last_openparen($rest); if ($pos >= 0) { $line =~ /^(\+| )([ \t]*)/; my $newindent = $2; my $goodtabindent = $oldindent . "\t" x ($pos / $tabsize) . " " x ($pos % $tabsize); my $goodspaceindent = $oldindent . " " x $pos; if ($newindent ne $goodtabindent && $newindent ne $goodspaceindent) { if (CHK("PARENTHESIS_ALIGNMENT", "Alignment should match open parenthesis\n" . $hereprev) && $fix && $line =~ /^\+/) { $fixed[$fixlinenr] =~ 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) = bar;" # structure definitions like "(struct foo) { 0 };" # multiline macros that define functions # known attributes or the __attribute__ keyword if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { if (CHK("SPACING", "No space is necessary after a cast\n" . $herecurr) && $fix) { $fixed[$fixlinenr] =~ s/(\(\s*$Type\s*\))[ \t]+/$1/; } } # 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 if ($prevline =~ /$;[ \t]*$/ && #ends in comment $prevrawline =~ /^\+.*?\/\*/ && #starting /* $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ $rawline =~ /^\+/ && #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 =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ WARN("BLOCK_COMMENT_STYLE", "Block comments use a trailing */ on a separate line\n" . $herecurr); } # Block comment * alignment if ($prevline =~ /$;[ \t]*$/ && #ends in comment $line =~ /^\+[ \t]*$;/ && #leading comment $rawline =~ /^\+[ \t]*\*/ && #leading * (($prevrawline =~ /^\+.*?\/\*/ && #leading /* $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */ $prevrawline =~ /^\+[ \t]*\*/)) { #leading * my $oldindent; $prevrawline =~ m@^\+([ \t]*/?)\*@; if (defined($1)) { $oldindent = expand_tabs($1); } else { $prevrawline =~ m@^\+(.*/?)\*@; $oldindent = expand_tabs($1); } $rawline =~ m@^\+([ \t]*)\*@; my $newindent = $1; $newindent = 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 =~ /^[\+ ]};?\s*$/ && $line =~ /^\+/ && !($line =~ /^\+\s*$/ || $line =~ /^\+\s*(?:EXPORT_SYMBOL|early_param)/ || $line =~ /^\+\s*MODULE_/i || $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || $line =~ /^\+[a-z_]*init/ || $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || $line =~ /^\+\s*DECLARE/ || $line =~ /^\+\s*builtin_[\w_]*driver/ || $line =~ /^\+\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 =~ /^[\+ ]\s*$/ && $line =~ /^\+\s*$/ && $last_blank_line != ($linenr - 1)) { if (CHK("LINE_SPACING", "Please don't use multiple blank lines\n" . $hereprev) && $fix) { fix_delete_line($fixlinenr, $rawline); } $last_blank_line = $linenr; } # check for missing blank lines after declarations # (declarations must have the same indentation and not be at the start of line) if (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/) { # use temporaries my $sl = $sline; my $pl = $prevline; # remove $Attribute/$Sparse uses to simplify comparisons $sl =~ s/\b(?:$Attribute|$Sparse)\b//g; $pl =~ s/\b(?:$Attribute|$Sparse)\b//g; if (($pl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || # function pointer declarations $pl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || # foo bar; where foo is some local typedef or #define $pl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || # known declaration macros $pl =~ /^\+\s+$declaration_macros/) && # for "else if" which can look like "$Ident $Ident" !($pl =~ /^\+\s+$c90_Keywords\b/ || # other possible extensions of declaration lines $pl =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || # not starting a section or a macro "\" extended line $pl =~ /(?:\{\s*|\\)$/) && # looks like a declaration !($sl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || # function pointer declarations $sl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || # foo bar; where foo is some local typedef or #define $sl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || # known declaration macros $sl =~ /^\+\s+$declaration_macros/ || # start of struct or union or enum $sl =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ || # start or end of block or continuation of declaration $sl =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || # bitfield continuation $sl =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || # other possible extensions of declaration lines $sl =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/)) { if (WARN("LINE_SPACING", "Missing a blank line after declarations\n" . $hereprev) && $fix) { fix_insert_line($fixlinenr, "\+"); } }