如何从源文件中提取单个函数

时间:2009-07-17 15:37:43

标签: c regex text-processing code-metrics mcc

我正在开展一项关于extremely long and complicated functions in the Linux kernel的小型学术研究。我试图找出是否有充分的理由来编写600或800行长的函数。

为此,我想找到一个可以从.c文件中提取函数的工具,这样我就可以在函数上运行一些自动化测试。

例如,如果我在文件connect.c中有函数cifs_parse_mount_options(),我正在寻找一个大致类似的解决方案:

extract /fs/cifs/connect.c cifs_parse_mount_options

并返回函数的523行代码(!),从开括号到结束括号。

当然,任何操纵现有软件包(如gcc)的方法都是最有帮助的。

谢谢,

乌迪

编辑: Regex to pull out C function prototype declarations?的答案使我确信正则表达式匹配的函数声明远非微不足道。

3 个答案:

答案 0 :(得分:3)

为什么不编写一个小的PERL / PHP / Python脚本,甚至是一个小的C ++,Java或C#程序呢?

我不知道有任何已经制作的工具,但是编写代码来解析文本文件并从C ++代码文件中提取函数体不应该超过20行代码。 难以部分将定位函数的开头,这应该是使用RegEx的相对简单的任务。之后,您只需要遍历文件的其余部分,跟踪打开和关闭花括号,当您到达函数体关闭括号时,您就完成了。

答案 1 :(得分:1)

缩进-kr代码-o code.out

awk -f split.awk code.out

你必须适应一点split.awk,这有点特定于我的代码和重构需求(例如y有这样的struct不是typedef

我相信你可以制作一个更好的剧本: - )

--
BEGIN   { line=0; FS="";
    out=ARGV[ARGC-1]  ".out";
    var=ARGV[ARGC-1]  ".var";
    ext=ARGV[ARGC-1]  ".ext";
    def=ARGV[ARGC-1]  ".def";
    inc=ARGV[ARGC-1]  ".inc";
    typ=ARGV[ARGC-1]  ".typ";
    system ( rm " " -f " " out " " var " " ext " " def " " inc " " typ );
    }
/^[     ]*\/\/.*/   { print "comment :" $0 "\n"; print $0 >> out ; next ;}
/^#define.*/        { print "define :" $0 ; print $0 >>def ; next;}
/^#include.*/       { print "define :" $0 ; print $0 >>inc ; next;}
/^typedef.*{$/      { print "typedef var :" $0 "\n"; decl="typedef";print $0 >> typ;infile="typ";next;}
/^extern.*$/        { print "extern :" $0 "\n"; print $0 >> ext;infile="ext";next;}
/^[^    }].*{$/     { print "init var :" $0 "\n";decl="var";print $0 >> var; infile="vars";
                print $0;
                fout=gensub("^([^    \\*])*[    ]*([a-zA-A0-9_]*)\\[.*","\\2","g") ".vars";
                     print "var decl : " $0 "in file " fout;
                     print $0 >fout;
                next;
                        }
/^[^    }].*)$/     { print "func  :" $0 "\n";decl="func"; infile="func";
                print $0;
                fout=gensub("^.*[    \\*]([a-zA-A0-9_]*)[   ]*\\(.*","\\1","g") ".func";
                     print "function : " $0 "in file " fout;
                     print $0 >fout;
                next;
            }
/^}[    ]*$/        { print "end of " decl ":" $0 "\n"; 
                if(infile=="typ") {
                    print $0 >> typ;
                }else if (infile=="ext"){
                    print $0 >> ext;
                }else if (infile=="var") {
                    print $0 >> var;
                }else if ((infile=="func")||(infile=="vars")) {
                    print $0 >> fout; 
                    fflush (fout);
                    close (fout);
                }else if (infile=="def") {
                    print $0 >> def;
                }else if (infile=="inc"){
                    print $0 >> inc;
                }else print $0 >> out;
                next;
            }
/^[a-zA-Z_]/        { print "extern :" $0 "\n"; print $0 >> var;infile="var";next;}
            { print "other :" $0 "\n" ; 
                if(infile=="typ") {
                    print $0 >> typ;
                }else if (infile=="ext"){
                    print $0 >> ext;
                }else if (infile=="var") {
                    print $0 >> var;
                }else if ((infile=="func")||(infile=="vars")){
                    print $0 >> fout;
                }else if (infile=="def") {
                    print $0 >> def;
                }else if (infile=="inc"){
                    print $0 >> inc;
                }else print $0 >> out;
               next;
               }

答案 2 :(得分:0)

如果您发现难以提取函数名称:

1>使用ctags(程序)来提取函数名称。   ctags -x --c-kinds = fp path_to_file。 2 - ;一旦你得到了函数名,就编写一个简单的perl脚本,通过传递上述函数的脚本名来提取函数的内容。