$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r85369 - in branches/release/tools/quickbook: . doc src test test/include
From: dnljms_at_[hidden]
Date: 2013-08-17 05:46:47
Author: danieljames
Date: 2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)
New Revision: 85369
URL: http://svn.boost.org/trac/boost/changeset/85369
Log:
Merge quickbook from trunk.
>From the change log:
- Improved markup for lists.
- Make escaping templates with a punctuation identifier illegal.
  Escaping templates with an alphanumeric identifier is still fine.
- 1.7 changes:
  - Make it an error to use an element in the wrong context.
  - Error if the body of a phrase element doesn't parse.
  - List markup in nested blocks.
  - Allow block elements in phrase templates.
  - Make it an error to put a paragraph break (i.e. a blank line)
    in a phrase template.
- Internal changes:
  - Clean up the id manager implementation.
Added:
   branches/release/tools/quickbook/doc/1_7.qbk
      - copied unchanged from r85368, trunk/tools/quickbook/doc/1_7.qbk
   branches/release/tools/quickbook/doc/language_versions.qbk
      - copied unchanged from r85368, trunk/tools/quickbook/doc/language_versions.qbk
   branches/release/tools/quickbook/src/id_generation.cpp
      - copied unchanged from r85368, trunk/tools/quickbook/src/id_generation.cpp
   branches/release/tools/quickbook/src/id_manager_impl.hpp
      - copied unchanged from r85368, trunk/tools/quickbook/src/id_manager_impl.hpp
   branches/release/tools/quickbook/src/id_xml.cpp
      - copied unchanged from r85368, trunk/tools/quickbook/src/id_xml.cpp
   branches/release/tools/quickbook/test/link-1_7-fail.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/link-1_7-fail.quickbook
   branches/release/tools/quickbook/test/list_test-1_7-fail1.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/list_test-1_7-fail1.quickbook
   branches/release/tools/quickbook/test/mismatched_brackets3-1_1.gold
      - copied unchanged from r85368, trunk/tools/quickbook/test/mismatched_brackets3-1_1.gold
   branches/release/tools/quickbook/test/mismatched_brackets3-1_1.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/mismatched_brackets3-1_1.quickbook
   branches/release/tools/quickbook/test/role-1_7-fail.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/role-1_7-fail.quickbook
   branches/release/tools/quickbook/test/role-1_7.gold
      - copied unchanged from r85368, trunk/tools/quickbook/test/role-1_7.gold
   branches/release/tools/quickbook/test/role-1_7.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/role-1_7.quickbook
   branches/release/tools/quickbook/test/table-1_7.gold
      - copied unchanged from r85368, trunk/tools/quickbook/test/table-1_7.gold
   branches/release/tools/quickbook/test/table-1_7.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/table-1_7.quickbook
   branches/release/tools/quickbook/test/templates-1_6-fail1.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/templates-1_6-fail1.quickbook
   branches/release/tools/quickbook/test/templates-1_6.gold
      - copied unchanged from r85368, trunk/tools/quickbook/test/templates-1_6.gold
   branches/release/tools/quickbook/test/templates-1_6.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/templates-1_6.quickbook
   branches/release/tools/quickbook/test/templates-1_7-fail1.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/templates-1_7-fail1.quickbook
   branches/release/tools/quickbook/test/templates-1_7.gold
      - copied unchanged from r85368, trunk/tools/quickbook/test/templates-1_7.gold
   branches/release/tools/quickbook/test/templates-1_7.quickbook
      - copied unchanged from r85368, trunk/tools/quickbook/test/templates-1_7.quickbook
Properties modified: 
   branches/release/tools/quickbook/   (props changed)
Text files modified: 
   branches/release/tools/quickbook/doc/1_6.qbk                             |   177 +------                                 
   branches/release/tools/quickbook/doc/1_7.qbk                             |   176 +++++++                                 
   branches/release/tools/quickbook/doc/block.qbk                           |     4                                         
   branches/release/tools/quickbook/doc/change_log.qbk                      |    12                                         
   branches/release/tools/quickbook/doc/language_versions.qbk               |    46 +                                       
   branches/release/tools/quickbook/doc/quickbook.qbk                       |     3                                         
   branches/release/tools/quickbook/src/Jamfile.v2                          |     2                                         
   branches/release/tools/quickbook/src/actions.cpp                         |   243 +++++----                               
   branches/release/tools/quickbook/src/actions.hpp                         |    39 -                                       
   branches/release/tools/quickbook/src/block_element_grammar.cpp           |    13                                         
   branches/release/tools/quickbook/src/block_tags.hpp                      |     2                                         
   branches/release/tools/quickbook/src/doc_info_grammar.cpp                |     4                                         
   branches/release/tools/quickbook/src/grammar.cpp                         |     4                                         
   branches/release/tools/quickbook/src/grammar.hpp                         |     4                                         
   branches/release/tools/quickbook/src/grammar_impl.hpp                    |    22                                         
   branches/release/tools/quickbook/src/id_generation.cpp                   |   378 +++++++++++++++                         
   branches/release/tools/quickbook/src/id_manager.cpp                      |   989 ++++++--------------------------------- 
   branches/release/tools/quickbook/src/id_manager.hpp                      |     1                                         
   branches/release/tools/quickbook/src/id_manager_impl.hpp                 |   144 +++++                                   
   branches/release/tools/quickbook/src/id_xml.cpp                          |   153 ++++++                                  
   branches/release/tools/quickbook/src/main_grammar.cpp                    |   442 +++++++++++------                       
   branches/release/tools/quickbook/src/markups.cpp                         |     1                                         
   branches/release/tools/quickbook/src/phrase_element_grammar.cpp          |     2                                         
   branches/release/tools/quickbook/src/quickbook.cpp                       |     2                                         
   branches/release/tools/quickbook/src/state.cpp                           |    41                                         
   branches/release/tools/quickbook/src/state.hpp                           |     9                                         
   branches/release/tools/quickbook/src/state_save.hpp                      |    19                                         
   branches/release/tools/quickbook/src/syntax_highlight.cpp                |    50 -                                       
   branches/release/tools/quickbook/test/Jamfile.v2                         |    10                                         
   branches/release/tools/quickbook/test/elements-1_6.gold                  |    24                                         
   branches/release/tools/quickbook/test/elements-1_6.quickbook             |    10                                         
   branches/release/tools/quickbook/test/include/in_section-1_5.gold        |    28 +                                       
   branches/release/tools/quickbook/test/include/in_section-1_6.gold        |    24                                         
   branches/release/tools/quickbook/test/include/in_section-inc1.quickbook  |     4                                         
   branches/release/tools/quickbook/test/include/in_section-inc2.quickbook  |     4                                         
   branches/release/tools/quickbook/test/link-1_7-fail.quickbook            |     5                                         
   branches/release/tools/quickbook/test/list_test-1_6.gold                 |    56 +-                                      
   branches/release/tools/quickbook/test/list_test-1_7-fail1.quickbook      |     9                                         
   branches/release/tools/quickbook/test/list_test-1_7.gold                 |   102 +--                                     
   branches/release/tools/quickbook/test/mismatched_brackets3-1_1.gold      |    12                                         
   branches/release/tools/quickbook/test/mismatched_brackets3-1_1.quickbook |     6                                         
   branches/release/tools/quickbook/test/role-1_7-fail.quickbook            |     5                                         
   branches/release/tools/quickbook/test/role-1_7.gold                      |     9                                         
   branches/release/tools/quickbook/test/role-1_7.quickbook                 |     5                                         
   branches/release/tools/quickbook/test/table-1_7.gold                     |   514 ++++++++++++++++++++                    
   branches/release/tools/quickbook/test/table-1_7.quickbook                |   148 +++++                                   
   branches/release/tools/quickbook/test/templates-1_3.gold                 |    23                                         
   branches/release/tools/quickbook/test/templates-1_3.quickbook            |    16                                         
   branches/release/tools/quickbook/test/templates-1_4.gold                 |     7                                         
   branches/release/tools/quickbook/test/templates-1_4.quickbook            |    18                                         
   branches/release/tools/quickbook/test/templates-1_5.gold                 |   269 +++++++++-                              
   branches/release/tools/quickbook/test/templates-1_5.quickbook            |   255 +++++++++                               
   branches/release/tools/quickbook/test/templates-1_6-fail1.quickbook      |     8                                         
   branches/release/tools/quickbook/test/templates-1_6.gold                 |   257 ++++++++++                              
   branches/release/tools/quickbook/test/templates-1_6.quickbook            |   313 ++++++++++++                            
   branches/release/tools/quickbook/test/templates-1_7-fail1.quickbook      |    12                                         
   branches/release/tools/quickbook/test/templates-1_7.gold                 |   302 ++++++++++++                            
   branches/release/tools/quickbook/test/templates-1_7.quickbook            |   322 +++++++++++++                           
   58 files changed, 4235 insertions(+), 1524 deletions(-)
Modified: branches/release/tools/quickbook/doc/1_6.qbk
==============================================================================
--- branches/release/tools/quickbook/doc/1_6.qbk	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/doc/1_6.qbk	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -1,47 +1,12 @@
 [/
     Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
-    Copyright 2010-2011 Daniel James
+    Copyright 2010-2013 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)
 ]
 
-[chapter Language Versions
-    [quickbook 1.7]
-    [compatibility-mode 1.5]
-    [id quickbook.versions]
-    [source-mode teletype]
-]
-
-[section:stable Stable Versions]
-
-Since quickbook 1.3 the `quickbook` attribute in the document block selects
-which version of the language to use. Not all changes to quickbook are
-implemented using a version switch, it's mainly just the changes that change
-the way a document is interpreted or would break existing documentation.
-
-[heading Quickbook 1.3 and later]
-
-* Introduced quickbook language versioning.
-* In the documentation info, allow phrase markup in license and purpose
-  attributes.
-* Fully qualified section and headers. Subsection names are concatenated to the
-  ID to avoid clashing. Example: `doc_name.sect_name.sub_sect_name.sub_sub_sect_name`.
-
-[heading Quickbook 1.5 and later]
-
-* Ignore template argument separators inside square brackets.
-* Don't separate the final template argument if the `..` separator was
-  used. i.e. never mix `..` and whitespace separators.
-* Statically scope templates and their arguments rather than dynamically
-  scope them.
-* Give table ids, and let you set them.
-* Allow spaces between the `:` character and ids in elements which can
-  have ids.
-
-[endsect]
-
 [section:1_6 Quickbook 1.6]
 
 Everything described in here may change depending on the feedback received.
@@ -246,6 +211,30 @@
 
 [endsect] [/xmlbase]
 
+[section:template_parser Improved template parser]
+
+There's a new parser for template declarations and parameters which does
+a better job of understanding escaped and bracketed text. Unfortunately
+it does not understand element names so there are some cases where it
+could go wrong. For example:
+
+    [template doesnt_work[]
+    [ordered_list
+        [`code phrase`]
+    ]
+    ]
+
+In this case it will think the `[\`` is a template call and give a parse
+error. To work around this put an escaped space before the code phrase:
+
+    [template works[]
+    [ordered_list
+        [\ `code phrase`]
+    ]
+    ]
+
+[endsect]
+
 [section:elements New Elements]
 
 [section:block `block`]
@@ -314,119 +303,3 @@
 [endsect]
 
 [endsect] [/ Quickbok 1.6]
