autoconf-patches
[Top][All Lists]
Advanced

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

Re: 10-fyi-autom4te-trace-patterns.patch


From: Akim Demaille
Subject: Re: 10-fyi-autom4te-trace-patterns.patch
Date: 10 Aug 2001 09:52:16 +0200
User-agent: Gnus/5.0808 (Gnus v5.8.8) XEmacs/21.4 (Academic Rigor)

>>>>> "Russ" == Russ Allbery <address@hidden> writes:

Russ> You should be able to put the file you're loading with do into
Russ> another namespace with a package directive in the file... does
Russ> that not work for what you're trying to do?

Err, maybe :)  Here is what I'm trying to do:

~/src/ace % cat /tmp/foo.pl                                       nostromo 9:31
#! /usr/bin/perl

use Carp;

# source ($FILE)
# --------------
sub source
{
  my ($file) = @_;

  (my $return) = do "$file";

  croak "$me: cannot parse $file: address@hidden" if $@;
  croak "$me: cannot do $file: $!\n"    if $!;
  croak "$me: cannot run $file\n"       unless $return;
}


sub try
{
  my $bar = "You lose.";
  source ('/tmp/bar1.pl');
  print $bar, "\n";
  source ('/tmp/bar2.pl');
  print $bar, "\n";
}

