過去のソフトの解析として、関数呼び出しの関係を可視化したい


過去のソフトの解析を現在行っているのですが  
関数の呼び出しをリスト化するアプリは無いでしょうか

doxygenでコールグラフは作れたのですがあまりに入り組んでいて、書類化出来ないので  
csv等で出力したいです(csvに限らずとにかくリスト化できればいいです)

fooa->foob->fooc1  
->fooc2

という呼び出しだったら  
fooa,foob,fooc1  
,,fooc2

のように出力するソフトを探しています  
無意味に再帰していたり、関数のコールがループしたりしていたりするのでそれもマークをつけてくれると嬉しいですが  
とにかくリスト化できるようなアプリがあったら教えてください




user29553さんのコメントにありますが、cflowがいいと思います。  
結果をCSVに整形してみました。

【awkによる整形の例(call_stack.sh)】

[code]

    #!/bin/bash
    while read file; do cflow ${file}; done | sed '
    s/    /\t/g
    s/) /)\t/
    ' | awk -F '\t' '
    BEGIN{
            ##DELIMITER = "->"
            DELIMITER = ","
    }
    {
            num = NF;
            for(no = 1; no <= num; no++){
                    if($no != ""){
                            if(!match($no, "^<")){
                                    ga[no] = $no
                            }
                            else{
                                    if(match($no, "recursive:")){
                                            ga[no-1] = ga[no-1] "*";
                                    }
                                    delete ga[no];
                                    num -= 1;
                            }
                    }
            }
            dlmt = ""
            call_stack = "";
            for(no = 1; no <= num; no++){
                    call_stack = call_stack dlmt ga[no]
                    dlmt = DELIMITER
            }
            printf("%s\n", call_stack);
    }
    '
    
    
[/code]

【使い方】

[code]

    find . -name "*.c" | ./call_stack.sh
    
    
[/code]

【実行結果】  
単純な再帰呼び出しはcflowが検出してくれるので、関数に`*`をマークしました。

[code]

    func()
    func(),printf()
    func(),func2()
    func(),n_sub()
    func(),n_sub(),func3()
    func(),n_sub(),printf()
    func(),func()*
    func2()
    func2(),printf()
    func2(),n_sub()
    func2(),n_sub(),func3()
    func2(),n_sub(),printf()
    func2(),func()
    func3()
    func3(),printf()
    func3(),func2()
    func3(),n_sub()
    func3(),n_sub(),printf()
    main()
    main(),printf()
    main(),n_sub()
    main(),n_sub(),printf()
    main(),func()
    main(),func2()
    
    
[/code]

【cflowの出力(参考)】

[code]

    for file in *.c; do cflow  ${file}; done
    
[/code]

[code]

    func() <int func () at func.c:7> (R):
        printf()
        func2()
        n_sub() <int n_sub () at func.c:14>:
            func3()
            printf()
        func() <int func () at func.c:7> (recursive: see 1)
    func2() <int func2 (void) at func2.c:7>:
        printf()
        n_sub() <int n_sub () at func2.c:13>:
            func3()
            printf()
        func()
    func3() <int func3 () at func3.c:5>:
        printf()
        func2()
        n_sub() <int n_sub () at func3.c:11>:
            printf()
    main() <int main (int argc, char *argv[]) at main.c:6>:
        printf()
        n_sub() <int n_sub () at main.c:13>:
            printf()
        func()
        func2()
    
    
[/code]

【使用したツール】

cflow (GNU cflow) 1.4  
sed (GNU sed) 4.4  
GNU bash, バージョン 4.4.20(1)-release (x86_64-pc-linux-gnu)  
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 4.0.1, GNU MP 6.1.2)

【おまけ】

ClangのPython bindingを使うと、C言語のソース解析がとても楽にできます。  
※ 関数の呼び出し関係を調べるだけならcflowの方が簡単です。

