Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r56276 - in trunk: boost/wave libs/wave libs/wave/doc tools/wave
From: hartmut.kaiser_at_[hidden]
Date: 2009-09-17 13:54:08


Author: hkaiser
Date: 2009-09-17 13:54:07 EDT (Thu, 17 Sep 2009)
New Revision: 56276
URL: http://svn.boost.org/trac/boost/changeset/56276

Log:
Wave: added preprocessing hook to detect #pragma once directives or include guards
Text files modified:
   trunk/boost/wave/cpp_context.hpp | 5 ++
   trunk/boost/wave/preprocessing_hooks.hpp | 57 ++++++++++++++++++++++++++++--
   trunk/libs/wave/ChangeLog | 8 +++-
   trunk/libs/wave/doc/class_reference_ctxpolicy.html | 52 ++++++++++++++++++++-------
   trunk/libs/wave/doc/wave_driver.html | 17 ++++++++
   trunk/tools/wave/cpp.cpp | 33 ++++++++++++++++-
   trunk/tools/wave/trace_macro_expansion.hpp | 74 +++++++++++++++++++++++++++++++++++++--
   7 files changed, 217 insertions(+), 29 deletions(-)

Modified: trunk/boost/wave/cpp_context.hpp
==============================================================================
--- trunk/boost/wave/cpp_context.hpp (original)
+++ trunk/boost/wave/cpp_context.hpp 2009-09-17 13:54:07 EDT (Thu, 17 Sep 2009)
@@ -404,7 +404,10 @@
         { return includes.has_pragma_once(filename_); }
     bool add_pragma_once_header(std::string const &filename_,
             std::string const& guard_name = "__BOOST_WAVE_PRAGMA_ONCE__")
- { return includes.add_pragma_once_header(filename_, guard_name); }
+ {
+ get_hooks().detected_pragma_once(derived(), filename_, guard_name);
+ return includes.add_pragma_once_header(filename_, guard_name);
+ }
 #endif
 
 #if BOOST_WAVE_SERIALIZATION != 0

Modified: trunk/boost/wave/preprocessing_hooks.hpp
==============================================================================
--- trunk/boost/wave/preprocessing_hooks.hpp (original)
+++ trunk/boost/wave/preprocessing_hooks.hpp 2009-09-17 13:54:07 EDT (Thu, 17 Sep 2009)
@@ -238,7 +238,7 @@
         std::string const& absname, bool is_system_include)
     {}
 #endif
-
+
     ///////////////////////////////////////////////////////////////////////////
     //
     // The function 'returning_from_include_file' is called, whenever an
@@ -261,6 +261,55 @@
     {}
 #endif
 
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'detected_pragma_once' is called whenever either a
+ // include file is about to be added to the list of #pragma once headers.
+ // That means this header file will not be opened and parsed again even
+ // if it is specified in a later #include directive.
+ // This function is called either as the result of a detected directive
+ // #pragma once, or as the result of a detected include guard scheme.
+ //
+ // The implemented heuristics for include guards detects two forms of
+ // include guards:
+ //
+ // #ifndef INCLUDE_GUARD_MACRO
+ // #define INCLUDE_GUARD_MACRO
+ // ...
+ // #endif
+ //
+ // or
+ //
+ // if !defined(INCLUDE_GUARD_MACRO)
+ // #define INCLUDE_GUARD_MACRO
+ // ...
+ // #endif
+ //
+ // note, that the parenthesis are optional (i.e. !defined INCLUDE_GUARD_MACRO
+ // will work as well). The code allows for any whitespace, newline and single
+ // '#' tokens before the #if/#ifndef and after the final #endif.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'filename' contains the file system path of the
+ // opened file (this is relative to the directory of the currently
+ // processed file or a absolute path depending on the paths given as the
+ // include search paths).
+ //
+ // The parameter include_guard is either "__BOOST_WAVE_PRAGMA_ONCE__" (if
+ // a #pragma once has been detected) or contains the name of the detected
+ // include guard.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT>
+ void
+ detected_pragma_once(ContextT const& ctx, std::string const& filename,
+ std::string const& include_guard)
+ {}
+#endif
+
     ///////////////////////////////////////////////////////////////////////////
     //
     // The function 'interpret_pragma' is called, whenever a '#pragma command'
@@ -368,7 +417,7 @@
     undefined_macro(ContextT const& ctx, TokenT const& macro_name)
     {}
 #endif
