Lua2.4コンパイラ入口luac.c

4269 ワード

luac.cはコンパイラluacのエントリファイルです.いつものルール、main関数から見て、この過程でプログラムが何をしたか見てみましょう.
int main(int argc, char* argv[])
{
 char* d="luac.out";            /* default output file */
 int i;
 for (i=1; i<argc; i++)
 {
  if (argv[i][0]!='-')            /* end of options */
   break;
  else if (IS("-"))            /* use stdin */
   break;
  else if (IS("-d"))            /* debug */
   lua_debug=1;
  else if (IS("-l"))            /* list */
   listing=1;
  else if (IS("-o"))            /* output file */
   d=argv[++i];
  else if (IS("-p"))            /* parse only (for timing purposes) */
   dumping=0;
  else if (IS("-v"))            /* show version */
   printf("%s  %s
(written by %s)

",LUA_VERSION,LUA_COPYRIGHT,LUA_AUTHORS);   else                    /* unknown option */    usage();  }  --i;                    /* fake new argv[0] */  argc-=i;  argv+=i;  if (argc<2) usage();  for (i=1; i<argc; i++)   if (IS(d))   {    fprintf(stderr,"luac: will not overwrite input file \"%s\"
",d);    exit(1);   }  D=(dumping) ? fopen(d,"wb") : stdout;    /* must open in  binary mode */  if (D==NULL)  {   fprintf(stderr,"luac: cannot open ");   perror(d);   exit(1);  }  for (i=1; i<argc; i++) compile(IS("-")? NULL : argv[i]);  fclose(D);  return 0; }

このコードを見るときは、luacのマニュアルを参考にして、いろいろな選択肢よりもはっきり見えるようにしたほうがいいです.プログラムは最初からデフォルトの出力ファイル「luac.out」を定義しています.次に、コマンドラインの入力を巡回して、ユーザーがコマンドラインから入力するオプションを取得します.プログラムが中線(マイナス記号'-')ではないヘッダのオプションに遭遇すると、ループは終了します.luacのコマンドラインオプションのフォーマットは、中に線を引いた後に文字を付けて空白で分割する点でunixの伝統と同じです.また,一般的なコマンドラインプログラム操作インタフェースとも一致する.オプションは、1つの中に線を引くだけで、標準入力を入力ファイルとして使用し、ループを終了します.ここのISはマクロで、これはC言語の中の1つのコードをもっと実際的な意義ともっと読みやすい方法で、Luaのソースコードの中で多くのマクロを使って、コードの量を減らすことができる以外に、最も重要なのはコードをもっと読みやすくして、もっと意味があることです.'-d'デバッグオプションは、オンにすると、バイトコードを生成するときにデバッグに関する情報を生成します.たとえば、行番号やデバッグしやすい内容などです.デバッグインタフェースの中には、デバッグを開くときだけ意味があるものもあります.'-l'バイトコードを印刷するかどうか.'-o′出力ファイルを設定し、出力ファイル文は直接オプションの後ろにあり、このオプションを使用しない場合は、上述のluacを使用する.outファイルを出力ファイルとして使用します.'-p'は文法解析のみを行います.'-v'はLuaのバージョン番号、著作権情報、および著者を表示します.そうでなければ、誤ったオプションがある場合は、usageを呼び出し、使用方法を印刷します.
static void usage(void)
{
 fprintf(stderr,"usage: luac [-dlpv] [-o output] file ...
");  exit(0); }

コマンドラインオプションが終了した場合、コマンドラインオプションはLuaスクリプトのソースファイルになっているはずです.パラメータの個数が間違っている場合も、同じようにusageを呼び出し、使用方法を印刷します.ファイルをコンパイルする前に、Luaスクリプトファイルが出力ファイルと同じ名前であるかどうかを確認し、同じ名前であればエラーメッセージを印刷して終了します.このforループです
 for (i=1; i<argc; i++)
  if (IS(d))
  {
   fprintf(stderr,"luac: will not overwrite input file \"%s\"
",d);    exit(1);   }

出力ファイルを開き、出力が必要でなければ標準出力を出力として開きます.ファイルを開くときにエラーが発生した場合は、印刷エラーが発生して終了します.ここでdumpingフラグはコンパイル後のバイトコードの出力にのみ影響し,他のプロセスには影響しない.
 D=(dumping) ? fopen(d,"wb") : stdout;    /* must open in  binary mode */
 if (D==NULL)
 {
  fprintf(stderr,"luac: cannot open ");
  perror(d);
  exit(1);
 }

最後のforループは、すべてのLuaスクリプトファイルをコンパイルすることです.
 for (i=1; i<argc; i++) compile(IS("-")? NULL : argv[i]);

compile関数の役割は、ファイルを開き、コンパイルし、ファイルを閉じることです.
static void compile(char* filename)
{
 if (lua_openfile(filename)==NULL)
 {
  fprintf(stderr,"luac: cannot open ");
  perror(filename);
  exit(1);
 }
 do_compile();
 lua_closefile();
}

do_compileをコンパイルし、出力します.
static void do_compile(void)
{
 TFunc* tf=new(TFunc);
 luaI_initTFunc(tf);
 tf->fileName = lua_parsedfile;
 lua_parse(tf);
 do_dump(tf);
}

do_dumpは名前を見ると,実際のdump作業を行う,すなわち出力バイトコード,あるいは転送バイトコードと呼ぶ.
static void do_dump(TFunc* tf)        /* only for tf==main */
{
 if (dumping) DumpHeader(D);
 while (tf!=NULL)
 {
  TFunc* nf;
  if (listing) PrintFunction(tf);
  if (dumping) DumpFunction(tf,D);
  nf=tf->next;                /* list only built after first main */
  luaI_freefunc(tf);
  tf=nf;
 }
}

このファイルは終わりましたが、ここには何も言っていません.例えば、上のファイルが開いて閉じて何をしているのか、なぜそんなことをしているのか.do_compileの中のTFuncは何ですか?その初期化は何ですか?lua_parserって何?do_dump方法で調整したいくつかの方法はそれぞれ何をしていますか?これらのものは、ここで呼び出される順番によって少しずつ徐々に現れていきます.