chiark / gitweb /
Warning reporting: Warning suppression system
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 28 Dec 2019 13:55:12 +0000 (13:55 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 30 Dec 2019 11:35:16 +0000 (11:35 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
README
generate
tests/filter/stderr.expected

diff --git a/README b/README
index e5e937f..98fe313 100644 (file)
--- a/README
+++ b/README
@@ -269,6 +269,14 @@ So pathname syntax is a subset of:
        `all' is extra special: every directory has an `all'
        target, which corresponds to &TARGETS.
 
+&:warn [!]WARNTAG ...
+       Suppress (with !) or re-enable (without !) warnings tagged
+       WARNTAG (see section `Warnings', below).  The suppression list
+       is reset at the start of processing in each subdirectory.
+       Warnings that appear at the end of processing are controlled
+       by the final warning state after processing all the toplevel
+       input files (including Final.sd.mk).
+
 &:changequote NEWQUOTE
        changes the escape sequence from & to literally NEWQUOTE
        NEWQUOTE may be any series of of non-whitespace characters,
@@ -373,6 +381,31 @@ In more detail, with all the various options laid out:
 (This assumes you have appropriate make variables src, PWD and
 abs_src.)
 
+Warnings
+--------
+
+subdirmk's `generate' program, which does the acual &-substitution,
+can produce some warnings about your .sd.mk files.  These can be
+suppressed with the &:warn directive.  The warning tags are:
+
+    local+global
+       The same VARNAME was used both with and without an & prefix.
+       This can be confusing.  Also, if you avoid this then you will
+       get a warning iff you accidentally leave off a needed &.
+
+    single-char-var
+       A variable expansion like $FBAR.  make's expansion rules
+       interpret this as $(F)BAR.  It's normally better to write
+       it this way, at least if the variable expansion is followed
+       by more letters.  Note that &$FOO works differently to
+       raw make: it expands to $(sub_dir_FOO).
+
+    unknown-warning
+       &:warn was used to try to enable a warning that this version
+       of subdirmk does not understand.  (Note that an attempt to
+       *dis*able an unknown warning is only reported if some other
+       warning was issued which might have been disabled.)
+
 Subdirectory and variable naming
 --------------------------------
 
index 1380918..3caf4e6 100755 (executable)
--- a/generate
+++ b/generate
@@ -173,14 +173,32 @@ sub set_dir_vars ($) {
 
 our $err_file;
 
+our @warn_ena_dfl = map { $_ => 1 } qw(
+    local+global
+    single-char-var
+    unknown-warning
+);
+our %warn_ena = @warn_ena_dfl;
+
+our $warned;
+our %warn_unk;
+
 sub err ($) {
     my ($m) = @_;
     die "subdirmk: ${err_file}:$.: $m\n";
 }
 
-sub wrn ($) {
-    my ($m) = @_;
-    print STDERR "subdirmk: warning: ${err_file}:$.: $m\n";
+sub wrncore ($$) {
+    my ($wk,$m) = @_;
+    return 0 unless $warn_ena{$wk} // warn "internal error $wk ?";
+    $warned++;
+    print STDERR "subdirmk: warning ($wk): $m\n";
+    return 1;
+}
+
+sub wrn ($$) {
+    my ($wk,$m) = @_;
+    wrncore($wk, "${err_file}:$.: $m");
 }
 
 sub ddbl_only ($) {
@@ -257,6 +275,20 @@ sub process_input_mk ($$$$) {
            $pop_nest->('macro');
            od "endef\n";
            next;
+       } elsif (s#^\s*$esc\:warn\s+(\S.*)$##) {
+           foreach my $wk (split /\s+/, $1) {
+               my $yes = $wk !~ s{^!}{};
+               if (defined $warn_ena{$wk}) {
+                   $warn_ena{$wk} = $yes;
+                   next;
+               } elsif ($yes) {
+                   wrn 'unknown-warning',
+                       "unknown warning $wk requested";
+               } else {
+                   $warn_unk{$wk} //= "$f:$.";
+               }
+           }
+           next;
        } elsif (s#^\s*$esc\:(?=(-?)include|macro)##) {
            $buffering_output='';
        } elsif (m#^\s*$esc\:([a-z][-0-9a-z_]*)#) {
@@ -289,7 +321,7 @@ sub process_input_mk ($$$$) {
                od $2;
                if (s{^\$}{}) { od $&; }
                elsif (m{^[a-zA-Z]\w}) {
-                   wrn
+                   wrn 'single-char-var',
                    'possibly confusing unbracketed single-char $-expansion';
                }
                elsif (m{^\(($esc)?([^()\$]+)\)} ||
@@ -402,6 +434,7 @@ sub process_subtree ($$) {
        my @childpath = (@$path, $child->[0]);
        my $child_subdir = join '/', @childpath;
        mkdir $child_subdir or $!==EEXIST or die "mkdir $child_subdir: $!\n";
+       local %warn_ena = @warn_ena_dfl;
        push @{ $targets{$_} }, $child_subdir foreach
            process_subtree($child, \@childpath);
     }
@@ -480,7 +513,7 @@ sub print_varref_warnings () {
     foreach my $vn (sort keys %varref) {
        my $vv = $varref{$vn};
        next unless $vv->{''} && $vv->{1};
-       print STDERR "subdirmk: warning: saw both $vn and &$vn\n";
+       wrncore 'local+global', "saw both $vn and &$vn" or return;
        foreach my $amp ('', 1) {
            printf STDERR " saw %s%s at %s\n",
                ($amp ? '&' : ''), $vn, $_
@@ -491,7 +524,16 @@ sub print_varref_warnings () {
     }
 }
 
+sub print_warning_warnings () {
+    return unless $warned;
+    foreach my $wk (sort keys %warn_unk) {
+       wrncore 'unknown-warning',
+           "$warn_unk{$wk}: attempt to suppress unknown warning(s) \`$wk'";
+    }
+}
+
 build_tree();
 process_tree();
 print_varref_warnings();
+print_warning_warnings();
 install_output_files();
index 0700625..5568e62 100644 (file)
@@ -1,5 +1,5 @@
-subdirmk: warning: ./Dir.sd.mk:8: possibly confusing unbracketed single-char $-expansion
-subdirmk: warning: saw both WARN and &WARN
+subdirmk: warning (single-char-var): ./Dir.sd.mk:8: possibly confusing unbracketed single-char $-expansion
+subdirmk: warning (local+global): saw both WARN and &WARN
  saw WARN at ./Dir.sd.mk:6
  saw WARN at ./Dir.sd.mk:9
  saw &WARN at ./Dir.sd.mk:7