-
+
     ///////////////////////////////////////////////////////////////////////////
     //
     // The function 'found_directive' is called, whenever a preprocessor
@@ -441,7 +490,7 @@
         bool expression_value)
     { return false; } // ok to continue, do not re-evaluate expression
 #endif
-
+
     ///////////////////////////////////////////////////////////////////////////
     //
     // The function 'skipped_token' is called, whenever a token is about to be
@@ -591,7 +640,7 @@
     found_line_directive(ContextT const& ctx, ContainerT const& arguments,
         unsigned int line, std::string const& filename)
     {}
-
+
     ///////////////////////////////////////////////////////////////////////////
     //
     // The function 'throw_exception' will be called by the library whenever a

Modified: trunk/libs/wave/ChangeLog
==============================================================================
--- trunk/libs/wave/ChangeLog (original)
+++ trunk/libs/wave/ChangeLog 2009-09-17 13:54:07 EDT (Thu, 17 Sep 2009)
@@ -16,8 +16,6 @@
 - Fix the trigraph backslash problem in the re2c (C/C++ and IDL) scanners, if
   there is the end of the (internal) buffer just in between a '??/' and a '\n'.
 
-- Do a sourceforge release.
-
 -------------------------------------------------------------------------------
 
 CHANGELOG
@@ -37,6 +35,12 @@
   (default is cout).
 - Fixed compilation problems caused by recent changes to the multi_pass iterator
   from Spirit V2.1.
+- Added a new preprocessing hook detected_pragma_once() which is getting called
+ whenever either a #pragma once has been detected or if the include guard
+ heuristics detected an include guard for a particular include file.
+- Added a new command line option to the wave driver tool: --listguards/-g
+ allowing to trace all include files which are either contain a #pragma once
+ or contain include guards.
 
 Boost V1.40.0
 - V2.0.2

Modified: trunk/libs/wave/doc/class_reference_ctxpolicy.html
==============================================================================
--- trunk/libs/wave/doc/class_reference_ctxpolicy.html (original)
+++ trunk/libs/wave/doc/class_reference_ctxpolicy.html 2009-09-17 13:54:07 EDT (Thu, 17 Sep 2009)
@@ -59,7 +59,9 @@
         <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> <span class="keyword">void</span> skipped_token(ContextT <span class="keyword">const</span> &amp;ctx, <br> TokenT <span class="keyword">const</span>&amp; token);<br><br> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> TokenT <span class="keyword">const</span>&amp; generated_token(ContextT <span class="keyword">const</span> &amp;ctx, <br> TokenT <span class="keyword">const</span>&amp; token);<br><br> <span class="comment">// macro expansion tracing</span><span class="keyword">
         template</span> &lt;<span class="keyword">
             typename</span> ContextT, <span class="keyword">typename</span> TokenT, <span class="keyword">typename</span> ContainerT,<br> <span class="keyword">typename</span> IteratorT<br> &gt;<br> <span class="keyword">bool</span> expanding_function_like_macro(<br> ContextT <span class="keyword">const</span> &amp;ctx, TokenT <span class="keyword">const</span> &amp;macrodef, <br> <span class="keyword">std::vector</span>&lt;TokenT&gt; <span class="keyword">const</span> &amp;formal_args, <br> ContainerT <span class="keyword">const</span> &amp;definition, TokenT <span class="keyword">const</span> &amp;macrocall, <br> <span class="keyword">std::vector</span>&lt;ContainerT&gt; <span class="keyword">const</span> &amp;arguments,<br> IteratorT <span class="keyword">const</span> &amp;seqstart, Iterator <span class="keyword">const</span> &amp;seqend);<br> <br>
    <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">bool</span> expanding_object_like_macro(<br> ContextT <span class="keyword">const</span> &amp;ctx, TokenT <span class="keyword">const</span> &amp;macro, <br> ContainerT <span class="keyword">const</span> &amp;definition, TokenT <span class="keyword">const</span> &amp;macrocall);<br> <br> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">void</span> expanded_macro(ContextT <span class="keyword">const</span> &amp;ctx, <br> ContainerT <span class="keyword">const</span> &amp;result);<br> <br>
   <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">void</span> rescanned_macro(ContextT <span class="keyword">const</span> &amp;ctx, <br> ContainerT <span class="keyword">const</span> &amp;result);<br><br> <span class="comment">// include file tracing functions</span>
