Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

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...

First thing I realise is that qw is semantically not very different from split, except that it always uses / +/ as the delimiting pattern.

So then, reading from the beginning...

First we set $s to ';pop' and clear $_ to the empty string. After the comment we do something funny with globs that apparently makes @_ and @ARGV synonymous. Then we set @_ (and thus @ARGV I think; yeah, ISTR that @ARGV is settable, but I think Perl allows that just for obfuscatory value) to that list of space-delimited strings. Finally, the substitution does all the work. For every e, apparently, it evaluates $s, and then it substitutes the final result into $_ presumably. So $s gets evaluated n times.

The real trick is figuring out how evaluating $s multiple times has the desired effect. Obviously it pops the last string (each time) off of @_ (also @ARGV), but then what?

How does this arrange for $_ to be evaluated each time?

[Consults camel re: pop()]

OOOOOH. Of course, pop returns the thing it pops off. (Duh.) Which then gets evaluated.

Hmmm... So the first e evaluates $s, which returns ';pop'; The next e evaluates _that_, which returns the last string in @_, namely, '@_=map{s|$|$s|s;$_}@_;pop'.

Err, I'm really not comfortable with map yet, so let's break that down. s|$|$s|s; is a normal substitution, probably not significantly different from s/$/$s/s; After the map the next string back is popped, so that's what gets returned to be evaluated next. But what did the map do?

[Consults camel re: map]

mmmkay, so we have (effectively): map { $_ =~ s/$/$s/s; return $_; }, @_;  pop; $ is of course the end of the string. Oh.

That explains the ; at the beginning of $s that didn't seem necessary before. map returns a list containing all the strings @_ had in it but with ';pop' appended to each one. But that's not what is returned to be evaluated, because pop comes after and pops off the next thing from @_ to be evaluated. What happens to the list map returns?

The camel doesn't say, but I'm supposing it must get assigned to @_, probably due to map's being called in void context. Woo. That makes sense, but is it documented anyplace?

Okay, so @_ now contains the following:

( '4a4a2bfe01ac410d0105f4fd0dae30150dfab448f90208fa0d98;pop', 'pop;pop', 'print+chr(shift);pop', 'print+chr(shift);pop', 'unshift@_,(shift()+shift())x2;pop', 'push@_,(pop,pop)x24;pop', ';;pop', 'unshift@_,(map{unpack'c',$_}split//)[0..25];pop', ';;pop', 's/../chr(hex$&)/eg;pop', );

Additionally, the pop returned '$_=substr(shift,0,52);pop' to be evaluated next. This stores the hex string in $_, removing it from @_, and pops the next string to be evaluated.

Evaluating 's/../chr(hex$&)/eg;pop' is easy enough to follow. $& is the last thing matched, and I just finished using hex in a japh, so we're converting the data in $_ from hex to ASCII. Then of course we pop the next command.

[Consults ASCII chart]

# Umm, let's write that hex string in bytepairs... # 4a 4a 2b fe 01 ac 41 0d 01 05 f4 fd 0d ae 30 15 # 0d fa b4 48 f9 02 08 fa 0d 98
Urgle, these data needs more processing... lots of those aren't printable chars.

Anyway, ;;pop must just be padding to make the lines come out (right?), because I can't figure what it would do other than pop the next string to be evaluated. Which is 'unshift@_,(map{unpack'c',$_}split//)[0..25];pop'

I think we're taking a slice of a list (26 elements worth) and prepending it back to @_ for storage, then we pop the next string for evaluation. Okay, so what's this list we're taking 26 elements from? It comes from splitting $_ (the messy data above) into chars, unpacking each one, and returning that as a list. The unshift takes the slice in list context and prepends all of it to @_ as separate elements, so our @_ now has all those unpacked chars as individual elements.

Now, about that unpacking... 'c' means [consults Camel] a signed char value. That means we're getting numbers from -127 to 127, I guess, or approximitely like that. I can never remember exactly what the bounds are. It doesn't matter here since there are no values very close to 127 anyway.

We're now getting those data as signed (decimal) values. Here's a conversion chart:

4a 4a 2b fe 01 ac 41 0d 01 05 f4 fd 0d 74 74 43 -2 1 -84 65 13 1 5 -12 -3 13 ae 30 15 0d fa b4 48 f9 02 08 fa 0d 98 -82 48 21 13 -6 -76 72 -7 2 8 -6 13 -104

mmmkay, so next instruction (after the NOP) is 'push@_,(pop,pop)x24;pop' Whooooah. The first two pops get these...

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.

In reply to Confused about one thing (Re: 59 /e explained) by Anonymous Monk
in thread 59 /e by BooK

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others wandering the Monastery: (5)
    As of 2021-05-07 13:37 GMT
    Find Nodes?
      Voting Booth?
      Perl 7 will be out ...

      Results (91 votes). Check out past polls.