-
-[section:1_7 Quickbook 1.7]
-
-[section:source_mode Source mode for single entities]
-
-1.7 introduces a new `!` element type for setting the source mode of a single
-entity without changing the source mode otherwise. This can be used for
-code blocks and other elements. For example:
-
-```
-[!c++]
-    void foo() {};
-
-[!python]``\`\`\`\ ``def foo():``\`\`\`\ ``
-```
-
-It can also be used to set the source mode for elements:
-
-```
-[!teletype][table
-    [[code][meaning]]
-    [[`+`][addition]]
-]
-```
-
-When used a section, it's only set for the section element, not the
-whole section.
-
-Currently it does support other syntactic entities such as paragraphs
-and lists. I'm not sure if it would be a good idea.
-
-[endsect]
-
-[section:callouts Callouts in code block]
-
-Currently callouts can only be used in code snippets. 1.7 add
-support in normal code blocks. The same syntax is used as in
-code snippets, the callout descriptions appear immediately
-after the code block.
-
-[endsect]
-
-[section:escaped_docinfo_attributes Escaped docbook in docinfo blocks]
-
-Quickbook docinfo attributes will probably never be as rich as docbook
-attributes so to allow more flexible markup, not supported by quickbook
-escaped docbook can be included in the docinfo block:
-
-```
-[article Some article
-[quickbook 1.7]
-'''<author>
-    <firstname>John</firstname>
-    <surname>Doe</surname>
-    <email>john.doe_at_[hidden]</email>
-</author>'''
-]
-```
-
-The escaped docbook is always placed at the end of the docinfo block,
-so it shouldn't be assumed that it will interleave the markup. A mixture
-of quickbook and docbook attributes for the same information will not work
-well.
-
-[endsect] [/escaped_docinfo_attributes]
-
-[section:listparagraphs Pargraphs in lists]
-
-I'm still refining this, but paragraphs and block elements can now be used
-in lists:
-
-[pre
-* Para 1
-
-  Para 2
-  * Nested Para 1
-
-    Nested Para 2
-
-        Code block
-  Para 3
-]
-
-generates:
-
-* Para 1
-
-  Para 2
-  * Nested Para 1
-
-    Nested Para 2
-
-        Code block
-  Para 3
-
-The docbook markup that this generates is pretty bad, but seems to create okay
-html.
-
-[endsect]
-
-[section:templates_in_link_values Templates in link values]
-
-There's very premilinary support for calling templates in link values. A lot
-more work needs to be done, including:
-
-* Considering other places where templates could be called (e.g. images are
-  quite tricky, as templates could get confused with attributes, should
-  templates be callable from something like an element's id?).
-* Trimming spaces from the body of the template (which can cause surprising
-  results).
-* Checking that the contents of the template are appropriate for the context.
-  Possibly even using a different grammar.
-
-[endsect] [/templates_in_link_values]
-
-[endsect] [/ Quickbok 1.7]
Copied: branches/release/tools/quickbook/doc/1_7.qbk (from r85368, trunk/tools/quickbook/doc/1_7.qbk)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/doc/1_7.qbk	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/doc/1_7.qbk)
@@ -0,0 +1,176 @@
+[/
+    Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+    Copyright 2012-2013 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)
+]
+
+[section:1_7 Quickbook 1.7]
+
+[section:context_error Error for elements used in incorrect context]
+
+Previously if you used an element in the wrong context it would just be
+unprocessed, which was surprising. People often didn't realise that their
+element hadn't been processed. So now it's an error.
+
+[endsect]
+
+[section:phrase_parse_error Error for invalid phrase elements]
+
+If the body of a phrase element didn't parse, it would be just used
+unprocessed. Now change it to be a hard error.
+
+[endsect]
+
+[section:source_mode Source mode for single entities]
+
+1.7 introduces a new `!` element type for setting the source mode of a single
+entity without changing the source mode otherwise. This can be used for
+code blocks and other elements. For example:
+
+```
+[!c++]
+    void foo() {};
+
+[!python]``\`\`\`\ ``def foo():``\`\`\`\ ``
+```
+
+It can also be used to set the source mode for elements:
+
+```
+[!teletype][table
+    [[code][meaning]]
+    [[`+`][addition]]
+]
+```
+
+When used before a section, it sets the source mode for the section element,
+not the whole section.
+
+Currently it does not support other syntactic entities such as paragraphs
+and lists. It will currently be used to the next code block or element.
+This is a bit messy, but I'm not sure what would be a good idea.
+
+[endsect]
+
+[section:callouts Callouts in code blocks]
+
+Currently callouts can only be used in code snippets. 1.7 add
+support in normal code blocks. The same syntax is used as in
+code snippets, the callout descriptions appear immediately
+after the code block.
+
+[endsect]
+
+[section:escaped_docinfo_attributes Escaped docbook in docinfo blocks]
+
+Quickbook docinfo attributes will probably never be as rich as docbook
+attributes so to allow more flexible markup, not supported by quickbook
+escaped docbook can be included in the docinfo block:
+
+```
+[article Some article
+[quickbook 1.7]
+'''<author>
+    <firstname>John</firstname>
+    <surname>Doe</surname>
+    <email>john.doe_at_[hidden]</email>
+</author>'''
+]
+```
+
+The escaped docbook is always placed at the end of the docinfo block,
+so it shouldn't be assumed that it will interleave the markup. A mixture
+of quickbook and docbook attributes for the same information will not work
+well.
+
+[endsect] [/escaped_docinfo_attributes]
+
+[section:listparagraphs Pargraphs in lists]
+
+I'm still refining this, but paragraphs and block elements can now be used
+in lists:
+
+[pre
+* Para 1
+
+  Para 2
+  * Nested Para 1
+
+    Nested Para 2
+
+        Code block
+  Para 3
+]
+
+generates:
+
+* Para 1
+
+  Para 2
+  * Nested Para 1
+
+    Nested Para 2
+
+        Code block
+  Para 3
+
+The docbook markup that this generates is pretty bad, but seems to create okay
+html.
+
+[endsect]
+
+[section:templates_in_link_values Templates in link values]
+
+There's very premilinary support for calling templates in link values. A lot
+more work needs to be done, including:
+
+* Considering other places where templates could be called (e.g. images are
+  quite tricky, as templates could get confused with attributes, should
+  templates be callable from something like an element's id?).
+* Trimming spaces from the body of the template (which can cause surprising
+  results).
+* Checking that the contents of the template are appropriate for the context.
+  Possibly even using a different grammar.
+
+[endsect] [/templates_in_link_values]
+
+[section:list_markup_in_tables List Markup in Nested Blocks]
+
+Can now place list markup in nested blocks, e.g in tables, variables lists etc.
+Unfortunately indented code blocks are more tricky, because the contents of
+these blocks are often indented already. It seemed easier to just not support
+indented code blocks in this context than to try to work out sensible actions
+for the edges cases. If you want to use code blocks in this context, you should
+still be able to use explicit markup.
+
+[endsect]
+
+[section:phrase_block_templates Allow block elements in phrase templates]
+
+Block elements can now be used in phrase templates, but paragraphs breaks aren't
+allowed, so this is an error:
+
+    [template paras[] Something or other.
+
+    Second paragraph.]
+
+If a phrase template only contains block elements, then it's practically
+indistinguishable from a block template. So you'll get the same output from:
+
+    [template foo[] [blurb Blah, blah, blah]]
+
+as:
+
+    [template foo[]
+    [blurb Blah, blah, blah]
+    ]
+
+If a phrase template has phrase content mixed with block elements, it'll generate
+output as if it was expanded inline.
+
+[endsect]
+
+[endsect] [/ Quickbok 1.7]
Modified: branches/release/tools/quickbook/doc/block.qbk
==============================================================================
--- branches/release/tools/quickbook/doc/block.qbk	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/doc/block.qbk	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -973,9 +973,7 @@
 * Any macros defined in the included file are scoped to that file.
 
 The [^\[include\]] directive lets you specify a document id to use for the
-included file. When this id is not explicitly specified, the id defaults to
-the filename ("someother", in the example above). You can specify the id
-like this:
+included file. You can specify the id like this:
 
 ```
 [include:someid someother.qbk]
Modified: branches/release/tools/quickbook/doc/change_log.qbk
==============================================================================
--- branches/release/tools/quickbook/doc/change_log.qbk	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/doc/change_log.qbk	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -303,3 +303,15 @@
   (Can still nest block elements in lists though).
 * Don't break out of lists after a nested block element.
 * Check for errors when writing dependency files.
+* Improved markup for lists.
+* Make escaping templates with a punctuation identifier illegal.
+  Escaping templates with an alphanumeric identifier is still fine.
+* 1.7 changes:
+  * Make it an error to use an element in the wrong context.
+  * Error if the body of a phrase element doesn't parse.
+  * List markup in nested blocks.
+  * Allow block elements in phrase templates.
+  * Make it an error to put a paragraph break (i.e. a blank line)
+    in a phrase template.
+* Internal changes:
+  * Clean up the id manager implementation.
Copied: branches/release/tools/quickbook/doc/language_versions.qbk (from r85368, trunk/tools/quickbook/doc/language_versions.qbk)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/doc/language_versions.qbk	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/doc/language_versions.qbk)
@@ -0,0 +1,46 @@
+[/
+    Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+    Copyright 2010-2013 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)
+]
+
+[chapter Language Versions
+    [quickbook 1.7]
+    [compatibility-mode 1.5]
+    [id quickbook.versions]
+    [source-mode teletype]
+]
+
+[section:stable Stable Versions]
+
+Since quickbook 1.3 the `quickbook` attribute in the document block selects
+which version of the language to use. Not all changes to quickbook are
+implemented using a version switch, it's mainly just the changes that change
+the way a document is interpreted or would break existing documentation.
+
+[heading Quickbook 1.3 and later]
+
+* Introduced quickbook language versioning.
+* In the documentation info, allow phrase markup in license and purpose
+  attributes.
+* Fully qualified section and headers. Subsection names are concatenated to the
+  ID to avoid clashing. Example: `doc_name.sect_name.sub_sect_name.sub_sub_sect_name`.
+
+[heading Quickbook 1.5 and later]
+
+* Ignore template argument separators inside square brackets.
+* Don't separate the final template argument if the `..` separator was
+  used. i.e. never mix `..` and whitespace separators.
+* Statically scope templates and their arguments rather than dynamically
+  scope them.
+* Give table ids, and let you set them.
+* Allow spaces between the `:` character and ids in elements which can
+  have ids.
+
+[endsect]
+
+[include 1_6.qbk]
+[include 1_7.qbk]
Modified: branches/release/tools/quickbook/doc/quickbook.qbk
==============================================================================
--- branches/release/tools/quickbook/doc/quickbook.qbk	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/doc/quickbook.qbk	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -87,8 +87,9 @@
 [include structure.qbk]
 [include phrase.qbk]
 [include block.qbk]
+[include language_versions.qbk]
 [include 1_6.qbk]
 [include install.qbk]
 [include editors.qbk]
 [include faq.qbk]
-[include ref.qbk]
\ No newline at end of file
+[include ref.qbk]
Modified: branches/release/tools/quickbook/src/Jamfile.v2
==============================================================================
--- branches/release/tools/quickbook/src/Jamfile.v2	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/Jamfile.v2	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -33,6 +33,8 @@
     input_path.cpp
     values.cpp
     id_manager.cpp
+    id_generation.cpp
+    id_xml.cpp
     post_process.cpp
     collector.cpp
     template_stack.cpp
Modified: branches/release/tools/quickbook/src/actions.cpp
==============================================================================
--- branches/release/tools/quickbook/src/actions.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/actions.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -198,7 +198,7 @@
 
     void break_action::operator()(parse_iterator first, parse_iterator) const
     {
-        write_anchors(state, phrase);
+        write_anchors(state, state.phrase);
 
         if(*first == '\\')
         {
@@ -216,7 +216,7 @@
             state.warned_about_breaks = true;
         }
             
-        phrase << detail::get_markup(phrase_tags::break_mark).pre;
+        state.phrase << detail::get_markup(phrase_tags::break_mark).pre;
     }
 
     void error_message_action::operator()(parse_iterator first, parse_iterator last) const
@@ -322,27 +322,18 @@
         while(pos != end && cl::space_p.test(*pos)) ++pos;
 
         if(pos != end) {
-            detail::markup markup = detail::get_markup(block_tags::paragraph);
+            detail::markup markup = state.in_list ?
+                detail::get_markup(block_tags::paragraph_in_list) :
+                detail::get_markup(block_tags::paragraph);
             state.out << markup.pre << str;
             write_anchors(state, state.out);
             state.out << markup.post;
         }
     }
 
-    void list_item_action::operator()() const
+    void explicit_list_action::operator()() const
     {
-        // Be careful as this is sometimes called in the wrong place
-        // for markup such as:
-        //
-        // * A
-        // [endsect]
-        //
-        // This action is called before [endsect] (to end the list item)
-        // and then also after it due to the way the parser works.
-        std::string str;
-        state.phrase.swap(str);
-        state.out << str;
-        write_anchors(state, state.out);
+        state.explicit_list = true;
     }
 
     void phrase_end_action::operator()() const
@@ -405,6 +396,8 @@
 
         if (!element_id.empty())
         {
+            // Use an explicit id.
+
             std::string anchor = state.ids.add_id(
                 element_id.get_quickbook(),
                 id_category::explicit_id);
@@ -412,40 +405,54 @@
             write_bridgehead(state, level,
                 content.get_encoded(), anchor, self_linked_headers);
         }
-        else if (!generic && state.ids.compatibility_version() < 103) // version 1.2 and below
+        else if (state.ids.compatibility_version() >= 106u)
         {
-            // This generates the old id style if both the interpreting
-            // version and the generation version are less then 103u.
+            // Generate ids for 1.6+
 
-            std::string anchor = state.ids.old_style_id(
-                detail::make_identifier(
-                    state.ids.replace_placeholders_with_unresolved_ids(
-                        content.get_encoded())),
+            std::string anchor = state.ids.add_id(
+                detail::make_identifier(content.get_quickbook()),
                 id_category::generated_heading);
 
             write_bridgehead(state, level,
-                content.get_encoded(), anchor, false);
-
+                content.get_encoded(), anchor, self_linked_headers);
         }
         else
         {
-            std::string anchor = state.ids.add_id(
-                detail::make_identifier(
-                    state.ids.compatibility_version() >= 106 ?
-                        content.get_quickbook() :
-                        state.ids.replace_placeholders_with_unresolved_ids(
-                            content.get_encoded())
-                ),
-                id_category::generated_heading);
+            // Generate ids that are compatible with older versions of quickbook.
 
-            write_bridgehead(state, level,
-                content.get_encoded(), anchor, self_linked_headers);
+            // Older versions of quickbook used the generated boostbook, but
+            // we only have an intermediate version which can contain id
+            // placeholders. So to generate the ids they must be replaced
+            // by the ids that the older versions would have used - i.e. the
+            // unresolved ids.
+            //
+            // Note that this doesn't affect the actual boostbook generated for
+            // the content, it's just used to generate this id.
+
+            std::string id = detail::make_identifier(
+                    state.ids.replace_placeholders_with_unresolved_ids(
+                        content.get_encoded()));
+
+            if (generic || state.ids.compatibility_version() >= 103) {
+                std::string anchor =
+                    state.ids.add_id(id, id_category::generated_heading);
+
+                write_bridgehead(state, level,
+                    content.get_encoded(), anchor, self_linked_headers);
+            }
+            else {
+                std::string anchor =
+                    state.ids.old_style_id(id, id_category::generated_heading);
+
+                write_bridgehead(state, level,
+                    content.get_encoded(), anchor, false);
+            }
         }
     }
 
     void simple_phrase_action::operator()(char mark) const
     {
-        write_anchors(state, out);
+        write_anchors(state, state.phrase);
 
         int tag =
             mark == '*' ? phrase_tags::bold :
@@ -461,9 +468,9 @@
         value content = values.consume();
         values.finish();
 
-        out << markup.pre;
-        out << content.get_encoded();
-        out << markup.post;
+        state.phrase << markup.pre;
+        state.phrase << content.get_encoded();
+        state.phrase << markup.post;
     }
 
     bool cond_phrase_push::start()
@@ -480,8 +487,7 @@
             state.conditional = find(state.macro, macro.c_str());
 
             if (!state.conditional) {
-                state.phrase.push();
-                state.out.push();
+                state.push_output();
                 state.anchors.swap(anchors);
             }
         }
@@ -493,8 +499,7 @@
     {
         if (saved_conditional && !state.conditional)
         {
-            state.phrase.pop();
-            state.out.pop();
+            state.pop_output();
             state.anchors.swap(anchors);
         }
 
@@ -522,9 +527,11 @@
 
     void state::start_list(char mark)
     {
-        write_anchors(*this, out);
+        write_anchors(*this, (in_list ? phrase : out));
         assert(mark == '*' || mark == '#');
+        push_output();
         out << ((mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
+        in_list = true;
     }
 
     void state::end_list(char mark)
@@ -532,18 +539,27 @@
         write_anchors(*this, out);
         assert(mark == '*' || mark == '#');
         out << ((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
+
+        std::string list_output;
+        out.swap(list_output);
+
+        pop_output();
+
+        (in_list ? phrase : out) << list_output;
     }
 
     void state::start_list_item()
     {
-        out << "<listitem><simpara>";
-        write_anchors(*this, out);
+        out << "<listitem>";
+        write_anchors(*this, phrase);
     }
 
     void state::end_list_item()
     {
-        write_anchors(*this, out);
-        out << "</simpara></listitem>";
+        write_anchors(*this, phrase);
+        paragraph_action para(*this);
+        para();
+        out << "</listitem>";
     }
 
     namespace
@@ -593,7 +609,7 @@
             std::string callout_value;
 
             {
-                template_state state(*this);
+                state_save save(*this, state_save::scope_all);
                 ++template_depth;
 
                 bool r = parse_template(callout_body, *this);
@@ -654,35 +670,35 @@
 
     void do_macro_action::operator()(std::string const& str) const
     {
-        write_anchors(state, phrase);
+        write_anchors(state, state.phrase);
 
         if (str == quickbook_get_date)
         {
             char strdate[64];
             strftime(strdate, sizeof(strdate), "%Y-%b-%d", current_time);
-            phrase << strdate;
+            state.phrase << strdate;
         }
         else if (str == quickbook_get_time)
         {
             char strdate[64];
             strftime(strdate, sizeof(strdate), "%I:%M:%S %p", current_time);
-            phrase << strdate;
+            state.phrase << strdate;
         }
         else
         {
-            phrase << str;
+            state.phrase << str;
         }
     }
 
     void raw_char_action::operator()(char ch) const
     {
-        out << ch;
+        state.phrase << ch;
     }
 
     void raw_char_action::operator()(parse_iterator first, parse_iterator last) const
     {
         while (first != last)
-            out << *first++;
+            state.phrase << *first++;
     }
 
     void source_mode_action(quickbook::state& state, value source_mode)
@@ -742,52 +758,50 @@
             boost::swap(state.current_file, saved_file);
 
             // print the code with syntax coloring
-            std::string str = syntax_highlight(first_, last_, state,
-                source_mode, block);
+            //
+            // We must not place a \n after the <programlisting> tag
+            // otherwise PDF output starts code blocks with a blank line:
+            state.phrase << "<programlisting>";
+            syntax_highlight(first_, last_, state, source_mode, block);
+            state.phrase << "</programlisting>\n";
 
             boost::swap(state.current_file, saved_file);
 
-            collector& output = inline_code ? state.phrase : state.out;
-
-            // We must not place a \n after the <programlisting> tag
-            // otherwise PDF output starts code blocks with a blank line:
-            //
-            output << "<programlisting>";
-            output << str;
-            output << "</programlisting>\n";
+            if (qbk_version_n >= 107u) state.phrase << state.end_callouts();
 
-            if (qbk_version_n >= 107u) output << state.end_callouts();
+            if (!inline_code) {
+                state.out << state.phrase.str();
+                state.phrase.clear();
+            }
         }
         else {
             parse_iterator first_(code_value.begin());
             parse_iterator last_(code_value.end());
-            std::string str = syntax_highlight(first_, last_, state,
-                source_mode, block);
 
             state.phrase << "<code>";
-            state.phrase << str;
+            syntax_highlight(first_, last_, state, source_mode, block);
             state.phrase << "</code>";
         }
     }
 
     void plain_char_action::operator()(char ch) const
     {
-        write_anchors(state, phrase);
+        write_anchors(state, state.phrase);
 
-        detail::print_char(ch, phrase.get());
+        detail::print_char(ch, state.phrase.get());
     }
 
     void plain_char_action::operator()(parse_iterator first, parse_iterator last) const
     {
-        write_anchors(state, phrase);
+        write_anchors(state, state.phrase);
 
         while (first != last)
-            detail::print_char(*first++, phrase.get());
+            detail::print_char(*first++, state.phrase.get());
     }
 
     void escape_unicode_action::operator()(parse_iterator first, parse_iterator last) const
     {
-        write_anchors(state, phrase);
+        write_anchors(state, state.phrase);
 
         while(first != last && *first == '0') ++first;
 
@@ -799,10 +813,11 @@
         
         if(hex_digits.size() == 2 && *first > '0' && *first <= '7') {
             using namespace std;
-            detail::print_char(strtol(hex_digits.c_str(), 0, 16), phrase.get());
+            detail::print_char(strtol(hex_digits.c_str(), 0, 16),
+                    state.phrase.get());
         }
         else {
-            phrase << "&#x" << hex_digits << ";";
+            state.phrase << "&#x" << hex_digits << ";";
         }
     }
 
@@ -1217,7 +1232,7 @@
             bool r = cl::parse(first, last,
                     content.get_tag() == template_tags::phrase ?
                         state.grammar().inline_phrase :
-                        state.grammar().block
+                        state.grammar().block_start
                 ).full;
 
             boost::swap(state.current_file, saved_current_file);
@@ -1232,23 +1247,17 @@
             string_iterator first)
     {
         bool is_block = symbol->content.get_tag() != template_tags::phrase;
+        quickbook::paragraph_action paragraph_action(state);
+
+        // Finish off any existing paragraphs.
+        if (is_block) paragraph_action();
 
         // If this template contains already encoded text, then just
         // write it out, without going through any of the rigamarole.
 
         if (symbol->content.is_encoded())
         {
-            if (is_block)
-            {
-                paragraph_action para(state);
-                para();
-                state.out << symbol->content.get_encoded();
-            }
-            else
-            {
-                state.phrase << symbol->content.get_encoded();
-            }
-
+            (is_block ? state.out : state.phrase) << symbol->content.get_encoded();
             return;
         }
 
@@ -1259,11 +1268,11 @@
         // arguments are expanded.
         template_scope const& call_scope = state.templates.top_scope();
 
-        std::string block;
-        std::string phrase;
-
         {
-            template_state save(state);
+            state_save save(state, state_save::scope_callables);
+            std::string save_block;
+            std::string save_phrase;
+
             state.templates.start_template(symbol);
 
             qbk_version_n = symbol->content.get_file()->version();
@@ -1296,6 +1305,11 @@
             ///////////////////////////////////
             // parse the template body:
 
+            if (symbol->content.get_file()->version() < 107u) {
+                state.out.swap(save_block);
+                state.phrase.swap(save_phrase);
+            }
+
             if (!parse_template(symbol->content, state))
             {
                 detail::outerr(state.current_file, first)
@@ -1321,19 +1335,24 @@
                 return;
             }
 
-            state.out.swap(block);
-            state.phrase.swap(phrase);
-        }
-
-        if(is_block || !block.empty()) {
-            paragraph_action para(state);
-            para(); // For paragraphs before the template call.
-            state.out << block;
-            state.phrase << phrase;
-            para();
-        }
-        else {
-            state.phrase << phrase;
+            if (symbol->content.get_file()->version() < 107u) {
+                state.out.swap(save_block);
+                state.phrase.swap(save_phrase);
+
+                if(is_block || !save_block.empty()) {
+                    paragraph_action();
+                    state.out << save_block;
+                    state.phrase << save_phrase;
+                    paragraph_action();
+                }
+                else {
+                    state.phrase << save_phrase;
+                }
+            }
+            else
+            {
+                if (is_block) paragraph_action();
+            }
         }
     }
 
@@ -1933,10 +1952,10 @@
             //
             // For old versions of quickbook, templates aren't scoped by the
             // file.
-            file_state save(state,
-                load_type == block_tags::import ? file_state::scope_output :
-                qbk_version_n >= 106u ? file_state::scope_callables :
-                file_state::scope_macros);
+            state_save save(state,
+                load_type == block_tags::import ? state_save::scope_output :
+                qbk_version_n >= 106u ? state_save::scope_callables :
+                state_save::scope_macros);
 
             state.current_file = load(paths.filename); // Throws load_error
             state.filename_relative = paths.filename_relative;
@@ -2069,8 +2088,7 @@
 
     bool to_value_scoped_action::start(value::tag_type t)
     {
-        state.out.push();
-        state.phrase.push();
+        state.push_output();
         state.anchors.swap(saved_anchors);
         tag = t;
 
@@ -2101,8 +2119,7 @@
     
     void to_value_scoped_action::cleanup()
     {
-        state.phrase.pop();
-        state.out.pop();
+        state.pop_output();
         state.anchors.swap(saved_anchors);
     }
 }
Modified: branches/release/tools/quickbook/src/actions.hpp
==============================================================================
--- branches/release/tools/quickbook/src/actions.hpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/actions.hpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -46,7 +46,7 @@
     int load_snippets(fs::path const& file, std::vector<template_symbol>& storage,
         std::string const& extension, value::tag_type load_type);
 
-    std::string syntax_highlight(
+    void syntax_highlight(
         parse_iterator first, parse_iterator last,
         quickbook::state& state,
         std::string const& source_mode,
@@ -119,12 +119,12 @@
         quickbook::state& state;
     };
 
-    struct list_item_action
+    struct explicit_list_action
     {
         //  implicit paragraphs
         //  doesn't output the paragraph if it's only whitespace.
 
-        list_item_action(
+        explicit_list_action(
             quickbook::state& state)
         : state(state) {}
 
@@ -149,15 +149,11 @@
     {
         //  Handles simple text formats
 
-        simple_phrase_action(
-            collector& out
-          , quickbook::state& state)
-        : out(out)
-        , state(state) {}
+        simple_phrase_action(quickbook::state& state)
+        : state(state) {}
 
         void operator()(char) const;
 
-        collector& out;
         quickbook::state& state;
     };
 
@@ -178,12 +174,9 @@
     {
         // Handles macro substitutions
 
-        do_macro_action(collector& phrase, quickbook::state& state)
-            : phrase(phrase)
-            , state(state) {}
+        do_macro_action(quickbook::state& state) : state(state) {}
 
         void operator()(std::string const& str) const;
-        collector& phrase;
         quickbook::state& state;
     };
 
@@ -191,13 +184,12 @@
     {
         // Prints a space
 
-        raw_char_action(collector& out)
-            : out(out) {}
+        raw_char_action(quickbook::state& state) : state(state) {}
 
         void operator()(char ch) const;
         void operator()(parse_iterator first, parse_iterator last) const;
 
-        collector& out;
+        quickbook::state& state;
     };
 
     struct plain_char_action
@@ -205,36 +197,29 @@
         // Prints a single plain char.
         // Converts '<' to "<"... etc See utils.hpp
 
-        plain_char_action(collector& phrase, quickbook::state& state)
-        : phrase(phrase)
-        , state(state) {}
+        plain_char_action(quickbook::state& state) : state(state) {}
 
         void operator()(char ch) const;
         void operator()(parse_iterator first, parse_iterator last) const;
 
-        collector& phrase;
         quickbook::state& state;
     };
     
     struct escape_unicode_action
     {
-        escape_unicode_action(collector& phrase, quickbook::state& state)
-        : phrase(phrase)
-        , state(state) {}
+        escape_unicode_action(quickbook::state& state) : state(state) {}
+
         void operator()(parse_iterator first, parse_iterator last) const;
 
-        collector& phrase;
         quickbook::state& state;
     };
 
     struct break_action
     {
-        break_action(collector& phrase, quickbook::state& state)
-        : phrase(phrase), state(state) {}
+        break_action(quickbook::state& state) : state(state) {}
 
         void operator()(parse_iterator f, parse_iterator) const;
 
-        collector& phrase;
         quickbook::state& state;
     };
 
Modified: branches/release/tools/quickbook/src/block_element_grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/block_element_grammar.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/block_element_grammar.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -47,7 +47,8 @@
         // Actions
         error_action error(state);
         element_id_warning_action element_id_warning(state);
-        raw_char_action raw_char(state.phrase);
+        raw_char_action raw_char(state);
+        explicit_list_action explicit_list(state);
         scoped_parser<to_value_scoped_action> to_value(state);
 
         local.element_id =
@@ -66,8 +67,8 @@
                 !(qbk_ver(106u) >> local.element_id);
 
         elements.add
-            ("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))
+            ("section", element_info(element_info::section_block, &local.begin_section, block_tags::begin_section))
+            ("endsect", element_info(element_info::section_block, &local.end_section, block_tags::end_section))
             ;
 
         local.begin_section =
@@ -261,7 +262,11 @@
             ("itemized_list", element_info(element_info::nested_block, &local.list, block_tags::itemized_list, 106))
             ;
 
-        local.list = *local.cell;
+        local.list =
+            *(  cl::eps_p                       [explicit_list]
+            >>  local.cell
+            )
+            ;
 
         local.cell =
                 space
Modified: branches/release/tools/quickbook/src/block_tags.hpp
==============================================================================
--- branches/release/tools/quickbook/src/block_tags.hpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/block_tags.hpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -22,7 +22,7 @@
         (macro_definition)(template_definition)
         (variable_list)(table)
         (xinclude)(import)(include)
-        (paragraph)
+        (paragraph)(paragraph_in_list)
         (ordered_list)(itemized_list)
         (hr)
     )
Modified: branches/release/tools/quickbook/src/doc_info_grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/doc_info_grammar.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/doc_info_grammar.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -118,8 +118,8 @@
 
         // Actions
         error_action error(state);
-        plain_char_action plain_char(state.phrase, state);
-        do_macro_action do_macro(state.phrase, state);
+        plain_char_action plain_char(state);
+        do_macro_action do_macro(state);
         scoped_parser<to_value_scoped_action> to_value(state);
         
         doc_info_details =
Modified: branches/release/tools/quickbook/src/grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/grammar.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/grammar.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -17,8 +17,8 @@
         : impl_(new impl(s))
         , command_line_macro(impl_->command_line, "command_line_macro")
         , inline_phrase(impl_->inline_phrase, "inline_phrase")
-        , phrase(impl_->phrase_start, "phrase")
-        , block(impl_->block_start, "block")
+        , phrase_start(impl_->phrase_start, "phrase")
+        , block_start(impl_->block_start, "block")
         , doc_info(impl_->doc_info_details, "doc_info")
     {
     }
Modified: branches/release/tools/quickbook/src/grammar.hpp
==============================================================================
--- branches/release/tools/quickbook/src/grammar.hpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/grammar.hpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -58,8 +58,8 @@
     public:
         grammar command_line_macro;
         grammar inline_phrase;
-        grammar phrase;
-        grammar block;
+        grammar phrase_start;
+        grammar block_start;
         grammar doc_info;
 
         quickbook_grammar(quickbook::state&);
Modified: branches/release/tools/quickbook/src/grammar_impl.hpp
==============================================================================
--- branches/release/tools/quickbook/src/grammar_impl.hpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/grammar_impl.hpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -24,7 +24,7 @@
     {
         enum type_enum {
             nothing = 0,
-            block = 1,
+            section_block = 1,
             conditional_or_block = 2,
             nested_block = 4,
             phrase = 8,
@@ -32,14 +32,20 @@
         };
 
         enum context {
-            in_phrase = phrase | maybe_block,
-            in_nested_block = phrase | maybe_block | nested_block,
+            // At the top level we allow everything.
+            in_top_level = phrase | maybe_block | nested_block | conditional_or_block | section_block,
+            // In conditional phrases and list blocks we everything but section elements.
             in_conditional = phrase | maybe_block | nested_block | conditional_or_block,
-            in_block = phrase | maybe_block | nested_block | conditional_or_block | block,
-            only_nested_block = nested_block,
-            only_block = nested_block | conditional_or_block | block,
-            only_list_block = nested_block | conditional_or_block,
-            only_contextual_block = maybe_block | nested_block | conditional_or_block | block
+            in_list_block = phrase | maybe_block | nested_block | conditional_or_block,
+            // In nested blocks we allow a much more limited range of elements.
+            in_nested_block = phrase | maybe_block | nested_block,
+            // In a phrase we only allow phrase elements, ('maybe_block'
+            // elements are treated as phrase elements in this context)
+            in_phrase = phrase | maybe_block,
+            // At the start of a block these are all block elements.
+            is_contextual_block = maybe_block | nested_block | conditional_or_block | section_block,
+            // These are all block elements in all other contexts.
+            is_block = nested_block | conditional_or_block | section_block,
         };
 
         element_info()
Copied: branches/release/tools/quickbook/src/id_generation.cpp (from r85368, trunk/tools/quickbook/src/id_generation.cpp)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/src/id_generation.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/src/id_generation.cpp)
@@ -0,0 +1,378 @@
+/*=============================================================================
+    Copyright (c) 2011, 2013 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)
+=============================================================================*/
+
+#include "id_manager_impl.hpp"
+#include <boost/make_shared.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
+#include <boost/range/algorithm.hpp>
+
+// TODO: This should possibly try to always generate valid XML ids:
+// http://www.w3.org/TR/REC-xml/#NT-NameStartChar
+
+namespace quickbook {
+    //
+    // The maximum size of a generated part of an id.
+    //
+    // Not a strict maximum, sometimes broken because the user
+    // explicitly uses a longer id, or for backwards compatibility.
+
+    static const std::size_t max_size = 32;
+
+    typedef std::vector<id_placeholder const*> placeholder_index;
+    placeholder_index index_placeholders(id_state const&, boost::string_ref);
+
+    void generate_id_block(
+            placeholder_index::iterator, placeholder_index::iterator,
+            std::vector<std::string>& generated_ids);
+
+    std::vector<std::string> generate_ids(id_state const& state, boost::string_ref xml)
+    {
+        std::vector<std::string> generated_ids(state.placeholders.size());
+
+        // Get a list of the placeholders in the order that we wish to
+        // process them.
+        placeholder_index placeholders = index_placeholders(state, xml);
+
+        typedef std::vector<id_placeholder const*>::iterator iterator;
+        iterator it = placeholders.begin(), end = placeholders.end();
+
+        while (it != end) {
+            // We process all the ids that have the same number of dots
+            // together. Note that ids with different parents can clash, e.g.
+            // because of old fashioned id generation or anchors containing
+            // multiple dots.
+            //
+            // So find the group of placeholders with the same number of dots.
+            iterator group_begin = it, group_end = it;
+            while (group_end != end && (*group_end)->num_dots == (*it)->num_dots)
+                ++group_end;
+
+            generate_id_block(group_begin, group_end, generated_ids);
+            it = group_end;
+        }
+
+        return generated_ids;
+    }
+
+    //
+    // index_placeholders
+    //
+    // Create a sorted index of the placeholders, in order
+    // to make numbering duplicates easy. A total order.
+    //
+
+    struct placeholder_compare
+    {
+        std::vector<unsigned>& order;
+
+        placeholder_compare(std::vector<unsigned>& order) : order(order) {}
+
+        bool operator()(id_placeholder const* x, id_placeholder const* y) const
+        {
+            bool x_explicit = x->category.c >= id_category::explicit_id;
+            bool y_explicit = y->category.c >= id_category::explicit_id;
+
+            return
+                x->num_dots < y->num_dots ? true :
+                x->num_dots > y->num_dots ? false :
+                x_explicit > y_explicit ? true :
+                x_explicit < y_explicit ? false :
+                order[x->index] < order[y->index];
+        }
+    };
+
+    struct get_placeholder_order_callback : xml_processor::callback
+    {
+        id_state const& state;
+        std::vector<unsigned>& order;
+        unsigned count;
+
+        get_placeholder_order_callback(id_state const& state,
+                std::vector<unsigned>& order)
+          : state(state),
+            order(order),
+            count(0)
+        {}
+
+        void id_value(boost::string_ref value)
+        {
+            set_placeholder_order(state.get_placeholder(value));
+        }
+
+        void set_placeholder_order(id_placeholder const* p)
+        {
+            if (p && !order[p->index]) {
+                set_placeholder_order(p->parent);
+                order[p->index] = ++count;
+            }
+        }
+    };
+
+    placeholder_index index_placeholders(
+            id_state const& state,
+            boost::string_ref xml)
+    {
+        // The order that the placeholder appear in the xml source.
+        std::vector<unsigned> order(state.placeholders.size());
+
+        xml_processor processor;
+        get_placeholder_order_callback callback(state, order);
+        processor.parse(xml, callback);
+
+        placeholder_index sorted_placeholders;
+        sorted_placeholders.reserve(state.placeholders.size());
+        BOOST_FOREACH(id_placeholder const& p, state.placeholders)
+            if (order[p.index]) sorted_placeholders.push_back(&p);
+        boost::sort(sorted_placeholders, placeholder_compare(order));
+
+        return sorted_placeholders;
+    }
+
+    // Resolve and generate ids.
+
+    struct generate_id_block_type
+    {
+        // The ids which won't require duplicate handling.
+        typedef boost::unordered_map<std::string, id_placeholder const*>
+            chosen_id_map;
+        chosen_id_map chosen_ids;
+        std::vector<std::string>& generated_ids;
+
+        generate_id_block_type(std::vector<std::string>& generated_ids) :
+            generated_ids(generated_ids) {}
+
+        void generate(placeholder_index::iterator begin,
+            placeholder_index::iterator end);
+
+        std::string resolve_id(id_placeholder const*);
+        std::string generate_id(id_placeholder const*, std::string const&);
+    };
+
+    void generate_id_block(placeholder_index::iterator begin,
+            placeholder_index::iterator end,
+            std::vector<std::string>& generated_ids)
+    {
+        generate_id_block_type impl(generated_ids);
+        impl.generate(begin, end);
+    }
+
+    void generate_id_block_type::generate(placeholder_index::iterator begin,
+            placeholder_index::iterator end)
+    {
+        std::vector<std::string> resolved_ids;
+
+        for (placeholder_index::iterator i = begin; i != end; ++i)
+            resolved_ids.push_back(resolve_id(*i));
+
+        unsigned index = 0;
+        for (placeholder_index::iterator i = begin; i != end; ++i, ++index)
+        {
+            generated_ids[(**i).index] =
+                generate_id(*i, resolved_ids[index]);
+        }
+    }
+
+    std::string generate_id_block_type::resolve_id(id_placeholder const* p)
+    {
+        std::string id = p->parent ?
+            generated_ids[p->parent->index] + "." + p->id :
+            p->id;
+
+        if (p->category.c > id_category::numbered) {
+            // Reserve the id if it isn't already reserved.
+            chosen_id_map::iterator pos = chosen_ids.emplace(id, p).first;
+
+            // If it was reserved by a placeholder with a lower category,
+            // then overwrite it.
+            if (p->category.c > pos->second->category.c)
+                pos->second = p;
+        }
+
+        return id;
+    }
+
+    std::string generate_id_block_type::generate_id(id_placeholder const* p,
+            std::string const& resolved_id)
+    {
+        if (p->category.c > id_category::numbered &&
+                chosen_ids.at(resolved_id) == p)
+        {
+            return resolved_id;
+        }
+
+        // Split the id into its parent part and child part.
+        //
+        // Note: can't just use the placeholder's parent, as the
+        // placeholder id might contain dots.
+        unsigned child_start = resolved_id.rfind('.');
+        std::string parent_id, base_id;
+
+        if (child_start == std::string::npos) {
+            base_id = normalize_id(resolved_id, max_size - 1);
+        }
+        else {
+            parent_id = resolved_id.substr(0, child_start + 1);
+            base_id = normalize_id(resolved_id.substr(child_start + 1),
+                    max_size - 1);
+        }
+
+        // Since we're adding digits, don't want an id that ends in
+        // a digit.
+
+        unsigned int length = base_id.size();
+
+        if (length > 0 && std::isdigit(base_id[length - 1])) {
+            if (length < max_size - 1) {
+                base_id += '_';
+                ++length;
+            }
+            else {
+                while (length > 0 && std::isdigit(base_id[length -1]))
+                    --length;
+                base_id.erase(length);
+            }
+        }
+
+        unsigned count = 0;
+
+        while (true)
+        {
+            std::string postfix =
+                boost::lexical_cast<std::string>(count++);
+
+            if ((base_id.size() + postfix.size()) > max_size) {
+                // The id is now too long, so reduce the length and
+                // start again.
+
+                // Would need a lot of ids to get this far....
+                if (length == 0) throw std::runtime_error("Too many ids");
+
+                // Trim a character.
+                --length;
+
+                // Trim any trailing digits.
+                while (length > 0 && std::isdigit(base_id[length -1]))
+                    --length;
+
+                base_id.erase(length);
+                count = 0;
+            }
+            else {
+                // Try to reserve this id.
+                std::string generated_id = parent_id + base_id + postfix;
+
+                if (chosen_ids.emplace(generated_id, p).second) {
+                    return generated_id;
+                }
+            }
+        }
+    }
+
+    //
+    // replace_ids
+    //
+    // Return a copy of the xml with all the placeholders replaced by
+    // generated_ids.
+    //
+
+    struct replace_ids_callback : xml_processor::callback
+    {
+        id_state const& state;
+        std::vector<std::string> const* ids;
+        boost::string_ref::const_iterator source_pos;
+        std::string result;
+
+        replace_ids_callback(id_state const& state,
+                std::vector<std::string> const* ids)
+          : state(state),
+            ids(ids),
+            source_pos(),
+            result()
+        {}
+
+        void start(boost::string_ref xml)
+        {
+            source_pos = xml.begin();
+        }
+
+        void id_value(boost::string_ref value)
+        {
+            if (id_placeholder const* p = state.get_placeholder(value))
+            {
+                boost::string_ref id = ids ?
+                    (*ids)[p->index] : p->unresolved_id;
+
+                result.append(source_pos, value.begin());
+                result.append(id.begin(), id.end());
+                source_pos = value.end();
+            }
+        }
+
+        void finish(boost::string_ref xml)
+        {
+            result.append(source_pos, xml.end());
+            source_pos = xml.end();
+        }
+    };
+
+    std::string replace_ids(id_state const& state, boost::string_ref xml,
+            std::vector<std::string> const* ids)
+    {
+        xml_processor processor;
+        replace_ids_callback callback(state, ids);
+        processor.parse(xml, callback);
+        return callback.result;
+    }
+
+    //
+    // normalize_id
+    //
+    // Normalizes generated ids.
+    //
+
+    std::string normalize_id(boost::string_ref src_id)
+    {
+        return normalize_id(src_id, max_size);
+    }
+
+    std::string normalize_id(boost::string_ref src_id, std::size_t size)
+    {
+        std::string id(src_id.begin(), src_id.end());
+
+        std::size_t src = 0;
+        std::size_t dst = 0;
+
+        while (src < id.length() && id[src] == '_') {
+            ++src;
+        }
+
+        if (src == id.length()) {
+            id = "_";
+        }
+        else {
+            while (src < id.length() && dst < size) {
+                if (id[src] == '_') {
+                    do {
+                        ++src;
+                    } while(src < id.length() && id[src] == '_');
+
+                    if (src < id.length()) id[dst++] = '_';
+                }
+                else {
+                    id[dst++] = id[src++];
+                }
+            }
+
+            id.erase(dst);
+        }
+
+        return id;
+    }
+}
Modified: branches/release/tools/quickbook/src/id_manager.cpp
==============================================================================
--- branches/release/tools/quickbook/src/id_manager.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/id_manager.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -1,229 +1,90 @@
 /*=============================================================================
-    Copyright (c) 2011 Daniel James
+    Copyright (c) 2011, 2013 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)
 =============================================================================*/
 
-#include "id_manager.hpp"
+#include "id_manager_impl.hpp"
 #include "utils.hpp"
-#include <boost/utility/string_ref.hpp>
 #include <boost/make_shared.hpp>
-#include <boost/unordered_map.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/range/algorithm.hpp>
-#include <boost/foreach.hpp>
-#include <deque>
-#include <vector>
 #include <cctype>
 
 namespace quickbook
 {
-    // TODO: This should possibly try to make ids are generated:
-    // http://www.w3.org/TR/REC-xml/#NT-NameStartChar
-
-    //
-    // Forward declarations
-    //
-
-    struct id_placeholder;
-    struct id_data;
-    std::string replace_ids(id_state& state, boost::string_ref xml,
-            bool use_resolved_ids = true);
-    std::string process_ids(id_state&, boost::string_ref);
-
-    static const std::size_t max_size = 32;
-
-    //
-    // id_placeholder
-    //
-
-    struct id_placeholder
-    {
-        enum state_enum { child, unresolved, resolved, generated };
-
-        unsigned index;         // The poisition in the placeholder deque.
-        state_enum generation_state;
-                                // Placeholder's position in generation
-                                // process.
-        std::string unresolved_id;
-                                // The id that would be generated without any
-                                // duplicate handling.
-        std::string id;         // The id so far.
-        id_placeholder* parent; // Placeholder of the parent id.
-                                // Only when generation_state == child
-        id_category category;
-        unsigned num_dots;      // Number of dots in the id.
-                                // Normally equal to the section level.
-        unsigned order;         // Order of the placeholders in the generated
-                                // xml. Stored because it can be slightly
-                                // different to the order they're generated
-                                // in. e.g. for nested tables the cells
-                                // are processed before the title id.
-                                // Only set when processing ids.
-        id_data* data;          // Assigned data shared by duplicate ids
-                                // used to detect them. Only when
-                                // generation_state == resolved
-
-        id_placeholder(
-                unsigned index,
-                boost::string_ref id,
-                id_category category,
-                id_placeholder* parent_ = 0)
-          : index(index),
-            generation_state(parent_ ? child : unresolved),
-            unresolved_id(parent_ ?
-                parent_->unresolved_id + '.' + detail::to_s(id) :
-                detail::to_s(id)),
-            id(id.begin(), id.end()),
-            parent(parent_),
-            category(category),
-            num_dots(boost::range::count(id, '.') +
-                (parent_ ? parent_->num_dots + 1 : 0)),
-            order(0),
-            data(0)
-        {
-        }
-
-        std::string to_string()
-        {
-            return '$' + boost::lexical_cast<std::string>(index);
-        }
-
-        bool check_state() const
-        {
-            return (
-                (generation_state == child) == (bool) parent &&
-                (generation_state == resolved) == (bool) data);
-        }
-
-        bool check_state(state_enum s) const
-        {
-            return s == generation_state && check_state();
-        }
-    };
-
-    //
-    // id_state
-    //
-
-    struct file_info;
-    struct doc_info;
-    struct section_info;
-
-    struct id_state
-    {
-        boost::shared_ptr<file_info> current_file;
-        std::deque<id_placeholder> placeholders;
-
-        // Placeholder methods
-
-        id_placeholder* add_placeholder(
-                boost::string_ref, id_category, id_placeholder* parent = 0);
-
-        id_placeholder* get_placeholder(boost::string_ref);
-
-        // Events
-
-        id_placeholder* start_file(
-                unsigned compatibility_version,
-                bool document_root,
-                boost::string_ref include_doc_id,
-                boost::string_ref id,
-                value const& title);
-
-        void end_file();
-
-        id_placeholder* add_id(
-                boost::string_ref id,
-                id_category category);
-        id_placeholder* old_style_id(
-            boost::string_ref id,
-            id_category category);
-        id_placeholder* begin_section(
-                boost::string_ref id,
-                id_category category);
-        void end_section();
-
-private:
-        id_placeholder* add_id_to_section(
-                boost::string_ref id,
-                id_category category,
-                boost::shared_ptr<section_info> const& section);
-        id_placeholder* create_new_section(
-                boost::string_ref id,
-                id_category category);
-
-        void switch_section(id_placeholder*);
-        void reswitch_sections(boost::shared_ptr<section_info> const&,
-            boost::shared_ptr<section_info> const&);
-        void restore_section();
-    };
-
     struct file_info
     {
-        boost::shared_ptr<file_info> parent;
-        boost::shared_ptr<doc_info> document;
+        boost::shared_ptr<file_info> const parent;
+        boost::shared_ptr<doc_info> const document;
 
-        bool document_root; // !parent || document != parent->document
-        unsigned compatibility_version;
-        boost::shared_ptr<section_info> switched_section;
-        id_placeholder* original_placeholder;
+        bool const document_root; // !parent || document != parent->document
+        unsigned const compatibility_version;
+        unsigned const depth;
+        unsigned const override_depth;
+        id_placeholder const* const override_id;
 
         // The 1.1-1.5 document id would actually change per file due to
         // explicit ids in includes and a bug which would sometimes use the
         // document title instead of the id.
-        std::string doc_id_1_1;
+        std::string const doc_id_1_1;
 
+        // Constructor for files that aren't the root of a document.
         file_info(boost::shared_ptr<file_info> const& parent,
-                unsigned compatibility_version) :
+                unsigned compatibility_version,
+                boost::string_ref doc_id_1_1,
+                id_placeholder const* override_id) :
             parent(parent), document(parent->document), document_root(false),
             compatibility_version(compatibility_version),
-            switched_section(), original_placeholder()
+            depth(parent->depth + 1),
+            override_depth(override_id ? depth : parent->override_depth),
+            override_id(override_id ? override_id : parent->override_id),
+            doc_id_1_1(detail::to_s(doc_id_1_1))
         {}
 
+        // Constructor for files that are the root of a document.
         file_info(boost::shared_ptr<file_info> const& parent,
                 boost::shared_ptr<doc_info> const& document,
-                unsigned compatibility_version) :
+                unsigned compatibility_version,
+                boost::string_ref doc_id_1_1) :
             parent(parent), document(document), document_root(true),
             compatibility_version(compatibility_version),
-            switched_section(), original_placeholder()
+            depth(0), override_depth(0), override_id(0),
+            doc_id_1_1(detail::to_s(doc_id_1_1))
         {}
     };
 
     struct doc_info
     {
         boost::shared_ptr<section_info> current_section;
+
+        // Note: these are mutable to remain bug compatible with old versions
+        // of quickbook. They would set these values at the start of new files
+        // and sections and then not restore them at the end.
         std::string last_title_1_1;
         std::string section_id_1_1;
-
-        doc_info() :
-            current_section(), last_title_1_1(), section_id_1_1()
-        {}
     };
 
     struct section_info
     {
-        boost::shared_ptr<section_info> parent;
-        unsigned compatibility_version;
-        unsigned level;
-        std::string id_1_1;
-        id_placeholder* placeholder_1_6;
+        boost::shared_ptr<section_info> const parent;
+        unsigned const compatibility_version;
+        unsigned const file_depth;
+        unsigned const level;
+        std::string const id_1_1;
+        id_placeholder const* const placeholder_1_6;
 
         section_info(boost::shared_ptr<section_info> const& parent,
-                unsigned compatibility_version, boost::string_ref id) :
-            parent(parent), compatibility_version(compatibility_version),
+                file_info const* current_file, boost::string_ref id,
+                boost::string_ref id_1_1, id_placeholder const* placeholder_1_6) :
+            parent(parent),
+            compatibility_version(current_file->compatibility_version),
+            file_depth(current_file->depth),
             level(parent ? parent->level + 1 : 1),
-            id_1_1(), placeholder_1_6(0)
-        {
-            if (parent && compatibility_version < 106u) {
-                id_1_1 = parent->id_1_1;
-                if (!id_1_1.empty() && !id.empty())
-                    id_1_1 += ".";
-                id_1_1.append(id.begin(), id.end());
-            }
-        }
+            id_1_1(detail::to_s(id_1_1)),
+            placeholder_1_6(placeholder_1_6) {}
     };
 
     //
@@ -295,13 +156,14 @@
     std::string id_manager::replace_placeholders_with_unresolved_ids(
             boost::string_ref xml) const
     {
-        return replace_ids(*state, xml, false);
+        return replace_ids(*state, xml);
     }
 
     std::string id_manager::replace_placeholders(boost::string_ref xml) const
     {
         assert(!state->current_file);
-        return process_ids(*state, xml);
+        std::vector<std::string> ids = generate_ids(*state, xml);
+        return replace_ids(*state, xml, &ids);
     }
 
     unsigned id_manager::compatibility_version() const
@@ -310,70 +172,45 @@
     }
 
     //
-    // normalize_id
-    //
-    // Normalizes generated ids.
+    // id_placeholder
     //
 
-    namespace
+    id_placeholder::id_placeholder(
+            unsigned index,
+            boost::string_ref id,
+            id_category category,
+            id_placeholder const* parent_)
+      : index(index),
+        unresolved_id(parent_ ?
+            parent_->unresolved_id + '.' + detail::to_s(id) :
+            detail::to_s(id)),
+        id(id.begin(), id.end()),
+        parent(parent_),
+        category(category),
+        num_dots(boost::range::count(id, '.') +
+            (parent_ ? parent_->num_dots + 1 : 0))
     {
-        std::string normalize_id(
-                boost::string_ref src_id,
-                std::size_t prefix = 0,
-                std::size_t size = max_size)
-        {
-            std::string id(src_id.begin(), src_id.end());
-
-            std::size_t src = prefix;
-            std::size_t dst = prefix;
-            size += prefix;
-
-            if (src >= id.length()) {
-                return id;
-            }
-
-            while (src < id.length() && id[src] == '_') {
-                ++src;
-            }
-
-            if (src >= id.length()) {
-                id += '_';
-                return id;
-            }
-
-            while (src < id.length() && dst < size) {
-                if (id[src] == '_') {
-                    do {
-                        ++src;
-                    } while(src < id.length() && id[src] == '_');
-
-                    if (src < id.length()) id[dst++] = '_';
-                }
-                else {
-                    id[dst++] = id[src++];
-                }
-            }
-
-            id.erase(dst);
+    }
 
-            return id;
-        }
+    std::string id_placeholder::to_string() const
+    {
+        return '$' + boost::lexical_cast<std::string>(index);
     }
 
     //
     // id_state
     //
 
-    id_placeholder* id_state::add_placeholder(
+    id_placeholder const* id_state::add_placeholder(
             boost::string_ref id, id_category category,
-            id_placeholder* parent)
+            id_placeholder const* parent)
     {
         placeholders.push_back(id_placeholder(
             placeholders.size(), id, category, parent));
         return &placeholders.back();
     }
 
-    id_placeholder* id_state::get_placeholder(boost::string_ref value)
+    id_placeholder const* id_state::get_placeholder(boost::string_ref value) const
     {
         // If this isn't a placeholder id.
         if (value.size() <= 1 || *value.begin() != '$')
@@ -385,68 +222,26 @@
         return &placeholders.at(index);
     }
 
-    void id_state::switch_section(id_placeholder* p)
-    {
-        assert(!current_file->original_placeholder);
-        current_file->switched_section = current_file->document->current_section;
-        current_file->original_placeholder = current_file->switched_section->placeholder_1_6;
-        current_file->switched_section->placeholder_1_6 = p;
-    }
-
-    void id_state::reswitch_sections(
-        boost::shared_ptr<section_info> const& popped_section,
-        boost::shared_ptr<section_info> const& parent_section)
-    {
-        boost::shared_ptr<file_info> file = current_file;
-        boost::shared_ptr<file_info> first_switched_file;
-
-        for (;;) {
-            if (file->switched_section == popped_section)
-            {
-                first_switched_file = file;
-                file->switched_section = parent_section;
-            }
-            
-            if (file->document_root) break;
-            file = file->parent;
-        }
-        
-        if (first_switched_file) {
-            first_switched_file->original_placeholder =
-                parent_section->placeholder_1_6;
-            parent_section->placeholder_1_6 =
-                popped_section->placeholder_1_6;
-        }
-    }
-
-    void id_state::restore_section()
+    id_placeholder const* id_state::get_id_placeholder(
+            boost::shared_ptr<section_info> const& section) const
     {
-        if (current_file->original_placeholder) {
-            current_file->switched_section->placeholder_1_6 =
-                current_file->original_placeholder;        
-        }
+        return !section ? 0 :
+            section->file_depth < current_file->override_depth ?
+                current_file->override_id : section->placeholder_1_6;
     }
 
-    id_placeholder* id_state::start_file(
+    id_placeholder const* id_state::start_file(
             unsigned compatibility_version,
             bool document_root,
             boost::string_ref include_doc_id,
             boost::string_ref id,
             value const& title)
     {
-        // Create new file
-
         boost::shared_ptr<file_info> parent = current_file;
+        assert(parent || document_root);
 
-        if (document_root) {
-            current_file = boost::make_shared<file_info>(parent,
-                    boost::make_shared<doc_info>(),
-                    compatibility_version);
-        }
-        else {
-            current_file =
-                boost::make_shared<file_info>(parent, compatibility_version);
-        }
+        boost::shared_ptr<doc_info> document =
+            document_root ? boost::make_shared<doc_info>() : parent->document;
 
         // Choose specified id to use. Prefer 'include_doc_id' (the id
         // specified in an 'include' element) unless backwards compatibility
@@ -456,32 +251,39 @@
 
         if (document_root ||
             compatibility_version >= 106u ||
-            (parent && parent->compatibility_version >= 106u)) {
+            parent->compatibility_version >= 106u)
+        {
             initial_doc_id = !include_doc_id.empty() ? include_doc_id : id;
         }
         else {
             initial_doc_id = !id.empty() ? id : include_doc_id;
         }
 
-        // Set variables used for backwards compatible id generation.
-        // They're a bit odd because of old bugs.
+        // Work out this file's doc_id for older versions of quickbook.
+        // A bug meant that this need to be done per file, not per
+        // document.
 
-        if (document_root || compatibility_version < 106u) {
-            // Note: this is done for older versions even if docinfo is
-            // otherwise ignored.
+        std::string doc_id_1_1;
 
+        if (document_root || compatibility_version < 106u) {
             if (title.check())
-                current_file->document->last_title_1_1 =
-                    detail::to_s(title.get_quickbook());
+                document->last_title_1_1 = detail::to_s(title.get_quickbook());
 
-            current_file->doc_id_1_1 = !initial_doc_id.empty() ? detail::to_s(initial_doc_id) :
-                detail::make_identifier(current_file->document->last_title_1_1);
+            doc_id_1_1 = !initial_doc_id.empty() ? detail::to_s(initial_doc_id) :
+                detail::make_identifier(document->last_title_1_1);
         }
         else if (parent) {
-            current_file->doc_id_1_1 = parent->doc_id_1_1;
+            doc_id_1_1 = parent->doc_id_1_1;
         }
 
         if (document_root) {
+            // Create new file
+
+            current_file = boost::make_shared<file_info>(parent,
+                    document, compatibility_version, doc_id_1_1);
+
+            // Create a section for the new document.
+
             if (!initial_doc_id.empty()) {
                 return create_new_section(id, id_category::explicit_section_id);
             }
@@ -498,28 +300,41 @@
             }
         }
         else {
-            // If an id was set for the file, then switch the current section
-            // with a new section with this id. This will be maintained in
-            // 'end_section' if the current section ends, and then the original
-            // section restored in 'end_file'
-
-            if (compatibility_version >= 106u && !initial_doc_id.empty()) {
-                switch_section(add_id_to_section(initial_doc_id,
-                    id_category::explicit_section_id,
-                    boost::shared_ptr<section_info>()));
+            // If an id was set for the file, then the file overrides the
+            // current section's id with this id.
+            //
+            // Don't do this for document_root as it will create a section
+            // for the document.
+            //
+            // Don't do this for older versions, as they use a different
+            // backwards compatible mechanism to handle file ids.
+
+            id_placeholder const* override_id = 0;
+
+            if (!initial_doc_id.empty() && compatibility_version >= 106u)
+            {
+                boost::shared_ptr<section_info> null_section;
+
+                override_id = add_id_to_section(initial_doc_id,
+                    id_category::explicit_section_id, null_section);
             }
 
+            // Create new file
+
+            current_file =
+                boost::make_shared<file_info>(parent, compatibility_version,
+                        doc_id_1_1, override_id);
+
             return 0;
         }
     }
 
     void id_state::end_file()
     {
-        restore_section();
         current_file = current_file->parent;
     }
 
-    id_placeholder* id_state::add_id(
+    id_placeholder const* id_state::add_id(
             boost::string_ref id,
             id_category category)
     {
@@ -527,7 +342,7 @@
             current_file->document->current_section);
     }
 
-    id_placeholder* id_state::add_id_to_section(
+    id_placeholder const* id_state::add_id_to_section(
             boost::string_ref id,
             id_category category,
             boost::shared_ptr<section_info> const& section)
@@ -542,27 +357,27 @@
             id_part = normalize_id(id);
         }
 
+        id_placeholder const* placeholder_1_6 = get_id_placeholder(section);
+
         if(!section || section->compatibility_version >= 106u) {
-            return add_placeholder(id_part, category,
-                section ? section->placeholder_1_6 : 0);
+            return add_placeholder(id_part, category, placeholder_1_6);
         }
         else {
             std::string const& qualified_id = section->id_1_1;
 
             std::string new_id;
-            if (!section->placeholder_1_6)
+            if (!placeholder_1_6)
                 new_id = current_file->doc_id_1_1;
             if (!new_id.empty() && !qualified_id.empty()) new_id += '.';
             new_id += qualified_id;
             if (!new_id.empty() && !id_part.empty()) new_id += '.';
             new_id += id_part;
 
-            return add_placeholder(new_id, category,
-                section->placeholder_1_6);
+            return add_placeholder(new_id, category, placeholder_1_6);
         }
     }
 
-    id_placeholder* id_state::old_style_id(
+    id_placeholder const* id_state::old_style_id(
         boost::string_ref id,
         id_category category)
     {
@@ -572,7 +387,7 @@
                 add_id(id, category);
     }
 
-    id_placeholder* id_state::begin_section(
+    id_placeholder const* id_state::begin_section(
             boost::string_ref id,
             id_category category)
     {
@@ -580,564 +395,62 @@
         return create_new_section(id, category);
     }
 
-    id_placeholder* id_state::create_new_section(
+    id_placeholder const* id_state::create_new_section(
             boost::string_ref id,
             id_category category)
     {
         boost::shared_ptr<section_info> parent =
             current_file->document->current_section;
 
-        boost::shared_ptr<section_info> new_section =
-            boost::make_shared<section_info>(parent,
-                current_file->compatibility_version, id);
+        id_placeholder const* p = 0;
+        id_placeholder const* placeholder_1_6 = 0;
 
-        id_placeholder* p;
+        std::string id_1_1;
 
-        if (new_section->compatibility_version >= 106u) {
-            p = add_id_to_section(id, category, parent);
-            new_section->placeholder_1_6 = p;
+        if (parent && current_file->compatibility_version < 106u) {
+            id_1_1 = parent->id_1_1;
+            if (!id_1_1.empty() && !id.empty())
+                id_1_1 += ".";
+            id_1_1.append(id.begin(), id.end());
         }
-        else if (new_section->compatibility_version >= 103u) {
-            if (parent)
-                new_section->placeholder_1_6 = parent->placeholder_1_6;
+
+        if (current_file->compatibility_version >= 106u) {
+            p = placeholder_1_6 = add_id_to_section(id, category, parent);
+        }
+        else if (current_file->compatibility_version >= 103u) {
+            placeholder_1_6 = get_id_placeholder(parent);
 
             std::string new_id;
-            if (!new_section->placeholder_1_6) {
+            if (!placeholder_1_6) {
                 new_id = current_file->doc_id_1_1;
-                if (!new_section->id_1_1.empty()) new_id += '.';
+                if (!id_1_1.empty()) new_id += '.';
             }
-            new_id += new_section->id_1_1;
+            new_id += id_1_1;
 
-            p = add_placeholder(new_id, category,
-                new_section->placeholder_1_6);
+            p = add_placeholder(new_id, category, placeholder_1_6);
         }
         else {
-            if (parent)
-                new_section->placeholder_1_6 = parent->placeholder_1_6;
+            placeholder_1_6 = get_id_placeholder(parent);
 
             std::string new_id;
-            if (parent && !new_section->placeholder_1_6)
+            if (parent && !placeholder_1_6)
                 new_id = current_file->doc_id_1_1 + '.';
 
             new_id += detail::to_s(id);
 
-            p = add_placeholder(new_id, category,
-                new_section->placeholder_1_6);
+            p = add_placeholder(new_id, category, placeholder_1_6);
         }
 
-        current_file->document->current_section = new_section;
+        current_file->document->current_section =
+            boost::make_shared<section_info>(parent,
+                current_file.get(), id, id_1_1, placeholder_1_6);
         
         return p;
     }
 
     void id_state::end_section()
     {
-        boost::shared_ptr<section_info> popped_section =
-            current_file->document->current_section;
-        current_file->document->current_section = popped_section->parent;
-
-        reswitch_sections(popped_section, popped_section->parent);
-    }
-
-    //
-    // Xml subset parser used for finding id values.
-    //
-    // I originally tried to integrate this into the post processor
-    // but that proved tricky. Alternatively it could use a proper
-    // xml parser, but I want this to be able to survive badly
-    // marked up escapes.
-    //
-
-    struct xml_processor
-    {
-        xml_processor();
-
-        std::vector<std::string> id_attributes;
-
-        struct callback {
-            virtual void start(boost::string_ref) {}
-            virtual void id_value(boost::string_ref) {}
-            virtual void finish(boost::string_ref) {}
-            virtual ~callback() {}
-        };
-
-        void parse(boost::string_ref, callback&);
-    };
-
-    namespace
-    {
-        char const* id_attributes_[] =
-        {
-            "id",
-            "linkend",
-            "linkends",
-            "arearefs"
-        };
-    }
-
-    xml_processor::xml_processor()
-    {
-        static int const n_id_attributes = sizeof(id_attributes_)/sizeof(char const*);
-        for (int i = 0; i != n_id_attributes; ++i)
-        {
-            id_attributes.push_back(id_attributes_[i]);
-        }
-
-        boost::sort(id_attributes);
-    }
-
-    template <typename Iterator>
-    bool read(Iterator& it, Iterator end, char const* text)
-    {
-        for(Iterator it2 = it;; ++it2, ++text) {
-            if (!*text) {
-                it = it2;
-                return true;
-            }
-
-            if (it2 == end || *it2 != *text)
-                return false;
-        }
-    }
-
-    template <typename Iterator>
-    void read_past(Iterator& it, Iterator end, char const* text)
-    {
-        while (it != end && !read(it, end, text)) ++it;
-    }
-
-    bool find_char(char const* text, char c)
-    {
-        for(;*text; ++text)
-            if (c == *text) return true;
-        return false;
-    }
-
-    template <typename Iterator>
-    void read_some_of(Iterator& it, Iterator end, char const* text)
-    {
-        while(it != end && find_char(text, *it)) ++it;
-    }
-
-    template <typename Iterator>
-    void read_to_one_of(Iterator& it, Iterator end, char const* text)
-    {
-        while(it != end && !find_char(text, *it)) ++it;
-    }
-
-    void xml_processor::parse(boost::string_ref source, callback& c)
-    {
-        typedef boost::string_ref::const_iterator iterator;
-
-        c.start(source);
-
-        iterator it = source.begin(), end = source.end();
-
-        for(;;)
-        {
-            read_past(it, end, "<");
-            if (it == end) break;
-
-            if (read(it, end, "!--quickbook-escape-prefix-->"))
-            {
-                read_past(it, end, "<!--quickbook-escape-postfix-->");
-                continue;
-            }
-
-            switch(*it)
-            {
-            case '?':
-                ++it;
-                read_past(it, end, "?>");
-                break;
-
-            case '!':
-                if (read(it, end, "!--"))
-                    read_past(it, end, "-->");
-                else
-                    read_past(it, end, ">");
-                break;
-
-            default:
-                if ((*it >= 'a' && *it <= 'z') ||
-                        (*it >= 'A' && *it <= 'Z') ||
-                        *it == '_' || *it == ':')
-                {
-                    read_to_one_of(it, end, " \t\n\r>");
-
-                    for (;;) {
-                        read_some_of(it, end, " \t\n\r");
-                        iterator name_start = it;
-                        read_to_one_of(it, end, "= \t\n\r>");
-                        if (it == end || *it == '>') break;
-                        boost::string_ref name(name_start, it - name_start);
-                        ++it;
-
-                        read_some_of(it, end, "= \t\n\r");
-                        if (it == end || (*it != '"' && *it != '\'')) break;
-
-                        char delim = *it;
-                        ++it;
-
-                        iterator value_start = it;
-
-                        it = std::find(it, end, delim);
-                        if (it == end) break;
-                        boost::string_ref value(value_start, it - value_start);
-                        ++it;
-
-                        if (boost::find(id_attributes, detail::to_s(name))
-                                != id_attributes.end())
-                        {
-                            c.id_value(value);
-                        }
-                    }
-                }
-                else
-                {
-                    read_past(it, end, ">");
-                }
-            }
-        }
-
-        c.finish(source);
-    }
-
-    //
-    // process_ids
-    //
-
-    //
-    // Data used for generating placeholders that have duplicates.
-    //
-
-    struct id_generation_data
-    {
-        id_generation_data(boost::string_ref src_id)
-          : child_start(src_id.rfind('.') + 1),
-            id(normalize_id(src_id, child_start, max_size - 1)),
-                // 'max_size - 1' leaves a character to append
-                // a number.
-            count(0)
-        {
-            if (std::isdigit(id[id.length() - 1]))
-            {
-                if (child_length() < max_size - 1)
-                    id += '_';
-                else
-                    reduce_id();
-            }
-        }
-
-        void reduce_id()
-        {
-            assert(id.length() > child_start);
-            std::size_t length = id.length() - 1;
-            while(length > child_start && std::isdigit(id[length - 1])) --length;
-            id.erase(length);
-            count = 0;
-        }
-
-        std::size_t child_length() const
-        {
-            return id.length() - child_start;
-        }
-
-        std::size_t child_start;
-        std::string id;
-        int count;
-    };
-
-    // Created for all desired ids, either when resolving an id or due to
-    // generating a new id to avoid duplicates.
-    struct id_data
-    {
-        id_data()
-          : category(id_category::numbered),
-            used(false),
-            generation_data()
-        {}
-
-        void update_category(id_category c)
-        {
-            if (c.c > category.c) category = c;
-        }
-
-        id_category category;   // The highest priority category of the
-                                // placeholders that want to use this id.
-        bool used;              // Whether this id has been used.
-        boost::shared_ptr<id_generation_data> generation_data;
-                                // If a duplicates are found, this is
-                                // created to generate new ids.
-                                //
-                                // Many to one relationship, because truncation
-                                // can lead to different ids contending for the
-                                // same id prefix.
-    };
-
-    typedef boost::unordered_map<std::string, id_data> allocated_ids;
-    typedef std::vector<id_placeholder*> placeholder_index;
-
-    placeholder_index index_placeholders(id_state&, boost::string_ref xml);
-    void resolve_id(id_placeholder&, allocated_ids&);
-    void generate_id(id_placeholder&, allocated_ids&);
-
-    std::string process_ids(id_state& state, boost::string_ref xml)
-    {
-        placeholder_index placeholders = index_placeholders(state, xml);
-
-        typedef std::vector<id_placeholder*>::iterator iterator;
-
-        iterator it = placeholders.begin(),
-            end = placeholders.end();
-
-        // Placeholder ids are processed in blocks of ids with
-        // an equal number of dots.
-        while (it != end) {
-            unsigned num_dots = (*it)->num_dots;
-
-            // ids can't clash with ids at a different num_dots, so
-            // this only needs to track the id generation data
-            // for a single num_dots at a time.
-            allocated_ids ids;
-
-            iterator it2 = it;
-            do {
-                resolve_id(**it2++, ids);
-            } while(it2 != end && (*it2)->num_dots == num_dots);
-
-            do {
-                generate_id(**it++, ids);
-            } while(it != it2);
-        }
-
-        return replace_ids(state, xml);
-    }
-
-    //
-    // index_placeholders
-    //
-    // Create a sorted index of the placeholders, in order
-    // to make numbering duplicates easy. A total order.
-    //
-
-    struct placeholder_compare
-    {
-        bool operator()(id_placeholder* x, id_placeholder* y) const
-        {
-            bool x_explicit = x->category.c >= id_category::explicit_id;
-            bool y_explicit = y->category.c >= id_category::explicit_id;
-
-            return
-                x->num_dots < y->num_dots ? true :
-                x->num_dots > y->num_dots ? false :
-                x_explicit > y_explicit ? true :
-                x_explicit < y_explicit ? false :
-                x->order < y->order;
-        }
-    };
-
-    struct number_placeholders_callback : xml_processor::callback
-    {
-        id_state& state;
-        unsigned count;
-
-        number_placeholders_callback(id_state& state)
-          : state(state),
-            count(0)
-        {}
-
-        void id_value(boost::string_ref value)
-        {
-            id_placeholder* p = state.get_placeholder(value);
-            number(p);
-        }
-
-        void number(id_placeholder* p)
-        {
-            if (p && !p->order) {
-                number(p->parent);
-                p->order = ++count;
-            }
-        }
-    };
-
-    placeholder_index index_placeholders(
-            id_state& state,
-            boost::string_ref xml)
-    {
-        xml_processor processor;
-        number_placeholders_callback callback(state);
-        processor.parse(xml, callback);
-
-        placeholder_index sorted_placeholders;
-        sorted_placeholders.reserve(state.placeholders.size());
-        BOOST_FOREACH(id_placeholder& p, state.placeholders)
-            if (p.order) sorted_placeholders.push_back(&p);
-        boost::sort(sorted_placeholders, placeholder_compare());
-
-        return sorted_placeholders;
-    }
-
-    //
-    // resolve_id
-    //
-    // Convert child ids to full ids, and add to the
-    // allocated ids (although not yet set in stone because
-    // there might be duplicates).
-    //
-    // Note that the parent ids has to be generated before resolving
-    // the child id.
-    //
-
-    void resolve_id(id_placeholder& p, allocated_ids& ids)
-    {
-        if (p.generation_state == id_placeholder::child)
-        {
-            assert(p.check_state());
-
-            assert(p.parent->check_state(id_placeholder::generated));
-
-            p.id = p.parent->id + "." + p.id;
-            p.generation_state = id_placeholder::unresolved;
-            p.parent = 0;
-        }
-
-        assert(p.check_state(id_placeholder::unresolved));
-
-        id_data& data = ids.emplace(p.id, id_data()).first->second;
-        data.update_category(p.category);
-
-        p.data = &data;
-        p.generation_state = id_placeholder::resolved;
-    }
-
-    //
-    // generate_id
-    //
-    // Finally generate the final id.
-    //
-
-    void register_generation_data(id_placeholder&, allocated_ids&);
-
-    void generate_id(id_placeholder& p, allocated_ids& ids)
-    {
-        assert(p.check_state(id_placeholder::resolved));
-
-        // If the placeholder id is available, then update data
-        // and return.
-        if (p.category == p.data->category && !p.data->used &&
-            p.category.c != id_category::numbered)
-        {
-            p.data->used = true;
-            p.generation_state = id_placeholder::generated;
-            p.data = 0;
-            return;
-        }
-
-        if (!p.data->generation_data)
-        {
-            p.data->generation_data =
-                boost::make_shared<id_generation_data>(p.id);
-            register_generation_data(p, ids);
-        }
-
-        // Loop until an available id is found.
-        for(;;)
-        {
-            id_generation_data& generation_data = *p.data->generation_data;
-
-            std::string postfix =
-                boost::lexical_cast<std::string>(generation_data.count++);
-
-            if (generation_data.child_length() + postfix.length() > max_size) {
-                // The resulting id is too long, so move to a shorter id.
-                generation_data.reduce_id();
-                register_generation_data(p, ids);
-            }
-            else {
-                std::string id = generation_data.id + postfix;
-
-                if (ids.find(id) == ids.end()) {
-                    p.id.swap(id);
-                    p.generation_state = id_placeholder::generated;
-                    p.data = 0;
-                    return;
-                }
-            }
-        }
-    }
-
-    // Every time the generation id is changed, this is called to
-    // check if that id is already in use.
-    void register_generation_data(id_placeholder& p, allocated_ids& ids)
-    {
-        std::string const& id = p.data->generation_data->id;
-
-        id_data& new_data = ids.emplace(id, id_data()).first->second;
-
-        // If there is already generation_data for the new id then use that.
-        // Otherwise use the placeholder's existing generation_data.
-        if (new_data.generation_data)
-            p.data->generation_data = new_data.generation_data;
-        else
-            new_data.generation_data = p.data->generation_data;
-    }
-
-    //
-    // replace_ids
-    //
-    // Return a copy of the xml with all the placeholders replaced by
-    // generated_ids.
-    //
-
-    struct replace_ids_callback : xml_processor::callback
-    {
-        id_state& state;
-        bool use_resolved_ids;
-        boost::string_ref::const_iterator source_pos;
-        std::string result;
-
-        replace_ids_callback(id_state& state, bool resolved)
-          : state(state),
-            use_resolved_ids(resolved),
-            source_pos(),
-            result()
-        {}
-
-        void start(boost::string_ref xml)
-        {
-            source_pos = xml.begin();
-        }
-
-        void id_value(boost::string_ref value)
-        {
-            if (id_placeholder* p = state.get_placeholder(value))
-            {
-                assert(!use_resolved_ids ||
-                    p->check_state(id_placeholder::generated));
-                boost::string_ref id = use_resolved_ids ?
-                    p->id : p->unresolved_id;
-
-                result.append(source_pos, value.begin());
-                result.append(id.begin(), id.end());
-                source_pos = value.end();
-            }
-        }
-
-        void finish(boost::string_ref xml)
-        {
-            result.append(source_pos, xml.end());
-            source_pos = xml.end();
-        }
-    };
-
-    std::string replace_ids(id_state& state, boost::string_ref xml,
-            bool use_unresolved_ids)
-    {
-        xml_processor processor;
-        replace_ids_callback callback(state, use_unresolved_ids);
-        processor.parse(xml, callback);
-        return callback.result;
+        current_file->document->current_section =
+            current_file->document->current_section->parent;
     }
 }
Modified: branches/release/tools/quickbook/src/id_manager.hpp
==============================================================================
--- branches/release/tools/quickbook/src/id_manager.hpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/id_manager.hpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -45,7 +45,6 @@
     };
 
     struct id_state;
-    struct section_manager;
 
     struct id_manager
     {
Copied: branches/release/tools/quickbook/src/id_manager_impl.hpp (from r85368, trunk/tools/quickbook/src/id_manager_impl.hpp)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/src/id_manager_impl.hpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/src/id_manager_impl.hpp)
@@ -0,0 +1,144 @@
+/*=============================================================================
+    Copyright (c) 2011-2013 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)
+=============================================================================*/
+
+#if !defined(BOOST_QUICKBOOK_ID_MANAGER_IMPL_HPP)
+#define BOOST_QUICKBOOK_ID_MANAGER_IMPL_HPP
+
+#include "id_manager.hpp"
+#include "utils.hpp"
+#include <boost/utility/string_ref.hpp>
+#include <boost/shared_ptr.hpp>
+#include <deque>
+#include <string>
+#include <vector>
+
+namespace quickbook
+{
+    //
+    // id_placeholder
+    //
+    // When generating the xml, quickbook can't allocate the identifiers until
+    // the end, so it stores in the intermedia xml a placeholder string,
+    // e.g. id="$1". This represents one of these placeholders.
+    //
+
+    struct id_placeholder
+    {
+        unsigned index;         // The index in id_state::placeholders.
+                                // Use for the dollar identifiers in
+                                // intermediate xml.
+        std::string unresolved_id;
+                                // The id that would be generated
+                                // without any duplicate handling.
+                                // Used for generating old style header anchors.
+        std::string id;         // The node id.
+        id_placeholder const* parent;
+                                // Placeholder of the parent id.
+        id_category category;
+        unsigned num_dots;      // Number of dots in the id.
+                                // Normally equal to the section level
+                                // but not when an explicit id contains
+                                // dots.
+
+        id_placeholder(unsigned index, boost::string_ref id,
+                id_category category, id_placeholder const* parent_);
+
+        std::string to_string() const;
+    };
+
+    //
+    // id_state
+    //
+    // Contains all the data tracked by the id_manager.
+    //
+
+    struct file_info;
+    struct doc_info;
+    struct section_info;
+
+    struct id_state
+    {
+        boost::shared_ptr<file_info> current_file;
+        std::deque<id_placeholder> placeholders;
+
+        // Placeholder methods
+
+        id_placeholder const* add_placeholder(boost::string_ref, id_category,
+            id_placeholder const* parent = 0);
+
+        id_placeholder const* get_placeholder(boost::string_ref) const;
+
+        id_placeholder const* get_id_placeholder(
+                boost::shared_ptr<section_info> const& section) const;
+
+        // Events
+
+        id_placeholder const* start_file(
+                unsigned compatibility_version,
+                bool document_root,
+                boost::string_ref include_doc_id,
+                boost::string_ref id,
+                value const& title);
+
+        void end_file();
+
+        id_placeholder const* add_id(
+                boost::string_ref id,
+                id_category category);
+        id_placeholder const* old_style_id(
+            boost::string_ref id,
+            id_category category);
+        id_placeholder const* begin_section(
+                boost::string_ref id,
+                id_category category);
+        void end_section();
+
+    private:
+        id_placeholder const* add_id_to_section(
+                boost::string_ref id,
+                id_category category,
+                boost::shared_ptr<section_info> const& section);
+        id_placeholder const* create_new_section(
+                boost::string_ref id,
+                id_category category);
+    };
+
+    std::string replace_ids(id_state const& state, boost::string_ref xml,
+            std::vector<std::string> const* = 0);
+    std::vector<std::string> generate_ids(id_state const&, boost::string_ref);
+
+    std::string normalize_id(boost::string_ref src_id);
+    std::string normalize_id(boost::string_ref src_id, std::size_t);
+
+    //
+    // Xml subset parser used for finding id values.
+    //
+    // I originally tried to integrate this into the post processor
+    // but that proved tricky. Alternatively it could use a proper
+    // xml parser, but I want this to be able to survive badly
+    // marked up escapes.
+    //
+
+    struct xml_processor
+    {
+        xml_processor();
+
+        std::vector<std::string> id_attributes;
+
+        struct callback {
+            virtual void start(boost::string_ref) {}
+            virtual void id_value(boost::string_ref) {}
+            virtual void finish(boost::string_ref) {}
+            virtual ~callback() {}
+        };
+
+        void parse(boost::string_ref, callback&);
+    };
+}
+
+#endif
Copied: branches/release/tools/quickbook/src/id_xml.cpp (from r85368, trunk/tools/quickbook/src/id_xml.cpp)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/src/id_xml.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/src/id_xml.cpp)
@@ -0,0 +1,153 @@
+/*=============================================================================
+    Copyright (c) 2011-2013 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)
+=============================================================================*/
+
+#include "id_manager_impl.hpp"
+#include "utils.hpp"
+#include <boost/range/algorithm.hpp>
+
+namespace quickbook
+{
+    namespace
+    {
+        char const* id_attributes_[] =
+        {
+            "id",
+            "linkend",
+            "linkends",
+            "arearefs"
+        };
+    }
+
+    xml_processor::xml_processor()
+    {
+        static int const n_id_attributes = sizeof(id_attributes_)/sizeof(char const*);
+        for (int i = 0; i != n_id_attributes; ++i)
+        {
+            id_attributes.push_back(id_attributes_[i]);
+        }
+
+        boost::sort(id_attributes);
+    }
+
+    template <typename Iterator>
+    bool read(Iterator& it, Iterator end, char const* text)
+    {
+        for(Iterator it2 = it;; ++it2, ++text) {
+            if (!*text) {
+                it = it2;
+                return true;
+            }
+
+            if (it2 == end || *it2 != *text)
+                return false;
+        }
+    }
+
+    template <typename Iterator>
+    void read_past(Iterator& it, Iterator end, char const* text)
+    {
+        while (it != end && !read(it, end, text)) ++it;
+    }
+
+    bool find_char(char const* text, char c)
+    {
+        for(;*text; ++text)
+            if (c == *text) return true;
+        return false;
+    }
+
+    template <typename Iterator>
+    void read_some_of(Iterator& it, Iterator end, char const* text)
+    {
+        while(it != end && find_char(text, *it)) ++it;
+    }
+
+    template <typename Iterator>
+    void read_to_one_of(Iterator& it, Iterator end, char const* text)
+    {
+        while(it != end && !find_char(text, *it)) ++it;
+    }
+
+    void xml_processor::parse(boost::string_ref source, callback& c)
+    {
+        typedef boost::string_ref::const_iterator iterator;
+
+        c.start(source);
+
+        iterator it = source.begin(), end = source.end();
+
+        for(;;)
+        {
+            read_past(it, end, "<");
+            if (it == end) break;
+
+            if (read(it, end, "!--quickbook-escape-prefix-->"))
+            {
+                read_past(it, end, "<!--quickbook-escape-postfix-->");
+                continue;
+            }
+
+            switch(*it)
+            {
+            case '?':
+                ++it;
+                read_past(it, end, "?>");
+                break;
+
+            case '!':
+                if (read(it, end, "!--"))
+                    read_past(it, end, "-->");
+                else
+                    read_past(it, end, ">");
+                break;
+
+            default:
+                if ((*it >= 'a' && *it <= 'z') ||
+                        (*it >= 'A' && *it <= 'Z') ||
+                        *it == '_' || *it == ':')
+                {
+                    read_to_one_of(it, end, " \t\n\r>");
+
+                    for (;;) {
+                        read_some_of(it, end, " \t\n\r");
+                        iterator name_start = it;
+                        read_to_one_of(it, end, "= \t\n\r>");
+                        if (it == end || *it == '>') break;
+                        boost::string_ref name(name_start, it - name_start);
+                        ++it;
+
+                        read_some_of(it, end, "= \t\n\r");
+                        if (it == end || (*it != '"' && *it != '\'')) break;
+
+                        char delim = *it;
+                        ++it;
+
+                        iterator value_start = it;
+
+                        it = std::find(it, end, delim);
+                        if (it == end) break;
+                        boost::string_ref value(value_start, it - value_start);
+                        ++it;
+
+                        if (boost::find(id_attributes, detail::to_s(name))
+                                != id_attributes.end())
+                        {
+                            c.id_value(value);
+                        }
+                    }
+                }
+                else
+                {
+                    read_past(it, end, ">");
+                }
+            }
+        }
+
+        c.finish(source);
+    }
+}
Modified: branches/release/tools/quickbook/src/main_grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/main_grammar.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/main_grammar.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -33,8 +33,15 @@
     namespace cl = boost::spirit::classic;
 
     struct list_stack_item {
-        bool root; // Is this the root of the context
-                   // (e.g. top, template, table cell etc.)
+        // Is this the root of the context
+        // (e.g. top, template, table cell etc.)
+        enum list_item_type {
+            syntactic_list,   // In a list marked up '*' or '#'
+            top_level,        // At the top level of a parse
+                              // (might be a template body)
+            nested_block      // Nested in a block element.
+        } type;
+
         unsigned int indent;  // Indent of list marker
                               // (or paragraph if not in a list)
         unsigned int indent2; // Indent of paragraph
@@ -46,11 +53,11 @@
         //   * List item
         //     |indent2 
 
-        list_stack_item() :
-            root(true), indent(0), indent2(0), mark('\0') {}
+        list_stack_item(list_item_type r) :
+            type(r), indent(0), indent2(0), mark('\0') {}
 
         list_stack_item(char mark, unsigned int indent, unsigned int indent2) :
-            root(false), indent(indent), indent2(indent2), mark(mark)
+            type(syntactic_list), indent(indent), indent2(indent2), mark(mark)
         {}
 
     };
@@ -82,6 +89,7 @@
         // Local actions
 
         void start_blocks_impl(parse_iterator first, parse_iterator last);
+        void start_nested_blocks_impl(parse_iterator first, parse_iterator last);
         void end_blocks_impl(parse_iterator first, parse_iterator last);
         void check_indentation_impl(parse_iterator first, parse_iterator last);
         void check_code_block_impl(parse_iterator first, parse_iterator last);
@@ -94,8 +102,8 @@
         // Local members
 
         cl::rule<scanner>
-                        top_level, indent_check,
-                        paragraph_separator,
+                        template_phrase, top_level, indent_check,
+                        paragraph_separator, inside_paragraph,
                         code, code_line, blank_line, hr,
                         inline_code, skip_inline_code,
                         template_,
@@ -112,36 +120,27 @@
                         skip_escape
                         ;
 
-        struct simple_markup_closure
-            : cl::closure<simple_markup_closure, char>
-        {
-            member1 mark;
-        };
-
-        struct block_item_closure : cl::closure<block_item_closure, bool>
-        {
-            member1 still_in_block;
-        };
-
-        struct context_closure : cl::closure<context_closure, element_info::context>
+        struct block_context_closure : cl::closure<block_context_closure,
+            element_info::context>
         {
-            member1 context;
+            member1 is_block;
         };
 
-        cl::rule<scanner, simple_markup_closure::context_t> simple_markup;
-        cl::rule<scanner> simple_markup_end;
+        cl::rule<scanner> simple_markup, simple_markup_end;
 
-        cl::rule<scanner, block_item_closure::context_t> paragraph;
-        cl::rule<scanner, context_closure::context_t> paragraph_item;
-        cl::rule<scanner, block_item_closure::context_t> list;
-        cl::rule<scanner, context_closure::context_t> list_item;
-        cl::rule<scanner, context_closure::context_t> common;
-        cl::rule<scanner, context_closure::context_t> element;
+        cl::rule<scanner> paragraph;
+        cl::rule<scanner> list;
+        cl::rule<scanner, block_context_closure::context_t> syntactic_block_item;
+        cl::rule<scanner> common;
+        cl::rule<scanner> element;
 
         // state
         std::stack<list_stack_item> list_stack;
         unsigned int list_indent;
         bool no_eols;
+        element_info::context context;
+        char mark; // Simple markup's deliminator
+        bool still_in_block; // Inside a syntatic block
 
         // transitory state
         block_types::values block_type;
@@ -158,31 +157,36 @@
             : list_stack()
             , list_indent(0)
             , no_eols(true)
+            , context(element_info::in_top_level)
+            , mark('\0')
             , state_(state)
             {}
     };
 
     struct process_element_impl : scoped_action_base {
         process_element_impl(main_grammar_local& l)
-            : l(l) {}
+            : l(l), element_context_error_(false) {}
 
         bool start()
         {
-            if (!(l.info.type & l.element.context()) ||
-                    qbk_version_n < l.info.qbk_version)
+            // This element doesn't exist in the current language version.
+            if (qbk_version_n < l.info.qbk_version)
                 return false;
 
-            info_ = l.info;
-
-            if (!l.list_stack.empty() && !l.list_stack.top().root &&
-                    info_.type == element_info::block)
+            // The element is not allowed in this context.
+            if (!(l.info.type & l.context))
             {
-                // If in a list and the element is a block, end the list.
-                list_item_action list_item(l.state_);
-                list_item();
-                l.clear_stack();
+                if (qbk_version_n < 107u) {
+                    return false;
+                }
+                else {
+                    element_context_error_ = true;
+                }
             }
-            else if (info_.type != element_info::phrase &&
+
+            info_ = l.info;
+
+            if (info_.type != element_info::phrase &&
                     info_.type != element_info::maybe_block)
             {
                 paragraph_action para(l.state_);
@@ -205,12 +209,27 @@
         template <typename ResultT, typename ScannerT>
         bool result(ResultT result, ScannerT const& scan)
         {
-            if (result || info_.type & element_info::in_phrase)
-                return result;
-
-            error_action error(l.state_);
-            error(scan.first, scan.first);
-            return true;
+            if (element_context_error_) {
+                error_message_action error(l.state_,
+                        "Element not allowed in this context.");
+                error(scan.first, scan.first);
+                return true;
+            }
+            else if (result) {
+                return true;
+            }
+            else if (qbk_version_n < 107u &&
+                    info_.type & element_info::in_phrase) {
+                // Old versions of quickbook had a soft fail
+                // for unparsed phrase elements.
+                return false;
+            }
+            else {
+                // Parse error in body.
+                error_action error(l.state_);
+                error(scan.first, scan.first);
+                return true;
+            }
         }
 
         void success(parse_iterator, parse_iterator) { l.element_type = info_.type; }
@@ -224,37 +243,52 @@
         main_grammar_local& l;
         element_info info_;
         std::string saved_source_mode_;
+        bool element_context_error_;
+    };
+
+    struct in_list_impl {
+        main_grammar_local& l;
+
+        in_list_impl(main_grammar_local& l) :
+            l(l) {}
+
+        bool operator()() const {
+            return !l.list_stack.empty() &&
+                l.list_stack.top().type == list_stack_item::syntactic_list;
+        }
     };
 
-    struct set_no_eols_scoped : scoped_action_base
+    template <typename T, typename M>
+    struct set_scoped_value_impl : scoped_action_base
     {
-        set_no_eols_scoped(main_grammar_local& l)
-            : l(l) {}
+        typedef M T::*member_ptr;
 
-        bool start() {
-            saved_no_eols = l.no_eols;
-            l.no_eols = false;
+        set_scoped_value_impl(T& l, member_ptr ptr)
+            : l(l), ptr(ptr), saved_value() {}
+
+        bool start(M const& value) {
+            saved_value = l.*ptr;
+            l.*ptr = value;
 
             return true;
         }
 
         void cleanup() {
-            l.no_eols = saved_no_eols;
+            l.*ptr = saved_value;
         }
 
-        main_grammar_local& l;
-        bool saved_no_eols;
+        T& l;
+        member_ptr ptr;
+        M saved_value;
     };
 
-    struct in_list_impl {
-        main_grammar_local& l;
-
-        in_list_impl(main_grammar_local& l) :
-            l(l) {}
+    template <typename T, typename M>
+    struct set_scoped_value : scoped_parser<set_scoped_value_impl<T, M> >
+    {
+        typedef set_scoped_value_impl<T, M> impl;
 
-        bool operator()() const {
-            return !l.list_stack.top().root;
-        }
+        set_scoped_value(T& l, typename impl::member_ptr ptr) :
+            scoped_parser<impl>(impl(l, ptr)) {}
     };
 
     ////////////////////////////////////////////////////////////////////////////
@@ -266,19 +300,18 @@
             new main_grammar_local(state));
 
         // Global Actions
-        element_action element(state);
-        paragraph_action paragraph(state);
-        list_item_action list_item(state);
+        quickbook::element_action element_action(state);
+        quickbook::paragraph_action paragraph_action(state);
 
         phrase_end_action end_phrase(state);
-        raw_char_action raw_char(state.phrase);
-        plain_char_action plain_char(state.phrase, state);
-        escape_unicode_action escape_unicode(state.phrase, state);
+        raw_char_action raw_char(state);
+        plain_char_action plain_char(state);
+        escape_unicode_action escape_unicode(state);
 
-        simple_phrase_action simple_markup(state.phrase, state);
+        simple_phrase_action simple_markup(state);
 
-        break_action break_(state.phrase, state);
-        do_macro_action do_macro(state.phrase, state);
+        break_action break_(state);
+        do_macro_action do_macro(state);
 
         error_action error(state);
         element_id_warning_action element_id_warning(state);
@@ -287,14 +320,23 @@
 
         // Local Actions
         scoped_parser<process_element_impl> process_element(local);
-        scoped_parser<set_no_eols_scoped> scoped_no_eols(local);
         in_list_impl in_list(local);
+
+        set_scoped_value<main_grammar_local, bool> scoped_no_eols(
+                local, &main_grammar_local::no_eols);
+        set_scoped_value<main_grammar_local, element_info::context> scoped_context(
+                local, &main_grammar_local::context);
+        set_scoped_value<main_grammar_local, bool> scoped_still_in_block(
+                local, &main_grammar_local::still_in_block);
+
         member_action<main_grammar_local> check_indentation(local,
             &main_grammar_local::check_indentation_impl);
         member_action<main_grammar_local> check_code_block(local,
             &main_grammar_local::check_code_block_impl);
         member_action<main_grammar_local> start_blocks(local,
             &main_grammar_local::start_blocks_impl);
+        member_action<main_grammar_local> start_nested_blocks(local,
+            &main_grammar_local::start_nested_blocks_impl);
         member_action<main_grammar_local> end_blocks(local,
             &main_grammar_local::end_blocks_impl);
 
@@ -309,9 +351,9 @@
         // brackets.
         nested_phrase =
             state.values.save()
-            [   *( ~cl::eps_p(']')
-                >>  local.common(element_info::in_phrase)
-                )
+            [
+                scoped_context(element_info::in_phrase)
+                [*(~cl::eps_p(']') >> local.common)]
             ]
             ;
 
@@ -319,9 +361,9 @@
         // by a paragraph end.
         paragraph_phrase =
             state.values.save()
-            [   *( ~cl::eps_p(phrase_end)
-                >>  local.common(element_info::in_phrase)
-                )
+            [
+                scoped_context(element_info::in_phrase)
+                [*(~cl::eps_p(phrase_end) >> local.common)]
             ]
             ;
 
@@ -329,9 +371,9 @@
         // elements.
         extended_phrase =
             state.values.save()
-            [   *( ~cl::eps_p(phrase_end)
-                >>  local.common(element_info::in_conditional)
-                )
+            [
+                scoped_context(element_info::in_conditional)
+                [*(~cl::eps_p(phrase_end) >> local.common)]
             ]
             ;
 
@@ -341,28 +383,65 @@
         // is part of the paragraph that contains it.
         inline_phrase =
             state.values.save()
-            [   *local.common(element_info::in_phrase)
+            [   qbk_ver(107u)
+            >>  local.template_phrase
+            |   qbk_ver(0, 107u)
+            >>  scoped_context(element_info::in_phrase)
+                [*local.common]
             ]
             ;
 
         table_title_phrase =
             state.values.save()
-            [   *( ~cl::eps_p(space >> (']' | '[' >> space >> '['))
-                >>  local.common(element_info::in_phrase)
-                )
+            [
+                scoped_context(element_info::in_phrase)
+                [   *( ~cl::eps_p(space >> (']' | '[' >> space >> '['))
+                    >>  local.common
+                    )
+                ]
             ]
             ;
 
         inside_preformatted =
-            scoped_no_eols()
+            scoped_no_eols(false)
             [   paragraph_phrase
             ]
             ;
 
+        // Phrase templates can contain block tags, but can't contain
+        // syntatic blocks.
+        local.template_phrase =
+                scoped_context(element_info::in_top_level)
+                [   *(  (local.paragraph_separator >> space >> cl::anychar_p)
+                                        [error("Paragraph in phrase template.")]
+                    |   local.common
+                    )
+                ]
+            ;
+
         // Top level blocks
         block_start =
-                (*eol)                          [start_blocks]
-            >>  (*local.top_level)              [end_blocks]
+                (*eol)                  [start_blocks]
+            >>  (   *(  local.top_level
+                    >>  !(  qbk_ver(106u)
+                        >>  cl::ch_p(']')
+                        >>  cl::eps_p   [error("Mismatched close bracket")]
+                        )
+                    )
+                )                       [end_blocks]
+            ;
+
+        // Blocks contains within an element, e.g. a table cell or a footnote.
+        inside_paragraph =
+            state.values.save()
+            [   cl::eps_p               [start_nested_blocks]
+            >>  (   qbk_ver(107u)
+                >>  (*eol)
+                >>  (*local.top_level)
+                |   qbk_ver(0, 107u)
+                >>  local.inside_paragraph
+                )                       [end_blocks]
+            ]
             ;
 
         local.top_level =
@@ -387,40 +466,49 @@
             ;
 
         local.paragraph =
-                cl::eps_p                       [local.paragraph.still_in_block = true]
-            >>  local.paragraph_item(element_info::only_contextual_block)
-            >>  *(  cl::eps_p(local.paragraph.still_in_block)
-                >>  local.paragraph_item(element_info::only_block)
-                )
-            >>  cl::eps_p                       [paragraph]
-            ;
-
-        local.paragraph_item =
-                local.element(local.paragraph_item.context)
-            >>  !eol                            [local.paragraph.still_in_block = false]
-            |   local.paragraph_separator       [local.paragraph.still_in_block = false]
-            |   local.common(element_info::in_phrase)
+                                                // Usually superfluous call
+                                                // for paragraphs in lists.
+            cl::eps_p                           [paragraph_action]
+        >>  scoped_context(element_info::in_top_level)
+            [   scoped_still_in_block(true)
+                [   local.syntactic_block_item(element_info::is_contextual_block)
+                >>  *(  cl::eps_p(ph::var(local.still_in_block))
+                    >>  local.syntactic_block_item(element_info::is_block)
+                    )
+                ]
+            ]                                   [paragraph_action]
             ;
 
         local.list =
                 *cl::blank_p
             >>  (cl::ch_p('*') | '#')
-            >>  (*cl::blank_p)                  [local.list.still_in_block = true]
-            >>  *(  cl::eps_p(local.list.still_in_block)
-                >>  (   qbk_ver(107u) >> local.list_item(element_info::only_block)
-                    |   qbk_ver(0, 107u) >> local.list_item(element_info::only_list_block)
-                    )
-                )
-                // TODO: This is sometimes called in the wrong place. Currently
-                // harmless.
-            >>  cl::eps_p                       [list_item]
+            >>  (*cl::blank_p)
+            >>  scoped_context(element_info::in_list_block)
+                [   scoped_still_in_block(true)
+                    [   *(  cl::eps_p(ph::var(local.still_in_block))
+                        >>  local.syntactic_block_item(element_info::is_block)
+                        )
+                    ]
+                ]
             ;
 
-        local.list_item =
-                local.element(local.list_item.context)
-            >>  !(qbk_ver(0, 106u) >> eol)      [local.list.still_in_block = false]
-            |   local.paragraph_separator       [local.list.still_in_block = false]
-            |   local.common(element_info::in_phrase)
+        local.syntactic_block_item =
+                local.paragraph_separator       [ph::var(local.still_in_block) = false]
+            |   (cl::eps_p(~cl::ch_p(']')) | qbk_ver(0, 107u))
+                                                [ph::var(local.element_type) = element_info::nothing]
+            >>  local.common
+                // If the element is a block, then a newline will end the
+                // current syntactic block.
+                // Note that we don't do this for lists in 1.6 to avoid messing
+                // up on nested block elements.
+            >>  !(  cl::eps_p(in_list) >> qbk_ver(106u)
+                |   cl::eps_p
+                    (
+                        ph::static_cast_<int>(local.syntactic_block_item.is_block) &
+                        ph::static_cast_<int>(ph::var(local.element_type))
+                    )
+                >>  eol                         [ph::var(local.still_in_block) = false]
+                )
             ;
 
         local.paragraph_separator =
@@ -436,13 +524,13 @@
             ;
 
         // Blocks contains within an element, e.g. a table cell or a footnote.
-        inside_paragraph =
-            state.values.save()
-            [   *(  local.paragraph_separator   [paragraph]
+        local.inside_paragraph =
+            scoped_context(element_info::in_nested_block)
+            [   *(  local.paragraph_separator   [paragraph_action]
                 |   ~cl::eps_p(']')
-                >>  local.common(element_info::in_nested_block)
+                >>  local.common
                 )
-            ]                                   [paragraph]
+            ]                                   [paragraph_action]
             ;
 
         local.hr =
@@ -454,7 +542,7 @@
                     >>  *(line_comment | (cl::anychar_p - (cl::eol_p | "[/")))
                     )
                 >>  *eol
-                ]                               [element]
+                ]                               [element_action]
             ;
 
         local.element
@@ -469,7 +557,7 @@
                     [   cl::lazy_p(*ph::var(local.info.rule))
                     >>  space
                     >>  ']'
-                    ]                           [element]
+                    ]                           [element_action]
                 ]
             ;
 
@@ -478,7 +566,7 @@
             [(  local.code_line
                 >> *(*local.blank_line >> local.code_line)
             )                                   [state.values.entry(ph::arg1, ph::arg2)]
-            ]                                   [element]
+            ]                                   [element_action]
             >> *eol
             ;
 
@@ -497,7 +585,7 @@
 
         local.common =
                 local.macro
-            |   local.element(local.common.context)
+            |   local.element
             |   local.template_
             |   local.break_
             |   local.code_block
@@ -512,6 +600,8 @@
 
         skip_entity =
                 '['
+                // For escaped templates:
+            >>  !(space >> cl::ch_p('`') >> (cl::alpha_p | '_'))
             >>  *(~cl::eps_p(']') >> skip_entity)
             >>  !cl::ch_p(']')
             |   local.skip_code_block
@@ -547,17 +637,31 @@
             (   '['
             >>  space
             >>  state.values.list(template_tags::template_)
-                [   !cl::str_p("`")             [state.values.entry(ph::arg1, ph::arg2, template_tags::escape)]
-                >>  (   cl::eps_p(cl::punct_p)
-                    >>  state.templates.scope   [state.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
-                    |   state.templates.scope   [state.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
+                [   (   cl::str_p('`')
+                    >>  cl::eps_p(cl::punct_p)
+                    >>  state.templates.scope
+                            [state.values.entry(ph::arg1, ph::arg2, template_tags::escape)]
+                            [state.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
+                    >>  !qbk_ver(106u)
+                            [error("Templates with punctuation names can't be escaped in quickbook 1.6+")]
+                    |   cl::str_p('`')
+                    >>  state.templates.scope
+                            [state.values.entry(ph::arg1, ph::arg2, template_tags::escape)]
+                            [state.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
+
+                    |   cl::eps_p(cl::punct_p)
+                    >>  state.templates.scope
+                            [state.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
+
+                    |   state.templates.scope
+                            [state.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
                     >>  cl::eps_p(hard_space)
                     )
                 >>  space
                 >>  !local.template_args
                 >>  ']'
                 ]
-            )                                   [element]
+            )                                   [element_action]
             ;
 
         local.template_args =
@@ -637,7 +741,7 @@
                 ) >> cl::eps_p('`')
             )                                   [state.values.entry(ph::arg1, ph::arg2)]
             >>  '`'
-            ]                                   [element]
+            ]                                   [element_action]
             ;
 
         local.skip_inline_code =
@@ -695,7 +799,7 @@
                             >>  !(*cl::blank_p >> cl::eol_p)
                         )                   [state.values.entry(ph::arg1, ph::arg2)]
                     >>  (*cl::space_p >> "```")
-                    ]                       [element]
+                    ]                       [element_action]
                 |   cl::eps_p               [error("Unfinished code block")]
                 >>  *cl::anychar_p
                 )
