parse_config_file函數(shù)是分析*.rc配置文件,并且把里面的參數(shù)組成鏈表的方式。下面來仔細地分析代碼,如下:
#001 int parse_config_file(const char *fn)
#002 {
輸入來的參數(shù)是文件名稱的路徑。
#003 char *data;
#004 data = read_file(fn, 0);
#005 if (!data) return -1;
這段代碼是從文件里讀取數(shù)據(jù),并保存數(shù)據(jù)緩沖區(qū)的指針在data里。
#006
#007 parse_config(fn, data);
這行代碼是分析data數(shù)據(jù)里,然后把里面的參數(shù)組成鏈表的方式。
#008 DUMP();
這行代碼是用來調(diào)試時輸出配置文件里的內(nèi)容。
#009 return 0;
#010 }
接著下來分析函數(shù)read_file的代碼,如下:
#001 /* reads a file, making sure it is terminated with /n /0 */
#002 void *read_file(const char *fn, unsigned *_sz)
#003 {
#004 char *data;
#005 int sz;
#006 int fd;
#007
#008 data = 0;
#009 fd = open(fn, O_RDONLY);
#010 if(fd < 0) return 0;
這段代碼是打開文件路徑為fn的文件,使用只讀的方式打開。
#011
#012 sz = lseek(fd, 0, SEEK_END);
#013 if(sz < 0) goto oops;
這段代碼是移動文件指針到文件末尾,然后計算出文件的長度。
#014
#015 if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
這段代碼是移動到文件頭開始位置。
#016
#017 data = (char*) malloc(sz + 2);
#018 if(data == 0) goto oops;
這段代碼是分配文件所需內(nèi)存大小。
#019
#020 if(read(fd, data, sz) != sz) goto oops;
#021 close(fd);
#022 data[sz] = '/n';
#023 data[sz+1] = 0;
這段代碼是讀取文件數(shù)據(jù)到緩沖區(qū),并設(shè)置緩沖區(qū)最后的結(jié)束字符為換行符和0字符。
#024 if(_sz) *_sz = sz;
#025 return data;
這段代碼是返回文件的長度和文件緩沖區(qū)的指針。
#026
#027 oops:
#028 close(fd);
#029 if(data != 0) free(data);
#030 return 0;
#031 }
這段代碼是讀取文件出錯,刪除緩沖區(qū)。
再接著來分析函數(shù)parse_config,主要實現(xiàn)從緩沖區(qū)里分析配置數(shù)據(jù),生成鏈表。它的代碼如下:
#001 static void parse_config(const char *fn, char *s)
#002 {
#003 struct parse_state state;
#004 char *args[SVC_MAXARGS];
#005 int nargs;
#006
#007 nargs = 0;
#008 state.filename = fn;
#009 state.line = 1;
#010 state.ptr = s;
#011 state.nexttoken = 0;
#012 state.parse_line = parse_line_no_op;
這段代碼是設(shè)置分析開始狀態(tài),其實state.filename指向文件名稱;state.line是第一行;state.ptr是指向數(shù)據(jù)緩沖區(qū);state.nexttoken是下一個詞位置;state.parse_line是指向空操作行函數(shù)。
下面開始循環(huán)適別所有配置文件。
#013 for (;;) {
下面根據(jù)三種狀態(tài)進行處理。
#014 switch (next_token(&state)) {
#015 case T_EOF:
已經(jīng)到了文件結(jié)尾字符處理。
#016 state.parse_line(&state, 0, 0);
#017 return;
新一行配置文件處理。
#018 case T_NEWLINE:
#019 if (nargs) {
查找這一行里配置的關(guān)鍵字。
#020 int kw = lookup_keyword(args[0]);
#021 if (kw_is(kw, SECTION)) {
是關(guān)鍵字處理,分近這一行字符。
#022 state.parse_line(&state, 0, 0);
調(diào)用函數(shù)parse_new_section來分析這一節(jié)配置文件的意思,比如服務(wù)或者動作,或者參數(shù)等等。
#023 parse_new_section(&state, kw, nargs, args);
#024 } else {
保存一行的參數(shù)。
#025 state.parse_line(&state, nargs, args);
#026 }
#027 nargs = 0;
#028 }
#029 break;
保存命令配置的參數(shù)。
#030 case T_TEXT:
#031 if (nargs < SVC_MAXARGS) {
#032 args[nargs++] = state.text;
#033 }
#034 break;
#035 }
#036 }
#037 }
聯(lián)系客服