在閱讀有些程序的源碼時,很但願可以立刻弄清楚源碼中到底包含了哪些頭文件,以肯定是否須要爲了特殊的函數而手動加入#include。藉助flex的詞法分析實現了這一功能,本質上就是對正則表達式的匹配。注意這個程序不可以處理包含嵌套的情形(也就是說不能指出包含文件包含了哪些文件),感興趣的能夠經過棧來實現。源碼以下:正則表達式
1 /*源代碼:ic.l*/ 2 3 /*定義文件預處理指令文件名起始狀態*/ 4 %x IFILE 5 6 %% 7 ^"#"[ \t]*include[ \t]*[\"<] {BEGIN IFILE;} /*#include的多種表達方式的正則表達式*/ 8 <IFILE>[^\t\n\">]+ {/*進入文件名狀態*/ 9 printf("%d:%s\n",yylineno++,yytext);/*輸出行號和文件名,yylineno是flex定義的全局變量,yytext是當前 10 輸入流*/ 11 { 12 char c; 13 /*去處行尾可能的換行符*/ 14 while((c=input()) && c!='\n'); 15 } 16 /*回覆至初始狀態*/ 17 BEGIN INITIAL; 18 }/*下面的RE用於處理行首換行(空行)和換行的狀況,增長yylineno的值*/ 19 ^\n {++yylineno;} 20 \n {++yylineno;} 21 . {/*直接忽略*/} 22 %% 23 24 int main(int argc,char *argv[]) 25 { 26 /*命令行讀取文件名參數*/ 27 if (argc<2) 28 { 29 fprintf(stderr,"Usage:%s filename\n",argv[0]); 30 } 31 FILE *f; 32 int i; 33 /*循環打開文件*/ 34 for (i=1;i<argc;++i) 35 { 36 f=fopen(argv[i],"r"); 37 if (!f) 38 { 39 perror(argv[i]); 40 exit(EXIT_FAILURE); 41 } 42 /*從新開始輸入*/ 43 yyrestart(f); 44 yylineno=1; 45 /*開始新的文件,函數初始化爲1*/ 46 printf("\t%s:\n",argv[i]); 47 yylex();/*開始詞法分析*/ 48 printf("\n"); 49 fclose(f); 50 } 51 return 0; 52 }
編譯指令:函數
1 $flex -o ic.lex.c ic.l 2 $gcc -o ic ic.lex.c -lfl
示範運行結果:flex
1 $ ./ic test_inc.c inc_count.lex.c 2 test_inc.c: 3 1:stdio.h 4 5 inc_count.lex.c: 6 20:stdio.h 7 21:string.h 8 22:errno.h 9 23:stdlib.h 10 43:inttypes.h 11 487:unistd.h
可見已經達到了目的。spa