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

[Fun With Perl] Re: One of those fancy .sig files



Just for completeness (if I'm collecting, maybe someone else is too), 
here's the way I worked this one out (and also Russ's explanation). 
My solution was similar to Michael Schwern's but I concentrated on 
different aspects. (I never calculated the precise character 
translation table. cool)

  > #!/usr/bin/perl -- Russ Allbery, Just Another Perl Hacker
  > $^=q;@!>~|{>krw>yn{u<$$<[~||<Juukn{=,<S~|}<Jwx}qn{<Yn{u<Qjltn{ > 0gFzD gD,
  >  00Fz, 0,,( 0hF 0g)F/=, 0> "L$/GEIFewe{,$/ 0C$~> "@=,m,|,(e 0.), 01,pnn,y{
  > rw} >;,$0=q,$,,($_=$^)=~y,$/ C-~><@=\n\r,-~$:-u/ #y,d,s,(\$.),$1,gee,print
  >
  >                                                  ^
  >                                                  |
  >                                                  why does it even *see*
  > the print statement?
 
  Because that isn't a comment, it's a sharp sign ;-)
 
  He's fooling you, making you see things that aren't there.
  It's a classic magic trick.
 
  Try it like this:

   #!/usr/bin/perl -- Russ Allbery, Just Another Perl Hacker
   $^ = q;
       @!>~|{>krw>yn{u<$$<[~||<Juukn{=,<S~|}<Jwx}qn{<Yn{u<Qjltn{ > 0gFzD gD,
       00Fz, 0,,( 0hF 0g)F/=, 0> "L$/GEIFewe{,$/ 0C$~> "@=,m,|,(e 0.), 01,pnn,y{
        rw} >
     ;
   ,
   $0 = q,$,
   ,
   ($_=$^) =~ y,$/ C-~><@=\n\r,-~$:-u/ #y,d
   ,
   s,(\$.),$1,gee
   ,
   print

  I _think_ what's going on is this (I haven't walked it all the way through):
 
    1)   $^ = q;    <------ this isn't a semicolon, this is a delimiter
 
    2)   The ; could have been anything as long as it is eventually matched
 
    3)   There are no actual statement-ending ; in the whole thing.
 
    4) He also makes plentiful use of the side effects of the comma operator
 
  Try looking at this:

      $^ = q/hey/, $0 = q/$/ , ($_=$^) =~ y/a/b/d, s/(\$.)/$1/gee, print

  I think it's essentially the same format (different content and 
results, of course).
 
  That # is probably what's printing the # in #!.... in the output
 
 
 
# To: Vicki Brown <vlb@cfcl.com>
# Subject: Re: JAPH
# From: Russ Allbery <rra@stanford.edu>
# Date: 15 Feb 1999 03:20:47 -0800
# Lines: 96
#
# Vicki Brown <vlb@cfcl.com> writes:
#
# > A co-worker forwarded me your sig (which I have been trying to ignore
# > :-)
#
# *laugh*
#
# > Here's my breakdown.  Am I close?
#
# Yup!  Very.
#
# > I _think_ what's going on is this (I haven't walked it all the way
# > through):
#
# >   1) $^ = q; <------ this isn't a semicolon, this is a delimiter
# >   2) The ; could have been anything as long as it is eventually matched
# >   3) There are no actual statement-ending ; in the whole thing.
#
# Yup.
#
# >   4) He also makes plentiful use of the side effects of the comma
# >   operator.
#
# I'm actually just using it for all of:  a quoting symbol with q, a
# delimiter with both y/// and s///, and as a statement separator.
#
# > Try looking at this:
#
# >      $^ = q/hey/, $0 = q/$/ , ($_=$^) =~ y/a/b/d, s/(\$.)/$1/gee, print
#
# Ayup.
#
# > That # is probably what's printing the # in #!.... in the output
#
# Sort of.  It's what @ signs get mapped to.  Here's the "official"
# explanation that I wrote up a while back since I get asked how it works in
# e-mail on a periodic basis:
#
   #!/usr/bin/perl -- Russ Allbery, Just Another Perl Hacker
   $^=q;@!>~|{>krw>yn{u<$$<[~||<Juukn{=,<S~|}<Jwx}qn{<Yn{u<Qjltn{ > 0gFzD gD,
   00Fz, 0,,( 0hF 0g)F/=, 0> "L$/GEIFewe{,$/ 0C$~> "@=,m,|,(e 0.), 01,pnn,y{
   rw} >;,$0=q,$,,($_=$^)=~y,$/ C-~><@=\n\r,-~$:-u/ #y,d,s,(\$.),$1,gee,print
#
# The first thing to notice is that it actually begins with a variable
# assignment, and quite a bit of the rest is a quoted string (starting with
# q) that uses ; as the quote character.  So this is a single assignment:
#
   $^=q;@!>~|{>krw>yn{u<$$<[~||<Juukn{=,<S~|}<Jwx}qn{<Yn{u<Qjltn{ > 0gFzD gD,
   00Fz, 0,,( 0hF 0g)F/=, 0> "L$/GEIFewe{,$/ 0C$~> "@=,m,|,(e 0.), 01,pnn,y{
   rw} >;
#
# Then we do this:
#
   $0=q,$,
#
# which just assigns '$' to $0.  Now....
#
   ($_=$^)=~y,$/ C-~><@=\n\r,-~$:-u/ #y,d
#
# makes a copy of the first string that we assigned to $^, puts it in $_
# (the default variable for the print we're going to do later), and then
# does a y/// on it (same as a tr///).  I use , as the delimiter for y///.
# This is the part that decodes the string.  The mapping is:
#
   $/ C-~><@=   # ...maps to...
   -~$:-u/ #y
#
# Note that there's a range in there; the range C-~ maps to :-u.  You need
# an ASCII chart to see precisely what that does, but you can apply that
# transform to the string and get something that looks much more familiar
# (it includes the string "#!/usr/bin/perl -- Russ Allbery"..., for example.
#
# It also deletes \r and \n characters, to strip off the line endings.
#
   s,(\$.),$1,gee
#
# is a substitute on the decoded string.  $ followed by a single character
# is replaced by that string evaluated twice (/ee) globally (/g).  This
# causes $0 to turn into $ (so we can escape $'s in the string as $0) and
# more importantly replaces $^ with the original quoted string.  That's the
# magic that allows the whole thing to be self-printing; the trick to
# writing self-printing programs is to find a way to use the same string
# twice in the output.  The quoted string that we put in $^ becomes the text
# at the beginning and end of the sig after it was decoded, and then the
# original encoded string is embedded in the middle again to get the
# original sig back.  Note that $/ is also present in the decoded string and
# becomes \n to preserve the original line endings.
#
# Finally:
#
# print
#
# just prints out $_, which at this point contains the entire sig.
#
# --
# Russ Allbery (rra@stanford.edu)         <URL:http://www.eyrie.org/~eagle/>
-- --
        |\      _,,,---,,_       Vicki Brown <vlb@cfcl.com>
  ZZZzz /,`.-'`'    -.  ;-;;,_   Journeyman Sourceror: Scripts & Philtres
       |,4-  ) )-,_. ,\ (  `'-'  P.O. Box 1269  San Bruno  CA  94066
      '---''(_/--'  `-'\_) http://www.cfcl.com/~vlb  http://www.macperl.org

==== Want to unsubscribe from this list? (Don't you love us anymore?)
==== Well, if you insist... Send mail with body "unsubscribe" to
==== fwp-request@technofile.org

</x-flowed>