- <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">bool</span> found_include_directive(ContextT <span class="keyword">const</span> &amp;ctx, <br> std::string <span class="keyword">const</span> &amp;filename, <span class="keyword">bool</span> include_next);<br><br> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">void </span>opened_include_file(ContextT <span class="keyword">const</span> &amp;ctx, <br> std::string <span class="keyword">const</span> &amp;relname, std::string const&amp; absname,<br> <span class="keyword">bool</span> is_system_include); <br><br> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="key
word">void</span> returning_from_include_file(ContextT <span class="keyword">const</span> &amp;ctx);<br><br> <span class="comment">// interpretation of #pragma's of the form </span>
+ <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">bool</span> found_include_directive(ContextT <span class="keyword">const</span> &amp;ctx, <br> std::string <span class="keyword">const</span> &amp;filename, <span class="keyword">bool</span> include_next);<br><br> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">void </span>opened_include_file(ContextT <span class="keyword">const</span> &amp;ctx, <br> std::string <span class="keyword">const</span> &amp;relname, std::string <span class="keyword">const</span>&amp; absname,<br> <span class="keyword">bool</span> is_system_include); <br><br> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt
;<br> <span class="keyword">void</span> returning_from_include_file(ContextT <span class="keyword">const</span> &amp;ctx);<br><br> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">void</span> detected_pragma_once(ContextT <span class="keyword">const</span> &amp;ctx,
+ std::string <span class="keyword">const</span>&amp; filename,
+ std::string <span class="keyword">const</span>&amp; include_guard);<br><br> <span class="comment">// interpretation of #pragma's of the form </span>
         <span class="comment">// 'wave option[(value)]'</span>
         <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">bool</span> interpret_pragma(ContextT <span class="keyword">const</span> &amp;ctx, ContainerT &amp;pending, <br> <span class="keyword">typename</span> ContextT::token_type <span class="keyword">const</span> &amp;option, <br> ContainerT <span class="keyword">const</span> &amp;values, <br> <span class="keyword">typename</span> ContextT::token_type <span class="keyword">const</span> &amp;pragma_token);<br><br> <span class="comment">// macro definition hooks</span>
         <span class="keyword">template</span> &lt;<br> <span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT, <span class="keyword">
