Lua2.4 編譯器入口 luac.c

來源:互聯網
上載者:User

標籤:io   os   使用   ar   for   檔案   sp   c   on   

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\n(written by %s)\n\n",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\"\n",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 的傳統是一樣的。並且和一般的命令列程式操作介面也是一致的。

選項如果只是一個中劃線,使用標準輸入做為輸入檔案,遍曆結束。
這裡的 IS 是一個宏,這是 C 語言裡面的一個令代碼更有實際意義及更加容易閱讀的一個方法,Lua 的原始碼裡用到了不少的宏,除了可以減少代碼量外,最重要的就是讓代碼更易讀,以及更有意義。

‘-d‘ 調試選項,如果開啟的話,程式會在產生位元組碼的時候產生一些調試相關的資訊。比如行號和其它一些方便調試的內容。有一些調試介面是只在你開啟調試時,它才有意義。

‘-l‘ 是否列印位元組碼。

‘-o‘ 設定輸出檔案,輸出檔案句直接在選項的後面,如果不使用這個選項,則使用上面提到的那個 luac.out 檔案做為輸出檔案。

‘-p‘ 只進行文法分析。

‘-v‘ 顯示 Lua 的版本號碼,著作權資訊及作者。

否則,如果有錯誤的選項,調用 usage,列印使用方法。

static void usage(void){ fprintf(stderr,"usage: luac [-dlpv] [-o output] file ...\n"); exit(0);}

命令列選項遍曆退出時,說明這時命令列選項應該是到了 Lua 指令碼的原始碼檔案了。
如果參數個數不對,則也同樣調用 usage , 列印使用方法。

在對檔案進行編譯之前,要先檢查一下 Lua 指令檔是否和輸出檔案同名了,如果同名,列印出錯資訊並退出。就是這個 for 迴圈:

 for (i=1; i<argc; i++)  if (IS(d))  {   fprintf(stderr,"luac: will not overwrite input file \"%s\"\n",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 方法裡調的那幾個方法又分別是幹什麼的?

這些東西都會根據這裡調用的順序一點點慢慢的展現出來的。

Lua2.4 編譯器入口 luac.c

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.