軟件名: code_analyzer
使用c語言 pcre正則庫分析源碼文件,包括文件中的頭文件、宏定義、函數。
用途:
無聊時,可以用來打發下時間。
演示:
對於本源程序的分析結果如下:
##########################頭文件########################
1.頭文件: stdio.h
2.頭文件: stdlib.h
3.頭文件: string.h
4.頭文件: pcre.h
##########################宏##########################
1.宏原型: #define OVECCOUNT 30
宏名: OVECCOUNT
值: 30
2.宏原型: #define EBUFLEN 128
宏名: EBUFLEN
值: 128
3.宏原型: #define BUFLEN 10024
宏名: BUFLEN
值: 10024
########################函數#########################
1.函數原型: int main(int argc, char *argv[])
函數返回值: int
函數名: main
參數: int argc, char *argv[]
2.函數原型: void read_file(char *filename, char *buf)
函數返回值: void
函數名: read_file
參數: char *filename, char *buf
3.函數原型: int regex_f(char *src, char *pattern, regex_buf *re_buf, regex_flag flag)
函數返回值: int
函數名: regex_f
參數: char *src, char *pattern, regex_buf *re_buf, regex_flag flag
使用方法:
命令行使用方法是:
參數1:源程序文件, 參數2:輸出文件名(可選項,默認out.txt)
源碼:
//******************************************************************************** // Author: tanhehe // DateTime: Mon Aug 26 19:34:47 2013 // SearchMe: http://www.cnblogs.com/tanhehe // email: 443016215@qq.com // 程序名: CodeAnalyzer // Description: 代碼分析助手 // //******************************************************************************** #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pcre.h> #define OVECCOUNT 30 #define EBUFLEN 128 #define BUFLEN 10024 typedef enum regex_flag {REG_FUNCTION, REG_MACRO, REG_HEADERS, REG_VARIABLES}regex_flag; union regex_content { char func[100][5][100]; /* 存儲函數信息 */ char macr[100][3][30]; /* 存儲宏信息 */ char head[100][2][30]; /* 存儲頭文件信息 */ }; typedef struct regex_buf { int cn; regex_flag flag; union regex_content buf; }regex_buf; void read_file(char *filename, char *buf); int regex_f(char *src, char *pattern, regex_buf *re_buf, regex_flag flag); char buf[BUFLEN]; int main(int argc, char *argv[]) { char *ifilename = "main.c"; char *ofilename = "out.txt"; char *pattern_function = "((\\w+\\s+\\*?)(?#返回值)\\s*+(\\w+)(?#函數名)\\s*\\(((.(?![\"=><])(?#參數內不能包含引號))*)(?#參數)\\))\\s*{"; char *pattern_macro = "#\\s?define\\s+(\\w+)\\s+(.+)"; //char *pattern_variables = "(\\w+)\\s+(\\w+);"; char *pattern_headers = "#\\s*include\\s*<(.+)>"; FILE *fp; regex_buf re_buf; int i; if(argc < 2) { fprintf(stderr, "缺少源文件\n"); return 1; } if(argc >= 2) { ifilename = argv[1]; } if(argc >= 3) { ofilename = argv[2]; } if((fp = fopen(ofilename, "w")) == NULL) { fprintf(stderr, "open file error!\n"); } read_file(ifilename, buf); printf("成功讀取%s......\n", ifilename); fprintf(fp, "\n##########################頭文件########################\n\n"); if(regex_f(buf, pattern_headers, &re_buf, REG_HEADERS) == 0) { for(i=0; i<re_buf.cn; i++) { fprintf(fp, "%d.頭文件: %20s\n", i+1, re_buf.buf.head[i][1]); } } printf("已分析完畢頭文件......\n"); fprintf(fp, "\n##########################宏##########################\n\n"); if(regex_f(buf, pattern_macro, &re_buf, REG_MACRO) == 0) { for(i=0; i<re_buf.cn; i++) { fprintf(fp, "%d.宏原型: %s\n", i+1, re_buf.buf.macr[i][0]); fprintf(fp, "宏名: %20s\n值: %20s\n", re_buf.buf.macr[i][1], re_buf.buf.macr[i][2]); } } printf("已分析完畢宏定義......\n"); fprintf(fp, "\n########################函數#########################\n\n"); if(regex_f(buf, pattern_function, &re_buf, REG_FUNCTION) == 0) { for(i=0; i<re_buf.cn; i++) { fprintf(fp, "%d.函數原型: %s\n", i+1, re_buf.buf.func[i][1]); fprintf(fp, "函數返回值: %10s\n函數名: %15s\n參數: %20s\n\n", re_buf.buf.func[i][2], re_buf.buf.func[i][3], re_buf.buf.func[i][4]); } } printf("已分析完畢函數......\n"); fclose(fp); printf("已成功寫入%s......\n", ofilename); return 0; } void read_file(char *filename, char *buf) { FILE *fp; char temp[1000]; if((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "readerr!\n"); exit(1); } buf[0] = '\0'; while(fgets(temp, sizeof(temp)-1, fp)) { strcat(buf, temp); } } int regex_f(char *src, char *pattern, regex_buf *re_buf, regex_flag flag) { pcre *re; const char *error; int erroffset; int ovector[OVECCOUNT]; int rc, i; int cn = 0; re_buf->flag = flag; re_buf->cn = 0; re = pcre_compile(pattern, 0, &error, &erroffset, NULL); if(re == NULL) { printf("PCRE compilation failed at offset %d: %s\n", erroffset, error); return 1; } rc = pcre_exec(re, NULL, src, strlen(src), 0, 0, ovector, OVECCOUNT); if(rc < 0) { if(rc == PCRE_ERROR_NOMATCH) printf("Sorry, no match ...\n"); else printf("Matching error %d\n", rc); free(re); return -1; } for(i=0; i<rc; i++) { char *substring_start = src + ovector[2*i]; int substring_length = ovector[2*i+1]-ovector[2*i]; //printf("%2d: %.*s\n", i, substring_length, substring_start); switch(flag) { case REG_MACRO: sprintf(re_buf->buf.macr[cn][i], "%.*s", substring_length, substring_start); break; case REG_FUNCTION: sprintf(re_buf->buf.func[cn][i], "%.*s", substring_length, substring_start); break; case REG_HEADERS: sprintf(re_buf->buf.head[cn][i], "%.*s", substring_length, substring_start); break; // 擴展 } } cn++; for(;;) { int start_offset = ovector[1]; rc = pcre_exec(re, NULL, src, strlen(src), start_offset, 0, ovector, OVECCOUNT); if(rc == PCRE_ERROR_NOMATCH) { /* 匹配完畢 */ break; } else if(rc < 0) { /* 匹配錯誤 */ //printf("Matching error %d\n", rc); pcre_free(re); return 1; } else if(rc == 0) { /* 匹配, 但空間不足 */ rc = OVECCOUNT/3; printf("ovector only has room for %d captured substring\n", rc-1); return 1; } for(i=0; i<rc; i++) { char *substring_start = src + ovector[2*i]; int substring_length = ovector[2*i+1] - ovector[2*i]; // printf("%2d: %.*s\n", i, substring_length, substring_start); switch(flag) { case REG_MACRO: sprintf(re_buf->buf.macr[cn][i], "%.*s", substring_length, substring_start); break; case REG_FUNCTION: sprintf(re_buf->buf.func[cn][i], "%.*s", substring_length, substring_start); break; case REG_HEADERS: sprintf(re_buf->buf.head[cn][i], "%.*s", substring_length, substring_start); break; // 擴展 } } cn++; } pcre_free(re); re_buf->cn = cn; return 0; }
說明 :
因為在windows下,配置pcre庫未成功,所以不打算弄個windows版本了。只有linux版本.
其實呢, 這個軟件和上一個 是我目標軟件中的兩個功能。現在把他們單獨實現。隨着以后的學習,有能力時,會繼續完成其他功能,然后整合在一起。
源程序:http://tanhe123.ys168.com/
源代碼:https://github.com/tanhe123/code_analyzer