PHPのソースを読もう てきめんのPHPソース追っかけ冒険記 PHP Advent Calendar 2015 11日目
TOP > てきとうにこらむ > ゲーム作りとプログラミング日記 > PHPのソースを読もう てきめんのPHPソース追っかけ冒険記 PHP Advent Calendar 2015 11日目
PHPつかってるかい!?
みなさんこんにちは。なんかさいきん、あんたとしいくつだよとか言われるようになったてきめんです!
PHPのソースって読んでるかい!?
とか言いながら、ぼくはPHP7のソースはちょっとしか読んでいません。とはいえ、php-astとか面白そうで闇PHP勉強会の時はノリノリで覗いていました。 だからこそ、どんどんソースを読んでいきたいです。今回はソースコードを追っていったぼくの歴史を話そうかと思います。
どうやって動いているのだろう - 関数編 -
最初に見つけたのが関数でした。どうやって動いているのだろうって気になりだしてついに。
fgetcsv
最初にPHPのソースを読もうと思った動機は「fgetcsvの挙動がわからん」でした。わからないならソースコードよんでしまえっっていうノリで。でもですね、解読不可能だったんですよ…
https://github.com/php/php-src/blob/master/ext/standard/file.c#L1985
今読んでもちょっとめまいしてきた…
session_save_handler
PHPのSESSIONで、いきなり想定の時間より早くきれてしまうことがよくありました。そんな時、ぐぐってもなかなか答えが出ない。しゃーない。ソース読むぞ
http://tekitoh-memdhoi.info/views/330
ということで、読んだら結構簡単でした。同じディレクトリにセッションファイル入れちゃダメよんっていうだけでした。
PHP関数の引数
そんなかんじでいつも通りにソースコードを漁っていると引っかかったのが「関数の引数」でした。PHPは関数の引数の個数を間違えたり、引数を文字列としているところに配列を入れると予想外の挙動をすることがわかりました。
http://tekitoh-memdhoi.info/views/577
海老原さんの記事のほうが早かった。
どうやって動いているのだろう - コアら編 -
関数だけ読んでても面白くなかったので、PHPそのものがどのように動いているのか知りたくなりました。
構文解析
PHPの挙動自体が知りたくなってきたので、色々調べてみました。 気になったのが、Zend/zend_language_parser.yでした。これってなんだろう?と思い探してみると、Bisonと呼ばれる構文解析器のことでした。
Bisonで検索すると、徳丸先生のページが見つかりました。2000年ごろに書かれたようですが、全然使えてしまいました。セキュリティ以外で教えを請うことになるとは(当然、こういう知識がないとできない仕事だとは思います)。ありがとうございます。ひげぽんさんのページも参考にさせていただきました。
字句解析
Bisonを調べた結果、re2cを使う、すなわち字句解析ツールを使用することがわかってきました。
前述のBison、re2cの実装共にakkera102さんのページが参考になりました。ありがとうございます。
そしたら電卓作ろうぜ!
というわけで出来たのがcalc-modokiです。これは最近は特に何もしてません。相変わらず「DO NOT PRODUCTION USE」です。
http://tekitoh-memdhoi.info/views/624
これがきっかけで「インタプリタってどうやって作ればいいのだろう」という疑問が湧いてきます。
PHPのバージョンアップで起こったへんてこなアップデート
PHP5.5.16と5.4.32にて修正されたバグのうち、もちろんセキュリティアップデートもありましたが、なんとしれっとこんなバグも修正されました。
<?php
$b=array(-1=>0);
$c=array_pop($b); assert($c == 0);
assert(array_push($b, 0), 1);
assert(array_push($b, 0), 2);
var_dump($b);
assert(array_push($b, 0), 3);
?>
array(2) {
[-1]=>
int(0)
[9223372036854775807]=>
int(0)
}
PHP Warning: array_push(): Cannot add element to the array as the next element is already occupied in /home/tekitoh/php/test.php on line 11
PHP Warning: assert(): 3 failed in /home/tekitoh/php/test.php on line 11
まとめたページはhttp://tekitoh-memdhoi.info/views/632になりますが、これをきっかけにPHPのバージョンアップにはChangelogを絶対覗くべきだと確信しました。
また、PHPのarrayの挙動に関しても謎が出てきました。なんでBucket構造体のhはunsigned longなのでしょう?という謎です。PHPカンファレンスや闇PHP勉強会で誰に聞いても未だにわからない…
やっぱりまたやらかしてた
5.5.25と5.6.9のTraitで。みんなコレ知ってるのかな?#69467 Wrong checked for the interface by using Trait
Test script:
---------------
interface Baz {
public function bad();
}
trait Bar{
protected function bad(){}
}
class Foo implements Baz{
use Bar;
}
$test = new Foo();
var_dump($test instanceof Baz);
Expected result:
----------------
Fatal error
Actual result:
--------------
bool(true)
そもそも、Trait周りは結構バグ多い印象ありますね。いま読んでみると。
そしたらインタプリタ作ろうぜ!
やっぱここまでいくとインタプリタ作りたくなるじゃないですか。作ってみました。ちょうどいい本があったので。
http://tekitoh-memdhoi.info/views/661
てきめんラジコンにぶちこんでやったぜ
これはJavaですが、声を使って命令する際に字句解析、構文解析のやり方を参考にさせてもらいましたへへへ
http://tekitoh-memdhoi.info/views/688
ソースコードの追い方
ぼくはとりあえず以下のツールがあればどうにか読めます。
- vim
- grep
- ctags
- php-vld
- gdb
PHPでのgdbの使い方は、ヤフーさんの記事が参考になります。http://techblog.yahoo.co.jp/tips/php/
関数の挙動であれば
ぼくは、関数の挙動であれば、ソースのディレクトリ下でgrepをかけます。
$ grep -lr 'PHP_FUNCTION(fgetcsv' .
あとは、GNU ctagsは必須ですね。
$ ctags -R .
そして、viで掘っていきます。
$ vi ext/standard/file.c
その中でまた検索でもかければ良いんじゃないかなぁ。
ありがとうございました。
気がついたらたらたら長い文章になってしまいました。ていうかただの自分語りポエムになってしまいましたねヽ(^。^)ノ
とはいえ、PHPのソースコードを追っかけるというのは慣れれば楽しいです。さあ、みんなでPHPのソースを追っかけよう!