$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r70872 - branches/quickbook-dev/tools/quickbook/src
From: dnljms_at_[hidden]
Date: 2011-04-02 13:45:30
Author: danieljames
Date: 2011-04-02 13:45:28 EDT (Sat, 02 Apr 2011)
New Revision: 70872
URL: http://svn.boost.org/trac/boost/changeset/70872
Log:
Quickbook: Clearer tracking of state in templates and files.
Not quite exception safe, since macros can't be swapped.
Text files modified: 
   branches/quickbook-dev/tools/quickbook/src/actions.cpp       |   114 ++++++++++++---------------------       
   branches/quickbook-dev/tools/quickbook/src/actions_class.cpp |   131 +++++++++++++++++++-------------------- 
   branches/quickbook-dev/tools/quickbook/src/actions_class.hpp |   119 +++++++++++++++++++----------------     
   3 files changed, 171 insertions(+), 193 deletions(-)
Modified: branches/quickbook-dev/tools/quickbook/src/actions.cpp
==============================================================================
--- branches/quickbook-dev/tools/quickbook/src/actions.cpp	(original)
+++ branches/quickbook-dev/tools/quickbook/src/actions.cpp	2011-04-02 13:45:28 EDT (Sat, 02 Apr 2011)
@@ -1177,8 +1177,9 @@
         std::string block;
         std::string phrase;
 
-        actions.push(); // scope the actions' states
         {
+            template_state state(actions);
+        
             // Store the current section level so that we can ensure that
             // [section] and [endsect] tags in the template are balanced.
             actions.min_section_level = actions.section_level;
@@ -1199,7 +1200,6 @@
             
                 if (!break_arguments(args, symbol->params, actions.filename, pos))
                 {
-                    actions.pop(); // restore the actions' states
                     --actions.template_depth;
                     ++actions.error_count;
                     return;
@@ -1246,7 +1246,6 @@
 
             if (!get_arg_result)
             {
-                actions.pop(); // restore the actions' states
                 --actions.template_depth;
                 return;
             }
@@ -1265,7 +1264,6 @@
                     << detail::utf8(symbol->body.content.get_quickbook())
                     << "------------------end--------------------" << std::endl
                     << std::endl;
-                actions.pop(); // restore the actions' states
                 --actions.template_depth;
                 ++actions.error_count;
                 return;
@@ -1275,16 +1273,14 @@
             {
                 detail::outerr(actions.filename, pos.line)
                     << "Mismatched sections in template " << detail::utf8(identifier) << std::endl;
-                actions.pop(); // restore the actions' states
                 --actions.template_depth;
                 ++actions.error_count;
                 return;
             }
-        }
 
-        actions.out.swap(block);
-        actions.phrase.swap(phrase);
-        actions.pop(); // restore the actions' states
+            actions.out.swap(block);
+            actions.phrase.swap(phrase);
+        }
 
         if(!symbol->callouts.empty())
         {
@@ -1296,23 +1292,25 @@
                     boost::lexical_cast<std::string>(detail::callout_id++);
 
                 std::string callout_value;
-                actions.push();
-                bool r = parse_template(
-                    template_body(c, symbol->body.filename), false, actions);
-                actions.out.swap(callout_value);
-                actions.pop();
-
-                if(!r)
                 {
-                    detail::outerr(symbol->body.filename, c.get_position().line)
-                        << "Expanding callout." << std::endl
-                        << "------------------begin------------------" << std::endl
-                        << detail::utf8(c.get_quickbook())
-                        << std::endl
-                        << "------------------end--------------------" << std::endl
-                        ;
-                    ++actions.error_count;
-                    return;
+                    template_state state(actions);
+                    bool r = parse_template(
+                        template_body(c, symbol->body.filename), false, actions);
+
+                    if(!r)
+                    {
+                        detail::outerr(symbol->body.filename, c.get_position().line)
+                            << "Expanding callout." << std::endl
+                            << "------------------begin------------------" << std::endl
+                            << detail::utf8(c.get_quickbook())
+                            << std::endl
+                            << "------------------end--------------------" << std::endl
+                            ;
+                        ++actions.error_count;
+                        return;
+                    }
+
+                    actions.out.swap(callout_value);
                 }
                 
                 block += "<callout arearefs=\"" + callout_id + "co\" ";
@@ -1785,58 +1783,30 @@
             check_path(values.consume(), actions), actions);
         values.finish();
 
