cprotoツールについて

# はじめに
　この記事では、cprotoというツールについて解説します。
cprotoとは、Cソースコードから関数のプロトタイプや変数宣言等ができるツールです。
これによりC言語を用いた開発業務の効率がupします。
インストール方法、オプション、使用例、注意点について解説します。

# cprotoとは
　cprotoとは、Cソースコードから関数プロトタイプ宣言や変数宣言、K＆Rスタイル ↔ ANSIスタイルの相互変換を行えるツールです。大量のCソースコードのK＆Rスタイル ↔ ANSIスタイルの相互変換を自動かつ一発で行える非常に便利なツールです。
タイポを防げかつ開発能率を上げることができます。

※K＆Rスタイルとは、以下の形式の関数宣言です。
```c
int main(argc, argv) // ()内に引数の型が宣言されていない。
int argc; 
char *argv []; 
{ 
}
```
　
※ANSIスタイルとは、以下の形式の関数宣言です。
```c
int main(int argc, char * argv []) // ()内に引数の型が宣言されている。
{
}
```

# インストール方法
　通常のツールのインストール方法と何ら変わりません。以下のサイトから実行ファイルをダウンロードできます。

　・Windows
　　http://gnuwin32.sourceforge.net/packages/cproto.htm

　・linux
　　http://rpmfind.net/linux/rpm2html/search.php?query=cproto

# オプション
　cprotoツールのオプションについて解説します。
　※linuxオプションを想定しています

* **-e**
グローバルスコープを持つ各宣言の前にexternを出力します。

* **-f** (数値)
生成される関数プロトタイプのスタイルを設定します。
※数値は0、1、2、3のいずれかです。

たとえば、以下の関数宣言があるとします。
```c
main (argc, argv)
int argc;
char *argv[];
{
}
```

n=0の場合、プロトタイプは生成されません。

n=1の場合、以下の出力になります。
```c
int main(/*int argc, char *argv[]*/);
```

n=2の場合、出力の形式は以下のとおりです。
```c
int main(int /*argc*/, char * /*argv*/[]);
```

デフォルト値は3です。これにより、完全な関数プロトタイプが生成されます。
```c
int main(int argc, char *argv[]);
```

* **-c**
-f1および-f2オプションによって生成されたプロトタイプのパラメーターコメントを出力します。
※デフォルトでは省略されます。

* **-m**
生成されたすべてのプロトタイプのパラメーターリストの周りにマクロを配置します。
例：
```c
int main P_((int argc, char * argv []));
```

* **-M** (マクロ名)
オプション-mで生成されるマクロの名前を設定します。
※デフォルトは「P_」

* **-d**
-mオプションで使用されるプロトタイプマクロの定義を省略します。

* **-l**
lint ライブラリのテキストを生成します。
「-f」オプションをオーバーライドします。
出力にはコメント「/ * LINTLIBRARY * /」が含まれます。

特別なコメントLINT_EXTERNおよびLINT_PREPRO（ "VARARGS"）は、それぞれ "-x"オプションをオンにし、コメントテキストを出力にコピーします（lintでの前処理用）。

コメント「/* LINT_EXTERN2 */」を使用して、インクルードファイルの第1レベルで定義されたexternをインクルードします。

コメント「/* LINT_SHADOWED */」を使用して、cprotoが各lintライブラリ宣言の前に「#undef」ディレクティブを配置するようにします。
つまり、関数と同じ名前が必要なマクロとの競合を回避し、構文エラーを引き起こします。

これらの特別なコメントは、VAX-Cでのcppの「-C」オプションに相当するものがないため、VAX/VMSではサポートされていないことに注意してください。

* **-o** (ファイル)
出力ファイル名を指定します。
※デフォルトでは標準出力に出力されます。

* **-O** (ファイル)
エラーファイル名を指定します。
※デフォルトでは標準エラーに出力されます。

* **-q**
プログラムが#includeディレクティブ で指定されたファイルを読み取れない場合、エラーメッセージを出力しません。

* **-i**
インライン宣言を出力します。
※デフォルトでは、グローバルスコープを持つ関数と変数の宣言のみ生成されます。

* **-s**
静的宣言を出力します。
※デフォルトでは、グローバルスコープを持つ関数と変数の宣言のみ生成されます。

