CRuby がプログラムをどう実行しているのかを自分がいまいち理解していないので、その理解のために書いていくものです。 実験的に、あっちこっちリンクで飛ぶように書きたいと思います。
CRuby の実行ファイルである ruby(Windows であれば ruby.exe)は、Ruby スクリプトを解釈して実行します。
たとえば ruby -e 0 などとすると、0 という一文字の Ruby スクリプトだと解釈され、実行されます。画面に何も表示しないので本当かどうかよくわかりませんが、そうらしいです。
このとき内部では何が起きているのか、追ってみたいと思います。 読んでいくソースコードは ruby-2.7.1 としたいと思います。 https://github.com/ruby/ruby/tree/v2_7_1
CRuby は C 言語で書かれており、実行されたときに最初に呼び出されるのは main() 関数です。
中身を抜粋します。
#ifdef RUBY_DEBUG_ENV
ruby_set_debug_option(getenv("RUBY_DEBUG"));
#endif
#ifdef HAVE_LOCALE_H
setlocale(LC_CTYPE, "");
#endif
ruby_sysinit(&argc, &argv);
{
RUBY_INIT_STACK;
ruby_init();
return ruby_run_node(ruby_options(argc, argv));
}
マクロ定数 RUBY_DEBUG_ENV が定義されていたら環境変数 RUBY_DEBUG を取り出して ruby_set_debug_option() を呼び出す。
マクロ定数 HAVE_LOCALE_H が定義されていたら、つまり locale.h が読み込まれていたら setlocale() で LC_TYPE をクリアする。
ここまではあまり本質的ではない前処理です。
これ以降の処理を箇条書きします。
ruby_sysinit()を呼び出す。RUBY_INIT_STACKマクロを展開する。ruby_init()を呼び出す。ruby_run_node()を呼び出して返り値を返す。- このとき引数に
ruby_options()の返り値を渡す。
- このとき引数に
たったこれだけでした。簡単ですね……というわけにはいきません。 要素数は少ないですがそれぞれの要素が何を表す何をするものなのか、これだけだとまったくわかりません。
個別に見ていきます。
getenv()→google検索- locale.h→google検索
RUBY_DEBUG_ENVruby_set_debug_option()→TODOifdef HAVE_***_Hをなぜ「***.h が読み込まれていたら」と読み下すのか?ruby_sysinit()→TODORUBY_INIT_STACK→TODOruby_init()→TODOruby_run_node()→TODOruby_options()→TODO
このマクロが設定されているとき、起動時に ruby_set_debug_option() を呼び出します。
それ以外にこのマクロを参照している箇所がないので、この呼び出しの有無を制御するためだけのもののようです。
これは CRuby に限らず、C 言語のヘッダーファイル、とくに *nix とか POSIX とか言われる界隈で見られる慣習およびテクニックのようです。 初出がどこなのかは私は知りませんが、ヘッダーファイル全体を
/* locale.h */
#ifndef HAVE_LOCALE_H
#define HAVE_LOCALE_H
...(中略)..
#endif /* HAVE_LOCALE_H */
[EOF]
のような形で #ifndef ... #endif でくるんでやることで、
- 読み込まれる前 ->
HAVE_LOCALE_H未定義 - 初回読み込み ->
HAVE_LOCALE_H定義しつつ、ヘッダーファイルの内容を展開する - 二回目以降の読み込み ->
HAVE_LOCALE_H定義済みなのでなにもしない
というようにすることがよくあります。これにより「多重読み込み防止」「ヘッダーをすでに読み込んだかの判断が可能になる」というものです。
まだ書けていません。すみません。