壊れたメガネ

ホッチキスの達人の意識の高いブログ。

PHP に hellowork 構文を追加する

ここしばらく ZendEngine のコード読んで、ちょっと読めた気になっている勘違い野郎です。
なので今日は実際に手を動かしてみました。

id:anatoo さんのエントリ『「PHPをハックしてオレオレ文法を追加する」PHP カンファレンス2011発表してきました』で公開されている資料helloworld構文を追加するっていうのを実際にやってみました。'helloworld' だとそのまんま過ぎるなぁと思いつつタイプしたら、 'hellowork' という(自分的には)神がかり的タイポをしたのでそれを使うことに。 PHP のコード的には次のような感じ。

<?php
hellowork; // "goto hellowork" と出力する

php_qiq という構文拡張モジュールと、 php-5.2.5 のコードを読んでいる最中だったのでこのバージョンのソースコードをもとにいろいろ触ってみました。


この hellowork 構文は他の構文に比べたら本当シンプルなもので、

  • スキャナ(Zend/zend_language_scanner.l)にトークンの追加
  • パーサー(Zend/zend_language_parser.y)に構文の追加
  • Zend/zend_compile.c に "goto hellowork" を出力する関数の定義と、 Zend/zend_compile.h に関数プロトタイプの追加

という風に、helloworld構文を追加する そのまんま。

基本そのまんまだったけど、コンパイルでちょっとてこずった。
当初のコンパイル環境

  • gcc version 4.5.1 20100924
  • flex version 2.5.35
  • bison version 2.4.3

と、どれも yum でいれたもので、コンパイルして php -r "hellowork;" としても、'PHP Notice: Use of undefined constant hellowork' と出るばかり。
configure スクリプトを見ると、 flex と bison のバージョンが適してなかったのが原因でした。この辺は configure スクリプトみるよりググった方が早かったなぁ。configure を触ってもコンパイル通せただろうけど、素直に yum remove してflex-2.5.4bison-1.28をインストール。

あと、http://anatoo.jp/phpcon2011/#28 のコードには php-5.4.x から導入されたマクロが使われていたのでそれを php-5.2.5 でも使えるように書き直した。

void zend_do_hellowork(znode *arg TSRMLS_DC)
{
    zend_op *opline
      = get_next_op(CG(active_op_array) TSRMLS_CC);

     ZVAL_STRING(&(arg->u.constant), "goto hellowork", 1);
 
     opline->opcode = ZEND_ECHO; // 文字列を出力する命令
-    SET_NODE(opline->op1, arg);
+    opline->op1 = *arg;
     SET_UNUSED(opline->op2);
}

そして、

[oasynnoum@localhost php-5.2.5]$ make install 
[oasynnoum@localhost php-5.2.5]$ ~/local/bin/php -r "hellowork;"
goto hellowork[oasynnoum@localhost php-5.2.5]$ 

やった!できた! id:anatoo さんありがとう!


やっぱ、それにしても実際に手を動かすと眠くならないね。