TAKESAKOさんの ppencode が何で動くのか分かった。

かなり古い話題かもしれませんが,ppencode の動作原理が分かったのでその感動を日記に記します。


僕は半年前ほど前からperlの勉強を始めましたが,始めてまだ間もない頃にppencodeを知って,これが何故動くのかが当時は全然分かりませんでした。


ppencodeって何?って方は下記URLを参照すると,分かります。’予約語プログラミング’なんてキーワードでググってみても関連情報が出てきます。

TAKESAKOさんのサイトでppencodeのデモが見れる
http://www.namazu.org/~takesako/ppencode/demo.html


id:naoyaさんのブログエントリ
http://d.hatena.ne.jp/naoya/20050901/1125556355


上述したTAKESAKOさんのデモページで'test'の文字列を入れるとですね・・下記のようなppencodeに変換されます。

#!/usr/bin/perl -w
length q rmdir and print chr ord q stat s and print chr ord q ge log 
and print chr ord q msgctl m and print chr ord q stat s 


このコードを実行すると,ちゃんと'test'と表示されます。で,何でこんなコードが動くのかと言うと・・。
まず,このままだと分かりにくいのでコードを分解します。

#!/usr/bin/perl -w
length q cmp lc
and
print chr ord q stat s
and
print chr ord q ge log
and
print chr ord q msgctl m
and
print chr ord q stat s


赤字のところが実際に't'や'e','s','t'を表示する文です。例に4行目の't'をprintする文を見てみましょう。

例:print chr ord q stat s

1. これは,q stat s の部分がミソで,qs 〜 sでクオートされた'tat 'という文字列を意味します。
2. 'tat 'を ord に渡してやると,ord は't'のASCII値を返してくれます。
3. 't'のASCII値を chr に渡すと,文字列't'が返ってきます(!)
4. 't'を print します。


1の部分がミソで,3の部分でトリックの謎が解けた感じですね。'q stat s'がクオートだということが分かれば,あとはord→chrで「な〜んだ」というくらい簡単な処理をしているだけです。もう一つ別の行を見てみましょう。今度は先ほどよりも早く何を表示する行か分かるはずです。なぜなら,クオートされた文字列の先頭文字を見れば良いからです。

例:print chr ord q msgctl m

この文は's'を表示します。qm〜mとなっていることが分かりますでしょうか?

分かってみると何でもないかもしれませんが,文字だけの予約語を巧みに使った面白いトリックだと思います。substrで文字列の先頭文字を取ろうとすると,数字を使わなきゃいけないところが,ord → chr をすれば文字列だけで出来るなんて!


masutaro を変換すると,こんなppencodeが表示されます。

#!/usr/bin/perl -w
length q caller getc and print chr ord qw q m q and print chr ord q map m and print chr ord q msgctl m and print chr ord q dump and and print chr ord q stat s and print chr ord q each ne and print chr ord q qr eq and print chr ord q pop


パッと見ただけじゃ何が書いてあるのか分からないですよねw
初めて見た人に,「なんじゃこれーー!」「何でこれが動くの!?」っていう驚きを与えられるところが,ppencodeの面白いところだと思います^^


このppencode,漢字もできますが,漢字は単純に’あ’を変換しただけでも出力されるコードが,英語に比べて少し長いようです。
chr hex という部分がありますが,どうやらここがミソっぽいですね。また時間のあるときにでも見てみようと思います。


あ,あとちなみに変換後のコードの最初(#!/usr/bin/perl -wは除く)はいつも length〜ってので始まります。これを解釈すると,

length q cmp lc and


qc〜c だから・・,'mp l'を length に渡していることが分かります。
後の処理を and で続けていますが,ここでperlのバージョンチェックをしているのでしょうかね。なくても動きます。

それとも見た人を,かく乱させるためのダミーでしょうか??