2009-07-17 29 views
4

私はextremely long and complicated functions in the Linux kernelについての小規模な学術研究に取り組んでいます。私は、600または800行の長さの関数を記述する正当な理由があるかどうかを判断しようとしています。ソースファイルから単一の関数を抽出する方法

この目的のために、私は.cファイルから関数を抽出できるツールを探したいので、その関数についていくつかの自動テストを実行できます。

extract /fs/cifs/connect.c cifs_parse_mount_options 

とコードの523行を返す関数の(!):私は、ファイル内の関数connect.ccifs_parse_mount_options()をお持ちの場合は例えば

、私は大体同じように動作するソリューションを求めています、開き括弧から閉じ括弧に至るまで。

もちろん、これを行うにはgccのような既存のソフトウェアパッケージを操作する方法は、最も役に立ちます。

おかげで、

のUdi

EDITは:Regex to pull out C function prototype declarations?から答えは正規表現で、関数宣言に一致することは些細から遠く離れていることを私に確信させました。

答えて

3

小さなPERL/PHP/Pythonスクリプト、あるいはこれを実行する小さなC++、Java、C#プログラムを作成してみませんか?

私はそれを行うためのツールを知らないが、テキストファイルを解析してC++コードファイルから関数本体を抽出するコードを書くことは、20行以上のコードを取るべきではない。 難易度部分は機能の始めに位置しており、RegExを使用して比較的簡単な作業でなければなりません。その後、必要なのは、ファイルの残りの部分を繰り返して、中括弧の開閉を追跡し、関数の中身を閉じる中括弧に到達するだけです。あなたは少しsplit.awkのウィッヒを適応させる必要があり、コード-o code.out

のawk -f split.awk code.out

-kr

+0

これは私の最初のアイデアでしたが、コメントは少し複雑になりました。 しかし、もし私がそのようなスクリプトを書いているのであれば。私はそれを公開するだろうと思う - それは他の人にとって役に立つかもしれない。 –

+0

私は同意します。内側に不一致の中括弧が入っている可能性がある場合に備え、コメントを考慮する必要があるでしょう。それでもコード化するのは難しいことではありません。 –

+0

私は、それらを取り除き、関数の終わりの位置を取得し、コメント付きのコードを抽出する必要があります。 もう1つの問題は、上に関数シグネチャがあることです。これは複数行になる可能性があります。 前にも触れましたが、大したことではありませんが、私は研究に専念し、既製のツールを使用します。それができないなら、私はPythonに問題を起こすでしょう! –

1

インデントは私のコードとリファクタリングのニーズに多少固有のものです(例えばyがそう

をの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; 
       } 
0

:-)よりよいスクリプトを作ることができると確信しています名前:

1>関数名を抽出するためにctags(プログラム)を使用します。 ctags -x --c-kinds = fp path_to_file。 2>関数名を取得したら、上記の関数のスクリプト名を渡して関数の内容を抽出する単純なperlスクリプトを作成します。

関連する問題