< Previous PageNext Page > |
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.
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?
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:
They are preceded by a HeaderDoc comment block.
They appear between the beginning and end of a class that is preceded by a HeaderDoc comment block.
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.
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”.
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.
HeaderDoc’s implementation of #include behaves differently than you might expect. The differences include the following:
No notion of paths.
Because the include paths are not specified as they
are with a compiler, HeaderDoc cannot reasonably determine that <dir1/file.h>
and <dir2/file.h>
are
distinct. For this reason, processing files with the same name in
different directories is discouraged.
Mandatory recursion protection.
Because HeaderDoc does not process #if, #ifdef, and #ifndef conditionals, HeaderDoc enforces recursion protection by not allowing a file to get processed twice. Once a file is processed, a precompiled copy of its macros is stored for future use, and is automatically inserted whenever another #include requests it.
While most well-behaved headers will be handled correctly, this has two potential side-effects in a few cases. They are as follows:
A #include cannot be altered in a context-dependent way—that is, if a header incudes <a.h> and then <b.h>, the macros defined in <a.h> will not automatically affect the parse of <b.h>. In the rare cases where this matters, it can be fixed by making sure that <b.h> includes <a.h>.
The #include directive
behaves much like #import.
The result is that if <a.h>
includes <b.h>
which
includes <c.h>
which includes <a.h>
,
the definitions leading up to the reinclusion of <a.h> will
not affect the way <a.h> is
parsed. Granted, such use of macros borders on obfuscated C, but
in theory, it could cause unexpected behavior....
Macro contents will be shown in the documentation output.
Rather than try to carry around some notion of the original tokens read from the file, HeaderDoc inserts macros into the parse tree as if the modified version had been read from the file. This means that it is not possible, for example, for HeaderDoc to show you the unaltered definition of a macro that includes another macro. (The same applies for data types, functions, and so on if they are altered by a macro, though this is generally the expected behavior.)
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.
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.
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:
|
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)