@@ -711,18 +815,18 @@
                             >>  !(*cl::blank_p >> cl::eol_p)
                         )                   [state.values.entry(ph::arg1, ph::arg2)]
                     >>  (*cl::space_p >> "``")
-                    ]                       [element]
+                    ]                       [element_action]
                 |   cl::eps_p               [error("Unfinished code block")]
                 >>  *cl::anychar_p
                 )
             ;
 
         local.simple_markup =
-                cl::chset<>("*/_=")             [local.simple_markup.mark = ph::arg1]
+                cl::chset<>("*/_=")             [ph::var(local.mark) = ph::arg1]
             >>  cl::eps_p(cl::graph_p)          // graph_p must follow first mark
             >>  lookback
                 [   cl::anychar_p               // skip back over the markup
-                >>  ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark))
+                >>  ~cl::eps_p(cl::ch_p(boost::ref(local.mark)))
                                                 // first mark not be preceeded by
                                                 // the same character.
                 >>  (cl::space_p | cl::punct_p | cl::end_p)
@@ -736,15 +840,15 @@
                     [
                         cl::eps_p((state.macro & macro_identifier) >> local.simple_markup_end)
                     >>  state.macro       [do_macro]
-                    |   ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark))
+                    |   ~cl::eps_p(cl::ch_p(boost::ref(local.mark)))
                     >>  +(  ~cl::eps_p
-                            (   lookback [~cl::f_ch_p(local.simple_markup.mark)]
+                            (   lookback [~cl::ch_p(boost::ref(local.mark))]
                             >>  local.simple_markup_end
                             )
                         >>  cl::anychar_p   [plain_char]
                         )
                     ]
