< Previous PageNext Page >

Using the C Preprocessor

Beginning in HeaderDoc 8.5, HeaderDoc contains a basic C preprocessor implementation (enabled with the -p flag). Because HeaderDoc does not have access to the full compile-time environment of the headers, its behavior may differ from normal C preprocessors in certain cases. This section describes some of those differences.

In this section:

Parsing Rules
Multiply-Defined Macros
Embedded HeaderDoc Comments in a Macro
Handling of #include
Other Issues
What if I Don’t Want to See the Macros in the Documentation?

Parsing Rules

Most #define macros are not parsed by default, even if the preprocessor is enabled. This permits you as the user to choose which macros to process.

Macros are processed if any of the following are true:

The reason for this second case is a side-effect of the way that HeaderDoc parses classes to ensure that lines are processed in the order in which they appear in the file (which is necessary for a preprocessor to even be possible). For maximum control, preprocessor directives should be at the start of the file, outside of class braces.

Multiply-Defined Macros

HeaderDoc does not attempt to handle #if, #ifdef, or #ifndef directives. This may, in certain circumstances, result in multiple definitions of a #define directive if the preprocessor is enabled. As with most preprocessors, all such definitions are ignored except for the one that appears first in the file.

This is made slightly more complicated by the parsing rules described in “Parsing Rules”.

Embedded HeaderDoc Comments in a Macro

With most data types, HeaderDoc comments appearing inside the data type are associated with the data type itself. This is normally true for #define macros as well. However, that behavior would create a problem when the C preprocessor is enabled, as it is reasonable to allow macros to define contents to be blown into a class, and those contents could potentially include HeaderDoc markup.

For this reason, when the C preprocessor is enabled, embedded headerdoc processing is disabled for #define macros marked with @parseonly. Any HeaderDoc markup within the body of such a macro will be blown in wherever the macro is used, and will only be processed in the resulting context.

While HeaderDoc does allow a macro to insert multiple declarations and HeaderDoc comment blocks within a class, it does not allow this outside of a class. When a macro inserts HeaderDoc comments outside of a class scope, parsing will end at the end of the first declaration and any other contents inserted by the macro will be skipped.

Handling of #include

HeaderDoc’s implementation of #include behaves differently than you might expect. The differences include the following:

These differences generally do not affect headers written in a typical fashion, but may cause problems if you are using preprocessor directives in a nonstandard way.

Other Issues

A few common function-like preprocessor macros are predefined within HeaderDoc itself to avoid parse problems with I/O Kit headers. These will probably not affect you, but you should be aware of them.

Because HeaderDoc does not strip comments prior to processing macros (since doing so would remove HeaderDoc markup), the preprocessor may behave in subtly different ways. In particular, newlines are preserved, and any closing single-line (//) comments in macros will automatically be converted into a multi-line (/* */) comment to avoid causing the rest of the line to disappear when that macro actually gets used.

Finally, HeaderDoc does do basic string, character, and comment handling, even within macros. As a result, mismatched single or double quotes within a #define macro may cause serious problems.

What if I Don’t Want to See the Macros in the Documentation?

Most of the time, having #define macros defined in the documentation is helpful. In some cases, though, the macros get so big and ugly that you just want to get rid of them. For this reason, HeaderDoc has the @parseOnly tag.

For example:

/*! This is an ugly internal macro. @parseOnly */
#define CreateStructors \
    /*! Constructor */ \
    blah(); \
    /*! Destructor */ \
    ~blah();

By adding this tag at the end of the HeaderDoc comment block for the macro, the macro will be parsed and used by the preprocessor, but will not appear in the documentation.



< Previous PageNext Page >


© 1999, 2004 Apple Computer, Inc. All Rights Reserved. (Last updated: 2004-10-27)