gnu gawk1.0源码分析……大致看懂了
最近过年,天天吃喝,没看代码,总觉得好象虚度了光阴。于是,今天又开始读源码。
gawk能编译成功后,读代码就容易了。但因为牵涉到bison,而bison又不熟悉。为此,先读awk.y,通过反复读这个文件,终于对awk的语法更熟悉了。因为awk.y写得太好了,其中如何进行语法分析,写得相当精彩。
start : program
;
program : rule
| program rule
;
rule : pattern action
;
我看了许多遍后,终于对awk的语法有了些理解。并且产生了若干奇怪的想法,如可以出现多个BEGIN块吗?可以把BEGIN块不放在开头吗?等等。
接着分析awk1.c这个主程序,这个程序是入口,我说下我的理解。
先进行初始化
对命令行进行解析,没有调用getopt,而是自己手工解析
如果-d
进行调试
如果-R
设置参数RS
如果-f
打开awk命令文件,并读入lexptr字串中。
如果没有-f,就把写在命令行中的awk指令读入lexptr串中。
调yyparse()进行语法分析
init_fields()进行$1,$2,$3..$30的初始化。
找到BEGIN,END块,如果有多个BEGIN块,只取最后的一个。
查看,命令行中是否有程序中要处理的参数。如awk '....' abc=10 file1
其中,abc是一个变量,要在awk程序中用到。
打开命令行中的数据文件,如果有多个就循环处理。
//具体的处理,还是用代码说话,用普通话说,太麻烦了。
if(inrec()==0) { //inrec()中读入一行,并设置字段变量
if(do_vars) {
while(do_vars!=argv && *do_vars) { //找出命令行的变量
char *cp;
cp=index(*do_vars,'=');
*cp++='\0';
variable(*do_vars)->var_value=make_string(cp,strlen(cp));
do_vars++;
}
do_vars=0;
}
do
obstack_free(&temp_strings, ob_dummy);
while (interpret(expression_value) && inrec() == 0);
//interpret(expression_value)中进行了awk命令的解析,然后再用
//inrec()读入下一行
}
if(input_file!=stdin) fclose(input_file);//处理下一个文件
argv++;
终于把gawk文件读了一个半懂。也就是说,大概的流程知道了。但详细的细节,就要慢慢研读了。
awk中用到了正则表达式,用到了bison,而且awk是perl,ruby语言的先驱,感觉读了后,非常有收获。
下次,我就再慢慢的研读。