pkgsrc-Changes-HG archive

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

[pkgsrc/trunk]: pkgsrc/pkgtools/pkglint/files Added a new check for SUBST blo...



details:   https://anonhg.NetBSD.org/pkgsrc/rev/e3028298726d
branches:  trunk
changeset: 514783:e3028298726d
user:      rillig <rillig%pkgsrc.org@localhost>
date:      Sun Jun 18 00:48:47 2006 +0000

description:
Added a new check for SUBST blocks. In contrast to all other checks,
this one is defined in PkgLint::SubstContext instead of the main
package. Time will show whether this was a good decision. Since the
checking subroutines heavily modify the fields of the SubstContext, it
seems to be Done Right.

diffstat:

 pkgtools/pkglint/files/pkglint.pl |  165 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 163 insertions(+), 2 deletions(-)

diffs (208 lines):

diff -r abef4d25f827 -r e3028298726d pkgtools/pkglint/files/pkglint.pl
--- a/pkgtools/pkglint/files/pkglint.pl Sun Jun 18 00:45:45 2006 +0000
+++ b/pkgtools/pkglint/files/pkglint.pl Sun Jun 18 00:48:47 2006 +0000
@@ -1,5 +1,5 @@
 #! @PERL@
-# $NetBSD: pkglint.pl,v 1.627 2006/06/17 22:46:45 rillig Exp $
+# $NetBSD: pkglint.pl,v 1.628 2006/06/18 00:48:47 rillig Exp $
 #
 
 # pkglint - static analyzer and checker for pkgsrc packages
@@ -1303,6 +1303,162 @@
 
 #== End of PkgLint::VarUseContext =========================================
 