-        std::string doc_id;
-
-        // swap the filenames
-        std::swap(actions.filename, filein.filename);
-        std::swap(actions.filename_relative, filein.filename_relative);
-
-        // save the doc info strings and source mode
-        if(qbk_version_n >= 106) {
-            doc_id = actions.doc_id;
-        }
-        else {
-            actions.doc_id.swap(doc_id);
-        }
+        {
+            file_state state(actions);
         
-        // save the source mode (only restored for 1.6+)
-        std::string source_mode = actions.source_mode;
-
-        // scope the macros
-        string_symbols macro = actions.macro;
-        // scope the templates
-        //~ template_symbols templates = actions.templates; $$$ fixme $$$
-
-        // if an id is specified in this include (as in [include:id foo.qbk])
-        // then use it as the doc_id.
-        if (!include_doc_id.empty())
-            actions.doc_id = include_doc_id.get_quickbook();
-
-        // update the __FILENAME__ macro
-        *boost::spirit::classic::find(actions.macro, "__FILENAME__")
-            = detail::path_to_generic(actions.filename_relative);
-
-        // save values
-        actions.values.builder.save();
+            actions.filename = filein.filename;
+            actions.filename_relative = filein.filename_relative;
 
-        // parse the file
-        quickbook::parse_file(actions.filename.string().c_str(), actions, true);
+            // remain bug compatible with old versions of quickbook
+            if(qbk_version_n < 106) actions.doc_id.clear();
 
-        // restore the values
-        actions.values.builder.restore();
+            // if an id is specified in this include (as in [include:id foo.qbk])
+            // then use it as the doc_id.
+            if (!include_doc_id.empty())
+                actions.doc_id = include_doc_id.get_quickbook();
+
+            // update the __FILENAME__ macro
+            *boost::spirit::classic::find(actions.macro, "__FILENAME__")
+                = detail::path_to_generic(actions.filename_relative);
 
-        std::swap(actions.filename, filein.filename);
-        std::swap(actions.filename_relative, filein.filename_relative);
-
-        actions.doc_id.swap(doc_id);
+            // parse the file
+            quickbook::parse_file(actions.filename.string().c_str(), actions, true);
         
-        if(qbk_version_n >= 106)
-            actions.source_mode = source_mode;
-
-        // restore the macros
-        actions.macro = macro;
-        // restore the templates
-        //~ actions.templates = templates; $$$ fixme $$$
+            // Don't restore source_mode on older versions.
+            if (qbk_version_n < 106) state.source_mode = actions.source_mode;
+        }
 
         // restore the __FILENAME__ macro
         *boost::spirit::classic::find(actions.macro, "__FILENAME__")
Modified: branches/quickbook-dev/tools/quickbook/src/actions_class.cpp
==============================================================================
--- branches/quickbook-dev/tools/quickbook/src/actions_class.cpp	(original)
+++ branches/quickbook-dev/tools/quickbook/src/actions_class.cpp	2011-04-02 13:45:28 EDT (Sat, 02 Apr 2011)
@@ -22,48 +22,44 @@
     actions::actions(fs::path const& filein_, fs::path const& xinclude_base_, string_stream& out_)
         : grammar_()
 
-    // header info
         , doc_type()
         , doc_title_qbk()
+        , xinclude_base(xinclude_base_)
+
+        , template_depth(0)
+        , templates()
+        , error_count(0)
+        , anchors()
+        , no_eols(true)
+        , suppress(false)
+        , warned_about_breaks(false)
+        , context(0)
+
+        , macro()
+        , source_mode("c++")
         , doc_id()
+        , filename(filein_)
+        , filename_relative(filein_.filename())
 
