summaryrefslogtreecommitdiff
path: root/share/doc/cppinternals/Guard-Macros.html
diff options
context:
space:
mode:
Diffstat (limited to 'share/doc/cppinternals/Guard-Macros.html')
-rw-r--r--share/doc/cppinternals/Guard-Macros.html188
1 files changed, 188 insertions, 0 deletions
diff --git a/share/doc/cppinternals/Guard-Macros.html b/share/doc/cppinternals/Guard-Macros.html
new file mode 100644
index 0000000..72bd485
--- /dev/null
+++ b/share/doc/cppinternals/Guard-Macros.html
@@ -0,0 +1,188 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<!-- Created by GNU Texinfo 5.1, http://www.gnu.org/software/texinfo/ -->
+<head>
+<title>The GNU C Preprocessor Internals: Guard Macros</title>
+
+<meta name="description" content="The GNU C Preprocessor Internals: Guard Macros">
+<meta name="keywords" content="The GNU C Preprocessor Internals: Guard Macros">
+<meta name="resource-type" content="document">
+<meta name="distribution" content="global">
+<meta name="Generator" content="makeinfo">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link href="index.html#Top" rel="start" title="Top">
+<link href="Concept-Index.html#Concept-Index" rel="index" title="Concept Index">
+<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
+<link href="index.html#Top" rel="up" title="Top">
+<link href="Files.html#Files" rel="next" title="Files">
+<link href="Line-Numbering.html#Line-Numbering" rel="previous" title="Line Numbering">
+<style type="text/css">
+<!--
+a.summary-letter {text-decoration: none}
+blockquote.smallquotation {font-size: smaller}
+div.display {margin-left: 3.2em}
+div.example {margin-left: 3.2em}
+div.indentedblock {margin-left: 3.2em}
+div.lisp {margin-left: 3.2em}
+div.smalldisplay {margin-left: 3.2em}
+div.smallexample {margin-left: 3.2em}
+div.smallindentedblock {margin-left: 3.2em; font-size: smaller}
+div.smalllisp {margin-left: 3.2em}
+kbd {font-style:oblique}
+pre.display {font-family: inherit}
+pre.format {font-family: inherit}
+pre.menu-comment {font-family: serif}
+pre.menu-preformatted {font-family: serif}
+pre.smalldisplay {font-family: inherit; font-size: smaller}
+pre.smallexample {font-size: smaller}
+pre.smallformat {font-family: inherit; font-size: smaller}
+pre.smalllisp {font-size: smaller}
+span.nocodebreak {white-space:nowrap}
+span.nolinebreak {white-space:nowrap}
+span.roman {font-family:serif; font-weight:normal}
+span.sansserif {font-family:sans-serif; font-weight:normal}
+ul.no-bullet {list-style: none}
+-->
+</style>
+
+
+</head>
+
+<body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000">
+<a name="Guard-Macros"></a>
+<div class="header">
+<p>
+Next: <a href="Files.html#Files" accesskey="n" rel="next">Files</a>, Previous: <a href="Line-Numbering.html#Line-Numbering" accesskey="p" rel="previous">Line Numbering</a>, Up: <a href="index.html#Top" accesskey="u" rel="up">Top</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p>
+</div>
+<hr>
+<a name="The-Multiple_002dInclude-Optimization"></a>
+<h2 class="unnumbered">The Multiple-Include Optimization</h2>
+<a name="index-guard-macros"></a>
+<a name="index-controlling-macros"></a>
+<a name="index-multiple_002dinclude-optimization"></a>
+
+<p>Header files are often of the form
+</p>
+<div class="smallexample">
+<pre class="smallexample">#ifndef FOO
+#define FOO
+&hellip;
+#endif
+</pre></div>
+
+<p>to prevent the compiler from processing them more than once. The
+preprocessor notices such header files, so that if the header file
+appears in a subsequent <code>#include</code> directive and <code>FOO</code> is
+defined, then it is ignored and it doesn&rsquo;t preprocess or even re-open
+the file a second time. This is referred to as the <em>multiple
+include optimization</em>.
+</p>
+<p>Under what circumstances is such an optimization valid? If the file
+were included a second time, it can only be optimized away if that
+inclusion would result in no tokens to return, and no relevant
+directives to process. Therefore the current implementation imposes
+requirements and makes some allowances as follows:
+</p>
+<ol>
+<li> There must be no tokens outside the controlling <code>#if</code>-<code>#endif</code>
+pair, but whitespace and comments are permitted.
+
+</li><li> There must be no directives outside the controlling directive pair, but
+the <em>null directive</em> (a line containing nothing other than a single
+&lsquo;<samp>#</samp>&rsquo; and possibly whitespace) is permitted.
+
+</li><li> The opening directive must be of the form
+
+<div class="smallexample">
+<pre class="smallexample">#ifndef FOO
+</pre></div>
+
+<p>or
+</p>
+<div class="smallexample">
+<pre class="smallexample">#if !defined FOO [equivalently, #if !defined(FOO)]
+</pre></div>
+
+</li><li> In the second form above, the tokens forming the <code>#if</code> expression
+must have come directly from the source file&mdash;no macro expansion must
+have been involved. This is because macro definitions can change, and
+tracking whether or not a relevant change has been made is not worth the
+implementation cost.
+
+</li><li> There can be no <code>#else</code> or <code>#elif</code> directives at the outer
+conditional block level, because they would probably contain something
+of interest to a subsequent pass.
+</li></ol>
+
+<p>First, when pushing a new file on the buffer stack,
+<code>_stack_include_file</code> sets the controlling macro <code>mi_cmacro</code> to
+<code>NULL</code>, and sets <code>mi_valid</code> to <code>true</code>. This indicates
+that the preprocessor has not yet encountered anything that would
+invalidate the multiple-include optimization. As described in the next
+few paragraphs, these two variables having these values effectively
+indicates top-of-file.
+</p>
+<p>When about to return a token that is not part of a directive,
+<code>_cpp_lex_token</code> sets <code>mi_valid</code> to <code>false</code>. This
+enforces the constraint that tokens outside the controlling conditional
+block invalidate the optimization.
+</p>
+<p>The <code>do_if</code>, when appropriate, and <code>do_ifndef</code> directive
+handlers pass the controlling macro to the function
+<code>push_conditional</code>. cpplib maintains a stack of nested conditional
+blocks, and after processing every opening conditional this function
+pushes an <code>if_stack</code> structure onto the stack. In this structure
+it records the controlling macro for the block, provided there is one
+and we&rsquo;re at top-of-file (as described above). If an <code>#elif</code> or
+<code>#else</code> directive is encountered, the controlling macro for that
+block is cleared to <code>NULL</code>. Otherwise, it survives until the
+<code>#endif</code> closing the block, upon which <code>do_endif</code> sets
+<code>mi_valid</code> to true and stores the controlling macro in
+<code>mi_cmacro</code>.
+</p>
+<p><code>_cpp_handle_directive</code> clears <code>mi_valid</code> when processing any
+directive other than an opening conditional and the null directive.
+With this, and requiring top-of-file to record a controlling macro, and
+no <code>#else</code> or <code>#elif</code> for it to survive and be copied to
+<code>mi_cmacro</code> by <code>do_endif</code>, we have enforced the absence of
+directives outside the main conditional block for the optimization to be
+on.
+</p>
+<p>Note that whilst we are inside the conditional block, <code>mi_valid</code> is
+likely to be reset to <code>false</code>, but this does not matter since
+the closing <code>#endif</code> restores it to <code>true</code> if appropriate.
+</p>
+<p>Finally, since <code>_cpp_lex_direct</code> pops the file off the buffer stack
+at <code>EOF</code> without returning a token, if the <code>#endif</code> directive
+was not followed by any tokens, <code>mi_valid</code> is <code>true</code> and
+<code>_cpp_pop_file_buffer</code> remembers the controlling macro associated
+with the file. Subsequent calls to <code>stack_include_file</code> result in
+no buffer being pushed if the controlling macro is defined, effecting
+the optimization.
+</p>
+<p>A quick word on how we handle the
+</p>
+<div class="smallexample">
+<pre class="smallexample">#if !defined FOO
+</pre></div>
+
+<p>case. <code>_cpp_parse_expr</code> and <code>parse_defined</code> take steps to see
+whether the three stages &lsquo;<samp>!</samp>&rsquo;, &lsquo;<samp>defined-expression</samp>&rsquo; and
+&lsquo;<samp>end-of-directive</samp>&rsquo; occur in order in a <code>#if</code> expression. If
+so, they return the guard macro to <code>do_if</code> in the variable
+<code>mi_ind_cmacro</code>, and otherwise set it to <code>NULL</code>.
+<code>enter_macro_context</code> sets <code>mi_valid</code> to false, so if a macro
+was expanded whilst parsing any part of the expression, then the
+top-of-file test in <code>push_conditional</code> fails and the optimization
+is turned off.
+</p>
+<hr>
+<div class="header">
+<p>
+Next: <a href="Files.html#Files" accesskey="n" rel="next">Files</a>, Previous: <a href="Line-Numbering.html#Line-Numbering" accesskey="p" rel="previous">Line Numbering</a>, Up: <a href="index.html#Top" accesskey="u" rel="up">Top</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p>
+</div>
+
+
+
+</body>
+</html>