http://www.perlmonks.org?node_id=89199

This not an obfuscation per se, but rather a proof of concept... (which doesn't support -w)

use strict;my$s=';pop';$_='';# 59 /e, © 2001 Philippe "BooK" Bruhat *_=*ARGV;@_=qw(4a4a2bfe01ac410d0105f4fd0dae30150dfab448f90208fa0d98 pop print+chr(shift) print+chr(shift) unshift@_,(shift()+shift())x2 push@_,(pop,pop)x24 ; unshift@_,(map{unpack'c',$_}split//)[0..25] ; s/../chr(hex$&)/eg $_=substr(shift,0,52) @_=map{s|$|$s|s;$_}@_;pop) ;s//$s/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee;

Once you've understood this one (and the way it loops), you know there is no limit to the number of /e you can put in a s///.

Replies are listed 'Best First'.
Re: 59 /e
by iamcal (Friar) on Jun 18, 2001 at 11:01 UTC
    I like this JAPH alot.
    # # use strict or die # use strict; # # this is the command we use to start working on @_ in the s///e # my$s=';pop'; # # set $_ to be empty to start with # $_=''; # # a comment # # 59 /e, © 2001 Philippe "BooK" Bruhat # # ??? # *_=*ARGV; # # set up @_ to contain our list of japh commands # @_=qw(4a4a2bfe01ac410d0105f4fd0dae30150dfab448f90208fa0d98 pop print+c +hr(shift) print+chr(shift) unshift@_,(shift()+shift())x2 push@_,(pop, +pop)x24 print+join"\n",@_; unshift@_,(map{unpack'c',$_}split//)[0..25 +] ; s/../chr(hex$&)/eg $_=substr(shift,0,52) @_=map{s|$|$s|s;$_}@_;po +p); # # start the chain of evals # s//$s/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee;
    A breakdown of what the eval does (a JAPH in itself):

    # # first we do the pop as stored in $s # pop(@_); # # the pop'ed command adds ";pop" to the end of each element of @_, the +n pops the next command off the @_ array # @_=map{s|$|$s|s;$_}@_; pop(@_); # # set $_ to "4a4a2bfe01ac410d0105f4fd0dae30150dfab448f90208fa0d98" and + pop # $_=substr(shift(@_),0,52); pop(@_); # # Transform each pair of hex digits into a character and pop # s/../chr(hex$&)/eg; pop(@_); # # pop # ;;pop(@_); # # unpack each of the first 25 characters in $_ and unshift them on to +the beginning of $_ and pop # unshift@_,(map{unpack'c',$_}split//)[0..25]; pop(@_); # # pop # ;;pop(@_); # # take the last 2 elements from $_ and put them back on the beginning +again. do this 24 times (so there should be 26 pairs of these command +s in all). then pop # push(@_,(pop(@_),pop(@_))x24); pop(@_); # # do these commands 26 times: # take two chars from @_, add them, put them back on @_ and then remov +e and print them # unshift(@_,((shift(@_)+shift(@_))x2)); pop(@_); print(chr(shift(@_))); pop(@_); # # finally print the last character # print chr(shift(@_)); pop(@_); # # and do some more pop'ing # pop(@_); pop(@_);
Re: 59 /e
by John M. Dlugosz (Monsignor) on Jun 18, 2001 at 05:36 UTC
    so s//$s/eeee... is the same idea as the eval; eval; eval; ... from the other day. That iterated on $_ which exposed a different statement each time. Yours iterativly evaluates the contents of $s, in a much more compact way.

      I guess you are talking about Careful Evaluation. That one did set $_ within each eval().

      It's not exactly the same here. The program is loosely inspired from my little PostScript experience. It has a stack, and spents most of its time working with it.

      @_ (aliased to @ARGV, so that pop() works the way I want) is my stack. I store the data on the bottom of the stack, and the code on top of it. Each line of code is followed by a pop() that put the next line of code in the program counter (sort of). This is not the same as assigning to $_. In fact, $_ is only assigned the value of the result of the last instruction (a pop() on an empty @_: nothing).

      To understand the program you have to read the stack (er, @_) backwards.

      The first commands put a pop() command at the end of each element (including the data, oops), to ensure that the program will run smoothly.

      Next, the hexadecimal data (except the ;pop at the end of it, thanks to substr()) is converted into characters. (OK, this part of the program uses $_ instead of the stack.)

      The data is then split, converted into numbers (and negative ones, too, because these are considered signed characters) and shifted back in the bottom of the stack.

      Now, the loop is constructed by repeating the two commands on top of the stack 24 times (and the print() goes first). The first piece of data is converted and printed (chr 74 is a J). The next command takes the first two bits of data, add them and put the result twice on the stack. And we loop. print(), keep the result, and add it to the next data.

      By now, you found out that the hexadecimal data is the list of offset between the characters of the infamous JAPH line.

      The last print() command gives the \n, and the last two pop() clean up the stack (@_) and $_.

      Maybe not as easy as you first thought ($s remains the same during the whole program, and $_ is changed several times, without having its content evaluated).

        I'm confused about one thing. A lot of it I follow without your explanation, and your explanation makes most of the rest clear, but... well, whatever is going on with the print statement and the chr(shift) has me confounded.

        Okay, first my own analysis up to the sticking point...

        And here's where I get lost...

        # 'unshift@_,(shift()+shift())x2;pop', # 'print+chr(shift);pop' # Apparently we construct an anonymous list out of those, repeat it 24 # times, and push it (flattened, presumably) onto the tail end of @_. # This means that the next 48 instructions (err, 49) will be those two # instructions alternating. Since the first is pushed first, the # second will be popped first. Also last since It's repeated again # just above the two instructions we popped off to repeat. # WTF is that doing? # Okay, break it down... # print with no args prints $_ on STDOUT and returns... what? # [consults Camel] # print returns 1 if successful, 0 otherwise. # So we're printing $_, removing the next char from the # beginning of @_, taking its numeric value, adding one # to it (or possibly 0, but I think 1), and... throwing # that value away? What? # Also, what's on $_? Isn't it still the messy unprocessed ASCII # version of those hex data? I thought we were done with that after # we converted it and threw the result on @_? But here we're throwing # away the converted data from @_ and going back to (repeatedly) # printing $_? # HUH? # [Consults camel] # [Consults camel more] # [Consults camel yet more] # Losted am I.