LCC編譯器的源程式分析 4 處理檔案引數

2021-04-13 00:16:28 字數 4877 閱讀 1596

上面已經介紹選擇不同的目標輸出的引數處理,那麼接著下來,自然的事情就是處理剩下的兩個引數的問題,當然

lcc

rcc.exe -target=x86/na** hello.i hello.a** 其中

hello.i

是輸入檔案,

hello.a**

是輸出檔案。那麼

lcc是怎麼樣開啟輸入檔案和輸出檔案呢?輸入檔案又有什麼技巧呢?要仔細地理解源程式,就知道它的輸入處理是非常高效的。

當選擇合適的目標輸出後,就呼叫下面的函式來處理: //

init(argc, argv);

這個函式就是用來處理其它引數的。它的源程式如下:

#001 void init(int argc, char *argv)

#002 

#007  

#008  

#012  

#013  

#017 } 第

1行**裡傳入了命令列的引數。 第

5行**是處理引數的處理。如果在第

5行裡呼叫沒有處理

main_init

,那麼在第

10行裡會再次呼叫它進行引數處理。 第

15行調函式

type_init

進行型別初始化,比如

c預設的資料型別初始化,比如

int型別,就初始化為

4位元組的有符號型別,還有很多其

c預設的型別定義。

先來分析函式

input_init

的源程式是做什麼工作的,下面就是它的程式:

#001 void input_init(int argc, char *argv)

#002  第

5行處理是否初始化,因為只允許初始化一次。第

8行設定初始化變數為

1,讓這段**不要執行兩次。 第

9行呼叫主要引數處理函式。後面再接著介紹。 第

11行讓當前行指標和緩衝區指標指向輸入緩衝區的尾部。 第

12行初始化讀取檔案塊大小為

-1,也就是讀取檔案失敗的狀態。 第

13行設定分析的

c程式行號為0。

第14行設定當前輸入檔名稱為空。 第

16行是從輸入檔案裡讀取資料到輸入緩衝區,同時設定當前處理的指標。 第

17行判斷當前指標是否大於資料緩衝區的指標。 第

20行讀取下一行源程式到緩衝區裡。

呼叫函式

main_init

主要處理引數,並且開啟輸入的檔案和輸出的檔案。它的程式如下:

#001 void main_init(int argc, char *argv)

#002 

#030               }   

#031         }

#032         else if (strcmp(argv[i], "-x") == 0)

#033               xref++;

#034         else if (strcmp(argv[i], "-a") == 0)

#035        

#038         else if (strcmp(argv[i], "-p") == 0)

#039               pflag++;

#040         else if (strcmp(argv[i], "-w") == 0)

#041               wflag++;

#042         else if (strcmp(argv[i], "-v") == 0)

#043               fprint(stderr, "%s %s/n", argv[0], rcsid);

#044         else if (strncmp(argv[i], "-s", 2) == 0)

#045               density = strtod(&argv[i][2], null);

#046         else if (strncmp(argv[i], "-errout=", 8) == 0)

#047        

#054 

#055               fclose(f);

#056                f = freopen(argv[i]+8, "w", stderr);

#057               assert(f);

#058         }

#059         else if (strncmp(argv[i], "-e", 2) == 0)

#060        

#065         else if (strncmp(argv[i], "-little_endian=", 15) == 0)

#066               ir->little_endian = argv[i][15] - '0';

#067        else if (strncmp(argv[i], "-mulops_calls=", 18) == 0)

#068               ir->mulops_calls = argv[i][18] - '0';

#069         else if (strncmp(argv[i], "-wants_callb=", 13) == 0)

#070               ir->wants_callb = argv[i][13] - '0';

#071         else if (strncmp(argv[i], "-wants_argb=", 12) == 0)

#072               ir->wants_argb = argv[i][12] - '0';

#073         else if (strncmp(argv[i], "-left_to_right=", 15) == 0)

#074               ir->left_to_right = argv[i][15] - '0';

#075         else if (strncmp(argv[i], "-wants_dag=", 11) == 0)

#076               ir->wants_dag = argv[i][11] - '0';

#077         else if (*argv[i] != '-' || strcmp(argv[i], "-") == 0)

#078        

#084 

#085         if (infile != null && strcmp(infile, "-") != 0

#086               && freopen(infile, "r", stdin) == null)

#087        

#091 

#092         if (outfile != null && strcmp(outfile, "-") != 0

#093               && freopen(outfile, "w", stdout) == null)

#094        

#098 } 第

7行到第

10行,同樣是讓這個函式只執行一次的**。 第

79行到第

82行是讀取輸入檔案和輸出檔案的名稱。 第

85行到第

90行是開啟輸入的檔案,並處理出錯的情況。 第

92行到第

97行是開啟輸出的檔案,並處理出錯的情況。

其它**就是處理其它引數的功能,這裡就不詳略地介紹了。 ok

,到這裡就已經把輸入的檔案和輸入的檔案開啟,準備好處理源程式的基礎了。由於在函式

input_init

裡已經呼叫

main_init

,後面再呼叫它已經是不再處理了。

下面再來看看函式

input_init

裡呼叫的兩個函式

fillbuf

和nextline

。先來看函式

fillbuf:

#001 void fillbuf(void)

#002 

#019 

#020  if (feof(stdin))

#021         bsize = 0;

#022  else

#023         bsize = fread(&buffer[maxline+1], 1, bufsize, stdin);

#024 

#025  if (bsize < 0)

#026  

#030  limit = &buffer[maxline+1+bsize];

#031  *limit = '/n';

#032 } 第

3行處理讀取資料為

0的情況,這時就返回去,因為沒有資料處理。 第

6行處理在緩衝區裡已經可以識別所有單詞的情況,如果在行緩衝以後都不能識別出來的單詞,這時又需從檔案裡讀取資料出來,那麼就需要把緩衝區後面的資料移到行緩衝最前面去,這樣就可以把這些字串可以拼接在一起進行處理了,第

10行到

17行就是做這樣的事情。 第

20行是判斷是否讀完檔案,不是的話,在第

23行裡就讀取緩衝區的大小字串。 第

30行調整緩衝區最後的指標,它是指向緩衝區的尾部的。

上面就實現了緩衝檔案的輸入,並且處理檔案的順序識別,當然也限制了一行**是

512個位元組的大小,這也是

c標準裡定義一行**最大的大小,所以寫

c程式時,一行**是不能超過

512個位元組的。

已經分析了這麼多內容,下一節再分析

nextline

吧。  

LCC編譯器的源程式分析 12 13

語法分析是比較複雜的處理,下面再來分析乙個例子,它的 如下 typedef unsigned short wchar t typedef wchar t wint t 第一句語句在lcc裡的處理,前面已經解釋清楚,主要生成wchar t儲存符號表裡,並且記錄這個id的型別屬性。那麼第二句是怎麼樣通過...

LCC編譯器的源程式分析 18 19

lcc編譯器的源程式分析 19 全域性函式的定義 函式定義funcdefn處理裡,已經準備好呼叫引數和引數返回,接著就是呼叫全域性函式宣告來處理。如下面的 132 宣告函式。133 cfunc dclglobal sclass,id,ty,pt 134 上面的 是處理函式全域性定義。現在就去就分析d...

LCC編譯器的源程式分析 20 復合語句

在 c語言裡,有一種語句叫做復合語句。它是由 把一些語句括起來的,如下面的例子 在lcc 裡處理這樣的復合語句的函式是 compound 它在上面函式定義函式 funcdefn 是這樣呼叫的 150labels table null,labels 151stmtlabs table null,lab...