summaryrefslogtreecommitdiff
path: root/pkgtools
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools')
-rw-r--r--pkgtools/pkglint/files/pkglint.pl296
1 files changed, 211 insertions, 85 deletions
diff --git a/pkgtools/pkglint/files/pkglint.pl b/pkgtools/pkglint/files/pkglint.pl
index a6aeb4cfd47..96f9ddbc29a 100644
--- a/pkgtools/pkglint/files/pkglint.pl
+++ b/pkgtools/pkglint/files/pkglint.pl
@@ -1,5 +1,5 @@
#! @PERL@
-# $NetBSD: pkglint.pl,v 1.662 2006/07/24 09:25:57 rillig Exp $
+# $NetBSD: pkglint.pl,v 1.663 2006/07/27 13:05:09 rillig Exp $
#
# pkglint - static analyzer and checker for pkgsrc packages
@@ -57,12 +57,12 @@ use constant true => 1;
use constant dont_know => 2;
use constant doesnt_matter => 3;
-sub assert($) {
- my ($cond) = @_;
+sub assert($$) {
+ my ($cond, $msg) = @_;
my (@callers, $n);
if (!$cond) {
- print STDERR ("FATAL: Assertion failed.\n");
+ print STDERR ("FATAL: Assertion failed: ${msg}.\n");
for ($n = 0; my @info = caller($n); $n++) {
push(@callers, [$info[2], $info[3]]);
@@ -70,7 +70,7 @@ sub assert($) {
for (my $i = $#callers; $i >= 0; $i--) {
my $info = $callers[$i];
- printf STDERR (" at line %4d in %s\n", $info->[0], $info->[1]);
+ printf STDERR (" line %4d called %s\n", $info->[0], $info->[1]);
}
exit(1);
}
@@ -468,12 +468,16 @@ sub highlight($$) {
# Some other methods allow modification of the physical lines, but leave
# the logical line (the C<text>) untouched. These methods are used in the
# --autofix mode.
+#
+# A line can have some "extra" fields that allow the results of parsing to
+# be saved under a name.
#==========================================================================
package PkgLint::Line;
BEGIN {
import PkgLint::Util qw(
false true
+ assert
);
}
@@ -484,10 +488,11 @@ use constant PHYSLINES => 3;
use constant CHANGED => 4;
use constant BEFORE => 5;
use constant AFTER => 6;
+use constant EXTRA => 7;
sub new($$$$) {
my ($class, $fname, $lines, $text, $physlines) = @_;
- my ($self) = ([$fname, $lines, $text, $physlines, false, [], []]);
+ my ($self) = ([$fname, $lines, $text, $physlines, false, [], [], {}]);
bless($self, $class);
return $self;
}
@@ -498,6 +503,22 @@ sub text($) { return shift(@_)->[TEXT]; }
# Note: physlines is _not_ a usual getter method.
sub is_changed($) { return shift(@_)->[CHANGED]; }
+# querying, getting and setting the extra values.
+sub has($$) {
+ my ($self, $name) = @_;
+ return exists($self->[EXTRA]->{$name});
+}
+sub get($$) {
+ my ($self, $name) = @_;
+ assert(exists($self->[EXTRA]->{$name}), "Field ${name} does not exist.");
+ return $self->[EXTRA]->{$name};
+}
+sub set($$$) {
+ my ($self, $name, $value) = @_;
+ assert(!exists($self->[EXTRA]->{$name}), "Field ${name} already exists.");
+ $self->[EXTRA]->{$name} = $value;
+}
+
sub physlines($) {
my ($self) = @_;
return [@{$self->[BEFORE]}, @{$self->[PHYSLINES]}, @{$self->[AFTER]}];
@@ -1679,7 +1700,6 @@ my (%warnings) = (
);
my $opt_autofix = false;
-my $opt_debug = false;
my $opt_dumpmakefile = false;
my $opt_import = false;
my $opt_klickibunti = false; # experimental
@@ -1718,8 +1738,6 @@ my (@options) = (
my ($opt, $val) = @_;
parse_multioption($val, \%warnings);
} ],
- [ "-d|--debug", "Print additional warnings that are mostly of use to pkglint's author",
- "debug|d", \$opt_debug ],
[ "-e|--explain", "Explain the diagnostics or give further help",
"explain|e", sub {
PkgLint::Logging::set_explain();
@@ -1764,17 +1782,20 @@ use constant regex_dependency_wildcard
=> qr"^((?:\$\{[\w_]+\}|[\w_]|-[^\d\[])+)-(?:\[0-9\]|\d.*)$";
use constant regex_gnu_configure_volatile_vars
=> qr"^(?:CFLAGS||CPPFLAGS|CXXFLAGS|FFLAGS|LDFLAGS|LIBS)$";
+use constant regex_mk_comment => qr"^ *\s*#(.*)$";
use constant regex_mk_cond => qr"^\.(\s*)(if|ifdef|ifndef|else|elif|endif|for|endfor|undef)(?:\s+([^\s#][^#]*?))?\s*(?:#.*)?$";
use constant regex_mk_dependency=> qr"^([^\s:]+(?:\s*[^\s:]+)*):\s*([^#]*?)(?:\s*#.*)?$";
use constant regex_mk_include => qr"^\.\s*s?include\s+\"([^\"]+)\"(?:\s*#.*)?$";
use constant regex_mk_shellvaruse => qr"(?:^|[^\$])\$\$\{?(\w+)\}?"; # XXX: not perfect
use constant regex_pkgname => qr"^((?:[\w.+]|-[^\d])+)-(\d(?:\w|\.\d)*)$";
-use constant regex_shellcmd => qr"^\t(.*)$";
+use constant regex_mk_shellcmd => qr"^\t(.*)$";
use constant regex_unresolved => qr"\$\{";
use constant regex_validchars => qr"[\011\040-\176]";
# Note: the following regular expression looks more complicated than
# necessary to avoid a stack overflow in the Perl interpreter.
-use constant regex_varassign => qr"^([-*+A-Z_a-z0-9.\${}\[]+?)\s*(=|\?=|\+=|:=|!=)\s*((?:[^\\#\s]+|\s+?|(?:\\#)+|\\)*?)(?:\s*(#.*))?$";
+# The leading white-space may only consist of \040 characters, otherwise
+# the order of regex_varassign and regex_mk_shellcmd becomes important.
+use constant regex_varassign => qr"^ *([-*+A-Z_a-z0-9.\${}\[]+?)\s*(=|\?=|\+=|:=|!=)\s*((?:[^\\#\s]+|\s+?|(?:\\#)+|\\)*?)(?:\s*(#.*))?$";
use constant regex_sh_varassign => qr"^([A-Z_a-z][0-9A-Z_a-z]*)=";
# The following "constants" are often used in contexts where
@@ -1785,6 +1806,8 @@ use constant regex_sh_varassign => qr"^([A-Z_a-z][0-9A-Z_a-z]*)=";
# it will catch almost all shell programs that are portable enough to be
# used in pkgsrc.
my $regex_shellword = qr"\s*(
+ \#.* # shell comment
+ |
(?: '[^']*' # single quoted string
| \"(?:\\.|[^\"\\])*\" # double quoted string
| \`[^\`]*\` # backticks string
@@ -1793,9 +1816,10 @@ my $regex_shellword = qr"\s*(
| \$\([^()]+\) # make(1) variable, $(...)
| \$[/\@<^] # special make(1) variables
| \$\$[0-9A-Z_a-z]+ # shell variable
+ | \$\$[?@] # special shell variables
| \$\$\{[0-9A-Z_a-z]+\} # shell variable in braces
| \$\$\( # POSIX-style backticks replacement
- | [^\(\)'\"\\\s;&\|<>\#\`\$] # non-special character
+ | [^\(\)'\"\\\s;&\|<>\`\$] # non-special character
| \$\{[^\s\"'`]+ # HACK: nested make(1) variables
)+ | ;;? | &&? | \|\|? | \( | \) | >& | <<? | >>? | \#.*)"sx;
my $regex_varname = qr"[-*+.0-9A-Z_a-z{}\[]+";
@@ -2242,7 +2266,7 @@ sub load_dist_sites() {
# ignore multiple inclusion guards
} else {
- $line->log_error("Unknown line type.");
+ $line->log_fatal("Unknown line type.");
}
}
@@ -2329,7 +2353,7 @@ sub load_tool_names() {
}
}
}
- assert(scalar(@tool_files) > 1);
+ assert(scalar(@tool_files) > 1, "Too few tool files. Maybe the files have been renamed again?");
#
# Scan the tool files for the actual definitions of the tools.
@@ -2814,7 +2838,7 @@ sub unescape_shellword($) {
my ($text) = @_;
# TODO: implement this.
- assert(false);
+ assert(false, "unescape_shellword is not yet implemented.");
}
# Removes all uses of make variables from a string.
@@ -2841,8 +2865,6 @@ sub strings_to_lines($) {
sub backtrace() {
my (@callers);
- return unless $opt_debug;
-
my $n = 0;
while (my @info = caller($n)) {
push(@callers, [$info[2], $info[3]]);
@@ -2925,7 +2947,7 @@ sub extract_used_variables($$) {
}
if ($rest ne "") {
- $opt_debug and $line->log_warning("Could not extract variables: ${rest}");
+ $opt_debug_misc and $line->log_warning("Could not extract variables: ${rest}");
}
return $result;
@@ -2967,8 +2989,8 @@ sub check_pkglint_version() {
sub lines_log_warning($$$) {
my ($lines, $lineno, $msg) = @_;
- assert(0 <= $lineno);
- assert(@{$lines} != 0);
+ assert(0 <= $lineno, "The line number is negative (${lineno}).");
+ assert(@{$lines} != 0, "The lines may not be empty.");
if ($lineno <= $#{$lines}) {
$lines->[$lineno]->log_warning($msg);
@@ -3015,7 +3037,7 @@ sub get_variable_type($$) {
my ($line, $varname) = @_;
my ($type);
- assert(defined($varname));
+ assert(defined($varname), "The varname parameter must be defined.");
if (exists(get_vartypes_map()->{$varname})) {
return get_vartypes_map()->{$varname};
@@ -3202,6 +3224,86 @@ sub variable_needs_quoting($$$) {
}
#
+# Parsing.
+#
+
+# This procedure fills in the extra fields of a line, depending on the
+# line type. These fields can later be queried without having to parse
+# them again and again.
+#
+sub parseline_mk($) {
+ my ($line) = @_;
+ my $text = $line->text;
+
+ if ($text =~ regex_varassign) {
+ my ($varname, $op, $value, $comment) = ($1, $2, $3, $4);
+
+ # In variable assignments, a '#' character is preceded
+ # by a backslash. In shell commands, it is interpreted
+ # literally.
+ $value =~ s/\\\#/\#/g;
+
+ $line->set("is_varassign", true);
+ $line->set("varname", $varname);
+ $line->set("op", $op);
+ $line->set("value", $value);
+ defined($comment) and $line->set("comment", $comment);
+
+ } elsif ($text =~ regex_mk_shellcmd) {
+ my ($shellcmd) = @_;
+
+ # Shell command lines cannot have embedded comments.
+ $line->set("is_shellcmd", true);
+ $line->set("shellcmd", $shellcmd);
+
+ } elsif ($text =~ regex_mk_comment) {
+ my ($comment) = @_;
+
+ $line->set("is_comment", true);
+ $line->set("comment", $comment);
+
+ } elsif ($text eq "") {
+
+ $line->set("is_empty", true);
+
+ } elsif ($text =~ regex_mk_cond) {
+ my ($indent, $directive, $args, $comment) = ($1, $2, $3, $4);
+
+ $line->set("is_cond", true);
+ $line->set("indent", $indent);
+ $line->set("directive", $directive);
+ defined($args) and $line->set("args", $args);
+ defined($comment) and $line->set("comment", $comment);
+
+ } elsif ($text =~ regex_mk_include) {
+ my ($includefile, $comment) = ($1, $2);
+
+ $line->set("is_include", true);
+ $line->set("includefile", $includefile);
+ defined($comment) and $line->set("comment", $comment);
+
+ } elsif ($text =~ regex_mk_dependency) {
+ my ($targets, $sources, $comment) = ($1, $2, $3);
+
+ $line->set("is_dependency", true);
+ $line->set("targets", $targets);
+ $line->set("sources", $sources);
+ defined($comment) and $line->set("comment", $comment);
+
+ } else {
+ assert(false, "Unknown line format: " . $line->to_string());
+ }
+}
+
+sub parselines_mk($) {
+ my ($lines) = @_;
+
+ foreach my $line (@{$lines}) {
+ parseline_mk($line);
+ }
+}
+
+#
# Loading package-specific data from files.
#
@@ -3215,6 +3317,7 @@ sub readmakefile($$$$) {
if (!$lines) {
return false;
}
+ parselines_mk($lines);
$is_main_Makefile = (@{$main_lines} == 0);
@@ -3283,8 +3386,8 @@ sub readmakefile($$$$) {
}
}
- } elsif ($text =~ regex_varassign) {
- my ($varname, $op, $value, $comment) = ($1, $2, $3, $4);
+ } elsif ($line->has("is_varassign")) {
+ my ($varname, $op, $value) = ($line->get("varname"), $line->get("op"), $line->get("value"));
# Record all variables that are defined in these lines, so that they
# are not reported as "used but not defined".
@@ -3410,12 +3513,8 @@ sub checkline_valid_characters_in_variable($$) {
my ($line, $re_validchars) = @_;
my ($varname, $rest);
- $rest = $line->text;
- if ($rest =~ regex_varassign) {
- ($varname, undef, $rest) = ($1, $2, $3);
- } else {
- return;
- }
+ $varname = $line->get("varname");
+ $rest = $line->get("value");
$rest =~ s/$re_validchars//g;
if ($rest ne "") {
@@ -3632,7 +3731,7 @@ sub checkline_cpp_macro_names($$) {
sub checkline_mk_varuse($$$$) {
my ($line, $varname, $mod, $context) = @_;
- assert(defined($varname));
+ assert(defined($varname), "The varname parameter must be defined");
$opt_debug_trace and $line->log_debug("checkline_mk_varuse(\"${varname}\", \"${mod}\", ".$context->to_string().")");
# Check for spelling mistakes.
@@ -3739,7 +3838,7 @@ sub checkline_mk_varuse($$$$) {
}
}
- assert(defined($mkctx_build_defs));
+ assert(defined($mkctx_build_defs), "The build_defs variable must be defined here.");
if (exists(get_userdefined_variables()->{$varname}) && !exists(get_system_build_defs()->{$varname}) && !exists($mkctx_build_defs->{$varname})) {
$line->log_warning("The user-defined variable ${varname} is used but not added to BUILD_DEFS.");
}
@@ -3845,10 +3944,19 @@ sub checkline_mk_shellword($$$) {
# make variables have the same syntax, no matter in which
# state we are currently.
- if ($rest =~ s/^\$\{(${regex_varname})(:[^\{]+)?\}//
- || $rest =~ s/^\$\((${regex_varname})(:[^\)]+)?\)//) {
+ if ($rest =~ s/^\$\{(${regex_varname}|[\@])(:[^\{]+)?\}//
+ || $rest =~ s/^\$\((${regex_varname}|[\@])(:[^\)]+)?\)//
+ || $rest =~ s/^\$(\@)//) {
my ($varname, $mod) = ($1, $2);
+ if ($varname eq "\@") {
+ $line->log_warning("Please use \"\${.TARGET}\" instead of \"\$\@\".");
+ $line->explain_warning(
+ "The variable \$\@ can easily be confused with the shell variable of the",
+ "same name, which has a completely different meaning.");
+ $varname = ".TARGET";
+ }
+
if ($state == SWST_PLAIN && defined($mod) && $mod =~ qr":Q$") {
# Fine.
@@ -3878,24 +3986,39 @@ sub checkline_mk_shellword($$$) {
: VUC_SHELLWORD_UNKNOWN,
VUC_EXTENT_WORD_PART
);
- checkline_mk_varuse($line, $varname, defined($mod) ? $mod : "", $ctx);
+ if ($varname ne "\@") {
+ checkline_mk_varuse($line, $varname, defined($mod) ? $mod : "", $ctx);
+ }
} elsif ($state == SWST_PLAIN) {
- if ($rest =~ s/^[!\%&\(\)*+,\-.\/0-9:;<=>?\@A-Z\[\]^_a-z{|}~]+//) {
+ if ($rest =~ s/^[!#\%&\(\)*+,\-.\/0-9:;<=>?\@A-Z\[\]^_a-z{|}~]+//) {
} elsif ($rest =~ s/^\'//) {
$state = SWST_SQUOT;
} elsif ($rest =~ s/^\"//) {
$state = SWST_DQUOT;
} elsif ($rest =~ s/^\`//) {
$state = SWST_BACKT;
- } elsif ($rest =~ s/^\\[ !"#'\(\)*;\\^{}]//) {
+ } elsif ($rest =~ s/^\\[ !"#'\(\)*;\\^{|}]//) {
} elsif ($rest =~ s/^\$\$([0-9A-Z_a-z]+)//
|| $rest =~ s/^\$\$\{([0-9A-Z_a-z]+)\}//) {
my ($shvarname) = ($1);
if ($opt_warn_quoting && $check_quoting) {
$line->log_warning("Unquoted shell variable \"${shvarname}\".");
}
- } elsif ($rest =~ s/\$\$\(/(/) {
+
+ } elsif ($rest =~ s/^\$\@//) {
+ $line->log_warning("Please use \"\${.TARGET}\" instead of \"\$@\".");
+ $line->explain_warning(
+ "It is more readable and prevents confusion with the shell variable of",
+ "the same name.");
+
+ } elsif ($rest =~ s/^\$\$\@//) {
+ $line->log_warning("The \$@ shell variable should only be used in double quotes.");
+
+ } elsif ($rest =~ s/^\$\$\?//) {
+ $line->log_warning("The \$? shell variable is often not available in \"set -e\" mode.");
+
+ } elsif ($rest =~ s/^\$\$\(/(/) {
$line->log_warning("Invoking subshells via \$(...) is not portable enough.");
$line->explain_warning(
"The Solaris /bin/sh does not know this way to execute a command in a",
@@ -3925,7 +4048,7 @@ sub checkline_mk_shellword($$$) {
$opt_debug_shell and $line->log_debug("[checkline_mk_shellword] Found double-quoted variable ${shvarname}.");
} elsif ($rest =~ s/^\$\$//) {
$line->log_warning("Unquoted \$ or strange shell variable found.");
- } elsif ($rest =~ s/^\\([\(\)*\-.0-9n])//) {
+ } elsif ($rest =~ s/^\\(.)//) {
my ($char) = ($1);
$line->log_warning("Please use \"\\\\${char}\" instead of \"\\${char}\".");
$line->explain_warning(
@@ -3980,8 +4103,8 @@ sub checkline_mk_shellword($$$) {
last;
}
}
- if ($rest ne "") {
- $opt_debug_shell and $line->log_debug("Unparseable shell word in " . statename->[$state] . ": ${rest}");
+ if ($rest !~ qr"^\s*$") {
+ $line->log_error("Internal pkglint error: " . statename->[$state] . ": rest=${rest}");
}
}
@@ -4388,8 +4511,8 @@ sub checkline_mk_shelltext($$) {
};
}
- if ($rest ne "") {
- $opt_debug and $line->log_error("[checkline_mk_shelltext] " . scst_statename->[$state] . ": rest=${rest}");
+ if ($rest !~ qr"^\s*$") {
+ $line->log_error("Internal pkglint error: " . scst_statename->[$state] . ": rest=${rest}");
}
}
@@ -4533,19 +4656,10 @@ sub checkline_mk_vartype_basic($$$$$$$$) {
if ($value =~ qr"^-D([0-9A-Z_a-z]+)=(.*)") {
my ($macname, $macval) = ($1, $2);
- if ($macval =~ qr"^\\\"(?:\$\{[A-Z0-9_]+:Q\}|[^\$])*\\\"") {
- # Everything's fine.
+ # No checks needed, since the macro definitions
+ # are usually directory names, which don't need
+ # any quoting.
- } elsif ($macval =~ qr"^\"\\\"[^\$]*\$\{[A-Z0-9_]+\}.*\\\"\"") {
- $opt_debug and $line->log_note("Not the best style for CPP macros, but accepted.");
-
- } elsif ($macval =~ regex_unresolved && $macval =~ qr"[\"']") {
- $line->log_warning("Unusual macro value ${macval}.");
- $line->explain_warning(
- "String macro definitions should start and end with an escaped quote",
- "(\\\"). Between these quotes, there should be quoted variables in the",
- "form \${VARNAME:Q} or arbitrary non-dollar characters.");
- }
} elsif ($value =~ qr"^-[DU]([0-9A-Z_a-z]+)") {
my ($macname) = ($1);
@@ -4751,10 +4865,10 @@ sub checkline_mk_vartype_basic($$$$$$$$) {
));
my $license_file = "${cwd_pkgsrcdir}/licenses/${value}";
- if (defined($pkgctx_vardef) && exists($pkgctx_vardef->{"LICENSE_FILE"}) && $pkgctx_vardef->{"LICENSE_FILE"}->text =~ regex_varassign) {
- my ($varname, $op, $value, $comment) = ($1, $2, $3, $4);
+ if (defined($pkgctx_vardef) && exists($pkgctx_vardef->{"LICENSE_FILE"})) {
+ my $license_file_line = $pkgctx_vardef->{"LICENSE_FILE"};
- $license_file = "${current_dir}/" . resolve_relative_path($value, false);
+ $license_file = "${current_dir}/" . resolve_relative_path($license_file_line->get("value"), false);
}
if (!-f $license_file) {
$line->log_warning("License file ".normalize_pathname($license_file)." does not exist.");
@@ -4831,13 +4945,13 @@ sub checkline_mk_vartype_basic($$$$$$$$) {
}
} elsif ($type eq "Pathmask") {
- if ($value_novar !~ qr"^[-0-9A-Za-z._~+%*?/\[\]]*$") {
+ if ($value_novar !~ qr"^[#\-0-9A-Za-z._~+%*?/\[\]]*$") {
$line->log_warning("\"${value}\" is not a valid pathname mask.");
}
checkline_mk_absolute_pathname($line, $value);
} elsif ($type eq "Pathname") {
- if ($value_novar !~ qr"^[-0-9A-Za-z._~+%/]*$") {
+ if ($value_novar !~ qr"^[#\-0-9A-Za-z._~+%/]*$") {
$line->log_warning("\"${value}\" is not a valid pathname.");
}
checkline_mk_absolute_pathname($line, $value);
@@ -5023,7 +5137,7 @@ sub checkline_mk_vartype_basic($$$$$$$$) {
} elsif ($value =~ regex_unresolved) {
# No further checks
- } elsif ($value =~ qr"^(https?|ftp|gopher)://([-0-9A-Za-z.]+)(?::(\d+))?/([-%&+,./0-9:=?\@A-Z_a-z~]|\\#)*$") {
+ } elsif ($value =~ qr"^(https?|ftp|gopher)://([-0-9A-Za-z.]+)(?::(\d+))?/([-%&+,./0-9:=?\@A-Z_a-z~]|#)*$") {
my ($proto, $host, $port, $path) = ($1, $2, $3, $4);
my $sites = get_dist_sites();
@@ -5200,7 +5314,7 @@ sub checkline_mk_vartype($$$$$) {
}
if ($rest !~ qr"^\s*$") {
- $opt_debug and $line->log_warning("Invalid shell word \"${value}\" at the end.");
+ $line->log_error("Internal pkglint error: rest=${rest}");
}
} else {
@@ -5283,7 +5397,7 @@ sub checkline_mk_varassign($$$$$) {
}
if ($varname eq "BUILD_DEFS") {
- assert(defined($mkctx_build_defs));
+ assert(defined($mkctx_build_defs), "The build_defs variable must be defined here.");
foreach my $bdvar (split(qr"\s+", $value)) {
$mkctx_build_defs->{$bdvar} = true;
$opt_debug_misc and $line->log_debug("${bdvar} is added to BUILD_DEFS.");
@@ -5453,8 +5567,8 @@ sub checklines_package_Makefile_varorder($) {
if ($text =~ qr"^#") {
$lineno++;
- } elsif ($text =~ regex_varassign) {
- my ($varname, $op, $value, $comment) = ($1, $2, $3, $4);
+ } elsif ($line->has("varname")) {
+ my $varname = $line->get("varname");
if (exists($below->{$varname})) {
if (defined($below->{$varname})) {
@@ -5511,7 +5625,7 @@ sub checklines_mk($) {
my ($allowed_targets) = ({});
my ($substcontext) = PkgLint::SubstContext->new();
- assert(@{$lines} != 0);
+ assert(@{$lines} != 0, "checklines_mk may only be called with non-empty lines.");
$opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_mk()");
# Define global variables for the Makefile context.
@@ -5537,16 +5651,18 @@ sub checklines_mk($) {
checkline_trailing_whitespace($line);
checkline_spellcheck($line);
- if ($text =~ qr"^\s*$") {
+ if ($line->has("is_empty")) {
$substcontext->check_end($line);
- } elsif ($text =~ qr"^#") {
+ } elsif ($line->has("is_comment")) {
# No further checks.
} elsif ($text =~ regex_varassign) {
- my ($varname, $op, $value, $comment) = ($1, $2, $3, $4);
+ my ($varname, $op, undef, $comment) = ($1, $2, $3, $4);
my $space1 = substr($text, $+[1], $-[2] - $+[1]);
my $align = substr($text, $+[2], $-[3] - $+[2]);
+ my $value = $line->get("value");
+
if ($align !~ qr"^(\t*|[ ])$") {
$opt_warn_space && $line->log_note("Alignment of variable values should be done with tabs, not spaces.");
my $prefix = "${varname}${space1}${op}";
@@ -5559,7 +5675,7 @@ sub checklines_mk($) {
checkline_mk_varassign($line, $varname, $op, $value, $comment);
$substcontext->check_varassign($line, $varname, $op, $value);
- } elsif ($text =~ regex_shellcmd) {
+ } elsif ($text =~ regex_mk_shellcmd) {
my ($shellcmd) = ($1);
checkline_mk_shellcmd($line, $shellcmd);
@@ -5746,7 +5862,7 @@ sub checklines_buildlink3_inclusion($) {
my ($lines) = @_;
my ($included_files);
- assert(@{$lines} != 0);
+ assert(@{$lines} != 0, "The lines array must be non-empty.");
$opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_buildlink3_inclusion()");
if (!defined($pkgctx_bl3)) {
@@ -5816,6 +5932,7 @@ sub checkfile_buildlink3_mk($) {
return;
}
+ parselines_mk($lines);
checklines_mk($lines);
$lineno = 0;
@@ -5955,6 +6072,14 @@ sub checkfile_buildlink3_mk($) {
}
}
+ if ($varname =~ qr"^BUILDLINK_[\w_]+\.(.*)$") {
+ my ($varparam) = ($1);
+
+ if ($varparam ne $bl_pkgbase) {
+ $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file.");
+ }
+ }
+
# TODO: More checks.
} elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) {
@@ -6255,6 +6380,7 @@ sub checkfile_mk($) {
return;
}
+ parselines_mk($lines);
checklines_mk($lines);
autofix($lines);
}
@@ -6310,27 +6436,24 @@ sub checkfile_package_Makefile($$$) {
if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) {
my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"};
+ my $value = $languages_line->get("value");
- if ($languages_line->text =~ regex_varassign) {
- my (undef, $op, $value, $comment) = ($1, $2, $3, $4);
+ if ($languages_line->has("comment") && $languages_line->get("comment") =~ qr"(?:^|\s+)c(?:\s+|$)"i) {
+ # Don't emit a warning, since the comment
+ # probably contains a statement that C is
+ # really not needed.
- if (defined($comment) && $comment =~ qr"(?:^|\s+)c(?:\s+|$)"i) {
- # Don't emit a warning, since the comment
- # probably contains a statement that C is
- # really not needed.
-
- } elsif ($value !~ qr"(?:^|\s+)(?:c|objc)(?:\s+|$)") {
- $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ...");
- $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES.");
- }
+ } elsif ($value !~ qr"(?:^|\s+)(?:c|objc)(?:\s+|$)") {
+ $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ...");
+ $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES.");
}
}
my $distname_line = $pkgctx_vardef->{"DISTNAME"};
my $pkgname_line = $pkgctx_vardef->{"PKGNAME"};
- my $distname = (defined($distname_line) && $distname_line->text =~ regex_varassign) ? $3 : undef;
- my $pkgname = (defined($pkgname_line) && $pkgname_line->text =~ regex_varassign) ? $3 : undef;
+ my $distname = defined($distname_line) ? $distname_line->get("value") : undef;
+ my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef;
if (defined($pkgname) && defined($distname) && ($pkgname eq $distname || $pkgname eq "\${DISTNAME}")) {
$pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You don't need to define PKGNAME.");
@@ -6526,7 +6649,7 @@ sub checkfile_patch($) {
(defined($addlines) && $addlines > 0))) {
if (defined($context_scanning_leading)) {
if ($leading_context_lines != $trailing_context_lines) {
- $opt_debug and $line->log_warning("The hunk that ends here does not have as many leading (${leading_context_lines}) as trailing (${trailing_context_lines}) lines of context.");
+ $opt_debug_patches and $line->log_warning("The hunk that ends here does not have as many leading (${leading_context_lines}) as trailing (${trailing_context_lines}) lines of context.");
}
}
$nextstate = $newstate;
@@ -6864,7 +6987,7 @@ sub checkfile_PLIST($) {
} elsif ($text =~ qr"^etc/") {
my $f = "mk/pkginstall/bsd.pkginstall.mk";
- assert(-f "${cwd_pkgsrcdir}/${f}");
+ assert(-f "${cwd_pkgsrcdir}/${f}", "${cwd_pkgsrcdir}/${f} is not a regular file.");
$line->log_error("Configuration files must not be registered in the PLIST. Please use the CONF_FILES framework, which is described in ${f}.");
} elsif ($text =~ qr"^include/.*\.(?:h|hpp)$") {
@@ -7094,6 +7217,7 @@ sub checkdir_root() {
return;
}
+ parselines_mk($lines);
if (0 <= $#{$lines}) {
checkline_rcsid_regex($lines->[0], qr"#\s+", "# ");
}
@@ -7147,6 +7271,7 @@ sub checkdir_category() {
log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
return;
}
+ parselines_mk($lines);
$lineno = 0;
@@ -7360,6 +7485,7 @@ sub checkdir_package() {
foreach my $fname (@files) {
if ($fname =~ qr"^((?:.*/)?Makefile\..*|.*\.mk)$"
&& (defined(my $lines = load_lines($fname, true)))) {
+ parselines_mk($lines);
determine_used_variables($lines);
}
}