-                >>  cl::f_ch_p(local.simple_markup.mark)
+                >>  cl::ch_p(boost::ref(local.mark))
                                                 [simple_markup]
                 ]
             ;
@@ -752,8 +856,8 @@
         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))
+                >>  cl::ch_p(boost::ref(local.mark))
+                >>  ~cl::eps_p(cl::ch_p(boost::ref(local.mark)))
                                                 // final mark not be followed by
                                                 // the same character.
                 >>  (cl::space_p | cl::punct_p | cl::end_p)
@@ -779,7 +883,7 @@
                 [   (*(cl::anychar_p - "'''"))  [state.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
                 >>  (   cl::str_p("'''")
                     |   cl::eps_p               [error("Unclosed boostbook escape.")]
-                    )                           [element]
+                    )                           [element_action]
                 ]
             ;
 
@@ -810,7 +914,7 @@
             >>  (*(cl::anychar_p - "'''"))
             >>  (   cl::str_p("'''")
                 |   cl::eps_p                   [error("Unclosed boostbook escape.")]
-                )                               [element]
+                )                               [element_action]
             ;
 
         attribute_value_1_7 =
@@ -850,7 +954,7 @@
                 >>  *cl::space_p
                 )
             >>  cl::end_p
-            ]                                   [element]
+            ]                                   [element_action]
             ;
 
         local.command_line_macro_identifier =
