UNIFDEF(1)

名称
unifdef, unifdefall - プリプロセッサ条件行を取り除く

書式
unifdef [-ceklst] [ -Ipath -Dsym[=val] -Usym -iDsym[=val] -iUsym] ... [file] unifdefall [-Ipath] ... file

解説
unifdef ユーティリティは cpp(1) の条件ディレクティブ (前処理指令) を選択的に処理します。 ファイルから削除するように特定されたディレクティブとテキストの 両方を削除します。 そうでない場合はファイルをそのままにしておきます。

unifdef ユーティリティは #if, #ifdef, #ifndef, #elif, #else, #endif 行に働きますが、 #if と #elif 行の式文法のよく使われるサブセットしか理解しません。 コマンドラインで定義されたシンボルの整数値や defined() オペレータがコマンドラインで define したり、undefine したシンボルや 演算子!, <, >, <=, >=, ==, !=, &&, || と括弧で囲まれた式を扱うことができます。 より複雑なものはそのまま無傷で通過させます。 #ifdef と #ifndef ディレクティブはシンボルがコマンドラインで指定された場合だけ 処理されます。その他の場合には変更されずに、素通りさせます。 デフォルトでは、定数式を持つ #if と #elif の行は無視しますが、コマンドラインに -k フラグを指定することによりこれらを処理できます。

unifdef ユーティリティにはコメントやバックスラッシュによる行継続 で無効にされたディレクティブも理解することができます。 また、普通ではない形式のプリプロセッサディレクティブを指摘することで、 レイアウトが変になりすぎてもう扱えないことを検知します。

unifdefall シェルスクリプトはファイルから cpp(1) の条件処理ディレクティブをすべて削除することができます。 すべての制御シンボルとその定義 (または未定義) のリストを得るために、 unifdef -s と cpp -dM を使用します。 それからそのファイルを処理するのに適切な引数を付けて unifdef を呼び出します。

利用可能なオプション :

-Dsym[=val]
    定義されるシンボルを指定します。 また、オプションで #if と #elif ディレクティブを操作するためにシンボルに与える値を指定します。

-Usym
    未定義にするシンボルを指定します。 同じシンボルを複数指定した場合には、 最後に指定されたものが有効になります。

-c  -c フラグが指定された場合には、 unifdef の動作は逆にされます。 すなわち、削除されるか空白にされる行を残し、 逆に残すはずだった行を削除します。

-e  unifdef は入力行を 1 度に 1 行ずつ処理しますので、 複数行にまたがるプリプロセッサディレクティブを削除できません。 もっとも一般的な例は、 複数行にわたって右側にぶらさがるコメントが付く、ディレクティブです。 デフォルトでは、 unifdef がそのようなディレクティブを処理するときは、行が分かりにくいと文句を言います。 -e オプションはこの動作を変え、 可能ならばエラーを報告する代りにそのような行をそのまま残します。

-k  定数式を持つ #if と #elif の行を処理します。 デフォルトでは、このような行で制御される部分は変更されずに素通りされます。 なぜなら、これらは典型的には “#if 0” で始まり、未来または過去の開発の概要を記述するコメント的に使用されるからです。 通常のコメントを削除してしまうことが失礼かもしれないのと同様、 これらを削除してしまうのは失礼かもしれません。

-l  削除される行を削除する代わりに空行に置き換えます。

-s  通常の入力ファイルを処理する代わりに、 このオプションは unifdef に unifdef が理解する式に現れたシンボルのリストを生成させます。 それは、 cpp(1) の -dM オプションと協力して unifdef のコマンドラインを生成するのに有用です。

-t  C 言語のコメントと行の継続の解釈を禁止します。 通常のテキストファイル等に unifdef を適用する場合に有用です。

-iDsym[=val]
-iUsym
    #ifdef を無視します。C 言語のコードで #ifdef をコメントや作りかけのコードのような C 言語でない部分を区切るために用いている場合は、 unifdef が #ifdef の中のコメントや行の継続を解析しないように どのシンボルがその目的で使用されているかを指示する必要があります。 無視するシンボルを指示する方法は -iDsym[=val] や -iUsym で、上記の -Dsym[=val] や -Usym と同様です。

-Ipath
    unifdefall に追加の場所にある #include ファイルを探すように指示します。 cpp(1) との互換性と unifdefall の実装を簡単にするために unifdef はこのオプションは無視します。

unifdef ユーティリティはその出力を stdout にコピーします。 file 引数が指定されなかった場合は stdin から読み込みます。

unifdef ユーティリティは diff(1) の -Dsym オプションとともに使用することができます。

関連項目
cpp(1), diff(1)

診断

多過ぎるネストレベルを検出します。

不適切な #elif, #else, #endif を検出します。

分かりにくいプリプロセッサ制御行を検出します。

早過ぎる EOF を検出します (もっとも最近の未完了の #if の行番号を表示します)。

コメント中の EOF を検出します。
unifdef ユーティリティは出力が入力と同じになる場合 0、 そうでなければ 1、エラー時には 2 を終了ステータスとして返します。

バグ
構文評価がたいへん限定的です。

(コメントまたはバックスラッシュと改行によって) 複数の物理行にまたがるプリプロセッサ制御行は、 すべての状況において正しく扱われるわけではありません。

トライグラフは認識されません。

ソースファイル中の複数の場所で異なった定義を持つシンボルはサポートされません。

テキストモードおよび機能無視は、最近の cpp(1) の動作とは対応していません。

歴史
unifdef は 4.3BSD から登場しました。 ANSI C サポートは FreeBSD 4.7 で追加されました。