* **-S**
静的宣言のみを出力します。

* **-T**
各ファイルからtypedef宣言をコピーします。
「-l」オプションとは異なり、インクルードファイルの定義はコピーされます。

* **-v**
ソースで定義された変数の宣言を出力します。

* **-x**
「extern」と宣言されたプロシージャと変数を出力に含めます。

* **-X** (レベル)
宣言が抽出されるインクルードファイルレベルを制限します。

* **-a**
関数定義をK＆RスタイルからANSIスタイルに変換します。

* **-t**
関数定義をANSIスタイルからK＆Rスタイルに変換します。

* **-b**
関数定義ヘッダを書き直して、条件付きコンパイルディレクティブで区切られたK＆RスタイルとANSIスタイルの両方の宣言を含めます。
例：
```c
#ifdef ANSI_FUNC
int
main (int argc, char *argv[])
#else

int
main (argc, argv)
int argc;
char *argv[]
#endif
{
}
```

* **-B** (ディレクティブ)
-bオプションによって生成された関数定義の先頭に出力するように、条件付きコンパイルディレクティブを設定します。
※デフォルトは#ifdef ANSI_FUNC

* **-P** (テンプレート)
* **-F** (テンプレート)
* **-C** (テンプレート)
生成されたプロトタイプ、関数定義、および関数定義の出力形式を、それぞれパラメーターコメント付きで設定します。
フォーマットは、以下のテンプレートによって指定されます。
```c
" int f ( a, b )"
```
ただし、この文字列の各スペースを任意の数の空白文字に置き換えることができます。

例：オプション
```c
-F"int f(\n\ta,\n\tb\n\t)"
```
は以下を生成します。
```c
int main(
        int argc,
        char *argv[]
        )
```

* **-p**
K＆Rスタイルの関数定義で仮パラメータの昇格を無効にします。
※デフォルトでは、char型またはshort型 → int型、float型 → double型に昇格されます。

* **-D** (名前)
プリプロセッサに渡され、 ＃ifdefなどの条件で使用するシンボルを定義するために使用されます。

* **-U** (名前)
プリプロセッサに渡され、シンボルの定義を削除するために使用されます。

* **-I** (ディレクトリ)
プリプロセッサに渡され、＃includeで参照されるファイルを検索するディレクトリを指定するために使用されます。

* **-E** cpp
プロトタイプを生成するときに、指定されたCプリプロセッサコマンドを介して入力ファイルをパイプします。
※デフォルトでは、プログラムは/ lib/cppを使用します。

* **-E** 0
Cプリプロセッサが実行されません。

* **-V**
バージョン情報を出力します。

# 使用例
　cprotoを使用することで関数宣言の記述がどのように変換されるか、実行イメージを記載します。

## 1．K＆R → ANSI変換

**before**
```c
int main(argc, argv) // K＆Rスタイル
int argc;
char *argv[];
{
}
```
 
 **↓  <font color="DarkBlue">「cproto -a (ソースファイル名) 」</font>**

**after**
```c
int 
main (int argc, char *argv[]) // ANSIスタイル
{
}
```

## 2．K＆R → ANSI変換 型昇格を防ぐ

**before**
```c
void xxyyzz(a, b) // K＆Rスタイル
int a;
short b;
{
}
```
            
 **↓  <font color="DarkBlue">「cproto -ap (ソースファイル名)」</font>**

**after**
```c
void xxyyzz(int a, short b) // ANSIスタイル 引数bの型がshortのまま。
{
}
```
オプション「p」を付けない場合、型昇格が自動で行われ void xxyyzz(int a, int b){}となります。

# 注意点
　cproto使用時の注意点を2点述べます。

1. 変換元のファイルを上書きしてしまうので、困るのであれば使用前にバックアップを取ってください。
2. プロトタイプや関数定義にタグなし構造体、共用体が記載されている場合、{}の中の宣言が空になります。
実行後手動で補う等してください。

# おわりに
　ここまでcprotoツールについて解説しました。
cprotoの使用についてググった際記事が充実しておらず不便な思いをしたので、投稿を決意しました。
この記事が誰かにとって参考になれば幸いです。