次へ: 4 行のチェック
上へ: C のソースからプロトタイプ宣言を作成
前へ: 2 プロトタイプ宣言について
(PDF ファイル: awktg.pdf)
3 関数定義部の取り出しについて
人によって C のソースの書き方は色々あるので
万人向けのツールを作るのは難しいですが、
自分の (今の) ソースの書き方に限定すれば2関数定義の先頭を見つけるのはそれほど難しくはないと思います。
私は、C の関数の書き方は、例えば以下のようにしています。
int f1(int x,int y)
{
int p;
....
}
int f2(double *long_name_variable_1, int *long_name_variable_2,
char *long_name_variable_3, float *long_name_variable_4,
long *long_name_variable_4)
{
int p;
....
}
おおまかには、次のようなルールで書いています。
- 関数の返り値の型と関数名、およびそれに続く小カッコ `(' は
同じ行に書く。
- 関数の返り値の型は、インデントなしに行の先頭から書き始める。
- 関数の引数部が長い場合、それはすぐ次の行にインデント
(行頭にタブやスペースを入れること) をして書き続ける。
- 引数部の終わりの小カッコ `)' は、引数部の行末につける。
- 引数部の行の次の行に、インデントなしで中カッコ `{'
のみの行を書き、関数本体は、その次の行からインデントをつけて書く。
- 関数本体の終わりは、インデントなしで中カッコ `}'
のみの行を書く。
この私の (現在の) ルールによれば、行頭にインデントなしで
(中カッコでなく) 文字が始まっていればそれは関数定義部となりそうですが、
実際の C のソースでは必ずしもそうではなく、
これ以外にも行頭から文字が始まる場合があります。
私が関数定義部以外に行頭から書くものとしては、以下のようなものがあります。
- 外部変数宣言
int external_variable1;
double ex1=0.0,ex2=1.0;
- マクロ定義、インクルードファイルなどのプリプロセッサ命令
#include <stdio.h>
#define add(x,y) ((x)+(y))
#ifdef HOGE
(長いマクロ定義では、2 行目以降にインデントを入れて書く)
- 構造体、共用体、enum の定義
typedef struct mylist {
int n;
struct mylist *next;
} Mylist;
enum Error_number { Err_file, Err_input, No_Err=0 };
- コメント
/* これはコメント */
/* これもコメント
* これもコメント
*/
- (既にある) 関数のプロトタイプ宣言
これらがあるので、単純に行頭が文字列でも関数定義とは限りませんが、
コメントやプリプロセッサは、
行頭が記号 (`#', `/') ですからこれは考慮する必要はなく、
構造体などは、その行に小カッコ `(' が含まれないのでそれで判別できます。
外部変数は、小カッコが含まれるもの、例えば
char (*a)[10];
double (*f)(double);
みたいなものを決して使わないとはいえませんが、
これは行末が `)' では終わらず、`;' で終わりますので
それで判別できます。
プロトタイプ宣言が既にある場合も同様です。
よって、今回は、
- 行頭がアルファベット、または `_' (アンダースコア) で始まっていて、
その行に `(' が含まれ、
- その行末が、`)' であるか、
またはそれ以下にインデントされている行がいくつか続き、
その最後の行の行末が `)' となっていて、
- その次の行が `{' のみの行
である場合にこの部分が関数定義であると見なし、
それを抜き出して `;' を付加して出力することにします。
結局、この関数定義部分の判別は複数の行によってなされることになるので、
AWK でも結構面倒です。
次へ: 4 行のチェック
上へ: C のソースからプロトタイプ宣言を作成
前へ: 2 プロトタイプ宣言について
竹野茂治@新潟工科大学
2006年6月22日