39

元の質問

私が望むのは、標準の C プリプロセッサではなく、どこか (おそらく -DNAME1 および -UNAME2 オプションを介したコマンド ライン) から受け入れられるバリエーションであり、どのマクロが定義されているかの仕様であり、デッドを排除します。コード。

いくつかの例を使用すると、私が求めていることを理解しやすくなる場合があります。

#ifdef NAME1
#define ALBUQUERQUE "ambidextrous"
#else
#define PHANTASMAGORIA "ghostly"
#endif

コマンドが「-DNAME1」で実行された場合、出力は次のようになります。

#define ALBUQUERQUE "ambidextrous"

コマンドが「-UNAME1」で実行された場合、出力は次のようになります。

#define PHANTASMAGORIA "ghostly"

どちらのオプションも指定せずにコマンドを実行すると、出力は入力と同じになります。

これは単純なケースです。コードがより複雑なケースも処理できることを願っています。

現実世界の単純な例で説明するには:

#ifdef USE_VOID
#ifdef PLATFORM1
#define VOID void
#else
#undef VOID
typedef void    VOID;
#endif /* PLATFORM1 */
typedef void *  VOIDPTR;
#else
typedef mint     VOID;
typedef char *  VOIDPTR;
#endif /* USE_VOID */

コマンドを実行して出力を取得したい-DUSE_VOID -UPLATFORM1

#undef VOID
typedef void    VOID;
typedef void *  VOIDPTR;

もう一つの例:

#ifndef DOUBLEPAD
#if (defined NT) || (defined OLDUNIX)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */

-UOLDUNIX理想的には、実行して出力を取得したいと思います。

#ifndef DOUBLEPAD
#if (defined NT)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */

これは私の運を後押ししているかもしれません!

動機: 多数の条件付きコードを含む大規模で古いコード ベース。条件の多くは適用されなくなりました。たとえば、OLDUNIX プラットフォームは製造されなくなり、サポートも終了したため、コード内でこれを参照する必要はありません。他の条件は常に true です。たとえば、条件付きコンパイルを使用して機能が追加されるため、単一バージョンのコードを、機能が利用できない古いバージョンのソフトウェアと利用できる新しいバージョンの両方に使用できます (多かれ少なかれ)。最終的に、機能のない古いバージョンはサポートされなくなります - すべてが機能を使用します - そのため、機能が存在するかどうかの条件を削除し、「機能が存在しない場合」のコードも削除する必要があります。私'

(ツールの非常に賢いバージョンは、#include'd ファイルを読み取って、コマンド ラインで -D または -U によって指定された制御マクロがそれらのファイルで定義されているかどうかを判断する場合があります。ただし、それが何をするにしても、疑似プリプロセッサはマクロを展開したり、ファイルを逐語的にインクルードしたりしてはなりません. 出力は、入力コードと同様のソースである必要がありますが、通常は入力コードよりも単純でなければなりません.)

現状報告(1年後)

1年間使用した後、選択した回答が推奨する「 sunifdef 」に非常に満足しています。それはまだ間違いを犯していませんし、そうなるとは思っていません。私がそれについて持っている唯一の疑問は文体です。次のような入力が与えられた場合:

#if (defined(A) && defined(B)) || defined(C) || (defined(D) && defined(E))

'-UC' (C は定義されていません) を指定して実行すると、出力は次のようになります。

#if defined(A) && defined(B) || defined(D) && defined(E)

「&&」は「||」よりも強く結合するため、これは技術的には正しいのですが、混乱への公然たる招待状です。元のように、「&&」条件のセットを括弧で囲むことをお勧めします。

#if (defined(A) && defined(B)) || (defined(D) && defined(E))

ただし、私が使用しなければならないコードの一部が不明瞭であることを考えると、それが最大のつまらないものであるということは、強力な賛辞です。それは私にとって貴重なツールです。


ザ・ニュー・キッド・オン・ザ・ブロック

上記の情報に含まれる URL を確認したところ、(予測どおり) 「sunifdef」の後継であるCoanという新しいプログラムがあることがわかりました。これは SourceForge で入手でき、2010 年 1 月から利用できます。私はそれを調べます...今年後半、または来年、あるいはいつか、またはまったく報告しないでしょう。

4

5 に答える 5

26

Cについてはまったく知りませんが、のようなものを探しているようunifdefです。2000年以降更新されていないことに注意してください。ただし、「Son of unifdef」(sunifdef)と呼ばれる後継があります。

于 2009-02-08T07:09:13.017 に答える
6

また、このツールを試すこともできますhttp://coan2.sourceforge.net/

このようなものは ifdef ブロックを削除します:

coan source -UYOUR_FLAG --filter c,h --recurse YourSourceTree

于 2013-06-20T15:58:53.303 に答える
4

私は何年も前に、あなたが説明した種類の問題に unifdef を使用しましたが、うまくいきました。2000 年以降更新されていない場合でも、プリプロセッサの ifdefs の構文はそれ以来大幅に変更されていないため、引き続き期待どおりの動作をすると思います。パッケージは最近のように見えますが、コンパイルに問題がある可能性があると思います。

私は sunifdef を使ったことがないので、直接コメントすることはできません。

于 2009-02-08T07:37:46.033 に答える
3

2004年頃、私はあなたが探しているものを正確に実行するツールを書きました. ツールを配布することはできませんでしたが、コードは次の場所にあります。

http://casey.dnsalias.org/exifdef-0.2.zip (これは DSL リンクです)

これは約 1.7k 行であり、bison と flex を使用してプリプロセッサ ステートメント、コメント、および文字列を解析するのに十分な C 文法を実装しています。

于 2009-02-08T07:36:21.557 に答える
2

プリプロセッサに似たものが必要な場合、柔軟なソリューションはWave (boost から) です。これは、C プリプロセッサのようなツール (C++03 や C++0x プリプロセッサなどを含む) を構築するために設計されたライブラリです。ライブラリなので、その入力コードと出力コードにフックできます。

于 2009-02-10T14:39:57.370 に答える