-    // main output stream
-        , out(out_)
+        , section_level(0)
+        , min_section_level(0)
+        , section_id()
+        , qualified_section_id()
 
-    // auxilliary streams
+        , out(out_)
         , phrase()
-
-    // value actions
         , values()
+
+    // actions
         , phrase_value(*this, phrase)
         , out_value(*this, out)
         , docinfo_value(*this)
+
         , scoped_cond_phrase(*this)
         , scoped_output(*this)
         , scoped_no_eols(*this)
         , scoped_context(*this)
 
-    // state
-        , filename(filein_)
-        , filename_relative(filein_.filename())
-        , xinclude_base(xinclude_base_)
-        , macro()
-        , section_level(0)
-        , min_section_level(0)
-        , section_id()
-        , qualified_section_id()
-        , source_mode("c++")
-
-    // temporary or global state
-        , template_depth(0)
-        , templates()
-        , error_count(0)
-        , anchors()
-        , no_eols(true)
-        , suppress(false)
-        , warned_about_breaks(false)
-
-    // actions
         , element(*this)
         , error(*this)
         , code(out, phrase, *this)
@@ -93,49 +89,52 @@
             new quickbook_grammar(*this));
         grammar_.swap(g);
     }
-    
-    void actions::push()
+
+    quickbook_grammar& actions::grammar() const {
+        return *grammar_;
+    }
+
+    file_state::file_state(actions& a)
+        : a(a)
+        , doc_id(a.doc_id)
+        , filename(a.filename)
+        , filename_relative(a.filename_relative)
+        , macro(a.macro)
+        , source_mode(a.source_mode)
     {
-        state_stack.push(
-            boost::make_tuple(
-                filename
-              , xinclude_base
-              , macro
-              , section_level
-              , min_section_level
-              , section_id
-              , qualified_section_id
-              , source_mode
-            )
-        );
-
-        out.push();
-        phrase.push();
-        templates.push();
-        values.builder.save();
+        a.values.builder.save();
     }
-    
-    void actions::pop()
+
+    file_state::~file_state()
     {
-        boost::tie(
-            filename
-          , xinclude_base
-          , macro
-          , section_level
-          , min_section_level
-          , section_id
-          , qualified_section_id
-          , source_mode
-        ) = state_stack.top();
-        state_stack.pop();
-
-        out.pop();
-        phrase.pop();
-        templates.pop();
-        values.builder.restore();
+        a.values.builder.restore();
+        boost::swap(a.doc_id, doc_id);
+        boost::swap(a.filename, filename);
+        boost::swap(a.filename_relative, filename_relative);
+        a.macro = macro;
+        boost::swap(a.source_mode, source_mode);
     }
     
-    quickbook_grammar& actions::grammar() const {
-        return *grammar_;
+    template_state::template_state(actions& a)
+        : file_state(a)
+        , section_level(a.section_level)
+        , min_section_level(a.min_section_level)
+        , section_id(a.section_id)
+        , qualified_section_id(a.qualified_section_id)
+    {
+        a.out.push();
+        a.phrase.push();
+        a.templates.push();
+    }
+
+    template_state::~template_state()
+    {
+        a.templates.pop();
+        a.phrase.pop();
+        a.out.pop();
+        boost::swap(a.section_level, section_level);
+        boost::swap(a.min_section_level, min_section_level);
+        boost::swap(a.section_id, section_id);
+        boost::swap(a.qualified_section_id, qualified_section_id);
     }
 }
Modified: branches/quickbook-dev/tools/quickbook/src/actions_class.hpp
==============================================================================
--- branches/quickbook-dev/tools/quickbook/src/actions_class.hpp	(original)
+++ branches/quickbook-dev/tools/quickbook/src/actions_class.hpp	2011-04-02 13:45:28 EDT (Sat, 02 Apr 2011)
@@ -10,7 +10,6 @@
 #if !defined(BOOST_SPIRIT_ACTIONS_CLASS_HPP)
 #define BOOST_SPIRIT_ACTIONS_CLASS_HPP
 
-#include <boost/tuple/tuple.hpp>
 #include <boost/scoped_ptr.hpp>
 #include "actions.hpp"
 #include "parsers.hpp"
@@ -38,78 +37,59 @@
 
         static int const max_template_depth = 100;
 
-    // header info
-        std::string             doc_type;      // For the whole document, not
-                                               // the current file.
+    // global state
+        std::string             doc_type;       // For the whole document, not
+                                                // the current file.
         std::string             doc_title_qbk;
-        std::string             doc_id;
-
-    // main output stream
-        collector               out;
-
-    // auxilliary streams
-        collector               phrase;
-
-    // value actions
-        value_parser            values;
-        collector_to_value_action phrase_value;
-        collector_to_value_action out_value;
-        phrase_to_docinfo_action docinfo_value;
-        
-        scoped_parser<cond_phrase_push>
-                                scoped_cond_phrase;
-        scoped_parser<scoped_output_push>
-                                scoped_output;
-        scoped_parser<set_no_eols_scoped>
-                                scoped_no_eols;
-        scoped_parser<scoped_context_impl>
-                                scoped_context;
+        fs::path                xinclude_base;
+        int                     template_depth;
+        template_stack          templates;
+        int                     error_count;
+        string_list             anchors;
+        bool                    no_eols;
+        bool                    suppress;
+        bool                    warned_about_breaks;
+        int                     context;
 
-    // state
+    // state saved for files and templates.
+        string_symbols          macro;
+        std::string             source_mode;
+        std::string             doc_id;
         fs::path                filename;
         fs::path                filename_relative;  // for the __FILENAME__ macro.
                                                     // (relative to the original file
                                                     //  or include path).
-        fs::path                xinclude_base;
-        string_symbols          macro;
+
+    // state saved for templates.
         int                     section_level;
         int                     min_section_level;
         std::string             section_id;
         std::string             qualified_section_id;
-        std::string             source_mode;
-
-        typedef boost::tuple<
-            fs::path
-          , fs::path
-          , string_symbols
-          , int
-          , int
-          , std::string
-          , std::string
-          , std::string>
-        state_tuple;
 
-        std::stack<state_tuple> state_stack;
+    // output state - scoped by templates and grammar
+        collector               out;            // main output stream
+        collector               phrase;         // phrase output stream
+        value_parser            values;         // parsed values
 
-    // temporary or global state
-        int                     template_depth;
-        template_stack          templates;
-        int                     error_count;
-        string_list             anchors;
-        bool                    no_eols;
-        bool                    suppress;
-        bool                    warned_about_breaks;
-        int                     context;
-
-    // push/pop the states and the streams
-        void push();
-        void pop();
         quickbook_grammar& grammar() const;
 
     ///////////////////////////////////////////////////////////////////////////
     // actions
     ///////////////////////////////////////////////////////////////////////////
 
+        collector_to_value_action phrase_value;
+        collector_to_value_action out_value;
+        phrase_to_docinfo_action docinfo_value;
+        
+        scoped_parser<cond_phrase_push>
+                                scoped_cond_phrase;
+        scoped_parser<scoped_output_push>
+                                scoped_output;
+        scoped_parser<set_no_eols_scoped>
+                                scoped_no_eols;
+        scoped_parser<scoped_context_impl>
+                                scoped_context;
+
         element_action          element;
         error_action            error;
 
@@ -129,6 +109,35 @@
 
         element_id_warning_action element_id_warning;
     };
+
+    // State savers
+
+    struct file_state
+    {
+        explicit file_state(actions&);
+        ~file_state();
+        
+        quickbook::actions& a;
+        std::string doc_id;
+        fs::path filename;
+        fs::path filename_relative;
+        string_symbols macro;
+        std::string source_mode;
+    private:
+        file_state(file_state const&);
+        file_state& operator=(file_state const&);
+    };
+
+    struct template_state : file_state
+    {
+        explicit template_state(actions&);
+        ~template_state();
+
+        int section_level;
+        int min_section_level;
+        std::string section_id;
+        std::string qualified_section_id;
+    };
 }
 
 #endif // BOOST_SPIRIT_ACTIONS_CLASS_HPP