Open1

Cプログラムのヘッダーおよびソースファイルから関数定義部を抽出する

堀江誠一堀江誠一

表題の方法を調べたのでメモしておく。なお、C++のクラスや構造体からのメンバー関数の抽出などはとりあえず考えていない。

中核をなす処理は関数定義部の抽出で、これにはctagsを使う。ただし、ctagsは関数定義部が複数行に分割されている時には最初の1行しか抽出できない。そこで事前にclang-formatで関数をフォーマットして関数定義部を1行にしてしまう。

ヘッダー部分を1行に整形する

clang-formatを使うと簡単にC/C++プログラムを整形できる。整形の方法として多様なオプションが用意されているが、今回は関数定義部のみ抽出すればいいので、それに見合った整形をする。要するに途中で折り返しが起きないよう、1行の長さを長くしてしまえばいい。

--style引数のColumnLimit:によって指定できる。ColumnLimit:は':'の後ろに空白が必要であることに注意。

clang-format foo.h --style="{ColumnLimit: 9999}" > bar.h

結果を標準出力ではなくファイルに出力しているのは後述のctagsの制限による。

関数定義部の抽出

ctagsは本来エディタ向けのツールで、ソースコードからインデックス情報を取り出すためのものである。これに-xオプションを与えると、結果をテキストにしてくれる。--c++-kinds=pfは、staticおよび非staticな関数の双方を抽出するよう指示している。

なお、ctagsはソースコードを標準入力から受け取ることはできない。

ctags -x --c++-kinds=pf bar.h  

ただ、これだけだと不要な情報が含まれる。具体的には

  • 関数定義部に続く関数本体などが同じ行にあると、そのまま出力される。
  • 関数プロトタイプの;が出力される。
  • インデックスのための情報が出力される。

そこで、以下のパイプラインで不要な情報を削除している。

まず、{以降行末までと、;以降行末までをsedで削除する。

sed s/{.*$// | sed s/\;.*$//

次に、インデックス情報である最初の4つのフィールドをawkで空欄にする。

awk '{$1="";$2="";$3="";$4="";print $0}'

最後に、inline,staticといった不要なキーワードをsedで削除する。

sed s/static// | sed s/inline// 

これらを合わせて一つにすると、以下の通りになる。

ctags -x --c++-kinds=pf bar.h | sed s/{.*$// | sed s/\;.*$// | awk '{$1="";$2="";$3="";$4="";print $0}'| sed s/static// | sed s/inline//