Orb/Doxygen/doc/preprocessing.doc
changeset 3 d8fccb2cd802
parent 0 42188c7ea2d9
equal deleted inserted replaced
2:932c358ece3e 3:d8fccb2cd802
       
     1 /******************************************************************************
       
     2  *
       
     3  * 
       
     4  *
       
     5  * Copyright (C) 1997-2008 by Dimitri van Heesch.
       
     6  *
       
     7  * Permission to use, copy, modify, and distribute this software and its
       
     8  * documentation under the terms of the GNU General Public License is hereby 
       
     9  * granted. No representations are made about the suitability of this software 
       
    10  * for any purpose. It is provided "as is" without express or implied warranty.
       
    11  * See the GNU General Public License for more details.
       
    12  *
       
    13  * Documents produced by Doxygen are derivative works derived from the
       
    14  * input used in their production; they are not affected by this license.
       
    15  *
       
    16  */
       
    17 /*! \page preprocessing Preprocessing
       
    18 
       
    19 Source files that are used as input to doxygen can be parsed by doxygen's
       
    20 built-in C-preprocessor.
       
    21 
       
    22 By default doxygen does only partial preprocessing. That is, it 
       
    23 evaluates conditional compilation statements (like \#if) and 
       
    24 evaluates macro definitions, but it does not perform macro expansion.
       
    25 
       
    26 So if you have the following code fragment
       
    27 \verbatim
       
    28 #define VERSION 200
       
    29 #define CONST_STRING const char *
       
    30 
       
    31 #if VERSION >= 200
       
    32   static CONST_STRING version = "2.xx";
       
    33 #else
       
    34   static CONST_STRING version = "1.xx";
       
    35 #endif
       
    36 \endverbatim
       
    37 
       
    38 Then by default doxygen will feed the following to its parser:
       
    39 
       
    40 \verbatim
       
    41 #define VERSION
       
    42 #define CONST_STRING
       
    43 
       
    44   static CONST_STRING version = "2.xx";
       
    45 \endverbatim
       
    46 
       
    47 You can disable all preprocessing by setting 
       
    48 \ref cfg_enable_preprocessing "ENABLE_PREPROCESSING" to \c 
       
    49 NO in the configuation file. In the case above doxygen will then read
       
    50 both statements, i.e:
       
    51 
       
    52 \verbatim
       
    53   static CONST_STRING version = "2.xx";
       
    54   static CONST_STRING version = "1.xx";
       
    55 \endverbatim
       
    56 
       
    57 In case you want to expand the \c CONST_STRING macro, you should set the
       
    58 \ref cfg_macro_expansion "MACRO_EXPANSION" tag in the config file 
       
    59 to \c YES. Then the result after preprocessing becomes:
       
    60 
       
    61 \verbatim
       
    62 #define VERSION
       
    63 #define CONST_STRING
       
    64 
       
    65   static const char * version = "1.xx";
       
    66 \endverbatim
       
    67 
       
    68 Note that doxygen will now expand \e all macro definitions 
       
    69 (recursively if needed). This is often too much. Therefore, doxygen also 
       
    70 allows you to expand only those defines that you explicitly 
       
    71 specify. For this you have to set the 
       
    72 \ref cfg_expand_only_predef "EXPAND_ONLY_PREDEF" tag to \c YES
       
    73 and specify the macro definitions after 
       
    74 the \ref cfg_predefined "PREDEFINED" or 
       
    75 \ref cfg_expand_as_defined "EXPAND_AS_DEFINED" tag.  
       
    76 
       
    77 A typically example where some help from the preprocessor is needed is
       
    78 when dealing with Microsoft's __declspec language extension. Here is an
       
    79 example function.
       
    80 
       
    81 \verbatim
       
    82 extern "C" void __declspec(dllexport) ErrorMsg( String aMessage,...);
       
    83 \endverbatim
       
    84 
       
    85 When nothing is done, doxygen will be confused and see __declspec as
       
    86 some sort of function. To help doxygen one typically uses the following
       
    87 preprocessor settings:
       
    88 
       
    89 \verbatim  
       
    90 ENABLE_PREPROCESSING   = YES
       
    91 MACRO_EXPANSION        = YES
       
    92 EXPAND_ONLY_PREDEF     = YES
       
    93 PREDEFINED             = __declspec(x)=
       
    94 \endverbatim
       
    95 
       
    96 This will make sure the __declspec(dllexport) is removed before doxygen
       
    97 parses the source code.
       
    98 
       
    99 For a more complex example, suppose you have the following obfuscated 
       
   100 code fragment of an abstract base class called \c IUnknown:
       
   101 
       
   102 \verbatim
       
   103 /*! A reference to an IID */
       
   104 #ifdef __cplusplus
       
   105 #define REFIID const IID &
       
   106 #else
       
   107 #define REFIID const IID *
       
   108 #endif
       
   109 
       
   110 
       
   111 /*! The IUnknown interface */
       
   112 DECLARE_INTERFACE(IUnknown)
       
   113 {
       
   114   STDMETHOD(HRESULT,QueryInterface) (THIS_ REFIID iid, void **ppv) PURE;
       
   115   STDMETHOD(ULONG,AddRef) (THIS) PURE;
       
   116   STDMETHOD(ULONG,Release) (THIS) PURE;
       
   117 };
       
   118 \endverbatim
       
   119 
       
   120 without macro expansion doxygen will get confused, but we may not want to 
       
   121 expand the REFIID macro, because it is documented and the user that reads 
       
   122 the documentation should use it when implementing the interface.
       
   123 
       
   124 By setting the following in the config file:
       
   125 
       
   126 \verbatim
       
   127 ENABLE_PREPROCESSING = YES
       
   128 MACRO_EXPANSION      = YES
       
   129 EXPAND_ONLY_PREDEF   = YES
       
   130 PREDEFINED           = "DECLARE_INTERFACE(name)=class name" \
       
   131                        "STDMETHOD(result,name)=virtual result name" \
       
   132                        "PURE= = 0" \
       
   133                        THIS_= \
       
   134                        THIS= \
       
   135 		       __cplusplus
       
   136 \endverbatim
       
   137 
       
   138 we can make sure that the proper result is fed to doxygen's parser:
       
   139 \verbatim
       
   140 /*! A reference to an IID */
       
   141 #define REFIID
       
   142 
       
   143 /*! The IUnknown interface */
       
   144 class  IUnknown
       
   145 {
       
   146   virtual  HRESULT   QueryInterface ( REFIID iid, void **ppv) = 0;
       
   147   virtual  ULONG   AddRef () = 0;
       
   148   virtual  ULONG   Release () = 0;
       
   149 };
       
   150 \endverbatim
       
   151 
       
   152 Note that the \ref cfg_predefined "PREDEFINED" tag accepts function 
       
   153 like macro definitions
       
   154 (like \c DECLARE_INTERFACE ), normal macro 
       
   155 substitutions (like \c PURE and \c THIS) and plain 
       
   156 defines (like \c __cplusplus).
       
   157 
       
   158 Note also that preprocessor definitions that are normally defined 
       
   159 automatically by the preprocessor (like \c __cplusplus), have to be defined 
       
   160 by hand with doxygen's parser (this is done because these defines
       
   161 are often platform/compiler specific).
       
   162 
       
   163 In some cases you may want to substitute a macro name or function by 
       
   164 something else without exposing the result to further macro substitution.
       
   165 You can do this but using the <code>:=</code> operator instead of 
       
   166 <code>=</code>
       
   167 
       
   168 As an example suppose we have the following piece of code:
       
   169 \verbatim
       
   170 #define QList QListT
       
   171 class QListT
       
   172 {
       
   173 };
       
   174 \endverbatim
       
   175 
       
   176 Then the only way to get doxygen interpret this as a class definition
       
   177 for class QList is to define:
       
   178 \verbatim
       
   179 PREDEFINED = QListT:=QList
       
   180 \endverbatim
       
   181 
       
   182 Here is an example provided by Valter Minute and Reyes Ponce that helps 
       
   183 doxygen to wade through the boilerplate code in Microsoft's ATL \& MFC 
       
   184 libraries:
       
   185 
       
   186 \verbatim
       
   187 PREDEFINED           = "DECLARE_INTERFACE(name)=class name" \
       
   188                        "STDMETHOD(result,name)=virtual result name" \
       
   189                        "PURE= = 0" \
       
   190                        THIS_= \
       
   191                        THIS= \
       
   192                        DECLARE_REGISTRY_RESOURCEID=// \
       
   193                        DECLARE_PROTECT_FINAL_CONSTRUCT=// \
       
   194                        "DECLARE_AGGREGATABLE(Class)= " \
       
   195                        "DECLARE_REGISTRY_RESOURCEID(Id)= " \
       
   196                        DECLARE_MESSAGE_MAP= \
       
   197                        BEGIN_MESSAGE_MAP=/* \
       
   198                        END_MESSAGE_MAP=*/// \
       
   199                        BEGIN_COM_MAP=/* \
       
   200                        END_COM_MAP=*/// \
       
   201                        BEGIN_PROP_MAP=/* \
       
   202                        END_PROP_MAP=*/// \
       
   203                        BEGIN_MSG_MAP=/* \
       
   204                        END_MSG_MAP=*/// \
       
   205                        BEGIN_PROPERTY_MAP=/* \
       
   206                        END_PROPERTY_MAP=*/// \
       
   207                        BEGIN_OBJECT_MAP=/* \
       
   208                        END_OBJECT_MAP()=*/// \
       
   209                        DECLARE_VIEW_STATUS=// \
       
   210                        "STDMETHOD(a)=HRESULT a" \
       
   211                        "ATL_NO_VTABLE= " \
       
   212                        "__declspec(a)= " \
       
   213                        BEGIN_CONNECTION_POINT_MAP=/* \
       
   214                        END_CONNECTION_POINT_MAP=*/// \
       
   215                        "DECLARE_DYNAMIC(class)= " \
       
   216                        "IMPLEMENT_DYNAMIC(class1, class2)= " \
       
   217                        "DECLARE_DYNCREATE(class)= " \
       
   218                        "IMPLEMENT_DYNCREATE(class1, class2)= " \
       
   219                        "IMPLEMENT_SERIAL(class1, class2, class3)= " \
       
   220                        "DECLARE_MESSAGE_MAP()= " \
       
   221                        TRY=try \
       
   222                        "CATCH_ALL(e)= catch(...)" \
       
   223                        END_CATCH_ALL= \
       
   224                        "THROW_LAST()= throw"\
       
   225                        "RUNTIME_CLASS(class)=class" \
       
   226                        "MAKEINTRESOURCE(nId)=nId" \
       
   227                        "IMPLEMENT_REGISTER(v, w, x, y, z)= " \
       
   228                        "ASSERT(x)=assert(x)" \
       
   229                        "ASSERT_VALID(x)=assert(x)" \
       
   230                        "TRACE0(x)=printf(x)" \
       
   231                        "OS_ERR(A,B)={ #A, B }" \
       
   232                        __cplusplus \
       
   233                        "DECLARE_OLECREATE(class)= " \
       
   234                        "BEGIN_DISPATCH_MAP(class1, class2)= " \
       
   235                        "BEGIN_INTERFACE_MAP(class1, class2)= " \
       
   236                        "INTERFACE_PART(class, id, name)= " \
       
   237                        "END_INTERFACE_MAP()=" \
       
   238                        "DISP_FUNCTION(class, name, function, result, id)=" \
       
   239                        "END_DISPATCH_MAP()=" \
       
   240                        "IMPLEMENT_OLECREATE2(class, name, id1, id2, id3, id4,\
       
   241                         id5, id6, id7, id8, id9, id10, id11)="
       
   242 \endverbatim
       
   243 
       
   244 As you can see doxygen's preprocessor is quite powerful, but if you want
       
   245 even more flexibility you can always write an input filter and specify it 
       
   246 after the \ref cfg_input_filter "INPUT_FILTER" tag.
       
   247 
       
   248 If you are unsure what the effect of doxygen's preprocessing will be
       
   249 you can run doxygen as follows:
       
   250 \verbatim
       
   251   doxygen -d Preprocessor
       
   252 \endverbatim
       
   253 This will instruct doxygen to dump the input sources to standard output after
       
   254 preprocessing has been done (Hint: set <code>QUIET = YES</code> and 
       
   255 <code>WARNINGS = NO</code> in the configuration file to disable any other 
       
   256 output).
       
   257 
       
   258 \htmlonly
       
   259 Go to the <a href="external.html">next</a> section or return to the
       
   260  <a href="index.html">index</a>.
       
   261 \endhtmlonly
       
   262 
       
   263 */