ツリー図の作成[閉じる]

ツリー図の作成[閉じる]

ディレクトリにプログラムP11があり、このプログラムが2つの異なるプログラムP21とP22を呼び出すとします。 P21とP22はそれぞれ2〜2つの異なるプログラムを呼び出します。

つまり

Level-1:           |--------------P11-------------|
Level-2:  |--------P21----------|    |----------P22----------|...
Level-3:  P31                 P32    P33                   P34...
       .                   .      .                     .
       .                   .      .                     . 

水形図と同様に、100個のレベルがあり、各レベルには100個のノードがあるため、合計1000個のノードがあります。

このようなツリー構造を提供するには、シェルスクリプトが必要です。

たとえば、シェルスクリプトプログラムは -' MYPGM.sh' です。

実行時にパラメータが必要です。ここにプログラム名(例:P11)を指定できます。そしてスクリプトはそのようなツリー図を提供します。

出力構造は、上記の図のような形式である必要はありません。索引や提案するすべてを使用できます。たとえば、出力ファイルは次のようになります。

1. P11
1.1 P21 - 1.2 P22
1.1.1 P31 - 1.1.2 P32 – 1.2.1 P33 – 1.2.2 P34

つまり、各プログラムのインデックス=親プログラムのインデックス+「。」 + 対応する親プログラムのシリアル番号です。

実際には、レベル数と各レベルのノード数は不明ですが、非常に大きいということです。

他のプログラムを呼び出すためのプログラム構文は次のとおりです。

「CHILD_PGM_NAME」に電話をかける

特定のプログラムでサブルーチンを見つけるためのコマンドは次のとおりです。

 egrep '^CALL| CALL ' $pgm_name > call_output | cut -d'"' -f2 call_output > call_output_cut | cat call_output_cut

詰まった。上記の出力ファイルを取得するためにこのコマンドを繰り返す方法です。

誰でも提案できますか?

答え1

この問題は、awk、python、perlなどを提案します。以下の開始点は、まだアクセスされていない場合に「プログラム」をキューに追加するPerlスクリプトです。出力はグラフィック可視化形式です(@derobertが提案したように)。

#!/usr/bin/perl

print "digraph{\n rankdir=LR \n";

my %visited = ();
while(<>){                               # for all lines in all files in @ARGV

  $visited{$ARGV}=1;                     # $ARGV = current file

  if(/\bCALL\s*"(.+?)"/) {
      print "$ARGV -> $1;\n" ;
      push @ARGV,$1  unless $visited{$1};
      $visited{$1}=1;
  }
}

print "}\n";

使用法:

perl calltree p1 > x.dot
dot -Tpdf -o x.pdf x.dot

または(@derobertに感謝)

dot -Tx11 x.dot

今グラフを確認してください。

@muruが指摘したように、これは通常木ではありません。

答え2

@JJoaoの方法は間違いなく使用するのに最適です。しかし、私は面白いかもしれない非常に非効率的なスクリプトを書いています。

#! /bin/bash

SRC_DIR="/path/to/programs"
TMP_DIR="/tmp/tree"
declare -A FUNCS

iterate ()
(
    program="$1"
    FUNCS["$program"]="$TMP_DIR/$program"
    mkdir "${FUNCS[$program]}"
    grep -Po '(?<=\bCALL ")[^"]*' "$SRC_DIR/$program" | while read child
    do
        if [[ -n ${FUNCS[$child]} ]]
        then
            ln -s "${FUNCS[$child]}" "${FUNCS[$program]}/$child"
        else
            iterate "$child"
        fi
    done
)

[[ -n $1 ]] && { iterate "$1"; tree -dlo call-graph.html -H "$TMP_DIR" "$TMP_DIR"; }
rm -rf "$TMP_DIR"

ディレクトリを作成します、各ディレクトリは関数を表し、その関数が呼び出す他のディレクトリ/関数へのシンボリックリンクを含みます。このtreeプログラムは自然に木を描くのに慣れています(この-lオプションは、再帰が検出されない限りシンボリックリンクに沿って-oHTML出力を生成します)。

もちろん、理想的には、あなたの言語に適した呼び出しグラフジェネレータを見ることをお勧めします。これだから質問はC言語の複数のバージョンがリストされており、その言語をサポートするバージョンを見つけることができます。

関連情報