@@ -70,7 +72,7 @@
 <h2><a name="member_functions"></a>Member functions</h2>
 <h3>General hook functions </h3>
 <p><a name="found_directive"></a><strong>found_directive</strong></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> <span class="keyword">bool</span> found_directive(ContextT <span class="keyword">const</span>&amp; ctx, TokenT <span class="keyword">const </span>&amp;directive);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> <span class="keyword">bool</span> found_directive(ContextT <span class="keyword">const</span>&amp; ctx, TokenT <span class="keyword">const </span>&amp;directive);<br>
 </pre>
 <blockquote>
   <p>The function <tt>found_directive</tt> is called, whenever the preprocessor has detected one of the preprocessing directives (<span class="preprocessor">#define</span>, <span class="preprocessor">#undef</span>, <span class="preprocessor">#if</span>, <span class="preprocessor">#idef</span>, <span class="preprocessor">#ifndef</span>, <span class="preprocessor">#elif</span>, <span class="preprocessor">#endif</span>, <span class="preprocessor">#error</span>, <span class="preprocessor">#include</span>, <span class="preprocessor">#pragma</span> or <span class="preprocessor">#warning</span>) .</p>
@@ -83,14 +85,14 @@
     value is <tt>false</tt>, the directive is processed in the normal manner. </p>
 </blockquote>
 <p><a name="throw_exception"></a><strong>throw_exception</strong></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ExceptionT&gt;<br> void throw_exception(ContextT <span class="keyword">const</span> &amp;ctx, <br> ExceptionT <span class="keyword">const</span>&amp; e);</pre>
+<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ExceptionT&gt;<br> void throw_exception(ContextT <span class="keyword">const</span> &amp;ctx, <br> ExceptionT <span class="keyword">const</span>&amp; e);</pre>
 <blockquote>
   <p>he function&nbsp;<tt>throw_exception</tt> is called, whenever a preprocessing exception occurs .</p>
   <p>The <tt>ctx</tt> parameter provides a reference to the <tt>context_type</tt> used during instantiation of the preprocessing iterators by the user.&nbsp; </p>
   <p>The parameter&nbsp;<tt>e</tt> is the exception object containing detailed error information. </p>
 </blockquote>
 <p><a name="may_skip_whitespace" id="may_skip"></a><strong>may_skipwhitespace</strong></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> <span class="keyword">bool</span> may_skip_whitespace(ContextT <span class="keyword">const</span>&amp; ctx, TokenT &amp;token, <br> <span class="keyword">bool</span>&amp; skipped_newline);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> <span class="keyword">bool</span> may_skip_whitespace(ContextT <span class="keyword">const</span>&amp; ctx, TokenT &amp;token, <br> <span class="keyword">bool</span>&amp; skipped_newline);<br>
 </pre>
 <blockquote>
   <p>The function <tt>may_skipwhitespace</tt> will be called by the library, whenever a token is about to be returned to the calling application. </p>
@@ -104,7 +106,7 @@
 </blockquote>
 <h3>Conditional compilation hook functions </h3>
 <p><a name="evaluated_conditional_expression"></a><strong>evaluated_conditional_expression</strong></p>
-<pre><span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT, <span class="keyword">typename</span> ContainerT&gt;<br><span class="keyword"> bool</span> evaluated_conditional_expression(ContextT <span class="keyword">const</span>&amp; ctx, <br> TokenT <span class="keyword">const</span>&amp; directive, ContainerT <span class="keyword">const</span>&amp; expression, <span class="keyword"><br> bool</span> expression_value);<br>
+<pre><span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT, <span class="keyword">typename</span> ContainerT&gt;<br><span class="keyword"> bool</span> evaluated_conditional_expression(ContextT <span class="keyword">const</span>&amp; ctx, <br> TokenT <span class="keyword">const</span>&amp; directive, ContainerT <span class="keyword">const</span>&amp; expression, <span class="keyword"><br> bool</span> expression_value);<br>
 </pre>
 <blockquote>
   <p>The function <tt>evaluated_conditional_expression</tt> is called, whenever the preprocessor has encountered a <span class="preprocessor">#if</span>, <span class="preprocessor">#elif</span>, <span class="preprocessor">#ifdef</span> or <span class="preprocessor">#ifndef</span> directive. This hook gets passed the non-expanded conditional
@@ -124,7 +126,7 @@
   </p>
 </blockquote>
 <p><a name="skipped_token"></a><strong>skipped_token</strong></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> <span class="keyword">void</span> skipped_token(ContextT <span class="keyword">const</span>&amp; ctx, TokenT <span class="keyword">const</span>&amp; token);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> <span class="keyword">void</span> skipped_token(ContextT <span class="keyword">const</span>&amp; ctx, TokenT <span class="keyword">const</span>&amp; token);<br>
 </pre>
 <blockquote>
   <p>The function <tt>skipped_token</tt> is called, whenever a token is about to be skipped due to a false preprocessor condition (code fragments to be
@@ -134,7 +136,7 @@
   <p>The parameter <tt>token</tt> refers to the token to be skipped.</p>
 </blockquote>
 <p><a name="generated_token"></a><strong>generated_token</strong></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> TokenT <span class="keyword">const</span>&amp; generated_token(ContextT <span class="keyword">const</span>&amp; ctx, TokenT <span class="keyword">const</span>&amp; token);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT&gt;<br> TokenT <span class="keyword">const</span>&amp; generated_token(ContextT <span class="keyword">const</span>&amp; ctx, TokenT <span class="keyword">const</span>&amp; token);<br>
 </pre>
 <blockquote>
   <p>The function <tt>generated_token</tt> is called, whenever a token is about to be returned from the library.</p>
@@ -181,7 +183,7 @@
   </p>
 </blockquote>
 <p><a name="expanding_object_like_macro"></a><b>expanding_object_like_macro</b></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">bool</span> expanding_object_like_macro(<br> ContextT <span class="keyword">const</span>&amp; ctx, TokenT <span class="keyword">const</span> &amp;macro, <br> ContainerT <span class="keyword">const</span> &amp;definition, TokenT <span class="keyword">const</span> &amp;macrocall);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> TokenT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">bool</span> expanding_object_like_macro(<br> ContextT <span class="keyword">const</span>&amp; ctx, TokenT <span class="keyword">const</span> &amp;macro, <br> ContainerT <span class="keyword">const</span> &amp;definition, TokenT <span class="keyword">const</span> &amp;macrocall);<br>
 </pre>
 <blockquote>
   <p>The function <tt>expanding_object_like_macro</tt> is called, whenever a object-like
@@ -201,7 +203,7 @@
   </p>
 </blockquote>
 <p><a name="expanded_macro"></a><b>expanded_macro</b></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">void</span> expanded_macro(ContextT <span class="keyword">const</span>&amp; ctx, ContainerT <span class="keyword">const</span> &amp;result);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">void</span> expanded_macro(ContextT <span class="keyword">const</span>&amp; ctx, ContainerT <span class="keyword">const</span> &amp;result);<br>
 </pre>
 <blockquote>
   <p>The function <tt>expanded_macro</tt> is called whenever the expansion of
@@ -213,7 +215,7 @@
     so far. This is a standard STL container containing the generated token sequence.</p>
 </blockquote>
 <p><a name="rescanned_macro"></a><b>rescanned_macro</b></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">void</span> rescanned_macro(ContextT <span class="keyword">const</span>&amp; ctx, ContainerT <span class="keyword">const</span> &amp;result);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ContainerT&gt;<br> <span class="keyword">void</span> rescanned_macro(ContextT <span class="keyword">const</span>&amp; ctx, ContainerT <span class="keyword">const</span> &amp;result);<br>
 </pre>
 <blockquote>
   <p>The function <tt>rescanned_macro</tt> is called whenever the rescanning
@@ -226,7 +228,7 @@
 </blockquote>
 <h3>Include file tracing functions</h3>
 <p><a name="opened_include_file" id="found_include_directive"></a><strong>found_include_directive</strong></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">bool</span> found_include_directive(ContextT <span class="keyword">const</span>&amp; ctx, <br> std::string <span class="keyword">const</span> &amp;filename, <span class="keyword">bool</span> include_next);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">bool</span> found_include_directive(ContextT <span class="keyword">const</span>&amp; ctx, <br> std::string <span class="keyword">const</span> &amp;filename, <span class="keyword">bool</span> include_next);<br>
 </pre>
 <blockquote>
   <p>The function <tt>found_include_directive</tt> is called whenever whenever a #include directive was located..</p>
@@ -246,7 +248,7 @@
   </p>
 </blockquote>
 <p><a name="opened_include_file" id="opened_include_file"></a><strong>opened_include_file</strong></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">void</span> opened_include_file(ContextT <span class="keyword">const</span>&amp; ctx, <br> std::string <span class="keyword">const</span> &amp;rel_filename, std::string <span class="keyword">const</span> &amp;abs_filename, <br> <span class="keyword">bool</span> is_system_include);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">void</span> opened_include_file(ContextT <span class="keyword">const</span>&amp; ctx, <br> std::string <span class="keyword">const</span> &amp;rel_filename, std::string <span class="keyword">const</span> &amp;abs_filename, <br> <span class="keyword">bool</span> is_system_include);<br>
 </pre>
 <blockquote>
   <p>The function <tt>opened_include_file</tt> is called whenever a file referred
@@ -263,7 +265,7 @@
     as a result of a <tt>#include&nbsp;&lt;...&gt;</tt> directive.</p>
 </blockquote>
 <p><a name="returning_from_include_file" id="returning_from_include_file"></a><strong>returning_from_include_file</strong></p>
-<pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">void</span> returning_from_include_file(ContextT <span class="keyword">const</span>&amp; ctx);<br>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">void</span> returning_from_include_file(ContextT <span class="keyword">const</span>&amp; ctx);<br>
 </pre>
 <blockquote>
   <p>The function <tt>returning_from_include_file</tt> is called whenever an
@@ -271,6 +273,28 @@
   <p>The <tt>ctx</tt> parameter provides a reference to the <tt>context_type</tt> used during instantiation of the preprocessing iterators by the user.
     Note, this parameter was added for the Boost V1.35.0 release. </p>
 </blockquote>
+<p><a name="detected_pragma_once" id="A1">detected_pragma_once</a></p>
+<pre> <span class="keyword"> template</span> &lt;<span class="keyword">typename</span> ContextT&gt;<br> <span class="keyword">void</span> detected_pragma_once(ContextT <span class="keyword">const</span>&amp; ctx,
+ std::string <span class="keyword">const</span>&amp; filename,
+ std::string <span class="keyword">const</span>&amp; include_guard);<br>
+</pre>
+<blockquote>
+ <p>The function <tt>detected_pragma_once</tt> is called whenever either a
+ include file is about to be added to the list of #pragma once headers. That
+ means this header file will not be opened and parsed again even if it is
+ specified in a later #include directive. This function is called either as the
+ result of a detected directive #pragma once, or as the result of a detected
+ include guard scheme. </p>
+ <p>The <tt>ctx</tt> parameter provides a reference to the <tt>context_type</tt>
+ used during instantiation of the preprocessing iterators by the user. </p>
+ <p>The parameter <tt>filename</tt> contains the file system path of the opened file
+ (this is relative to the directory of the currently processed file or a
+ absolute path depending on the paths given as the include search paths).</p>
+ <p>The parameter <tt>include_guard</tt> is either <span class="string">
+ &quot;__BOOST_WAVE_PRAGMA_ONCE__&quot;</span> (if a
+ <span class="preprocessor">#pragma once</span> has been detected) or
+ contains the name of the detected include guard.<br> </p>
+</blockquote>
 <h3>Interpretation of #pragma's</h3>
 <p><strong><a name="interpret_pragma"></a>interpret_pragma</strong></p>
 <pre> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ContextT, <span class="keyword">typename</span> ContainerT&gt;<br> bool interpret_pragma(ContextT <span class="keyword">const</span> &amp;ctx, ContainerT &amp;pending, <br> <span class="keyword">typename</span> ContextT::token_type <span class="keyword">const</span> &amp;option, <br> ContainerT <span class="keyword">const</span> &amp;values, <br> <span class="keyword">typename</span> ContextT::token_type<span class="keyword"> const</span> &amp;pragma_token);<br>
@@ -373,7 +397,7 @@
   1.0. (See accompanying file LICENSE_1_0.txt or copy at
   http://www.boost.org/LICENSE_1_0.txt) </font> </p>
 <p class="copyright"><span class="updated">Last updated:
- <!-- #BeginDate format:fcAm1m -->Tuesday, October 14, 2008 18:45<!-- #EndDate -->
+ <!-- #BeginDate format:fcAm1m -->Thursday, September 17, 2009 12:36<!-- #EndDate -->
   </span></p>
 </body>
 </html>

Modified: trunk/libs/wave/doc/wave_driver.html
==============================================================================
--- trunk/libs/wave/doc/wave_driver.html (original)
+++ trunk/libs/wave/doc/wave_driver.html 2009-09-17 13:54:07 EDT (Thu, 17 Sep 2009)
@@ -59,6 +59,8 @@
     -l [ --listincludes ] arg: list included file to a file [arg] or to stdout [-]
     -m [ --macronames ] arg: list names of all defined macros to a file [arg] or
                                  to stdout [-]
+ -c [ --macrocounts ] arg list macro invocation counts to a file [arg] or to
+ stdout [-]
     -p [ --preserve ] arg (=0): preserve whitespace
                                  0: no whitespace is preserved (default),
                                  1: comments are preserved,
@@ -68,6 +70,8 @@
                                  1: #line directives will be emitted (default)
     -x [ --extended ]: enable the #pragma wave system() directive
     -G [ --noguard ]: disable include guard detection
+ -g [ --listguards ]: list names of files flagged as 'include once' to a
+ file [arg] or to stdout [-]
     -s [ --state ] arg: load and save state information from/to the given
                                  file [arg] or 'wave.state' [-] (interactive mode
                                  only)
@@ -194,6 +198,10 @@
 <blockquote>
   <p dir="ltr">Enable the output of all defined macros. This includes the macro names, its parameter names (if the macro is a function like macro) and its definition. The path specifies the filename to use for the output of the generated macro list. If the filename given equals to <tt>'-'</tt> (without the quotes), the macro list is put into the standard output stream (stdout).</p>
 </blockquote>
+<p dir="ltr">-c [--macrocounts] path</p>
+<blockquote>
+ <p dir="ltr">Enable the output of all macro invocation counts. The path specifies the filename to use for the output of the generated list. If the filename given equals to <tt>'-'</tt> (without the quotes), the macro list is put into the standard output stream (stdout).</p>
+</blockquote>
 <p dir="ltr">-p [--preserve] arg </p>
 <blockquote>
   <p dir="ltr">Preserve the whitespace from the input stream not located inside of macro definitions. The argument defines the amount of whitespace to be preserved. A value of '0' (zero) skips all whitespace, a value of '1' preserves all the comments and a value of '2' will preserve all whitespace in the output.</p>
@@ -212,6 +220,13 @@
 <blockquote>
   <p dir="ltr">This option disables the automatic include guard detection normally performed by the Wave library during the processing of included files. For more information about automatic include guard detection please refer to The Context Object class reference. </p>
 </blockquote>
+<p dir="ltr">-g [--listguards] arg </p>
+<blockquote>
+ <p dir="ltr">This option lists all found include files which either contain a
+ <span class="preprocessor">#pragma once</span> or contain an include guard
+ into the given file. If the filename given equals to <tt>'-'</tt> (without the quotes), the
+ guards log is put into the standard output stream (stdout). For more information about automatic include guard detection please refer to The Context Object class reference. </p>
+</blockquote>
 <p dir="ltr">-s [--state]</p>
 <blockquote>
   <p dir="ltr">This option tries instructs the <tt>Wave</tt> tool to load the serialized information from the file given as the argument and to save back the internal state information at the end of the session to the same file. When using this option <tt>Wave</tt> loads and saves all defined macros (even the predefined ones) and the information about processed header files tagged with <span class="preprocessor">#pragma once</span> and/or identified to have include guards. </p>
@@ -273,7 +288,7 @@
 <font size="2">Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
 <span class="updated"></span>
 <p class="copyright"><span class="updated">Last updated:
- <!-- #BeginDate format:fcAm1m -->Tuesday, July 29, 2008 20:40<!-- #EndDate -->
+ <!-- #BeginDate format:fcAm1m -->Thursday, September 17, 2009 12:40<!-- #EndDate -->
 </span></p>
 </body>
 </html>

Modified: trunk/tools/wave/cpp.cpp
==============================================================================
--- trunk/tools/wave/cpp.cpp (original)
+++ trunk/tools/wave/cpp.cpp 2009-09-17 13:54:07 EDT (Thu, 17 Sep 2009)
@@ -672,6 +672,7 @@
     std::ofstream output;
     std::ofstream traceout;
     std::ofstream includelistout;
+ std::ofstream listguardsout;
 
     trace_flags enable_trace = trace_nothing;
 
@@ -723,6 +724,31 @@
                 rdbuf(cout.rdbuf());
         }
 
+ // Open the stream where to output the list of included file names
+ if (vm.count("listguards")) {
+ // try to open the file, where to put the include list
+ fs::path listguards_file(boost::wave::util::create_path(
+ vm["listguards"].as<std::string>()));
+
+ if (listguards_file != "-") {
+ fs::create_directories(boost::wave::util::branch_path(listguards_file));
+ listguardsout.open(listguards_file.string().c_str());
+ if (!listguardsout.is_open()) {
+ cerr << "wave: could not open include guard list file: "
+ << listguards_file.string() << endl;
+ return -1;
+ }
+ }
+ enable_trace = trace_flags(enable_trace | trace_guards);
+ }
+ if ((enable_trace & trace_guards) && !listguardsout.is_open()) {
+ // by default list included names to std::cout
+ listguardsout.copyfmt(cout);
+ listguardsout.clear(cout.rdstate());
+ static_cast<std::basic_ios<char> &>(listguardsout).
+ rdbuf(cout.rdbuf());
+ }
+
     // enable preserving comments mode
     bool preserve_comments = false;
     bool preserve_whitespace = false;
@@ -759,8 +785,8 @@
     bool allow_output = true; // will be manipulated from inside the hooks object
     std::string default_outfile; // will be used from inside the hooks object
     trace_macro_expansion<token_type> hooks(preserve_whitespace,
- output, traceout, includelistout, enable_trace, enable_system_command,
- allow_output, default_outfile);
+ output, traceout, includelistout, listguardsout, enable_trace,
+ enable_system_command, allow_output, default_outfile);
 
     // enable macro invocation count, if appropriate
         if (vm.count("macrocounts"))
@@ -1206,6 +1232,9 @@
             ("extended,x", "enable the #pragma wave system() directive")
 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
             ("noguard,G", "disable include guard detection")
+ ("listguards,g", po::value<std::string>(),
+ "list names of files flagged as 'include once' to a file [arg] "
+ "or to stdout [-]")
 #endif
 #if BOOST_WAVE_SERIALIZATION != 0
             ("state,s", po::value<std::string>(),

Modified: trunk/tools/wave/trace_macro_expansion.hpp
==============================================================================
--- trunk/tools/wave/trace_macro_expansion.hpp (original)
+++ trunk/tools/wave/trace_macro_expansion.hpp 2009-09-17 13:54:07 EDT (Thu, 17 Sep 2009)
@@ -54,7 +54,8 @@
     trace_nothing = 0, // disable tracing
     trace_macros = 1, // enable macro tracing
     trace_macro_counts = 2, // enable invocation counting
- trace_includes = 4 // enable include file tracing
+ trace_includes = 4, // enable include file tracing
+ trace_guards = 8 // enable include guard tracing
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -144,10 +145,11 @@
 public:
     trace_macro_expansion(bool preserve_whitespace_,
             std::ofstream &output_, std::ostream &tracestrm_,
- std::ostream &includestrm_, trace_flags flags_,
- bool enable_system_command_, bool& generate_output_,
- std::string const& default_outfile_)
- : outputstrm(output_), tracestrm(tracestrm_), includestrm(includestrm_),
+ std::ostream &includestrm_, std::ostream &guardstrm_,
+ trace_flags flags_, bool enable_system_command_,
+ bool& generate_output_, std::string const& default_outfile_)
+ : outputstrm(output_), tracestrm(tracestrm_),
+ includestrm(includestrm_), guardstrm(guardstrm_),
         level(0), flags(flags_), logging_flags(trace_nothing),
         enable_system_command(enable_system_command_),
         preserve_whitespace(preserve_whitespace_),
@@ -571,6 +573,63 @@
         }
     }
 
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'detected_pragma_once' is called, whenever either a
+ // include file is about to be added to the list of #pragma once headers.
+ // That means this header file will not be opened and parsed again even
+ // if it is specified in a later #include directive.
+ // This function is called either as the result of a detected directive
+ // #pragma once, or as the result of a detected include guard scheme.
+ //
+ // The implemented heuristics for include guards detects two forms of
+ // include guards:
+ //
+ // #ifndef INCLUDE_GUARD_MACRO
+ // #define INCLUDE_GUARD_MACRO
+ // ...
+ // #endif
+ //
+ // or
+ //
+ // if !defined(INCLUDE_GUARD_MACRO)
+ // #define INCLUDE_GUARD_MACRO
+ // ...
+ // #endif
+ //
+ // note, that the parenthesis are optional (i.e. !defined INCLUDE_GUARD_MACRO
+ // will work as well). The code allows for any whitespace, newline and single
+ // '#' tokens before the #if/#ifndef and after the final #endif.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'filename' contains the file system path of the
+ // opened file (this is relative to the directory of the currently
+ // processed file or a absolute path depending on the paths given as the
+ // include search paths).
+ //
+ // The parameter include_guard is either "__BOOST_WAVE_PRAGMA_ONCE__" (if
+ // a #pragma once has been detected) or contains the name of the detected
+ // include guard.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT>
+ void
+ detected_pragma_once(ContextT const& ctx, std::string const& filename,
+ std::string const& include_guard)
+ {
+ if (enabled_guard_tracing()) {
+ if (include_guard == "__BOOST_WAVE_PRAGMA_ONCE__")
+ guardstrm << "#pragma once:" << std::endl;
+ else
+ guardstrm << include_guard << ":" << std::endl;
+ guardstrm << " " << filename << std::endl;
+ }
+ }
+#endif
+
     ///////////////////////////////////////////////////////////////////////////
     //
     // The function 'may_skip_whitespace' will be called by the
@@ -1129,6 +1188,10 @@
     {
         return (flags & trace_includes);
     }
+ bool enabled_guard_tracing() const
+ {
+ return (flags & trace_guards);
+ }
     bool enabled_macro_counting() const
     {
         return logging_flags & trace_macro_counts;
@@ -1178,6 +1241,7 @@
     std::ofstream &outputstrm; // main output stream
     std::ostream &tracestrm; // trace output stream
     std::ostream &includestrm; // included list output stream
+ std::ostream &guardstrm; // include guard output stream
     int level; // indentation level
     trace_flags flags; // enabled globally
     trace_flags logging_flags; // enabled by a #pragma


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk