$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r70930 - in branches/release/tools/quickbook: . doc src test test/command-line test/doc-info test/include test/include/sub test/snippets test/src test/unit
From: dnljms_at_[hidden]
Date: 2011-04-03 07:51:00
Author: danieljames
Date: 2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
New Revision: 70930
URL: http://svn.boost.org/trac/boost/changeset/70930
Log:
Quickbook: merge quickbook 1.5.5
Added:
   branches/release/tools/quickbook/src/block_tags.hpp
      - copied, changed from r70210, /trunk/tools/quickbook/src/block_tags.hpp
   branches/release/tools/quickbook/src/cleanup.hpp
      - copied unchanged from r70569, /trunk/tools/quickbook/src/cleanup.hpp
   branches/release/tools/quickbook/src/doc_info_tags.hpp
      - copied unchanged from r70210, /trunk/tools/quickbook/src/doc_info_tags.hpp
   branches/release/tools/quickbook/src/iterator.hpp
      - copied, changed from r70044, /trunk/tools/quickbook/src/iterator.hpp
   branches/release/tools/quickbook/src/parsers.hpp
      - copied, changed from r70210, /trunk/tools/quickbook/src/parsers.hpp
   branches/release/tools/quickbook/src/phrase_tags.hpp
      - copied, changed from r70210, /trunk/tools/quickbook/src/phrase_tags.hpp
   branches/release/tools/quickbook/src/scoped.hpp
      - copied unchanged from r70210, /trunk/tools/quickbook/src/scoped.hpp
   branches/release/tools/quickbook/src/template_tags.hpp
      - copied, changed from r70210, /trunk/tools/quickbook/src/template_tags.hpp
   branches/release/tools/quickbook/src/value_tags.hpp
      - copied unchanged from r70210, /trunk/tools/quickbook/src/value_tags.hpp
   branches/release/tools/quickbook/src/values.cpp
      - copied, changed from r70210, /trunk/tools/quickbook/src/values.cpp
   branches/release/tools/quickbook/src/values.hpp
      - copied, changed from r70210, /trunk/tools/quickbook/src/values.hpp
   branches/release/tools/quickbook/src/values_parse.hpp
      - copied, changed from r70210, /trunk/tools/quickbook/src/values_parse.hpp
   branches/release/tools/quickbook/test/command-line/
      - copied from r70210, /trunk/tools/quickbook/test/command-line/
   branches/release/tools/quickbook/test/command-line/Jamfile.v2
      - copied unchanged from r70210, /trunk/tools/quickbook/test/command-line/Jamfile.v2
   branches/release/tools/quickbook/test/command-line/error-fail.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/command-line/error-fail.quickbook
   branches/release/tools/quickbook/test/command-line/error1.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/command-line/error1.quickbook
   branches/release/tools/quickbook/test/command-line/error2.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/command-line/error2.quickbook
   branches/release/tools/quickbook/test/doc-info/
      - copied from r70210, /trunk/tools/quickbook/test/doc-info/
   branches/release/tools/quickbook/test/doc-info/Jamfile.v2
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/Jamfile.v2
   branches/release/tools/quickbook/test/doc-info/author1.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/author1.gold
   branches/release/tools/quickbook/test/doc-info/author1.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/author1.quickbook
   branches/release/tools/quickbook/test/doc-info/author2.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/author2.gold
   branches/release/tools/quickbook/test/doc-info/author2.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/author2.quickbook
   branches/release/tools/quickbook/test/doc-info/copyright-fail1.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/copyright-fail1.quickbook
   branches/release/tools/quickbook/test/doc-info/copyright-fail2.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/copyright-fail2.quickbook
   branches/release/tools/quickbook/test/doc-info/copyright1.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/copyright1.gold
   branches/release/tools/quickbook/test/doc-info/copyright1.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/copyright1.quickbook
   branches/release/tools/quickbook/test/doc-info/duplicates-1.1.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/duplicates-1.1.gold
   branches/release/tools/quickbook/test/doc-info/duplicates-1.1.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/duplicates-1.1.quickbook
   branches/release/tools/quickbook/test/doc-info/duplicates-1.5.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/duplicates-1.5.gold
   branches/release/tools/quickbook/test/doc-info/duplicates-1.5.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/duplicates-1.5.quickbook
   branches/release/tools/quickbook/test/doc-info/empty-attributes.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/empty-attributes.gold
   branches/release/tools/quickbook/test/doc-info/empty-attributes.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/empty-attributes.quickbook
   branches/release/tools/quickbook/test/doc-info/encode-1.5.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/encode-1.5.gold
   branches/release/tools/quickbook/test/doc-info/encode-1.5.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/encode-1.5.quickbook
   branches/release/tools/quickbook/test/doc-info/escape-1.6.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/escape-1.6.gold
   branches/release/tools/quickbook/test/doc-info/escape-1.6.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/escape-1.6.quickbook
   branches/release/tools/quickbook/test/doc-info/source-mode-1.4.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/source-mode-1.4.gold
   branches/release/tools/quickbook/test/doc-info/source-mode-1.4.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/source-mode-1.4.quickbook
   branches/release/tools/quickbook/test/doc-info/source-mode-1.5.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/source-mode-1.5.gold
   branches/release/tools/quickbook/test/doc-info/source-mode-1.5.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/source-mode-1.5.quickbook
   branches/release/tools/quickbook/test/doc-info/source-mode-1.6.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/source-mode-1.6.gold
   branches/release/tools/quickbook/test/doc-info/source-mode-1.6.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/source-mode-1.6.quickbook
   branches/release/tools/quickbook/test/doc-info/source-mode-cpp-include.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/source-mode-cpp-include.quickbook
   branches/release/tools/quickbook/test/doc-info/source-mode-python-include.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/source-mode-python-include.quickbook
   branches/release/tools/quickbook/test/doc-info/source-mode-teletype-include.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/doc-info/source-mode-teletype-include.quickbook
   branches/release/tools/quickbook/test/elements_1_5.gold
      - copied unchanged from r70301, /trunk/tools/quickbook/test/elements_1_5.gold
   branches/release/tools/quickbook/test/elements_1_5.quickbook
      - copied unchanged from r70301, /trunk/tools/quickbook/test/elements_1_5.quickbook
   branches/release/tools/quickbook/test/elements_1_6.gold
      - copied unchanged from r70301, /trunk/tools/quickbook/test/elements_1_6.gold
   branches/release/tools/quickbook/test/elements_1_6.quickbook
      - copied unchanged from r70301, /trunk/tools/quickbook/test/elements_1_6.quickbook
   branches/release/tools/quickbook/test/fail-mismatched-boostbook-escape.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/fail-mismatched-boostbook-escape.quickbook
   branches/release/tools/quickbook/test/include/
      - copied from r70301, /trunk/tools/quickbook/test/include/
   branches/release/tools/quickbook/test/include/Jamfile.v2
      - copied unchanged from r70301, /trunk/tools/quickbook/test/include/Jamfile.v2
   branches/release/tools/quickbook/test/include/filename-path.gold
      - copied unchanged from r70301, /trunk/tools/quickbook/test/include/filename-path.gold
   branches/release/tools/quickbook/test/include/filename-path.quickbook
      - copied unchanged from r70301, /trunk/tools/quickbook/test/include/filename-path.quickbook
   branches/release/tools/quickbook/test/include/filename.gold
      - copied unchanged from r70301, /trunk/tools/quickbook/test/include/filename.gold
   branches/release/tools/quickbook/test/include/filename.quickbook
      - copied unchanged from r70301, /trunk/tools/quickbook/test/include/filename.quickbook
   branches/release/tools/quickbook/test/include/filename_include2.quickbook
      - copied unchanged from r70301, /trunk/tools/quickbook/test/include/filename_include2.quickbook
   branches/release/tools/quickbook/test/include/sub/
      - copied from r70301, /trunk/tools/quickbook/test/include/sub/
   branches/release/tools/quickbook/test/include/sub/filename_include1.quickbook
      - copied unchanged from r70301, /trunk/tools/quickbook/test/include/sub/filename_include1.quickbook
   branches/release/tools/quickbook/test/snippets/
      - copied from r70210, /trunk/tools/quickbook/test/snippets/
   branches/release/tools/quickbook/test/snippets/Jamfile.v2
      - copied unchanged from r70210, /trunk/tools/quickbook/test/snippets/Jamfile.v2
   branches/release/tools/quickbook/test/snippets/pass_thru.cpp
      - copied, changed from r70210, /trunk/tools/quickbook/test/snippets/pass_thru.cpp
   branches/release/tools/quickbook/test/snippets/pass_thru.gold
      - copied unchanged from r70210, /trunk/tools/quickbook/test/snippets/pass_thru.gold
   branches/release/tools/quickbook/test/snippets/pass_thru.py
      - copied, changed from r70210, /trunk/tools/quickbook/test/snippets/pass_thru.py
   branches/release/tools/quickbook/test/snippets/pass_thru.quickbook
      - copied unchanged from r70210, /trunk/tools/quickbook/test/snippets/pass_thru.quickbook
   branches/release/tools/quickbook/test/src/Jamfile.v2
      - copied, changed from r69832, /trunk/tools/quickbook/test/src/Jamfile.v2
   branches/release/tools/quickbook/test/unit/
      - copied from r70210, /trunk/tools/quickbook/test/unit/
   branches/release/tools/quickbook/test/unit/Jamfile.v2
      - copied, changed from r70210, /trunk/tools/quickbook/test/unit/Jamfile.v2
   branches/release/tools/quickbook/test/unit/iterator_tests.cpp
      - copied unchanged from r70569, /trunk/tools/quickbook/test/unit/iterator_tests.cpp
   branches/release/tools/quickbook/test/unit/post_process_test.cpp
      - copied unchanged from r70210, /trunk/tools/quickbook/test/unit/post_process_test.cpp
   branches/release/tools/quickbook/test/unit/values_test.cpp
      - copied, changed from r70210, /trunk/tools/quickbook/test/unit/values_test.cpp
Removed:
   branches/release/tools/quickbook/src/rule_store.hpp
   branches/release/tools/quickbook/src/scoped_parser.hpp
   branches/release/tools/quickbook/test/doc-info-1.gold
   branches/release/tools/quickbook/test/doc-info-1.quickbook
   branches/release/tools/quickbook/test/doc-info-2.gold
   branches/release/tools/quickbook/test/doc-info-2.quickbook
   branches/release/tools/quickbook/test/doc-info-3.gold
   branches/release/tools/quickbook/test/doc-info-3.quickbook
   branches/release/tools/quickbook/test/doc-info-4.gold
   branches/release/tools/quickbook/test/doc-info-4.quickbook
Properties modified: 
   branches/release/tools/quickbook/   (props changed)
   branches/release/tools/quickbook/doc/   (props changed)
   branches/release/tools/quickbook/src/   (props changed)
   branches/release/tools/quickbook/test/   (props changed)
Text files modified: 
   branches/release/tools/quickbook/doc/quickbook.qbk              |    56 +                                       
   branches/release/tools/quickbook/src/Jamfile.v2                 |     9                                         
   branches/release/tools/quickbook/src/actions.cpp                |  1626 ++++++++++++++++++++++++--------------- 
   branches/release/tools/quickbook/src/actions.hpp                |   716 +---------------                        
   branches/release/tools/quickbook/src/actions_class.cpp          |   181 ---                                     
   branches/release/tools/quickbook/src/actions_class.hpp          |   187 ---                                     
   branches/release/tools/quickbook/src/block_element_grammar.cpp  |   261 ++---                                   
   branches/release/tools/quickbook/src/block_tags.hpp             |     3                                         
   branches/release/tools/quickbook/src/code_snippet.cpp           |   144 ++-                                     
   branches/release/tools/quickbook/src/doc_info_actions.cpp       |   344 +++++--                                 
   branches/release/tools/quickbook/src/doc_info_grammar.cpp       |   259 +++--                                   
   branches/release/tools/quickbook/src/fwd.hpp                    |    11                                         
   branches/release/tools/quickbook/src/grammar.cpp                |     2                                         
   branches/release/tools/quickbook/src/grammar.hpp                |     2                                         
   branches/release/tools/quickbook/src/grammar_impl.hpp           |    27                                         
   branches/release/tools/quickbook/src/input_path.cpp             |   256 +++++-                                  
   branches/release/tools/quickbook/src/input_path.hpp             |   127 ++                                      
   branches/release/tools/quickbook/src/iterator.hpp               |    15                                         
   branches/release/tools/quickbook/src/main_grammar.cpp           |   527 +++++++-----                            
   branches/release/tools/quickbook/src/markups.cpp                |   149 +--                                     
   branches/release/tools/quickbook/src/markups.hpp                |   100 --                                      
   branches/release/tools/quickbook/src/parsers.hpp                |     7                                         
   branches/release/tools/quickbook/src/phrase_element_grammar.cpp |   220 +----                                   
   branches/release/tools/quickbook/src/phrase_tags.hpp            |     2                                         
   branches/release/tools/quickbook/src/post_process.cpp           |    44                                         
   branches/release/tools/quickbook/src/post_process.hpp           |    16                                         
   branches/release/tools/quickbook/src/quickbook.cpp              |   229 ++++-                                   
   branches/release/tools/quickbook/src/quickbook.hpp              |    15                                         
   branches/release/tools/quickbook/src/syntax_highlight.hpp       |    31                                         
   branches/release/tools/quickbook/src/template_stack.cpp         |    19                                         
   branches/release/tools/quickbook/src/template_stack.hpp         |    62 -                                       
   branches/release/tools/quickbook/src/template_tags.hpp          |     1                                         
   branches/release/tools/quickbook/src/utils.cpp                  |    63 -                                       
   branches/release/tools/quickbook/src/utils.hpp                  |    50                                         
   branches/release/tools/quickbook/src/values.cpp                 |   309 +++++-                                  
   branches/release/tools/quickbook/src/values.hpp                 |    70 +                                       
   branches/release/tools/quickbook/src/values_parse.hpp           |     2                                         
   branches/release/tools/quickbook/test/Jamfile.v2                |    62                                         
   branches/release/tools/quickbook/test/anchor.gold               |    53 +                                       
   branches/release/tools/quickbook/test/anchor.quickbook          |    14                                         
   branches/release/tools/quickbook/test/blocks.gold               |     8                                         
   branches/release/tools/quickbook/test/code-block.gold           |     2                                         
   branches/release/tools/quickbook/test/heading.gold              |     6                                         
   branches/release/tools/quickbook/test/heading_1_6.gold          |     6                                         
   branches/release/tools/quickbook/test/identifier_1_5.gold       |     2                                         
   branches/release/tools/quickbook/test/identifier_1_6.gold       |     2                                         
   branches/release/tools/quickbook/test/link.quickbook            |     2                                         
   branches/release/tools/quickbook/test/list_test.gold            |   265 +++--                                   
   branches/release/tools/quickbook/test/list_test.quickbook       |     7                                         
   branches/release/tools/quickbook/test/quickbook-manual.gold     |   256 +++---                                  
   branches/release/tools/quickbook/test/quickbook-testing.jam     |    46                                         
   branches/release/tools/quickbook/test/simple_markup.gold        |    33                                         
   branches/release/tools/quickbook/test/simple_markup.quickbook   |    23                                         
   branches/release/tools/quickbook/test/snippets/pass_thru.cpp    |     8                                         
   branches/release/tools/quickbook/test/snippets/pass_thru.py     |     6                                         
   branches/release/tools/quickbook/test/src/Jamfile.v2            |     8                                         
   branches/release/tools/quickbook/test/table_1_5.gold            |    89 ++                                      
   branches/release/tools/quickbook/test/table_1_5.quickbook       |    31                                         
   branches/release/tools/quickbook/test/template-section.gold     |     2                                         
   branches/release/tools/quickbook/test/unicode-escape.gold       |     2                                         
   branches/release/tools/quickbook/test/unit/Jamfile.v2           |     9                                         
   branches/release/tools/quickbook/test/unit/values_test.cpp      |    53 +                                       
   branches/release/tools/quickbook/test/utf-8-bom.gold            |     2                                         
   branches/release/tools/quickbook/test/utf-8.gold                |     2                                         
   branches/release/tools/quickbook/test/variablelist.gold         |    12                                         
   branches/release/tools/quickbook/test/variablelist.quickbook    |    11                                         
   branches/release/tools/quickbook/test/xinclude.gold             |     2                                         
   67 files changed, 3870 insertions(+), 3296 deletions(-)
Modified: branches/release/tools/quickbook/doc/quickbook.qbk
==============================================================================
--- branches/release/tools/quickbook/doc/quickbook.qbk	(original)
+++ branches/release/tools/quickbook/doc/quickbook.qbk	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -239,7 +239,9 @@
   * XML escape documentation fields, with escapes to allow encoding unicode
     in ASCII.
 
-[heading Version 1.5.4 - Boost 1.46.0]
+[heading Version 1.5.4 - Boost 1.46.1]
+
+Boost 1.46.0:
 
 * Add support for `lang` attribute in documentation info.
 * Improved anchor implementation. Especially for using an anchor
@@ -251,6 +253,46 @@
 * Rearrange the structure of the grammar.
 * Use filesystem 3. Remove cygwin support.
 
+Boost 1.46.1:
+
+* Work around optimization bug in g++ 4.4 on 64 bit linux.
+
+[heading Version 1.5.5 - Boost 1.47]
+
+* Tweak anchor placement for titles.
+* Hard code the quickbook path into the quickbook testing tools. This
+  means that they can be used from multiple locations.
+* Generate an id for boostbook `bridgehead` elements. This results in
+  more consistent html, since docbook generates a random id if they
+  don't have one.
+* Improved unicode support on windows. Unicode can now be used from the
+  command line, and unicode filenames are supported. Unicode output is
+  a bit weak.
+* Check for windows paths, and warn about them.
+* Fix relative path detection on windows.
+* Reverse deprecation of `[br]`, printing a single warning about
+  generating invalid boostbook.
+* Fix handling empty category attributes.
+* Store data from the parser in a dynamic data structure.
+  This simplifies the implementation and makes it easier to parse
+  more complicated data structures.
+* Improved error messages for unknown doc info attributes.
+* Richer copyright syntax. Now understands:
+  `[copyright 2001-2006, 2010 One person, 2008 Another person]`.
+* Fix delimeter checking for simple markup.
+* Allow more block elements to be nested.
+* Go back to using invalid markup for lists. It generates better html.
+* Better anchor placement for lists.
+* Pass-thru comments in code snippets.
+* Use relative paths for `__FILENAME__` macro.
+* Rewrite xinclude path generator so that it doesn't use deprecated
+  filesystem functions.
+* Quickbook 1.6:
+  * Scope source mode changes to the file they're made in.
+  * Explicit markup for lists. e.g.
+    `[ordered_list [item1][item2]]` or
+    `[itemized_list [item1][item2]]`.
+
 [endsect] [/Change log]
 
 [section:syntax Syntax Summary]
@@ -1902,6 +1944,18 @@
 can be used to inhibit code from passing through to quickbook. All text between
 the delimeters will simply be ignored.
 
+Comments of this form:
+
+    //=int main() {}
+
+or
+
+    /*=foo()*/
+
+will be displayed as code that isn't in comments. This allows you to
+include some code in the snippet but not actually use it when
+compiling your example.
+
 [heading Callouts]
 
 Special comments of the form:
Modified: branches/release/tools/quickbook/src/Jamfile.v2
==============================================================================
--- branches/release/tools/quickbook/src/Jamfile.v2	(original)
+++ branches/release/tools/quickbook/src/Jamfile.v2	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -14,8 +14,12 @@
         <toolset>darwin:<c++-template-depth>300
         <toolset>gcc:<cflags>-g0
         <toolset>darwin:<cflags>-g0
+        <warnings>all
+        <toolset>msvc:<cflags>/wd4709
     ;
 
+lib shell32 ;
+
 exe quickbook
     :
     quickbook.cpp
@@ -24,6 +28,7 @@
     actions_class.cpp
     utils.cpp
     input_path.cpp
+    values.cpp
     post_process.cpp
     collector.cpp
     template_stack.cpp
@@ -38,8 +43,7 @@
     /boost//program_options
     /boost//filesystem
     : #<define>QUICKBOOK_NO_DATES
-      # Still using 'normalize' which has been deprecated.
-      #<define>BOOST_FILESYSTEM_NO_DEPRECATED
+      <define>BOOST_FILESYSTEM_NO_DEPRECATED
       <toolset>msvc:<cxxflags>/wd4355
       <toolset>msvc:<cxxflags>/wd4511
       <toolset>msvc:<cxxflags>/wd4512
@@ -50,4 +54,5 @@
       <toolset>msvc:<cxxflags>/wd4800
       <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
       <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+      <target-os>windows:<library>shell32
     ;
Modified: branches/release/tools/quickbook/src/actions.cpp
==============================================================================
--- branches/release/tools/quickbook/src/actions.cpp	(original)
+++ branches/release/tools/quickbook/src/actions.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -10,28 +10,33 @@
 =============================================================================*/
 #include <numeric>
 #include <functional>
-#include <algorithm>
+#include <vector>
+#include <map>
 #include <boost/filesystem/v3/convenience.hpp>
 #include <boost/filesystem/v3/fstream.hpp>
+#include <boost/range/distance.hpp>
+#include <boost/range/algorithm/replace.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/next_prior.hpp>
+#include <boost/foreach.hpp>
 #include "quickbook.hpp"
 #include "actions.hpp"
 #include "utils.hpp"
 #include "markups.hpp"
 #include "actions_class.hpp"
 #include "grammar.hpp"
+#include "input_path.hpp"
+#include "block_tags.hpp"
+#include "phrase_tags.hpp"
 
 namespace quickbook
 {
     char const* quickbook_get_date = "__quickbook_get_date__";
     char const* quickbook_get_time = "__quickbook_get_time__";
 
-    int qbk_major_version = -1;
-    int qbk_minor_version = -1;
     unsigned qbk_version_n = 0; // qbk_major_version * 100 + qbk_minor_version
 
-    void assign_qbk_version::operator()(int value) const { v_ = value; }
-
     namespace {
         std::string fully_qualified_id(std::string const& library_id,
             std::string const& qualified_section_id,
@@ -44,281 +49,478 @@
             id += section_id;
             return id;
         }
+
+        void write_anchors(quickbook::actions& actions, collector& tgt)
+        {
+            for(quickbook::actions::string_list::iterator
+                it = actions.anchors.begin(),
+                end = actions.anchors.end();
+                it != end; ++it)
+            {
+                tgt << "<anchor id=\"";
+                detail::print_string(*it, tgt.get());
+                tgt << "\"/>\n";
+            }
+            
+            actions.anchors.clear();
+        }    
+    }
+
+    void list_action(quickbook::actions&, value);
+    void explicit_list_action(quickbook::actions&, value);
+    void header_action(quickbook::actions&, value);
+    void begin_section_action(quickbook::actions&, value);
+    void end_section_action(quickbook::actions&, value, file_position);
+    void block_action(quickbook::actions&, value);
+    void block_empty_action(quickbook::actions&, value);
+    void macro_definition_action(quickbook::actions&, value);
+    void template_body_action(quickbook::actions&, value);
+    void variable_list_action(quickbook::actions&, value);
+    void table_action(quickbook::actions&, value);
+    void xinclude_action(quickbook::actions&, value);
+    void import_action(quickbook::actions&, value);
+    void include_action(quickbook::actions&, value);
+    void image_action(quickbook::actions&, value);
+    void anchor_action(quickbook::actions&, value);
+    void link_action(quickbook::actions&, value);
+    void phrase_action(quickbook::actions&, value);
+    void raw_phrase_action(quickbook::actions&, value);
+    void source_mode_action(quickbook::actions&, value);
+    void do_template_action(quickbook::actions&, value, file_position);
+    
+    void element_action::operator()(iterator first, iterator) const
+    {
+        value_consumer values = actions.values.release();
+        if(!values.check()) return;
+        value v = values.consume();
+        if(values.check()) return;
+        
+        switch(v.get_tag())
+        {
+        case block_tags::list:
+            return list_action(actions, v);
+        case block_tags::ordered_list:
+        case block_tags::itemized_list:
+            return explicit_list_action(actions, v);
+        case block_tags::generic_heading:
+        case block_tags::heading1:
+        case block_tags::heading2:
+        case block_tags::heading3:
+        case block_tags::heading4:
+        case block_tags::heading5:
+        case block_tags::heading6:
+            return header_action(actions, v);
+        case block_tags::begin_section:
+            return begin_section_action(actions, v);
+        case block_tags::end_section:
+            return end_section_action(actions, v, first.get_position());
+        case block_tags::blurb:
+        case block_tags::preformatted:
+        case block_tags::blockquote:
+        case block_tags::warning:
+        case block_tags::caution:
+        case block_tags::important:
+        case block_tags::note:
+        case block_tags::tip:
+            return block_action(actions,v);
+        case block_tags::hr:
+            return block_empty_action(actions,v);
+        case block_tags::macro_definition:
+            return macro_definition_action(actions,v);
+        case block_tags::template_definition:
+            return template_body_action(actions,v);
+        case block_tags::variable_list:
+            return variable_list_action(actions, v);
+        case block_tags::table:
+            return table_action(actions, v);
+        case block_tags::xinclude:
+            return xinclude_action(actions, v);
+        case block_tags::import:
+            return import_action(actions, v);
+        case block_tags::include:
+            return include_action(actions, v);
+        case phrase_tags::image:
+            return image_action(actions, v);
+        case phrase_tags::anchor:
+            return anchor_action(actions, v);
+        case phrase_tags::url:
+        case phrase_tags::link:
+        case phrase_tags::funcref:
+        case phrase_tags::classref:
+        case phrase_tags::memberref:
+        case phrase_tags::enumref:
+        case phrase_tags::macroref:
+        case phrase_tags::headerref:
+        case phrase_tags::conceptref:
+        case phrase_tags::globalref:
+            return link_action(actions, v);
+        case phrase_tags::bold:
+        case phrase_tags::italic:
+        case phrase_tags::underline:
+        case phrase_tags::teletype:
+        case phrase_tags::strikethrough:
+        case phrase_tags::quote:
+        case phrase_tags::replaceable:
+        case phrase_tags::footnote:
+            return phrase_action(actions, v);
+        case phrase_tags::escape:
+            return raw_phrase_action(actions, v);
+        case source_mode_tags::cpp:
+        case source_mode_tags::python:
+        case source_mode_tags::teletype:
+            return source_mode_action(actions, v);
+        case template_tags::template_:
+            return do_template_action(actions, v, first.get_position());
+        default:
+            break;
+        }
     }
 
     // Handles line-breaks (DEPRECATED!!!)
     void break_action::operator()(iterator first, iterator) const
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, phrase);
+
+        file_position const pos = first.get_position();
+        if(*first == '\\')
+        {
+            detail::outwarn(actions.filename, pos.line)
+                << "in column:" << pos.column << ", "
+                << "'\\n' is deprecated, pleases use '[br]' instead" << ".\n";
+        }
+
+        if(!actions.warned_about_breaks)
+        {
+            detail::outwarn(actions.filename, pos.line)
+                << "line breaks generate invalid boostbook"
+                << "    (will only note first occurrence)."
+                << "\n";
+
+            actions.warned_about_breaks = true;
+        }
+            
+        phrase << detail::get_markup(phrase_tags::break_mark).pre;
+    }
+
+    void error_message_action::operator()(iterator first, iterator last) const
+    {
+        file_position const pos = first.get_position();
+
+        std::string value(first, last);
+        std::string formatted_message = message;
+        boost::replace_all(formatted_message, "%s", value);
+        boost::replace_all(formatted_message, "%c",
+            boost::lexical_cast<std::string>(pos.column));
 
-        position const pos = first.get_position();
-        detail::outwarn(pos.file,pos.line) << "in column:" << pos.column << ", "
-            << "[br] and \\n are deprecated" << ".\n";
-        phrase << break_mark;
+        detail::outerr(actions.filename, pos.line)
+            << detail::utf8(formatted_message) << std::endl;
+        ++actions.error_count;
     }
 
     void error_action::operator()(iterator first, iterator /*last*/) const
     {
-        position const pos = first.get_position();
-        detail::outerr(pos.file,pos.line)
+        file_position const pos = first.get_position();
+        detail::outerr(actions.filename, pos.line)
             << "Syntax Error near column " << pos.column << ".\n";
-        ++error_count;
+        ++actions.error_count;
     }
 
-    void tagged_action::operator()(std::string const& str) const
+    void block_action(quickbook::actions& actions, value block)
     {
-        if(!actions.output_pre(out)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, actions.out);
 
-        out << pre << str << post;
+        detail::markup markup = detail::get_markup(block.get_tag());
+
+        value_consumer values = block;
+        actions.out << markup.pre << values.consume().get_boostbook() << markup.post;
+        values.finish();
     }
 
-    void phrase_action::operator()() const
+    void block_empty_action(quickbook::actions& actions, value block)
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, actions.out);
 
-        std::string str;
-        phrase.swap(str);
-        out << pre << str << post;
+        detail::markup markup = detail::get_markup(block.get_tag());
+        actions.out << markup.pre;
+    }
+
+    void phrase_action(quickbook::actions& actions, value phrase)
+    {
+        if (actions.suppress) return;
+        write_anchors(actions, actions.phrase);
+
+        detail::markup markup = detail::get_markup(phrase.get_tag());
+
+        value_consumer values = phrase;
+        actions.phrase << markup.pre << values.consume().get_boostbook() << markup.post;
+        values.finish();
     }
 
-    void implicit_paragraph_action::operator()() const
+    void raw_phrase_action(quickbook::actions& actions, value phrase)
+    {
+        if (actions.suppress) return;
+        write_anchors(actions, actions.phrase);
+
+        detail::markup markup = detail::get_markup(phrase.get_tag());
+        actions.phrase << markup.pre << phrase.get_quickbook() << markup.post;
+    }
+
+    void paragraph_action::operator()() const
     {
         if(actions.suppress) return;
     
         std::string str;
-        phrase.swap(str);
-
-        // TODO: Use spirit to do this?
+        actions.phrase.swap(str);
 
         std::string::const_iterator
             pos = str.begin(),
             end = str.end();
 
-        while(pos != end && (
-            *pos == ' ' || *pos == '\t' || *pos == '\n' || *pos == '\r'))
-        {
-            ++pos;
-        }
+        while(pos != end && cl::space_p.test(*pos)) ++pos;
 
         if(pos != end) {
-            out << pre << str;
-            // TODO: Is this right place?
-            actions.output_pre(out);
-            out << post;
+            detail::markup markup = detail::get_markup(block_tags::paragraph);
+            actions.out << markup.pre << str;
+            write_anchors(actions, actions.out);
+            actions.out << markup.post;
+        }
+    }
+    
+    namespace {
+        void write_bridgehead(collector& out, int level,
+            std::string const& str, std::string const& id, std::string const& linkend)
+        {
+            out << "<bridgehead renderas=\"sect" << level << "\"";
+            if(!id.empty()) out << " id=\"" << id << "\"";
+            out << ">";
+            if(!linkend.empty()) out << "<link linkend=\"" << linkend << "\">";
+            out << str;
+            if(!linkend.empty()) out << "</link>";
+            out << "</bridgehead>";
         }
     }
 
-    void header_action::operator()(iterator first, iterator last) const
+    void header_action(quickbook::actions& actions, value heading_list)
     {
         if(actions.suppress) return;
 
-        std::string str;
-        phrase.swap(str);
+        value_consumer values = heading_list;
+
+        bool generic = heading_list.get_tag() == block_tags::generic_heading;
+        value element_id = values.optional_consume(general_tags::element_id);
+        value content = values.consume();
+        values.finish();
+
+        int level;
+
+        if (generic)
+        {
+            level = actions.section_level + 2;
+                                            // section_level is zero-based. We need to use a
+                                            // one-based heading which is one greater
+                                            // than the current. Thus: section_level + 2.
+            if (level > 6 )                 // The max is h6, clip it if it goes
+                level =  6;                 // further than that
+        }
+        else
+        {
+            level = heading_list.get_tag() - block_tags::heading1 + 1;
+        }
 
         std::string anchor;
+        std::string linkend;
 
-        if (qbk_version_n < 103) // version 1.2 and below
+        if (!generic && qbk_version_n < 103) // version 1.2 and below
         {
-            anchor = section_id + '.' +
-                detail::make_identifier(str.begin(), str.end());
+            anchor = actions.section_id + '.' +
+                detail::make_identifier(content.get_boostbook());
         }
         else
         {
             std::string id =
-                !element_id.empty() ? element_id :
-                qbk_version_n >= 106 ? detail::make_identifier(first, last) :
-                detail::make_identifier(str.begin(), str.end());
+                !element_id.empty() ?
+                    element_id.get_quickbook() :
+                    detail::make_identifier(
+                        qbk_version_n >= 106 ?
+                            content.get_quickbook() :
+                            content.get_boostbook()
+                    );
 
-            anchor =
-                fully_qualified_id(library_id, qualified_section_id, id);
+            linkend = anchor =
+                fully_qualified_id(actions.doc_id, actions.qualified_section_id, id);
         }
 
-        actions.output_pre(out);
-        actions.anchors.swap(actions.saved_anchors);
         actions.anchors.push_back(anchor);
-        actions.output_pre(out);
+        write_anchors(actions, actions.out);
         
-        if (qbk_version_n < 103)
-        {        
-            out << pre << str << post
-                ;
-        }
-        else // version 1.3 and above
-        {
-            out << pre
-                << "<link linkend=\"" << anchor << "\">"
-                << str
-                << "</link>"
-                << post
-                ;
-        }
+        write_bridgehead(actions.out, level,
+            content.get_boostbook(), anchor + "-heading", linkend);
     }
 
-    void generic_header_action::operator()(iterator first, iterator last) const
+    void simple_phrase_action::operator()(char mark) const
     {
-        if(actions.suppress) return;
-
-        int level_ = section_level + 2;     // section_level is zero-based. We need to use a
-                                            // one-based heading which is one greater
-                                            // than the current. Thus: section_level + 2.
-        if (level_ > 6)                     // The max is h6, clip it if it goes
-            level_ = 6;                     // further than that
-        std::string str;
-        phrase.swap(str);
-
-        std::string id =
-            !element_id.empty() ? element_id :
-            qbk_version_n >= 106 ? detail::make_identifier(first, last) :
-            detail::make_identifier(str.begin(), str.end());
-
-        std::string anchor =
-            fully_qualified_id(library_id, qualified_section_id, id);
-
-        actions.output_pre(out);
-        actions.anchors.swap(actions.saved_anchors);
-        actions.anchors.push_back(anchor);
-        actions.output_pre(out);
+        if (actions.suppress) return;
+        write_anchors(actions, out);
 
-        out
-            << "<bridgehead renderas=\"sect" << level_ << "\">"
-            << "<link linkend=\"" << anchor << "\">"
-            << str
-            << "</link>"
-            << "</bridgehead>"
-            ;
-    }
+        int tag =
+            mark == '*' ? phrase_tags::bold :
+            mark == '/' ? phrase_tags::italic :
+            mark == '_' ? phrase_tags::underline :
+            mark == '=' ? phrase_tags::teletype :
+            0;
+        
+        assert(tag != 0);
+        detail::markup markup = detail::get_markup(tag);
 
-    void simple_phrase_action::operator()(iterator first, iterator last) const
-    {
-        if(!actions.output_pre(out)) return;
+        value_consumer values = actions.values.release();
+        value content = values.consume();
+        values.finish();
 
-        out << pre;
-        std::string str(first, last);
-        if (std::string const* ptr = find(macro, str.c_str()))
+        out << markup.pre;
+        if (std::string const* ptr = find(macro, content.get_quickbook().c_str()))
         {
             out << *ptr;
         }
         else
         {
-            while (first != last)
-                detail::print_char(*first++, out.get());
+            out << content.get_boostbook();
         }
-        out << post;
+        out << markup.post;
     }
 
-    void cond_phrase_action_pre::operator()(iterator first, iterator last) const
+    bool cond_phrase_push::start()
     {
-        std::string str(first, last);
-        condition = find(macro, str.c_str());
-    }
+        saved_suppress = actions.suppress;
+    
+        value_consumer values = actions.values.release();
+        bool condition = find(actions.macro,
+            values.consume().get_quickbook().c_str());
+    
+        actions.suppress = actions.suppress || !condition;
 
-    cond_phrase_push::cond_phrase_push(quickbook::actions& actions)
-        : actions(actions)
-        , saved_suppress(actions.suppress)
-    {
-        actions.suppress = actions.suppress || !actions.condition;
+        return true;
     }
     
-    cond_phrase_push::~cond_phrase_push()
+    void cond_phrase_push::cleanup()
     {
         actions.suppress = saved_suppress;
     }
 
-    void list_action::operator()(iterator first, iterator last) const
-    {
-        if(actions.suppress) return;
-    
-        BOOST_ASSERT(!list_marks.empty()); // there must be at least one item in the stack
-        out << list_buffer.str();
-        list_buffer.clear();
-
-        while (!list_marks.empty())
+    namespace {
+        int indent_length(std::string const& indent)
         {
-            char mark = list_marks.top().first;
-            list_marks.pop();
-            out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
-            if (list_marks.size() >= 1)
-                out << "</listitem>";
+            int length = 0;
+            for(std::string::const_iterator
+                first = indent.begin(), end = indent.end(); first != end; ++first)
+            {
+                switch(*first) {
+                    case ' ': ++length; break;
+                    // hardcoded tab to 4 for now
+                    case '\t': length = ((length + 4) / 4) * 4; break;
+                    default: BOOST_ASSERT(false);
+                }
+            }
+            
+            return length;
         }
-
-        list_indent = -1; // reset
     }
 
-    void list_format_action::operator()(iterator first, iterator last) const
+    void list_action(quickbook::actions& actions, value list)
     {
-        if(!actions.output_pre(out)) return;
-    
-        int new_indent = 0;
-        while (first != last && (*first == ' ' || *first == '\t'))
-        {
-            char mark = *first++;
-            if (mark == ' ')
-            {
-                ++new_indent;
-            }
-            else // must be a tab
-            {
-                BOOST_ASSERT(mark == '\t');
-                // hardcoded tab to 4 for now
-                new_indent = ((new_indent + 4) / 4) * 4;
-            }
-        }
+        if (actions.suppress) return;
+        write_anchors(actions, actions.out);
 
-        char mark = *first;
-        BOOST_ASSERT(mark == '#' || mark == '*'); // expecting a mark
+        typedef std::pair<char, int> mark_type;
+        std::stack<mark_type> list_marks;
+        int list_indent = -1;
 
-        if (list_indent == -1) // the very start
+        BOOST_FOREACH(value_consumer values, list)
         {
-            BOOST_ASSERT(new_indent == 0);
-        }
+            int new_indent = indent_length(
+                    values.consume(general_tags::list_indent).get_quickbook());
+            value mark_value = values.consume(general_tags::list_mark);
+            std::string content = values.consume().get_boostbook();
+            values.finish();
 
-        if (new_indent > list_indent)
-        {
-            list_indent = new_indent;
-            list_marks.push(mark_type(mark, list_indent));
-            if (list_marks.size() > 1)
+            char mark = mark_value.get_quickbook()[0];
+            assert(mark == '*' || mark == '#');
+
+            if(list_indent == -1) {
+                assert(new_indent == 0);
+            }
+
+            if(new_indent > list_indent)
             {
-                // Make this new list a child of the previous list.
-                // The previous listelem has already ended so we erase
-                // "</listitem>" to accomodate this sub-list. We'll close
-                // the listelem later.
+                list_indent = new_indent;
+                list_marks.push(mark_type(mark, list_indent));
 
-                std::string str;
-                out.swap(str);
-                std::string::size_type pos = str.rfind("</listitem>");
-                BOOST_ASSERT(pos <= str.size());
-                str.erase(str.begin()+pos, str.end());
-                out << str;
+                actions.out << ((mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
             }
-            out << std::string((mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
-        }
+            else if (new_indent < list_indent)
+            {
+                BOOST_ASSERT(!list_marks.empty());
+                list_indent = new_indent;
 
-        else if (new_indent < list_indent)
-        {
-            BOOST_ASSERT(!list_marks.empty());
-            list_indent = new_indent;
+                while (!list_marks.empty() && (list_indent < list_marks.top().second))
+                {
+                    char mark = list_marks.top().first;
+                    list_marks.pop();
+                    actions.out << "</simpara></listitem>";
+                    actions.out << ((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
+                }
+                actions.out << "</simpara></listitem>";
+            }
+            else
+            {
+                actions.out << "</simpara></listitem>";
+            }
 
-            while (!list_marks.empty() && (list_indent < list_marks.top().second))
+            if (mark != list_marks.top().first) // new_indent == list_indent
             {
-                char mark = list_marks.top().first;
-                list_marks.pop();
-                out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
-                if (list_marks.size() >= 1)
-                    out << "</listitem>";
+                file_position const pos = mark_value.get_position();
+                detail::outerr(actions.filename, pos.line)
+                    << "Illegal change of list style near column " << pos.column << ".\n";
+                detail::outwarn(actions.filename, pos.line)
+                    << "Ignoring change of list style" << std::endl;
+                ++actions.error_count;
             }
+            
+            actions.out << "<listitem><simpara>";
+            actions.out << content;
         }
 
-        if (mark != list_marks.top().first) // new_indent == list_indent
+        assert(!list_marks.empty());
+        while (!list_marks.empty())
         {
-            position const pos = first.get_position();
-            detail::outerr(pos.file,pos.line)
-                << "Illegal change of list style near column " << pos.column << ".\n";
-            detail::outwarn(pos.file,pos.line)
-                << "Ignoring change of list style" << std::endl;
-            ++error_count;
+            char mark = list_marks.top().first;
+            list_marks.pop();
+            actions.out << "</simpara></listitem>";
+            actions.out << ((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
         }
     }
 
+    void explicit_list_action(quickbook::actions& actions, value list)
+    {
+        if (actions.suppress) return;
+        write_anchors(actions, actions.out);
+
+        detail::markup markup = detail::get_markup(list.get_tag());
+
+        actions.out << markup.pre;
+
+        BOOST_FOREACH(value item, list)
+        {
+            actions.out << "<listitem>";
+            actions.out << item.get_boostbook();
+            actions.out << "</listitem>";
+        }
+
+        actions.out << markup.post;
+    }
+
     // TODO: No need to check suppress since this is only used in the syntax
     //       highlighter. I should moved this or something.
     void span::operator()(iterator first, iterator last) const
@@ -331,11 +533,11 @@
 
     void unexpected_char::operator()(iterator first, iterator last) const
     {
-        position const pos = first.get_position();
+        file_position const pos = first.get_position();
 
-        detail::outwarn(pos.file, pos.line)
+        detail::outwarn(actions.filename, pos.line)
             << "in column:" << pos.column
-            << ", unexpected character: " << std::string(first, last)
+            << ", unexpected character: " << detail::utf8(first, last)
             << "\n";
 
         // print out an unexpected character
@@ -345,15 +547,19 @@
         out << "</phrase>";
     }
 
-    void anchor_action::operator()(iterator first, iterator last) const
+    void anchor_action(quickbook::actions& actions, value anchor)
     {
-        if(!actions.suppress)
-            actions.anchors.push_back(std::string(first, last));
+        if(actions.suppress) return;
+        
+        value_consumer values = anchor;
+        actions.anchors.push_back(values.consume().get_quickbook());
+        values.finish();
     }
 
     void do_macro_action::operator()(std::string const& str) const
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, phrase);
 
         if (str == quickbook_get_date)
         {
@@ -384,21 +590,27 @@
             detail::print_space(*first++, out.get());
     }
 
-    void pre_escape_back::operator()(iterator first, iterator last) const
+    void pre_escape_back::operator()(iterator, iterator) const
     {
         escape_actions.phrase.push(); // save the stream
     }
 
-    void post_escape_back::operator()(iterator first, iterator last) const
+    void post_escape_back::operator()(iterator, iterator) const
     {
-        escape_actions.output_pre(escape_actions.phrase);
+        write_anchors(escape_actions, escape_actions.phrase);
         out << escape_actions.phrase.str();
         escape_actions.phrase.pop(); // restore the stream
     }
 
+    void source_mode_action(quickbook::actions& actions, value source_mode)
+    {
+        actions.source_mode = source_mode_tags::name(source_mode.get_tag());
+    }
+
     void code_action::operator()(iterator first, iterator last) const
     {
-        if(!actions.output_pre(out)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, out);
 
         // preprocess the code section to remove the initial indentation
         std::string program(first, last);
@@ -406,9 +618,8 @@
         if (program.size() == 0)
             return; // Nothing left to do here. The program is empty.
 
-        iterator first_(program.begin(), program.end());
-        iterator last_(program.end(), program.end());
-        first_.set_position(first.get_position());
+        iterator first_(program.begin(), first.get_position());
+        iterator last_(program.end());
 
         // TODO: Shouldn't phrase be empty here? Why would it be output
         // after the code block?
@@ -431,7 +642,8 @@
 
     void inline_code_action::operator()(iterator first, iterator last) const
     {
-        if(!actions.output_pre(out)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, out);
 
         std::string save;
         out.swap(save);
@@ -448,31 +660,40 @@
 
     void raw_char_action::operator()(char ch) const
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, phrase);
+
         phrase << ch;
     }
 
     void raw_char_action::operator()(iterator first, iterator /*last*/) const
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, phrase);
+
         phrase << *first;
     }
 
     void plain_char_action::operator()(char ch) const
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, phrase);
+
         detail::print_char(ch, phrase.get());
     }
 
     void plain_char_action::operator()(iterator first, iterator /*last*/) const
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, phrase);
+
         detail::print_char(*first, phrase.get());
     }
 
     void escape_unicode_action::operator()(iterator first, iterator last) const
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, phrase);
 
         while(first != last && *first == '0') ++first;
 
@@ -491,34 +712,86 @@
         }
     }
 
-    void attribute_action::operator()(iterator first, iterator last) const
+    void image_action(quickbook::actions& actions, value image)
     {
-        position const pos = first.get_position();
+        if (actions.suppress) return;
+        write_anchors(actions, actions.phrase);
+
+        typedef std::map<std::string, value> attribute_map;
+        attribute_map attributes;
 
-        if (!attributes.insert(
-                attribute_map::value_type(attribute_name, std::string(first, last))
-            ).second)
+        value_consumer values = image;
+        attributes["fileref"] = values.consume();
+
+        BOOST_FOREACH(value pair_, values)
         {
-            detail::outwarn(pos.file,pos.line)
-                << "Repeated attribute: " << attribute_name << ".\n";
+            value_consumer pair = pair_;
+            value name = pair.consume();
+            value value = pair.consume();
+            pair.finish();
+            if(!attributes.insert(std::make_pair(name.get_quickbook(), value)).second)
+            {
+                detail::outwarn(actions.filename, name.get_position().line)
+                    << "Duplicate image attribute: "
+                    << detail::utf8(name.get_quickbook())
+                    << std::endl;
+            }
         }
-    }
-
-    void image_action::operator()(iterator, iterator) const
-    {
-        if(!actions.output_pre(phrase)) return;
+        
+        values.finish();
 
-        fs::path const img_path(image_fileref);
+        // Find the file basename and extension.
+        //
+        // Not using Boost.Filesystem because I want to stay in UTF-8.
+        // Need to think about uri encoding.
         
-        attribute_map::iterator it = attributes.find("alt");
-        std::string alt_text = it != attributes.end() ?
-            it->second :
-            img_path.stem().generic_string();
-        attributes.erase("alt");
+        std::string fileref = attributes["fileref"].get_quickbook();
+
+        // Check for windows paths, then convert.
+        // A bit crude, but there you go.
+
+        if(fileref.find('\\') != std::string::npos)
+        {
+            detail::outwarn(actions.filename, attributes["fileref"].get_position().line)
+                << "Image path isn't portable: '"
+                << detail::utf8(fileref)
+                << "'"
+                << std::endl;
+        }
+
+        boost::replace(fileref, '\\', '/');
 
-        attributes.insert(attribute_map::value_type("fileref", image_fileref));
+        // Find the file basename and extension.
+        //
+        // Not using Boost.Filesystem because I want to stay in UTF-8.
+        // Need to think about uri encoding.
+
+        std::string::size_type pos;
+        std::string stem,extension;
+
+        pos = fileref.rfind('/');
+        stem = pos == std::string::npos ?
+            fileref :
+            fileref.substr(pos + 1);
 
-        if(img_path.extension() == ".svg")
+        pos = stem.rfind('.');
+        if (pos != std::string::npos)
+        {
+            extension = stem.substr(pos + 1);
+            stem = stem.substr(0, pos);
+        }
+
+        // Extract the alt tag, to use as a text description.
+        // Or if there isn't one, use the stem of the file name.
+        // TODO: IMO if there isn't an alt tag, then the description should
+        //       be empty or missing.
+
+        attribute_map::iterator alt_pos = attributes.find("alt");
+        std::string alt_text = alt_pos != attributes.end() ?
+            alt_pos->second.get_quickbook() : stem;
+        attributes.erase("alt");
+
+        if(extension == ".svg")
         {
            //
            // SVG's need special handling:
@@ -531,15 +804,18 @@
            //    a tiny box with scrollbars (Firefox), or else cropped to
            //    fit in a tiny box (IE7).
            //
-           attributes.insert(attribute_map::value_type("format", "SVG"));
+
+           attributes.insert(attribute_map::value_type("format", qbk_value("SVG")));
+
            //
            // Image paths are relative to the html subdirectory:
            //
-           fs::path img;
-           if(img_path.root_path().empty())
-              img = "html" / img_path;  // relative path
-           else
-              img = img_path;   // absolute path
+           // TODO: This seems wrong to me.
+           //
+           fs::path img = detail::generic_to_path(fileref);
+           if(img.root_path().empty())
+              img = "html" / img;  // relative path
+
            //
            // Now load the SVG file:
            //
@@ -565,8 +841,10 @@
            b = svg_text.find('\"', a + 1);
            if(a != std::string::npos)
            {
-              attributes.insert(attribute_map::value_type("contentwidth",
-                std::string(svg_text.begin() + a + 1, svg_text.begin() + b)));
+              attributes.insert(std::make_pair(
+                "contentwidth", qbk_value(std::string(
+                    svg_text.begin() + a + 1, svg_text.begin() + b))
+                ));
            }
            a = svg_text.find("height");
            a = svg_text.find('=', a);
@@ -574,141 +852,166 @@
            b = svg_text.find('\"', a + 1);
            if(a != std::string::npos)
            {
-              attributes.insert(attribute_map::value_type("contentdepth",
-                std::string(svg_text.begin() + a + 1, svg_text.begin() + b)));
+              attributes.insert(std::make_pair(
+                "contentdepth", qbk_value(std::string(
+                    svg_text.begin() + a + 1, svg_text.begin() + b))
+                ));
            }
         }
 
-        phrase << "<inlinemediaobject>";
+        actions.phrase << "<inlinemediaobject>";
 
-        phrase << "<imageobject><imagedata";
+        actions.phrase << "<imageobject><imagedata";
         
-        for(attribute_map::const_iterator
-            attr_first = attributes.begin(), attr_last  = attributes.end();
-            attr_first != attr_last; ++attr_first)
+        BOOST_FOREACH(attribute_map::value_type const& attr, attributes)
         {
-            phrase << " " << attr_first->first << "=\"";
+            actions.phrase << " " << attr.first << "=\"";
 
+            std::string value = attr.second.get_quickbook();
             for(std::string::const_iterator
-                first = attr_first->second.begin(),
-                last  = attr_first->second.end();
+                first = value.begin(), last  = value.end();
                 first != last; ++first)
             {
                 if (*first == '\\' && ++first == last) break;
-                detail::print_char(*first, phrase.get());
+                detail::print_char(*first, actions.phrase.get());
             }
 
-            phrase << "\"";
+            actions.phrase << "\"";
         }
 
-        phrase << "></imagedata></imageobject>";
+        actions.phrase << "></imagedata></imageobject>";
 
-        // Also add a textobject -- use the basename of the image file.
-        // This will mean we get "alt" attributes of the HTML img.
-        phrase << "<textobject><phrase>";
-        detail::print_string(alt_text, phrase.get());
-        phrase << "</phrase></textobject>";
+        // Add a textobject containing the alt tag from earlier.
+        // This will be used for the alt tag in html.
+        actions.phrase << "<textobject><phrase>";
+        detail::print_string(alt_text, actions.phrase.get());
+        actions.phrase << "</phrase></textobject>";
 
-        phrase << "</inlinemediaobject>";
+        actions.phrase << "</inlinemediaobject>";
     }
 
-    void macro_identifier_action::operator()(iterator first, iterator last) const
+    void macro_definition_action(quickbook::actions& actions, quickbook::value macro_definition)
     {
         if(actions.suppress) return;
-        actions.macro_id.assign(first, last);
-        actions.phrase.push(); // save the phrase
-    }
 
-    void macro_definition_action::operator()(iterator first, iterator last) const
-    {
-        if(actions.suppress) return;
+        value_consumer values = macro_definition;
+        std::string macro_id = values.consume().get_quickbook();
+        std::string phrase = values.consume().get_boostbook();
+        values.finish();
+
         actions.copy_macros_for_write();
         actions.macro.add(
-            actions.macro_id.begin()
-          , actions.macro_id.end()
-          , actions.phrase.str());
-        actions.phrase.pop(); // restore the phrase
+            macro_id.begin()
+          , macro_id.end()
+          , phrase);
     }
 
-    void template_body_action::operator()(iterator first, iterator last) const
+    void template_body_action(quickbook::actions& actions, quickbook::value template_definition)
     {
         if(actions.suppress) return;
+
+        value_consumer values = template_definition;
+        std::string identifier = values.consume().get_quickbook();
+
+        std::vector<std::string> template_values;
+        BOOST_FOREACH(value const& p, values.consume()) {
+            template_values.push_back(p.get_quickbook());
+        }
+
+        BOOST_ASSERT(values.check(template_tags::block) || values.check(template_tags::phrase));
+        value body = values.consume();
+        BOOST_ASSERT(!values.check());
+    
         if (!actions.templates.add(
-            template_symbol(actions.template_identifier, actions.template_info,
-                std::string(first, last), first.get_position(),
-                actions.template_block, &actions.templates.top_scope())))
-        {
-            position const pos = first.get_position();
-            detail::outerr(pos.file,pos.line)
-                << "Template Redefinition: " << actions.template_identifier << std::endl;
+            template_symbol(
+                identifier,
+                template_values,
+                body,
+                actions.filename,
+                &actions.templates.top_scope())))
+        {
+            file_position const pos = body.get_position();
+            detail::outerr(actions.filename, pos.line)
+                << "Template Redefinition: " << detail::utf8(identifier) << std::endl;
             ++actions.error_count;
         }
-
-        actions.template_identifier.clear();
-        actions.template_info.clear();
     }
 
     namespace
     {
-        iterator find_bracket_end(iterator begin, iterator const& end)
+        iterator find_first_seperator(iterator begin, iterator end)
         {
-            unsigned int depth = 1;
-
-            while(depth > 0) {
-                char const* search_chars = "[]\\";
-                begin = std::find_first_of(begin, end, search_chars, search_chars + 3);
-                if(begin == end) return begin;
-
-                if(*begin == '\\')
-                {
-                    if(++begin == end) return begin;
-                    ++begin;
-                }
-                else
+            if(qbk_version_n < 105) {
+                for(;begin != end; ++begin)
                 {
-                    depth += (*begin == '[') ? 1 : -1;
-                    ++begin;
+                    switch(*begin)
+                    {
+                    case ' ':
+                    case '\t':
+                    case '\n':
+                    case '\r':
+                        return begin;
+                    default:
+                        break;
+                    }
                 }
             }
-
-            return begin;
-        }
-
-        iterator find_first_seperator(iterator const& begin, iterator const& end)
-        {
-            if(qbk_version_n < 105) {
-                char const* whitespace = " \t\r\n";
-                return std::find_first_of(begin, end, whitespace, whitespace + 4);
-            }
             else {
-                iterator pos = begin;
+                unsigned int depth = 0;
 
-                while(true)
+                for(;begin != end; ++begin)
                 {
-                    char const* search_chars = " \t\r\n\\[";
-                    pos = std::find_first_of(pos, end, search_chars, search_chars + 6);
-                    if(pos == end) return pos;
-
-                    switch(*pos)
+                    switch(*begin)
                     {
                     case '[':
-                        pos = find_bracket_end(++pos, end);
+                        ++depth;
                         break;
                     case '\\':
-                        if(++pos == end) return pos;
-                        ++pos;
+                        if(++begin == end) return begin;
                         break;
+                    case ']':
+                        if (depth > 0) --depth;
+                        break;
+                    case ' ':
+                    case '\t':
+                    case '\n':
+                    case '\r':
+                        if (depth == 0) return begin;
                     default:
-                        return pos;
+                        break;
                     }
                 }
             }
+            
+            return begin;
+        }
+        
+        std::pair<iterator, iterator> find_seperator(iterator begin, iterator end)
+        {
+            iterator first = begin = find_first_seperator(begin, end);
+
+            for(;begin != end; ++begin)
+            {
+                switch(*begin)
+                {
+                case ' ':
+                case '\t':
+                case '\n':
+                case '\r':
+                    break;
+                default:
+                    return std::make_pair(first, begin);
+                }
+            }
+            
+            return std::make_pair(first, begin);
         }
     
         bool break_arguments(
             std::vector<template_body>& args
           , std::vector<std::string> const& params
-          , position const& pos
+          , fs::path const& filename
+          , file_position const& pos
         )
         {
             // Quickbook 1.4-: If there aren't enough parameters seperated by
@@ -729,28 +1032,25 @@
                     // arguments, or if there are no more spaces left.
 
                     template_body& body = args.back();
-                    iterator begin(body.content.begin(), body.content.end(),
-                        position(body.position.file.c_str(), body.position.line, body.position.column));
-                    iterator end(body.content.end(), body.content.end());
+                    iterator begin = body.content.get_quickbook_range().begin();
+                    iterator end = body.content.get_quickbook_range().end();
                     
-                    iterator l_pos = find_first_seperator(begin, end);
-                    if (l_pos == end)
-                        break;
-                    char const* whitespace = " \t\r\n";
-                    char const* whitespace_end = whitespace + 4;
-                    iterator r_pos = l_pos;
-                    while(r_pos != end && std::find(whitespace, whitespace_end, *r_pos) != whitespace_end) ++r_pos;
-                    if (r_pos == end)
-                        break;
-                    template_body second(std::string(r_pos, end), r_pos.get_position(), false);
-                    body.content = std::string(begin, l_pos);
+                    std::pair<iterator, iterator> pos =
+                        find_seperator(begin, end);
+                    if (pos.second == end) break;
+                    template_body second(
+                        qbk_value(pos.second, end, template_tags::phrase),
+                        body.filename);
+    
+                    body.content = qbk_value(begin, pos.first,
+                        body.content.get_tag());
                     args.push_back(second);
                 }
             }
 
             if (args.size() != params.size())
             {
-                detail::outerr(pos.file, pos.line)
+                detail::outerr(filename, pos.line)
                     << "Invalid number of arguments passed. Expecting: "
                     << params.size()
                     << " argument(s), got: "
@@ -767,7 +1067,7 @@
             std::vector<template_body>& args
           , std::vector<std::string> const& params
           , template_scope const& scope
-          , position const& pos
+          , file_position const& pos
           , quickbook::actions& actions
         )
         {
@@ -781,9 +1081,9 @@
             {
                 if (!actions.templates.add(
                         template_symbol(*tpl, empty_params, arg->content,
-                            arg->position, arg->is_block, &scope)))
+                            arg->filename, &scope)))
                 {
-                    detail::outerr(pos.file,pos.line)
+                    detail::outerr(actions.filename, pos.line)
                         << "Duplicate Symbol Found" << std::endl;
                     ++actions.error_count;
                     return std::make_pair(false, tpl);
@@ -810,17 +1110,18 @@
             {
                 //  escape the body of the template
                 //  we just copy out the literal body
-                (body.is_block ? actions.out : actions.phrase) << body.content;
+                (body.is_block() ? actions.out : actions.phrase) << body.content.get_quickbook();
                 return true;
             }
             else
             {
-                if (!body.is_block)
+                if (!body.is_block())
                 {
                     //  do a phrase level parse
-                    iterator first(body.content.begin(), body.content.end(),
-                        position(body.position.file.c_str(), body.position.line, body.position.column));
-                    iterator last(body.content.end(), body.content.end());
+                    actions.filename = body.filename;
+                    iterator first = body.content.get_quickbook_range().begin();
+                    iterator last = body.content.get_quickbook_range().end();
+                    
                     return cl::parse(first, last, actions.grammar().simple_phrase).full;
                 }
                 else
@@ -829,10 +1130,11 @@
                     //  ensure that we have enough trailing newlines to eliminate
                     //  the need to check for end of file in the grammar.
                     
-                    std::string content = body.content + "\n\n";
-                    iterator first(content.begin(), content.end(),
-                        position(body.position.file.c_str(), body.position.line, body.position.column));
-                    iterator last(content.end(), content.end());
+                    actions.filename = body.filename;
+                    std::string content = body.content.get_quickbook() + "\n\n";
+                    iterator first(content.begin(), body.content.get_position());
+                    iterator last(content.end());
+
                     return cl::parse(first, last, actions.grammar().block).full;
                 }
             }
@@ -844,33 +1146,32 @@
         int callout_id = 0;
     }
 
-    void template_arg_action::operator()(iterator first, iterator last) const
+    void do_template_action(quickbook::actions& actions, value template_list,
+            file_position pos)
     {
         if(actions.suppress) return;
 
-        actions.template_args.push_back(
-            template_body(
-                std::string(first, last),
-                first.get_position(),
-                actions.template_block));
-    }
+        // Get the arguments
+        value_consumer values = template_list;
 
-    void do_template_action::operator()(iterator first, iterator) const
-    {
-        if(actions.suppress) return;
+        bool template_escape = values.check(template_tags::escape);
+        if(template_escape) values.consume();
 
-        // Get the arguments and clear values stored in action.
+        std::string identifier = values.consume(template_tags::identifier).get_quickbook();
 
         std::vector<template_body> args;
-        std::string identifier;
-        std::swap(args, actions.template_args);
-        std::swap(identifier, actions.template_identifier);
-        position const pos = first.get_position();
+
+        BOOST_FOREACH(value arg, values)
+        {
+            args.push_back(template_body(arg, actions.filename));
+        }
+        
+        values.finish();
 
         ++actions.template_depth;
         if (actions.template_depth > actions.max_template_depth)
         {
-            detail::outerr(pos.file,pos.line)
+            detail::outerr(actions.filename, pos.line)
                 << "Infinite loop detected" << std::endl;
             --actions.template_depth;
             ++actions.error_count;
@@ -906,11 +1207,11 @@
             ///////////////////////////////////
             // Initialise the arguments
             
-            if (!symbol->callout)
+            if (!symbol->callouts.check())
             {
                 // Break the arguments for a template
             
-                if (!break_arguments(args, symbol->params, pos))
+                if (!break_arguments(args, symbol->params, actions.filename, pos))
                 {
                     actions.pop(); // restore the actions' states
                     --actions.template_depth;
@@ -922,7 +1223,7 @@
             {
                 if (!args.empty())
                 {
-                    detail::outerr(pos.file, pos.line)
+                    detail::outerr(actions.filename, pos.line)
                         << "Arguments for code snippet."
                         <<std::endl;
                     ++actions.error_count;
@@ -943,7 +1244,9 @@
                     code += "linkends=\"" + callout_id + "\" />";
                     code += "'''";
 
-                    args.push_back(template_body(code, first.get_position(), false));
+                    args.push_back(template_body(
+                        qbk_value(code, pos, template_tags::phrase),
+                        actions.filename));
                 }
             }
 
@@ -965,16 +1268,15 @@
             ///////////////////////////////////
             // parse the template body:
 
-            if (!parse_template(symbol->body, actions.template_escape, actions))
+            if (!parse_template(symbol->body, template_escape, actions))
             {
-                position const pos = first.get_position();
-                detail::outerr(pos.file,pos.line)
+                detail::outerr(actions.filename, pos.line)
                     << "Expanding "
-                    << (symbol->body.is_block ? "block" : "phrase")
-                    << " template: " << symbol->identifier << std::endl
+                    << (symbol->body.is_block() ? "block" : "phrase")
+                    << " template: " << detail::utf8(symbol->identifier) << std::endl
                     << std::endl
                     << "------------------begin------------------" << std::endl
-                    << symbol->body.content
+                    << detail::utf8(symbol->body.content.get_quickbook())
                     << "------------------end--------------------" << std::endl
                     << std::endl;
                 actions.pop(); // restore the actions' states
@@ -985,9 +1287,8 @@
 
             if (actions.section_level != actions.min_section_level)
             {
-                position const pos = first.get_position();
-                detail::outerr(pos.file,pos.line)
-                    << "Mismatched sections in template " << identifier << std::endl;
+                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;
@@ -999,27 +1300,28 @@
         actions.phrase.swap(phrase);
         actions.pop(); // restore the actions' states
 
-        if(symbol->callout && symbol->callouts.size() > 0)
+        if(!symbol->callouts.empty())
         {
             BOOST_ASSERT(phrase.empty());
             block += "<calloutlist>";
-            BOOST_FOREACH(template_body const& c, symbol->callouts)
+            BOOST_FOREACH(value c, symbol->callouts)
             {
                 std::string callout_id = actions.doc_id +
                     boost::lexical_cast<std::string>(detail::callout_id++);
 
                 std::string callout_value;
                 actions.push();
-                bool r = parse_template(c, false, actions);
+                bool r = parse_template(
+                    template_body(c, symbol->body.filename), false, actions);
                 actions.out.swap(callout_value);
                 actions.pop();
 
                 if(!r)
                 {
-                    detail::outerr(c.position.file, c.position.line)
+                    detail::outerr(symbol->body.filename, c.get_position().line)
                         << "Expanding callout." << std::endl
                         << "------------------begin------------------" << std::endl
-                        << c.content
+                        << detail::utf8(c.get_quickbook())
                         << std::endl
                         << "------------------end--------------------" << std::endl
                         ;
@@ -1035,8 +1337,8 @@
             block += "</calloutlist>";
         }
 
-        if(symbol->body.is_block || !block.empty()) {
-            actions.inside_paragraph();
+        if(symbol->body.is_block() || !block.empty()) {
+            actions.paragraph(); // For paragraphs before the template call.
             actions.out << block;
             actions.phrase << phrase;
         }
@@ -1046,73 +1348,106 @@
         --actions.template_depth;
     }
 
-    void link_action::operator()(iterator first, iterator last) const
+    void link_action(quickbook::actions& actions, value link)
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, actions.phrase);
 
-        iterator save = first;
-        phrase << tag;
-        while (first != last)
-            detail::print_char(*first++, phrase.get());
-        phrase << "\">";
+        detail::markup markup = detail::get_markup(link.get_tag());
 
-        // Yes, it is safe to dereference last here. When we
-        // reach here, *last is certainly valid. We test if
-        // *last == ']'. In which case, the url is the text.
-        // Example: [@http://spirit.sourceforge.net/]
+        value_consumer values = link;
+        value dst = values.consume();
+        value content = values.consume();
+        values.finish();
+        
+        actions.phrase << markup.pre;
+        detail::print_string(dst.get_quickbook(), actions.phrase.get());
+        actions.phrase << "\">";
 
-        if (*last == ']')
-        {
-            first = save;
-            while (first != last)
-                detail::print_char(*first++, phrase.get());
-        }
+        if (content.empty())
+            detail::print_string(dst.get_quickbook(), actions.phrase.get());
+        else
+            actions.phrase << content.get_boostbook();
+
+        actions.phrase << markup.post;
     }
 
-    void variablelist_action::operator()(iterator, iterator) const
+    void variable_list_action(quickbook::actions& actions, value variable_list)
     {
         if(actions.suppress) return;
+        write_anchors(actions, actions.out);
+
+        value_consumer values = variable_list;
+        std::string title = values.consume(table_tags::title).get_quickbook();
 
         actions.out << "<variablelist>\n";
 
         actions.out << "<title>";
-        std::string::iterator first = actions.table_title.begin();
-        std::string::iterator last = actions.table_title.end();
-        while (first != last)
-            detail::print_char(*first++, actions.out.get());
+        detail::print_string(title, actions.out.get());
         actions.out << "</title>\n";
 
-        std::string str;
-        actions.phrase.swap(str);
-        actions.out << str;
+        BOOST_FOREACH(value_consumer entry, values) {
+            actions.out << "<varlistentry>";
+            
+            if(entry.check()) {
+                actions.out << "<term>";
+                actions.out << entry.consume().get_boostbook();
+                actions.out << "</term>";
+            }
+            
+            if(entry.check()) {
+                actions.out << "<listitem>";
+                BOOST_FOREACH(value phrase, entry) actions.out << phrase.get_boostbook();
+                actions.out << "</listitem>";
+            }
+
+            actions.out << "</varlistentry>\n";
+        }
 
         actions.out << "</variablelist>\n";
-        actions.table_span = 0;
-        actions.table_header.clear();
-        actions.table_title.clear();
+        
+        values.finish();
     }
 
-    void table_action::operator()(iterator, iterator) const
+    void table_action(quickbook::actions& actions, value table)
     {
         if(actions.suppress) return;
+        write_anchors(actions, actions.out);
+
+        value_consumer values = table;
+
+        std::string element_id;
+        if(values.check(general_tags::element_id))
+            element_id = values.consume().get_quickbook();
 
-        std::string::iterator first = actions.table_title.begin();
-        std::string::iterator last = actions.table_title.end();
-        bool has_title = first != last;
+        std::string title = values.consume(table_tags::title).get_quickbook();
+        bool has_title = !title.empty();
         
         std::string table_id;
         if(qbk_version_n >= 105) {
-            if(!actions.element_id.empty()) {
+            if(!element_id.empty()) {
                 table_id = fully_qualified_id(actions.doc_id,
-                    actions.qualified_section_id, actions.element_id);
+                    actions.qualified_section_id, element_id);
             }
             else if(has_title) {
                 table_id = fully_qualified_id(actions.doc_id,
                     actions.qualified_section_id,
-                    detail::make_identifier(first, last));
+                    detail::make_identifier(title));
             }
         }
 
+        // Emulating the old behaviour which used the width of the final
+        // row for span_count.
+        int row_count = 0;
+        int span_count = 0;
+
+        value_consumer lookahead = values;
+        BOOST_FOREACH(value row, lookahead) {
+            ++row_count;
+            span_count = boost::distance(row);
+        }
+        lookahead.finish();
+
         if (has_title)
         {
             actions.out << "<table frame=\"all\"";
@@ -1120,8 +1455,7 @@
                 actions.out << " id=\"" << table_id << "\"";
             actions.out << ">\n";
             actions.out << "<title>";
-            while (first != last)
-                detail::print_char(*first++, actions.out.get());
+            detail::print_string(title, actions.out.get());
             actions.out << "</title>";
         }
         else
@@ -1132,18 +1466,28 @@
             actions.out << ">\n";
         }
 
-        actions.out << "<tgroup cols=\"" << actions.table_span << "\">\n";
+        actions.out << "<tgroup cols=\"" << span_count << "\">\n";
 
-        if (!actions.table_header.empty())
+        if (row_count > 1)
         {
-            actions.out << "<thead>" << actions.table_header << "</thead>\n";
+            actions.out << "<thead>" << "<row>";
+            BOOST_FOREACH(value cell, values.consume()) {
+                actions.out << "<entry>" << cell.get_boostbook() << "</entry>";
+            }
+            actions.out << "</row>\n" << "</thead>\n";
         }
 
         actions.out << "<tbody>\n";
 
-        std::string str;
-        actions.phrase.swap(str);
-        actions.out << str;
+        BOOST_FOREACH(value row, values) {
+            actions.out << "<row>";
+            BOOST_FOREACH(value cell, row) {
+                actions.out << "<entry>" << cell.get_boostbook() << "</entry>";
+            }
+            actions.out << "</row>\n";
+        }
+        
+        values.finish();
 
         actions.out << "</tbody>\n"
                      << "</tgroup>\n";
@@ -1156,206 +1500,284 @@
         {
             actions.out << "</informaltable>\n";
         }
-
-        actions.table_span = 0;
-        actions.table_header.clear();
-        actions.table_title.clear();
     }
 
-    void start_row_action::operator()(char) const
-    {
-        if (actions.suppress) return;
-
-        // the first row is the header
-        if (header.empty() && !phrase.str().empty())
-        {
-            phrase.swap(header);
-        }
-
-        phrase << start_row_;
-        span = 0;
-    }
-
-    void start_row_action::operator()(iterator f, iterator) const
-    {
-        (*this)(*f);
-    }
-
-    void col_action::operator()(std::string const& contents) const
-    {
-        if(actions.suppress) return;
-        phrase << start_cell_ << contents << end_cell_;
-        ++span;
-    }
-
-    void begin_section_action::operator()(iterator first, iterator last) const
+    void begin_section_action(quickbook::actions& actions, value begin_section_list)
     {    
         if(actions.suppress) return;
 
-        section_id = element_id.empty() ?
-            detail::make_identifier(first, last) :
-            element_id;
+        value_consumer values = begin_section_list;
+
+        value element_id = values.optional_consume(general_tags::element_id);
+        value content = values.consume();
+        values.finish();
+
+        actions.section_id = !element_id.empty() ?
+            element_id.get_quickbook() :
+            detail::make_identifier(content.get_quickbook());
 
-        if (section_level != 0)
-            qualified_section_id += '.';
+        if (actions.section_level != 0)
+            actions.qualified_section_id += '.';
         else
-            BOOST_ASSERT(qualified_section_id.empty());
-        qualified_section_id += section_id;
-        ++section_level;
+            BOOST_ASSERT(actions.qualified_section_id.empty());
 
-        actions.output_pre(out);
+        actions.qualified_section_id += actions.section_id;
+        ++actions.section_level;
+
+        actions::string_list saved_anchors;
+        saved_anchors.swap(actions.anchors);
 
         if (qbk_version_n < 103) // version 1.2 and below
         {
-            out << "\n<section id=\""
-                << library_id << "." << section_id << "\">\n";
+            actions.out << "\n<section id=\""
+                << actions.doc_id << "." << actions.section_id << "\">\n";
         }
         else // version 1.3 and above
         {
-            out << "\n<section id=\"" << library_id
-                << "." << qualified_section_id << "\">\n";
+            actions.out << "\n<section id=\"" << actions.doc_id
+                << "." << actions.qualified_section_id << "\">\n";
         }
-        std::string str;
-        phrase.swap(str);
 
-        actions.anchors.swap(actions.saved_anchors);
-        actions.output_pre(out);
+        actions.out << "<title>";
+
+        actions.anchors.swap(saved_anchors);
+        write_anchors(actions, actions.out);
 
         if (qbk_version_n < 103) // version 1.2 and below
         {
-            out << "<title>" << str << "</title>\n";
+            actions.out << content.get_boostbook();
         }
         else // version 1.3 and above
         {
-            out << "<title>"
-                << "<link linkend=\"" << library_id
-                    << "." << qualified_section_id << "\">"
-                << str
+            actions.out << "<link linkend=\"" << actions.doc_id
+                << "." << actions.qualified_section_id << "\">"
+                << content.get_boostbook()
                 << "</link>"
-                << "</title>\n"
                 ;
         }
+        
+        actions.out << "</title>\n";
     }
 
-    void end_section_action::operator()(iterator first, iterator last) const
+    void end_section_action(quickbook::actions& actions, value end_section, file_position pos)
     {
-        if(!actions.output_pre(out)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, actions.out);
 
-        if (section_level <= min_section_level)
+        if (actions.section_level <= actions.min_section_level)
         {
-            position const pos = first.get_position();
-            detail::outerr(pos.file,pos.line)
+            detail::outerr(actions.filename, pos.line)
                 << "Mismatched [endsect] near column " << pos.column << ".\n";
-            ++error_count;
+            ++actions.error_count;
             
             return;
         }
 
-        --section_level;
-        out << "</section>";
+        --actions.section_level;
+        actions.out << "</section>";
 
-        if (section_level == 0)
+        if (actions.section_level == 0)
         {
-            qualified_section_id.clear();
+            actions.qualified_section_id.clear();
         }
         else
         {
             std::string::size_type const n =
-                qualified_section_id.find_last_of('.');
-            qualified_section_id.erase(n, std::string::npos);
+                actions.qualified_section_id.find_last_of('.');
+            actions.qualified_section_id.erase(n, std::string::npos);
         }
     }
     
     void element_id_warning_action::operator()(iterator first, iterator) const
     {
-        position const pos = first.get_position();
-        detail::outwarn(pos.file,pos.line) << "Empty id.\n";        
+        file_position const pos = first.get_position();
+        detail::outwarn(actions.filename, pos.line) << "Empty id.\n";        
     }
 
-    fs::path path_difference(fs::path const& outdir, fs::path const& path)
+    // Not a general purpose normalization function, just
+    // from paths from the root directory. It strips the excess
+    // ".." parts from a path like: "x/../../y", leaving "y".
+    std::vector<fs::path> normalize_path_from_root(fs::path const& path)
     {
-        fs::path outtmp, temp;
-        fs::path::iterator out = outdir.begin(), file = path.begin();
-        for(; out != outdir.end() && file != path.end(); ++out, ++file)
+        assert(!path.has_root_directory() && !path.has_root_name());
+    
+        std::vector<fs::path> parts;
+
+        BOOST_FOREACH(fs::path const& part, path)
         {
-            if(!fs::equivalent(outtmp /= *out, temp /= *file))
-                break;
+            if (part.empty() || part == ".") {
+            }
+            else if (part == "..") {
+                if (!parts.empty()) parts.pop_back();
+            }
+            else {
+                parts.push_back(part);
+            }
         }
-        out = (out == outdir.begin()) ? outdir.end() : out;
+        
+        return parts;
+    }
+
+    // The relative path from base to path
+    fs::path path_difference(fs::path const& base, fs::path const& path)
+    {
+        fs::path
+            absolute_base = fs::absolute(base),
+            absolute_path = fs::absolute(path);
 
-        fs::path result = fs::path();
-        for(; out != outdir.end(); ++out)
-            if(*out != ".") result /= "..";
-        std::divides<fs::path> concat;
-        return std::accumulate(file, path.end(), result, concat);
+        // Remove '.', '..' and empty parts from the remaining path
+        std::vector<fs::path>
+            base_parts = normalize_path_from_root(absolute_base.relative_path()),
+            path_parts = normalize_path_from_root(absolute_path.relative_path());
+
+        std::vector<fs::path>::iterator
+            base_it = base_parts.begin(),
+            base_end = base_parts.end(),
+            path_it = path_parts.begin(),
+            path_end = path_parts.end();
+
+        // Build up the two paths in these variables, checking for the first
+        // difference.
+        fs::path
+            base_tmp = absolute_base.root_path(),
+            path_tmp = absolute_path.root_path();
+
+        fs::path result;
+
+        // If they have different roots then there's no relative path so
+        // just build an absolute path.
+        if (!fs::equivalent(base_tmp, path_tmp))
+        {
+            result = path_tmp;
+        }
+        else
+        {
+            // Find the point at which the paths differ    
+            for(; base_it != base_end && path_it != path_end; ++base_it, ++path_it)
+            {
+                if(!fs::equivalent(base_tmp /= *base_it, path_tmp /= *path_it))
+                    break;
+            }
+    
+            // Build a relative path to that point
+            for(; base_it != base_end; ++base_it) result /= "..";
+        }
+
+        // Build the rest of our path
+        for(; path_it != path_end; ++path_it) result /= *path_it;
+
+        return result;
     }
 
-    fs::path calculate_relative_path(
-        iterator first, iterator last, quickbook::actions& actions)
+    std::string check_path(value const& path, quickbook::actions& actions)
+    {
+        std::string path_text = path.get_quickbook();
+
+        if(path_text.find('\\') != std::string::npos)
+        {
+            detail::outwarn(actions.filename, path.get_position().line)
+                << "Path isn't portable: "
+                << detail::utf8(path_text)
+                << std::endl;
+        }
+        
+        boost::replace(path_text, '\\', '/');
+        
+        return path_text;
+    }
+
+    fs::path calculate_relative_path(std::string const& name, quickbook::actions& actions)
     {
         // Given a source file and the current filename, calculate the
         // path to the source file relative to the output directory.
-        fs::path path(std::string(first, last));
-        if (!path.is_complete())
+
+        fs::path path = detail::generic_to_path(name);
+        if (path.has_root_directory())
         {
-            fs::path infile = fs::absolute(actions.filename).normalize();
-            path = (infile.parent_path() / path).normalize();
-            fs::path outdir = fs::absolute(actions.outdir).normalize();
-            path = path_difference(outdir, path);
+            return path;
+        }
+        else
+        {
+            return path_difference(
+                actions.xinclude_base,
+                actions.filename.parent_path() / path);
+                
         }
-        return path;
     }
 
-    void xinclude_action::operator()(iterator first, iterator last) const
+    void xinclude_action(quickbook::actions& actions, value xinclude)
     {
-        if(!actions.output_pre(out)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, actions.out);
 
-        fs::path path = calculate_relative_path(first, last, actions);
-        out << "\n<xi:include href=\"";
-        detail::print_string(detail::escape_uri(path.generic_string()), out.get());
-        out << "\" />\n";
+        value_consumer values = xinclude;
+        fs::path path = calculate_relative_path(
+            check_path(values.consume(), actions), actions);
+        values.finish();
+
+        actions.out << "\n<xi:include href=\"";
+        detail::print_string(detail::escape_uri(path.generic_string()), actions.out.get());
+        actions.out << "\" />\n";
     }
 
     namespace
     {
-        fs::path include_search(fs::path const & current, std::string const & name)
+        struct include_search_return
         {
+            include_search_return(fs::path const& x, fs::path const& y)
+                : filename(x), filename_relative(y) {}
+
+            fs::path filename;
+            fs::path filename_relative;
+        };
+
+        include_search_return include_search(std::string const & name,
+                quickbook::actions const& actions)
+        {
+            fs::path current = actions.filename.parent_path();
             fs::path path(name);
 
             // If the path is relative, try and resolve it.
-            if (!path.is_complete())
+            if (!path.has_root_directory() && !path.has_root_name())
             {
                 // See if it can be found locally first.
                 if (fs::exists(current / path))
                 {
-                    return current / path;
+                    return include_search_return(
+                        current / path,
+                        actions.filename_relative.parent_path() / path);
                 }
 
                 // Search in each of the include path locations.
-                BOOST_FOREACH(std::string const & p, include_path)
+                BOOST_FOREACH(fs::path full, include_path)
                 {
-                    fs::path full(p);
                     full /= path;
                     if (fs::exists(full))
                     {
-                        return full;
+                        return include_search_return(full, path);
                     }
                 }
             }
 
-            return path;
+            return include_search_return(path,
+                actions.filename_relative.parent_path() / path);
         }
     }
 
-    void import_action::operator()(iterator first, iterator last) const
+    void import_action(quickbook::actions& actions, value import)
     {
-        if(!actions.output_pre(actions.out)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, actions.out);
+
+        value_consumer values = import;
+        include_search_return paths = include_search(
+            check_path(values.consume(), actions), actions);
+        values.finish();
 
-        fs::path path = include_search(actions.filename.parent_path(), std::string(first,last));
-        std::string ext = path.extension().generic_string();
+        std::string ext = paths.filename.extension().generic_string();
         std::vector<template_symbol> storage;
         actions.error_count +=
-            load_snippets(path.string(), storage, ext, actions.doc_id);
+            load_snippets(paths.filename.string(), storage, ext, actions.doc_id);
 
         BOOST_FOREACH(template_symbol& ts, storage)
         {
@@ -1363,42 +1785,42 @@
             ts.parent = &actions.templates.top_scope();
             if (!actions.templates.add(ts))
             {
-                cl::file_position const pos = ts.body.position;
-                detail::outerr(pos.file, pos.line)
-                    << "Template Redefinition: " << tname << std::endl;
+                detail::outerr(ts.body.filename, ts.body.content.get_position().line)
+                    << "Template Redefinition: " << detail::utf8(tname) << std::endl;
                 ++actions.error_count;
             }
         }
     }
 
-    void include_action::operator()(iterator first, iterator last) const
+    void include_action(quickbook::actions& actions, value include)
     {
-        if(!actions.output_pre(actions.out)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, actions.out);
+
+        value_consumer values = include;
+        value include_doc_id = values.optional_consume(general_tags::include_id);
+        include_search_return filein = include_search(
+            check_path(values.consume(), actions), actions);
+        values.finish();
 
-        fs::path filein = include_search(actions.filename.parent_path(), std::string(first,last));
         std::string doc_type, doc_id;
-        docinfo_string doc_dirname, doc_last_revision;
 
         // swap the filenames
-        std::swap(actions.filename, filein);
+        std::swap(actions.filename, filein.filename);
+        std::swap(actions.filename_relative, filein.filename_relative);
 
-        // save the doc info strings
+        // save the doc info strings and source mode
         if(qbk_version_n >= 106) {
             doc_type = actions.doc_type;
             doc_id = actions.doc_id;
-            doc_dirname = actions.doc_dirname;
-            doc_last_revision = actions.doc_last_revision;
         }
         else {
             actions.doc_type.swap(doc_type);
             actions.doc_id.swap(doc_id);
-            actions.doc_dirname.swap(doc_dirname);
-            actions.doc_last_revision.swap(doc_last_revision);
         }
         
-        // save the version info
-        unsigned qbk_major_version_store = qbk_major_version;
-        unsigned qbk_minor_version_store = qbk_minor_version;
+        // save the source mode and version info (only restored for 1.6+)
+        std::string source_mode = actions.source_mode;
         unsigned qbk_version_n_store = qbk_version_n;
 
         // scope the macros
@@ -1409,30 +1831,32 @@
 
         // if an id is specified in this include (as in [include:id foo.qbk])
         // then use it as the doc_id.
-        if (!actions.include_doc_id.empty())
-        {
-            actions.doc_id = actions.include_doc_id;
-            actions.include_doc_id.clear();
-        }
+        if (!include_doc_id.empty())
+            actions.doc_id = include_doc_id.get_quickbook();
 
         // update the __FILENAME__ macro
-        *boost::spirit::classic::find(actions.macro, "__FILENAME__") = actions.filename.string();
+        *boost::spirit::classic::find(actions.macro, "__FILENAME__")
+            = detail::path_to_generic(actions.filename_relative);
+
+        // save values
+        actions.values.builder.save();
 
         // parse the file
         quickbook::parse_file(actions.filename.string().c_str(), actions, true);
 
         // restore the values
-        std::swap(actions.filename, filein);
+        actions.values.builder.restore();
+
+        std::swap(actions.filename, filein.filename);
+        std::swap(actions.filename_relative, filein.filename_relative);
 
         actions.doc_type.swap(doc_type);
         actions.doc_id.swap(doc_id);
-        actions.doc_dirname.swap(doc_dirname);
-        actions.doc_last_revision.swap(doc_last_revision);
         
         if(qbk_version_n >= 106 || qbk_version_n_store >= 106)
         {
-            qbk_major_version = qbk_major_version_store;
-            qbk_minor_version = qbk_minor_version_store;
+            actions.source_mode = source_mode;
+
             qbk_version_n = qbk_version_n_store;
         }
 
@@ -1443,92 +1867,72 @@
         //~ actions.templates = templates; $$$ fixme $$$
     }
 
-    void phrase_to_string_action::operator()(iterator first, iterator last) const
+    void phrase_to_docinfo_action_impl::operator()(iterator first, iterator last,
+            value::tag_type tag) const
     {
-        if(!actions.output_pre(phrase)) return;
+        if (actions.suppress) return;
+        write_anchors(actions, actions.phrase);
 
-        out.clear();
-        phrase.swap(out);
+        std::string encoded;
+        actions.phrase.swap(encoded);
+        actions.values.builder.insert(
+            qbk_bbk_value(first, last, encoded, tag));
     }
 
-    void phrase_to_docinfo_action::operator()(iterator first, iterator last) const
+    void phrase_to_docinfo_action_impl::operator()(iterator first, iterator last) const
     {
-        if(!actions.output_pre(phrase)) return;
-
-        out.encoded.clear();
-        phrase.swap(out.encoded);
-        out.raw = std::string(first, last);
+        return (*this)(first, last, value::default_tag);
     }
     
-    void inner_phrase_action_pre::operator()(iterator, iterator) const
-    {
-        // TODO: Really?
-        if(actions.suppress) return;
-
-        actions.saved_anchors.clear();
-        actions.saved_anchors.swap(actions.anchors);
-    }
-
-    void inner_phrase_action_post::operator()(iterator, iterator) const
+    void collector_to_value_action::operator()(iterator, iterator) const
     {
-        if(actions.suppress) return;
-
-        actions.output_pre(actions.phrase);
-    }
-
-    bool pre_output_action::operator()(collector& tgt) const
-    {
-        if(actions.suppress) return false;
-
-        for(quickbook::actions::string_list::iterator
-            it = actions.anchors.begin(),
-            end = actions.anchors.end();
-            it != end; ++it)
-        {
-            tgt << "<anchor id=\"";
-            detail::print_string(*it, tgt.get());
-            tgt << "\"/>\n";
-        }
-        
-        actions.anchors.clear();
+        if (actions.suppress) return;
+        write_anchors(actions, output);
 
-        return true;
+        std::string value;
+        output.swap(value);
+        actions.values.builder.insert(bbk_value(value, value::default_tag));
     }
     
-    bool pre_output_action::operator()(iterator, iterator) const
-    {
-        return (*this)(actions.out);
-    }
-
-    scoped_block_push::scoped_block_push(quickbook::actions& actions)
-        : actions(actions)
+    bool scoped_output_push::start()
     {
         actions.out.push();
         actions.phrase.push();
+        actions.anchors.swap(saved_anchors);
+
+        return true;
     }
     
-    scoped_block_push::~scoped_block_push()
+    void scoped_output_push::cleanup()
     {
         actions.phrase.pop();
         actions.out.pop();
+        actions.anchors.swap(saved_anchors);
     }
 
-    std::string const& scoped_block_push::success_impl()
+    bool set_no_eols_scoped::start()
     {
-        // TODO: This should probably return an empty string
-        // if actions.suppress is true.
-        actions.inside_paragraph();
-        return actions.out.str();
+        saved_no_eols = actions.no_eols;
+        actions.no_eols = false;
+
+        return true;
     }
 
-    set_no_eols_scoped::set_no_eols_scoped(quickbook::actions& actions)
-        : actions(actions), saved_no_eols(actions.no_eols)
+    void set_no_eols_scoped::cleanup()
     {
-        actions.no_eols = false;
+        actions.no_eols = saved_no_eols;
     }
 
-    set_no_eols_scoped::~set_no_eols_scoped()
+    bool scoped_context_impl::start(int new_context)
     {
-        actions.no_eols = saved_no_eols;
+        saved_context_ = actions_.context;
+        actions_.context = new_context;
+
+        return true;
+    }
+
+    void scoped_context_impl::cleanup()
+    {
+        actions_.context = saved_context_;
     }
 }
Modified: branches/release/tools/quickbook/src/actions.hpp
==============================================================================
--- branches/release/tools/quickbook/src/actions.hpp	(original)
+++ branches/release/tools/quickbook/src/actions.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -10,41 +10,21 @@
 #if !defined(BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP)
 #define BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP
 
-#include <map>
 #include <string>
 #include <vector>
-#include <stack>
-#include <algorithm>
-#include <boost/filesystem/v3/operations.hpp>
-#include <boost/foreach.hpp>
-#include <boost/tuple/tuple.hpp>
+#include <boost/spirit/include/phoenix1_functions.hpp>
+#include <boost/spirit/include/classic_symbols_fwd.hpp>
 #include "fwd.hpp"
-#include "collector.hpp"
 #include "template_stack.hpp"
 #include "utils.hpp"
-
-#ifdef BOOST_MSVC
-// disable copy/assignment could not be generated, unreferenced formal params
-#pragma warning (push)
-#pragma warning(disable : 4511 4512 4100)
-#endif
+#include "values.hpp"
+#include "scoped.hpp"
 
 namespace quickbook
 {
     namespace cl = boost::spirit::classic;
-    namespace fs = boost::filesystem;
 
-    extern int qbk_major_version;
-    extern int qbk_minor_version;
     extern unsigned qbk_version_n; // qbk_major_version * 100 + qbk_minor_version
-    
-    // This struct is used to avoid an optimization bug
-    // in g++ 4.4 on 64-bit linux.
-    struct assign_qbk_version {
-        assign_qbk_version(int& v) : v_(v) {}
-        void operator()(int value) const;
-        int& v_;
-    };
 
     struct quickbook_range {
         template <typename Arg>
@@ -72,7 +52,6 @@
     }
 
     typedef cl::symbols<std::string> string_symbols;
-    typedef std::map<std::string, std::string> attribute_map;
 
     int load_snippets(std::string const& file, std::vector<template_symbol>& storage,
         std::string const& extension, std::string const& doc_id);
@@ -81,203 +60,60 @@
         actions& escape_actions,
         std::string const& source_mode);        
 
-    template <typename Derived, typename DataT = void>
-    struct scoped_action_base
+    struct error_message_action
     {
-        typedef quickbook::actions data_type;
-        
-        template <typename T>
-        struct result
-        {
-            typedef cl::match<DataT> type;
-        };
+        // Prints an error message to std::cerr
 
-        template <typename T>
-        DataT success(T const&)
-        {
-            return static_cast<Derived*>(this)->success_impl();
-        }
-        
-        void failure() {
-            return static_cast<Derived*>(this)->failure_impl();
-        }
-        
-        void failure_impl() {}
-    };
+        error_message_action(quickbook::actions& actions, std::string const& m)
+            : actions(actions)
+            , message(m)
+        {}
 
-    struct void_type {};
+        void operator()(iterator, iterator) const;
 
-    template <typename Derived>
-    struct scoped_action_base<Derived, void>
-        : scoped_action_base<Derived, void_type>
-    {
-        template <typename T>
-        void_type success(T const&)
-        {
-            static_cast<Derived*>(this)->success_impl();
-            return void_type();
-        }
-        
-        void success_impl() {}
+        quickbook::actions& actions;
+        std::string message;
     };
 
     struct error_action
     {
         // Prints an error message to std::cerr
 
-        error_action(
-            int& error_count)
-        : error_count(error_count) {}
+        error_action(quickbook::actions& actions)
+        : actions(actions) {}
 
         void operator()(iterator first, iterator /*last*/) const;
 
-        int& error_count;
-    };
-
-    struct tagged_action
-    {
-        tagged_action(
-            collector& out,
-            std::string const& pre,
-            std::string const& post,
-            quickbook::actions& actions)
-        : out(out)
-        , pre(pre)
-        , post(post)
-        , actions(actions) {}
-
-        void operator()(std::string const&) const;
+        error_message_action operator()(std::string const& message)
+        {
+            return error_message_action(actions, message);
+        }
 
-        collector& out;
-        std::string pre;
-        std::string post;
         quickbook::actions& actions;
     };
 
-    struct phrase_action
+    struct element_action
     {
-        //  blurb, blockquote, preformatted, list_item,
-        //  unordered_list, ordered_list
-
-        phrase_action(
-            collector& out,
-            collector& phrase,
-            std::string const& pre,
-            std::string const& post,
-            quickbook::actions& actions)
-        : out(out)
-        , phrase(phrase)
-        , pre(pre)
-        , post(post)
-        , actions(actions) {}
+        element_action(quickbook::actions& actions)
+            : actions(actions) {}
 
-        void operator()(iterator first, iterator last) const { return (*this)(); }
-        template <typename T>
-        void operator()(T const&) const { return (*this)(); }
-        void operator()() const;
+        void operator()(iterator, iterator) const;
 
-        collector& out;
-        collector& phrase;
-        std::string pre;
-        std::string post;
         quickbook::actions& actions;
     };
 
-    struct implicit_paragraph_action
+    struct paragraph_action
     {
         //  implicit paragraphs
         //  doesn't output the paragraph if it's only whitespace.
 
-        implicit_paragraph_action(
-            collector& out,
-            collector& phrase,
-            std::string const& pre,
-            std::string const& post,
+        paragraph_action(
             quickbook::actions& actions)
-        : out(out)
-        , phrase(phrase)
-        , pre(pre)
-        , post(post)
-        , actions(actions) {}
+        : actions(actions) {}
 
         void operator()() const;
-        void operator()(iterator first, iterator last) const { (*this)(); }
+        void operator()(iterator, iterator) const { (*this)(); }
 
-        collector& out;
-        collector& phrase;
-        std::string pre;
-        std::string post;
-        quickbook::actions& actions;
-    };
-
-    struct header_action
-    {
-        //  Handles paragraph, h1, h2, h3, h4, h5, h6,
-
-        header_action(
-            collector& out,
-            collector& phrase,
-            std::string const& element_id,
-            std::string const& library_id,
-            std::string const& section_id,
-            std::string const& qualified_section_id,
-            std::string const& pre,
-            std::string const& post,
-            quickbook::actions& actions)
-        : out(out)
-        , phrase(phrase)
-        , element_id(element_id)
-        , library_id(library_id)
-        , section_id(section_id)
-        , qualified_section_id(qualified_section_id)
-        , pre(pre)
-        , post(post)
-        , actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& out;
-        collector& phrase;
-        std::string const& element_id;
-        std::string const& library_id;
-        std::string const& section_id;
-        std::string const& qualified_section_id;
-        std::string pre;
-        std::string post;
-        quickbook::actions& actions;
-    };
-
-    struct generic_header_action
-    {
-        //  Handles h
-
-        generic_header_action(
-            collector& out,
-            collector& phrase,
-            std::string const& element_id,
-            std::string const& library_id,
-            std::string const& section_id,
-            std::string const& qualified_section_id,
-            int const& section_level,
-            quickbook::actions& actions)
-        : out(out)
-        , phrase(phrase)
-        , element_id(element_id)
-        , library_id(library_id)
-        , section_id(section_id)
-        , qualified_section_id(qualified_section_id)
-        , section_level(section_level)
-        , actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& out;
-        collector& phrase;
-        std::string const& element_id;
-        std::string const& library_id;
-        std::string const& section_id;
-        std::string const& qualified_section_id;
-        int const& section_level;
         quickbook::actions& actions;
     };
 
@@ -287,102 +123,31 @@
 
         simple_phrase_action(
             collector& out
-          , std::string const& pre
-          , std::string const& post
           , string_symbols const& macro
           , quickbook::actions& actions)
         : out(out)
-        , pre(pre)
-        , post(post)
         , macro(macro)
         , actions(actions) {}
 
-        void operator()(iterator first, iterator last) const;
+        void operator()(char) const;
 
         collector& out;
-        std::string pre;
-        std::string post;
         string_symbols const& macro;
         quickbook::actions& actions;
     };
 
-    struct cond_phrase_action_pre
+    struct cond_phrase_push : scoped_action_base
     {
-        //  Handles conditional phrases
-
-        cond_phrase_action_pre(
-            bool& condition
-          , string_symbols const& macro)
-        : condition(condition)
-        , macro(macro) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        bool& condition;
-        string_symbols const& macro;
-    };
+        cond_phrase_push(quickbook::actions& x)
+            : actions(x) {}
 
-    struct cond_phrase_push : scoped_action_base<cond_phrase_push>
-    {
-        cond_phrase_push(quickbook::actions&);
-        ~cond_phrase_push();
+        bool start();
+        void cleanup();
 
         quickbook::actions& actions;
         bool saved_suppress;
     };
 
-    struct list_action
-    {
-        //  Handles lists
-
-        typedef std::pair<char, int> mark_type;
-        list_action(
-            collector& out
-          , collector& list_buffer
-          , int& list_indent
-          , std::stack<mark_type>& list_marks
-          , quickbook::actions& actions)
-        : out(out)
-        , list_buffer(list_buffer)
-        , list_indent(list_indent)
-        , list_marks(list_marks)
-        , actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& out;
-        collector& list_buffer;
-        int& list_indent;
-        std::stack<mark_type>& list_marks;
-        quickbook::actions& actions;
-    };
-
-    struct list_format_action
-    {
-        //  Handles list formatting and hierarchy
-
-        typedef std::pair<char, int> mark_type;
-        list_format_action(
-            collector& out
-          , int& list_indent
-          , std::stack<mark_type>& list_marks
-          , int& error_count
-          , quickbook::actions& actions)
-        : out(out)
-        , list_indent(list_indent)
-        , list_marks(list_marks)
-        , error_count(error_count)
-        , actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& out;
-        int& list_indent;
-        std::stack<mark_type>& list_marks;
-        int& error_count;
-        quickbook::actions& actions;
-    };
-
     struct span
     {
         // Decorates c++ code fragments
@@ -400,23 +165,15 @@
     {
         // Handles unexpected chars in c++ syntax
 
-        unexpected_char(collector& out)
-        : out(out) {}
+        unexpected_char(
+            collector& out
+          , quickbook::actions& actions)
+        : out(out)
+        , actions(actions) {}
 
         void operator()(iterator first, iterator last) const;
 
         collector& out;
-    };
-
-    struct anchor_action
-    {
-        // Handles anchors
-
-        anchor_action(quickbook::actions& actions)
-            : actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
         quickbook::actions& actions;
     };
 
@@ -519,74 +276,6 @@
         quickbook::actions& actions;
     };
 
-    struct attribute_action
-    {
-        // Handle image attributes
-        
-        attribute_action(
-            attribute_map& attributes
-          , std::string& attribute_name
-          , int& error_count)
-        : attributes(attributes)
-        , attribute_name(attribute_name)
-        , error_count(error_count) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        attribute_map& attributes;
-        std::string& attribute_name;
-        int& error_count;
-    };
-
-    struct image_action
-    {
-        // Handles inline images
-
-        image_action(
-            collector& phrase
-          , attribute_map& attributes
-          , std::string& image_fileref
-          , quickbook::actions& actions)
-        : phrase(phrase)
-        , attributes(attributes)
-        , image_fileref(image_fileref)
-        , actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& phrase;
-        attribute_map& attributes;
-        std::string& image_fileref;
-        quickbook::actions& actions;
-    };
-
-    struct markup_action
-    {
-        // A generic markup action
-
-        markup_action(
-            collector& phrase,
-            std::string const& str,
-            quickbook::actions& actions)
-        : phrase(phrase), str(str), actions(actions) {}
-
-        template <typename T>
-        void operator()(T const&) const
-        {
-            phrase << str;
-        }
-
-        template <typename T>
-        void operator()(T const&, T const&) const
-        {
-            phrase << str;
-        }
-
-        collector& phrase;
-        std::string str;
-        quickbook::actions& actions;
-    };
-    
     struct code_action
     {
         // Does the actual syntax highlighing of code
@@ -638,341 +327,82 @@
         quickbook::actions& actions;
     };
 
-    struct macro_identifier_action
-    {
-        // Handles macro identifiers
-
-        macro_identifier_action(quickbook::actions& actions)
-        : actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        quickbook::actions& actions;
-    };
-
-    struct macro_definition_action
-    {
-        // Handles macro definitions
-
-        macro_definition_action(quickbook::actions& actions)
-        : actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        quickbook::actions& actions;
-    };
-
-    struct template_body_action
-    {
-        // Handles template definitions
-
-        template_body_action(quickbook::actions& actions)
-        : actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        quickbook::actions& actions;
-    };
-    
-    struct template_arg_action
-    {
-        // Handles a template argument
-
-        template_arg_action(quickbook::actions& actions)
-        : actions(actions) {}
-        
-        void operator()(iterator first, iterator last) const;
-
-        quickbook::actions& actions;
-    };
-
-    struct do_template_action
-    {
-        // Handles template substitutions
-
-        do_template_action(quickbook::actions& actions)
-        : actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        quickbook::actions& actions;
-    };
-
-    struct link_action
-    {
-        // Handles links (URL, XML refentry, function, class, member)
-
-        link_action(
-            collector& phrase,
-            char const* tag,
-            quickbook::actions& actions)
-        : phrase(phrase), tag(tag), actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& phrase;
-        char const* tag;
-        quickbook::actions& actions;
-    };
-
-    struct variablelist_action
-    {
-        // Handles variable lists
-
-        variablelist_action(quickbook::actions& actions)
-        : actions(actions) {}
-
-        void operator()(iterator, iterator) const;
-
-        quickbook::actions& actions;
-    };
-
-    struct table_action
-    {
-        // Handles tables
-
-        table_action(quickbook::actions& actions)
-        : actions(actions) {}
-
-        void operator()(iterator, iterator) const;
-
-        quickbook::actions& actions;
-    };
-
-    struct start_row_action
-    {
-        // Handles table rows
-
-        start_row_action(collector& phrase, unsigned& span, std::string& header, quickbook::actions& actions)
-            : phrase(phrase), span(span), header(header), actions(actions) {}
-
-        void operator()(char) const;
-        void operator()(iterator f, iterator) const;
-
-        collector& phrase;
-        unsigned& span;
-        std::string& header;
-        quickbook::actions& actions;
-    };
-
-    struct col_action
-    {
-        col_action(collector& phrase, unsigned& span, quickbook::actions& actions)
-        : phrase(phrase), span(span), actions(actions) {}
-
-        void operator()(std::string const&) const;
-
-        collector& phrase;
-        unsigned& span;
-        quickbook::actions& actions;
-    };
-
-    struct begin_section_action
-    {
-        // Handles begin page
-
-        begin_section_action(
-            collector& out
-          , collector& phrase
-          , std::string& library_id
-          , std::string& section_id
-          , int& section_level
-          , std::string& qualified_section_id
-          , std::string& element_id
-          , quickbook::actions& actions)
-        : out(out)
-        , phrase(phrase)
-        , library_id(library_id)
-        , section_id(section_id)
-        , section_level(section_level)
-        , qualified_section_id(qualified_section_id)
-        , element_id(element_id)
-        , actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& out;
-        collector& phrase;
-        std::string& library_id;
-        std::string& section_id;
-        int& section_level;
-        std::string& qualified_section_id;
-        std::string& element_id;
-        quickbook::actions& actions;
-    };
-
-    struct end_section_action
-    {
-        end_section_action(
-            collector& out
-          , int& section_level
-          , int& min_section_level
-          , std::string& qualified_section_id
-          , int& error_count
-          , quickbook::actions& actions)
-        : out(out)
-        , section_level(section_level)
-        , min_section_level(min_section_level)
-        , qualified_section_id(qualified_section_id)
-        , error_count(error_count)
-        , actions(actions) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& out;
-        int& section_level;
-        int& min_section_level;
-        std::string& qualified_section_id;
-        int& error_count;
-        quickbook::actions& actions;
-   };
-   
    struct element_id_warning_action
    {
-       void operator()(iterator first, iterator last) const;
-   };
-
-    struct xinclude_action
-    {
-        // Handles XML includes
-        xinclude_action(collector& out_, quickbook::actions& actions_)
-            : out(out_), actions(actions_) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& out;
-        quickbook::actions& actions;
-    };
-
-    struct include_action
-    {
-        // Handles QBK includes
-
-        include_action(quickbook::actions& actions_)
+        element_id_warning_action(quickbook::actions& actions_)
             : actions(actions_) {}
 
         void operator()(iterator first, iterator last) const;
 
         quickbook::actions& actions;
-    };
-
-    struct import_action
-    {
-        // Handles import of source code files (e.g. *.cpp *.py)
-        import_action(collector& out_, quickbook::actions& actions_)
-            : out(out_), actions(actions_) {}
-
-        void operator()(iterator first, iterator last) const;
-
-        collector& out;
-        quickbook::actions& actions;
-    };
-
-    struct docinfo_string {
-        std::string raw;
-        std::string encoded;
-
-        docinfo_string() : raw(), encoded() {}
-
-        void swap(docinfo_string& x) {
-            raw.swap(x.raw);
-            encoded.swap(x.encoded);
-        }
-
-        void clear() {
-            raw.clear();
-            encoded.clear();
-        }
-
-        bool empty() const {
-            return raw.empty();
-        }
-
-        std::string const& get(unsigned version) const;
-    };
+   };
 
     void pre(collector& out, quickbook::actions& actions, bool ignore_docinfo = false);
     void post(collector& out, quickbook::actions& actions, bool ignore_docinfo = false);
 
-    struct phrase_to_string_action
+    struct phrase_to_docinfo_action_impl
     {
-        phrase_to_string_action(std::string& out, collector& phrase, quickbook::actions& actions)
-            : out(out) , phrase(phrase), actions(actions) {}
+        template <typename Arg1, typename Arg2, typename Arg3 = void>
+        struct result { typedef void type; };
+    
+        phrase_to_docinfo_action_impl(quickbook::actions& actions)
+            : actions(actions) {}
 
         void operator()(iterator first, iterator last) const;
+        void operator()(iterator first, iterator last, value::tag_type) const;
 
-        std::string& out;
-        collector& phrase;
         quickbook::actions& actions;
     };
+    
+    typedef phoenix::function<phrase_to_docinfo_action_impl> phrase_to_docinfo_action;
 
-    struct phrase_to_docinfo_action
+    struct collector_to_value_action
     {
-        phrase_to_docinfo_action(docinfo_string& out, collector& phrase, quickbook::actions& actions)
-            : out(out)
-            , phrase(phrase)
-            , actions(actions) {}
+        collector_to_value_action(quickbook::actions& actions, collector& output)
+            : actions(actions), output(output) {}
 
         void operator()(iterator first, iterator last) const;
 
-        docinfo_string& out;
-        collector& phrase;
         quickbook::actions& actions;
+        collector& output;
     };
 
-    struct inner_phrase_action_pre
+    struct scoped_output_push : scoped_action_base
     {
-        inner_phrase_action_pre(quickbook::actions& actions)
+        scoped_output_push(quickbook::actions& actions)
             : actions(actions) {}
 
-        void operator()(iterator, iterator) const;
-        
-        quickbook::actions& actions;
-    };
-
-    struct inner_phrase_action_post
-    {
-        inner_phrase_action_post(quickbook::actions& actions)
-            : actions(actions) {}
+        bool start();
+        void cleanup();
 
-        void operator()(iterator, iterator) const;
-        
         quickbook::actions& actions;
+        std::vector<std::string> saved_anchors;
     };
 
-    struct pre_output_action
+    struct set_no_eols_scoped : scoped_action_base
     {
-        pre_output_action(quickbook::actions& actions)
+        set_no_eols_scoped(quickbook::actions& actions)
             : actions(actions) {}
-            
-        bool operator()(collector& tgt) const;
-        bool operator()(iterator, iterator) const;
-        
-        quickbook::actions& actions;
-    };
 
-    struct scoped_block_push : scoped_action_base<scoped_block_push, std::string>
-    {
-        scoped_block_push(quickbook::actions&);
-        ~scoped_block_push();
-        std::string const& success_impl();
+        bool start();
+        void cleanup();
 
         quickbook::actions& actions;
+        bool saved_no_eols;
     };
-
-    struct set_no_eols_scoped : scoped_action_base<set_no_eols_scoped>
+    
+    struct scoped_context_impl : scoped_action_base
     {
-        set_no_eols_scoped(quickbook::actions&);
-        ~set_no_eols_scoped();
+        scoped_context_impl(quickbook::actions& actions)
+            : actions_(actions) {}
 
-        quickbook::actions& actions;
-        bool saved_no_eols;
+        bool start(int);
+        void cleanup();
+
+    private:
+        quickbook::actions& actions_;
+        int saved_context_;
     };
 }
 
-#ifdef BOOST_MSVC
-#pragma warning (pop)
-#endif
-
 #endif // BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP
-
Modified: branches/release/tools/quickbook/src/actions_class.cpp
==============================================================================
--- branches/release/tools/quickbook/src/actions_class.cpp	(original)
+++ branches/release/tools/quickbook/src/actions_class.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -9,9 +9,9 @@
     http://www.boost.org/LICENSE_1_0.txt)
 =============================================================================*/
 #include "actions_class.hpp"
-#include "markups.hpp"
 #include "quickbook.hpp"
 #include "grammar.hpp"
+#include "input_path.hpp"
 
 #if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
 #pragma warning(disable:4355)
@@ -19,33 +19,34 @@
 
 namespace quickbook
 {
-    actions::actions(char const* filein_, fs::path const& outdir_, string_stream& out_)
+    actions::actions(fs::path const& filein_, fs::path const& xinclude_base_, string_stream& out_)
         : grammar_()
 
     // header info
         , doc_type()
-        , doc_title()
-        , doc_version()
+        , doc_title_qbk()
         , doc_id()
-        , doc_dirname()
-        , doc_copyrights()
-        , doc_purpose()
-        , doc_categories()
-        , doc_authors()
-        , doc_license()
-        , doc_last_revision()
-        , include_doc_id()
 
     // main output stream
         , out(out_)
 
     // auxilliary streams
         , phrase()
-        , list_buffer()
+
+    // value actions
+        , values()
+        , 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(fs::absolute(fs::path(filein_)))
-        , outdir(outdir_)
+        , filename(filein_)
+        , filename_relative(filein_.filename())
+        , xinclude_base(xinclude_base_)
         , macro_change_depth(0)
         , macro()
         , section_level(0)
@@ -55,164 +56,38 @@
         , source_mode("c++")
 
     // temporary or global state
-        , element_id()
-        , table_title()
-        , table_span(0)
-        , table_header()
-        , macro_id()
-        , list_marks()
-        , list_indent(-1)
-        , template_identifier()
-        , template_info()
         , template_depth(0)
-        , template_escape(false)
         , templates()
         , error_count(0)
-        , image_fileref()
-        , attribute_name()
-        , attributes()
         , anchors()
-        , saved_anchors()
         , no_eols(true)
         , suppress(false)
+        , warned_about_breaks(false)
 
     // actions
-        , error(error_count)
-        , extract_doc_title(doc_title, phrase, *this)
-        , extract_doc_license(doc_license, phrase, *this)
-        , extract_doc_purpose(doc_purpose, phrase, *this)
-        , extract_doc_version(doc_version, phrase, *this)
-        , extract_doc_id(doc_id_tmp, phrase, *this)
-        , extract_doc_dirname(doc_dirname, phrase, *this)
-        , extract_copyright_second(copyright.second, phrase, *this)
-        , extract_name_second(name.second, phrase, *this)
-        , extract_name_first(name.first, phrase, *this)
-        , extract_doc_last_revision(doc_last_revision, phrase, *this)
-        , extract_doc_category(doc_category, phrase, *this)
-        , extract_doc_biblioid(doc_biblioid.second, phrase, *this)
-        , extract_doc_lang(doc_lang, phrase, *this)
-        , scoped_block(*this)
+        , element(*this)
+        , error(*this)
         , code(out, phrase, *this)
         , code_block(phrase, phrase, *this)
         , inline_code(phrase, *this)
-        , inside_paragraph(out, phrase, paragraph_pre, paragraph_post, *this)
-        , h(out, phrase, element_id, doc_id, section_id, qualified_section_id, section_level, *this)
-        , h1(out, phrase, element_id, doc_id, section_id, qualified_section_id, h1_pre, h1_post, *this)
-        , h2(out, phrase, element_id, doc_id, section_id, qualified_section_id, h2_pre, h2_post, *this)
-        , h3(out, phrase, element_id, doc_id, section_id, qualified_section_id, h3_pre, h3_post, *this)
-        , h4(out, phrase, element_id, doc_id, section_id, qualified_section_id, h4_pre, h4_post, *this)
-        , h5(out, phrase, element_id, doc_id, section_id, qualified_section_id, h5_pre, h5_post, *this)
-        , h6(out, phrase, element_id, doc_id, section_id, qualified_section_id, h6_pre, h6_post, *this)
-        , hr(out, hr_, *this)
-        , blurb(out, blurb_pre, blurb_post, *this)
-        , blockquote(out, blockquote_pre, blockquote_post, *this)
-        , set_no_eols(*this)
-        , preformatted(out, phrase, preformatted_pre, preformatted_post, *this)
-        , warning(out, warning_pre, warning_post, *this)
-        , caution(out, caution_pre, caution_post, *this)
-        , important(out, important_pre, important_post, *this)
-        , note(out, note_pre, note_post, *this)
-        , tip(out, tip_pre, tip_post, *this)
+        , paragraph(*this)
         , space_char(phrase)
         , plain_char(phrase, *this)
         , raw_char(phrase, *this)
         , escape_unicode(phrase, *this)
-        , attribute(attributes, attribute_name, error_count)
-        , image(phrase, attributes, image_fileref, *this)
-        , cond_phrase_pre(condition, macro)
-        , scoped_cond_phrase(*this)
 
-        , list(out, list_buffer, list_indent, list_marks, *this)
-        , list_format(list_buffer, list_indent, list_marks, error_count, *this)
-        , list_item(list_buffer, phrase, list_item_pre, list_item_post, *this)
-
-        , funcref_pre(phrase, funcref_pre_, *this)
-        , funcref_post(phrase, funcref_post_, *this)
-        , classref_pre(phrase, classref_pre_, *this)
-        , classref_post(phrase, classref_post_, *this)
-        , memberref_pre(phrase, memberref_pre_, *this)
-        , memberref_post(phrase, memberref_post_, *this)
-        , enumref_pre(phrase, enumref_pre_, *this)
-        , enumref_post(phrase, enumref_post_, *this)
-        , macroref_pre(phrase, macroref_pre_, *this)
-        , macroref_post(phrase, macroref_post_, *this)
-        , headerref_pre(phrase, headerref_pre_, *this)
-        , headerref_post(phrase, headerref_post_, *this)
-        , conceptref_pre(phrase, conceptref_pre_, *this)
-        , conceptref_post(phrase, conceptref_post_, *this)
-        , globalref_pre(phrase, globalref_pre_, *this)
-        , globalref_post(phrase, globalref_post_, *this)
-
-        , bold_pre(phrase, bold_pre_, *this)
-        , bold_post(phrase, bold_post_, *this)
-        , italic_pre(phrase, italic_pre_, *this)
-        , italic_post(phrase, italic_post_, *this)
-        , underline_pre(phrase, underline_pre_, *this)
-        , underline_post(phrase, underline_post_, *this)
-        , teletype_pre(phrase, teletype_pre_, *this)
-        , teletype_post(phrase, teletype_post_, *this)
-        , strikethrough_pre(phrase, strikethrough_pre_, *this)
-        , strikethrough_post(phrase, strikethrough_post_, *this)
-        , quote_pre(phrase, quote_pre_, *this)
-        , quote_post(phrase, quote_post_, *this)
-        , replaceable_pre(phrase, replaceable_pre_, *this)
-        , replaceable_post(phrase, replaceable_post_, *this)
-        , footnote_pre(phrase, footnote_pre_, *this)
-        , footnote_post(phrase, footnote_post_, *this)
-
-        , simple_bold(phrase, bold_pre_, bold_post_, macro, *this)
-        , simple_italic(phrase, italic_pre_, italic_post_, macro, *this)
-        , simple_underline(phrase, underline_pre_, underline_post_, macro, *this)
-        , simple_teletype(phrase, teletype_pre_, teletype_post_, macro, *this)
-        , simple_strikethrough(phrase, strikethrough_pre_, strikethrough_post_, macro, *this)
-
-        , variablelist(*this)
-        , start_varlistentry(phrase, start_varlistentry_, *this)
-        , end_varlistentry(phrase, end_varlistentry_, *this)
-        , start_varlistterm(phrase, start_varlistterm_, *this)
-        , end_varlistterm(phrase, end_varlistterm_, *this)
-        , varlistitem(phrase, start_varlistitem_, end_varlistitem_, *this)
+        , simple_markup(phrase, macro, *this)
 
         , break_(phrase, *this)
-        , macro_identifier(*this)
-        , macro_definition(*this)
         , do_macro(phrase, *this)
-        , template_body(*this)
-        , template_arg(*this)
-        , do_template(*this)
-        , url_pre(phrase, url_pre_, *this)
-        , url_post(phrase, url_post_, *this)
-        , link_pre(phrase, link_pre_, *this)
-        , link_post(phrase, link_post_, *this)
-        , table(*this)
-        , start_row(phrase, table_span, table_header, *this)
-        , end_row(phrase, end_row_, *this)
-        , cell(phrase, table_span, *this)
-        , anchor(*this)
-
-        , begin_section(out, phrase, doc_id, section_id, section_level, qualified_section_id, element_id, *this)
-        , end_section(out, section_level, min_section_level, qualified_section_id, error_count, *this)
-        , xinclude(out, *this)
-        , include(*this)
-        , import(out, *this)
 
-        , escape_pre(phrase, escape_pre_, *this)
-        , escape_post(phrase, escape_post_, *this)
-        
-        , inner_phrase_pre(*this)
-        , inner_phrase_post(*this)
-        , output_pre(*this)
+        , element_id_warning(*this)
     {
-        // turn off __FILENAME__ macro on debug mode = true
-        std::string filename_str = debug_mode ?
-            std::string("NO_FILENAME_MACRO_GENERATED_IN_DEBUG_MODE") :
-            filename.string();
-
         // add the predefined macros
         macro.add
             ("__DATE__", std::string(quickbook_get_date))
             ("__TIME__", std::string(quickbook_get_time))
-            ("__FILENAME__", filename_str)
+            ("__FILENAME__", detail::path_to_generic(filename_relative))
         ;
         
         boost::scoped_ptr<quickbook_grammar> g(
@@ -225,7 +100,7 @@
         state_stack.push(
             boost::make_tuple(
                 filename
-              , outdir
+              , xinclude_base
               , macro_change_depth
               , section_level
               , min_section_level
@@ -237,8 +112,8 @@
 
         out.push();
         phrase.push();
-        list_buffer.push();
-        templates.push();        
+        templates.push();
+        values.builder.save();
     }
     
     // Pushing and popping the macro symbol table is pretty expensive, so
@@ -265,7 +140,7 @@
     
         boost::tie(
             filename
-          , outdir
+          , xinclude_base
           , macro_change_depth
           , section_level
           , min_section_level
@@ -277,8 +152,8 @@
 
         out.pop();
         phrase.pop();
-        list_buffer.pop();
         templates.pop();
+        values.builder.restore();
     }
     
     quickbook_grammar& actions::grammar() const {
Modified: branches/release/tools/quickbook/src/actions_class.hpp
==============================================================================
--- branches/release/tools/quickbook/src/actions_class.hpp	(original)
+++ branches/release/tools/quickbook/src/actions_class.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -10,10 +10,12 @@
 #if !defined(BOOST_SPIRIT_ACTIONS_CLASS_HPP)
 #define BOOST_SPIRIT_ACTIONS_CLASS_HPP
 
-#include "actions.hpp"
-#include "scoped_parser.hpp"
 #include <boost/tuple/tuple.hpp>
 #include <boost/scoped_ptr.hpp>
+#include "actions.hpp"
+#include "parsers.hpp"
+#include "values_parse.hpp"
+#include "collector.hpp"
 
 namespace quickbook
 {
@@ -22,7 +24,7 @@
 
     struct actions
     {
-        actions(char const* filein_, fs::path const& outdir, string_stream& out_);
+        actions(fs::path const& filein_, fs::path const& xinclude_base, string_stream& out_);
 
     private:
         boost::scoped_ptr<quickbook_grammar> grammar_;
@@ -34,49 +36,40 @@
 
         typedef std::vector<std::string> string_list;
 
-        typedef std::vector<docinfo_string> docinfo_list;
-        typedef std::pair<docinfo_string, docinfo_string> author;
-        typedef std::vector<author> author_list;
-        typedef std::pair<string_list, docinfo_string> copyright_item;
-        typedef std::vector<copyright_item> copyright_list;
-        typedef std::pair<std::string, docinfo_string> biblioid_item;
-        typedef std::vector<biblioid_item> biblioid_list;
-        typedef std::pair<char, int> mark_type;
         static int const max_template_depth = 100;
 
     // header info
         std::string             doc_type;
-        docinfo_string          doc_title;
-        docinfo_string          doc_version;
+        std::string             doc_title_qbk;
         std::string             doc_id;
-        docinfo_string          doc_dirname;
-        copyright_list          doc_copyrights;
-        docinfo_string          doc_purpose;
-        docinfo_list            doc_categories;
-        author_list             doc_authors;
-        docinfo_string          doc_license;
-        docinfo_string          doc_last_revision;
-        biblioid_list           doc_biblioid_items;
-        docinfo_string          doc_lang;
-        std::string             include_doc_id;
-        //temporary state
-        biblioid_item           doc_biblioid;
-        docinfo_string          doc_id_tmp;
-        author                  name;
-        copyright_item          copyright;
-        docinfo_string          doc_category;
-
 
     // main output stream
         collector               out;
 
     // auxilliary streams
         collector               phrase;
-        collector               list_buffer;
+
+    // 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;
 
     // state
         fs::path                filename;
-        fs::path                outdir;
+        fs::path                filename_relative;  // for the __FILENAME__ macro.
+                                                    // (relative to the original file
+                                                    //  or include path).
+        fs::path                xinclude_base;
         std::size_t             macro_change_depth;
         string_symbols          macro;
         int                     section_level;
@@ -101,30 +94,14 @@
         std::stack<string_symbols> macro_stack;
 
     // temporary or global state
-        std::string             element_id;
-        std::string             table_title;
-        unsigned                table_span;
-        std::string             table_header;
-        std::string             macro_id;
-        std::stack<mark_type>   list_marks;
-        int                     list_indent;
-        bool                    condition;
-        std::string             template_identifier;
-        string_list             template_info;
         int                     template_depth;
-        bool                    template_escape;
-        bool                    template_block;
-        std::vector<quickbook::template_body>
-                                template_args;
         template_stack          templates;
         int                     error_count;
-        std::string             image_fileref;
-        std::string             attribute_name;
-        attribute_map           attributes;
         string_list             anchors;
-        string_list             saved_anchors;
         bool                    no_eols;
         bool                    suppress;
+        bool                    warned_about_breaks;
+        int                     context;
 
     // push/pop the states and the streams
         void copy_macros_for_write();
@@ -135,127 +112,25 @@
     ///////////////////////////////////////////////////////////////////////////
     // actions
     ///////////////////////////////////////////////////////////////////////////
-        error_action            error;
-        phrase_to_docinfo_action extract_doc_title;
-        phrase_to_docinfo_action extract_doc_license;
-        phrase_to_docinfo_action extract_doc_purpose;
-        phrase_to_docinfo_action extract_doc_version;
-        phrase_to_docinfo_action extract_doc_id;
-        phrase_to_docinfo_action extract_doc_dirname;
-        phrase_to_docinfo_action extract_copyright_second;
-        phrase_to_docinfo_action extract_name_second;
-        phrase_to_docinfo_action extract_name_first;
-        phrase_to_docinfo_action extract_doc_last_revision;
-        phrase_to_docinfo_action extract_doc_category;
-        phrase_to_docinfo_action extract_doc_biblioid;
-        phrase_to_docinfo_action extract_doc_lang;
 
-        scoped_parser<scoped_block_push>
-                                scoped_block;
+        element_action          element;
+        error_action            error;
 
         code_action             code;
         code_action             code_block;
         inline_code_action      inline_code;
-        implicit_paragraph_action inside_paragraph;
-        generic_header_action   h;
-        header_action           h1, h2, h3, h4, h5, h6;
-        markup_action           hr;
-        tagged_action           blurb, blockquote;
-        scoped_parser<set_no_eols_scoped>
-                                set_no_eols;
-        phrase_action           preformatted;
-        tagged_action           warning, caution, important, note, tip;
+        paragraph_action        paragraph;
         space                   space_char;
         plain_char_action       plain_char;
         raw_char_action         raw_char;
         escape_unicode_action   escape_unicode;
-        attribute_action        attribute;
-        image_action            image;
-        cond_phrase_action_pre  cond_phrase_pre;
-        scoped_parser<cond_phrase_push>
-                                scoped_cond_phrase;
 
-        list_action             list;
-        list_format_action      list_format;
-        phrase_action           list_item;
-
-        link_action             funcref_pre;
-        markup_action           funcref_post;
-        link_action             classref_pre;
-        markup_action           classref_post;
-        link_action             memberref_pre;
-        markup_action           memberref_post;
-        link_action             enumref_pre;
-        markup_action           enumref_post;
-        link_action             macroref_pre;
-        markup_action           macroref_post;
-        link_action             headerref_pre;
-        markup_action           headerref_post;
-        link_action             conceptref_pre;
-        markup_action           conceptref_post;
-        link_action             globalref_pre;
-        markup_action           globalref_post;
-
-        markup_action           bold_pre;
-        markup_action           bold_post;
-        markup_action           italic_pre;
-        markup_action           italic_post;
-        markup_action           underline_pre;
-        markup_action           underline_post;
-        markup_action           teletype_pre;
-        markup_action           teletype_post;
-        markup_action           strikethrough_pre;
-        markup_action           strikethrough_post;
-        markup_action           quote_pre;
-        markup_action           quote_post;
-        markup_action           replaceable_pre;
-        markup_action           replaceable_post;
-        markup_action           footnote_pre;
-        markup_action           footnote_post;
-
-        simple_phrase_action    simple_bold;
-        simple_phrase_action    simple_italic;
-        simple_phrase_action    simple_underline;
-        simple_phrase_action    simple_teletype;
-        simple_phrase_action    simple_strikethrough;
-
-        variablelist_action     variablelist;
-        markup_action           start_varlistentry;
-        markup_action           end_varlistentry;
-        markup_action           start_varlistterm;
-        markup_action           end_varlistterm;
-        tagged_action           varlistitem;
+        simple_phrase_action    simple_markup;
 
         break_action            break_;
-        macro_identifier_action macro_identifier;
-        macro_definition_action macro_definition;
         do_macro_action         do_macro;
-        template_body_action    template_body;
-        template_arg_action     template_arg;
-        do_template_action      do_template;
-        link_action             url_pre;
-        markup_action           url_post;
-        link_action             link_pre;
-        markup_action           link_post;
-        table_action            table;
-        start_row_action        start_row;
-        markup_action           end_row;
-        col_action              cell;
-        anchor_action           anchor;
 
-        begin_section_action    begin_section;
-        end_section_action      end_section;
         element_id_warning_action element_id_warning;
-        xinclude_action         xinclude;
-        include_action          include;
-        import_action           import;
-
-        markup_action           escape_pre;
-        markup_action           escape_post;
-
-        inner_phrase_action_pre inner_phrase_pre;
-        inner_phrase_action_post inner_phrase_post;
-        pre_output_action       output_pre;
     };
 }
 
Modified: branches/release/tools/quickbook/src/block_element_grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/block_element_grammar.cpp	(original)
+++ branches/release/tools/quickbook/src/block_element_grammar.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -11,22 +11,25 @@
 #include "utils.hpp"
 #include "actions_class.hpp"
 #include "grammar_impl.hpp"
+#include "block_tags.hpp"
+#include "template_tags.hpp"
 #include <boost/spirit/include/classic_assign_actor.hpp>
 #include <boost/spirit/include/classic_if.hpp>
 #include <boost/spirit/include/classic_clear_actor.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+#include <boost/spirit/include/phoenix1_casts.hpp>
 
 namespace quickbook
 {
     namespace cl = boost::spirit::classic;
+    namespace ph = phoenix;
 
     struct block_element_grammar_local
     {
         cl::rule<scanner>
-                        h, h1, h2, h3, h4, h5, h6, blurb, blockquote,
-                        warning, caution, important, note, tip,
-                        inner_phrase, def_macro,
+                        heading, inner_block, inner_phrase, def_macro,
                         table, table_row, variablelist,
-                        varlistentry, varlistterm, varlistitem, table_cell,
+                        varlistentry, varlistterm, list, cell,
                         preformatted, begin_section, end_section,
                         xinclude, include,
                         template_, template_id, template_formal_arg,
@@ -36,144 +39,94 @@
 
     void quickbook_grammar::impl::init_block_elements()
     {
-        using detail::var;
-
-        block_element_grammar_local& local = store_.create();
+        block_element_grammar_local& local = cleanup_.add(
+            new block_element_grammar_local);
 
         local.element_id =
-                ':'
-            >>
-                (
-                    cl::if_p(qbk_since(105u)) [space]
-                >>  (+(cl::alnum_p | '_'))      [cl::assign_a(actions.element_id)]
+            !(  ':'
+            >>  (   cl::if_p(qbk_since(105u)) [space]
+                >>  (+(cl::alnum_p | '_'))      [actions.values.entry(ph::arg1, ph::arg2, general_tags::element_id)]
                 |   cl::eps_p                   [actions.element_id_warning]
-                                                [cl::assign_a(actions.element_id)]
                 )
-            | cl::eps_p                         [cl::assign_a(actions.element_id)]
+            )
             ;
         
         local.element_id_1_5 =
                 cl::if_p(qbk_since(105u)) [
                     local.element_id
                 ]
-                .else_p [
-                    cl::eps_p                   [cl::assign_a(actions.element_id)]
-                ]
                 ;
 
         local.element_id_1_6 =
                 cl::if_p(qbk_since(106u)) [
                     local.element_id
                 ]
-                .else_p [
-                    cl::eps_p                   [cl::assign_a(actions.element_id)]
-                ]
                 ;
 
         elements.add
-            ("section", element_info(element_info::block, &local.begin_section))
-            ("endsect", element_info(element_info::block, &local.end_section))
+            ("section", element_info(element_info::block, &local.begin_section, block_tags::begin_section))
+            ("endsect", element_info(element_info::block, &local.end_section, block_tags::end_section))
             ;
 
         local.begin_section =
                 space
             >>  local.element_id
             >>  space
-            >>  local.inner_phrase              [actions.begin_section]
+            >>  local.inner_phrase
             ;
 
         local.end_section =
-                cl::eps_p                       [actions.end_section]
+                cl::eps_p
             ;
 
-        elements.add
-            ("heading", element_info(element_info::block, &local.h))
-            ("h1", element_info(element_info::block, &local.h1))
-            ("h2", element_info(element_info::block, &local.h2))
-            ("h3", element_info(element_info::block, &local.h3))
-            ("h4", element_info(element_info::block, &local.h4))
-            ("h5", element_info(element_info::block, &local.h5))
-            ("h6", element_info(element_info::block, &local.h6))
-            ;
-
-        local.h  = space >> local.element_id_1_6 >> space >> local.inner_phrase [actions.h];
-        local.h1 = space >> local.element_id_1_6 >> space >> local.inner_phrase [actions.h1];
-        local.h2 = space >> local.element_id_1_6 >> space >> local.inner_phrase [actions.h2];
-        local.h3 = space >> local.element_id_1_6 >> space >> local.inner_phrase [actions.h3];
-        local.h4 = space >> local.element_id_1_6 >> space >> local.inner_phrase [actions.h4];
-        local.h5 = space >> local.element_id_1_6 >> space >> local.inner_phrase [actions.h5];
-        local.h6 = space >> local.element_id_1_6 >> space >> local.inner_phrase [actions.h6];
-        
-        static const bool true_ = true;
-        static const bool false_ = false;
-
-        elements.add("blurb", element_info(element_info::block, &local.blurb));
-
-        local.blurb =
-            actions.scoped_block[inside_paragraph]
-                                                [actions.blurb]
+        local.heading
+            =   space
+            >>  local.element_id_1_6
+            >>  space
+            >>  local.inner_phrase
             ;
 
         elements.add
-            (":", element_info(element_info::block, &local.blockquote))
-            ;
-
-        local.blockquote =
-            blank >> actions.scoped_block[inside_paragraph]
-                                                [actions.blockquote]
+            ("heading", element_info(element_info::conditional_or_block, &local.heading, block_tags::generic_heading))
+            ("h1", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading1))
+            ("h2", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading2))
+            ("h3", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading3))
+            ("h4", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading4))
+            ("h5", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading5))
+            ("h6", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading6))
             ;
 
         elements.add
-            ("warning", element_info(element_info::block, &local.warning))
-            ("caution", element_info(element_info::block, &local.caution))
-            ("important", element_info(element_info::block, &local.important))
-            ("note", element_info(element_info::block, &local.note))
-            ("tip", element_info(element_info::block, &local.tip))
-            ;
-
-        local.warning =
-            actions.scoped_block[inside_paragraph]
-                                                [actions.warning]
-            ;
-
-        local.caution =
-            actions.scoped_block[inside_paragraph]
-                                                [actions.caution]
-            ;
-
-        local.important =
-            actions.scoped_block[inside_paragraph]
-                                                [actions.important]
-            ;
-
-        local.note =
-            actions.scoped_block[inside_paragraph]
-                                                [actions.note]
-            ;
-
-        local.tip =
-            actions.scoped_block[inside_paragraph]
-                                                [actions.tip]
+            ("blurb", element_info(element_info::nested_block, &local.inner_block, block_tags::blurb))
+            (":", element_info(element_info::nested_block, &local.inner_block, block_tags::blockquote))
+            ("warning", element_info(element_info::nested_block, &local.inner_block, block_tags::warning))
+            ("caution", element_info(element_info::nested_block, &local.inner_block, block_tags::caution))
+            ("important", element_info(element_info::nested_block, &local.inner_block, block_tags::important))
+            ("note", element_info(element_info::nested_block, &local.inner_block, block_tags::note))
+            ("tip", element_info(element_info::nested_block, &local.inner_block, block_tags::tip))
             ;
 
         elements.add
-            ("pre", element_info(element_info::block, &local.preformatted))
+            ("pre", element_info(element_info::nested_block, &local.preformatted, block_tags::preformatted))
             ;
 
         local.preformatted =
                 space
             >>  !eol
-            >>  actions.set_no_eols[phrase]     [actions.preformatted]
+            >>  actions.scoped_no_eols()
+                [   local.inner_phrase
+                ]
             ;
 
         elements.add
-            ("def", element_info(element_info::block, &local.def_macro))
+            ("def", element_info(element_info::conditional_or_block, &local.def_macro, block_tags::macro_definition))
             ;
 
         local.def_macro =
                space
-            >> macro_identifier                 [actions.macro_identifier]
-            >> blank >> phrase                  [actions.macro_definition]
+            >> macro_identifier                 [actions.values.entry(ph::arg1, ph::arg2)]
+            >> blank
+            >> local.inner_phrase
             ;
 
         local.identifier =
@@ -185,27 +138,26 @@
             ;
 
         elements.add
-            ("template", element_info(element_info::block, &local.template_))
+            ("template", element_info(element_info::conditional_or_block, &local.template_, block_tags::template_definition))
             ;
 
         local.template_ =
                space
-            >> local.template_id                [cl::assign_a(actions.template_identifier)]
-                                                [cl::clear_a(actions.template_info)]
-            >>
+            >> local.template_id                [actions.values.entry(ph::arg1, ph::arg2)]
+            >> actions.values.list()[
             !(
                 space >> '['
                 >> *(
                         space
-                    >>  local.template_id       [cl::push_back_a(actions.template_info)]
+                    >>  local.template_id       [actions.values.entry(ph::arg1, ph::arg2)]
                     )
                 >> space >> ']'
             )
+            ]
             >>  (   cl::eps_p(*cl::blank_p >> cl::eol_p)
-                                                [cl::assign_a(actions.template_block, true_)]
-                |   cl::eps_p                   [cl::assign_a(actions.template_block, false_)]
+                >>  local.template_body         [actions.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+                |   local.template_body         [actions.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
                 )
-            >>  local.template_body             [actions.template_body]
             ;
 
         local.template_body =
@@ -215,119 +167,103 @@
             ;
 
         elements.add
-            ("variablelist", element_info(element_info::block, &local.variablelist))
+            ("variablelist", element_info(element_info::nested_block, &local.variablelist, block_tags::variable_list))
             ;
 
         local.variablelist =
                 (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
-            >>  (*(cl::anychar_p - eol))        [cl::assign_a(actions.table_title)]
-            >>  (+eol)                          [actions.output_pre]
+            >>  (*(cl::anychar_p - eol))        [actions.values.entry(ph::arg1, ph::arg2, table_tags::title)]
+            >>  (+eol)
             >>  *local.varlistentry
-            >>  cl::eps_p                       [actions.variablelist]
             ;
 
         local.varlistentry =
             space
-            >>  cl::ch_p('[')                   [actions.start_varlistentry]
-            >>
-            (
+            >>  cl::ch_p('[')
+            >>  actions.values.list()
+            [
                 (
                     local.varlistterm
-                    >>  (   actions.scoped_block [+local.varlistitem]
-                                                [actions.varlistitem]
+                    >>  (   +local.cell
                         |   cl::eps_p           [actions.error]
                         )
-                    >>  cl::ch_p(']')           [actions.end_varlistentry]
+                    >>  cl::ch_p(']')
                     >>  space
                 )
                 | cl::eps_p                     [actions.error]
-            )
+            ]
             ;
 
         local.varlistterm =
             space
-            >>  cl::ch_p('[')                   [actions.start_varlistterm]
-            >>
-            (
-                (
-                    phrase
-                    >>  cl::ch_p(']')           [actions.end_varlistterm]
-                    >>  space
-                )
-                | cl::eps_p                     [actions.error]
-            )
-            ;
-
-        local.varlistitem =
-            space
             >>  cl::ch_p('[')
-            >>
-            (
-                (
-                    inside_paragraph
-                    >>  cl::ch_p(']')
-                    >>  space
+            >>  local.inner_phrase
+            >>  (   cl::ch_p(']')
+                >>  space
+                |   cl::eps_p                   [actions.error]
                 )
-                | cl::eps_p                     [actions.error]
-            )
             ;
 
         elements.add
-            ("table", element_info(element_info::block, &local.table))
+            ("table", element_info(element_info::nested_block, &local.table, block_tags::table))
             ;
 
         local.table =
                 (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
             >>  local.element_id_1_5
             >>  (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
-            >>  (*(cl::anychar_p - eol))        [cl::assign_a(actions.table_title)]
-            >>  (+eol)                          [actions.output_pre]
+            >>  (*(cl::anychar_p - eol))        [actions.values.entry(ph::arg1, ph::arg2, table_tags::title)]
+            >>  (+eol)
             >>  *local.table_row
-            >>  cl::eps_p                       [actions.table]
             ;
 
         local.table_row =
             space
-            >>  cl::ch_p('[')                   [actions.start_row]
+            >>  cl::ch_p('[')
             >>
             (
                 (
-                    *local.table_cell
-                    >>  cl::ch_p(']')           [actions.end_row]
+                    actions.values.list(table_tags::row)
+                    [   *local.cell
+                    ]
+                    >>  cl::ch_p(']')
                     >>  space
                 )
                 | cl::eps_p                     [actions.error]
             )
             ;
 
-        local.table_cell =
+        elements.add
+            ("ordered_list", element_info(element_info::nested_block, &local.list, block_tags::ordered_list, 106))
+            ("itemized_list", element_info(element_info::nested_block, &local.list, block_tags::itemized_list, 106))
+            ;
+
+        local.list = *local.cell;
+
+        local.cell =
                 space
             >>  cl::ch_p('[')
-            >>  (   actions.scoped_block [
-                        inside_paragraph
-                    >>  cl::ch_p(']')
-                    >>  space
-                    ]                           [actions.cell]
-                | cl::eps_p                     [actions.error]
+            >>  (   local.inner_block
+                >>  cl::ch_p(']')
+                >>  space
+                |   cl::eps_p                   [actions.error]
                 )
             ;
 
         elements.add
-            ("xinclude", element_info(element_info::conditional_or_block, &local.xinclude))
-            ("import", element_info(element_info::conditional_or_block, &local.import))
-            ("include", element_info(element_info::conditional_or_block, &local.include))
+            ("xinclude", element_info(element_info::conditional_or_block, &local.xinclude, block_tags::xinclude))
+            ("import", element_info(element_info::conditional_or_block, &local.import, block_tags::import))
+            ("include", element_info(element_info::conditional_or_block, &local.include, block_tags::include))
             ;
 
         local.xinclude =
                space
-            >> (*(cl::anychar_p - phrase_end))
-                                                [actions.xinclude]
+            >> (*(cl::anychar_p - phrase_end))  [actions.values.entry(ph::arg1, ph::arg2)]
             ;
 
         local.import =
                space
-            >> (*(cl::anychar_p - phrase_end))
-                                                [actions.import]
+            >> (*(cl::anychar_p - phrase_end))  [actions.values.entry(ph::arg1, ph::arg2)]
             ;
 
         local.include =
@@ -336,17 +272,24 @@
            !(
                 ':'
                 >> (*((cl::alnum_p | '_') - cl::space_p))
-                                                [cl::assign_a(actions.include_doc_id)]
+                                                [actions.values.entry(ph::arg1, ph::arg2, general_tags::include_id)]
                 >> space
             )
-            >> (*(cl::anychar_p - phrase_end))
-                                                [actions.include]
+            >> (*(cl::anychar_p - phrase_end))  [actions.values.entry(ph::arg1, ph::arg2)]
+            ;
+
+        local.inner_block =
+            actions.scoped_output()
+            [
+                inside_paragraph                [actions.out_value]
+            ]
             ;
 
         local.inner_phrase =
-                cl::eps_p                       [actions.inner_phrase_pre]
-            >>  phrase
-            >>  cl::eps_p                       [actions.inner_phrase_post]
+            actions.scoped_output()
+            [
+                phrase                          [actions.docinfo_value(ph::arg1, ph::arg2)]
+            ]
             ;
     }
 }
Copied: branches/release/tools/quickbook/src/block_tags.hpp (from r70210, /trunk/tools/quickbook/src/block_tags.hpp)
==============================================================================
--- /trunk/tools/quickbook/src/block_tags.hpp	(original)
+++ branches/release/tools/quickbook/src/block_tags.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -23,7 +23,8 @@
         (variable_list)(table)
         (xinclude)(import)(include)
         (paragraph)
-        (list)
+        (list)(ordered_list)(itemized_list)
+        (hr)
     )
 
     QUICKBOOK_VALUE_TAGS(table_tags, 0x250,
Modified: branches/release/tools/quickbook/src/code_snippet.cpp
==============================================================================
--- branches/release/tools/quickbook/src/code_snippet.cpp	(original)
+++ branches/release/tools/quickbook/src/code_snippet.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -10,10 +10,12 @@
 #include <boost/spirit/include/classic_core.hpp>
 #include <boost/spirit/include/classic_actor.hpp>
 #include <boost/spirit/include/classic_confix.hpp>
+#include <boost/shared_ptr.hpp>
 #include <boost/bind.hpp>
 #include <boost/lexical_cast.hpp>
 #include "template_stack.hpp"
 #include "actions.hpp"
+#include "values.hpp"
 
 namespace quickbook
 {
@@ -22,10 +24,12 @@
     struct code_snippet_actions
     {
         code_snippet_actions(std::vector<template_symbol>& storage,
+                                 std::string const& filename,
                                  std::string const& doc_id,
                                  char const* source_type)
             : callout_id(0)
             , storage(storage)
+            , filename(filename)
             , doc_id(doc_id)
             , source_type(source_type)
         {}
@@ -49,20 +53,38 @@
                 , start_code(false)
                 , end_code(false)
             {}
-
+            
             std::string id;
             int callout_base_id;
             std::string content;
             bool start_code;
             bool end_code;
-            std::vector<template_body> callouts;
+            value_builder callouts;
+            boost::shared_ptr<snippet_data> next;
         };
         
+        void push_snippet_data(std::string const& id, int callout_base_id)
+        {
+            boost::shared_ptr<snippet_data> new_snippet(
+                new snippet_data(id, callout_base_id));
+            new_snippet->next = snippet_stack;
+            snippet_stack = new_snippet;
+        }
+
+        boost::shared_ptr<snippet_data> pop_snippet_data()
+        {
+            boost::shared_ptr<snippet_data> snippet(snippet_stack);
+            snippet_stack = snippet->next;
+            snippet->next.reset();
+            return snippet;
+        }
+        
         int callout_id;
-        std::stack<snippet_data> snippet_stack;
+        boost::shared_ptr<snippet_data> snippet_stack;
         std::string code;
         std::string id;
         std::vector<template_symbol>& storage;
+        fs::path filename;
         std::string const doc_id;
         char const* const source_type;
     };
@@ -96,6 +118,7 @@
                         start_snippet               [boost::bind(&actions_type::start_snippet, &actions, _1, _2)]
                     |   end_snippet                 [boost::bind(&actions_type::end_snippet, &actions, _1, _2)]
                     |   escaped_comment
+                    |   pass_thru_comment
                     |   ignore
                     |   cl::anychar_p               [boost::bind(&actions_type::pass_thru_char, &actions, _1)]
                     ;
@@ -139,11 +162,25 @@
                             "\"\"\""
                         )
                     ;
+
+                // Note: Unlike escaped_comment and ignore, this doesn't
+                // swallow preceeding whitespace.
+                pass_thru_comment
+                    =   "#="
+                    >>  (   *(cl::anychar_p - cl::eol_p)
+                        >>  (cl::eol_p | cl::end_p)
+                        )                           [boost::bind(&actions_type::pass_thru, &actions, _1, _2)]
+                    |   cl::confix_p(
+                            "\"\"\"=",
+                            (*cl::anychar_p)        [boost::bind(&actions_type::pass_thru, &actions, _1, _2)],
+                            "\"\"\""
+                        )
+                    ;
             }
 
             cl::rule<Scanner>
                 start_, identifier, code_elements, start_snippet, end_snippet,
-                escaped_comment, ignore;
+                escaped_comment, pass_thru_comment, ignore;
 
             cl::rule<Scanner> const&
             start() const { return start_; }
@@ -179,6 +216,7 @@
                     |   end_snippet                 [boost::bind(&actions_type::end_snippet, &actions, _1, _2)]
                     |   escaped_comment
                     |   ignore
+                    |   pass_thru_comment
                     |   line_callout
                     |   inline_callout
                     |   cl::anychar_p               [boost::bind(&actions_type::pass_thru_char, &actions, _1)]
@@ -246,11 +284,25 @@
                             "*/"
                         )
                     ;
+
+                // Note: Unlike escaped_comment and ignore, this doesn't
+                // swallow preceeding whitespace.
+                pass_thru_comment
+                    =   "//="
+                    >>  (   *(cl::anychar_p - cl::eol_p)
+                        >>  (cl::eol_p | cl::end_p)
+                        )                           [boost::bind(&actions_type::pass_thru, &actions, _1, _2)]
+                    |   cl::confix_p(
+                            "/*`",
+                            (*cl::anychar_p)        [boost::bind(&actions_type::pass_thru, &actions, _1, _2)],
+                            "*/"
+                        )
+                    ;
             }
 
             cl::rule<Scanner>
             start_, identifier, code_elements, start_snippet, end_snippet,
-                escaped_comment, inline_callout, line_callout, ignore;
+                escaped_comment, pass_thru_comment, inline_callout, line_callout, ignore;
 
             cl::rule<Scanner> const&
             start() const { return start_; }
@@ -271,13 +323,11 @@
         if (err != 0)
             return err; // return early on error
 
-        iterator first(code.begin(), code.end(), file.c_str());
-        iterator last(code.end(), code.end());
+        iterator first(code.begin());
+        iterator last(code.end());
 
-        size_t fname_len = file.size();
-        bool is_python = fname_len >= 3
-            && file[--fname_len]=='y' && file[--fname_len]=='p' && file[--fname_len]=='.';
-        code_snippet_actions a(storage, doc_id, is_python ? "[python]" : "[c++]");
+        bool is_python = extension == ".py";
+        code_snippet_actions a(storage, file, doc_id, is_python ? "[python]" : "[c++]");
         // TODO: Should I check that parse succeeded?
         if(is_python) {
             boost::spirit::classic::parse(first, last, python_code_snippet_grammar(a));
@@ -291,8 +341,8 @@
 
     void code_snippet_actions::append_code()
     {
-        if(snippet_stack.empty()) return;
-        snippet_data& snippet = snippet_stack.top();
+        if(!snippet_stack) return;
+        snippet_data& snippet = *snippet_stack;
     
         if (!code.empty())
         {
@@ -318,8 +368,8 @@
 
     void code_snippet_actions::close_code()
     {
-        if(snippet_stack.empty()) return;
-        snippet_data& snippet = snippet_stack.top();
+        if(!snippet_stack) return;
+        snippet_data& snippet = *snippet_stack;
     
         if(snippet.end_code)
         {
@@ -330,30 +380,29 @@
 
     void code_snippet_actions::pass_thru(iterator first, iterator last)
     {
-        if(snippet_stack.empty()) return;
-        code += *first;
+        if(!snippet_stack) return;
+        code.append(first, last);
     }
 
     void code_snippet_actions::pass_thru_char(char c)
     {
-        if(snippet_stack.empty()) return;
+        if(!snippet_stack) return;
         code += c;
     }
 
     void code_snippet_actions::callout(iterator first, iterator last)
     {
-        if(snippet_stack.empty()) return;
+        if(!snippet_stack) return;
         code += "``[[callout" + boost::lexical_cast<std::string>(callout_id) + "]]``";
     
-        snippet_stack.top().callouts.push_back(
-            template_body(std::string(first, last), first.get_position(), true));
+        snippet_stack->callouts.insert(qbk_value(first, last, template_tags::block));
         ++callout_id;
     }
 
     void code_snippet_actions::escaped_comment(iterator first, iterator last)
     {
-        if(snippet_stack.empty()) return;
-        snippet_data& snippet = snippet_stack.top();
+        if(!snippet_stack) return;
+        snippet_data& snippet = *snippet_stack;
         append_code();
         close_code();
 
@@ -365,53 +414,56 @@
         }
     }
 
-    void code_snippet_actions::start_snippet(iterator first, iterator last)
+    void code_snippet_actions::start_snippet(iterator, iterator)
     {
         append_code();
-        snippet_stack.push(snippet_data(id, callout_id));
+        push_snippet_data(id, callout_id);
         id.clear();
     }
 
-    void code_snippet_actions::end_snippet(iterator first, iterator last)
+    void code_snippet_actions::end_snippet(iterator first, iterator)
     {
         // TODO: Error?
-        if(snippet_stack.empty()) return;
+        if(!snippet_stack) return;
 
         append_code();
 
-        snippet_data snippet = snippet_stack.top();
-        snippet_stack.pop();
+        boost::shared_ptr<snippet_data> snippet = pop_snippet_data();
+        value callouts = snippet->callouts.release();
 
         std::string body;
-        if(snippet.start_code) {
+        if(snippet->start_code) {
             body += "\n\n";
             body += source_type;
             body += "```\n";
         }
-        body += snippet.content;
-        if(snippet.end_code) {
+        body += snippet->content;
+        if(snippet->end_code) {
             body += "```\n\n";
         }
-        
+
         std::vector<std::string> params;
-        for (size_t i = 0; i < snippet.callouts.size(); ++i)
+        int i = 0;
+        for(value::iterator it = callouts.begin(); it != callouts.end(); ++it)
         {
-            params.push_back("[callout" + boost::lexical_cast<std::string>(snippet.callout_base_id + i) + "]");
+            params.push_back("[callout" + boost::lexical_cast<std::string>(snippet->callout_base_id + i) + "]");
+            ++i;
         }
         
         // TODO: Save position in start_snippet
-        template_symbol symbol(snippet.id, params, body, first.get_position(), true);
-        symbol.callout = true;
-        symbol.callouts = snippet.callouts;
+        template_symbol symbol(snippet->id, params,
+            qbk_value(body, first.get_position(), template_tags::block),
+            filename);
+        symbol.callouts = callouts;
         storage.push_back(symbol);
 
         // Merge the snippet into its parent
 
-        if(!snippet_stack.empty())
+        if(snippet_stack)
         {
-            snippet_data& next = snippet_stack.top();
-            if(!snippet.content.empty()) {
-                if(!snippet.start_code) {
+            snippet_data& next = *snippet_stack;
+            if(!snippet->content.empty()) {
+                if(!snippet->start_code) {
                     close_code();
                 }
                 else if(!next.end_code) {
@@ -420,11 +472,11 @@
                     next.content += "```\n";
                 }
                 
-                next.content += snippet.content;
-                next.end_code = snippet.end_code;
+                next.content += snippet->content;
+                next.end_code = snippet->end_code;
             }
-            
-            next.callouts.insert(next.callouts.end(), snippet.callouts.begin(), snippet.callouts.end());
+
+            next.callouts.extend(callouts);
         }
     }
 }
Modified: branches/release/tools/quickbook/src/doc_info_actions.cpp
==============================================================================
--- branches/release/tools/quickbook/src/doc_info_actions.cpp	(original)
+++ branches/release/tools/quickbook/src/doc_info_actions.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -11,44 +11,130 @@
 #include <sstream>
 #include <boost/bind.hpp>
 #include <boost/algorithm/string/join.hpp>
+#include <boost/foreach.hpp>
 #include "quickbook.hpp"
 #include "utils.hpp"
+#include "input_path.hpp"
 #include "actions_class.hpp"
+#include "doc_info_tags.hpp"
 
 namespace quickbook
 {
-    std::string const& docinfo_string::get(unsigned version) const
+    static void write_document_title(collector& out, value const& title, value const& version);
+    
+    static std::string doc_info_output(value const& p, unsigned version)
+    {
+        return (qbk_version_n < version) ? p.get_quickbook() : p.get_boostbook();
+    }
+
+    value consume_last(value_consumer& c, value::tag_type tag,
+            std::vector<std::string>* duplicates)
     {
-        return (qbk_version_n < version) ? raw : encoded;
+        value p;
+
+        int count = 0;
+        while(c.check(tag)) {
+            p = c.consume();
+            ++count;
+        }
+
+        if(count > 1) duplicates->push_back(doc_info_attributes::name(tag));
+
+        return p;
+    }
+
+    value consume_last_single(value_consumer& c, value::tag_type tag,
+            std::vector<std::string>* duplicates)
+    {
+        value l = consume_last(c, tag, duplicates);
+        if(l.empty()) return l;
+
+        assert(l.is_list());
+        value_consumer c2 = l;
+        value p = c2.consume();
+        c2.finish();
+
+        return p;
     }
 
-    static void write_document_title(collector& out, quickbook::actions& actions);
-    static void write_document_info(collector& out, quickbook::actions& actions);
+    std::vector<value> consume_multiple(value_consumer& c, value::tag_type tag)
+    {
+        std::vector<value> values;
+        
+        while(c.check(tag)) {
+            values.push_back(c.consume());
+        }
+        
+        return values;
+    }
 
     void pre(collector& out, quickbook::actions& actions, bool ignore_docinfo)
     {
         // The doc_info in the file has been parsed. Here's what we'll do
         // *before* anything else.
 
-        if (!actions.doc_id_tmp.empty())
-            actions.doc_id = actions.doc_id_tmp.get(106);
+        value_consumer values = actions.values.release();
 
-        if (actions.doc_id.empty())
-            actions.doc_id = detail::make_identifier(
-                actions.doc_title.raw.begin(),actions.doc_title.raw.end());
+        // Skip over invalid attributes
+
+        while (values.check(value::default_tag)) values.consume();
+        
+        value qbk_version = values.optional_consume(doc_info_tags::qbk_version);
+        
+        value doc_title;
+        if (values.check())
+        {
+            actions.doc_type = values.consume(doc_info_tags::type).get_quickbook();
+            doc_title = values.consume(doc_info_tags::title);
+            actions.doc_title_qbk = doc_title.get_quickbook();
+        }
+
+        std::vector<std::string> duplicates;
+
+        value id = consume_last_single(values, doc_info_attributes::id, &duplicates);
+        value dirname = consume_last_single(values, doc_info_attributes::dirname, &duplicates);
+        value last_revision = consume_last_single(values, doc_info_attributes::last_revision, &duplicates);
+        value purpose = consume_last_single(values, doc_info_attributes::purpose, &duplicates);
+        std::vector<value> categories = consume_multiple(values, doc_info_attributes::category);
+        value lang = consume_last_single(values, doc_info_attributes::lang, &duplicates);
+        value version = consume_last_single(values, doc_info_attributes::version, &duplicates);
+        std::vector<value> authors = consume_multiple(values, doc_info_attributes::authors);
+        std::vector<value> copyrights = consume_multiple(values, doc_info_attributes::copyright);
+        value license = consume_last_single(values, doc_info_attributes::license, &duplicates);
+        std::vector<value> biblioids = consume_multiple(values, doc_info_attributes::biblioid);
+        
+        // Skip over source-mode tags (already dealt with)
+
+        while (values.check(doc_info_attributes::source_mode)) values.consume();
+
+        values.finish();
 
-        if (actions.doc_dirname.empty() && actions.doc_type == "library") {
-            if (!actions.doc_id_tmp.empty()) {
-                actions.doc_dirname = actions.doc_id_tmp;
+        if(!duplicates.empty())
+        {
+            detail::outwarn(actions.filename,1)
+                << (duplicates.size() > 1 ?
+                    "Duplicate attributes" : "Duplicate attribute")
+                << ":" << detail::utf8(boost::algorithm::join(duplicates, ", "))
+                << "\n"
+                ;
+        }
+
+        if (!id.empty())
+            actions.doc_id = id.get_quickbook();
+
+        if (actions.doc_id.empty())
+            actions.doc_id = detail::make_identifier(actions.doc_title_qbk);
+        
+        if (dirname.empty() && actions.doc_type == "library") {
+            if (!id.empty()) {
+                dirname = id;
             }
             else {
-                actions.doc_dirname.raw = actions.doc_dirname.encoded = actions.doc_id;
+                dirname = qbk_bbk_value(actions.doc_id, doc_info_attributes::dirname);
             }
         }
 
-        actions.doc_id_tmp.clear();
-
-        if (actions.doc_last_revision.empty())
+        if (last_revision.empty())
         {
             // default value for last-revision is now
 
@@ -60,7 +146,7 @@
                     "$" /* prevent CVS substitution */ "Date: %Y/%m/%d %H:%M:%S $"),
                 current_gm_time
             );
-            actions.doc_last_revision.raw = actions.doc_last_revision.encoded = strdate;
+            last_revision = qbk_bbk_value(strdate, doc_info_attributes::last_revision);
         }
 
         // if we're ignoring the document info, we're done.
@@ -71,31 +157,37 @@
 
         // Quickbook version
 
-        if (qbk_major_version == -1)
+        int qbk_major_version, qbk_minor_version;
+
+        if (qbk_version.empty())
         {
             // hard code quickbook version to v1.1
             qbk_major_version = 1;
             qbk_minor_version = 1;
-            qbk_version_n = 101;
-            detail::outwarn(actions.filename.string(),1)
+            detail::outwarn(actions.filename,1)
                 << "Warning: Quickbook version undefined. "
                 "Version 1.1 is assumed" << std::endl;
         }
         else
         {
-            qbk_version_n = ((unsigned) qbk_major_version * 100) +
-                (unsigned) qbk_minor_version;
+            value_consumer qbk_version_values(qbk_version);
+            qbk_major_version = qbk_version_values.consume().get_int();
+            qbk_minor_version = qbk_version_values.consume().get_int();
+            qbk_version_values.finish();
         }
         
+        qbk_version_n = ((unsigned) qbk_major_version * 100) +
+            (unsigned) qbk_minor_version;
+
         if (qbk_version_n == 106)
         {
-            detail::outwarn(actions.filename.string(),1)
+            detail::outwarn(actions.filename,1)
                 << "Quickbook 1.6 is still under development and is "
                 "likely to change in the future." << std::endl;
         }
         else if(qbk_version_n < 100 || qbk_version_n > 106)
         {
-            detail::outerr(actions.filename.string(),1)
+            detail::outerr(actions.filename,1)
                 << "Unknown version of quickbook: quickbook "
                 << qbk_major_version
                 << "."
@@ -110,22 +202,22 @@
         {
             std::vector<std::string> invalid_attributes;
 
-            if (!actions.doc_purpose.empty())
+            if (!purpose.empty())
                 invalid_attributes.push_back("purpose");
 
-            if (!actions.doc_categories.empty())
+            if (!categories.empty())
                 invalid_attributes.push_back("category");
 
-            if (!actions.doc_dirname.empty())
+            if (!dirname.empty())
                 invalid_attributes.push_back("dirname");
 
             if(!invalid_attributes.empty())
             {
-                detail::outwarn(actions.filename.string(),1)
+                detail::outwarn(actions.filename,1)
                     << (invalid_attributes.size() > 1 ?
                         "Invalid attributes" : "Invalid attribute")
-                    << " for '" << actions.doc_type << " document info': "
-                    << boost::algorithm::join(invalid_attributes, ", ")
+                    << " for '" << detail::utf8(actions.doc_type) << " document info': "
+                    << detail::utf8(boost::algorithm::join(invalid_attributes, ", "))
                     << "\n"
                     ;
             }
@@ -143,109 +235,87 @@
             << actions.doc_id
             << "\"\n";
         
-        if(!actions.doc_lang.empty())
+        if(!lang.empty())
         {
             out << "    lang=\""
-                << actions.doc_lang.get(106)
+                << doc_info_output(lang, 106)
                 << "\"\n";
         }
 
         if(actions.doc_type == "library")
         {
-            out << "    name=\"" << actions.doc_title.get(106) << "\"\n";
+            out << "    name=\"" << doc_info_output(doc_title, 106) << "\"\n";
         }
 
-        if(!actions.doc_dirname.empty())
+        if(!dirname.empty())
         {
             out << "    dirname=\""
-                << actions.doc_dirname.get(106)
+                << doc_info_output(dirname, 106)
                 << "\"\n";
         }
 
         out << "    last-revision=\""
-            << actions.doc_last_revision.get(106)
+            << doc_info_output(last_revision, 106)
             << "\" \n"
             << "    xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n";
-            
-        if(actions.doc_type == "library") {
-            write_document_info(out, actions);
-            write_document_title(out, actions);
-        }
-        else {
-            write_document_title(out, actions);
-            write_document_info(out, actions);
-        }
-    }
-    
-    void post(collector& out, quickbook::actions& actions, bool ignore_docinfo)
-    {
-        // if we're ignoring the document info, do nothing.
-        if (ignore_docinfo)
-        {
-            return;
-        }
 
-        // We've finished generating our output. Here's what we'll do
-        // *after* everything else.
-        out << "\n</" << actions.doc_type << ">\n\n";
-    }
-
-    void write_document_title(collector& out, quickbook::actions& actions)
-    {
-        if (!actions.doc_title.empty())
-        {
-            out << "  <title>"
-                << actions.doc_title.get(106);
-            if (!actions.doc_version.empty()) {
-                out << ' ' << actions.doc_version.get(106);
-            }
-            out<< "</title>\n\n\n";
-        }
-    }
-
-    void write_document_info(collector& out, quickbook::actions& actions)
-    {
         std::ostringstream tmp;
 
-        if(!actions.doc_authors.empty())
+        if(!authors.empty())
         {
             tmp << "    <authorgroup>\n";
-            for(actions::author_list::const_iterator
-                it = actions.doc_authors.begin(),
-                end = actions.doc_authors.end();
-                it != end; ++it)
+            BOOST_FOREACH(value_consumer author_values, authors)
             {
-                tmp << "      <author>\n"
-                    << "        <firstname>"
-                    << it->first.get(106)
-                    << "</firstname>\n"
-                    << "        <surname>"
-                    << it->second.get(106)
-                    << "</surname>\n"
-                    << "      </author>\n";
+                while (author_values.check()) {
+                    value surname = author_values.consume(doc_info_tags::author_surname);
+                    value first = author_values.consume(doc_info_tags::author_first);
+    
+                    tmp << "      <author>\n"
+                        << "        <firstname>"
+                        << doc_info_output(first, 106)
+                        << "</firstname>\n"
+                        << "        <surname>"
+                        << doc_info_output(surname, 106)
+                        << "</surname>\n"
+                        << "      </author>\n";
+                }
             }
             tmp << "    </authorgroup>\n";
         }
 
-        if (!actions.doc_copyrights.empty())
+        BOOST_FOREACH(value_consumer copyright, copyrights)
         {
-            for(actions::copyright_list::const_iterator
-                it = actions.doc_copyrights.begin(),
-                end = actions.doc_copyrights.end();
-                it != end; ++it)
+            while(copyright.check())
             {
                 tmp << "\n" << "    <copyright>\n";
-        
-                for(actions::string_list::const_iterator
-                    it2 = it->first.begin(),
-                    end = it->first.end();
-                    it2 != end; ++it2)
+    
+                while(copyright.check(doc_info_tags::copyright_year))
                 {
-                    tmp << "      <year>" << *it2 << "</year>\n";
+                    int year_start = copyright.consume().get_int();
+                    int year_end =
+                        copyright.check(doc_info_tags::copyright_year_end) ?
+                        copyright.consume().get_int() :
+                        year_start;
+    
+                    if (year_end < year_start) {
+                        ++actions.error_count;
+    
+                        detail::outerr(actions.filename,
+                            copyright.begin()->get_position().line)
+                            << "Invalid year range: "
+                            << year_start
+                            << "-"
+                            << year_end
+                            << "."
+                            << std::endl;
+                    }
+    
+                    for(; year_start <= year_end; ++year_start)
+                        tmp << "      <year>" << year_start << "</year>\n";
                 }
-        
+            
                 tmp << "      <holder>"
-                    << it->second.get(106)
+                    << doc_info_output(copyright.consume(doc_info_tags::copyright_name), 106)
                     << "</holder>\n"
                     << "    </copyright>\n"
                     << "\n"
@@ -253,63 +323,95 @@
             }
         }
 
-        if (!actions.doc_license.empty())
+        if (!license.empty())
         {
             tmp << "    <legalnotice>\n"
                 << "      <para>\n"
-                << "        " << actions.doc_license.get(103) << "\n"
+                << "        " << doc_info_output(license, 103) << "\n"
                 << "      </para>\n"
                 << "    </legalnotice>\n"
                 << "\n"
             ;
         }
 
-        if (!actions.doc_purpose.empty())
+        if (!purpose.empty())
         {
             tmp << "    <" << actions.doc_type << "purpose>\n"
-                << "      " << actions.doc_purpose.get(103)
+                << "      " << doc_info_output(purpose, 103)
                 << "    </" << actions.doc_type << "purpose>\n"
                 << "\n"
                 ;
         }
 
-        if (!actions.doc_categories.empty())
-        {
-            for(actions::docinfo_list::const_iterator
-                it = actions.doc_categories.begin(),
-                end = actions.doc_categories.end();
-                it != end; ++it)
-            {
+        BOOST_FOREACH(value_consumer values, categories) {
+            value category = values.optional_consume();
+            if(!category.empty()) {
                 tmp << "    <" << actions.doc_type << "category name=\"category:"
-                    << it->get(106)
+                    << doc_info_output(category, 106)
                     << "\"></" << actions.doc_type << "category>\n"
                     << "\n"
                 ;
             }
+            values.finish();
         }
 
-        for (actions::biblioid_list::const_iterator
-            it = actions.doc_biblioid_items.begin(),
-            end = actions.doc_biblioid_items.end();
-            it != end; ++it)
+        BOOST_FOREACH(value_consumer biblioid, biblioids)
         {
+            value class_ = biblioid.consume(doc_info_tags::biblioid_class);
+            value value_ = biblioid.consume(doc_info_tags::biblioid_value);
+            
             tmp << "    <biblioid class=\""
-                << it->first
+                << class_.get_quickbook()
                 << "\">"
-                << it->second.get(103)
+                << doc_info_output(value_, 106)
                 << "</biblioid>"
                 << "\n"
                 ;
+            biblioid.finish();
         }
 
-        std::string value = tmp.str();
-        if(!value.empty())
+        if(actions.doc_type != "library") {
+            write_document_title(out, doc_title, version);
+        }
+
+        std::string docinfo = tmp.str();
+        if(!docinfo.empty())
         {
             out << "  <" << actions.doc_type << "info>\n"
-                << value
+                << docinfo
                 << "  </" << actions.doc_type << "info>\n"
                 << "\n"
             ;
         }
+
+        if(actions.doc_type == "library") {
+            write_document_title(out, doc_title, version);
+        }
+    }
+    
+    void post(collector& out, quickbook::actions& actions, bool ignore_docinfo)
+    {
+        // if we're ignoring the document info, do nothing.
+        if (ignore_docinfo)
+        {
+            return;
+        } 
+
+        // We've finished generating our output. Here's what we'll do
+        // *after* everything else.
+        out << "\n</" << actions.doc_type << ">\n\n";
+    }
+
+    static void write_document_title(collector& out, value const& title, value const& version)
+    {
+        if (!title.empty())
+        {
+            out << "  <title>"
+                << doc_info_output(title, 106);
+            if (!version.empty()) {
+                out << ' ' << doc_info_output(version, 106);
+            }
+            out<< "</title>\n\n\n";
+        }
     }
 }
Modified: branches/release/tools/quickbook/src/doc_info_grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/doc_info_grammar.cpp	(original)
+++ branches/release/tools/quickbook/src/doc_info_grammar.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -8,32 +8,89 @@
     http://www.boost.org/LICENSE_1_0.txt)
 =============================================================================*/
 
-#include "grammar_impl.hpp"
-#include "actions_class.hpp"
+#include <map>
+#include <boost/foreach.hpp>
 #include <boost/spirit/include/classic_core.hpp>
 #include <boost/spirit/include/classic_actor.hpp>
 #include <boost/spirit/include/classic_loops.hpp>
 #include <boost/spirit/include/classic_symbols.hpp>
 #include <boost/spirit/include/classic_chset.hpp>
+#include <boost/spirit/include/classic_numerics.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+#include "grammar_impl.hpp"
+#include "actions_class.hpp"
+#include "doc_info_tags.hpp"
+#include "phrase_tags.hpp"
 
 namespace quickbook
 {
     namespace cl = boost::spirit::classic;
 
+    struct attribute_info
+    {
+        attribute_info(value::tag_type t, cl::rule<scanner>* r)
+            : tag(t), rule(r)
+        {}
+
+        value::tag_type tag;
+        cl::rule<scanner>* rule;
+    };
+
     struct doc_info_grammar_local
     {
+        struct assign_attribute_type
+        {
+            assign_attribute_type(doc_info_grammar_local& l)
+                : l(l)
+            {}
+
+            void operator()(value::tag_type& t) const {
+                l.attribute_rule = *l.attribute_rules[t];
+                l.attribute_tag = t;
+            }
+            
+            doc_info_grammar_local& l;
+        };
+        
+        struct fallback_attribute_type
+        {
+            fallback_attribute_type(doc_info_grammar_local& l)
+                : l(l)
+            {}
+
+            void operator()(iterator, iterator) const {
+                l.attribute_rule = l.doc_fallback;
+                l.attribute_tag = value::default_tag;
+            }
+            
+            doc_info_grammar_local& l;
+        };
+
         cl::rule<scanner>
-                        doc_title, doc_version, doc_id, doc_dirname,
-                        doc_copyright, doc_purpose, doc_category, doc_authors,
-                        doc_author, doc_license,
-                        doc_last_revision, doc_source_mode, doc_biblioid, doc_lang,
+                        doc_title, doc_simple, doc_phrase, doc_fallback,
+                        doc_authors, doc_author,
+                        doc_copyright, doc_copyright_holder,
+                        doc_source_mode, doc_biblioid,
                         quickbook_version, char_;
+        cl::uint_parser<int, 10, 4, 4> doc_copyright_year;
         cl::symbols<> doc_types;
+        cl::symbols<value::tag_type> doc_attributes;
+        std::map<value::tag_type, cl::rule<scanner>* > attribute_rules;
+        value::tag_type attribute_tag;
+        cl::rule<scanner> attribute_rule;
+        assign_attribute_type assign_attribute;
+        fallback_attribute_type fallback_attribute;
+        
+        doc_info_grammar_local()
+            : assign_attribute(*this)
+            , fallback_attribute(*this)
+        {}
     };
 
     void quickbook_grammar::impl::init_doc_info()
     {
-        doc_info_grammar_local& local = store_.create();
+        doc_info_grammar_local& local = cleanup_.add(
+            new doc_info_grammar_local);
 
         typedef cl::uint_parser<int, 10, 1, 2>  uint2_t;
 
@@ -42,150 +99,143 @@
           , "appendix", "preface", "qandadiv", "qandaset"
           , "reference", "set"
         ;
+
+        BOOST_FOREACH(value::tag_type t, doc_info_attributes::tags()) {
+            local.doc_attributes.add(doc_info_attributes::name(t), t);
+        }
         
         doc_info_details =
             space
             >> '[' >> space
             >> (local.doc_types >> cl::eps_p)
-                                            [cl::assign_a(actions.doc_type)]
+                                            [actions.values.reset()]
+                                            [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::type)]
             >> hard_space
             >>  (  *(~cl::eps_p(cl::ch_p('[') | ']' | cl::eol_p) >> local.char_)
-                )                           [actions.extract_doc_title]
+                )                           [actions.docinfo_value(ph::arg1, ph::arg2, doc_info_tags::title)]
             >>  !(
                     space >> '[' >>
                         local.quickbook_version
                     >> space >> ']'
                 )
-            >>
-                *(
-                    space >> '[' >>
-                    (
-                      local.doc_version
-                    | local.doc_id
-                    | local.doc_dirname
-                    | local.doc_copyright   [cl::push_back_a(actions.doc_copyrights, actions.copyright)]
-                    | local.doc_purpose
-                    | local.doc_category
-                    | local.doc_authors
-                    | local.doc_license
-                    | local.doc_last_revision
-                    | local.doc_source_mode
-                    | local.doc_biblioid
-                    | local.doc_lang
+            >>  *(
+                    space
+                >>  '['
+                >>  space
+                >>  (   local.doc_attributes
+                                            [local.assign_attribute]
+                    |   (+(cl::alnum_p | '_' | '-'))
+                                            [local.fallback_attribute]
+                                            [actions.error("Unrecognized document attribute: '%s'.")]
                     )
-                    >> space >> ']' >> +cl::eol_p
+                >>  hard_space
+                >>  actions.values.list(ph::var(local.attribute_tag))
+                    [local.attribute_rule]
+                >>  space
+                >>  ']'
+                >>  +cl::eol_p
                 )
-            >> space >> ']' >> +cl::eol_p
+            >>  space                       [actions.values.sort()]
+            >>  ']'
+            >>  +cl::eol_p
             ;
 
         local.quickbook_version =
-                "quickbook" >> hard_space
-            >>  (   cl::uint_p              [assign_qbk_version(qbk_major_version)]
+            actions.values.list(doc_info_tags::qbk_version)
+            [   "quickbook"
+            >>  hard_space
+            >>  (   cl::uint_p              [actions.values.entry(ph::arg1)]
                     >> '.' 
-                    >>  uint2_t()           [assign_qbk_version(qbk_minor_version)]
+                    >>  uint2_t()           [actions.values.entry(ph::arg1)]
                 )
+            ]
             ;
 
-        local.doc_version =
-                "version" >> hard_space
-            >> (*(~cl::eps_p(']') >> local.char_))
-                                            [actions.extract_doc_version]
-            ;
-
-        // TODO: Restrictions on doc_id?
-        local.doc_id =
-                "id" >> hard_space
-            >> (*(~cl::eps_p(']') >> local.char_))
-                                            [actions.extract_doc_id]
-            ;
-
-        // TODO: Restrictions on doc_dirname?
-        local.doc_dirname =
-                "dirname" >> hard_space
-            >> (*(~cl::eps_p(']') >> local.char_))
-                                            [actions.extract_doc_dirname]
-            ;
+        // TODO: Clear phrase afterwards?
+
+        local.doc_fallback = (*(~cl::eps_p(']') >> local.char_));
+
+        // TODO: Restrictions on doc_id and doc_dirname?
+
+        local.doc_simple = (*(~cl::eps_p(']') >> local.char_)) [actions.docinfo_value(ph::arg1, ph::arg2)];
+        local.attribute_rules[doc_info_attributes::version] = &local.doc_simple;
+        local.attribute_rules[doc_info_attributes::id] = &local.doc_simple;
+        local.attribute_rules[doc_info_attributes::dirname] = &local.doc_simple;
+        local.attribute_rules[doc_info_attributes::category] = &local.doc_simple;
+        local.attribute_rules[doc_info_attributes::last_revision] = &local.doc_simple;
+        local.attribute_rules[doc_info_attributes::lang] = &local.doc_simple;
+
+        local.doc_copyright_holder
+            =   *(  ~cl::eps_p
+                    (   ']'
+                    |   ',' >> space >> local.doc_copyright_year
+                    )
+                >>  local.char_
+                );
 
         local.doc_copyright =
-                "copyright"
-            >> hard_space                   [cl::clear_a(actions.copyright.first)]
-            >> +( cl::repeat_p(4)[cl::digit_p]
-                                            [cl::push_back_a(actions.copyright.first)]
-                  >> space
+            *(  +(  local.doc_copyright_year
+                                            [actions.values.entry(ph::arg1, doc_info_tags::copyright_year)]
+                >>  space
+                >>  !(  '-'
+                    >>  space
+                    >>  local.doc_copyright_year
+                                            [actions.values.entry(ph::arg1, doc_info_tags::copyright_year_end)]
+                    >>  space
+                    )
+                >>  !cl::ch_p(',')
+                >>  space
                 )
-            >> space
-            >> (*(~cl::eps_p(']') >> local.char_))
-                                            [actions.extract_copyright_second]
+            >>  local.doc_copyright_holder  [actions.docinfo_value(ph::arg1, ph::arg2, doc_info_tags::copyright_name)]
+            >>  !cl::ch_p(',')
+            >>  space
+            )
             ;
 
-        local.doc_purpose =
-                "purpose" >> hard_space
-            >> simple_phrase                [actions.extract_doc_purpose]
-            ;
+        local.attribute_rules[doc_info_attributes::copyright] = &local.doc_copyright;
 
-        local.doc_category =
-                "category" >> hard_space
-            >> (*(~cl::eps_p(']') >> local.char_))
-                                            [actions.extract_doc_category]
-                                            [cl::push_back_a(actions.doc_categories, actions.doc_category)]
-            ;
+        local.doc_phrase = simple_phrase [actions.docinfo_value(ph::arg1, ph::arg2)];
+        local.attribute_rules[doc_info_attributes::purpose] = &local.doc_phrase;
+        local.attribute_rules[doc_info_attributes::license] = &local.doc_phrase;
 
         local.doc_author =
-                '[' >> space
+                '['
+            >>   space
             >>  (*(~cl::eps_p(',') >> local.char_))
-                                            [actions.extract_name_second]
+                                            [actions.docinfo_value(ph::arg1, ph::arg2, doc_info_tags::author_surname)]
             >>  ',' >> space
             >>  (*(~cl::eps_p(']') >> local.char_))
-                                            [actions.extract_name_first]
+                                            [actions.docinfo_value(ph::arg1, ph::arg2, doc_info_tags::author_first)]
             >>  ']'
             ;
 
         local.doc_authors =
-                "authors"
-            >>  hard_space
-            >>  local.doc_author            [cl::push_back_a(actions.doc_authors, actions.name)]
+            *(  local.doc_author
             >>  space
-            >>  *(  !(cl::ch_p(',') >> space)
-                >>  local.doc_author        [cl::push_back_a(actions.doc_authors, actions.name)]
-                >>  space
-                )
+            >>  !(cl::ch_p(',') >> space)
+            )
             ;
 
-        local.doc_license =
-                "license" >> hard_space
-            >> simple_phrase                [actions.extract_doc_license]
-            ;
-
-        local.doc_last_revision =
-                "last-revision" >> hard_space
-            >> (*(~cl::eps_p(']') >> local.char_))
-                                            [actions.extract_doc_last_revision]
-            ;
+        local.attribute_rules[doc_info_attributes::authors] = &local.doc_authors;
 
         local.doc_source_mode =
-                "source-mode" >> hard_space
-            >>  (
+                (
                    cl::str_p("c++") 
                 |  "python"
                 |  "teletype"
                 )                           [cl::assign_a(actions.source_mode)]
             ;
 
+        local.attribute_rules[doc_info_attributes::source_mode] = &local.doc_source_mode;
+
         local.doc_biblioid =
-                "biblioid"
-            >>  hard_space
-            >>  (+cl::alnum_p)              [cl::assign_a(actions.doc_biblioid.first)]
+                (+cl::alnum_p)              [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::biblioid_class)]
             >>  hard_space
             >>  (+(~cl::eps_p(']') >> local.char_))
-                                            [actions.extract_doc_biblioid]
-                                            [cl::push_back_a(actions.doc_biblioid_items, actions.doc_biblioid)]
+                                            [actions.docinfo_value(ph::arg1, ph::arg2, doc_info_tags::biblioid_value)]
             ;
 
-        local.doc_lang =
-                "lang" >> hard_space
-            >> (*(~cl::eps_p(']') >> local.char_))
-                                            [actions.extract_doc_lang]
-            ;
+        local.attribute_rules[doc_info_attributes::biblioid] = &local.doc_biblioid;
 
         local.char_ =
                 cl::str_p("\\n")            [actions.break_]
@@ -197,11 +247,12 @@
             |   "\\U" >> cl::repeat_p(8)
                     [cl::chset<>("0-9a-fA-F")]
                                             [actions.escape_unicode]
-            |   (
-                    ("'''" >> !cl::eol_p)   [actions.escape_pre]
-                >>  *(cl::anychar_p - "'''")[actions.raw_char]
-                >>  cl::str_p("'''")        [actions.escape_post]
-                )
+            |   ("'''" >> !eol)
+            >>  actions.values.save()
+                [  (*(cl::anychar_p - "'''"))
+                                            [actions.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
+                >>  cl::str_p("'''")        [actions.element]
+                ]
             |   cl::anychar_p               [actions.plain_char]
             ;
     }
Modified: branches/release/tools/quickbook/src/fwd.hpp
==============================================================================
--- branches/release/tools/quickbook/src/fwd.hpp	(original)
+++ branches/release/tools/quickbook/src/fwd.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -11,18 +11,17 @@
 #if !defined(BOOST_SPIRIT_FWD_HPP)
 #define BOOST_SPIRIT_FWD_HPP
 
-#include <boost/spirit/include/classic_iterator.hpp>
-#include <boost/range.hpp>
-#include <boost/shared_ptr.hpp>
+#include "iterator.hpp"
 
 namespace quickbook
 {
     struct actions;
     struct quickbook_grammar;
+    struct collector;
 
-    typedef boost::spirit::classic::file_position_base<char const*> position;
-    typedef boost::spirit::classic::position_iterator<
-        std::string::const_iterator, position> iterator;
+    typedef position_iterator<std::string::const_iterator> iterator;
+
+    inline void ignore_variable(void const*) {} 
 }
 
 #endif
Modified: branches/release/tools/quickbook/src/grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/grammar.cpp	(original)
+++ branches/release/tools/quickbook/src/grammar.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -30,7 +30,7 @@
 
     quickbook_grammar::impl::impl(quickbook::actions& a)
         : actions(a)
-        , store_()
+        , cleanup_()
     {
         init_main();
         init_block_elements();
Modified: branches/release/tools/quickbook/src/grammar.hpp
==============================================================================
--- branches/release/tools/quickbook/src/grammar.hpp	(original)
+++ branches/release/tools/quickbook/src/grammar.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -44,7 +44,7 @@
         cl::rule<scanner> const& start_rule;
     };
 
-    class quickbook_grammar
+    struct quickbook_grammar
     {
     public:
         struct impl;
Modified: branches/release/tools/quickbook/src/grammar_impl.hpp
==============================================================================
--- branches/release/tools/quickbook/src/grammar_impl.hpp	(original)
+++ branches/release/tools/quickbook/src/grammar_impl.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -12,7 +12,8 @@
 #define BOOST_SPIRIT_QUICKBOOK_GRAMMARS_IMPL_HPP
 
 #include "grammar.hpp"
-#include "rule_store.hpp"
+#include "cleanup.hpp"
+#include "values.hpp"
 #include <boost/spirit/include/classic_symbols.hpp>
 
 namespace quickbook
@@ -25,25 +26,37 @@
             in_block = 1,
             in_phrase = 2,
             in_conditional = 4,
+            in_nested_block = 8
         };
 
         enum type_enum {
-            block = 1,
-            phrase = 2,
-            conditional_or_block = 5
+            nothing = 0,
+            block = in_block,
+            conditional_or_block = block | in_conditional,
+            nested_block = conditional_or_block | in_nested_block,
+            phrase = nested_block | in_phrase
         };
 
-        element_info(type_enum t, cl::rule<scanner>* r)
-            : type(t), rule(r) {}
+        element_info()
+            : type(nothing), rule(), tag(0) {}
+
+        element_info(
+                type_enum t,
+                cl::rule<scanner>* r,
+                value::tag_type tag = value::default_tag,
+                unsigned int v = 0)
+            : type(t), rule(r), tag(tag), qbk_version(v) {}
 
         type_enum type;
         cl::rule<scanner>* rule;
+        value::tag_type tag;
+        unsigned int qbk_version;
     };
 
     struct quickbook_grammar::impl
     {
         quickbook::actions& actions;
-        rule_store store_;
+        cleanup cleanup_;
 
         // Main Grammar
         cl::rule<scanner> block_start;
Modified: branches/release/tools/quickbook/src/input_path.cpp
==============================================================================
--- branches/release/tools/quickbook/src/input_path.cpp	(original)
+++ branches/release/tools/quickbook/src/input_path.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -7,68 +7,240 @@
 =============================================================================*/
 
 #include <boost/program_options.hpp>
+#include <iostream>
 #include "input_path.hpp"
+#include "utils.hpp"
 
-#if !(defined(__cygwin__) || defined(__CYGWIN__))
+#if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS
+#include <boost/scoped_ptr.hpp>
+#include <windows.h>
+#include <io.h>
+#include <fcntl.h>
+#endif
 
-// Everything but cygwin
+#if QUICKBOOK_CYGWIN_PATHS
+#include <boost/scoped_array.hpp>
+#include <boost/program_options/errors.hpp>
+#include <sys/cygwin.h>
+#endif
 
-namespace quickbook { namespace detail
-{
-    void validate(boost::any& v,
-            const std::vector<std::string>& values,
-            input_path*, int)
-    {
-        std::string path
-            = boost::program_options::validators::get_single_string(values);
+namespace quickbook {
+    extern bool ms_errors;
+}
+
+namespace quickbook {
+namespace detail {
+
+// This is used for converting paths to UTF-8 on cygin.
+// Might be better not to use a windows 
+#if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS
+    namespace {
+        std::string to_utf8(std::wstring const& x)
+        {
+            int buffer_count = WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, 0, 0, 0, 0); 
+        
+            if (!buffer_count)
+                throw conversion_error("Error converting wide string to utf-8.");
+    
+            boost::scoped_ptr<char> buffer(new char[buffer_count]);
+    
+            if (!WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count, 0, 0))
+                throw conversion_error("Error converting wide string to utf-8.");
+            
+            return std::string(buffer.get());
+        }
 
-        v = input_path(path);
+        std::wstring from_utf8(std::string const& x)
+        {
+            int buffer_count = MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, 0, 0); 
+        
+            if (!buffer_count)
+                throw conversion_error("Error converting utf-8 to wide string.");
+    
+            boost::scoped_ptr<wchar_t> buffer(new wchar_t[buffer_count]);
+    
+            if (!MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count))
+                throw conversion_error("Error converting utf-8 to wide string.");
+            
+            return std::wstring(buffer.get());
+        }
     }
-}}
+#endif
 
+#if QUICKBOOK_WIDE_PATHS
+    std::string input_to_utf8(input_string const& x)
+    {
+        return to_utf8(x);
+    }
 #else
+    std::string input_to_utf8(input_string const& x)
+    {
+        return x;
+    }
+#endif
 
-// Cygwin 1.7.x
-    
-#include <boost/filesystem/v3/config.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/program_options/errors.hpp>
-#include <windows.h>
-#include <sys/cygwin.h>
+#if QUICKBOOK_WIDE_PATHS
+    fs::path generic_to_path(std::string const& x)
+    {
+        return fs::path(from_utf8(x));
+    }
 
-namespace quickbook { namespace detail
-{
-    void validate(boost::any& v,
-            const std::vector<std::string>& values,
-            input_path*, int)
-    {
-        std::string path
-            = boost::program_options::validators::get_single_string(values);
-
-#if defined(BOOST_WINDOWS_PATH)
-        cygwin_conv_path_t flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
-#elif defined(BOOST_POSIX_PATH)
-        cygwin_conv_path_t flags = CCP_WIN_A_TO_POSIX | CCP_RELATIVE;
+    std::string path_to_generic(fs::path const& x)
+    {
+        return to_utf8(x.generic_wstring());
+    }
 #else
-#    error "Boost filesystem path type doesn't seem to be set."
+    fs::path generic_to_path(std::string const& x)
+    {
+        return fs::path(x);
+    }
+
+    std::string path_to_generic(fs::path const& x)
+    {
+        return x.generic_string();
+    }
+
 #endif
 
+#if QUICKBOOK_CYGWIN_PATHS
+    fs::path input_to_path(input_string const& path)
+    {
+        cygwin_conv_path_t flags = CCP_POSIX_TO_WIN_W | CCP_RELATIVE;
+
         ssize_t size = cygwin_conv_path(flags, path.c_str(), NULL, 0);
         
-        if (size < 0) {
-            throw boost::program_options::validation_error(
-                boost::program_options::validation_error::invalid_option_value);
-        }
+        if (size < 0)
+            throw conversion_error("Error converting cygwin path to windows.");
+
+        // TODO: size is in bytes.
+        boost::scoped_array<wchar_t> result(new wchar_t[size]);
+
+        if(cygwin_conv_path(flags, path.c_str(), result.get(), size))
+            throw conversion_error("Error converting cygwin path to windows.");
+
+        return fs::path(result.get());
+    }
+    
+    stream_string path_to_stream(fs::path const& path)
+    {
+        cygwin_conv_path_t flags = CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
+
+        ssize_t size = cygwin_conv_path(flags, path.native().c_str(), NULL, 0);
+        
+        if (size < 0)
+            throw conversion_error("Error converting windows path to cygwin.");
 
         boost::scoped_array<char> result(new char[size]);
 
-        if(cygwin_conv_path(flags, path.c_str(), result.get(), size)) {
-            throw boost::program_options::validation_error(
-                boost::program_options::validation_error::invalid_option_value);
+        if(cygwin_conv_path(flags, path.native().c_str(), result.get(), size))
+            throw conversion_error("Error converting windows path to cygwin.");
+
+        return std::string(result.get());
+    }
+#else
+    fs::path input_to_path(input_string const& path)
+    {
+        return fs::path(path);
+    }
+
+#if QUICKBOOK_WIDE_PATHS && !QUICKBOOK_WIDE_STREAMS
+    stream_string path_to_stream(fs::path const& path)
+    {
+        return path.string();
+    }
+#else
+    stream_string path_to_stream(fs::path const& path)
+    {
+        return path.native();
+    }
+#endif
+
+#endif // QUICKBOOK_CYGWIN_PATHS
+
+#if QUICKBOOK_WIDE_STREAMS
+
+    void initialise_output()
+    {
+        if (_isatty(_fileno(stdout))) _setmode(_fileno(stdout), _O_U16TEXT);
+        if (_isatty(_fileno(stderr))) _setmode(_fileno(stderr), _O_U16TEXT);
+    }
+
+    void write_utf8(ostream& out, std::string const& x)
+    {
+        out << from_utf8(x);
+    }
+
+    ostream& out()
+    {
+        return std::wcout;
+    }
+
+    namespace
+    {
+        inline ostream& error_stream()
+        {
+            return std::wcerr;
         }
+    }
 
-        v = input_path(result.get());
+#else
+
+    void initialise_output()
+    {
+    }
+
+    void write_utf8(ostream& out, std::string const& x)
+    {
+        out << x;
+    }
+
+    ostream& out()
+    {
+        return std::cout;
+    }
+
+    namespace
+    {
+        inline ostream& error_stream()
+        {
+            return std::clog;
+        }
     }
-}}
 
 #endif
+
+    ostream& outerr()
+    {
+        return error_stream() << "Error: ";
+    }
+
+    ostream& outerr(fs::path const& file, int line)
+    {
+        if (line >= 0)
+        {
+            if (ms_errors)
+                return error_stream() << path_to_stream(file) << "(" << line << "): error: ";
+            else
+                return error_stream() << path_to_stream(file) << ":" << line << ": error: ";
+        }
+        else
+        {
+            return error_stream() << path_to_stream(file) << ": error: ";
+        }
+    }
+
+    ostream& outwarn(fs::path const& file, int line)
+    {
+        if (line >= 0)
+        {
+            if (ms_errors)
+                return error_stream() << path_to_stream(file) << "(" << line << "): warning: ";
+            else
+                return error_stream() << path_to_stream(file) << ":" << line << ": warning: ";
+        }
+        else
+        {
+            return error_stream() << path_to_stream(file) << ": warning: ";
+        }
+    }
+}}
Modified: branches/release/tools/quickbook/src/input_path.hpp
==============================================================================
--- branches/release/tools/quickbook/src/input_path.hpp	(original)
+++ branches/release/tools/quickbook/src/input_path.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -9,31 +9,112 @@
 #if !defined(BOOST_QUICKBOOK_DETAIL_INPUT_PATH_HPP)
 #define BOOST_QUICKBOOK_DETAIL_INPUT_PATH_HPP
 
-#include <vector>
-#include <boost/any.hpp>
+#include <boost/config.hpp>
+#include <boost/filesystem/v3/path.hpp>
 #include <string>
+#include <stdexcept>
+#include <iostream>
 
-namespace quickbook { namespace detail
+#if defined(__cygwin__) || defined(__CYGWIN__)
+#   define QUICKBOOK_CYGWIN_PATHS 1
+#elif defined(_WIN32)
+#   define QUICKBOOK_WIDE_PATHS 1
+#   if defined(BOOST_MSVC) && BOOST_MSVC >= 1400
+#       define QUICKBOOK_WIDE_STREAMS 1
+#   endif
+#endif
+
+#if !defined(QUICKBOOK_WIDE_PATHS)
+#define QUICKBOOK_WIDE_PATHS 0
+#endif
+
+#if !defined(QUICKBOOK_WIDE_STREAMS)
+#define QUICKBOOK_WIDE_STREAMS 0
+#endif
+
+#if !defined(QUICKBOOK_CYGWIN_PATHS)
+#define QUICKBOOK_CYGWIN_PATHS 0
+#endif
+
+namespace quickbook
 {
-    // Use this class with Boost.Program Options to convert paths to the format
-    // the Boost.Filesystem expects. This is needed on cygwin to convert cygwin
-    // paths to windows paths (or vice versa, depending on how filesystem is set
-    // up).
-    //
-    // Note that we don't want to convert paths in quickbook files, as they
-    // should be platform independent, and aren't necessarily relative to the
-    // current directory.
-
-    class input_path {
-        std::string path_;
-    public:
-        explicit input_path(char const* c) : path_(c) {}
-        explicit input_path(std::string const& c) : path_(c) {}
-        operator std::string() const { return path_; }
-
-        friend void validate(boost::any&, const std::vector<std::string>&,
-            input_path*, int);
-    };
-}}
+    namespace fs = boost::filesystem;
+
+    namespace detail
+    {
+        struct conversion_error : std::runtime_error
+        {
+            conversion_error(char const* m) : std::runtime_error(m) {}
+        };
+
+        // 'generic':   Paths in quickbook source and the generated boostbook.
+        //              Always UTF-8.
+        // 'input':     Paths (or other parameters) from the command line and
+        //              possibly other sources in the future. Wide strings on
+        //              normal windows, UTF-8 for cygwin and other platforms
+        //              (hopefully).
+        // 'stream':    Strings to be written to a stream.
+        // 'path':      Stored as a boost::filesystem::path. Since
+        //              Boost.Filesystem doesn't support cygwin, this
+        //              is always wide on windows. UTF-8 on other
+        //              platforms (again, hopefully).
+    
+#if QUICKBOOK_WIDE_PATHS
+        typedef std::wstring input_string;
+#else
+        typedef std::string input_string;
+#endif
+
+#if QUICKBOOK_WIDE_STREAMS
+        typedef std::wostream ostream;
+        typedef std::wstring stream_string;
+#else
+        typedef std::ostream ostream;
+        typedef std::string stream_string;
+#endif
+
+        std::string input_to_utf8(input_string const&);
+        fs::path input_to_path(input_string const&);
+        stream_string path_to_stream(fs::path const&);
+    
+        std::string path_to_generic(fs::path const&);
+        fs::path generic_to_path(std::string const&);
+
+        void initialise_output();
+        
+        ostream& out();
+
+        // Preformats an error/warning message so that it can be parsed by
+        // common IDEs. Uses the ms_errors global to determine if VS format
+        // or GCC format. Returns the stream to continue ouput of the verbose
+        // error message.
+        ostream& outerr();
+        ostream& outerr(fs::path const& file, int line = -1);
+        ostream& outwarn(fs::path const& file, int line = -1);
+        
+        struct utf8_proxy
+        {
+            std::string value;
+            
+            explicit utf8_proxy(std::string const& v) : value(v) {}
+        };
+
+        void write_utf8(ostream& out, std::string const&);
+        
+        inline ostream& operator<<(ostream& out, utf8_proxy const& p) {
+            write_utf8(out, p.value);
+            return out;
+        }
+
+        inline utf8_proxy utf8(std::string const& value) {
+            return utf8_proxy(value);
+        }
+
+        template <typename It>
+        inline utf8_proxy utf8(It begin, It end) {
+            return utf8_proxy(std::string(begin, end));
+        }
+    }
+}
 
 #endif
Copied: branches/release/tools/quickbook/src/iterator.hpp (from r70044, /trunk/tools/quickbook/src/iterator.hpp)
==============================================================================
--- /trunk/tools/quickbook/src/iterator.hpp	(original)
+++ branches/release/tools/quickbook/src/iterator.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -11,6 +11,8 @@
 
 #include <boost/operators.hpp>
 #include <boost/iterator/iterator_traits.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <iterator>
 
 namespace quickbook
 {
@@ -35,9 +37,9 @@
     {
         position_iterator() {}
         explicit position_iterator(Iterator base)
-            : base_(base), previous_('\0'), position_() {}
+            : original_(base), base_(base), previous_('\0'), position_() {}
         explicit position_iterator(Iterator base, file_position const& position)
-            : base_(base), previous_('\0'), position_(position) {}
+            : original_(base), base_(base), previous_('\0'), position_(position) {}
     
         friend bool operator==(
             position_iterator const& x,
@@ -82,8 +84,17 @@
         Iterator base() const {
             return base_;
         }
+
+        typedef boost::iterator_range<std::reverse_iterator<Iterator> >
+            lookback_range;
+
+        lookback_range lookback() const
+        {
+            return lookback_range(base_, original_);
+        }
     
     private:
+        Iterator original_;
         Iterator base_;
         char previous_;
         file_position position_;
Modified: branches/release/tools/quickbook/src/main_grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/main_grammar.cpp	(original)
+++ branches/release/tools/quickbook/src/main_grammar.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -11,114 +11,127 @@
 #include "grammar_impl.hpp"
 #include "actions_class.hpp"
 #include "utils.hpp"
+#include "template_tags.hpp"
+#include "block_tags.hpp"
+#include "phrase_tags.hpp"
+#include "parsers.hpp"
+#include "scoped.hpp"
 #include <boost/spirit/include/classic_core.hpp>
-#include <boost/spirit/include/classic_confix.hpp>
 #include <boost/spirit/include/classic_chset.hpp>
-#include <boost/spirit/include/classic_clear_actor.hpp>
 #include <boost/spirit/include/classic_if.hpp>
 #include <boost/spirit/include/classic_loops.hpp>
+#include <boost/spirit/include/classic_attribute.hpp>
+#include <boost/spirit/include/classic_lazy.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
 
 namespace quickbook
 {
     namespace cl = boost::spirit::classic;
 
-    template <typename Rule, typename Action>
-    inline void
-    simple_markup(
-        Rule& simple
-      , char mark
-      , Action const& action
-      , Rule const& close
-    )
-    {
-        simple =
-            mark >>
-            (
-                (
-                    cl::graph_p                 // A single char. e.g. *c*
-                    >> cl::eps_p(mark
-                        >> (cl::space_p | cl::punct_p | cl::end_p))
-                                                // space_p, punct_p or end_p
-                )                               // must follow mark
-            |
-                (   cl::graph_p >>              // graph_p must follow mark
-                    *(cl::anychar_p -
-                        (   (cl::graph_p >> mark) // Make sure that we don't go
-                        |   close                 // past a single block
-                        )
-                    ) >> cl::graph_p            // graph_p must precede mark
-                    >> cl::eps_p(mark
-                        >> (cl::space_p | cl::punct_p | cl::end_p))
-                                                // space_p, punct_p or end_p
-                )                               // must follow mark
-            )                                   [action]
-            >> mark
-            ;
-    }
-
     struct main_grammar_local
     {
+        struct process_element_impl : scoped_action_base {
+            process_element_impl(main_grammar_local& l)
+                : l(l) {}
+
+            bool start()
+            {
+                if (!(l.info.type & l.actions_.context) ||
+                        qbk_version_n < l.info.qbk_version)
+                    return false;
+
+                info_ = l.info;
+
+                if (!(info_.type & element_info::in_phrase))
+                    l.actions_.paragraph();
+
+                l.actions_.values.builder.reset();
+                
+                return true;
+            }
+            
+            template <typename ResultT, typename ScannerT>
+            bool result(ResultT result, ScannerT const& scan)
+            {
+                if (result || info_.type & element_info::in_phrase)
+                    return result;
+
+                l.actions_.error(scan.first, scan.first);
+                return true;
+            }
+
+            void success() { l.element_type = info_.type; }
+            void failure() { l.element_type = element_info::nothing; }
+
+            main_grammar_local& l;
+            element_info info_;
+        };
+        
+        struct is_block_type
+        {
+            typedef bool result_type;
+            template <typename Arg1 = void>
+            struct result { typedef bool type; };
+        
+            is_block_type(main_grammar_local& l)
+                : l_(l)
+            {}
+
+            bool operator()() const
+            {
+                return l_.element_type && !(l_.element_type & element_info::in_phrase);
+            }
+            
+            main_grammar_local& l_;
+        };
+
         cl::rule<scanner>
                         top_level, blocks, paragraph_separator,
-                        block_element,
                         code, code_line, blank_line, hr,
-                        list, ordered_list, list_item,
-                        phrase_element, extended_phrase_element, element,
-                        simple_phrase_end,
-                        escape,
-                        inline_code, simple_format,
-                        simple_bold, simple_italic, simple_underline,
-                        simple_teletype, template_,
+                        list, list_item,
+                        nested_char, escape,
+                        inline_code,
+                        template_,
                         code_block, macro,
                         template_args,
                         template_args_1_4, template_arg_1_4,
                         template_inner_arg_1_4, brackets_1_4,
-                        template_args_1_5, template_arg_1_5,
+                        template_args_1_5, template_arg_1_5, template_arg_1_5_content,
                         template_inner_arg_1_5, brackets_1_5,
+                        break_,
                         command_line_macro_identifier, command_line_phrase,
                         dummy_block
                         ;
 
-        struct assign_element_type {
-            assign_element_type(main_grammar_local& l) : l(l) {}
+        cl::rule<scanner> element;
 
-            void operator()(element_info& t) const {
-                l.element_type = t.type;
-                l.element_rule = *t.rule;
-            }
-            
-            main_grammar_local& l;
+        struct simple_markup_closure
+            : cl::closure<simple_markup_closure, char>
+        {
+            member1 mark;
         };
 
-        struct check_element_type {
-            check_element_type(main_grammar_local const& l, element_info::context t)
-                : l(l), t(t) {}
-
-            bool operator()() const {
-                return l.element_type & t;
-            }
-
-            main_grammar_local const& l;
-            element_info::context t;
-        };
+        cl::rule<scanner, simple_markup_closure::context_t> simple_markup;
+        cl::rule<scanner> simple_markup_end;
 
+        element_info info;
         element_info::type_enum element_type;
-        cl::rule<scanner> element_rule;
-        assign_element_type assign_element;
 
-        main_grammar_local()
-            : assign_element(*this) {}
-        
-        check_element_type check_element(element_info::context t) const {
-            return check_element_type(*this, t);
-        }
+        quickbook::actions& actions_;
+        scoped_parser<process_element_impl> process_element;
+        is_block_type is_block;
+
+        main_grammar_local(quickbook::actions& actions)
+            : actions_(actions)
+            , process_element(*this)
+            , is_block(*this)
+            {}
     };
 
     void quickbook_grammar::impl::init_main()
     {
-        using detail::var;
-
-        main_grammar_local& local = store_.create();
+        main_grammar_local& local = cleanup_.add(
+            new main_grammar_local(actions));
 
         block_skip_initial_spaces =
             *(cl::blank_p | comment) >> block_start
@@ -128,20 +141,25 @@
             local.top_level >> blank
             ;
 
-        local.top_level
-            =   local.blocks
-            >>  *(
-                    local.block_element >> !(+eol >> local.blocks)
+        local.top_level =
+            actions.scoped_context(element_info::in_block)
+            [   local.blocks
+            >>  *(  local.element
+                >>  cl::if_p(local.is_block)
+                    [   !(+eol >> local.blocks)
+                    ]
                 |   local.paragraph_separator >> local.blocks
                 |   common
                 |   cl::space_p                 [actions.space_char]
                 |   cl::anychar_p               [actions.plain_char]
-                );
+                )
+            ]
+            ;
 
         local.blocks =
            *(   local.code
-            |   local.list                      [actions.list]
-            |   local.hr                        [actions.hr]
+            |   local.list
+            |   local.hr
             |   +eol
             )
             ;
@@ -149,28 +167,33 @@
         local.paragraph_separator
             =   cl::eol_p
             >> *cl::blank_p
-            >>  cl::eol_p                       [actions.inside_paragraph]
+            >>  cl::eol_p                       [actions.paragraph]
             ;
 
         local.hr =
-            cl::str_p("----")
-            >> *(cl::anychar_p - eol)
-            >> +eol
+                cl::str_p("----")
+            >>  actions.values.list(block_tags::hr)
+                [   *(cl::anychar_p - eol)
+                >>  +eol
+                ]                               [actions.element]
             ;
 
-        local.block_element
-            =   '[' >> space
-            >>  local.element
-            >>  cl::eps_p(local.check_element(element_info::in_block))
-                                                [actions.inside_paragraph]
-            >>  (   local.element_rule
-                >>  (   (space >> ']')
-                    |   cl::eps_p               [actions.error]
-                    )
-                |   cl::eps_p                   [actions.error]
+        local.element
+            =   '['
+            >>  (   cl::eps_p(cl::punct_p)
+                >>  elements                    [ph::var(local.info) = ph::arg1]
+                |   elements                    [ph::var(local.info) = ph::arg1]
+                >>  (cl::eps_p - (cl::alnum_p | '_'))
                 )
+            >>  local.process_element()
+                [   actions.values.list(ph::var(local.info.tag))
+                    [   cl::lazy_p(*ph::var(local.info.rule))
+                    >>  space
+                    >>  ']'
+                    ]                           [actions.element]
+                ]
             ;
-        
+
         local.code =
             (
                 local.code_line
@@ -188,32 +211,47 @@
             ;
 
         local.list =
-            cl::eps_p(cl::ch_p('*') | '#') >>
-           +(
-                (*cl::blank_p
-                >> (cl::ch_p('*') | '#'))       [actions.list_format]
-                >> *cl::blank_p
-                >> local.list_item
-            )                                   [actions.list_item]
+                cl::eps_p(cl::ch_p('*') | '#')
+                                            [actions.values.reset()]
+            >>  actions.scoped_output()
+                [
+                actions.values.list(block_tags::list)
+                [   +actions.values.list()
+                    [   (*cl::blank_p)      [actions.values.entry(ph::arg1, ph::arg2, general_tags::list_indent)]
+                    >>  (cl::ch_p('*') | '#')
+                                            [actions.values.entry(ph::arg1, ph::arg2, general_tags::list_mark)]
+                    >>  *cl::blank_p
+                    >>  local.list_item     [actions.phrase_value]
+                    ]
+                ]
+                ]                           [actions.element]
             ;
 
         local.list_item =
-           *(   common
-            |   (cl::anychar_p -
-                    (   cl::eol_p >> *cl::blank_p
-                    >>  (cl::ch_p('*') | '#' | cl::eol_p)
-                    )
-                )                               [actions.plain_char]
-            )
+            actions.scoped_context(element_info::in_phrase)
+            [
+            actions.values.save()
+            [
+                *(  common
+                |   (cl::anychar_p -
+                        (   cl::eol_p >> *cl::blank_p
+                        >>  (cl::ch_p('*') | '#' | cl::eol_p)
+                        )
+                    )                       [actions.plain_char]
+                )
+            ]
+            ]
             >> +eol
             ;
 
         common =
                 local.macro
-            |   local.phrase_element
+            |   local.element
+            |   local.template_
+            |   local.break_
             |   local.code_block
             |   local.inline_code
-            |   local.simple_format
+            |   local.simple_markup
             |   local.escape
             |   comment
             ;
@@ -225,31 +263,21 @@
             >> actions.macro                    [actions.do_macro]
             ;
 
-        static const bool true_ = true;
-        static const bool false_ = false;
-
         local.template_ =
-            (
-                cl::ch_p('`')                   [cl::assign_a(actions.template_escape,true_)]
-                |
-                cl::eps_p                       [cl::assign_a(actions.template_escape,false_)]
-            )
-            >>
-            ( (
-                (cl::eps_p(cl::punct_p)
-                    >> actions.templates.scope
-                )                               [cl::assign_a(actions.template_identifier)]
-                                                [cl::clear_a(actions.template_args)]
-                >> !local.template_args
-            ) | (
-                (actions.templates.scope
-                    >> cl::eps_p(hard_space)
-                )                               [cl::assign_a(actions.template_identifier)]
-                                                [cl::clear_a(actions.template_args)]
-                >> space
-                >> !local.template_args
-            ) )
-            >> cl::eps_p(']')
+            (   '['
+            >>  space
+            >>  actions.values.list(template_tags::template_)
+                [   !cl::str_p("`")             [actions.values.entry(ph::arg1, ph::arg2, template_tags::escape)]
+                >>  (   cl::eps_p(cl::punct_p)
+                    >>  actions.templates.scope [actions.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
+                    |   actions.templates.scope [actions.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
+                    >>  cl::eps_p(hard_space)
+                    )
+                >>  space
+                >>  !local.template_args
+                >>  ']'
+                ]
+            )                                   [actions.element]
             ;
 
         local.template_args =
@@ -263,11 +291,10 @@
         local.template_args_1_4 = local.template_arg_1_4 >> *(".." >> local.template_arg_1_4);
 
         local.template_arg_1_4 =
-                (   cl::eps_p(*cl::blank_p >> cl::eol_p)
-                                                [cl::assign_a(actions.template_block, true_)]
-                |   cl::eps_p                   [cl::assign_a(actions.template_block, false_)]
-                )
-            >>  local.template_inner_arg_1_4    [actions.template_arg]
+            (   cl::eps_p(*cl::blank_p >> cl::eol_p)
+            >>  local.template_inner_arg_1_4    [actions.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+            |   local.template_inner_arg_1_4    [actions.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
+            )                               
             ;
 
         local.template_inner_arg_1_4 =
@@ -281,12 +308,14 @@
         local.template_args_1_5 = local.template_arg_1_5 >> *(".." >> local.template_arg_1_5);
 
         local.template_arg_1_5 =
-                (   cl::eps_p(*cl::blank_p >> cl::eol_p)
-                                                [cl::assign_a(actions.template_block, true_)]
-                |   cl::eps_p                   [cl::assign_a(actions.template_block, false_)]
-                )
-            >>  (+(local.brackets_1_5 | ('\\' >> cl::anychar_p) | (cl::anychar_p - (cl::str_p("..") | '[' | ']'))))
-                                                [actions.template_arg]
+            (   cl::eps_p(*cl::blank_p >> cl::eol_p)
+            >>  local.template_arg_1_5_content  [actions.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+            |   local.template_arg_1_5_content  [actions.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
+            )
+            ;
+
+        local.template_arg_1_5_content =
+            +(local.brackets_1_5 | ('\\' >> cl::anychar_p) | (cl::anychar_p - (cl::str_p("..") | '[' | ']')))
             ;
 
         local.template_inner_arg_1_5 =
@@ -297,6 +326,15 @@
             '[' >> local.template_inner_arg_1_5 >> ']'
             ;
 
+        local.break_
+            =   (   '['
+                >>  space
+                >>  "br"
+                >>  space
+                >>  ']'
+                )                               [actions.break_]
+                ;
+
         local.inline_code =
             '`' >>
             (
@@ -329,75 +367,97 @@
                 )
             ;
 
-        local.simple_format =
-                local.simple_bold
-            |   local.simple_italic
-            |   local.simple_underline
-            |   local.simple_teletype
-            ;
-
-        local.simple_phrase_end = '[' | phrase_end;
-
-        simple_markup(local.simple_bold,
-            '*', actions.simple_bold, local.simple_phrase_end);
-        simple_markup(local.simple_italic,
-            '/', actions.simple_italic, local.simple_phrase_end);
-        simple_markup(local.simple_underline,
-            '_', actions.simple_underline, local.simple_phrase_end);
-        simple_markup(local.simple_teletype,
-            '=', actions.simple_teletype, local.simple_phrase_end);
+        local.simple_markup =
+                cl::chset<>("*/_=")            [local.simple_markup.mark = ph::arg1]
+            >>  cl::eps_p(cl::graph_p)         // graph_p must follow first mark
+            >>  lookback
+                [   cl::anychar_p
+                >>  ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark))
+                                                // first mark not be preceeded by
+                                                // the same character.
+                >>  (cl::space_p | cl::punct_p | cl::end_p)
+                                                // first mark must be preceeded
+                                                // by space or punctuation or the
+                                                // mark character or a the start.
+                ]
+            >>  actions.values.save()
+                [
+                    actions.scoped_output()
+                    [
+                        (*( ~cl::eps_p(local.simple_markup_end)
+                        >>  local.nested_char
+                        ))                      [actions.docinfo_value(ph::arg1, ph::arg2)]
+                    ]                           
+                    >>  cl::f_ch_p(local.simple_markup.mark)
+                                                [actions.simple_markup]
+                ]
+            ;
+
+        local.simple_markup_end
+            =   (   lookback[cl::graph_p]       // final mark must be preceeded by
+                                                // graph_p
+                >>  cl::f_ch_p(local.simple_markup.mark)
+                >>  ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark))
+                                                // final mark not be followed by
+                                                // the same character.
+                >>  (cl::space_p | cl::punct_p | cl::end_p)
+                                                 // final mark must be followed by
+                                                 // space or punctuation
+                )
+            |   '['
+            |   "'''"
+            |   '`'
+            |   phrase_end
+                ;
 
         phrase =
-           *(   common
-            |   (cl::anychar_p - phrase_end)    [actions.plain_char]
-            )
+            actions.scoped_context(element_info::in_phrase)
+            [
+            actions.values.save()
+            [   *(  common
+                |   (cl::anychar_p - phrase_end)
+                                                [actions.plain_char]
+                )
+            ]
+            ]
             ;
 
         extended_phrase =
-           *(   local.extended_phrase_element
-            |   common
-            |   (cl::anychar_p - phrase_end)    [actions.plain_char]
-            )
-            ;
-
-        inside_paragraph =
-            (*( common
-            |   (cl::anychar_p - phrase_end)    [actions.plain_char]
-            |   (+eol)                          [actions.inside_paragraph]
-            ))                                  [actions.inside_paragraph]
-            ;
-
-        local.phrase_element
-            =   '['
-            >>  space
-            >>  (   local.element
-                >>  cl::eps_p(local.check_element(element_info::in_phrase))
-                >>  local.element_rule
-                |   local.template_             [actions.do_template]
-                |   cl::str_p("br")             [actions.break_]
+            actions.scoped_context(element_info::in_conditional)
+            [
+            actions.values.save()
+            [  *(   common
+                |   (cl::anychar_p - phrase_end)
+                                                [actions.plain_char]
                 )
-            >>  ']'
+            ]
+            ]
             ;
 
-        local.extended_phrase_element
-            =   '[' >> space
-            >>  local.element
-            >>  cl::eps_p(local.check_element(element_info::in_conditional))
-                                                [actions.inside_paragraph]
-            >>  (   local.element_rule
-                >>  (   (space >> ']')
-                    |   cl::eps_p               [actions.error]
-                    )
-                |   cl::eps_p                   [actions.error]
+        inside_paragraph =
+            actions.scoped_context(element_info::in_nested_block)
+            [
+            actions.values.save()
+            [   *(  local.paragraph_separator   [actions.paragraph]
+                |   common
+                |   (cl::anychar_p - phrase_end)
+                                                [actions.plain_char]
                 )
+            ]                                   [actions.paragraph]
+            ]
             ;
 
-
-        local.element
-            =   cl::eps_p(cl::punct_p)
-            >>  elements                    [local.assign_element]
-            |   elements                    [local.assign_element]
-            >>  (cl::eps_p - (cl::alnum_p | '_'))
+        local.nested_char =
+                cl::str_p("\\n")                [actions.break_]
+            |   "\\ "                           // ignore an escaped space
+            |   '\\' >> cl::punct_p             [actions.raw_char]
+            |   "\\u" >> cl::repeat_p(4)
+                    [cl::chset<>("0-9a-fA-F")]
+                                                [actions.escape_unicode]
+            |   "\\U" >> cl::repeat_p(8)
+                    [cl::chset<>("0-9a-fA-F")]
+                                                [actions.escape_unicode]
+            |   cl::anychar_p                   [actions.plain_char]
             ;
 
         local.escape =
@@ -408,11 +468,13 @@
                                                 [actions.escape_unicode]
             |   "\\U" >> cl::repeat_p(8) [cl::chset<>("0-9a-fA-F")]
                                                 [actions.escape_unicode]
-            |   (
-                    ("'''" >> !eol)             [actions.escape_pre]
-                >>  *(cl::anychar_p - "'''")    [actions.raw_char]
-                >>  cl::str_p("'''")            [actions.escape_post]
-                )
+            |   ("'''" >> !eol)
+            >>  actions.values.save()
+                [   (*(cl::anychar_p - "'''"))  [actions.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
+                >>  (   cl::str_p("'''")
+                    |   cl::eps_p               [actions.error("Unclosed boostbook escape.")]
+                    )                           [actions.element]
+                ]
             ;
 
         //
@@ -420,9 +482,15 @@
         //
 
         simple_phrase =
+            actions.scoped_context(element_info::in_phrase)
+            [
+            actions.values.save()
+            [
            *(   common
-            |   (cl::anychar_p - ']')       [actions.plain_char]
+            |   (cl::anychar_p - ']')           [actions.plain_char]
             )
+            ]
+            ]
             ;
 
         //
@@ -430,17 +498,18 @@
         //
 
         command_line =
-                *cl::space_p
+            actions.values.list(block_tags::macro_definition)
+            [   *cl::space_p
             >>  local.command_line_macro_identifier
-                                            [actions.macro_identifier]
+                                                [actions.values.entry(ph::arg1, ph::arg2)]
             >>  *cl::space_p
             >>  (   '='
                 >>  *cl::space_p
                 >>  local.command_line_phrase
-                                            [actions.macro_definition]
                 >>  *cl::space_p
-                )
-            |   cl::eps_p                   [actions.macro_definition]
+                |   cl::eps_p
+                )                               [actions.phrase_value]
+            ]                                   [actions.element]
             ;
 
         local.command_line_macro_identifier =
@@ -449,9 +518,14 @@
 
 
         local.command_line_phrase =
-           *(   common
-            |   (cl::anychar_p - ']')       [actions.plain_char]
-            )
+            actions.scoped_context(element_info::in_phrase)
+            [
+            actions.values.save()
+            [   *(   common
+                |   (cl::anychar_p - ']')       [actions.plain_char]
+                )
+            ]
+            ]
             ;
 
         // Miscellaneous stuff
@@ -474,13 +548,12 @@
             ;
 
         phrase_end =
-            ']' |
-            cl::if_p(var(actions.no_eols))
-            [
-                cl::eol_p >> *cl::blank_p >> cl::eol_p
-                                                // Make sure that we don't go
-            ]                                   // past a single block, except
-            ;                                   // when preformatted.
+                ']'
+            |   cl::eps_p(ph::var(actions.no_eols))
+            >>  cl::eol_p >> *cl::blank_p >> cl::eol_p
+            ;                                   // Make sure that we don't go
+                                                // past a single block, except
+                                                // when preformatted.
 
         comment =
             "[/" >> *(local.dummy_block | (cl::anychar_p - ']')) >> ']'
Modified: branches/release/tools/quickbook/src/markups.cpp
==============================================================================
--- branches/release/tools/quickbook/src/markups.cpp	(original)
+++ branches/release/tools/quickbook/src/markups.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -8,94 +8,71 @@
     http://www.boost.org/LICENSE_1_0.txt)
 =============================================================================*/
 
+#include "quickbook.hpp"
 #include "markups.hpp"
+#include "block_tags.hpp"
+#include "phrase_tags.hpp"
+#include <boost/foreach.hpp>
+#include <ostream>
+#include <map>
 
 namespace quickbook
 {
-    const char* comment_pre         = "<!--";
-    const char* comment_post        = "-->";
-    const char* paragraph_pre       = "<para>\n";
-    const char* paragraph_post      = "</para>\n";
-    const char* h1_pre              = "<bridgehead renderas=\"sect1\">";
-    const char* h1_post             = "</bridgehead>";
-    const char* h2_pre              = "<bridgehead renderas=\"sect2\">";
-    const char* h2_post             = "</bridgehead>";
-    const char* h3_pre              = "<bridgehead renderas=\"sect3\">";
-    const char* h3_post             = "</bridgehead>";
-    const char* h4_pre              = "<bridgehead renderas=\"sect4\">";
-    const char* h4_post             = "</bridgehead>";
-    const char* h5_pre              = "<bridgehead renderas=\"sect5\">";
-    const char* h5_post             = "</bridgehead>";
-    const char* h6_pre              = "<bridgehead renderas=\"sect6\">";
-    const char* h6_post             = "</bridgehead>";
-    const char* hr_                 = "<para/>";
-    const char* blurb_pre           = "<sidebar role=\"blurb\">\n";
-    const char* blurb_post          = "</sidebar>\n";
-    const char* blockquote_pre      = "<blockquote>";
-    const char* blockquote_post     = "</blockquote>";
-    const char* preformatted_pre    = "<programlisting>";
-    const char* preformatted_post   = "</programlisting>";
-    const char* warning_pre         = "<warning>";
-    const char* warning_post        = "</warning>";
-    const char* caution_pre         = "<caution>";
-    const char* caution_post        = "</caution>";
-    const char* important_pre       = "<important>";
-    const char* important_post      = "</important>";
-    const char* note_pre            = "<note>";
-    const char* note_post           = "</note>";
-    const char* tip_pre             = "<tip>";
-    const char* tip_post            = "</tip>";
-    const char* list_item_pre       = "<listitem><simpara>\n";
-    const char* list_item_post      = "\n</simpara></listitem>";
-    const char* bold_pre_           = "<emphasis role=\"bold\">";
-    const char* bold_post_          = "</emphasis>";
-    const char* italic_pre_         = "<emphasis>";
-    const char* italic_post_        = "</emphasis>";
-    const char* underline_pre_      = "<emphasis role=\"underline\">";
-    const char* underline_post_     = "</emphasis>";
-    const char* teletype_pre_       = "<literal>";
-    const char* teletype_post_      = "</literal>";
-    const char* strikethrough_pre_  = "<emphasis role=\"strikethrough\">";
-    const char* strikethrough_post_ = "</emphasis>";
-    const char* quote_pre_          = "<quote>";
-    const char* quote_post_         = "</quote>";
-    const char* break_mark          = "<sbr/>\n";
-    const char* url_pre_            = "<ulink url=\"";
-    const char* url_post_           = "</ulink>";
-    const char* link_pre_           = "<link linkend=\"";
-    const char* link_post_          = "</link>";
-    const char* start_varlistentry_ = "<varlistentry>";
-    const char* end_varlistentry_   = "</varlistentry>\n";
-    const char* start_varlistterm_  = "<term>";
-    const char* end_varlistterm_    = "</term>";
-    const char* start_varlistitem_  = "<listitem>";
-    const char* end_varlistitem_    = "</listitem>";
-    const char* start_header_       = "<thead>";
-    const char* end_header_         = "</thead>\n";
-    const char* start_row_          = "<row>";
-    const char* end_row_            = "</row>\n";
-    const char* start_cell_         = "<entry>";
-    const char* end_cell_           = "</entry>";
-    const char* funcref_pre_        = "<functionname alt=\"";
-    const char* funcref_post_       = "</functionname>";
-    const char* classref_pre_       = "<classname alt=\"";
-    const char* classref_post_      = "</classname>";
-    const char* memberref_pre_      = "<methodname alt=\"";
-    const char* memberref_post_     = "</methodname>";
-    const char* enumref_pre_        = "<enumname alt=\"";
-    const char* enumref_post_       = "</enumname>";
-    const char* macroref_pre_       = "<macroname alt=\"";
-    const char* macroref_post_      = "</macroname>";
-    const char* headerref_pre_      = "<headername alt=\"";
-    const char* headerref_post_     = "</headername>";
-    const char* conceptref_pre_     = "<conceptname alt=\"";
-    const char* conceptref_post_    = "</conceptname>";
-    const char* globalref_pre_      = "<globalname alt=\"";
-    const char* globalref_post_     = "</globalname>";
-    const char* footnote_pre_       = "<footnote><para>";
-    const char* footnote_post_      = "</para></footnote>";
-    const char* escape_pre_         = "<!--quickbook-escape-prefix-->";
-    const char* escape_post_        = "<!--quickbook-escape-postfix-->";
-    const char* replaceable_pre_    = "<replaceable>";
-    const char* replaceable_post_   = "</replaceable>";
+    namespace detail
+    {
+        std::map<value::tag_type, markup> markups;
+
+        void initialise_markups()
+        {
+            markup init_markups[] = {
+                { block_tags::paragraph, "<para>\n", "</para>\n" },
+                { block_tags::blurb, "<sidebar role=\"blurb\">\n", "</sidebar>\n" },
+                { block_tags::blockquote, "<blockquote>", "</blockquote>" },
+                { block_tags::preformatted, "<programlisting>", "</programlisting>" },
+                { block_tags::warning, "<warning>", "</warning>" },
+                { block_tags::caution, "<caution>", "</caution>" },
+                { block_tags::important, "<important>", "</important>" },
+                { block_tags::note, "<note>", "</note>" },
+                { block_tags::tip, "<tip>", "</tip>" },
+                { block_tags::ordered_list, "<orderedlist>", "</orderedlist>" },
+                { block_tags::itemized_list, "<itemizedlist>", "</itemizedlist>" },
+                { block_tags::hr, "<para/>", 0 },
+                { phrase_tags::url, "<ulink url=\"", "</ulink>" },
+                { phrase_tags::link, "<link linkend=\"", "</link>" },
+                { phrase_tags::funcref, "<functionname alt=\"", "</functionname>" },
+                { phrase_tags::classref, "<classname alt=\"", "</classname>" },
+                { phrase_tags::memberref, "<methodname alt=\"", "</methodname>" },
+                { phrase_tags::enumref, "<enumname alt=\"", "</enumname>" },
+                { phrase_tags::macroref, "<macroname alt=\"", "</macroname>" },
+                { phrase_tags::headerref, "<headername alt=\"", "</headername>" },
+                { phrase_tags::conceptref, "<conceptname alt=\"", "</conceptname>" },
+                { phrase_tags::globalref, "<globalname alt=\"", "</globalname>" },
+                { phrase_tags::bold, "<emphasis role=\"bold\">", "</emphasis>" },
+                { phrase_tags::italic, "<emphasis>", "</emphasis>" },
+                { phrase_tags::underline, "<emphasis role=\"underline\">", "</emphasis>" },
+                { phrase_tags::teletype, "<literal>", "</literal>" },
+                { phrase_tags::strikethrough, "<emphasis role=\"strikethrough\">", "</emphasis>" },
+                { phrase_tags::quote, "<quote>", "</quote>" },
+                { phrase_tags::replaceable, "<replaceable>", "</replaceable>" },
+                { phrase_tags::footnote, "<footnote><para>", "</para></footnote>" },
+                { phrase_tags::escape, "<!--quickbook-escape-prefix-->", "<!--quickbook-escape-postfix-->" },
+                { phrase_tags::break_mark, "<sbr/>\n", 0 }
+            };
+
+            BOOST_FOREACH(markup m, init_markups)
+            {
+                markups[m.tag] = m;
+            }
+        }
+
+        markup const& get_markup(value::tag_type t)
+        {
+            return markups[t];
+        }
+
+        std::ostream& operator<<(std::ostream& out, markup const& m)
+        {
+            return out<<"{"<<m.tag<<": \""<<m.pre<<"\", \""<<m.post<<"\"}";
+        }
+    }
 }
Modified: branches/release/tools/quickbook/src/markups.hpp
==============================================================================
--- branches/release/tools/quickbook/src/markups.hpp	(original)
+++ branches/release/tools/quickbook/src/markups.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -10,94 +10,22 @@
 #if !defined(BOOST_SPIRIT_MARKUPS_HPP)
 #define BOOST_SPIRIT_MARKUPS_HPP
 
+#include <iosfwd>
+#include "values.hpp"
+
 namespace quickbook
 {
-    extern const char* comment_pre;
-    extern const char* comment_post;
-    extern const char* paragraph_pre;
-    extern const char* paragraph_post;
-    extern const char* h1_pre;
-    extern const char* h1_post;
-    extern const char* h2_pre;
-    extern const char* h2_post;
-    extern const char* h3_pre;
-    extern const char* h3_post;
-    extern const char* h4_pre;
-    extern const char* h4_post;
-    extern const char* h5_pre;
-    extern const char* h5_post;
-    extern const char* h6_pre;
-    extern const char* h6_post;
-    extern const char* hr_;
-    extern const char* blurb_pre;
-    extern const char* blurb_post;
-    extern const char* blockquote_pre;
-    extern const char* blockquote_post;
-    extern const char* preformatted_pre;
-    extern const char* preformatted_post;
-    extern const char* warning_pre;
-    extern const char* warning_post;
-    extern const char* caution_pre;
-    extern const char* caution_post;
-    extern const char* important_pre;
-    extern const char* important_post;
-    extern const char* note_pre;
-    extern const char* note_post;
-    extern const char* tip_pre;
-    extern const char* tip_post;
-    extern const char* list_item_pre;
-    extern const char* list_item_post;
-    extern const char* bold_pre_;
-    extern const char* bold_post_;
-    extern const char* italic_pre_;
-    extern const char* italic_post_;
-    extern const char* underline_pre_;
-    extern const char* underline_post_;
-    extern const char* teletype_pre_;
-    extern const char* teletype_post_;
-    extern const char* strikethrough_pre_;
-    extern const char* strikethrough_post_;
-    extern const char* quote_pre_;
-    extern const char* quote_post_;
-    extern const char* break_mark;
-    extern const char* url_pre_;
-    extern const char* url_post_;
-    extern const char* link_pre_;
-    extern const char* link_post_;
-    extern const char* start_varlistentry_;
-    extern const char* end_varlistentry_;
-    extern const char* start_varlistterm_;
-    extern const char* end_varlistterm_;
-    extern const char* start_varlistitem_;
-    extern const char* end_varlistitem_;
-    extern const char* start_header_;
-    extern const char* end_header_;
-    extern const char* start_row_;
-    extern const char* end_row_;
-    extern const char* start_cell_;
-    extern const char* end_cell_;
-    extern const char* funcref_pre_;
-    extern const char* funcref_post_;
-    extern const char* classref_pre_;
-    extern const char* classref_post_;
-    extern const char* memberref_pre_;
-    extern const char* memberref_post_;
-    extern const char* enumref_pre_;
-    extern const char* enumref_post_;
-    extern const char* macroref_pre_;
-    extern const char* macroref_post_;
-    extern const char* headerref_pre_;
-    extern const char* headerref_post_;
-    extern const char* conceptref_pre_;
-    extern const char* conceptref_post_;
-    extern const char* globalref_pre_;
-    extern const char* globalref_post_;
-    extern const char* footnote_pre_;
-    extern const char* footnote_post_;
-    extern const char* escape_pre_;
-    extern const char* escape_post_;
-    extern const char* replaceable_pre_;
-    extern const char* replaceable_post_;
+    namespace detail
+    {    
+        struct markup {
+            value::tag_type tag;
+            char const* pre;
+            char const* post;
+        };
+        
+        markup const& get_markup(value::tag_type);
+        std::ostream& operator<<(std::ostream&, markup const&);
+    }
 }
 
 #endif // BOOST_SPIRIT_MARKUPS_HPP
Copied: branches/release/tools/quickbook/src/parsers.hpp (from r70210, /trunk/tools/quickbook/src/parsers.hpp)
==============================================================================
--- /trunk/tools/quickbook/src/parsers.hpp	(original)
+++ branches/release/tools/quickbook/src/parsers.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -176,7 +176,7 @@
         {
             typedef phoenix::tuple<> tuple;
             return scoped_parser_gen<Impl, tuple>(impl_, tuple());
-        };
+        }
 
         template <typename Arg1>
         scoped_parser_gen<Impl, phoenix::tuple<Arg1> >
@@ -184,7 +184,7 @@
         {
             typedef phoenix::tuple<Arg1> tuple;
             return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1));
-        };
+        }
     
         template <typename Arg1, typename Arg2>
         scoped_parser_gen<Impl, phoenix::tuple<Arg1, Arg2> >
@@ -192,7 +192,7 @@
         {
             typedef phoenix::tuple<Arg1, Arg2> tuple;
             return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1, x2));
-        };
+        }
         
         Impl impl_;
     };
@@ -252,4 +252,5 @@
     
     lookback_gen const lookback = lookback_gen();
 }
+
 #endif // BOOST_QUICKBOOK_SCOPED_BLOCK_HPP
Modified: branches/release/tools/quickbook/src/phrase_element_grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/phrase_element_grammar.cpp	(original)
+++ branches/release/tools/quickbook/src/phrase_element_grammar.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -11,10 +11,13 @@
 #include "grammar_impl.hpp"
 #include "actions_class.hpp"
 #include "utils.hpp"
+#include "phrase_tags.hpp"
 #include <boost/spirit/include/classic_core.hpp>
 #include <boost/spirit/include/classic_assign_actor.hpp>
 #include <boost/spirit/include/classic_clear_actor.hpp>
 #include <boost/spirit/include/classic_if.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+#include <boost/spirit/include/phoenix1_casts.hpp>
 
 namespace quickbook
 {
@@ -23,22 +26,14 @@
     struct phrase_element_grammar_local
     {
         cl::rule<scanner>
-                        image,
-                        bold, italic, underline, teletype,
-                        strikethrough, url, funcref, classref,
-                        memberref, enumref, macroref, headerref, conceptref, globalref,
-                        anchor, link,
-                        source_mode_cpp, source_mode_python, source_mode_teletype,
-                        quote, footnote, replaceable,
-                        cond_phrase
+                        image, anchor, link, empty, cond_phrase, inner_phrase
                         ;
     };
 
     void quickbook_grammar::impl::init_phrase_elements()
     {
-        using detail::var;
-
-        phrase_element_grammar_local& local = store_.create();
+        phrase_element_grammar_local& local = cleanup_.add(
+            new phrase_element_grammar_local);
 
         elements.add
             ("?", element_info(element_info::phrase, &local.cond_phrase))
@@ -46,207 +41,94 @@
 
         local.cond_phrase =
                 blank
-            >>  macro_identifier                [actions.cond_phrase_pre]
-            >>  actions.scoped_cond_phrase[extended_phrase]
+            >>  macro_identifier                [actions.values.entry(ph::arg1, ph::arg2)]
+            >>  actions.scoped_cond_phrase()
+                [extended_phrase]
             ;
 
         elements.add
-            ("$", element_info(element_info::phrase, &local.image))
+            ("$", element_info(element_info::phrase, &local.image, phrase_tags::image))
             ;
 
         local.image =
-                blank                           [cl::clear_a(actions.attributes)]
+                blank
             >>  cl::if_p(qbk_since(105u)) [
                         (+(
                             *cl::space_p
                         >>  +(cl::anychar_p - (cl::space_p | phrase_end | '['))
-                        ))                       [cl::assign_a(actions.image_fileref)]
+                        ))                      [actions.values.entry(ph::arg1, ph::arg2)]
                     >>  hard_space
-                    >>  *(
-                            '['
-                        >>  (*(cl::alnum_p | '_'))  [cl::assign_a(actions.attribute_name)]
+                    >>  *actions.values.list()
+                        [   '['
+                        >>  (*(cl::alnum_p | '_')) 
+                                                [actions.values.entry(ph::arg1, ph::arg2)]
                         >>  space
                         >>  (*(cl::anychar_p - (phrase_end | '[')))
-                                                [actions.attribute]
+                                                [actions.values.entry(ph::arg1, ph::arg2)]
                         >>  ']'
                         >>  space
-                        )
+                        ]
                 ].else_p [
                         (*(cl::anychar_p - phrase_end))
-                                                [cl::assign_a(actions.image_fileref)]
+                                                [actions.values.entry(ph::arg1, ph::arg2)]
                 ]
-            >>  cl::eps_p(']')                  [actions.image]
+            >>  cl::eps_p(']')
             ;
             
         elements.add
-            ("@", element_info(element_info::phrase, &local.url))
-            ;
-
-        local.url =
-                (*(cl::anychar_p -
-                    (']' | hard_space)))  [actions.url_pre]
-            >>  hard_space
-            >>  phrase                          [actions.url_post]
-            ;
-
-        elements.add
-            ("link", element_info(element_info::phrase, &local.link))
+            ("@", element_info(element_info::phrase, &local.link, phrase_tags::url))
+            ("link", element_info(element_info::phrase, &local.link, phrase_tags::link))
+            ("funcref", element_info(element_info::phrase, &local.link, phrase_tags::funcref))
+            ("classref", element_info(element_info::phrase, &local.link, phrase_tags::classref))
+            ("memberref", element_info(element_info::phrase, &local.link, phrase_tags::memberref))
+            ("enumref", element_info(element_info::phrase, &local.link, phrase_tags::enumref))
+            ("macroref", element_info(element_info::phrase, &local.link, phrase_tags::macroref))
+            ("headerref", element_info(element_info::phrase, &local.link, phrase_tags::headerref))
+            ("conceptref", element_info(element_info::phrase, &local.link, phrase_tags::conceptref))
+            ("globalref", element_info(element_info::phrase, &local.link, phrase_tags::globalref))
             ;
 
         local.link =
                 space
             >>  (*(cl::anychar_p - (']' | hard_space)))
-                                                [actions.link_pre]
+                                                [actions.values.entry(ph::arg1, ph::arg2)]
             >>  hard_space
-            >>  phrase                          [actions.link_post]
+            >>  local.inner_phrase
             ;
 
         elements.add
-            ("#", element_info(element_info::phrase, &local.anchor))
+            ("#", element_info(element_info::phrase, &local.anchor, phrase_tags::anchor))
             ;
 
         local.anchor =
                 blank
-            >>  (*(cl::anychar_p - phrase_end)) [actions.anchor]
-            ;
-
-        elements.add
-            ("funcref", element_info(element_info::phrase, &local.funcref))
-            ("classref", element_info(element_info::phrase, &local.classref))
-            ("memberref", element_info(element_info::phrase, &local.memberref))
-            ("enumref", element_info(element_info::phrase, &local.enumref))
-            ("macroref", element_info(element_info::phrase, &local.macroref))
-            ("headerref", element_info(element_info::phrase, &local.headerref))
-            ("conceptref", element_info(element_info::phrase, &local.conceptref))
-            ("globalref", element_info(element_info::phrase, &local.globalref))
-            ;
-
-        local.funcref =
-                space
-            >>  (*(cl::anychar_p -
-                    (']' | hard_space)))        [actions.funcref_pre]
-            >>  hard_space
-            >>  phrase                          [actions.funcref_post]
-            ;
-
-        local.classref =
-                space
-            >>  (*(cl::anychar_p -
-                    (']' | hard_space)))        [actions.classref_pre]
-            >>  hard_space
-            >>  phrase                          [actions.classref_post]
-            ;
-
-        local.memberref =
-                space
-            >>  (*(cl::anychar_p -
-                    (']' | hard_space)))        [actions.memberref_pre]
-            >>  hard_space
-            >>  phrase                          [actions.memberref_post]
-            ;
-
-        local.enumref =
-                space
-            >>  (*(cl::anychar_p -
-                    (']' | hard_space)))        [actions.enumref_pre]
-            >>  hard_space
-            >>  phrase                          [actions.enumref_post]
-            ;
-
-        local.macroref =
-                space
-            >>  (*(cl::anychar_p -
-                    (']' | hard_space)))        [actions.macroref_pre]
-            >>  hard_space
-            >>  phrase                          [actions.macroref_post]
-            ;
-
-        local.headerref =
-                space
-            >>  (*(cl::anychar_p -
-                    (']' | hard_space)))        [actions.headerref_pre]
-            >>  hard_space
-            >>  phrase                          [actions.headerref_post]
-            ;
-
-        local.conceptref =
-                space
-            >>  (*(cl::anychar_p -
-                    (']' | hard_space)))        [actions.conceptref_pre]
-            >>  hard_space
-            >>  phrase                          [actions.conceptref_post]
-            ;
-
-        local.globalref =
-                space
-            >>  (*(cl::anychar_p -
-                    (']' | hard_space)))        [actions.globalref_pre]
-            >>  hard_space
-            >>  phrase                          [actions.globalref_post]
+            >>  (*(cl::anychar_p - phrase_end)) [actions.values.entry(ph::arg1, ph::arg2)]
             ;
 
         elements.add
-            ("*", element_info(element_info::phrase, &local.bold))
-            ("'", element_info(element_info::phrase, &local.italic))
-            ("_", element_info(element_info::phrase, &local.underline))
-            ("^", element_info(element_info::phrase, &local.teletype))
-            ("-", element_info(element_info::phrase, &local.strikethrough))
-            ("\"", element_info(element_info::phrase, &local.quote))
-            ("~", element_info(element_info::phrase, &local.replaceable))
-            ;
-
-        local.bold =
-                blank                           [actions.bold_pre]
-            >>  phrase                          [actions.bold_post]
-            ;
-
-        local.italic =
-                blank                           [actions.italic_pre]
-            >>  phrase                          [actions.italic_post]
-            ;
-
-        local.underline =
-                blank                           [actions.underline_pre]
-            >>  phrase                          [actions.underline_post]
-            ;
-
-        local.teletype =
-                blank                           [actions.teletype_pre]
-            >>  phrase                          [actions.teletype_post]
-            ;
-
-        local.strikethrough =
-                blank                           [actions.strikethrough_pre]
-            >>  phrase                          [actions.strikethrough_post]
-            ;
-
-        local.quote =
-                blank                           [actions.quote_pre]
-            >>  phrase                          [actions.quote_post]
-            ;
-
-        local.replaceable =
-                blank                           [actions.replaceable_pre]
-            >>  phrase                          [actions.replaceable_post]
+            ("*", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::bold))
+            ("'", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::italic))
+            ("_", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::underline))
+            ("^", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::teletype))
+            ("-", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::strikethrough))
+            ("\"", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::quote))
+            ("~", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::replaceable))
+            ("footnote", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::footnote))
             ;
 
         elements.add
-            ("c++", element_info(element_info::phrase, &local.source_mode_cpp))
-            ("python", element_info(element_info::phrase, &local.source_mode_python))
-            ("teletype", element_info(element_info::phrase, &local.source_mode_teletype))
+            ("c++", element_info(element_info::phrase, &local.empty, source_mode_tags::cpp))
+            ("python", element_info(element_info::phrase, &local.empty, source_mode_tags::python))
+            ("teletype", element_info(element_info::phrase, &local.empty, source_mode_tags::teletype))
             ;
         
-        local.source_mode_cpp = cl::eps_p [cl::assign_a(actions.source_mode, "c++")];
-        local.source_mode_python = cl::eps_p [cl::assign_a(actions.source_mode, "python")];
-        local.source_mode_teletype = cl::eps_p [cl::assign_a(actions.source_mode, "teletype")];
+        local.empty = cl::eps_p;
 
-        elements.add
-            ("footnote", element_info(element_info::phrase, &local.footnote))
-            ;
-
-        local.footnote =
-                blank                           [actions.footnote_pre]
-            >>  phrase                          [actions.footnote_post]
+        local.inner_phrase =
+                blank
+            >>  actions.scoped_output()
+                [   phrase                          [actions.phrase_value]
+                ]
             ;
     }
 }
Copied: branches/release/tools/quickbook/src/phrase_tags.hpp (from r70210, /trunk/tools/quickbook/src/phrase_tags.hpp)
==============================================================================
--- /trunk/tools/quickbook/src/phrase_tags.hpp	(original)
+++ branches/release/tools/quickbook/src/phrase_tags.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -20,6 +20,8 @@
         (macroref)(headerref)(conceptref)(globalref)
         (bold)(italic)(underline)(teletype)(strikethrough)(quote)(replaceable)
         (footnote)
+        (escape)
+        (break_mark)
     )
     
     QUICKBOOK_VALUE_NAMED_TAGS(source_mode_tags, 0x550,
Modified: branches/release/tools/quickbook/src/post_process.cpp
==============================================================================
--- branches/release/tools/quickbook/src/post_process.cpp	(original)
+++ branches/release/tools/quickbook/src/post_process.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -7,7 +7,6 @@
     http://www.boost.org/LICENSE_1_0.txt)
 =============================================================================*/
 #include "post_process.hpp"
-#include "utils.hpp"
 #include <boost/spirit/include/classic_core.hpp>
 #include <boost/bind.hpp>
 #include <set>
@@ -403,6 +402,9 @@
 
         void do_end_tag(iter_type f, iter_type l) const
         {
+            if (state.tags.empty())
+                throw quickbook::post_process_failure("Mismatched tags.");
+        
             bool is_flow_tag = state.is_flow_tag(state.tags.top());
             if (!is_flow_tag)
             {
@@ -419,9 +421,8 @@
         int indent;
     };
 
-    int post_process(
+    std::string post_process(
         std::string const& in
-      , std::ostream& out
       , int indent
       , int linewidth)
     {
@@ -430,36 +431,17 @@
         if (linewidth == -1)
             linewidth = 80;     // set default to 80
 
-        try
+        std::string tidy;
+        tidy_compiler state(tidy, linewidth);
+        tidy_grammar g(state, indent);
+        cl::parse_info<iter_type> r = parse(in.begin(), in.end(), g, cl::space_p);
+        if (r.full)
         {
-            std::string tidy;
-            tidy_compiler state(tidy, linewidth);
-            tidy_grammar g(state, indent);
-            cl::parse_info<iter_type> r = parse(in.begin(), in.end(), g, cl::space_p);
-            if (r.full)
-            {
-                out << tidy;
-                return 0;
-            }
-            else
-            {
-                // fallback!
-                ::quickbook::detail::outerr("")
-                    << "Warning: Post Processing Failed."
-                    << std::endl;
-                out << in;
-                return 1;
-            }
+            return tidy;
         }
-
-        catch(...)
-        {
-            // fallback!
-            ::quickbook::detail::outerr("")
-                << "Post Processing Failed."
-                << std::endl;
-            out << in;
-            return 1;
+        else
+        {
+            throw quickbook::post_process_failure("Post Processing Failed.");
         }
     }
 }
Modified: branches/release/tools/quickbook/src/post_process.hpp
==============================================================================
--- branches/release/tools/quickbook/src/post_process.hpp	(original)
+++ branches/release/tools/quickbook/src/post_process.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -9,16 +9,22 @@
 #if !defined(BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP)
 #define BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP
 
-#include <iostream>
 #include <string>
+#include <stdexcept>
 
 namespace quickbook
 {
-    int post_process(
+    std::string post_process(
         std::string const& in
-      , std::ostream& out
-      , int indent
-      , int linewidth);
+      , int indent = -1
+      , int linewidth = -1);
+
+    class post_process_failure : public std::runtime_error
+    {
+    public:
+        explicit post_process_failure(std::string const& error)
+            : std::runtime_error(error) {}
+    };
 }
 
 #endif // BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP
Modified: branches/release/tools/quickbook/src/quickbook.cpp
==============================================================================
--- branches/release/tools/quickbook/src/quickbook.cpp	(original)
+++ branches/release/tools/quickbook/src/quickbook.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -13,22 +13,28 @@
 #include "post_process.hpp"
 #include "utils.hpp"
 #include "input_path.hpp"
-#include <boost/spirit/include/classic_iterator.hpp>
 #include <boost/program_options.hpp>
 #include <boost/filesystem/v3/path.hpp>
 #include <boost/filesystem/v3/operations.hpp>
+#include <boost/filesystem/v3/fstream.hpp>
+#include <boost/range/algorithm.hpp>
 #include <boost/ref.hpp>
+#include <boost/version.hpp>
 
 #include <stdexcept>
-#include <fstream>
-#include <iostream>
 #include <vector>
+#include <iterator>
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <shellapi.h>
+#endif
 
 #if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
 #pragma warning(disable:4355)
 #endif
 
-#define QUICKBOOK_VERSION "Quickbook Version 1.5.4"
+#define QUICKBOOK_VERSION "Quickbook Version 1.5.5"
 
 namespace quickbook
 {
@@ -39,7 +45,7 @@
     tm* current_gm_time; // the current UTC time
     bool debug_mode; // for quickbook developers only
     bool ms_errors = false; // output errors/warnings as if for VS
-    std::vector<std::string> include_path;
+    std::vector<fs::path> include_path;
     std::vector<std::string> preset_defines;
 
     static void set_macros(actions& actor)
@@ -49,8 +55,9 @@
                 end = preset_defines.end();
                 it != end; ++it)
         {
-            iterator first(it->begin(), it->end(), "command line parameter");
-            iterator last(it->end(), it->end());
+            // TODO: Set filename in actor???
+            iterator first(it->begin());
+            iterator last(it->end());
 
             cl::parse(first, last, actor.grammar().command_line_macro);
             // TODO: Check result?
@@ -63,9 +70,8 @@
     //
     ///////////////////////////////////////////////////////////////////////////
     int
-    parse_file(char const* filein_, actions& actor, bool ignore_docinfo)
+    parse_file(fs::path const& filein_, actions& actor, bool ignore_docinfo)
     {
-        using std::cerr;
         using std::vector;
         using std::string;
 
@@ -76,8 +82,8 @@
             return err;
         }
 
-        iterator first(storage.begin(), storage.end(), filein_);
-        iterator last(storage.end(), storage.end());
+        iterator first(storage.begin());
+        iterator last(storage.end());
 
         cl::parse_info<iterator> info = cl::parse(first, last, actor.grammar().doc_info);
 
@@ -94,8 +100,8 @@
 
         if (!info.full)
         {
-            position const pos = info.stop.get_position();
-            detail::outerr(pos.file,pos.line)
+            file_position const& pos = info.stop.get_position();
+            detail::outerr(actor.filename, pos.line)
                 << "Syntax Error near column " << pos.column << ".\n";
             ++actor.error_count;
         }
@@ -104,9 +110,12 @@
     }
 
     static int
-    parse_document(char const* filein_, fs::path const& outdir, string_stream& out, bool ignore_docinfo = false)
+    parse_document(
+        fs::path const& filein_,
+        fs::path const& xinclude_base,
+            string_stream& out)
     {
-        actions actor(filein_, outdir, out);
+        actions actor(filein_, xinclude_base, out);
 
         set_macros(actor);
         bool r = parse_file(filein_, actor);
@@ -117,7 +126,7 @@
 
         if(actor.error_count)
         {
-            detail::outerr(filein_)
+            detail::outerr()
                 << "Error count: " << actor.error_count << ".\n";
         }
 
@@ -126,26 +135,36 @@
 
     static int
     parse_document(
-        char const* filein_
-      , char const* fileout_
+        fs::path const& filein_
+      , fs::path const& fileout_
+      , fs::path const& xinclude_base_
       , int indent
       , int linewidth
       , bool pretty_print)
     {
         int result = 0;
-        fs::path outdir = fs::path(fileout_).parent_path();
-        if (outdir.empty())
-            outdir = ".";
         string_stream buffer;
-        result = parse_document(filein_, outdir, buffer);
+        result = parse_document(filein_, xinclude_base_, buffer);
 
         if (result == 0)
         {
-            std::ofstream fileout(fileout_);
+            fs::ofstream fileout(fileout_);
 
             if (pretty_print)
             {
-                result = post_process(buffer.str(), fileout, indent, linewidth);
+                try
+                {
+                    fileout << post_process(buffer.str(), indent, linewidth);
+                }
+                catch (quickbook::post_process_failure&)
+                {
+                    // fallback!
+                    ::quickbook::detail::outerr()
+                        << "Post Processing Failed."
+                        << std::endl;
+                    fileout << buffer.str();
+                    return 1;
+                }
             }
             else
             {
@@ -166,33 +185,62 @@
 {
     try
     {
+        namespace fs = boost::filesystem;
+        namespace po = boost::program_options;
+
         using boost::program_options::options_description;
         using boost::program_options::variables_map;
         using boost::program_options::store;
         using boost::program_options::parse_command_line;
+        using boost::program_options::wcommand_line_parser;
         using boost::program_options::command_line_parser;
         using boost::program_options::notify;
-        using boost::program_options::value;
         using boost::program_options::positional_options_description;
+        
+        using quickbook::detail::input_string;
 
         // First thing, the filesystem should record the current working directory.
-        boost::filesystem::initial_path<boost::filesystem::path>();
+        fs::initial_path<fs::path>();
+        
+        // Various initialisation methods
+        quickbook::detail::initialise_output();
+        quickbook::detail::initialise_markups();
 
         options_description desc("Allowed options");
+        options_description hidden("Hidden options");
+        options_description all("All options");
+
+#if QUICKBOOK_WIDE_PATHS
+#define PO_VALUE po::wvalue
+#else
+#define PO_VALUE po::value
+#endif
+
         desc.add_options()
             ("help", "produce help message")
             ("version", "print version string")
             ("no-pretty-print", "disable XML pretty printing")
-            ("indent", value<int>(), "indent spaces")
-            ("linewidth", value<int>(), "line width")
-            ("input-file", value<quickbook::detail::input_path>(), "input file")
-            ("output-file", value<quickbook::detail::input_path>(), "output file")
+            ("indent", PO_VALUE<int>(), "indent spaces")
+            ("linewidth", PO_VALUE<int>(), "line width")
+            ("input-file", PO_VALUE<input_string>(), "input file")
+            ("output-file", PO_VALUE<input_string>(), "output file")
             ("debug", "debug mode (for developers)")
             ("ms-errors", "use Microsoft Visual Studio style error & warn message format")
-            ("include-path,I", value< std::vector<quickbook::detail::input_path> >(), "include path")
-            ("define,D", value< std::vector<std::string> >(), "define macro")
+            ("include-path,I", PO_VALUE< std::vector<input_string> >(), "include path")
+            ("define,D", PO_VALUE< std::vector<input_string> >(), "define macro")
         ;
 
+        hidden.add_options()
+            ("expect-errors",
+                "Succeed if the input file contains a correctly handled "
+                "error, fail otherwise.")
+            ("xinclude-base", PO_VALUE<input_string>(),
+                "Generate xincludes as if generating for this target "
+                "directory.")
+        ;
+
+        all.add(desc).add(hidden);
+
         positional_options_description p;
         p.add("input-file", -1);
 
@@ -200,18 +248,59 @@
         int indent = -1;
         int linewidth = -1;
         bool pretty_print = true;
-        store(command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
+
+#if QUICKBOOK_WIDE_PATHS
+        quickbook::ignore_variable(&argc);
+        quickbook::ignore_variable(&argv);
+
+        int wide_argc;
+        LPWSTR* wide_argv = CommandLineToArgvW(GetCommandLineW(), &wide_argc);
+        if (!wide_argv)
+        {
+            quickbook::detail::outerr() << "Error getting argument values." << std::endl;
+            return 1;
+        }
+
+        store(
+            wcommand_line_parser(wide_argc, wide_argv)
+                .options(all)
+                .positional(p)
+                .run(), vm);
+
+        LocalFree(wide_argv);
+#else
+        store(command_line_parser(argc, argv)
+                .options(all)
+                .positional(p)
+                .run(), vm);
+#endif
+
         notify(vm);
 
+        bool expect_errors = vm.count("expect-errors");
+
         if (vm.count("help"))
         {
-            std::cout << desc << "\n";
+            std::ostringstream description_text;
+            description_text << desc;
+
+            quickbook::detail::out()
+                << quickbook::detail::utf8(description_text.str()) << "\n";
+
             return 0;
         }
 
         if (vm.count("version"))
         {
-            std::cout << QUICKBOOK_VERSION << std::endl;
+            std::string boost_version = BOOST_LIB_VERSION;
+            boost::replace(boost_version, '_', '.');
+        
+            quickbook::detail::out()
+                << QUICKBOOK_VERSION
+                << " (Boost "
+                << quickbook::detail::utf8(boost_version)
+                << ")"
+                << std::endl;
             return 0;
         }
 
@@ -252,60 +341,90 @@
             quickbook::debug_mode = false;
         }
         
+        quickbook::include_path.clear();
         if (vm.count("include-path"))
         {
-            std::vector<quickbook::detail::input_path> paths
-                = vm["include-path"].as<
-                    std::vector<quickbook::detail::input_path> >();
-            quickbook::include_path
-                = std::vector<std::string>(paths.begin(), paths.end());
+            boost::transform(
+                vm["include-path"].as<std::vector<input_string> >(),
+                std::back_inserter(quickbook::include_path),
+                quickbook::detail::input_to_path);
         }
 
+        quickbook::preset_defines.clear();
         if (vm.count("define"))
         {
-            quickbook::preset_defines
-                = vm["define"].as<std::vector<std::string> >();
+            boost::transform(
+                vm["define"].as<std::vector<input_string> >(),
+                std::back_inserter(quickbook::preset_defines),
+                quickbook::detail::input_to_utf8);
         }
 
         if (vm.count("input-file"))
         {
-            std::string filein
-                = vm["input-file"].as<quickbook::detail::input_path>();
-            std::string fileout;
+            fs::path filein = quickbook::detail::input_to_path(
+                vm["input-file"].as<input_string>());
+            fs::path fileout;
 
             if (vm.count("output-file"))
             {
-                fileout = vm["output-file"].as<quickbook::detail::input_path>();
+                fileout = quickbook::detail::input_to_path(
+                    vm["output-file"].as<input_string>());
+            }
+            else
+            {
+                fileout = filein;
+                fileout.replace_extension(".xml");
+            }
+            
+            fs::path xinclude_base;
+            if (vm.count("xinclude-base"))
+            {
+                xinclude_base = quickbook::detail::input_to_path(
+                    vm["xinclude-base"].as<input_string>());
             }
             else
             {
-                fileout = quickbook::detail::remove_extension(filein.c_str());
-                fileout += ".xml";
+                xinclude_base = fileout.parent_path();
+                if (xinclude_base.empty())
+                    xinclude_base = ".";
             }
 
-            std::cout << "Generating Output File: "
-                << fileout
+            quickbook::detail::out() << "Generating Output File: "
+                << quickbook::detail::path_to_stream(fileout)
                 << std::endl;
 
-            return quickbook::parse_document(filein.c_str(), fileout.c_str(), indent, linewidth, pretty_print);
+            int r = quickbook::parse_document(filein, fileout, xinclude_base, indent, linewidth, pretty_print);
+
+            if (expect_errors)
+            {
+                if (!r) quickbook::detail::outerr() << "No errors detected for --expect-errors." << std::endl;
+                return !r;
+            }
+            else
+            {
+                return r;
+            }
         }
         else
         {
-            quickbook::detail::outerr("") << "Error: No filename given\n\n"
-                << desc << std::endl;
+            std::ostringstream description_text;
+            description_text << desc;
+        
+            quickbook::detail::outerr() << "No filename given\n\n"
+                << quickbook::detail::utf8(description_text.str()) << std::endl;
             return 1;
         }        
     }
 
     catch(std::exception& e)
     {
-        quickbook::detail::outerr("") << "Error: " << e.what() << "\n";
+        quickbook::detail::outerr() << quickbook::detail::utf8(e.what()) << "\n";
         return 1;
     }
 
     catch(...)
     {
-        quickbook::detail::outerr("") << "Error: Exception of unknown type caught\n";
+        quickbook::detail::outerr() << "Exception of unknown type caught\n";
         return 1;
     }
 
Modified: branches/release/tools/quickbook/src/quickbook.hpp
==============================================================================
--- branches/release/tools/quickbook/src/quickbook.hpp	(original)
+++ branches/release/tools/quickbook/src/quickbook.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -15,17 +15,28 @@
 #include <time.h>
 #include <vector>
 #include <string>
+#include <boost/filesystem/v3/path.hpp>
 #include "fwd.hpp"
 
 namespace quickbook
 {
+    namespace fs = boost::filesystem;
+
     extern tm* current_time; // the current time
     extern tm* current_gm_time; // the current UTC time
     extern bool debug_mode;
-    extern std::vector<std::string> include_path;
+    extern std::vector<fs::path> include_path;
     extern std::vector<std::string> preset_defines;
 
-    int parse_file(char const* filein_, actions& actor, bool ignore_docinfo = false);
+    int parse_file(fs::path const& filein_, actions& actor, bool ignore_docinfo = false);
+    
+    // Some initialisation methods
+    //
+    // Declared here to avoid including other headers
+    namespace detail
+    {
+        void initialise_markups();
+    }
 }
 
 #endif
Deleted: branches/release/tools/quickbook/src/rule_store.hpp
==============================================================================
--- branches/release/tools/quickbook/src/rule_store.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,83 +0,0 @@
-/*=============================================================================
-    Copyright (c) 2010 Daniel James
-
-    Use, modification and distribution is subject to 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)
-=============================================================================*/
-
-// This header defines a class which can will manage quickbook rules for a
-// grammar class so that it doesn't have to declare every rule it'll use.
-//
-// TODO: Noncopyable, but some sort of reference counting scheme would work.
-
-#if !defined(BOOST_SPIRIT_QUICKBOOK_RULE_STORE_HPP)
-#define BOOST_SPIRIT_QUICKBOOK_RULE_STORE_HPP
-
-#include <deque>
-#include <boost/assert.hpp>
-#include <utility>
-
-namespace quickbook
-{
-    namespace detail
-    {
-        template <typename T>
-        void delete_impl(void* ptr) {
-            delete static_cast<T*>(ptr);
-        }
-        
-        struct scoped_void
-        {
-            void* ptr_;
-            void (*del_)(void*);
-            
-            scoped_void() : ptr_(0), del_(0) {}
-            scoped_void(scoped_void const& src) : ptr_(0), del_(0) {
-                BOOST_ASSERT(!src.ptr_);
-            }
-            ~scoped_void() {
-                if(ptr_) del_(ptr_);
-            }
-            
-            void store(void* ptr, void (*del)(void* x)) {
-                ptr = ptr_;
-                del = del_;
-            }
-        private:
-            scoped_void& operator=(scoped_void const&);
-        };
-    }
-    
-    struct rule_store
-    {
-        struct instantiate
-        {
-            rule_store& s;
-            instantiate(rule_store& s) : s(s) {}
-            
-            template <typename T>
-            operator T&() {
-                std::auto_ptr<T> obj(new T());
-                T& ref = *obj;
-                s.store_.push_back(detail::scoped_void());
-                s.store_.back().store(obj.release(), &detail::delete_impl<T>);
-                return ref;
-            }
-        };
-
-        rule_store() {}
-
-        instantiate create() {
-            instantiate i(*this);
-            return i;
-        }
-
-        std::deque<detail::scoped_void> store_;
-    private:
-        rule_store& operator=(rule_store const&);
-        rule_store(rule_store const&);
-    };
-}
-
-#endif
Deleted: branches/release/tools/quickbook/src/scoped_parser.hpp
==============================================================================
--- branches/release/tools/quickbook/src/scoped_parser.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,97 +0,0 @@
-/*=============================================================================
-    Copyright (c) 2010 Daniel James
-    Copyright (c) 2003 Martin Wille
-    http://spirit.sourceforge.net/
-
-  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)
- =============================================================================*/
- 
-// Used to store variables/state while parsing 
-
-#ifndef BOOST_QUICKBOOK_SCOPED_PARSER_HPP
-#define BOOST_QUICKBOOK_SCOPED_PARSER_HPP
-
-#include <boost/spirit/include/classic_core.hpp>
-
-namespace quickbook {
-    namespace cl = boost::spirit::classic;
-    
-    template <typename ScopeT, typename DataT, typename ParserT>
-    struct scoped_parser_impl
-        : public cl::unary< ParserT, cl::parser< scoped_parser_impl<ScopeT, DataT, ParserT> > >
-    {
-        typedef scoped_parser_impl<ScopeT, DataT, ParserT> self_t;
-        typedef cl::unary< ParserT, cl::parser< scoped_parser_impl<ScopeT, DataT, ParserT> > > base_t;
-
-        template <typename ScannerT>
-        struct result :
-            ScopeT::template result<
-                typename cl::parser_result<ParserT, ScannerT>::type
-            >
-        {
-        };
-
-        scoped_parser_impl(DataT& actions, ParserT const &p)
-            : base_t(p)
-            , actions(actions)
-        {}
-
-        template <typename ScannerT>
-        typename result<ScannerT>::type parse(ScannerT const &scan) const
-        {
-            typedef typename ScannerT::iterator_t iterator_t;
-            iterator_t save = scan.first;
-
-            ScopeT scope(actions);
-            typename cl::parser_result<ParserT, ScannerT>::type result
-                = this->subject().parse(scan);
-
-            if (result) {
-                return scan.create_match(result.length(), scope.success(result), save, scan.first);
-            }
-            else {
-                scope.failure();
-                return scan.no_match();
-            }
-        }
-        
-        DataT& actions;
-    };
-
-    ///////////////////////////////////////////////////////////////////////////
-    //
-    // scoped_parser
-    //
-    //      generator for scoped_parser_impl objects
-    //      operator[] returns scoped_parser_impl according to its argument
-    //
-    ///////////////////////////////////////////////////////////////////////////
-    template <typename ScopeT>
-    struct scoped_parser
-    {
-        typedef typename ScopeT::data_type data_type;
-    
-        explicit scoped_parser(data_type& actions)
-            : actions(actions) {}
-
-        template<typename ParserT>
-        scoped_parser_impl
-        <
-            ScopeT,
-            data_type,
-            typename cl::as_parser<ParserT>::type
-        >
-        operator[](ParserT const &p) const
-        {
-            typedef cl::as_parser<ParserT> as_parser_t;
-            typedef typename as_parser_t::type parser_t;
-
-            return scoped_parser_impl<ScopeT, data_type, parser_t>
-                (actions, as_parser_t::convert(p));
-        }
-        
-        data_type& actions;
-    };
-}
-#endif // BOOST_QUICKBOOK_SCOPED_BLOCK_HPP
Modified: branches/release/tools/quickbook/src/syntax_highlight.hpp
==============================================================================
--- branches/release/tools/quickbook/src/syntax_highlight.hpp	(original)
+++ branches/release/tools/quickbook/src/syntax_highlight.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -16,6 +16,7 @@
 #include <boost/spirit/include/classic_symbols.hpp>
 #include <boost/spirit/include/classic_loops.hpp>
 #include "grammar.hpp"
+#include "grammar_impl.hpp" // Just for context stuff. Should move?
 
 namespace quickbook
 {
@@ -57,7 +58,7 @@
                     |   char_           [Process("char", self.out)]
                     |   number          [Process("number", self.out)]
                     |   cl::repeat_p(1)[cl::anychar_p]
-                                        [Unexpected(self.out)]
+                                        [Unexpected(self.out, self.escape_actions)]
                     )
                     ;
 
@@ -69,10 +70,12 @@
                     ;
 
                 qbk_phrase =
-                   *(   g.common
-                    |   (cl::anychar_p - cl::str_p("``"))
+                    self.escape_actions.scoped_context(element_info::in_phrase)
+                    [  *(   g.common
+                        |   (cl::anychar_p - cl::str_p("``"))
                                         [self.escape_actions.plain_char]
-                    )
+                        )
+                    ]
                     ;
 
                 escape =
@@ -206,7 +209,7 @@
                     |   string_         [Process("string", self.out)]
                     |   number          [Process("number", self.out)]
                     |   cl::repeat_p(1)[cl::anychar_p]
-                                        [Unexpected(self.out)]
+                                        [Unexpected(self.out, self.escape_actions)]
                     )
                     ;
 
@@ -218,10 +221,13 @@
                     ;
 
                 qbk_phrase =
-                   *(   g.common
-                    |   (cl::anychar_p - cl::str_p("``"))
+                    self.escape_actions.scoped_context(element_info::in_phrase)
+                    [
+                       *(   g.common
+                        |   (cl::anychar_p - cl::str_p("``"))
                                         [self.escape_actions.plain_char]
-                    )
+                        )
+                    ]
                     ;
 
                 escape =
@@ -362,10 +368,13 @@
                     ;
 
                 qbk_phrase =
-                   *(   g.common
-                    |   (cl::anychar_p - cl::str_p("``"))
+                    self.escape_actions.scoped_context(element_info::in_phrase)
+                    [
+                       *(   g.common
+                        |   (cl::anychar_p - cl::str_p("``"))
                                         [self.escape_actions.plain_char]
-                    )
+                        )
+                    ]
                     ;
 
                 escape =
Modified: branches/release/tools/quickbook/src/template_stack.cpp
==============================================================================
--- branches/release/tools/quickbook/src/template_stack.cpp	(original)
+++ branches/release/tools/quickbook/src/template_stack.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -6,6 +6,8 @@
     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
     http://www.boost.org/LICENSE_1_0.txt)
 =============================================================================*/
+
+#include <cassert>
 #include "template_stack.hpp"
 
 #ifdef BOOST_MSVC
@@ -14,6 +16,23 @@
 
 namespace quickbook
 {
+    template_body::template_body(
+            value const& content,
+            fs::path const& filename
+        )
+        : content(content)
+        , filename(filename)
+    {
+        assert(content.get_tag() == template_tags::block ||
+            content.get_tag() == template_tags::phrase);
+    }
+
+    bool template_body::is_block() const
+    {
+        return content.get_tag() == template_tags::block;
+    }
+
+
     template_stack::template_stack()
         : scope(template_stack::parser(*this))
         , scopes()
Modified: branches/release/tools/quickbook/src/template_stack.hpp
==============================================================================
--- branches/release/tools/quickbook/src/template_stack.hpp	(original)
+++ branches/release/tools/quickbook/src/template_stack.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -14,42 +14,25 @@
 #include <vector>
 #include <boost/tuple/tuple.hpp>
 #include <boost/assert.hpp>
-#include <boost/spirit/include/classic_position_iterator.hpp>
 #include <boost/spirit/include/classic_functor_parser.hpp>
 #include <boost/spirit/include/classic_symbols.hpp>
 #include <boost/next_prior.hpp>
+#include <boost/filesystem/path.hpp>
+#include "fwd.hpp"
+#include "values.hpp"
+#include "template_tags.hpp"
 
 namespace quickbook
 {
+    namespace fs = boost::filesystem;
+
     struct template_body
     {
-        template_body(
-                std::string const& content,
-                boost::spirit::classic::file_position const& position,
-                bool is_block
-            )
-            : content(content)
-            , position(position)
-            , is_block(is_block)
-        {
-        }
+        template_body(value const&, fs::path const&);
+        bool is_block() const;
 
-        template_body(
-                std::string const& content,
-                boost::spirit::classic::file_position_base<char const*> const& position,
-                bool is_block
-            )
-            : content(content)
-            , position(position.file, position.line, position.column)
-            , is_block(is_block)
-        {
-        }
-    
-        std::string content;
-        // Note: Using file_position to store the filename after the file
-        // has been closed.
-        boost::spirit::classic::file_position position;
-        bool is_block;
+        stored_value content;
+        fs::path filename;        
     };
 
     struct template_scope;
@@ -59,29 +42,13 @@
         template_symbol(
                 std::string const& identifier,
                 std::vector<std::string> const& params,
-                std::string const& body,
-                boost::spirit::classic::file_position const& position,
-                bool is_block,
-                template_scope const* parent = 0)
-           : identifier(identifier)
-           , params(params)
-           , body(body, position, is_block)
-           , parent(parent)
-           , callout(false)
-           , callouts() {}
-
-        template_symbol(
-                std::string const& identifier,
-                std::vector<std::string> const& params,
-                std::string const& body,
-                boost::spirit::classic::file_position_base<char const*> const& position,
-                bool is_block,
+                value const& content,
+                fs::path const& filename,
                 template_scope const* parent = 0)
            : identifier(identifier)
            , params(params)
-           , body(body, position, is_block)
+           , body(content, filename)
            , parent(parent)
-           , callout(false)
            , callouts() {}
 
         std::string identifier;
@@ -93,8 +60,7 @@
         // or static_parent for clarity.
         template_scope const* parent;
 
-        bool callout;
-        std::vector<template_body> callouts;
+        stored_value callouts;
     };
 
     typedef boost::spirit::classic::symbols<template_symbol> template_symbols;
Copied: branches/release/tools/quickbook/src/template_tags.hpp (from r70210, /trunk/tools/quickbook/src/template_tags.hpp)
==============================================================================
--- /trunk/tools/quickbook/src/template_tags.hpp	(original)
+++ branches/release/tools/quickbook/src/template_tags.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -14,6 +14,7 @@
 namespace quickbook
 {
     QUICKBOOK_VALUE_TAGS(template_tags, 0x100,
+        (template_)
         (escape)
         (identifier)
         (block)
Modified: branches/release/tools/quickbook/src/utils.cpp
==============================================================================
--- branches/release/tools/quickbook/src/utils.cpp	(original)
+++ branches/release/tools/quickbook/src/utils.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -8,19 +8,17 @@
     http://www.boost.org/LICENSE_1_0.txt)
 =============================================================================*/
 #include "utils.hpp"
+#include "input_path.hpp"
 #include <boost/spirit/include/classic_core.hpp>
+#include <boost/filesystem/v3/fstream.hpp>
 
 #include <cctype>
 #include <cstring>
 #include <stdexcept>
 #include <fstream>
-#include <iostream>
+#include <ostream>
 #include <map>
 
-namespace quickbook {
-    extern bool ms_errors;
-}
-
 namespace quickbook { namespace detail
 {
     void print_char(char ch, std::ostream& out)
@@ -118,21 +116,6 @@
         }
     }
 
-    // remove the extension from a filename
-    std::string
-    remove_extension(std::string const& filename)
-    {
-        std::string::size_type const n = filename.find_last_of('.');
-        if(std::string::npos == n)
-        {
-            return filename;
-        }
-        else
-        {
-            return std::string(filename.begin(), filename.begin()+n);
-        }
-    }
-
     std::string escape_uri(std::string uri)
     {
         for (std::string::size_type n = 0; n < uri.size(); ++n)
@@ -151,36 +134,6 @@
         return uri;
     }
 
-    std::ostream& outerr(std::string const& file, int line)
-    {
-        if (line >= 0)
-        {
-            if (ms_errors)
-                return std::clog << file << "(" << line << "): error: ";
-            else
-                return std::clog << file << ":" << line << ": error: ";
-        }
-        else
-        {
-            return std::clog << file << ": error: ";
-        }
-    }
-
-    std::ostream& outwarn(std::string const& file, int line)
-    {
-        if (line >= 0)
-        {
-            if (ms_errors)
-                return std::clog << file << "(" << line << "): warning: ";
-            else
-                return std::clog << file << ":" << line << ": warning: ";
-        }
-        else
-        {
-            return std::clog << file << ": warning: ";
-        }
-    }
-
     // Read the first few bytes in a file to see it starts with a byte order
     // mark. If it doesn't, then write the characters we've already read in.
     // Although, given how UTF-8 works, if we've read anything in, the files
@@ -238,12 +191,13 @@
 
     template <class InputIterator, class OutputIterator>
     bool normalize(InputIterator begin, InputIterator end,
-            OutputIterator out, std::string const& filename)
+            OutputIterator out, fs::path const& filename)
     {
         std::string encoding = read_bom(begin, end, out);
 
         if(encoding != "UTF-8" && encoding != "") {
-            outerr(filename) << encoding << " is not supported. Please use UTF-8."
+            outerr(filename) << encoding.c_str()
+                << " is not supported. Please use UTF-8."
                 << std::endl;
 
             return false;
@@ -263,15 +217,14 @@
         return true;
     }
 
-    int load(std::string const& filename, std::string& storage)
+    int load(fs::path const& filename, std::string& storage)
     {
-        using std::cerr;
         using std::endl;
         using std::ios;
         using std::ifstream;
         using std::istream_iterator;
 
-        ifstream in(filename.c_str(), std::ios_base::in);
+        fs::ifstream in(filename, std::ios_base::in);
 
         if (!in)
         {
Modified: branches/release/tools/quickbook/src/utils.hpp
==============================================================================
--- branches/release/tools/quickbook/src/utils.hpp	(original)
+++ branches/release/tools/quickbook/src/utils.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -11,64 +11,44 @@
 #define BOOST_SPIRIT_QUICKBOOK_UTILS_HPP
 
 #include <string>
-#include <iostream>
 #include <cctype>
-#include <boost/ref.hpp>
 #include <boost/assert.hpp>
+#include <boost/filesystem/v3/path.hpp>
+#include <boost/range/algorithm_ext/push_back.hpp>
+#include <boost/range/adaptor/transformed.hpp>
 
-namespace quickbook { namespace detail
+
+namespace quickbook {
+
+    namespace fs = boost::filesystem;
+
+namespace detail
 {
     void print_char(char ch, std::ostream& out);
     void print_string(std::basic_string<char> const& str, std::ostream& out);
     void print_space(char ch, std::ostream& out);
     char filter_identifier_char(char ch);
 
-    template <typename Iterator>
+    template <typename Range>
     inline std::string
-    make_identifier(Iterator const& first, Iterator const& last)
+    make_identifier(Range const& range)
     {
         std::string out_name;
-        for (Iterator i = first; i != last; ++i)
-            out_name += filter_identifier_char(*i);
-        return out_name;
-    }
-
-    template <typename T>
-    struct var_wrapper
-        : public ::boost::reference_wrapper<T>
-    {
-        typedef ::boost::reference_wrapper<T> parent;
 
-        explicit inline var_wrapper(T& t) : parent(t) {}
+        boost::push_back(out_name,
+            range | boost::adaptors::transformed(filter_identifier_char));
 
-        inline T& operator()() const { return parent::get(); }
-    };
-
-    template <typename T>
-    inline var_wrapper<T>
-    var(T& t)
-    {
-        return var_wrapper<T>(t);
+        return out_name;
     }
 
     // un-indent a code segment
     void unindent(std::string& program);
 
-    // remove the extension from a filename
-    std::string remove_extension(std::string const& filename);
-
     std::string escape_uri(std::string uri);
 
-    // Preformats an error/warning message so that it can be parsed by
-    // common IDEs. Uses the ms_errors global to determine if VS format
-    // or GCC format. Returns the stream to continue ouput of the verbose
-    // error message.
-    std::ostream & outerr(std::string const& file, int line = -1);
-    std::ostream & outwarn(std::string const& file, int line = -1);
-
     // load file into memory with extra trailing newlines to eliminate
     //  the need to check for end of file in the grammar.
-    int load(std::string const& filename, std::string& storage);
+    int load(fs::path const& filename, std::string& storage);
 
     // given a file extension, return the type of the source file
     // we'll have an internal database for known file types.
Copied: branches/release/tools/quickbook/src/values.cpp (from r70210, /trunk/tools/quickbook/src/values.cpp)
==============================================================================
--- /trunk/tools/quickbook/src/values.cpp	(original)
+++ branches/release/tools/quickbook/src/values.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -12,7 +12,7 @@
 #include <boost/lexical_cast.hpp>
 
 #define UNDEFINED_ERROR() \
-    throw value_error( \
+    throw value_undefined_method( \
         std::string(BOOST_CURRENT_FUNCTION) +\
         " not defined for " + \
         this->type_name() + \
@@ -24,9 +24,17 @@
     ////////////////////////////////////////////////////////////////////////////
     // Value Error
     
+    struct value_undefined_method : value_error
+    {
+        value_undefined_method(std::string const&);
+    };
+    
     value_error::value_error(std::string const& x)
         : std::logic_error(x) {}
-    
+
+    value_undefined_method::value_undefined_method(std::string const& x)
+        : value_error(x) {}
+
     ////////////////////////////////////////////////////////////////////////////
     // Node
 
@@ -44,15 +52,51 @@
         file_position value_node::get_position() const { UNDEFINED_ERROR(); }
         int value_node::get_int() const { UNDEFINED_ERROR(); }
         std::string value_node::get_quickbook() const { UNDEFINED_ERROR(); }
-        std::string value_node::get_boostbook() const {  UNDEFINED_ERROR(); }
-        value_node* value_node::get_list() const {  UNDEFINED_ERROR(); }
+        value_node::qbk_range value_node::get_quickbook_range() const { UNDEFINED_ERROR(); }
+        std::string value_node::get_boostbook() const { UNDEFINED_ERROR(); }
+        value_node* value_node::get_list() const { UNDEFINED_ERROR(); }
 
         bool value_node::empty() const { return false; }
+        bool value_node::check() const { return true; }
         bool value_node::is_list() const { return false; }
         bool value_node::is_string() const { return false; }
+        bool value_node::equals(value_node*) const { UNDEFINED_ERROR(); }
     }
 
     ////////////////////////////////////////////////////////////////////////////
+    // List end value
+    //
+    // A special value for marking the end of lists.
+
+    namespace detail
+    {
+        struct value_list_end_impl : public value_node
+        {
+            static value_list_end_impl instance;
+        private:
+            value_list_end_impl()
+                : value_node(value::default_tag)
+            {
+                intrusive_ptr_add_ref(&instance);
+                next_ = this;
+            }
+
+            virtual char const* type_name() const { return "list end"; }
+            virtual value_node* clone() const { UNDEFINED_ERROR(); }
+
+            virtual bool equals(value_node* other) const
+            { return this == other; }
+
+            bool empty() const { UNDEFINED_ERROR(); }
+            bool check() const { UNDEFINED_ERROR(); }
+            bool is_list() const { UNDEFINED_ERROR(); }
+            bool is_string() const { UNDEFINED_ERROR(); }
+        };
+
+        value_list_end_impl value_list_end_impl::instance;
+    }
+        
+    ////////////////////////////////////////////////////////////////////////////
     // Empty/nil values
     //
     // (nil is just a special case of empty, don't be mislead by the name
@@ -76,6 +120,12 @@
 
             virtual bool empty() const
                 { return true; }
+
+            virtual bool check() const
+                { return false; }
+
+            virtual bool equals(value_node* other) const
+                { return !other->check(); }
             
             friend value quickbook::empty_value(value::tag_type);
         };
@@ -88,9 +138,10 @@
                 : value_empty_impl(value::default_tag)
             {
                 intrusive_ptr_add_ref(&instance);
+                next_ = &value_list_end_impl::instance;
             }
         };
-        
+
         value_nil_impl value_nil_impl::instance;
 
         value_node* value_empty_impl::new_(value::tag_type t) {
@@ -107,6 +158,11 @@
         }
     }
 
+    value empty_value(value::tag_type t)
+    {
+        return value(detail::value_empty_impl::new_(t));
+    }
+
     ////////////////////////////////////////////////////////////////////////////
     // value_counted
 
@@ -140,24 +196,10 @@
             intrusive_ptr_add_ref(value_);
         }
     
-        value_counted& value_counted::operator=(value_counted x)
-        {
-            swap(x);
-            return *this;
-        }
-    
         value_counted::~value_counted()
         {
             intrusive_ptr_release(value_);
         }
-
-        void value_counted::store()
-        {
-            value_node* new_value = value_->store();
-            intrusive_ptr_add_ref(new_value);
-            intrusive_ptr_release(value_);
-            value_ = new_value;
-        }
     }
     
     ////////////////////////////////////////////////////////////////////////////
@@ -173,7 +215,7 @@
     {
     }
 
-    value::value(detail::value_ref x)
+    value::value(detail::value_base const& x)
         : detail::value_counted(x)
     {
     }
@@ -182,19 +224,35 @@
         : detail::value_counted(x)
     {
     }
-    
+
+    value& value::operator=(value x)
+    {
+        swap(x);
+        return *this;
+    }
+
     ////////////////////////////////////////////////////////////////////////////
-    // Iterator
+    // stored_value
 
-    namespace detail
+    stored_value::stored_value()
+        : detail::value_counted()
     {
-        value::iterator::iterator()
-            : ptr_(&value_nil_impl::instance) {}
     }
 
-    value empty_value(value::tag_type t)
+    stored_value::stored_value(stored_value const& x)
+        : detail::value_counted(x)
+    {
+    }
+
+    stored_value::stored_value(detail::value_base const& x)
+        : detail::value_counted(x.value_->store())
     {
-        return value(detail::value_empty_impl::new_(t));
+    }
+
+    stored_value& stored_value::operator=(stored_value x)
+    {
+        swap(x);
+        return *this;
     }
 
     ////////////////////////////////////////////////////////////////////////////
@@ -213,7 +271,8 @@
             virtual std::string get_quickbook() const;
             virtual std::string get_boostbook() const;
             virtual bool empty() const;
-    
+            virtual bool equals(value_node*) const;
+
             int value_;
         };
 
@@ -246,6 +305,15 @@
         {
             return false;
         }
+
+        bool value_int_impl::equals(value_node* other) const {
+            try {
+                return value_ == other->get_int();
+            }
+            catch(value_undefined_method&) {
+                return false;
+            }
+        }
     }
 
     value int_value(int v, value::tag_type t)
@@ -270,7 +338,8 @@
             virtual std::string get_boostbook() const;
             virtual bool is_string() const;
             virtual bool empty() const;
-    
+            virtual bool equals(value_node*) const;
+
             std::string value_;
         };
     
@@ -289,8 +358,10 @@
             virtual value_node* clone() const;
             virtual file_position get_position() const;
             virtual std::string get_quickbook() const;
+            qbk_range get_quickbook_range() const;
             virtual bool is_string() const;
             virtual bool empty() const;
+            virtual bool equals(value_node*) const;
     
             std::string value_;
             file_position position_;
@@ -308,9 +379,11 @@
             virtual value_node* store();
             virtual file_position get_position() const;
             virtual std::string get_quickbook() const;
+            qbk_range get_quickbook_range() const;
             virtual bool is_string() const;
             virtual bool empty() const;
-    
+            virtual bool equals(value_node*) const;
+
             quickbook::iterator begin_;
             quickbook::iterator end_;
         };
@@ -332,9 +405,11 @@
             virtual value_node* clone() const;
             virtual file_position get_position() const;
             virtual std::string get_quickbook() const;
+            qbk_range get_quickbook_range() const;
             virtual std::string get_boostbook() const;
             virtual bool is_string() const;
             virtual bool empty() const;
+            virtual bool equals(value_node*) const;
 
             std::string qbk_value_;
             std::string bbk_value_;
@@ -375,6 +450,15 @@
         bool value_string_impl::empty() const
             { return value_.empty(); }
 
+        bool value_string_impl::equals(value_node* other) const {
+            try {
+                return value_ == other->get_boostbook();
+            }
+            catch(value_undefined_method&) {
+                return false;
+            }
+        }
+
         // value_qbk_string_impl
     
         value_qbk_string_impl::value_qbk_string_impl(
@@ -408,12 +492,26 @@
         std::string value_qbk_string_impl::get_quickbook() const
             { return value_; }
 
+        value::qbk_range value_qbk_string_impl::get_quickbook_range() const
+            { return qbk_range(
+                iterator(value_.begin(), position_),
+                iterator(value_.end())); }
+
         bool value_qbk_string_impl::is_string() const
             { return true; }
 
         bool value_qbk_string_impl::empty() const
             { return value_.empty(); }
-    
+
+        bool value_qbk_string_impl::equals(value_node* other) const {
+            try {
+                return value_ == other->get_quickbook();
+            }
+            catch(value_undefined_method&) {
+                return false;
+            }
+        }
+
         // value_qbk_ref_impl
     
         value_qbk_ref_impl::value_qbk_ref_impl(
@@ -443,12 +541,24 @@
         std::string value_qbk_ref_impl::get_quickbook() const
             { return std::string(begin_.base(), end_.base()); }
 
+        value::qbk_range value_qbk_ref_impl::get_quickbook_range() const
+            { return qbk_range(begin_, end_); }
+
         bool value_qbk_ref_impl::is_string() const
             { return true; }
 
         bool value_qbk_ref_impl::empty() const
             { return begin_ == end_; }
     
+        bool value_qbk_ref_impl::equals(value_node* other) const {
+            try {
+                return this->get_quickbook() == other->get_quickbook();
+            }
+            catch(value_undefined_method&) {
+                return false;
+            }
+        }
+
         // value_qbk_bbk_impl
     
         value_qbk_bbk_impl::value_qbk_bbk_impl(
@@ -503,6 +613,11 @@
         std::string value_qbk_bbk_impl::get_quickbook() const
             { return qbk_value_; }
 
+        value::qbk_range value_qbk_bbk_impl::get_quickbook_range() const
+            { return qbk_range(
+                iterator(qbk_value_.begin(), position_),
+                iterator(qbk_value_.end())); }
+
         std::string value_qbk_bbk_impl::get_boostbook() const
             { return bbk_value_; }
 
@@ -512,6 +627,20 @@
         // Should this test the quickbook, the boostbook or both?
         bool value_qbk_bbk_impl::empty() const
             { return bbk_value_.empty(); }
+
+        bool value_qbk_bbk_impl::equals(value_node* other) const {
+            try {
+                return this->get_quickbook() == other->get_quickbook();
+            }
+            catch(value_undefined_method&) {}
+
+            try {
+                return this->get_boostbook() == other->get_boostbook();
+            }
+            catch(value_undefined_method&) {}
+
+            return false;
+        }
     }
 
     value qbk_value(iterator x, iterator y, value::tag_type t)
@@ -557,7 +686,7 @@
 
         value_node** list_ref_back(value_node** back)
         {
-            while(*back != &value_nil_impl::instance) {
+            while(*back != &value_list_end_impl::instance) {
                 intrusive_ptr_add_ref(*back);
                 back = &(*back)->next_;
             }
@@ -567,7 +696,7 @@
 
         void list_ref(value_node* ptr)
         {
-            while(ptr != &value_nil_impl::instance) {
+            while(ptr != &value_list_end_impl::instance) {
                 intrusive_ptr_add_ref(ptr);
                 ptr = ptr->next_;
             }
@@ -575,7 +704,7 @@
 
         void list_unref(value_node* ptr)
         {
-            while(ptr != &value_nil_impl::instance) {
+            while(ptr != &value_list_end_impl::instance) {
                 value_node* next = ptr->next_;
                 intrusive_ptr_release(ptr);
                 ptr = next;
@@ -584,7 +713,7 @@
 
         value_node** merge_sort(value_node** l)
         {
-            if(*l == &value_nil_impl::instance)
+            if(*l == &value_list_end_impl::instance)
                 return l;
             else
                 return merge_sort(l, 9999);
@@ -594,7 +723,7 @@
         {
             value_node** p = &(*l)->next_;
             for(int count = 0;
-                count < recurse_limit && *p != &value_nil_impl::instance;
+                count < recurse_limit && *p != &value_list_end_impl::instance;
                 ++count)
             {
                 p = merge(l, p, merge_sort(p, count));
@@ -639,7 +768,7 @@
             *first = *second;
             *second = *third;
             *third = tmp;
-            //if(*second != &value_nil_impl::instance) back = second;
+            //if(*second != &value_list_end_impl::instance) back = second;
         }
     }
     }
@@ -652,27 +781,36 @@
         struct value_list_impl : public value_node
         {
             value_list_impl(value::tag_type);
-            value_list_impl(value_node*, value::tag_type);
+            value_list_impl(value_list_builder&, value::tag_type);
         private:
+            value_list_impl(value_list_impl const&);
+
             char const* type_name() const { return "list"; }
 
             virtual ~value_list_impl();
             virtual value_node* clone() const;
             virtual value_node* store();
             virtual bool empty() const;
+            virtual bool equals(value_node*) const;
+
             virtual bool is_list() const;
-    
             virtual value_node* get_list() const;
     
             value_node* head_;
         };
-
+        
         value_list_impl::value_list_impl(value::tag_type tag)
-            : value_node(tag), head_(&value_nil_impl::instance)
+            : value_node(tag), head_(&value_list_end_impl::instance)
         {}
     
-        value_list_impl::value_list_impl(value_node* ptr, value::tag_type tag)
-            : value_node(tag), head_(ptr)
+        value_list_impl::value_list_impl(value_list_builder& builder,
+                value::tag_type tag)
+            : value_node(tag), head_(builder.release())
+        {
+        }
+
+        value_list_impl::value_list_impl(value_list_impl const& x)
+            : value_node(x.tag_), head_(x.head_)
         {
             list_ref(head_);
         }
@@ -684,17 +822,16 @@
 
         value_node* value_list_impl::clone() const
         {
-            return new value_list_impl(head_, tag_);
+            return new value_list_impl(*this);
         }
 
-        // TODO: Could reuse nodes is any node has a reference count of 1.
         value_node* value_list_impl::store()
         {
             value_node* pos = head_;
             boost::intrusive_ptr<value_node> new_node;
 
-            while(true) {
-                if(pos == &value_nil_impl::instance)
+            for(;;) {
+                if(pos == &value_list_end_impl::instance)
                     return this;
                 new_node = pos->store();
                 if(new_node.get() != pos) break;
@@ -703,23 +840,23 @@
 
             value_list_builder build;
 
-            for(value_node* pos2 = head_;
-                pos2 != &value_nil_impl::instance;
-                pos2 = pos2->next_)
-            {
-                if(pos2 == pos)
-                    build.append(new_node.get());
-                else
-                    build.append(pos2);
-            }
+            value_node* pos2 = head_;
 
-            return new value_list_impl(build.get(), tag_);
-        }
+            for(;pos2 != pos; pos2 = pos2->next_)
+                build.append(pos2);
+
+            build.append(new_node.get());
+            pos2 = pos2->next_;
+
+            for(;pos2 != &value_list_end_impl::instance; pos2 = pos2->next_)
+                build.append(pos2->store());
 
+            return new value_list_impl(build, tag_);
+        }
 
         bool value_list_impl::empty() const
         {
-            return head_ == &value_nil_impl::instance;
+            return head_ == &value_list_end_impl::instance;
         }
     
         bool value_list_impl::is_list() const
@@ -731,6 +868,25 @@
         {
             return head_;
         }
+
+        bool value_list_impl::equals(value_node* other) const {
+            value_node* x1;
+
+            try {
+                 x1 = other->get_list();
+            }
+            catch(value_undefined_method&) {
+                return false;
+            }
+
+            for(value_node *x2 = head_; x1 != x2; x1 = x1->next_, x2 = x2->next_)
+            {
+                if (x2 == &value_list_end_impl::instance ||
+                    !x1->equals(x2)) return false;
+            }
+            
+            return true;
+        }
     }
 
     //////////////////////////////////////////////////////////////////////////
@@ -741,7 +897,7 @@
         // value_list_builder
     
         value_list_builder::value_list_builder()
-            : head_(&value_nil_impl::instance)
+            : head_(&value_list_end_impl::instance)
             , back_(&head_)
         {}
 
@@ -762,9 +918,11 @@
             if(other.back_ == &head_) other.back_ = &other.head_;
         }
 
-        // TODO: Multiple list refs are incompatible with 'store'
-        value_node* value_list_builder::get() const {
-            return head_;
+        value_node* value_list_builder::release() {
+            value_node* r = head_;
+            head_ = &value_list_end_impl::instance;
+            back_ = &head_;
+            return r;
         }
     
         void value_list_builder::append(value_node* item)
@@ -779,7 +937,7 @@
         void value_list_builder::sort()
         {
             back_ = merge_sort(&head_);
-            assert(*back_ == &value_nil_impl::instance);
+            assert(*back_ == &value_list_end_impl::instance);
         }
     }
 
@@ -811,8 +969,8 @@
         swap(*store);
     }
 
-    value value_builder::get() {
-        return value(new detail::value_list_impl(current.get(), list_tag));
+    value value_builder::release() {
+        return value(new detail::value_list_impl(current, list_tag));
     }
 
     void value_builder::reset() {
@@ -825,6 +983,14 @@
         current.append(item.value_);
     }
 
+    void value_builder::extend(value const& list) {
+        for (value::iterator begin = list.begin(), end = list.end();
+            begin != end; ++begin)
+        {
+            insert(*begin);
+        }
+    }
+
     void value_builder::start_list(value::tag_type tag) {
         value::tag_type saved_tag = tag;
         save();
@@ -832,7 +998,7 @@
     }
 
     void value_builder::finish_list() {
-        value list = get();
+        value list = release();
         restore();
         insert(list);
     }
@@ -845,4 +1011,13 @@
     {
         current.sort();
     }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Iterator
+
+    namespace detail
+    {
+        value::iterator::iterator()
+            : ptr_(&value_list_end_impl::instance) {}
+    }
 }
Copied: branches/release/tools/quickbook/src/values.hpp (from r70210, /trunk/tools/quickbook/src/values.hpp)
==============================================================================
--- /trunk/tools/quickbook/src/values.hpp	(original)
+++ branches/release/tools/quickbook/src/values.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -16,12 +16,14 @@
 #include <cassert>
 #include <boost/scoped_ptr.hpp>
 #include <boost/iterator/iterator_traits.hpp>
+#include <boost/range/iterator_range.hpp>
 #include <stdexcept>
 #include "fwd.hpp"
 
 namespace quickbook
 {
     class value;
+    class stored_value;
     class value_builder;
     class value_error;
 
@@ -38,6 +40,7 @@
 
         public:
             typedef int tag_type;
+            typedef boost::iterator_range<quickbook::iterator> qbk_range;
 
         protected:
             explicit value_node(tag_type);
@@ -51,11 +54,14 @@
             virtual file_position get_position() const;
             virtual std::string get_quickbook() const;
             virtual std::string get_boostbook() const;
+            virtual qbk_range get_quickbook_range() const;
             virtual int get_int() const;
 
+            virtual bool check() const;
             virtual bool empty() const;
             virtual bool is_list() const;
             virtual bool is_string() const;
+            virtual bool equals(value_node*) const;
 
             virtual value_node* get_list() const;
             
@@ -83,6 +89,7 @@
             typedef iterator const_iterator;
             typedef value_node::tag_type tag_type;
             enum { default_tag = 0 };
+            typedef boost::iterator_range<quickbook::iterator> qbk_range;
 
         protected:
             explicit value_base(value_node* base)
@@ -93,9 +100,9 @@
 
             ~value_base() {}
 
-        public:
             void swap(value_base& x) { std::swap(value_, x.value_); }
-
+        public:
+            bool check() const { return value_->check(); }
             bool empty() const { return value_->empty(); }
             bool is_list() const { return value_->is_list(); }
             bool is_string() const { return value_->is_string(); }
@@ -109,17 +116,25 @@
             { return value_->get_position(); }
             std::string get_quickbook() const
             { return value_->get_quickbook(); }
+            qbk_range get_quickbook_range() const
+            { return value_->get_quickbook_range(); }
             std::string get_boostbook() const
             { return value_->get_boostbook(); }
             int get_int() const
             { return value_->get_int(); }
 
+            // Equality is pretty inefficient. Not really designed for anything
+            // more than testing purposes.
+            friend bool operator==(value_base const& x, value_base const& y)
+            { return x.value_->equals(y.value_); }
+
         protected:
             value_node* value_;
 
             // value_builder needs to access 'value_' to get the node
             // from a value.
             friend class quickbook::value_builder;
+            friend class quickbook::stored_value;
         };
         
         ////////////////////////////////////////////////////////////////////////
@@ -173,15 +188,13 @@
 
         class value_counted : public value_base
         {
-        public:
+            value_counted& operator=(value_counted const&);
+        protected:
             value_counted();
             value_counted(value_counted const&);
             value_counted(value_base const&);
             value_counted(value_node*);
-            value_counted& operator=(value_counted);
             ~value_counted();
-
-            void store();
         };
 
         ////////////////////////////////////////////////////////////////////////
@@ -198,7 +211,7 @@
             value_list_builder(value_node*);
             ~value_list_builder();
             void swap(value_list_builder& b);
-            value_node* get() const;
+            value_node* release();
 
             void append(value_node*);
             void sort();
@@ -218,8 +231,20 @@
     public:
         value();
         value(value const&);
-        value(detail::value_ref);
+        value(detail::value_base const&);
         explicit value(detail::value_node*);
+        value& operator=(value);
+        void swap(value& x) { detail::value_counted::swap(x); }
+    };
+    
+    class stored_value : public detail::value_counted
+    {
+    public:
+        stored_value();
+        stored_value(stored_value const&);
+        stored_value(detail::value_base const&);
+        stored_value& operator=(stored_value);
+        void swap(stored_value& x) { detail::value_counted::swap(x); }
     };
 
     // Empty
@@ -252,11 +277,12 @@
         void save();
         void restore();
 
-        value get();
+        value release();
 
         void reset();
         void set_tag(value::tag_type);
         void insert(value const&);
+        void extend(value const&);
 
         void start_list(value::tag_type = value::default_tag);
         void finish_list();
@@ -273,10 +299,10 @@
     // Value Error
     //
     
-    class value_error : std::logic_error
+    class value_error : public std::logic_error
     {
     public:
-        value_error(std::string const&);
+        explicit value_error(std::string const&);
     };
 
     ////////////////////////////////////////////////////////////////////////////
@@ -305,7 +331,6 @@
             value::iterator* ptr_;
         };
 
-
         typedef iterator const_iterator;
         typedef iterator::reference reference;
     
@@ -323,13 +348,13 @@
 
         reference consume()
         {
-            assert(check());
+            assert_check();
             return *pos_++;
         }
 
         reference consume(value::tag_type t)
         {
-            assert(check(t));
+            assert_check(t);
             return *pos_++;
         }
 
@@ -365,12 +390,27 @@
         
         void finish() const
         {
-            assert(pos_ == end_);
+            if (pos_ != end_)
+            throw value_error("Not all values handled.");
         }
 
         iterator begin() { return iterator(&pos_); }
         iterator end() { return iterator(&end_); }
     private:
+
+    void assert_check() const
+    {
+        if (pos_ == end_)
+        throw value_error("Attempt to read past end of value list.");
+    }
+
+    void assert_check(value::tag_type t) const
+    {
+        assert_check();
+        if (t != pos_->get_tag())
+        throw value_error("Incorrect value tag.");
+    }
+
         value list_;
         value::iterator pos_, end_;
     };
Copied: branches/release/tools/quickbook/src/values_parse.hpp (from r70210, /trunk/tools/quickbook/src/values_parse.hpp)
==============================================================================
--- /trunk/tools/quickbook/src/values_parse.hpp	(original)
+++ branches/release/tools/quickbook/src/values_parse.hpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -123,7 +123,7 @@
             , sort(builder)
             {}
     
-        value get() { return builder.get(); }
+        value release() { return builder.release(); }
 
         value_builder builder;
         scoped_parser<value_builder_save> save;
Modified: branches/release/tools/quickbook/test/Jamfile.v2
==============================================================================
--- branches/release/tools/quickbook/test/Jamfile.v2	(original)
+++ branches/release/tools/quickbook/test/Jamfile.v2	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -6,9 +6,18 @@
 #   http://www.boost.org/LICENSE_1_0.txt)
 #
 
-project test ;
+project test
+    : requirements
+        <toolset>msvc:<debug-symbols>off
+    ;
+
+build-project doc-info ;
+build-project unit ;
+build-project command-line ;
+build-project snippets ;
+build-project "include" ;
 
-import quickbook-testing : quickbook-test quickbook-fail-test ;
+import quickbook-testing : quickbook-test quickbook-error-test ;
 
 test-suite quickbook.test :
     [ quickbook-test quickbook-manual ]
@@ -27,8 +36,8 @@
     [ quickbook-test template-section ]
     [ quickbook-test mismatched-brackets-1 ]
     [ quickbook-test mismatched-brackets-2 ]
-    [ quickbook-fail-test mismatched-brackets-3 ]
-    #[ quickbook-test xinclude ]
+    [ quickbook-error-test mismatched-brackets-3 ]
+    [ quickbook-test xinclude : : : <quickbook-xinclude-base>../src ]
     [ quickbook-test import ]
     [ quickbook-test include_1_5 ]
     [ quickbook-test include_1_6 ]
@@ -46,38 +55,37 @@
     [ quickbook-test list_test ]
     [ quickbook-test cond_phrase ]
     [ quickbook-test macro ]
-    [ quickbook-test doc-info-1 ]
-    [ quickbook-test doc-info-2 ]
-    [ quickbook-test doc-info-3 ]
-    [ quickbook-test doc-info-4 ]
     [ quickbook-test callouts ]
     [ quickbook-test simple_markup ]
     [ quickbook-test xml-escape_1_2 ]
     [ quickbook-test xml-escape_1_5 ]
     [ quickbook-test blocks ]
+    [ quickbook-test elements_1_5 ]
+    [ quickbook-test elements_1_6 ]
     [ quickbook-test newline ]
     [ quickbook-test anchor ]
     [ quickbook-test command_line_macro : : : <quickbook-test-define>__macro__=*bold* ]
-    [ quickbook-fail-test fail-include ]
-    [ quickbook-fail-test fail-import ]
-    [ quickbook-fail-test fail-template-arguments1 ]
-    [ quickbook-fail-test fail-template-arguments2 ]
-    [ quickbook-fail-test fail-template-arguments3 ]
-    [ quickbook-fail-test fail-cpp-mismatched-escape ]
-    [ quickbook-fail-test fail-python-mismatched-escape ]
-    [ quickbook-fail-test fail-post-process ]
-    [ quickbook-fail-test fail-parse-error1 ]
-    [ quickbook-fail-test fail-parse-error2 ]
-    [ quickbook-fail-test fail-template-lookup1 ]
-    [ quickbook-fail-test fail-template-section-1 ]
-    [ quickbook-fail-test fail-template-section-2 ]
-    [ quickbook-fail-test fail-template-section-3 ]
-    [ quickbook-fail-test fail-unknown-quickbook-1 ]
-    [ quickbook-fail-test fail-unknown-quickbook-2 ]
-    [ quickbook-fail-test fail-unknown-quickbook-3 ]
+    [ quickbook-error-test fail-include ]
+    [ quickbook-error-test fail-import ]
+    [ quickbook-error-test fail-template-arguments1 ]
+    [ quickbook-error-test fail-template-arguments2 ]
+    [ quickbook-error-test fail-template-arguments3 ]
+    [ quickbook-error-test fail-cpp-mismatched-escape ]
+    [ quickbook-error-test fail-python-mismatched-escape ]
+    [ quickbook-error-test fail-post-process ]
+    [ quickbook-error-test fail-parse-error1 ]
+    [ quickbook-error-test fail-parse-error2 ]
+    [ quickbook-error-test fail-template-lookup1 ]
+    [ quickbook-error-test fail-template-section-1 ]
+    [ quickbook-error-test fail-template-section-2 ]
+    [ quickbook-error-test fail-template-section-3 ]
+    [ quickbook-error-test fail-unknown-quickbook-1 ]
+    [ quickbook-error-test fail-unknown-quickbook-2 ]
+    [ quickbook-error-test fail-unknown-quickbook-3 ]
+    [ quickbook-error-test fail-mismatched-boostbook-escape ]
     [ quickbook-test utf-8 ]
     [ quickbook-test utf-8-bom ]
     [ quickbook-test unicode-escape ]
-    [ quickbook-fail-test utf-16be-bom ]
-    [ quickbook-fail-test utf-16le-bom ]
+    [ quickbook-error-test utf-16be-bom ]
+    [ quickbook-error-test utf-16le-bom ]
     ;
Modified: branches/release/tools/quickbook/test/anchor.gold
==============================================================================
--- branches/release/tools/quickbook/test/anchor.gold	(original)
+++ branches/release/tools/quickbook/test/anchor.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -10,37 +10,74 @@
       We want to make sure they appear in the correct place. <anchor id="a3"/>
     </para>
     <anchor id="anchor_test.anchors.this_heading_shouldn_t_pick_up_the_previous_anchor"/>
-    <bridgehead renderas="sect3">
+    <bridgehead renderas="sect3" id="anchor_test.anchors.this_heading_shouldn_t_pick_up_the_previous_anchor-heading">
       <link linkend="anchor_test.anchors.this_heading_shouldn_t_pick_up_the_previous_anchor">This
       heading shouldn't pick up the previous anchor</link>
     </bridgehead>
     <anchor id="a4"/> <anchor id="anchor_test.anchors.this_heading_should_pick_up_the_previous_anchor"/>
-    <bridgehead renderas="sect3">
+    <bridgehead renderas="sect3" id="anchor_test.anchors.this_heading_should_pick_up_the_previous_anchor-heading">
       <link linkend="anchor_test.anchors.this_heading_should_pick_up_the_previous_anchor">This
       heading should pick up the previous anchor</link>
     </bridgehead>
     <anchor id="a5"/> <anchor id="anchor_test.anchors.and_this_one"/>
-    <bridgehead renderas="sect3">
+    <bridgehead renderas="sect3" id="anchor_test.anchors.and_this_one-heading">
       <link linkend="anchor_test.anchors.and_this_one">And this one</link>
     </bridgehead>
     <anchor id="a6"/> <anchor id="anchor_test.anchors.also_this_one"/>
-    <bridgehead renderas="sect3">
+    <bridgehead renderas="sect3" id="anchor_test.anchors.also_this_one-heading">
       <link linkend="anchor_test.anchors.also_this_one">Also this one</link>
     </bridgehead>
     <anchor id="a7"/> <anchor id="anchors.finally_this"/>
-    <bridgehead renderas="sect3">
+    <bridgehead renderas="sect3" id="anchors.finally_this-heading">
       Finally this
     </bridgehead>
     <anchor id="a8"/>
   </section>
   <section id="anchor_test.section_anchor">
-    <anchor id="a9"/> <title>Section Anchor</title>
+    <title><anchor id="a9"/> Section Anchor</title>
     <section id="anchor_test.nested_section">
-      <anchor id="a10"/> <title>Nested Section</title>
+      <title><anchor id="a10"/> Nested Section</title>
     </section>
     <anchor id="a11"/>
   </section>
   <section id="anchor_test.conditional_section_anchor">
-    <anchor id="a12"/> <title>Conditional Section Anchor</title>
+    <title><anchor id="a12"/> Conditional Section Anchor</title>
+  </section>
+  <section id="anchor_test.lists">
+    <title>Lists</title> <anchor id="a14"/>
+    <itemizedlist>
+      <listitem>
+        <simpara>
+          Item 1
+        </simpara>
+      </listitem>
+      <listitem>
+        <simpara>
+          Item 2
+        </simpara>
+      </listitem>
+      <listitem>
+        <simpara>
+          Nested List <anchor id="a15"/>
+          <itemizedlist>
+            <listitem>
+              <simpara>
+                Nested Item 1
+              </simpara>
+            </listitem>
+            <listitem>
+              <simpara>
+                Nested Item 2
+              </simpara>
+            </listitem>
+          </itemizedlist>
+        </simpara>
+      </listitem>
+      <listitem>
+        <simpara>
+          Item 3
+        </simpara>
+      </listitem>
+    </itemizedlist>
   </section>
 </article>
Modified: branches/release/tools/quickbook/test/anchor.quickbook
==============================================================================
--- branches/release/tools/quickbook/test/anchor.quickbook	(original)
+++ branches/release/tools/quickbook/test/anchor.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -33,4 +33,18 @@
 
 [#a12][?__not_defined__ #a13]
 [section Conditional Section Anchor]
+[endsect]
+
+[section Lists]
+
+[#a14]
+
+* Item 1
+* Item 2
+* Nested List
+  [#a15]
+  * Nested Item 1
+  * Nested Item 2
+* Item 3
+
 [endsect]
\ No newline at end of file
Modified: branches/release/tools/quickbook/test/blocks.gold
==============================================================================
--- branches/release/tools/quickbook/test/blocks.gold	(original)
+++ branches/release/tools/quickbook/test/blocks.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -3,7 +3,7 @@
 <article id="various_blocks" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
  xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>Various blocks</title> <anchor id="various_blocks.blockquotes"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="various_blocks.blockquotes-heading">
     <link linkend="various_blocks.blockquotes">Blockquotes</link>
   </bridgehead>
   <para>
@@ -26,7 +26,7 @@
     </para>
   </blockquote>
   <anchor id="various_blocks.admonitions"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="various_blocks.admonitions-heading">
     <link linkend="various_blocks.admonitions">Admonitions</link>
   </bridgehead>
   <warning>
@@ -63,7 +63,7 @@
     </para>
   </warning>
   <anchor id="various_blocks.blurb"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="various_blocks.blurb-heading">
     <link linkend="various_blocks.blurb">Blurb</link>
   </bridgehead>
   <sidebar role="blurb">
@@ -71,7 +71,7 @@
     Blurb
   </para>
   </sidebar> <anchor id="various_blocks.inline_blocks"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="various_blocks.inline_blocks-heading">
     <link linkend="various_blocks.inline_blocks">Inline blocks</link>
   </bridgehead>
   <blockquote>
Modified: branches/release/tools/quickbook/test/code-block.gold
==============================================================================
--- branches/release/tools/quickbook/test/code-block.gold	(original)
+++ branches/release/tools/quickbook/test/code-block.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -27,7 +27,7 @@
     Paragraph.
   </para>
   <anchor id="indented_code_blocks.code_blocks_separated_by_comment"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="indented_code_blocks.code_blocks_separated_by_comment-heading">
     <link linkend="indented_code_blocks.code_blocks_separated_by_comment">Code blocks
     separated by comment</link>
   </bridgehead>
Deleted: branches/release/tools/quickbook/test/doc-info-1.gold
 Deleted: branches/release/tools/quickbook/test/doc-info-1.quickbook
 Deleted: branches/release/tools/quickbook/test/doc-info-2.gold
 Deleted: branches/release/tools/quickbook/test/doc-info-2.quickbook
 Deleted: branches/release/tools/quickbook/test/doc-info-3.gold
 Deleted: branches/release/tools/quickbook/test/doc-info-3.quickbook
 Deleted: branches/release/tools/quickbook/test/doc-info-4.gold
 Deleted: branches/release/tools/quickbook/test/doc-info-4.quickbook
 Modified: branches/release/tools/quickbook/test/heading.gold
 Modified: branches/release/tools/quickbook/test/heading_1_6.gold
 Modified: branches/release/tools/quickbook/test/identifier_1_5.gold
 Modified: branches/release/tools/quickbook/test/identifier_1_6.gold
 Modified: branches/release/tools/quickbook/test/link.quickbook
 Modified: branches/release/tools/quickbook/test/list_test.gold
 Modified: branches/release/tools/quickbook/test/list_test.quickbook
 Modified: branches/release/tools/quickbook/test/quickbook-manual.gold
 Modified: branches/release/tools/quickbook/test/quickbook-testing.jam
 Modified: branches/release/tools/quickbook/test/simple_markup.gold
 Modified: branches/release/tools/quickbook/test/simple_markup.quickbook
 Copied: branches/release/tools/quickbook/test/snippets/pass_thru.cpp (from r70210, /trunk/tools/quickbook/test/snippets/pass_thru.cpp)
 Copied: branches/release/tools/quickbook/test/snippets/pass_thru.py (from r70210, /trunk/tools/quickbook/test/snippets/pass_thru.py)
 Copied: branches/release/tools/quickbook/test/src/Jamfile.v2 (from r69832, /trunk/tools/quickbook/test/src/Jamfile.v2)
 Modified: branches/release/tools/quickbook/test/table_1_5.gold
 Modified: branches/release/tools/quickbook/test/table_1_5.quickbook
 Modified: branches/release/tools/quickbook/test/template-section.gold
 Modified: branches/release/tools/quickbook/test/unicode-escape.gold
 Copied: branches/release/tools/quickbook/test/unit/Jamfile.v2 (from r70210, /trunk/tools/quickbook/test/unit/Jamfile.v2)
 Copied: branches/release/tools/quickbook/test/unit/values_test.cpp (from r70210, /trunk/tools/quickbook/test/unit/values_test.cpp)
 Modified: branches/release/tools/quickbook/test/utf-8-bom.gold
 Modified: branches/release/tools/quickbook/test/utf-8.gold
 Modified: branches/release/tools/quickbook/test/variablelist.gold
 Modified: branches/release/tools/quickbook/test/variablelist.quickbook
 Modified: branches/release/tools/quickbook/test/xinclude.gold
==============================================================================
--- branches/release/tools/quickbook/test/doc-info-1.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<article id="karel_vom_u00e1_u010dka_and_tom_u00e1_u0161_martin_u00edk" lang="en"
-last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
-  <title>Karel Vomáčka and Tomáš Martiník</title>
-  <articleinfo>
-    <authorgroup>
-    <author>
-      <firstname>Matti</firstname> <surname>Meikäläinen</surname>
-    </author>
-    <author>
-      <firstname>Pero</firstname> <surname>Perić</surname>
-    </author>
-    </authorgroup>
-    <copyright>
-      <year>2010</year> <holder>Meðal-Jón and Jóna Jónsdóttir</holder>
-    </copyright>
-    <articlepurpose>
-      Inline code test: <code>1 + 2</code>
-    </articlepurpose>
-    <articlecategory name="category:tests"></articlecategory> <articlecategory name="category:irrelevance"></articlecategory>
-    <biblioid class="uri">http://www.boost.org/tools/quickbook/test/doc-info-1.quickbook>
-  </articleinfo>
-</article>
==============================================================================
--- branches/release/tools/quickbook/test/doc-info-1.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,12 +0,0 @@
-[article Karel Vom\u00E1\u010Dka and Tom\u00E1\u0161 Martin\u00EDk
-[quickbook 1.6]
-[authors [Meik\u00E4l\u00E4inen, Matti][Peri\u0107, Pero]]
-[copyright 2010 Me\u00F0al-J\u00F3n and J\u00F3na J\u00F3nsd\u00F3ttir]
-[source-mode teletype]
-[purpose Inline code test: `1 + 2`]
-[category tests]
-[category irrelevance]
-[/ [category commented out] ]
-[biblioid uri http://www.boost.org/tools/quickbook/test/doc-info-1.quickbook]
-[lang en]
-]
==============================================================================
--- branches/release/tools/quickbook/test/doc-info-2.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<library id="karel_vom__xe1___x10d_ka_and_tom__xe1___x161__martin__xed_k" name="Karel Vomáčka and Tomáš Martiník"
-dirname="karel_vom__xe1___x10d_ka_and_tom__xe1___x161__martin__xed_k" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-  <libraryinfo>
-    <authorgroup>
-    <author>
-      <firstname>Matti</firstname> <surname>Meikäläinen</surname>
-    </author>
-    <author>
-      <firstname>Pero</firstname> <surname>Perić</surname>
-    </author>
-    </authorgroup>
-    <copyright>
-      <year>2010</year> <holder>Meðal-Jón and Jóna Jónsdóttir</holder>
-    </copyright>
-    <librarypurpose>
-      Inline code test: <code>1 + 2</code>
-    </librarypurpose>
-    <librarycategory name="category:tests"></librarycategory> <librarycategory name="category:irrelevance"></librarycategory>
-    <biblioid class="uri">http://www.boost.org/tools/quickbook/test/doc-info-2.quickbook>
-    <biblioid class="isbn">0-937383-18-X</biblioid>
-  </libraryinfo>
-  <title>Karel Vomáčka and Tomáš Martiník</title>
-</library>
==============================================================================
--- branches/release/tools/quickbook/test/doc-info-2.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,14 +0,0 @@
-[library Karel Vomáčka and Tomáš Martiník
-[quickbook 1.5]
-[authors [Meikäläinen, Matti],[Perić, Pero]]
-[copyright 2010 Meðal-Jón and Jóna Jónsdóttir]
-[source-mode teletype]
-[purpose Inline code test: `1 + 2`]
-[category tests]
-[category irrelevance]
-[/ [category commented out] ]
-[biblioid uri http://www.boost.org/tools/quickbook/test/doc-info-2.quickbook]
-[biblioid isbn 0-937383-18-X]
-]
-
-[/ Some comment]
==============================================================================
--- branches/release/tools/quickbook/test/doc-info-3.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE appendix PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<appendix id="document_information_4" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-  <title>Document Information 4</title>
-  <appendixinfo>
-    <authorgroup>
-    <author>
-      <firstname>Joe</firstname> <surname>Blow</surname>
-    </author>
-    </authorgroup>
-  </appendixinfo>
-</appendix>
==============================================================================
--- branches/release/tools/quickbook/test/doc-info-3.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,5 +0,0 @@
-[appendix Document Information 4
-[quickbook 1.5]
-[authors [Blow, Joe]]
-]
-[/ Some comment]
\ No newline at end of file
==============================================================================
--- branches/release/tools/quickbook/test/doc-info-4.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<chapter id="document_information_4" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-  <title>Document Information 4</title>
-  <chapterinfo>
-    <authorgroup>
-    <author>
-      <firstname>Joe</firstname> <surname>Blow</surname>
-    </author>
-    <author>
-      <firstname>Jane</firstname> <surname>Doe</surname>
-    </author>
-    <author>
-      <firstname>John</firstname> <surname>Coe</surname>
-    </author>
-    </authorgroup>
-  </chapterinfo>
-</chapter>
==============================================================================
--- branches/release/tools/quickbook/test/doc-info-4.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
+++ (empty file)
@@ -1,4 +0,0 @@
-[chapter Document Information 4
-[quickbook 1.5]
-[authors [Blow, Joe], [Doe, Jane] [Coe, John]]
-]
\ No newline at end of file
==============================================================================
--- branches/release/tools/quickbook/test/heading.gold	(original)
+++ branches/release/tools/quickbook/test/heading.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -2,21 +2,21 @@
 <!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
 <article id="header" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>Header</title> <anchor id="header.header_test"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="header.header_test-heading">
     <link linkend="header.header_test">Header Test</link>
   </bridgehead>
   <para>
     Testing headers without sections.
   </para>
   <anchor id="header._not_an_id"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="header._not_an_id-heading">
     <link linkend="header._not_an_id">:Not an Id</link>
   </bridgehead>
   <para>
     Paragraph.
   </para>
   <anchor id="header._not_an_id_again"/>
-  <bridgehead renderas="sect3">
+  <bridgehead renderas="sect3" id="header._not_an_id_again-heading">
     <link linkend="header._not_an_id_again">:Not an Id again</link>
   </bridgehead>
   <para>
==============================================================================
--- branches/release/tools/quickbook/test/heading_1_6.gold	(original)
+++ branches/release/tools/quickbook/test/heading_1_6.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -2,21 +2,21 @@
 <!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
 <article id="header" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>Header</title> <anchor id="header.header_test"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="header.header_test-heading">
     <link linkend="header.header_test">Header Test</link>
   </bridgehead>
   <para>
     Paragraph.
   </para>
   <anchor id="header.heading_id"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="header.heading_id-heading">
     <link linkend="header.heading_id">Heading with an id</link>
   </bridgehead>
   <para>
     Paragraph.
   </para>
   <anchor id="header.heading_id2"/>
-  <bridgehead renderas="sect3">
+  <bridgehead renderas="sect3" id="header.heading_id2-heading">
     <link linkend="header.heading_id2">Heading with an id</link>
   </bridgehead>
   <para>
==============================================================================
--- branches/release/tools/quickbook/test/identifier_1_5.gold	(original)
+++ branches/release/tools/quickbook/test/identifier_1_5.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -3,7 +3,7 @@
 <article id="identifiers_in_quickbook_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
  xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>Identifiers in quickbook 1.5</title> <anchor id="identifiers_in_quickbook_1_5.test_heading_with__code__phrase_role__identifier__code__phrase___code_"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.test_heading_with__code__phrase_role__identifier__code__phrase___code_-heading">
     <link linkend="identifiers_in_quickbook_1_5.test_heading_with__code__phrase_role__identifier__code__phrase___code_">Test
     heading with <code><phrase role="identifier">code</phrase></code></link>
   </bridgehead>
==============================================================================
--- branches/release/tools/quickbook/test/identifier_1_6.gold	(original)
+++ branches/release/tools/quickbook/test/identifier_1_6.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -3,7 +3,7 @@
 <article id="identifiers_in_quickbook_1_6" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
  xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>Identifiers in quickbook 1.6</title> <anchor id="identifiers_in_quickbook_1_6.test_heading_with__code_"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.test_heading_with__code_-heading">
     <link linkend="identifiers_in_quickbook_1_6.test_heading_with__code_">Test heading
     with <code><phrase role="identifier">code</phrase></code></link>
   </bridgehead>
==============================================================================
--- branches/release/tools/quickbook/test/link.quickbook	(original)
+++ branches/release/tools/quickbook/test/link.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -4,7 +4,7 @@
 [section Different types of links]
 
 [@http://www.boost.org/]
-[@http://www.boost.org/ Boost]
+[@  http://www.boost.org/ Boost]
 [link link-id]
 [link link-id Link Text]
 [#link-id]
==============================================================================
--- branches/release/tools/quickbook/test/list_test.gold	(original)
+++ branches/release/tools/quickbook/test/list_test.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -39,36 +39,36 @@
     <listitem>
       <simpara>
         A
+        <itemizedlist>
+          <listitem>
+            <simpara>
+              A
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              B
+            </simpara>
+          </listitem>
+        </itemizedlist>
       </simpara>
-      <itemizedlist>
-        <listitem>
-          <simpara>
-            A
-          </simpara>
-        </listitem>
-        <listitem>
-          <simpara>
-            B
-          </simpara>
-        </listitem>
-      </itemizedlist>
     </listitem>
     <listitem>
       <simpara>
         B
+        <itemizedlist>
+          <listitem>
+            <simpara>
+              A
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              B
+            </simpara>
+          </listitem>
+        </itemizedlist>
       </simpara>
-      <itemizedlist>
-        <listitem>
-          <simpara>
-            A
-          </simpara>
-        </listitem>
-        <listitem>
-          <simpara>
-            B
-          </simpara>
-        </listitem>
-      </itemizedlist>
     </listitem>
   </itemizedlist>
   <para>
@@ -78,36 +78,36 @@
     <listitem>
       <simpara>
         A
+        <itemizedlist>
+          <listitem>
+            <simpara>
+              A
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              B
+            </simpara>
+          </listitem>
+        </itemizedlist>
       </simpara>
-      <itemizedlist>
-        <listitem>
-          <simpara>
-            A
-          </simpara>
-        </listitem>
-        <listitem>
-          <simpara>
-            B
-          </simpara>
-        </listitem>
-      </itemizedlist>
     </listitem>
     <listitem>
       <simpara>
         B
+        <itemizedlist>
+          <listitem>
+            <simpara>
+              A
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              B
+            </simpara>
+          </listitem>
+        </itemizedlist>
       </simpara>
-      <itemizedlist>
-        <listitem>
-          <simpara>
-            A
-          </simpara>
-        </listitem>
-        <listitem>
-          <simpara>
-            B
-          </simpara>
-        </listitem>
-      </itemizedlist>
     </listitem>
   </orderedlist>
   <para>
@@ -117,53 +117,53 @@
     <listitem>
       <simpara>
         A
+        <itemizedlist>
+          <listitem>
+            <simpara>
+              A
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              B
+              <itemizedlist>
+                <listitem>
+                  <simpara>
+                    C
+                  </simpara>
+                </listitem>
+                <listitem>
+                  <simpara>
+                    D
+                  </simpara>
+                </listitem>
+              </itemizedlist>
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              E
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              F
+              <itemizedlist>
+                <listitem>
+                  <simpara>
+                    G
+                  </simpara>
+                </listitem>
+                <listitem>
+                  <simpara>
+                    H
+                  </simpara>
+                </listitem>
+              </itemizedlist>
+            </simpara>
+          </listitem>
+        </itemizedlist>
       </simpara>
-      <itemizedlist>
-        <listitem>
-          <simpara>
-            A
-          </simpara>
-        </listitem>
-        <listitem>
-          <simpara>
-            B
-          </simpara>
-          <itemizedlist>
-            <listitem>
-              <simpara>
-                C
-              </simpara>
-            </listitem>
-            <listitem>
-              <simpara>
-                D
-              </simpara>
-            </listitem>
-          </itemizedlist>
-        </listitem>
-        <listitem>
-          <simpara>
-            E
-          </simpara>
-        </listitem>
-        <listitem>
-          <simpara>
-            F
-          </simpara>
-          <itemizedlist>
-            <listitem>
-              <simpara>
-                G
-              </simpara>
-            </listitem>
-            <listitem>
-              <simpara>
-                H
-              </simpara>
-            </listitem>
-          </itemizedlist>
-        </listitem>
-      </itemizedlist>
     </listitem>
   </orderedlist>
   <para>
@@ -173,31 +173,31 @@
     <listitem>
       <simpara>
         A
+        <itemizedlist>
+          <listitem>
+            <simpara>
+              A
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              B
+              <orderedlist>
+                <listitem>
+                  <simpara>
+                    C
+                  </simpara>
+                </listitem>
+                <listitem>
+                  <simpara>
+                    D
+                  </simpara>
+                </listitem>
+              </orderedlist>
+            </simpara>
+          </listitem>
+        </itemizedlist>
       </simpara>
-      <itemizedlist>
-        <listitem>
-          <simpara>
-            A
-          </simpara>
-        </listitem>
-        <listitem>
-          <simpara>
-            B
-          </simpara>
-          <orderedlist>
-            <listitem>
-              <simpara>
-                C
-              </simpara>
-            </listitem>
-            <listitem>
-              <simpara>
-                D
-              </simpara>
-            </listitem>
-          </orderedlist>
-        </listitem>
-      </itemizedlist>
     </listitem>
     <listitem>
       <simpara>
@@ -210,6 +210,35 @@
       </simpara>
     </listitem>
   </orderedlist>
+  <para>
+    Markup in list:
+  </para>
+  <itemizedlist>
+    <listitem>
+      <simpara>
+        <emphasis role="bold">Bold</emphasis>
+      </simpara>
+    </listitem>
+    <listitem>
+      <simpara>
+        <emphasis role="bold">Bold</emphasis>
+      </simpara>
+    </listitem>
+    <listitem>
+      <simpara>
+        <quote>Quoted</quote>
+      </simpara>
+    </listitem>
+    <listitem>
+      <simpara>
+        <footnote>
+        <para>
+          Footnote
+        </para>
+        </footnote>
+      </simpara>
+    </listitem>
+  </itemizedlist>
   <section id="list_test.list_immediately_following_markup">
     <title><link linkend="list_test.list_immediately_following_markup">List immediately
     following markup</link></title>
==============================================================================
--- branches/release/tools/quickbook/test/list_test.quickbook	(original)
+++ branches/release/tools/quickbook/test/list_test.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -52,6 +52,13 @@
 # G
 # H
 
+Markup in list:
+
+*   *Bold*
+*   [*Bold]
+*   ["Quoted]
+*   [footnote Footnote]
+
 [section List immediately following markup]
 * One
 * Two
==============================================================================
--- branches/release/tools/quickbook/test/quickbook-manual.gold	(original)
+++ branches/release/tools/quickbook/test/quickbook-manual.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -104,7 +104,7 @@
   <section id="quickbook.change_log">
     <title><link linkend="quickbook.change_log">Change Log</link></title> <anchor
     id="quickbook.change_log.version_1_3"/>
-    <bridgehead renderas="sect3">
+    <bridgehead renderas="sect3" id="quickbook.change_log.version_1_3-heading">
       <link linkend="quickbook.change_log.version_1_3">Version 1.3</link>
     </bridgehead>
     <itemizedlist>
@@ -1272,48 +1272,48 @@
             <listitem>
               <simpara>
                 Three
+                <orderedlist>
+                  <listitem>
+                    <simpara>
+                      Three.a
+                    </simpara>
+                  </listitem>
+                  <listitem>
+                    <simpara>
+                      Three.b
+                    </simpara>
+                  </listitem>
+                  <listitem>
+                    <simpara>
+                      Three.c
+                    </simpara>
+                  </listitem>
+                </orderedlist>
               </simpara>
-              <orderedlist>
-                <listitem>
-                  <simpara>
-                    Three.a
-                  </simpara>
-                </listitem>
-                <listitem>
-                  <simpara>
-                    Three.b
-                  </simpara>
-                </listitem>
-                <listitem>
-                  <simpara>
-                    Three.c
-                  </simpara>
-                </listitem>
-              </orderedlist>
             </listitem>
             <listitem>
               <simpara>
                 Fourth
+                <orderedlist>
+                  <listitem>
+                    <simpara>
+                      Four.a
+                      <orderedlist>
+                        <listitem>
+                          <simpara>
+                            Four.a.i
+                          </simpara>
+                        </listitem>
+                        <listitem>
+                          <simpara>
+                            Four.a.ii
+                          </simpara>
+                        </listitem>
+                      </orderedlist>
+                    </simpara>
+                  </listitem>
+                </orderedlist>
               </simpara>
-              <orderedlist>
-                <listitem>
-                  <simpara>
-                    Four.a
-                  </simpara>
-                  <orderedlist>
-                    <listitem>
-                      <simpara>
-                        Four.a.i
-                      </simpara>
-                    </listitem>
-                    <listitem>
-                      <simpara>
-                        Four.a.ii
-                      </simpara>
-                    </listitem>
-                  </orderedlist>
-                </listitem>
-              </orderedlist>
             </listitem>
             <listitem>
               <simpara>
@@ -1418,24 +1418,24 @@
             <listitem>
               <simpara>
                 Three
+                <itemizedlist>
+                  <listitem>
+                    <simpara>
+                      Three.a
+                    </simpara>
+                  </listitem>
+                  <listitem>
+                    <simpara>
+                      Three.b
+                    </simpara>
+                  </listitem>
+                  <listitem>
+                    <simpara>
+                      Three.c
+                    </simpara>
+                  </listitem>
+                </itemizedlist>
               </simpara>
-              <itemizedlist>
-                <listitem>
-                  <simpara>
-                    Three.a
-                  </simpara>
-                </listitem>
-                <listitem>
-                  <simpara>
-                    Three.b
-                  </simpara>
-                </listitem>
-                <listitem>
-                  <simpara>
-                    Three.c
-                  </simpara>
-                </listitem>
-              </itemizedlist>
             </listitem>
             <listitem>
               <simpara>
@@ -1467,72 +1467,72 @@
             <listitem>
               <simpara>
                 1
+                <itemizedlist>
+                  <listitem>
+                    <simpara>
+                      1.a
+                      <orderedlist>
+                        <listitem>
+                          <simpara>
+                            1.a.1
+                          </simpara>
+                        </listitem>
+                        <listitem>
+                          <simpara>
+                            1.a.2
+                          </simpara>
+                        </listitem>
+                      </orderedlist>
+                    </simpara>
+                  </listitem>
+                  <listitem>
+                    <simpara>
+                      1.b
+                    </simpara>
+                  </listitem>
+                </itemizedlist>
               </simpara>
-              <itemizedlist>
-                <listitem>
-                  <simpara>
-                    1.a
-                  </simpara>
-                  <orderedlist>
-                    <listitem>
-                      <simpara>
-                        1.a.1
-                      </simpara>
-                    </listitem>
-                    <listitem>
-                      <simpara>
-                        1.a.2
-                      </simpara>
-                    </listitem>
-                  </orderedlist>
-                </listitem>
-                <listitem>
-                  <simpara>
-                    1.b
-                  </simpara>
-                </listitem>
-              </itemizedlist>
             </listitem>
             <listitem>
               <simpara>
                 2
-              </simpara>
-              <itemizedlist>
-                <listitem>
-                  <simpara>
-                    2.a
-                  </simpara>
-                </listitem>
-                <listitem>
-                  <simpara>
-                    2.b
-                  </simpara>
-                  <orderedlist>
-                    <listitem>
-                      <simpara>
-                        2.b.1
-                      </simpara>
-                    </listitem>
-                    <listitem>
-                      <simpara>
-                        2.b.2
-                      </simpara>
-                      <itemizedlist>
+                <itemizedlist>
+                  <listitem>
+                    <simpara>
+                      2.a
+                    </simpara>
+                  </listitem>
+                  <listitem>
+                    <simpara>
+                      2.b
+                      <orderedlist>
                         <listitem>
                           <simpara>
-                            2.b.2.a
+                            2.b.1
                           </simpara>
                         </listitem>
                         <listitem>
                           <simpara>
-                            2.b.2.b
+                            2.b.2
+                            <itemizedlist>
+                              <listitem>
+                                <simpara>
+                                  2.b.2.a
+                                </simpara>
+                              </listitem>
+                              <listitem>
+                                <simpara>
+                                  2.b.2.b
+                                </simpara>
+                              </listitem>
+                            </itemizedlist>
                           </simpara>
                         </listitem>
-                      </itemizedlist>
-                    </listitem>
-                  </orderedlist>
-                </listitem>
-              </itemizedlist>
+                      </orderedlist>
+                    </simpara>
+                  </listitem>
+                </itemizedlist>
+              </simpara>
             </listitem>
           </orderedlist>
         </section>
@@ -1707,27 +1707,27 @@
 [h6 Heading 6]
 <!--quickbook-escape-postfix--></programlisting>
         <anchor id="quickbook.syntax.block.headings.heading_1"/>
-        <bridgehead renderas="sect1">
+        <bridgehead renderas="sect1" id="quickbook.syntax.block.headings.heading_1-heading">
           <link linkend="quickbook.syntax.block.headings.heading_1">Heading 1</link>
         </bridgehead>
         <anchor id="quickbook.syntax.block.headings.heading_2"/>
-        <bridgehead renderas="sect2">
+        <bridgehead renderas="sect2" id="quickbook.syntax.block.headings.heading_2-heading">
           <link linkend="quickbook.syntax.block.headings.heading_2">Heading 2</link>
         </bridgehead>
         <anchor id="quickbook.syntax.block.headings.heading_3"/>
-        <bridgehead renderas="sect3">
+        <bridgehead renderas="sect3" id="quickbook.syntax.block.headings.heading_3-heading">
           <link linkend="quickbook.syntax.block.headings.heading_3">Heading 3</link>
         </bridgehead>
         <anchor id="quickbook.syntax.block.headings.heading_4"/>
-        <bridgehead renderas="sect4">
+        <bridgehead renderas="sect4" id="quickbook.syntax.block.headings.heading_4-heading">
           <link linkend="quickbook.syntax.block.headings.heading_4">Heading 4</link>
         </bridgehead>
         <anchor id="quickbook.syntax.block.headings.heading_5"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.headings.heading_5-heading">
           <link linkend="quickbook.syntax.block.headings.heading_5">Heading 5</link>
         </bridgehead>
         <anchor id="quickbook.syntax.block.headings.heading_6"/>
-        <bridgehead renderas="sect6">
+        <bridgehead renderas="sect6" id="quickbook.syntax.block.headings.heading_6-heading">
           <link linkend="quickbook.syntax.block.headings.heading_6">Heading 6</link>
         </bridgehead>
         <para>
@@ -1943,7 +1943,7 @@
                 </entry>
                 <entry>
                   <para>
-                    NO_FILENAME_MACRO_GENERATED_IN_DEBUG_MODE
+                    quickbook-manual.quickbook
                   </para>
                 </entry>
               </row>
@@ -1972,7 +1972,7 @@
 ]
 <!--quickbook-escape-postfix--></programlisting>
         <anchor id="quickbook.syntax.block.templates.template_identifier"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.template_identifier-heading">
           <link linkend="quickbook.syntax.block.templates.template_identifier">Template
           Identifier</link>
         </bridgehead>
@@ -1994,7 +1994,7 @@
           </listitem>
         </itemizedlist>
         <anchor id="quickbook.syntax.block.templates.formal_template_arguments"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.formal_template_arguments-heading">
           <link linkend="quickbook.syntax.block.templates.formal_template_arguments">Formal
           Template Arguments</link>
         </bridgehead>
@@ -2014,7 +2014,7 @@
           of the template call.
         </para>
         <anchor id="quickbook.syntax.block.templates.template_body"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.template_body-heading">
           <link linkend="quickbook.syntax.block.templates.template_body">Template
           Body</link>
         </bridgehead>
@@ -2041,7 +2041,7 @@
           block level elements are not allowed in phrase templates.
         </para>
         <anchor id="quickbook.syntax.block.templates.template_expansion"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.template_expansion-heading">
           <link linkend="quickbook.syntax.block.templates.template_expansion">Template
           Expansion</link>
         </bridgehead>
@@ -2084,7 +2084,7 @@
           by the close parenthesis.
         </para>
         <anchor id="quickbook.syntax.block.templates.nullary_templates"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.nullary_templates-heading">
           <link linkend="quickbook.syntax.block.templates.nullary_templates">Nullary
           Templates</link>
         </bridgehead>
@@ -2177,7 +2177,7 @@
           brackets, though.
         </para>
         <anchor id="quickbook.syntax.block.templates.simple_arguments"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.simple_arguments-heading">
           <link linkend="quickbook.syntax.block.templates.simple_arguments">Simple
           Arguments</link>
         </bridgehead>
@@ -2252,7 +2252,7 @@
           what do you think man?
         </para>
         <anchor id="quickbook.syntax.block.templates.punctuation_templates"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.punctuation_templates-heading">
           <link linkend="quickbook.syntax.block.templates.punctuation_templates">Punctuation
           Templates</link>
         </bridgehead>
@@ -2656,7 +2656,7 @@
           QuickBook's import facility provides a nice solution.
         </para>
         <anchor id="quickbook.syntax.block.import.example"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.import.example-heading">
           <link linkend="quickbook.syntax.block.import.example">Example</link>
         </bridgehead>
         <para>
@@ -2734,7 +2734,7 @@
           Some trailing text here
         </para>
         <anchor id="quickbook.syntax.block.import.code_snippet_markup"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.import.code_snippet_markup-heading">
           <link linkend="quickbook.syntax.block.import.code_snippet_markup">Code
           Snippet Markup</link>
         </bridgehead>
@@ -2756,7 +2756,7 @@
           This too will not be visible in quickbook.
         </para>
         <anchor id="quickbook.syntax.block.import.special_comments"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.import.special_comments-heading">
           <link linkend="quickbook.syntax.block.import.special_comments">Special
           Comments</link>
         </bridgehead>
@@ -2779,7 +2779,7 @@
           initial slash-star-tick and the final star-slash shall be ignored.
         </para>
         <anchor id="quickbook.syntax.block.import.callouts"/>
-        <bridgehead renderas="sect5">
+        <bridgehead renderas="sect5" id="quickbook.syntax.block.import.callouts-heading">
           <link linkend="quickbook.syntax.block.import.callouts">Callouts</link>
         </bridgehead>
         <para>
@@ -3147,7 +3147,7 @@
   <section id="quickbook.faq">
     <title><link linkend="quickbook.faq">Frequently Asked Questions</link></title>
     <anchor id="quickbook.faq.can_i_use_quickbook_for_non_boost_documentation_"/>
-    <bridgehead renderas="sect3">
+    <bridgehead renderas="sect3" id="quickbook.faq.can_i_use_quickbook_for_non_boost_documentation_-heading">
       <link linkend="quickbook.faq.can_i_use_quickbook_for_non_boost_documentation_">Can
       I use QuickBook for non-Boost documentation?</link>
     </bridgehead>
@@ -3178,8 +3178,8 @@
     :
         my_doc
     :
-        <xsl:param>boost.image.src<literal>images/my_project_logo.png
-        <xsl:param>boost.image.alt</literal>"\"My Project\""
+        <xsl:param>boost.image.src=images/my_project_logo.png
+        <xsl:param>boost.image.alt="\"My Project\""
         <xsl:param>boost.image.w=100
         <xsl:param>boost.image.h=50
         <xsl:param>nav.layout=none
==============================================================================
--- branches/release/tools/quickbook/test/quickbook-testing.jam	(original)
+++ branches/release/tools/quickbook/test/quickbook-testing.jam	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -17,6 +17,8 @@
 
 feature.feature quickbook-testing.quickbook-command : : free dependency ;
 feature.feature <quickbook-test-define> : : free ;
+feature.feature <quickbook-test-include> : : free path ;
+feature.feature <quickbook-xinclude-base> : : free ;
 
 type.register QUICKBOOK_INPUT : quickbook ;
 type.register QUICKBOOK_OUTPUT ;
@@ -24,8 +26,6 @@
 generators.register-standard quickbook-testing.process-quickbook : QUICKBOOK_INPUT : QUICKBOOK_OUTPUT ;
 
 ################################################################################
-exe line-compare-tool : src/text_diff.cpp ;
-
 #
 #   quickbook-test - generates a test for quickbook itself. A quickbook-test is
 #   actually made up of two tests:
@@ -43,6 +43,8 @@
 
     local project = [ project.current ] ;
 
+    local boost-root = [ modules.peek : BOOST_ROOT ] ;
+
     local t =
         [ targets.create-typed-target QUICKBOOK_OUTPUT
             : $(project)
@@ -50,13 +52,13 @@
             : $(input)
             : $(requirements)
                 <location-prefix>$(target-name).test
-                <quickbook-testing.quickbook-command>../src//quickbook
+                <quickbook-testing.quickbook-command>$(boost-root)/tools/quickbook/src//quickbook
         ]
 
         [ targets.create-typed-target RUN
             : $(project)
             : $(target-name)
-            : .//line-compare-tool
+            : $(boost-root)/tools/quickbook/test/src//line-compare-tool
             : $(requirements)
                 <location-prefix>$(target-name).test
                 <testing.input-file>$(reference-output)
@@ -75,14 +77,42 @@
     input ?= $(target-name).quickbook ;
 
     local project = [ project.current ] ;
-    requirements += <testing.arg>$(input:J=" ") ;
+    
+    local boost-root = [ modules.peek : BOOST_ROOT ] ;
 
     local t =
         [ targets.create-typed-target RUN_FAIL
             : $(project)
             : $(target-name)
-            : ../src//quickbook
+            : $(boost-root)/tools/quickbook/src//quickbook
+            : $(requirements)
+              <testing.input-file>$(input)
+              <preserve-test-targets>on
+              <dependency>$(input)
+        ]
+        ;
+
+    modules.poke testing : .all-tests : \$\(all-tests\) $(t) ;
+
+    return $(t) ;
+}
+
+rule quickbook-error-test ( target-name : input ? : requirements * )
+{
+    input ?= $(target-name).quickbook ;
+
+    local project = [ project.current ] ;
+    
+    local boost-root = [ modules.peek : BOOST_ROOT ] ;
+
+    local t =
+        [ targets.create-typed-target RUN
+            : $(project)
+            : $(target-name)
+            : $(boost-root)/tools/quickbook/src//quickbook
             : $(requirements)
+              <testing.input-file>$(input)
+              <testing.arg>--expect-errors
               <preserve-test-targets>on
               <dependency>$(input)
         ]
@@ -96,6 +126,8 @@
 ################################################################################
 toolset.flags quickbook-testing.process-quickbook quickbook-command <quickbook-testing.quickbook-command> ;
 toolset.flags quickbook-testing.process-quickbook QB-DEFINES        <quickbook-test-define> ;
+toolset.flags quickbook-testing.process-quickbook XINCLUDE          <quickbook-xinclude-base> ;
+toolset.flags quickbook-testing.process-quickbook INCLUDES          <quickbook-test-include> ;
 
 rule process-quickbook ( target : source : properties * )
 {
@@ -104,6 +136,6 @@
 
 actions process-quickbook bind quickbook-command
 {
-    $(quickbook-command) $(>) --output-file=$(<) --debug -D"$(QB-DEFINES)"
+    $(quickbook-command) $(>) --output-file=$(<) --debug -D"$(QB-DEFINES)" -I"$(INCLUDES)" --xinclude-base="$(XINCLUDE)"
 }
 
==============================================================================
--- branches/release/tools/quickbook/test/simple_markup.gold	(original)
+++ branches/release/tools/quickbook/test/simple_markup.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -10,10 +10,41 @@
       role="underline">underline</emphasis> <literal>teletype</literal>
     </para>
     <para>
-      /all<emphasis>italic</emphasis> * not bold*
+      <emphasis>/italic/</emphasis> <emphasis role="bold">*bold*</emphasis> <emphasis
+      role="underline">_underline_</emphasis> <literal>=teletype=</literal>
+    </para>
+    <para>
+      not__underlined__hopefully
+    </para>
+    <para>
+      (<emphasis role="bold">bold</emphasis>) <emphasis role="underline">und/er/lined</emphasis>
+    </para>
+    <para>
+      <emphasis>all/italic</emphasis> * not bold*
     </para>
     <para>
       /not italic <ulink url="http://www.boost.org/"><emphasis role="bold">bold</emphasis></ulink>
     </para>
+    <para>
+      not_underlined_
+    </para>
+    <para>
+      _Should not underline escaped markup_. _or this escaped_ markup form.
+    </para>
+    <para>
+      <literal>Matti Meikäläinen</literal>
+    </para>
+    <para>
+      <literal>replaced</literal>
+    </para>
+    <para>
+      <emphasis role="underline">replaced</emphasis>
+    </para>
+    <para>
+      <literal>_macro_</literal>
+    </para>
+    <para>
+      /not italic/
+    </para>
   </section>
 </article>
==============================================================================
--- branches/release/tools/quickbook/test/simple_markup.quickbook	(original)
+++ branches/release/tools/quickbook/test/simple_markup.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -2,12 +2,35 @@
 [quickbook 1.5]
 ]
 
+[def _macro_ replaced]
+
 [section Simple Markup]
 
 /italic/ *bold* _underline_ =teletype=
 
+//italic// **bold** __underline__ ==teletype==
+
+not__underlined__hopefully
+
+(*bold*) _und/er/lined_
+
 /all/italic/ * not bold*
 
 /not italic [@http://www.boost.org/ *bold*]
 
+not_underlined_
+
+_Should not underline '''escaped''' markup_.
+_or this '''escaped_ markup''' form.
+
+=Matti  Meik\u00E4l\u00E4inen=
+
+=_macro_=
+
+__macro__
+
+=_mac\ ro_=
+
+/not italic\/
+
 [endsect]
\ No newline at end of file
==============================================================================
--- /trunk/tools/quickbook/test/snippets/pass_thru.cpp	(original)
+++ branches/release/tools/quickbook/test/snippets/pass_thru.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -1,3 +1,11 @@
+/*=============================================================================
+    Copyright (c) 2011 Daniel James
+
+    Use, modification and distribution is subject to 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)
+=============================================================================*/
+
 //[foo_cpp
 struct Foo{
 
==============================================================================
--- /trunk/tools/quickbook/test/snippets/pass_thru.py	(original)
+++ branches/release/tools/quickbook/test/snippets/pass_thru.py	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -1,3 +1,9 @@
+# Copyright (c) 2011 Daniel James
+#
+# Use, modification and distribution is subject to 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)
+
 #[foo_py
 def foo:
     #=print('foo')
==============================================================================
--- /trunk/tools/quickbook/test/src/Jamfile.v2	(original)
+++ branches/release/tools/quickbook/test/src/Jamfile.v2	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -1 +1,9 @@
+#
+#   Copyright (c) 2011 Daniel James
+#
+#   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)
+#
+
 exe line-compare-tool : text_diff.cpp ;
==============================================================================
--- branches/release/tools/quickbook/test/table_1_5.gold	(original)
+++ branches/release/tools/quickbook/test/table_1_5.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -233,5 +233,94 @@
         </tbody>
       </tgroup>
     </table>
+    <table frame="all" id="table_1_5.section1.nested_tables">
+      <title>Nested Tables</title>
+      <tgroup cols="1">
+        <thead>
+          <row>
+            <entry>
+              <para>
+                Header 1
+              </para>
+            </entry>
+            <entry>
+              <para>
+                Header 2
+              </para>
+            </entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry>
+              <table frame="all" id="table_1_5.section1.inner_table">
+                <title>Inner Table</title>
+                <tgroup cols="2">
+                  <thead>
+                    <row>
+                      <entry>
+                        <para>
+                          1.1
+                        </para>
+                      </entry>
+                      <entry>
+                        <para>
+                          1.2
+                        </para>
+                      </entry>
+                    </row>
+                  </thead>
+                  <tbody>
+                    <row>
+                      <entry>
+                        <para>
+                          2.1
+                        </para>
+                      </entry>
+                      <entry>
+                        <para>
+                          2.2
+                        </para>
+                      </entry>
+                    </row>
+                  </tbody>
+                </tgroup>
+              </table>
+            </entry>
+          </row>
+          <row>
+            <entry>
+              <para>
+                Something.
+              </para>
+            </entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+    <anchor id="id1"/>
+    <table frame="all" id="table_1_5.section1.table_with_anchors">
+      <title>Table with anchors</title>
+      <tgroup cols="1">
+        <thead>
+          <row>
+            <entry>
+              <para>
+                <anchor id="id2"/> a<anchor id="id3"/>
+              </para>
+            </entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry>
+              <para>
+                b
+              </para>
+            </entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
   </section>
 </article>
==============================================================================
--- branches/release/tools/quickbook/test/table_1_5.quickbook	(original)
+++ branches/release/tools/quickbook/test/table_1_5.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -69,4 +69,33 @@
   ]
 ]
 
-[endsect]
\ No newline at end of file
+[table Nested Tables
+  [
+    [
+      Header 1
+    ]
+    [
+      Header 2
+    ]
+  ]
+  [
+    [
+      [table Inner Table
+        [[1.1][1.2]]
+        [[2.1][2.2]]
+      ]
+    ]
+  ]
+  [
+    [
+      Something.
+    ]
+  ]
+]
+
+[#id1]
+[table Table with anchors
+[[[#id2]a[#id3]]][[b]]
+]
+
+[endsect]
==============================================================================
--- branches/release/tools/quickbook/test/template-section.gold	(original)
+++ branches/release/tools/quickbook/test/template-section.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -12,7 +12,7 @@
       Hello.
     </para>
     <anchor id="section_in_a_template.test.just_to_test_id_generation"/>
-    <bridgehead renderas="sect3">
+    <bridgehead renderas="sect3" id="section_in_a_template.test.just_to_test_id_generation-heading">
       <link linkend="section_in_a_template.test.just_to_test_id_generation">Just
       to test id generation</link>
     </bridgehead>
==============================================================================
--- branches/release/tools/quickbook/test/unicode-escape.gold	(original)
+++ branches/release/tools/quickbook/test/unicode-escape.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -2,7 +2,7 @@
 <!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
 <article id="utf_8_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>UTF-8 test</title> <anchor id="utf_8_test.i__xf1_t__xeb_rn__xe2_ti__xf4_n__xe0_liz__xe6_ti__xf8_n"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="utf_8_test.i__xf1_t__xeb_rn__xe2_ti__xf4_n__xe0_liz__xe6_ti__xf8_n-heading">
     <link linkend="utf_8_test.i__xf1_t__xeb_rn__xe2_ti__xf4_n__xe0_liz__xe6_ti__xf8_n">Iñtërnâtiônàlizætiøn</link>
   </bridgehead>
   <itemizedlist>
==============================================================================
--- /trunk/tools/quickbook/test/unit/Jamfile.v2	(original)
+++ branches/release/tools/quickbook/test/unit/Jamfile.v2	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -1,3 +1,11 @@
+#
+#   Copyright (c) 2011 Daniel James
+#
+#   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)
+#
+
 import testing ;
 
 project quickbook-unit-tests
@@ -6,3 +14,4 @@
 
 run values_test.cpp ../../src/values.cpp ;
 run post_process_test.cpp ../../src/post_process.cpp ;
+run iterator_tests.cpp ../../src/values.cpp ;
==============================================================================
--- /trunk/tools/quickbook/test/unit/values_test.cpp	(original)
+++ branches/release/tools/quickbook/test/unit/values_test.cpp	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -11,6 +11,7 @@
 
 #include <boost/detail/lightweight_test.hpp>
 #include <boost/range/algorithm/equal.hpp>
+#include <vector>
 #include "values.hpp"
 
 void empty_tests()
@@ -39,7 +40,7 @@
     b.insert(quickbook::bbk_value("d", 8));
     b.sort_list();
     
-    quickbook::value_consumer c = b.get();
+    quickbook::value_consumer c = b.release();
     BOOST_TEST(c.check(2)); BOOST_TEST_EQ(c.consume(2).get_boostbook(), "b");
     BOOST_TEST(c.check(5)); c.consume(5);
     BOOST_TEST(c.check(8)); c.consume(8);
@@ -62,8 +63,8 @@
 
     list2.insert(quickbook::bbk_value("c", 3));
 
-    quickbook::value_consumer l1 = list1.get(); list1.reset();
-    quickbook::value_consumer l2 = list2.get(); list2.reset();
+    quickbook::value_consumer l1 = list1.release();
+    quickbook::value_consumer l2 = list2.release();
 
     BOOST_TEST(l1.check(10));
     BOOST_TEST_EQ(l1.consume(10).get_boostbook(), "b");
@@ -80,18 +81,19 @@
 
 void store_test1()
 {
-    quickbook::value q;
+    quickbook::stored_value q;
     
     {
         std::string src = "Hello";
-        q = quickbook::qbk_value(
+        quickbook::value q1 = quickbook::qbk_value(
             quickbook::iterator(src.begin()),
             quickbook::iterator(src.end()),
             5);
 
+        BOOST_TEST_EQ(q1.get_quickbook(), "Hello");
+        q = q1;
         BOOST_TEST_EQ(q.get_quickbook(), "Hello");
-        q.store();
-        BOOST_TEST_EQ(q.get_quickbook(), "Hello");
+        BOOST_TEST_EQ(q1.get_quickbook(), "Hello");
     }
 
     BOOST_TEST_EQ(q.get_quickbook(), "Hello");
@@ -109,7 +111,7 @@
 
 void store_test2()
 {
-    quickbook::value q;
+    quickbook::stored_value q;
     
     {
         quickbook::value_builder list1;
@@ -120,15 +122,43 @@
             5));
         list1.insert(quickbook::bbk_value("World", 10));
         
-        q = list1.get();
+        quickbook::value q2 = list1.release();
 
+        store_test2_check(q2);
+        q = q2;
         store_test2_check(q);
-        q.store();
-        store_test2_check(q);
+        store_test2_check(q2);
     }
     store_test2_check(q);
 }
 
+void equality_tests()
+{
+    std::vector<quickbook::value> distinct_values;
+
+    quickbook::value_builder builder;
+    quickbook::value nil;
+    
+    // 0: nil
+    distinct_values.push_back(nil);
+
+    // 1: []
+    distinct_values.push_back(builder.release());
+
+    // 2: [nil]
+    builder.insert(nil);
+    distinct_values.push_back(builder.release());
+
+    for(int i = 0; i < distinct_values.size(); ++i)
+        for(int j = 0; j < distinct_values.size(); ++j)
+            if ((i == j) != (distinct_values[i] == distinct_values[j]))
+            {
+                BOOST_ERROR("Value mismatch.");
+                BOOST_LIGHTWEIGHT_TEST_OSTREAM
+                    << "\tat " << i << ", " << j << std::endl;
+            }
+}
+
 int main()
 {
     empty_tests();
@@ -137,6 +167,7 @@
     multiple_list_test();
     store_test1();
     store_test2();
+    equality_tests();
 
     return boost::report_errors();
 }
==============================================================================
--- branches/release/tools/quickbook/test/utf-8-bom.gold	(original)
+++ branches/release/tools/quickbook/test/utf-8-bom.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -2,7 +2,7 @@
 <!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
 <article id="utf_8_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>UTF-8 test</title> <anchor id="utf_8_test.i__t__rn__ti__n__liz__ti__n"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="utf_8_test.i__t__rn__ti__n__liz__ti__n-heading">
     <link linkend="utf_8_test.i__t__rn__ti__n__liz__ti__n">Iñtërnâtiônàlizætiøn</link>
   </bridgehead>
   <itemizedlist>
==============================================================================
--- branches/release/tools/quickbook/test/utf-8.gold	(original)
+++ branches/release/tools/quickbook/test/utf-8.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -2,7 +2,7 @@
 <!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
 <article id="utf_8_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>UTF-8 test</title> <anchor id="utf_8_test.i__t__rn__ti__n__liz__ti__n"/>
-  <bridgehead renderas="sect2">
+  <bridgehead renderas="sect2" id="utf_8_test.i__t__rn__ti__n__liz__ti__n-heading">
     <link linkend="utf_8_test.i__t__rn__ti__n__liz__ti__n">Iñtërnâtiônàlizætiøn</link>
   </bridgehead>
   <itemizedlist>
==============================================================================
--- branches/release/tools/quickbook/test/variablelist.gold	(original)
+++ branches/release/tools/quickbook/test/variablelist.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -92,4 +92,16 @@
       </listitem>
     </varlistentry>
   </variablelist>
+  <anchor id="id1"/>
+  <variablelist>
+    <title>Variable List with anchors</title>
+    <varlistentry>
+      <term><anchor id="id2"/> a<anchor id="id3"/> </term>
+      <listitem>
+        <para>
+          <anchor id="id4"/> b<anchor id="id5"/>
+        </para>
+      </listitem>
+    </varlistentry>
+  </variablelist>
 </article>
==============================================================================
--- branches/release/tools/quickbook/test/variablelist.quickbook	(original)
+++ branches/release/tools/quickbook/test/variablelist.quickbook	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -19,4 +19,13 @@
     [[a][b][c][d]]
     [[a][b][c][d][e]]
     [[a][b]]
-]
\ No newline at end of file
+]
+
+[#id1]
+[variablelist Variable List with anchors
+	[
+	[[#id2]a[#id3]]
+	[[#id4]b[#id5]]
+	]
+]
+	
==============================================================================
--- branches/release/tools/quickbook/test/xinclude.gold	(original)
+++ branches/release/tools/quickbook/test/xinclude.gold	2011-04-03 07:50:51 EDT (Sun, 03 Apr 2011)
@@ -2,5 +2,5 @@
 <!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
 <article id="include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>Include</title>
-  <xi:include href="../../../../../../../../../tools/quickbook/test/stub.xml" />
+  <xi:include href="../test/stub.xml" />
 </article>
 
$include_dir="/home/hyper-archives/boost-commit/include";
include("$include_dir/msg-footer.inc");
?>