parse_config_file函数是分析*.rc配置文件,并且把里面的参数组成链表的方式。下面来仔细地分析代码,如下: #001 int parse_config_file(const char *fn) #002 { 输入来的参数是文件名称的路径。
#003 char *data; #004 data = read_file(fn, 0); #005 if (!data) return -1; 这段代码是从文件里读取数据,并保存数据缓冲区的指针在data里。
#006 #007 parse_config(fn, data); 这行代码是分析data数据里,然后把里面的参数组成链表的方式。
#008 DUMP(); 这行代码是用来调试时输出配置文件里的内容。
#009 return 0; #010 }
接着下来分析函数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; 这段代码是分配文件所需内存大小。
#019 #020 if(read(fd, data, sz) != sz) goto oops; #021 close(fd); #022 data[sz] = '/n'; #023 data[sz+1] = 0; 这段代码是读取文件数据到缓冲区,并设置缓冲区最后的结束字符为换行符和0字符。
#024 if(_sz) *_sz = sz; #025 return data; 这段代码是返回文件的长度和文件缓冲区的指针。
#026 #027 oops: #028 close(fd); #029 if(data != 0) free(data); #030 return 0; #031 } 这段代码是读取文件出错,删除缓冲区。
再接着来分析函数parse_config,主要实现从缓冲区里分析配置数据,生成链表。它的代码如下: #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; 这段代码是设置分析开始状态,其实state.filename指向文件名称;state.line是第一行;state.ptr是指向数据缓冲区;state.nexttoken是下一个词位置;state.parse_line是指向空操作行函数。
下面开始循环适别所有配置文件。 #013 for (;;) {
下面根据三种状态进行处理。 #014 switch (next_token(&state)) { #015 case T_EOF:
已经到了文件结尾字符处理。 #016 state.parse_line(&state, 0, 0); #017 return;
新一行配置文件处理。 #018 case T_NEWLINE: #019 if (nargs) {
查找这一行里配置的关键字。 #020 int kw = lookup_keyword(args[0]); #021 if (kw_is(kw, SECTION)) {
是关键字处理,分近这一行字符。 #022 state.parse_line(&state, 0, 0);
调用函数parse_new_section来分析这一节配置文件的意思,比如服务或者动作,或者参数等等。 #023 parse_new_section(&state, kw, nargs, args); #024 } else {
保存一行的参数。 #025 state.parse_line(&state, nargs, args); #026 } #027 nargs = 0; #028 } #029 break;
保存命令配置的参数。 #030 case T_TEXT: #031 if (nargs < SVC_MAXARGS) { #032 args[nargs++] = state.text; #033 } #034 break; #035 } #036 } #037 } |
|