Skip to content

rcシェル内部の実行制御

This content is a draft and will not be included in production builds.

rc シェルは内部にスタックマシンのような実行環境を持っている。これは codebuf という変数で表現されていて、例えば

Terminal window
$str

をスタックマシンで表現すると次のような命令列になる。

block-beta
block
columns 1
s1[".f = Xmark"]
s2[".f = Xword"]
s3(".s = str")
s4[".f = Xdol"]
end
%% style simple fill:none,stroke-width:0px

他にも

Terminal window
ls /dev

これは以下のような命令列として扱われる。

block-beta
block
columns 1
s1[".f = Xmark"]
s2[".f = Xword"]
s3(".s = /dev")
s4[".f = Xword"]
s5(".s = ls")
s6[".f = Xsimple"]
end

codebufcompile のたびに新しく生成される。compileXrdcmds 命令から呼ばれるが、この命令は組み込みの .finit 1からのみ生成されるので、おそらくだがファイル単位で codebuf が切り替わるのだろう。

それぞれの codebuf は先頭に参照カウントを持っている。codecopy すると先頭の参照カウントが増加する。

emitfemits で、それぞれの型に応じた命令を生成する。

命令とは別に、argv というコマンド文字列を管理する領域も持っている。

Terminal window
ls $home

という命令は codebuf 上に命令列として展開されるが、命令を評価した結果は命令列では扱えない。そこで Xdol 命令などでは評価した結果を argv に格納しておき、Xsimple 等の引数が必要な命令でそれを利用する。

1つの argvXmark 命令で開始し、新しい評価結果は末尾に追加する。

新しいリストは newlist で作る。リスト中の値は pushlistpoplist で末尾の値を操作する。

runq という名前で実行状態を管理する。この状態は

  • 命令列(codebuf)
  • 次の実行位置(pc)
  • コマンドライン引数(argv)
  • ローカル変数(local)

などを持っている。

start 関数で新しく実行キューが作られる。startcodebuf と実行を開始するインデックスを受け取る。

Xsubshell, Xasync, Xbackq など平行実行が必要な場面で start が呼ばれているので、実行キューも並列実行毎に作られる。このとき codebuf の参照カウントを増加させるので、全ての参照がなくなるまでは runq が参照する codebuf も残る。

bootstrap命令列は以下のようなコードを生成する。

Terminal window
. /rc/lib/main $*

命令列に並べると以下のようになる。

block-beta
block
columns 1
s1([".i = 1"])
s2[".f = Xmark"]
s3[".f = Xword"]
s4(".s = *")
s5[".f = Xassign"]
s6[".f = Xmark"]
s7[".f = Xmark"]
s8[".f = Xword"]
s9(".s = *")
s10[".f = Xdol"]
s11[".f = Xword"]
s12(".s = /rc/lib/rcmain")
s13[".f = Xword"]
s14(".s = .")
s15[".f = Xsimple"]
s16[".f = Xexit"]
s17([".i = 0"])
end
%% style simple fill:none,stroke-width:0px
  1. このコマンドはマニュアルに載ってないので詳細が分からないが関数ファイルを読んでそう