in reply to Unlocking the Dark Mysteries of Acme::Bleach
Open the filename name stored in the global variable $0 (which stores the name of the script perl was called with) and assign a filehandle to 0 (this is a rather obscure feature of open). If it can't be opened then print out an error message and exit the program.open 0 or print "Can't rebleach '$0'\n" and exit;
Slurp in the contents of the 0 filehandle (the program code), join them into a single string and assign them to $shirt, then immediately perform a replace on it by removing everything before and including use Acme::Bleach.(my $shirt = join "", <0>) =~ s/.*^\s*use\s+Acme::Bleach\s*;\n//sm;
Locally change the __WARN__ handler to dirty() which returns true if a warning matches non-whitespace (likely to supress any warnings in the code that follows).local $SIG{__WARN__} = \&dirty;
Unless the contents of $shirt (the program code) matches non-whitespace or doesn't begin with $tie (a sequence of 8 space and tab alternations) then evaluate the return of brighten $shirt and exit (this is the bit that is run post-bleaching).do { eval brighten $shirt; exit } unless dirty $shirt && not dress $shirt;
Locally assign $_ to the last element of @_, which is the program code (the is $_ localised so it isn't clobbered and also sets it as the current topicalizer). Remove a leading $tie (the tabs) or any non space/tab characters. The tr will change every space to 0 and every tab to 1 and the pack then converts it back to it's original form (ready to be evaluated).sub brighten { local $_ = pop; s/^$tie|[^ \t]//g; tr/ \t/01/; pack "b*", $_ }
Reopen the the script in $0 for writing (to be bleached in this case).open 0, ">$0" or print "Cannot bleach '$0'\n" and exit;
Use the alternate syntax of print to write use Acme::Bleach; and the return of whiten $shirt to the 0 filehandle then exit.print {0} "use Acme::Bleach;\n", whiten $shirt and exit;
Once again, $_ is localised and is assigned a bit string created by unpack of the last element of @_ (the contents of $0 in this case). Replace all the 0s and 1s as spaces and tabs respectively and return the modified $_ with $tie prepended.sub whiten { local $_ = unpack "b*", pop; tr/01/ \t/; s/(.{9})/$1\n/g; $tie.$_ }
So basically Acme::Bleach converts the contents of the code into a bitstring of spaces and tabs on the first run, and then on subsequent runs uncompresses the bitstring and runs the code. Simple as that :)
HTH
_________
broquaint
update: $tie comment now correct and further explanation of the warning handler localisation
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Re: Unlocking the Dark Mysteries of Acme::Bleach
by demerphq (Chancellor) on Jun 29, 2003 at 23:19 UTC | |
by Aristotle (Chancellor) on Jun 30, 2003 at 23:17 UTC |