latest release v1.8.11 - last update Sun Aug 15 2021 |
前処理doxygenの入力に使うソースファイルは、組込のC言語プリプロセッサによって解析します。 デフォルトでは、部分的な前処理しかしません。つまり、条件付コンパイル構文(#ifのような)と、マクロ定義は評価しますが、マクロ展開はしません。 ですので、次のようなコード断片があると、 #define VERSION 200 #define CONST_STRING const char * #if VERSION >= 200 static CONST_STRING version = "2.xx"; #else static CONST_STRING version = "1.xx"; #endif doxygenは、以下のようにパーサーに渡します。 #define VERSION #define CONST_STRING static CONST_STRING version = "2.xx"; 前処理を全部無効にするには、設定ファイルで、ENABLE_PREPROCESSING を static CONST_STRING version = "2.xx"; static CONST_STRING version = "1.xx";
#define VERSION #define CONST_STRING static const char * version = "1.xx"; となります。 このとき、doxygenは すべて のマクロ定義を展開します(必要なら再帰的に)。 しかし、これでは過剰なことも多いです。 ですので、明示的に指定したdefineのみを展開するよう指示することもできます。 それには、EXPAND_ONLY_PREDEF を 前処理時点でヘルプが必要となる典型的な例があります。それは、Microsoft の言語拡張 declspec と、GNU の __attribute 拡張です。前者の例です。 extern "C" void __declspec(dllexport) ErrorMsg( String aMessage,...); 何もしないと、doxygenは混乱し、__declspec をある種の関数とみなします。この場合、次のようにします。 ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES PREDEFINED = __declspec(x)= こうすると、__declspec(dllexport) が、ソースコードを解析する前に、確実に取り除かれます。 さらに複雑な例として、 /*! IID への参照 */ #ifdef __cplusplus #define REFIID const IID & #else #define REFIID const IID * #endif /*! IUnknown インターフェース */ DECLARE_INTERFACE(IUnknown) { STDMETHOD(HRESULT,QueryInterface) (THIS_ REFIID iid, void **ppv) PURE; STDMETHOD(ULONG,AddRef) (THIS) PURE; STDMETHOD(ULONG,Release) (THIS) PURE; }; マクロを展開しないと、doxygenは混乱してしまうでしょう。しかし、REFIIDマクロは展開したくないところです。ドキュメントがついていますし、ドキュメントを読んだユーザは、インタフェースを実装する際に使うことになるからです。 設定ファイル内で次のように設定すれば、 ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES PREDEFINED = "DECLARE_INTERFACE(name)=class name" \ "STDMETHOD(result,name)=virtual result name" \ "PURE= = 0" \ THIS_= \ THIS= \ __cplusplus 次のように、適切な結果がdoxygenパーサーに与えられます。 /*! IID への参照 */ #define REFIID /*! IUnknown インターフェース */ class IUnknown { virtual HRESULT QueryInterface ( REFIID iid, void **ppv) = 0; virtual ULONG AddRef () = 0; virtual ULONG Release () = 0; }; ここで、PREDEFINED タグは、関数形式のマクロ定義( また、通常はプリプロセッサが自動的に定義するプリプロセッサ定義( 場合によっては、マクロ名や関数を他のもので置き換えて、その結果をマクロ置換えさせたくないこともあるでしょう。これを行うには、 例えば、次のようなコードがあるとします。 #define QList QListT class QListT { }; QListクラスのクラス定義としてdoxygenに解釈させる方法は、以下のようにdefineするしかありません。 PREDEFINED = QListT:=QList 次は、Valter Minute と Reyes Ponce から提供された例です。これで、MicrosoftのATL & MFC ライブラリの定型コードを読み進むことが可能なように、doxygenをサポートしてくれます。 PREDEFINED = "DECLARE_INTERFACE(name)=class name" \ "STDMETHOD(result,name)=virtual result name" \ "PURE= = 0" \ THIS_= \ THIS= \ DECLARE_REGISTRY_RESOURCEID=// \ DECLARE_PROTECT_FINAL_CONSTRUCT=// \ "DECLARE_AGGREGATABLE(Class)= " \ "DECLARE_REGISTRY_RESOURCEID(Id)= " \ DECLARE_MESSAGE_MAP= \ BEGIN_MESSAGE_MAP=/* \ END_MESSAGE_MAP=*/// \ BEGIN_COM_MAP=/* \ END_COM_MAP=*/// \ BEGIN_PROP_MAP=/* \ END_PROP_MAP=*/// \ BEGIN_MSG_MAP=/* \ END_MSG_MAP=*/// \ BEGIN_PROPERTY_MAP=/* \ END_PROPERTY_MAP=*/// \ BEGIN_OBJECT_MAP=/* \ END_OBJECT_MAP()=*/// \ DECLARE_VIEW_STATUS=// \ "STDMETHOD(a)=HRESULT a" \ "ATL_NO_VTABLE= " \ "__declspec(a)= " \ BEGIN_CONNECTION_POINT_MAP=/* \ END_CONNECTION_POINT_MAP=*/// \ "DECLARE_DYNAMIC(class)= " \ "IMPLEMENT_DYNAMIC(class1, class2)= " \ "DECLARE_DYNCREATE(class)= " \ "IMPLEMENT_DYNCREATE(class1, class2)= " \ "IMPLEMENT_SERIAL(class1, class2, class3)= " \ "DECLARE_MESSAGE_MAP()= " \ TRY=try \ "CATCH_ALL(e)= catch(...)" \ END_CATCH_ALL= \ "THROW_LAST()= throw"\ "RUNTIME_CLASS(class)=class" \ "MAKEINTRESOURCE(nId)=nId" \ "IMPLEMENT_REGISTER(v, w, x, y, z)= " \ "ASSERT(x)=assert(x)" \ "ASSERT_VALID(x)=assert(x)" \ "TRACE0(x)=printf(x)" \ "OS_ERR(A,B)={ #A, B }" \ __cplusplus \ "DECLARE_OLECREATE(class)= " \ "BEGIN_DISPATCH_MAP(class1, class2)= " \ "BEGIN_INTERFACE_MAP(class1, class2)= " \ "INTERFACE_PART(class, id, name)= " \ "END_INTERFACE_MAP()=" \ "DISP_FUNCTION(class, name, function, result, id)=" \ "END_DISPATCH_MAP()=" \ "IMPLEMENT_OLECREATE2(class, name, id1, id2, id3, id4,\ id5, id6, id7, id8, id9, id10, id11)=" doxygenのプリプロセッサがいかにパワフルかお分かりかと思いますが、さらに自由度が必要なら、いつでも入力フィルタを書いてそれを INPUT_FILTER の後に指定できます。 前処理の効果に不安をお持ちなら、次のように実行してみてください。 doxygen -d Preprocessor これによってdoxygenは、前処理を実行した後の入力ソースを標準出力にダンプします。(ヒント:他の出力を無効にするには、設定ファイルで、 |
|
This page was last modified on Sun Aug 15 2021.
© 1997-2021 Dimitri van Heesch, first release 27 oct 1997.
© 2001 OKA Toshiyuki (Japanese translation). © 2006-2021 TSUJI Takahiro (Japanese translation). © 2006-2014 TAKAGI Nobuhisa (Japanese translation). |