pkgsrc-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[pkgsrc/trunk]: pkgsrc/pkgtools/pkglint/files Removed the --debug option, whi...



details:   https://anonhg.NetBSD.org/pkgsrc/rev/af9c7fe02ddd
branches:  trunk
changeset: 516759:af9c7fe02ddd
user:      rillig <rillig%pkgsrc.org@localhost>
date:      Thu Jul 27 13:05:09 2006 +0000

description:
Removed the --debug option, which has been superseded by the various
-D... options.

Removed the check for the :Q operator in C preprocessor macro
definitions, since we generally don't expect directory names with
embedded special characters in pkgsrc.

In buildlink3.mk files, the only BUILDLINK_* variables that may be set
are those of the current package.

The shell variables $@ and $? are now recognized. Since the shell parser
is able to parse the complete code in all pkgsrc packages, make parse
errors show in the normal pkglint output. These errors had been hidden
before.

Fixed the regular expressions in the shell parser to only match at the
beginning of the string. That way, when the shell command contains $$@,
the $@ is not removed, leaving a single $ behind.

Added some code to deal with the different parsing styles of bmake in
variable assignments and shell commands. For that, the PkgLint::Line
class has been extended to contain arbitrary additional data. This will
also allow to reduce the number of duplicate warnings later.

The assert() procedure has got a second parameter, the message to be
printed.

Variable assignment lines start start with a space character (\u0020)
are now recognized, but no warning is printed.

In pathnames and pathmasks, the '#' character is allowed, since some
packages need to remove the .#* files from CVS before installing.

diffstat:

 pkgtools/pkglint/files/pkglint.pl |  304 ++++++++++++++++++++++++++-----------
 1 files changed, 215 insertions(+), 89 deletions(-)

diffs (truncated from 705 to 300 lines):

diff -r dbc0e8a73557 -r af9c7fe02ddd pkgtools/pkglint/files/pkglint.pl
--- a/pkgtools/pkglint/files/pkglint.pl Thu Jul 27 12:00:00 2006 +0000
+++ b/pkgtools/pkglint/files/pkglint.pl Thu Jul 27 13:05:09 2006 +0000
@@ -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 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 @@
 
                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 @@
 # 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 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 @@
 # 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 $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 ($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 @@
                                => 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 @@
 # 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 @@
        |       \$\([^()]+\)            # 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 @@
                        # ignore multiple inclusion guards
 
                } else {
-                       $line->log_error("Unknown line type.");
+                       $line->log_fatal("Unknown line type.");
                }
        }
 
@@ -2329,7 +2353,7 @@
                        }
                }
        }
-       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 @@
        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 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 @@
        }
 
        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 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 @@
        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 @@
 }
 
 #
+# 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.
 #



Home | Main Index | Thread Index | Old Index