summaryrefslogtreecommitdiff
path: root/tools/quickbook
diff options
context:
space:
mode:
Diffstat (limited to 'tools/quickbook')
-rw-r--r--tools/quickbook/doc/1_6.qbk226
-rw-r--r--tools/quickbook/doc/1_7.qbk191
-rw-r--r--tools/quickbook/doc/Jamfile.v28
-rw-r--r--tools/quickbook/doc/block.qbk191
-rw-r--r--tools/quickbook/doc/change_log.qbk83
-rw-r--r--tools/quickbook/doc/language_versions.qbk46
-rw-r--r--tools/quickbook/doc/phrase.qbk36
-rw-r--r--tools/quickbook/doc/quickbook.qbk6
-rw-r--r--tools/quickbook/doc/structure.qbk65
-rw-r--r--tools/quickbook/src/Jamfile.v212
-rw-r--r--tools/quickbook/src/actions.cpp702
-rw-r--r--tools/quickbook/src/actions.hpp138
-rw-r--r--tools/quickbook/src/block_element_grammar.cpp39
-rw-r--r--tools/quickbook/src/block_tags.hpp2
-rw-r--r--tools/quickbook/src/code_snippet.cpp49
-rw-r--r--tools/quickbook/src/dependency_tracker.cpp184
-rw-r--r--tools/quickbook/src/dependency_tracker.hpp53
-rw-r--r--tools/quickbook/src/doc_info_actions.cpp41
-rw-r--r--tools/quickbook/src/doc_info_grammar.cpp50
-rw-r--r--tools/quickbook/src/document_state.cpp472
-rw-r--r--tools/quickbook/src/document_state.hpp (renamed from tools/quickbook/src/id_manager.hpp)43
-rw-r--r--tools/quickbook/src/document_state_impl.hpp147
-rw-r--r--tools/quickbook/src/files.cpp368
-rw-r--r--tools/quickbook/src/files.hpp34
-rw-r--r--tools/quickbook/src/fwd.hpp6
-rw-r--r--tools/quickbook/src/glob.cpp301
-rw-r--r--tools/quickbook/src/glob.hpp30
-rw-r--r--tools/quickbook/src/grammar.cpp6
-rw-r--r--tools/quickbook/src/grammar.hpp5
-rw-r--r--tools/quickbook/src/grammar_impl.hpp76
-rw-r--r--tools/quickbook/src/id_generation.cpp379
-rw-r--r--tools/quickbook/src/id_manager.cpp1143
-rw-r--r--tools/quickbook/src/id_xml.cpp153
-rw-r--r--tools/quickbook/src/include_paths.cpp291
-rw-r--r--tools/quickbook/src/include_paths.hpp68
-rw-r--r--tools/quickbook/src/main_grammar.cpp672
-rw-r--r--tools/quickbook/src/markups.cpp1
-rw-r--r--tools/quickbook/src/native_text.cpp (renamed from tools/quickbook/src/input_path.cpp)40
-rw-r--r--tools/quickbook/src/native_text.hpp (renamed from tools/quickbook/src/input_path.hpp)32
-rw-r--r--tools/quickbook/src/phrase_element_grammar.cpp29
-rw-r--r--tools/quickbook/src/quickbook.cpp209
-rw-r--r--tools/quickbook/src/state.cpp136
-rw-r--r--tools/quickbook/src/state.hpp43
-rw-r--r--tools/quickbook/src/state_save.hpp23
-rw-r--r--tools/quickbook/src/string_ref.cpp37
-rw-r--r--tools/quickbook/src/string_ref.hpp89
-rw-r--r--tools/quickbook/src/syntax_highlight.cpp209
-rw-r--r--tools/quickbook/src/syntax_highlight.hpp58
-rw-r--r--tools/quickbook/src/template_tags.hpp1
-rw-r--r--tools/quickbook/src/utils.cpp59
-rw-r--r--tools/quickbook/src/utils.hpp18
-rw-r--r--tools/quickbook/src/values.cpp14
-rw-r--r--tools/quickbook/src/values.hpp6
-rw-r--r--tools/quickbook/test/Jamfile.v224
-rw-r--r--tools/quickbook/test/anchor-1_7.gold151
-rw-r--r--tools/quickbook/test/anchor-1_7.quickbook97
-rw-r--r--tools/quickbook/test/code_cpp-1_5.gold15
-rw-r--r--tools/quickbook/test/code_cpp-1_5.quickbook12
-rw-r--r--tools/quickbook/test/command-line/Jamfile.v24
-rw-r--r--tools/quickbook/test/doc-info/Jamfile.v24
-rw-r--r--tools/quickbook/test/doc-info/macros1-1_5.gold11
-rw-r--r--tools/quickbook/test/doc-info/macros1-1_5.quickbook6
-rw-r--r--tools/quickbook/test/doc-info/macros1-1_6.gold8
-rw-r--r--tools/quickbook/test/doc-info/macros1-1_6.quickbook7
-rw-r--r--tools/quickbook/test/doc-info/macros1-inc_1_6.quickbook4
-rw-r--r--tools/quickbook/test/elements-1_6.gold24
-rw-r--r--tools/quickbook/test/elements-1_6.quickbook10
-rw-r--r--tools/quickbook/test/empty-inc.quickbook (renamed from tools/quickbook/test/empty.qbk)0
-rw-r--r--tools/quickbook/test/heading-1_7.gold113
-rw-r--r--tools/quickbook/test/heading-1_7.quickbook83
-rw-r--r--tools/quickbook/test/include-1_5.quickbook14
-rw-r--r--tools/quickbook/test/include-1_6.quickbook10
-rw-r--r--tools/quickbook/test/include-1_7.gold36
-rw-r--r--tools/quickbook/test/include-1_7.quickbook18
-rw-r--r--tools/quickbook/test/include-inc-1_5.quickbook (renamed from tools/quickbook/test/include_sub-1_5.qbk)0
-rw-r--r--tools/quickbook/test/include-inc.quickbook (renamed from tools/quickbook/test/include_sub.qbk)0
-rw-r--r--tools/quickbook/test/include/Jamfile.v26
-rw-r--r--tools/quickbook/test/include/compatibility-1_1.quickbook8
-rw-r--r--tools/quickbook/test/include/compatibility-1_5.quickbook8
-rw-r--r--tools/quickbook/test/include/compatibility-1_6.quickbook8
-rw-r--r--tools/quickbook/test/include/compatibility-inc.quickbook (renamed from tools/quickbook/test/include/compatibility-inc.qbk)0
-rw-r--r--tools/quickbook/test/include/compatibility-inc_1_1.quickbook (renamed from tools/quickbook/test/include/compatibility-inc_1_1.qbk)0
-rw-r--r--tools/quickbook/test/include/compatibility-inc_1_5.quickbook (renamed from tools/quickbook/test/include/compatibility-inc_1_5.qbk)0
-rw-r--r--tools/quickbook/test/include/compatibility-inc_1_6.quickbook (renamed from tools/quickbook/test/include/compatibility-inc_1_6.qbk)0
-rw-r--r--tools/quickbook/test/include/filename-1_7.gold46
-rw-r--r--tools/quickbook/test/include/filename-1_7.quickbook21
-rw-r--r--tools/quickbook/test/include/filename_path-1_7.gold18
-rw-r--r--tools/quickbook/test/include/filename_path-1_7.quickbook7
-rw-r--r--tools/quickbook/test/include/glob-1_7.gold41
-rw-r--r--tools/quickbook/test/include/glob-1_7.quickbook39
-rw-r--r--tools/quickbook/test/include/glob1/a.qbk1
-rw-r--r--tools/quickbook/test/include/glob1/glob1-1/b.qbk1
-rw-r--r--tools/quickbook/test/include/glob2/a.qbk3
-rw-r--r--tools/quickbook/test/include/glob2/glob2-1/b.qbk1
-rw-r--r--tools/quickbook/test/include/in_section-1_5.gold28
-rw-r--r--tools/quickbook/test/include/in_section-1_5.quickbook12
-rw-r--r--tools/quickbook/test/include/in_section-1_6.gold24
-rw-r--r--tools/quickbook/test/include/in_section-1_6.quickbook12
-rw-r--r--tools/quickbook/test/include/in_section-inc1.quickbook (renamed from tools/quickbook/test/include/in_section-include1.qbk)4
-rw-r--r--tools/quickbook/test/include/in_section-inc2.quickbook (renamed from tools/quickbook/test/include/in_section-include2.qbk)4
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-1_6.quickbook4
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-inc1.quickbook (renamed from tools/quickbook/test/include/include_id_unbalanced-inc1.qbk)2
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-inc1a.quickbook (renamed from tools/quickbook/test/include/include_id_unbalanced-inc1a.qbk)0
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-inc2.quickbook (renamed from tools/quickbook/test/include/include_id_unbalanced-inc2.qbk)2
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-inc2a.quickbook (renamed from tools/quickbook/test/include/include_id_unbalanced-inc2a.qbk)0
-rw-r--r--tools/quickbook/test/include/nested_compatibility-1_5.quickbook8
-rw-r--r--tools/quickbook/test/include/nested_compatibility-1_6.quickbook8
-rw-r--r--tools/quickbook/test/include/nested_compatibility-inc-1_5.quickbook (renamed from tools/quickbook/test/include/nested_compatibility_inc-1_5.qbk)0
-rw-r--r--tools/quickbook/test/include/nested_compatibility-inc-1_6.quickbook (renamed from tools/quickbook/test/include/nested_compatibility_inc-1_6.qbk)0
-rw-r--r--tools/quickbook/test/include/source_mode-1_5.gold2
-rw-r--r--tools/quickbook/test/include/source_mode-1_5.quickbook3
-rw-r--r--tools/quickbook/test/include/source_mode-1_6.gold2
-rw-r--r--tools/quickbook/test/include/source_mode-1_6.quickbook3
-rw-r--r--tools/quickbook/test/include/source_mode-inc1.quickbook (renamed from tools/quickbook/test/include/source_mode-inc1.qbk)0
-rw-r--r--tools/quickbook/test/include/source_mode-inc2.quickbook3
-rw-r--r--tools/quickbook/test/include/template_include-1_7.gold12
-rw-r--r--tools/quickbook/test/include/template_include-1_7.quickbook8
-rw-r--r--tools/quickbook/test/include2-1_6.quickbook6
-rw-r--r--tools/quickbook/test/include_invalid_path1-1_7-fail.quickbook5
-rw-r--r--tools/quickbook/test/include_invalid_path2-1_7-fail.quickbook5
-rw-r--r--tools/quickbook/test/include_invalid_path3-1_7-fail.quickbook5
-rw-r--r--tools/quickbook/test/include_unicode_glob-1_7-fail.quickbook5
-rw-r--r--tools/quickbook/test/include_win_path-1_6-fail.quickbook2
-rw-r--r--tools/quickbook/test/link-1_1.gold11
-rw-r--r--tools/quickbook/test/link-1_1.quickbook7
-rw-r--r--tools/quickbook/test/link-1_6.gold11
-rw-r--r--tools/quickbook/test/link-1_6.quickbook7
-rw-r--r--tools/quickbook/test/link-1_7-fail.quickbook5
-rw-r--r--tools/quickbook/test/link-1_7-fail2.quickbook6
-rw-r--r--tools/quickbook/test/link-1_7.gold18
-rw-r--r--tools/quickbook/test/link-1_7.quickbook15
-rw-r--r--tools/quickbook/test/list_test-1_6-fail.quickbook46
-rw-r--r--tools/quickbook/test/list_test-1_6.gold160
-rw-r--r--tools/quickbook/test/list_test-1_6.quickbook49
-rw-r--r--tools/quickbook/test/list_test-1_7-fail1.quickbook9
-rw-r--r--tools/quickbook/test/list_test-1_7.gold479
-rw-r--r--tools/quickbook/test/list_test-1_7.quickbook134
-rw-r--r--tools/quickbook/test/mismatched_brackets3-1_1.gold12
-rw-r--r--tools/quickbook/test/mismatched_brackets3-1_1.quickbook6
-rw-r--r--tools/quickbook/test/python/include_glob.qbk11
-rw-r--r--tools/quickbook/test/python/include_glob_deps.txt6
-rw-r--r--tools/quickbook/test/python/include_glob_locs.txt9
-rw-r--r--tools/quickbook/test/python/include_path.qbk8
-rw-r--r--tools/quickbook/test/python/include_path_deps.txt3
-rw-r--r--tools/quickbook/test/python/include_path_locs.txt3
-rw-r--r--tools/quickbook/test/python/missing_relative.qbk8
-rw-r--r--tools/quickbook/test/python/missing_relative_deps.txt3
-rw-r--r--tools/quickbook/test/python/missing_relative_locs.txt3
-rw-r--r--tools/quickbook/test/python/output-deps.py38
-rw-r--r--tools/quickbook/test/python/sub1/a.qbk8
-rw-r--r--tools/quickbook/test/python/sub2/b.qbk8
-rw-r--r--tools/quickbook/test/python/svg_missing.qbk8
-rw-r--r--tools/quickbook/test/python/svg_missing_deps.txt3
-rw-r--r--tools/quickbook/test/python/svg_missing_locs.txt3
-rw-r--r--tools/quickbook/test/role-1_7-fail.quickbook5
-rw-r--r--tools/quickbook/test/role-1_7.gold13
-rw-r--r--tools/quickbook/test/role-1_7.quickbook13
-rw-r--r--tools/quickbook/test/section-1_7.gold26
-rw-r--r--tools/quickbook/test/section-1_7.quickbook18
-rw-r--r--tools/quickbook/test/snippets/Jamfile.v22
-rw-r--r--tools/quickbook/test/snippets/unbalanced_snippet1.cpp10
-rw-r--r--tools/quickbook/test/snippets/unbalanced_snippet2.cpp11
-rw-r--r--tools/quickbook/test/source_mode-1_7.gold27
-rw-r--r--tools/quickbook/test/source_mode-1_7.quickbook14
-rw-r--r--tools/quickbook/test/table-1_7.gold520
-rw-r--r--tools/quickbook/test/table-1_7.quickbook151
-rw-r--r--tools/quickbook/test/templates-1_3.gold23
-rw-r--r--tools/quickbook/test/templates-1_3.quickbook16
-rw-r--r--tools/quickbook/test/templates-1_4.gold7
-rw-r--r--tools/quickbook/test/templates-1_4.quickbook18
-rw-r--r--tools/quickbook/test/templates-1_5.gold269
-rw-r--r--tools/quickbook/test/templates-1_5.quickbook255
-rw-r--r--tools/quickbook/test/templates-1_6-fail1.quickbook8
-rw-r--r--tools/quickbook/test/templates-1_6.gold257
-rw-r--r--tools/quickbook/test/templates-1_6.quickbook313
-rw-r--r--tools/quickbook/test/templates-1_7-fail1.quickbook12
-rw-r--r--tools/quickbook/test/templates-1_7-fail2.quickbook11
-rw-r--r--tools/quickbook/test/templates-1_7.gold302
-rw-r--r--tools/quickbook/test/templates-1_7.quickbook322
-rw-r--r--tools/quickbook/test/unit/Jamfile.v26
-rw-r--r--tools/quickbook/test/unit/glob_test.cpp122
-rw-r--r--tools/quickbook/test/unit/source_map_test.cpp395
-rw-r--r--tools/quickbook/test/unit/values_test.cpp6
-rw-r--r--tools/quickbook/test/versions/Jamfile.v22
-rw-r--r--tools/quickbook/test/versions/invalid_macro-1_6.quickbook4
-rw-r--r--tools/quickbook/test/versions/invalid_macro-inc-1_1.quickbook (renamed from tools/quickbook/test/versions/invalid_macro-inc-1_1.qbk)0
-rw-r--r--tools/quickbook/test/versions/templates-inc-1_1.quickbook (renamed from tools/quickbook/test/versions/templates-1_1.qbk)0
-rw-r--r--tools/quickbook/test/versions/templates-inc-1_4.quickbook (renamed from tools/quickbook/test/versions/templates-1_4.qbk)0
-rw-r--r--tools/quickbook/test/versions/templates-inc-1_5.quickbook (renamed from tools/quickbook/test/versions/templates-1_5.qbk)0
-rw-r--r--tools/quickbook/test/versions/versions-1_6.quickbook12
-rw-r--r--tools/quickbook/test/xinclude/Jamfile.v22
-rw-r--r--tools/quickbook/test/xinclude/sub/boost-no-inspect2
192 files changed, 9657 insertions, 2962 deletions
diff --git a/tools/quickbook/doc/1_6.qbk b/tools/quickbook/doc/1_6.qbk
index 89c41f2ac0..7a10cb1298 100644
--- a/tools/quickbook/doc/1_6.qbk
+++ b/tools/quickbook/doc/1_6.qbk
@@ -1,50 +1,54 @@
[/
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.6]
- [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`.
+[section:1_6 Quickbook 1.6]
-[heading Quickbook 1.5 and later]
+Upgrading a document from an earlier version of quickbook shouldn't be too
+hard. The first thing to do is update the version in the docinfo block.
+For example, if you were updating the Xpressive documentation, the existing
+docinfo block looks like:
-* 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.
+ [library Boost.Xpressive
+ [quickbook 1.3]
+ ...
+ ]
-[endsect]
+Change this to:
-[section:1_6 Quickbook 1.6]
+ [library Boost.Xpressive
+ [quickbook 1.6]
+ [compatibility-mode 1.3]
+ ...
+ ]
-Everything described in here may change depending on the feedback received.
+The =compatibility-mode= tag ensures that automatically generated links
+won't change. It might turn out that it isn't required, but in Xpressive's
+case if it isn't included it will break a lot of links.
+
+Then try building it. You might need to fix some stray square brackets. The
+new version has a stricter parser which will have an error for brackets
+which don't pair up. They might be there by mistake, in which case they
+should probably be deleted, or if they're intentional escaped. For example,
+to write out the half-open range \[a,b), use: `\[a,b)`.
+
+Next, you might need to reconsider how templates and macros are defined.
+If you `include` a file to use its templates, you'll now need to `import` it
+instead as templates are now scoped by included files. Also, if you define
+templates and macros in your main quickbook file, you might want to put them
+into a separate file and `import` that, which allows the main documentation
+files to concentrate on the structure and contents of the document, making them
+easier to read.
+
+Now that headings can have ids, it can be a good idea to add ids to existing
+headings. This means that the headings will have more predictable ids which
+don't change when the text of the heading changes. In order to preserve
+links you can use the existing generated id as the heading.
[section:docinfo Includes with docinfo]
@@ -70,6 +74,19 @@ before.
[endsect] [/docinfo]
+[section:doc_info_macros Macros in docinfo block]
+
+You can now expand macros in text fields in the docinfo block. In the top
+docinfo block only the predefined macros are available, but in nested documents
+macros defined in the parent document are also available.
+
+There's a small bug here - this leaks into older versions for the `license`
+and `purpose` fields, but since only the predefined macros are available, it's
+unlikely to break any existing documents. So I'd rather not complicate the code
+further by fixing that.
+
+[endsect]
+
[section:scope Scoping templates and macros]
A long standing quickbook bug is that macros are scoped by file, but templates
@@ -233,131 +250,38 @@ if you're totally sure that you will need it.
[endsect] [/xmlbase]
-[section:elements New Elements]
-
-New elements in 1.6 (to be documented later):
-
-* `block`
-* `ordered_list`
-* `itemized_list`
-* `role`
-
-[endsect]
-
-[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
+[section:template_parser Improved template parser]
- Para 2
- * Nested Para 1
+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:
- Nested Para 2
-
- Code block
- Para 3
-
-The docbook markup that this generates is pretty bad, but seems to create okay
-html.
-
-[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]
+ [template doesnt_work[]
+ [ordered_list
+ [`code phrase`]
+ ]
+ ]
-[section:callouts Callouts in code block]
+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:
-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.
+ [template works[]
+ [ordered_list
+ [\ `code phrase`]
+ ]
+ ]
[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@example.com</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:templates_in_link_values Templates in link values]
+[section:elements New Elements]
-There's very premilinary support for calling templates in link values. A lot
-more work needs to be done, including:
+New elements added in quickbook 1.6:
-* 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.
+* [link quickbook.ref.block `block`]
+* [link quickbook.ref.list_tags `ordered_list` and `itemized_list`]
+* [link quickbook.ref.role `role`]
-[endsect] [/templates_in_link_values]
+[endsect] [/ elements]
-[endsect] [/ Quickbok 1.7]
+[endsect] [/ Quickbok 1.6]
diff --git a/tools/quickbook/doc/1_7.qbk b/tools/quickbook/doc/1_7.qbk
new file mode 100644
index 0000000000..745247fe45
--- /dev/null
+++ b/tools/quickbook/doc/1_7.qbk
@@ -0,0 +1,191 @@
+[/
+ 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 whole section.
+
+If it appears at the beginning of a paragraph, it will be used for the
+whole paragraph only if there's a newline, eg.
+
+```
+[!c++]
+A declaration `void foo();` and a definition `void foo() {}`.
+```
+
+[endsect]
+
+[section:callouts Callouts in code blocks]
+
+Currently callouts can only be used in code snippets. 1.7 adds
+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. To allow more flexible markup that is 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@example.com</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 with markup generated from
+quickbook. A mixture
+of quickbook and docbook attributes for the same information will not work
+well.
+
+[endsect] [/escaped_docinfo_attributes]
+
+[section:listparagraphs Pargraphs in lists]
+
+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
+
+[endsect]
+
+[section:templates_in_attributes Templates in some attributes]
+
+There's support for calling templates in link values, anchors, roles and
+includes. This is sometimes a bit of a change, especially in places where
+spaces are currently allowed, so I might try using a slightly different
+grammar where required. I think I also need to add some validation, since
+the parser can allow more symbols than some of the old ones.
+
+[endsect] [/templates_in_attributes]
+
+[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]
+
+[section:glob Including multiple files with Globs]
+
+One can now include multiple files at once using a glob pattern for the
+file reference:
+
+ [include sub/*/*.qbk]
+ [include include/*.h]
+
+All the matching files, and intermediate irectories, will match and be
+included. The glob pattern can be "\*" for matching zero or more characters,
+"?" for matching a single character, "\[<c>-<c>\]" to match a character class,
+"\[\^<char>-<char>\]" to exclusive match a character class, "\\\\" to escape
+a glob special character which is then matched, and anything else is matched
+to the character.
+
+[note Because of the escaping in file references the "\\\\" glob escape is
+a double "\\"; i.e. and escaped back-slash.]
+
+[endsect]
+
+[endsect] [/ Quickbok 1.7]
diff --git a/tools/quickbook/doc/Jamfile.v2 b/tools/quickbook/doc/Jamfile.v2
index f2f11f09eb..bfa7591578 100644
--- a/tools/quickbook/doc/Jamfile.v2
+++ b/tools/quickbook/doc/Jamfile.v2
@@ -8,7 +8,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
#==============================================================================
-project boost/quickbook/doc ;
+project quickbook/doc ;
using boostbook ;
using quickbook ;
@@ -21,7 +21,11 @@ boostbook standalone
:
quickbook
:
- <xsl:param>boost.root=../../../..
+ <format>html:<xsl:param>boost.root=../../../..
+ <format>html:<xsl:param>img.src.path=../../../../doc/html/
+ <format>xhtml:<xsl:param>boost.root=../../../..
+ <format>xhtml:<xsl:param>img.src.path=../../../../doc/html/
+
#<xsl:param>callout.graphics.path=../../images/callouts//
<format>pdf:<xsl:param>img.src.path=$(images)/
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
diff --git a/tools/quickbook/doc/block.qbk b/tools/quickbook/doc/block.qbk
index c6765131f7..1be2041b37 100644
--- a/tools/quickbook/doc/block.qbk
+++ b/tools/quickbook/doc/block.qbk
@@ -26,6 +26,38 @@ You can include another XML file with:
This is useful when file.xml has been generated by Doxygen and contains your
reference section.
+=xinclude= paths are normally used unchanged in the generated documentation,
+which will not work if you wish them to be relative to the current quickbook
+file. Quickbook can add a =xml:base= attribute to the boostbook documentation
+to specify where =xinclude= files should be found. For example, if you wish
+them to be relative to the current quickbook file:
+
+ [article Article with xincludes
+ [quickbook 1.6]
+ [xmlbase .]
+ ]
+
+ [xinclude file.xml]
+
+Now the xinclude should work if =file.xml= is in the same directory as the
+quickbook file. Although it might not work if you distribute the generated
+files (as their relative directories can change).
+
+Say the article is generated in a sub-directory, by running something like:
+
+ quickbook article.qbk --output-file=output/article.xml
+
+This will generate a boostbook root tag:
+
+ <article id="article_with_xincludes"
+ last-revision="$Date: 2013/08/20 08:26:48 $"
+ xml:base=".."
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+Because =xml:base= is set to =..=, the xml processor will know to look in
+the parent directory to find =file.xml=, which it comes across the
+=xi:include= tag.
+
[endsect] [/xinclude]
[#quickbook.ref.paragraphs]
@@ -190,6 +222,31 @@ will generate:
* 2.b.2.b
[endsect] [/mixed_lists]
+
+[#quickbook.ref.list_tags]
+[section:list_tags Explicit list tags]
+
+Sometimes the wiki-style list markup can be tricky to use, especially
+if you wish to include more complicated markup with the list. So in
+quickbook 1.6, an alternative way to mark up lists introduced:
+
+ [ordered_list [item1][item2]]
+
+is equivalent to:
+
+ # item1
+ # item2
+
+And:
+
+ [itemized_list [item1][item2]]
+
+is equivalent to:
+
+ * item1
+ * item2
+
+[endsect] [/list_tags]
[endsect] [/lists]
[#quickbook.ref.code]
@@ -356,8 +413,23 @@ to produce the desired effect.
[h5 Heading 5]
[h6 Heading 6]
-Headings 1-3 \[h1 h2 and h3\] will automatically have anchors with
-normalized names with
+You can specify an id for a heading:
+
+```
+[h1:heading_id A heading to link to]
+```
+
+To link to it, you'll need to include the enclosing section's id:
+
+```
+[link document_id.section_id.heading_id The link text]
+```
+
+Although you can preceed a heading by an [link quickbook.ref.anchors anchor]
+if you wish to use a location independent link.
+
+If a heading doesn't have an id, one will be automatically generated
+with a normalized name with
[^name="document_id.section_id.normalized_header_text"] (i.e. valid
characters are =a-z=, =A-Z=, =0-9= and =_=. All non-valid characters are
converted to underscore and all upper-case are converted to lower-case.
@@ -370,6 +442,9 @@ For example: Heading 1 in section Section 2 will be normalized to
to link to them. See __anchor_links__ and __section__ for more info.
+[note Specifying heading ids is a quickbook 1.6 feature, earlier
+ versions don't support them.]
+
[endsect] [/headings]
[#quickbook.ref.generic_heading]
@@ -393,7 +468,7 @@ however, headings in a particular section is just flat. Example:
```
[section A]
[h2 X]
-[h2 Y]
+[h2:link_id Y]
[h2 Z]
[endsect]
```
@@ -965,17 +1040,25 @@ You can include one QuickBook file from another. The syntax is simply:
[include someother.qbk]
```
-The included file will be processed as if it had been cut and pasted
+In quickbook 1.6 and later, if the included file has a
+[link quickbook.ref.docinfo docinfo block] then it will create a nested
+document. This will be processed as a standalone document, although any macros
+or templates from the enclosing file will still be defined.
+
+Otherwise the included file will be processed as if it had been cut and pasted
into the current document, with the following exceptions:
* The '''__FILENAME__''' predefined macro will reflect the name of the
file currently being processed.
-* Any macros defined in the included file are scoped to that file.
+* Any macros or templates defined in the included file are scoped to that file,
+ i.e. they are not added to the enclosing file.
+
+[note In quickbook 1.5 and earlier templates weren't scoped in included files.
+If you want to use templates or macros from a file in quickbook 1.6,
+use [link quickbook.ref.import import] instead.]
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]
@@ -986,11 +1069,70 @@ for instance, if there is a top section in someother.qbk named "Intro", the
named anchor for that section will be "someid.intro", and you can link to
it with [^\[link someid.intro The Intro\]].
+If the included file has a docinfo block, an id specified in an [^\[include\]]
+directive will overwrite it.
+
+You can also include C, C++ and python source files. This will include any
+quickbook blocks in the file that aren't inside of named code snippets. See
+the [link quickbook.ref.import Import section] for syntax details. For example,
+say you included this file:
+
+ /**
+ * Hello world example
+ */
+
+ // In this comment, the backtick indicates that this is a
+ // quickbook source block that will be included.
+
+ /*`
+ First include the appropriate header: [hello_includes]
+ Then write your main function: [hello_main]
+ */
+
+ // This defines a code snippet, the syntax is
+ // described in the import section. It's available
+ // in the whole of this source file, not just after
+ // its definition.
+
+ //[hello_includes
+ #include <iostream>
+ //]
+
+ //[hello_main
+ int main() {
+ std::cout << "Hello, trivial example" << std::endl;
+ }
+ //]
+
+It will generate:
+
+ First include the appropriate header:
+
+ #include <iostream>
+
+ Then write your main function:
+
+ int main() {
+ std::cout << "Hello, trivial example" << std::endl;
+ }
+
[endsect] [/include]
[#quickbook.ref.import]
[section:import Import]
+In quickbook 1.6 and later if you wish to use a template, macro or code
+snippet from a file, you need to import it. This will not include any
+of the content from that file, but will pull templates, macros and code
+snippets into the current file's scope.
+
+With quickbook files, this allows you to create template and macro
+libraries. For python (indicated by the `.py` extension), C or
+C++ files this allows you to include code snippets from source files,
+so that your code examples can be kept up to date and fully tested.
+
+[/ Old justification text, might move this into a new section:
+
When documenting code, you'd surely need to present code from actual source
files. While it is possible to copy some code and paste them in your QuickBook
file, doing so is error prone and the extracted code in the documentation tends
@@ -999,6 +1141,7 @@ always, is that once documentation is written, the tendency is for the docs to
languish in the archives without maintenance.
QuickBook's import facility provides a nice solution.
+]
[heading Example]
@@ -1132,6 +1275,36 @@ Example:
[class_]
-See the actual code here: [@boost:/tools/quickbook/test/stub.cpp]
+See the actual code here:
+[@boost:/tools/quickbook/test/stub.cpp tools/quickbook/test/stub.cpp]
[endsect] [/import]
+
+[#quickbook.ref.block]
+[section:block Plain blocks]
+
+`block` is a plain block element, that doesn't wrap its contents
+in any docbook or boostbook tags. This can be useful when using
+escaped docbook block tags, such as:
+
+ [template chapter[title]
+ [block'''<chapter><title>'''[title]'''</title>''']
+ ]
+
+ [template chapterend
+ [block'''</chapter>''']
+ ]
+
+ [chapter An example chapter]
+
+ Content
+
+ [chapterend]
+
+Without the `block` element, the `chapter` and `chapterend` templates
+would be wrapped in paragraph tags.
+
+[note In this example, the template body has to start with a newline so that
+the template will be interpreted in block mode.]
+
+[endsect] [/block]
diff --git a/tools/quickbook/doc/change_log.qbk b/tools/quickbook/doc/change_log.qbk
index 96fa45dec3..a4942c2632 100644
--- a/tools/quickbook/doc/change_log.qbk
+++ b/tools/quickbook/doc/change_log.qbk
@@ -248,3 +248,86 @@ Boost 1.46.1:
block (`quickbook`, `compatibility-mode`, `source-mode`).
* Only add explicit alt text to images.
* Don't put 'inline' code blocks inside paragraphs.
+
+[heading Version 1.5.8 - Boost 1.50]
+
+* Write dependencies to a file, using `--output-deps`
+ ([@https://svn.boost.org/trac/boost/ticket/6691 #6691]).
+* Fix handling of section tags in lists.
+* Fix indented code blocks in lists.
+* Fix handling UTF-8 code points in the syntax highlighter.
+ Was treating each individual byte as a character.
+ Still doesn't deal with combining code points.
+* Internal changes:
+ * A lot of restructuring.
+ * Stop using 'v3' filesystem paths and namespaces, it's now
+ the default version.
+ * Remove awkward intrusive reference counting implementation,
+ avoids a gcc internal compiler error
+ ([@http://svn.boost.org/trac/boost/ticket/6794 #6794]),
+ but is also a cleaner implementation.
+* 1.6 changes:
+ * Better handling of brackets in link values.
+ * Improved handling of escaped characters in include paths.
+* Starting to develop 1.7:
+ * Source mode for single entities.
+ * Callouts in code blocks.
+ * Escaped docbook in docinfo blocks.
+ * Starting to implement calling templates from link values.
+
+[heading Version 1.5.9 - Boost 1.54]
+
+* When code blocks are indented using a mixture of tabs and spaces,
+ convert indentation to spaces.
+* In the C++ systax highlighter, fix syntax highlighting for `#`, so that it's
+ used for preprocessor statements at the start of a line, and as a 'special'
+ character elsewhere
+ ([@https://svn.boost.org/trac/boost/ticket/8510 #8510],
+ [@https://svn.boost.org/trac/boost/ticket/8511 #8511]).
+* Add C++11 keywords to syntax highlighter
+ ([@https://svn.boost.org/trac/boost/ticket/8541 #8541]).
+* Hidden options for formatting of `--output-deps`. Not really for public use
+* yet.
+* 1.6 changes:
+ * Better template argument parsing, so that it understands things
+ like escaped markup.
+ * Support for using macros in the doc info block.
+* Internal changes:
+ * Convert to use `boost::string_ref`.
+ * Clean up the source map implementation (used to get the correct
+ location for error messages in things like templates and snippets).
+
+[heading Version 1.6.0 - Boost 1.55]
+
+* Remove nested blocks in lists from 1.6, move to 1.7.
+ (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.
+* Fix detection of code blocks at the start of a file.
+* XML encode the contents of the `__FILENAME__` macro.
+* 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.
+
+[heading Version 1.6.1]
+
+* Better URI encoding of links.
+* Extra validation of attribute values.
+* 1.7 changes:
+ * Improved source mode tagging:
+ * Works for lists and paragraphs.
+ * If the source mode is changed inside a tagged element, that change
+ will now persist after the element.
+ * Tagged sections will now use the source mode for the whole section.
+ * Template calls from anchor, role and include elements.
+ * Stricter handling of templates called in attribute values.
+ * Glob support.
diff --git a/tools/quickbook/doc/language_versions.qbk b/tools/quickbook/doc/language_versions.qbk
new file mode 100644
index 0000000000..df9089dc53
--- /dev/null
+++ b/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]
diff --git a/tools/quickbook/doc/phrase.qbk b/tools/quickbook/doc/phrase.qbk
index f6f8859798..2cdf57b18b 100644
--- a/tools/quickbook/doc/phrase.qbk
+++ b/tools/quickbook/doc/phrase.qbk
@@ -165,6 +165,42 @@ And one for the little boy who lives down the lane.
[endsect] [/simple_formatting]
+[#quickbook.ref.role]
+[section:role Role]
+
+This generates a docbook phrase with a `role` attribute, which can be used
+to classify the phrase. This can be used to mark text for a use that isn't
+covered elsewhere. The docbook `role` will generate a html class, which can
+be used to style text. And the xsl stylesheets can be customized to treat
+certain roles specially when generating pdfs.
+
+The boostbook css stylesheets, and xsl stylesheets
+contain support for a limited number of colours that can be used with
+`role`. For example if you write:
+
+ [role red Text content]
+
+You'll get red text if you're using the boostbook css (for html) or
+the boostbook xsl for generating pdfs.
+
+The full list of colours that will be available is:
+
+* [role red red]
+* [role green green]
+* [role lime lime]
+* [role blue blue]
+* [role navy navy]
+* [role yellow yellow]
+* [role magenta magenta]
+* [role indigo indigo]
+* [role cyan cyan]
+* [role purple purple]
+* [role gold gold]
+* [role silver silver]
+* [role gray gray]
+
+[endsect] [/role]
+
[#quickbook.ref.inline_code]
[section:inline_code Inline code]
diff --git a/tools/quickbook/doc/quickbook.qbk b/tools/quickbook/doc/quickbook.qbk
index ea988f9e2f..2c8de9fb92 100644
--- a/tools/quickbook/doc/quickbook.qbk
+++ b/tools/quickbook/doc/quickbook.qbk
@@ -11,7 +11,7 @@
[quickbook 1.6]
[compatibility-mode 1.5]
[id quickbook]
- [version 1.5]
+ [version 1.6]
[authors [de Guzman, Joel], [Niebler, Eric]]
[copyright 2002 2004 2006 Joel de Guzman, Eric Niebler]
[copyright 2010-2011 Daniel James]
@@ -87,8 +87,8 @@
[include structure.qbk]
[include phrase.qbk]
[include block.qbk]
-[include 1_6.qbk]
+[include language_versions.qbk]
[include install.qbk]
[include editors.qbk]
[include faq.qbk]
-[include ref.qbk] \ No newline at end of file
+[include ref.qbk]
diff --git a/tools/quickbook/doc/structure.qbk b/tools/quickbook/doc/structure.qbk
index c9a4be9c33..4e9bfb4f0b 100644
--- a/tools/quickbook/doc/structure.qbk
+++ b/tools/quickbook/doc/structure.qbk
@@ -82,13 +82,37 @@ They are all optional.
[heading Quickbook specific meta data]
```
- [quickbook 1.5]
+ [quickbook 1.6]
```
The `quickbook` attribute declares the version of quickbook
the document is written for.
In its absence, version 1.1 is assumed. It's recommended that
-you use `[quickbook 1.5]` which is the version described here.
+you use `[quickbook 1.6]` which is the version described here.
+
+[note
+
+The quickbook version also makes some changes to the markup
+that's generated. Most notably, the ids that are automatically
+for headers and sections are different in later versions. To
+minimise disruption, you can use the =compatibility-mode=
+attribute to generate similar markup to the old version:
+
+```
+[article Article that was original
+ written in quickbook 1.3
+[quickbook 1.6]
+[compatibility-mode 1.3]
+]
+```
+
+This feature shouldn't be used for new documents, just for
+porting old documents to the new version.
+]
+
+Both the =quickbook= and =compatibility-mode= tags can be used
+at the start of the file, before the document info block, and
+also in files that don't have a document info block.
```
[source-mode teletype]
@@ -144,6 +168,43 @@ that's just ignored by the style sheets.
[endsect] [/attributes]
+[section:nesting Nesting quickbook documents]
+
+Docinfo blocks can only appear at the beginning of a quickbook file, so to
+create a more complicated document you need to use several quickbook files and
+use the [link quickbook.ref.include include tag] to nest them. For example, say
+you wish to create a book with an introduction and a chapter, you first create
+a file for the book:
+
+ [book Simple example
+ [quickbook 1.6]
+ ]
+
+ [include introduction.qbk]
+ [include chapter.qbk]
+
+[note Structuring a document like this was introduced in quickbook 1.6, so the
+`[quickbook 1.6]` docinfo field is required.]
+
+The appropriate document type for an introduction is `preface`, so
+the contents of `introduction.qbk` should be something like:
+
+ [preface Introduction
+ [quickbook 1.6]
+ ]
+
+ Write the introduction to the book here....
+
+And `chapter.qbk`:
+
+ [chapter A chapter
+ [quickbook 1.6]
+ ]
+
+ Chapter contents....
+
+[endsect] [/nesting]
+
[endsect] [/docinfo]
[#quickbook.ref.section]
diff --git a/tools/quickbook/src/Jamfile.v2 b/tools/quickbook/src/Jamfile.v2
index 0c55c7ae8b..8d847123e8 100644
--- a/tools/quickbook/src/Jamfile.v2
+++ b/tools/quickbook/src/Jamfile.v2
@@ -15,8 +15,6 @@ project quickbook
<toolset>gcc:<cflags>-g0
<toolset>darwin:<cflags>-g0
<toolset>msvc:<cflags>/wd4709
- <toolset>gcc:<define>BOOST_DETAIL_CONTAINER_FWD
- <toolset>darwin:<define>BOOST_DETAIL_CONTAINER_FWD
;
lib shell32 ;
@@ -27,12 +25,16 @@ exe quickbook
actions.cpp
doc_info_actions.cpp
state.cpp
+ dependency_tracker.cpp
utils.cpp
files.cpp
- string_ref.cpp
- input_path.cpp
+ native_text.cpp
+ glob.cpp
+ include_paths.cpp
values.cpp
- id_manager.cpp
+ document_state.cpp
+ id_generation.cpp
+ id_xml.cpp
post_process.cpp
collector.cpp
template_stack.cpp
diff --git a/tools/quickbook/src/actions.cpp b/tools/quickbook/src/actions.cpp
index 304663ffe1..1ada175942 100644
--- a/tools/quickbook/src/actions.cpp
+++ b/tools/quickbook/src/actions.cpp
@@ -23,16 +23,18 @@
#include <boost/foreach.hpp>
#include "quickbook.hpp"
#include "actions.hpp"
+#include "syntax_highlight.hpp"
#include "utils.hpp"
#include "files.hpp"
#include "markups.hpp"
#include "state.hpp"
#include "state_save.hpp"
#include "grammar.hpp"
-#include "input_path.hpp"
+#include "native_text.hpp"
#include "block_tags.hpp"
#include "phrase_tags.hpp"
-#include "id_manager.hpp"
+#include "document_state.hpp"
+#include "include_paths.hpp"
namespace quickbook
{
@@ -41,12 +43,12 @@ namespace quickbook
{
// TODO: This works but is a bit of an odd place to put it.
// Might need to redefine the purpose of this function.
- if (!state.source_mode_next.empty()) {
- detail::outwarn(state.source_mode_next.get_file(),
- state.source_mode_next.get_position())
+ if (state.source_mode_next) {
+ detail::outwarn(state.source_mode_next_pos.get_file(),
+ state.source_mode_next_pos.get_position())
<< "Temporary source mode unsupported here."
<< std::endl;
- state.source_mode_next = value();
+ state.source_mode_next = 0;
}
for(quickbook::state::string_list::iterator
@@ -63,14 +65,62 @@ namespace quickbook
}
std::string add_anchor(quickbook::state& state,
- std::string const& id,
+ boost::string_ref id,
id_category::categories category =
id_category::explicit_anchor_id)
{
- std::string placeholder = state.ids.add_anchor(id, category);
+ std::string placeholder = state.document.add_anchor(id, category);
state.anchors.push_back(placeholder);
return placeholder;
}
+
+ std::string get_attribute_value(quickbook::state& state,
+ quickbook::value const& value)
+ {
+ std::string x = value.is_encoded() ?
+ value.get_encoded() : detail::to_s(value.get_quickbook());
+
+ if (x.empty()) {
+ detail::outerr(value.get_file(), value.get_position())
+ << "Empty attribute value."
+ << std::endl;
+ ++state.error_count;
+ x = "xxx";
+ }
+
+ return x;
+ }
+
+ std::string validate_id(quickbook::state& state,
+ quickbook::value const& id_value)
+ {
+ bool valid = true;
+ std::string id = get_attribute_value(state, id_value);
+
+ // Special case since I use dollar ids for id placeholders.
+ if (id[0] == '$') { valid = false; id[0] = '_'; }
+
+ if (qbk_version_n >= 107u) {
+ char const* allowed_punctuation = "_.-";
+
+ BOOST_FOREACH(char c, id) {
+ if (!std::isalnum(c) &&
+ !std::strchr(allowed_punctuation, c))
+ valid = false;
+ }
+ }
+
+ if (!valid) {
+ detail::outerr(id_value.get_file(), id_value.get_position())
+ << "Invalid id: "
+ << (id_value.is_encoded() ? id_value.get_encoded() :
+ detail::to_s(id_value.get_quickbook()))
+ << std::endl;
+ ++state.error_count;
+ }
+
+ return id;
+ }
}
bool quickbook_range::in_range() const {
@@ -189,6 +239,7 @@ namespace quickbook
case code_tags::inline_code_block:
case code_tags::inline_code:
return code_action(state, v);
+ case template_tags::attribute_template:
case template_tags::template_:
return do_template_action(state, v, first.base());
default:
@@ -198,7 +249,7 @@ namespace quickbook
void break_action::operator()(parse_iterator first, parse_iterator) const
{
- write_anchors(state, phrase);
+ write_anchors(state, state.phrase);
if(*first == '\\')
{
@@ -216,7 +267,7 @@ namespace quickbook
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
@@ -273,19 +324,23 @@ namespace quickbook
values.finish();
}
- void role_action(quickbook::state& state, value role)
+ void role_action(quickbook::state& state, value role_list)
{
write_anchors(state, state.phrase);
- value_consumer values = role;
+ value_consumer values = role_list;
+ value role = values.consume();
+ value phrase = values.consume();
+ values.finish();
+
state.phrase
<< "<phrase role=\"";
- detail::print_string(values.consume().get_quickbook(), state.phrase.get());
+ detail::print_string(get_attribute_value(state, role),
+ state.phrase.get());
state.phrase
<< "\">"
- << values.consume().get_encoded()
+ << phrase.get_encoded()
<< "</phrase>";
- values.finish();
}
void footnote_action(quickbook::state& state, value phrase)
@@ -295,7 +350,7 @@ namespace quickbook
value_consumer values = phrase;
state.phrase
<< "<footnote id=\""
- << state.ids.add_id("f", id_category::numbered)
+ << state.document.add_id("f", id_category::numbered)
<< "\"><para>"
<< values.consume().get_encoded()
<< "</para></footnote>";
@@ -322,27 +377,18 @@ namespace quickbook
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
@@ -358,7 +404,7 @@ namespace quickbook
{
state.out << "<bridgehead renderas=\"sect" << level << "\"";
state.out << " id=\"";
- state.out << state.ids.add_id("h", id_category::numbered);
+ state.out << state.document.add_id("h", id_category::numbered);
state.out << "\">";
state.out << "<phrase id=\"" << id << "\"/>";
state.out << "<link linkend=\"" << id << "\">";
@@ -390,7 +436,7 @@ namespace quickbook
if (generic)
{
- level = state.ids.section_level() + 1;
+ level = state.document.section_level() + 1;
// We need to use a heading which is one greater
// than the current.
if (level > 6 ) // The max is h6, clip it if it goes
@@ -405,47 +451,63 @@ namespace quickbook
if (!element_id.empty())
{
- std::string anchor = state.ids.add_id(
- element_id.get_quickbook(),
+ // Use an explicit id.
+
+ std::string anchor = state.document.add_id(
+ validate_id(state, element_id),
id_category::explicit_id);
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.document.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.document.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.document.replace_placeholders_with_unresolved_ids(
+ content.get_encoded()));
+
+ if (generic || state.document.compatibility_version() >= 103) {
+ std::string anchor =
+ state.document.add_id(id, id_category::generated_heading);
+
+ write_bridgehead(state, level,
+ content.get_encoded(), anchor, self_linked_headers);
+ }
+ else {
+ std::string anchor =
+ state.document.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 +523,9 @@ namespace quickbook
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()
@@ -474,14 +536,13 @@ namespace quickbook
if (saved_conditional)
{
- string_ref macro1 = values.consume().get_quickbook();
+ boost::string_ref macro1 = values.consume().get_quickbook();
std::string macro(macro1.begin(), macro1.end());
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,38 +554,23 @@ namespace quickbook
{
if (saved_conditional && !state.conditional)
{
- state.phrase.pop();
- state.out.pop();
+ state.pop_output();
state.anchors.swap(anchors);
}
state.conditional = saved_conditional;
}
- namespace {
- int indent_length(std::string const& indent)
- {
- int length = 0;
- for(std::string::const_iterator
- first = indent.begin(), end = indent.end(); first != end; ++first)
- {
- switch(*first) {
- case ' ': ++length; break;
- // hardcoded tab to 4 for now
- case '\t': length = ((length + 4) / 4) * 4; break;
- default: BOOST_ASSERT(false);
- }
- }
-
- return length;
- }
- }
-
void state::start_list(char mark)
{
- write_anchors(*this, out);
+ push_tagged_source_mode(source_mode_next);
+ source_mode_next = 0;
+
+ 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,23 +578,35 @@ namespace quickbook
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;
+
+ pop_tagged_source_mode();
}
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
{
- bool parse_template(value const&, quickbook::state& state);
+ bool parse_template(value const&, quickbook::state& state,
+ bool is_attribute_template = false);
}
void state::start_callouts()
@@ -558,8 +616,8 @@ namespace quickbook
std::string state::add_callout(value v)
{
- std::string callout_id1 = ids.add_id("c", id_category::numbered);
- std::string callout_id2 = ids.add_id("c", id_category::numbered);
+ std::string callout_id1 = document.add_id("c", id_category::numbered);
+ std::string callout_id2 = document.add_id("c", id_category::numbered);
callouts.insert(encoded_value(callout_id1));
callouts.insert(encoded_value(callout_id2));
@@ -593,7 +651,7 @@ namespace quickbook
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);
@@ -647,53 +705,53 @@ namespace quickbook
value anchor_id = values.consume();
// Note: anchor_id is never encoded as boostbook. If it
// is encoded, it's just things like escapes.
- add_anchor(state, anchor_id.is_encoded() ?
- anchor_id.get_encoded() : anchor_id.get_quickbook());
+ add_anchor(state, validate_id(state, anchor_id));
values.finish();
}
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)
{
- state.source_mode = source_mode_tags::name(source_mode.get_tag());
+ state.change_source_mode(source_mode.get_tag());
}
void next_source_mode_action(quickbook::state& state, value source_mode)
{
value_consumer values = source_mode;
- state.source_mode_next = values.consume();
+ state.source_mode_next_pos = values.consume();
+ state.source_mode_next = values.consume().get_int();
values.finish();
}
@@ -702,16 +760,16 @@ namespace quickbook
int code_tag = code_block.get_tag();
value_consumer values = code_block;
- string_ref code_value = values.consume().get_quickbook();
+ boost::string_ref code_value = values.consume().get_quickbook();
values.finish();
bool inline_code = code_tag == code_tags::inline_code ||
(code_tag == code_tags::inline_code_block && qbk_version_n < 106u);
bool block = code_tag != code_tags::inline_code;
- std::string source_mode = state.source_mode_next.empty() ?
- state.source_mode : state.source_mode_next.get_quickbook();
- state.source_mode_next = value();
+ source_mode_type source_mode = state.source_mode_next ?
+ state.source_mode_next : state.current_source_mode().source_mode;
+ state.source_mode_next = 0;
if (inline_code) {
write_anchors(state, state.phrase);
@@ -726,68 +784,66 @@ namespace quickbook
// preprocess the code section to remove the initial indentation
mapped_file_builder mapped;
mapped.start(state.current_file);
- mapped.unindent_and_add(code_value.begin(), code_value.end());
+ mapped.unindent_and_add(code_value);
file_ptr f = mapped.release();
- if (f->source.empty())
+ if (f->source().empty())
return; // Nothing left to do here. The program is empty.
if (qbk_version_n >= 107u) state.start_callouts();
- parse_iterator first_(f->source.begin());
- parse_iterator last_(f->source.end());
+ parse_iterator first_(f->source().begin());
+ parse_iterator last_(f->source().end());
file_ptr saved_file = f;
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;
+ if (qbk_version_n >= 107u) state.phrase << state.end_callouts();
- // 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) 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 +855,11 @@ namespace quickbook
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 << ";";
}
}
@@ -813,8 +870,8 @@ namespace quickbook
detail::print_string(v.get_encoded(), out);
}
else {
- std::string value = v.get_quickbook();
- for(std::string::const_iterator
+ boost::string_ref value = v.get_quickbook();
+ for(boost::string_ref::const_iterator
first = value.begin(), last = value.end();
first != last; ++first)
{
@@ -841,8 +898,10 @@ namespace quickbook
value_consumer pair = pair_;
value name = pair.consume();
value value = pair.consume();
+ std::string name_str(name.get_quickbook().begin(),
+ name.get_quickbook().end());
pair.finish();
- if(!attributes.insert(std::make_pair(name.get_quickbook(), value)).second)
+ if(!attributes.insert(std::make_pair(name_str, value)).second)
{
detail::outwarn(name.get_file(), name.get_position())
<< "Duplicate image attribute: "
@@ -860,7 +919,7 @@ namespace quickbook
std::string fileref = attributes["fileref"].is_encoded() ?
attributes["fileref"].get_encoded() :
- attributes["fileref"].get_quickbook();
+ detail::to_s(attributes["fileref"].get_quickbook());
// Check for windows paths, then convert.
// A bit crude, but there you go.
@@ -937,7 +996,7 @@ namespace quickbook
// Now load the SVG file:
//
std::string svg_text;
- if (state.add_dependency(img)) {
+ if (state.dependencies.add_dependency(img)) {
fs::ifstream fs(img);
std::stringstream buffer;
buffer << fs.rdbuf();
@@ -1006,7 +1065,7 @@ namespace quickbook
void macro_definition_action(quickbook::state& state, quickbook::value macro_definition)
{
value_consumer values = macro_definition;
- std::string macro_id = values.consume().get_quickbook();
+ std::string macro_id = detail::to_s(values.consume().get_quickbook());
value phrase_value = values.optional_consume();
std::string phrase;
if (phrase_value.check()) phrase = phrase_value.get_encoded();
@@ -1035,11 +1094,11 @@ namespace quickbook
void template_body_action(quickbook::state& state, quickbook::value template_definition)
{
value_consumer values = template_definition;
- std::string identifier = values.consume().get_quickbook();
+ std::string identifier = detail::to_s(values.consume().get_quickbook());
std::vector<std::string> template_values;
BOOST_FOREACH(value const& p, values.consume()) {
- template_values.push_back(p.get_quickbook());
+ template_values.push_back(detail::to_s(p.get_quickbook()));
}
BOOST_ASSERT(values.check(template_tags::block) || values.check(template_tags::phrase));
@@ -1202,20 +1261,23 @@ namespace quickbook
bool parse_template(
value const& content
, quickbook::state& state
+ , bool is_attribute_template
)
{
file_ptr saved_current_file = state.current_file;
state.current_file = content.get_file();
- string_ref source = content.get_quickbook();
+ boost::string_ref source = content.get_quickbook();
parse_iterator first(source.begin());
parse_iterator last(source.end());
bool r = cl::parse(first, last,
+ is_attribute_template ?
+ state.grammar().attribute_template_body :
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);
@@ -1227,26 +1289,23 @@ namespace quickbook
void call_template(quickbook::state& state,
template_symbol const* symbol,
std::vector<value> const& args,
- string_iterator first)
+ string_iterator first,
+ bool is_attribute_template = false)
{
bool is_block = symbol->content.get_tag() != template_tags::phrase;
+ assert(!(is_attribute_template && is_block));
+
+ 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;
}
@@ -1257,11 +1316,11 @@ namespace quickbook
// 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();
@@ -1277,7 +1336,7 @@ namespace quickbook
// Store the current section level so that we can ensure that
// [section] and [endsect] tags in the template are balanced.
- state.min_section_level = state.ids.section_level();
+ state.min_section_level = state.document.section_level();
///////////////////////////////////
// Prepare the arguments as local templates
@@ -1294,22 +1353,26 @@ namespace quickbook
///////////////////////////////////
// parse the template body:
- if (!parse_template(symbol->content, state))
+ if (symbol->content.get_file()->version() < 107u) {
+ state.out.swap(save_block);
+ state.phrase.swap(save_phrase);
+ }
+
+ if (!parse_template(symbol->content, state, is_attribute_template))
{
detail::outerr(state.current_file, first)
<< "Expanding "
<< (is_block ? "block" : "phrase")
- << " template: " << symbol->identifier << std::endl
- << std::endl
- << "------------------begin------------------" << std::endl
+ << " template: " << symbol->identifier << "\n\n"
+ << "------------------begin------------------\n"
<< symbol->content.get_quickbook()
- << "------------------end--------------------" << std::endl
+ << "------------------end--------------------\n"
<< std::endl;
++state.error_count;
return;
}
- if (state.ids.section_level() != state.min_section_level)
+ if (state.document.section_level() != state.min_section_level)
{
detail::outerr(state.current_file, first)
<< "Mismatched sections in template "
@@ -1319,19 +1382,24 @@ namespace quickbook
return;
}
- state.out.swap(block);
- state.phrase.swap(phrase);
- }
+ if (symbol->content.get_file()->version() < 107u) {
+ state.out.swap(save_block);
+ state.phrase.swap(save_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(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();
+ }
}
}
@@ -1357,13 +1425,16 @@ namespace quickbook
void do_template_action(quickbook::state& state, value template_list,
string_iterator first)
{
+ bool const is_attribute_template =
+ template_list.get_tag() == template_tags::attribute_template;
+
// Get the arguments
value_consumer values = template_list;
bool template_escape = values.check(template_tags::escape);
if(template_escape) values.consume();
- std::string identifier = values.consume(template_tags::identifier).get_quickbook();
+ std::string identifier = detail::to_s(values.consume(template_tags::identifier).get_quickbook());
std::vector<value> args;
@@ -1419,6 +1490,20 @@ namespace quickbook
}
///////////////////////////////////
+ // Check that attribute templates are phrase templates
+
+ if (is_attribute_template &&
+ symbol->content.get_tag() != template_tags::phrase)
+ {
+ detail::outerr(state.current_file, first)
+ << "Only phrase templates can be used in attribute values."
+ << std::endl;
+
+ ++state.error_count;
+ return;
+ }
+
+ ///////////////////////////////////
// Initialise the arguments
switch(symbol->content.get_tag())
@@ -1443,7 +1528,7 @@ namespace quickbook
return;
}
- call_template(state, symbol, args, first);
+ call_template(state, symbol, args, first, is_attribute_template);
break;
case template_tags::snippet:
@@ -1477,10 +1562,19 @@ namespace quickbook
value content = values.consume();
values.finish();
- // Note: dst is never actually encoded as boostbook, which
- // is why the result is called with 'print_string' later.
- std::string dst = dst_value.is_encoded() ?
- dst_value.get_encoded() : dst_value.get_quickbook();
+ std::string dst;
+
+ if (link.get_tag() == phrase_tags::link) {
+ dst = validate_id(state, dst_value);
+ }
+ else {
+ dst = get_attribute_value(state, dst_value);
+
+ // TODO: Might be better to have an error for some invalid urls.
+ if (link.get_tag() == phrase_tags::url) {
+ dst = detail::partially_escape_uri(dst);
+ }
+ }
state.phrase << markup.pre;
detail::print_string(dst, state.phrase.get());
@@ -1499,7 +1593,7 @@ namespace quickbook
write_anchors(state, state.out);
value_consumer values = variable_list;
- std::string title = values.consume(table_tags::title).get_quickbook();
+ std::string title = detail::to_s(values.consume(table_tags::title).get_quickbook());
state.out << "<variablelist>\n";
@@ -1537,8 +1631,9 @@ namespace quickbook
value_consumer values = table;
std::string element_id;
- if(values.check(general_tags::element_id))
- element_id = values.consume().get_quickbook();
+ if(values.check(general_tags::element_id)) {
+ element_id = validate_id(state, values.consume());
+ }
value title = values.consume(table_tags::title);
bool has_title = !title.empty();
@@ -1546,14 +1641,14 @@ namespace quickbook
std::string table_id;
if (!element_id.empty()) {
- table_id = state.ids.add_id(element_id, id_category::explicit_id);
+ table_id = state.document.add_id(element_id, id_category::explicit_id);
}
else if (has_title) {
- if (state.ids.compatibility_version() >= 105) {
- table_id = state.ids.add_id(detail::make_identifier(title.get_quickbook()), id_category::generated);
+ if (state.document.compatibility_version() >= 105) {
+ table_id = state.document.add_id(detail::make_identifier(title.get_quickbook()), id_category::generated);
}
else {
- table_id = state.ids.add_id("t", id_category::numbered);
+ table_id = state.document.add_id("t", id_category::numbered);
}
}
@@ -1636,20 +1731,21 @@ namespace quickbook
value content = values.consume();
values.finish();
- std::string full_id = state.ids.begin_section(
- !element_id.empty() ?
- element_id.get_quickbook() :
- detail::make_identifier(content.get_quickbook()),
- !element_id.empty() ?
- id_category::explicit_section_id :
- id_category::generated_section);
+ std::string full_id = state.document.begin_section(
+ element_id.empty() ?
+ detail::make_identifier(content.get_quickbook()) :
+ validate_id(state, element_id),
+ element_id.empty() ?
+ id_category::generated_section :
+ id_category::explicit_section_id,
+ state.current_source_mode());
state.out << "\n<section id=\"" << full_id << "\">\n";
state.out << "<title>";
write_anchors(state, state.out);
- if (self_linked_headers && state.ids.compatibility_version() >= 103)
+ if (self_linked_headers && state.document.compatibility_version() >= 103)
{
state.out << "<link linkend=\"" << full_id << "\">"
<< content.get_encoded()
@@ -1668,7 +1764,7 @@ namespace quickbook
{
write_anchors(state, state.out);
- if (state.ids.section_level() <= state.min_section_level)
+ if (state.document.section_level() <= state.min_section_level)
{
file_position const pos = state.current_file->position_of(first);
@@ -1680,7 +1776,7 @@ namespace quickbook
}
state.out << "</section>";
- state.ids.end_section();
+ state.document.end_section();
}
void element_id_warning_action::operator()(parse_iterator first, parse_iterator) const
@@ -1763,71 +1859,49 @@ namespace quickbook
return result;
}
- struct path_details {
- // Will possibly add 'url' and 'glob' to this list later:
- enum path_type { path };
-
- std::string value;
- path_type type;
-
- path_details(std::string const& value, path_type type) :
- value(value), type(type)
- {
- }
- };
-
- path_details check_path(value const& path, quickbook::state& state)
+ xinclude_path calculate_xinclude_path(value const& p, quickbook::state& state)
{
- // Paths are encoded for quickbook 1.6+ and also xmlbase
- // values (technically xmlbase is a 1.6 feature, but that
- // isn't enforced as it's backwards compatible).
- //
- // Counter-intuitively: encoded == plain text here.
-
- std::string path_text = qbk_version_n >= 106u || path.is_encoded() ?
- path.get_encoded() : path.get_quickbook();
-
- if(path_text.find('\\') != std::string::npos)
- {
- quickbook::detail::ostream* err;
-
- if (qbk_version_n >= 106u) {
- err = &detail::outerr(path.get_file(), path.get_position());
+ path_parameter parameter = check_path(p, state);
+
+ switch (parameter.type) {
+ case path_parameter::glob:
+ // TODO: Should know if this is an xinclude or an xmlbase.
+ // Would also help with implementation of 'check_path'.
+ detail::outerr(p.get_file(), p.get_position())
+ << "Glob used in xinclude/xmlbase."
+ << std::endl;
++state.error_count;
- }
- else {
- err = &detail::outwarn(path.get_file(), path.get_position());
- }
-
- *err << "Path isn't portable: '"
- << path_text
- << "'"
- << std::endl;
+ break;
- boost::replace(path_text, '\\', '/');
- }
+ case path_parameter::invalid:
+ // There should have already been an error message in this case.
+ break;
- return path_details(path_text, path_details::path);
- }
+ case path_parameter::path:
+ {
+ fs::path path = detail::generic_to_path(parameter.value);
+ fs::path full_path = path;
- xinclude_path calculate_xinclude_path(value const& p, quickbook::state& state)
- {
- path_details details = check_path(p, state);
+ // If the path is relative
+ if (!path.has_root_directory())
+ {
+ // Resolve the path from the current file
+ full_path = state.current_file->path.parent_path() / path;
- fs::path path = detail::generic_to_path(details.value);
- fs::path full_path = path;
+ // Then calculate relative to the current xinclude_base.
+ path = path_difference(state.xinclude_base, full_path);
+ }
- // If the path is relative
- if (!path.has_root_directory())
- {
- // Resolve the path from the current file
- full_path = state.current_file->path.parent_path() / path;
+ return xinclude_path(full_path,
+ detail::escape_uri(detail::path_to_generic(path)));
+ }
- // Then calculate relative to the current xinclude_base.
- path = path_difference(state.xinclude_base, full_path);
+ default:
+ assert(false);
}
- return xinclude_path(full_path, detail::escape_uri(detail::path_to_generic(path)));
+ // If we didn't find a path, just use this:
+ return xinclude_path(state.current_file->path.parent_path(), "");
}
void xinclude_action(quickbook::state& state, value xinclude)
@@ -1843,77 +1917,8 @@ namespace quickbook
state.out << "\" />\n";
}
- namespace
- {
- struct include_search_return
- {
- include_search_return(fs::path const& x, fs::path const& y)
- : filename(x), filename_relative(y) {}
-
- fs::path filename;
- fs::path filename_relative;
-
- bool operator < (include_search_return const & other) const
- {
- if (filename_relative < other.filename_relative) return true;
- else if (other.filename_relative < filename_relative) return false;
- else return filename < other.filename;
- }
- };
-
- std::set<include_search_return> include_search(path_details const& details,
- quickbook::state& state, string_iterator pos)
- {
- std::set<include_search_return> result;
-
- fs::path path = detail::generic_to_path(details.value);
-
- // If the path is relative, try and resolve it.
- if (!path.has_root_directory() && !path.has_root_name())
- {
- fs::path local_path =
- state.current_file->path.parent_path() / path;
-
- // See if it can be found locally first.
- if (state.add_dependency(local_path))
- {
- result.insert(include_search_return(
- local_path,
- state.filename_relative.parent_path() / path));
- return result;
- }
-
- BOOST_FOREACH(fs::path full, include_path)
- {
- full /= path;
-
- if (state.add_dependency(full))
- {
- result.insert(include_search_return(full, path));
- return result;
- }
- }
- }
- else
- {
- if (state.add_dependency(path)) {
- result.insert(include_search_return(path, path));
- return result;
- }
- }
-
- detail::outerr(state.current_file, pos)
- << "Unable to find file: "
- << details.value
- << std::endl;
- ++state.error_count;
-
- return result;
- }
- }
-
void load_quickbook(quickbook::state& state,
- include_search_return const& paths,
+ quickbook_path const& path,
value::tag_type load_type,
value const& include_doc_id = value())
{
@@ -1931,18 +1936,17 @@ namespace quickbook
//
// 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;
+ state.current_file = load(path.file_path); // Throws load_error
+ state.current_path = path;
state.imported = (load_type == block_tags::import);
// update the __FILENAME__ macro
- *boost::spirit::classic::find(state.macro, "__FILENAME__")
- = detail::path_to_generic(state.filename_relative);
+ state.update_filename_macro();
// parse the file
quickbook::parse_file(state, include_doc_id, true);
@@ -1952,12 +1956,11 @@ namespace quickbook
}
// restore the __FILENAME__ macro
- *boost::spirit::classic::find(state.macro, "__FILENAME__")
- = detail::path_to_generic(state.filename_relative);
+ state.update_filename_macro();
}
void load_source_file(quickbook::state& state,
- include_search_return const& paths,
+ quickbook_path const& path,
value::tag_type load_type,
string_iterator first,
value const& include_doc_id = value())
@@ -1965,11 +1968,11 @@ namespace quickbook
assert(load_type == block_tags::include ||
load_type == block_tags::import);
- std::string ext = paths.filename.extension().generic_string();
+ std::string ext = path.file_path.extension().generic_string();
std::vector<template_symbol> storage;
// Throws load_error
state.error_count +=
- load_snippets(paths.filename, storage, ext, load_type);
+ load_snippets(path.file_path, storage, ext, load_type);
if (load_type == block_tags::include)
{
@@ -2014,41 +2017,42 @@ namespace quickbook
value_consumer values = include;
value include_doc_id = values.optional_consume(general_tags::include_id);
- path_details details = check_path(values.consume(), state);
+ path_parameter parameter = check_path(values.consume(), state);
values.finish();
- std::set<include_search_return> search = include_search(details, state, first);
- std::set<include_search_return>::iterator i = search.begin();
- std::set<include_search_return>::iterator e = search.end();
+ std::set<quickbook_path> search =
+ include_search(parameter, state, first);
+ std::set<quickbook_path>::iterator i = search.begin();
+ std::set<quickbook_path>::iterator e = search.end();
for (; i != e; ++i)
{
- include_search_return const & paths = *i;
+ quickbook_path const & path = *i;
try {
if (qbk_version_n >= 106)
{
if (state.imported && include.get_tag() == block_tags::include)
return;
- std::string ext = paths.filename.extension().generic_string();
+ std::string ext = path.file_path.extension().generic_string();
if (ext == ".qbk" || ext == ".quickbook")
{
- load_quickbook(state, paths, include.get_tag(), include_doc_id);
+ load_quickbook(state, path, include.get_tag(), include_doc_id);
}
else
{
- load_source_file(state, paths, include.get_tag(), first, include_doc_id);
+ load_source_file(state, path, include.get_tag(), first, include_doc_id);
}
}
else
{
if (include.get_tag() == block_tags::include)
{
- load_quickbook(state, paths, include.get_tag(), include_doc_id);
+ load_quickbook(state, path, include.get_tag(), include_doc_id);
}
else
{
- load_source_file(state, paths, include.get_tag(), first, include_doc_id);
+ load_source_file(state, path, include.get_tag(), first, include_doc_id);
}
}
}
@@ -2057,7 +2061,7 @@ namespace quickbook
detail::outerr(state.current_file, first)
<< "Loading file "
- << paths.filename
+ << path.file_path
<< ": "
<< e.what()
<< std::endl;
@@ -2067,8 +2071,7 @@ namespace quickbook
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;
@@ -2099,8 +2102,7 @@ namespace quickbook
void to_value_scoped_action::cleanup()
{
- state.phrase.pop();
- state.out.pop();
+ state.pop_output();
state.anchors.swap(saved_anchors);
}
}
diff --git a/tools/quickbook/src/actions.hpp b/tools/quickbook/src/actions.hpp
index 5a93cf949a..44b5a27704 100644
--- a/tools/quickbook/src/actions.hpp
+++ b/tools/quickbook/src/actions.hpp
@@ -46,12 +46,6 @@ namespace quickbook
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(
- parse_iterator first, parse_iterator last,
- quickbook::state& state,
- std::string const& source_mode,
- bool is_block);
-
struct xinclude_path {
xinclude_path(fs::path const& path, std::string const& uri) :
path(path), uri(uri) {}
@@ -119,12 +113,12 @@ namespace quickbook
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 +143,11 @@ namespace quickbook
{
// 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 +168,9 @@ namespace quickbook
{
// 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 +178,12 @@ namespace quickbook
{
// 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 +191,29 @@ namespace quickbook
// 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;
};
@@ -265,6 +244,101 @@ namespace quickbook
std::vector<std::string> saved_anchors;
value::tag_type tag;
};
+
+ // member_action
+ //
+ // Action for calling a member function taking two parse iterators.
+
+ template <typename T>
+ struct member_action
+ {
+ typedef void(T::*member_function)(parse_iterator, parse_iterator);
+
+ T& l;
+ member_function mf;
+
+ member_action(T& l, member_function mf) : l(l), mf(mf) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const {
+ (l.*mf)(first, last);
+ }
+ };
+
+ // member_action1
+ //
+ // Action for calling a member function taking two parse iterators and a value.
+
+ template <typename T, typename Arg1>
+ struct member_action1
+ {
+ typedef void(T::*member_function)(parse_iterator, parse_iterator, Arg1);
+
+ T& l;
+ member_function mf;
+
+ member_action1(T& l, member_function mf) : l(l), mf(mf) {}
+
+ struct impl
+ {
+ member_action1 a;
+ Arg1 value;
+
+ impl(member_action1& a, Arg1 value) :
+ a(a), value(value)
+ {}
+
+ void operator()(parse_iterator first, parse_iterator last) const {
+ (a.l.*a.mf)(first, last, value);
+ }
+ };
+
+ impl operator()(Arg1 a1) {
+ return impl(*this, a1);
+ }
+ };
+
+ // member_action_value
+ //
+ // Action for calling a unary member function.
+
+ template <typename T, typename Value>
+ struct member_action_value
+ {
+ typedef void(T::*member_function)(Value);
+
+ T& l;
+ member_function mf;
+
+ member_action_value(T& l, member_function mf) : l(l), mf(mf) {}
+
+ void operator()(Value v) const {
+ (l.*mf)(v);
+ }
+ };
+
+ // member_action_value
+ //
+ // Action for calling a unary member function with a fixed value.
+
+ template <typename T, typename Value>
+ struct member_action_fixed_value
+ {
+ typedef void(T::*member_function)(Value);
+
+ T& l;
+ member_function mf;
+ Value v;
+
+ member_action_fixed_value(T& l, member_function mf, Value v) : l(l), mf(mf), v(v) {}
+
+ void operator()() const {
+ (l.*mf)(v);
+ }
+
+ void operator()(parse_iterator first, parse_iterator last) const {
+ (l.*mf)(v);
+ }
+ };
}
#endif // BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP
diff --git a/tools/quickbook/src/block_element_grammar.cpp b/tools/quickbook/src/block_element_grammar.cpp
index 1f5d5daec4..04a320e9e3 100644
--- a/tools/quickbook/src/block_element_grammar.cpp
+++ b/tools/quickbook/src/block_element_grammar.cpp
@@ -35,7 +35,7 @@ namespace quickbook
xinclude, include, include_filename,
template_, template_id, template_formal_arg,
template_body, identifier, import,
- element_id, element_id_1_5, element_id_1_6,
+ element_id,
same_line;
};
@@ -47,27 +47,25 @@ namespace quickbook
// 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 =
!( ':'
- >> ( !(qbk_ver(105u) >> space)
+ >> ( qbk_ver(107u)
+ >> to_value(general_tags::element_id) [attribute_value_1_7]
+ | qbk_ver(0, 107u)
+ >> !(qbk_ver(105u) >> space)
>> (+(cl::alnum_p | '_')) [state.values.entry(ph::arg1, ph::arg2, general_tags::element_id)]
| cl::eps_p [element_id_warning]
)
)
;
- local.element_id_1_5 =
- !(qbk_ver(105u) >> local.element_id);
-
- local.element_id_1_6 =
- !(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 =
@@ -83,7 +81,7 @@ namespace quickbook
local.heading
= space
- >> local.element_id_1_6
+ >> !(qbk_ver(106u) >> local.element_id)
>> space
>> local.inner_phrase
;
@@ -169,7 +167,10 @@ namespace quickbook
;
local.template_body =
- *(('[' >> local.template_body >> ']') | (cl::anychar_p - ']'))
+ qbk_ver(106u)
+ >> *(~cl::eps_p(']') >> skip_entity)
+ | qbk_ver(0,106u)
+ >> *(('[' >> local.template_body >> ']') | (cl::anychar_p - ']'))
>> cl::eps_p(space >> ']')
>> space
;
@@ -219,7 +220,7 @@ namespace quickbook
local.table =
local.same_line
- >> local.element_id_1_5
+ >> !(qbk_ver(105u) >> local.element_id)
>> local.same_line
>> local.table_title
>> *local.table_row
@@ -258,7 +259,11 @@ namespace quickbook
("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
@@ -301,13 +306,15 @@ namespace quickbook
local.include_filename =
qbk_ver(0, 106u)
>> (*(cl::anychar_p - phrase_end)) [state.values.entry(ph::arg1, ph::arg2)]
- | qbk_ver(106u)
+ | qbk_ver(106u, 107u)
>> to_value()
[ *( raw_escape
| (cl::anychar_p - phrase_end)
[raw_char]
)
]
+ | qbk_ver(107u)
+ >> to_value() [ attribute_value_1_7 ]
;
local.inner_block =
diff --git a/tools/quickbook/src/block_tags.hpp b/tools/quickbook/src/block_tags.hpp
index b01271fc0b..3049b57c51 100644
--- a/tools/quickbook/src/block_tags.hpp
+++ b/tools/quickbook/src/block_tags.hpp
@@ -22,7 +22,7 @@ namespace quickbook
(macro_definition)(template_definition)
(variable_list)(table)
(xinclude)(import)(include)
- (paragraph)
+ (paragraph)(paragraph_in_list)
(ordered_list)(itemized_list)
(hr)
)
diff --git a/tools/quickbook/src/code_snippet.cpp b/tools/quickbook/src/code_snippet.cpp
index 4c63a3ba0e..fe54f46ce1 100644
--- a/tools/quickbook/src/code_snippet.cpp
+++ b/tools/quickbook/src/code_snippet.cpp
@@ -12,14 +12,13 @@
#include <boost/spirit/include/classic_confix.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
-#include <boost/lexical_cast.hpp>
#include "block_tags.hpp"
#include "template_stack.hpp"
#include "actions.hpp"
#include "state.hpp"
#include "values.hpp"
#include "files.hpp"
-#include "input_path.hpp"
+#include "native_text.hpp"
namespace quickbook
{
@@ -30,7 +29,7 @@ namespace quickbook
code_snippet_actions(std::vector<template_symbol>& storage,
file_ptr source_file,
char const* source_type)
- : last_code_pos(source_file->source.begin())
+ : last_code_pos(source_file->source().begin())
, in_code(false)
, snippet_stack()
, storage(storage)
@@ -63,13 +62,13 @@ namespace quickbook
std::string id;
bool start_code;
- std::string::const_iterator source_pos;
+ string_iterator source_pos;
mapped_file_builder::pos start_pos;
boost::shared_ptr<snippet_data> next;
};
void push_snippet_data(std::string const& id,
- std::string::const_iterator pos)
+ string_iterator pos)
{
boost::shared_ptr<snippet_data> new_snippet(new snippet_data(id));
new_snippet->next = snippet_stack;
@@ -88,8 +87,8 @@ namespace quickbook
}
mapped_file_builder content;
- std::string::const_iterator mark_begin, mark_end;
- std::string::const_iterator last_code_pos;
+ boost::string_ref::const_iterator mark_begin, mark_end;
+ boost::string_ref::const_iterator last_code_pos;
bool in_code;
boost::shared_ptr<snippet_data> snippet_stack;
std::vector<template_symbol>& storage;
@@ -352,8 +351,8 @@ namespace quickbook
bool is_python = extension == ".py";
code_snippet_actions a(storage, load(filename, qbk_version_n), is_python ? "[python]" : "[c++]");
- string_iterator first(a.source_file->source.begin());
- string_iterator last(a.source_file->source.end());
+ string_iterator first(a.source_file->source().begin());
+ string_iterator last(a.source_file->source().end());
cl::parse_info<string_iterator> info;
@@ -376,14 +375,14 @@ namespace quickbook
if (last_code_pos != first) {
if (!in_code)
{
- content.add("\n\n", last_code_pos);
- content.add(source_type, last_code_pos);
- content.add("```\n", last_code_pos);
+ content.add_at_pos("\n\n", last_code_pos);
+ content.add_at_pos(source_type, last_code_pos);
+ content.add_at_pos("```\n", last_code_pos);
in_code = true;
}
- content.add(last_code_pos, first);
+ content.add(boost::string_ref(last_code_pos, first - last_code_pos));
}
}
@@ -396,7 +395,7 @@ namespace quickbook
if (in_code)
{
- content.add("\n```\n\n", last_code_pos);
+ content.add_at_pos("\n```\n\n", last_code_pos);
in_code = false;
}
}
@@ -414,13 +413,13 @@ namespace quickbook
if (!in_code)
{
- content.add("\n\n", first);
- content.add(source_type, first);
- content.add("```\n", first);
+ content.add_at_pos("\n\n", first);
+ content.add_at_pos(source_type, first);
+ content.add_at_pos("```\n", first);
in_code = true;
}
- content.add(mark_begin, mark_end);
+ content.add(boost::string_ref(mark_begin, mark_end - mark_begin));
}
void code_snippet_actions::escaped_comment(string_iterator first, string_iterator last)
@@ -437,8 +436,8 @@ namespace quickbook
snippet_data& snippet = *snippet_stack;
- content.add("\n", mark_begin);
- content.unindent_and_add(mark_begin, mark_end);
+ content.add_at_pos("\n", mark_begin);
+ content.unindent_and_add(boost::string_ref(mark_begin, mark_end - mark_begin));
if (snippet.id == "!")
{
@@ -516,13 +515,13 @@ namespace quickbook
mapped_file_builder f;
f.start(source_file);
if (snippet->start_code) {
- f.add("\n\n", snippet->source_pos);
- f.add(source_type, snippet->source_pos);
- f.add("```\n", snippet->source_pos);
+ f.add_at_pos("\n\n", snippet->source_pos);
+ f.add_at_pos(source_type, snippet->source_pos);
+ f.add_at_pos("```\n", snippet->source_pos);
}
f.add(content, snippet->start_pos, content.get_pos());
if (in_code) {
- f.add("\n```\n\n", position);
+ f.add_at_pos("\n```\n\n", position);
}
std::vector<std::string> params;
@@ -530,7 +529,7 @@ namespace quickbook
file_ptr body = f.release();
storage.push_back(template_symbol(snippet->id, params,
- qbk_value(body, body->source.begin(), body->source.end(),
+ qbk_value(body, body->source().begin(), body->source().end(),
template_tags::snippet)));
}
}
diff --git a/tools/quickbook/src/dependency_tracker.cpp b/tools/quickbook/src/dependency_tracker.cpp
new file mode 100644
index 0000000000..12b2a757a9
--- /dev/null
+++ b/tools/quickbook/src/dependency_tracker.cpp
@@ -0,0 +1,184 @@
+/*=============================================================================
+ Copyright (c) 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 "dependency_tracker.hpp"
+#include "native_text.hpp"
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/foreach.hpp>
+
+namespace quickbook
+{
+ // Convert the path to its canonical representation if it exists.
+ // Or something close if it doesn't.
+ static fs::path normalize_path(fs::path const& path)
+ {
+ fs::path p = fs::absolute(path); // The base of the path.
+ fs::path extra; // The non-existant part of the path.
+ int parent_count = 0; // Number of active '..' sections
+
+ // Invariant: path is equivalent to: p / ('..' * parent_count) / extra
+ // i.e. if parent_count == 0: p/extra
+ // if parent_count == 2: p/../../extra
+
+ // Pop path sections from path until we find an existing
+ // path, adjusting for any dot path sections.
+ while (!fs::exists(fs::status(p))) {
+ fs::path name = p.filename();
+ p = p.parent_path();
+ if (name == "..") {
+ ++parent_count;
+ }
+ else if (name == ".") {
+ }
+ else if (parent_count) {
+ --parent_count;
+ }
+ else {
+ extra = name / extra;
+ }
+ }
+
+ // If there are any left over ".." sections, then add them
+ // on to the end of the real path, and trust Boost.Filesystem
+ // to sort them out.
+ while (parent_count) {
+ p = p / "..";
+ --parent_count;
+ }
+
+ // Cannoicalize the existing part of the path, and add 'extra' back to
+ // the end.
+ return fs::canonical(p) / extra;
+ }
+
+ static char const* control_escapes[16] = {
+ "\\000", "\\001", "\\002", "\\003",
+ "\\004", "\\005", "\\006", "\\a",
+ "\\b", "\\t", "\\n", "\\v",
+ "\\f", "\\r", "\\016", "\\017"
+ };
+
+ static std::string escaped_path(std::string const& generic)
+ {
+ std::string result;
+ result.reserve(generic.size());
+
+ BOOST_FOREACH(char c, generic)
+ {
+ if (c >= 0 && c < 16) {
+ result += control_escapes[(unsigned int) c];
+ }
+ else if (c == '\\') {
+ result += "\\\\";
+ }
+ else if (c == 127) {
+ result += "\\177";
+ }
+ else {
+ result += c;
+ }
+ }
+
+ return result;
+ }
+
+ static std::string get_path(fs::path const& path,
+ dependency_tracker::flags f)
+ {
+ std::string generic = quickbook::detail::path_to_generic(path);
+
+ if (f & dependency_tracker::escaped) {
+ generic = escaped_path(generic);
+ }
+
+ return generic;
+ }
+
+ dependency_tracker::dependency_tracker() :
+ dependencies(), glob_dependencies(),
+ last_glob(glob_dependencies.end()) {}
+
+ bool dependency_tracker::add_dependency(fs::path const& f) {
+ bool found = fs::exists(fs::status(f));
+ dependencies[normalize_path(f)] |= found;
+ return found;
+ }
+
+ void dependency_tracker::add_glob(fs::path const& f) {
+ std::pair<glob_list::iterator, bool> r = glob_dependencies.insert(
+ std::make_pair(normalize_path(f), glob_list::mapped_type()));
+ last_glob = r.first;
+ }
+
+ void dependency_tracker::add_glob_match(fs::path const& f) {
+ assert(last_glob != glob_dependencies.end());
+ last_glob->second.insert(normalize_path(f));
+ }
+
+ void dependency_tracker::write_dependencies(fs::path const& file_out,
+ flags f)
+ {
+ fs::ofstream out(file_out);
+
+ if (out.fail()) {
+ throw std::runtime_error(
+ "Error opening dependency file " +
+ quickbook::detail::path_to_generic(file_out));
+ }
+
+ out.exceptions(std::ios::badbit);
+ write_dependencies(out, f);
+ }
+
+ void dependency_tracker::write_dependencies(std::ostream& out,
+ flags f)
+ {
+ if (f & checked) {
+ BOOST_FOREACH(dependency_list::value_type const& d, dependencies)
+ {
+ out << (d.second ? "+ " : "- ")
+ << get_path(d.first, f) << std::endl;
+ }
+
+ BOOST_FOREACH(glob_list::value_type const& g, glob_dependencies)
+ {
+ out << "g "
+ << get_path(g.first, f) << std::endl;
+
+ BOOST_FOREACH(fs::path const& p, g.second)
+ {
+ out << "+ " << get_path(p, f) << std::endl;
+ }
+ }
+ }
+ else {
+ std::set<std::string> paths;
+
+ BOOST_FOREACH(dependency_list::value_type const& d, dependencies)
+ {
+ if (d.second) {
+ paths.insert(get_path(d.first, f));
+ }
+ }
+
+ BOOST_FOREACH(glob_list::value_type const& g, glob_dependencies)
+ {
+ BOOST_FOREACH(fs::path const& p, g.second)
+ {
+ paths.insert(get_path(p, f));
+ }
+ }
+
+ BOOST_FOREACH(std::string const& p, paths)
+ {
+ out << p << std::endl;
+ }
+ }
+ }
+}
diff --git a/tools/quickbook/src/dependency_tracker.hpp b/tools/quickbook/src/dependency_tracker.hpp
new file mode 100644
index 0000000000..2da44f5c03
--- /dev/null
+++ b/tools/quickbook/src/dependency_tracker.hpp
@@ -0,0 +1,53 @@
+/*=============================================================================
+ Copyright (c) 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(QUICKBOOK_DEPENDENCY_TRACKER_HPP)
+#define QUICKBOOK_DEPENDENCY_TRACKER_HPP
+
+#include <map>
+#include <set>
+#include <iosfwd>
+#include <boost/filesystem/path.hpp>
+
+namespace quickbook
+{
+ namespace fs = boost::filesystem;
+
+ struct dependency_tracker {
+ private:
+
+ typedef std::map<fs::path, bool> dependency_list;
+ typedef std::map<fs::path, std::set<fs::path> > glob_list;
+
+ dependency_list dependencies;
+ glob_list glob_dependencies;
+ glob_list::iterator last_glob;
+
+ public:
+
+ enum flags {
+ default_ = 0,
+ checked = 1,
+ escaped = 2
+ };
+
+ dependency_tracker();
+
+ // Call this before loading any file so that it will be included in the
+ // list of dependencies. Returns true if file exists.
+ bool add_dependency(fs::path const&);
+
+ void add_glob(fs::path const&);
+ void add_glob_match(fs::path const&);
+
+ void write_dependencies(fs::path const&, flags = default_);
+ void write_dependencies(std::ostream&, flags = default_);
+ };
+}
+
+#endif
diff --git a/tools/quickbook/src/doc_info_actions.cpp b/tools/quickbook/src/doc_info_actions.cpp
index 42ee961832..4e60f5168f 100644
--- a/tools/quickbook/src/doc_info_actions.cpp
+++ b/tools/quickbook/src/doc_info_actions.cpp
@@ -16,11 +16,11 @@
#include "quickbook.hpp"
#include "utils.hpp"
#include "files.hpp"
-#include "input_path.hpp"
+#include "native_text.hpp"
#include "state.hpp"
#include "actions.hpp"
#include "doc_info_tags.hpp"
-#include "id_manager.hpp"
+#include "document_state.hpp"
namespace quickbook
{
@@ -29,7 +29,7 @@ namespace quickbook
static std::string doc_info_output(value const& p, unsigned version)
{
if (qbk_version_n < version) {
- std::string value = p.get_quickbook();
+ std::string value = detail::to_s(p.get_quickbook());
value.erase(value.find_last_not_of(" \t") + 1);
return value;
}
@@ -141,7 +141,7 @@ namespace quickbook
if (values.check(doc_info_tags::type))
{
- doc_type = values.consume(doc_info_tags::type).get_quickbook();
+ doc_type = detail::to_s(values.consume(doc_info_tags::type).get_quickbook());
doc_title = values.consume(doc_info_tags::title);
use_doc_info = !nested_file || qbk_version_n >= 106u;
}
@@ -200,20 +200,23 @@ namespace quickbook
std::string include_doc_id_, id_;
if (!include_doc_id.empty())
- include_doc_id_ = include_doc_id.get_quickbook();
+ include_doc_id_ = detail::to_s(include_doc_id.get_quickbook());
if (!id.empty())
- id_ = id.get_quickbook();
+ id_ = detail::to_s(id.get_quickbook());
// Quickbook version
unsigned new_version = get_version(state, use_doc_info, qbk_version);
- if (new_version != qbk_version_n && new_version >= 106)
+ if (new_version != qbk_version_n)
{
- detail::outwarn(state.current_file->path)
- << "Quickbook " << (new_version / 100) << "." << (new_version % 100)
- << " is still under development and is "
- "likely to change in the future." << std::endl;
+ if (new_version >= 107u)
+ {
+ detail::outwarn(state.current_file->path)
+ << "Quickbook " << (new_version / 100) << "." << (new_version % 100)
+ << " is still under development and is "
+ "likely to change in the future." << std::endl;
+ }
}
if (new_version) {
@@ -236,20 +239,20 @@ namespace quickbook
if (!compatibility_version) {
compatibility_version = use_doc_info ?
- qbk_version_n : state.ids.compatibility_version();
+ qbk_version_n : state.document.compatibility_version();
}
// Start file, finish here if not generating document info.
if (!use_doc_info)
{
- state.ids.start_file(compatibility_version, include_doc_id_, id_,
+ state.document.start_file(compatibility_version, include_doc_id_, id_,
doc_title);
return "";
}
std::string id_placeholder =
- state.ids.start_file_with_docinfo(
+ state.document.start_file_with_docinfo(
compatibility_version, include_doc_id_, id_, doc_title);
// Make sure we really did have a document info block.
@@ -460,7 +463,7 @@ namespace quickbook
if (!license.empty())
{
tmp << " <legalnotice id=\""
- << state.ids.add_id("legal", id_category::generated)
+ << state.document.add_id("legal", id_category::generated)
<< "\">\n"
<< " <para>\n"
<< " " << doc_info_output(license, 103) << "\n"
@@ -541,18 +544,18 @@ namespace quickbook
// *after* everything else.
// Close any open sections.
- if (!doc_type.empty() && state.ids.section_level() > 1) {
+ if (!doc_type.empty() && state.document.section_level() > 1) {
detail::outwarn(state.current_file->path)
<< "Missing [endsect] detected at end of file."
<< std::endl;
- while(state.ids.section_level() > 1) {
+ while(state.document.section_level() > 1) {
state.out << "</section>";
- state.ids.end_section();
+ state.document.end_section();
}
}
- state.ids.end_file();
+ state.document.end_file();
if (!doc_type.empty()) state.out << "\n</" << doc_type << ">\n\n";
}
diff --git a/tools/quickbook/src/doc_info_grammar.cpp b/tools/quickbook/src/doc_info_grammar.cpp
index 862d0ce57a..1d71e3b3eb 100644
--- a/tools/quickbook/src/doc_info_grammar.cpp
+++ b/tools/quickbook/src/doc_info_grammar.cpp
@@ -11,7 +11,6 @@
#include <map>
#include <boost/foreach.hpp>
#include <boost/spirit/include/classic_core.hpp>
-#include <boost/spirit/include/classic_actor.hpp>
#include <boost/spirit/include/classic_loops.hpp>
#include <boost/spirit/include/classic_symbols.hpp>
#include <boost/spirit/include/classic_chset.hpp>
@@ -75,7 +74,7 @@ namespace quickbook
doc_authors, doc_author,
doc_copyright, doc_copyright_holder,
doc_source_mode, doc_biblioid, doc_compatibility_mode,
- quickbook_version, char_;
+ quickbook_version, macro, char_;
cl::uint_parser<int, 10, 4, 4> doc_copyright_year;
cl::symbols<> doc_types;
cl::symbols<value::tag_type> doc_info_attributes;
@@ -118,15 +117,23 @@ namespace quickbook
// Actions
error_action error(state);
- plain_char_action plain_char(state.phrase, state);
+ plain_char_action plain_char(state);
+ do_macro_action do_macro(state);
scoped_parser<to_value_scoped_action> to_value(state);
+ member_action_value<quickbook::state, source_mode_type> change_source_mode(
+ state, &state::change_source_mode);
+ member_action_fixed_value<quickbook::state, source_mode_type> default_source_mode(
+ state, &state::change_source_mode, source_mode_tags::cpp);
doc_info_details =
- space [ph::var(local.source_mode_unset) = true]
- >> *( local.doc_attribute
- >> space
+ cl::eps_p [ph::var(local.source_mode_unset) = true]
+ >> *( space
+ >> local.doc_attribute
+ )
+ >> !( space
+ >> local.doc_info_block
)
- >> !local.doc_info_block
+ >> *eol
;
local.doc_info_block =
@@ -145,7 +152,7 @@ namespace quickbook
]
>> space
>> !(qbk_ver(106u) >> cl::eps_p(ph::var(local.source_mode_unset))
- [cl::assign_a(state.source_mode, "c++")]
+ [default_source_mode]
)
>> ( *( ( local.doc_info_attribute
| local.doc_info_escaped_attributes
@@ -154,7 +161,7 @@ namespace quickbook
)
) [state.values.sort()]
>> ( ']'
- >> (+eol | cl::end_p)
+ >> (eol | cl::end_p)
| cl::eps_p [error]
)
;
@@ -218,12 +225,8 @@ namespace quickbook
local.attribute_rules[doc_attributes::compatibility_mode] = &local.doc_compatibility_mode;
- local.doc_source_mode =
- (
- cl::str_p("c++")
- | "python"
- | "teletype"
- ) [cl::assign_a(state.source_mode)]
+ local.doc_source_mode = source_modes
+ [change_source_mode]
[ph::var(local.source_mode_unset) = false]
;
@@ -302,6 +305,21 @@ namespace quickbook
local.attribute_rules[doc_info_attributes::biblioid] = &local.doc_biblioid;
- local.char_ = escape | cl::anychar_p[plain_char];
+ local.char_ =
+ escape
+ | local.macro
+ | cl::anychar_p[plain_char];
+ ;
+
+ local.macro =
+ cl::eps_p
+ ( ( state.macro
+ >> ~cl::eps_p(cl::alpha_p | '_')
+ // must not be followed by alpha or underscore
+ )
+ & macro_identifier // must be a valid macro for the current version
+ )
+ >> state.macro [do_macro]
+ ;
}
}
diff --git a/tools/quickbook/src/document_state.cpp b/tools/quickbook/src/document_state.cpp
new file mode 100644
index 0000000000..2841389cab
--- /dev/null
+++ b/tools/quickbook/src/document_state.cpp
@@ -0,0 +1,472 @@
+/*=============================================================================
+ 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 "document_state_impl.hpp"
+#include "utils.hpp"
+#include <boost/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/range/algorithm.hpp>
+#include <cctype>
+
+namespace quickbook
+{
+ struct file_info
+ {
+ boost::shared_ptr<file_info> const parent;
+ boost::shared_ptr<doc_info> const 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 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,
+ boost::string_ref doc_id_1_1,
+ id_placeholder const* override_id) :
+ parent(parent), document(parent->document),
+ compatibility_version(compatibility_version),
+ 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,
+ boost::string_ref doc_id_1_1) :
+ parent(parent), document(document),
+ compatibility_version(compatibility_version),
+ 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;
+ };
+
+ struct section_info
+ {
+ 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;
+ source_mode_info const source_mode;
+
+ section_info(boost::shared_ptr<section_info> const& parent,
+ file_info const* current_file, boost::string_ref id,
+ boost::string_ref id_1_1, id_placeholder const* placeholder_1_6,
+ source_mode_info const& source_mode) :
+ parent(parent),
+ compatibility_version(current_file->compatibility_version),
+ file_depth(current_file->depth),
+ level(parent ? parent->level + 1 : 1),
+ id_1_1(detail::to_s(id_1_1)),
+ placeholder_1_6(placeholder_1_6),
+ source_mode(source_mode) {}
+ };
+
+ //
+ // document_state
+ //
+
+ document_state::document_state()
+ : state(new document_state_impl)
+ {
+ }
+
+ document_state::~document_state() {}
+
+ void document_state::start_file(
+ unsigned compatibility_version,
+ boost::string_ref include_doc_id,
+ boost::string_ref id,
+ value const& title)
+ {
+ state->start_file(compatibility_version, false, include_doc_id, id, title);
+ }
+
+ std::string document_state::start_file_with_docinfo(
+ unsigned compatibility_version,
+ boost::string_ref include_doc_id,
+ boost::string_ref id,
+ value const& title)
+ {
+ return state->start_file(compatibility_version, true, include_doc_id,
+ id, title)->to_string();
+ }
+
+ void document_state::end_file()
+ {
+ state->end_file();
+ }
+
+ std::string document_state::begin_section(boost::string_ref id,
+ id_category category, source_mode_info const& source_mode)
+ {
+ return state->begin_section(id, category, source_mode)->to_string();
+ }
+
+ void document_state::end_section()
+ {
+ return state->end_section();
+ }
+
+ int document_state::section_level() const
+ {
+ return state->current_file->document->current_section->level;
+ }
+
+ source_mode_info document_state::section_source_mode() const
+ {
+ return state->current_file ?
+ state->current_file->document->current_section->source_mode :
+ source_mode_info();
+ }
+
+ std::string document_state::old_style_id(boost::string_ref id, id_category category)
+ {
+ return state->old_style_id(id, category)->to_string();
+ }
+
+ std::string document_state::add_id(boost::string_ref id, id_category category)
+ {
+ return state->add_id(id, category)->to_string();
+ }
+
+ std::string document_state::add_anchor(boost::string_ref id, id_category category)
+ {
+ return state->add_placeholder(id, category)->to_string();
+ }
+
+ std::string document_state::replace_placeholders_with_unresolved_ids(
+ boost::string_ref xml) const
+ {
+ return replace_ids(*state, xml);
+ }
+
+ std::string document_state::replace_placeholders(boost::string_ref xml) const
+ {
+ assert(!state->current_file);
+ std::vector<std::string> ids = generate_ids(*state, xml);
+ return replace_ids(*state, xml, &ids);
+ }
+
+ unsigned document_state::compatibility_version() const
+ {
+ return state->current_file->compatibility_version;
+ }
+
+ //
+ // id_placeholder
+ //
+
+ 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 id_placeholder::to_string() const
+ {
+ return '$' + boost::lexical_cast<std::string>(index);
+ }
+
+ //
+ // document_state_impl
+ //
+
+ id_placeholder const* document_state_impl::add_placeholder(
+ boost::string_ref id, id_category category,
+ id_placeholder const* parent)
+ {
+ placeholders.push_back(id_placeholder(
+ placeholders.size(), id, category, parent));
+ return &placeholders.back();
+ }
+
+ id_placeholder const* document_state_impl::get_placeholder(boost::string_ref value) const
+ {
+ // If this isn't a placeholder id.
+ if (value.size() <= 1 || *value.begin() != '$')
+ return 0;
+
+ unsigned index = boost::lexical_cast<int>(std::string(
+ value.begin() + 1, value.end()));
+
+ return &placeholders.at(index);
+ }
+
+ id_placeholder const* document_state_impl::get_id_placeholder(
+ boost::shared_ptr<section_info> const& section) const
+ {
+ return !section ? 0 :
+ section->file_depth < current_file->override_depth ?
+ current_file->override_id : section->placeholder_1_6;
+ }
+
+ id_placeholder const* document_state_impl::start_file(
+ unsigned compatibility_version,
+ bool document_root,
+ boost::string_ref include_doc_id,
+ boost::string_ref id,
+ value const& title)
+ {
+ boost::shared_ptr<file_info> parent = current_file;
+ assert(parent || document_root);
+
+ 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
+ // is required.
+
+ boost::string_ref initial_doc_id;
+
+ if (document_root ||
+ 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;
+ }
+
+ // 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.
+
+ std::string doc_id_1_1;
+
+ if (document_root || compatibility_version < 106u) {
+ if (title.check())
+ document->last_title_1_1 = detail::to_s(title.get_quickbook());
+
+ 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) {
+ 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.
+
+ source_mode_info default_source_mode;
+
+ if (!initial_doc_id.empty()) {
+ return create_new_section(id, id_category::explicit_section_id,
+ default_source_mode);
+ }
+ else if (!title.empty()) {
+ return create_new_section(
+ detail::make_identifier(title.get_quickbook()),
+ id_category::generated_doc,
+ default_source_mode);
+ }
+ else if (compatibility_version >= 106u) {
+ return create_new_section("doc", id_category::numbered, default_source_mode);
+ }
+ else {
+ return create_new_section("", id_category::generated_doc, default_source_mode);
+ }
+ }
+ else {
+ // 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 document_state_impl::end_file()
+ {
+ current_file = current_file->parent;
+ }
+
+ id_placeholder const* document_state_impl::add_id(
+ boost::string_ref id,
+ id_category category)
+ {
+ return add_id_to_section(id, category,
+ current_file->document->current_section);
+ }
+
+ id_placeholder const* document_state_impl::add_id_to_section(
+ boost::string_ref id,
+ id_category category,
+ boost::shared_ptr<section_info> const& section)
+ {
+ std::string id_part(id.begin(), id.end());
+
+ // Note: Normalizing id according to file compatibility version, but
+ // adding to section according to section compatibility version.
+
+ if (current_file->compatibility_version >= 106u &&
+ category.c < id_category::explicit_id) {
+ 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, placeholder_1_6);
+ }
+ else {
+ std::string const& qualified_id = section->id_1_1;
+
+ std::string new_id;
+ 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, placeholder_1_6);
+ }
+ }
+
+ id_placeholder const* document_state_impl::old_style_id(
+ boost::string_ref id,
+ id_category category)
+ {
+ return current_file->compatibility_version < 103u ?
+ add_placeholder(
+ current_file->document->section_id_1_1 + "." + detail::to_s(id), category) :
+ add_id(id, category);
+ }
+
+ id_placeholder const* document_state_impl::begin_section(
+ boost::string_ref id,
+ id_category category,
+ source_mode_info const& source_mode)
+ {
+ current_file->document->section_id_1_1 = detail::to_s(id);
+ return create_new_section(id, category, source_mode);
+ }
+
+ id_placeholder const* document_state_impl::create_new_section(
+ boost::string_ref id,
+ id_category category,
+ source_mode_info const& source_mode)
+ {
+ boost::shared_ptr<section_info> parent =
+ current_file->document->current_section;
+
+ id_placeholder const* p = 0;
+ id_placeholder const* placeholder_1_6 = 0;
+
+ std::string id_1_1;
+
+ 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());
+ }
+
+ 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 (!placeholder_1_6) {
+ new_id = current_file->doc_id_1_1;
+ if (!id_1_1.empty()) new_id += '.';
+ }
+ new_id += id_1_1;
+
+ p = add_placeholder(new_id, category, placeholder_1_6);
+ }
+ else {
+ placeholder_1_6 = get_id_placeholder(parent);
+
+ std::string new_id;
+ 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, placeholder_1_6);
+ }
+
+ current_file->document->current_section =
+ boost::make_shared<section_info>(parent,
+ current_file.get(), id, id_1_1, placeholder_1_6,
+ source_mode);
+
+ return p;
+ }
+
+ void document_state_impl::end_section()
+ {
+ current_file->document->current_section =
+ current_file->document->current_section->parent;
+ }
+}
diff --git a/tools/quickbook/src/id_manager.hpp b/tools/quickbook/src/document_state.hpp
index e071241773..2210c41731 100644
--- a/tools/quickbook/src/id_manager.hpp
+++ b/tools/quickbook/src/document_state.hpp
@@ -1,17 +1,19 @@
/*=============================================================================
- 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)
=============================================================================*/
-#if !defined(BOOST_QUICKBOOK_ID_MANAGER_HPP)
-#define BOOST_QUICKBOOK_ID_MANAGER_HPP
+#if !defined(BOOST_QUICKBOOK_DOCUMENT_STATE_HPP)
+#define BOOST_QUICKBOOK_DOCUMENT_STATE_HPP
#include <boost/scoped_ptr.hpp>
+#include <boost/utility/string_ref.hpp>
#include <string>
#include "values.hpp"
+#include "syntax_highlight.hpp"
namespace quickbook
{
@@ -43,43 +45,44 @@ namespace quickbook
categories c;
};
- struct id_state;
- struct section_manager;
+ struct document_state_impl;
- struct id_manager
+ struct document_state
{
- id_manager();
- ~id_manager();
+ document_state();
+ ~document_state();
std::string start_file_with_docinfo(
unsigned compatibility_version,
- std::string const& include_doc_id,
- std::string const& id,
+ boost::string_ref include_doc_id,
+ boost::string_ref id,
value const& title);
void start_file(
unsigned compatibility_version,
- std::string const& include_doc_id,
- std::string const& id,
+ boost::string_ref include_doc_id,
+ boost::string_ref id,
value const& title);
void end_file();
- std::string begin_section(std::string const&, id_category);
+ std::string begin_section(boost::string_ref, id_category,
+ source_mode_info const&);
void end_section();
int section_level() const;
+ source_mode_info section_source_mode() const;
- std::string old_style_id(std::string const&, id_category);
- std::string add_id(std::string const&, id_category);
- std::string add_anchor(std::string const&, id_category);
+ std::string old_style_id(boost::string_ref, id_category);
+ std::string add_id(boost::string_ref, id_category);
+ std::string add_anchor(boost::string_ref, id_category);
std::string replace_placeholders_with_unresolved_ids(
- std::string const&) const;
- std::string replace_placeholders(std::string const&) const;
-
+ boost::string_ref) const;
+ std::string replace_placeholders(boost::string_ref) const;
+
unsigned compatibility_version() const;
private:
- boost::scoped_ptr<id_state> state;
+ boost::scoped_ptr<document_state_impl> state;
};
}
diff --git a/tools/quickbook/src/document_state_impl.hpp b/tools/quickbook/src/document_state_impl.hpp
new file mode 100644
index 0000000000..e9258e3b11
--- /dev/null
+++ b/tools/quickbook/src/document_state_impl.hpp
@@ -0,0 +1,147 @@
+/*=============================================================================
+ 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_DOCUMENT_STATE_IMPL_HPP)
+#define BOOST_QUICKBOOK_DOCUMENT_STATE_IMPL_HPP
+
+#include "document_state.hpp"
+#include "phrase_tags.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 document_state_impl::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;
+ };
+
+ //
+ // document_state_impl
+ //
+ // Contains all the data tracked by document_state.
+ //
+
+ struct file_info;
+ struct doc_info;
+ struct section_info;
+
+ struct document_state_impl
+ {
+ 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,
+ source_mode_info const&);
+ 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,
+ source_mode_info const&);
+ };
+
+ std::string replace_ids(document_state_impl const& state, boost::string_ref xml,
+ std::vector<std::string> const* = 0);
+ std::vector<std::string> generate_ids(document_state_impl 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
diff --git a/tools/quickbook/src/files.cpp b/tools/quickbook/src/files.cpp
index f85b611623..9999b0f220 100644
--- a/tools/quickbook/src/files.cpp
+++ b/tools/quickbook/src/files.cpp
@@ -15,6 +15,7 @@
#include <boost/foreach.hpp>
#include <fstream>
#include <iterator>
+#include <vector>
namespace quickbook
{
@@ -135,12 +136,17 @@ namespace quickbook
return pos->second;
}
+ std::ostream& operator<<(std::ostream& out, file_position const& x)
+ {
+ return out << "line: " << x.line << ", column: " << x.column;
+ }
+
file_position relative_position(
- std::string::const_iterator begin,
- std::string::const_iterator iterator)
+ boost::string_ref::const_iterator begin,
+ boost::string_ref::const_iterator iterator)
{
file_position pos;
- std::string::const_iterator line_begin = begin;
+ boost::string_ref::const_iterator line_begin = begin;
while (begin != iterator)
{
@@ -172,9 +178,9 @@ namespace quickbook
return pos;
}
- file_position file::position_of(std::string::const_iterator iterator) const
+ file_position file::position_of(boost::string_ref::const_iterator iterator) const
{
- return relative_position(source.begin(), iterator);
+ return relative_position(source().begin(), iterator);
}
// Mapped files.
@@ -195,50 +201,8 @@ namespace quickbook
std::string::size_type original_pos,
std::string::size_type our_pos,
section_types section_type = normal) :
- original_pos(original_pos), our_pos(our_pos), section_type(section_type) {}
-
- std::string::size_type to_original_pos(std::string::size_type pos)
- {
- switch (section_type) {
- case normal:
- return pos - our_pos + original_pos;
- case empty:
- return original_pos;
- case indented:
- // Indented doesn't really work, but that's okay because we
- // currently don't break up indented code.
- assert(pos == our_pos);
- return pos - our_pos + original_pos;
- default:
- assert(false);
- return original_pos;
- }
- }
-
- // If 'to_original_pos' worked for indented blocks, this wouldn't
- // be necessary.
- file_position calculate_position(
- file_position const& original,
- file_position const& relative) const
- {
- switch (section_type) {
- case normal:
- return file_position(
- original.line + relative.line - 1,
- relative.line == 1 ?
- original.column + relative.column - 1 :
- relative.column);
- case empty:
- return original;
- case indented:
- return file_position(
- original.line + relative.line - 1,
- original.column + relative.column - 1);
- default:
- assert(false);
- return file_position();
- }
- }
+ original_pos(original_pos), our_pos(our_pos),
+ section_type(section_type) {}
};
struct mapped_section_original_cmp
@@ -293,9 +257,9 @@ namespace quickbook
file_ptr original;
std::vector<mapped_file_section> mapped_sections;
- void add_empty_mapped_file_section(std::string::const_iterator pos) {
+ void add_empty_mapped_file_section(boost::string_ref::const_iterator pos) {
std::string::size_type original_pos =
- pos - original->source.begin();
+ pos - original->source().begin();
if (mapped_sections.empty() ||
mapped_sections.back().section_type !=
@@ -303,23 +267,109 @@ namespace quickbook
mapped_sections.back().original_pos != original_pos)
{
mapped_sections.push_back(mapped_file_section(
- original_pos, source.size(),
+ original_pos, source().size(),
mapped_file_section::empty));
}
}
- void add_mapped_file_section(std::string::const_iterator pos) {
+ void add_mapped_file_section(boost::string_ref::const_iterator pos) {
mapped_sections.push_back(mapped_file_section(
- pos - original->source.begin(), source.size()));
+ pos - original->source().begin(), source().size()));
}
- void add_indented_mapped_file_section(std::string::const_iterator pos) {
+ void add_indented_mapped_file_section(boost::string_ref::const_iterator pos)
+ {
mapped_sections.push_back(mapped_file_section(
- pos - original->source.begin(), source.size(),
+ pos - original->source().begin(), source().size(),
mapped_file_section::indented));
}
- virtual file_position position_of(std::string::const_iterator) const;
+ std::string::size_type to_original_pos(
+ std::vector<mapped_file_section>::const_iterator section,
+ std::string::size_type pos) const
+ {
+ switch (section->section_type) {
+ case mapped_file_section::normal:
+ return pos - section->our_pos + section->original_pos;
+
+ case mapped_file_section::empty:
+ return section->original_pos;
+
+ case mapped_file_section::indented: {
+ // Will contain the start of the current line.
+ boost::string_ref::size_type our_line = section->our_pos;
+
+ // Will contain the number of lines in the block before
+ // the current line.
+ unsigned newline_count = 0;
+
+ for(boost::string_ref::size_type i = section->our_pos;
+ i != pos; ++i)
+ {
+ if (source()[i] == '\n') {
+ our_line = i + 1;
+ ++newline_count;
+ }
+ }
+
+ // The start of the line in the original source.
+ boost::string_ref::size_type original_line =
+ section->original_pos;
+
+ while(newline_count > 0) {
+ if (original->source()[original_line] == '\n')
+ --newline_count;
+ ++original_line;
+ }
+
+ // The start of line content (i.e. after indentation).
+ our_line = skip_indentation(source(), our_line);
+
+ // The position is in the middle of indentation, so
+ // just return the start of the whitespace, which should
+ // be good enough.
+ if (our_line > pos) return original_line;
+
+ original_line =
+ skip_indentation(original->source(), original_line);
+
+ // Confirm that we are actually in the same position.
+ assert(original->source()[original_line] ==
+ source()[our_line]);
+
+ // Calculate the position
+ return original_line + (pos - our_line);
+ }
+ default:
+ assert(false);
+ return section->original_pos;
+ }
+ }
+
+ std::vector<mapped_file_section>::const_iterator find_section(
+ boost::string_ref::const_iterator pos) const
+ {
+ std::vector<mapped_file_section>::const_iterator section =
+ boost::upper_bound(mapped_sections,
+ std::string::size_type(pos - source().begin()),
+ mapped_section_pos_cmp());
+ assert(section != mapped_sections.begin());
+ --section;
+
+ return section;
+ }
+
+ virtual file_position position_of(boost::string_ref::const_iterator) const;
+
+ private:
+
+ static std::string::size_type skip_indentation(
+ boost::string_ref src, std::string::size_type i)
+ {
+ while (i != src.size() && (src[i] == ' ' || src[i] == '\t')) ++i;
+ return i;
+ }
+
};
namespace {
@@ -361,57 +411,49 @@ namespace quickbook
bool mapped_file_builder::empty() const
{
- return data->new_file->source.empty();
+ return data->new_file->source().empty();
}
mapped_file_builder::pos mapped_file_builder::get_pos() const
{
- return data->new_file->source.size();
+ return data->new_file->source().size();
}
- void mapped_file_builder::add(char const* x, iterator pos)
- {
- data->new_file->add_empty_mapped_file_section(pos);
- data->new_file->source.append(x);
- }
-
- void mapped_file_builder::add(std::string const& x, iterator pos)
+ void mapped_file_builder::add_at_pos(boost::string_ref x, iterator pos)
{
data->new_file->add_empty_mapped_file_section(pos);
- data->new_file->source.append(x);
+ data->new_file->source_.append(x.begin(), x.end());
}
- void mapped_file_builder::add(iterator begin, iterator end)
+ void mapped_file_builder::add(boost::string_ref x)
{
- data->new_file->add_mapped_file_section(begin);
- data->new_file->source.append(begin, end);
+ data->new_file->add_mapped_file_section(x.begin());
+ data->new_file->source_.append(x.begin(), x.end());
}
void mapped_file_builder::add(mapped_file_builder const& x)
{
- add(x, 0, x.data->new_file->source.size());
+ add(x, 0, x.data->new_file->source_.size());
}
void mapped_file_builder::add(mapped_file_builder const& x,
pos begin, pos end)
{
assert(data->new_file->original == x.data->new_file->original);
- assert(begin <= x.data->new_file->source.size());
- assert(end <= x.data->new_file->source.size());
+ assert(begin <= x.data->new_file->source_.size());
+ assert(end <= x.data->new_file->source_.size());
if (begin != end)
{
- std::vector<mapped_file_section>::iterator start =
- boost::upper_bound(x.data->new_file->mapped_sections,
- begin, mapped_section_pos_cmp());
- assert(start != x.data->new_file->mapped_sections.begin());
- --start;
+ std::vector<mapped_file_section>::const_iterator start =
+ x.data->new_file->find_section(
+ x.data->new_file->source().begin() + begin);
- std::string::size_type size = data->new_file->source.size();
+ std::string::size_type size = data->new_file->source_.size();
data->new_file->mapped_sections.push_back(mapped_file_section(
- start->to_original_pos(begin), size,
- start->section_type));
+ x.data->new_file->to_original_pos(start, begin),
+ size, start->section_type));
for (++start; start != x.data->new_file->mapped_sections.end() &&
start->our_pos < end; ++start)
@@ -421,89 +463,141 @@ namespace quickbook
start->section_type));
}
- data->new_file->source.append(
- x.data->new_file->source.begin() + begin,
- x.data->new_file->source.begin() + end);
+ data->new_file->source_.append(
+ x.data->new_file->source_.begin() + begin,
+ x.data->new_file->source_.begin() + end);
}
}
- void mapped_file_builder::unindent_and_add(iterator begin, iterator end)
+ boost::string_ref::size_type indentation_count(boost::string_ref x)
{
- std::string program(begin, end);
+ unsigned count = 0;
- // Erase leading blank lines and newlines:
- std::string::size_type start = program.find_first_not_of(" \t");
- if (start != std::string::npos &&
- (program[start] == '\r' || program[start] == '\n'))
+ for(boost::string_ref::const_iterator begin = x.begin(), end = x.end();
+ begin != end; ++begin)
{
- program.erase(0, start);
+ switch(*begin)
+ {
+ case ' ':
+ ++count;
+ break;
+ case '\t':
+ // hardcoded tab to 4 for now
+ count = count - (count % 4) + 4;
+ break;
+ default:
+ assert(false);
+ }
}
- start = program.find_first_not_of("\r\n");
- program.erase(0, start);
- if (program.size() == 0)
- return; // nothing left to do
+ return count;
+ }
+
+ void mapped_file_builder::unindent_and_add(boost::string_ref x)
+ {
+ // I wanted to do everything using a string_ref, but unfortunately
+ // they don't have all the overloads used in here. So...
+ std::string const program(x.begin(), x.end());
+
+ // Erase leading blank lines and newlines:
+ std::string::size_type start = program.find_first_not_of(" \t\r\n");
+ if (start == std::string::npos) return;
+
+ start = program.find_last_of("\r\n", start);
+ start = start == std::string::npos ? 0 : start + 1;
+
+ assert(start < program.size());
+
+ // Get the first line indentation
+ std::string::size_type indent = program.find_first_not_of(" \t", start) - start;
+ boost::string_ref::size_type full_indent = indentation_count(
+ boost::string_ref(&program[start], indent));
+
+ std::string::size_type pos = start;
- // Get the first line indent
- std::string::size_type indent = program.find_first_not_of(" \t");
- std::string::size_type pos = 0;
- if (std::string::npos == indent)
+ // Calculate the minimum indent from the rest of the lines
+ // Detecting a mix of spaces and tabs.
+ while (std::string::npos != (pos = program.find_first_of("\r\n", pos)))
{
- // Nothing left to do here. The code is empty (just spaces).
- // We clear the program to signal the caller that it is empty
- // and return early.
- program.clear();
- return;
+ pos = program.find_first_not_of("\r\n", pos);
+ if (std::string::npos == pos) break;
+
+ std::string::size_type n = program.find_first_not_of(" \t", pos);
+ if (n == std::string::npos) break;
+
+ char ch = program[n];
+ if (ch == '\r' || ch == '\n') continue; // ignore empty lines
+
+ indent = (std::min)(indent, n-pos);
+ full_indent = (std::min)(full_indent, indentation_count(
+ boost::string_ref(&program[pos], n-pos)));
}
- // Calculate the minimum indent from the rest of the lines
- do
+ // Detect if indentation is mixed.
+ bool mixed_indentation = false;
+ boost::string_ref first_indent(&program[start], indent);
+ pos = start;
+
+ while (std::string::npos != (pos = program.find_first_of("\r\n", pos)))
{
pos = program.find_first_not_of("\r\n", pos);
- if (std::string::npos == pos)
- break;
+ if (std::string::npos == pos) break;
std::string::size_type n = program.find_first_not_of(" \t", pos);
- if (n != std::string::npos)
- {
- char ch = program[n];
- if (ch != '\r' && ch != '\n') // ignore empty lines
- indent = (std::min)(indent, n-pos);
+ if (n == std::string::npos || n-pos < indent) continue;
+
+ if (boost::string_ref(&program[pos], indent) != first_indent) {
+ mixed_indentation = true;
+ break;
}
}
- while (std::string::npos != (pos = program.find_first_of("\r\n", pos)));
// Trim white spaces from column 0..indent
- pos = 0;
- program.erase(0, indent);
- while (std::string::npos != (pos = program.find_first_of("\r\n", pos)))
- {
+ std::string unindented_program;
+ std::string::size_type copy_start = start;
+ pos = start;
+
+ do {
if (std::string::npos == (pos = program.find_first_not_of("\r\n", pos)))
- {
break;
+
+ unindented_program.append(program.begin() + copy_start, program.begin() + pos);
+ copy_start = pos;
+
+ // Find the end of the indentation.
+ std::string::size_type next = program.find_first_not_of(" \t", pos);
+ if (next == std::string::npos) next = program.size();
+
+ if (mixed_indentation)
+ {
+ unsigned length = indentation_count(boost::string_ref(
+ &program[pos], next - pos));
+
+ if (length > full_indent) {
+ std::string new_indentation(length - full_indent, ' ');
+ unindented_program.append(new_indentation);
+ }
+
+ copy_start = next;
+ }
+ else
+ {
+ copy_start = (std::min)(pos + indent, next);
}
- std::string::size_type next = program.find_first_of("\r\n", pos);
- program.erase(pos, (std::min)(indent, next-pos));
- }
+ pos = next;
+ } while (std::string::npos !=
+ (pos = program.find_first_of("\r\n", pos)));
+
+ unindented_program.append(program.begin() + copy_start, program.end());
- data->new_file->add_indented_mapped_file_section(begin + indent);
- data->new_file->source.append(program);
+ data->new_file->add_indented_mapped_file_section(x.begin());
+ data->new_file->source_.append(unindented_program);
}
- file_position mapped_file::position_of(std::string::const_iterator pos) const
+ file_position mapped_file::position_of(boost::string_ref::const_iterator pos) const
{
- std::vector<mapped_file_section>::const_iterator section =
- boost::upper_bound(mapped_sections,
- std::string::size_type(pos - source.begin()),
- mapped_section_pos_cmp());
- assert(section != mapped_sections.begin());
- --section;
-
- return section->calculate_position(
- original->position_of(
- original->source.begin() + section->original_pos),
- relative_position(source.begin() + section->our_pos, pos)
- );
+ return original->position_of(original->source().begin() +
+ to_original_pos(find_section(pos), pos - source().begin()));
}
}
diff --git a/tools/quickbook/src/files.hpp b/tools/quickbook/src/files.hpp
index 4f217e70cd..0a2e5309c5 100644
--- a/tools/quickbook/src/files.hpp
+++ b/tools/quickbook/src/files.hpp
@@ -14,8 +14,10 @@
#include <string>
#include <boost/filesystem/path.hpp>
#include <boost/intrusive_ptr.hpp>
+#include <boost/utility/string_ref.hpp>
#include <stdexcept>
#include <cassert>
+#include <iosfwd>
namespace quickbook {
@@ -31,6 +33,13 @@ namespace quickbook {
int line;
int column;
+
+ bool operator==(file_position const& other) const
+ {
+ return line == other.line && column == other.column;
+ }
+
+ friend std::ostream& operator<<(std::ostream&, file_position const&);
};
struct file
@@ -41,21 +50,23 @@ namespace quickbook {
file(file const&);
public:
fs::path const path;
- std::string source;
+ std::string source_;
bool is_code_snippets;
private:
unsigned qbk_version;
unsigned ref_count;
public:
+ boost::string_ref source() const { return source_; }
- file(fs::path const& path, std::string const& source,
+ file(fs::path const& path, boost::string_ref source,
unsigned qbk_version) :
- path(path), source(source), is_code_snippets(false),
+ path(path), source_(source.begin(), source.end()), is_code_snippets(false),
qbk_version(qbk_version), ref_count(0)
{}
- file(file const& f, std::string const& source) :
- path(f.path), source(source), is_code_snippets(f.is_code_snippets),
+ file(file const& f, boost::string_ref source) :
+ path(f.path), source_(source.begin(), source.end()),
+ is_code_snippets(f.is_code_snippets),
qbk_version(f.qbk_version), ref_count(0)
{}
@@ -76,7 +87,7 @@ namespace quickbook {
qbk_version = v;
}
- virtual file_position position_of(std::string::const_iterator) const;
+ virtual file_position position_of(boost::string_ref::const_iterator) const;
friend void intrusive_ptr_add_ref(file* ptr) { ++ptr->ref_count; }
@@ -101,8 +112,8 @@ namespace quickbook {
struct mapped_file_builder
{
- typedef std::string::const_iterator iterator;
- typedef std::string::size_type pos;
+ typedef boost::string_ref::const_iterator iterator;
+ typedef boost::string_ref::size_type pos;
mapped_file_builder();
~mapped_file_builder();
@@ -114,12 +125,11 @@ namespace quickbook {
bool empty() const;
pos get_pos() const;
- void add(char const*, iterator);
- void add(std::string const&, iterator);
- void add(iterator, iterator);
+ void add_at_pos(boost::string_ref, iterator);
+ void add(boost::string_ref);
void add(mapped_file_builder const&);
void add(mapped_file_builder const&, pos, pos);
- void unindent_and_add(iterator, iterator);
+ void unindent_and_add(boost::string_ref);
private:
mapped_file_builder_data* data;
diff --git a/tools/quickbook/src/fwd.hpp b/tools/quickbook/src/fwd.hpp
index 7cccde8735..5dec2d68a2 100644
--- a/tools/quickbook/src/fwd.hpp
+++ b/tools/quickbook/src/fwd.hpp
@@ -13,19 +13,21 @@
#include "iterator.hpp"
#include <boost/intrusive_ptr.hpp>
+#include <boost/utility/string_ref.hpp>
namespace quickbook
{
struct state;
struct quickbook_grammar;
struct collector;
- struct id_manager;
+ struct document_state;
struct section_info;
struct file;
struct template_symbol;
typedef boost::intrusive_ptr<file> file_ptr;
+ typedef unsigned source_mode_type;
- typedef std::string::const_iterator string_iterator;
+ typedef boost::string_ref::const_iterator string_iterator;
typedef lookback_iterator<string_iterator> parse_iterator;
inline void ignore_variable(void const*) {}
diff --git a/tools/quickbook/src/glob.cpp b/tools/quickbook/src/glob.cpp
new file mode 100644
index 0000000000..474bdeb077
--- /dev/null
+++ b/tools/quickbook/src/glob.cpp
@@ -0,0 +1,301 @@
+/*=============================================================================
+ Copyright (c) 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 "glob.hpp"
+#include <cassert>
+
+namespace quickbook
+{
+ typedef boost::string_ref::const_iterator glob_iterator;
+
+ void check_glob_range(glob_iterator&, glob_iterator);
+ void check_glob_escape(glob_iterator&, glob_iterator);
+
+ bool match_section(glob_iterator& pattern_begin, glob_iterator pattern_end,
+ glob_iterator& filename_begin, glob_iterator& filename_end);
+ bool match_range(glob_iterator& pattern_begin, glob_iterator pattern_end,
+ unsigned char x);
+
+ bool check_glob(boost::string_ref pattern)
+ {
+ bool is_glob = false;
+ bool is_ascii = true;
+
+ glob_iterator begin = pattern.begin();
+ glob_iterator end = pattern.end();
+
+ while (begin != end) {
+ if (*begin < 32 || *begin > 127)
+ is_ascii = false;
+
+ switch(*begin) {
+ case '\\':
+ check_glob_escape(begin, end);
+ break;
+
+ case '[':
+ check_glob_range(begin, end);
+ is_glob = true;
+ break;
+
+ case ']':
+ throw glob_error("uneven square brackets");
+
+ case '?':
+ is_glob = true;
+ ++begin;
+ break;
+
+ case '*':
+ is_glob = true;
+ ++begin;
+
+ if (begin != end && *begin == '*') {
+ throw glob_error("'**' not supported");
+ }
+ break;
+
+ default:
+ ++begin;
+ }
+ }
+
+ if (is_glob && !is_ascii)
+ throw glob_error("invalid character, globs are ascii only");
+
+ return is_glob;
+ }
+
+ void check_glob_range(glob_iterator& begin, glob_iterator end)
+ {
+ assert(begin != end && *begin == '[');
+ ++begin;
+
+ if (*begin == ']')
+ throw glob_error("empty range");
+
+ while (begin != end) {
+ switch (*begin) {
+ case '\\':
+ ++begin;
+
+ if (begin == end) {
+ throw glob_error("trailing escape");
+ }
+ else if (*begin == '\\' || *begin == '/') {
+ throw glob_error("contains escaped slash");
+ }
+
+ ++begin;
+ break;
+ case '[':
+ // TODO: Allow?
+ throw glob_error("nested square brackets");
+ case ']':
+ ++begin;
+ return;
+ case '/':
+ throw glob_error("slash in square brackets");
+ default:
+ ++begin;
+ }
+ }
+
+ throw glob_error("uneven square brackets");
+ }
+
+ void check_glob_escape(glob_iterator& begin, glob_iterator end)
+ {
+ assert(begin != end && *begin == '\\');
+
+ ++begin;
+
+ if (begin == end) {
+ throw glob_error("trailing escape");
+ }
+ else if (*begin == '\\' || *begin == '/') {
+ throw glob_error("contains escaped slash");
+ }
+
+ ++begin;
+ }
+
+ bool glob(boost::string_ref const& pattern,
+ boost::string_ref const& filename)
+ {
+ // If there wasn't this special case then '*' would match an
+ // empty string.
+ if (filename.empty()) return pattern.empty();
+
+ glob_iterator pattern_it = pattern.begin();
+ glob_iterator pattern_end = pattern.end();
+
+ glob_iterator filename_it = filename.begin();
+ glob_iterator filename_end = filename.end();
+
+ if (!match_section(pattern_it, pattern_end, filename_it, filename_end))
+ return false;
+
+ while (pattern_it != pattern_end) {
+ assert(*pattern_it == '*');
+ ++pattern_it;
+
+ if (pattern_it == pattern_end) return true;
+
+ // TODO: Error?
+ if (*pattern_it == '*') return false;
+
+ while (true) {
+ if (filename_it == filename_end) return false;
+ if (match_section(pattern_it, pattern_end, filename_it, filename_end))
+ break;
+ ++filename_it;
+ }
+ }
+
+ return filename_it == filename_end;
+ }
+
+ bool match_section(glob_iterator& pattern_begin, glob_iterator pattern_end,
+ glob_iterator& filename_begin, glob_iterator& filename_end)
+ {
+ glob_iterator pattern_it = pattern_begin;
+ glob_iterator filename_it = filename_begin;
+
+ while (pattern_it != pattern_end && *pattern_it != '*') {
+ if (filename_it == filename_end) return false;
+
+ switch(*pattern_it) {
+ case '*':
+ assert(false);
+ return false;
+ case '[':
+ if (!match_range(pattern_it, pattern_end, *filename_it))
+ return false;
+ ++filename_it;
+ break;
+ case '?':
+ ++pattern_it;
+ ++filename_it;
+ break;
+ case '\\':
+ ++pattern_it;
+ if (pattern_it == pattern_end) return false;
+ BOOST_FALLTHROUGH;
+ default:
+ if (*pattern_it != *filename_it) return false;
+ ++pattern_it;
+ ++filename_it;
+ }
+ }
+
+ if (pattern_it == pattern_end && filename_it != filename_end)
+ return false;
+
+ pattern_begin = pattern_it;
+ filename_begin = filename_it;
+ return true;
+ }
+
+ bool match_range(glob_iterator& pattern_begin, glob_iterator pattern_end,
+ unsigned char x)
+ {
+ assert(pattern_begin != pattern_end && *pattern_begin == '[');
+ ++pattern_begin;
+ if (pattern_begin == pattern_end) return false;
+
+ bool invert_match = false;
+ bool matched = false;
+
+ if (*pattern_begin == '^') {
+ invert_match = true;
+ ++pattern_begin;
+ if (pattern_begin == pattern_end) return false;
+ }
+
+ // Search for a match
+ while (true) {
+ unsigned char first = *pattern_begin;
+ ++pattern_begin;
+ if (first == ']') break;
+ if (pattern_begin == pattern_end) return false;
+
+ if (first == '\\') {
+ first = *pattern_begin;
+ ++pattern_begin;
+ if (pattern_begin == pattern_end) return false;
+ }
+
+ if (*pattern_begin != '-') {
+ matched = matched || (first == x);
+ }
+ else {
+ ++pattern_begin;
+ if (pattern_begin == pattern_end) return false;
+
+ unsigned char second = *pattern_begin;
+ ++pattern_begin;
+ if (second == ']') {
+ matched = matched || (first == x) || (x == '-');
+ break;
+ }
+ if (pattern_begin == pattern_end) return false;
+
+ if (second == '\\') {
+ second = *pattern_begin;
+ ++pattern_begin;
+ if (pattern_begin == pattern_end) return false;
+ }
+
+ // TODO: What if second < first?
+ matched = matched || (first <= x && x <= second);
+ }
+ }
+
+ return invert_match != matched;
+ }
+
+ std::size_t find_glob_char(boost::string_ref pattern,
+ std::size_t pos)
+ {
+ // Weird style is because boost::string_ref's find_first_of
+ // doesn't take a position argument.
+ std::size_t removed = 0;
+
+ while (true) {
+ pos = pattern.find_first_of("[]?*\\");
+ if (pos == boost::string_ref::npos) return pos;
+ if (pattern[pos] != '\\') return pos + removed;
+ pattern.remove_prefix(pos + 2);
+ removed += pos + 2;
+ }
+ }
+
+ std::string glob_unescape(boost::string_ref pattern)
+ {
+ std::string result;
+
+ while (true) {
+ std::size_t pos = pattern.find("\\");
+ if (pos == boost::string_ref::npos) {
+ result.append(pattern.data(), pattern.size());
+ break;
+ }
+
+ result.append(pattern.data(), pos);
+ ++pos;
+ if (pos < pattern.size()) {
+ result += pattern[pos];
+ ++pos;
+ }
+ pattern.remove_prefix(pos);
+ }
+
+ return result;
+ }
+}
diff --git a/tools/quickbook/src/glob.hpp b/tools/quickbook/src/glob.hpp
new file mode 100644
index 0000000000..8e8458961a
--- /dev/null
+++ b/tools/quickbook/src/glob.hpp
@@ -0,0 +1,30 @@
+/*=============================================================================
+ Copyright (c) 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 <boost/utility/string_ref.hpp>
+#include <stdexcept>
+
+namespace quickbook
+{
+ struct glob_error : std::runtime_error
+ {
+ explicit glob_error(char const* error) :
+ std::runtime_error(error) {}
+ };
+
+ // Is this path a glob? Throws glob_error if glob is invalid.
+ bool check_glob(boost::string_ref);
+
+ // pre: glob is valid (call check_glob first on user data).
+ bool glob(boost::string_ref const& pattern,
+ boost::string_ref const& filename);
+
+ std::size_t find_glob_char(boost::string_ref,
+ std::size_t start = 0);
+ std::string glob_unescape(boost::string_ref);
+}
diff --git a/tools/quickbook/src/grammar.cpp b/tools/quickbook/src/grammar.cpp
index 8f244f18ac..54ed64aa06 100644
--- a/tools/quickbook/src/grammar.cpp
+++ b/tools/quickbook/src/grammar.cpp
@@ -17,8 +17,10 @@ namespace quickbook
: 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")
+ , attribute_template_body(impl_->attribute_template_body,
+ "attribute_template_body")
, doc_info(impl_->doc_info_details, "doc_info")
{
}
diff --git a/tools/quickbook/src/grammar.hpp b/tools/quickbook/src/grammar.hpp
index 54aaf2b3ea..01d634c90f 100644
--- a/tools/quickbook/src/grammar.hpp
+++ b/tools/quickbook/src/grammar.hpp
@@ -58,8 +58,9 @@ namespace quickbook
public:
grammar command_line_macro;
grammar inline_phrase;
- grammar phrase;
- grammar block;
+ grammar phrase_start;
+ grammar block_start;
+ grammar attribute_template_body;
grammar doc_info;
quickbook_grammar(quickbook::state&);
diff --git a/tools/quickbook/src/grammar_impl.hpp b/tools/quickbook/src/grammar_impl.hpp
index 090b399048..8d37d351f1 100644
--- a/tools/quickbook/src/grammar_impl.hpp
+++ b/tools/quickbook/src/grammar_impl.hpp
@@ -20,26 +20,81 @@ namespace quickbook
{
namespace cl = boost::spirit::classic;
+ // Information about a square bracket element (e.g. [* word]).
+ //
+ // TODO: The naming is a bit confused as element is also sometimes used for
+ // syntactic/implicit elements (such as lists and horizontal rules). Maybe
+ // should use entity as a more general name instead of element. Or it might
+ // be better to use 'tag' for square bracket elements, although that is
+ // currently used for the type of entities.
struct element_info
{
+ // Types of elements.
+ //
+ // Used to determine:
+ //
+ // - where they can be used.
+ // - whether they end a paragraph
+ // - how following newlines are interpreted by the grammar.
+ // - and possibly other things.....
enum type_enum {
+ // Used when there's no element.
nothing = 0,
- block = 1,
+
+ // A section tag. These can't be nested.
+ section_block = 1,
+
+ // Block elements that can be used in conditional phrases and lists,
+ // but not nested. (TODO: not a good name).
conditional_or_block = 2,
+
+ // Block elements that can be nested in other elements.
nested_block = 4,
+
+ // Phrase elements.
phrase = 8,
+
+ // Depending on the context this can be a block or phrase.
+ //
+ // Currently this is only used for elements that don't actually
+ // generate output (e.g. anchors, source mode tags). The main
+ // reason is so that lists can be preceeded by the element, e.g.
+ //
+ // [#anchor]
+ // * list item.
+ //
+ // If the anchor was considered to be a phrase element, then the
+ // list wouldn't be recognised.
maybe_block = 16
};
+ // Masks to determine which context elements can be used in (in_*), and
+ // whether they are consided to be a block element (is_*).
enum context {
- in_phrase = phrase | maybe_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_list_block = phrase | maybe_block | nested_block |
+ conditional_or_block,
+
+ // In nested blocks we allow a more limited range of elements.
in_nested_block = phrase | maybe_block | nested_block,
- 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 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()
@@ -74,9 +129,11 @@ namespace quickbook
cl::rule<scanner> inside_preformatted;
cl::rule<scanner> inside_paragraph;
cl::rule<scanner> command_line;
+ cl::rule<scanner> attribute_template_body;
cl::rule<scanner> attribute_value_1_7;
cl::rule<scanner> escape;
cl::rule<scanner> raw_escape;
+ cl::rule<scanner> skip_entity;
// Miscellaneous stuff
cl::rule<scanner> hard_space;
@@ -90,6 +147,9 @@ namespace quickbook
// Element Symbols
cl::symbols<element_info> elements;
+
+ // Source mode
+ cl::symbols<source_mode_type> source_modes;
// Doc Info
cl::rule<scanner> doc_info_details;
diff --git a/tools/quickbook/src/id_generation.cpp b/tools/quickbook/src/id_generation.cpp
new file mode 100644
index 0000000000..b6445a5816
--- /dev/null
+++ b/tools/quickbook/src/id_generation.cpp
@@ -0,0 +1,379 @@
+/*=============================================================================
+ 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 <cctype>
+#include "document_state_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(document_state_impl 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(document_state_impl 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
+ {
+ document_state_impl const& state;
+ std::vector<unsigned>& order;
+ unsigned count;
+
+ get_placeholder_order_callback(document_state_impl 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(
+ document_state_impl 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.
+ std::size_t 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
+ {
+ document_state_impl const& state;
+ std::vector<std::string> const* ids;
+ boost::string_ref::const_iterator source_pos;
+ std::string result;
+
+ replace_ids_callback(document_state_impl 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(document_state_impl 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;
+ }
+}
diff --git a/tools/quickbook/src/id_manager.cpp b/tools/quickbook/src/id_manager.cpp
deleted file mode 100644
index 3b2f601a11..0000000000
--- a/tools/quickbook/src/id_manager.cpp
+++ /dev/null
@@ -1,1143 +0,0 @@
-/*=============================================================================
- Copyright (c) 2011 Daniel James
-
- Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-=============================================================================*/
-
-#include "id_manager.hpp"
-#include "utils.hpp"
-#include "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, std::string const& xml,
- bool use_resolved_ids = true);
- std::string process_ids(id_state&, std::string const&);
-
- 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,
- std::string const& id,
- id_category category,
- id_placeholder* parent_ = 0)
- : index(index),
- generation_state(parent_ ? child : unresolved),
- unresolved_id(parent_ ? parent_->unresolved_id + '.' + id : id),
- id(id),
- 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(
- std::string const&, id_category, id_placeholder* parent = 0);
-
- id_placeholder* get_placeholder(string_ref);
-
- // Events
-
- id_placeholder* start_file(
- unsigned compatibility_version,
- bool document_root,
- std::string const& include_doc_id,
- std::string const& id,
- value const& title);
-
- void end_file();
-
- id_placeholder* add_id(
- std::string const& id,
- id_category category);
- id_placeholder* old_style_id(
- std::string const& id,
- id_category category);
- id_placeholder* begin_section(
- std::string const& id,
- id_category category);
- void end_section();
-
-private:
- id_placeholder* add_id_to_section(
- std::string const& id,
- id_category category,
- boost::shared_ptr<section_info> const& section);
- id_placeholder* create_new_section(
- std::string const& 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;
-
- bool document_root; // !parent || document != parent->document
- unsigned compatibility_version;
- boost::shared_ptr<section_info> switched_section;
- id_placeholder* original_placeholder;
-
- // 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;
-
- file_info(boost::shared_ptr<file_info> const& parent,
- unsigned compatibility_version) :
- parent(parent), document(parent->document), document_root(false),
- compatibility_version(compatibility_version),
- switched_section(), original_placeholder()
- {}
-
- file_info(boost::shared_ptr<file_info> const& parent,
- boost::shared_ptr<doc_info> const& document,
- unsigned compatibility_version) :
- parent(parent), document(document), document_root(true),
- compatibility_version(compatibility_version),
- switched_section(), original_placeholder()
- {}
- };
-
- struct doc_info
- {
- boost::shared_ptr<section_info> current_section;
- 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;
-
- section_info(boost::shared_ptr<section_info> const& parent,
- unsigned compatibility_version, std::string const& id) :
- parent(parent), compatibility_version(compatibility_version),
- 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 += id;
- }
- }
- };
-
- //
- // id_manager
- //
-
- id_manager::id_manager()
- : state(new id_state)
- {
- }
-
- id_manager::~id_manager() {}
-
- void id_manager::start_file(
- unsigned compatibility_version,
- std::string const& include_doc_id,
- std::string const& id,
- value const& title)
- {
- state->start_file(compatibility_version, false, include_doc_id, id, title);
- }
-
- std::string id_manager::start_file_with_docinfo(
- unsigned compatibility_version,
- std::string const& include_doc_id,
- std::string const& id,
- value const& title)
- {
- return state->start_file(compatibility_version, true, include_doc_id,
- id, title)->to_string();
- }
-
- void id_manager::end_file()
- {
- state->end_file();
- }
-
- std::string id_manager::begin_section(std::string const& id,
- id_category category)
- {
- return state->begin_section(id, category)->to_string();
- }
-
- void id_manager::end_section()
- {
- return state->end_section();
- }
-
- int id_manager::section_level() const
- {
- return state->current_file->document->current_section->level;
- }
-
- std::string id_manager::old_style_id(std::string const& id, id_category category)
- {
- return state->old_style_id(id, category)->to_string();
- }
-
- std::string id_manager::add_id(std::string const& id, id_category category)
- {
- return state->add_id(id, category)->to_string();
- }
-
- std::string id_manager::add_anchor(std::string const& id, id_category category)
- {
- return state->add_placeholder(id, category)->to_string();
- }
-
- std::string id_manager::replace_placeholders_with_unresolved_ids(
- std::string const& xml) const
- {
- return replace_ids(*state, xml, false);
- }
-
- std::string id_manager::replace_placeholders(std::string const& xml) const
- {
- assert(!state->current_file);
- return process_ids(*state, xml);
- }
-
- unsigned id_manager::compatibility_version() const
- {
- return state->current_file->compatibility_version;
- }
-
- //
- // normalize_id
- //
- // Normalizes generated ids.
- //
-
- namespace
- {
- std::string normalize_id(
- std::string src_id,
- std::size_t prefix = 0,
- std::size_t size = max_size)
- {
- std::string id;
- id.swap(src_id);
-
- 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;
- }
- }
-
- //
- // id_state
- //
-
- id_placeholder* id_state::add_placeholder(
- std::string const& id, id_category category,
- id_placeholder* parent)
- {
- placeholders.push_back(id_placeholder(
- placeholders.size(), id, category, parent));
- return &placeholders.back();
- }
-
- id_placeholder* id_state::get_placeholder(string_ref value)
- {
- // If this isn't a placeholder id.
- if (value.size() <= 1 || *value.begin() != '$')
- return 0;
-
- unsigned index = boost::lexical_cast<int>(std::string(
- value.begin() + 1, value.end()));
-
- 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()
- {
- if (current_file->original_placeholder) {
- current_file->switched_section->placeholder_1_6 =
- current_file->original_placeholder;
- }
- }
-
- id_placeholder* id_state::start_file(
- unsigned compatibility_version,
- bool document_root,
- std::string const& include_doc_id,
- std::string const& id,
- value const& title)
- {
- // Create new file
-
- boost::shared_ptr<file_info> parent = current_file;
-
- 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);
- }
-
- // Choose specified id to use. Prefer 'include_doc_id' (the id
- // specified in an 'include' element) unless backwards compatibility
- // is required.
-
- std::string initial_doc_id;
-
- if (document_root ||
- compatibility_version >= 106u ||
- (parent && 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.
-
- if (document_root || compatibility_version < 106u) {
- // Note: this is done for older versions even if docinfo is
- // otherwise ignored.
-
- if (title.check())
- current_file->document->last_title_1_1 =
- title.get_quickbook();
-
- current_file->doc_id_1_1 = !initial_doc_id.empty() ? initial_doc_id :
- detail::make_identifier(current_file->document->last_title_1_1);
- }
- else if (parent) {
- current_file->doc_id_1_1 = parent->doc_id_1_1;
- }
-
- if (document_root) {
- if (!initial_doc_id.empty()) {
- return create_new_section(id, id_category::explicit_section_id);
- }
- else if (!title.empty()) {
- return create_new_section(
- detail::make_identifier(title.get_quickbook()),
- id_category::generated_doc);
- }
- else if (compatibility_version >= 106u) {
- return create_new_section("doc", id_category::numbered);
- }
- else {
- return create_new_section("", id_category::generated_doc);
- }
- }
- 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>()));
- }
-
- return 0;
- }
- }
-
- void id_state::end_file()
- {
- restore_section();
- current_file = current_file->parent;
- }
-
- id_placeholder* id_state::add_id(
- std::string const& id,
- id_category category)
- {
- return add_id_to_section(id, category,
- current_file->document->current_section);
- }
-
- id_placeholder* id_state::add_id_to_section(
- std::string const& id,
- id_category category,
- boost::shared_ptr<section_info> const& section)
- {
- std::string id_part = id;
-
- // Note: Normalizing id according to file compatibility version, but
- // adding to section according to section compatibility version.
-
- if (current_file->compatibility_version >= 106u &&
- category.c < id_category::explicit_id) {
- id_part = normalize_id(id);
- }
-
- if(!section || section->compatibility_version >= 106u) {
- return add_placeholder(id_part, category,
- section ? section->placeholder_1_6 : 0);
- }
- else {
- std::string const& qualified_id = section->id_1_1;
-
- std::string new_id;
- if (!section->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);
- }
- }
-
- id_placeholder* id_state::old_style_id(
- std::string const& id,
- id_category category)
- {
- return current_file->compatibility_version < 103u ?
- add_placeholder(
- current_file->document->section_id_1_1 + "." + id, category) :
- add_id(id, category);
- }
-
- id_placeholder* id_state::begin_section(
- std::string const& id,
- id_category category)
- {
- current_file->document->section_id_1_1 = id;
- return create_new_section(id, category);
- }
-
- id_placeholder* id_state::create_new_section(
- std::string const& 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* p;
-
- if (new_section->compatibility_version >= 106u) {
- p = add_id_to_section(id, category, parent);
- new_section->placeholder_1_6 = p;
- }
- else if (new_section->compatibility_version >= 103u) {
- if (parent)
- new_section->placeholder_1_6 = parent->placeholder_1_6;
-
- std::string new_id;
- if (!new_section->placeholder_1_6) {
- new_id = current_file->doc_id_1_1;
- if (!new_section->id_1_1.empty()) new_id += '.';
- }
- new_id += new_section->id_1_1;
-
- p = add_placeholder(new_id, category,
- new_section->placeholder_1_6);
- }
- else {
- if (parent)
- new_section->placeholder_1_6 = parent->placeholder_1_6;
-
- std::string new_id;
- if (parent && !new_section->placeholder_1_6)
- new_id = current_file->doc_id_1_1 + '.';
-
- new_id += id;
-
- p = add_placeholder(new_id, category,
- new_section->placeholder_1_6);
- }
-
- current_file->document->current_section = new_section;
-
- 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(string_ref) {}
- virtual void id_value(string_ref) {}
- virtual void finish(string_ref) {}
- virtual ~callback() {}
- };
-
- void parse(std::string const&, 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(std::string const& source, callback& c)
- {
- typedef std::string::const_iterator iterator;
-
- string_ref source_ref(source.begin(), source.end());
- c.start(source_ref);
-
- iterator it = source_ref.begin(), end = source_ref.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;
- string_ref name(name_start, it);
- ++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;
- string_ref value(value_start, it);
- ++it;
-
- if (boost::find(id_attributes, name)
- != id_attributes.end())
- {
- c.id_value(value);
- }
- }
- }
- else
- {
- read_past(it, end, ">");
- }
- }
- }
-
- c.finish(source_ref);
- }
-
- //
- // process_ids
- //
-
- //
- // Data used for generating placeholders that have duplicates.
- //
-
- struct id_generation_data
- {
- id_generation_data(std::string const& 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&, std::string const& xml);
- void resolve_id(id_placeholder&, allocated_ids&);
- void generate_id(id_placeholder&, allocated_ids&);
-
- std::string process_ids(id_state& state, std::string const& 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(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,
- std::string const& 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;
- std::string::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(string_ref xml)
- {
- source_pos = xml.begin();
- }
-
- void id_value(string_ref value)
- {
- if (id_placeholder* p = state.get_placeholder(value))
- {
- assert(!use_resolved_ids ||
- p->check_state(id_placeholder::generated));
- std::string const& 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(string_ref xml)
- {
- result.append(source_pos, xml.end());
- source_pos = xml.end();
- }
- };
-
- std::string replace_ids(id_state& state, std::string const& xml,
- bool use_unresolved_ids)
- {
- xml_processor processor;
- replace_ids_callback callback(state, use_unresolved_ids);
- processor.parse(xml, callback);
- return callback.result;
- }
-}
diff --git a/tools/quickbook/src/id_xml.cpp b/tools/quickbook/src/id_xml.cpp
new file mode 100644
index 0000000000..d69336b784
--- /dev/null
+++ b/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 "document_state_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);
+ }
+}
diff --git a/tools/quickbook/src/include_paths.cpp b/tools/quickbook/src/include_paths.cpp
new file mode 100644
index 0000000000..de910dcbaf
--- /dev/null
+++ b/tools/quickbook/src/include_paths.cpp
@@ -0,0 +1,291 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2005 Thomas Guest
+ Copyright (c) 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 "native_text.hpp"
+#include "glob.hpp"
+#include "include_paths.hpp"
+#include "state.hpp"
+#include "utils.hpp"
+#include "quickbook.hpp" // For the include_path global (yuck)
+#include <boost/foreach.hpp>
+#include <boost/range/algorithm/replace.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <cassert>
+
+namespace quickbook
+{
+ //
+ // check_path
+ //
+
+ path_parameter check_path(value const& path, quickbook::state& state)
+ {
+ if (qbk_version_n >= 107u) {
+ std::string path_text = path.get_encoded();
+
+ try {
+ if (check_glob(path_text)) {
+ return path_parameter(path_text, path_parameter::glob);
+ }
+ else {
+ return path_parameter(glob_unescape(path_text),
+ path_parameter::path);
+ }
+ } catch(glob_error& e) {
+ detail::outerr(path.get_file(), path.get_position())
+ << "Invalid path (" << e.what() << "): "
+ << path_text
+ << std::endl;
+ ++state.error_count;
+ return path_parameter(path_text, path_parameter::invalid);
+ }
+ }
+ else {
+ // Paths are encoded for quickbook 1.6+ and also xmlbase
+ // values (technically xmlbase is a 1.6 feature, but that
+ // isn't enforced as it's backwards compatible).
+ //
+ // Counter-intuitively: encoded == plain text here.
+
+ std::string path_text = qbk_version_n >= 106u || path.is_encoded() ?
+ path.get_encoded() : detail::to_s(path.get_quickbook());
+
+ if (path_text.find('\\') != std::string::npos)
+ {
+ quickbook::detail::ostream* err;
+
+ if (qbk_version_n >= 106u) {
+ err = &detail::outerr(path.get_file(), path.get_position());
+ ++state.error_count;
+ }
+ else {
+ err = &detail::outwarn(path.get_file(), path.get_position());
+ }
+
+ *err << "Path isn't portable: '"
+ << path_text
+ << "'"
+ << std::endl;
+
+ boost::replace(path_text, '\\', '/');
+ }
+
+ return path_parameter(path_text, path_parameter::path);
+ }
+ }
+
+ //
+ // Search include path
+ //
+
+ void include_search_glob(std::set<quickbook_path> & result,
+ quickbook_path const& location,
+ std::string path, quickbook::state& state)
+ {
+ std::size_t glob_pos = find_glob_char(path);
+
+ if (glob_pos == std::string::npos)
+ {
+ quickbook_path complete_path = location / glob_unescape(path);
+
+ if (fs::exists(complete_path.file_path))
+ {
+ state.dependencies.add_glob_match(complete_path.file_path);
+ result.insert(complete_path);
+ }
+ return;
+ }
+
+ std::size_t prev = path.rfind('/', glob_pos);
+ std::size_t next = path.find('/', glob_pos);
+
+ std::size_t glob_begin = prev == std::string::npos ? 0 : prev + 1;
+ std::size_t glob_end = next == std::string::npos ? path.size() : next;
+
+ quickbook_path new_location = location;
+
+ if (prev != std::string::npos) {
+ new_location /= glob_unescape(path.substr(0, prev));
+ }
+
+ if (next != std::string::npos) ++next;
+
+ boost::string_ref glob(
+ path.data() + glob_begin,
+ glob_end - glob_begin);
+
+ fs::path base_dir = new_location.file_path.empty() ?
+ fs::path(".") : new_location.file_path;
+ if (!fs::is_directory(base_dir)) return;
+
+ // Walk through the dir for matches.
+ for (fs::directory_iterator dir_i(base_dir), dir_e;
+ dir_i != dir_e; ++dir_i)
+ {
+ fs::path f = dir_i->path().filename();
+ std::string generic_path = detail::path_to_generic(f);
+
+ // Skip if the dir item doesn't match.
+ if (!quickbook::glob(glob, generic_path)) continue;
+
+ // If it's a file we add it to the results.
+ if (next == std::string::npos)
+ {
+ if (fs::is_regular_file(dir_i->status()))
+ {
+ quickbook_path r = new_location / generic_path;
+ state.dependencies.add_glob_match(r.file_path);
+ result.insert(r);
+ }
+ }
+ // If it's a matching dir, we recurse looking for more files.
+ else
+ {
+ if (!fs::is_regular_file(dir_i->status()))
+ {
+ include_search_glob(result, new_location / generic_path,
+ path.substr(next), state);
+ }
+ }
+ }
+ }
+
+ std::set<quickbook_path> include_search(path_parameter const& parameter,
+ quickbook::state& state, string_iterator pos)
+ {
+ std::set<quickbook_path> result;
+
+ switch (parameter.type) {
+ case path_parameter::glob:
+ // If the path has some glob match characters
+ // we do a discovery of all the matches..
+ {
+ fs::path current = state.current_file->path.parent_path();
+
+ // Search for the current dir accumulating to the result.
+ state.dependencies.add_glob(current / parameter.value);
+ include_search_glob(result, state.current_path.parent_path(),
+ parameter.value, state);
+
+ // Search the include path dirs accumulating to the result.
+ unsigned count = 0;
+ BOOST_FOREACH(fs::path dir, include_path)
+ {
+ ++count;
+ state.dependencies.add_glob(dir / parameter.value);
+ include_search_glob(result,
+ quickbook_path(dir, count, fs::path()),
+ parameter.value, state);
+ }
+
+ // Done.
+ return result;
+ }
+
+ case path_parameter::path:
+ {
+ fs::path path = detail::generic_to_path(parameter.value);
+
+ // If the path is relative, try and resolve it.
+ if (!path.has_root_directory() && !path.has_root_name())
+ {
+ quickbook_path path2 =
+ state.current_path.parent_path() / parameter.value;
+
+ // See if it can be found locally first.
+ if (state.dependencies.add_dependency(path2.file_path))
+ {
+ result.insert(path2);
+ return result;
+ }
+
+ // Search in each of the include path locations.
+ unsigned count = 0;
+ BOOST_FOREACH(fs::path full, include_path)
+ {
+ ++count;
+ full /= path;
+
+ if (state.dependencies.add_dependency(full))
+ {
+ result.insert(quickbook_path(full, count, path));
+ return result;
+ }
+ }
+ }
+ else
+ {
+ if (state.dependencies.add_dependency(path)) {
+ result.insert(quickbook_path(path, 0, path));
+ return result;
+ }
+ }
+
+ detail::outerr(state.current_file, pos)
+ << "Unable to find file: "
+ << parameter.value
+ << std::endl;
+ ++state.error_count;
+
+ return result;
+ }
+
+ case path_parameter::invalid:
+ return result;
+
+ default:
+ assert(0);
+ return result;
+ }
+ }
+
+ //
+ // quickbook_path
+ //
+
+ void swap(quickbook_path& x, quickbook_path& y) {
+ boost::swap(x.file_path, y.file_path);
+ boost::swap(x.include_path_offset, y.include_path_offset);
+ boost::swap(x.abstract_file_path, y.abstract_file_path);
+ }
+
+ bool quickbook_path::operator<(quickbook_path const& other) const
+ {
+ // TODO: Is comparing file_path redundant? Surely if quickbook_path
+ // and abstract_file_path are equal, it must also be.
+ // (but not vice-versa)
+ return
+ abstract_file_path != other.abstract_file_path ?
+ abstract_file_path < other.abstract_file_path :
+ include_path_offset != other.include_path_offset ?
+ include_path_offset < other.include_path_offset :
+ file_path < other.file_path;
+ }
+
+ quickbook_path quickbook_path::operator/(boost::string_ref x) const
+ {
+ return quickbook_path(*this) /= x;
+ }
+
+ quickbook_path& quickbook_path::operator/=(boost::string_ref x)
+ {
+ fs::path x2 = detail::generic_to_path(x);
+ file_path /= x2;
+ abstract_file_path /= x2;
+ return *this;
+ }
+
+ quickbook_path quickbook_path::parent_path() const
+ {
+ return quickbook_path(file_path.parent_path(), include_path_offset,
+ abstract_file_path.parent_path());
+ }
+}
diff --git a/tools/quickbook/src/include_paths.hpp b/tools/quickbook/src/include_paths.hpp
new file mode 100644
index 0000000000..2139f9c99f
--- /dev/null
+++ b/tools/quickbook/src/include_paths.hpp
@@ -0,0 +1,68 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2005 Thomas Guest
+ Copyright (c) 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_INCLUDE_PATHS_HPP)
+#define BOOST_QUICKBOOK_INCLUDE_PATHS_HPP
+
+// Classes and functions for dealing with the values from include, import and
+// xinclude elements.
+
+#include "fwd.hpp"
+#include "values.hpp"
+#include <set>
+#include <string>
+#include <boost/filesystem/path.hpp>
+
+namespace quickbook
+{
+ struct path_parameter {
+ // Will possibly add 'url' to this list later:
+ enum path_type { invalid, path, glob };
+
+ std::string value;
+ path_type type;
+
+ path_parameter(std::string const& value, path_type type) :
+ value(value), type(type) {}
+ };
+
+ path_parameter check_path(value const& path, quickbook::state& state);
+
+ struct quickbook_path
+ {
+ quickbook_path(fs::path const& x, unsigned offset, fs::path const& y)
+ : file_path(x), include_path_offset(offset), abstract_file_path(y) {}
+
+ friend void swap(quickbook_path&, quickbook_path&);
+
+ quickbook_path parent_path() const;
+
+ bool operator<(quickbook_path const& other) const;
+ quickbook_path operator/(boost::string_ref) const;
+ quickbook_path& operator/=(boost::string_ref);
+
+ // The actual location of the file.
+ fs::path file_path;
+
+ // The member of the include path that this file is relative to.
+ // (1-indexed, 0 == original quickbook file)
+ unsigned include_path_offset;
+
+ // A machine independent representation of the file's
+ // path - not unique per-file
+ fs::path abstract_file_path;
+ };
+
+ std::set<quickbook_path> include_search(path_parameter const&,
+ quickbook::state& state, string_iterator pos);
+}
+
+#endif
diff --git a/tools/quickbook/src/main_grammar.cpp b/tools/quickbook/src/main_grammar.cpp
index 74dbecea76..b01f4a0b84 100644
--- a/tools/quickbook/src/main_grammar.cpp
+++ b/tools/quickbook/src/main_grammar.cpp
@@ -17,7 +17,7 @@
#include "phrase_tags.hpp"
#include "parsers.hpp"
#include "scoped.hpp"
-#include "input_path.hpp"
+#include "native_text.hpp"
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_chset.hpp>
#include <boost/spirit/include/classic_if.hpp>
@@ -33,8 +33,15 @@ namespace quickbook
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 @@ namespace quickbook
// * 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)
{}
};
@@ -61,27 +68,13 @@ namespace quickbook
};
};
- template <typename T>
- struct member_action
- {
- typedef void(T::*member_function)(parse_iterator, parse_iterator);
-
- T& l;
- member_function mf;
-
- member_action(T& l, member_function mf) : l(l), mf(mf) {}
-
- void operator()(parse_iterator first, parse_iterator last) const {
- (l.*mf)(first, last);
- }
- };
-
struct main_grammar_local
{
////////////////////////////////////////////////////////////////////////
// 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);
@@ -90,87 +83,51 @@ namespace quickbook
string_iterator last);
void clear_stack();
- struct in_list_impl {
- main_grammar_local& l;
-
- in_list_impl(main_grammar_local& l) :
- l(l) {}
-
- bool operator()() const {
- return !l.list_stack.top().root;
- }
- };
-
- struct set_no_eols_scoped : scoped_action_base
- {
- set_no_eols_scoped(main_grammar_local& l)
- : l(l) {}
-
- bool start() {
- saved_no_eols = l.no_eols;
- l.no_eols = false;
-
- return true;
- }
-
- void cleanup() {
- l.no_eols = saved_no_eols;
- }
-
- main_grammar_local& l;
- bool saved_no_eols;
- };
-
////////////////////////////////////////////////////////////////////////
// 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,
- template_,
- code_block, macro,
+ inline_code, skip_inline_code,
+ template_, attribute_template, template_body,
+ code_block, skip_code_block, macro,
template_args,
template_args_1_4, template_arg_1_4,
template_inner_arg_1_4, brackets_1_4,
template_args_1_5, template_arg_1_5, template_arg_1_5_content,
template_inner_arg_1_5, brackets_1_5,
+ template_args_1_6, template_arg_1_6, template_arg_1_6_content,
break_,
command_line_macro_identifier,
- dummy_block, line_dummy_block, square_brackets
+ dummy_block, line_dummy_block, square_brackets,
+ skip_escape
;
- struct simple_markup_closure
- : cl::closure<simple_markup_closure, char>
+ struct block_context_closure : cl::closure<block_context_closure,
+ element_info::context>
{
- member1 mark;
+ // Mask used to determine whether or not an element is a block
+ // element.
+ member1 is_block_mask;
};
- struct block_item_closure : cl::closure<block_item_closure, bool>
- {
- member1 still_in_block;
- };
-
- struct context_closure : cl::closure<context_closure, element_info::context>
- {
- member1 context;
- };
-
- 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;
@@ -187,31 +144,36 @@ namespace quickbook
: 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) {}
+ process_element_impl(main_grammar_local& l) :
+ l(l), pushed_source_mode_(false), 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_);
@@ -220,12 +182,12 @@ namespace quickbook
assert(l.state_.values.builder.empty());
- if (!l.state_.source_mode_next.empty() &&
+ if (l.state_.source_mode_next &&
info_.type != element_info::maybe_block)
{
- l.state_.source_mode.swap(saved_source_mode_);
- l.state_.source_mode = l.state_.source_mode_next.get_quickbook();
- l.state_.source_mode_next = value();
+ l.state_.push_tagged_source_mode(l.state_.source_mode_next);
+ pushed_source_mode_ = true;
+ l.state_.source_mode_next = 0;
}
return true;
@@ -234,45 +196,61 @@ namespace quickbook
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; }
void failure() { l.element_type = element_info::nothing; }
void cleanup() {
- if (!saved_source_mode_.empty())
- l.state_.source_mode.swap(saved_source_mode_);
+ if (pushed_source_mode_)
+ l.state_.pop_tagged_source_mode();
}
main_grammar_local& l;
element_info info_;
- std::string saved_source_mode_;
+ bool pushed_source_mode_;
+ bool element_context_error_;
};
- struct set_no_eols_scoped : scoped_action_base
+ struct scoped_paragraph : scoped_action_base
{
- set_no_eols_scoped(main_grammar_local& l)
- : l(l) {}
+ scoped_paragraph(quickbook::state& state) :
+ state(state), pushed(false) {}
bool start() {
- saved_no_eols = l.no_eols;
- l.no_eols = false;
-
+ state.push_tagged_source_mode(state.source_mode_next);
+ pushed = true;
+ state.source_mode_next = 0;
return true;
}
void cleanup() {
- l.no_eols = saved_no_eols;
+ if (pushed) state.pop_tagged_source_mode();
}
- main_grammar_local& l;
- bool saved_no_eols;
+ quickbook::state& state;
+ bool pushed;
};
struct in_list_impl {
@@ -282,8 +260,42 @@ namespace quickbook
l(l) {}
bool operator()() const {
- return !l.list_stack.top().root;
+ return !l.list_stack.empty() &&
+ l.list_stack.top().type == list_stack_item::syntactic_list;
+ }
+ };
+
+ template <typename T, typename M>
+ struct set_scoped_value_impl : scoped_action_base
+ {
+ typedef M T::*member_ptr;
+
+ 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.*ptr = saved_value;
}
+
+ T& l;
+ member_ptr ptr;
+ M saved_value;
+ };
+
+ 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;
+
+ set_scoped_value(T& l, typename impl::member_ptr ptr) :
+ scoped_parser<impl>(impl(l, ptr)) {}
};
////////////////////////////////////////////////////////////////////////////
@@ -295,35 +307,44 @@ namespace quickbook
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);
scoped_parser<to_value_scoped_action> to_value(state);
+ scoped_parser<scoped_paragraph> scope_paragraph(state);
// 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);
@@ -338,9 +359,9 @@ namespace quickbook
// 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)]
]
;
@@ -348,9 +369,9 @@ namespace quickbook
// 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)]
]
;
@@ -358,9 +379,9 @@ namespace quickbook
// 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)]
]
;
@@ -370,28 +391,65 @@ namespace quickbook
// 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 =
@@ -416,40 +474,57 @@ namespace quickbook
;
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]
+ >> scope_paragraph()
+ [
+ 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(106u) >> local.list_item(element_info::only_block)
- | qbk_ver(0, 106u) >> 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)
- >> !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, as it causes
+ // the list block to end. The support for nested syntactic
+ // blocks in 1.7 will fix that. Although it does mean the
+ // following line will need to be indented. TODO: Flag that
+ // the indentation check shouldn't be made?
+ >> !( cl::eps_p(in_list) >> qbk_ver(106u, 107u)
+ | cl::eps_p
+ (
+ ph::static_cast_<int>(local.syntactic_block_item.is_block_mask) &
+ ph::static_cast_<int>(ph::var(local.element_type))
+ )
+ >> eol [ph::var(local.still_in_block) = false]
+ )
;
local.paragraph_separator =
@@ -465,14 +540,13 @@ namespace quickbook
;
// Blocks contains within an element, e.g. a table cell or a footnote.
- inside_paragraph =
- state.values.save()
- [ *( local.paragraph_separator [paragraph]
- >> *eol
+ 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 =
@@ -484,7 +558,7 @@ namespace quickbook
>> *(line_comment | (cl::anychar_p - (cl::eol_p | "[/")))
)
>> *eol
- ] [element]
+ ] [element_action]
;
local.element
@@ -499,7 +573,7 @@ namespace quickbook
[ cl::lazy_p(*ph::var(local.info.rule))
>> space
>> ']'
- ] [element]
+ ] [element_action]
]
;
@@ -508,7 +582,7 @@ namespace quickbook
[( local.code_line
>> *(*local.blank_line >> local.code_line)
) [state.values.entry(ph::arg1, ph::arg2)]
- ] [element]
+ ] [element_action]
>> *eol
;
@@ -527,7 +601,7 @@ namespace quickbook
local.common =
local.macro
- | local.element(local.common.context)
+ | local.element
| local.template_
| local.break_
| local.code_block
@@ -540,6 +614,19 @@ namespace quickbook
| cl::anychar_p [plain_char]
;
+ skip_entity =
+ '['
+ // For escaped templates:
+ >> !(space >> cl::ch_p('`') >> (cl::alpha_p | '_'))
+ >> *(~cl::eps_p(']') >> skip_entity)
+ >> !cl::ch_p(']')
+ | local.skip_code_block
+ | local.skip_inline_code
+ | local.skip_escape
+ | comment
+ | (cl::anychar_p - '[' - ']')
+ ;
+
local.square_brackets =
( cl::ch_p('[') [plain_char]
>> paragraph_phrase
@@ -566,21 +653,50 @@ namespace quickbook
( '['
>> 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)]
+ [ local.template_body
+ >> ']'
+ ]
+ ) [element_action]
+ ;
+
+ local.attribute_template =
+ ( '['
+ >> space
+ >> state.values.list(template_tags::attribute_template)
+ [ local.template_body
+ >> ']'
+ ]
+ ) [element_action]
+ ;
+
+ local.template_body =
+ ( 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]
;
local.template_args =
- qbk_ver(105u) >> local.template_args_1_5
+ qbk_ver(106u) >> local.template_args_1_6
+ | qbk_ver(105u, 106u) >> local.template_args_1_5
| qbk_ver(0, 105u) >> local.template_args_1_4
;
@@ -622,6 +738,19 @@ namespace quickbook
'[' >> local.template_inner_arg_1_5 >> ']'
;
+ local.template_args_1_6 = local.template_arg_1_6 >> *(".." >> local.template_arg_1_6);
+
+ local.template_arg_1_6 =
+ ( cl::eps_p(*cl::blank_p >> cl::eol_p)
+ >> local.template_arg_1_6_content [state.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+ | local.template_arg_1_6_content [state.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
+ )
+ ;
+
+ local.template_arg_1_6_content =
+ + ( ~cl::eps_p("..") >> skip_entity )
+ ;
+
local.break_
= ( '['
>> space
@@ -642,7 +771,49 @@ namespace quickbook
) >> cl::eps_p('`')
) [state.values.entry(ph::arg1, ph::arg2)]
>> '`'
- ] [element]
+ ] [element_action]
+ ;
+
+ local.skip_inline_code =
+ '`'
+ >> *(cl::anychar_p -
+ ( '`'
+ | (cl::eol_p >> *cl::blank_p >> cl::eol_p)
+ // Make sure that we don't go
+ ) // past a single block
+ )
+ >> !cl::ch_p('`')
+ ;
+
+ local.skip_code_block =
+ "```"
+ >> ~cl::eps_p("`")
+ >> ( !( *(*cl::blank_p >> cl::eol_p)
+ >> ( *( "````" >> *cl::ch_p('`')
+ | ( cl::anychar_p
+ - (*cl::space_p >> "```" >> ~cl::eps_p("`"))
+ )
+ )
+ >> !(*cl::blank_p >> cl::eol_p)
+ )
+ >> (*cl::space_p >> "```")
+ )
+ | *cl::anychar_p
+ )
+ | "``"
+ >> ~cl::eps_p("`")
+ >> ( ( *(*cl::blank_p >> cl::eol_p)
+ >> ( *( "```" >> *cl::ch_p('`')
+ | ( cl::anychar_p
+ - (*cl::space_p >> "``" >> ~cl::eps_p("`"))
+ )
+ )
+ >> !(*cl::blank_p >> cl::eol_p)
+ )
+ >> (*cl::space_p >> "``")
+ )
+ | *cl::anychar_p
+ )
;
local.code_block =
@@ -658,7 +829,7 @@ namespace quickbook
>> !(*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
)
@@ -674,18 +845,18 @@ namespace quickbook
>> !(*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)
@@ -699,15 +870,15 @@ namespace quickbook
[
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]
]
;
@@ -715,8 +886,8 @@ namespace quickbook
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)
@@ -742,10 +913,23 @@ namespace quickbook
[ (*(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]
]
;
+ local.skip_escape =
+ cl::str_p("\\n")
+ | cl::str_p("\\ ")
+ | '\\' >> cl::punct_p
+ | "\\u" >> cl::repeat_p(4) [cl::chset<>("0-9a-fA-F")]
+ | "\\U" >> cl::repeat_p(8) [cl::chset<>("0-9a-fA-F")]
+ | ("'''" >> !eol)
+ >> (*(cl::anychar_p - "'''"))
+ >> ( cl::str_p("'''")
+ | cl::eps_p
+ )
+ ;
+
raw_escape =
cl::str_p("\\n") [error("Newlines invalid here.")]
| cl::str_p("\\ ") // ignore an escaped space
@@ -760,11 +944,12 @@ namespace quickbook
>> (*(cl::anychar_p - "'''"))
>> ( cl::str_p("'''")
| cl::eps_p [error("Unclosed boostbook escape.")]
- ) [element]
+ )
;
- attribute_value_1_7 =
- *( ~cl::eps_p(']' | cl::space_p | comment)
+ attribute_template_body =
+ space
+ >> *( ~cl::eps_p(space >> cl::end_p | comment)
>> ( cl::eps_p
( cl::ch_p('[')
>> space
@@ -775,13 +960,38 @@ namespace quickbook
)
) [error("Elements not allowed in attribute values.")]
>> local.square_brackets
- | local.template_
+ | local.attribute_template
| cl::eps_p(cl::ch_p('[')) [error("Unmatched template in attribute value.")]
>> local.square_brackets
| raw_escape
| cl::anychar_p [raw_char]
)
)
+ >> space
+ ;
+
+
+ attribute_value_1_7 =
+ state.values.save() [
+ +( ~cl::eps_p(']' | cl::space_p | comment)
+ >> ( cl::eps_p
+ ( cl::ch_p('[')
+ >> space
+ >> ( cl::eps_p(cl::punct_p)
+ >> elements
+ | elements
+ >> (cl::eps_p - (cl::alnum_p | '_'))
+ )
+ ) [error("Elements not allowed in attribute values.")]
+ >> local.square_brackets
+ | local.attribute_template
+ | cl::eps_p(cl::ch_p('['))[error("Unmatched template in attribute value.")]
+ >> local.square_brackets
+ | raw_escape
+ | cl::anychar_p [raw_char]
+ )
+ )
+ ]
;
//
@@ -800,7 +1010,7 @@ namespace quickbook
>> *cl::space_p
)
>> cl::end_p
- ] [element]
+ ] [element_action]
;
local.command_line_macro_identifier =
@@ -883,7 +1093,21 @@ namespace quickbook
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)
@@ -922,10 +1146,16 @@ namespace quickbook
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);
@@ -933,7 +1163,8 @@ namespace quickbook
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
@@ -956,7 +1187,7 @@ namespace quickbook
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);
@@ -972,14 +1203,24 @@ namespace quickbook
block_type = block_types::paragraph;
}
+
+ 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"
+ << std::endl;
+ ++state_.error_count;
+ }
}
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;
}
}
@@ -990,12 +1231,14 @@ namespace quickbook
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);
}
@@ -1005,7 +1248,8 @@ namespace quickbook
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);
@@ -1032,7 +1276,7 @@ namespace quickbook
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();
diff --git a/tools/quickbook/src/markups.cpp b/tools/quickbook/src/markups.cpp
index 558848444b..f077943a0f 100644
--- a/tools/quickbook/src/markups.cpp
+++ b/tools/quickbook/src/markups.cpp
@@ -26,6 +26,7 @@ namespace quickbook
{
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>" },
diff --git a/tools/quickbook/src/input_path.cpp b/tools/quickbook/src/native_text.cpp
index 9b6a87784d..3e4ce8749a 100644
--- a/tools/quickbook/src/input_path.cpp
+++ b/tools/quickbook/src/native_text.cpp
@@ -8,7 +8,7 @@
#include <boost/program_options.hpp>
#include <iostream>
-#include "input_path.hpp"
+#include "native_text.hpp"
#include "utils.hpp"
#include "files.hpp"
@@ -51,8 +51,9 @@ namespace detail {
return std::string(buffer.get());
}
- std::wstring from_utf8(std::string const& x)
+ std::wstring from_utf8(boost::string_ref text)
{
+ std::string x(text.begin(), text.end());
int buffer_count = MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, 0, 0);
if (!buffer_count)
@@ -69,19 +70,19 @@ namespace detail {
#endif
#if QUICKBOOK_WIDE_PATHS
- std::string input_to_utf8(input_string const& x)
+ std::string command_line_to_utf8(command_line_string const& x)
{
return to_utf8(x);
}
#else
- std::string input_to_utf8(input_string const& x)
+ std::string command_line_to_utf8(command_line_string const& x)
{
return x;
}
#endif
#if QUICKBOOK_WIDE_PATHS
- fs::path generic_to_path(std::string const& x)
+ fs::path generic_to_path(boost::string_ref x)
{
return fs::path(from_utf8(x));
}
@@ -91,9 +92,9 @@ namespace detail {
return to_utf8(x.generic_wstring());
}
#else
- fs::path generic_to_path(std::string const& x)
+ fs::path generic_to_path(boost::string_ref x)
{
- return fs::path(x);
+ return fs::path(x.begin(), x.end());
}
std::string path_to_generic(fs::path const& x)
@@ -104,7 +105,7 @@ namespace detail {
#endif
#if QUICKBOOK_CYGWIN_PATHS
- fs::path input_to_path(input_string const& path)
+ fs::path command_line_to_path(command_line_string const& path)
{
cygwin_conv_path_t flags = CCP_POSIX_TO_WIN_W | CCP_RELATIVE;
@@ -139,7 +140,7 @@ namespace detail {
return std::string(result.get());
}
#else
- fs::path input_to_path(input_string const& path)
+ fs::path command_line_to_path(command_line_string const& path)
{
return fs::path(path);
}
@@ -166,7 +167,7 @@ namespace detail {
if (_isatty(_fileno(stderr))) _setmode(_fileno(stderr), _O_U16TEXT);
}
- void write_utf8(ostream::base_ostream& out, std::string const& x)
+ void write_utf8(ostream::base_ostream& out, boost::string_ref x)
{
out << from_utf8(x);
}
@@ -192,7 +193,7 @@ namespace detail {
{
}
- void write_utf8(ostream::base_ostream& out, std::string const& x)
+ void write_utf8(ostream::base_ostream& out, boost::string_ref x)
{
out << x;
}
@@ -281,6 +282,11 @@ namespace detail {
return *this;
}
+ ostream& ostream::operator<<(boost::string_ref x) {
+ write_utf8(base, x);
+ return *this;
+ }
+
ostream& ostream::operator<<(int x) {
base << x;
return *this;
@@ -301,6 +307,18 @@ namespace detail {
return *this;
}
+#if !defined(BOOST_NO_LONG_LONG)
+ ostream& ostream::operator<<(long long x) {
+ base << x;
+ return *this;
+ }
+
+ ostream& ostream::operator<<(unsigned long long x) {
+ base << x;
+ return *this;
+ }
+#endif
+
ostream& ostream::operator<<(fs::path const& x) {
base << path_to_stream(x);
return *this;
diff --git a/tools/quickbook/src/input_path.hpp b/tools/quickbook/src/native_text.hpp
index a9b55f6b2c..11b990da0d 100644
--- a/tools/quickbook/src/input_path.hpp
+++ b/tools/quickbook/src/native_text.hpp
@@ -6,11 +6,14 @@
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
-#if !defined(BOOST_QUICKBOOK_DETAIL_INPUT_PATH_HPP)
-#define BOOST_QUICKBOOK_DETAIL_INPUT_PATH_HPP
+// For handling native strings and streams.
+
+#if !defined(BOOST_QUICKBOOK_DETAIL_NATIVE_TEXT_HPP)
+#define BOOST_QUICKBOOK_DETAIL_NATIVE_TEXT_HPP
#include <boost/config.hpp>
#include <boost/filesystem/path.hpp>
+#include <boost/utility/string_ref.hpp>
#include <string>
#include <stdexcept>
#include <iostream>
@@ -50,20 +53,22 @@ namespace quickbook
// 'generic': Paths in quickbook source and the generated boostbook.
// Always UTF-8.
- // 'input': Paths (or other parameters) from the command line and
+ // 'command_line':
+ // Paths (or other parameters) from the command line and
// possibly other sources in the future. Wide strings on
// normal windows, UTF-8 for cygwin and other platforms
// (hopefully).
- // 'stream': Strings to be written to a stream.
// 'path': Stored as a boost::filesystem::path. Since
// Boost.Filesystem doesn't support cygwin, this
// is always wide on windows. UTF-8 on other
// platforms (again, hopefully).
#if QUICKBOOK_WIDE_PATHS
- typedef std::wstring input_string;
+ typedef std::wstring command_line_string;
+ typedef boost::wstring_ref command_line_string_ref;
#else
- typedef std::string input_string;
+ typedef std::string command_line_string;
+ typedef boost::string_ref command_line_string_ref;
#endif
// A light wrapper around C++'s streams that gets things right
@@ -76,10 +81,12 @@ namespace quickbook
typedef std::wostream base_ostream;
typedef std::wios base_ios;
typedef std::wstring string;
+ typedef boost::wstring_ref string_ref;
#else
typedef std::ostream base_ostream;
typedef std::ios base_ios;
typedef std::string string;
+ typedef boost::string_ref string_ref;
#endif
base_ostream& base;
@@ -91,12 +98,19 @@ namespace quickbook
// std::string should be UTF-8 (what a mess!)
ostream& operator<<(std::string const&);
+ ostream& operator<<(boost::string_ref);
// Other value types.
ostream& operator<<(int x);
ostream& operator<<(unsigned int x);
ostream& operator<<(long x);
ostream& operator<<(unsigned long x);
+
+#if !defined(BOOST_NO_LONG_LONG)
+ ostream& operator<<(long long x);
+ ostream& operator<<(unsigned long long x);
+#endif
+
ostream& operator<<(fs::path const&);
// Modifiers
@@ -105,11 +119,11 @@ namespace quickbook
};
- std::string input_to_utf8(input_string const&);
- fs::path input_to_path(input_string const&);
+ std::string command_line_to_utf8(command_line_string const&);
+ fs::path command_line_to_path(command_line_string const&);
std::string path_to_generic(fs::path const&);
- fs::path generic_to_path(std::string const&);
+ fs::path generic_to_path(boost::string_ref);
void initialise_output();
diff --git a/tools/quickbook/src/phrase_element_grammar.cpp b/tools/quickbook/src/phrase_element_grammar.cpp
index b287d63621..2c0a597ff5 100644
--- a/tools/quickbook/src/phrase_element_grammar.cpp
+++ b/tools/quickbook/src/phrase_element_grammar.cpp
@@ -19,6 +19,7 @@
#include <boost/spirit/include/classic_if.hpp>
#include <boost/spirit/include/phoenix1_primitives.hpp>
#include <boost/spirit/include/phoenix1_casts.hpp>
+#include <boost/foreach.hpp>
namespace quickbook
{
@@ -38,7 +39,7 @@ namespace quickbook
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);
@@ -146,13 +147,15 @@ namespace quickbook
blank
>> ( qbk_ver(0, 106u)
>> (*(cl::anychar_p - phrase_end)) [state.values.entry(ph::arg1, ph::arg2)]
- | qbk_ver(106u)
+ | qbk_ver(106u, 107u)
>> to_value()
[ *( raw_escape
| (cl::anychar_p - phrase_end)
[raw_char]
)
]
+ | qbk_ver(107u)
+ >> to_value() [attribute_value_1_7]
)
;
@@ -171,16 +174,14 @@ namespace quickbook
;
local.source_mode =
- ( cl::str_p("c++")
- | "python"
- | "teletype"
- ) [state.values.entry(ph::arg1, ph::arg2)];
+ cl::eps_p [state.values.entry(ph::arg1, ph::arg2)]
+ >> source_modes [state.values.entry(ph::arg1)];
- elements.add
- ("c++", element_info(element_info::phrase, &local.empty, source_mode_tags::cpp))
- ("python", element_info(element_info::phrase, &local.empty, source_mode_tags::python))
- ("teletype", element_info(element_info::phrase, &local.empty, source_mode_tags::teletype))
- ;
+ BOOST_FOREACH(int tag, source_mode_tags::tags()) {
+ source_modes.add(source_mode_tags::name(tag), tag);
+ elements.add(source_mode_tags::name(tag),
+ element_info(element_info::phrase, &local.empty, tag));
+ }
elements.add
("role", element_info(element_info::phrase, &local.role, phrase_tags::role, 106u))
@@ -188,7 +189,11 @@ namespace quickbook
local.role
= space
- >> (+(cl::alnum_p | '_')) [state.values.entry(ph::arg1, ph::arg2)]
+ >> ( qbk_ver(0, 107u)
+ >> (+(cl::alnum_p | '_')) [state.values.entry(ph::arg1, ph::arg2)]
+ | qbk_ver(107u)
+ >> to_value() [attribute_value_1_7]
+ )
>> hard_space
>> local.inner_phrase
;
diff --git a/tools/quickbook/src/quickbook.cpp b/tools/quickbook/src/quickbook.cpp
index 5a359ed3e1..f867f3583e 100644
--- a/tools/quickbook/src/quickbook.cpp
+++ b/tools/quickbook/src/quickbook.cpp
@@ -14,8 +14,8 @@
#include "post_process.hpp"
#include "utils.hpp"
#include "files.hpp"
-#include "input_path.hpp"
-#include "id_manager.hpp"
+#include "native_text.hpp"
+#include "document_state.hpp"
#include <boost/program_options.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
@@ -24,6 +24,8 @@
#include <boost/ref.hpp>
#include <boost/version.hpp>
#include <boost/foreach.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
#include <stdexcept>
#include <vector>
@@ -38,7 +40,7 @@
#pragma warning(disable:4355)
#endif
-#define QUICKBOOK_VERSION "Quickbook Version 1.5.8"
+#define QUICKBOOK_VERSION "Quickbook Version 1.6.1"
namespace quickbook
{
@@ -61,8 +63,9 @@ namespace quickbook
end = preset_defines.end();
it != end; ++it)
{
- parse_iterator first(it->begin());
- parse_iterator last(it->end());
+ boost::string_ref val(*it);
+ parse_iterator first(val.begin());
+ parse_iterator last(val.end());
cl::parse_info<parse_iterator> info =
cl::parse(first, last, state.grammar().command_line_macro);
@@ -85,8 +88,8 @@ namespace quickbook
///////////////////////////////////////////////////////////////////////////
void parse_file(quickbook::state& state, value include_doc_id, bool nested_file)
{
- parse_iterator first(state.current_file->source.begin());
- parse_iterator last(state.current_file->source.end());
+ parse_iterator first(state.current_file->source().begin());
+ parse_iterator last(state.current_file->source().end());
cl::parse_info<parse_iterator> info = cl::parse(first, last, state.grammar().doc_info);
assert(info.hit);
@@ -96,7 +99,7 @@ namespace quickbook
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);
@@ -110,28 +113,41 @@ namespace quickbook
}
}
+ struct parse_document_options
+ {
+ parse_document_options() :
+ indent(-1),
+ linewidth(-1),
+ pretty_print(true),
+ deps_out_flags(quickbook::dependency_tracker::default_)
+ {}
+
+ int indent;
+ int linewidth;
+ bool pretty_print;
+ fs::path deps_out;
+ quickbook::dependency_tracker::flags deps_out_flags;
+ fs::path locations_out;
+ fs::path xinclude_base;
+ };
+
static int
parse_document(
fs::path const& filein_
, fs::path const& fileout_
- , fs::path const& deps_out_
- , fs::path const& locations_out_
- , fs::path const& xinclude_base_
- , int indent
- , int linewidth
- , bool pretty_print)
+ , parse_document_options const& options_)
{
string_stream buffer;
- id_manager ids;
+ document_state output;
int result = 0;
try {
- quickbook::state state(filein_, xinclude_base_, buffer, ids);
+ quickbook::state state(filein_, options_.xinclude_base, buffer, output);
set_macros(state);
if (state.error_count == 0) {
- state.add_dependency(filein_);
+ state.dependencies.add_dependency(filein_);
state.current_file = load(filein_); // Throws load_error
parse_file(state);
@@ -144,37 +160,31 @@ namespace quickbook
result = state.error_count ? 1 : 0;
- if (!deps_out_.empty())
+ if (!options_.deps_out.empty())
{
- fs::ofstream out(deps_out_);
- BOOST_FOREACH(quickbook::state::dependency_list::value_type
- const& d, state.dependencies)
- {
- if (d.second) {
- out << detail::path_to_generic(d.first) << std::endl;
- }
- }
+ state.dependencies.write_dependencies(options_.deps_out,
+ options_.deps_out_flags);
}
- if (!locations_out_.empty())
+ if (!options_.locations_out.empty())
{
- fs::ofstream out(locations_out_);
- BOOST_FOREACH(quickbook::state::dependency_list::value_type
- const& d, state.dependencies)
- {
- out << (d.second ? "+ " : "- ")
- << detail::path_to_generic(d.first) << std::endl;
- }
+ fs::ofstream out(options_.locations_out);
+ state.dependencies.write_dependencies(options_.locations_out,
+ dependency_tracker::checked);
}
}
catch (load_error& e) {
detail::outerr(filein_) << e.what() << std::endl;
result = 1;
}
+ catch (std::runtime_error& e) {
+ detail::outerr() << e.what() << std::endl;
+ result = 1;
+ }
if (!fileout_.empty() && result == 0)
{
- std::string stage2 = ids.replace_placeholders(buffer.str());
+ std::string stage2 = output.replace_placeholders(buffer.str());
fs::ofstream fileout(fileout_);
@@ -187,11 +197,12 @@ namespace quickbook
return 1;
}
- if (pretty_print)
+ if (options_.pretty_print)
{
try
{
- fileout << post_process(stage2, indent, linewidth);
+ fileout << post_process(stage2, options_.indent,
+ options_.linewidth);
}
catch (quickbook::post_process_failure&)
{
@@ -244,7 +255,7 @@ main(int argc, char* argv[])
using boost::program_options::notify;
using boost::program_options::positional_options_description;
- using quickbook::detail::input_string;
+ using quickbook::detail::command_line_string;
// First thing, the filesystem should record the current working directory.
fs::initial_path<fs::path>();
@@ -253,6 +264,8 @@ main(int argc, char* argv[])
quickbook::detail::initialise_output();
quickbook::detail::initialise_markups();
+ // Declare the program options
+
options_description desc("Allowed options");
options_description hidden("Hidden options");
options_description all("All options");
@@ -270,27 +283,32 @@ main(int argc, char* argv[])
("no-self-linked-headers", "stop headers linking to themselves")
("indent", PO_VALUE<int>(), "indent spaces")
("linewidth", PO_VALUE<int>(), "line width")
- ("input-file", PO_VALUE<input_string>(), "input file")
- ("output-file", PO_VALUE<input_string>(), "output file")
- ("output-deps", PO_VALUE<input_string>(), "output dependency file")
+ ("input-file", PO_VALUE<command_line_string>(), "input file")
+ ("output-file", PO_VALUE<command_line_string>(), "output file")
+ ("output-deps", PO_VALUE<command_line_string>(), "output dependency file")
("debug", "debug mode (for developers)")
("ms-errors", "use Microsoft Visual Studio style error & warn message format")
- ("include-path,I", PO_VALUE< std::vector<input_string> >(), "include path")
- ("define,D", PO_VALUE< std::vector<input_string> >(), "define macro")
- ("image-location", PO_VALUE<input_string>(), "image location")
+ ("include-path,I", PO_VALUE< std::vector<command_line_string> >(), "include path")
+ ("define,D", PO_VALUE< std::vector<command_line_string> >(), "define macro")
+ ("image-location", PO_VALUE<command_line_string>(), "image location")
;
hidden.add_options()
("expect-errors",
"Succeed if the input file contains a correctly handled "
"error, fail otherwise.")
- ("xinclude-base", PO_VALUE<input_string>(),
+ ("xinclude-base", PO_VALUE<command_line_string>(),
"Generate xincludes as if generating for this target "
"directory.")
- ("output-checked-locations", PO_VALUE<input_string>(),
+ ("output-deps-format", PO_VALUE<command_line_string>(),
+ "Comma separated list of formatting options for output-deps, "
+ "options are: escaped, checked")
+ ("output-checked-locations", PO_VALUE<command_line_string>(),
"Writes a file listing all the file locations that were "
"checked, starting with '+' if they were found, or '-' "
- "if they weren't.")
+ "if they weren't.\n"
+ "This is deprecated, use 'output-deps-format=checked' to "
+ "write the deps file in this format.")
;
all.add(desc).add(hidden);
@@ -298,10 +316,9 @@ main(int argc, char* argv[])
positional_options_description p;
p.add("input-file", -1);
+ // Read option from the command line
+
variables_map vm;
- int indent = -1;
- int linewidth = -1;
- bool pretty_print = true;
#if QUICKBOOK_WIDE_PATHS
quickbook::ignore_variable(&argc);
@@ -331,6 +348,9 @@ main(int argc, char* argv[])
notify(vm);
+ // Process the command line options
+
+ quickbook::parse_document_options parse_document_options;
bool expect_errors = vm.count("expect-errors");
int error_count = 0;
@@ -362,15 +382,15 @@ main(int argc, char* argv[])
quickbook::ms_errors = true;
if (vm.count("no-pretty-print"))
- pretty_print = false;
+ parse_document_options.pretty_print = false;
quickbook::self_linked_headers = !vm.count("no-self-link-headers");
if (vm.count("indent"))
- indent = vm["indent"].as<int>();
+ parse_document_options.indent = vm["indent"].as<int>();
if (vm.count("linewidth"))
- linewidth = vm["linewidth"].as<int>();
+ parse_document_options.linewidth = vm["linewidth"].as<int>();
if (vm.count("debug"))
{
@@ -401,48 +421,82 @@ main(int argc, char* argv[])
if (vm.count("include-path"))
{
boost::transform(
- vm["include-path"].as<std::vector<input_string> >(),
+ vm["include-path"].as<std::vector<command_line_string> >(),
std::back_inserter(quickbook::include_path),
- quickbook::detail::input_to_path);
+ quickbook::detail::command_line_to_path);
}
quickbook::preset_defines.clear();
if (vm.count("define"))
{
boost::transform(
- vm["define"].as<std::vector<input_string> >(),
+ vm["define"].as<std::vector<command_line_string> >(),
std::back_inserter(quickbook::preset_defines),
- quickbook::detail::input_to_utf8);
+ quickbook::detail::command_line_to_utf8);
}
if (vm.count("input-file"))
{
- fs::path filein = quickbook::detail::input_to_path(
- vm["input-file"].as<input_string>());
+ fs::path filein = quickbook::detail::command_line_to_path(
+ vm["input-file"].as<command_line_string>());
fs::path fileout;
- fs::path deps_out;
- fs::path locations_out;
bool default_output = true;
if (vm.count("output-deps"))
{
- deps_out = quickbook::detail::input_to_path(
- vm["output-deps"].as<input_string>());
+ parse_document_options.deps_out =
+ quickbook::detail::command_line_to_path(
+ vm["output-deps"].as<command_line_string>());
default_output = false;
}
+ if (vm.count("output-deps-format"))
+ {
+ std::string format_flags =
+ quickbook::detail::command_line_to_utf8(
+ vm["output-deps-format"].as<command_line_string>());
+
+ std::vector<std::string> flag_names;
+ boost::algorithm::split(flag_names, format_flags,
+ boost::algorithm::is_any_of(", "),
+ boost::algorithm::token_compress_on);
+
+ unsigned flags = 0;
+
+ BOOST_FOREACH(std::string const& flag, flag_names) {
+ if (flag == "checked") {
+ flags |= quickbook::dependency_tracker::checked;
+ }
+ else if (flag == "escaped") {
+ flags |= quickbook::dependency_tracker::escaped;
+ }
+ else if (!flag.empty()) {
+ quickbook::detail::outerr()
+ << "Unknown dependency format flag: "
+ << flag
+ <<std::endl;
+
+ ++error_count;
+ }
+ }
+
+ parse_document_options.deps_out_flags =
+ quickbook::dependency_tracker::flags(flags);
+ }
+
if (vm.count("output-checked-locations"))
{
- locations_out = quickbook::detail::input_to_path(
- vm["output-checked-locations"].as<input_string>());
+ parse_document_options.locations_out =
+ quickbook::detail::command_line_to_path(
+ vm["output-checked-locations"].as<command_line_string>());
default_output = false;
}
if (vm.count("output-file"))
{
- fileout = quickbook::detail::input_to_path(
- vm["output-file"].as<input_string>());
+ fileout = quickbook::detail::command_line_to_path(
+ vm["output-file"].as<command_line_string>());
}
else if (default_output)
{
@@ -450,20 +504,20 @@ main(int argc, char* argv[])
fileout.replace_extension(".xml");
}
- fs::path xinclude_base;
if (vm.count("xinclude-base"))
{
- xinclude_base = quickbook::detail::input_to_path(
- vm["xinclude-base"].as<input_string>());
+ parse_document_options.xinclude_base =
+ quickbook::detail::command_line_to_path(
+ vm["xinclude-base"].as<command_line_string>());
}
else
{
- xinclude_base = fileout.parent_path();
- if (xinclude_base.empty())
- xinclude_base = ".";
+ parse_document_options.xinclude_base = fileout.parent_path();
+ if (parse_document_options.xinclude_base.empty())
+ parse_document_options.xinclude_base = ".";
}
- if (!fs::is_directory(xinclude_base))
+ if (!fs::is_directory(parse_document_options.xinclude_base))
{
quickbook::detail::outerr()
<< (vm.count("xinclude-base") ?
@@ -474,8 +528,8 @@ main(int argc, char* argv[])
if (vm.count("image-location"))
{
- quickbook::image_location = quickbook::detail::input_to_path(
- vm["image-location"].as<input_string>());
+ quickbook::image_location = quickbook::detail::command_line_to_path(
+ vm["image-location"].as<command_line_string>());
}
else
{
@@ -490,8 +544,7 @@ main(int argc, char* argv[])
if (!error_count)
error_count += quickbook::parse_document(
- filein, fileout, deps_out, locations_out,
- xinclude_base, indent, linewidth, pretty_print);
+ filein, fileout, parse_document_options);
if (expect_errors)
{
diff --git a/tools/quickbook/src/state.cpp b/tools/quickbook/src/state.cpp
index d16200d626..be14604f71 100644
--- a/tools/quickbook/src/state.cpp
+++ b/tools/quickbook/src/state.cpp
@@ -10,10 +10,13 @@
=============================================================================*/
#include "state.hpp"
#include "state_save.hpp"
+#include "document_state.hpp"
#include "quickbook.hpp"
#include "grammar.hpp"
-#include "input_path.hpp"
-#include <boost/filesystem/operations.hpp>
+#include "native_text.hpp"
+#include "utils.hpp"
+#include "phrase_tags.hpp"
+#include <boost/foreach.hpp>
#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
#pragma warning(disable:4355)
@@ -27,9 +30,10 @@ namespace quickbook
unsigned qbk_version_n = 0; // qbk_major_version * 100 + qbk_minor_version
state::state(fs::path const& filein_, fs::path const& xinclude_base_,
- string_stream& out_, id_manager& ids)
+ string_stream& out_, document_state& document)
: grammar_()
+ , order_pos(0)
, xinclude_base(xinclude_base_)
, templates()
@@ -37,30 +41,37 @@ namespace quickbook
, anchors()
, warned_about_breaks(false)
, conditional(true)
- , ids(ids)
+ , document(document)
, callouts()
, callout_depth(0)
+ , dependencies()
+ , explicit_list(false)
, imported(false)
, macro()
- , source_mode("c++")
+ , source_mode()
, source_mode_next()
+ , source_mode_next_pos()
, current_file(0)
- , filename_relative(filein_.filename())
+ , current_path(filein_, 0, filein_.filename())
, template_depth(0)
, min_section_level(1)
+ , in_list(false)
+ , in_list_save()
, out(out_)
, phrase()
+
, values(&current_file)
{
// add the predefined macros
macro.add
("__DATE__", std::string(quickbook_get_date))
("__TIME__", std::string(quickbook_get_time))
- ("__FILENAME__", detail::path_to_generic(filename_relative))
+ ("__FILENAME__", std::string())
;
+ update_filename_macro();
boost::scoped_ptr<quickbook_grammar> g(
new quickbook_grammar(*this));
@@ -71,89 +82,100 @@ namespace quickbook
return *grammar_;
}
- bool state::add_dependency(fs::path const& f) {
- fs::path p = fs::absolute(f);
- bool found = fs::exists(fs::status(p));
-
- // Pop path sections from path until we find an existing
- // path, adjusting for any dot path sections.
- fs::path extra;
- int parent_count = 0;
- while (!fs::exists(fs::status(p))) {
- fs::path name = p.filename();
- p = p.parent_path();
- if (name == "..") {
- ++parent_count;
- }
- else if (name == ".") {
- }
- else if (parent_count) {
- --parent_count;
- }
- else {
- extra = name / extra;
- }
+ void state::update_filename_macro() {
+ *boost::spirit::classic::find(macro, "__FILENAME__")
+ = detail::encode_string(
+ detail::path_to_generic(current_path.abstract_file_path));
+ }
+
+ unsigned state::get_new_order_pos() {
+ return ++order_pos;
+ }
+
+ 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();
+ }
+
+ source_mode_info state::tagged_source_mode() const {
+ source_mode_info result;
+
+ BOOST_FOREACH(source_mode_info const& s, tagged_source_mode_stack) {
+ result.update(s);
}
- // If there are any left over ".." sections, then add them
- // on to the end of the real path, and trust Boost.Filesystem
- // to sort them out.
- while (parent_count) {
- p = p / "..";
- --parent_count;
+ return result;
+ }
+
+ source_mode_info state::current_source_mode() const {
+ source_mode_info result = source_mode;
+
+ result.update(document.section_source_mode());
+
+ BOOST_FOREACH(source_mode_info const& s, tagged_source_mode_stack) {
+ result.update(s);
}
- p = fs::canonical(p) / extra;
- dependencies[p] |= found;
- return found;
+ return result;
+ }
+
+ void state::change_source_mode(source_mode_type s) {
+ source_mode = source_mode_info(s, get_new_order_pos());
}
- file_state::file_state(quickbook::state& state, scope_flags scope)
+ void state::push_tagged_source_mode(source_mode_type s) {
+ tagged_source_mode_stack.push_back(
+ source_mode_info(s, s ? get_new_order_pos() : 0));
+ }
+
+ void state::pop_tagged_source_mode() {
+ assert(!tagged_source_mode_stack.empty());
+ tagged_source_mode_stack.pop_back();
+ }
+
+ state_save::state_save(quickbook::state& state, scope_flags scope)
: state(state)
, scope(scope)
, qbk_version(qbk_version_n)
, imported(state.imported)
, current_file(state.current_file)
- , filename_relative(state.filename_relative)
+ , current_path(state.current_path)
, 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);
boost::swap(state.imported, imported);
boost::swap(state.current_file, current_file);
- boost::swap(state.filename_relative, filename_relative);
+ boost::swap(state.current_path, current_path);
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);
}
diff --git a/tools/quickbook/src/state.hpp b/tools/quickbook/src/state.hpp
index b750904588..e4271906ad 100644
--- a/tools/quickbook/src/state.hpp
+++ b/tools/quickbook/src/state.hpp
@@ -17,6 +17,9 @@
#include "collector.hpp"
#include "template_stack.hpp"
#include "symbols.hpp"
+#include "dependency_tracker.hpp"
+#include "syntax_highlight.hpp"
+#include "include_paths.hpp"
namespace quickbook
{
@@ -26,7 +29,7 @@ namespace quickbook
struct state
{
state(fs::path const& filein_, fs::path const& xinclude_base, string_stream& out_,
- id_manager&);
+ document_state&);
private:
boost::scoped_ptr<quickbook_grammar> grammar_;
@@ -37,39 +40,46 @@ namespace quickbook
///////////////////////////////////////////////////////////////////////////
typedef std::vector<std::string> string_list;
- typedef std::map<fs::path, bool> dependency_list;
static int const max_template_depth = 100;
// global state
+ unsigned order_pos;
fs::path xinclude_base;
template_stack templates;
int error_count;
string_list anchors;
bool warned_about_breaks;
bool conditional;
- id_manager& ids;
+ document_state& document;
value_builder callouts; // callouts are global as
int callout_depth; // they don't nest.
- dependency_list dependencies;
+ dependency_tracker dependencies;
+ bool explicit_list; // set when using a list
// state saved for files and templates.
bool imported;
string_symbols macro;
- std::string source_mode;
- value source_mode_next;
+ source_mode_info source_mode;
+ source_mode_type source_mode_next;
+ value source_mode_next_pos;
+ std::vector<source_mode_info>
+ tagged_source_mode_stack;
file_ptr current_file;
- fs::path filename_relative; // for the __FILENAME__ macro.
- // (relative to the original file
- // or include path).
+ quickbook_path current_path;
// state saved for templates.
int template_depth;
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,9 +88,12 @@ namespace quickbook
// actions
///////////////////////////////////////////////////////////////////////////
- // Call this before loading any file so that it will be included in the
- // list of dependencies. Returns true if file exists.
- bool add_dependency(fs::path const&);
+ void update_filename_macro();
+
+ unsigned get_new_order_pos();
+
+ void push_output();
+ void pop_output();
void start_list(char mark);
void end_list(char mark);
@@ -90,6 +103,12 @@ namespace quickbook
void start_callouts();
std::string add_callout(value);
std::string end_callouts();
+
+ source_mode_info current_source_mode() const;
+ source_mode_info tagged_source_mode() const;
+ void change_source_mode(source_mode_type);
+ void push_tagged_source_mode(source_mode_type);
+ void pop_tagged_source_mode();
};
extern unsigned qbk_version_n; // qbk_major_version * 100 + qbk_minor_version
diff --git a/tools/quickbook/src/state_save.hpp b/tools/quickbook/src/state_save.hpp
index f8b53e7c8e..8cae8cd1b2 100644
--- a/tools/quickbook/src/state_save.hpp
+++ b/tools/quickbook/src/state_save.hpp
@@ -18,7 +18,7 @@ namespace quickbook
//
// Defined in state.cpp
- struct file_state
+ struct state_save
{
enum scope_flags {
scope_none = 0,
@@ -29,8 +29,8 @@ namespace quickbook
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;
@@ -38,22 +38,15 @@ namespace quickbook
bool imported;
std::string doc_type;
file_ptr current_file;
- fs::path filename_relative;
+ quickbook_path current_path;
fs::path xinclude_base;
- std::string source_mode;
+ source_mode_info 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&);
};
}
diff --git a/tools/quickbook/src/string_ref.cpp b/tools/quickbook/src/string_ref.cpp
deleted file mode 100644
index 6c33df1260..0000000000
--- a/tools/quickbook/src/string_ref.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*=============================================================================
- Copyright (c) 2011 Daniel James
-
- Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-=============================================================================*/
-
-#include "string_ref.hpp"
-#include <boost/range/algorithm/equal.hpp>
-#include <boost/range/algorithm/lexicographical_compare.hpp>
-#include <boost/utility/swap.hpp>
-#include <ostream>
-
-namespace quickbook
-{
- void string_ref::swap(string_ref& x)
- {
- boost::swap(begin_, x.begin_);
- boost::swap(end_, x.end_);
- }
-
- bool operator==(string_ref const& x, string_ref const& y)
- {
- return boost::equal(x, y);
- }
-
- bool operator<(string_ref const& x, string_ref const& y)
- {
- return boost::lexicographical_compare(x, y);
- }
-
- std::ostream& operator<<(std::ostream& out, string_ref const& x)
- {
- return out.write(&*x.begin(), x.end() - x.begin());
- }
-}
diff --git a/tools/quickbook/src/string_ref.hpp b/tools/quickbook/src/string_ref.hpp
deleted file mode 100644
index ffb95bf71d..0000000000
--- a/tools/quickbook/src/string_ref.hpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*=============================================================================
- Copyright (c) 2011 Daniel James
-
- Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-=============================================================================*/
-
-#if !defined(BOOST_QUICKBOOK_STRING_REF_HPP)
-#define BOOST_QUICKBOOK_STRING_REF_HPP
-
-#include <boost/operators.hpp>
-#include <string>
-#include <iosfwd>
-
-namespace quickbook
-{
- struct string_ref
- : boost::less_than_comparable<string_ref,
- boost::less_than_comparable<string_ref, std::string,
- boost::equality_comparable<string_ref,
- boost::equality_comparable<string_ref, std::string> > > >
- {
- public:
- typedef std::string::const_iterator iterator;
- typedef std::string::const_iterator const_iterator;
-
- private:
- iterator begin_, end_;
-
- public:
- string_ref() : begin_(), end_() {}
-
- explicit string_ref(iterator b, iterator e)
- : begin_(b), end_(e) {}
-
- explicit string_ref(std::string const& x)
- : begin_(x.begin()), end_(x.end()) {}
-
- void swap(string_ref&);
-
- void clear() {
- begin_ = end_ = iterator();
- }
-
- operator std::string() const {
- return std::string(begin_, end_);
- }
-
- iterator begin() const { return begin_; }
- iterator end() const { return end_; }
-
- std::size_t size() const
- {
- return static_cast<std::size_t>(end_ - begin_);
- }
-
- bool empty() const
- {
- return begin_ == end_;
- }
- };
-
- bool operator==(string_ref const& x, string_ref const& y);
- bool operator<(string_ref const& x, string_ref const& y);
- std::ostream& operator<<(std::ostream&, string_ref const& x);
-
- inline bool operator==(string_ref const& x, std::string const& y)
- {
- return x == string_ref(y);
- }
-
- inline bool operator<(string_ref const& x, std::string const& y)
- {
- return x < string_ref(y);
- }
-
- inline bool operator>(string_ref const& x, std::string const& y)
- {
- return x > string_ref(y);
- }
-
- inline void swap(string_ref& x, string_ref& y)
- {
- x.swap(y);
- }
-}
-
-#endif
diff --git a/tools/quickbook/src/syntax_highlight.cpp b/tools/quickbook/src/syntax_highlight.cpp
index e618c07dd6..12e2c5e077 100644
--- a/tools/quickbook/src/syntax_highlight.cpp
+++ b/tools/quickbook/src/syntax_highlight.cpp
@@ -13,91 +13,32 @@
#include <boost/spirit/include/classic_symbols.hpp>
#include <boost/spirit/include/classic_loops.hpp>
#include "grammar.hpp"
-#include "grammar_impl.hpp" // Just for context stuff. Should move?
#include "state.hpp"
#include "actions.hpp"
+#include "syntax_highlight.hpp"
#include "utils.hpp"
#include "files.hpp"
-#include "input_path.hpp"
+#include "native_text.hpp"
+#include "phrase_tags.hpp"
namespace quickbook
{
namespace cl = boost::spirit::classic;
- template <typename T, typename Value>
- struct member_action_value
- {
- typedef void(T::*member_function)(Value);
-
- T& l;
- member_function mf;
-
- member_action_value(T& l, member_function mf) : l(l), mf(mf) {}
-
- void operator()(Value v) const {
- (l.*mf)(v);
- }
- };
-
- template <typename T>
- struct member_action
- {
- typedef void(T::*member_function)(parse_iterator, parse_iterator);
-
- T& l;
- member_function mf;
-
- member_action(T& l, member_function mf) : l(l), mf(mf) {}
-
- void operator()(parse_iterator first, parse_iterator last) const {
- (l.*mf)(first, last);
- }
- };
-
- template <typename T, typename Arg1>
- struct member_action1
- {
- typedef void(T::*member_function)(parse_iterator, parse_iterator, Arg1);
-
- T& l;
- member_function mf;
-
- member_action1(T& l, member_function mf) : l(l), mf(mf) {}
-
- struct impl
- {
- member_action1 a;
- Arg1 value;
-
- impl(member_action1& a, Arg1 value) :
- a(a), value(value)
- {}
-
- void operator()(parse_iterator first, parse_iterator last) const {
- (a.l.*a.mf)(first, last, value);
- }
- };
-
- impl operator()(Arg1 a1) {
- return impl(*this, a1);
- }
- };
-
// Syntax Highlight Actions
struct syntax_highlight_actions
{
- quickbook::collector out;
quickbook::state& state;
do_macro_action do_macro_impl;
// State
bool support_callouts;
- string_ref marked_text;
+ 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 +60,26 @@ namespace quickbook
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 +93,32 @@ namespace quickbook
<< "\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)
@@ -186,12 +129,12 @@ namespace quickbook
void syntax_highlight_actions::mark_text(parse_iterator first,
parse_iterator last)
{
- marked_text = string_ref(first.base(), last.base());
+ marked_text = boost::string_ref(first.base(), last.base() - first.base());
}
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();
}
@@ -205,20 +148,23 @@ namespace quickbook
keywords_holder()
{
cpp
- = "and_eq", "and", "asm", "auto", "bitand", "bitor",
- "bool", "break", "case", "catch", "char", "class",
- "compl", "const_cast", "const", "continue", "default",
- "delete", "do", "double", "dynamic_cast", "else",
- "enum", "explicit", "export", "extern", "false",
- "float", "for", "friend", "goto", "if", "inline",
- "int", "long", "mutable", "namespace", "new", "not_eq",
- "not", "operator", "or_eq", "or", "private",
- "protected", "public", "register", "reinterpret_cast",
- "return", "short", "signed", "sizeof", "static",
+ = "alignas", "alignof", "and_eq", "and", "asm", "auto",
+ "bitand", "bitor", "bool", "break", "case", "catch",
+ "char", "char16_t", "char32_t", "class", "compl",
+ "const", "const_cast", "constexpr", "continue",
+ "decltype", "default", "delete", "do", "double",
+ "dynamic_cast", "else", "enum", "explicit", "export",
+ "extern", "false", "float", "for", "friend", "goto",
+ "if", "inline", "int", "long", "mutable", "namespace",
+ "new", "noexcept", "not_eq", "not", "nullptr",
+ "operator", "or_eq", "or", "private", "protected",
+ "public", "register", "reinterpret_cast", "return",
+ "short", "signed", "sizeof", "static", "static_assert",
"static_cast", "struct", "switch", "template", "this",
- "throw", "true", "try", "typedef", "typeid",
- "typename", "union", "unsigned", "using", "virtual",
- "void", "volatile", "wchar_t", "while", "xor_eq", "xor"
+ "thread_local", "throw", "true", "try", "typedef",
+ "typeid", "typename", "union", "unsigned", "using",
+ "virtual", "void", "volatile", "wchar_t", "while",
+ "xor_eq", "xor"
;
python
@@ -270,12 +216,21 @@ namespace quickbook
do_macro(self.actions, &syntax_highlight_actions::do_macro);
error_action error(self.actions.state);
- program
- =
- *( (+cl::space_p) [plain_char]
+ program =
+ *( (*cl::space_p) [plain_char]
+ >> (line_start | rest_of_line)
+ >> *rest_of_line
+ )
+ ;
+
+ line_start =
+ preprocessor [span("preprocessor")]
+ ;
+
+ rest_of_line =
+ (+cl::blank_p) [plain_char]
| macro
| escape
- | preprocessor [span("preprocessor")]
| cl::eps_p(ph::var(self.actions.support_callouts))
>> ( line_callout [callout]
| inline_callout [callout]
@@ -287,8 +242,8 @@ namespace quickbook
| string_ [span("string")]
| char_ [span("char")]
| number [span("number")]
- | u8_codepoint_p [unexpected_char]
- )
+ | ~cl::eps_p(cl::eol_p)
+ >> u8_codepoint_p [unexpected_char]
;
macro =
@@ -306,7 +261,7 @@ namespace quickbook
(
(
(+(cl::anychar_p - "``") >> cl::eps_p("``"))
- & g.phrase
+ & g.phrase_start
)
>> cl::str_p("``")
)
@@ -359,7 +314,7 @@ namespace quickbook
; // make sure we recognize whole words only
special
- = +cl::chset_p("~!%^&*()+={[}]:;,<.>?/|\\-")
+ = +cl::chset_p("~!%^&*()+={[}]:;,<.>?/|\\#-")
;
string_char = ('\\' >> u8_codepoint_p) | (cl::anychar_p - '\\');
@@ -387,7 +342,7 @@ namespace quickbook
}
cl::rule<Scanner>
- program, macro, preprocessor,
+ program, line_start, rest_of_line, macro, preprocessor,
inline_callout, line_callout, comment,
special, string_,
char_, number, identifier, keyword, escape,
@@ -461,7 +416,7 @@ namespace quickbook
(
(
(+(cl::anychar_p - "``") >> cl::eps_p("``"))
- & g.phrase
+ & g.phrase_start
)
>> cl::str_p("``")
)
@@ -583,7 +538,7 @@ namespace quickbook
(
(
(+(cl::anychar_p - "``") >> cl::eps_p("``"))
- & g.phrase
+ & g.phrase_start
)
>> cl::str_p("``")
)
@@ -607,39 +562,35 @@ namespace quickbook
syntax_highlight_actions& actions;
};
- std::string syntax_highlight(
+ void syntax_highlight(
parse_iterator first,
parse_iterator last,
quickbook::state& state,
- std::string const& source_mode,
+ source_mode_type source_mode,
bool is_block)
{
syntax_highlight_actions syn_actions(state, is_block);
// print the code with syntax coloring
- if (source_mode == "c++")
- {
- cpp_highlight cpp_p(syn_actions);
- boost::spirit::classic::parse(first, last, cpp_p);
- }
- else if (source_mode == "python")
+ switch(source_mode)
{
- python_highlight python_p(syn_actions);
- boost::spirit::classic::parse(first, last, python_p);
- }
- else if (source_mode == "teletype")
- {
- teletype_highlight teletype_p(syn_actions);
- boost::spirit::classic::parse(first, last, teletype_p);
- }
- else
- {
- BOOST_ASSERT(0);
+ case source_mode_tags::cpp: {
+ cpp_highlight cpp_p(syn_actions);
+ boost::spirit::classic::parse(first, last, cpp_p);
+ break;
+ }
+ case source_mode_tags::python: {
+ python_highlight python_p(syn_actions);
+ boost::spirit::classic::parse(first, last, python_p);
+ break;
+ }
+ case source_mode_tags::teletype: {
+ teletype_highlight teletype_p(syn_actions);
+ boost::spirit::classic::parse(first, last, teletype_p);
+ break;
+ }
+ default:
+ BOOST_ASSERT(0);
}
-
- std::string str;
- syn_actions.out.swap(str);
-
- return str;
}
}
diff --git a/tools/quickbook/src/syntax_highlight.hpp b/tools/quickbook/src/syntax_highlight.hpp
new file mode 100644
index 0000000000..12b3a63ae0
--- /dev/null
+++ b/tools/quickbook/src/syntax_highlight.hpp
@@ -0,0 +1,58 @@
+/*=============================================================================
+ 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_SYNTAX_HIGHLIGHT_HPP)
+#define BOOST_QUICKBOOK_SYNTAX_HIGHLIGHT_HPP
+
+#include "fwd.hpp"
+#include "phrase_tags.hpp"
+#include <boost/swap.hpp>
+
+namespace quickbook
+{
+ //
+ // source_mode_info
+ //
+ // The source mode is stored in a few places, so the order needs to also be
+ // stored to work out which is the current source mode.
+
+ struct source_mode_info {
+ source_mode_type source_mode;
+ unsigned order;
+
+ source_mode_info() : source_mode(source_mode_tags::cpp), order(0) {}
+
+ source_mode_info(source_mode_type source_mode, unsigned order) :
+ source_mode(source_mode),
+ order(order) {}
+
+ void update(source_mode_info const& x) {
+ if (x.order > order) {
+ source_mode = x.source_mode;
+ order = x.order;
+ }
+ }
+
+ void swap(source_mode_info& x) {
+ boost::swap(source_mode, x.source_mode);
+ boost::swap(order, x.order);
+ }
+ };
+
+ inline void swap(source_mode_info& x, source_mode_info& y) {
+ x.swap(y);
+ }
+
+ void syntax_highlight(
+ parse_iterator first, parse_iterator last,
+ quickbook::state& state,
+ source_mode_type source_mode,
+ bool is_block);
+}
+
+#endif
diff --git a/tools/quickbook/src/template_tags.hpp b/tools/quickbook/src/template_tags.hpp
index a47158dae6..d895707bc9 100644
--- a/tools/quickbook/src/template_tags.hpp
+++ b/tools/quickbook/src/template_tags.hpp
@@ -15,6 +15,7 @@ namespace quickbook
{
QUICKBOOK_VALUE_TAGS(template_tags, 0x100,
(template_)
+ (attribute_template)
(escape)
(identifier)
(block)
diff --git a/tools/quickbook/src/utils.cpp b/tools/quickbook/src/utils.cpp
index 3a5ee42e4d..6f3b49acda 100644
--- a/tools/quickbook/src/utils.cpp
+++ b/tools/quickbook/src/utils.cpp
@@ -15,6 +15,27 @@
namespace quickbook { namespace detail
{
+ std::string encode_string(boost::string_ref str)
+ {
+ std::string result;
+ result.reserve(str.size());
+
+ for (boost::string_ref::const_iterator it = str.begin();
+ it != str.end(); ++it)
+ {
+ switch (*it)
+ {
+ case '<': result += "&lt;"; break;
+ case '>': result += "&gt;"; break;
+ case '&': result += "&amp;"; break;
+ case '"': result += "&quot;"; break;
+ default: result += *it; break;
+ }
+ }
+
+ return result;
+ }
+
void print_char(char ch, std::ostream& out)
{
switch (ch)
@@ -29,9 +50,9 @@ namespace quickbook { namespace detail
}
}
- void print_string(std::basic_string<char> const& str, std::ostream& out)
+ void print_string(boost::string_ref str, std::ostream& out)
{
- for (std::string::const_iterator cur = str.begin();
+ for (boost::string_ref::const_iterator cur = str.begin();
cur != str.end(); ++cur)
{
print_char(*cur, out);
@@ -45,21 +66,45 @@ namespace quickbook { namespace detail
return static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
}
- std::string escape_uri(std::string uri)
+ static std::string escape_uri_impl(std::string& uri_param, char const* mark)
{
+ // Extra capital characters for validating percent escapes.
+ static char const hex[] = "0123456789abcdefABCDEF";
+
+ std::string uri;
+ uri.swap(uri_param);
+
for (std::string::size_type n = 0; n < uri.size(); ++n)
{
- static char const mark[] = "-_.!~*'()?\\/";
- if((!std::isalnum(static_cast<unsigned char>(uri[n])) || 127 < static_cast<unsigned char>(uri[n]))
- && 0 == std::strchr(mark, uri[n]))
+ if (static_cast<unsigned char>(uri[n]) > 127 ||
+ (!std::isalnum(static_cast<unsigned char>(uri[n])) &&
+ !std::strchr(mark, uri[n])) ||
+ (uri[n] == '%' && !(n + 2 < uri.size() &&
+ std::strchr(hex, uri[n+1]) &&
+ std::strchr(hex, uri[n+2]))))
{
- static char const hex[] = "0123456789abcdef";
char escape[] = { hex[uri[n] / 16], hex[uri[n] % 16] };
uri.insert(n + 1, escape, 2);
uri[n] = '%';
n += 2;
}
+ else if (uri[n] == '%')
+ {
+ n += 2;
+ }
}
+
return uri;
}
+
+ std::string escape_uri(std::string uri_param)
+ {
+ // TODO: I don't understand this choice of characters.....
+ return escape_uri_impl(uri_param, "-_.!~*'()?\\/");
+ }
+
+ std::string partially_escape_uri(std::string uri_param)
+ {
+ return escape_uri_impl(uri_param, "-_.!~*'()?\\/:&=#%+");
+ }
}}
diff --git a/tools/quickbook/src/utils.hpp b/tools/quickbook/src/utils.hpp
index 9170f81043..3f5c5455dc 100644
--- a/tools/quickbook/src/utils.hpp
+++ b/tools/quickbook/src/utils.hpp
@@ -14,10 +14,12 @@
#include <ostream>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <boost/range/adaptor/transformed.hpp>
+#include <boost/utility/string_ref.hpp>
namespace quickbook { namespace detail {
+ std::string encode_string(boost::string_ref);
void print_char(char ch, std::ostream& out);
- void print_string(std::basic_string<char> const& str, std::ostream& out);
+ void print_string(boost::string_ref str, std::ostream& out);
char filter_identifier_char(char ch);
template <typename Range>
@@ -32,7 +34,21 @@ namespace quickbook { namespace detail {
return out_name;
}
+ // URI escape string
std::string escape_uri(std::string uri);
+ inline std::string escape_uri(boost::string_ref uri) {
+ return escape_uri(std::string(uri.begin(), uri.end()));
+ }
+
+ // URI escape string, leaving characters generally used in URIs.
+ std::string partially_escape_uri(std::string uri);
+ inline std::string partially_escape_uri(boost::string_ref uri) {
+ return escape_uri(std::string(uri.begin(), uri.end()));
+ }
+
+ inline std::string to_s(boost::string_ref x) {
+ return std::string(x.begin(), x.end());
+ }
}}
#endif // BOOST_SPIRIT_QUICKBOOK_UTILS_HPP
diff --git a/tools/quickbook/src/values.cpp b/tools/quickbook/src/values.cpp
index 904cc8b38f..59c11cfa48 100644
--- a/tools/quickbook/src/values.cpp
+++ b/tools/quickbook/src/values.cpp
@@ -50,7 +50,7 @@ namespace quickbook
file_ptr value_node::get_file() const { UNDEFINED_ERROR(); }
string_iterator value_node::get_position() const { UNDEFINED_ERROR(); }
int value_node::get_int() const { UNDEFINED_ERROR(); }
- string_ref value_node::get_quickbook() const { UNDEFINED_ERROR(); }
+ boost::string_ref value_node::get_quickbook() const { UNDEFINED_ERROR(); }
std::string value_node::get_encoded() const { UNDEFINED_ERROR(); }
value_node* value_node::get_list() const { UNDEFINED_ERROR(); }
@@ -332,7 +332,7 @@ namespace quickbook
virtual value_node* clone() const;
virtual file_ptr get_file() const;
virtual string_iterator get_position() const;
- virtual string_ref get_quickbook() const;
+ virtual boost::string_ref get_quickbook() const;
virtual bool empty() const;
virtual bool equals(value_node*) const;
@@ -354,7 +354,7 @@ namespace quickbook
virtual value_node* clone() const;
virtual file_ptr get_file() const;
virtual string_iterator get_position() const;
- virtual string_ref get_quickbook() const;
+ virtual boost::string_ref get_quickbook() const;
virtual std::string get_encoded() const;
virtual bool empty() const;
virtual bool is_encoded() const;
@@ -433,8 +433,8 @@ namespace quickbook
string_iterator qbk_value_impl::get_position() const
{ return begin_; }
- string_ref qbk_value_impl::get_quickbook() const
- { return string_ref(begin_, end_); }
+ boost::string_ref qbk_value_impl::get_quickbook() const
+ { return boost::string_ref(begin_, end_ - begin_); }
bool qbk_value_impl::empty() const
{ return begin_ == end_; }
@@ -481,8 +481,8 @@ namespace quickbook
string_iterator encoded_qbk_value_impl::get_position() const
{ return begin_; }
- string_ref encoded_qbk_value_impl::get_quickbook() const
- { return string_ref(begin_, end_); }
+ boost::string_ref encoded_qbk_value_impl::get_quickbook() const
+ { return boost::string_ref(begin_, end_ - begin_); }
std::string encoded_qbk_value_impl::get_encoded() const
{ return encoded_value_; }
diff --git a/tools/quickbook/src/values.hpp b/tools/quickbook/src/values.hpp
index d637ea2adb..e681c8a75f 100644
--- a/tools/quickbook/src/values.hpp
+++ b/tools/quickbook/src/values.hpp
@@ -16,9 +16,9 @@
#include <cassert>
#include <boost/scoped_ptr.hpp>
#include <boost/iterator/iterator_traits.hpp>
+#include <boost/utility/string_ref.hpp>
#include <stdexcept>
#include "fwd.hpp"
-#include "string_ref.hpp"
#include "files.hpp"
namespace quickbook
@@ -51,7 +51,7 @@ namespace quickbook
virtual file_ptr get_file() const;
virtual string_iterator get_position() const;
- virtual string_ref get_quickbook() const;
+ virtual boost::string_ref get_quickbook() const;
virtual std::string get_encoded() const;
virtual int get_int() const;
@@ -113,7 +113,7 @@ namespace quickbook
{ return value_->get_file(); }
string_iterator get_position() const
{ return value_->get_position(); }
- string_ref get_quickbook() const
+ boost::string_ref get_quickbook() const
{ return value_->get_quickbook(); }
std::string get_encoded() const
{ return value_->get_encoded(); }
diff --git a/tools/quickbook/test/Jamfile.v2 b/tools/quickbook/test/Jamfile.v2
index 900b4758a2..505b58ff1a 100644
--- a/tools/quickbook/test/Jamfile.v2
+++ b/tools/quickbook/test/Jamfile.v2
@@ -6,7 +6,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
#
-project test
+project quickbook/test
: requirements
<toolset>msvc:<debug-symbols>off
;
@@ -24,6 +24,7 @@ import quickbook-testing : quickbook-test quickbook-error-test ;
test-suite quickbook.test :
[ quickbook-test anchor-1_1 ]
[ quickbook-test anchor-1_6 ]
+ [ quickbook-test anchor-1_7 ]
[ quickbook-test blocks-1_5 ]
[ quickbook-test callouts-1_5 ]
[ quickbook-test callouts-1_7 ]
@@ -52,6 +53,7 @@ test-suite quickbook.test :
[ quickbook-test heading-1_3 ]
[ quickbook-test heading-1_5 ]
[ quickbook-test heading-1_6 ]
+ [ quickbook-test heading-1_7 ]
[ quickbook-error-test heading_unclosed-1_4-fail ]
[ quickbook-test hr-1_5 ]
[ quickbook-test hr-1_6 ]
@@ -63,33 +65,48 @@ test-suite quickbook.test :
[ quickbook-error-test include-1_1-fail ]
[ quickbook-test include-1_5 ]
[ quickbook-test include-1_6 ]
+ [ quickbook-test include-1_7 ]
[ quickbook-test include2-1_6 ]
[ quickbook-error-test include_win_path-1_6-fail ]
+ [ quickbook-error-test include_invalid_path1-1_7-fail ]
+ [ quickbook-error-test include_invalid_path2-1_7-fail ]
+ [ quickbook-error-test include_invalid_path3-1_7-fail ]
+ [ quickbook-error-test include_unicode_glob-1_7-fail ]
[ quickbook-test link-1_1 ]
[ quickbook-test link-1_6 ]
[ quickbook-test link-1_7 ]
+ [ quickbook-error-test link-1_7-fail ]
+ [ quickbook-error-test link-1_7-fail2 ]
[ 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 ]
+ [ quickbook-test section-1_7 ]
[ quickbook-test simple_markup-1_5 ]
[ quickbook-test source_mode-1_7 ]
[ quickbook-test svg-1_1 ]
[ 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 ]
@@ -100,6 +117,11 @@ test-suite quickbook.test :
[ 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-error-test templates-1_7-fail2 ]
[ quickbook-test unicode_escape-1_5 ]
[ quickbook-test unmatched_element-1_5 ]
[ quickbook-test unmatched_element-1_6 ]
diff --git a/tools/quickbook/test/anchor-1_7.gold b/tools/quickbook/test/anchor-1_7.gold
new file mode 100644
index 0000000000..71e22458da
--- /dev/null
+++ b/tools/quickbook/test/anchor-1_7.gold
@@ -0,0 +1,151 @@
+<?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="anchor_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Anchor Test</title>
+ <section id="anchor_test.anchors">
+ <title><link linkend="anchor_test.anchors">Anchors</link></title>
+ <para>
+ <anchor id="a1"/>A paragraph containing several anchors. <anchor id="a2"/>We
+ want to make sure they appear in the correct place. <anchor id="a3"/>
+ </para>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h0">
+ <phrase id="anchor_test.anchors.this_heading_shouldn_t_pick_up_t"/><link linkend="anchor_test.anchors.this_heading_shouldn_t_pick_up_t">This
+ heading shouldn't pick up the previous anchor</link>
+ </bridgehead>
+ <anchor id="a4"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h1">
+ <phrase id="anchor_test.anchors.this_heading_should_pick_up_the_"/><link linkend="anchor_test.anchors.this_heading_should_pick_up_the_">This
+ heading should pick up the previous anchor</link>
+ </bridgehead>
+ <anchor id="a5"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h2">
+ <phrase id="anchor_test.anchors.and_this_one"/><link linkend="anchor_test.anchors.and_this_one">And
+ this one</link>
+ </bridgehead>
+ <anchor id="a6"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h3">
+ <phrase id="anchor_test.anchors.also_this_one"/><link linkend="anchor_test.anchors.also_this_one">Also
+ this one</link>
+ </bridgehead>
+ <anchor id="a7"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h4">
+ <phrase id="anchor_test.anchors.finally_this"/><link linkend="anchor_test.anchors.finally_this">Finally
+ this</link>
+ </bridgehead>
+ <anchor id="a8"/>
+ </section>
+ <section id="anchor_test.section_anchor">
+ <title><anchor id="a9"/><link linkend="anchor_test.section_anchor">Section Anchor</link></title>
+ <section id="anchor_test.section_anchor.nested_section">
+ <title><anchor id="a10"/><link linkend="anchor_test.section_anchor.nested_section">Nested
+ Section</link></title>
+ </section>
+ <anchor id="a11"/>
+ </section>
+ <section id="anchor_test.conditional_section_anchor">
+ <title><anchor id="a12"/><link linkend="anchor_test.conditional_section_anchor">Conditional
+ Section Anchor</link></title>
+ </section>
+ <section id="anchor_test.lists">
+ <title><link linkend="anchor_test.lists">Lists</link></title> <anchor id="a14"/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Item 1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Item 2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Nested List <anchor id="a15"/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Nested Item 1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Nested Item 2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <anchor id="a16"/>Nested Item 3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Item 3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="anchor_test.anchors_in_templates">
+ <title><link linkend="anchor_test.anchors_in_templates">Anchors in templates</link></title>
+ <para>
+ <anchor id="t1"/>Some text.
+ </para>
+ <para>
+ <anchor id="t2"/>Text content
+ </para>
+ </section>
+ <section id="anchor_test.anchors_in_syntax_highlighted_co">
+ <title><link linkend="anchor_test.anchors_in_syntax_highlighted_co">Anchors in
+ syntax highlighted code</link></title>
+<programlisting><phrase role="keyword">int</phrase> <anchor id="s1"/><phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
+</programlisting>
+ </section>
+ <section id="anchor_test.nested_anchors">
+ <title><link linkend="anchor_test.nested_anchors">Nested anchors</link></title>
+ <table frame="all" id="anchor_test.nested_anchors.table_with_anchors">
+ <title>Table with anchors</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <anchor id="table1"/>Cell 1
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <anchor id="table2"/>Cell 2
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Cell 3<anchor id="table3"/>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="anchor_test.templates">
+ <title><link linkend="anchor_test.templates">Anchors with templates</link></title>
+ <anchor id="anchor1"/><anchor id="anchor2"/><anchor id="x1y"/><anchor id="x12y"/>
+ </section>
+</article>
diff --git a/tools/quickbook/test/anchor-1_7.quickbook b/tools/quickbook/test/anchor-1_7.quickbook
new file mode 100644
index 0000000000..f2b5c13db5
--- /dev/null
+++ b/tools/quickbook/test/anchor-1_7.quickbook
@@ -0,0 +1,97 @@
+[article Anchor Test
+[quickbook 1.7]
+]
+
+[section Anchors]
+
+[#a1] A paragraph containing several anchors. [#a2] We want to make sure
+they appear in the correct place. [#a3]
+
+[heading This heading shouldn't pick up the previous anchor]
+
+[#a4]
+
+[heading This heading should pick up the previous anchor]
+
+[#a5]
+[heading And this one]
+
+[#a6][heading Also this one]
+
+[#a7][h3 Finally this]
+
+[#a8]
+
+[endsect]
+
+[#a9]
+[section Section Anchor]
+[#a10][section Nested Section]
+[endsect]
+[/ This anchor is invalid, I'm not sure what to do with it]
+[#a11]
+[endsect]
+
+[#a12][?__not_defined__ #a13]
+[section Conditional Section Anchor]
+[endsect]
+
+[section Lists]
+
+[#a14]
+* Item 1
+* Item 2
+* Nested List
+ [#a15]
+ * Nested Item 1
+ * Nested Item 2
+ * [#a16] Nested Item 3
+* Item 3
+
+[endsect]
+
+[section Anchors in templates]
+
+[template anchor1[][#t1]]
+[template para[] Text content]
+
+[anchor1]
+
+Some text.
+
+[#t2]
+
+[para]
+
+[endsect]
+
+[section Anchors in syntax highlighted code]
+
+ int ``[#s1]``main() {}
+
+[endsect]
+
+[section Nested anchors]
+
+[table Table with anchors
+ [[Heading]]
+ [[[#table1]Cell 1]]
+ [[[#table2] Cell 2]]
+ [[Cell 3[#table3]]]
+]
+[endsect]
+
+[section:templates Anchors with templates]
+
+[template a1 anchor1]
+[template a2 anchor2]
+
+[#[a1]]
+[#[a2]]
+
+[template anchor[name] [#x[name]y]]
+
+[anchor 1]
+[anchor 12]
+
+[endsect] [/ templates]
diff --git a/tools/quickbook/test/code_cpp-1_5.gold b/tools/quickbook/test/code_cpp-1_5.gold
index be33bfdfd3..d0bc79a3f6 100644
--- a/tools/quickbook/test/code_cpp-1_5.gold
+++ b/tools/quickbook/test/code_cpp-1_5.gold
@@ -3,7 +3,11 @@
<article id="c___code_blocks" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
xmlns:xi="http://www.w3.org/2001/XInclude">
<title>C++ Code Blocks</title>
-<programlisting><phrase role="comment">// No escape</phrase>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">some_header</phrase><phrase role="special">&gt;</phrase>
+ <phrase role="preprocessor">#include</phrase> <phrase role="string">&quot;another_header.hpp&quot;</phrase>
+<phrase role="preprocessor"># define</phrase> <phrase role="identifier">A_MACRO</phrase> <phrase role="identifier">value</phrase>
+<phrase role="preprocessor">#define</phrase> <phrase role="identifier">stringize</phrase><phrase role="special">(</phrase><phrase role="identifier">hello</phrase><phrase role="special">)</phrase> <phrase role="special">#</phrase><phrase role="identifier">hello</phrase>
+<phrase role="comment">// No escape</phrase>
<phrase role="comment">/* No escape */</phrase>
<phrase role="comment">/* No escape
* with newlines
@@ -13,6 +17,7 @@
<phrase role="comment">/* Multiple escapes: <emphasis>italic</emphasis>
* <emphasis role="underline">underline</emphasis><emphasis role="bold">bold</emphasis>
*/</phrase>
+<phrase role="comment">/* Token pasting: */</phrase> <phrase role="identifier">a</phrase><phrase role="special">##</phrase><phrase role="identifier">b</phrase>
</programlisting>
<para>
A badly formed comment:
@@ -24,4 +29,12 @@
</para>
<programlisting><phrase role="comment">/* Oh dear <emphasis role="bold">bold</emphasis>
</phrase></programlisting>
+ <para>
+ Just some code:
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <phrase role="keyword">constexpr</phrase> <phrase role="keyword">char32_t</phrase> <phrase role="identifier">x</phrase> <phrase role="special">=</phrase> <phrase role="char">'a'</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">y</phrase> <phrase role="special">=</phrase> <phrase role="identifier">x</phrase> <phrase role="special">-</phrase> <phrase role="char">' '</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
</article>
diff --git a/tools/quickbook/test/code_cpp-1_5.quickbook b/tools/quickbook/test/code_cpp-1_5.quickbook
index be8043a018..fdaa926bbb 100644
--- a/tools/quickbook/test/code_cpp-1_5.quickbook
+++ b/tools/quickbook/test/code_cpp-1_5.quickbook
@@ -2,6 +2,10 @@
[quickbook 1.5]
]
+ #include <some_header>
+ #include "another_header.hpp"
+ # define A_MACRO value
+ #define stringize(hello) #hello
// No escape
/* No escape */
/* No escape
@@ -12,6 +16,7 @@
/* Multiple escapes: ``/italic/``
* ``_underline_````*bold*``
*/
+ /* Token pasting: */ a##b
A badly formed comment:
@@ -20,3 +25,10 @@ A badly formed comment:
A badly formed comment with an escape:
/* Oh dear ``*bold*``
+
+Just some code:
+
+ int main() {
+ constexpr char32_t x = 'a';
+ const auto y = x - ' ';
+ }
diff --git a/tools/quickbook/test/command-line/Jamfile.v2 b/tools/quickbook/test/command-line/Jamfile.v2
index 052ec82afb..9e838e0a4e 100644
--- a/tools/quickbook/test/command-line/Jamfile.v2
+++ b/tools/quickbook/test/command-line/Jamfile.v2
@@ -7,7 +7,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
#
-project quickook/tests/command-line ;
+project quickbook/tests/command-line ;
import quickbook-testing : quickbook-test quickbook-fail-test quickbook-error-test ;
@@ -25,4 +25,4 @@ test-suite command-line.test :
output_nested_in_file :
basic-1_6.quickbook :
<testing.arg>--output-file=basic-1_6.quickbook/basic.xml ]
- ; \ No newline at end of file
+ ;
diff --git a/tools/quickbook/test/doc-info/Jamfile.v2 b/tools/quickbook/test/doc-info/Jamfile.v2
index 9d4913b81c..a35229c09b 100644
--- a/tools/quickbook/test/doc-info/Jamfile.v2
+++ b/tools/quickbook/test/doc-info/Jamfile.v2
@@ -6,7 +6,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
#
-project quickook/tests/doc-info ;
+project quickbook/tests/doc-info ;
import quickbook-testing : quickbook-test quickbook-error-test ;
@@ -20,6 +20,8 @@ test-suite quickbook.test :
[ quickbook-test escaped_attributes2-1_7 ]
[ quickbook-test duplicates-1.1 ]
[ quickbook-test duplicates-1.5 ]
+ [ quickbook-test macros1-1_5 ]
+ [ quickbook-test macros1-1_6 ]
[ quickbook-test source-mode-1.4 ]
[ quickbook-test source-mode-1.5 ]
[ quickbook-test source-mode-1.6 ]
diff --git a/tools/quickbook/test/doc-info/macros1-1_5.gold b/tools/quickbook/test/doc-info/macros1-1_5.gold
new file mode 100644
index 0000000000..0b76b9da15
--- /dev/null
+++ b/tools/quickbook/test/doc-info/macros1-1_5.gold
@@ -0,0 +1,11 @@
+<?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="macro_shouldn_t_expand____date__" last-revision="__DATE__" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Macro shouldn't expand: __DATE__</title>
+ <articleinfo>
+ <articlepurpose>
+ Unfortunately this does expand: 2000-Dec-20, but I'm not fixing it, as I don't
+ think it'll cause any real problems.
+ </articlepurpose>
+ </articleinfo>
+</article>
diff --git a/tools/quickbook/test/doc-info/macros1-1_5.quickbook b/tools/quickbook/test/doc-info/macros1-1_5.quickbook
new file mode 100644
index 0000000000..c66a1de6d5
--- /dev/null
+++ b/tools/quickbook/test/doc-info/macros1-1_5.quickbook
@@ -0,0 +1,6 @@
+[article Macro shouldn't expand: __DATE__
+ [quickbook 1.5]
+ [last-revision __DATE__]
+ [purpose Unfortunately this does expand: __DATE__, but I'm not fixing it,
+ as I don't think it'll cause any real problems.]
+]
diff --git a/tools/quickbook/test/doc-info/macros1-1_6.gold b/tools/quickbook/test/doc-info/macros1-1_6.gold
new file mode 100644
index 0000000000..92ac1a191d
--- /dev/null
+++ b/tools/quickbook/test/doc-info/macros1-1_6.gold
@@ -0,0 +1,8 @@
+<?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="testing_date_date" last-revision="2000-Dec-20" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Testing date: 2000-Dec-20</title>
+ <chapter id="testing_macro_date_nested_macro" last-revision="5 May 2013" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Testing macro date: 5 May 2013</title>
+ </chapter>
+</article>
diff --git a/tools/quickbook/test/doc-info/macros1-1_6.quickbook b/tools/quickbook/test/doc-info/macros1-1_6.quickbook
new file mode 100644
index 0000000000..058c349547
--- /dev/null
+++ b/tools/quickbook/test/doc-info/macros1-1_6.quickbook
@@ -0,0 +1,7 @@
+[article Testing date: __DATE__
+ [quickbook 1.6]
+ [last-revision __DATE__]
+]
+
+[def NESTED_MACRO 5 May 2013]
+[include macros1-inc_1_6.quickbook]
diff --git a/tools/quickbook/test/doc-info/macros1-inc_1_6.quickbook b/tools/quickbook/test/doc-info/macros1-inc_1_6.quickbook
new file mode 100644
index 0000000000..47fc84a813
--- /dev/null
+++ b/tools/quickbook/test/doc-info/macros1-inc_1_6.quickbook
@@ -0,0 +1,4 @@
+[chapter Testing macro date: NESTED_MACRO
+ [quickbook 1.6]
+ [last-revision NESTED_MACRO]
+]
diff --git a/tools/quickbook/test/elements-1_6.gold b/tools/quickbook/test/elements-1_6.gold
index bc9ee06f31..59a90af5cf 100644
--- a/tools/quickbook/test/elements-1_6.gold
+++ b/tools/quickbook/test/elements-1_6.gold
@@ -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>
diff --git a/tools/quickbook/test/elements-1_6.quickbook b/tools/quickbook/test/elements-1_6.quickbook
index 68372d1238..e313cd98d6 100644
--- a/tools/quickbook/test/elements-1_6.quickbook
+++ b/tools/quickbook/test/elements-1_6.quickbook
@@ -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>''']
diff --git a/tools/quickbook/test/empty.qbk b/tools/quickbook/test/empty-inc.quickbook
index e69de29bb2..e69de29bb2 100644
--- a/tools/quickbook/test/empty.qbk
+++ b/tools/quickbook/test/empty-inc.quickbook
diff --git a/tools/quickbook/test/heading-1_7.gold b/tools/quickbook/test/heading-1_7.gold
new file mode 100644
index 0000000000..52f8291ab5
--- /dev/null
+++ b/tools/quickbook/test/heading-1_7.gold
@@ -0,0 +1,113 @@
+<?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="heading_test_1_7" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Heading Test 1.7</title>
+ <bridgehead renderas="sect2" id="heading_test_1_7.h0">
+ <phrase id="heading_test_1_7.generic_header"/><link linkend="heading_test_1_7.generic_header">Generic
+ header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_7.h2">
+ <phrase id="heading_test_1_7.level_1"/><link linkend="heading_test_1_7.level_1">Level
+ 1</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="heading_test_1_7.h3">
+ <phrase id="heading_test_1_7.level_2"/><link linkend="heading_test_1_7.level_2">Level
+ 2</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="heading_test_1_7.h4">
+ <phrase id="heading_test_1_7.level_3"/><link linkend="heading_test_1_7.level_3">Level
+ 3</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="heading_test_1_7.h5">
+ <phrase id="heading_test_1_7.level_4"/><link linkend="heading_test_1_7.level_4">Level
+ 4</link>
+ </bridgehead>
+ <bridgehead renderas="sect5" id="heading_test_1_7.h6">
+ <phrase id="heading_test_1_7.level_5"/><link linkend="heading_test_1_7.level_5">Level
+ 5</link>
+ </bridgehead>
+ <bridgehead renderas="sect6" id="heading_test_1_7.h8">
+ <phrase id="heading_test_1_7.level_6"/><link linkend="heading_test_1_7.level_6">Level
+ 6</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_7.h9">
+ <phrase id="heading_test_1_7.bold"/><link linkend="heading_test_1_7.bold"><emphasis
+ role="bold">Bold</emphasis></link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_7.h10">
+ <phrase id="heading_test_1_7.comment"/><link linkend="heading_test_1_7.comment">Comment</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_7.h11">
+ <phrase id="heading_test_1_7.anchor_anchor_heading"/><link linkend="heading_test_1_7.anchor_anchor_heading"><anchor
+ id="anchor"/>Anchor heading</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_7.h12">
+ <phrase id="heading_test_1_7.link_anchor_link_heading"/><link linkend="heading_test_1_7.link_anchor_link_heading"><link
+ linkend="anchor">Link heading</link></link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_7.h13">
+ <phrase id="heading_test_1_7.h1"/><link linkend="heading_test_1_7.h1">H1</link>
+ </bridgehead>
+ <section id="heading_test_1_7.s1">
+ <title><link linkend="heading_test_1_7.s1">S1</link></title>
+ <bridgehead renderas="sect3" id="heading_test_1_7.s1.h0">
+ <phrase id="heading_test_1_7.s1.h2"/><link linkend="heading_test_1_7.s1.h2">H2</link>
+ </bridgehead>
+ <section id="heading_test_1_7.s1.s2">
+ <title><link linkend="heading_test_1_7.s1.s2">S2</link></title>
+ <bridgehead renderas="sect3" id="heading_test_1_7.s1.s2.h0">
+ <phrase id="heading_test_1_7.s1.s2.h3"/><link linkend="heading_test_1_7.s1.s2.h3">H3</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect2" id="heading_test_1_7.s1.h1">
+ <phrase id="heading_test_1_7.s1.h4"/><link linkend="heading_test_1_7.s1.h4">H4</link>
+ </bridgehead>
+ <section id="heading_test_1_7.s1.s3">
+ <title><link linkend="heading_test_1_7.s1.s3">S3</link></title>
+ <bridgehead renderas="sect4" id="heading_test_1_7.s1.s3.h0">
+ <phrase id="heading_test_1_7.s1.s3.h5"/><link linkend="heading_test_1_7.s1.s3.h5">H5</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect2" id="heading_test_1_7.s1.h3">
+ <phrase id="heading_test_1_7.s1.h6"/><link linkend="heading_test_1_7.s1.h6">H6</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect1" id="heading_test_1_7.h14">
+ <phrase id="heading_test_1_7.h7"/><link linkend="heading_test_1_7.h7">H7</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_7.h15">
+ <phrase id="heading_test_1_7.a1"/><link linkend="heading_test_1_7.a1">H1</link>
+ </bridgehead>
+ <section id="heading_test_1_7.s1_0">
+ <title><link linkend="heading_test_1_7.s1_0">S1</link></title>
+ <bridgehead renderas="sect2" id="heading_test_1_7.s1_0.h0">
+ <phrase id="heading_test_1_7.s1_0.a2"/><link linkend="heading_test_1_7.s1_0.a2">H2</link>
+ </bridgehead>
+ <section id="heading_test_1_7.s1_0.s2">
+ <title><link linkend="heading_test_1_7.s1_0.s2">S2</link></title>
+ <bridgehead renderas="sect3" id="heading_test_1_7.s1_0.s2.h0">
+ <phrase id="heading_test_1_7.s1_0.s2.a3"/><link linkend="heading_test_1_7.s1_0.s2.a3">H3</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect2" id="heading_test_1_7.s1_0.h1">
+ <phrase id="heading_test_1_7.s1_0.a4"/><link linkend="heading_test_1_7.s1_0.a4">H4</link>
+ </bridgehead>
+ <section id="heading_test_1_7.s1_0.s3">
+ <title><link linkend="heading_test_1_7.s1_0.s3">S3</link></title>
+ <bridgehead renderas="sect3" id="heading_test_1_7.s1_0.s3.h0">
+ <phrase id="heading_test_1_7.s1_0.s3.a5"/><link linkend="heading_test_1_7.s1_0.s3.a5">H5</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect3" id="heading_test_1_7.s1_0.h2">
+ <phrase id="heading_test_1_7.s1_0.a6"/><link linkend="heading_test_1_7.s1_0.a6">H6</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect1" id="heading_test_1_7.h16">
+ <phrase id="heading_test_1_7.a7"/><link linkend="heading_test_1_7.a7">H7</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="heading_test_1_7.h17">
+ <phrase id="heading_test_1_7.abc-2"/><link linkend="heading_test_1_7.abc-2">Template
+ Id</link>
+ </bridgehead>
+</article>
diff --git a/tools/quickbook/test/heading-1_7.quickbook b/tools/quickbook/test/heading-1_7.quickbook
new file mode 100644
index 0000000000..47f878add2
--- /dev/null
+++ b/tools/quickbook/test/heading-1_7.quickbook
@@ -0,0 +1,83 @@
+[article Heading Test 1.7
+[quickbook 1.7]
+]
+
+[/ Basic headers ]
+
+[heading Generic header]
+[h1 Level 1]
+[h2 Level 2]
+[h3 Level 3]
+[h4 Level 4]
+[h5 Level 5]
+[h6 Level 6]
+
+[/ Test how heading ids are generated when different types of markup are present]
+
+[h1 *Bold*]
+[h1 [/]Comment[/]]
+
+[/ Test how ids are generated for headings containing things like anchors
+ and links ]
+
+[h1 [#anchor]Anchor heading]
+[h1 [link anchor Link heading]]
+
+[/ Test how heading ids are generated inside sections]
+
+[h1 H1]
+
+[section:s1 S1]
+
+[heading H2]
+
+[section:s2 S2]
+
+[h3 H3]
+
+[endsect]
+
+[h2 H4]
+
+[section:s3 S3]
+
+[heading H5]
+
+[endsect]
+
+[h2 H6]
+
+[endsect]
+
+[h1 H7]
+
+[/ Repeat with explicit ids]
+
+[h1:a1 H1]
+
+[section:s1 S1]
+
+[h2:a2 H2]
+
+[section:s2 S2]
+
+[h3:a3 H3]
+
+[endsect]
+
+[h2:a4 H4]
+
+[section:s3 S3]
+
+[h3:a5 H5]
+
+[endsect]
+
+[heading:a6 H6]
+
+[endsect]
+
+[h1:a7 H7]
+
+[template thing[] abc]
+[heading:[thing]-2 Template Id]
diff --git a/tools/quickbook/test/include-1_5.quickbook b/tools/quickbook/test/include-1_5.quickbook
index 849d19ceca..9720121925 100644
--- a/tools/quickbook/test/include-1_5.quickbook
+++ b/tools/quickbook/test/include-1_5.quickbook
@@ -3,15 +3,15 @@
[id include-test]
]
-[include include_sub-1_5.qbk]
-[include .\include_sub.qbk]
-[include:foo include_sub.qbk]
-[include empty.qbk]
+[include include-inc-1_5.quickbook]
+[include .\include-inc.quickbook]
+[include:foo include-inc.quickbook]
+[include empty-inc.quickbook]
[def __defined__]
-[? __undefined__ [include:foo1 include_sub.qbk] ]
-[? __undefined__ [include:foo1 not_a_file.qbk] ]
+[? __undefined__ [include:foo1 include-inc.quickbook] ]
+[? __undefined__ [include:foo1 not_a_file.quickbook] ]
[? __defined__
- Just trying including in a conditional macro. [include:foo2 include_sub.qbk]
+ Just trying including in a conditional macro. [include:foo2 include-inc.quickbook]
With some text around it.]
diff --git a/tools/quickbook/test/include-1_6.quickbook b/tools/quickbook/test/include-1_6.quickbook
index 00d6033e3b..29a7611926 100644
--- a/tools/quickbook/test/include-1_6.quickbook
+++ b/tools/quickbook/test/include-1_6.quickbook
@@ -3,13 +3,13 @@
[id include-test]
]
-[include include_sub.qbk]
-[include:foo include_sub.qbk]
+[include include-inc.quickbook]
+[include:foo include-inc.quickbook]
[def __defined__]
-[? __undefined__ [include:foo1 include_sub.qbk] ]
-[? __undefined__ [include:foo1 not-a-file.qbk] ]
+[? __undefined__ [include:foo1 include-inc.quickbook] ]
+[? __undefined__ [include:foo1 not-a-file.quickbook] ]
[? __defined__
- Just trying including in a conditional macro. [include:foo2 include_sub.qbk]
+ Just trying including in a conditional macro. [include:foo2 include-inc.quickbook]
With some text around it.]
diff --git a/tools/quickbook/test/include-1_7.gold b/tools/quickbook/test/include-1_7.gold
new file mode 100644
index 0000000000..206509bf20
--- /dev/null
+++ b/tools/quickbook/test/include-1_7.gold
@@ -0,0 +1,36 @@
+<?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="include-test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include Test</title>
+ <section id="include-test.test">
+ <title><link linkend="include-test.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <section id="foo.test">
+ <title><link linkend="foo.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <section id="foo0.test">
+ <title><link linkend="foo0.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <para>
+ Just trying including in a conditional macro.
+ </para>
+ <section id="foo2.test">
+ <title><link linkend="foo2.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <para>
+ With some text around it.
+ </para>
+</article>
diff --git a/tools/quickbook/test/include-1_7.quickbook b/tools/quickbook/test/include-1_7.quickbook
new file mode 100644
index 0000000000..481e4130ae
--- /dev/null
+++ b/tools/quickbook/test/include-1_7.quickbook
@@ -0,0 +1,18 @@
+[article Include Test
+ [quickbook 1.7]
+ [id include-test]
+]
+
+[include include-inc.quickbook]
+[include:foo include-inc.quickbook]
+
+[template id2[] include-inc]
+[include:foo0 [id2].quickbook]
+
+[def __defined__]
+
+[? __undefined__ [include:foo1 include-inc.quickbook] ]
+[? __undefined__ [include:foo1 not-a-file.quickbook] ]
+[? __defined__
+ Just trying including in a conditional macro. [include:foo2 include-inc.quickbook]
+ With some text around it.]
diff --git a/tools/quickbook/test/include_sub-1_5.qbk b/tools/quickbook/test/include-inc-1_5.quickbook
index 1dcbff9ff4..1dcbff9ff4 100644
--- a/tools/quickbook/test/include_sub-1_5.qbk
+++ b/tools/quickbook/test/include-inc-1_5.quickbook
diff --git a/tools/quickbook/test/include_sub.qbk b/tools/quickbook/test/include-inc.quickbook
index 1fa61608b8..1fa61608b8 100644
--- a/tools/quickbook/test/include_sub.qbk
+++ b/tools/quickbook/test/include-inc.quickbook
diff --git a/tools/quickbook/test/include/Jamfile.v2 b/tools/quickbook/test/include/Jamfile.v2
index 3ab39b201a..a40bf55430 100644
--- a/tools/quickbook/test/include/Jamfile.v2
+++ b/tools/quickbook/test/include/Jamfile.v2
@@ -6,7 +6,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
#
-project test/includes
+project quickbook/test/includes
: requirements
<toolset>msvc:<debug-symbols>off
;
@@ -16,7 +16,9 @@ import quickbook-testing : quickbook-test quickbook-error-test ;
test-suite quickbook.test :
[ quickbook-test import-basic-1.6 ]
[ quickbook-test filename ]
+ [ quickbook-test filename-1_7 ]
[ quickbook-test filename-path : : : <quickbook-test-include>sub ]
+ [ quickbook-test filename_path-1_7 : : : <quickbook-test-include>sub ]
[ quickbook-test doc-title1-1.5 ]
[ quickbook-test doc-title1a-1.5 ]
[ quickbook-test section ]
@@ -41,4 +43,6 @@ test-suite quickbook.test :
[ quickbook-test source_mode-1_6 ]
[ quickbook-test nested_compatibility-1_5 ]
[ quickbook-test nested_compatibility-1_6 ]
+ [ quickbook-test template_include-1_7 ]
+ [ quickbook-test glob-1_7 ]
;
diff --git a/tools/quickbook/test/include/compatibility-1_1.quickbook b/tools/quickbook/test/include/compatibility-1_1.quickbook
index ec5d62f55b..afdd39dc41 100644
--- a/tools/quickbook/test/include/compatibility-1_1.quickbook
+++ b/tools/quickbook/test/include/compatibility-1_1.quickbook
@@ -5,14 +5,14 @@
]
[section:collision Outer]
-[include compatibility-inc.qbk]
+[include compatibility-inc.quickbook]
[endsect]
[section:collision Include compatibility 1.1]
-[include compatibility-inc_1_1.qbk]
+[include compatibility-inc_1_1.quickbook]
[endsect]
[section:collision Include compatibility 1.5]
-[include compatibility-inc_1_5.qbk]
+[include compatibility-inc_1_5.quickbook]
[endsect]
[section:collision Include compatibility 1.6]
-[include compatibility-inc_1_6.qbk]
+[include compatibility-inc_1_6.quickbook]
[endsect]
diff --git a/tools/quickbook/test/include/compatibility-1_5.quickbook b/tools/quickbook/test/include/compatibility-1_5.quickbook
index c16ddac5e9..9593df720b 100644
--- a/tools/quickbook/test/include/compatibility-1_5.quickbook
+++ b/tools/quickbook/test/include/compatibility-1_5.quickbook
@@ -5,14 +5,14 @@
]
[section:collision Outer]
-[include compatibility-inc.qbk]
+[include compatibility-inc.quickbook]
[endsect]
[section:collision Include compatibility 1.1]
-[include compatibility-inc_1_1.qbk]
+[include compatibility-inc_1_1.quickbook]
[endsect]
[section:collision Include compatibility 1.5]
-[include compatibility-inc_1_5.qbk]
+[include compatibility-inc_1_5.quickbook]
[endsect]
[section:collision Include compatibility 1.6]
-[include compatibility-inc_1_6.qbk]
+[include compatibility-inc_1_6.quickbook]
[endsect]
diff --git a/tools/quickbook/test/include/compatibility-1_6.quickbook b/tools/quickbook/test/include/compatibility-1_6.quickbook
index 276674afca..46880a8c39 100644
--- a/tools/quickbook/test/include/compatibility-1_6.quickbook
+++ b/tools/quickbook/test/include/compatibility-1_6.quickbook
@@ -4,14 +4,14 @@
]
[section:collision Outer]
-[include compatibility-inc.qbk]
+[include compatibility-inc.quickbook]
[endsect]
[section:collision Include compatibility 1.1]
-[include compatibility-inc_1_1.qbk]
+[include compatibility-inc_1_1.quickbook]
[endsect]
[section:collision Include compatibility 1.5]
-[include compatibility-inc_1_5.qbk]
+[include compatibility-inc_1_5.quickbook]
[endsect]
[section:collision Include compatibility 1.6]
-[include compatibility-inc_1_6.qbk]
+[include compatibility-inc_1_6.quickbook]
[endsect]
diff --git a/tools/quickbook/test/include/compatibility-inc.qbk b/tools/quickbook/test/include/compatibility-inc.quickbook
index 66fbb54eee..66fbb54eee 100644
--- a/tools/quickbook/test/include/compatibility-inc.qbk
+++ b/tools/quickbook/test/include/compatibility-inc.quickbook
diff --git a/tools/quickbook/test/include/compatibility-inc_1_1.qbk b/tools/quickbook/test/include/compatibility-inc_1_1.quickbook
index 89b4d6554a..89b4d6554a 100644
--- a/tools/quickbook/test/include/compatibility-inc_1_1.qbk
+++ b/tools/quickbook/test/include/compatibility-inc_1_1.quickbook
diff --git a/tools/quickbook/test/include/compatibility-inc_1_5.qbk b/tools/quickbook/test/include/compatibility-inc_1_5.quickbook
index 5551da5b37..5551da5b37 100644
--- a/tools/quickbook/test/include/compatibility-inc_1_5.qbk
+++ b/tools/quickbook/test/include/compatibility-inc_1_5.quickbook
diff --git a/tools/quickbook/test/include/compatibility-inc_1_6.qbk b/tools/quickbook/test/include/compatibility-inc_1_6.quickbook
index 61f3c7bcd1..61f3c7bcd1 100644
--- a/tools/quickbook/test/include/compatibility-inc_1_6.qbk
+++ b/tools/quickbook/test/include/compatibility-inc_1_6.quickbook
diff --git a/tools/quickbook/test/include/filename-1_7.gold b/tools/quickbook/test/include/filename-1_7.gold
new file mode 100644
index 0000000000..935b426422
--- /dev/null
+++ b/tools/quickbook/test/include/filename-1_7.gold
@@ -0,0 +1,46 @@
+<?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="filename_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Filename Test</title>
+ <para>
+ filename-1_7.quickbook
+ </para>
+ <bridgehead renderas="sect2" id="filename_test.h0">
+ <phrase id="filename_test.test_1"/><link linkend="filename_test.test_1">Test
+ 1</link>
+ </bridgehead>
+ <para>
+ sub/filename_include1.quickbook
+ </para>
+ <para>
+ sub/../filename_include2.quickbook
+ </para>
+ <bridgehead renderas="sect2" id="filename_test.h1">
+ <phrase id="filename_test.test_2"/><link linkend="filename_test.test_2">Test
+ 2</link>
+ </bridgehead>
+ <para>
+ filename_include2.quickbook
+ </para>
+ <bridgehead renderas="sect2" id="filename_test.h2">
+ <phrase id="filename_test.test_3"/><link linkend="filename_test.test_3">Test
+ 3</link>
+ </bridgehead>
+ <para>
+ sub/filename_include1.quickbook
+ </para>
+ <para>
+ sub/../filename_include2.quickbook
+ </para>
+ <bridgehead renderas="sect2" id="filename_test.h3">
+ <phrase id="filename_test.test_4"/><link linkend="filename_test.test_4">Test
+ 4</link>
+ </bridgehead>
+ <para>
+ sub/filename_include1.quickbook
+ </para>
+ <para>
+ sub/../filename_include2.quickbook
+ </para>
+</article>
diff --git a/tools/quickbook/test/include/filename-1_7.quickbook b/tools/quickbook/test/include/filename-1_7.quickbook
new file mode 100644
index 0000000000..9d462af89f
--- /dev/null
+++ b/tools/quickbook/test/include/filename-1_7.quickbook
@@ -0,0 +1,21 @@
+[article Filename Test
+[quickbook 1.7]
+]
+
+__FILENAME__
+
+[heading Test 1]
+
+[include sub/*.quickbook]
+
+[heading Test 2]
+
+[include filename_include?.quickbook]
+
+[heading Test 3]
+
+[include su\[b\]/filename\\_include1.quickbook]
+
+[heading Test 4]
+
+[include su\\b/*.quickbook]
diff --git a/tools/quickbook/test/include/filename_path-1_7.gold b/tools/quickbook/test/include/filename_path-1_7.gold
new file mode 100644
index 0000000000..6f52dafc1d
--- /dev/null
+++ b/tools/quickbook/test/include/filename_path-1_7.gold
@@ -0,0 +1,18 @@
+<?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="filename_test_with_include_path" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Filename test with include path</title>
+ <para>
+ filename_path-1_7.quickbook
+ </para>
+ <para>
+ filename_include1.quickbook
+ </para>
+ <para>
+ ../filename_include2.quickbook
+ </para>
+ <para>
+ filename_include2.quickbook
+ </para>
+</article>
diff --git a/tools/quickbook/test/include/filename_path-1_7.quickbook b/tools/quickbook/test/include/filename_path-1_7.quickbook
new file mode 100644
index 0000000000..741d76ad57
--- /dev/null
+++ b/tools/quickbook/test/include/filename_path-1_7.quickbook
@@ -0,0 +1,7 @@
+[article Filename test with include path
+[quickbook 1.7]
+]
+
+__FILENAME__
+
+[include filename_include?.quickbook]
diff --git a/tools/quickbook/test/include/glob-1_7.gold b/tools/quickbook/test/include/glob-1_7.gold
new file mode 100644
index 0000000000..ba31ae9615
--- /dev/null
+++ b/tools/quickbook/test/include/glob-1_7.gold
@@ -0,0 +1,41 @@
+<?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="glob_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Glob Test</title>
+ <section id="glob_test.t1_0">
+ <title><link linkend="glob_test.t1_0">Test 1.0</link></title>
+ </section>
+ <section id="glob_test.t1_1">
+ <title><link linkend="glob_test.t1_1">Test 1.1</link></title>
+ <para>
+ A
+ </para>
+ </section>
+ <section id="glob_test.t1_2">
+ <title><link linkend="glob_test.t1_2">Test 1.2</link></title>
+ <para>
+ B
+ </para>
+ </section>
+ <section id="glob_test.t1_3">
+ <title><link linkend="glob_test.t1_3">Test 1.3</link></title>
+ <para>
+ B
+ </para>
+ </section>
+ <section id="glob_test.t2_1">
+ <title><link linkend="glob_test.t2_1">Test 2.1</link></title>
+ <para>
+ A
+ </para>
+ <para>
+ B
+ </para>
+ </section>
+ <section id="glob_test.t2_2">
+ <title><link linkend="glob_test.t2_2">Test 2.2</link></title>
+ <para>
+ B
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/glob-1_7.quickbook b/tools/quickbook/test/include/glob-1_7.quickbook
new file mode 100644
index 0000000000..826c12be81
--- /dev/null
+++ b/tools/quickbook/test/include/glob-1_7.quickbook
@@ -0,0 +1,39 @@
+[article Glob Test
+[quickbook 1.7]
+]
+
+[section:t1_0 Test 1.0]
+
+[include glob0/*]
+
+[endsect] [/t1_0]
+
+[section:t1_1 Test 1.1]
+
+[include glob1/*]
+
+[endsect] [/t1_1]
+
+[section:t1_2 Test 1.2]
+
+[include glob1/*/*]
+
+[endsect] [/t1_2]
+
+[section:t1_3 Test 1.3]
+
+[include glob1/*/b.qbk]
+
+[endsect] [/t1_3]
+
+[section:t2_1 Test 2.1]
+
+[include glob2/*]
+
+[endsect] [/t2_1]
+
+[section:t2_2 Test 2.2]
+
+[include glob2/*/*]
+
+[endsect] [/t2_2]
diff --git a/tools/quickbook/test/include/glob1/a.qbk b/tools/quickbook/test/include/glob1/a.qbk
new file mode 100644
index 0000000000..f70f10e4db
--- /dev/null
+++ b/tools/quickbook/test/include/glob1/a.qbk
@@ -0,0 +1 @@
+A
diff --git a/tools/quickbook/test/include/glob1/glob1-1/b.qbk b/tools/quickbook/test/include/glob1/glob1-1/b.qbk
new file mode 100644
index 0000000000..223b7836fb
--- /dev/null
+++ b/tools/quickbook/test/include/glob1/glob1-1/b.qbk
@@ -0,0 +1 @@
+B
diff --git a/tools/quickbook/test/include/glob2/a.qbk b/tools/quickbook/test/include/glob2/a.qbk
new file mode 100644
index 0000000000..1605808010
--- /dev/null
+++ b/tools/quickbook/test/include/glob2/a.qbk
@@ -0,0 +1,3 @@
+A
+
+[include */*.qbk]
diff --git a/tools/quickbook/test/include/glob2/glob2-1/b.qbk b/tools/quickbook/test/include/glob2/glob2-1/b.qbk
new file mode 100644
index 0000000000..223b7836fb
--- /dev/null
+++ b/tools/quickbook/test/include/glob2/glob2-1/b.qbk
@@ -0,0 +1 @@
+B
diff --git a/tools/quickbook/test/include/in_section-1_5.gold b/tools/quickbook/test/include/in_section-1_5.gold
index 1dfeaff908..3548e2c479 100644
--- a/tools/quickbook/test/include/in_section-1_5.gold
+++ b/tools/quickbook/test/include/in_section-1_5.gold
@@ -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>
diff --git a/tools/quickbook/test/include/in_section-1_5.quickbook b/tools/quickbook/test/include/in_section-1_5.quickbook
index 9cd15f61d9..28183096a0 100644
--- a/tools/quickbook/test/include/in_section-1_5.quickbook
+++ b/tools/quickbook/test/include/in_section-1_5.quickbook
@@ -3,14 +3,14 @@
]
[section:container Container]
-[include in_section-include1.qbk]
-[include in_section-include2.qbk]
+[include in_section-inc1.quickbook]
+[include in_section-inc2.quickbook]
[endsect]
-[include in_section-include1.qbk]
-[include in_section-include2.qbk]
+[include in_section-inc1.quickbook]
+[include in_section-inc2.quickbook]
[section:container2 Container2]
-[include in_section-include1.qbk]
-[include in_section-include2.qbk]
+[include in_section-inc1.quickbook]
+[include in_section-inc2.quickbook]
[endsect]
diff --git a/tools/quickbook/test/include/in_section-1_6.gold b/tools/quickbook/test/include/in_section-1_6.gold
index 7601df44f7..3ffa601709 100644
--- a/tools/quickbook/test/include/in_section-1_6.gold
+++ b/tools/quickbook/test/include/in_section-1_6.gold
@@ -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>
diff --git a/tools/quickbook/test/include/in_section-1_6.quickbook b/tools/quickbook/test/include/in_section-1_6.quickbook
index 45be4411b1..686f97ec4d 100644
--- a/tools/quickbook/test/include/in_section-1_6.quickbook
+++ b/tools/quickbook/test/include/in_section-1_6.quickbook
@@ -3,14 +3,14 @@
]
[section:container Container]
-[include in_section-include1.qbk]
-[include in_section-include2.qbk]
+[include in_section-inc1.quickbook]
+[include in_section-inc2.quickbook]
[endsect]
-[include in_section-include1.qbk]
-[include in_section-include2.qbk]
+[include in_section-inc1.quickbook]
+[include in_section-inc2.quickbook]
[section:container2 Container2]
-[include in_section-include1.qbk]
-[include in_section-include2.qbk]
+[include in_section-inc1.quickbook]
+[include in_section-inc2.quickbook]
[endsect]
diff --git a/tools/quickbook/test/include/in_section-include1.qbk b/tools/quickbook/test/include/in_section-inc1.quickbook
index f8fab4d12a..f74bf5dbd9 100644
--- a/tools/quickbook/test/include/in_section-include1.qbk
+++ b/tools/quickbook/test/include/in_section-inc1.quickbook
@@ -8,4 +8,6 @@
[h1 Test2]
-[endsect] \ No newline at end of file
+[include include-id-inc1.quickbook]
+
+[endsect]
diff --git a/tools/quickbook/test/include/in_section-include2.qbk b/tools/quickbook/test/include/in_section-inc2.quickbook
index 9d8ee51698..0a30aaa744 100644
--- a/tools/quickbook/test/include/in_section-include2.qbk
+++ b/tools/quickbook/test/include/in_section-inc2.quickbook
@@ -9,4 +9,6 @@
[h1 Test2]
-[endsect] \ No newline at end of file
+[include include-id-inc1.quickbook]
+
+[endsect]
diff --git a/tools/quickbook/test/include/include_id_unbalanced-1_6.quickbook b/tools/quickbook/test/include/include_id_unbalanced-1_6.quickbook
index 0b299a606b..b1568d4f9b 100644
--- a/tools/quickbook/test/include/include_id_unbalanced-1_6.quickbook
+++ b/tools/quickbook/test/include/include_id_unbalanced-1_6.quickbook
@@ -5,7 +5,7 @@
[/ Sections start in included files ]
-[include:include1 include_id_unbalanced-inc1.qbk]
+[include:include1 include_id_unbalanced-inc1.quickbook]
[heading:x1 X1]
[endsect]
[heading:x2 X2]
@@ -16,4 +16,4 @@
[heading:x1 X1]
[section:sect2 Section 2]
[heading:x2 X2]
-[include:include2 include_id_unbalanced-inc2.qbk]
+[include:include2 include_id_unbalanced-inc2.quickbook]
diff --git a/tools/quickbook/test/include/include_id_unbalanced-inc1.qbk b/tools/quickbook/test/include/include_id_unbalanced-inc1.quickbook
index 3170f2601d..d3214811a0 100644
--- a/tools/quickbook/test/include/include_id_unbalanced-inc1.qbk
+++ b/tools/quickbook/test/include/include_id_unbalanced-inc1.quickbook
@@ -1,4 +1,4 @@
[section:inc1 Include 1]
[heading:inc1_1 Heading 1]
-[include:include1a include_id_unbalanced-inc1a.qbk]
+[include:include1a include_id_unbalanced-inc1a.quickbook]
[heading:inc1_2 Heading 2]
diff --git a/tools/quickbook/test/include/include_id_unbalanced-inc1a.qbk b/tools/quickbook/test/include/include_id_unbalanced-inc1a.quickbook
index 1bc46b4f57..1bc46b4f57 100644
--- a/tools/quickbook/test/include/include_id_unbalanced-inc1a.qbk
+++ b/tools/quickbook/test/include/include_id_unbalanced-inc1a.quickbook
diff --git a/tools/quickbook/test/include/include_id_unbalanced-inc2.qbk b/tools/quickbook/test/include/include_id_unbalanced-inc2.quickbook
index b71932423a..37c313cae0 100644
--- a/tools/quickbook/test/include/include_id_unbalanced-inc2.qbk
+++ b/tools/quickbook/test/include/include_id_unbalanced-inc2.quickbook
@@ -1,5 +1,5 @@
[heading:inc2_1 Heading 1]
[endsect]
[heading:inc2_2 Heading 2]
-[include:include2a include_id_unbalanced-inc2a.qbk]
+[include:include2a include_id_unbalanced-inc2a.quickbook]
[heading:inc2_3 Heading 3]
diff --git a/tools/quickbook/test/include/include_id_unbalanced-inc2a.qbk b/tools/quickbook/test/include/include_id_unbalanced-inc2a.quickbook
index 780fb40572..780fb40572 100644
--- a/tools/quickbook/test/include/include_id_unbalanced-inc2a.qbk
+++ b/tools/quickbook/test/include/include_id_unbalanced-inc2a.quickbook
diff --git a/tools/quickbook/test/include/nested_compatibility-1_5.quickbook b/tools/quickbook/test/include/nested_compatibility-1_5.quickbook
index 8276715faf..f9d78b1e46 100644
--- a/tools/quickbook/test/include/nested_compatibility-1_5.quickbook
+++ b/tools/quickbook/test/include/nested_compatibility-1_5.quickbook
@@ -2,11 +2,11 @@
[article Nested Compatibility Test]
[section Duplicate Name]
-[include nested_compatibility_inc-1_5.qbk]
-[include nested_compatibility_inc-1_6.qbk]
+[include nested_compatibility-inc-1_5.quickbook]
+[include nested_compatibility-inc-1_6.quickbook]
[endsect]
[section Duplicate Name]
-[include nested_compatibility_inc-1_5.qbk]
-[include nested_compatibility_inc-1_6.qbk]
+[include nested_compatibility-inc-1_5.quickbook]
+[include nested_compatibility-inc-1_6.quickbook]
[endsect]
diff --git a/tools/quickbook/test/include/nested_compatibility-1_6.quickbook b/tools/quickbook/test/include/nested_compatibility-1_6.quickbook
index 72c4b65512..8beeb8a064 100644
--- a/tools/quickbook/test/include/nested_compatibility-1_6.quickbook
+++ b/tools/quickbook/test/include/nested_compatibility-1_6.quickbook
@@ -2,11 +2,11 @@
[article Nested Compatibility Test]
[section Duplicate Name]
-[include nested_compatibility_inc-1_5.qbk]
-[include nested_compatibility_inc-1_6.qbk]
+[include nested_compatibility-inc-1_5.quickbook]
+[include nested_compatibility-inc-1_6.quickbook]
[endsect]
[section Duplicate Name]
-[include nested_compatibility_inc-1_5.qbk]
-[include nested_compatibility_inc-1_6.qbk]
+[include nested_compatibility-inc-1_5.quickbook]
+[include nested_compatibility-inc-1_6.quickbook]
[endsect]
diff --git a/tools/quickbook/test/include/nested_compatibility_inc-1_5.qbk b/tools/quickbook/test/include/nested_compatibility-inc-1_5.quickbook
index 3c79855a49..3c79855a49 100644
--- a/tools/quickbook/test/include/nested_compatibility_inc-1_5.qbk
+++ b/tools/quickbook/test/include/nested_compatibility-inc-1_5.quickbook
diff --git a/tools/quickbook/test/include/nested_compatibility_inc-1_6.qbk b/tools/quickbook/test/include/nested_compatibility-inc-1_6.quickbook
index d0790840cd..d0790840cd 100644
--- a/tools/quickbook/test/include/nested_compatibility_inc-1_6.qbk
+++ b/tools/quickbook/test/include/nested_compatibility-inc-1_6.quickbook
diff --git a/tools/quickbook/test/include/source_mode-1_5.gold b/tools/quickbook/test/include/source_mode-1_5.gold
index 4fbee6f63a..2ed6b7fee3 100644
--- a/tools/quickbook/test/include/source_mode-1_5.gold
+++ b/tools/quickbook/test/include/source_mode-1_5.gold
@@ -4,4 +4,6 @@
xmlns:xi="http://www.w3.org/2001/XInclude">
<title>Souce Mode Include</title>
<programlisting>void main() {}</programlisting>
+<programlisting>void main() {}
+</programlisting>
</article>
diff --git a/tools/quickbook/test/include/source_mode-1_5.quickbook b/tools/quickbook/test/include/source_mode-1_5.quickbook
index 24e52a01b9..d5df05bd4b 100644
--- a/tools/quickbook/test/include/source_mode-1_5.quickbook
+++ b/tools/quickbook/test/include/source_mode-1_5.quickbook
@@ -1,3 +1,4 @@
[article Souce Mode Include [source-mode teletype][quickbook 1.5]]
-[include source_mode-inc1.qbk] \ No newline at end of file
+[include source_mode-inc1.quickbook]
+[include source_mode-inc2.quickbook]
diff --git a/tools/quickbook/test/include/source_mode-1_6.gold b/tools/quickbook/test/include/source_mode-1_6.gold
index 6d20203e66..aa01d20575 100644
--- a/tools/quickbook/test/include/source_mode-1_6.gold
+++ b/tools/quickbook/test/include/source_mode-1_6.gold
@@ -8,4 +8,6 @@
<title>Source include with no source-mode</title>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
</article>
+<programlisting>void main() {}
+</programlisting>
</article>
diff --git a/tools/quickbook/test/include/source_mode-1_6.quickbook b/tools/quickbook/test/include/source_mode-1_6.quickbook
index 9eb81d9401..fc4243f3b1 100644
--- a/tools/quickbook/test/include/source_mode-1_6.quickbook
+++ b/tools/quickbook/test/include/source_mode-1_6.quickbook
@@ -1,4 +1,5 @@
[source-mode teletype][quickbook 1.6]
[article Souce Mode Include]
-[include source_mode-inc1.qbk] \ No newline at end of file
+[include source_mode-inc1.quickbook]
+[include source_mode-inc2.quickbook]
diff --git a/tools/quickbook/test/include/source_mode-inc1.qbk b/tools/quickbook/test/include/source_mode-inc1.quickbook
index 3cefbe6bc7..3cefbe6bc7 100644
--- a/tools/quickbook/test/include/source_mode-inc1.qbk
+++ b/tools/quickbook/test/include/source_mode-inc1.quickbook
diff --git a/tools/quickbook/test/include/source_mode-inc2.quickbook b/tools/quickbook/test/include/source_mode-inc2.quickbook
new file mode 100644
index 0000000000..81dba8a17d
--- /dev/null
+++ b/tools/quickbook/test/include/source_mode-inc2.quickbook
@@ -0,0 +1,3 @@
+[/ Source include with no source-mode, and no docinfo.]
+
+ void main() {}
diff --git a/tools/quickbook/test/include/template_include-1_7.gold b/tools/quickbook/test/include/template_include-1_7.gold
new file mode 100644
index 0000000000..163ff30eea
--- /dev/null
+++ b/tools/quickbook/test/include/template_include-1_7.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="template_include_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Template include test</title>
+ <bridgehead renderas="sect2" id="template_include_test.h0">
+ <phrase id="template_include_test.simple_include"/><link linkend="template_include_test.simple_include">Simple
+ include</link>
+ </bridgehead>
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
+</programlisting>
+</article>
diff --git a/tools/quickbook/test/include/template_include-1_7.quickbook b/tools/quickbook/test/include/template_include-1_7.quickbook
new file mode 100644
index 0000000000..19f58fab04
--- /dev/null
+++ b/tools/quickbook/test/include/template_include-1_7.quickbook
@@ -0,0 +1,8 @@
+[article Template include test
+[quickbook 1.7]
+]
+
+[template include_foo[name] [include [name].quickbook]]
+
+[include_foo include-id-inc1]
+[include_foo source_mode-inc2]
diff --git a/tools/quickbook/test/include2-1_6.quickbook b/tools/quickbook/test/include2-1_6.quickbook
index be78fcc7fd..66b4897ef5 100644
--- a/tools/quickbook/test/include2-1_6.quickbook
+++ b/tools/quickbook/test/include2-1_6.quickbook
@@ -3,6 +3,6 @@
[id include-test]
]
-[include include_sub-1_5.qbk]
-[include include_sub.qbk]
-[include:foo include_sub.qbk]
+[include include-inc-1_5.quickbook]
+[include include-inc.quickbook]
+[include:foo include-inc.quickbook]
diff --git a/tools/quickbook/test/include_invalid_path1-1_7-fail.quickbook b/tools/quickbook/test/include_invalid_path1-1_7-fail.quickbook
new file mode 100644
index 0000000000..fa7e8e3379
--- /dev/null
+++ b/tools/quickbook/test/include_invalid_path1-1_7-fail.quickbook
@@ -0,0 +1,5 @@
+[article Include invalid path fail
+[quickbook 1.7]
+]
+
+[include .\\\/empty-inc.quickbook]
diff --git a/tools/quickbook/test/include_invalid_path2-1_7-fail.quickbook b/tools/quickbook/test/include_invalid_path2-1_7-fail.quickbook
new file mode 100644
index 0000000000..4f26728403
--- /dev/null
+++ b/tools/quickbook/test/include_invalid_path2-1_7-fail.quickbook
@@ -0,0 +1,5 @@
+[article Include invalid path fail
+[quickbook 1.7]
+]
+
+[include .\\\\empty-inc.quickbook]
diff --git a/tools/quickbook/test/include_invalid_path3-1_7-fail.quickbook b/tools/quickbook/test/include_invalid_path3-1_7-fail.quickbook
new file mode 100644
index 0000000000..5c99c1143b
--- /dev/null
+++ b/tools/quickbook/test/include_invalid_path3-1_7-fail.quickbook
@@ -0,0 +1,5 @@
+[article Include invalid path fail
+[quickbook 1.7]
+]
+
+[include empty\[-/\]inc.quickbook]
diff --git a/tools/quickbook/test/include_unicode_glob-1_7-fail.quickbook b/tools/quickbook/test/include_unicode_glob-1_7-fail.quickbook
new file mode 100644
index 0000000000..79a9df667a
--- /dev/null
+++ b/tools/quickbook/test/include_unicode_glob-1_7-fail.quickbook
@@ -0,0 +1,5 @@
+[article Unicode glob
+[quickbook 1.7]
+]
+
+[include £*.quickbook]
diff --git a/tools/quickbook/test/include_win_path-1_6-fail.quickbook b/tools/quickbook/test/include_win_path-1_6-fail.quickbook
index 2e25423fd1..aff5fd2c30 100644
--- a/tools/quickbook/test/include_win_path-1_6-fail.quickbook
+++ b/tools/quickbook/test/include_win_path-1_6-fail.quickbook
@@ -2,4 +2,4 @@
[quickbook 1.6]
]
-[include .\empty.qbk]
+[include .\empty-inc.quickbook]
diff --git a/tools/quickbook/test/link-1_1.gold b/tools/quickbook/test/link-1_1.gold
index 70fd440f1e..955fdec767 100644
--- a/tools/quickbook/test/link-1_1.gold
+++ b/tools/quickbook/test/link-1_1.gold
@@ -31,4 +31,15 @@
as well.
</para>
</section>
+ <section id="link_tests.escaping_links">
+ <title>Escaping links</title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ <ulink url="http://svn.boost.org/trac/boost/query?status=closed&amp;milestone=Boost+1.34.1">Boost
+ Trac</ulink>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
</article>
diff --git a/tools/quickbook/test/link-1_1.quickbook b/tools/quickbook/test/link-1_1.quickbook
index 2ddb0bf218..a22ce70f08 100644
--- a/tools/quickbook/test/link-1_1.quickbook
+++ b/tools/quickbook/test/link-1_1.quickbook
@@ -39,3 +39,10 @@ whitespace when they appear together as in [link x] [link y]. Also in [link x]
as well.
[endsect]
+
+[section Escaping links]
+
+* [@http://svn.boost.org/trac/boost/query?status=closed&milestone=Boost+1.34.1
+ Boost Trac]
+
+[endsect]
diff --git a/tools/quickbook/test/link-1_6.gold b/tools/quickbook/test/link-1_6.gold
index 05af56162a..587b67be37 100644
--- a/tools/quickbook/test/link-1_6.gold
+++ b/tools/quickbook/test/link-1_6.gold
@@ -35,4 +35,15 @@
as well.
</para>
</section>
+ <section id="link_tests.escaping_links">
+ <title><link linkend="link_tests.escaping_links">Escaping links</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ <ulink url="http://svn.boost.org/trac/boost/query?status=closed&amp;milestone=Boost+1.34.1">Boost
+ Trac</ulink>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
</article>
diff --git a/tools/quickbook/test/link-1_6.quickbook b/tools/quickbook/test/link-1_6.quickbook
index 28e99dbfd0..c874a79c65 100644
--- a/tools/quickbook/test/link-1_6.quickbook
+++ b/tools/quickbook/test/link-1_6.quickbook
@@ -43,3 +43,10 @@ whitespace when they appear together as in [link x] [link y]. Also in [link x]
as well.
[endsect]
+
+[section Escaping links]
+
+* [@http://svn.boost.org/trac/boost/query?status=closed&milestone=Boost+1.34.1
+ Boost Trac]
+
+[endsect]
diff --git a/tools/quickbook/test/link-1_7-fail.quickbook b/tools/quickbook/test/link-1_7-fail.quickbook
new file mode 100644
index 0000000000..9f2db1fb1f
--- /dev/null
+++ b/tools/quickbook/test/link-1_7-fail.quickbook
@@ -0,0 +1,5 @@
+[article Link fail test
+[quickbook 1.7]
+]
+
+[link something [table]]
diff --git a/tools/quickbook/test/link-1_7-fail2.quickbook b/tools/quickbook/test/link-1_7-fail2.quickbook
new file mode 100644
index 0000000000..30ac49570b
--- /dev/null
+++ b/tools/quickbook/test/link-1_7-fail2.quickbook
@@ -0,0 +1,6 @@
+[article Link fail test
+[quickbook 1.7]
+]
+
+[/ Escapes aren't allowed in links.]
+[link '''escaped stuff''']
diff --git a/tools/quickbook/test/link-1_7.gold b/tools/quickbook/test/link-1_7.gold
index f3eec12e74..c2e5f0398d 100644
--- a/tools/quickbook/test/link-1_7.gold
+++ b/tools/quickbook/test/link-1_7.gold
@@ -21,9 +21,6 @@
<para>
<link linkend="link">description</link>
</para>
- <para>
- <link linkend="link[Hello]">description</link>
- </para>
</section>
<section id="link_tests.side_by_side_links">
<title><link linkend="link_tests.side_by_side_links">Side-by-side links</link></title>
@@ -40,5 +37,20 @@
<para>
<link linkend="blah.x2">Templated link?</link>
</para>
+ <para>
+ <link linkend="something-one-two">something-one-two</link> <link linkend="something-one-two">something-one-two</link>
+ <link linkend="something-one-two">something-one-two</link>
+ </para>
+ </section>
+ <section id="link_tests.escaping_links">
+ <title><link linkend="link_tests.escaping_links">Escaping links</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ <ulink url="http://svn.boost.org/trac/boost/query?status=closed&amp;milestone=Boost+1.34.1">Boost
+ Trac</ulink>
+ </simpara>
+ </listitem>
+ </itemizedlist>
</section>
</article>
diff --git a/tools/quickbook/test/link-1_7.quickbook b/tools/quickbook/test/link-1_7.quickbook
index 8e146b9706..acfba31889 100644
--- a/tools/quickbook/test/link-1_7.quickbook
+++ b/tools/quickbook/test/link-1_7.quickbook
@@ -28,9 +28,6 @@
[link link[/ comment]description]
-[link link\[Hello\] description]
-
-
[endsect]
[section Side-by-side links]
@@ -49,4 +46,16 @@ as well.
[template thing[]x]
[link blah.[thing]2 Templated link?]
+[template link_in_template[x y] [link something-[x]-[y]]]
+[link_in_template one two]
+[link_in_template one..two]
+[link_in_template one .. two ]
+
+[endsect]
+
+[section Escaping links]
+
+* [@http://svn.boost.org/trac/boost/query?status=closed&milestone=Boost+1.34.1
+ Boost Trac]
+
[endsect]
diff --git a/tools/quickbook/test/list_test-1_6-fail.quickbook b/tools/quickbook/test/list_test-1_6-fail.quickbook
new file mode 100644
index 0000000000..7ca8a93993
--- /dev/null
+++ b/tools/quickbook/test/list_test-1_6-fail.quickbook
@@ -0,0 +1,46 @@
+[article List Test
+[quickbook 1.6]
+]
+
+Markup in list:
+
+* [table [[Heading]][[Cell]]]
+* [heading The heading for a list item]
+
+ The content of the list item.
+
+[section Paragraphs in list items]
+
+* A1
+
+ A2
+
+* B1
+ * C1
+
+ C2
+
+ B2
+
+* D1
+ * E1
+
+ E2
+
+ E3
+
+ D2
+
+[endsect]
+
+[section Indented code blocks in lists]
+
+* A
+
+ B
+ C
+* D
+
+ E
+* F
+[endsect]
diff --git a/tools/quickbook/test/list_test-1_6.gold b/tools/quickbook/test/list_test-1_6.gold
index f0055257ab..b6d3775a68 100644
--- a/tools/quickbook/test/list_test-1_6.gold
+++ b/tools/quickbook/test/list_test-1_6.gold
@@ -310,40 +310,51 @@
</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>
<listitem>
<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>
+ [section Doesn't expand] Blah, blah. [endsect]
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Paragraph cheat 1.
+ </simpara>
+ <simpara>
+ Paragraph cheat 2.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Paragraph cheat 3.
+ </simpara>
+ <simpara>
+ Paragraph cheat 4.
</simpara>
</listitem>
</itemizedlist>
@@ -426,99 +437,12 @@
<itemizedlist>
<listitem>
<simpara>
- One
- </simpara>
- </listitem>
- </itemizedlist>
- <section id="list_test.list_immediately_following_mark0.nested_section">
- <title><link linkend="list_test.list_immediately_following_mark0.nested_section">Nested
- section</link></title>
- <itemizedlist>
- <listitem>
- <simpara>
- Two
- </simpara>
- </listitem>
- </itemizedlist>
- </section>
- </section>
- <section id="list_test.paragraphs_in_list_items">
- <title><link linkend="list_test.paragraphs_in_list_items">Paragraphs in list
- items</link></title>
- <itemizedlist>
- <listitem>
- <simpara>
- A1
- <para>
- A2
- </para>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- B1
- <itemizedlist>
- <listitem>
- <simpara>
- C1
- <para>
- C2
- </para>
- </simpara>
- </listitem>
- </itemizedlist>
- <para>
- B2
- </para>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- D1
- <itemizedlist>
- <listitem>
- <simpara>
- E1
- <para>
- E2
- </para>
- <para>
- E3
- </para>
- </simpara>
- </listitem>
- </itemizedlist>
- <para>
- D2
- </para>
- </simpara>
- </listitem>
- </itemizedlist>
- </section>
- <section id="list_test.indented_code_blocks_in_lists">
- <title><link linkend="list_test.indented_code_blocks_in_lists">Indented code
- blocks in lists</link></title>
- <itemizedlist>
- <listitem>
- <simpara>
- A
-<programlisting><phrase role="identifier">B</phrase>
-</programlisting>
- <para>
- C
- </para>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- D
-<programlisting><phrase role="identifier">E</phrase>
-</programlisting>
+ One [section Nested section]
</simpara>
</listitem>
<listitem>
<simpara>
- F
+ Two [endsect]
</simpara>
</listitem>
</itemizedlist>
diff --git a/tools/quickbook/test/list_test-1_6.quickbook b/tools/quickbook/test/list_test-1_6.quickbook
index dbba74258e..fe1e187568 100644
--- a/tools/quickbook/test/list_test-1_6.quickbook
+++ b/tools/quickbook/test/list_test-1_6.quickbook
@@ -74,9 +74,17 @@ Markup in list:
* ["Quoted]
* [footnote Footnote]
* [table [[Heading]][[Cell]]]
-* [heading The heading for a list item]
-
- The content of the list item.
+ Some text.
+* [section Doesn't expand]
+ Blah, blah.
+ [endsect]
+
+* Paragraph cheat 1.
+ [block]
+ Paragraph cheat 2.
+* Paragraph cheat 3.
+ [block]
+ Paragraph cheat 4.
Don't end list with comment 1:
@@ -108,40 +116,5 @@ Don't end list with comment 2:
[section Nested section]
* Two
[endsect]
-[endsect]
-
-[section Paragraphs in list items]
-
-* A1
-
- A2
-
-* B1
- * C1
-
- C2
-
- B2
-
-* D1
- * E1
-
- E2
-
- E3
-
- D2
-
-[endsect]
-
-[section Indented code blocks in lists]
-
-* A
-
- B
- C
-* D
- E
-* F
[endsect]
diff --git a/tools/quickbook/test/list_test-1_7-fail1.quickbook b/tools/quickbook/test/list_test-1_7-fail1.quickbook
new file mode 100644
index 0000000000..c8beed1c5c
--- /dev/null
+++ b/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]
diff --git a/tools/quickbook/test/list_test-1_7.gold b/tools/quickbook/test/list_test-1_7.gold
new file mode 100644
index 0000000000..dec074c74b
--- /dev/null
+++ b/tools/quickbook/test/list_test-1_7.gold
@@ -0,0 +1,479 @@
+<?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="list_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>List Test</title>
+ <para>
+ Simple list:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Simple list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Two level list:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Two level list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Three level list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ D
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ E
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ F
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ G
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ H
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Three level list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <orderedlist>
+ <listitem>
+ <simpara>
+ C
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ D
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ G
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ H
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Inconsistent Indentation:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ B1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B2
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ C2
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B3
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B4
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B5
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B6
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Markup in list:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ <emphasis role="bold">Bold</emphasis>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <emphasis role="bold">Bold</emphasis>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <quote>Quoted</quote>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <footnote id="list_test.f0">
+ <para>
+ Footnote
+ </para>
+ </footnote>
+ </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>
+ </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>
+ The content of the list item.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Don't end list with comment 1:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A3
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A4
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Don't end list with comment 2:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ B1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <section id="list_test.paragraphs_in_list_items">
+ <title><link linkend="list_test.paragraphs_in_list_items">Paragraphs in list
+ items</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ </simpara>
+ <simpara>
+ A2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C1
+ </simpara>
+ <simpara>
+ C2
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ <simpara>
+ B2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ D1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ E1
+ </simpara>
+ <simpara>
+ E2
+ </simpara>
+ <simpara>
+ E3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ <simpara>
+ D2
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="list_test.indented_code_blocks_in_lists">
+ <title><link linkend="list_test.indented_code_blocks_in_lists">Indented code
+ blocks in lists</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+<programlisting><phrase role="identifier">B</phrase>
+</programlisting>
+ <simpara>
+ C
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ D
+ </simpara>
+<programlisting><phrase role="identifier">E</phrase>
+</programlisting>
+ </listitem>
+ <listitem>
+ <simpara>
+ F
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+</article>
diff --git a/tools/quickbook/test/list_test-1_7.quickbook b/tools/quickbook/test/list_test-1_7.quickbook
new file mode 100644
index 0000000000..8eac6a7182
--- /dev/null
+++ b/tools/quickbook/test/list_test-1_7.quickbook
@@ -0,0 +1,134 @@
+[article List Test
+[quickbook 1.7]
+]
+
+Simple list:
+
+* A
+* B
+
+Simple list:
+
+#A
+#B
+
+Two level list:
+
+* A
+ * A
+ * B
+* B
+ * A
+ * B
+
+Two level list:
+
+# A
+ * A
+ * B
+# B
+ * A
+ * B
+
+Three level list:
+
+# A
+ * A
+ * B
+ * C
+ * D
+ * E
+ * F
+ * G
+ * H
+
+Three level list:
+
+# A
+ * A
+ * B
+ # C
+ # D
+# G
+# H
+
+Inconsistent Indentation:
+
+* A1
+ * B1
+ * B2
+ * C1
+ * C2
+ * B3
+ * B4
+ * B5
+ * C3
+ * B6
+ * A2
+* A3
+
+Markup in list:
+
+* *Bold*
+* [*Bold]
+* ["Quoted]
+* [footnote Footnote]
+* [table [[Heading]][[Cell]]]
+* [heading The heading for a list item]
+
+ The content of the list item.
+
+Don't end list with comment 1:
+
+* A1
+* A2
+
+[/ End list?]
+* A3
+* A4
+
+Don't end list with comment 2:
+
+* A1
+ * B1
+
+[/ End list?]
+ * B2
+ * B3
+
+[section Paragraphs in list items]
+
+* A1
+
+ A2
+
+* B1
+ * C1
+
+ C2
+
+ B2
+
+* D1
+ * E1
+
+ E2
+
+ E3
+
+ D2
+
+[endsect]
+
+[section Indented code blocks in lists]
+
+* A
+
+ B
+ C
+* D
+
+ E
+* F
+
+[endsect]
diff --git a/tools/quickbook/test/mismatched_brackets3-1_1.gold b/tools/quickbook/test/mismatched_brackets3-1_1.gold
new file mode 100644
index 0000000000..a7ab11e833
--- /dev/null
+++ b/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>
diff --git a/tools/quickbook/test/mismatched_brackets3-1_1.quickbook b/tools/quickbook/test/mismatched_brackets3-1_1.quickbook
new file mode 100644
index 0000000000..dadd42692a
--- /dev/null
+++ b/tools/quickbook/test/mismatched_brackets3-1_1.quickbook
@@ -0,0 +1,6 @@
+[article Mismatched brackets]
+
+[section Something]
+
+[endsect]
+]
diff --git a/tools/quickbook/test/python/include_glob.qbk b/tools/quickbook/test/python/include_glob.qbk
new file mode 100644
index 0000000000..6e1f5248a4
--- /dev/null
+++ b/tools/quickbook/test/python/include_glob.qbk
@@ -0,0 +1,11 @@
+[/
+ 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)
+]
+
+[quickbook 1.7]
+[article Include Path]
+[include ?.qbk]
diff --git a/tools/quickbook/test/python/include_glob_deps.txt b/tools/quickbook/test/python/include_glob_deps.txt
new file mode 100644
index 0000000000..82fb66e68e
--- /dev/null
+++ b/tools/quickbook/test/python/include_glob_deps.txt
@@ -0,0 +1,6 @@
+# Copyright 2012-2013 Daniel James
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+include_glob.qbk
+sub1/a.qbk
+sub2/b.qbk
diff --git a/tools/quickbook/test/python/include_glob_locs.txt b/tools/quickbook/test/python/include_glob_locs.txt
new file mode 100644
index 0000000000..ccab607e02
--- /dev/null
+++ b/tools/quickbook/test/python/include_glob_locs.txt
@@ -0,0 +1,9 @@
+# Copyright 2012-2013 Daniel James
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
++ include_glob.qbk
+g ?.qbk
+g sub1/?.qbk
++ sub1/a.qbk
+g sub2/?.qbk
++ sub2/b.qbk
diff --git a/tools/quickbook/test/python/include_path.qbk b/tools/quickbook/test/python/include_path.qbk
index c9a4dcd981..3af3b37043 100644
--- a/tools/quickbook/test/python/include_path.qbk
+++ b/tools/quickbook/test/python/include_path.qbk
@@ -1,3 +1,11 @@
+[/
+ 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)
+]
+
[quickbook 1.5]
[article Include Path]
[include a.qbk]
diff --git a/tools/quickbook/test/python/include_path_deps.txt b/tools/quickbook/test/python/include_path_deps.txt
index 994d776ee6..86875d79be 100644
--- a/tools/quickbook/test/python/include_path_deps.txt
+++ b/tools/quickbook/test/python/include_path_deps.txt
@@ -1,3 +1,6 @@
+# Copyright 2012-2013 Daniel James
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
include_path.qbk
sub1/a.qbk
sub2/b.qbk
diff --git a/tools/quickbook/test/python/include_path_locs.txt b/tools/quickbook/test/python/include_path_locs.txt
index aaffb8d13f..7926db6156 100644
--- a/tools/quickbook/test/python/include_path_locs.txt
+++ b/tools/quickbook/test/python/include_path_locs.txt
@@ -1,3 +1,6 @@
+# Copyright 2012-2013 Daniel James
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ include_path.qbk
- a.qbk
+ sub1/a.qbk
diff --git a/tools/quickbook/test/python/missing_relative.qbk b/tools/quickbook/test/python/missing_relative.qbk
index 8fdc0ee049..ff96b10881 100644
--- a/tools/quickbook/test/python/missing_relative.qbk
+++ b/tools/quickbook/test/python/missing_relative.qbk
@@ -1,3 +1,11 @@
+[/
+ 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)
+]
+
[quickbook 1.5]
[article Missing Relative]
diff --git a/tools/quickbook/test/python/missing_relative_deps.txt b/tools/quickbook/test/python/missing_relative_deps.txt
index a9de670365..fb8f27fee3 100644
--- a/tools/quickbook/test/python/missing_relative_deps.txt
+++ b/tools/quickbook/test/python/missing_relative_deps.txt
@@ -1 +1,4 @@
+# Copyright 2012-2013 Daniel James
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
missing_relative.qbk
diff --git a/tools/quickbook/test/python/missing_relative_locs.txt b/tools/quickbook/test/python/missing_relative_locs.txt
index 69b51f28f4..ac85cec10f 100644
--- a/tools/quickbook/test/python/missing_relative_locs.txt
+++ b/tools/quickbook/test/python/missing_relative_locs.txt
@@ -1,3 +1,6 @@
+# Copyright 2012-2013 Daniel James
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ missing_relative.qbk
- ../missing.qbk
- missing-dir/x.qbk
diff --git a/tools/quickbook/test/python/output-deps.py b/tools/quickbook/test/python/output-deps.py
index 7b77c27d84..875a808db9 100644
--- a/tools/quickbook/test/python/output-deps.py
+++ b/tools/quickbook/test/python/output-deps.py
@@ -1,5 +1,9 @@
#!/usr/bin/env python
+# Copyright 2012-2013 Daniel James
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
import sys, os, subprocess, tempfile, re
def main(args, directory):
@@ -20,6 +24,10 @@ def main(args, directory):
deps_gold = 'include_path_deps.txt',
locations_gold = 'include_path_locs.txt',
input_path = ['sub1', 'sub2'])
+ failures += run_quickbook(quickbook_command, 'include_glob.qbk',
+ deps_gold = 'include_glob_deps.txt',
+ locations_gold = 'include_glob_locs.txt',
+ input_path = ['sub1', 'sub2'])
if failures == 0:
print "Success"
@@ -110,6 +118,7 @@ def load_dependencies(filename, adjust_paths = False):
dependencies = set()
f = open(filename, 'r')
for path in f:
+ if path[0] == '#': continue
if adjust_paths:
path = os.path.realpath(path)
if path in dependencies:
@@ -118,21 +127,34 @@ def load_dependencies(filename, adjust_paths = False):
return dependencies
def load_locations(filename, adjust_paths = False):
- line_matcher = re.compile("^([+-]) (.*)$")
+ line_matcher = re.compile("^([+-g]) (.*)$")
dependencies = {}
f = open(filename, 'r')
+ glob = None
+ globs = {}
for line in f:
+ if line[0] == '#': continue
m = line_matcher.match(line)
- if not m:
- raise Exception("Invalid dependency file: %1s" % filename)
- found = m.group(1) == '+'
+
path = m.group(2)
if adjust_paths:
path = os.path.realpath(path)
- if path in dependencies:
- raise Exception("Duplicate path (%1s) in %2s" % (path, filename))
- dependencies[path] = found
- return dependencies
+
+ if not m:
+ raise Exception("Invalid dependency file: %1s" % filename)
+ if m.group(1) == 'g':
+ globs[path] = []
+ glob = path
+ elif glob:
+ if m.group(1) != '+':
+ raise Exception("Negative match in glob.")
+ globs[glob].append(path)
+ else:
+ found = m.group(1) == '+'
+ if path in dependencies:
+ raise Exception("Duplicate path (%1s) in %2s" % (path, filename))
+ dependencies[path] = found
+ return { 'dependencies': dependencies, 'globs': globs }
def temp_filename(extension):
file = tempfile.mkstemp(suffix = extension)
diff --git a/tools/quickbook/test/python/sub1/a.qbk b/tools/quickbook/test/python/sub1/a.qbk
index 7898192261..f3abe6ebf0 100644
--- a/tools/quickbook/test/python/sub1/a.qbk
+++ b/tools/quickbook/test/python/sub1/a.qbk
@@ -1 +1,9 @@
+[/
+ 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)
+]
+
a
diff --git a/tools/quickbook/test/python/sub2/b.qbk b/tools/quickbook/test/python/sub2/b.qbk
index 6178079822..9b4336bdc3 100644
--- a/tools/quickbook/test/python/sub2/b.qbk
+++ b/tools/quickbook/test/python/sub2/b.qbk
@@ -1 +1,9 @@
+[/
+ 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)
+]
+
b
diff --git a/tools/quickbook/test/python/svg_missing.qbk b/tools/quickbook/test/python/svg_missing.qbk
index 2b25c2f3b6..1b54ece45e 100644
--- a/tools/quickbook/test/python/svg_missing.qbk
+++ b/tools/quickbook/test/python/svg_missing.qbk
@@ -1,3 +1,11 @@
+[/
+ 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)
+]
+
[article Dependencies for missing svg]
[$missing.svg]
diff --git a/tools/quickbook/test/python/svg_missing_deps.txt b/tools/quickbook/test/python/svg_missing_deps.txt
index 25d1c0e502..91487e85e9 100644
--- a/tools/quickbook/test/python/svg_missing_deps.txt
+++ b/tools/quickbook/test/python/svg_missing_deps.txt
@@ -1 +1,4 @@
+# Copyright 2012-2013 Daniel James
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
svg_missing.qbk
diff --git a/tools/quickbook/test/python/svg_missing_locs.txt b/tools/quickbook/test/python/svg_missing_locs.txt
index 379d4142f0..0f4c9b8061 100644
--- a/tools/quickbook/test/python/svg_missing_locs.txt
+++ b/tools/quickbook/test/python/svg_missing_locs.txt
@@ -1,2 +1,5 @@
+# Copyright 2012-2013 Daniel James
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
- html/missing.svg
+ svg_missing.qbk
diff --git a/tools/quickbook/test/role-1_7-fail.quickbook b/tools/quickbook/test/role-1_7-fail.quickbook
new file mode 100644
index 0000000000..b01d16e23c
--- /dev/null
+++ b/tools/quickbook/test/role-1_7-fail.quickbook
@@ -0,0 +1,5 @@
+[article Quickbook Role Fail Test
+[quickbook 1.7]
+]
+
+[role]
diff --git a/tools/quickbook/test/role-1_7.gold b/tools/quickbook/test/role-1_7.gold
new file mode 100644
index 0000000000..4cd7d5bb79
--- /dev/null
+++ b/tools/quickbook/test/role-1_7.gold
@@ -0,0 +1,13 @@
+<?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>
+ <para>
+ road <phrase role="red">Red</phrase> <phrase role="red"></phrase> <phrase role="three-colours-red">Three
+ Colours Red</phrase> <phrase role="red-road">Red Road</phrase>
+ </para>
+</article>
diff --git a/tools/quickbook/test/role-1_7.quickbook b/tools/quickbook/test/role-1_7.quickbook
new file mode 100644
index 0000000000..17bf449522
--- /dev/null
+++ b/tools/quickbook/test/role-1_7.quickbook
@@ -0,0 +1,13 @@
+[article Quickbook Role Test
+[quickbook 1.7]
+]
+
+[role keyword Keyword] [role keyword]
+
+[template r red]
+[template r2 road]
+[r2]
+[role [r] Red] [role [r]]
+[role three-colours-[r] Three Colours Red]
+[role [r]-[r2] Red Road]
+
diff --git a/tools/quickbook/test/section-1_7.gold b/tools/quickbook/test/section-1_7.gold
new file mode 100644
index 0000000000..33c67675aa
--- /dev/null
+++ b/tools/quickbook/test/section-1_7.gold
@@ -0,0 +1,26 @@
+<?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="section_id_1_7" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Section Id 1.7</title>
+ <section id="section_id_1_7.quickbook_section_no_id_test">
+ <title><link linkend="section_id_1_7.quickbook_section_no_id_test">Quickbook
+ section no id test</link></title>
+ </section>
+ <section id="section_id_1_7.id_test1">
+ <title><link linkend="section_id_1_7.id_test1">Quickbook section id test</link></title>
+ </section>
+ <section id="section_id_1_7.id_test2">
+ <title><link linkend="section_id_1_7.id_test2">Quickbook section id test</link></title>
+ </section>
+ <section id="section_id_1_7.id_test3_quickbook_section_id_te">
+ <title><link linkend="section_id_1_7.id_test3_quickbook_section_id_te">id_test3
+ Quickbook section id test</link></title>
+ </section>
+ <section id="section_id_1_7.--">
+ <title><link linkend="section_id_1_7.--">Quickbook section odd id test</link></title>
+ </section>
+ <section id="section_id_1_7.sect-abc">
+ <title><link linkend="section_id_1_7.sect-abc">Section with template in id</link></title>
+ </section>
+</article>
diff --git a/tools/quickbook/test/section-1_7.quickbook b/tools/quickbook/test/section-1_7.quickbook
new file mode 100644
index 0000000000..925e34b2ce
--- /dev/null
+++ b/tools/quickbook/test/section-1_7.quickbook
@@ -0,0 +1,18 @@
+[article Section Id 1.7
+ [quickbook 1.7]
+]
+
+[section Quickbook section no id test]
+[endsect]
+[section:id_test1 Quickbook section id test]
+[endsect]
+[section :id_test2 Quickbook section id test]
+[endsect]
+[section: id_test3 Quickbook section id test]
+[endsect]
+[section:-- Quickbook section odd id test]
+[endsect]
+
+[template thing[] abc]
+[section:sect-[thing] Section with template in id]
+[endsect]
diff --git a/tools/quickbook/test/snippets/Jamfile.v2 b/tools/quickbook/test/snippets/Jamfile.v2
index 4dfd0d0e8f..6765dff9e4 100644
--- a/tools/quickbook/test/snippets/Jamfile.v2
+++ b/tools/quickbook/test/snippets/Jamfile.v2
@@ -6,7 +6,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
#
-project quickook/tests/snippets ;
+project quickbook/test/snippets ;
import quickbook-testing : quickbook-test quickbook-error-test ;
diff --git a/tools/quickbook/test/snippets/unbalanced_snippet1.cpp b/tools/quickbook/test/snippets/unbalanced_snippet1.cpp
index ec49a78878..ee5983912a 100644
--- a/tools/quickbook/test/snippets/unbalanced_snippet1.cpp
+++ b/tools/quickbook/test/snippets/unbalanced_snippet1.cpp
@@ -1,3 +1,11 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
//[unclosed
-int main() {} \ No newline at end of file
+int main() {}
diff --git a/tools/quickbook/test/snippets/unbalanced_snippet2.cpp b/tools/quickbook/test/snippets/unbalanced_snippet2.cpp
index b0575171ea..238b976357 100644
--- a/tools/quickbook/test/snippets/unbalanced_snippet2.cpp
+++ b/tools/quickbook/test/snippets/unbalanced_snippet2.cpp
@@ -1 +1,10 @@
-//] \ No newline at end of file
+//]
+
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
diff --git a/tools/quickbook/test/source_mode-1_7.gold b/tools/quickbook/test/source_mode-1_7.gold
index e40bae8608..2cc454a6dd 100644
--- a/tools/quickbook/test/source_mode-1_7.gold
+++ b/tools/quickbook/test/source_mode-1_7.gold
@@ -26,7 +26,14 @@
<itemizedlist>
<listitem>
<simpara>
- Sadly this doesn't work.
+ <code><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase
+ role="special">()</phrase> <phrase role="special">{}</phrase></code>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <code><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase
+ role="special">()</phrase> <phrase role="special">{}</phrase></code>
</simpara>
</listitem>
<listitem>
@@ -35,4 +42,22 @@
</simpara>
</listitem>
</itemizedlist>
+ <para>
+ <code><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase
+ role="special">()</phrase> <phrase role="special">{}</phrase></code> and <code><phrase
+ role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+ <phrase role="special">{}</phrase></code> should both be C++ highlighted. <code>int
+ main() {}</code> shouldn't be, but <code><phrase role="keyword">int</phrase>
+ <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase
+ role="special">{}</phrase></code> should.
+ </para>
+ <para>
+ <code><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase
+ role="special">()</phrase> <phrase role="special">{}</phrase></code>. Not highlighted:
+ <code>int main() {}</code>.
+ </para>
+ <section id="source_mode_test.cpp">
+ <title><link linkend="source_mode_test.cpp">C++ section</link></title>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </section>
</article>
diff --git a/tools/quickbook/test/source_mode-1_7.quickbook b/tools/quickbook/test/source_mode-1_7.quickbook
index f5b9ee37fe..9388867c80 100644
--- a/tools/quickbook/test/source_mode-1_7.quickbook
+++ b/tools/quickbook/test/source_mode-1_7.quickbook
@@ -8,5 +8,17 @@
[!c++]`int main() {}` but `plain text`.
[!c++]
-* Sadly this doesn't work.
* `int main() {}`
+* `int main() {}`
+* [teletype] `int main() {}` [/ shouldn't be highlighted]
+
+[!c++]
+`int main() {}` and `int main() {}` should both be C++ highlighted.
+[!teletype]`int main() {}` shouldn't be, but `int main() {}` should.
+
+[!c++] `int main() {}`. Not highlighted: `int main() {}`.
+
+[!c++]
+[section:cpp C++ section]
+``int main() {}``
+[endsect]
diff --git a/tools/quickbook/test/table-1_7.gold b/tools/quickbook/test/table-1_7.gold
new file mode 100644
index 0000000000..6b8eafabf7
--- /dev/null
+++ b/tools/quickbook/test/table-1_7.gold
@@ -0,0 +1,520 @@
+<?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>
+ <informaltable frame="all" id="table_tests.-table5-">
+ <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.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>
+ <table frame="all" id="table_tests.section1.id123">
+ <title>Table with template id</title>
+ <tgroup cols="0">
+ <tbody>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+</article>
diff --git a/tools/quickbook/test/table-1_7.quickbook b/tools/quickbook/test/table-1_7.quickbook
new file mode 100644
index 0000000000..84d68f71d4
--- /dev/null
+++ b/tools/quickbook/test/table-1_7.quickbook
@@ -0,0 +1,151 @@
+[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]]
+]
+
+[template id_value[] id123]
+[table:[id_value] Table with template id]
+
+[endsect]
diff --git a/tools/quickbook/test/templates-1_3.gold b/tools/quickbook/test/templates-1_3.gold
index c53fef1e62..ed3668fdaf 100644
--- a/tools/quickbook/test/templates-1_3.gold
+++ b/tools/quickbook/test/templates-1_3.gold
@@ -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>
diff --git a/tools/quickbook/test/templates-1_3.quickbook b/tools/quickbook/test/templates-1_3.quickbook
index 457cd157d7..a6d4348788 100644
--- a/tools/quickbook/test/templates-1_3.quickbook
+++ b/tools/quickbook/test/templates-1_3.quickbook
@@ -198,3 +198,19 @@ Paragraphs 2
* [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]
diff --git a/tools/quickbook/test/templates-1_4.gold b/tools/quickbook/test/templates-1_4.gold
index 72e33e0bfa..40c2443690 100644
--- a/tools/quickbook/test/templates-1_4.gold
+++ b/tools/quickbook/test/templates-1_4.gold
@@ -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>
diff --git a/tools/quickbook/test/templates-1_4.quickbook b/tools/quickbook/test/templates-1_4.quickbook
index fc808554e8..3fb8937481 100644
--- a/tools/quickbook/test/templates-1_4.quickbook
+++ b/tools/quickbook/test/templates-1_4.quickbook
@@ -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]
diff --git a/tools/quickbook/test/templates-1_5.gold b/tools/quickbook/test/templates-1_5.gold
index bb05aaca96..9577f1a915 100644
--- a/tools/quickbook/test/templates-1_5.gold
+++ b/tools/quickbook/test/templates-1_5.gold
@@ -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>
diff --git a/tools/quickbook/test/templates-1_5.quickbook b/tools/quickbook/test/templates-1_5.quickbook
index 038b8b3f05..55ec031fde 100644
--- a/tools/quickbook/test/templates-1_5.quickbook
+++ b/tools/quickbook/test/templates-1_5.quickbook
@@ -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 @@ A <emphasis>paragraph</emphasis>.
'''<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]
diff --git a/tools/quickbook/test/templates-1_6-fail1.quickbook b/tools/quickbook/test/templates-1_6-fail1.quickbook
new file mode 100644
index 0000000000..0fd039b1e7
--- /dev/null
+++ b/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]
+[`~]
diff --git a/tools/quickbook/test/templates-1_6.gold b/tools/quickbook/test/templates-1_6.gold
new file mode 100644
index 0000000000..b37604e75f
--- /dev/null
+++ b/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>
diff --git a/tools/quickbook/test/templates-1_6.quickbook b/tools/quickbook/test/templates-1_6.quickbook
new file mode 100644
index 0000000000..627bd7fd87
--- /dev/null
+++ b/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]
diff --git a/tools/quickbook/test/templates-1_7-fail1.quickbook b/tools/quickbook/test/templates-1_7-fail1.quickbook
new file mode 100644
index 0000000000..0618bebb95
--- /dev/null
+++ b/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]
diff --git a/tools/quickbook/test/templates-1_7-fail2.quickbook b/tools/quickbook/test/templates-1_7-fail2.quickbook
new file mode 100644
index 0000000000..548884b16a
--- /dev/null
+++ b/tools/quickbook/test/templates-1_7-fail2.quickbook
@@ -0,0 +1,11 @@
+[article Template 1.7 fail
+[quickbook 1.7]
+]
+
+[/ This should fail because it's a block template called from an attribute ]
+
+[template fail[]
+
+Block template.]
+
+[link this-should-[fail]]
diff --git a/tools/quickbook/test/templates-1_7.gold b/tools/quickbook/test/templates-1_7.gold
new file mode 100644
index 0000000000..c7d4c64e09
--- /dev/null
+++ b/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>
diff --git a/tools/quickbook/test/templates-1_7.quickbook b/tools/quickbook/test/templates-1_7.quickbook
new file mode 100644
index 0000000000..bf1feaca2c
--- /dev/null
+++ b/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]
diff --git a/tools/quickbook/test/unit/Jamfile.v2 b/tools/quickbook/test/unit/Jamfile.v2
index 0b583b796b..68262d65c0 100644
--- a/tools/quickbook/test/unit/Jamfile.v2
+++ b/tools/quickbook/test/unit/Jamfile.v2
@@ -8,7 +8,7 @@
import testing ;
-project quickbook-unit-tests
+project quickbook/test/unit-tests
: requirements
<include>../../src
<warnings>all
@@ -20,8 +20,10 @@ project quickbook-unit-tests
<toolset>darwin:<define>BOOST_DETAIL_CONTAINER_FWD
;
-run values_test.cpp ../../src/values.cpp ../../src/files.cpp ../../src/string_ref.cpp ;
+run values_test.cpp ../../src/values.cpp ../../src/files.cpp ;
run post_process_test.cpp ../../src/post_process.cpp ;
+run source_map_test.cpp ../../src/files.cpp ;
+run glob_test.cpp ../../src/glob.cpp ;
# Copied from spirit
run symbols_tests.cpp ;
diff --git a/tools/quickbook/test/unit/glob_test.cpp b/tools/quickbook/test/unit/glob_test.cpp
new file mode 100644
index 0000000000..fa2578116c
--- /dev/null
+++ b/tools/quickbook/test/unit/glob_test.cpp
@@ -0,0 +1,122 @@
+/*=============================================================================
+ Copyright (c) 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 "glob.hpp"
+#include <boost/detail/lightweight_test.hpp>
+
+void glob_tests() {
+ BOOST_TEST(quickbook::glob("", ""));
+
+ BOOST_TEST(!quickbook::glob("*", ""));
+ BOOST_TEST(quickbook::glob("*", "a"));
+ BOOST_TEST(quickbook::glob("*b", "b"));
+ BOOST_TEST(quickbook::glob("*b", "ab"));
+ BOOST_TEST(quickbook::glob("*b", "bab"));
+ BOOST_TEST(quickbook::glob("*b*", "b"));
+ BOOST_TEST(quickbook::glob("*b*", "ab"));
+ BOOST_TEST(quickbook::glob("*b*", "bc"));
+ BOOST_TEST(quickbook::glob("*b*", "abc"));
+ BOOST_TEST(!quickbook::glob("*b*", ""));
+ BOOST_TEST(!quickbook::glob("*b*", "a"));
+ BOOST_TEST(!quickbook::glob("*b*", "ac"));
+
+ BOOST_TEST(quickbook::glob("hello.txt", "hello.txt"));
+ BOOST_TEST(!quickbook::glob("world.txt", "helloworld.txt"));
+ BOOST_TEST(quickbook::glob("*world.txt", "helloworld.txt"));
+ BOOST_TEST(!quickbook::glob("world.txt*", "helloworld.txt"));
+ BOOST_TEST(!quickbook::glob("hello", "helloworld.txt"));
+ BOOST_TEST(!quickbook::glob("*hello", "helloworld.txt"));
+ BOOST_TEST(quickbook::glob("hello*", "helloworld.txt"));
+ BOOST_TEST(quickbook::glob("*world*", "helloworld.txt"));
+
+ BOOST_TEST(quickbook::glob("?", "a"));
+ BOOST_TEST(!quickbook::glob("?", ""));
+ BOOST_TEST(!quickbook::glob("?", "ab"));
+ BOOST_TEST(quickbook::glob("a?", "ab"));
+ BOOST_TEST(quickbook::glob("?b", "ab"));
+ BOOST_TEST(quickbook::glob("?bc", "abc"));
+ BOOST_TEST(quickbook::glob("a?c", "abc"));
+ BOOST_TEST(quickbook::glob("ab?", "abc"));
+ BOOST_TEST(!quickbook::glob("?bc", "aac"));
+ BOOST_TEST(!quickbook::glob("a?c", "bbc"));
+ BOOST_TEST(!quickbook::glob("ab?", "abcd"));
+
+ BOOST_TEST(quickbook::glob("[a]", "a"));
+ BOOST_TEST(!quickbook::glob("[^a]", "a"));
+ BOOST_TEST(!quickbook::glob("[b]", "a"));
+ BOOST_TEST(quickbook::glob("[^b]", "a"));
+ BOOST_TEST(quickbook::glob("[a-z]", "a"));
+ BOOST_TEST(!quickbook::glob("[^a-z]", "a"));
+ BOOST_TEST(!quickbook::glob("[b-z]", "a"));
+ BOOST_TEST(quickbook::glob("[^b-z]", "a"));
+ BOOST_TEST(quickbook::glob("[-a]", "a"));
+ BOOST_TEST(quickbook::glob("[-a]", "-"));
+ BOOST_TEST(!quickbook::glob("[-a]", "b"));
+ BOOST_TEST(!quickbook::glob("[^-a]", "a"));
+ BOOST_TEST(!quickbook::glob("[^-a]", "-"));
+ BOOST_TEST(quickbook::glob("[^-a]", "b"));
+ BOOST_TEST(quickbook::glob("[a-]", "a"));
+ BOOST_TEST(quickbook::glob("[a-]", "-"));
+ BOOST_TEST(!quickbook::glob("[a-]", "b"));
+ BOOST_TEST(!quickbook::glob("[^a-]", "a"));
+ BOOST_TEST(!quickbook::glob("[^a-]", "-"));
+ BOOST_TEST(quickbook::glob("[^a-]", "b"));
+ BOOST_TEST(quickbook::glob("[a-ce-f]", "a"));
+ BOOST_TEST(!quickbook::glob("[a-ce-f]", "d"));
+ BOOST_TEST(quickbook::glob("[a-ce-f]", "f"));
+ BOOST_TEST(!quickbook::glob("[a-ce-f]", "g"));
+ BOOST_TEST(!quickbook::glob("[^a-ce-f]", "a"));
+ BOOST_TEST(quickbook::glob("[^a-ce-f]", "d"));
+ BOOST_TEST(!quickbook::glob("[^a-ce-f]", "f"));
+ BOOST_TEST(quickbook::glob("[^a-ce-f]", "g"));
+ BOOST_TEST(!quickbook::glob("[b]", "a"));
+ BOOST_TEST(quickbook::glob("[a]bc", "abc"));
+ BOOST_TEST(quickbook::glob("a[b]c", "abc"));
+ BOOST_TEST(quickbook::glob("ab[c]", "abc"));
+ BOOST_TEST(quickbook::glob("a[a-c]c", "abc"));
+ BOOST_TEST(quickbook::glob("*[b]*", "abc"));
+ BOOST_TEST(quickbook::glob("[\\]]", "]"));
+ BOOST_TEST(!quickbook::glob("[^\\]]", "]"));
+
+ BOOST_TEST(quickbook::glob("b*ana", "banana"));
+ BOOST_TEST(quickbook::glob("1234*1234*1234", "123412341234"));
+ BOOST_TEST(!quickbook::glob("1234*1234*1234", "1234123341234"));
+ BOOST_TEST(quickbook::glob("1234*1234*1234", "123412312312341231231234"));
+ BOOST_TEST(!quickbook::glob("1234*1234*1234", "12341231231234123123123"));
+}
+
+void check_glob_tests()
+{
+ BOOST_TEST(!quickbook::check_glob(""));
+ BOOST_TEST(!quickbook::check_glob("file"));
+ BOOST_TEST(!quickbook::check_glob("file\\[\\]"));
+ BOOST_TEST(quickbook::check_glob("[x]"));
+ BOOST_TEST(quickbook::check_glob("abc[x]"));
+ BOOST_TEST(quickbook::check_glob("[x]abd"));
+ BOOST_TEST_THROWS(quickbook::check_glob("["), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("[xyz"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("xyx["), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("]"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("abc]"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("]def"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("[]"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("[[]"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("[]]"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("**"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("[/]"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("\\"), quickbook::glob_error);
+ BOOST_TEST_THROWS(quickbook::check_glob("\\\\"), quickbook::glob_error);
+}
+
+int main()
+{
+ glob_tests();
+ check_glob_tests();
+
+ return boost::report_errors();
+}
diff --git a/tools/quickbook/test/unit/source_map_test.cpp b/tools/quickbook/test/unit/source_map_test.cpp
new file mode 100644
index 0000000000..3eb305741c
--- /dev/null
+++ b/tools/quickbook/test/unit/source_map_test.cpp
@@ -0,0 +1,395 @@
+/*=============================================================================
+ Copyright (c) 2012 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 "fwd.hpp"
+#include "files.hpp"
+#include <boost/utility/string_ref.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/range/algorithm/find.hpp>
+
+void simple_map_tests()
+{
+ boost::string_ref source("First Line\nSecond Line");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+
+ quickbook::string_iterator line1 = fake_file->source().begin();
+ quickbook::string_iterator line1_end = boost::find(fake_file->source(), '\n');
+ quickbook::string_iterator line2 = line1_end + 1;
+ quickbook::string_iterator line2_end = fake_file->source().end();
+
+ quickbook::mapped_file_builder builder;
+
+ { // Empty test
+ builder.start(fake_file);
+ BOOST_TEST(builder.empty());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST(f1->source().empty());
+ }
+
+ { // Add full text
+ builder.start(fake_file);
+ builder.add(boost::string_ref(line1, line2_end - line1));
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(), source);
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(1,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
+ quickbook::file_position(1,3));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line1_end - line1)),
+ quickbook::file_position(1,line1_end - line1 + 1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2 - line1)),
+ quickbook::file_position(2,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().end()),
+ fake_file->position_of(fake_file->source().end()));
+ }
+
+ { // Add first line
+ builder.start(fake_file);
+ builder.add(boost::string_ref(line1, line1_end - line1));
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref(source.begin(), line1_end - line1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(1,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
+ quickbook::file_position(1,3));
+ BOOST_TEST_EQ(f1->position_of(f1->source().end()),
+ quickbook::file_position(1,line1_end - line1 + 1));
+ }
+
+ { // Add second line
+ builder.start(fake_file);
+ builder.add(boost::string_ref(line2, line2_end - line2));
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(), boost::string_ref("Second Line"));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(2,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
+ quickbook::file_position(2,3));
+ BOOST_TEST_EQ(f1->position_of(f1->source().end()),
+ quickbook::file_position(2,line2_end - line2 + 1));
+ }
+
+ { // Out of order
+ builder.start(fake_file);
+ builder.add(boost::string_ref(line2, line2_end - line2));
+ builder.add(boost::string_ref(line1_end, 1));
+ builder.add(boost::string_ref(line1, line1_end - line1));
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Second Line\nFirst Line"));
+
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(2,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
+ quickbook::file_position(2,3));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2 - 1)),
+ quickbook::file_position(2,line2_end - line2));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2)),
+ quickbook::file_position(1,(line1_end - line1 + 1)));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2 + 1)),
+ quickbook::file_position(1,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().end()),
+ quickbook::file_position(1,line1_end - line1 + 1));
+ }
+
+ { // Repeated text
+ builder.start(fake_file);
+ builder.add(boost::string_ref(line2, line2_end - line2));
+ builder.add(boost::string_ref(line1_end, 1));
+ builder.add(boost::string_ref(line2, line2_end - line2));
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Second Line\nSecond Line"));
+
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(2,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
+ quickbook::file_position(2,3));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2 - 1)),
+ quickbook::file_position(2,line2_end - line2));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2)),
+ quickbook::file_position(1,(line1_end - line1 + 1)));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2 + 1)),
+ quickbook::file_position(2,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().end()),
+ quickbook::file_position(2,line2_end - line2 + 1));
+ }
+
+
+ { // Generated text
+ builder.start(fake_file);
+ builder.add_at_pos("------\n", line1);
+ builder.add(boost::string_ref(line1, line1_end - line1));
+ builder.add_at_pos("\n------\n", line1_end);
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("------\nFirst Line\n------\n"));
+
+ quickbook::string_iterator newline = boost::find(f1->source(), '\n');
+
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(1,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
+ quickbook::file_position(1,1));
+ BOOST_TEST_EQ(f1->position_of(newline),
+ quickbook::file_position(1,1));
+ BOOST_TEST_EQ(f1->position_of(newline + 1),
+ quickbook::file_position(1,1));
+ BOOST_TEST_EQ(f1->position_of(newline + 2),
+ quickbook::file_position(1,2));
+ BOOST_TEST_EQ(f1->position_of(newline + (line1_end - line1)),
+ quickbook::file_position(1,line1_end - line1));
+ BOOST_TEST_EQ(f1->position_of(newline + (line1_end - line1 + 1)),
+ quickbook::file_position(1,line1_end - line1 + 1));
+ BOOST_TEST_EQ(f1->position_of(newline + (line1_end - line1 + 2)),
+ quickbook::file_position(1,line1_end - line1 + 1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().end()),
+ quickbook::file_position(1,line1_end - line1 + 1));
+ }
+}
+
+void indented_map_tests()
+{
+ boost::string_ref source(
+ " Code line1\n"
+ " Code line2\n");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+
+ quickbook::mapped_file_builder builder;
+
+ {
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\nCode line2\n"));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(1,4));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 1),
+ quickbook::file_position(1,5));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 5),
+ quickbook::file_position(1,9));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 10),
+ quickbook::file_position(1,14));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 11),
+ quickbook::file_position(2,4));
+ // TODO: Shouldn't this be (3,1)? Does it matter?
+ BOOST_TEST_EQ(f1->position_of(f1->source().end()),
+ quickbook::file_position(3,1));
+ }
+
+ {
+ builder.start(fake_file);
+ {
+ quickbook::mapped_file_builder builder2;
+ builder2.start(fake_file);
+ builder2.unindent_and_add(fake_file->source());
+ builder.add(builder2);
+ }
+ quickbook::file_ptr f1 = builder.release();
+
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\nCode line2\n"));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(1,4));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 1),
+ quickbook::file_position(1,5));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 5),
+ quickbook::file_position(1,9));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 10),
+ quickbook::file_position(1,14));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 11),
+ quickbook::file_position(2,4));
+ BOOST_TEST_EQ(f1->position_of(f1->source().end()),
+ quickbook::file_position(3,1));
+ }
+
+ {
+ builder.start(fake_file);
+ builder.unindent_and_add(boost::string_ref(
+ fake_file->source().begin() + 3,
+ fake_file->source().end() - (fake_file->source().begin() + 3)));
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\n Code line2\n"));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(1,4));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 1),
+ quickbook::file_position(1,5));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 5),
+ quickbook::file_position(1,9));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 10),
+ quickbook::file_position(1,14));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 11),
+ quickbook::file_position(2,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().end()),
+ quickbook::file_position(3,1));
+ }
+}
+
+void indented_map_tests2()
+{
+ boost::string_ref source(
+ " Code line1\n"
+ "\n"
+ " Code line2\n");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+
+ quickbook::mapped_file_builder builder;
+
+ {
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\n\nCode line2\n"));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
+ quickbook::file_position(1,4));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 1),
+ quickbook::file_position(1,5));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 5),
+ quickbook::file_position(1,9));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 10),
+ quickbook::file_position(1,14));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 11),
+ quickbook::file_position(2,1));
+ BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 12),
+ quickbook::file_position(3,4));
+ }
+}
+
+void indented_map_leading_blanks_test()
+{
+ quickbook::mapped_file_builder builder;
+
+ {
+ boost::string_ref source("\n\n Code line1\n");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\n"));
+ }
+
+ {
+ boost::string_ref source(" \n \n Code line1\n");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\n"));
+ }
+
+ {
+ boost::string_ref source(" Code line1\n \n Code line2");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\n\nCode line2"));
+ }
+}
+
+void indented_map_trailing_blanks_test()
+{
+ quickbook::mapped_file_builder builder;
+
+ {
+ boost::string_ref source("\n\n Code line1\n ");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\n"));
+ }
+
+ {
+ boost::string_ref source(" \n \n Code line1\n ");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\n "));
+ }
+
+ {
+ boost::string_ref source(" Code line1\n \n Code line2\n ");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line1\n\nCode line2\n"));
+ }
+
+}
+
+void indented_map_mixed_test()
+{
+ quickbook::mapped_file_builder builder;
+
+ {
+ boost::string_ref source("\tCode line 1\n Code line 2\n\t Code line 3\n \tCode line 4");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line 1\nCode line 2\n Code line 3\n Code line 4"));
+ }
+
+ {
+ boost::string_ref source(" Code line 1\n\tCode line 2");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line 1\n Code line 2"));
+ }
+
+ {
+ boost::string_ref source(" Code line 1\n \tCode line 2");
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ builder.start(fake_file);
+ builder.unindent_and_add(fake_file->source());
+ quickbook::file_ptr f1 = builder.release();
+ BOOST_TEST_EQ(f1->source(),
+ boost::string_ref("Code line 1\n\tCode line 2"));
+ }
+}
+
+
+int main()
+{
+ simple_map_tests();
+ indented_map_tests();
+ indented_map_tests2();
+ indented_map_leading_blanks_test();
+ indented_map_trailing_blanks_test();
+ indented_map_mixed_test();
+ return boost::report_errors();
+}
diff --git a/tools/quickbook/test/unit/values_test.cpp b/tools/quickbook/test/unit/values_test.cpp
index b6d186c555..d3da4a857e 100644
--- a/tools/quickbook/test/unit/values_test.cpp
+++ b/tools/quickbook/test/unit/values_test.cpp
@@ -32,10 +32,10 @@ void qbk_tests()
"(fake file)", source, 105u);
q = quickbook::qbk_value(
fake_file,
- fake_file->source.begin(),
- fake_file->source.end());
+ fake_file->source().begin(),
+ fake_file->source().end());
}
- BOOST_TEST_EQ(q.get_quickbook(), source);
+ BOOST_TEST_EQ(q.get_quickbook(), boost::string_ref(source));
}
void sort_test()
diff --git a/tools/quickbook/test/versions/Jamfile.v2 b/tools/quickbook/test/versions/Jamfile.v2
index ccb46dc7bf..dd185d5879 100644
--- a/tools/quickbook/test/versions/Jamfile.v2
+++ b/tools/quickbook/test/versions/Jamfile.v2
@@ -6,7 +6,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
#
-project test/versions
+project quickbook/test/versions
: requirements
<toolset>msvc:<debug-symbols>off
;
diff --git a/tools/quickbook/test/versions/invalid_macro-1_6.quickbook b/tools/quickbook/test/versions/invalid_macro-1_6.quickbook
index f579f7252e..860d58b718 100644
--- a/tools/quickbook/test/versions/invalid_macro-1_6.quickbook
+++ b/tools/quickbook/test/versions/invalid_macro-1_6.quickbook
@@ -4,11 +4,11 @@
Import:
-[import invalid_macro-inc-1_1.qbk]
+[import invalid_macro-inc-1_1.quickbook]
* __valid__
* __invalid\macro__
Include:
-[include invalid_macro-inc-1_1.qbk]
+[include invalid_macro-inc-1_1.quickbook]
diff --git a/tools/quickbook/test/versions/invalid_macro-inc-1_1.qbk b/tools/quickbook/test/versions/invalid_macro-inc-1_1.quickbook
index c44bd67417..c44bd67417 100644
--- a/tools/quickbook/test/versions/invalid_macro-inc-1_1.qbk
+++ b/tools/quickbook/test/versions/invalid_macro-inc-1_1.quickbook
diff --git a/tools/quickbook/test/versions/templates-1_1.qbk b/tools/quickbook/test/versions/templates-inc-1_1.quickbook
index be5365055d..be5365055d 100644
--- a/tools/quickbook/test/versions/templates-1_1.qbk
+++ b/tools/quickbook/test/versions/templates-inc-1_1.quickbook
diff --git a/tools/quickbook/test/versions/templates-1_4.qbk b/tools/quickbook/test/versions/templates-inc-1_4.quickbook
index 8b565512d4..8b565512d4 100644
--- a/tools/quickbook/test/versions/templates-1_4.qbk
+++ b/tools/quickbook/test/versions/templates-inc-1_4.quickbook
diff --git a/tools/quickbook/test/versions/templates-1_5.qbk b/tools/quickbook/test/versions/templates-inc-1_5.quickbook
index 9dd07f6939..9dd07f6939 100644
--- a/tools/quickbook/test/versions/templates-1_5.qbk
+++ b/tools/quickbook/test/versions/templates-inc-1_5.quickbook
diff --git a/tools/quickbook/test/versions/versions-1_6.quickbook b/tools/quickbook/test/versions/versions-1_6.quickbook
index baac8e08d6..fed5a93ea9 100644
--- a/tools/quickbook/test/versions/versions-1_6.quickbook
+++ b/tools/quickbook/test/versions/versions-1_6.quickbook
@@ -1,9 +1,9 @@
[quickbook 1.6]
[article Mixed version tests]
-[import templates-1_1.qbk]
-[import templates-1_4.qbk]
-[import templates-1_5.qbk]
+[import templates-inc-1_1.quickbook]
+[import templates-inc-1_4.quickbook]
+[import templates-inc-1_5.quickbook]
[/ This test calls a 1.4 template -> 1.5 template -> 1.4 template.
The name lookup in the 1.4 template should skip the 1.5 template
@@ -21,6 +21,6 @@
[/ For comparison]
-[include templates-1_1.qbk]
-[include templates-1_4.qbk]
-[include templates-1_5.qbk]
+[include templates-inc-1_1.quickbook]
+[include templates-inc-1_4.quickbook]
+[include templates-inc-1_5.quickbook]
diff --git a/tools/quickbook/test/xinclude/Jamfile.v2 b/tools/quickbook/test/xinclude/Jamfile.v2
index 2974e86089..fbc8981c4e 100644
--- a/tools/quickbook/test/xinclude/Jamfile.v2
+++ b/tools/quickbook/test/xinclude/Jamfile.v2
@@ -6,7 +6,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
#
-project test/xinclude
+project quickbook/test/xinclude
: requirements
<toolset>msvc:<debug-symbols>off
;
diff --git a/tools/quickbook/test/xinclude/sub/boost-no-inspect b/tools/quickbook/test/xinclude/sub/boost-no-inspect
new file mode 100644
index 0000000000..099a233ec9
--- /dev/null
+++ b/tools/quickbook/test/xinclude/sub/boost-no-inspect
@@ -0,0 +1,2 @@
+This directory just contains simple test files, which might be disrupted by
+adding copyright etc.