chiark / gitweb /
test/filter; Cause some warnings, to check they appear
[subdirmk.git] / generate
index a6a6cda90c6b1e032dabf49797086c0280789a41..13809183f4050d6eafe2b2096716adad3dcd48eb 100755 (executable)
--- a/generate
+++ b/generate
@@ -152,6 +152,8 @@ Makefile run-main.mk:
 END
 }
 
+our %varref;
+
 our ($dir_prefix, $dir_suffix, $dir_name,
      $var_prefix, $var_prefix_name);
 
@@ -176,6 +178,11 @@ sub err ($) {
     die "subdirmk: ${err_file}:$.: $m\n";
 }
 
+sub wrn ($) {
+    my ($m) = @_;
+    print STDERR "subdirmk: warning: ${err_file}:$.: $m\n";
+}
+
 sub ddbl_only ($) {
     my ($e) = @_;
     return if $ddbl;
@@ -216,6 +223,7 @@ sub process_input_mk ($$$$) {
 
     local $ddbl;
     my @nest = (['']);
+    my $evalcall_brackets;
 
     my $push_nest = sub {
        my ($nk, $nndbl, $what) = @_;
@@ -229,7 +237,18 @@ sub process_input_mk ($$$$) {
        $ddbl = (shift @nest)[1];
     };
 
+    # Our detection of variable settings does not have to be completely
+    # accurate, since it is only going to be used for advice to the user.
+    my $note_varref = sub {
+       my ($vn,$amp) = @_;
+       $varref{$vn}{$amp}{"$f:$."} = 1;
+    };
+
     while (<$input>) {
+       if (m#^\s*($esc)?(\w+)\s*(?:=|\+=|\?=|:=)# ||
+           m#^\s*(?:$esc\:macro|define)\s+($esc)?(\S+)\s#) {
+           $note_varref->($2,!!$1);
+       }
        if (s#^\s*$esc\:changequote\s+(\S+)\s+$##) {
            $$esclitr = $1;
            $set_esc->();
@@ -244,23 +263,39 @@ sub process_input_mk ($$$$) {
            err "unknown directive &:$1 or bad argumnt syntax";
        } elsif (s{^\s*${esc}TARGETS(?:_([0-9a-zA-Z_]+))?(?=\W)}{}) {
            my $t = $1 // 'all';
-           od target_varname($var_prefix, $t);
+           my $vn = target_varname($var_prefix, $t);
+           $note_varref->($vn,1);
+           od $vn;
            $targets->{$t} //= [ ];
        }
        for (;;) {
            err 'cannot $-double &-processed RHS of directive'
                if $ddbl && defined $buffering_output;
            unless ($nest[0][0] eq 'eval'
-                   ? s{^(.*?)($esc|[{}])}{}
-                   : s{^(.*?)($esc)}{}) { od $_; last; }
+                   ? s{^(.*?)($esc|\$|[{}])}{}
+                   : s{^(.*?)($esc|\$)}{}) { od $_; last; }
            od $1;
            if ($2 eq '{') {
-               $ddbl++;
+               od $2;
+               $evalcall_brackets++;
                next;
            } elsif ($2 eq '}') {
-               next if --$ddbl;
+               od $2;
+               next if --$evalcall_brackets;
                $pop_nest->('eval');
-               od '}}';
+               od '}';
+               next;
+           } elsif ($2 eq '$') {
+               od $2;
+               if (s{^\$}{}) { od $&; }
+               elsif (m{^[a-zA-Z]\w}) {
+                   wrn
+                   'possibly confusing unbracketed single-char $-expansion';
+               }
+               elsif (m{^\(($esc)?([^()\$]+)\)} ||
+                      m{^\{($esc)?([^{}\$]+)\}}) {
+                   $note_varref->($2,!!$1);
+               }
                next;
            }
            if (s{^\\$esc}{}) { od "$$esclitr" }
@@ -268,7 +303,10 @@ sub process_input_mk ($$$$) {
            elsif (s{^\\\s+$}{}) { }
            elsif (s{^$esc}{}) { od "$$esclitr$$esclitr" }
            elsif (m{^(?=$caps_re)}) { od $var_prefix }
-           elsif (s{^\$([A-Za-z]\w+)}{}) { od "\$(${var_prefix}$1)" }
+           elsif (s{^\$([A-Za-z]\w+)}{}) {
+               $note_varref->($1,1);
+               od "\$(${var_prefix}$1)";
+           }
            elsif (s{^([~^]?)(?=$lc_re)}{}) { od $pfxmap{$1} }
            elsif (s{^_}{}) { od $var_prefix }
            elsif (s{^=}{}) { od $var_prefix_name }
@@ -277,12 +315,17 @@ sub process_input_mk ($$$$) {
            elsif (s{^([~^])\.}{}) { od $srcdirmap{$1} }
            elsif (s{^\$\-}{}) { $ddbl=undef; }
            elsif (s{^\$\+}{}) { $ddbl=1; }
-           elsif (s{^\$\(}{}) { ddbl_only($&); oud "\$("; }
+           elsif (s{^\$\(}{}) {
+               ddbl_only($&); oud "\$(";
+               $note_varref->($2,!!$1) if m{^($esc)?([^()\$]+\))};
+           }
            elsif (s{^\$(\d+)}{}) { ddbl_only($&); oud "\$($1)"; }
            elsif (s{^\$\{}{}) {
                err 'macro invocation cannot be re-$-doubled' if $ddbl;
                od '${eval ${call ';
+               $evalcall_brackets = 1;
                $push_nest->('eval',1, '&${...}');
+               $note_varref->($2,!!$1) if m{^\s*($esc)?([^,{}\$]+)};
            } elsif (s{^([~^]?)(?=[ \t])}{}) {
                my $prefix = $pfxmap{$1} // die "internal error ($1?)";
                my $after='';
@@ -384,16 +427,16 @@ sub process_subtree ($$) {
     my @targets = sort keys %targets;
     foreach my $target (@targets) {
        my $target_varname = target_varname($var_prefix, $target);
-       print O "${dir_prefix}${target}:: \$($target_varname)";
+       oraw "${dir_prefix}${target}:: \$($target_varname)";
        foreach my $child_subdir (@{ $targets{$target} }) {
-           print O " $child_subdir/$target";
+           oraw " $child_subdir/$target";
        }
-       print O "\n";
+       oraw "\n";
     }
     if (@targets) {
-       print O ".PHONY:";
-       print O " ${dir_prefix}${_}" foreach @targets;
-       print O "\n";
+       oraw ".PHONY:";
+       oraw " ${dir_prefix}${_}" foreach @targets;
+       oraw "\n";
     }
 
     return @targets;
@@ -431,6 +474,24 @@ sub process_tree() {
     oraw "include \$(SUBDIRMK_MAKEFILES)\n";
 }
 
+sub flmap ($) { local ($_) = @_; s{:(\d+)$}{ sprintf ":%10d", $1 }e; $_; }
+
+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";
+       foreach my $amp ('', 1) {
+           printf STDERR " saw %s%s at %s\n",
+               ($amp ? '&' : ''), $vn, $_
+               foreach
+               sort { flmap($a) cmp flmap($b) }
+               keys %{ $vv->{$amp} };
+       }
+    }
+}
+
 build_tree();
 process_tree();
+print_varref_warnings();
 install_output_files();