php の '@' 演算子

以下 php4.4 の話。

ふしぎなphp

いきなり関係ないですが、

<?php
@
?>

ってやると、

Parse error: parse error, unexpected ';' in /hoge/fuga.php on line 3

って言われます。どこに期待していない ';' があるんだよ! って思いますよね。

理由は zend_compile.c の 2516 行目付近、

case T_CLOSE_TAG:
    if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1]=='\n'
        || (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-2]=='\r' && LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1])) {
        CG(increment_lineno) = 1;
    }
    retval = ';'; /* implicit ; */
    break;

にあるように、 implicit に ';' を補完してくれるんだそうです。ちゃんと ';' を書いていた場合はからっぽな statement があると思うんでしょうかね。

で、これを見ていて思うのは、 if 文の 3 つめの条件は " == '\n' " が抜けてるんじゃないの? ってことですよ。ためしに

<?php echo "line = " . __LINE__ . "\n" ?>
<?php echo "line = " . __LINE__ . "\n" ?>

というのを、改行コードを '\r' (set ff=mac もしくは C-x RET f mac) にしてみると

line = 1
line = 1

ムキー!!

ついでに scanner の T_CLOSE_TAG あたり (zend_language_scanner.l, line 1443 とか) を見てたら、

<script language=php>
echo 'hoge';
?>

なんてのが正しく動くことがわかりました。フーン。

本題

'@' 演算子 (http://jp.php.net/manual/ja/language.operators.errorcontrol.php) ってなにしてるんだろ、ってのが本題。

zend_execute.c の line 2581 にあるとおり、 error_reporting(0) するだけでした。おわり。