system ('cat >/tmp/bar1.pl <<\EOF
$bar = "You win!";
EOF
');

system ('cat >/tmp/bar2.pl <<\EOF
package caller;
$bar = "You win!";
EOF
');

try;
~/src/ace % perl /tmp/foo.pl                                      nostromo 9:31
You lose.
You lose.
~/src/ace %                                                       nostromo 9:31

(but again, it is my understanding this is prohibited for `my': if I
use `local $bar' both work.  I want to know if there is a means to do
that with `my' vars).

Russ> The problem that you're having with chop (and well, first off,
Russ> you don't want to be using chop; you want to be using chomp
Russ> instead, which only removes newlines and is therefore safer than
Russ> chop which will remove the last character no matter what it is)

OK, thanks!

Russ> is that you're using it inside the code block of a map or grep,
Russ> so it *is* in a scalar context.

OK.  What can I do to tell it its an array context?

Russ> What you actually want to do is chomp a list.  And as it
Russ> happens, chomp can take a list as an argument.  So instead just
Russ> write:

Russ>     my @patterns = new IO::File ("$tmp/patterns")->getlines;
Russ> chomp @patterns;

Russ> and that will do exactly what you want.

Thanks!  I had not realized.

Russ> Second, with these lines:

> my $forbidden = join ('|', grep { s/^forbid:// } @patterns) ||"^\$"; 
> my $allowed =   join ('|', grep { s/^allow:// }  @patterns) || "^\$";

Russ> remember that $_ inside the code block of a grep or map is an
Russ> *alias* for the corresponding element of the list.  You're
Russ> assuming that grep makes a copy of @patterns and then applies
Russ> the code block to it, when what actually happens is that grep
Russ> iterates over @patterns and makes $_ an alias for each element
Russ> in turn.  So the s/// pattern is affecting the original list.

Yes, I understood this.  That's actually what the comment was saying:

  # A potential bad bug is that the grep for $forbidden and $allowed
  # *do modify @PATTERNS!  So when $FORBIDDEN is computed, @PATTERNS
  # still contains the forbidden patterns, but without the leading
  # `forbid:'.  So if some use forbids `allow:FOO', @ALLOW will receive
  # `FOO', which is _bad_.  But since `:' is not valid in macro names,
  # this is science fiction.


Russ> What you want in this case so far as I can tell is to grap all
Russ> of the patterns in @patterns beginning with "forbid:" (or
Russ> "allow:") and store them in a variable, separated by |, with the
Russ> prefix removed.  Try:

Russ> my $forbidden = join ('|', map { /^forbid:(.*)/ } @patterns) || "^\$";

Hm, I had not realized either I could use $1...  Thanks!

Russ> This code is slightly more straightforward, IMO, if written as
Russ> three separate commands, but that approach will get it on one
Russ> line (which has other benefits for readability, so it's probably
Russ> a wash).  

Yep, this is really what I meant to write.

Russ> What that's doing instead is using a pattern match to extract
Russ> the portion that you're interested in rather than a substitution
Russ> to remove the portion that you don't want, and then using the
Russ> behavior of m// in a list context to return the result of the
Russ> pattern match.

Aaaaaaah!  Yet another thanks :)


Thanks a lot!

I have one last question.  The documentation for map says:

       map BLOCK LIST
       map EXPR,LIST
               [...]  Evalu­
               ates BLOCK or EXPR in list context, so each ele­
               ment of LIST may produce zero, one, or more ele­
               ments in the returned value.

and I just don't know how to return 0 elements.  I tried this, without
success:

~/src/ace % cat /tmp/map.pl                                       nostromo 9:43
#! /usr/bin/perl -w

my @list = ('0: even', '1: odd', '2: even', '3: odd');

my @evens = map { $1 if m/(\d): even/ } @list;
my @odds  = map { $1 if m/(\d): odd/  } @list;

print "Odds:  ", join (',', @odds), "\n";
print "Evens: ", join (',', @evens), "\n";
~/src/ace % perl /tmp/map.pl                                      nostromo 9:44
Odds:  ,1,,3
Evens: 0,,2,


Clearly, I do return 1 element each time, empty though.  So my
question is ``how to return 0 elements?´´.

Thanks, I really appreciate your help!  Here is what I commit:

Index: ChangeLog
from  Akim Demaille  <address@hidden>

        * bin/autom4te.in (&handle_output): Don't use `grep' with side
        effects.
        Suggested by Russ Allbery.

Index: bin/autom4te.in
===================================================================
RCS file: /cvs/autoconf/bin/autom4te.in,v
retrieving revision 1.24
diff -u -u -r1.24 autom4te.in
--- bin/autom4te.in 2001/08/09 10:27:40 1.24
+++ bin/autom4te.in 2001/08/10 07:47:31
@@ -552,26 +552,14 @@
   verbose "creating $output";
 
   # Load the forbidden/allowed patterns.
-  #
-  # I'm having fun with grep and map, but it's not extremely safe here...
-  # First of all, I still don't understand why I can't use `map' for
-  # instance to get @PATTERNS: `chop' thinks it's in a scalar context
-  # and returns 1 instead of `$_' :(.
-  #
-  # A potential bad bug is that the grep for $forbidden and $allowed
-  # *do modify @PATTERNS!  So when $FORBIDDEN is computed, @PATTERNS
-  # still contains the forbidden patterns, but without the leading
-  # `forbid:'.  So if some use forbids `allow:FOO', @ALLOW will receive
-  # `FOO', which is _bad_.  But since `:' is not valid in macro names,
-  # this is science fiction.
-  #
-  # Still, if someone could teach me how to write this properly... --akim
   handle_traces ($req, "$tmp/patterns",
                 ('m4_pattern_forbid' => 'forbid:$1',
                  'm4_pattern_allow'  => 'allow:$1'));
-  my @patterns = grep { chop } new IO::File ("$tmp/patterns")->getlines;
-  my $forbidden = join ('|', grep { s/^forbid:// } @patterns) || "^\$";
-  my $allowed   = join ('|', grep { s/^allow:// }  @patterns) || "^\$";
+  my @patterns = new IO::File ("$tmp/patterns")->getlines;
+  chomp @patterns;
+  my $forbidden = join ('|', map { /^forbid:(.*)/ } @patterns) || "^\$";
+  my $allowed   = join ('|', map { /^allow:(.*)/  } @patterns) || "^\$";
+
   verbose "forbidden tokens: $forbidden";
   verbose "allowed   tokens: $allowed";
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]