+package PkgLint::SubstContext;
+#==========================================================================
+# This class records the state of a block of variable assignments that make
+# up a SUBST class. As these variable assignments are not easy to get right
+# unless you do it every day, and the possibility of typos is high, pkglint
+# provides additional checks for them.
+#==========================================================================
+
+BEGIN {
+       import PkgLint::Util qw(
+               false true
+       );
+       import PkgLint::Logging qw(
+               log_warning
+       );
+}
+
+use constant SUBST_CLASS       => 0;
+use constant SUBST_STAGE       => 1;
+use constant SUBST_MESSAGE     => 2;
+use constant SUBST_FILES       => 3;
+use constant SUBST_SED         => 4;
+use constant SUBST_FILTER_CMD  => 5;
+
+sub new($) {
+       my ($class) = @_;
+       my ($self) = ([undef, undef, undef, [], [], undef]);
+       bless($self, $class);
+       return $self;
+}
+
+sub subst_class($)             { return shift(@_)->[SUBST_CLASS]; }
+sub subst_stage($)             { return shift(@_)->[SUBST_STAGE]; }
+sub subst_message($)           { return shift(@_)->[SUBST_MESSAGE]; }
+sub subst_files($)             { return shift(@_)->[SUBST_FILES]; }
+sub subst_sed($)               { return shift(@_)->[SUBST_SED]; }
+sub subst_filter_cmd($)                { return shift(@_)->[SUBST_FILTER_CMD]; }
+
+sub init($) {
+       my ($self) = @_;
+
+       $self->[SUBST_CLASS] = undef;
+       $self->[SUBST_STAGE] = undef;
+       $self->[SUBST_MESSAGE] = undef;
+       $self->[SUBST_FILES] = [];
+       $self->[SUBST_SED] = [];
+       $self->[SUBST_FILTER_CMD] = undef;
+}
+
+sub check_end($$) {
+       my ($self, $line) = @_;
+
+       return unless defined($self->subst_class);
+
+       if (!defined($self->subst_stage)) {
+               $line->log_warning("Incomplete SUBST block: SUBST_STAGE missing.");
+       }
+       if (!defined($self->subst_message)) {
+               $line->log_note("Incomplete SUBST block: SUBST_MESSAGE missing.");
+       }
+       if (@{$self->subst_files} == 0) {
+               $line->log_warning("Incomplete SUBST block: SUBST_FILES missing.");
+       }
+       if (@{$self->subst_sed} == 0 && !defined($self->subst_filter_cmd)) {
+               $line->log_warning("Incomplete SUBST block: SUBST_SED missing.");
+       }
+       $self->init();
+}
+
+sub check_varassign($$$$$) {
+       my ($self, $line, $varname, $op, $value) = @_;
+
+       if ($varname eq "SUBST_CLASSES") {
+               $self->check_end($line);
+
+               if ($value =~ qr"\s") {
+                       $line->log_warning("Please add only one class at a time to SUBST_CLASSES.");
+               } else {
+                       $self->[SUBST_CLASS] = $value;
+               }
+               return;
+       }
+
+       my $class = $self->subst_class;
+       if (!defined($class)) {
+               # XXX: Later, a check may be added that SUBST_* variables
+               # are not assigned in other paragraphs.
+               return;
+       }
+
+       if ($varname !~ qr"^(SUBST_(?:STAGE|MESSAGE|FILES|SED|FILTER_CMD))\.([\-\w_]+)$") {
+               $line->log_warning("Foreign variable in SUBST block.");
+               return;
+       }
+       my ($varbase, $varparam) = ($1, $2);
+
+       if ($varparam ne $class) {
+               $line->log_warning("Variable parameter \"${varparam}\" does not match SUBST class \"${class}\".");
+       }
+
+       if ($varbase eq "SUBST_STAGE") {
+               if (defined($self->subst_stage)) {
+                       $line->log_warning("Duplicate definition of SUBST_STAGE.${class}.");
+               } else {
+                       $self->[SUBST_STAGE] = $value;
+               }
+
+       } elsif ($varbase eq "SUBST_MESSAGE") {
+               if (defined($self->subst_message)) {
+                       $line->log_warning("Duplicate definition of SUBST_MESSAGE.${class}.");
+               } else {
+                       $self->[SUBST_MESSAGE] = $value;
+               }
+
+       } elsif ($varbase eq "SUBST_FILES") {
+               if (@{$self->subst_files} > 0) {
+                       if ($op ne "+=") {
+                               $line->log_warning("All but the first SUBST_FILES line should use the \"+=\" operator.");
+                       }
+                       push(@{$self->subst_files}, $value);
+               }
+
+       } elsif ($varbase eq "SUBST_SED") {
+               if (@{$self->subst_sed} > 0) {
+                       if ($op ne "+=") {
+                               $line->log_warning("All but the first SUBST_SED line should use the \"+=\" operator.");
+                       }
+                       push(@{$self->subst_sed}, $value);
+               }
+
+       } elsif ($varbase eq "SUBST_FILTER_CMD") {
+               if (defined($self->subst_filter_cmd)) {
+                       $line->log_warning("Duplicate definition of SUBST_FILTER_CMD.${class}.");
+               } else {
+                       $self->[SUBST_FILTER_CMD] = $value;
+               }
+
+       } else {
+               $line->log_warning("Foreign variable in SUBST block.");
+       }
+}
+
+sub to_string($) {
+       my ($self) = @_;
+
+       return sprintf("SubstContext(%s %s %s %s %s)",
+           (defined($self->subst_class) ? $self->subst_class : "(undef)"),
+           (defined($self->subst_stage) ? $self->subst_stage : "(undef)"),
+           (defined($self->subst_message) ? $self->subst_message : "(undef)"),
+           scalar(@{$self->subst_files}),
+           scalar(@{$self->subst_sed}));
+}
+
+
+#== End of PkgLint::SubstContext ==========================================
+
 package main;
 #==========================================================================
 # This package contains the application-specific code of pkglint.
@@ -4663,6 +4819,7 @@
 sub checklines_mk($) {
        my ($lines) = @_;
        my ($allowed_targets, $for_variables) = ({}, {});
+       my ($substcontext) = PkgLint::SubstContext->new();
 
        # Define global variables for the Makefile context.
        $mkctx_indentations = [0];
@@ -4681,7 +4838,7 @@
                checkline_spellcheck($line);
 
                if ($text =~ qr"^\s*$" || $text =~ qr"^#") {
-                       # Ignore empty lines and comments
+                       $substcontext->check_end($line);
 
                } elsif ($text =~ regex_varassign) {
                        my ($varname, $op, $value, $comment) = ($1, $2, $3, $4);
@@ -4697,6 +4854,7 @@
                                }
                        }
                        checkline_mk_varassign($line, $varname, $op, $value, $comment);
+                       $substcontext->check_varassign($line, $varname, $op, $value);
 
                } elsif ($text =~ regex_shellcmd) {
                        my ($shellcmd) = ($1);
@@ -4845,6 +5003,9 @@
                        $line->log_error("[Internal] Unknown line format: $text");
                }
        }
+       if (@{$lines} > 0) {
+               $substcontext->check_end($lines->[-1]);
+       }
 
        checklines_trailing_empty_lines($lines);
 



Home | Main Index | Thread Index | Old Index