@@ -933,7 +1037,21 @@
 
     void main_grammar_local::start_blocks_impl(parse_iterator, parse_iterator)
     {
-        list_stack.push(list_stack_item());
+        list_stack.push(list_stack_item(list_stack_item::top_level));
+    }
+
+    void main_grammar_local::start_nested_blocks_impl(parse_iterator, parse_iterator)
+    {
+        // If this nested block is part of a list, then tell the
+        // output state.
+        //
+        // TODO: This is a bit dodgy, it would be better if this
+        // was handled when the output state is pushed (currently
+        // in to_value_scoped_action).
+        state_.in_list = state_.explicit_list;
+        state_.explicit_list = false;
+
+        list_stack.push(list_stack_item(list_stack_item::nested_block));
     }
 
     void main_grammar_local::end_blocks_impl(parse_iterator, parse_iterator)
@@ -972,10 +1090,16 @@
             unsigned int new_indent = indent_length(first, last);
 
             if (new_indent > list_stack.top().indent2) {
-                block_type = block_types::code;
+                if (list_stack.top().type != list_stack_item::nested_block) {
+                    block_type = block_types::code;
+                }
+                else {
+                    block_type = block_types::paragraph;
+                }
             }
             else {
-                while (!list_stack.top().root && new_indent < list_stack.top().indent)
+                while (list_stack.top().type == list_stack_item::syntactic_list
+                        && new_indent < list_stack.top().indent)
                 {
                     state_.end_list_item();
                     state_.end_list(list_stack.top().mark);
@@ -983,7 +1107,8 @@
                     list_indent = list_stack.top().indent;
                 }
 
-                if (!list_stack.top().root && new_indent == list_stack.top().indent)
+                if (list_stack.top().type == list_stack_item::syntactic_list
+                        && new_indent == list_stack.top().indent)
                 {
                     // If the paragraph is aligned with the list item's marker,
                     // then end the current list item if that's aligned (or to
@@ -1006,7 +1131,7 @@
                     list_stack_item save = list_stack.top();
                     list_stack.pop();
 
-                    assert(list_stack.top().root ?
+                    assert(list_stack.top().type != list_stack_item::syntactic_list ?
                         new_indent >= list_stack.top().indent :
                         new_indent > list_stack.top().indent);
 
@@ -1023,7 +1148,8 @@
                 block_type = block_types::paragraph;
             }
 
-            if (qbk_version_n == 106u && !list_stack.top().root) {
+            if (qbk_version_n == 106u &&
+                    list_stack.top().type == list_stack_item::syntactic_list) {
                 detail::outerr(state_.current_file, first)
                     << "Nested blocks in lists won't be supported in "
                     << "quickbook 1.6"
@@ -1034,10 +1160,11 @@
         else {
             clear_stack();
 
-            if (last == first)
-                block_type = block_types::paragraph;
-            else
+            if (list_stack.top().type != list_stack_item::nested_block &&
+                    last != first)
                 block_type = block_types::code;
+            else
+                block_type = block_types::paragraph;
         }
     }
 
@@ -1048,12 +1175,14 @@
         unsigned int new_indent2 = indent_length(first, last);
         char mark = *mark_pos;
 
-        if (list_stack.top().root && new_indent > 0) {
+        if (list_stack.top().type == list_stack_item::top_level &&
+                new_indent > 0) {
             block_type = block_types::code;
             return;
         }
 
-        if (list_stack.top().root || new_indent > list_indent) {
+        if (list_stack.top().type != list_stack_item::syntactic_list ||
+                new_indent > list_indent) {
             list_stack.push(list_stack_item(mark, new_indent, new_indent2));
             state_.start_list(mark);
         }
@@ -1063,7 +1192,8 @@
         else {
             // This should never reach root, since the first list
             // has indentation 0.
-            while(!list_stack.top().root && new_indent < list_stack.top().indent)
+            while(list_stack.top().type == list_stack_item::syntactic_list &&
+                    new_indent < list_stack.top().indent)
             {
                 state_.end_list_item();
                 state_.end_list(list_stack.top().mark);
@@ -1090,7 +1220,7 @@
 
     void main_grammar_local::clear_stack()
     {
-        while (!list_stack.top().root) {
+        while (list_stack.top().type == list_stack_item::syntactic_list) {
             state_.end_list_item();
             state_.end_list(list_stack.top().mark);
             list_stack.pop();
Modified: branches/release/tools/quickbook/src/markups.cpp
==============================================================================
--- branches/release/tools/quickbook/src/markups.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/markups.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -26,6 +26,7 @@
         {
             markup init_markups[] = {
                 { block_tags::paragraph, "<para>\n", "</para>\n" },
+                { block_tags::paragraph_in_list, "<simpara>\n", "</simpara>\n" },
                 { block_tags::blurb, "<sidebar role=\"blurb\">\n", "</sidebar>\n" },
                 { block_tags::blockquote, "<blockquote>", "</blockquote>" },
                 { block_tags::preformatted, "<programlisting>", "</programlisting>" },
Modified: branches/release/tools/quickbook/src/phrase_element_grammar.cpp
==============================================================================
--- branches/release/tools/quickbook/src/phrase_element_grammar.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/phrase_element_grammar.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -38,7 +38,7 @@
             new phrase_element_grammar_local);
 
         error_action error(state);
-        raw_char_action raw_char(state.phrase);
+        raw_char_action raw_char(state);
         scoped_parser<cond_phrase_push> scoped_cond_phrase(state);
         scoped_parser<to_value_scoped_action> to_value(state);
 
Modified: branches/release/tools/quickbook/src/quickbook.cpp
==============================================================================
--- branches/release/tools/quickbook/src/quickbook.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/quickbook.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -99,7 +99,7 @@
             parse_iterator pos = info.stop;
             std::string doc_type = pre(state, pos, include_doc_id, nested_file);
 
-            info = cl::parse(info.hit ? info.stop : first, last, state.grammar().block);
+            info = cl::parse(info.hit ? info.stop : first, last, state.grammar().block_start);
 
             post(state, doc_type);
 
Modified: branches/release/tools/quickbook/src/state.cpp
==============================================================================
--- branches/release/tools/quickbook/src/state.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/state.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -39,6 +39,8 @@
         , ids(ids)
         , callouts()
         , callout_depth(0)
+        , dependencies()
+        , explicit_list(false)
 
         , imported(false)
         , macro()
@@ -50,8 +52,11 @@
         , template_depth(0)
         , min_section_level(1)
 
+        , in_list(false)
+        , in_list_save()
         , out(out_)
         , phrase()
+
         , values(¤t_file)
     {
         // add the predefined macros
@@ -69,8 +74,21 @@
     quickbook_grammar& state::grammar() const {
         return *grammar_;
     }
+    
+    void state::push_output() {
+        out.push();
+        phrase.push();
+        in_list_save.push(in_list);
+    }
+
+    void state::pop_output() {
+        phrase.pop();
+        out.pop();
+        in_list = in_list_save.top();
+        in_list_save.pop();
+    }
 
-    file_state::file_state(quickbook::state& state, scope_flags scope)
+    state_save::state_save(quickbook::state& state, scope_flags scope)
         : state(state)
         , scope(scope)
         , qbk_version(qbk_version_n)
@@ -80,17 +98,18 @@
         , xinclude_base(state.xinclude_base)
         , source_mode(state.source_mode)
         , macro()
+        , template_depth(state.template_depth)
+        , min_section_level(state.min_section_level)
     {
         if (scope & scope_macros) macro = state.macro;
         if (scope & scope_templates) state.templates.push();
         if (scope & scope_output) {
-            state.out.push();
-            state.phrase.push();
+            state.push_output();
         }
         state.values.builder.save();
     }
 
-    file_state::~file_state()
+    state_save::~state_save()
     {
         state.values.builder.restore();
         boost::swap(qbk_version_n, qbk_version);
@@ -100,22 +119,10 @@
         boost::swap(state.xinclude_base, xinclude_base);
         boost::swap(state.source_mode, source_mode);
         if (scope & scope_output) {
-            state.out.pop();
-            state.phrase.pop();
+            state.pop_output();
         }
         if (scope & scope_templates) state.templates.pop();
         if (scope & scope_macros) state.macro = macro;
-    }
-
-    template_state::template_state(quickbook::state& state)
-        : file_state(state, file_state::scope_all)
-        , template_depth(state.template_depth)
-        , min_section_level(state.min_section_level)
-    {
-    }
-
-    template_state::~template_state()
-    {
         boost::swap(state.template_depth, template_depth);
         boost::swap(state.min_section_level, min_section_level);
     }
Modified: branches/release/tools/quickbook/src/state.hpp
==============================================================================
--- branches/release/tools/quickbook/src/state.hpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/state.hpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -52,6 +52,7 @@
         value_builder           callouts;           // callouts are global as
         int                     callout_depth;      // they don't nest.
         dependency_tracker      dependencies;
+        bool                    explicit_list;      // set when using a list
 
     // state saved for files and templates.
         bool                    imported;
@@ -68,8 +69,13 @@
         int                     min_section_level;
 
     // output state - scoped by templates and grammar
+        bool                    in_list;        // generating a list
+        std::stack<bool>        in_list_save;   // save the in_list state
+                                                // TODO: Something better...
         collector               out;            // main output stream
         collector               phrase;         // phrase output stream
+
+    // values state - scoped by everything.
         value_parser            values;         // parsed values
 
         quickbook_grammar& grammar() const;
@@ -78,6 +84,9 @@
     // actions
     ///////////////////////////////////////////////////////////////////////////
 
+        void push_output();
+        void pop_output();
+
         void start_list(char mark);
         void end_list(char mark);
         void start_list_item();
Modified: branches/release/tools/quickbook/src/state_save.hpp
==============================================================================
--- branches/release/tools/quickbook/src/state_save.hpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/state_save.hpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -18,7 +18,7 @@
     //
     // Defined in state.cpp
 
-    struct file_state
+    struct state_save
     {
         enum scope_flags {
             scope_none = 0,
@@ -29,8 +29,8 @@
             scope_all = scope_callables + scope_output
         };
 
-        explicit file_state(quickbook::state&, scope_flags);
-        ~file_state();
+        explicit state_save(quickbook::state&, scope_flags);
+        ~state_save();
 
         quickbook::state& state;
         scope_flags scope;
@@ -42,18 +42,11 @@
         fs::path xinclude_base;
         std::string source_mode;
         string_symbols macro;
-    private:
-        file_state(file_state const&);
-        file_state& operator=(file_state const&);
-    };
-
-    struct template_state : file_state
-    {
-        explicit template_state(quickbook::state&);
-        ~template_state();
-
         int template_depth;
         int min_section_level;
+    private:
+        state_save(state_save const&);
+        state_save& operator=(state_save const&);
     };
 }
 
Modified: branches/release/tools/quickbook/src/syntax_highlight.cpp
==============================================================================
--- branches/release/tools/quickbook/src/syntax_highlight.cpp	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/src/syntax_highlight.cpp	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -87,7 +87,6 @@
 
     struct syntax_highlight_actions
     {
-        quickbook::collector out;
         quickbook::state& state;
         do_macro_action do_macro_impl;
 
@@ -96,8 +95,8 @@
         boost::string_ref marked_text;
 
         syntax_highlight_actions(quickbook::state& state, bool is_block) :
-            out(), state(state),
-            do_macro_impl(out, state),
+            state(state),
+            do_macro_impl(state),
             support_callouts(is_block && (qbk_version_n >= 107u ||
                 state.current_file->is_code_snippets)),
             marked_text()
@@ -119,26 +118,26 @@
     void syntax_highlight_actions::span(parse_iterator first,
             parse_iterator last, char const* name)
     {
-        out << "<phrase role=\"" << name << "\">";
+        state.phrase << "<phrase role=\"" << name << "\">";
         while (first != last)
-            detail::print_char(*first++, out.get());
-        out << "</phrase>";
+            detail::print_char(*first++, state.phrase.get());
+        state.phrase << "</phrase>";
     }
 
     void syntax_highlight_actions::span_start(parse_iterator first,
             parse_iterator last, char const* name)
     {
-        out << "<phrase role=\"" << name << "\">";
+        state.phrase << "<phrase role=\"" << name << "\">";
         while (first != last)
-            detail::print_char(*first++, out.get());
+            detail::print_char(*first++, state.phrase.get());
     }
 
     void syntax_highlight_actions::span_end(parse_iterator first,
             parse_iterator last)
     {
         while (first != last)
-            detail::print_char(*first++, out.get());
-        out << "</phrase>";
+            detail::print_char(*first++, state.phrase.get());
+        state.phrase << "</phrase>";
     }
 
     void syntax_highlight_actions::unexpected_char(parse_iterator first,
@@ -152,30 +151,32 @@
             << "\n";
 
         // print out an unexpected character
-        out << "<phrase role=\"error\">";
+        state.phrase << "<phrase role=\"error\">";
         while (first != last)
-            detail::print_char(*first++, out.get());
-        out << "</phrase>";
+            detail::print_char(*first++, state.phrase.get());
+        state.phrase << "</phrase>";
     }
 
     void syntax_highlight_actions::plain_char(parse_iterator first,
             parse_iterator last)
     {
         while (first != last)
-            detail::print_char(*first++, out.get());
+            detail::print_char(*first++, state.phrase.get());
     }
 
     void syntax_highlight_actions::pre_escape_back(parse_iterator,
             parse_iterator)
     {
-        state.phrase.push(); // save the stream
+        state.push_output(); // save the stream
     }
 
     void syntax_highlight_actions::post_escape_back(parse_iterator,
             parse_iterator)
     {
-        out << state.phrase.str();
-        state.phrase.pop(); // restore the stream
+        std::string tmp;
+        state.phrase.swap(tmp);
+        state.pop_output(); // restore the stream
+        state.phrase << tmp;
     }
 
     void syntax_highlight_actions::do_macro(std::string const& v)
@@ -191,7 +192,7 @@
 
     void syntax_highlight_actions::callout(parse_iterator, parse_iterator)
     {
-        out << state.add_callout(qbk_value(state.current_file,
+        state.phrase << state.add_callout(qbk_value(state.current_file,
             marked_text.begin(), marked_text.end()));
         marked_text.clear();
     }
@@ -318,7 +319,7 @@
                         (
                             (
                                 (+(cl::anychar_p - "``") >> cl::eps_p("``"))
-                                & g.phrase
+                                & g.phrase_start
                             )
                             >>  cl::str_p("``")
                         )
@@ -473,7 +474,7 @@
                         (
                             (
                                 (+(cl::anychar_p - "``") >> cl::eps_p("``"))
-                                & g.phrase
+                                & g.phrase_start
                             )
                             >>  cl::str_p("``")
                         )
@@ -595,7 +596,7 @@
                         (
                             (
                                 (+(cl::anychar_p - "``") >> cl::eps_p("``"))
-                                & g.phrase
+                                & g.phrase_start
                             )
                             >>  cl::str_p("``")
                         )
@@ -619,7 +620,7 @@
         syntax_highlight_actions& actions;
     };
 
-    std::string syntax_highlight(
+    void syntax_highlight(
         parse_iterator first,
         parse_iterator last,
         quickbook::state& state,
@@ -648,10 +649,5 @@
         {
             BOOST_ASSERT(0);
         }
-
-        std::string str;
-        syn_actions.out.swap(str);
-        
-        return str;
     }
 }
Modified: branches/release/tools/quickbook/test/Jamfile.v2
==============================================================================
--- branches/release/tools/quickbook/test/Jamfile.v2	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/Jamfile.v2	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -68,21 +68,26 @@
     [ quickbook-test link-1_1 ]
     [ quickbook-test link-1_6 ]
     [ quickbook-test link-1_7 ]
+    [ quickbook-error-test link-1_7-fail ]
     [ quickbook-test list_test-1_5 ]
     [ quickbook-test list_test-1_6 ]
     [ quickbook-error-test list_test-1_6-fail ]
     [ quickbook-test list_test-1_7 ]
+    [ quickbook-error-test list_test-1_7-fail1 ]
     [ quickbook-test macro-1_5 ]
     [ quickbook-test macro-1_6 ]
     [ quickbook-error-test mismatched_brackets-1_1-fail ]
     [ quickbook-test mismatched_brackets1-1_1 ]
     [ quickbook-test mismatched_brackets2-1_1 ]
+    [ quickbook-test mismatched_brackets3-1_1 ]
     [ quickbook-test newline-1_1 ]
     [ quickbook-test para_test-1_5 ]
     [ quickbook-error-test post_process-fail ]
     [ quickbook-test preformatted-1_1 ]
     [ quickbook-test preformatted-1_6 ]
     [ quickbook-test role-1_6 ]
+    [ quickbook-test role-1_7 ]
+    [ quickbook-error-test role-1_7-fail ]
     [ quickbook-test section-1_4 ]
     [ quickbook-test section-1_5-unclosed ]
     [ quickbook-test section-1_5 ]
@@ -92,6 +97,7 @@
     [ quickbook-test table-1_3 ]
     [ quickbook-test table-1_5 ]
     [ quickbook-test table-1_6 ]
+    [ quickbook-test table-1_7 ]
     [ quickbook-error-test template_arguments1-1_1-fail ]
     [ quickbook-error-test template_arguments2-1_1-fail ]
     [ quickbook-error-test template_arguments3-1_1-fail ]
@@ -102,6 +108,10 @@
     [ quickbook-test templates-1_3 ]
     [ quickbook-test templates-1_4 ]
     [ quickbook-test templates-1_5 ]
+    [ quickbook-test templates-1_6 ]
+    [ quickbook-error-test templates-1_6-fail1 ]
+    [ quickbook-test templates-1_7 ]
+    [ quickbook-error-test templates-1_7-fail1 ]
     [ quickbook-test unicode_escape-1_5 ]
     [ quickbook-test unmatched_element-1_5 ]
     [ quickbook-test unmatched_element-1_6 ]
Modified: branches/release/tools/quickbook/test/elements-1_6.gold
==============================================================================
--- branches/release/tools/quickbook/test/elements-1_6.gold	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/elements-1_6.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -5,28 +5,36 @@
   <title>1.6 Elements</title>
   <orderedlist>
     <listitem>
-      <para>
+      <simpara>
         item1
-      </para>
+      </simpara>
     </listitem>
     <listitem>
-      <para>
+      <simpara>
         item2
-      </para>
+      </simpara>
     </listitem>
   </orderedlist>
   <itemizedlist>
     <listitem>
-      <para>
+      <simpara>
         item1
-      </para>
+      </simpara>
     </listitem>
     <listitem>
-      <para>
+      <simpara>
         item2
-      </para>
+      </simpara>
     </listitem>
   </itemizedlist>
+  <orderedlist>
+    <listitem>
+      <simpara>
+        Check that <emphasis role="bold">bold text</emphasis> isn't confused with
+        a list.
+      </simpara>
+    </listitem>
+  </orderedlist>
   <simplesect><title>A <emphasis role="bold">simplesect</emphasis>!</title></simplesect>
 
 </article>
Modified: branches/release/tools/quickbook/test/elements-1_6.quickbook
==============================================================================
--- branches/release/tools/quickbook/test/elements-1_6.quickbook	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/elements-1_6.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -8,6 +8,14 @@
 
 [itemized_list [item1][item2]]
 
+[ordered_list
+    [
+        Check that
+        *bold text*
+        isn't confused with a list.
+    ]
+]
+
 [block'''<simplesect><title>'''A *simplesect*!'''</title>''']
 
-[block'''</simplesect>''']
\ No newline at end of file
+[block'''</simplesect>''']
Modified: branches/release/tools/quickbook/test/include/in_section-1_5.gold
==============================================================================
--- branches/release/tools/quickbook/test/include/in_section-1_5.gold	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/include/in_section-1_5.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -13,6 +13,11 @@
       <bridgehead renderas="sect1" id="include_in_section_include_1.container.inner.h0">
         <phrase id="include_in_section_include_1.container.inner.test2"/><link linkend="include_in_section_include_1.container.inner.test2">Test2</link>
       </bridgehead>
+      <bridgehead renderas="sect4" id="include_in_section_include_1.container.inner.h1">
+        <phrase id="include_in_section_include_1.container.inner.simple_include"/><link
+        linkend="include_in_section_include_1.container.inner.simple_include">Simple
+        include</link>
+      </bridgehead>
     </section>
     <bridgehead renderas="sect1" id="section_include.container.h0">
       <phrase id="section_include.container.test1"/><link linkend="section_include.container.test1">Test1</link>
@@ -22,6 +27,11 @@
       <bridgehead renderas="sect1" id="section_include.container.inner.h0">
         <phrase id="section_include.container.inner.test2"/><link linkend="section_include.container.inner.test2">Test2</link>
       </bridgehead>
+      <bridgehead renderas="sect4" id="include_in_section_include_2.container.inner.h0">
+        <phrase id="include_in_section_include_2.container.inner.simple_include"/><link
+        linkend="include_in_section_include_2.container.inner.simple_include">Simple
+        include</link>
+      </bridgehead>
     </section>
   </section>
   <bridgehead renderas="sect1" id="include_in_section_include_1.h0">
@@ -32,6 +42,10 @@
     <bridgehead renderas="sect1" id="include_in_section_include_1.inner.h0">
       <phrase id="include_in_section_include_1.inner.test2"/><link linkend="include_in_section_include_1.inner.test2">Test2</link>
     </bridgehead>
+    <bridgehead renderas="sect3" id="include_in_section_include_1.inner.h1">
+      <phrase id="include_in_section_include_1.inner.simple_include"/><link linkend="include_in_section_include_1.inner.simple_include">Simple
+      include</link>
+    </bridgehead>
   </section>
   <bridgehead renderas="sect1" id="section_include.h0">
     <phrase id="section_include.test1"/><link linkend="section_include.test1">Test1</link>
@@ -41,6 +55,10 @@
     <bridgehead renderas="sect1" id="section_include.inner.h0">
       <phrase id="section_include.inner.test2"/><link linkend="section_include.inner.test2">Test2</link>
     </bridgehead>
+    <bridgehead renderas="sect3" id="include_in_section_include_2.inner.h0">
+      <phrase id="include_in_section_include_2.inner.simple_include"/><link linkend="include_in_section_include_2.inner.simple_include">Simple
+      include</link>
+    </bridgehead>
   </section>
   <section id="include_in_section_1_5.container2">
     <title><link linkend="include_in_section_1_5.container2">Container2</link></title>
@@ -52,6 +70,11 @@
       <bridgehead renderas="sect1" id="include_in_section_include_1.container2.inner.h0">
         <phrase id="include_in_section_include_1.container2.inner.test2"/><link linkend="include_in_section_include_1.container2.inner.test2">Test2</link>
       </bridgehead>
+      <bridgehead renderas="sect4" id="include_in_section_include_1.container2.inner.h1">
+        <phrase id="include_in_section_include_1.container2.inner.simple_include"/><link
+        linkend="include_in_section_include_1.container2.inner.simple_include">Simple
+        include</link>
+      </bridgehead>
     </section>
     <bridgehead renderas="sect1" id="section_include.container2.h0">
       <phrase id="section_include.container2.test1"/><link linkend="section_include.container2.test1">Test1</link>
@@ -61,6 +84,11 @@
       <bridgehead renderas="sect1" id="section_include.container2.inner.h0">
         <phrase id="section_include.container2.inner.test2"/><link linkend="section_include.container2.inner.test2">Test2</link>
       </bridgehead>
+      <bridgehead renderas="sect4" id="include_in_section_include_2.container2.inner.h0">
+        <phrase id="include_in_section_include_2.container2.inner.simple_include"/><link
+        linkend="include_in_section_include_2.container2.inner.simple_include">Simple
+        include</link>
+      </bridgehead>
     </section>
   </section>
 </article>
Modified: branches/release/tools/quickbook/test/include/in_section-1_6.gold
==============================================================================
--- branches/release/tools/quickbook/test/include/in_section-1_6.gold	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/include/in_section-1_6.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -16,6 +16,10 @@
         <bridgehead renderas="sect1" id="include_in_section_include_1.inner.h0">
           <phrase id="include_in_section_include_1.inner.test2"/><link linkend="include_in_section_include_1.inner.test2">Test2</link>
         </bridgehead>
+        <bridgehead renderas="sect3" id="include_in_section_include_1.inner.h1">
+          <phrase id="include_in_section_include_1.inner.simple_include"/><link linkend="include_in_section_include_1.inner.simple_include">Simple
+          include</link>
+        </bridgehead>
       </section>
     </article>
     <article id="section_include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
@@ -29,6 +33,10 @@
         <bridgehead renderas="sect1" id="section_include.inner.h0">
           <phrase id="section_include.inner.test2"/><link linkend="section_include.inner.test2">Test2</link>
         </bridgehead>
+        <bridgehead renderas="sect3" id="section_include.inner.h1">
+          <phrase id="section_include.inner.simple_include"/><link linkend="section_include.inner.simple_include">Simple
+          include</link>
+        </bridgehead>
       </section>
     </article>
   </section>
@@ -43,6 +51,10 @@
       <bridgehead renderas="sect1" id="include_in_section_include_1_0.inner.h0">
         <phrase id="include_in_section_include_1_0.inner.test2"/><link linkend="include_in_section_include_1_0.inner.test2">Test2</link>
       </bridgehead>
+      <bridgehead renderas="sect3" id="include_in_section_include_1_0.inner.h1">
+        <phrase id="include_in_section_include_1_0.inner.simple_include"/><link linkend="include_in_section_include_1_0.inner.simple_include">Simple
+        include</link>
+      </bridgehead>
     </section>
   </article>
   <article id="section_include0" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
@@ -56,6 +68,10 @@
       <bridgehead renderas="sect1" id="section_include0.inner.h0">
         <phrase id="section_include0.inner.test2"/><link linkend="section_include0.inner.test2">Test2</link>
       </bridgehead>
+      <bridgehead renderas="sect3" id="section_include0.inner.h1">
+        <phrase id="section_include0.inner.simple_include"/><link linkend="section_include0.inner.simple_include">Simple
+        include</link>
+      </bridgehead>
     </section>
   </article>
   <section id="include_in_section_1_6.container2">
@@ -71,6 +87,10 @@
         <bridgehead renderas="sect1" id="include_in_section_include_1_1.inner.h0">
           <phrase id="include_in_section_include_1_1.inner.test2"/><link linkend="include_in_section_include_1_1.inner.test2">Test2</link>
         </bridgehead>
+        <bridgehead renderas="sect3" id="include_in_section_include_1_1.inner.h1">
+          <phrase id="include_in_section_include_1_1.inner.simple_include"/><link
+          linkend="include_in_section_include_1_1.inner.simple_include">Simple include</link>
+        </bridgehead>
       </section>
     </article>
     <article id="section_include1" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
@@ -84,6 +104,10 @@
         <bridgehead renderas="sect1" id="section_include1.inner.h0">
           <phrase id="section_include1.inner.test2"/><link linkend="section_include1.inner.test2">Test2</link>
         </bridgehead>
+        <bridgehead renderas="sect3" id="section_include1.inner.h1">
+          <phrase id="section_include1.inner.simple_include"/><link linkend="section_include1.inner.simple_include">Simple
+          include</link>
+        </bridgehead>
       </section>
     </article>
   </section>
Modified: branches/release/tools/quickbook/test/include/in_section-inc1.quickbook
==============================================================================
--- branches/release/tools/quickbook/test/include/in_section-inc1.quickbook	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/include/in_section-inc1.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -8,4 +8,6 @@
 
 [h1 Test2]
 
-[endsect]
\ No newline at end of file
+[include include-id-inc1.quickbook]
+
+[endsect]
Modified: branches/release/tools/quickbook/test/include/in_section-inc2.quickbook
==============================================================================
--- branches/release/tools/quickbook/test/include/in_section-inc2.quickbook	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/include/in_section-inc2.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -9,4 +9,6 @@
 
 [h1 Test2]
 
-[endsect]
\ No newline at end of file
+[include include-id-inc1.quickbook]
+
+[endsect]
Copied: branches/release/tools/quickbook/test/link-1_7-fail.quickbook (from r85368, trunk/tools/quickbook/test/link-1_7-fail.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/link-1_7-fail.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/link-1_7-fail.quickbook)
@@ -0,0 +1,5 @@
+[article Link fail test
+[quickbook 1.7]
+]
+
+[link something [table]]
Modified: branches/release/tools/quickbook/test/list_test-1_6.gold
==============================================================================
--- branches/release/tools/quickbook/test/list_test-1_6.gold	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/list_test-1_6.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -310,29 +310,29 @@
       </simpara>
     </listitem>
     <listitem>
+      <informaltable frame="all">
+        <tgroup cols="1">
+          <thead>
+            <row>
+              <entry>
+                <para>
+                  Heading
+                </para>
+              </entry>
+            </row>
+          </thead>
+          <tbody>
+            <row>
+              <entry>
+                <para>
+                  Cell
+                </para>
+              </entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </informaltable>
       <simpara>
-        <informaltable frame="all">
-          <tgroup cols="1">
-            <thead>
-              <row>
-                <entry>
-                  <para>
-                    Heading
-                  </para>
-                </entry>
-              </row>
-            </thead>
-            <tbody>
-              <row>
-                <entry>
-                  <para>
-                    Cell
-                  </para>
-                </entry>
-              </row>
-            </tbody>
-          </tgroup>
-        </informaltable>
         Some text.
       </simpara>
     </listitem>
@@ -343,17 +343,17 @@
     </listitem>
     <listitem>
       <simpara>
-        <para>
-          Paragraph cheat 1.
-        </para>
+        Paragraph cheat 1.
+      </simpara>
+      <simpara>
         Paragraph cheat 2.
       </simpara>
     </listitem>
     <listitem>
       <simpara>
-        <para>
-          Paragraph cheat 3.
-        </para>
+        Paragraph cheat 3.
+      </simpara>
+      <simpara>
         Paragraph cheat 4.
       </simpara>
     </listitem>
Copied: branches/release/tools/quickbook/test/list_test-1_7-fail1.quickbook (from r85368, trunk/tools/quickbook/test/list_test-1_7-fail1.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/list_test-1_7-fail1.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/list_test-1_7-fail1.quickbook)
@@ -0,0 +1,9 @@
+[article List Fail Test 1
+[quickbook 1.7]
+]
+
+[section List immediately following markup]
+* One
+* Two
+* Three
+[endsect]
Modified: branches/release/tools/quickbook/test/list_test-1_7.gold
==============================================================================
--- branches/release/tools/quickbook/test/list_test-1_7.gold	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/list_test-1_7.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -310,40 +310,36 @@
       </simpara>
     </listitem>
     <listitem>
-      <simpara>
-        <informaltable frame="all">
-          <tgroup cols="1">
-            <thead>
-              <row>
-                <entry>
-                  <para>
-                    Heading
-                  </para>
-                </entry>
-              </row>
-            </thead>
-            <tbody>
-              <row>
-                <entry>
-                  <para>
-                    Cell
-                  </para>
-                </entry>
-              </row>
-            </tbody>
-          </tgroup>
-        </informaltable>
-      </simpara>
+      <informaltable frame="all">
+        <tgroup cols="1">
+          <thead>
+            <row>
+              <entry>
+                <para>
+                  Heading
+                </para>
+              </entry>
+            </row>
+          </thead>
+          <tbody>
+            <row>
+              <entry>
+                <para>
+                  Cell
+                </para>
+              </entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </informaltable>
     </listitem>
     <listitem>
+      <bridgehead renderas="sect2" id="list_test.h0">
+        <phrase id="list_test.the_heading_for_a_list_item"/><link linkend="list_test.the_heading_for_a_list_item">The
+        heading for a list item</link>
+      </bridgehead>
       <simpara>
-        <bridgehead renderas="sect2" id="list_test.h0">
-          <phrase id="list_test.the_heading_for_a_list_item"/><link linkend="list_test.the_heading_for_a_list_item">The
-          heading for a list item</link>
-        </bridgehead>
-        <para>
-          The content of the list item.
-        </para>
+        The content of the list item.
       </simpara>
     </listitem>
   </itemizedlist>
@@ -406,9 +402,9 @@
       <listitem>
         <simpara>
           A1
-          <para>
-            A2
-          </para>
+        </simpara>
+        <simpara>
+          A2
         </simpara>
       </listitem>
       <listitem>
@@ -418,15 +414,15 @@
             <listitem>
               <simpara>
                 C1
-                <para>
-                  C2
-                </para>
+              </simpara>
+              <simpara>
+                C2
               </simpara>
             </listitem>
           </itemizedlist>
-          <para>
-            B2
-          </para>
+        </simpara>
+        <simpara>
+          B2
         </simpara>
       </listitem>
       <listitem>
@@ -436,18 +432,18 @@
             <listitem>
               <simpara>
                 E1
-                <para>
-                  E2
-                </para>
-                <para>
-                  E3
-                </para>
+              </simpara>
+              <simpara>
+                E2
+              </simpara>
+              <simpara>
+                E3
               </simpara>
             </listitem>
           </itemizedlist>
-          <para>
-            D2
-          </para>
+        </simpara>
+        <simpara>
+          D2
         </simpara>
       </listitem>
     </itemizedlist>
@@ -459,19 +455,19 @@
       <listitem>
         <simpara>
           A
+        </simpara>
 <programlisting><phrase role="identifier">B</phrase>
 </programlisting>
-          <para>
-            C
-          </para>
+        <simpara>
+          C
         </simpara>
       </listitem>
       <listitem>
         <simpara>
           D
+        </simpara>
 <programlisting><phrase role="identifier">E</phrase>
 </programlisting>
-        </simpara>
       </listitem>
       <listitem>
         <simpara>
Copied: branches/release/tools/quickbook/test/mismatched_brackets3-1_1.gold (from r85368, trunk/tools/quickbook/test/mismatched_brackets3-1_1.gold)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/mismatched_brackets3-1_1.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/mismatched_brackets3-1_1.gold)
@@ -0,0 +1,12 @@
+<?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="mismatched_brackets" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+  <title>Mismatched brackets</title>
+  <section id="mismatched_brackets.something">
+    <title>Something</title>
+  </section>
+  <para>
+    ]
+  </para>
+</article>
Copied: branches/release/tools/quickbook/test/mismatched_brackets3-1_1.quickbook (from r85368, trunk/tools/quickbook/test/mismatched_brackets3-1_1.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/mismatched_brackets3-1_1.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/mismatched_brackets3-1_1.quickbook)
@@ -0,0 +1,6 @@
+[article Mismatched brackets]
+
+[section Something]
+
+[endsect]
+]
Copied: branches/release/tools/quickbook/test/role-1_7-fail.quickbook (from r85368, trunk/tools/quickbook/test/role-1_7-fail.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/role-1_7-fail.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/role-1_7-fail.quickbook)
@@ -0,0 +1,5 @@
+[article Quickbook Role Fail Test
+[quickbook 1.7]
+]
+
+[role]
Copied: branches/release/tools/quickbook/test/role-1_7.gold (from r85368, trunk/tools/quickbook/test/role-1_7.gold)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/role-1_7.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/role-1_7.gold)
@@ -0,0 +1,9 @@
+<?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="quickbook_role_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+  <title>Quickbook Role Test</title>
+  <para>
+    <phrase role="keyword">Keyword</phrase> <phrase role="keyword"></phrase>
+  </para>
+</article>
Copied: branches/release/tools/quickbook/test/role-1_7.quickbook (from r85368, trunk/tools/quickbook/test/role-1_7.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/role-1_7.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/role-1_7.quickbook)
@@ -0,0 +1,5 @@
+[article Quickbook Role Test
+[quickbook 1.6]
+]
+
+[role keyword Keyword] [role keyword]
Copied: branches/release/tools/quickbook/test/table-1_7.gold (from r85368, trunk/tools/quickbook/test/table-1_7.gold)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/table-1_7.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/table-1_7.gold)
@@ -0,0 +1,514 @@
+<?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="table_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+  <title>Table 1.7</title>
+  <table frame="all" id="table_tests.table1">
+    <title>Table 1</title>
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              cell
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+  <table frame="all" id="table_tests.table_2">
+    <title>Table 2</title>
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              cell
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+  <informaltable frame="all">
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              cell
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </informaltable>
+  <informaltable frame="all" id="table_tests.table4">
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              cell
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </informaltable>
+  <table frame="all" id="table_tests.table5">
+    <title>-table5-</title>
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              cell
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+  <table frame="all" id="table_tests.title">
+    <title>Title</title>
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              cell
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+  <table frame="all" id="table_tests.title0">
+    <title>Title</title>
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              cell
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+  <table frame="all" id="table_tests.title_containing_a_comment">
+    <title>Title containing a comment</title>
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              cell
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+  <table frame="all" id="table_tests.title1">
+    <title>Title</title>
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              cell
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+  <informaltable frame="all">
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              Cell 1
+            </para>
+          </entry>
+        </row>
+        <row>
+          <entry>
+            <para>
+              Cell 2
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </informaltable>
+  <table frame="all" id="table_tests.title_on_multiple_lines_with_bol">
+    <title>Title on multiple lines with <emphasis role="bold">bold</emphasis> text?</title>
+    <tgroup cols="1">
+      <thead>
+        <row>
+          <entry>
+            <para>
+              Heading
+            </para>
+          </entry>
+        </row>
+      </thead>
+      <tbody>
+        <row>
+          <entry>
+            <para>
+              Cell 1
+            </para>
+          </entry>
+        </row>
+        <row>
+          <entry>
+            <para>
+              Cell 2
+            </para>
+          </entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+  <section id="table_tests.section1">
+    <title><link linkend="table_tests.section1">Section 1</link></title>
+    <table frame="all" id="table_tests.section1.table1">
+      <title>Table 1</title>
+      <tgroup cols="1">
+        <thead>
+          <row>
+            <entry>
+              <para>
+                Heading
+              </para>
+            </entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry>
+              <para>
+                cell
+              </para>
+            </entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+    <table frame="all" id="table_tests.section1.a_b">
+      <title>A & B</title>
+      <tgroup cols="2">
+        <thead>
+          <row>
+            <entry>
+              <para>
+                A
+              </para>
+            </entry>
+            <entry>
+              <para>
+                B
+              </para>
+            </entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry>
+              <para>
+                a
+              </para>
+            </entry>
+            <entry>
+              <para>
+                b
+              </para>
+            </entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+    <table frame="all" id="table_tests.section1.empty_table">
+      <title>Empty Table</title>
+      <tgroup cols="0">
+        <tbody>
+        </tbody>
+      </tgroup>
+    </table>
+    <table frame="all" id="table_tests.section1.table_with_an_empty_cell">
+      <title>Table with an empty cell</title>
+      <tgroup cols="1">
+        <tbody>
+          <row>
+            <entry>
+              <para>
+                x
+              </para>
+            </entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+    <table frame="all" id="table_tests.section1.indentation">
+      <title>Indentation</title>
+      <tgroup cols="2">
+        <thead>
+          <row>
+            <entry>
+              <para>
+                Header 1. Paragraph 1
+              </para>
+              <para>
+                Header 1. Paragraph 2
+              </para>
+            </entry>
+            <entry>
+              <para>
+                Header 2
+              </para>
+            </entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry>
+              <para>
+                Row 1. Cell 1.
+              </para>
+            </entry>
+            <entry>
+              <para>
+                Row 1. Cell 2.
+              </para>
+              <para>
+                Row 1. Cell 2. Paragraph 2.
+              </para>
+            </entry>
+          </row>
+          <row>
+            <entry>
+              <para>
+                Row 2. Cell 1.
+              </para>
+              <itemizedlist>
+                <listitem>
+                  <simpara>
+                    Row 2. Cell 1. List item 1.
+                  </simpara>
+                </listitem>
+                <listitem>
+                  <simpara>
+                    Row 2. Cell 1. List item 2.
+                  </simpara>
+                </listitem>
+              </itemizedlist>
+            </entry>
+            <entry>
+              <para>
+                Row 2. Cell 2.
+              </para>
+              <itemizedlist>
+                <listitem>
+                  <simpara>
+                    Row 2. Cell 2. List item 1.
+                  </simpara>
+                </listitem>
+                <listitem>
+                  <simpara>
+                    Row 2. Cell 2. List item 2.
+                  </simpara>
+                </listitem>
+              </itemizedlist>
+            </entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+    <table frame="all" id="table_tests.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_tests.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_tests.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>
Copied: branches/release/tools/quickbook/test/table-1_7.quickbook (from r85368, trunk/tools/quickbook/test/table-1_7.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/table-1_7.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/table-1_7.quickbook)
@@ -0,0 +1,148 @@
+[article Table 1.7
+    [quickbook 1.7]
+    [id table_tests]
+]
+
+[table:table1 Table 1 [[Heading]][[cell]]]
+
+[table Table 2
+    [[Heading]]
+    [[cell]]
+]
+
+[table
+    [[Heading]]
+    [[cell]]
+]
+
+[table:table4
+    [[Heading]]
+    [[cell]]
+]
+
+[table:-table5-
+    [[Heading]]
+    [[cell]]
+]
+
+[table [/ Comment?] Title
+    [[Heading]]
+    [[cell]]
+]
+
+[table [/ Multi line
+comment] Title
+    [[Heading]]
+    [[cell]]
+]
+
+[table Title [/  ] containing a comment
+    [[Heading]]
+    [[cell]]
+]
+
+[table [/ Multi line
+comment]
+    Title
+    [[Heading]]
+    [[cell]]
+]
+
+[table [/ Multi line
+comment]
+    [[Heading]]
+    [[Cell 1]]
+    [[Cell 2]]
+]
+
+[table Title on multiple
+    lines with *bold* text?
+    [[Heading]]
+    [[Cell 1]]
+    [[Cell 2]]
+]
+
+[section:section1 Section 1]
+
+[table:table1 Table 1
+    [[Heading]]
+    [[cell]]
+]
+
+[table A & B
+    [[A][B]]
+    [[a][b]]
+]
+
+[table Empty Table]
+
+[table Table with an empty cell
+[[x]]]
+
+[table Indentation
+  [
+    [
+      Header 1. Paragraph 1
+
+      Header 1. Paragraph 2
+    ]
+    [
+      Header 2
+    ]
+  ]
+  [
+    [
+      Row 1. Cell 1.
+    ]
+    [
+      Row 1. Cell 2.
+
+      Row 1. Cell 2. Paragraph 2.
+    ]
+  ]
+  [
+    [
+Row 2. Cell 1.
+
+* Row 2. Cell 1. List item 1.
+* Row 2. Cell 1. List item 2.
+    ]
+    [
+      Row 2. Cell 2.
+
+      * Row 2. Cell 2. List item 1.
+      * Row 2. Cell 2. List item 2.
+    ]
+  ]
+]
+
+[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]
Modified: branches/release/tools/quickbook/test/templates-1_3.gold
==============================================================================
--- branches/release/tools/quickbook/test/templates-1_3.gold	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/templates-1_3.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -167,25 +167,26 @@
         </simpara>
       </listitem>
       <listitem>
-        <simpara>
-          <para/>
-        </simpara>
+        <para/>
       </listitem>
       <listitem>
-        <simpara>
 <programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
-        </simpara>
       </listitem>
       <listitem>
         <simpara>
-          <para>
-            Paragraphs 1
-          </para>
-          <para>
-            Paragraphs 2
-          </para>
+          Paragraphs 1
+        </simpara>
+        <simpara>
+          Paragraphs 2
         </simpara>
       </listitem>
     </itemizedlist>
   </section>
+  <section id="templates.escaped_templates">
+    <title><link linkend="templates.escaped_templates">Escaped templates</link></title>
+    <para>
+      <thingbob>Not real boostbook</thingbob> <thingbob>Also not real boostbook</thingbob>
+      <thingbob>More fake boostbook</thingbob> <thingbob>Final fake boostbook</thingbob>
+    </para>
+  </section>
 </article>
Modified: branches/release/tools/quickbook/test/templates-1_3.quickbook
==============================================================================
--- branches/release/tools/quickbook/test/templates-1_3.quickbook	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/templates-1_3.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -198,3 +198,19 @@
 * [paragraphs]
 
 [endsect]
+
+[/----------------------------------- Escaped templates ]
+
+[section Escaped templates]
+
+[template raw_markup <thingbob>Not real boostbook</thingbob>]
+[template | <thingbob>Also not real boostbook</thingbob>]
+[template escaped1 [|] [`|]]
+[template escaped2 [x] [`x]]
+
+[`raw_markup]
+[`|]
+[escaped1 <thingbob>More fake boostbook</thingbob>]
+[escaped2 <thingbob>Final fake boostbook</thingbob>]
+
+[endsect]
Modified: branches/release/tools/quickbook/test/templates-1_4.gold
==============================================================================
--- branches/release/tools/quickbook/test/templates-1_4.gold	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/templates-1_4.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -18,4 +18,11 @@
   <para>
     {1-2-3} {1-2-3} {1-2-3 4} {1 2-3-4} {[1-2-3}
   </para>
+  <section id="template_1_4.escaped_templates">
+    <title><link linkend="template_1_4.escaped_templates">Escaped templates</link></title>
+    <para>
+      <thingbob>Not real boostbook</thingbob> <thingbob>Also not real boostbook</thingbob>
+      <thingbob>More fake boostbook</thingbob> <thingbob>Final fake boostbook</thingbob>
+    </para>
+  </section>
 </article>
Modified: branches/release/tools/quickbook/test/templates-1_4.quickbook
==============================================================================
--- branches/release/tools/quickbook/test/templates-1_4.quickbook	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/templates-1_4.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -34,4 +34,20 @@
 [ternary 1 2 3]    [/ {1-2-3} ]
 [ternary 1..2 3 4] [/ {1-2-3 4} ]
 [ternary 1 2..3 4] [/ {1 2-3-4} ]
-[ternary [1..2..3] [/ {(1-2-3} (but with a square bracket) ]
\ No newline at end of file
+[ternary [1..2..3] [/ {(1-2-3} (but with a square bracket) ]
+
+[/----------------------------------- Escaped templates ]
+
+[section Escaped templates]
+
+[template raw_markup <thingbob>Not real boostbook</thingbob>]
+[template | <thingbob>Also not real boostbook</thingbob>]
+[template escaped1 [|] [`|]]
+[template escaped2 [x] [`x]]
+
+[`raw_markup]
+[`|]
+[escaped1 <thingbob>More fake boostbook</thingbob>]
+[escaped2 <thingbob>Final fake boostbook</thingbob>]
+
+[endsect]
Modified: branches/release/tools/quickbook/test/templates-1_5.gold
==============================================================================
--- branches/release/tools/quickbook/test/templates-1_5.gold	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/templates-1_5.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -3,40 +3,237 @@
 <article id="template_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
  xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>Template 1.5</title>
-  <para>
-    static scoping
-  </para>
-  <para>
-    [a]
-  </para>
-  <para>
-    new
-  </para>
-  <para>
-    foo foo
-  </para>
-  <para>
-    {1-2} {1-2} {1-2 3 4} {1 2-3 4} {1 2 3-4} {1..2-3} {1..2-3}
-  </para>
-  <para>
-    { {1 2-3}-4} { {1 2-3}-4} { {1-2 3}-4}
-  </para>
-  <para>
-    {[1-2] 3} {[1-2] 3} {[1-2}
-  </para>
-  <para>
-    {1-2-3} {1-2-3}
-  </para>
-  <para>
-    Some <emphasis role="bold">text</emphasis>
-  </para>
-  <para>
-    A <emphasis>paragraph</emphasis>.
-  </para>
-  <para>
-    Some *text* A <emphasis>paragraph</emphasis>.
-  </para>
-  <para>
-    <index type="things"><title>Things</title></index>
-  </para>
+  <section id="template_1_5.templates">
+    <title><link linkend="template_1_5.templates">Templates</link></title>
+    <para>
+      nullary_arg
+    </para>
+    <para>
+      foo baz
+    </para>
+    <para>
+      foo baz
+    </para>
+    <para>
+      This is a complete paragraph. kalamazoo kalamazoo kalamazoo kalamazoo kalamazoo
+      kalamazoo kalamazoo kalamazoo kalamazoo.... blah blah blah......
+    </para>
+    <para>
+      <hey>baz</hey>
+    </para>
+    <para>
+      This is a complete paragraph. madagascar madagascar madagascar madagascar madagascar
+      madagascar madagascar madagascar madagascar.... blah blah blah......
+    </para>
+    <para>
+      zoom peanut zoom
+    </para>
+    <para>
+      exactly xanadu
+    </para>
+    <para>
+      wx
+    </para>
+    <para>
+      wxyz wxyz trail
+    </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> "Hello, World" <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+    <para>
+      x<superscript>2</superscript>
+    </para>
+    <para>
+      α<superscript>2</superscript>
+    </para>
+    <para>
+      x<superscript>2</superscript>
+    </para>
+    <para>
+      got a banana?
+    </para>
+    <para>
+      .0 00
+    </para>
+    <para>
+      [fool]
+    </para>
+  </section>
+  <section id="template_1_5.empty_templates">
+    <title><link linkend="template_1_5.empty_templates">Empty Templates</link></title>
+  </section>
+  <section id="template_1_5.nested_templates">
+    <title><link linkend="template_1_5.nested_templates">Nested Templates</link></title>
+    <para>
+      Pre
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Hello!
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      Post
+    </para>
+    <para>
+      Pre
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Start phrase template. Hello! End phrase template.
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      Post
+    </para>
+    <para>
+      Pre
+    </para>
+    <para>
+      Start phrase template.
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Hello!
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      End phrase template.
+    </para>
+    <para>
+      Post
+    </para>
+    <para>
+      Pre Start phrase template. Start phrase template. Hello! End phrase template.
+      End phrase template. Post
+    </para>
+  </section>
+  <section id="template_1_5.block_markup">
+    <title><link linkend="template_1_5.block_markup">Block Markup</link></title>
+    <itemizedlist>
+      <listitem>
+        <simpara>
+          a
+        </simpara>
+      </listitem>
+      <listitem>
+        <simpara>
+          b
+        </simpara>
+      </listitem>
+    </itemizedlist>
+    <para/>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+    <para>
+      Paragraphs 1
+    </para>
+    <para>
+      Paragraphs 2
+    </para>
+    <itemizedlist>
+      <listitem>
+        <simpara>
+          <itemizedlist>
+            <listitem>
+              <simpara>
+                a
+              </simpara>
+            </listitem>
+            <listitem>
+              <simpara>
+                b
+              </simpara>
+            </listitem>
+          </itemizedlist>
+        </simpara>
+      </listitem>
+      <listitem>
+        <para/>
+      </listitem>
+      <listitem>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+      </listitem>
+      <listitem>
+        <simpara>
+          Paragraphs 1
+        </simpara>
+        <simpara>
+          Paragraphs 2
+        </simpara>
+      </listitem>
+    </itemizedlist>
+  </section>
+  <section id="template_1_5.static_scoping">
+    <title><link linkend="template_1_5.static_scoping">Static Scoping</link></title>
+    <para>
+      static scoping
+    </para>
+    <para>
+      [a]
+    </para>
+    <para>
+      new
+    </para>
+    <para>
+      foo foo
+    </para>
+  </section>
+  <section id="template_1_5.template_arguments">
+    <title><link linkend="template_1_5.template_arguments">Template Arguments</link></title>
+    <para>
+      {1-2} {1-2} {1-2 3 4} {1 2-3 4} {1 2 3-4} {1..2-3} {1..2-3}
+    </para>
+    <para>
+      { {1 2-3}-4} { {1 2-3}-4} { {1-2 3}-4}
+    </para>
+    <para>
+      {[1-2] 3} {[1-2] 3} {[1-2}
+    </para>
+    <para>
+      {1-2-3} {1-2-3}
+    </para>
+  </section>
+  <section id="template_1_5.block_and_phrase_templates">
+    <title><link linkend="template_1_5.block_and_phrase_templates">Block and phrase
+    templates</link></title>
+    <para>
+      Some <emphasis role="bold">text</emphasis>
+    </para>
+    <para>
+      A <emphasis>paragraph</emphasis>.
+    </para>
+    <para>
+      Some *text* A <emphasis>paragraph</emphasis>.
+    </para>
+    <para>
+      <index type="things"><title>Things</title></index>
+    </para>
+  </section>
+  <section id="template_1_5.escaped_templates">
+    <title><link linkend="template_1_5.escaped_templates">Escaped templates</link></title>
+    <para>
+      <thingbob>Not real boostbook</thingbob> <thingbob>Also not real boostbook</thingbob>
+      <thingbob>More fake boostbook</thingbob> <thingbob>Final fake boostbook</thingbob>
+    </para>
+  </section>
 </article>
Modified: branches/release/tools/quickbook/test/templates-1_5.quickbook
==============================================================================
--- branches/release/tools/quickbook/test/templates-1_5.quickbook	Fri Aug 16 13:31:26 2013	(r85368)
+++ branches/release/tools/quickbook/test/templates-1_5.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369)
@@ -2,12 +2,211 @@
     [quickbook 1.5]
 ]
 
-[/ 1.5 uses static scoping ]
+[section Templates]
+
+[/-------------------------------- nullary arg ]
+
+[template foo0 nullary_arg]
+
+[foo0]
+
+[/-------------------------------- unary arg, phrase syle ]
+
+[template foo1[bar] foo [bar]]
+
+[foo1 baz]
+
+[/-------------------------------- unary arg, block syle ]
+
+[template foo2[bar]
+foo [bar]
+]
+
+[foo2 baz]
+
+[template foo3[bar]
+This is a complete paragraph. [bar] [bar] [bar] [bar] [bar]
+[bar] [bar] [bar] [bar].... blah blah blah......
+]
+
+[foo3 kalamazoo]
+
+[/-------------------------------- unary arg, using punctuation ]
+
+[template ![bar] '''<hey>'''[bar]'''</hey>''']
+
+[!baz]
+
+[/-------------------------------- recursive templates ]
+
+[template foo4[bar]
+[foo3 [bar]]
+]
+
+[foo3 madagascar]
+
+[template foo5[x] zoom [x]]
+[template foo6[x] [x] zoom]
+
+[foo6[foo5 peanut]]
+
+[template kinda_weird[x y] [x] [y]]
+
+[kinda_weird exactly..xanadu]
+
+
+[/-------------------------------- space delimitted args ]
+
+[template simple1[a b] [a][b]]
+
+[simple1 w x]
+
+[template simple2[a b c d] [a][b][c][d]]
+
+[simple2 w x y z][simple2 w x y z trail]
+
+[/-------------------------------- John's templates ]
+
+[template code[x]
+    int main()
+    {
+        std::cout << ``[x]`` << std::endl;
+    }
+]
+
+[code "Hello\, World"]
+
+[template alpha '''α''']
+[template pow[a b] [a]'''<superscript>'''[b]'''</superscript>''' ]
+[template super[text]'''<superscript>'''[text]'''</superscript>''' ]
+
+[pow x 2]
+
+[pow [alpha] 2]
+
+x[super 2]
+
+[/-------------------------------- Some more ]
+
+[template banana got a banana?]
+[template plantation[bananarama] [bananarama]]
+
+[plantation [banana]]
+
+[/-------------------------------- Not a bug (there was a syntax error here) ]
+
+[template join1[a b] [b][a]]
+[template join2[a b] [a][b]]
+[template test[x] [join1 [join2 0 [x]]...0]]
+[test 0]
+
+[/-------------------------------- Mismatched template ]
+
+[template foo 1]
+[fool]
+
+[template blah 10]
+
+[endsect]
+
+[section Empty Templates]
+
+[template empty1]
+[template empty2 ]
+[template empty3 [/comment]]
+[template empty4 [/comment]
+
+]
+[template empty5
+]
+[template empty6
+
+]
+[template empty7
+[/comment]
+]
+[template empty8
+
+[/comment]
+]
+[template empty_arg1[x]]
+[template empty_arg2[x y]]
+
+[empty1]
+[empty2]
+[empty3]
+[empty4]
+[empty5]
+[empty6]
+[empty7]
+[empty8]
+[empty_arg1 1]
+[empty_arg2 1 2]
+
+[endsect]
+
+[/----------------------------------- Nested templates ]
+
+[section Nested Templates]
+
+[template block[content]
+
+Start block template.
+
+[content]
+
+End block template.
+]
+
+[template phrase[content] Start phrase template. [content] End phrase template.]
+
+Pre [block [block Hello!]] Post
+
+Pre [block [phrase Hello!]] Post
+
+Pre [phrase [block Hello!]] Post
+
+Pre [phrase [phrase Hello!]] Post
+
+[endsect]
+
+[/----------------------------------- Block Markup ]
+
+[section Block Markup]
+
+[template list
+* a
+* b]
+
+[template horizontal
+----]
+
+[template codeblock
+    int main() {}]
+
+[template paragraphs
+Paragraphs 1
+
+Paragraphs 2
+]
+
+[list][horizontal][codeblock][paragraphs]
+
+* [list]
+* [horizontal]
+* [codeblock]
+* [paragraphs]
+
+[endsect]
+
+[/----------------------------------- 1.5+ use static scoping ]
+
+[section Static Scoping]
 
 [template x static scoping]
-[template foo1[] [x]]
-[template foo2[x] [foo1]]
-[foo2 dynamic scoping]
+[template static_test1[] [x]]
+[template static_test2[x] [static_test1]]
+[static_test2 dynamic scoping]
 
 [/ This should be '[a]' because [a] isn't matched. ]
 [template test1[] [a]]
@@ -17,8 +216,8 @@
 [/ In 1.5 template arguments are scoped at the point they are defined]
 
 [template y new]
-[template foo3[a y] [a]]
-[foo3 [y] old]
+[template static_test3[a y] [a]]
+[static_test3 [y] old]
 
 [/ From https://svn.boost.org/trac/boost/ticket/2034 ]
 
@@ -27,7 +226,11 @@
 [template echo_twice[x] [echo [same [x]]..[same [x]]]]
 [echo_twice foo]
 
-[/ 1.5 template arguments]
+[endsect]
+
+[/----------------------------------- 1.5+ template arguments ]
+
+[section Template Arguments]
 
 [template binary[x y] {[x]-[y]}]
 [binary 1..2]     [/ {1-2} ]
@@ -50,18 +253,22 @@
 [ternary 1..2..3]  [/ {1-2-3} ]
 [ternary 1 2 3]    [/ {1-2-3} ]
 
-[/ Block vs. phrase templates ]
+[endsect]
 
-[template phrase[] Some *text*]
-[template block[]
+[/----------------------------------- Block and phrases ]
+
+[section Block and phrase templates]
+
+[template phrase_template[] Some *text*]
+[template block_template[]
 
 A <emphasis>paragraph</emphasis>.
 ]
 
-[phrase]
-[block]
-[`phrase]
-[`block]
+[phrase_template]
+[block_template]
+[`phrase_template]
+[`block_template]
 
 [/ Trailing newline shouldn't be included]
 
@@ -69,4 +276,22 @@
 '''<index type="'''[type]'''"><title>'''[title]'''</title></index>'''
 ]
 
-[named_index things Things]
\ No newline at end of file
+[named_index things Things]
+
+[endsect]
+
+[/----------------------------------- Escaped templates ]
+
+[section Escaped templates]
+
+[template raw_markup <thingbob>Not real boostbook</thingbob>]
+[template | <thingbob>Also not real boostbook</thingbob>]
+[template escaped1 [|] [`|]]
+[template escaped2 [x] [`x]]
+
+[`raw_markup]
+[`|]
+[escaped1 <thingbob>More fake boostbook</thingbob>]
+[escaped2 <thingbob>Final fake boostbook</thingbob>]
+
+[endsect]
Copied: branches/release/tools/quickbook/test/templates-1_6-fail1.quickbook (from r85368, trunk/tools/quickbook/test/templates-1_6-fail1.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/templates-1_6-fail1.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/templates-1_6-fail1.quickbook)
@@ -0,0 +1,8 @@
+[article Template 1.6 fail 1
+    [quickbook 1.6]
+]
+
+[/ I've removed support for escaping punctuation templates in 1.6. ]
+
+[template ~ body]
+[`~]
Copied: branches/release/tools/quickbook/test/templates-1_6.gold (from r85368, trunk/tools/quickbook/test/templates-1_6.gold)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/templates-1_6.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/templates-1_6.gold)
@@ -0,0 +1,257 @@
+<?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="template_1_6" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+  <title>Template 1.6</title>
+  <section id="template_1_6.templates">
+    <title><link linkend="template_1_6.templates">Templates</link></title>
+    <para>
+      nullary_arg
+    </para>
+    <para>
+      foo baz
+    </para>
+    <para>
+      foo baz
+    </para>
+    <para>
+      This is a complete paragraph. kalamazoo kalamazoo kalamazoo kalamazoo kalamazoo
+      kalamazoo kalamazoo kalamazoo kalamazoo.... blah blah blah......
+    </para>
+    <para>
+      <hey>baz</hey>
+    </para>
+    <para>
+      This is a complete paragraph. madagascar madagascar madagascar madagascar madagascar
+      madagascar madagascar madagascar madagascar.... blah blah blah......
+    </para>
+    <para>
+      zoom peanut zoom
+    </para>
+    <para>
+      exactly xanadu
+    </para>
+    <para>
+      wx
+    </para>
+    <para>
+      wxyz wxyz trail
+    </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> "Hello, World" <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+    <para>
+      x<superscript>2</superscript>
+    </para>
+    <para>
+      α<superscript>2</superscript>
+    </para>
+    <para>
+      x<superscript>2</superscript>
+    </para>
+    <para>
+      got a banana?
+    </para>
+    <para>
+      .0 00
+    </para>
+    <para>
+      [fool]
+    </para>
+  </section>
+  <section id="template_1_6.empty_templates">
+    <title><link linkend="template_1_6.empty_templates">Empty Templates</link></title>
+  </section>
+  <section id="template_1_6.nested_templates">
+    <title><link linkend="template_1_6.nested_templates">Nested Templates</link></title>
+    <para>
+      Pre
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Hello!
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      Post
+    </para>
+    <para>
+      Pre
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Start phrase template. Hello! End phrase template.
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      Post
+    </para>
+    <para>
+      Pre
+    </para>
+    <para>
+      Start phrase template.
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Hello!
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      End phrase template.
+    </para>
+    <para>
+      Post
+    </para>
+    <para>
+      Pre Start phrase template. Start phrase template. Hello! End phrase template.
+      End phrase template. Post
+    </para>
+  </section>
+  <section id="template_1_6.block_markup">
+    <title><link linkend="template_1_6.block_markup">Block Markup</link></title>
+    <itemizedlist>
+      <listitem>
+        <simpara>
+          a
+        </simpara>
+      </listitem>
+      <listitem>
+        <simpara>
+          b
+        </simpara>
+      </listitem>
+    </itemizedlist>
+    <para/>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+    <para>
+      Paragraphs 1
+    </para>
+    <para>
+      Paragraphs 2
+    </para>
+    <itemizedlist>
+      <listitem>
+        <simpara>
+          <itemizedlist>
+            <listitem>
+              <simpara>
+                a
+              </simpara>
+            </listitem>
+            <listitem>
+              <simpara>
+                b
+              </simpara>
+            </listitem>
+          </itemizedlist>
+        </simpara>
+      </listitem>
+      <listitem>
+        <para/>
+      </listitem>
+      <listitem>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+      </listitem>
+      <listitem>
+        <simpara>
+          Paragraphs 1
+        </simpara>
+        <simpara>
+          Paragraphs 2
+        </simpara>
+      </listitem>
+    </itemizedlist>
+  </section>
+  <section id="template_1_6.static_scoping">
+    <title><link linkend="template_1_6.static_scoping">Static Scoping</link></title>
+    <para>
+      static scoping
+    </para>
+    <para>
+      [a]
+    </para>
+    <para>
+      new
+    </para>
+    <para>
+      foo foo
+    </para>
+  </section>
+  <section id="template_1_6.template_arguments">
+    <title><link linkend="template_1_6.template_arguments">Template Arguments</link></title>
+    <para>
+      {1-2} {1-2} {1-2 3 4} {1 2-3 4} {1 2 3-4} {1..2-3} {1..2-3}
+    </para>
+    <para>
+      { {1 2-3}-4} { {1 2-3}-4} { {1-2 3}-4}
+    </para>
+    <para>
+      {[1-2] 3} {[1-2] 3} {[1-2}
+    </para>
+    <para>
+      {1-2-3} {1-2-3}
+    </para>
+  </section>
+  <section id="template_1_6.block_and_phrase_templates">
+    <title><link linkend="template_1_6.block_and_phrase_templates">Block and phrase
+    templates</link></title>
+    <para>
+      Some <emphasis role="bold">text</emphasis>
+    </para>
+    <para>
+      A <emphasis>paragraph</emphasis>.
+    </para>
+    <para>
+      Some *text* A <emphasis>paragraph</emphasis>.
+    </para>
+    <para>
+      <index type="things"><title>Things</title></index>
+    </para>
+  </section>
+  <section id="template_1_6.template_body">
+    <title><link linkend="template_1_6.template_body">Skipping the template body
+    correctly</link></title>
+    <para>
+      <emphasis>Argument</emphasis>
+    </para>
+    <orderedlist>
+      <listitem>
+<programlisting><phrase role="identifier">code</phrase></programlisting>
+      </listitem>
+    </orderedlist>
+    <orderedlist>
+      <listitem>
+        <simpara>
+          <code><phrase role="identifier">code</phrase></code>
+        </simpara>
+      </listitem>
+    </orderedlist>
+  </section>
+  <section id="template_1_6.escaped_templates">
+    <title><link linkend="template_1_6.escaped_templates">Escaped templates</link></title>
+    <para>
+      <thingbob>Not real boostbook</thingbob> <thingbob>More fake boostbook</thingbob>
+    </para>
+  </section>
+</article>
Copied: branches/release/tools/quickbook/test/templates-1_6.quickbook (from r85368, trunk/tools/quickbook/test/templates-1_6.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/templates-1_6.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/templates-1_6.quickbook)
@@ -0,0 +1,313 @@
+[article Template 1.6
+    [quickbook 1.6]
+]
+
+[section Templates]
+
+[/-------------------------------- nullary arg ]
+
+[template foo0 nullary_arg]
+
+[foo0]
+
+[/-------------------------------- unary arg, phrase syle ]
+
+[template foo1[bar] foo [bar]]
+
+[foo1 baz]
+
+[/-------------------------------- unary arg, block syle ]
+
+[template foo2[bar]
+foo [bar]
+]
+
+[foo2 baz]
+
+[template foo3[bar]
+This is a complete paragraph. [bar] [bar] [bar] [bar] [bar]
+[bar] [bar] [bar] [bar].... blah blah blah......
+]
+
+[foo3 kalamazoo]
+
+[/-------------------------------- unary arg, using punctuation ]
+
+[template ![bar] '''<hey>'''[bar]'''</hey>''']
+
+[!baz]
+
+[/-------------------------------- recursive templates ]
+
+[template foo4[bar]
+[foo3 [bar]]
+]
+
+[foo3 madagascar]
+
+[template foo5[x] zoom [x]]
+[template foo6[x] [x] zoom]
+
+[foo6[foo5 peanut]]
+
+[template kinda_weird[x y] [x] [y]]
+
+[kinda_weird exactly..xanadu]
+
+
+[/-------------------------------- space delimitted args ]
+
+[template simple1[a b] [a][b]]
+
+[simple1 w x]
+
+[template simple2[a b c d] [a][b][c][d]]
+
+[simple2 w x y z][simple2 w x y z trail]
+
+[/-------------------------------- John's templates ]
+
+[template code[x]
+    int main()
+    {
+        std::cout << ``[x]`` << std::endl;
+    }
+]
+
+[code "Hello\, World"]
+
+[template alpha '''α''']
+[template pow[a b] [a]'''<superscript>'''[b]'''</superscript>''' ]
+[template super[text]'''<superscript>'''[text]'''</superscript>''' ]
+
+[pow x 2]
+
+[pow [alpha] 2]
+
+x[super 2]
+
+[/-------------------------------- Some more ]
+
+[template banana got a banana?]
+[template plantation[bananarama] [bananarama]]
+
+[plantation [banana]]
+
+[/-------------------------------- Not a bug (there was a syntax error here) ]
+
+[template join1[a b] [b][a]]
+[template join2[a b] [a][b]]
+[template test[x] [join1 [join2 0 [x]]...0]]
+[test 0]
+
+[/-------------------------------- Mismatched template ]
+
+[template foo 1]
+[fool]
+
+[template blah 10]
+
+[endsect]
+
+[section Empty Templates]
+
+[template empty1]
+[template empty2 ]
+[template empty3 [/comment]]
+[template empty4 [/comment]
+
+]
+[template empty5
+]
+[template empty6
+
+]
+[template empty7
+[/comment]
+]
+[template empty8
+
+[/comment]
+]
+[template empty_arg1[x]]
+[template empty_arg2[x y]]
+
+[empty1]
+[empty2]
+[empty3]
+[empty4]
+[empty5]
+[empty6]
+[empty7]
+[empty8]
+[empty_arg1 1]
+[empty_arg2 1 2]
+
+[endsect]
+
+[/----------------------------------- Nested templates ]
+
+[section Nested Templates]
+
+[template block_foo[content]
+
+Start block template.
+
+[content]
+
+End block template.
+]
+
+[template phrase_foo[content] Start phrase template. [content] End phrase template.]
+
+Pre [block_foo [block_foo Hello!]] Post
+
+Pre [block_foo [phrase_foo Hello!]] Post
+
+Pre [phrase_foo [block_foo Hello!]] Post
+
+Pre [phrase_foo [phrase_foo Hello!]] Post
+
+[endsect]
+
+[/----------------------------------- Block Markup ]
+
+[section Block Markup]
+
+[template list
+* a
+* b]
+
+[template horizontal
+----]
+
+[template codeblock
+    int main() {}]
+
+[template paragraphs
+Paragraphs 1
+
+Paragraphs 2
+]
+
+[list][horizontal][codeblock][paragraphs]
+
+* [list]
+* [horizontal]
+* [codeblock]
+* [paragraphs]
+
+[endsect]
+
+[/----------------------------------- 1.5+ use static scoping ]
+
+[section Static Scoping]
+
+[template x static scoping]
+[template static_test1[] [x]]
+[template static_test2[x] [static_test1]]
+[static_test2 dynamic scoping]
+
+[/ This should be '[a]' because [a] isn't matched. ]
+[template test1[] [a]]
+[template test2[a] [test1]]
+[test2 1]
+
+[/ In 1.5 template arguments are scoped at the point they are defined]
+
+[template y new]
+[template static_test3[a y] [a]]
+[static_test3 [y] old]
+
+[/ From https://svn.boost.org/trac/boost/ticket/2034 ]
+
+[template same[x] [x]]
+[template echo[a b] [a] [b]]
+[template echo_twice[x] [echo [same [x]]..[same [x]]]]
+[echo_twice foo]
+
+[endsect]
+
+[/----------------------------------- 1.5+ template arguments ]
+
+[section Template Arguments]
+
+[template binary[x y] {[x]-[y]}]
+[binary 1..2]     [/ {1-2} ]
+[binary 1 2]      [/ {1-2} ]
+[binary 1..2 3 4] [/ {1-2 3 4} ]
+[binary 1 2..3 4] [/ {1 2-3 4} ]
+[binary 1 2 3..4] [/ {1 2 3-4} ]
+[binary 1.\.2..3] [/ {1..2-3} ]
+[binary 1.\.2 3]  [/ {1..2-3} ]
+
+[binary [binary 1 2..3]..4] [/ { {1 2-3}-4} ]
+[binary [binary 1 2..3] 4] [/ { {1 2-3}-4} ]
+[binary [binary 1 2 3]..4] [/ { {1-2 3}-4} ]
+
+[binary \[1 2\] 3] [/ {[1-2] 3} ]
+[binary \[1..2\] 3] [/ {[1-2] 3} ]
+[binary \[1 2] [/ {(1-2} ]
+
+[template ternary[x y z] {[x]-[y]-[z]}]
+[ternary 1..2..3]  [/ {1-2-3} ]
+[ternary 1 2 3]    [/ {1-2-3} ]
+
+[endsect]
+
+[/----------------------------------- Block and phrases ]
+
+[section Block and phrase templates]
+
+[template phrase_template[] Some *text*]
+[template block_template[]
+
+A <emphasis>paragraph</emphasis>.
+]
+
+[phrase_template]
+[block_template]
+[`phrase_template]
+[`block_template]
+
+[/ Trailing newline shouldn't be included]
+
+[template named_index[type title]
+'''<index type="'''[type]'''"><title>'''[title]'''</title></index>'''
+]
+
+[named_index things Things]
+
+[endsect]
+
+[/-------------------------------- Skipping template body ]
+
+[section:template_body Skipping the template body correctly]
+
+[template args1[x] [`x]]
+[template args2[]
+[ordered_list [``code``]]
+]
+[/ Due to a bug in the template parser need to stop the parser
+   thinking that the code is an escaped template. ]
+[template args3[]
+[ordered_list [\ `code`]]
+]
+
+[args1 <emphasis>Argument</emphasis>]
+[args2]
+[args3]
+
+[endsect]
+
+[/----------------------------------- Escaped templates ]
+
+[section Escaped templates]
+
+[template raw_markup <thingbob>Not real boostbook</thingbob>]
+[template escaped1 [x] [`x]]
+
+[`raw_markup]
+[escaped1 <thingbob>More fake boostbook</thingbob>]
+
+[endsect]
Copied: branches/release/tools/quickbook/test/templates-1_7-fail1.quickbook (from r85368, trunk/tools/quickbook/test/templates-1_7-fail1.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/templates-1_7-fail1.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/templates-1_7-fail1.quickbook)
@@ -0,0 +1,12 @@
+[article Template 1.7 fail
+[quickbook 1.7]
+]
+
+[/ This should fail because it's a phrase template containing a paragraph
+   separator. ]
+
+[template fail[] Phrase content.
+
+Paragraph content.]
+
+[fail]
Copied: branches/release/tools/quickbook/test/templates-1_7.gold (from r85368, trunk/tools/quickbook/test/templates-1_7.gold)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/templates-1_7.gold	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/templates-1_7.gold)
@@ -0,0 +1,302 @@
+<?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="template_1_7" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+  <title>Template 1.7</title>
+  <section id="template_1_7.templates">
+    <title><link linkend="template_1_7.templates">Templates</link></title>
+    <para>
+      nullary_arg
+    </para>
+    <para>
+      foo baz
+    </para>
+    <para>
+      foo baz
+    </para>
+    <para>
+      This is a complete paragraph. kalamazoo kalamazoo kalamazoo kalamazoo kalamazoo
+      kalamazoo kalamazoo kalamazoo kalamazoo.... blah blah blah......
+    </para>
+    <para>
+      <hey>baz</hey>
+    </para>
+    <para>
+      This is a complete paragraph. madagascar madagascar madagascar madagascar madagascar
+      madagascar madagascar madagascar madagascar.... blah blah blah......
+    </para>
+    <para>
+      zoom peanut zoom
+    </para>
+    <para>
+      exactly xanadu
+    </para>
+    <para>
+      wx
+    </para>
+    <para>
+      wxyz wxyz trail
+    </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> "Hello, World" <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+    <para>
+      x<superscript>2</superscript>
+    </para>
+    <para>
+      α<superscript>2</superscript>
+    </para>
+    <para>
+      x<superscript>2</superscript>
+    </para>
+    <para>
+      got a banana?
+    </para>
+    <para>
+      .0 00
+    </para>
+    <para>
+      [fool]
+    </para>
+  </section>
+  <section id="template_1_7.empty_templates">
+    <title><link linkend="template_1_7.empty_templates">Empty Templates</link></title>
+  </section>
+  <section id="template_1_7.nested_templates">
+    <title><link linkend="template_1_7.nested_templates">Nested Templates</link></title>
+    <para>
+      Pre
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Hello!
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      Post
+    </para>
+    <para>
+      Pre
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Start phrase template. Hello! End phrase template.
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      Post
+    </para>
+    <para>
+      Pre Start phrase template.
+    </para>
+    <para>
+      Start block template.
+    </para>
+    <para>
+      Hello!
+    </para>
+    <para>
+      End block template.
+    </para>
+    <para>
+      End phrase template. Post
+    </para>
+    <para>
+      Pre Start phrase template. Start phrase template. Hello! End phrase template.
+      End phrase template. Post
+    </para>
+  </section>
+  <section id="template_1_7.block_markup">
+    <title><link linkend="template_1_7.block_markup">Block Markup</link></title>
+    <itemizedlist>
+      <listitem>
+        <simpara>
+          a
+        </simpara>
+      </listitem>
+      <listitem>
+        <simpara>
+          b
+        </simpara>
+      </listitem>
+    </itemizedlist>
+    <para/>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+    <para>
+      Paragraphs 1
+    </para>
+    <para>
+      Paragraphs 2
+    </para>
+    <itemizedlist>
+      <listitem>
+        <simpara>
+          <itemizedlist>
+            <listitem>
+              <simpara>
+                a
+              </simpara>
+            </listitem>
+            <listitem>
+              <simpara>
+                b
+              </simpara>
+            </listitem>
+          </itemizedlist>
+        </simpara>
+      </listitem>
+      <listitem>
+        <para/>
+      </listitem>
+      <listitem>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+      </listitem>
+      <listitem>
+        <simpara>
+          Paragraphs 1
+        </simpara>
+        <simpara>
+          Paragraphs 2
+        </simpara>
+      </listitem>
+    </itemizedlist>
+  </section>
+  <section id="template_1_7.static_scoping">
+    <title><link linkend="template_1_7.static_scoping">Static Scoping</link></title>
+    <para>
+      static scoping
+    </para>
+    <para>
+      [a]
+    </para>
+    <para>
+      new
+    </para>
+    <para>
+      foo foo
+    </para>
+  </section>
+  <section id="template_1_7.template_arguments">
+    <title><link linkend="template_1_7.template_arguments">Template Arguments</link></title>
+    <para>
+      {1-2} {1-2} {1-2 3 4} {1 2-3 4} {1 2 3-4} {1..2-3} {1..2-3}
+    </para>
+    <para>
+      { {1 2-3}-4} { {1 2-3}-4} { {1-2 3}-4}
+    </para>
+    <para>
+      {[1-2] 3} {[1-2] 3} {[1-2}
+    </para>
+    <para>
+      {1-2-3} {1-2-3}
+    </para>
+  </section>
+  <section id="template_1_7.block_and_phrase_templates">
+    <title><link linkend="template_1_7.block_and_phrase_templates">Block and phrase
+    templates</link></title>
+    <para>
+      Some <emphasis role="bold">text</emphasis>
+    </para>
+    <para>
+      A <emphasis>paragraph</emphasis>.
+    </para>
+    <para>
+      Some *text* A <emphasis>paragraph</emphasis>.
+    </para>
+    <para>
+      <index type="things"><title>Things</title></index>
+    </para>
+    <informaltable frame="all">
+      <tgroup cols="0">
+        <tbody>
+        </tbody>
+      </tgroup>
+    </informaltable>
+    <informaltable frame="all">
+      <tgroup cols="0">
+        <tbody>
+        </tbody>
+      </tgroup>
+    </informaltable>
+    <para>
+      Text2 afterwards. Text3 before.
+    </para>
+    <informaltable frame="all">
+      <tgroup cols="0">
+        <tbody>
+        </tbody>
+      </tgroup>
+    </informaltable>
+    <para>
+      Text4 before.
+    </para>
+    <informaltable frame="all">
+      <tgroup cols="0">
+        <tbody>
+        </tbody>
+      </tgroup>
+    </informaltable>
+    <para>
+      Text4 afterwards.
+    </para>
+    <informaltable frame="all">
+      <tgroup cols="0">
+        <tbody>
+        </tbody>
+      </tgroup>
+    </informaltable>
+    <para>
+      * Not a list.
+    </para>
+    <informaltable frame="all">
+      <tgroup cols="0">
+        <tbody>
+        </tbody>
+      </tgroup>
+    </informaltable>
+    <para>
+      * Not a list.
+    </para>
+  </section>
+  <section id="template_1_7.template_body">
+    <title><link linkend="template_1_7.template_body">Skipping the template body
+    correctly</link></title>
+    <para>
+      <emphasis>Argument</emphasis>
+    </para>
+    <orderedlist>
+      <listitem>
+<programlisting><phrase role="identifier">code</phrase></programlisting>
+      </listitem>
+    </orderedlist>
+    <orderedlist>
+      <listitem>
+        <simpara>
+          <code><phrase role="identifier">code</phrase></code>
+        </simpara>
+      </listitem>
+    </orderedlist>
+  </section>
+  <section id="template_1_7.escaped_templates">
+    <title><link linkend="template_1_7.escaped_templates">Escaped templates</link></title>
+    <para>
+      <thingbob>Not real boostbook</thingbob> <thingbob>More fake boostbook</thingbob>
+    </para>
+  </section>
+</article>
Copied: branches/release/tools/quickbook/test/templates-1_7.quickbook (from r85368, trunk/tools/quickbook/test/templates-1_7.quickbook)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/tools/quickbook/test/templates-1_7.quickbook	2013-08-17 05:46:47 EDT (Sat, 17 Aug 2013)	(r85369, copy of r85368, trunk/tools/quickbook/test/templates-1_7.quickbook)
@@ -0,0 +1,322 @@
+[article Template 1.7
+    [quickbook 1.7]
+]
+
+[section Templates]
+
+[/-------------------------------- nullary arg ]
+
+[template foo0 nullary_arg]
+
+[foo0]
+
+[/-------------------------------- unary arg, phrase syle ]
+
+[template foo1[bar] foo [bar]]
+
+[foo1 baz]
+
+[/-------------------------------- unary arg, block syle ]
+
+[template foo2[bar]
+foo [bar]
+]
+
+[foo2 baz]
+
+[template foo3[bar]
+This is a complete paragraph. [bar] [bar] [bar] [bar] [bar]
+[bar] [bar] [bar] [bar].... blah blah blah......
+]
+
+[foo3 kalamazoo]
+
+[/-------------------------------- unary arg, using punctuation ]
+
+[template |[bar] '''<hey>'''[bar]'''</hey>''']
+
+[|baz]
+
+[/-------------------------------- recursive templates ]
+
+[template foo4[bar]
+[foo3 [bar]]
+]
+
+[foo3 madagascar]
+
+[template foo5[x] zoom [x]]
+[template foo6[x] [x] zoom]
+
+[foo6[foo5 peanut]]
+
+[template kinda_weird[x y] [x] [y]]
+
+[kinda_weird exactly..xanadu]
+
+
+[/-------------------------------- space delimitted args ]
+
+[template simple1[a b] [a][b]]
+
+[simple1 w x]
+
+[template simple2[a b c d] [a][b][c][d]]
+
+[simple2 w x y z][simple2 w x y z trail]
+
+[/-------------------------------- John's templates ]
+
+[template code[x]
+    int main()
+    {
+        std::cout << ``[x]`` << std::endl;
+    }
+]
+
+[code "Hello\, World"]
+
+[template alpha '''α''']
+[template pow[a b] [a]'''<superscript>'''[b]'''</superscript>''' ]
+[template super[text]'''<superscript>'''[text]'''</superscript>''' ]
+
+[pow x 2]
+
+[pow [alpha] 2]
+
+x[super 2]
+
+[/-------------------------------- Some more ]
+
+[template banana got a banana?]
+[template plantation[bananarama] [bananarama]]
+
+[plantation [banana]]
+
+[/-------------------------------- Not a bug (there was a syntax error here) ]
+
+[template join1[a b] [b][a]]
+[template join2[a b] [a][b]]
+[template test[x] [join1 [join2 0 [x]]...0]]
+[test 0]
+
+[/-------------------------------- Mismatched template ]
+
+[template foo 1]
+[fool]
+
+[template blah 10]
+
+[endsect]
+
+[section Empty Templates]
+
+[template empty1]
+[template empty2 ]
+[template empty3 [/comment]]
+[template empty4 [/comment]
+
+]
+[template empty5
+]
+[template empty6
+
+]
+[template empty7
+[/comment]
+]
+[template empty8
+
+[/comment]
+]
+[template empty_arg1[x]]
+[template empty_arg2[x y]]
+
+[empty1]
+[empty2]
+[empty3]
+[empty4]
+[empty5]
+[empty6]
+[empty7]
+[empty8]
+[empty_arg1 1]
+[empty_arg2 1 2]
+
+[endsect]
+
+[/----------------------------------- Nested templates ]
+
+[section Nested Templates]
+
+[template block_foo[content]
+
+Start block template.
+
+[content]
+
+End block template.
+]
+
+[template phrase_foo[content] Start phrase template. [content] End phrase template.]
+
+Pre [block_foo [block_foo Hello!]] Post
+
+Pre [block_foo [phrase_foo Hello!]] Post
+
+Pre [phrase_foo [block_foo Hello!]] Post
+
+Pre [phrase_foo [phrase_foo Hello!]] Post
+
+[endsect]
+
+[/----------------------------------- Block Markup ]
+
+[section Block Markup]
+
+[template list
+* a
+* b]
+
+[template horizontal
+----]
+
+[template codeblock
+    int main() {}]
+
+[template paragraphs
+Paragraphs 1
+
+Paragraphs 2
+]
+
+[list][horizontal][codeblock][paragraphs]
+
+* [list]
+* [horizontal]
+* [codeblock]
+* [paragraphs]
+
+[endsect]
+
+[/----------------------------------- 1.5+ use static scoping ]
+
+[section Static Scoping]
+
+[template x static scoping]
+[template static_test1[] [x]]
+[template static_test2[x] [static_test1]]
+[static_test2 dynamic scoping]
+
+[/ This should be '[a]' because [a] isn't matched. ]
+[template test1[] [a]]
+[template test2[a] [test1]]
+[test2 1]
+
+[/ In 1.5 template arguments are scoped at the point they are defined]
+
+[template y new]
+[template static_test3[a y] [a]]
+[static_test3 [y] old]
+
+[/ From https://svn.boost.org/trac/boost/ticket/2034 ]
+
+[template same[x] [x]]
+[template echo[a b] [a] [b]]
+[template echo_twice[x] [echo [same [x]]..[same [x]]]]
+[echo_twice foo]
+
+[endsect]
+
+[/----------------------------------- 1.5+ template arguments ]
+
+[section Template Arguments]
+
+[template binary[x y] {[x]-[y]}]
+[binary 1..2]     [/ {1-2} ]
+[binary 1 2]      [/ {1-2} ]
+[binary 1..2 3 4] [/ {1-2 3 4} ]
+[binary 1 2..3 4] [/ {1 2-3 4} ]
+[binary 1 2 3..4] [/ {1 2 3-4} ]
+[binary 1.\.2..3] [/ {1..2-3} ]
+[binary 1.\.2 3]  [/ {1..2-3} ]
+
+[binary [binary 1 2..3]..4] [/ { {1 2-3}-4} ]
+[binary [binary 1 2..3] 4] [/ { {1 2-3}-4} ]
+[binary [binary 1 2 3]..4] [/ { {1-2 3}-4} ]
+
+[binary \[1 2\] 3] [/ {[1-2] 3} ]
+[binary \[1..2\] 3] [/ {[1-2] 3} ]
+[binary \[1 2] [/ {(1-2} ]
+
+[template ternary[x y z] {[x]-[y]-[z]}]
+[ternary 1..2..3]  [/ {1-2-3} ]
+[ternary 1 2 3]    [/ {1-2-3} ]
+
+[endsect]
+
+[/----------------------------------- Block and phrases ]
+
+[section Block and phrase templates]
+
+[template phrase_template[] Some *text*]
+[template block_template[]
+
+A <emphasis>paragraph</emphasis>.
+]
+
+[phrase_template]
+[block_template]
+[`phrase_template]
+[`block_template]
+
+[/ Trailing newline shouldn't be included]
+
+[template named_index[type title]
+'''<index type="'''[type]'''"><title>'''[title]'''</title></index>'''
+]
+
+[named_index things Things]
+
+[/ Blocks in phrase templates ]
+
+[template phrase_block1[] [table]]
+[template phrase_block2[] [table] Text2 afterwards.]
+[template phrase_block3[] Text3 before. [table]]
+[template phrase_block4[] Text4 before. [table] Text4 afterwards.]
+[template phrase_block5[] [table] * Not a list.]
+[template phrase_block6[] [table]
+* Not a list.]
+
+[phrase_block1][phrase_block2][phrase_block3][phrase_block4]
+[phrase_block5][phrase_block6]
+
+[endsect]
+
+[/-------------------------------- Skipping template body ]
+
+[section:template_body Skipping the template body correctly]
+
+[template args1[x] [`x]]
+[template args2[] [ordered_list [``code``]]]
+[/ Due to a bug in the template parser need to stop the parser
+   thinking that the code is an escaped template. ]
+[template args3[] [ordered_list [\ `code`]]]
+
+[args1 <emphasis>Argument</emphasis>]
+[args2]
+[args3]
+
+[endsect]
+
+[/----------------------------------- Escaped templates ]
+
+[section Escaped templates]
+
+[template raw_markup <thingbob>Not real boostbook</thingbob>]
+[template escaped1 [x] [`x]]
+
+[`raw_markup]
+[escaped1 <thingbob>More fake boostbook</thingbob>]
+
+[endsect]