Boost logo

Boost-Commit :

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 "&lt;"... 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(&current_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 &amp; 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 &lt;emphasis&gt;paragraph&lt;/emphasis&gt;.
- </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">&lt;&lt;</phrase> &quot;Hello, World&quot; <phrase role="special">&lt;&lt;</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>
+ &alpha;<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 &lt;emphasis&gt;paragraph&lt;/emphasis&gt;.
+ </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 '''&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">&lt;&lt;</phrase> &quot;Hello, World&quot; <phrase role="special">&lt;&lt;</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>
+ &alpha;<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 &lt;emphasis&gt;paragraph&lt;/emphasis&gt;.
+ </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 '''&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">&lt;&lt;</phrase> &quot;Hello, World&quot; <phrase role="special">&lt;&lt;</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>
+ &alpha;<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 &lt;emphasis&gt;paragraph&lt;/emphasis&gt;.
+ </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 '''&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]


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