summaryrefslogtreecommitdiff
path: root/tools/quickbook
diff options
context:
space:
mode:
Diffstat (limited to 'tools/quickbook')
-rw-r--r--tools/quickbook/doc/1_6.qbk84
-rw-r--r--tools/quickbook/doc/block.qbk120
-rw-r--r--tools/quickbook/doc/phrase.qbk104
-rw-r--r--tools/quickbook/doc/quickbook.qbk82
-rw-r--r--tools/quickbook/doc/structure.qbk7
-rw-r--r--tools/quickbook/doc/syntax.qbk6
-rw-r--r--tools/quickbook/src/Jamfile.v24
-rw-r--r--tools/quickbook/src/actions.cpp1154
-rw-r--r--tools/quickbook/src/actions.hpp151
-rw-r--r--tools/quickbook/src/actions_class.cpp136
-rw-r--r--tools/quickbook/src/block_element_grammar.cpp75
-rw-r--r--tools/quickbook/src/code_snippet.cpp88
-rw-r--r--tools/quickbook/src/doc_info_actions.cpp146
-rw-r--r--tools/quickbook/src/doc_info_grammar.cpp76
-rw-r--r--tools/quickbook/src/doc_info_tags.hpp1
-rw-r--r--tools/quickbook/src/files.cpp8
-rw-r--r--tools/quickbook/src/files.hpp29
-rw-r--r--tools/quickbook/src/fwd.hpp3
-rw-r--r--tools/quickbook/src/grammar.cpp8
-rw-r--r--tools/quickbook/src/grammar.hpp2
-rw-r--r--tools/quickbook/src/grammar_impl.hpp6
-rw-r--r--tools/quickbook/src/id_manager.cpp70
-rw-r--r--tools/quickbook/src/input_path.cpp79
-rw-r--r--tools/quickbook/src/input_path.hpp65
-rw-r--r--tools/quickbook/src/intrusive_base.hpp36
-rw-r--r--tools/quickbook/src/main_grammar.cpp464
-rw-r--r--tools/quickbook/src/parsers.hpp43
-rw-r--r--tools/quickbook/src/phrase_element_grammar.cpp87
-rw-r--r--tools/quickbook/src/phrase_tags.hpp7
-rw-r--r--tools/quickbook/src/quickbook.cpp136
-rw-r--r--tools/quickbook/src/quickbook.hpp4
-rw-r--r--tools/quickbook/src/state.cpp160
-rw-r--r--tools/quickbook/src/state.hpp (renamed from tools/quickbook/src/actions_class.hpp)53
-rw-r--r--tools/quickbook/src/state_save.hpp (renamed from tools/quickbook/src/actions_state.hpp)10
-rw-r--r--tools/quickbook/src/string_ref.cpp7
-rw-r--r--tools/quickbook/src/string_ref.hpp11
-rw-r--r--tools/quickbook/src/syntax_highlight.cpp400
-rw-r--r--tools/quickbook/src/utils.cpp19
-rw-r--r--tools/quickbook/src/utils.hpp11
-rw-r--r--tools/quickbook/src/values.cpp23
-rw-r--r--tools/quickbook/src/values.hpp6
-rw-r--r--tools/quickbook/test/Jamfile.v26
-rw-r--r--tools/quickbook/test/callouts-1_7.gold247
-rw-r--r--tools/quickbook/test/callouts-1_7.quickbook68
-rw-r--r--tools/quickbook/test/code_unclosed_block-1_6-fail.quickbook4
-rw-r--r--tools/quickbook/test/doc-info/Jamfile.v22
-rw-r--r--tools/quickbook/test/doc-info/escaped_attributes1-1_7.gold16
-rw-r--r--tools/quickbook/test/doc-info/escaped_attributes1-1_7.quickbook11
-rw-r--r--tools/quickbook/test/doc-info/escaped_attributes2-1_7.gold12
-rw-r--r--tools/quickbook/test/doc-info/escaped_attributes2-1_7.quickbook10
-rw-r--r--tools/quickbook/test/link-1_7.gold44
-rw-r--r--tools/quickbook/test/link-1_7.quickbook52
-rw-r--r--tools/quickbook/test/list_test-1_5.gold16
-rw-r--r--tools/quickbook/test/list_test-1_5.quickbook8
-rw-r--r--tools/quickbook/test/list_test-1_6.gold50
-rw-r--r--tools/quickbook/test/list_test-1_6.quickbook21
-rw-r--r--tools/quickbook/test/python/include_path.qbk4
-rw-r--r--tools/quickbook/test/python/include_path_deps.txt3
-rw-r--r--tools/quickbook/test/python/include_path_locs.txt6
-rw-r--r--tools/quickbook/test/python/missing_relative.qbk6
-rw-r--r--tools/quickbook/test/python/missing_relative_deps.txt1
-rw-r--r--tools/quickbook/test/python/missing_relative_locs.txt4
-rw-r--r--tools/quickbook/test/python/output-deps.py151
-rw-r--r--tools/quickbook/test/python/sub1/a.qbk1
-rw-r--r--tools/quickbook/test/python/sub2/b.qbk1
-rw-r--r--tools/quickbook/test/python/svg_missing.qbk3
-rw-r--r--tools/quickbook/test/python/svg_missing_deps.txt1
-rw-r--r--tools/quickbook/test/python/svg_missing_locs.txt2
-rw-r--r--tools/quickbook/test/source_mode-1_7.gold38
-rw-r--r--tools/quickbook/test/source_mode-1_7.quickbook12
-rw-r--r--tools/quickbook/test/unit/Jamfile.v27
-rw-r--r--tools/quickbook/test/version-1_8-fail.quickbook (renamed from tools/quickbook/test/version-1_7-fail.quickbook)2
72 files changed, 3080 insertions, 1710 deletions
diff --git a/tools/quickbook/doc/1_6.qbk b/tools/quickbook/doc/1_6.qbk
index c3ca99c0a0..89c41f2ac0 100644
--- a/tools/quickbook/doc/1_6.qbk
+++ b/tools/quickbook/doc/1_6.qbk
@@ -278,4 +278,86 @@ html.
[endsect]
-[endsect] [/ Quickbok 1.6] \ No newline at end of file
+[endsect] [/ Quickbok 1.6]
+
+[section:1_7 Quickbook 1.7]
+
+[section:source_mode Source mode for single entities]
+
+1.7 introduces a new `!` element type for setting the source mode of a single
+entity without changing the source mode otherwise. This can be used for
+code blocks and other elements. For example:
+
+```
+[!c++]
+ void foo() {};
+
+[!python]``\`\`\`\ ``def foo():``\`\`\`\ ``
+```
+
+It can also be used to set the source mode for elements:
+
+```
+[!teletype][table
+ [[code][meaning]]
+ [[`+`][addition]]
+]
+```
+
+When used a section, it's only set for the section element, not the
+whole section.
+
+Currently it does support other syntactic entities such as paragraphs
+and lists. I'm not sure if it would be a good idea.
+
+[endsect]
+
+[section:callouts Callouts in code block]
+
+Currently callouts can only be used in code snippets. 1.7 add
+support in normal code blocks. The same syntax is used as in
+code snippets, the callout descriptions appear immediately
+after the code block.
+
+[endsect]
+
+[section:escaped_docinfo_attributes Escaped docbook in docinfo blocks]
+
+Quickbook docinfo attributes will probably never be as rich as docbook
+attributes so to allow more flexible markup, not supported by quickbook
+escaped docbook can be included in the docinfo block:
+
+```
+[article Some article
+[quickbook 1.7]
+'''<author>
+ <firstname>John</firstname>
+ <surname>Doe</surname>
+ <email>john.doe@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]
+
+There's very premilinary support for calling templates in link values. A lot
+more work needs to be done, including:
+
+* Considering other places where templates could be called (e.g. images are
+ quite tricky, as templates could get confused with attributes, should
+ templates be callable from something like an element's id?).
+* Trimming spaces from the body of the template (which can cause surprising
+ results).
+* Checking that the contents of the template are appropriate for the context.
+ Possibly even using a different grammar.
+
+[endsect] [/templates_in_link_values]
+
+[endsect] [/ Quickbok 1.7]
diff --git a/tools/quickbook/doc/block.qbk b/tools/quickbook/doc/block.qbk
index f9da265b77..c6765131f7 100644
--- a/tools/quickbook/doc/block.qbk
+++ b/tools/quickbook/doc/block.qbk
@@ -14,7 +14,8 @@
[source-mode teletype]
]
-[section xinclude]
+[#quickbook.ref.xinclude]
+[section:xinclude xinclude]
You can include another XML file with:
@@ -27,7 +28,8 @@ reference section.
[endsect] [/xinclude]
-[section Paragraphs]
+[#quickbook.ref.paragraphs]
+[section:paragraphs Paragraphs]
Paragraphs start left-flushed and are terminated by two or more newlines. No
markup is needed for paragraphs. QuickBook automatically detects paragraphs from
@@ -36,10 +38,12 @@ the context. Block markups \[section, endsect, h1, h2, h3, h4, h5, h6, blurb,
[/ <-- There's a space here. Don't remove. this is intentianal, for testing]
This is a new paragraph...
-[endsect] [/Paragraphs]
+[endsect] [/paragraphs]
-[section Lists]
-[section Ordered lists]
+[#quickbook.ref.lists]
+[section:lists Lists]
+[#quickbook.ref.ordered_lists]
+[section:ordered_lists Ordered lists]
[pre
# One
@@ -53,8 +57,9 @@ will generate:
# Two
# Three
-[endsect] [/Ordered lists]
-[section List Hierarchies]
+[endsect] [/ordered_lists]
+[#quickbook.ref.list_hierarchies]
+[section:list_hierarchies List Hierarchies]
List hierarchies are supported. Example:
@@ -86,8 +91,9 @@ will generate:
# Four.a.ii
# Five
-[endsect] [/List Hierarchies]
-[section Long List Lines]
+[endsect] [/list_hierarchies]
+[#quickbook.ref.long_list_lines]
+[section:long_list_lines Long List Lines]
Long lines will be wrapped appropriately. Example:
@@ -109,8 +115,9 @@ Long lines will be wrapped appropriately. Example:
A very long item. A very long item. A very long item.
# A short item.
-[endsect] [/Long list lines]
-[section Unordered lists]
+[endsect] [/long_list_lines]
+[#quickbook.ref.unordered_lists]
+[section:unordered_lists Unordered lists]
```
* First
@@ -124,8 +131,9 @@ will generate:
* Second
* Third
-[endsect] [/Unordered lists]
-[section Mixed lists]
+[endsect] [/unordered_lists]
+[#quickbook.ref.mixed_lists]
+[section:mixed_lists Mixed lists]
Mixed lists (ordered and unordered) are supported. Example:
@@ -181,10 +189,11 @@ will generate:
* 2.b.2.a
* 2.b.2.b
-[endsect] [/Mixed lists]
-[endsect] [/Lists]
+[endsect] [/mixed_lists]
+[endsect] [/lists]
-[section Code]
+[#quickbook.ref.code]
+[section:code Code]
Preformatted code starts with a space or a tab. The code will be
syntax highlighted according to the current __source_mode__:
@@ -227,8 +236,9 @@ Generates:
using __boost__::__array__;
-[endsect] [/Code]
+[endsect] [/code]
+[#quickbook.ref.escape_back]
[section:escape_back Escaping Back To QuickBook]
Inside code, code blocks and inline code, QuickBook does not allow any
@@ -252,9 +262,10 @@ Will generate:
When escaping from code to QuickBook, only phrase level markups are
allowed. Block level markups like lists, tables etc. are not allowed.
-[endsect] [/Escaping back to quickbook]
+[endsect] [/escaping_back_to_quickbook]
-[section Preformatted]
+[#quickbook.ref.preformatted]
+[section:preformatted Preformatted]
Sometimes, you don't want some preformatted text to be parsed as source code. In such
cases, use the [^\[pre ... \]] markup block.
@@ -288,9 +299,10 @@ Some *preformatted* text Some *preformatted* text
Notice that unlike Code, phrase markup such as font style is still permitted
inside =pre= blocks.
-[endsect] [/Preformatted]
+[endsect] [/preformatted]
-[section Blockquote]
+[#quickbook.ref.blockquote]
+[section:blockquote Blockquote]
[pre
'''[:sometext...]'''
@@ -298,9 +310,10 @@ inside =pre= blocks.
[:Indents the paragraph. This applies to one paragraph only.]
-[endsect] [/Blockquote]
+[endsect] [/blockquote]
-[section Admonitions]
+[#quickbook.ref.admonitions]
+[section:admonitions Admonitions]
```
[note This is a note]
@@ -322,9 +335,10 @@ These are the only admonitions supported by __docbook__. So,
for example [^\[information This is some information\]] is unlikely
to produce the desired effect.
-[endsect] [/Admonitions]
+[endsect] [/admonitions]
-[section Headings]
+[#quickbook.ref.headings]
+[section:headings Headings]
```
[h1 Heading 1]
@@ -356,9 +370,10 @@ For example: Heading 1 in section Section 2 will be normalized to
to link to them. See __anchor_links__ and __section__ for more info.
-[endsect] [/Headings]
+[endsect] [/headings]
-[section Generic Heading]
+[#quickbook.ref.generic_heading]
+[section:generic_heading Generic Heading]
In cases when you don't want to care about the heading level (1 to 6), you
can use the /Generic Heading/:
@@ -402,9 +417,10 @@ at will without any extra work to ensure correct heading levels. In fact,
with /section/ and /heading/, you have all you need. /h1/../h6/ becomes
redundant. /h1/../h6/ might be deprecated in the future.
-[endsect] [/Generic Heading]
+[endsect] [/generic_heading]
-[section Macros]
+[#quickbook.ref.macros]
+[section:macros Macros]
```
[def macro_identifier some text]
@@ -455,9 +471,10 @@ will generate this:
Hi __spirit__ :-)
-[endsect] [/Macros]
+[endsect] [/macros]
-[section Predefined Macros]
+[#quickbook.ref.predefined_macros]
+[section:predefined_macros Predefined Macros]
Quickbook has some predefined macros that you can already use.
@@ -468,9 +485,10 @@ Quickbook has some predefined macros that you can already use.
[[[^\__FILENAME__]][Quickbook source filename] [__FILENAME__]]
]
-[endsect] [/Predefined Macros]
+[endsect] [/predefined_macros]
-[section Templates]
+[#quickbook.ref.templates]
+[section:templates Templates]
Templates provide a more versatile text substitution mechanism. Templates
come in handy when you need to create parameterizable, multi-line,
@@ -496,6 +514,7 @@ Hi, my name is [name]. I am [age] years old. I am a [what].
]
+[#quickbook.ref.template_identifier]
[heading Template Identifier]
Template identifiers can either consist of:
@@ -513,7 +532,7 @@ alphanumeric characters or the underscore. This is similar to your typical
C/C++ identifier.
A template formal argument temporarily hides a template of the same name at
-the point where the [link quickbook.syntax.block.templates.template_expansion
+the point where the [link quickbook.ref.template_expansion
template is expanded]. Note that the body of the [^person] template above
refers to [^name] [^age] and [^what] as [^\[name\]] [^\[age\]] and
[^\[what\]]. [^name] [^age] and [^what] are actually templates that exist
@@ -620,7 +639,7 @@ Some squiggles...[*[alpha][beta]]
The difference with macros are
-* The explicit [link quickbook.syntax.block.templates.template_expansion
+* The explicit [link quickbook.ref.template_expansion
template expansion syntax]. This is an advantage because, now, we don't
have to use obscure naming conventions like double underscores (e.g.
\_\_alpha\_\_) to avoid unwanted
@@ -729,7 +748,7 @@ With templates, one of our objectives is to allow us to rewrite QuickBook
in QuickBook (as a qbk library). For that to happen, we need to accommodate
single character punctuation templates which are fairly common in
QuickBook. You might have noticed that single character punctuations are
-allowed as [link quickbook.syntax.block.templates.template_identifier
+allowed as [link quickbook.ref.template_identifier
template identifiers]. Example:
```
@@ -748,9 +767,10 @@ We will have:
<hey>baz</hey>
]
-[endsect] [/Templates]
+[endsect] [/templates]
-[section Blurbs]
+[#quickbook.ref.blurbs]
+[section:blurbs Blurbs]
```
[blurb ``\:-)`` [*An eye catching advertisement or note...]
@@ -772,12 +792,13 @@ will generate this:
(EBNF) completely in C++.
]
-[note Prefer [link quickbook.syntax.block.admonitions admonitions] wherever
+[note Prefer [link quickbook.ref.admonitions admonitions] wherever
appropriate.]
-[endsect] [/Blurbs]
+[endsect] [/blurbs]
-[section Tables]
+[#quickbook.ref.tables]
+[section:tables Tables]
```
[table:id A Simple Table
@@ -899,9 +920,10 @@ Here's how to have preformatted blocks of code in a table cell:
]
]
-[endsect] [/Tables]
+[endsect] [/tables]
-[section Variable Lists]
+[#quickbook.ref.variable_lists]
+[section:variable_lists Variable Lists]
```
[variablelist A Variable List
@@ -932,9 +954,10 @@ only 2 "columns" are allowed. The first column contains the terms, and
the second column contains the definitions. Those familiar with HTML
will recognize this as a "definition list".
-[endsect] [/Variable Lists]
+[endsect] [/variable_lists]
-[section Include]
+[#quickbook.ref.include]
+[section:include Include]
You can include one QuickBook file from another. The syntax is simply:
@@ -963,9 +986,10 @@ 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\]].
-[endsect] [/Include]
+[endsect] [/include]
-[section Import]
+[#quickbook.ref.import]
+[section:import Import]
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
@@ -1110,4 +1134,4 @@ Example:
See the actual code here: [@boost:/tools/quickbook/test/stub.cpp]
-[endsect] [/Import]
+[endsect] [/import]
diff --git a/tools/quickbook/doc/phrase.qbk b/tools/quickbook/doc/phrase.qbk
index 613d730bc5..f6f8859798 100644
--- a/tools/quickbook/doc/phrase.qbk
+++ b/tools/quickbook/doc/phrase.qbk
@@ -14,7 +14,8 @@
[source-mode teletype]
]
-[section Font Styles]
+[#quickbook.ref.font_styles]
+[section:font_styles Font Styles]
```
['italic], [*bold], [_underline], [^teletype], [-strikethrough]
@@ -34,9 +35,10 @@ will generate:
[*['bold-italic]]
-[endsect] [/Font Styles]
+[endsect] [/font_styles]
-[section Replaceable]
+[#quickbook.ref.replaceable]
+[section:replaceable Replaceable]
When you want content that may or must be replaced by the user, use the syntax:
@@ -48,9 +50,10 @@ This will generate:
[~replacement]
-[endsect] [/Replaceable]
+[endsect] [/replaceable]
-[section Quotations]
+[#quickbook.ref.quotations]
+[section:quotations Quotations]
```
["A question that sometimes drives me hazy: am I or are the others crazy?]--Einstein
@@ -76,9 +79,10 @@ will generate:
["Here's the rule for bargains: ["Do other men, for they would do you.]
That's the true business precept.]
-[endsect] [/Quotations]
+[endsect] [/quotations]
-[section Simple formatting]
+[#quickbook.ref.simple_formatting]
+[section:simple_formatting Simple formatting]
Simple markup for formatting text, common in many applications, is now supported:
@@ -159,9 +163,10 @@ Yes sir, yes sir, three bags full!
One for the master, one for the dame,
And one for the little boy who lives down the lane.
-[endsect] [/Simple Formatting]
+[endsect] [/simple_formatting]
-[section Inline code]
+[#quickbook.ref.inline_code]
+[section:inline_code Inline code]
Inlining code in paragraphs is quite common when writing C++ documentation. We
provide a very simple markup for this. For example, this:
@@ -179,9 +184,10 @@ syntax highlighted.
single quote: `"'"`. Note too that [^\`some code\`] is preferred over
`[^some code]`. ]
-[endsect] [/Inline Code]
+[endsect] [/inline_code]
-[section Code blocks]
+[#quickbook.ref.code_blocks]
+[section:code_blocks Code blocks]
Preformatted code simply starts with a space or a tab (See __code__).
However, such a simple syntax cannot be used as phrase elements in lists
@@ -235,9 +241,10 @@ will generate:
[teletype]
-[endsect] [/Code blocks]
+[endsect] [/code_blocks]
-[section Source Mode]
+[#quickbook.ref.source_mode]
+[section:source_mode Source Mode]
If a document contains more than one type of source code then the source
mode may be changed dynamically as the document is processed. All QuickBook
@@ -270,10 +277,10 @@ C++ comment `// looks like this` whereas a Python comment [python]
[note The source mode strings are lowercase.]
-[endsect] [/Source Mode]
+[endsect] [/source_mode]
-[#ref-line-break]
-[section line-break]
+[#quickbook.ref.line_break]
+[section:line_break line-break]
```
[br]
@@ -283,9 +290,10 @@ C++ comment `// looks like this` whereas a Python comment [python]
there might be problems, especially when using an alternative docbook
processor.]
-[endsect] [/Line break]
+[endsect] [/line_break]
-[section Anchors]
+[#quickbook.ref.anchors]
+[section:anchors Anchors]
```
[#named_anchor]
@@ -299,9 +307,10 @@ These anchors are global and can be accessed from anywhere in the
quickbook documentation. Be careful to avoid clashes with anchors in
other sections.
-[endsect] [/Anchors]
+[endsect] [/anchors]
-[section Links]
+[#quickbook.ref.links]
+[section:links Links]
```
[@http://www.boost.org this is [*boost's] website....]
@@ -339,9 +348,10 @@ will generate: [@boost:/libs/spirit/index.html the Boost.Spirit documentation]
Note that this is only available when using BoostBook, and only for links
- it can't be used for images.
-[endsect] [/Links]
+[endsect] [/links]
-[section Anchor links]
+[#quickbook.ref.anchor_links]
+[section:anchor_links Anchor links]
You can link within a document using:
@@ -351,9 +361,10 @@ You can link within a document using:
See sections __section__ and __heading__ for more info.
-[endsect] [/Anchor links]
+[endsect] [/anchor_links]
-[section refentry links]
+[#quickbook.ref.refentry_links]
+[section:refentry_links refentry links]
In addition, you can link internally to an XML refentry like:
@@ -372,8 +383,9 @@ automatically be the refentry. Example:
This gets converted into [^<link linkend="xml.refentry">xml.refentry</link>].
-[endsect] [/refentry links]
+[endsect] [/refentry_links]
+[#quickbook.ref.code_links]
[section:code_links Code Links]
If you want to link to a function, class, member, enum, concept, global, or header in
@@ -400,9 +412,10 @@ Example:
would have "boost::bar::baz" as the link text.
-[endsect] [/Code Links]
+[endsect] [/code_links]
-[section Escape]
+[#quickbook.ref.escape]
+[section:escape Escape]
The escape mark-up is used when we don't want to do any processing.
@@ -427,9 +440,10 @@ Escaping allows us to pass XML markup to __boostbook__ or __docbook__. For examp
[important Be careful when using the escape. The text must conform to
__boostbook__/__docbook__ syntax.]
-[endsect] [/Escape]
+[endsect] [/escape]
-[section Single char escape]
+[#quickbook.ref.single_char_escape]
+[section:single_char_escape Single char escape]
The backslash may be used to escape a single punctuation character. The
punctuation immediately after the backslash is passed without any processing.
@@ -439,15 +453,16 @@ For example, how do you escape the triple quote? Simple: [^\\'\\'\\']
`\n` has a special meaning. It is used to generate line breaks.
-[warning `\n` is now deprecated, use [link ref-line-break `[br]`]
+[warning `\n` is now deprecated, use [link quickbook.ref.line_break `[br]`]
instead. Although, use it sparingly as it can generated invalid docbook]
The escaped space: `\ ` also has a special meaning. The escaped space is removed
from the output.
-[endsect] [/Single char escape]
+[endsect] [/single_char_escape]
-[section Unicode escape]
+[#quickbook.ref.unicode_escape]
+[section:unicode_escape Unicode escape]
You can enter any 16-bit unicode character by using `\u` followed by its 4 digit
hexadecimal code, or a 32-bit character by using `\U` followed by an 8 digit
@@ -463,9 +478,10 @@ will generate:
\u03B1 + \u03B2
]
-[endsect] [/Unicode escape]
+[endsect] [/unicode_escape]
-[section Images]
+[#quickbook.ref.images]
+[section:images Images]
```
[$image.jpg]
@@ -479,9 +495,10 @@ DocBook imagedata attributes]:
[$image.jpg [width 200in] [height 200in]]
```
-[endsect] [/Images]
+[endsect] [/images]
-[section Footnotes]
+[#quickbook.ref.footnotes]
+[section:footnotes Footnotes]
As of version 1.3, QuickBook supports footnotes. Just put the text of the
footnote in a `[footnote]` block, and the text will be put at the bottom
@@ -493,9 +510,10 @@ of the current page. For example, this:
will generate this[footnote A sample footnote].
-[endsect] [/Footnotes]
+[endsect] [/footnotes]
-[section Macro Expansion]
+[#quickbook.ref.macro_expansion]
+[section:macro_expansion Macro Expansion]
```
__a_macro_identifier__
@@ -503,9 +521,10 @@ __a_macro_identifier__
See __macros__ for details.
-[endsect] [/Macro Expansion]
+[endsect] [/macro_expansion]
-[section Template Expansion]
+[#quickbook.ref.template_expansion]
+[section:template_expansion Template Expansion]
```
[a_template_identifier]
@@ -513,8 +532,9 @@ See __macros__ for details.
See __templates__ for details.
-[endsect] [/Template Expansion]
+[endsect] [/template_expansion]
+[#quickbook.ref.cond]
[section:cond Conditional Generation]
Like C++ `#ifdef`, you can generate phrases depending on the presence of
@@ -543,4 +563,4 @@ And try again:
Yes!
-[endsect] [/Condition Generation]
+[endsect] [/cond]
diff --git a/tools/quickbook/doc/quickbook.qbk b/tools/quickbook/doc/quickbook.qbk
index da3f9a8fbe..ea988f9e2f 100644
--- a/tools/quickbook/doc/quickbook.qbk
+++ b/tools/quickbook/doc/quickbook.qbk
@@ -37,49 +37,49 @@
[def __boostbook__ [@http://www.boost.org/doc/html/boostbook.html BoostBook]]
[def __docbook__ [@http://www.docbook.org/ DocBook]]
-[def __comments__ [link quickbook.syntax.comments Comments]]
+[def __comments__ [link quickbook.ref.comments Comments]]
-[def __font_styles__ [link quickbook.syntax.phrase.font_styles Font Styles]]
-[def __quotations__ [link quickbook.syntax.phrase.quotations Quotations]]
-[def __replaceable__ [link quickbook.syntax.phrase.replaceable Replaceble]]
-[def __simple_formatting__ [link quickbook.syntax.phrase.simple_formatting Simple formatting]]
-[def __inline_code__ [link quickbook.syntax.phrase.inline_code Inline code]]
-[def __code_blocks__ [link quickbook.syntax.phrase.code_blocks Code blocks]]
-[def __source_mode__ [link quickbook.syntax.phrase.source_mode Source Mode]]
-[def __line_break__ [link quickbook.syntax.phrase.line_break line-break]]
-[def __anchors__ [link quickbook.syntax.phrase.anchors Anchors]]
-[def __links__ [link quickbook.syntax.phrase.links Links]]
-[def __anchor_links__ [link quickbook.syntax.phrase.anchor_links Anchor links]]
-[def __refentry_links__ [link quickbook.syntax.phrase.refentry_links refentry links]]
-[def __code_links__ [link quickbook.syntax.phrase.code_links function, class, member, enum, macro, concept or header links]]
-[def __escape__ [link quickbook.syntax.phrase.escape Escape]]
-[def __single_char_escape__ [link quickbook.syntax.phrase.single_char_escape Single char escape]]
-[def __images__ [link quickbook.syntax.phrase.images Images]]
-[def __cond__ [link quickbook.syntax.phrase.cond Conditional Generation]]
+[def __font_styles__ [link quickbook.ref.font_styles Font Styles]]
+[def __quotations__ [link quickbook.ref.quotations Quotations]]
+[def __replaceable__ [link quickbook.ref.replaceable Replaceble]]
+[def __simple_formatting__ [link quickbook.ref.simple_formatting Simple formatting]]
+[def __inline_code__ [link quickbook.ref.inline_code Inline code]]
+[def __code_blocks__ [link quickbook.ref.code_blocks Code blocks]]
+[def __source_mode__ [link quickbook.ref.source_mode Source Mode]]
+[def __line_break__ [link quickbook.ref.line_break line-break]]
+[def __anchors__ [link quickbook.ref.anchors Anchors]]
+[def __links__ [link quickbook.ref.links Links]]
+[def __anchor_links__ [link quickbook.ref.anchor_links Anchor links]]
+[def __refentry_links__ [link quickbook.ref.refentry_links refentry links]]
+[def __code_links__ [link quickbook.ref.code_links function, class, member, enum, macro, concept or header links]]
+[def __escape__ [link quickbook.ref.escape Escape]]
+[def __single_char_escape__ [link quickbook.ref.single_char_escape Single char escape]]
+[def __images__ [link quickbook.ref.images Images]]
+[def __cond__ [link quickbook.ref.cond Conditional Generation]]
-[def __document__ [link quickbook.syntax.structure.docinfo Document]]
-[def __section__ [link quickbook.syntax.structure.section Section]]
-[def __xinclude__ [link quickbook.syntax.block.xinclude xinclude]]
-[def __paragraphs__ [link quickbook.syntax.block.paragraphs Paragraphs]]
-[def __ordered_lists__ [link quickbook.syntax.block.lists.ordered_lists Ordered lists]]
-[def __list_hierarchies__ [link quickbook.syntax.block.lists.list_hierarchies List Hierarchies]]
-[def __long_list_lines__ [link quickbook.syntax.block.lists.long_list_lines Long List Lines]]
-[def __unordered_lists__ [link quickbook.syntax.block.lists.unordered_lists Unordered lists]]
-[def __mixed_lists__ [link quickbook.syntax.block.lists.mixed_lists Mixed lists]]
-[def __code__ [link quickbook.syntax.block.code Code]]
-[def __escape_back__ [link quickbook.syntax.block.escape_back Escaping Back To QuickBook]]
-[def __preformatted__ [link quickbook.syntax.block.preformatted Preformatted]]
-[def __blockquote__ [link quickbook.syntax.block.blockquote Blockquote]]
-[def __heading__ [link quickbook.syntax.block.headings Heading]]
-[def __macros__ [link quickbook.syntax.block.macros Macros]]
-[def __templates__ [link quickbook.syntax.block.templates Templates]]
-[def __predefined_macros__ [link quickbook.syntax.block.predefined_macros Predefined Macros]]
-[def __blurbs__ [link quickbook.syntax.block.blurbs Blurbs]]
-[def __admonitions__ [link quickbook.syntax.block.admonitions Admonitions]]
-[def __tables__ [link quickbook.syntax.block.tables Tables]]
-[def __variable_lists__ [link quickbook.syntax.block.variable_lists Variable Lists]]
-[def __include__ [link quickbook.syntax.block.include Include]]
-[def __import__ [link quickbook.syntax.block.import Import]]
+[def __document__ [link quickbook.ref.docinfo Document]]
+[def __section__ [link quickbook.ref.section Section]]
+[def __xinclude__ [link quickbook.ref.xinclude xinclude]]
+[def __paragraphs__ [link quickbook.ref.paragraphs Paragraphs]]
+[def __ordered_lists__ [link quickbook.ref.ordered_lists Ordered lists]]
+[def __list_hierarchies__ [link quickbook.ref.list_hierarchies List Hierarchies]]
+[def __long_list_lines__ [link quickbook.ref.long_list_lines Long List Lines]]
+[def __unordered_lists__ [link quickbook.ref.unordered_lists Unordered lists]]
+[def __mixed_lists__ [link quickbook.ref.mixed_lists Mixed lists]]
+[def __code__ [link quickbook.ref.code Code]]
+[def __escape_back__ [link quickbook.ref.escape_back Escaping Back To QuickBook]]
+[def __preformatted__ [link quickbook.ref.preformatted Preformatted]]
+[def __blockquote__ [link quickbook.ref.blockquote Blockquote]]
+[def __heading__ [link quickbook.ref.headings Heading]]
+[def __macros__ [link quickbook.ref.macros Macros]]
+[def __templates__ [link quickbook.ref.templates Templates]]
+[def __predefined_macros__ [link quickbook.ref.predefined_macros Predefined Macros]]
+[def __blurbs__ [link quickbook.ref.blurbs Blurbs]]
+[def __admonitions__ [link quickbook.ref.admonitions Admonitions]]
+[def __tables__ [link quickbook.ref.tables Tables]]
+[def __variable_lists__ [link quickbook.ref.variable_lists Variable Lists]]
+[def __include__ [link quickbook.ref.include Include]]
+[def __import__ [link quickbook.ref.import Import]]
[include introduction.qbk]
[include change_log.qbk]
diff --git a/tools/quickbook/doc/structure.qbk b/tools/quickbook/doc/structure.qbk
index 80e812c2f1..c9a4be9c33 100644
--- a/tools/quickbook/doc/structure.qbk
+++ b/tools/quickbook/doc/structure.qbk
@@ -26,7 +26,7 @@ quickbook allows you to use it now, it isn't recommended as it is
currently a work in progress and subject to change.
]
-[#ref-docinfo]
+[#quickbook.ref.docinfo]
[section:docinfo Document Info]
Every document must begin with a Document Info section, which looks something
@@ -73,6 +73,7 @@ So the documentation for the 'foo' library might start:
]
```
+[#quickbook.ref.attributes]
[section:attributes Document Info Attributes]
The document info block has a few different types of attributes.
@@ -145,6 +146,7 @@ that's just ignored by the style sheets.
[endsect] [/docinfo]
+[#quickbook.ref.section]
[section:section Sections]
Quickbook documents are structured using 'sections'. These are used
@@ -173,11 +175,12 @@ A sectioned document might look like:
```
Sections start with the `section` tag, and end with the `[endsect]` tag.
-(`[/...]` is a comment, [link quickbook.syntax.comments described later]).
+(`[/...]` is a comment, [link quickbook.ref.comments described later]).
Sections can be given an optional id:
```
+[#quickbook.ref.id]
[section:id The Section Title]
```
diff --git a/tools/quickbook/doc/syntax.qbk b/tools/quickbook/doc/syntax.qbk
index 2c3c41e465..5088278fc3 100644
--- a/tools/quickbook/doc/syntax.qbk
+++ b/tools/quickbook/doc/syntax.qbk
@@ -28,7 +28,8 @@ Phrases in each block cannot contain a block terminator. This way, syntax errors
such as un-matched closing brackets do not go haywire and corrupt anything past
a single block.
-[section Comments]
+[#quickbook.ref.comments]
+[section:comments Comments]
Can be placed anywhere.
@@ -50,5 +51,4 @@ Can be placed anywhere.
[/ for testing [*only ] ]
-[endsect] [/Comments]
-
+[endsect] [/comments]
diff --git a/tools/quickbook/src/Jamfile.v2 b/tools/quickbook/src/Jamfile.v2
index 9372559492..0c55c7ae8b 100644
--- a/tools/quickbook/src/Jamfile.v2
+++ b/tools/quickbook/src/Jamfile.v2
@@ -15,6 +15,8 @@ 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 ;
@@ -24,7 +26,7 @@ exe quickbook
quickbook.cpp
actions.cpp
doc_info_actions.cpp
- actions_class.cpp
+ state.cpp
utils.cpp
files.cpp
string_ref.cpp
diff --git a/tools/quickbook/src/actions.cpp b/tools/quickbook/src/actions.cpp
index 4802893cb1..304663ffe1 100644
--- a/tools/quickbook/src/actions.cpp
+++ b/tools/quickbook/src/actions.cpp
@@ -12,8 +12,9 @@
#include <functional>
#include <vector>
#include <map>
-#include <boost/filesystem/v3/convenience.hpp>
-#include <boost/filesystem/v3/fstream.hpp>
+#include <set>
+#include <boost/filesystem/convenience.hpp>
+#include <boost/filesystem/fstream.hpp>
#include <boost/range/distance.hpp>
#include <boost/range/algorithm/replace.hpp>
#include <boost/lexical_cast.hpp>
@@ -25,8 +26,8 @@
#include "utils.hpp"
#include "files.hpp"
#include "markups.hpp"
-#include "actions_class.hpp"
-#include "actions_state.hpp"
+#include "state.hpp"
+#include "state_save.hpp"
#include "grammar.hpp"
#include "input_path.hpp"
#include "block_tags.hpp"
@@ -35,17 +36,22 @@
namespace quickbook
{
- char const* quickbook_get_date = "__quickbook_get_date__";
- char const* quickbook_get_time = "__quickbook_get_time__";
-
- unsigned qbk_version_n = 0; // qbk_major_version * 100 + qbk_minor_version
-
namespace {
- void write_anchors(quickbook::actions& actions, collector& tgt)
+ void write_anchors(quickbook::state& state, collector& tgt)
{
- for(quickbook::actions::string_list::iterator
- it = actions.anchors.begin(),
- end = actions.anchors.end();
+ // 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())
+ << "Temporary source mode unsupported here."
+ << std::endl;
+ state.source_mode_next = value();
+ }
+
+ for(quickbook::state::string_list::iterator
+ it = state.anchors.begin(),
+ end = state.anchors.end();
it != end; ++it)
{
tgt << "<anchor id=\"";
@@ -53,46 +59,52 @@ namespace quickbook
tgt << "\"/>";
}
- actions.anchors.clear();
+ state.anchors.clear();
}
- std::string add_anchor(quickbook::actions& actions,
+ std::string add_anchor(quickbook::state& state,
std::string const& id,
id_category::categories category =
id_category::explicit_anchor_id)
{
- std::string placeholder = actions.ids.add_anchor(id, category);
- actions.anchors.push_back(placeholder);
+ std::string placeholder = state.ids.add_anchor(id, category);
+ state.anchors.push_back(placeholder);
return placeholder;
}
}
- void explicit_list_action(quickbook::actions&, value);
- void header_action(quickbook::actions&, value);
- void begin_section_action(quickbook::actions&, value);
- void end_section_action(quickbook::actions&, value, string_iterator);
- void block_action(quickbook::actions&, value);
- void block_empty_action(quickbook::actions&, value);
- void macro_definition_action(quickbook::actions&, value);
- void template_body_action(quickbook::actions&, value);
- void variable_list_action(quickbook::actions&, value);
- void table_action(quickbook::actions&, value);
- void xinclude_action(quickbook::actions&, value);
- void include_action(quickbook::actions&, value, string_iterator);
- void image_action(quickbook::actions&, value);
- void anchor_action(quickbook::actions&, value);
- void link_action(quickbook::actions&, value);
- void phrase_action(quickbook::actions&, value);
- void role_action(quickbook::actions&, value);
- void footnote_action(quickbook::actions&, value);
- void raw_phrase_action(quickbook::actions&, value);
- void source_mode_action(quickbook::actions&, value);
- void do_template_action(quickbook::actions&, value, string_iterator);
+ bool quickbook_range::in_range() const {
+ return qbk_version_n >= lower && qbk_version_n < upper;
+ }
+
+ void explicit_list_action(quickbook::state&, value);
+ void header_action(quickbook::state&, value);
+ void begin_section_action(quickbook::state&, value);
+ void end_section_action(quickbook::state&, value, string_iterator);
+ void block_action(quickbook::state&, value);
+ void block_empty_action(quickbook::state&, value);
+ void macro_definition_action(quickbook::state&, value);
+ void template_body_action(quickbook::state&, value);
+ void variable_list_action(quickbook::state&, value);
+ void table_action(quickbook::state&, value);
+ void xinclude_action(quickbook::state&, value);
+ void include_action(quickbook::state&, value, string_iterator);
+ void image_action(quickbook::state&, value);
+ void anchor_action(quickbook::state&, value);
+ void link_action(quickbook::state&, value);
+ void phrase_action(quickbook::state&, value);
+ void role_action(quickbook::state&, value);
+ void footnote_action(quickbook::state&, value);
+ void raw_phrase_action(quickbook::state&, value);
+ void source_mode_action(quickbook::state&, value);
+ void next_source_mode_action(quickbook::state&, value);
+ void code_action(quickbook::state&, value);
+ void do_template_action(quickbook::state&, value, string_iterator);
void element_action::operator()(parse_iterator first, parse_iterator) const
{
- value_consumer values = actions.values.release();
- if(!values.check() || !actions.conditional) return;
+ value_consumer values = state.values.release();
+ if(!values.check() || !state.conditional) return;
value v = values.consume();
values.finish();
@@ -100,7 +112,7 @@ namespace quickbook
{
case block_tags::ordered_list:
case block_tags::itemized_list:
- return explicit_list_action(actions, v);
+ return explicit_list_action(state, v);
case block_tags::generic_heading:
case block_tags::heading1:
case block_tags::heading2:
@@ -108,11 +120,11 @@ namespace quickbook
case block_tags::heading4:
case block_tags::heading5:
case block_tags::heading6:
- return header_action(actions, v);
+ return header_action(state, v);
case block_tags::begin_section:
- return begin_section_action(actions, v);
+ return begin_section_action(state, v);
case block_tags::end_section:
- return end_section_action(actions, v, first.base());
+ return end_section_action(state, v, first.base());
case block_tags::blurb:
case block_tags::preformatted:
case block_tags::blockquote:
@@ -122,26 +134,26 @@ namespace quickbook
case block_tags::note:
case block_tags::tip:
case block_tags::block:
- return block_action(actions,v);
+ return block_action(state,v);
case block_tags::hr:
- return block_empty_action(actions,v);
+ return block_empty_action(state,v);
case block_tags::macro_definition:
- return macro_definition_action(actions,v);
+ return macro_definition_action(state,v);
case block_tags::template_definition:
- return template_body_action(actions,v);
+ return template_body_action(state,v);
case block_tags::variable_list:
- return variable_list_action(actions, v);
+ return variable_list_action(state, v);
case block_tags::table:
- return table_action(actions, v);
+ return table_action(state, v);
case block_tags::xinclude:
- return xinclude_action(actions, v);
+ return xinclude_action(state, v);
case block_tags::import:
case block_tags::include:
- return include_action(actions, v, first.base());
+ return include_action(state, v, first.base());
case phrase_tags::image:
- return image_action(actions, v);
+ return image_action(state, v);
case phrase_tags::anchor:
- return anchor_action(actions, v);
+ return anchor_action(state, v);
case phrase_tags::url:
case phrase_tags::link:
case phrase_tags::funcref:
@@ -152,7 +164,7 @@ namespace quickbook
case phrase_tags::headerref:
case phrase_tags::conceptref:
case phrase_tags::globalref:
- return link_action(actions, v);
+ return link_action(state, v);
case phrase_tags::bold:
case phrase_tags::italic:
case phrase_tags::underline:
@@ -160,19 +172,25 @@ namespace quickbook
case phrase_tags::strikethrough:
case phrase_tags::quote:
case phrase_tags::replaceable:
- return phrase_action(actions, v);
+ return phrase_action(state, v);
case phrase_tags::footnote:
- return footnote_action(actions, v);
+ return footnote_action(state, v);
case phrase_tags::escape:
- return raw_phrase_action(actions, v);
+ return raw_phrase_action(state, v);
case phrase_tags::role:
- return role_action(actions, v);
+ return role_action(state, v);
case source_mode_tags::cpp:
case source_mode_tags::python:
case source_mode_tags::teletype:
- return source_mode_action(actions, v);
+ return source_mode_action(state, v);
+ case code_tags::next_source_mode:
+ return next_source_mode_action(state, v);
+ case code_tags::code_block:
+ case code_tags::inline_code_block:
+ case code_tags::inline_code:
+ return code_action(state, v);
case template_tags::template_:
- return do_template_action(actions, v, first.base());
+ return do_template_action(state, v, first.base());
default:
break;
}
@@ -180,22 +198,22 @@ namespace quickbook
void break_action::operator()(parse_iterator first, parse_iterator) const
{
- write_anchors(actions, phrase);
+ write_anchors(state, phrase);
if(*first == '\\')
{
- detail::outwarn(actions.current_file, first.base())
+ detail::outwarn(state.current_file, first.base())
//<< "in column:" << pos.column << ", "
<< "'\\n' is deprecated, pleases use '[br]' instead" << ".\n";
}
- if(!actions.warned_about_breaks)
+ if(!state.warned_about_breaks)
{
- detail::outwarn(actions.current_file, first.base())
+ detail::outwarn(state.current_file, first.base())
<< "line breaks generate invalid boostbook "
"(will only note first occurrence).\n";
- actions.warned_about_breaks = true;
+ state.warned_about_breaks = true;
}
phrase << detail::get_markup(phrase_tags::break_mark).pre;
@@ -203,7 +221,7 @@ namespace quickbook
void error_message_action::operator()(parse_iterator first, parse_iterator last) const
{
- file_position const pos = actions.current_file->position_of(first.base());
+ file_position const pos = state.current_file->position_of(first.base());
std::string value(first, last);
std::string formatted_message = message;
@@ -211,91 +229,91 @@ namespace quickbook
boost::replace_all(formatted_message, "%c",
boost::lexical_cast<std::string>(pos.column));
- detail::outerr(actions.current_file->path, pos.line)
- << detail::utf8(formatted_message) << std::endl;
- ++actions.error_count;
+ detail::outerr(state.current_file->path, pos.line)
+ << formatted_message << std::endl;
+ ++state.error_count;
}
void error_action::operator()(parse_iterator first, parse_iterator /*last*/) const
{
- file_position const pos = actions.current_file->position_of(first.base());
+ file_position const pos = state.current_file->position_of(first.base());
- detail::outerr(actions.current_file->path, pos.line)
+ detail::outerr(state.current_file->path, pos.line)
<< "Syntax Error near column " << pos.column << ".\n";
- ++actions.error_count;
+ ++state.error_count;
}
- void block_action(quickbook::actions& actions, value block)
+ void block_action(quickbook::state& state, value block)
{
- write_anchors(actions, actions.out);
+ write_anchors(state, state.out);
detail::markup markup = detail::get_markup(block.get_tag());
value_consumer values = block;
- actions.out << markup.pre << values.consume().get_encoded() << markup.post;
+ state.out << markup.pre << values.consume().get_encoded() << markup.post;
values.finish();
}
- void block_empty_action(quickbook::actions& actions, value block)
+ void block_empty_action(quickbook::state& state, value block)
{
- write_anchors(actions, actions.out);
+ write_anchors(state, state.out);
detail::markup markup = detail::get_markup(block.get_tag());
- actions.out << markup.pre;
+ state.out << markup.pre;
}
- void phrase_action(quickbook::actions& actions, value phrase)
+ void phrase_action(quickbook::state& state, value phrase)
{
- write_anchors(actions, actions.phrase);
+ write_anchors(state, state.phrase);
detail::markup markup = detail::get_markup(phrase.get_tag());
value_consumer values = phrase;
- actions.phrase << markup.pre << values.consume().get_encoded() << markup.post;
+ state.phrase << markup.pre << values.consume().get_encoded() << markup.post;
values.finish();
}
- void role_action(quickbook::actions& actions, value role)
+ void role_action(quickbook::state& state, value role)
{
- write_anchors(actions, actions.phrase);
+ write_anchors(state, state.phrase);
value_consumer values = role;
- actions.phrase
+ state.phrase
<< "<phrase role=\"";
- detail::print_string(values.consume().get_quickbook(), actions.phrase.get());
- actions.phrase
+ detail::print_string(values.consume().get_quickbook(), state.phrase.get());
+ state.phrase
<< "\">"
<< values.consume().get_encoded()
<< "</phrase>";
values.finish();
}
- void footnote_action(quickbook::actions& actions, value phrase)
+ void footnote_action(quickbook::state& state, value phrase)
{
- write_anchors(actions, actions.phrase);
+ write_anchors(state, state.phrase);
value_consumer values = phrase;
- actions.phrase
+ state.phrase
<< "<footnote id=\""
- << actions.ids.add_id("f", id_category::numbered)
+ << state.ids.add_id("f", id_category::numbered)
<< "\"><para>"
<< values.consume().get_encoded()
<< "</para></footnote>";
values.finish();
}
- void raw_phrase_action(quickbook::actions& actions, value phrase)
+ void raw_phrase_action(quickbook::state& state, value phrase)
{
- write_anchors(actions, actions.phrase);
+ write_anchors(state, state.phrase);
detail::markup markup = detail::get_markup(phrase.get_tag());
- actions.phrase << markup.pre << phrase.get_quickbook() << markup.post;
+ state.phrase << markup.pre << phrase.get_quickbook() << markup.post;
}
void paragraph_action::operator()() const
{
std::string str;
- actions.phrase.swap(str);
+ state.phrase.swap(str);
std::string::const_iterator
pos = str.begin(),
@@ -305,53 +323,61 @@ namespace quickbook
if(pos != end) {
detail::markup markup = detail::get_markup(block_tags::paragraph);
- actions.out << markup.pre << str;
- write_anchors(actions, actions.out);
- actions.out << markup.post;
+ state.out << markup.pre << str;
+ write_anchors(state, state.out);
+ state.out << markup.post;
}
}
void list_item_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;
- actions.phrase.swap(str);
- actions.out << str;
- write_anchors(actions, actions.out);
+ state.phrase.swap(str);
+ state.out << str;
+ write_anchors(state, state.out);
}
void phrase_end_action::operator()() const
{
- write_anchors(actions, actions.phrase);
+ write_anchors(state, state.phrase);
}
namespace {
- void write_bridgehead(quickbook::actions& actions, int level,
+ void write_bridgehead(quickbook::state& state, int level,
std::string const& str, std::string const& id, bool self_link)
{
if (self_link && !id.empty())
{
- actions.out << "<bridgehead renderas=\"sect" << level << "\"";
- actions.out << " id=\"";
- actions.out << actions.ids.add_id("h", id_category::numbered);
- actions.out << "\">";
- actions.out << "<phrase id=\"" << id << "\"/>";
- actions.out << "<link linkend=\"" << id << "\">";
- actions.out << str;
- actions.out << "</link>";
- actions.out << "</bridgehead>";
+ state.out << "<bridgehead renderas=\"sect" << level << "\"";
+ state.out << " id=\"";
+ state.out << state.ids.add_id("h", id_category::numbered);
+ state.out << "\">";
+ state.out << "<phrase id=\"" << id << "\"/>";
+ state.out << "<link linkend=\"" << id << "\">";
+ state.out << str;
+ state.out << "</link>";
+ state.out << "</bridgehead>";
}
else
{
- actions.out << "<bridgehead renderas=\"sect" << level << "\"";
- if(!id.empty()) actions.out << " id=\"" << id << "\"";
- actions.out << ">";
- actions.out << str;
- actions.out << "</bridgehead>";
+ state.out << "<bridgehead renderas=\"sect" << level << "\"";
+ if(!id.empty()) state.out << " id=\"" << id << "\"";
+ state.out << ">";
+ state.out << str;
+ state.out << "</bridgehead>";
}
}
}
- void header_action(quickbook::actions& actions, value heading_list)
+ void header_action(quickbook::state& state, value heading_list)
{
value_consumer values = heading_list;
@@ -364,7 +390,7 @@ namespace quickbook
if (generic)
{
- level = actions.ids.section_level() + 1;
+ level = state.ids.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
@@ -375,51 +401,51 @@ namespace quickbook
level = heading_list.get_tag() - block_tags::heading1 + 1;
}
- write_anchors(actions, actions.out);
+ write_anchors(state, state.out);
if (!element_id.empty())
{
- std::string anchor = actions.ids.add_id(
+ std::string anchor = state.ids.add_id(
element_id.get_quickbook(),
id_category::explicit_id);
- write_bridgehead(actions, level,
+ write_bridgehead(state, level,
content.get_encoded(), anchor, self_linked_headers);
}
- else if (!generic && actions.ids.compatibility_version() < 103) // version 1.2 and below
+ else if (!generic && state.ids.compatibility_version() < 103) // version 1.2 and below
{
// This generates the old id style if both the interpreting
// version and the generation version are less then 103u.
- std::string anchor = actions.ids.old_style_id(
+ std::string anchor = state.ids.old_style_id(
detail::make_identifier(
- actions.ids.replace_placeholders_with_unresolved_ids(
+ state.ids.replace_placeholders_with_unresolved_ids(
content.get_encoded())),
id_category::generated_heading);
- write_bridgehead(actions, level,
+ write_bridgehead(state, level,
content.get_encoded(), anchor, false);
}
else
{
- std::string anchor = actions.ids.add_id(
+ std::string anchor = state.ids.add_id(
detail::make_identifier(
- actions.ids.compatibility_version() >= 106 ?
+ state.ids.compatibility_version() >= 106 ?
content.get_quickbook() :
- actions.ids.replace_placeholders_with_unresolved_ids(
+ state.ids.replace_placeholders_with_unresolved_ids(
content.get_encoded())
),
id_category::generated_heading);
- write_bridgehead(actions, level,
+ write_bridgehead(state, level,
content.get_encoded(), anchor, self_linked_headers);
}
}
void simple_phrase_action::operator()(char mark) const
{
- write_anchors(actions, out);
+ write_anchors(state, out);
int tag =
mark == '*' ? phrase_tags::bold :
@@ -431,7 +457,7 @@ namespace quickbook
assert(tag != 0);
detail::markup markup = detail::get_markup(tag);
- value_consumer values = actions.values.release();
+ value_consumer values = state.values.release();
value content = values.consume();
values.finish();
@@ -442,21 +468,21 @@ namespace quickbook
bool cond_phrase_push::start()
{
- value_consumer values = actions.values.release();
+ value_consumer values = state.values.release();
- saved_conditional = actions.conditional;
+ saved_conditional = state.conditional;
if (saved_conditional)
{
string_ref macro1 = values.consume().get_quickbook();
std::string macro(macro1.begin(), macro1.end());
- actions.conditional = find(actions.macro, macro.c_str());
+ state.conditional = find(state.macro, macro.c_str());
- if (!actions.conditional) {
- actions.phrase.push();
- actions.out.push();
- actions.anchors.swap(anchors);
+ if (!state.conditional) {
+ state.phrase.push();
+ state.out.push();
+ state.anchors.swap(anchors);
}
}
@@ -465,14 +491,14 @@ namespace quickbook
void cond_phrase_push::cleanup()
{
- if (saved_conditional && !actions.conditional)
+ if (saved_conditional && !state.conditional)
{
- actions.phrase.pop();
- actions.out.pop();
- actions.anchors.swap(anchors);
+ state.phrase.pop();
+ state.out.pop();
+ state.anchors.swap(anchors);
}
- actions.conditional = saved_conditional;
+ state.conditional = saved_conditional;
}
namespace {
@@ -494,64 +520,141 @@ namespace quickbook
}
}
- void actions::start_list(char mark)
+ void state::start_list(char mark)
{
write_anchors(*this, out);
assert(mark == '*' || mark == '#');
out << ((mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
}
- void actions::end_list(char mark)
+ void state::end_list(char mark)
{
write_anchors(*this, out);
assert(mark == '*' || mark == '#');
out << ((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
}
- void actions::start_list_item()
+ void state::start_list_item()
{
out << "<listitem><simpara>";
write_anchors(*this, out);
}
- void actions::end_list_item()
+ void state::end_list_item()
{
write_anchors(*this, out);
out << "</simpara></listitem>";
}
- void explicit_list_action(quickbook::actions& actions, value list)
+ namespace
+ {
+ bool parse_template(value const&, quickbook::state& state);
+ }
+
+ void state::start_callouts()
+ {
+ ++callout_depth;
+ }
+
+ 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);
+
+ callouts.insert(encoded_value(callout_id1));
+ callouts.insert(encoded_value(callout_id2));
+ callouts.insert(v);
+
+ std::string code;
+ code += "<co id=\"" + callout_id1 + "\" ";
+ code += "linkends=\"" + callout_id2 + "\" />";
+
+ return code;
+ }
+
+ std::string state::end_callouts()
{
- write_anchors(actions, actions.out);
+ assert(callout_depth > 0);
+ std::string block;
+
+ --callout_depth;
+ if (callout_depth > 0) return block;
+
+ value_consumer c = callouts.release();
+ if (!c.check()) return block;
+
+ block += "<calloutlist>";
+ while (c.check())
+ {
+ std::string callout_id1 = c.consume().get_encoded();
+ std::string callout_id2 = c.consume().get_encoded();
+ value callout_body = c.consume();
+
+ std::string callout_value;
+
+ {
+ template_state state(*this);
+ ++template_depth;
+
+ bool r = parse_template(callout_body, *this);
+
+ if(!r)
+ {
+ detail::outerr(callout_body.get_file(), callout_body.get_position())
+ << "Expanding callout." << std::endl
+ << "------------------begin------------------" << std::endl
+ << callout_body.get_quickbook()
+ << std::endl
+ << "------------------end--------------------" << std::endl
+ ;
+ ++error_count;
+ }
+
+ out.swap(callout_value);
+ }
+
+ block += "<callout arearefs=\"" + callout_id1 + "\" ";
+ block += "id=\"" + callout_id2 + "\">";
+ block += callout_value;
+ block += "</callout>";
+ }
+ block += "</calloutlist>";
+
+ return block;
+ }
+
+ void explicit_list_action(quickbook::state& state, value list)
+ {
+ write_anchors(state, state.out);
detail::markup markup = detail::get_markup(list.get_tag());
- actions.out << markup.pre;
+ state.out << markup.pre;
BOOST_FOREACH(value item, list)
{
- actions.out << "<listitem>";
- actions.out << item.get_encoded();
- actions.out << "</listitem>";
+ state.out << "<listitem>";
+ state.out << item.get_encoded();
+ state.out << "</listitem>";
}
- actions.out << markup.post;
+ state.out << markup.post;
}
- void anchor_action(quickbook::actions& actions, value anchor)
+ void anchor_action(quickbook::state& state, value anchor)
{
value_consumer values = anchor;
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(actions, anchor_id.is_encoded() ?
+ add_anchor(state, anchor_id.is_encoded() ?
anchor_id.get_encoded() : anchor_id.get_quickbook());
values.finish();
}
void do_macro_action::operator()(std::string const& str) const
{
- write_anchors(actions, phrase);
+ write_anchors(state, phrase);
if (str == quickbook_get_date)
{
@@ -582,56 +685,69 @@ namespace quickbook
out << *first++;
}
- void source_mode_action(quickbook::actions& actions, value source_mode)
+ void source_mode_action(quickbook::state& state, value source_mode)
+ {
+ state.source_mode = source_mode_tags::name(source_mode.get_tag());
+ }
+
+ void next_source_mode_action(quickbook::state& state, value source_mode)
{
- actions.source_mode = source_mode_tags::name(source_mode.get_tag());
+ value_consumer values = source_mode;
+ state.source_mode_next = values.consume();
+ values.finish();
}
- void code_action::operator()(parse_iterator first, parse_iterator last) const
+ void code_action(quickbook::state& state, value code_block)
{
- bool inline_code = type == inline_ ||
- (type == inline_block && qbk_version_n < 106u);
- bool block = type != inline_;
+ int code_tag = code_block.get_tag();
+
+ value_consumer values = code_block;
+ 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();
if (inline_code) {
- write_anchors(actions, actions.phrase);
+ write_anchors(state, state.phrase);
}
else {
- actions.paragraph();
- write_anchors(actions, actions.out);
+ paragraph_action para(state);
+ para();
+ write_anchors(state, state.out);
}
- std::string str;
-
if (block) {
// preprocess the code section to remove the initial indentation
mapped_file_builder mapped;
- mapped.start(actions.current_file);
- mapped.unindent_and_add(first.base(), last.base());
+ mapped.start(state.current_file);
+ mapped.unindent_and_add(code_value.begin(), code_value.end());
file_ptr f = mapped.release();
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());
file_ptr saved_file = f;
- boost::swap(actions.current_file, saved_file);
+ boost::swap(state.current_file, saved_file);
// print the code with syntax coloring
- str = syntax_highlight(first_, last_, actions, actions.source_mode);
+ std::string str = syntax_highlight(first_, last_, state,
+ source_mode, block);
- boost::swap(actions.current_file, saved_file);
- }
- else {
- parse_iterator first_(first);
- str = syntax_highlight(first_, last, actions, actions.source_mode);
- }
+ boost::swap(state.current_file, saved_file);
- if (block) {
- collector& output = inline_code ? actions.phrase : actions.out;
+ collector& output = inline_code ? state.phrase : state.out;
// We must not place a \n after the <programlisting> tag
// otherwise PDF output starts code blocks with a blank line:
@@ -639,24 +755,31 @@ namespace quickbook
output << "<programlisting>";
output << str;
output << "</programlisting>\n";
+
+ if (qbk_version_n >= 107u) output << state.end_callouts();
}
else {
- actions.phrase << "<code>";
- actions.phrase << str;
- actions.phrase << "</code>";
+ 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;
+ state.phrase << "</code>";
}
}
void plain_char_action::operator()(char ch) const
{
- write_anchors(actions, phrase);
+ write_anchors(state, phrase);
detail::print_char(ch, phrase.get());
}
void plain_char_action::operator()(parse_iterator first, parse_iterator last) const
{
- write_anchors(actions, phrase);
+ write_anchors(state, phrase);
while (first != last)
detail::print_char(*first++, phrase.get());
@@ -664,7 +787,7 @@ namespace quickbook
void escape_unicode_action::operator()(parse_iterator first, parse_iterator last) const
{
- write_anchors(actions, phrase);
+ write_anchors(state, phrase);
while(first != last && *first == '0') ++first;
@@ -701,9 +824,9 @@ namespace quickbook
}
}
- void image_action(quickbook::actions& actions, value image)
+ void image_action(quickbook::state& state, value image)
{
- write_anchors(actions, actions.phrase);
+ write_anchors(state, state.phrase);
// Note: attributes are never encoded as boostbook, if they're
// encoded, it's just things like escapes.
@@ -723,7 +846,7 @@ namespace quickbook
{
detail::outwarn(name.get_file(), name.get_position())
<< "Duplicate image attribute: "
- << detail::utf8(name.get_quickbook())
+ << name.get_quickbook()
<< std::endl;
}
}
@@ -748,10 +871,10 @@ namespace quickbook
detail::outerr(attributes["fileref"].get_file(), attributes["fileref"].get_position()) :
detail::outwarn(attributes["fileref"].get_file(), attributes["fileref"].get_position()))
<< "Image path isn't portable: '"
- << detail::utf8(fileref)
+ << fileref
<< "'"
<< std::endl;
- if (qbk_version_n >= 106u) ++actions.error_count;
+ if (qbk_version_n >= 106u) ++state.error_count;
}
boost::replace(fileref, '\\', '/');
@@ -814,10 +937,13 @@ namespace quickbook
// Now load the SVG file:
//
std::string svg_text;
- fs::ifstream fs(img);
- char c;
- while(fs.get(c) && fs.good())
- svg_text.push_back(c);
+ if (state.add_dependency(img)) {
+ fs::ifstream fs(img);
+ std::stringstream buffer;
+ buffer << fs.rdbuf();
+ svg_text = buffer.str();
+ }
+
//
// Extract the svg header from the file:
//
@@ -853,31 +979,31 @@ namespace quickbook
}
}
- actions.phrase << "<inlinemediaobject>";
+ state.phrase << "<inlinemediaobject>";
- actions.phrase << "<imageobject><imagedata";
+ state.phrase << "<imageobject><imagedata";
BOOST_FOREACH(attribute_map::value_type const& attr, attributes)
{
- actions.phrase << " " << attr.first << "=\"";
- write_plain_text(actions.phrase.get(), attr.second);
- actions.phrase << "\"";
+ state.phrase << " " << attr.first << "=\"";
+ write_plain_text(state.phrase.get(), attr.second);
+ state.phrase << "\"";
}
- actions.phrase << "></imagedata></imageobject>";
+ state.phrase << "></imagedata></imageobject>";
// Add a textobject containing the alt tag from earlier.
// This will be used for the alt tag in html.
if (alt_text.check()) {
- actions.phrase << "<textobject><phrase>";
- write_plain_text(actions.phrase.get(), alt_text);
- actions.phrase << "</phrase></textobject>";
+ state.phrase << "<textobject><phrase>";
+ write_plain_text(state.phrase.get(), alt_text);
+ state.phrase << "</phrase></textobject>";
}
- actions.phrase << "</inlinemediaobject>";
+ state.phrase << "</inlinemediaobject>";
}
- void macro_definition_action(quickbook::actions& actions, quickbook::value macro_definition)
+ void macro_definition_action(quickbook::state& state, quickbook::value macro_definition)
{
value_consumer values = macro_definition;
std::string macro_id = values.consume().get_quickbook();
@@ -887,7 +1013,7 @@ namespace quickbook
values.finish();
std::string* existing_macro =
- boost::spirit::classic::find(actions.macro, macro_id.c_str());
+ boost::spirit::classic::find(state.macro, macro_id.c_str());
quickbook::ignore_variable(&existing_macro);
if (existing_macro)
@@ -900,13 +1026,13 @@ namespace quickbook
// return;
}
- actions.macro.add(
+ state.macro.add(
macro_id.begin()
, macro_id.end()
, phrase);
}
- void template_body_action(quickbook::actions& actions, quickbook::value template_definition)
+ void template_body_action(quickbook::state& state, quickbook::value template_definition)
{
value_consumer values = template_definition;
std::string identifier = values.consume().get_quickbook();
@@ -920,16 +1046,16 @@ namespace quickbook
value body = values.consume();
BOOST_ASSERT(!values.check());
- if (!actions.templates.add(
+ if (!state.templates.add(
template_symbol(
identifier,
template_values,
body,
- &actions.templates.top_scope())))
+ &state.templates.top_scope())))
{
detail::outwarn(body.get_file(), body.get_position())
- << "Template Redefinition: " << detail::utf8(identifier) << std::endl;
- ++actions.error_count;
+ << "Template Redefinition: " << identifier << std::endl;
+ ++state.error_count;
}
}
@@ -1050,7 +1176,7 @@ namespace quickbook
, std::vector<std::string> const& params
, template_scope const& scope
, string_iterator first
- , quickbook::actions& actions
+ , quickbook::state& state
)
{
std::vector<value>::const_iterator arg = args.begin();
@@ -1060,12 +1186,12 @@ namespace quickbook
// Store each of the argument passed in as local templates:
while (arg != args.end())
{
- if (!actions.templates.add(
+ if (!state.templates.add(
template_symbol(*tpl, empty_params, *arg, &scope)))
{
- detail::outerr(actions.current_file, first)
+ detail::outerr(state.current_file, first)
<< "Duplicate Symbol Found" << std::endl;
- ++actions.error_count;
+ ++state.error_count;
return std::make_pair(false, tpl);
}
++arg; ++tpl;
@@ -1075,47 +1201,50 @@ namespace quickbook
bool parse_template(
value const& content
- , quickbook::actions& actions
+ , quickbook::state& state
)
{
- file_ptr saved_current_file = actions.current_file;
+ file_ptr saved_current_file = state.current_file;
- actions.current_file = content.get_file();
+ state.current_file = content.get_file();
string_ref source = content.get_quickbook();
parse_iterator first(source.begin());
parse_iterator last(source.end());
bool r = cl::parse(first, last,
- content.get_tag() == template_tags::block ?
- actions.grammar().block :
- actions.grammar().inline_phrase
+ content.get_tag() == template_tags::phrase ?
+ state.grammar().inline_phrase :
+ state.grammar().block
).full;
- boost::swap(actions.current_file, saved_current_file);
+ boost::swap(state.current_file, saved_current_file);
return r;
}
}
- void call_template(quickbook::actions& actions,
+ void call_template(quickbook::state& state,
template_symbol const* symbol,
std::vector<value> const& args,
string_iterator first)
{
+ bool is_block = symbol->content.get_tag() != template_tags::phrase;
+
// 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 (symbol->content.get_tag() == template_tags::block)
+ if (is_block)
{
- actions.paragraph();
- actions.out << symbol->content.get_encoded();
+ paragraph_action para(state);
+ para();
+ state.out << symbol->content.get_encoded();
}
else
{
- actions.phrase << symbol->content.get_encoded();
+ state.phrase << symbol->content.get_encoded();
}
return;
@@ -1126,36 +1255,36 @@ namespace quickbook
//
// Note that for quickbook 1.4- this value is just ignored when the
// arguments are expanded.
- template_scope const& call_scope = actions.templates.top_scope();
+ template_scope const& call_scope = state.templates.top_scope();
std::string block;
std::string phrase;
{
- template_state state(actions);
- actions.templates.start_template(symbol);
+ template_state save(state);
+ state.templates.start_template(symbol);
qbk_version_n = symbol->content.get_file()->version();
- ++actions.template_depth;
- if (actions.template_depth > actions.max_template_depth)
+ ++state.template_depth;
+ if (state.template_depth > state.max_template_depth)
{
- detail::outerr(actions.current_file, first)
+ detail::outerr(state.current_file, first)
<< "Infinite loop detected" << std::endl;
- ++actions.error_count;
+ ++state.error_count;
return;
}
// Store the current section level so that we can ensure that
// [section] and [endsect] tags in the template are balanced.
- actions.min_section_level = actions.ids.section_level();
+ state.min_section_level = state.ids.section_level();
///////////////////////////////////
// Prepare the arguments as local templates
bool get_arg_result;
std::vector<std::string>::const_iterator tpl;
boost::tie(get_arg_result, tpl) =
- get_arguments(args, symbol->params, call_scope, first, actions);
+ get_arguments(args, symbol->params, call_scope, first, state);
if (!get_arg_result)
{
@@ -1165,128 +1294,67 @@ namespace quickbook
///////////////////////////////////
// parse the template body:
- if (!parse_template(symbol->content, actions))
+ if (!parse_template(symbol->content, state))
{
- detail::outerr(actions.current_file, first)
+ detail::outerr(state.current_file, first)
<< "Expanding "
- << (symbol->content.get_tag() == template_tags::block ? "block" : "phrase")
- << " template: " << detail::utf8(symbol->identifier) << std::endl
+ << (is_block ? "block" : "phrase")
+ << " template: " << symbol->identifier << std::endl
<< std::endl
<< "------------------begin------------------" << std::endl
- << detail::utf8(symbol->content.get_quickbook())
+ << symbol->content.get_quickbook()
<< "------------------end--------------------" << std::endl
<< std::endl;
- ++actions.error_count;
+ ++state.error_count;
return;
}
- if (actions.ids.section_level() != actions.min_section_level)
+ if (state.ids.section_level() != state.min_section_level)
{
- detail::outerr(actions.current_file, first)
+ detail::outerr(state.current_file, first)
<< "Mismatched sections in template "
- << detail::utf8(symbol->identifier)
+ << symbol->identifier
<< std::endl;
- ++actions.error_count;
+ ++state.error_count;
return;
}
- actions.out.swap(block);
- actions.phrase.swap(phrase);
+ state.out.swap(block);
+ state.phrase.swap(phrase);
}
- if(symbol->content.get_tag() == template_tags::block || !block.empty()) {
- actions.paragraph(); // For paragraphs before the template call.
- actions.out << block;
- actions.phrase << phrase;
- actions.paragraph();
+ if(is_block || !block.empty()) {
+ paragraph_action para(state);
+ para(); // For paragraphs before the template call.
+ state.out << block;
+ state.phrase << phrase;
+ para();
}
else {
- actions.phrase << phrase;
+ state.phrase << phrase;
}
}
- void call_code_snippet(quickbook::actions& actions,
+ void call_code_snippet(quickbook::state& state,
template_symbol const* symbol,
string_iterator first)
{
- value_consumer values = symbol->content;
- value content = values.consume(template_tags::block);
- value callouts = values.consume();
- values.finish();
-
- std::vector<std::string> callout_ids;
+ assert(symbol->params.size() == 0);
std::vector<value> args;
- unsigned int size = symbol->params.size();
- std::string callout_base("c");
-
- for(unsigned int i = 0; i < size; ++i)
- {
- std::string callout_id1 = actions.ids.add_id(callout_base, id_category::numbered);
- std::string callout_id2 = actions.ids.add_id(callout_base, id_category::numbered);
-
- std::string code;
- code += "<co id=\"" + callout_id1 + "\" ";
- code += "linkends=\"" + callout_id2 + "\" />";
-
- args.push_back(encoded_value(code, template_tags::phrase));
- callout_ids.push_back(callout_id1);
- callout_ids.push_back(callout_id2);
- }
// Create a fake symbol for call_template
template_symbol t(
symbol->identifier,
symbol->params,
- content,
+ symbol->content,
symbol->lexical_parent);
- call_template(actions, &t, args, first);
-
- std::string block;
-
- if(!callouts.empty())
- {
- block += "<calloutlist>";
- int i = 0;
- BOOST_FOREACH(value c, callouts)
- {
- std::string callout_id1 = callout_ids[i++];
- std::string callout_id2 = callout_ids[i++];
-
- std::string callout_value;
- {
- template_state state(actions);
- ++actions.template_depth;
-
- bool r = parse_template(c, actions);
-
- if(!r)
- {
- detail::outerr(c.get_file(), c.get_position())
- << "Expanding callout." << std::endl
- << "------------------begin------------------" << std::endl
- << detail::utf8(c.get_quickbook())
- << std::endl
- << "------------------end--------------------" << std::endl
- ;
- ++actions.error_count;
- return;
- }
-
- actions.out.swap(callout_value);
- }
-
- block += "<callout arearefs=\"" + callout_id1 + "\" ";
- block += "id=\"" + callout_id2 + "\">";
- block += callout_value;
- block += "</callout>";
- }
- block += "</calloutlist>";
- }
- actions.out << block;
+ state.start_callouts();
+ call_template(state, &t, args, first);
+ state.out << state.end_callouts();
}
- void do_template_action(quickbook::actions& actions, value template_list,
+ void do_template_action(quickbook::state& state, value template_list,
string_iterator first)
{
// Get the arguments
@@ -1306,7 +1374,7 @@ namespace quickbook
values.finish();
- template_symbol const* symbol = actions.templates.find(identifier);
+ template_symbol const* symbol = state.templates.find(identifier);
BOOST_ASSERT(symbol);
// Deal with escaped templates.
@@ -1315,19 +1383,19 @@ namespace quickbook
{
if (!args.empty())
{
- detail::outerr(actions.current_file, first)
+ detail::outerr(state.current_file, first)
<< "Arguments for escaped template."
<<std::endl;
- ++actions.error_count;
+ ++state.error_count;
}
if (symbol->content.is_encoded())
{
- actions.phrase << symbol->content.get_encoded();
+ state.phrase << symbol->content.get_encoded();
}
else
{
- actions.phrase << symbol->content.get_quickbook();
+ state.phrase << symbol->content.get_quickbook();
/*
@@ -1339,7 +1407,7 @@ namespace quickbook
quickbook::detail::markup escape_markup
= detail::get_markup(phrase_tags::escape);
- actions.phrase
+ state.phrase
<< escape_markup.pre
<< symbol->content.get_quickbook()
<< escape_markup.post
@@ -1359,11 +1427,11 @@ namespace quickbook
case template_tags::phrase:
// Break the arguments for a template
- break_arguments(args, symbol->params, actions.current_file->path);
+ break_arguments(args, symbol->params, state.current_file->path);
if (args.size() != symbol->params.size())
{
- detail::outerr(actions.current_file, first)
+ detail::outerr(state.current_file, first)
<< "Invalid number of arguments passed. Expecting: "
<< symbol->params.size()
<< " argument(s), got: "
@@ -1371,26 +1439,26 @@ namespace quickbook
<< " argument(s) instead."
<< std::endl;
- ++actions.error_count;
+ ++state.error_count;
return;
}
- call_template(actions, symbol, args, first);
+ call_template(state, symbol, args, first);
break;
case template_tags::snippet:
if (!args.empty())
{
- detail::outerr(actions.current_file, first)
+ detail::outerr(state.current_file, first)
<< "Arguments for code snippet."
<<std::endl;
- ++actions.error_count;
+ ++state.error_count;
args.clear();
}
- call_code_snippet(actions, symbol, first);
+ call_code_snippet(state, symbol, first);
break;
default:
@@ -1398,9 +1466,9 @@ namespace quickbook
}
}
- void link_action(quickbook::actions& actions, value link)
+ void link_action(quickbook::state& state, value link)
{
- write_anchors(actions, actions.phrase);
+ write_anchors(state, state.phrase);
detail::markup markup = detail::get_markup(link.get_tag());
@@ -1414,57 +1482,57 @@ namespace quickbook
std::string dst = dst_value.is_encoded() ?
dst_value.get_encoded() : dst_value.get_quickbook();
- actions.phrase << markup.pre;
- detail::print_string(dst, actions.phrase.get());
- actions.phrase << "\">";
+ state.phrase << markup.pre;
+ detail::print_string(dst, state.phrase.get());
+ state.phrase << "\">";
if (content.empty())
- detail::print_string(dst, actions.phrase.get());
+ detail::print_string(dst, state.phrase.get());
else
- actions.phrase << content.get_encoded();
+ state.phrase << content.get_encoded();
- actions.phrase << markup.post;
+ state.phrase << markup.post;
}
- void variable_list_action(quickbook::actions& actions, value variable_list)
+ void variable_list_action(quickbook::state& state, value variable_list)
{
- write_anchors(actions, actions.out);
+ write_anchors(state, state.out);
value_consumer values = variable_list;
std::string title = values.consume(table_tags::title).get_quickbook();
- actions.out << "<variablelist>\n";
+ state.out << "<variablelist>\n";
- actions.out << "<title>";
- detail::print_string(title, actions.out.get());
- actions.out << "</title>\n";
+ state.out << "<title>";
+ detail::print_string(title, state.out.get());
+ state.out << "</title>\n";
BOOST_FOREACH(value_consumer entry, values) {
- actions.out << "<varlistentry>";
+ state.out << "<varlistentry>";
if(entry.check()) {
- actions.out << "<term>";
- actions.out << entry.consume().get_encoded();
- actions.out << "</term>";
+ state.out << "<term>";
+ state.out << entry.consume().get_encoded();
+ state.out << "</term>";
}
if(entry.check()) {
- actions.out << "<listitem>";
- BOOST_FOREACH(value phrase, entry) actions.out << phrase.get_encoded();
- actions.out << "</listitem>";
+ state.out << "<listitem>";
+ BOOST_FOREACH(value phrase, entry) state.out << phrase.get_encoded();
+ state.out << "</listitem>";
}
- actions.out << "</varlistentry>\n";
+ state.out << "</varlistentry>\n";
}
- actions.out << "</variablelist>\n";
+ state.out << "</variablelist>\n";
values.finish();
}
- void table_action(quickbook::actions& actions, value table)
+ void table_action(quickbook::state& state, value table)
{
- write_anchors(actions, actions.out);
+ write_anchors(state, state.out);
value_consumer values = table;
@@ -1478,14 +1546,14 @@ namespace quickbook
std::string table_id;
if (!element_id.empty()) {
- table_id = actions.ids.add_id(element_id, id_category::explicit_id);
+ table_id = state.ids.add_id(element_id, id_category::explicit_id);
}
else if (has_title) {
- if (actions.ids.compatibility_version() >= 105) {
- table_id = actions.ids.add_id(detail::make_identifier(title.get_quickbook()), id_category::generated);
+ if (state.ids.compatibility_version() >= 105) {
+ table_id = state.ids.add_id(detail::make_identifier(title.get_quickbook()), id_category::generated);
}
else {
- table_id = actions.ids.add_id("t", id_category::numbered);
+ table_id = state.ids.add_id("t", id_category::numbered);
}
}
@@ -1503,64 +1571,64 @@ namespace quickbook
if (has_title)
{
- actions.out << "<table frame=\"all\"";
+ state.out << "<table frame=\"all\"";
if(!table_id.empty())
- actions.out << " id=\"" << table_id << "\"";
- actions.out << ">\n";
- actions.out << "<title>";
+ state.out << " id=\"" << table_id << "\"";
+ state.out << ">\n";
+ state.out << "<title>";
if (qbk_version_n < 106u) {
- detail::print_string(title.get_quickbook(), actions.out.get());
+ detail::print_string(title.get_quickbook(), state.out.get());
}
else {
- actions.out << title.get_encoded();
+ state.out << title.get_encoded();
}
- actions.out << "</title>";
+ state.out << "</title>";
}
else
{
- actions.out << "<informaltable frame=\"all\"";
+ state.out << "<informaltable frame=\"all\"";
if(!table_id.empty())
- actions.out << " id=\"" << table_id << "\"";
- actions.out << ">\n";
+ state.out << " id=\"" << table_id << "\"";
+ state.out << ">\n";
}
- actions.out << "<tgroup cols=\"" << span_count << "\">\n";
+ state.out << "<tgroup cols=\"" << span_count << "\">\n";
if (row_count > 1)
{
- actions.out << "<thead>" << "<row>";
+ state.out << "<thead>" << "<row>";
BOOST_FOREACH(value cell, values.consume()) {
- actions.out << "<entry>" << cell.get_encoded() << "</entry>";
+ state.out << "<entry>" << cell.get_encoded() << "</entry>";
}
- actions.out << "</row>\n" << "</thead>\n";
+ state.out << "</row>\n" << "</thead>\n";
}
- actions.out << "<tbody>\n";
+ state.out << "<tbody>\n";
BOOST_FOREACH(value row, values) {
- actions.out << "<row>";
+ state.out << "<row>";
BOOST_FOREACH(value cell, row) {
- actions.out << "<entry>" << cell.get_encoded() << "</entry>";
+ state.out << "<entry>" << cell.get_encoded() << "</entry>";
}
- actions.out << "</row>\n";
+ state.out << "</row>\n";
}
values.finish();
- actions.out << "</tbody>\n"
- << "</tgroup>\n";
+ state.out << "</tbody>\n"
+ << "</tgroup>\n";
if (has_title)
{
- actions.out << "</table>\n";
+ state.out << "</table>\n";
}
else
{
- actions.out << "</informaltable>\n";
+ state.out << "</informaltable>\n";
}
}
- void begin_section_action(quickbook::actions& actions, value begin_section_list)
+ void begin_section_action(quickbook::state& state, value begin_section_list)
{
value_consumer values = begin_section_list;
@@ -1568,7 +1636,7 @@ namespace quickbook
value content = values.consume();
values.finish();
- std::string full_id = actions.ids.begin_section(
+ std::string full_id = state.ids.begin_section(
!element_id.empty() ?
element_id.get_quickbook() :
detail::make_identifier(content.get_quickbook()),
@@ -1576,48 +1644,48 @@ namespace quickbook
id_category::explicit_section_id :
id_category::generated_section);
- actions.out << "\n<section id=\"" << full_id << "\">\n";
- actions.out << "<title>";
+ state.out << "\n<section id=\"" << full_id << "\">\n";
+ state.out << "<title>";
- write_anchors(actions, actions.out);
+ write_anchors(state, state.out);
- if (self_linked_headers && actions.ids.compatibility_version() >= 103)
+ if (self_linked_headers && state.ids.compatibility_version() >= 103)
{
- actions.out << "<link linkend=\"" << full_id << "\">"
+ state.out << "<link linkend=\"" << full_id << "\">"
<< content.get_encoded()
<< "</link>"
;
}
else
{
- actions.out << content.get_encoded();
+ state.out << content.get_encoded();
}
- actions.out << "</title>\n";
+ state.out << "</title>\n";
}
- void end_section_action(quickbook::actions& actions, value end_section, string_iterator first)
+ void end_section_action(quickbook::state& state, value end_section, string_iterator first)
{
- write_anchors(actions, actions.out);
+ write_anchors(state, state.out);
- if (actions.ids.section_level() <= actions.min_section_level)
+ if (state.ids.section_level() <= state.min_section_level)
{
- file_position const pos = actions.current_file->position_of(first);
+ file_position const pos = state.current_file->position_of(first);
- detail::outerr(actions.current_file->path, pos.line)
+ detail::outerr(state.current_file->path, pos.line)
<< "Mismatched [endsect] near column " << pos.column << ".\n";
- ++actions.error_count;
+ ++state.error_count;
return;
}
- actions.out << "</section>";
- actions.ids.end_section();
+ state.out << "</section>";
+ state.ids.end_section();
}
void element_id_warning_action::operator()(parse_iterator first, parse_iterator) const
{
- detail::outwarn(actions.current_file, first.base()) << "Empty id.\n";
+ detail::outwarn(state.current_file, first.base()) << "Empty id.\n";
}
// Not a general purpose normalization function, just
@@ -1695,57 +1763,84 @@ namespace quickbook
return result;
}
- fs::path check_path(value const& path, quickbook::actions& actions)
+ 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)
{
- std::string path_text = path.is_encoded() ? path.get_encoded() :
- path.get_quickbook();
+ // 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)
{
- (qbk_version_n >= 106u ?
- detail::outerr(path.get_file(), path.get_position()) :
- detail::outwarn(path.get_file(), path.get_position()))
- << "Path isn't portable: '"
- << detail::utf8(path_text)
+ 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;
- if (qbk_version_n >= 106u) ++actions.error_count;
+
+ boost::replace(path_text, '\\', '/');
}
-
- boost::replace(path_text, '\\', '/');
-
- return detail::generic_to_path(path_text);
+
+ return path_details(path_text, path_details::path);
}
- xinclude_path calculate_xinclude_path(value const& p, quickbook::actions& actions)
+ xinclude_path calculate_xinclude_path(value const& p, quickbook::state& state)
{
- fs::path path = check_path(p, actions);
+ path_details details = check_path(p, state);
+
+ fs::path path = detail::generic_to_path(details.value);
fs::path full_path = path;
// If the path is relative
if (!path.has_root_directory())
{
// Resolve the path from the current file
- full_path = actions.current_file->path.parent_path() / path;
+ full_path = state.current_file->path.parent_path() / path;
// Then calculate relative to the current xinclude_base.
- path = path_difference(actions.xinclude_base, full_path);
+ path = path_difference(state.xinclude_base, full_path);
}
return xinclude_path(full_path, detail::escape_uri(detail::path_to_generic(path)));
}
- void xinclude_action(quickbook::actions& actions, value xinclude)
+ void xinclude_action(quickbook::state& state, value xinclude)
{
- write_anchors(actions, actions.out);
+ write_anchors(state, state.out);
value_consumer values = xinclude;
- xinclude_path x = calculate_xinclude_path(values.consume(), actions);
+ xinclude_path x = calculate_xinclude_path(values.consume(), state);
values.finish();
- actions.out << "\n<xi:include href=\"";
- detail::print_string(x.uri, actions.out.get());
- actions.out << "\" />\n";
+ state.out << "\n<xi:include href=\"";
+ detail::print_string(x.uri, state.out.get());
+ state.out << "\" />\n";
}
namespace
@@ -1757,41 +1852,67 @@ namespace quickbook
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;
+ }
};
- include_search_return include_search(fs::path const& path,
- quickbook::actions const& actions)
+ std::set<include_search_return> include_search(path_details const& details,
+ quickbook::state& state, string_iterator pos)
{
- fs::path current = actions.current_file->path.parent_path();
+ 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 (fs::exists(current / path))
+ if (state.add_dependency(local_path))
{
- return include_search_return(
- current / path,
- actions.filename_relative.parent_path() / path);
+ result.insert(include_search_return(
+ local_path,
+ state.filename_relative.parent_path() / path));
+ return result;
}
- // Search in each of the include path locations.
BOOST_FOREACH(fs::path full, include_path)
{
full /= path;
- if (fs::exists(full))
+
+ if (state.add_dependency(full))
{
- return include_search_return(full, path);
+ 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 include_search_return(path,
- actions.filename_relative.parent_path() / path);
+ return result;
}
}
- void load_quickbook(quickbook::actions& actions,
+ void load_quickbook(quickbook::state& state,
include_search_return const& paths,
value::tag_type load_type,
value const& include_doc_id = value())
@@ -1810,32 +1931,32 @@ namespace quickbook
//
// For old versions of quickbook, templates aren't scoped by the
// file.
- file_state state(actions,
+ 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);
- actions.current_file = load(paths.filename); // Throws load_error
- actions.filename_relative = paths.filename_relative;
- actions.imported = (load_type == block_tags::import);
+ state.current_file = load(paths.filename); // Throws load_error
+ state.filename_relative = paths.filename_relative;
+ state.imported = (load_type == block_tags::import);
// update the __FILENAME__ macro
- *boost::spirit::classic::find(actions.macro, "__FILENAME__")
- = detail::path_to_generic(actions.filename_relative);
+ *boost::spirit::classic::find(state.macro, "__FILENAME__")
+ = detail::path_to_generic(state.filename_relative);
// parse the file
- quickbook::parse_file(actions, include_doc_id, true);
+ quickbook::parse_file(state, include_doc_id, true);
// Don't restore source_mode on older versions.
- if (keep_inner_source_mode) state.source_mode = actions.source_mode;
+ if (keep_inner_source_mode) save.source_mode = state.source_mode;
}
// restore the __FILENAME__ macro
- *boost::spirit::classic::find(actions.macro, "__FILENAME__")
- = detail::path_to_generic(actions.filename_relative);
+ *boost::spirit::classic::find(state.macro, "__FILENAME__")
+ = detail::path_to_generic(state.filename_relative);
}
- void load_source_file(quickbook::actions& actions,
+ void load_source_file(quickbook::state& state,
include_search_return const& paths,
value::tag_type load_type,
string_iterator first,
@@ -1847,12 +1968,12 @@ namespace quickbook
std::string ext = paths.filename.extension().generic_string();
std::vector<template_symbol> storage;
// Throws load_error
- actions.error_count +=
+ state.error_count +=
load_snippets(paths.filename, storage, ext, load_type);
if (load_type == block_tags::include)
{
- actions.templates.push();
+ state.templates.push();
}
BOOST_FOREACH(template_symbol& ts, storage)
@@ -1860,12 +1981,12 @@ namespace quickbook
std::string tname = ts.identifier;
if (tname != "!")
{
- ts.lexical_parent = &actions.templates.top_scope();
- if (!actions.templates.add(ts))
+ ts.lexical_parent = &state.templates.top_scope();
+ if (!state.templates.add(ts))
{
detail::outerr(ts.content.get_file(), ts.content.get_position())
- << "Template Redefinition: " << detail::utf8(tname) << std::endl;
- ++actions.error_count;
+ << "Template Redefinition: " << tname << std::endl;
+ ++state.error_count;
}
}
}
@@ -1878,71 +1999,77 @@ namespace quickbook
if (tname == "!")
{
- ts.lexical_parent = &actions.templates.top_scope();
- call_code_snippet(actions, &ts, first);
+ ts.lexical_parent = &state.templates.top_scope();
+ call_code_snippet(state, &ts, first);
}
}
- actions.templates.pop();
+ state.templates.pop();
}
}
- void include_action(quickbook::actions& actions, value include, string_iterator first)
+ void include_action(quickbook::state& state, value include, string_iterator first)
{
- write_anchors(actions, actions.out);
+ write_anchors(state, state.out);
value_consumer values = include;
value include_doc_id = values.optional_consume(general_tags::include_id);
- include_search_return paths = include_search(
- check_path(values.consume(), actions), actions);
+ path_details details = check_path(values.consume(), state);
values.finish();
- try {
- if (qbk_version_n >= 106)
- {
- if (actions.imported && include.get_tag() == block_tags::include)
- return;
-
- std::string ext = paths.filename.extension().generic_string();
-
- if (ext == ".qbk" || ext == ".quickbook")
+ 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();
+ for (; i != e; ++i)
+ {
+ include_search_return const & paths = *i;
+ try {
+ if (qbk_version_n >= 106)
{
- load_quickbook(actions, paths, include.get_tag(), include_doc_id);
+ if (state.imported && include.get_tag() == block_tags::include)
+ return;
+
+ std::string ext = paths.filename.extension().generic_string();
+
+ if (ext == ".qbk" || ext == ".quickbook")
+ {
+ load_quickbook(state, paths, include.get_tag(), include_doc_id);
+ }
+ else
+ {
+ load_source_file(state, paths, include.get_tag(), first, include_doc_id);
+ }
}
else
{
- load_source_file(actions, paths, include.get_tag(), first, include_doc_id);
+ if (include.get_tag() == block_tags::include)
+ {
+ load_quickbook(state, paths, include.get_tag(), include_doc_id);
+ }
+ else
+ {
+ load_source_file(state, paths, include.get_tag(), first, include_doc_id);
+ }
}
}
- else
- {
- if (include.get_tag() == block_tags::include)
- {
- load_quickbook(actions, paths, include.get_tag(), include_doc_id);
- }
- else
- {
- load_source_file(actions, paths, include.get_tag(), first, include_doc_id);
- }
+ catch (load_error& e) {
+ ++state.error_count;
+
+ detail::outerr(state.current_file, first)
+ << "Loading file "
+ << paths.filename
+ << ": "
+ << e.what()
+ << std::endl;
}
}
- catch (load_error& e) {
- ++actions.error_count;
-
- detail::outerr(actions.current_file, first)
- << "Loading file "
- << paths.filename
- << ": "
- << detail::utf8(e.what())
- << std::endl;
- }
}
bool to_value_scoped_action::start(value::tag_type t)
{
- actions.out.push();
- actions.phrase.push();
- actions.anchors.swap(saved_anchors);
+ state.out.push();
+ state.phrase.push();
+ state.anchors.swap(saved_anchors);
tag = t;
return true;
@@ -1952,27 +2079,28 @@ namespace quickbook
{
std::string value;
- if (!actions.out.str().empty())
+ if (!state.out.str().empty())
{
- actions.paragraph();
- write_anchors(actions, actions.out);
- actions.out.swap(value);
+ paragraph_action para(state);
+ para(); // For paragraphs before the template call.
+ write_anchors(state, state.out);
+ state.out.swap(value);
}
else
{
- write_anchors(actions, actions.phrase);
- actions.phrase.swap(value);
+ write_anchors(state, state.phrase);
+ state.phrase.swap(value);
}
- actions.values.builder.insert(encoded_qbk_value(
- actions.current_file, first.base(), last.base(), value, tag));
+ state.values.builder.insert(encoded_qbk_value(
+ state.current_file, first.base(), last.base(), value, tag));
}
void to_value_scoped_action::cleanup()
{
- actions.phrase.pop();
- actions.out.pop();
- actions.anchors.swap(saved_anchors);
+ state.phrase.pop();
+ state.out.pop();
+ state.anchors.swap(saved_anchors);
}
}
diff --git a/tools/quickbook/src/actions.hpp b/tools/quickbook/src/actions.hpp
index 4f67aec09b..5a93cf949a 100644
--- a/tools/quickbook/src/actions.hpp
+++ b/tools/quickbook/src/actions.hpp
@@ -13,46 +13,33 @@
#include <string>
#include <vector>
#include "fwd.hpp"
-#include "template_stack.hpp"
#include "utils.hpp"
#include "values.hpp"
#include "scoped.hpp"
-#include "symbols.hpp"
#include <boost/spirit/include/classic_parser.hpp>
namespace quickbook
{
namespace cl = boost::spirit::classic;
- extern unsigned qbk_version_n; // qbk_major_version * 100 + qbk_minor_version
-
struct quickbook_range : cl::parser<quickbook_range> {
- quickbook_range(unsigned min_, unsigned max_)
- : min_(min_), max_(max_) {}
+ quickbook_range(unsigned lower, unsigned upper)
+ : lower(lower), upper(upper) {}
+
+ bool in_range() const;
template <typename ScannerT>
typename cl::parser_result<quickbook_range, ScannerT>::type
parse(ScannerT const& scan) const
{
- if (qbk_version_n >= min_ && qbk_version_n < max_)
- {
- return scan.empty_match();
- }
- else
- {
- return scan.no_match();
- }
+ return in_range() ? scan.empty_match() : scan.no_match();
}
- unsigned min_, max_;
+ unsigned lower, upper;
};
- inline quickbook_range qbk_since(unsigned min_) {
- return quickbook_range(min_, 999);
- }
-
- inline quickbook_range qbk_before(unsigned max_) {
- return quickbook_range(0, max_);
+ inline quickbook_range qbk_ver(unsigned lower, unsigned upper = 999u) {
+ return quickbook_range(lower, upper);
}
// Throws load_error
@@ -61,31 +48,32 @@ namespace quickbook
std::string syntax_highlight(
parse_iterator first, parse_iterator last,
- actions& escape_actions,
- std::string const& source_mode);
+ quickbook::state& state,
+ std::string const& source_mode,
+ bool is_block);
struct xinclude_path {
- xinclude_path(fs::path& path, std::string const& uri) :
+ xinclude_path(fs::path const& path, std::string const& uri) :
path(path), uri(uri) {}
fs::path path;
std::string uri;
};
- xinclude_path calculate_xinclude_path(value const&, quickbook::actions&);
+ xinclude_path calculate_xinclude_path(value const&, quickbook::state&);
struct error_message_action
{
// Prints an error message to std::cerr
- error_message_action(quickbook::actions& actions, std::string const& m)
- : actions(actions)
+ error_message_action(quickbook::state& state, std::string const& m)
+ : state(state)
, message(m)
{}
void operator()(parse_iterator, parse_iterator) const;
- quickbook::actions& actions;
+ quickbook::state& state;
std::string message;
};
@@ -93,27 +81,27 @@ namespace quickbook
{
// Prints an error message to std::cerr
- error_action(quickbook::actions& actions)
- : actions(actions) {}
+ error_action(quickbook::state& state)
+ : state(state) {}
void operator()(parse_iterator first, parse_iterator last) const;
error_message_action operator()(std::string const& message)
{
- return error_message_action(actions, message);
+ return error_message_action(state, message);
}
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct element_action
{
- element_action(quickbook::actions& actions)
- : actions(actions) {}
+ element_action(quickbook::state& state)
+ : state(state) {}
void operator()(parse_iterator, parse_iterator) const;
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct paragraph_action
@@ -122,13 +110,13 @@ namespace quickbook
// doesn't output the paragraph if it's only whitespace.
paragraph_action(
- quickbook::actions& actions)
- : actions(actions) {}
+ quickbook::state& state)
+ : state(state) {}
void operator()() const;
void operator()(parse_iterator, parse_iterator) const { (*this)(); }
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct list_item_action
@@ -137,24 +125,24 @@ namespace quickbook
// doesn't output the paragraph if it's only whitespace.
list_item_action(
- quickbook::actions& actions)
- : actions(actions) {}
+ quickbook::state& state)
+ : state(state) {}
void operator()() const;
void operator()(parse_iterator, parse_iterator) const { (*this)(); }
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct phrase_end_action
{
- phrase_end_action(quickbook::actions& actions) :
- actions(actions) {}
+ phrase_end_action(quickbook::state& state) :
+ state(state) {}
void operator()() const;
void operator()(parse_iterator, parse_iterator) const { (*this)(); }
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct simple_phrase_action
@@ -163,43 +151,40 @@ namespace quickbook
simple_phrase_action(
collector& out
- , quickbook::actions& actions)
+ , quickbook::state& state)
: out(out)
- , actions(actions) {}
+ , state(state) {}
void operator()(char) const;
collector& out;
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct cond_phrase_push : scoped_action_base
{
- cond_phrase_push(quickbook::actions& x)
- : actions(x) {}
+ cond_phrase_push(quickbook::state& x)
+ : state(x) {}
bool start();
void cleanup();
- quickbook::actions& actions;
+ quickbook::state& state;
bool saved_conditional;
std::vector<std::string> anchors;
};
- extern char const* quickbook_get_date;
- extern char const* quickbook_get_time;
-
struct do_macro_action
{
// Handles macro substitutions
- do_macro_action(collector& phrase, quickbook::actions& actions)
+ do_macro_action(collector& phrase, quickbook::state& state)
: phrase(phrase)
- , actions(actions) {}
+ , state(state) {}
void operator()(std::string const& str) const;
collector& phrase;
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct raw_char_action
@@ -220,83 +205,63 @@ namespace quickbook
// Prints a single plain char.
// Converts '<' to "&lt;"... etc See utils.hpp
- plain_char_action(collector& phrase, quickbook::actions& actions)
+ plain_char_action(collector& phrase, quickbook::state& state)
: phrase(phrase)
- , actions(actions) {}
+ , state(state) {}
void operator()(char ch) const;
void operator()(parse_iterator first, parse_iterator last) const;
collector& phrase;
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct escape_unicode_action
{
- escape_unicode_action(collector& phrase, quickbook::actions& actions)
+ escape_unicode_action(collector& phrase, quickbook::state& state)
: phrase(phrase)
- , actions(actions) {}
+ , state(state) {}
void operator()(parse_iterator first, parse_iterator last) const;
collector& phrase;
- quickbook::actions& actions;
- };
-
- struct code_action
- {
- enum code_type { block, inline_block, inline_ };
-
- // Does the actual syntax highlighing of code
-
- code_action(
- code_type type
- , quickbook::actions& actions)
- : type(type)
- , actions(actions)
- {
- }
-
- void operator()(parse_iterator first, parse_iterator last) const;
-
- code_type type;
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct break_action
{
- break_action(collector& phrase, quickbook::actions& actions)
- : phrase(phrase), actions(actions) {}
+ break_action(collector& phrase, quickbook::state& state)
+ : phrase(phrase), state(state) {}
void operator()(parse_iterator f, parse_iterator) const;
collector& phrase;
- quickbook::actions& actions;
+ quickbook::state& state;
};
struct element_id_warning_action
{
- element_id_warning_action(quickbook::actions& actions_)
- : actions(actions_) {}
+ element_id_warning_action(quickbook::state& state_)
+ : state(state_) {}
void operator()(parse_iterator first, parse_iterator last) const;
- quickbook::actions& actions;
+ quickbook::state& state;
};
// Returns the doc_type, or an empty string if there isn't one.
- std::string pre(quickbook::actions& actions, parse_iterator pos, value include_doc_id, bool nested_file);
- void post(quickbook::actions& actions, std::string const& doc_type);
+ std::string pre(quickbook::state& state, parse_iterator pos, value include_doc_id, bool nested_file);
+ void post(quickbook::state& state, std::string const& doc_type);
struct to_value_scoped_action : scoped_action_base
{
- to_value_scoped_action(quickbook::actions& actions)
- : actions(actions) {}
+ to_value_scoped_action(quickbook::state& state)
+ : state(state) {}
bool start(value::tag_type = value::default_tag);
void success(parse_iterator, parse_iterator);
void cleanup();
- quickbook::actions& actions;
+ quickbook::state& state;
std::vector<std::string> saved_anchors;
value::tag_type tag;
};
diff --git a/tools/quickbook/src/actions_class.cpp b/tools/quickbook/src/actions_class.cpp
deleted file mode 100644
index d94706c91a..0000000000
--- a/tools/quickbook/src/actions_class.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*=============================================================================
- Copyright (c) 2002 2004 2006 Joel de Guzman
- Copyright (c) 2004 Eric Niebler
- Copyright (c) 2005 Thomas Guest
- http://spirit.sourceforge.net/
-
- 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 "actions_class.hpp"
-#include "actions_state.hpp"
-#include "quickbook.hpp"
-#include "grammar.hpp"
-#include "input_path.hpp"
-
-#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
-#pragma warning(disable:4355)
-#endif
-
-namespace quickbook
-{
- actions::actions(fs::path const& filein_, fs::path const& xinclude_base_,
- string_stream& out_, id_manager& ids)
- : grammar_()
-
- , xinclude_base(xinclude_base_)
-
- , templates()
- , error_count(0)
- , anchors()
- , warned_about_breaks(false)
- , conditional(true)
- , ids(ids)
-
- , imported(false)
- , macro()
- , source_mode("c++")
- , current_file(0)
- , filename_relative(filein_.filename())
-
- , template_depth(0)
- , min_section_level(1)
-
- , out(out_)
- , phrase()
- , values(&current_file)
-
- , to_value(*this)
- , scoped_cond_phrase(*this)
-
- , element(*this)
- , error(*this)
- , code(code_action::block, *this)
- , code_block(code_action::inline_block, *this)
- , inline_code(code_action::inline_, *this)
- , paragraph(*this)
- , list_item(*this)
- , phrase_end(*this)
- , raw_char(phrase)
- , plain_char(phrase, *this)
- , escape_unicode(phrase, *this)
-
- , simple_markup(phrase, *this)
-
- , break_(phrase, *this)
- , do_macro(phrase, *this)
-
- , element_id_warning(*this)
- {
- // 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))
- ;
-
- boost::scoped_ptr<quickbook_grammar> g(
- new quickbook_grammar(*this));
- grammar_.swap(g);
- }
-
- quickbook_grammar& actions::grammar() const {
- return *grammar_;
- }
-
- file_state::file_state(actions& a, scope_flags scope)
- : a(a)
- , scope(scope)
- , qbk_version(qbk_version_n)
- , imported(a.imported)
- , current_file(a.current_file)
- , filename_relative(a.filename_relative)
- , xinclude_base(a.xinclude_base)
- , source_mode(a.source_mode)
- , macro()
- {
- if (scope & scope_macros) macro = a.macro;
- if (scope & scope_templates) a.templates.push();
- if (scope & scope_output) {
- a.out.push();
- a.phrase.push();
- }
- a.values.builder.save();
- }
-
- file_state::~file_state()
- {
- a.values.builder.restore();
- boost::swap(qbk_version_n, qbk_version);
- boost::swap(a.imported, imported);
- boost::swap(a.current_file, current_file);
- boost::swap(a.filename_relative, filename_relative);
- boost::swap(a.xinclude_base, xinclude_base);
- boost::swap(a.source_mode, source_mode);
- if (scope & scope_output) {
- a.out.pop();
- a.phrase.pop();
- }
- if (scope & scope_templates) a.templates.pop();
- if (scope & scope_macros) a.macro = macro;
- }
-
- template_state::template_state(actions& a)
- : file_state(a, file_state::scope_all)
- , template_depth(a.template_depth)
- , min_section_level(a.min_section_level)
- {
- }
-
- template_state::~template_state()
- {
- boost::swap(a.template_depth, template_depth);
- boost::swap(a.min_section_level, min_section_level);
- }
-}
diff --git a/tools/quickbook/src/block_element_grammar.cpp b/tools/quickbook/src/block_element_grammar.cpp
index f188e1379f..1f5d5daec4 100644
--- a/tools/quickbook/src/block_element_grammar.cpp
+++ b/tools/quickbook/src/block_element_grammar.cpp
@@ -9,7 +9,8 @@
=============================================================================*/
#include "utils.hpp"
-#include "actions_class.hpp"
+#include "state.hpp"
+#include "actions.hpp"
#include "grammar_impl.hpp"
#include "block_tags.hpp"
#include "template_tags.hpp"
@@ -43,20 +44,26 @@ namespace quickbook
block_element_grammar_local& local = cleanup_.add(
new block_element_grammar_local);
+ // Actions
+ error_action error(state);
+ element_id_warning_action element_id_warning(state);
+ raw_char_action raw_char(state.phrase);
+ scoped_parser<to_value_scoped_action> to_value(state);
+
local.element_id =
!( ':'
- >> ( !(qbk_since(105u) >> space)
- >> (+(cl::alnum_p | '_')) [actions.values.entry(ph::arg1, ph::arg2, general_tags::element_id)]
- | cl::eps_p [actions.element_id_warning]
+ >> ( !(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_since(105u) >> local.element_id);
+ !(qbk_ver(105u) >> local.element_id);
local.element_id_1_6 =
- !(qbk_since(106u) >> local.element_id);
+ !(qbk_ver(106u) >> local.element_id);
elements.add
("section", element_info(element_info::block, &local.begin_section, block_tags::begin_section))
@@ -110,10 +117,10 @@ namespace quickbook
;
local.preformatted =
- ( qbk_before(106) >> space
- | qbk_since(106) >> blank >> !eol
+ ( qbk_ver(0, 106) >> space
+ | qbk_ver(106) >> blank >> !eol
)
- >> actions.to_value()
+ >> to_value()
[
inside_preformatted
]
@@ -125,7 +132,7 @@ namespace quickbook
local.def_macro =
space
- >> macro_identifier [actions.values.entry(ph::arg1, ph::arg2)]
+ >> macro_identifier [state.values.entry(ph::arg1, ph::arg2)]
>> blank
>> local.inner_phrase
;
@@ -144,20 +151,20 @@ namespace quickbook
local.template_ =
space
- >> local.template_id [actions.values.entry(ph::arg1, ph::arg2)]
- >> actions.values.list()[
+ >> local.template_id [state.values.entry(ph::arg1, ph::arg2)]
+ >> state.values.list()[
!(
space >> '['
>> *(
space
- >> local.template_id [actions.values.entry(ph::arg1, ph::arg2)]
+ >> local.template_id [state.values.entry(ph::arg1, ph::arg2)]
)
>> space >> ']'
)
]
>> ( cl::eps_p(*cl::blank_p >> cl::eol_p)
- >> local.template_body [actions.values.entry(ph::arg1, ph::arg2, template_tags::block)]
- | local.template_body [actions.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
+ >> local.template_body [state.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+ | local.template_body [state.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
)
;
@@ -180,17 +187,17 @@ namespace quickbook
local.varlistentry =
space
>> cl::ch_p('[')
- >> actions.values.list()
+ >> state.values.list()
[
(
local.varlistterm
>> ( +local.cell
- | cl::eps_p [actions.error]
+ | cl::eps_p [error]
)
>> cl::ch_p(']')
>> space
)
- | cl::eps_p [actions.error]
+ | cl::eps_p [error]
]
;
@@ -200,7 +207,7 @@ namespace quickbook
>> local.inner_phrase
>> ( cl::ch_p(']')
>> space
- | cl::eps_p [actions.error]
+ | cl::eps_p [error]
)
;
@@ -224,22 +231,22 @@ namespace quickbook
>>
(
(
- actions.values.list(table_tags::row)
+ state.values.list(table_tags::row)
[ *local.cell
]
>> cl::ch_p(']')
>> space
)
- | cl::eps_p [actions.error]
+ | cl::eps_p [error]
)
;
local.table_title =
- qbk_before(106)
- >> (*(cl::anychar_p - eol)) [actions.values.entry(ph::arg1, ph::arg2, table_tags::title)]
+ qbk_ver(0, 106)
+ >> (*(cl::anychar_p - eol)) [state.values.entry(ph::arg1, ph::arg2, table_tags::title)]
>> (+eol)
- | qbk_since(106)
- >> actions.to_value(table_tags::title)
+ | qbk_ver(106)
+ >> to_value(table_tags::title)
[
table_title_phrase
]
@@ -259,7 +266,7 @@ namespace quickbook
>> ( local.inner_block
>> cl::ch_p(']')
>> space
- | cl::eps_p [actions.error]
+ | cl::eps_p [error]
)
;
@@ -285,33 +292,33 @@ namespace quickbook
!(
':'
>> (*((cl::alnum_p | '_') - cl::space_p))
- [actions.values.entry(ph::arg1, ph::arg2, general_tags::include_id)]
+ [state.values.entry(ph::arg1, ph::arg2, general_tags::include_id)]
>> space
)
>> local.include_filename
;
local.include_filename =
- qbk_before(106u)
- >> (*(cl::anychar_p - phrase_end)) [actions.values.entry(ph::arg1, ph::arg2)]
- | qbk_since(106u)
- >> actions.to_value()
+ qbk_ver(0, 106u)
+ >> (*(cl::anychar_p - phrase_end)) [state.values.entry(ph::arg1, ph::arg2)]
+ | qbk_ver(106u)
+ >> to_value()
[ *( raw_escape
| (cl::anychar_p - phrase_end)
- [actions.raw_char]
+ [raw_char]
)
]
;
local.inner_block =
- actions.to_value()
+ to_value()
[
inside_paragraph
]
;
local.inner_phrase =
- actions.to_value()
+ to_value()
[
paragraph_phrase
]
diff --git a/tools/quickbook/src/code_snippet.cpp b/tools/quickbook/src/code_snippet.cpp
index 8d9484cce2..4c63a3ba0e 100644
--- a/tools/quickbook/src/code_snippet.cpp
+++ b/tools/quickbook/src/code_snippet.cpp
@@ -16,6 +16,7 @@
#include "block_tags.hpp"
#include "template_stack.hpp"
#include "actions.hpp"
+#include "state.hpp"
#include "values.hpp"
#include "files.hpp"
#include "input_path.hpp"
@@ -31,13 +32,13 @@ namespace quickbook
char const* source_type)
: last_code_pos(source_file->source.begin())
, in_code(false)
- , callout_id(0)
, snippet_stack()
, storage(storage)
, source_file(source_file)
, source_type(source_type)
, error_count(0)
{
+ source_file->is_code_snippets = true;
content.start(source_file);
}
@@ -48,7 +49,6 @@ namespace quickbook
void start_snippet_impl(std::string const&, string_iterator);
void end_snippet(string_iterator first, string_iterator last);
void end_snippet_impl(string_iterator);
- void callout(string_iterator first, string_iterator last);
void end_file(string_iterator, string_iterator);
void append_code(string_iterator first, string_iterator last);
@@ -56,26 +56,22 @@ namespace quickbook
struct snippet_data
{
- snippet_data(std::string const& id, int callout_base_id)
+ snippet_data(std::string const& id)
: id(id)
- , callout_base_id(callout_base_id)
, start_code(false)
{}
std::string id;
- int callout_base_id;
bool start_code;
std::string::const_iterator source_pos;
mapped_file_builder::pos start_pos;
- value_builder callouts;
boost::shared_ptr<snippet_data> next;
};
- void push_snippet_data(std::string const& id, int callout_base_id,
+ void push_snippet_data(std::string const& id,
std::string::const_iterator pos)
{
- boost::shared_ptr<snippet_data> new_snippet(
- new snippet_data(id, callout_base_id));
+ boost::shared_ptr<snippet_data> new_snippet(new snippet_data(id));
new_snippet->next = snippet_stack;
snippet_stack = new_snippet;
snippet_stack->start_code = in_code;
@@ -95,7 +91,6 @@ namespace quickbook
std::string::const_iterator mark_begin, mark_end;
std::string::const_iterator last_code_pos;
bool in_code;
- int callout_id;
boost::shared_ptr<snippet_data> snippet_stack;
std::vector<template_symbol>& storage;
file_ptr source_file;
@@ -240,8 +235,6 @@ namespace quickbook
| escaped_comment [boost::bind(&actions_type::escaped_comment, &actions, _1, _2)]
| ignore [boost::bind(&actions_type::append_code, &actions, _1, _2)]
| pass_thru_comment [boost::bind(&actions_type::pass_thru, &actions, _1, _2)]
- | line_callout [boost::bind(&actions_type::callout, &actions, _1, _2)]
- | inline_callout [boost::bind(&actions_type::callout, &actions, _1, _2)]
| cl::anychar_p
;
@@ -287,23 +280,6 @@ namespace quickbook
"/*[*/"
;
- inline_callout
- = cl::confix_p(
- "/*<" >> *cl::space_p,
- (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
- ">*/"
- )
- ;
-
- line_callout
- = cl::confix_p(
- "/*<<" >> *cl::space_p,
- (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
- ">>*/"
- )
- >> *cl::space_p
- ;
-
ignore
= cl::confix_p(
*cl::blank_p >> "//<-",
@@ -354,7 +330,7 @@ namespace quickbook
cl::rule<Scanner>
start_, identifier, code_elements, start_snippet, end_snippet,
- escaped_comment, pass_thru_comment, inline_callout, line_callout, ignore;
+ escaped_comment, pass_thru_comment, ignore;
cl::rule<Scanner> const&
start() const { return start_; }
@@ -447,27 +423,6 @@ namespace quickbook
content.add(mark_begin, mark_end);
}
- void code_snippet_actions::callout(string_iterator first, string_iterator last)
- {
- if(!snippet_stack) return;
- append_code(first, last);
-
- if (!in_code)
- {
- content.add("\n\n", first);
- content.add(source_type, first);
- content.add("```\n", first);
- in_code = true;
- }
-
- content.add(
- "``[[callout" + boost::lexical_cast<std::string>(callout_id) + "]]``",
- first);
-
- snippet_stack->callouts.insert(qbk_value(source_file, mark_begin, mark_end, template_tags::block));
- ++callout_id;
- }
-
void code_snippet_actions::escaped_comment(string_iterator first, string_iterator last)
{
append_code(first, last);
@@ -529,7 +484,7 @@ namespace quickbook
if (qbk_version_n >= 106u) {
detail::outerr(source_file->path)
<< "Unclosed snippet '"
- << detail::utf8(snippet_stack->id)
+ << snippet_stack->id
<< "'"
<< std::endl;
++error_count;
@@ -537,7 +492,7 @@ namespace quickbook
else {
detail::outwarn(source_file->path)
<< "Unclosed snippet '"
- << detail::utf8(snippet_stack->id)
+ << snippet_stack->id
<< "'"
<< std::endl;
}
@@ -549,7 +504,7 @@ namespace quickbook
void code_snippet_actions::start_snippet_impl(std::string const& id,
string_iterator position)
{
- push_snippet_data(id, callout_id, position);
+ push_snippet_data(id, position);
}
void code_snippet_actions::end_snippet_impl(string_iterator position)
@@ -557,7 +512,6 @@ namespace quickbook
assert(snippet_stack);
boost::shared_ptr<snippet_data> snippet = pop_snippet_data();
- value callouts = snippet->callouts.release();
mapped_file_builder f;
f.start(source_file);
@@ -572,29 +526,11 @@ namespace quickbook
}
std::vector<std::string> params;
- int i = 0;
- for(value::iterator it = callouts.begin(); it != callouts.end(); ++it)
- {
- params.push_back("[callout" + boost::lexical_cast<std::string>(snippet->callout_base_id + i) + "]");
- ++i;
- }
file_ptr body = f.release();
- value_builder builder;
- builder.set_tag(template_tags::snippet);
- builder.insert(qbk_value(body, body->source.begin(), body->source.end(),
- template_tags::block));
- builder.insert(callouts);
-
- template_symbol symbol(snippet->id, params, builder.release());
- storage.push_back(symbol);
-
- // Copy the snippet's callouts to its parent
-
- if(snippet_stack)
- {
- snippet_stack->callouts.extend(callouts);
- }
+ storage.push_back(template_symbol(snippet->id, params,
+ qbk_value(body, body->source.begin(), body->source.end(),
+ template_tags::snippet)));
}
}
diff --git a/tools/quickbook/src/doc_info_actions.cpp b/tools/quickbook/src/doc_info_actions.cpp
index e23466fd3d..42ee961832 100644
--- a/tools/quickbook/src/doc_info_actions.cpp
+++ b/tools/quickbook/src/doc_info_actions.cpp
@@ -12,12 +12,13 @@
#include <boost/bind.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/foreach.hpp>
-#include <boost/filesystem/v3/operations.hpp>
+#include <boost/filesystem/operations.hpp>
#include "quickbook.hpp"
#include "utils.hpp"
#include "files.hpp"
#include "input_path.hpp"
-#include "actions_class.hpp"
+#include "state.hpp"
+#include "actions.hpp"
#include "doc_info_tags.hpp"
#include "id_manager.hpp"
@@ -75,7 +76,7 @@ namespace quickbook
}
// Any number of attributes, so stuff them into a vector.
- std::vector<value> consume_multiple_lists(value_consumer& c, value::tag_type tag)
+ std::vector<value> consume_multiple_values(value_consumer& c, value::tag_type tag)
{
std::vector<value> values;
@@ -86,7 +87,7 @@ namespace quickbook
return values;
}
- unsigned get_version(quickbook::actions& actions, bool using_docinfo,
+ unsigned get_version(quickbook::state& state, bool using_docinfo,
value version)
{
unsigned result = 0;
@@ -103,15 +104,15 @@ namespace quickbook
result = ((unsigned) major_verison * 100) +
(unsigned) minor_verison;
- if(result < 100 || result > 106)
+ if(result < 100 || result > 107)
{
- detail::outerr(actions.current_file->path)
+ detail::outerr(state.current_file->path)
<< "Unknown version: "
<< major_verison
<< "."
<< minor_verison
<< std::endl;
- ++actions.error_count;
+ ++state.error_count;
}
}
}
@@ -119,7 +120,7 @@ namespace quickbook
return result;
}
- std::string pre(quickbook::actions& actions, parse_iterator pos,
+ std::string pre(quickbook::state& state, parse_iterator pos,
value include_doc_id, bool nested_file)
{
// The doc_info in the file has been parsed. Here's what we'll do
@@ -128,7 +129,7 @@ namespace quickbook
// If there isn't a doc info block, then values will be empty, so most
// of the following code won't actually do anything.
- value_consumer values = actions.values.release();
+ value_consumer values = state.values.release();
// Skip over invalid attributes
@@ -148,15 +149,15 @@ namespace quickbook
{
if (!nested_file)
{
- detail::outerr(actions.current_file, pos.base())
+ detail::outerr(state.current_file, pos.base())
<< "No doc_info block."
<< std::endl;
- ++actions.error_count;
+ ++state.error_count;
// Create a fake document info block in order to continue.
doc_type = "article";
- doc_title = qbk_value(actions.current_file,
+ doc_title = qbk_value(state.current_file,
pos.base(), pos.base(),
doc_info_tags::type);
use_doc_info = true;
@@ -165,31 +166,33 @@ namespace quickbook
std::vector<std::string> duplicates;
+ std::vector<value> escaped_attributes = consume_multiple_values(values, doc_info_tags::escaped_attribute);
+
value qbk_version = consume_list(values, doc_attributes::qbk_version, &duplicates);
value compatibility_mode = consume_list(values, doc_attributes::compatibility_mode, &duplicates);
- consume_multiple_lists(values, doc_attributes::source_mode);
+ consume_multiple_values(values, doc_attributes::source_mode);
value id = consume_value_in_list(values, doc_info_attributes::id, &duplicates);
value dirname = consume_value_in_list(values, doc_info_attributes::dirname, &duplicates);
value last_revision = consume_value_in_list(values, doc_info_attributes::last_revision, &duplicates);
value purpose = consume_value_in_list(values, doc_info_attributes::purpose, &duplicates);
- std::vector<value> categories = consume_multiple_lists(values, doc_info_attributes::category);
+ std::vector<value> categories = consume_multiple_values(values, doc_info_attributes::category);
value lang = consume_value_in_list(values, doc_info_attributes::lang, &duplicates);
value version = consume_value_in_list(values, doc_info_attributes::version, &duplicates);
- std::vector<value> authors = consume_multiple_lists(values, doc_info_attributes::authors);
- std::vector<value> copyrights = consume_multiple_lists(values, doc_info_attributes::copyright);
+ std::vector<value> authors = consume_multiple_values(values, doc_info_attributes::authors);
+ std::vector<value> copyrights = consume_multiple_values(values, doc_info_attributes::copyright);
value license = consume_value_in_list(values, doc_info_attributes::license, &duplicates);
- std::vector<value> biblioids = consume_multiple_lists(values, doc_info_attributes::biblioid);
+ std::vector<value> biblioids = consume_multiple_values(values, doc_info_attributes::biblioid);
value xmlbase = consume_value_in_list(values, doc_info_attributes::xmlbase, &duplicates);
values.finish();
if(!duplicates.empty())
{
- detail::outwarn(actions.current_file->path)
+ detail::outwarn(state.current_file->path)
<< (duplicates.size() > 1 ?
"Duplicate attributes" : "Duplicate attribute")
- << ":" << detail::utf8(boost::algorithm::join(duplicates, ", "))
+ << ":" << boost::algorithm::join(duplicates, ", ")
<< "\n"
;
}
@@ -203,12 +206,13 @@ namespace quickbook
// Quickbook version
- unsigned new_version = get_version(actions, use_doc_info, qbk_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 && new_version >= 106)
{
- detail::outwarn(actions.current_file->path)
- << "Quickbook 1.6 is still under development and is "
+ 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;
}
@@ -218,34 +222,34 @@ namespace quickbook
else if (use_doc_info) {
// hard code quickbook version to v1.1
qbk_version_n = 101;
- detail::outwarn(actions.current_file, pos.base())
+ detail::outwarn(state.current_file, pos.base())
<< "Quickbook version undefined. "
"Version 1.1 is assumed" << std::endl;
}
- actions.current_file->version(qbk_version_n);
+ state.current_file->version(qbk_version_n);
// Compatibility Version
unsigned compatibility_version =
- get_version(actions, use_doc_info, compatibility_mode);
+ get_version(state, use_doc_info, compatibility_mode);
if (!compatibility_version) {
compatibility_version = use_doc_info ?
- qbk_version_n : actions.ids.compatibility_version();
+ qbk_version_n : state.ids.compatibility_version();
}
// Start file, finish here if not generating document info.
if (!use_doc_info)
{
- actions.ids.start_file(compatibility_version, include_doc_id_, id_,
+ state.ids.start_file(compatibility_version, include_doc_id_, id_,
doc_title);
return "";
}
std::string id_placeholder =
- actions.ids.start_file_with_docinfo(
+ state.ids.start_file_with_docinfo(
compatibility_version, include_doc_id_, id_, doc_title);
// Make sure we really did have a document info block.
@@ -258,22 +262,22 @@ namespace quickbook
if (!xmlbase.empty())
{
- xinclude_path x = calculate_xinclude_path(xmlbase, actions);
+ xinclude_path x = calculate_xinclude_path(xmlbase, state);
if (!fs::is_directory(x.path))
{
detail::outerr(xmlbase.get_file(), xmlbase.get_position())
<< "xmlbase \""
- << detail::utf8(xmlbase.get_quickbook())
+ << xmlbase.get_quickbook()
<< "\" isn't a directory."
<< std::endl;
- ++actions.error_count;
+ ++state.error_count;
}
else
{
xmlbase_value = x.uri;
- actions.xinclude_base = x.path;
+ state.xinclude_base = x.path;
}
}
@@ -294,11 +298,11 @@ namespace quickbook
if(!invalid_attributes.empty())
{
- detail::outwarn(actions.current_file->path)
+ detail::outwarn(state.current_file->path)
<< (invalid_attributes.size() > 1 ?
"Invalid attributes" : "Invalid attribute")
- << " for '" << detail::utf8(doc_type) << " document info': "
- << detail::utf8(boost::algorithm::join(invalid_attributes, ", "))
+ << " for '" << doc_type << " document info': "
+ << boost::algorithm::join(invalid_attributes, ", ")
<< "\n"
;
}
@@ -308,7 +312,7 @@ namespace quickbook
if (!nested_file)
{
- actions.out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ state.out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<!DOCTYPE "
<< doc_type
<< " PUBLIC \"-//Boost//DTD BoostBook XML V1.0//EN\"\n"
@@ -316,51 +320,51 @@ namespace quickbook
;
}
- actions.out << '<' << doc_type << "\n"
+ state.out << '<' << doc_type << "\n"
<< " id=\""
<< id_placeholder
<< "\"\n";
if(!lang.empty())
{
- actions.out << " lang=\""
+ state.out << " lang=\""
<< doc_info_output(lang, 106)
<< "\"\n";
}
if(doc_type == "library" && !doc_title.empty())
{
- actions.out << " name=\"" << doc_info_output(doc_title, 106) << "\"\n";
+ state.out << " name=\"" << doc_info_output(doc_title, 106) << "\"\n";
}
// Set defaults for dirname + last_revision
if (!dirname.empty() || doc_type == "library")
{
- actions.out << " dirname=\"";
+ state.out << " dirname=\"";
if (!dirname.empty()) {
- actions.out << doc_info_output(dirname, 106);
+ state.out << doc_info_output(dirname, 106);
}
else if (!id_.empty()) {
- actions.out << id_;
+ state.out << id_;
}
else if (!include_doc_id_.empty()) {
- actions.out << include_doc_id_;
+ state.out << include_doc_id_;
}
else if (!doc_title.empty()) {
- actions.out << detail::make_identifier(doc_title.get_quickbook());
+ state.out << detail::make_identifier(doc_title.get_quickbook());
}
else {
- actions.out << "library";
+ state.out << "library";
}
- actions.out << "\"\n";
+ state.out << "\"\n";
}
- actions.out << " last-revision=\"";
+ state.out << " last-revision=\"";
if (!last_revision.empty())
{
- actions.out << doc_info_output(last_revision, 106);
+ state.out << doc_info_output(last_revision, 106);
}
else
{
@@ -375,19 +379,19 @@ namespace quickbook
current_gm_time
);
- actions.out << strdate;
+ state.out << strdate;
}
- actions.out << "\" \n";
+ state.out << "\" \n";
if (!xmlbase.empty())
{
- actions.out << " xml:base=\""
+ state.out << " xml:base=\""
<< xmlbase_value
<< "\"\n";
}
- actions.out << " xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n";
+ state.out << " xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n";
std::ostringstream tmp;
@@ -429,9 +433,9 @@ namespace quickbook
year_start;
if (year_end < year_start) {
- ++actions.error_count;
+ ++state.error_count;
- detail::outerr(actions.current_file, copyright.begin()->get_position())
+ detail::outerr(state.current_file, copyright.begin()->get_position())
<< "Invalid year range: "
<< year_start
<< "-"
@@ -456,7 +460,7 @@ namespace quickbook
if (!license.empty())
{
tmp << " <legalnotice id=\""
- << actions.ids.add_id("legal", id_category::generated)
+ << state.ids.add_id("legal", id_category::generated)
<< "\">\n"
<< " <para>\n"
<< " " << doc_info_output(license, 103) << "\n"
@@ -502,14 +506,22 @@ namespace quickbook
biblioid.finish();
}
+ BOOST_FOREACH(value escaped, escaped_attributes)
+ {
+ tmp << "<!--quickbook-escape-prefix-->"
+ << escaped.get_quickbook()
+ << "<!--quickbook-escape-postfix-->"
+ ;
+ }
+
if(doc_type != "library") {
- write_document_title(actions.out, doc_title, version);
+ write_document_title(state.out, doc_title, version);
}
std::string docinfo = tmp.str();
if(!docinfo.empty())
{
- actions.out << " <" << doc_type << "info>\n"
+ state.out << " <" << doc_type << "info>\n"
<< docinfo
<< " </" << doc_type << "info>\n"
<< "\n"
@@ -517,31 +529,31 @@ namespace quickbook
}
if(doc_type == "library") {
- write_document_title(actions.out, doc_title, version);
+ write_document_title(state.out, doc_title, version);
}
return doc_type;
}
- void post(quickbook::actions& actions, std::string const& doc_type)
+ void post(quickbook::state& state, std::string const& doc_type)
{
// We've finished generating our output. Here's what we'll do
// *after* everything else.
// Close any open sections.
- if (!doc_type.empty() && actions.ids.section_level() > 1) {
- detail::outwarn(actions.current_file->path)
+ if (!doc_type.empty() && state.ids.section_level() > 1) {
+ detail::outwarn(state.current_file->path)
<< "Missing [endsect] detected at end of file."
<< std::endl;
- while(actions.ids.section_level() > 1) {
- actions.out << "</section>";
- actions.ids.end_section();
+ while(state.ids.section_level() > 1) {
+ state.out << "</section>";
+ state.ids.end_section();
}
}
- actions.ids.end_file();
- if (!doc_type.empty()) actions.out << "\n</" << doc_type << ">\n\n";
+ state.ids.end_file();
+ if (!doc_type.empty()) state.out << "\n</" << doc_type << ">\n\n";
}
static void write_document_title(collector& out, value const& title, value const& version)
diff --git a/tools/quickbook/src/doc_info_grammar.cpp b/tools/quickbook/src/doc_info_grammar.cpp
index 26418eec48..862d0ce57a 100644
--- a/tools/quickbook/src/doc_info_grammar.cpp
+++ b/tools/quickbook/src/doc_info_grammar.cpp
@@ -19,7 +19,8 @@
#include <boost/spirit/include/phoenix1_primitives.hpp>
#include <boost/spirit/include/phoenix1_operators.hpp>
#include "grammar_impl.hpp"
-#include "actions_class.hpp"
+#include "state.hpp"
+#include "actions.hpp"
#include "doc_info_tags.hpp"
#include "phrase_tags.hpp"
@@ -69,6 +70,7 @@ namespace quickbook
cl::rule<scanner>
doc_info_block, doc_attribute, doc_info_attribute,
+ doc_info_escaped_attributes,
doc_title, doc_simple, doc_phrase, doc_fallback,
doc_authors, doc_author,
doc_copyright, doc_copyright_holder,
@@ -113,6 +115,11 @@ namespace quickbook
BOOST_FOREACH(value::tag_type t, doc_info_attributes::tags()) {
local.doc_info_attributes.add(doc_info_attributes::name(t), t);
}
+
+ // Actions
+ error_action error(state);
+ plain_char_action plain_char(state.phrase, state);
+ scoped_parser<to_value_scoped_action> to_value(state);
doc_info_details =
space [ph::var(local.source_mode_unset) = true]
@@ -126,9 +133,9 @@ namespace quickbook
'['
>> space
>> (local.doc_types >> cl::eps_p)
- [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::type)]
+ [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::type)]
>> hard_space
- >> actions.to_value(doc_info_tags::title)
+ >> to_value(doc_info_tags::title)
[ *( ~cl::eps_p(blank >> (cl::ch_p('[') | ']' | cl::eol_p))
>> local.char_
)
@@ -137,15 +144,18 @@ namespace quickbook
>> blank
]
>> space
- >> !(qbk_since(106u) >> cl::eps_p(ph::var(local.source_mode_unset))
- [cl::assign_a(actions.source_mode, "c++")]
+ >> !(qbk_ver(106u) >> cl::eps_p(ph::var(local.source_mode_unset))
+ [cl::assign_a(state.source_mode, "c++")]
)
- >> (*( local.doc_info_attribute
- >> space
- )) [actions.values.sort()]
+ >> ( *( ( local.doc_info_attribute
+ | local.doc_info_escaped_attributes
+ )
+ >> space
+ )
+ ) [state.values.sort()]
>> ( ']'
>> (+eol | cl::end_p)
- | cl::eps_p [actions.error]
+ | cl::eps_p [error]
)
;
@@ -154,8 +164,8 @@ namespace quickbook
>> space
>> local.doc_attributes [local.assign_attribute]
>> hard_space
- >> actions.values.list(ph::var(local.attribute_tag))
- [ cl::eps_p [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::before_docinfo)]
+ >> state.values.list(ph::var(local.attribute_tag))
+ [ cl::eps_p [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::before_docinfo)]
>> local.attribute_rule
]
>> space
@@ -169,33 +179,41 @@ namespace quickbook
[local.assign_attribute]
| (+(cl::alnum_p | '_' | '-'))
[local.fallback_attribute]
- [actions.error("Unrecognized document attribute: '%s'.")]
+ [error("Unrecognized document attribute: '%s'.")]
)
>> hard_space
- >> actions.values.list(ph::var(local.attribute_tag))
+ >> state.values.list(ph::var(local.attribute_tag))
[local.attribute_rule]
>> space
>> ']'
;
- local.doc_fallback = actions.to_value() [
+ local.doc_fallback = to_value() [
*(~cl::eps_p(']') >> local.char_)
];
+ local.doc_info_escaped_attributes =
+ ("'''" >> !eol)
+ >> (*(cl::anychar_p - "'''")) [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::escaped_attribute)]
+ >> ( cl::str_p("'''")
+ | cl::eps_p [error("Unclosed boostbook escape.")]
+ )
+ ;
+
// Document Attributes
local.quickbook_version =
- cl::uint_p [actions.values.entry(ph::arg1)]
+ cl::uint_p [state.values.entry(ph::arg1)]
>> '.'
- >> uint2_t() [actions.values.entry(ph::arg1)]
+ >> uint2_t() [state.values.entry(ph::arg1)]
;
local.attribute_rules[doc_attributes::qbk_version] = &local.quickbook_version;
local.doc_compatibility_mode =
- cl::uint_p [actions.values.entry(ph::arg1)]
+ cl::uint_p [state.values.entry(ph::arg1)]
>> '.'
- >> uint2_t() [actions.values.entry(ph::arg1)]
+ >> uint2_t() [state.values.entry(ph::arg1)]
;
local.attribute_rules[doc_attributes::compatibility_mode] = &local.doc_compatibility_mode;
@@ -205,7 +223,7 @@ namespace quickbook
cl::str_p("c++")
| "python"
| "teletype"
- ) [cl::assign_a(actions.source_mode)]
+ ) [cl::assign_a(state.source_mode)]
[ph::var(local.source_mode_unset) = false]
;
@@ -213,7 +231,7 @@ namespace quickbook
// Document Info Attributes
- local.doc_simple = actions.to_value() [*(~cl::eps_p(']') >> local.char_)];
+ local.doc_simple = to_value() [*(~cl::eps_p(']') >> local.char_)];
local.attribute_rules[doc_info_attributes::version] = &local.doc_simple;
local.attribute_rules[doc_info_attributes::id] = &local.doc_simple;
local.attribute_rules[doc_info_attributes::dirname] = &local.doc_simple;
@@ -232,18 +250,18 @@ namespace quickbook
local.doc_copyright =
*( +( local.doc_copyright_year
- [actions.values.entry(ph::arg1, doc_info_tags::copyright_year)]
+ [state.values.entry(ph::arg1, doc_info_tags::copyright_year)]
>> space
>> !( '-'
>> space
>> local.doc_copyright_year
- [actions.values.entry(ph::arg1, doc_info_tags::copyright_year_end)]
+ [state.values.entry(ph::arg1, doc_info_tags::copyright_year_end)]
>> space
)
>> !cl::ch_p(',')
>> space
)
- >> actions.to_value(doc_info_tags::copyright_name) [ local.doc_copyright_holder ]
+ >> to_value(doc_info_tags::copyright_name) [ local.doc_copyright_holder ]
>> !cl::ch_p(',')
>> space
)
@@ -251,17 +269,17 @@ namespace quickbook
local.attribute_rules[doc_info_attributes::copyright] = &local.doc_copyright;
- local.doc_phrase = actions.to_value() [ nested_phrase ];
+ local.doc_phrase = to_value() [ nested_phrase ];
local.attribute_rules[doc_info_attributes::purpose] = &local.doc_phrase;
local.attribute_rules[doc_info_attributes::license] = &local.doc_phrase;
local.doc_author =
'['
>> space
- >> actions.to_value(doc_info_tags::author_surname)
+ >> to_value(doc_info_tags::author_surname)
[*(~cl::eps_p(',') >> local.char_)]
>> ',' >> space
- >> actions.to_value(doc_info_tags::author_first)
+ >> to_value(doc_info_tags::author_first)
[*(~cl::eps_p(']') >> local.char_)]
>> ']'
;
@@ -276,14 +294,14 @@ namespace quickbook
local.attribute_rules[doc_info_attributes::authors] = &local.doc_authors;
local.doc_biblioid =
- (+cl::alnum_p) [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::biblioid_class)]
+ (+cl::alnum_p) [state.values.entry(ph::arg1, ph::arg2, doc_info_tags::biblioid_class)]
>> hard_space
- >> actions.to_value(doc_info_tags::biblioid_value)
+ >> to_value(doc_info_tags::biblioid_value)
[+(~cl::eps_p(']') >> local.char_)]
;
local.attribute_rules[doc_info_attributes::biblioid] = &local.doc_biblioid;
- local.char_ = escape | cl::anychar_p[actions.plain_char];
+ local.char_ = escape | cl::anychar_p[plain_char];
}
}
diff --git a/tools/quickbook/src/doc_info_tags.hpp b/tools/quickbook/src/doc_info_tags.hpp
index 4caea3317c..ccc69186cb 100644
--- a/tools/quickbook/src/doc_info_tags.hpp
+++ b/tools/quickbook/src/doc_info_tags.hpp
@@ -21,6 +21,7 @@ namespace quickbook
(copyright_year)(copyright_year_end)(copyright_name)
(license)
(biblioid_class)(biblioid_value)
+ (escaped_attribute)
)
QUICKBOOK_VALUE_NAMED_TAGS(doc_attributes, 0x440,
diff --git a/tools/quickbook/src/files.cpp b/tools/quickbook/src/files.cpp
index ce63c84eb2..f85b611623 100644
--- a/tools/quickbook/src/files.cpp
+++ b/tools/quickbook/src/files.cpp
@@ -8,10 +8,11 @@
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#include "files.hpp"
-#include <boost/filesystem/v3/fstream.hpp>
+#include <boost/filesystem/fstream.hpp>
#include <boost/unordered_map.hpp>
#include <boost/range/algorithm/upper_bound.hpp>
#include <boost/range/algorithm/transform.hpp>
+#include <boost/foreach.hpp>
#include <fstream>
#include <iterator>
@@ -285,8 +286,9 @@ namespace quickbook
struct mapped_file : file
{
mapped_file(file_ptr original) :
- file(original->path, std::string(), original->version()),
- original(original), mapped_sections() {}
+ file(*original, std::string()),
+ original(original), mapped_sections()
+ {}
file_ptr original;
std::vector<mapped_file_section> mapped_sections;
diff --git a/tools/quickbook/src/files.hpp b/tools/quickbook/src/files.hpp
index 1b0ef282b0..4f217e70cd 100644
--- a/tools/quickbook/src/files.hpp
+++ b/tools/quickbook/src/files.hpp
@@ -12,11 +12,10 @@
#define BOOST_QUICKBOOK_FILES_HPP
#include <string>
-#include <boost/filesystem/v3/path.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/intrusive_ptr.hpp>
#include <stdexcept>
#include <cassert>
-#include "intrusive_base.hpp"
namespace quickbook {
@@ -34,20 +33,35 @@ namespace quickbook {
int column;
};
- struct file : intrusive_base<file>
+ struct file
{
+ private:
+ // Non copyable
+ file& operator=(file const&);
+ file(file const&);
+ public:
fs::path const path;
std::string source;
+ bool is_code_snippets;
private:
unsigned qbk_version;
+ unsigned ref_count;
public:
file(fs::path const& path, std::string const& source,
unsigned qbk_version) :
- path(path), source(source), qbk_version(qbk_version)
+ path(path), source(source), is_code_snippets(false),
+ qbk_version(qbk_version), ref_count(0)
{}
- virtual ~file() {}
+ file(file const& f, std::string const& source) :
+ path(f.path), source(source), is_code_snippets(f.is_code_snippets),
+ qbk_version(f.qbk_version), ref_count(0)
+ {}
+
+ virtual ~file() {
+ assert(!ref_count);
+ }
unsigned version() const {
assert(qbk_version);
@@ -63,6 +77,11 @@ namespace quickbook {
}
virtual file_position position_of(std::string::const_iterator) const;
+
+ friend void intrusive_ptr_add_ref(file* ptr) { ++ptr->ref_count; }
+
+ friend void intrusive_ptr_release(file* ptr)
+ { if(--ptr->ref_count == 0) delete ptr; }
};
// If version isn't supplied then it must be set later.
diff --git a/tools/quickbook/src/fwd.hpp b/tools/quickbook/src/fwd.hpp
index 7995c14097..7cccde8735 100644
--- a/tools/quickbook/src/fwd.hpp
+++ b/tools/quickbook/src/fwd.hpp
@@ -16,12 +16,13 @@
namespace quickbook
{
- struct actions;
+ struct state;
struct quickbook_grammar;
struct collector;
struct id_manager;
struct section_info;
struct file;
+ struct template_symbol;
typedef boost::intrusive_ptr<file> file_ptr;
typedef std::string::const_iterator string_iterator;
diff --git a/tools/quickbook/src/grammar.cpp b/tools/quickbook/src/grammar.cpp
index a0e2e57887..8f244f18ac 100644
--- a/tools/quickbook/src/grammar.cpp
+++ b/tools/quickbook/src/grammar.cpp
@@ -13,8 +13,8 @@
namespace quickbook
{
- quickbook_grammar::quickbook_grammar(quickbook::actions& a)
- : impl_(new impl(a))
+ quickbook_grammar::quickbook_grammar(quickbook::state& s)
+ : 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")
@@ -27,8 +27,8 @@ namespace quickbook
{
}
- quickbook_grammar::impl::impl(quickbook::actions& a)
- : actions(a)
+ quickbook_grammar::impl::impl(quickbook::state& s)
+ : state(s)
, cleanup_()
{
init_main();
diff --git a/tools/quickbook/src/grammar.hpp b/tools/quickbook/src/grammar.hpp
index 73aae4a26c..54aaf2b3ea 100644
--- a/tools/quickbook/src/grammar.hpp
+++ b/tools/quickbook/src/grammar.hpp
@@ -62,7 +62,7 @@ namespace quickbook
grammar block;
grammar doc_info;
- quickbook_grammar(quickbook::actions&);
+ quickbook_grammar(quickbook::state&);
~quickbook_grammar();
};
}
diff --git a/tools/quickbook/src/grammar_impl.hpp b/tools/quickbook/src/grammar_impl.hpp
index c968111b8c..090b399048 100644
--- a/tools/quickbook/src/grammar_impl.hpp
+++ b/tools/quickbook/src/grammar_impl.hpp
@@ -38,6 +38,7 @@ namespace quickbook
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
};
@@ -59,7 +60,7 @@ namespace quickbook
struct quickbook_grammar::impl
{
- quickbook::actions& actions;
+ quickbook::state& state;
cleanup cleanup_;
// Main Grammar
@@ -73,6 +74,7 @@ namespace quickbook
cl::rule<scanner> inside_preformatted;
cl::rule<scanner> inside_paragraph;
cl::rule<scanner> command_line;
+ cl::rule<scanner> attribute_value_1_7;
cl::rule<scanner> escape;
cl::rule<scanner> raw_escape;
@@ -92,7 +94,7 @@ namespace quickbook
// Doc Info
cl::rule<scanner> doc_info_details;
- impl(quickbook::actions&);
+ impl(quickbook::state&);
private:
diff --git a/tools/quickbook/src/id_manager.cpp b/tools/quickbook/src/id_manager.cpp
index 32e537df71..3b2f601a11 100644
--- a/tools/quickbook/src/id_manager.cpp
+++ b/tools/quickbook/src/id_manager.cpp
@@ -9,8 +9,7 @@
#include "id_manager.hpp"
#include "utils.hpp"
#include "string_ref.hpp"
-#include "intrusive_base.hpp"
-#include <boost/intrusive_ptr.hpp>
+#include <boost/make_shared.hpp>
#include <boost/unordered_map.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/range/algorithm.hpp>
@@ -113,7 +112,7 @@ namespace quickbook
struct id_state
{
- boost::intrusive_ptr<file_info> current_file;
+ boost::shared_ptr<file_info> current_file;
std::deque<id_placeholder> placeholders;
// Placeholder methods
@@ -149,25 +148,25 @@ private:
id_placeholder* add_id_to_section(
std::string const& id,
id_category category,
- boost::intrusive_ptr<section_info> const& section);
+ 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::intrusive_ptr<section_info> const&,
- boost::intrusive_ptr<section_info> const&);
+ void reswitch_sections(boost::shared_ptr<section_info> const&,
+ boost::shared_ptr<section_info> const&);
void restore_section();
};
- struct file_info : intrusive_base<file_info>
+ struct file_info
{
- boost::intrusive_ptr<file_info> parent;
- boost::intrusive_ptr<doc_info> document;
+ boost::shared_ptr<file_info> parent;
+ boost::shared_ptr<doc_info> document;
bool document_root; // !parent || document != parent->document
unsigned compatibility_version;
- boost::intrusive_ptr<section_info> switched_section;
+ 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
@@ -175,15 +174,15 @@ private:
// document title instead of the id.
std::string doc_id_1_1;
- file_info(boost::intrusive_ptr<file_info> const& parent,
+ 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::intrusive_ptr<file_info> const& parent,
- boost::intrusive_ptr<doc_info> const& document,
+ 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),
@@ -191,9 +190,9 @@ private:
{}
};
- struct doc_info : intrusive_base<doc_info>
+ struct doc_info
{
- boost::intrusive_ptr<section_info> current_section;
+ boost::shared_ptr<section_info> current_section;
std::string last_title_1_1;
std::string section_id_1_1;
@@ -202,15 +201,15 @@ private:
{}
};
- struct section_info : intrusive_base<section_info>
+ struct section_info
{
- boost::intrusive_ptr<section_info> parent;
+ boost::shared_ptr<section_info> parent;
unsigned compatibility_version;
unsigned level;
std::string id_1_1;
id_placeholder* placeholder_1_6;
- section_info(boost::intrusive_ptr<section_info> const& parent,
+ 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),
@@ -394,11 +393,11 @@ private:
}
void id_state::reswitch_sections(
- boost::intrusive_ptr<section_info> const& popped_section,
- boost::intrusive_ptr<section_info> const& parent_section)
+ boost::shared_ptr<section_info> const& popped_section,
+ boost::shared_ptr<section_info> const& parent_section)
{
- boost::intrusive_ptr<file_info> file = current_file;
- boost::intrusive_ptr<file_info> first_switched_file;
+ boost::shared_ptr<file_info> file = current_file;
+ boost::shared_ptr<file_info> first_switched_file;
for (;;) {
if (file->switched_section == popped_section)
@@ -436,15 +435,16 @@ private:
{
// Create new file
- boost::intrusive_ptr<file_info> parent = current_file;
+ boost::shared_ptr<file_info> parent = current_file;
if (document_root) {
- current_file = new file_info(parent, new doc_info(),
+ current_file = boost::make_shared<file_info>(parent,
+ boost::make_shared<doc_info>(),
compatibility_version);
}
else {
current_file =
- new file_info(parent, compatibility_version);
+ boost::make_shared<file_info>(parent, compatibility_version);
}
// Choose specified id to use. Prefer 'include_doc_id' (the id
@@ -505,7 +505,7 @@ private:
if (compatibility_version >= 106u && !initial_doc_id.empty()) {
switch_section(add_id_to_section(initial_doc_id,
id_category::explicit_section_id,
- boost::intrusive_ptr<section_info>()));
+ boost::shared_ptr<section_info>()));
}
return 0;
@@ -529,7 +529,7 @@ private:
id_placeholder* id_state::add_id_to_section(
std::string const& id,
id_category category,
- boost::intrusive_ptr<section_info> const& section)
+ boost::shared_ptr<section_info> const& section)
{
std::string id_part = id;
@@ -583,11 +583,12 @@ private:
std::string const& id,
id_category category)
{
- boost::intrusive_ptr<section_info> parent =
+ boost::shared_ptr<section_info> parent =
current_file->document->current_section;
- boost::intrusive_ptr<section_info> new_section =
- new section_info(parent, current_file->compatibility_version, id);
+ boost::shared_ptr<section_info> new_section =
+ boost::make_shared<section_info>(parent,
+ current_file->compatibility_version, id);
id_placeholder* p;
@@ -630,7 +631,7 @@ private:
void id_state::end_section()
{
- boost::intrusive_ptr<section_info> popped_section =
+ boost::shared_ptr<section_info> popped_section =
current_file->document->current_section;
current_file->document->current_section = popped_section->parent;
@@ -810,7 +811,7 @@ private:
// Data used for generating placeholders that have duplicates.
//
- struct id_generation_data : intrusive_base<id_generation_data>
+ struct id_generation_data
{
id_generation_data(std::string const& src_id)
: child_start(src_id.rfind('.') + 1),
@@ -865,7 +866,7 @@ private:
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::intrusive_ptr<id_generation_data> generation_data;
+ boost::shared_ptr<id_generation_data> generation_data;
// If a duplicates are found, this is
// created to generate new ids.
//
@@ -1036,7 +1037,8 @@ private:
if (!p.data->generation_data)
{
- p.data->generation_data.reset(new id_generation_data(p.id));
+ p.data->generation_data =
+ boost::make_shared<id_generation_data>(p.id);
register_generation_data(p, ids);
}
diff --git a/tools/quickbook/src/input_path.cpp b/tools/quickbook/src/input_path.cpp
index 4523ac6f22..9b6a87784d 100644
--- a/tools/quickbook/src/input_path.cpp
+++ b/tools/quickbook/src/input_path.cpp
@@ -122,7 +122,7 @@ namespace detail {
return fs::path(static_cast<wchar_t*>(ptr));
}
- stream_string path_to_stream(fs::path const& path)
+ ostream::string path_to_stream(fs::path const& path)
{
cygwin_conv_path_t flags = CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
@@ -145,12 +145,12 @@ namespace detail {
}
#if QUICKBOOK_WIDE_PATHS && !QUICKBOOK_WIDE_STREAMS
- stream_string path_to_stream(fs::path const& path)
+ ostream::string path_to_stream(fs::path const& path)
{
return path.string();
}
#else
- stream_string path_to_stream(fs::path const& path)
+ ostream::string path_to_stream(fs::path const& path)
{
return path.native();
}
@@ -166,21 +166,23 @@ namespace detail {
if (_isatty(_fileno(stderr))) _setmode(_fileno(stderr), _O_U16TEXT);
}
- void write_utf8(ostream& out, std::string const& x)
+ void write_utf8(ostream::base_ostream& out, std::string const& x)
{
out << from_utf8(x);
}
ostream& out()
{
- return std::wcout;
+ static ostream x(std::wcout);
+ return x;
}
namespace
{
inline ostream& error_stream()
{
- return std::wcerr;
+ static ostream x(std::wcerr);
+ return x;
}
}
@@ -190,21 +192,23 @@ namespace detail {
{
}
- void write_utf8(ostream& out, std::string const& x)
+ void write_utf8(ostream::base_ostream& out, std::string const& x)
{
out << x;
}
ostream& out()
{
- return std::cout;
+ static ostream x(std::cout);
+ return x;
}
namespace
{
inline ostream& error_stream()
{
- return std::clog;
+ static ostream x(std::clog);
+ return x;
}
}
@@ -254,4 +258,61 @@ namespace detail {
{
return outwarn(f->path, f->position_of(pos).line);
}
+
+ ostream& ostream::operator<<(char c) {
+ assert(c > 0 && c <= 127);
+ base << c;
+ return *this;
+ }
+
+ inline bool check_ascii(char const* x) {
+ for(;*x;++x) if(*x <= 0 || *x > 127) return false;
+ return true;
+ }
+
+ ostream& ostream::operator<<(char const* x) {
+ assert(check_ascii(x));
+ base << x;
+ return *this;
+ }
+
+ ostream& ostream::operator<<(std::string const& x) {
+ write_utf8(base, x);
+ return *this;
+ }
+
+ ostream& ostream::operator<<(int x) {
+ base << x;
+ return *this;
+ }
+
+ ostream& ostream::operator<<(unsigned int x) {
+ base << x;
+ return *this;
+ }
+
+ ostream& ostream::operator<<(long x) {
+ base << x;
+ return *this;
+ }
+
+ ostream& ostream::operator<<(unsigned long x) {
+ base << x;
+ return *this;
+ }
+
+ ostream& ostream::operator<<(fs::path const& x) {
+ base << path_to_stream(x);
+ return *this;
+ }
+
+ ostream& ostream::operator<<(base_ostream& (*x)(base_ostream&)) {
+ base << x;
+ return *this;
+ }
+
+ ostream& ostream::operator<<(base_ios& (*x)(base_ios&)) {
+ base << x;
+ return *this;
+ }
}}
diff --git a/tools/quickbook/src/input_path.hpp b/tools/quickbook/src/input_path.hpp
index a23474d3e1..a9b55f6b2c 100644
--- a/tools/quickbook/src/input_path.hpp
+++ b/tools/quickbook/src/input_path.hpp
@@ -10,7 +10,7 @@
#define BOOST_QUICKBOOK_DETAIL_INPUT_PATH_HPP
#include <boost/config.hpp>
-#include <boost/filesystem/v3/path.hpp>
+#include <boost/filesystem/path.hpp>
#include <string>
#include <stdexcept>
#include <iostream>
@@ -66,17 +66,47 @@ namespace quickbook
typedef std::string input_string;
#endif
+ // A light wrapper around C++'s streams that gets things right
+ // in the quickbook context.
+ //
+ // This is far from perfect but it fixes some issues.
+ struct ostream
+ {
#if QUICKBOOK_WIDE_STREAMS
- typedef std::wostream ostream;
- typedef std::wstring stream_string;
+ typedef std::wostream base_ostream;
+ typedef std::wios base_ios;
+ typedef std::wstring string;
#else
- typedef std::ostream ostream;
- typedef std::string stream_string;
+ typedef std::ostream base_ostream;
+ typedef std::ios base_ios;
+ typedef std::string string;
#endif
+ base_ostream& base;
+
+ explicit ostream(base_ostream& x) : base(x) {}
+
+ // C strings should always be ascii.
+ ostream& operator<<(char);
+ ostream& operator<<(char const*);
+
+ // std::string should be UTF-8 (what a mess!)
+ ostream& operator<<(std::string const&);
+
+ // Other value types.
+ ostream& operator<<(int x);
+ ostream& operator<<(unsigned int x);
+ ostream& operator<<(long x);
+ ostream& operator<<(unsigned long x);
+ ostream& operator<<(fs::path const&);
+
+ // Modifiers
+ ostream& operator<<(base_ostream& (*)(base_ostream&));
+ ostream& operator<<(base_ios& (*)(base_ios&));
+ };
+
std::string input_to_utf8(input_string const&);
fs::path input_to_path(input_string const&);
- stream_string path_to_stream(fs::path const&);
std::string path_to_generic(fs::path const&);
fs::path generic_to_path(std::string const&);
@@ -94,29 +124,6 @@ namespace quickbook
ostream& outwarn(fs::path const& file, int line = -1);
ostream& outerr(file_ptr const&, string_iterator);
ostream& outwarn(file_ptr const&, string_iterator);
-
- struct utf8_proxy
- {
- std::string value;
-
- explicit utf8_proxy(std::string const& v) : value(v) {}
- };
-
- void write_utf8(ostream& out, std::string const&);
-
- inline ostream& operator<<(ostream& out, utf8_proxy const& p) {
- write_utf8(out, p.value);
- return out;
- }
-
- inline utf8_proxy utf8(std::string const& value) {
- return utf8_proxy(value);
- }
-
- template <typename It>
- inline utf8_proxy utf8(It begin, It end) {
- return utf8_proxy(std::string(begin, end));
- }
}
}
diff --git a/tools/quickbook/src/intrusive_base.hpp b/tools/quickbook/src/intrusive_base.hpp
deleted file mode 100644
index 702c13d0b9..0000000000
--- a/tools/quickbook/src/intrusive_base.hpp
+++ /dev/null
@@ -1,36 +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_INTRUSIVE_BASE_HPP)
-#define BOOST_QUICKBOOK_INTRUSIVE_BASE_HPP
-
-namespace quickbook
-{
- //
- // instructive_base
- //
-
- template <typename T>
- struct intrusive_base
- {
- intrusive_base() : ref_count_(0) {}
- intrusive_base(intrusive_base const&) : ref_count_(0) {}
- intrusive_base& operator=(intrusive_base const&) { return *this; }
- ~intrusive_base() { assert(!ref_count_); }
-
- friend void intrusive_ptr_add_ref(T* ptr)
- { ++ptr->ref_count_; }
-
- friend void intrusive_ptr_release(T* ptr)
- { if(--ptr->ref_count_ == 0) delete ptr; }
- private:
- unsigned ref_count_;
- };
-}
-
-#endif
diff --git a/tools/quickbook/src/main_grammar.cpp b/tools/quickbook/src/main_grammar.cpp
index 1ec2ff9ca8..74dbecea76 100644
--- a/tools/quickbook/src/main_grammar.cpp
+++ b/tools/quickbook/src/main_grammar.cpp
@@ -9,7 +9,8 @@
=============================================================================*/
#include "grammar_impl.hpp"
-#include "actions_class.hpp"
+#include "state.hpp"
+#include "actions.hpp"
#include "utils.hpp"
#include "template_tags.hpp"
#include "block_tags.hpp"
@@ -27,8 +28,6 @@
#include <boost/range/algorithm/find_first_of.hpp>
#include <boost/range/as_literal.hpp>
-#include <iostream>
-
namespace quickbook
{
namespace cl = boost::spirit::classic;
@@ -91,44 +90,6 @@ namespace quickbook
string_iterator last);
void clear_stack();
- struct process_element_impl : scoped_action_base {
- process_element_impl(main_grammar_local& l)
- : l(l) {}
-
- bool start()
- {
- if (!(l.info.type & l.element.context()) ||
- qbk_version_n < l.info.qbk_version)
- return false;
-
- info_ = l.info;
-
- if (info_.type != element_info::phrase &&
- info_.type != element_info::maybe_block)
- l.actions_.paragraph();
-
- l.actions_.values.builder.reset();
-
- return true;
- }
-
- template <typename ResultT, typename ScannerT>
- bool result(ResultT result, ScannerT const& scan)
- {
- if (result || info_.type & element_info::in_phrase)
- return result;
-
- l.actions_.error(scan.first, scan.first);
- return true;
- }
-
- void success(parse_iterator, parse_iterator) { l.element_type = info_.type; }
- void failure() { l.element_type = element_info::nothing; }
-
- main_grammar_local& l;
- element_info info_;
- };
-
struct in_list_impl {
main_grammar_local& l;
@@ -216,53 +177,167 @@ namespace quickbook
element_info info;
element_info::type_enum element_type;
- // actions
- quickbook::actions& actions_;
- member_action<main_grammar_local> check_indentation;
- member_action<main_grammar_local> check_code_block;
- member_action<main_grammar_local> start_blocks;
- member_action<main_grammar_local> end_blocks;
- in_list_impl in_list;
- scoped_parser<process_element_impl> process_element;
- scoped_parser<set_no_eols_scoped> scoped_no_eols;
+ // state
+ quickbook::state& state_;
////////////////////////////////////////////////////////////////////////
// Local constructor
- main_grammar_local(quickbook::actions& actions)
+ main_grammar_local(quickbook::state& state)
: list_stack()
, list_indent(0)
, no_eols(true)
- , actions_(actions)
- , check_indentation(*this, &main_grammar_local::check_indentation_impl)
- , check_code_block(*this, &main_grammar_local::check_indentation_impl)
- , start_blocks(*this, &main_grammar_local::start_blocks_impl)
- , end_blocks(*this, &main_grammar_local::end_blocks_impl)
- , in_list(*this)
- , process_element(*this)
- , scoped_no_eols(*this)
+ , state_(state)
{}
};
+ struct process_element_impl : scoped_action_base {
+ process_element_impl(main_grammar_local& l)
+ : l(l) {}
+
+ bool start()
+ {
+ if (!(l.info.type & l.element.context()) ||
+ 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)
+ {
+ // 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();
+ }
+ else if (info_.type != element_info::phrase &&
+ info_.type != element_info::maybe_block)
+ {
+ paragraph_action para(l.state_);
+ para();
+ }
+
+ assert(l.state_.values.builder.empty());
+
+ if (!l.state_.source_mode_next.empty() &&
+ 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();
+ }
+
+ return true;
+ }
+
+ 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;
+ }
+
+ 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_);
+ }
+
+ main_grammar_local& l;
+ element_info info_;
+ std::string saved_source_mode_;
+ };
+
+ 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;
+ };
+
+ 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;
+ }
+ };
+
////////////////////////////////////////////////////////////////////////////
// Local grammar
void quickbook_grammar::impl::init_main()
{
main_grammar_local& local = cleanup_.add(
- new main_grammar_local(actions));
+ new main_grammar_local(state));
+
+ // Global Actions
+ element_action element(state);
+ paragraph_action paragraph(state);
+ list_item_action list_item(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);
+
+ simple_phrase_action simple_markup(state.phrase, state);
+
+ break_action break_(state.phrase, state);
+ do_macro_action do_macro(state.phrase, state);
+
+ error_action error(state);
+ element_id_warning_action element_id_warning(state);
+
+ scoped_parser<to_value_scoped_action> to_value(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);
+ 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> end_blocks(local,
+ &main_grammar_local::end_blocks_impl);
// phrase/phrase_start is used for an entirely self-contained
// phrase. For example, any remaining anchors are written out
// at the end instead of being saved for any following content.
phrase_start =
- inline_phrase [actions.phrase_end]
+ inline_phrase [end_phrase]
;
// nested_phrase is used for a phrase nested inside square
// brackets.
nested_phrase =
- actions.values.save()
+ state.values.save()
[ *( ~cl::eps_p(']')
>> local.common(element_info::in_phrase)
)
@@ -272,7 +347,7 @@ namespace quickbook
// paragraph_phrase is like a nested_phrase but is also terminated
// by a paragraph end.
paragraph_phrase =
- actions.values.save()
+ state.values.save()
[ *( ~cl::eps_p(phrase_end)
>> local.common(element_info::in_phrase)
)
@@ -282,7 +357,7 @@ namespace quickbook
// extended_phrase is like a paragraph_phrase but allows some block
// elements.
extended_phrase =
- actions.values.save()
+ state.values.save()
[ *( ~cl::eps_p(phrase_end)
>> local.common(element_info::in_conditional)
)
@@ -294,13 +369,13 @@ namespace quickbook
// is expanding a template, which is parsed separately but
// is part of the paragraph that contains it.
inline_phrase =
- actions.values.save()
+ state.values.save()
[ *local.common(element_info::in_phrase)
]
;
table_title_phrase =
- actions.values.save()
+ state.values.save()
[ *( ~cl::eps_p(space >> (']' | '[' >> space >> '['))
>> local.common(element_info::in_phrase)
)
@@ -308,15 +383,15 @@ namespace quickbook
;
inside_preformatted =
- local.scoped_no_eols()
+ scoped_no_eols()
[ paragraph_phrase
]
;
// Top level blocks
block_start =
- (*eol) [local.start_blocks]
- >> (*local.top_level) [local.end_blocks]
+ (*eol) [start_blocks]
+ >> (*local.top_level) [end_blocks]
;
local.top_level =
@@ -337,7 +412,7 @@ namespace quickbook
( *cl::blank_p
>> !( (cl::ch_p('*') | '#')
>> *cl::blank_p)
- ) [local.check_indentation]
+ ) [check_indentation]
;
local.paragraph =
@@ -346,7 +421,7 @@ namespace quickbook
>> *( cl::eps_p(local.paragraph.still_in_block)
>> local.paragraph_item(element_info::only_block)
)
- >> cl::eps_p [actions.paragraph]
+ >> cl::eps_p [paragraph]
;
local.paragraph_item =
@@ -361,9 +436,13 @@ namespace quickbook
>> (cl::ch_p('*') | '#')
>> (*cl::blank_p) [local.list.still_in_block = true]
>> *( cl::eps_p(local.list.still_in_block)
- >> local.list_item(element_info::only_block)
+ >> ( qbk_ver(106u) >> local.list_item(element_info::only_block)
+ | qbk_ver(0, 106u) >> local.list_item(element_info::only_list_block)
+ )
)
- >> cl::eps_p [actions.list_item]
+ // TODO: This is sometimes called in the wrong place. Currently
+ // harmless.
+ >> cl::eps_p [list_item]
;
local.list_item =
@@ -379,7 +458,7 @@ namespace quickbook
( *cl::blank_p
>> ( cl::eol_p
| cl::end_p
- | cl::eps_p(local.in_list) >> (cl::ch_p('*') | '#')
+ | cl::eps_p(in_list) >> (cl::ch_p('*') | '#')
)
)
>> *eol
@@ -387,25 +466,25 @@ namespace quickbook
// Blocks contains within an element, e.g. a table cell or a footnote.
inside_paragraph =
- actions.values.save()
- [ *( local.paragraph_separator [actions.paragraph]
+ state.values.save()
+ [ *( local.paragraph_separator [paragraph]
>> *eol
| ~cl::eps_p(']')
>> local.common(element_info::in_nested_block)
)
- ] [actions.paragraph]
+ ] [paragraph]
;
local.hr =
cl::str_p("----")
- >> actions.values.list(block_tags::hr)
- [ ( qbk_since(106u)
+ >> state.values.list(block_tags::hr)
+ [ ( qbk_ver(106u)
>> *(line_comment | (cl::anychar_p - (cl::eol_p | '[' | ']')))
- | qbk_before(106u)
+ | qbk_ver(0, 106u)
>> *(line_comment | (cl::anychar_p - (cl::eol_p | "[/")))
)
>> *eol
- ] [actions.element]
+ ] [element]
;
local.element
@@ -415,27 +494,28 @@ namespace quickbook
| elements [ph::var(local.info) = ph::arg1]
>> (cl::eps_p - (cl::alnum_p | '_'))
)
- >> local.process_element()
- [ actions.values.list(ph::var(local.info.tag))
+ >> process_element()
+ [ state.values.list(ph::var(local.info.tag))
[ cl::lazy_p(*ph::var(local.info.rule))
>> space
>> ']'
- ] [actions.element]
+ ] [element]
]
;
local.code =
- (
- local.code_line
+ state.values.list(code_tags::code_block)
+ [( local.code_line
>> *(*local.blank_line >> local.code_line)
- ) [actions.code]
+ ) [state.values.entry(ph::arg1, ph::arg2)]
+ ] [element]
>> *eol
;
local.code_line =
( *cl::blank_p
>> ~cl::eps_p(cl::eol_p)
- ) [local.check_code_block]
+ ) [check_code_block]
>> cl::eps_p(ph::var(local.block_type) == block_types::code)
>> *(cl::anychar_p - cl::eol_p)
>> (cl::eol_p | cl::end_p)
@@ -455,61 +535,61 @@ namespace quickbook
| local.simple_markup
| escape
| comment
- | qbk_since(106u) >> local.square_brackets
- | cl::space_p [actions.raw_char]
- | cl::anychar_p [actions.plain_char]
+ | qbk_ver(106u) >> local.square_brackets
+ | cl::space_p [raw_char]
+ | cl::anychar_p [plain_char]
;
local.square_brackets =
- ( cl::ch_p('[') [actions.plain_char]
+ ( cl::ch_p('[') [plain_char]
>> paragraph_phrase
- >> ( cl::ch_p(']') [actions.plain_char]
- | cl::eps_p [actions.error("Missing close bracket")]
+ >> ( cl::ch_p(']') [plain_char]
+ | cl::eps_p [error("Missing close bracket")]
)
- | cl::ch_p(']') [actions.plain_char]
- >> cl::eps_p [actions.error("Mismatched close bracket")]
+ | cl::ch_p(']') [plain_char]
+ >> cl::eps_p [error("Mismatched close bracket")]
)
;
local.macro =
cl::eps_p
- ( ( actions.macro
+ ( ( 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
)
- >> actions.macro [actions.do_macro]
+ >> state.macro [do_macro]
;
local.template_ =
( '['
>> space
- >> actions.values.list(template_tags::template_)
- [ !cl::str_p("`") [actions.values.entry(ph::arg1, ph::arg2, template_tags::escape)]
+ >> 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)
- >> actions.templates.scope [actions.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
- | actions.templates.scope [actions.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
+ >> 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
>> ']'
]
- ) [actions.element]
+ ) [element]
;
local.template_args =
- qbk_since(105u) >> local.template_args_1_5
- | qbk_before(105u) >> local.template_args_1_4
+ qbk_ver(105u) >> local.template_args_1_5
+ | qbk_ver(0, 105u) >> local.template_args_1_4
;
local.template_args_1_4 = local.template_arg_1_4 >> *(".." >> local.template_arg_1_4);
local.template_arg_1_4 =
( cl::eps_p(*cl::blank_p >> cl::eol_p)
- >> local.template_inner_arg_1_4 [actions.values.entry(ph::arg1, ph::arg2, template_tags::block)]
- | local.template_inner_arg_1_4 [actions.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
+ >> local.template_inner_arg_1_4 [state.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+ | local.template_inner_arg_1_4 [state.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
)
;
@@ -525,8 +605,8 @@ namespace quickbook
local.template_arg_1_5 =
( cl::eps_p(*cl::blank_p >> cl::eol_p)
- >> local.template_arg_1_5_content [actions.values.entry(ph::arg1, ph::arg2, template_tags::block)]
- | local.template_arg_1_5_content [actions.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
+ >> local.template_arg_1_5_content [state.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+ | local.template_arg_1_5_content [state.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
)
;
@@ -548,48 +628,55 @@ namespace quickbook
>> "br"
>> space
>> ']'
- ) [actions.break_]
+ ) [break_]
;
local.inline_code =
- '`' >>
- (
+ '`' >> state.values.list(code_tags::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::eps_p('`')
- ) [actions.inline_code]
+ ) [state.values.entry(ph::arg1, ph::arg2)]
>> '`'
+ ] [element]
;
local.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)
- ) [actions.code_block]
- >> ( *cl::space_p >> "```"
- | cl::eps_p [actions.error("Unfinished code block")]
+ >> ( state.values.list(code_tags::inline_code_block)
+ [ *(*cl::blank_p >> cl::eol_p)
+ >> ( *( "````" >> *cl::ch_p('`')
+ | ( cl::anychar_p
+ - (*cl::space_p >> "```" >> ~cl::eps_p("`"))
+ )
+ )
+ >> !(*cl::blank_p >> cl::eol_p)
+ ) [state.values.entry(ph::arg1, ph::arg2)]
+ >> (*cl::space_p >> "```")
+ ] [element]
+ | cl::eps_p [error("Unfinished code block")]
+ >> *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)
- ) [actions.code_block]
- >> ( *cl::space_p >> "``"
- | cl::eps_p [actions.error("Unfinished code block")]
+ >> ( state.values.list(code_tags::inline_code_block)
+ [ *(*cl::blank_p >> cl::eol_p)
+ >> ( *( "```" >> *cl::ch_p('`')
+ | ( cl::anychar_p
+ - (*cl::space_p >> "``" >> ~cl::eps_p("`"))
+ )
+ )
+ >> !(*cl::blank_p >> cl::eol_p)
+ ) [state.values.entry(ph::arg1, ph::arg2)]
+ >> (*cl::space_p >> "``")
+ ] [element]
+ | cl::eps_p [error("Unfinished code block")]
+ >> *cl::anychar_p
)
;
@@ -606,22 +693,22 @@ namespace quickbook
// by space or punctuation or the
// mark character or a the start.
]
- >> actions.values.save()
+ >> state.values.save()
[
- actions.to_value()
+ to_value()
[
- cl::eps_p((actions.macro & macro_identifier) >> local.simple_markup_end)
- >> actions.macro [actions.do_macro]
+ 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
( lookback [~cl::f_ch_p(local.simple_markup.mark)]
>> local.simple_markup_end
)
- >> cl::anychar_p [actions.plain_char]
+ >> cl::anychar_p [plain_char]
)
]
>> cl::f_ch_p(local.simple_markup.mark)
- [actions.simple_markup]
+ [simple_markup]
]
;
@@ -643,37 +730,58 @@ namespace quickbook
;
escape =
- cl::str_p("\\n") [actions.break_]
+ cl::str_p("\\n") [break_]
| cl::str_p("\\ ") // ignore an escaped space
- | '\\' >> cl::punct_p [actions.plain_char]
+ | '\\' >> cl::punct_p [plain_char]
| "\\u" >> cl::repeat_p(4) [cl::chset<>("0-9a-fA-F")]
- [actions.escape_unicode]
+ [escape_unicode]
| "\\U" >> cl::repeat_p(8) [cl::chset<>("0-9a-fA-F")]
- [actions.escape_unicode]
+ [escape_unicode]
| ("'''" >> !eol)
- >> actions.values.save()
- [ (*(cl::anychar_p - "'''")) [actions.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
+ >> state.values.save()
+ [ (*(cl::anychar_p - "'''")) [state.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
>> ( cl::str_p("'''")
- | cl::eps_p [actions.error("Unclosed boostbook escape.")]
- ) [actions.element]
+ | cl::eps_p [error("Unclosed boostbook escape.")]
+ ) [element]
]
;
raw_escape =
- cl::str_p("\\n") [actions.error("Newlines invalid here.")]
+ cl::str_p("\\n") [error("Newlines invalid here.")]
| cl::str_p("\\ ") // ignore an escaped space
- | '\\' >> cl::punct_p [actions.raw_char]
+ | '\\' >> cl::punct_p [raw_char]
| "\\u" >> cl::repeat_p(4) [cl::chset<>("0-9a-fA-F")]
- [actions.escape_unicode]
+ [escape_unicode]
| "\\U" >> cl::repeat_p(8) [cl::chset<>("0-9a-fA-F")]
- [actions.escape_unicode]
- | ('\\' >> cl::anychar_p) [actions.error("Invalid escape.")]
- [actions.raw_char]
- | ("'''" >> !eol) [actions.error("Boostbook escape invalid here.")]
+ [escape_unicode]
+ | ('\\' >> cl::anychar_p) [error("Invalid escape.")]
+ [raw_char]
+ | ("'''" >> !eol) [error("Boostbook escape invalid here.")]
>> (*(cl::anychar_p - "'''"))
>> ( cl::str_p("'''")
- | cl::eps_p [actions.error("Unclosed boostbook escape.")]
- ) [actions.element]
+ | cl::eps_p [error("Unclosed boostbook escape.")]
+ ) [element]
+ ;
+
+ attribute_value_1_7 =
+ *( ~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.template_
+ | cl::eps_p(cl::ch_p('[')) [error("Unmatched template in attribute value.")]
+ >> local.square_brackets
+ | raw_escape
+ | cl::anychar_p [raw_char]
+ )
+ )
;
//
@@ -681,22 +789,22 @@ namespace quickbook
//
command_line =
- actions.values.list(block_tags::macro_definition)
+ state.values.list(block_tags::macro_definition)
[ *cl::space_p
>> local.command_line_macro_identifier
- [actions.values.entry(ph::arg1, ph::arg2)]
+ [state.values.entry(ph::arg1, ph::arg2)]
>> *cl::space_p
>> !( '='
>> *cl::space_p
- >> actions.to_value() [ inline_phrase ]
+ >> to_value() [ inline_phrase ]
>> *cl::space_p
)
>> cl::end_p
- ] [actions.element]
+ ] [element]
;
local.command_line_macro_identifier =
- qbk_since(106u)
+ qbk_ver(106u)
>> +(cl::anychar_p - (cl::space_p | '[' | '\\' | ']' | '='))
| +(cl::anychar_p - (cl::space_p | ']' | '='))
;
@@ -745,9 +853,9 @@ namespace quickbook
;
macro_identifier =
- qbk_since(106u)
+ qbk_ver(106u)
>> +(cl::anychar_p - (cl::space_p | '[' | '\\' | ']'))
- | qbk_before(106u)
+ | qbk_ver(0, 106u)
>> +(cl::anychar_p - (cl::space_p | ']'))
;
}
@@ -819,8 +927,8 @@ namespace quickbook
else {
while (!list_stack.top().root && new_indent < list_stack.top().indent)
{
- actions_.end_list_item();
- actions_.end_list(list_stack.top().mark);
+ state_.end_list_item();
+ state_.end_list(list_stack.top().mark);
list_stack.pop();
list_indent = list_stack.top().indent;
}
@@ -853,8 +961,8 @@ namespace quickbook
new_indent > list_stack.top().indent);
if (new_indent <= list_stack.top().indent2) {
- actions_.end_list_item();
- actions_.end_list(save.mark);
+ state_.end_list_item();
+ state_.end_list(save.mark);
list_indent = list_stack.top().indent;
}
else {
@@ -889,44 +997,44 @@ namespace quickbook
if (list_stack.top().root || new_indent > list_indent) {
list_stack.push(list_stack_item(mark, new_indent, new_indent2));
- actions_.start_list(mark);
+ state_.start_list(mark);
}
else if (new_indent == list_indent) {
- actions_.end_list_item();
+ state_.end_list_item();
}
else {
// This should never reach root, since the first list
// has indentation 0.
while(!list_stack.top().root && new_indent < list_stack.top().indent)
{
- actions_.end_list_item();
- actions_.end_list(list_stack.top().mark);
+ state_.end_list_item();
+ state_.end_list(list_stack.top().mark);
list_stack.pop();
}
- actions_.end_list_item();
+ state_.end_list_item();
}
list_indent = new_indent;
if (mark != list_stack.top().mark)
{
- detail::outerr(actions_.current_file, first)
+ detail::outerr(state_.current_file, first)
<< "Illegal change of list style.\n";
- detail::outwarn(actions_.current_file, first)
+ detail::outwarn(state_.current_file, first)
<< "Ignoring change of list style." << std::endl;
- ++actions_.error_count;
+ ++state_.error_count;
}
- actions_.start_list_item();
+ state_.start_list_item();
block_type = block_types::list;
}
void main_grammar_local::clear_stack()
{
while (!list_stack.top().root) {
- actions_.end_list_item();
- actions_.end_list(list_stack.top().mark);
+ state_.end_list_item();
+ state_.end_list(list_stack.top().mark);
list_stack.pop();
}
}
diff --git a/tools/quickbook/src/parsers.hpp b/tools/quickbook/src/parsers.hpp
index 19d385de5e..c1c18803a5 100644
--- a/tools/quickbook/src/parsers.hpp
+++ b/tools/quickbook/src/parsers.hpp
@@ -17,6 +17,7 @@
#include <boost/spirit/include/phoenix1_primitives.hpp>
#include <boost/spirit/include/phoenix1_tuples.hpp>
#include <boost/spirit/include/phoenix1_binders.hpp>
+#include "fwd.hpp"
namespace quickbook {
namespace cl = boost::spirit::classic;
@@ -252,6 +253,48 @@ namespace quickbook {
};
lookback_gen const lookback = lookback_gen();
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // UTF-8 code point
+ //
+ // Very crude, it doesn't check that the code point is in any way valid.
+ // Just looks for the beginning of the next character. This is just for
+ // implementing some crude fixes, rather than full unicode support. I'm
+ // sure experts would be appalled.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ struct u8_codepoint_parser : public cl::parser<u8_codepoint_parser>
+ {
+ typedef u8_codepoint_parser self_t;
+
+ template <typename Scanner>
+ struct result
+ {
+ typedef cl::match<> type;
+ };
+
+ template <typename Scanner>
+ typename result<Scanner>::type parse(Scanner const& scan) const
+ {
+ typedef typename Scanner::iterator_t iterator_t;
+
+ if (scan.at_end()) return scan.no_match();
+
+ iterator_t save(scan.first);
+
+ do {
+ ++scan.first;
+ } while (!scan.at_end() &&
+ ((unsigned char) *scan.first & 0xc0) == 0x80);
+
+ return scan.create_match(scan.first.base() - save.base(),
+ cl::nil_t(), save, scan.first);
+ }
+ };
+
+ u8_codepoint_parser const u8_codepoint_p = u8_codepoint_parser();
}
#endif // BOOST_QUICKBOOK_SCOPED_BLOCK_HPP
diff --git a/tools/quickbook/src/phrase_element_grammar.cpp b/tools/quickbook/src/phrase_element_grammar.cpp
index 7a4e3c0a09..b287d63621 100644
--- a/tools/quickbook/src/phrase_element_grammar.cpp
+++ b/tools/quickbook/src/phrase_element_grammar.cpp
@@ -9,7 +9,8 @@
=============================================================================*/
#include "grammar_impl.hpp"
-#include "actions_class.hpp"
+#include "state.hpp"
+#include "actions.hpp"
#include "utils.hpp"
#include "phrase_tags.hpp"
#include <boost/spirit/include/classic_core.hpp>
@@ -27,7 +28,7 @@ namespace quickbook
{
cl::rule<scanner>
image, anchor, link, empty, cond_phrase, inner_phrase,
- role
+ role, source_mode
;
};
@@ -36,15 +37,19 @@ namespace quickbook
phrase_element_grammar_local& local = cleanup_.add(
new phrase_element_grammar_local);
+ error_action error(state);
+ raw_char_action raw_char(state.phrase);
+ scoped_parser<cond_phrase_push> scoped_cond_phrase(state);
+ scoped_parser<to_value_scoped_action> to_value(state);
+
elements.add
("?", element_info(element_info::phrase, &local.cond_phrase))
;
local.cond_phrase =
blank
- >> macro_identifier [actions.values.entry(ph::arg1, ph::arg2)]
- >> actions.scoped_cond_phrase()
- [extended_phrase]
+ >> macro_identifier [state.values.entry(ph::arg1, ph::arg2)]
+ >> scoped_cond_phrase() [extended_phrase]
;
elements.add
@@ -54,37 +59,37 @@ namespace quickbook
// Note that the attribute values here are encoded in plain text not
// boostbook.
local.image =
- qbk_since(105u)
+ qbk_ver(105u)
>> blank
- >> ( qbk_before(106u)
+ >> ( qbk_ver(0, 106u)
>> (+(
*cl::space_p
>> +(cl::anychar_p - (cl::space_p | phrase_end | '['))
- )) [actions.values.entry(ph::arg1, ph::arg2)]
- | qbk_since(106u)
- >> actions.to_value()
+ )) [state.values.entry(ph::arg1, ph::arg2)]
+ | qbk_ver(106u)
+ >> to_value()
[ +( raw_escape
| (+cl::space_p >> ~cl::eps_p(phrase_end | '['))
- [actions.raw_char]
+ [raw_char]
| (cl::anychar_p - (cl::space_p | phrase_end | '['))
- [actions.raw_char]
+ [raw_char]
)
]
)
>> hard_space
- >> *actions.values.list()
+ >> *state.values.list()
[ '['
>> (*(cl::alnum_p | '_'))
- [actions.values.entry(ph::arg1, ph::arg2)]
+ [state.values.entry(ph::arg1, ph::arg2)]
>> space
- >> ( qbk_before(106u)
+ >> ( qbk_ver(0, 106u)
>> (*(cl::anychar_p - (phrase_end | '[')))
- [actions.values.entry(ph::arg1, ph::arg2)]
- | qbk_since(106u)
- >> actions.to_value()
+ [state.values.entry(ph::arg1, ph::arg2)]
+ | qbk_ver(106u)
+ >> to_value()
[ *( raw_escape
| (cl::anychar_p - (phrase_end | '['))
- [actions.raw_char]
+ [raw_char]
)
]
)
@@ -92,9 +97,9 @@ namespace quickbook
>> space
]
>> cl::eps_p(']')
- | qbk_before(105u)
+ | qbk_ver(0, 105u)
>> blank
- >> (*(cl::anychar_p - phrase_end)) [actions.values.entry(ph::arg1, ph::arg2)]
+ >> (*(cl::anychar_p - phrase_end)) [state.values.entry(ph::arg1, ph::arg2)]
>> cl::eps_p(']')
;
@@ -113,16 +118,21 @@ namespace quickbook
local.link =
space
- >> ( qbk_before(106u)
+ >> ( qbk_ver(0, 106u)
>> (*(cl::anychar_p - (']' | space)))
- [actions.values.entry(ph::arg1, ph::arg2)]
- | qbk_since(106u)
- >> actions.to_value()
+ [state.values.entry(ph::arg1, ph::arg2)]
+ | qbk_ver(106u, 107u)
+ >> to_value()
[ *( raw_escape
- | (cl::anychar_p - (']' | space))
- [actions.raw_char]
+ | (cl::anychar_p - (cl::ch_p('[') | ']' | space))
+ [raw_char]
)
]
+ >> !( ~cl::eps_p(comment)
+ >> cl::eps_p('[') [error("Open bracket in link value.")]
+ )
+ | qbk_ver(107u)
+ >> to_value() [attribute_value_1_7]
)
>> hard_space
>> local.inner_phrase
@@ -134,13 +144,13 @@ namespace quickbook
local.anchor =
blank
- >> ( qbk_before(106u)
- >> (*(cl::anychar_p - phrase_end)) [actions.values.entry(ph::arg1, ph::arg2)]
- | qbk_since(106u)
- >> actions.to_value()
+ >> ( qbk_ver(0, 106u)
+ >> (*(cl::anychar_p - phrase_end)) [state.values.entry(ph::arg1, ph::arg2)]
+ | qbk_ver(106u)
+ >> to_value()
[ *( raw_escape
| (cl::anychar_p - phrase_end)
- [actions.raw_char]
+ [raw_char]
)
]
)
@@ -157,6 +167,15 @@ namespace quickbook
("footnote", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::footnote))
;
+ elements.add("!", element_info(element_info::maybe_block, &local.source_mode, code_tags::next_source_mode, 107u))
+ ;
+
+ local.source_mode =
+ ( cl::str_p("c++")
+ | "python"
+ | "teletype"
+ ) [state.values.entry(ph::arg1, ph::arg2)];
+
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))
@@ -169,7 +188,7 @@ namespace quickbook
local.role
= space
- >> (+(cl::alnum_p | '_')) [actions.values.entry(ph::arg1, ph::arg2)]
+ >> (+(cl::alnum_p | '_')) [state.values.entry(ph::arg1, ph::arg2)]
>> hard_space
>> local.inner_phrase
;
@@ -178,7 +197,7 @@ namespace quickbook
local.inner_phrase =
blank
- >> actions.to_value() [ paragraph_phrase ]
+ >> to_value() [ paragraph_phrase ]
;
}
}
diff --git a/tools/quickbook/src/phrase_tags.hpp b/tools/quickbook/src/phrase_tags.hpp
index bf9b754b6c..f4bba91653 100644
--- a/tools/quickbook/src/phrase_tags.hpp
+++ b/tools/quickbook/src/phrase_tags.hpp
@@ -30,6 +30,13 @@ namespace quickbook
((python)("python"))
((teletype)("teletype"))
)
+
+ QUICKBOOK_VALUE_TAGS(code_tags, 0x560,
+ (code_block)
+ (inline_code)
+ (inline_code_block)
+ (next_source_mode)
+ )
}
#endif
diff --git a/tools/quickbook/src/quickbook.cpp b/tools/quickbook/src/quickbook.cpp
index fc197b58c7..5a359ed3e1 100644
--- a/tools/quickbook/src/quickbook.cpp
+++ b/tools/quickbook/src/quickbook.cpp
@@ -9,19 +9,21 @@
=============================================================================*/
#include "grammar.hpp"
#include "quickbook.hpp"
-#include "actions_class.hpp"
+#include "state.hpp"
+#include "actions.hpp"
#include "post_process.hpp"
#include "utils.hpp"
#include "files.hpp"
#include "input_path.hpp"
#include "id_manager.hpp"
#include <boost/program_options.hpp>
-#include <boost/filesystem/v3/path.hpp>
-#include <boost/filesystem/v3/operations.hpp>
-#include <boost/filesystem/v3/fstream.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/fstream.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/ref.hpp>
#include <boost/version.hpp>
+#include <boost/foreach.hpp>
#include <stdexcept>
#include <vector>
@@ -36,7 +38,7 @@
#pragma warning(disable:4355)
#endif
-#define QUICKBOOK_VERSION "Quickbook Version 1.5.7"
+#define QUICKBOOK_VERSION "Quickbook Version 1.5.8"
namespace quickbook
{
@@ -52,7 +54,7 @@ namespace quickbook
std::vector<std::string> preset_defines;
fs::path image_location;
- static void set_macros(actions& actor)
+ static void set_macros(quickbook::state& state)
{
for(std::vector<std::string>::const_iterator
it = preset_defines.begin(),
@@ -63,15 +65,15 @@ namespace quickbook
parse_iterator last(it->end());
cl::parse_info<parse_iterator> info =
- cl::parse(first, last, actor.grammar().command_line_macro);
+ cl::parse(first, last, state.grammar().command_line_macro);
if (!info.full) {
detail::outerr()
<< "Error parsing command line definition: '"
- << detail::utf8(*it)
+ << *it
<< "'"
<< std::endl;
- ++actor.error_count;
+ ++state.error_count;
}
}
}
@@ -81,29 +83,29 @@ namespace quickbook
// Parse a file
//
///////////////////////////////////////////////////////////////////////////
- void parse_file(actions& actor, value include_doc_id, bool nested_file)
+ void parse_file(quickbook::state& state, value include_doc_id, bool nested_file)
{
- parse_iterator first(actor.current_file->source.begin());
- parse_iterator last(actor.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, actor.grammar().doc_info);
+ cl::parse_info<parse_iterator> info = cl::parse(first, last, state.grammar().doc_info);
assert(info.hit);
- if (!actor.error_count)
+ if (!state.error_count)
{
parse_iterator pos = info.stop;
- std::string doc_type = pre(actor, pos, include_doc_id, nested_file);
+ std::string doc_type = pre(state, pos, include_doc_id, nested_file);
- info = cl::parse(info.hit ? info.stop : first, last, actor.grammar().block);
+ info = cl::parse(info.hit ? info.stop : first, last, state.grammar().block);
- post(actor, doc_type);
+ post(state, doc_type);
if (!info.full)
{
- file_position const& pos = actor.current_file->position_of(info.stop.base());
- detail::outerr(actor.current_file->path, pos.line)
+ file_position const& pos = state.current_file->position_of(info.stop.base());
+ detail::outerr(state.current_file->path, pos.line)
<< "Syntax Error near column " << pos.column << ".\n";
- ++actor.error_count;
+ ++state.error_count;
}
}
}
@@ -112,6 +114,8 @@ namespace quickbook
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
@@ -123,28 +127,52 @@ namespace quickbook
int result = 0;
try {
- actions actor(filein_, xinclude_base_, buffer, ids);
- set_macros(actor);
+ quickbook::state state(filein_, xinclude_base_, buffer, ids);
+ set_macros(state);
- if (actor.error_count == 0) {
- actor.current_file = load(filein_); // Throws load_error
+ if (state.error_count == 0) {
+ state.add_dependency(filein_);
+ state.current_file = load(filein_); // Throws load_error
- parse_file(actor);
+ parse_file(state);
- if(actor.error_count) {
+ if(state.error_count) {
detail::outerr()
- << "Error count: " << actor.error_count << ".\n";
+ << "Error count: " << state.error_count << ".\n";
}
}
- result = actor.error_count ? 1 : 0;
+ result = state.error_count ? 1 : 0;
+
+ if (!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;
+ }
+ }
+ }
+
+ if (!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;
+ }
+ }
}
catch (load_error& e) {
- detail::outerr(filein_) << detail::utf8(e.what()) << std::endl;
+ detail::outerr(filein_) << e.what() << std::endl;
result = 1;
}
- if (result == 0)
+ if (!fileout_.empty() && result == 0)
{
std::string stage2 = ids.replace_placeholders(buffer.str());
@@ -244,6 +272,7 @@ main(int argc, char* argv[])
("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")
("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")
@@ -258,6 +287,10 @@ main(int argc, char* argv[])
("xinclude-base", PO_VALUE<input_string>(),
"Generate xincludes as if generating for this target "
"directory.")
+ ("output-checked-locations", PO_VALUE<input_string>(),
+ "Writes a file listing all the file locations that were "
+ "checked, starting with '+' if they were found, or '-' "
+ "if they weren't.")
;
all.add(desc).add(hidden);
@@ -306,8 +339,7 @@ main(int argc, char* argv[])
std::ostringstream description_text;
description_text << desc;
- quickbook::detail::out()
- << quickbook::detail::utf8(description_text.str()) << "\n";
+ quickbook::detail::out() << description_text.str() << "\n";
return 0;
}
@@ -320,7 +352,7 @@ main(int argc, char* argv[])
quickbook::detail::out()
<< QUICKBOOK_VERSION
<< " (Boost "
- << quickbook::detail::utf8(boost_version)
+ << boost_version
<< ")"
<< std::endl;
return 0;
@@ -388,18 +420,36 @@ main(int argc, char* argv[])
fs::path filein = quickbook::detail::input_to_path(
vm["input-file"].as<input_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>());
+ default_output = false;
+ }
+
+ if (vm.count("output-checked-locations"))
+ {
+ locations_out = quickbook::detail::input_to_path(
+ vm["output-checked-locations"].as<input_string>());
+ default_output = false;
+ }
if (vm.count("output-file"))
{
fileout = quickbook::detail::input_to_path(
vm["output-file"].as<input_string>());
}
- else
+ else if (default_output)
{
fileout = filein;
fileout.replace_extension(".xml");
}
-
+
fs::path xinclude_base;
if (vm.count("xinclude-base"))
{
@@ -432,12 +482,16 @@ main(int argc, char* argv[])
quickbook::image_location = filein.parent_path() / "html";
}
- quickbook::detail::out() << "Generating Output File: "
- << quickbook::detail::path_to_stream(fileout)
- << std::endl;
+ if (!fileout.empty()) {
+ quickbook::detail::out() << "Generating Output File: "
+ << fileout
+ << std::endl;
+ }
if (!error_count)
- error_count += quickbook::parse_document(filein, fileout, xinclude_base, indent, linewidth, pretty_print);
+ error_count += quickbook::parse_document(
+ filein, fileout, deps_out, locations_out,
+ xinclude_base, indent, linewidth, pretty_print);
if (expect_errors)
{
@@ -455,14 +509,14 @@ main(int argc, char* argv[])
description_text << desc;
quickbook::detail::outerr() << "No filename given\n\n"
- << quickbook::detail::utf8(description_text.str()) << std::endl;
+ << description_text.str() << std::endl;
return 1;
}
}
catch(std::exception& e)
{
- quickbook::detail::outerr() << quickbook::detail::utf8(e.what()) << "\n";
+ quickbook::detail::outerr() << e.what() << "\n";
return 1;
}
diff --git a/tools/quickbook/src/quickbook.hpp b/tools/quickbook/src/quickbook.hpp
index 265bc7ee53..27d07a4125 100644
--- a/tools/quickbook/src/quickbook.hpp
+++ b/tools/quickbook/src/quickbook.hpp
@@ -15,7 +15,7 @@
#include <time.h>
#include <vector>
#include <string>
-#include <boost/filesystem/v3/path.hpp>
+#include <boost/filesystem/path.hpp>
#include "fwd.hpp"
#include "values.hpp"
@@ -31,7 +31,7 @@ namespace quickbook
extern std::vector<std::string> preset_defines;
extern fs::path image_location;
- void parse_file(actions& actor,
+ void parse_file(quickbook::state& state,
value include_doc_id = value(),
bool nested_file = false);
// Some initialisation methods
diff --git a/tools/quickbook/src/state.cpp b/tools/quickbook/src/state.cpp
new file mode 100644
index 0000000000..d16200d626
--- /dev/null
+++ b/tools/quickbook/src/state.cpp
@@ -0,0 +1,160 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2005 Thomas Guest
+ http://spirit.sourceforge.net/
+
+ 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 "state.hpp"
+#include "state_save.hpp"
+#include "quickbook.hpp"
+#include "grammar.hpp"
+#include "input_path.hpp"
+#include <boost/filesystem/operations.hpp>
+
+#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
+#pragma warning(disable:4355)
+#endif
+
+namespace quickbook
+{
+ char const* quickbook_get_date = "__quickbook_get_date__";
+ char const* quickbook_get_time = "__quickbook_get_time__";
+
+ 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)
+ : grammar_()
+
+ , xinclude_base(xinclude_base_)
+
+ , templates()
+ , error_count(0)
+ , anchors()
+ , warned_about_breaks(false)
+ , conditional(true)
+ , ids(ids)
+ , callouts()
+ , callout_depth(0)
+
+ , imported(false)
+ , macro()
+ , source_mode("c++")
+ , source_mode_next()
+ , current_file(0)
+ , filename_relative(filein_.filename())
+
+ , template_depth(0)
+ , min_section_level(1)
+
+ , 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))
+ ;
+
+ boost::scoped_ptr<quickbook_grammar> g(
+ new quickbook_grammar(*this));
+ grammar_.swap(g);
+ }
+
+ quickbook_grammar& state::grammar() const {
+ 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;
+ }
+ }
+
+ // 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;
+ }
+
+ p = fs::canonical(p) / extra;
+ dependencies[p] |= found;
+ return found;
+ }
+
+ file_state::file_state(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)
+ , xinclude_base(state.xinclude_base)
+ , source_mode(state.source_mode)
+ , macro()
+ {
+ 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.values.builder.save();
+ }
+
+ file_state::~file_state()
+ {
+ 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.xinclude_base, xinclude_base);
+ boost::swap(state.source_mode, source_mode);
+ if (scope & scope_output) {
+ state.out.pop();
+ state.phrase.pop();
+ }
+ 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/actions_class.hpp b/tools/quickbook/src/state.hpp
index 979c3ccf67..b750904588 100644
--- a/tools/quickbook/src/actions_class.hpp
+++ b/tools/quickbook/src/state.hpp
@@ -10,20 +10,22 @@
#if !defined(BOOST_SPIRIT_ACTIONS_CLASS_HPP)
#define BOOST_SPIRIT_ACTIONS_CLASS_HPP
+#include <map>
#include <boost/scoped_ptr.hpp>
-#include "actions.hpp"
#include "parsers.hpp"
#include "values_parse.hpp"
#include "collector.hpp"
+#include "template_stack.hpp"
+#include "symbols.hpp"
namespace quickbook
{
namespace cl = boost::spirit::classic;
namespace fs = boost::filesystem;
- struct actions
+ struct state
{
- actions(fs::path const& filein_, fs::path const& xinclude_base, string_stream& out_,
+ state(fs::path const& filein_, fs::path const& xinclude_base, string_stream& out_,
id_manager&);
private:
@@ -35,9 +37,10 @@ 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
fs::path xinclude_base;
template_stack templates;
@@ -46,12 +49,16 @@ namespace quickbook
bool warned_about_breaks;
bool conditional;
id_manager& ids;
+ value_builder callouts; // callouts are global as
+ int callout_depth; // they don't nest.
+ dependency_list dependencies;
// state saved for files and templates.
bool imported;
string_symbols macro;
std::string source_mode;
- file_ptr current_file;
+ value source_mode_next;
+ file_ptr current_file;
fs::path filename_relative; // for the __FILENAME__ macro.
// (relative to the original file
// or include path).
@@ -71,37 +78,23 @@ 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 start_list(char mark);
void end_list(char mark);
void start_list_item();
void end_list_item();
- scoped_parser<to_value_scoped_action>
- to_value;
- scoped_parser<cond_phrase_push>
- scoped_cond_phrase;
-
- element_action element;
- error_action error;
-
- code_action code;
- code_action code_block;
- code_action inline_code;
- paragraph_action paragraph;
- list_item_action list_item;
- phrase_end_action phrase_end;
- raw_char_action raw_char;
- plain_char_action plain_char;
- escape_unicode_action escape_unicode;
-
- simple_phrase_action simple_markup;
-
- break_action break_;
- do_macro_action do_macro;
-
- element_id_warning_action element_id_warning;
+ void start_callouts();
+ std::string add_callout(value);
+ std::string end_callouts();
};
+
+ extern unsigned qbk_version_n; // qbk_major_version * 100 + qbk_minor_version
+ extern char const* quickbook_get_date;
+ extern char const* quickbook_get_time;
}
#endif // BOOST_SPIRIT_ACTIONS_CLASS_HPP
-
diff --git a/tools/quickbook/src/actions_state.hpp b/tools/quickbook/src/state_save.hpp
index aefa7f99da..f8b53e7c8e 100644
--- a/tools/quickbook/src/actions_state.hpp
+++ b/tools/quickbook/src/state_save.hpp
@@ -10,13 +10,13 @@
#if !defined(BOOST_SPIRIT_ACTIONS_STATE_HPP)
#define BOOST_SPIRIT_ACTIONS_STATE_HPP
-#include "actions_class.hpp"
+#include "state.hpp"
namespace quickbook
{
// State savers
//
- // Defined in actions_class.cpp
+ // Defined in state.cpp
struct file_state
{
@@ -29,10 +29,10 @@ namespace quickbook
scope_all = scope_callables + scope_output
};
- explicit file_state(actions&, scope_flags);
+ explicit file_state(quickbook::state&, scope_flags);
~file_state();
- quickbook::actions& a;
+ quickbook::state& state;
scope_flags scope;
unsigned qbk_version;
bool imported;
@@ -49,7 +49,7 @@ namespace quickbook
struct template_state : file_state
{
- explicit template_state(actions&);
+ explicit template_state(quickbook::state&);
~template_state();
int template_depth;
diff --git a/tools/quickbook/src/string_ref.cpp b/tools/quickbook/src/string_ref.cpp
index b4775576da..6c33df1260 100644
--- a/tools/quickbook/src/string_ref.cpp
+++ b/tools/quickbook/src/string_ref.cpp
@@ -9,10 +9,17 @@
#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);
diff --git a/tools/quickbook/src/string_ref.hpp b/tools/quickbook/src/string_ref.hpp
index b712006790..ffb95bf71d 100644
--- a/tools/quickbook/src/string_ref.hpp
+++ b/tools/quickbook/src/string_ref.hpp
@@ -37,6 +37,12 @@ namespace quickbook
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_);
}
@@ -73,6 +79,11 @@ namespace quickbook
{
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 2e790f5bb1..e618c07dd6 100644
--- a/tools/quickbook/src/syntax_highlight.cpp
+++ b/tools/quickbook/src/syntax_highlight.cpp
@@ -14,7 +14,9 @@
#include <boost/spirit/include/classic_loops.hpp>
#include "grammar.hpp"
#include "grammar_impl.hpp" // Just for context stuff. Should move?
-#include "actions_class.hpp"
+#include "state.hpp"
+#include "actions.hpp"
+#include "utils.hpp"
#include "files.hpp"
#include "input_path.hpp"
@@ -22,102 +24,100 @@ namespace quickbook
{
namespace cl = boost::spirit::classic;
- // quickbook::actions is used in a few places here, as 'escape_actions'.
- // It's named differently to distinguish it from the syntax highlighting
- // actions, declared below.
-
- // Syntax Highlight Actions
-
- struct span
+ template <typename T, typename Value>
+ struct member_action_value
{
- // Decorates c++ code fragments
+ typedef void(T::*member_function)(Value);
- span(char const* name, collector& out)
- : name(name), out(out) {}
+ T& l;
+ member_function mf;
- void operator()(parse_iterator first, parse_iterator last) const;
+ member_action_value(T& l, member_function mf) : l(l), mf(mf) {}
- char const* name;
- collector& out;
+ void operator()(Value v) const {
+ (l.*mf)(v);
+ }
};
- struct span_start
+ template <typename T>
+ struct member_action
{
- span_start(char const* name, collector& out)
- : name(name), out(out) {}
+ typedef void(T::*member_function)(parse_iterator, parse_iterator);
- void operator()(parse_iterator first, parse_iterator last) const;
+ T& l;
+ member_function mf;
- char const* name;
- collector& out;
- };
+ member_action(T& l, member_function mf) : l(l), mf(mf) {}
- struct span_end
- {
- span_end(collector& out)
- : out(out) {}
-
- void operator()(parse_iterator first, parse_iterator last) const;
-
- collector& out;
+ void operator()(parse_iterator first, parse_iterator last) const {
+ (l.*mf)(first, last);
+ }
};
- struct unexpected_char
+ template <typename T, typename Arg1>
+ struct member_action1
{
- // Handles unexpected chars in c++ syntax
+ typedef void(T::*member_function)(parse_iterator, parse_iterator, Arg1);
- unexpected_char(
- collector& out
- , quickbook::actions& escape_actions)
- : out(out)
- , escape_actions(escape_actions) {}
+ T& l;
+ member_function mf;
- void operator()(parse_iterator first, parse_iterator last) const;
-
- collector& out;
- quickbook::actions& escape_actions;
- };
+ member_action1(T& l, member_function mf) : l(l), mf(mf) {}
- struct plain_char
- {
- // Prints a single plain char.
- // Converts '<' to "&lt;"... etc See utils.hpp
+ struct impl
+ {
+ member_action1 a;
+ Arg1 value;
- plain_char(collector& out)
- : out(out) {}
+ impl(member_action1& a, Arg1 value) :
+ a(a), value(value)
+ {}
- void operator()(char ch) const;
- void operator()(parse_iterator first, parse_iterator last) const;
+ void operator()(parse_iterator first, parse_iterator last) const {
+ (a.l.*a.mf)(first, last, value);
+ }
+ };
- collector& out;
+ impl operator()(Arg1 a1) {
+ return impl(*this, a1);
+ }
};
- struct pre_escape_back
- {
- // Escapes back from code to quickbook (Pre)
-
- pre_escape_back(actions& escape_actions)
- : escape_actions(escape_actions) {}
-
- void operator()(parse_iterator first, parse_iterator last) const;
-
- actions& escape_actions;
- };
+ // Syntax Highlight Actions
- struct post_escape_back
+ struct syntax_highlight_actions
{
- // Escapes back from code to quickbook (Post)
-
- post_escape_back(collector& out, actions& escape_actions)
- : out(out), escape_actions(escape_actions) {}
-
- void operator()(parse_iterator first, parse_iterator last) const;
-
- collector& out;
- actions& escape_actions;
+ quickbook::collector out;
+ quickbook::state& state;
+ do_macro_action do_macro_impl;
+
+ // State
+ bool support_callouts;
+ string_ref marked_text;
+
+ syntax_highlight_actions(quickbook::state& state, bool is_block) :
+ out(), state(state),
+ do_macro_impl(out, state),
+ support_callouts(is_block && (qbk_version_n >= 107u ||
+ state.current_file->is_code_snippets)),
+ marked_text()
+ {}
+
+ void span(parse_iterator, parse_iterator, char const*);
+ void span_start(parse_iterator, parse_iterator, char const*);
+ void span_end(parse_iterator, parse_iterator);
+ void unexpected_char(parse_iterator, parse_iterator);
+ void plain_char(parse_iterator, parse_iterator);
+ void pre_escape_back(parse_iterator, parse_iterator);
+ void post_escape_back(parse_iterator, parse_iterator);
+ void do_macro(std::string const&);
+
+ void mark_text(parse_iterator, parse_iterator);
+ void callout(parse_iterator, parse_iterator);
};
- void span::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::span(parse_iterator first,
+ parse_iterator last, char const* name)
{
out << "<phrase role=\"" << name << "\">";
while (first != last)
@@ -125,27 +125,30 @@ namespace quickbook
out << "</phrase>";
}
- void span_start::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::span_start(parse_iterator first,
+ parse_iterator last, char const* name)
{
out << "<phrase role=\"" << name << "\">";
while (first != last)
detail::print_char(*first++, out.get());
}
- void span_end::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::span_end(parse_iterator first,
+ parse_iterator last)
{
while (first != last)
detail::print_char(*first++, out.get());
out << "</phrase>";
}
- void unexpected_char::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::unexpected_char(parse_iterator first,
+ parse_iterator last)
{
- file_position const pos = escape_actions.current_file->position_of(first.base());
+ file_position const pos = state.current_file->position_of(first.base());
- detail::outwarn(escape_actions.current_file->path, pos.line)
+ detail::outwarn(state.current_file->path, pos.line)
<< "in column:" << pos.column
- << ", unexpected character: " << detail::utf8(first, last)
+ << ", unexpected character: " << std::string(first.base(), last.base())
<< "\n";
// print out an unexpected character
@@ -155,26 +158,42 @@ namespace quickbook
out << "</phrase>";
}
- void plain_char::operator()(char ch) const
+ void syntax_highlight_actions::plain_char(parse_iterator first,
+ parse_iterator last)
{
- detail::print_char(ch, out.get());
+ while (first != last)
+ detail::print_char(*first++, out.get());
}
- void plain_char::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::pre_escape_back(parse_iterator,
+ parse_iterator)
{
- while (first != last)
- detail::print_char(*first++, out.get());
+ state.phrase.push(); // save the stream
+ }
+
+ void syntax_highlight_actions::post_escape_back(parse_iterator,
+ parse_iterator)
+ {
+ out << state.phrase.str();
+ state.phrase.pop(); // restore the stream
+ }
+
+ void syntax_highlight_actions::do_macro(std::string const& v)
+ {
+ do_macro_impl(v);
}
- void pre_escape_back::operator()(parse_iterator, parse_iterator) const
+ void syntax_highlight_actions::mark_text(parse_iterator first,
+ parse_iterator last)
{
- escape_actions.phrase.push(); // save the stream
+ marked_text = string_ref(first.base(), last.base());
}
- void post_escape_back::operator()(parse_iterator, parse_iterator) const
+ void syntax_highlight_actions::callout(parse_iterator, parse_iterator)
{
- out << escape_actions.phrase.str();
- escape_actions.phrase.pop(); // restore the stream
+ out << state.add_callout(qbk_value(state.current_file,
+ marked_text.begin(), marked_text.end()));
+ marked_text.clear();
}
// Syntax
@@ -225,45 +244,63 @@ namespace quickbook
}
// Grammar for C++ highlighting
- struct cpp_highlight
- : public cl::grammar<cpp_highlight>
+ struct cpp_highlight : public cl::grammar<cpp_highlight>
{
- cpp_highlight(collector& out, actions& escape_actions)
- : out(out), escape_actions(escape_actions) {}
+ cpp_highlight(syntax_highlight_actions& actions)
+ : actions(actions) {}
template <typename Scanner>
struct definition
{
definition(cpp_highlight const& self)
- : g(self.escape_actions.grammar())
+ : g(self.actions.state.grammar())
{
+ member_action1<syntax_highlight_actions, char const*>
+ span(self.actions, &syntax_highlight_actions::span),
+ span_start(self.actions, &syntax_highlight_actions::span_start);
+ member_action<syntax_highlight_actions>
+ span_end(self.actions, &syntax_highlight_actions::span_end),
+ unexpected_char(self.actions, &syntax_highlight_actions::unexpected_char),
+ plain_char(self.actions, &syntax_highlight_actions::plain_char),
+ pre_escape_back(self.actions, &syntax_highlight_actions::pre_escape_back),
+ post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back),
+ mark_text(self.actions, &syntax_highlight_actions::mark_text),
+ callout(self.actions, &syntax_highlight_actions::callout);
+ member_action_value<syntax_highlight_actions, std::string const&>
+ do_macro(self.actions, &syntax_highlight_actions::do_macro);
+ error_action error(self.actions.state);
+
program
=
- *( (+cl::space_p) [plain_char(self.out)]
+ *( (+cl::space_p) [plain_char]
| macro
| escape
- | preprocessor [span("preprocessor", self.out)]
+ | preprocessor [span("preprocessor")]
+ | cl::eps_p(ph::var(self.actions.support_callouts))
+ >> ( line_callout [callout]
+ | inline_callout [callout]
+ )
| comment
- | keyword [span("keyword", self.out)]
- | identifier [span("identifier", self.out)]
- | special [span("special", self.out)]
- | string_ [span("string", self.out)]
- | char_ [span("char", self.out)]
- | number [span("number", self.out)]
- | cl::repeat_p(1)[cl::anychar_p]
- [unexpected_char(self.out, self.escape_actions)]
+ | keyword [span("keyword")]
+ | identifier [span("identifier")]
+ | special [span("special")]
+ | string_ [span("string")]
+ | char_ [span("char")]
+ | number [span("number")]
+ | u8_codepoint_p [unexpected_char]
)
;
macro =
// must not be followed by alpha or underscore
- cl::eps_p(self.escape_actions.macro
+ cl::eps_p(self.actions.state.macro
>> (cl::eps_p - (cl::alpha_p | '_')))
- >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)]
+ >> self.actions.state.macro
+ [do_macro]
;
escape =
- cl::str_p("``") [pre_escape_back(self.escape_actions)]
+ cl::str_p("``") [pre_escape_back]
>>
(
(
@@ -275,29 +312,46 @@ namespace quickbook
)
|
(
- cl::eps_p [self.escape_actions.error]
+ cl::eps_p [error]
>> *cl::anychar_p
)
- ) [post_escape_back(self.out, self.escape_actions)]
+ ) [post_escape_back]
;
preprocessor
= '#' >> *cl::space_p >> ((cl::alpha_p | '_') >> *(cl::alnum_p | '_'))
;
+ inline_callout
+ = cl::confix_p(
+ "/*<" >> *cl::space_p,
+ (*cl::anychar_p) [mark_text],
+ ">*/"
+ )
+ ;
+
+ line_callout
+ = cl::confix_p(
+ "/*<<" >> *cl::space_p,
+ (*cl::anychar_p) [mark_text],
+ ">>*/"
+ )
+ >> *cl::space_p
+ ;
+
comment
- = cl::str_p("//") [span_start("comment", self.out)]
+ = cl::str_p("//") [span_start("comment")]
>> *( escape
| (+(cl::anychar_p - (cl::eol_p | "``")))
- [plain_char(self.out)]
+ [plain_char]
)
- >> cl::eps_p [span_end(self.out)]
- | cl::str_p("/*") [span_start("comment", self.out)]
+ >> cl::eps_p [span_end]
+ | cl::str_p("/*") [span_start("comment")]
>> *( escape
| (+(cl::anychar_p - (cl::str_p("*/") | "``")))
- [plain_char(self.out)]
+ [plain_char]
)
- >> (!cl::str_p("*/")) [span_end(self.out)]
+ >> (!cl::str_p("*/")) [span_end]
;
keyword
@@ -308,7 +362,7 @@ namespace quickbook
= +cl::chset_p("~!%^&*()+={[}]:;,<.>?/|\\-")
;
- string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\');
+ string_char = ('\\' >> u8_codepoint_p) | (cl::anychar_p - '\\');
string_
= !cl::as_lower_d['l'] >> cl::confix_p('"', *string_char, '"')
@@ -333,7 +387,9 @@ namespace quickbook
}
cl::rule<Scanner>
- program, macro, preprocessor, comment, special, string_,
+ program, macro, preprocessor,
+ inline_callout, line_callout, comment,
+ special, string_,
char_, number, identifier, keyword, escape,
string_char;
@@ -343,50 +399,63 @@ namespace quickbook
start() const { return program; }
};
- collector& out;
- actions& escape_actions;
+ syntax_highlight_actions& actions;
};
// Grammar for Python highlighting
// See also: The Python Reference Manual
// http://docs.python.org/ref/ref.html
- struct python_highlight
- : public cl::grammar<python_highlight>
+ struct python_highlight : public cl::grammar<python_highlight>
{
- python_highlight(collector& out, actions& escape_actions)
- : out(out), escape_actions(escape_actions) {}
+ python_highlight(syntax_highlight_actions& actions)
+ : actions(actions) {}
template <typename Scanner>
struct definition
{
definition(python_highlight const& self)
- : g(self.escape_actions.grammar())
+ : g(self.actions.state.grammar())
{
+ member_action1<syntax_highlight_actions, char const*>
+ span(self.actions, &syntax_highlight_actions::span),
+ span_start(self.actions, &syntax_highlight_actions::span_start);
+ member_action<syntax_highlight_actions>
+ span_end(self.actions, &syntax_highlight_actions::span_end),
+ unexpected_char(self.actions, &syntax_highlight_actions::unexpected_char),
+ plain_char(self.actions, &syntax_highlight_actions::plain_char),
+ pre_escape_back(self.actions, &syntax_highlight_actions::pre_escape_back),
+ post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back),
+ mark_text(self.actions, &syntax_highlight_actions::mark_text),
+ callout(self.actions, &syntax_highlight_actions::callout);
+ member_action_value<syntax_highlight_actions, std::string const&>
+ do_macro(self.actions, &syntax_highlight_actions::do_macro);
+ error_action error(self.actions.state);
+
program
=
- *( (+cl::space_p) [plain_char(self.out)]
+ *( (+cl::space_p) [plain_char]
| macro
| escape
| comment
- | keyword [span("keyword", self.out)]
- | identifier [span("identifier", self.out)]
- | special [span("special", self.out)]
- | string_ [span("string", self.out)]
- | number [span("number", self.out)]
- | cl::repeat_p(1)[cl::anychar_p]
- [unexpected_char(self.out, self.escape_actions)]
+ | keyword [span("keyword")]
+ | identifier [span("identifier")]
+ | special [span("special")]
+ | string_ [span("string")]
+ | number [span("number")]
+ | u8_codepoint_p [unexpected_char]
)
;
macro =
// must not be followed by alpha or underscore
- cl::eps_p(self.escape_actions.macro
+ cl::eps_p(self.actions.state.macro
>> (cl::eps_p - (cl::alpha_p | '_')))
- >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)]
+ >> self.actions.state.macro
+ [do_macro]
;
escape =
- cl::str_p("``") [pre_escape_back(self.escape_actions)]
+ cl::str_p("``") [pre_escape_back]
>>
(
(
@@ -398,19 +467,19 @@ namespace quickbook
)
|
(
- cl::eps_p [self.escape_actions.error]
+ cl::eps_p [error]
>> *cl::anychar_p
)
- ) [post_escape_back(self.out, self.escape_actions)]
+ ) [post_escape_back]
;
comment
- = cl::str_p("#") [span_start("comment", self.out)]
+ = cl::str_p("#") [span_start("comment")]
>> *( escape
| (+(cl::anychar_p - (cl::eol_p | "``")))
- [plain_char(self.out)]
+ [plain_char]
)
- >> cl::eps_p [span_end(self.out)]
+ >> cl::eps_p [span_end]
;
keyword
@@ -429,7 +498,7 @@ namespace quickbook
= ! string_prefix >> (long_string | short_string)
;
- string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\');
+ string_char = ('\\' >> u8_codepoint_p) | (cl::anychar_p - '\\');
short_string
= cl::confix_p('\'', * string_char, '\'') |
@@ -468,40 +537,47 @@ namespace quickbook
start() const { return program; }
};
- collector& out;
- actions& escape_actions;
+ syntax_highlight_actions& actions;
};
// Grammar for plain text (no actual highlighting)
- struct teletype_highlight
- : public cl::grammar<teletype_highlight>
+ struct teletype_highlight : public cl::grammar<teletype_highlight>
{
- teletype_highlight(collector& out, actions& escape_actions)
- : out(out), escape_actions(escape_actions) {}
+ teletype_highlight(syntax_highlight_actions& actions)
+ : actions(actions) {}
template <typename Scanner>
struct definition
{
definition(teletype_highlight const& self)
- : g(self.escape_actions.grammar())
+ : g(self.actions.state.grammar())
{
+ member_action<syntax_highlight_actions>
+ plain_char(self.actions, &syntax_highlight_actions::plain_char),
+ pre_escape_back(self.actions, &syntax_highlight_actions::pre_escape_back),
+ post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back);
+ member_action_value<syntax_highlight_actions, std::string const&>
+ do_macro(self.actions, &syntax_highlight_actions::do_macro);
+ error_action error(self.actions.state);
+
program
=
*( macro
| escape
- | cl::repeat_p(1)[cl::anychar_p] [plain_char(self.out)]
+ | u8_codepoint_p [plain_char]
)
;
macro =
// must not be followed by alpha or underscore
- cl::eps_p(self.escape_actions.macro
+ cl::eps_p(self.actions.state.macro
>> (cl::eps_p - (cl::alpha_p | '_')))
- >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)]
+ >> self.actions.state.macro
+ [do_macro]
;
escape =
- cl::str_p("``") [pre_escape_back(self.escape_actions)]
+ cl::str_p("``") [pre_escape_back]
>>
(
(
@@ -513,10 +589,10 @@ namespace quickbook
)
|
(
- cl::eps_p [self.escape_actions.error]
+ cl::eps_p [error]
>> *cl::anychar_p
)
- ) [post_escape_back(self.out, self.escape_actions)]
+ ) [post_escape_back]
;
}
@@ -528,32 +604,32 @@ namespace quickbook
start() const { return program; }
};
- collector& out;
- actions& escape_actions;
+ syntax_highlight_actions& actions;
};
std::string syntax_highlight(
parse_iterator first,
parse_iterator last,
- actions& escape_actions,
- std::string const& source_mode)
+ quickbook::state& state,
+ std::string const& source_mode,
+ bool is_block)
{
- quickbook::collector temp;
+ syntax_highlight_actions syn_actions(state, is_block);
// print the code with syntax coloring
if (source_mode == "c++")
{
- cpp_highlight cpp_p(temp, escape_actions);
+ cpp_highlight cpp_p(syn_actions);
boost::spirit::classic::parse(first, last, cpp_p);
}
else if (source_mode == "python")
{
- python_highlight python_p(temp, escape_actions);
+ python_highlight python_p(syn_actions);
boost::spirit::classic::parse(first, last, python_p);
}
else if (source_mode == "teletype")
{
- teletype_highlight teletype_p(temp, escape_actions);
+ teletype_highlight teletype_p(syn_actions);
boost::spirit::classic::parse(first, last, teletype_p);
}
else
@@ -562,7 +638,7 @@ namespace quickbook
}
std::string str;
- temp.swap(str);
+ syn_actions.out.swap(str);
return str;
}
diff --git a/tools/quickbook/src/utils.cpp b/tools/quickbook/src/utils.cpp
index 0defe6d182..3a5ee42e4d 100644
--- a/tools/quickbook/src/utils.cpp
+++ b/tools/quickbook/src/utils.cpp
@@ -62,23 +62,4 @@ namespace quickbook { namespace detail
}
return uri;
}
-
- file_type get_file_type(std::string const& extension)
- {
- static std::map<std::string, file_type> ftypes;
- if (ftypes.empty())
- {
- // init the map of types
- ftypes["cpp"] = cpp_file;
- ftypes["hpp"] = cpp_file;
- ftypes["h"] = cpp_file;
- ftypes["c"] = cpp_file;
- ftypes["cxx"] = cpp_file;
- ftypes["hxx"] = cpp_file;
- ftypes["ipp"] = cpp_file;
- ftypes["py"] = python_file;
- }
- return ftypes[extension];
- }
-
}}
diff --git a/tools/quickbook/src/utils.hpp b/tools/quickbook/src/utils.hpp
index e7afa05e1b..9170f81043 100644
--- a/tools/quickbook/src/utils.hpp
+++ b/tools/quickbook/src/utils.hpp
@@ -33,17 +33,6 @@ namespace quickbook { namespace detail {
}
std::string escape_uri(std::string uri);
-
- // given a file extension, return the type of the source file
- // we'll have an internal database for known file types.
-
- enum file_type
- {
- cpp_file
- , python_file
- };
-
- file_type get_file_type(std::string const& extension);
}}
#endif // BOOST_SPIRIT_QUICKBOOK_UTILS_HPP
diff --git a/tools/quickbook/src/values.cpp b/tools/quickbook/src/values.cpp
index 7c3521d50b..904cc8b38f 100644
--- a/tools/quickbook/src/values.cpp
+++ b/tools/quickbook/src/values.cpp
@@ -765,6 +765,11 @@ namespace quickbook
back_ = merge_sort(&head_);
assert(*back_ == &value_list_end_impl::instance);
}
+
+ bool value_list_builder::empty() const
+ {
+ return head_ == &value_list_end_impl::instance;
+ }
}
//////////////////////////////////////////////////////////////////////////
@@ -799,16 +804,6 @@ namespace quickbook
return value(new detail::value_list_impl(current, list_tag));
}
- void value_builder::reset() {
- detail::value_list_builder new_builder;
- current.swap(new_builder);
- list_tag = value::default_tag;
- }
-
- void value_builder::set_tag(value::tag_type tag) {
- list_tag = tag;
- }
-
void value_builder::insert(value const& item) {
current.append(item.value_);
}
@@ -822,9 +817,8 @@ namespace quickbook
}
void value_builder::start_list(value::tag_type tag) {
- value::tag_type saved_tag = tag;
save();
- list_tag = saved_tag;
+ list_tag = tag;
}
void value_builder::finish_list() {
@@ -842,6 +836,11 @@ namespace quickbook
current.sort();
}
+ bool value_builder::empty() const
+ {
+ return current.empty();
+ }
+
////////////////////////////////////////////////////////////////////////////
// Iterator
diff --git a/tools/quickbook/src/values.hpp b/tools/quickbook/src/values.hpp
index 2380b0d5dc..d637ea2adb 100644
--- a/tools/quickbook/src/values.hpp
+++ b/tools/quickbook/src/values.hpp
@@ -211,6 +211,8 @@ namespace quickbook
void append(value_node*);
void sort();
+
+ bool empty() const;
private:
value_node* head_;
value_node** back_;
@@ -269,8 +271,6 @@ namespace quickbook
value release();
- void reset();
- void set_tag(value::tag_type);
void insert(value const&);
void extend(value const&);
@@ -279,6 +279,8 @@ namespace quickbook
void clear_list();
void sort_list();
+ bool empty() const;
+
private:
detail::value_list_builder current;
value::tag_type list_tag;
diff --git a/tools/quickbook/test/Jamfile.v2 b/tools/quickbook/test/Jamfile.v2
index fca35b5be4..900b4758a2 100644
--- a/tools/quickbook/test/Jamfile.v2
+++ b/tools/quickbook/test/Jamfile.v2
@@ -26,6 +26,7 @@ test-suite quickbook.test :
[ quickbook-test anchor-1_6 ]
[ quickbook-test blocks-1_5 ]
[ quickbook-test callouts-1_5 ]
+ [ quickbook-test callouts-1_7 ]
[ quickbook-test code-1_1 ]
[ quickbook-test code-1_5 ]
[ quickbook-test code_cpp-1_5 ]
@@ -34,6 +35,7 @@ test-suite quickbook.test :
[ quickbook-error-test code_python_mismatched_escape-1_4-fail ]
[ quickbook-test code_snippet-1_1 ]
[ quickbook-test code_teletype-1_5 ]
+ [ quickbook-error-test code_unclosed_block-1_6-fail ]
[ quickbook-test command_line_macro-1_1 : : :
<quickbook-test-define>__macro__=*bold*
<quickbook-test-define>__empty__ ]
@@ -65,6 +67,7 @@ test-suite quickbook.test :
[ quickbook-error-test include_win_path-1_6-fail ]
[ quickbook-test link-1_1 ]
[ quickbook-test link-1_6 ]
+ [ quickbook-test link-1_7 ]
[ quickbook-test list_test-1_5 ]
[ quickbook-test list_test-1_6 ]
[ quickbook-test macro-1_5 ]
@@ -82,6 +85,7 @@ test-suite quickbook.test :
[ quickbook-test section-1_5-unclosed ]
[ quickbook-test section-1_5 ]
[ 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 ]
@@ -106,7 +110,7 @@ test-suite quickbook.test :
[ quickbook-error-test variablelist-1_5-fail ]
[ quickbook-test variablelist-1_5 ]
[ quickbook-error-test version-0_1-fail ]
- [ quickbook-error-test version-1_7-fail ]
+ [ quickbook-error-test version-1_8-fail ]
[ quickbook-error-test version-2_0-fail ]
[ quickbook-test xml_escape-1_2 ]
[ quickbook-test xml_escape-1_5 ]
diff --git a/tools/quickbook/test/callouts-1_7.gold b/tools/quickbook/test/callouts-1_7.gold
new file mode 100644
index 0000000000..5cf0dc59ef
--- /dev/null
+++ b/tools/quickbook/test/callouts-1_7.gold
@@ -0,0 +1,247 @@
+<?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="callout_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Callout Tests</title>
+ <para>
+ Example 1:
+ </para>
+ <para>
+ Now we can define a function that simulates an ordinary six-sided die.
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.c0" linkends="callout_tests.c1" />
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.c0" id="callout_tests.c1">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 2:
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.c2" linkends="callout_tests.c3" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.c2" id="callout_tests.c3">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 3:
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.c4" linkends="callout_tests.c5" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.c4" id="callout_tests.c5">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 3 (again!):
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.c6" linkends="callout_tests.c7" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.c6" id="callout_tests.c7">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 4:
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.c8" linkends="callout_tests.c9" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+ <co id="callout_tests.c10" linkends="callout_tests.c11" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.c12" linkends="callout_tests.c13" />
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.c8" id="callout_tests.c9">
+ <para>
+ callout 1
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.c10" id="callout_tests.c11">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.c12" id="callout_tests.c13">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+<programlisting><co id="callout_tests.c14" linkends="callout_tests.c15" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.c16" linkends="callout_tests.c17" />
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.c14" id="callout_tests.c15">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.c16" id="callout_tests.c17">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ <section id="callout_tests.test_section">
+ <title><link linkend="callout_tests.test_section">Try callouts in a section</link></title>
+ <para>
+ Example 1:
+ </para>
+ <para>
+ Now we can define a function that simulates an ordinary six-sided die.
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.test_section.c0" linkends="callout_tests.test_section.c1" />
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c0" id="callout_tests.test_section.c1">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 2:
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.test_section.c2" linkends="callout_tests.test_section.c3" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c2" id="callout_tests.test_section.c3">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 3:
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.test_section.c4" linkends="callout_tests.test_section.c5" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c4" id="callout_tests.test_section.c5">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 3 (again!):
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.test_section.c6" linkends="callout_tests.test_section.c7" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c6" id="callout_tests.test_section.c7">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 4:
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.test_section.c8" linkends="callout_tests.test_section.c9" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+ <co id="callout_tests.test_section.c10" linkends="callout_tests.test_section.c11" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.test_section.c12" linkends="callout_tests.test_section.c13" />
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c8" id="callout_tests.test_section.c9">
+ <para>
+ callout 1
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.test_section.c10" id="callout_tests.test_section.c11">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.test_section.c12" id="callout_tests.test_section.c13">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+<programlisting><co id="callout_tests.test_section.c14" linkends="callout_tests.test_section.c15" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.test_section.c16" linkends="callout_tests.test_section.c17" />
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c14" id="callout_tests.test_section.c15">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.test_section.c16" id="callout_tests.test_section.c17">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ </section>
+ <section id="callout_tests.blocks">
+ <title><link linkend="callout_tests.blocks">Callouts in code blocks</link></title>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.blocks.c0" linkends="callout_tests.blocks.c1" />
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.blocks.c0" id="callout_tests.blocks.c1">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.blocks.c2" linkends="callout_tests.blocks.c3" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <calloutlist>
+ <callout arearefs="callout_tests.blocks.c2" id="callout_tests.blocks.c3">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ <code><phrase role="comment">/*&lt; This shouldn't be a callout &gt;*/</phrase></code>
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/callouts-1_7.quickbook b/tools/quickbook/test/callouts-1_7.quickbook
new file mode 100644
index 0000000000..fd3d9ee8b8
--- /dev/null
+++ b/tools/quickbook/test/callouts-1_7.quickbook
@@ -0,0 +1,68 @@
+[article Callout Tests
+ [quickbook 1.7]
+]
+
+[import callouts.cpp]
+
+Example 1:
+
+[example1]
+
+Example 2:
+
+[example2]
+
+Example 3:
+
+[example3]
+
+Example 3 (again!):
+
+[example3]
+
+Example 4:
+
+[example4]
+[example4a]
+
+[section:test_section Try callouts in a section]
+
+Example 1:
+
+[example1]
+
+Example 2:
+
+[example2]
+
+Example 3:
+
+[example3]
+
+Example 3 (again!):
+
+[example3]
+
+Example 4:
+
+[example4]
+[example4a]
+
+[endsect]
+
+[section:blocks Callouts in code blocks]
+
+ int roll_die() {
+ boost::uniform_int<> dist(1, 6); /*< create a uniform_int distribution >*/
+ }
+
+```
+int roll_die() {
+ /*<< [important test] >>*/
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+```
+
+`/*< This shouldn't be a callout >*/`
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/code_unclosed_block-1_6-fail.quickbook b/tools/quickbook/test/code_unclosed_block-1_6-fail.quickbook
new file mode 100644
index 0000000000..f02887c440
--- /dev/null
+++ b/tools/quickbook/test/code_unclosed_block-1_6-fail.quickbook
@@ -0,0 +1,4 @@
+[article Odd code markup. [quickbook 1.6] ]
+
+``
+int main() {}
diff --git a/tools/quickbook/test/doc-info/Jamfile.v2 b/tools/quickbook/test/doc-info/Jamfile.v2
index f7d262c050..9d4913b81c 100644
--- a/tools/quickbook/test/doc-info/Jamfile.v2
+++ b/tools/quickbook/test/doc-info/Jamfile.v2
@@ -16,6 +16,8 @@ test-suite quickbook.test :
[ quickbook-test author1 ]
[ quickbook-test author2 ]
[ quickbook-test empty-attributes ]
+ [ quickbook-test escaped_attributes1-1_7 ]
+ [ quickbook-test escaped_attributes2-1_7 ]
[ quickbook-test duplicates-1.1 ]
[ quickbook-test duplicates-1.5 ]
[ quickbook-test source-mode-1.4 ]
diff --git a/tools/quickbook/test/doc-info/escaped_attributes1-1_7.gold b/tools/quickbook/test/doc-info/escaped_attributes1-1_7.gold
new file mode 100644
index 0000000000..b6425d910e
--- /dev/null
+++ b/tools/quickbook/test/doc-info/escaped_attributes1-1_7.gold
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library id="escaped_name" name="Escaped name" dirname="escaped_name" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <libraryinfo>
+ <copyright>
+ <year>1325</year> <holder>John Doe</holder>
+ </copyright>
+ <librarycategory name="category:test"></librarycategory> <author>
+ <firstname>John</firstname>
+ <surname>Doe</surname>
+ <email>john.doe@example.com</email>
+</author>
+ </libraryinfo>
+ <title>Escaped name</title>
+</library>
diff --git a/tools/quickbook/test/doc-info/escaped_attributes1-1_7.quickbook b/tools/quickbook/test/doc-info/escaped_attributes1-1_7.quickbook
new file mode 100644
index 0000000000..e701613751
--- /dev/null
+++ b/tools/quickbook/test/doc-info/escaped_attributes1-1_7.quickbook
@@ -0,0 +1,11 @@
+[library Escaped name
+[quickbook 1.7]
+[copyright 1325 John Doe]
+'''<author>
+ <firstname>John</firstname>
+ <surname>Doe</surname>
+ <email>john.doe@example.com</email>
+</author>'''
+[category test]
+]
+
diff --git a/tools/quickbook/test/doc-info/escaped_attributes2-1_7.gold b/tools/quickbook/test/doc-info/escaped_attributes2-1_7.gold
new file mode 100644
index 0000000000..259111ac43
--- /dev/null
+++ b/tools/quickbook/test/doc-info/escaped_attributes2-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="multiple_escaped_attributes" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Multiple escaped attributes</title>
+ <articleinfo>
+ <author>
+ <firstname>John</firstname>
+ <surname>Doe</surname>
+ <email>john.doe@example.com</email>
+</author><orgname>Acme Corporation</orgname></articleinfo>
+</article>
diff --git a/tools/quickbook/test/doc-info/escaped_attributes2-1_7.quickbook b/tools/quickbook/test/doc-info/escaped_attributes2-1_7.quickbook
new file mode 100644
index 0000000000..70676f8a16
--- /dev/null
+++ b/tools/quickbook/test/doc-info/escaped_attributes2-1_7.quickbook
@@ -0,0 +1,10 @@
+[article Multiple escaped attributes
+[quickbook 1.7]
+'''<author>
+ <firstname>John</firstname>
+ <surname>Doe</surname>
+ <email>john.doe@example.com</email>
+</author>'''
+'''<orgname>Acme Corporation</orgname>'''
+]
+
diff --git a/tools/quickbook/test/link-1_7.gold b/tools/quickbook/test/link-1_7.gold
new file mode 100644
index 0000000000..f3eec12e74
--- /dev/null
+++ b/tools/quickbook/test/link-1_7.gold
@@ -0,0 +1,44 @@
+<?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="link_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Link tests</title>
+ <section id="link_tests.different_types_of_links">
+ <title><link linkend="link_tests.different_types_of_links">Different types of
+ links</link></title>
+ <para>
+ <ulink url="http://www.boost.org/">http://www.boost.org/</ulink> <ulink url="http://www.boost.org/">Boost</ulink>
+ <link linkend="link-id">link-id</link> <link linkend="link-id">Link Text</link>
+ <anchor id="link-id"/><functionname alt="foo">foo</functionname> <functionname
+ alt="foo">link text</functionname> <classname alt="foo">foo</classname> <classname
+ alt="foo">link text</classname> <methodname alt="foo">foo</methodname> <methodname
+ alt="foo">link text</methodname> <enumname alt="foo">foo</enumname> <enumname
+ alt="foo">link text</enumname> <macroname alt="foo">foo</macroname> <macroname
+ alt="foo">link text</macroname> <headername alt="foo">foo</headername> <headername
+ alt="foo">link text</headername> <conceptname alt="foo">foo</conceptname>
+ <conceptname alt="foo">link text</conceptname> <globalname alt="foo">foo</globalname>
+ <globalname alt="foo">link text</globalname>
+ </para>
+ <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>
+ <para>
+ <link linkend="x">x</link> and <link linkend="y">y</link> are two distinct
+ links, which should be separated by whitespace when they appear together as
+ in <link linkend="x">x</link> <link linkend="y">y</link>. Also in <link linkend="x">x</link>
+ <link linkend="y">y</link>, and in <link linkend="x">x</link> <link linkend="y">y</link>
+ as well.
+ </para>
+ </section>
+ <section id="link_tests.templates_is_links">
+ <title><link linkend="link_tests.templates_is_links">Templates is links....</link></title>
+ <para>
+ <link linkend="blah.x2">Templated link?</link>
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/link-1_7.quickbook b/tools/quickbook/test/link-1_7.quickbook
new file mode 100644
index 0000000000..8e146b9706
--- /dev/null
+++ b/tools/quickbook/test/link-1_7.quickbook
@@ -0,0 +1,52 @@
+[article Link tests
+[quickbook 1.7]
+]
+
+[section Different types of links]
+
+[@http://www.boost.org/]
+[@ http://www.boost.org/ Boost]
+[link link-id]
+[link link-id Link Text]
+[#link-id]
+[funcref foo]
+[funcref foo link text]
+[classref foo]
+[classref foo link text]
+[memberref foo]
+[memberref foo link text]
+[enumref foo]
+[enumref foo link text]
+[macroref foo]
+[macroref foo link text]
+[headerref foo]
+[headerref foo link text]
+[conceptref foo]
+[conceptref foo link text]
+[globalref foo]
+[globalref foo link text]
+
+[link link[/ comment]description]
+
+[link link\[Hello\] description]
+
+
+[endsect]
+
+[section Side-by-side links]
+
+[link x] and [link y] are two distinct links, which should be separated by
+whitespace when they appear together as in [link x] [link y]. Also in [link x]
+[link y], and in
+[link x]
+[link y]
+as well.
+
+[endsect]
+
+[section Templates is links....]
+
+[template thing[]x]
+[link blah.[thing]2 Templated link?]
+
+[endsect]
diff --git a/tools/quickbook/test/list_test-1_5.gold b/tools/quickbook/test/list_test-1_5.gold
index a1b44d829e..4d25aa7cce 100644
--- a/tools/quickbook/test/list_test-1_5.gold
+++ b/tools/quickbook/test/list_test-1_5.gold
@@ -383,4 +383,20 @@
</listitem>
</itemizedlist>
</section>
+ <section id="list_test.list_immediately_following_markup_2">
+ <title><link linkend="list_test.list_immediately_following_markup_2">List immediately
+ following markup 2</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ One [section Nested section]
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Two [endsect]
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
</article>
diff --git a/tools/quickbook/test/list_test-1_5.quickbook b/tools/quickbook/test/list_test-1_5.quickbook
index ab78e6f588..64b391a614 100644
--- a/tools/quickbook/test/list_test-1_5.quickbook
+++ b/tools/quickbook/test/list_test-1_5.quickbook
@@ -98,3 +98,11 @@ Don't end list with comment 2:
* Three
[endsect]
+
+[section List immediately following markup 2]
+* One
+[section Nested section]
+* Two
+[endsect]
+
+[endsect]
diff --git a/tools/quickbook/test/list_test-1_6.gold b/tools/quickbook/test/list_test-1_6.gold
index 223509a590..f0055257ab 100644
--- a/tools/quickbook/test/list_test-1_6.gold
+++ b/tools/quickbook/test/list_test-1_6.gold
@@ -420,6 +420,28 @@
</listitem>
</itemizedlist>
</section>
+ <section id="list_test.list_immediately_following_mark0">
+ <title><link linkend="list_test.list_immediately_following_mark0">List immediately
+ following markup 2</link></title>
+ <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>
@@ -473,4 +495,32 @@
</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>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ F
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
</article>
diff --git a/tools/quickbook/test/list_test-1_6.quickbook b/tools/quickbook/test/list_test-1_6.quickbook
index fd01b389d5..dbba74258e 100644
--- a/tools/quickbook/test/list_test-1_6.quickbook
+++ b/tools/quickbook/test/list_test-1_6.quickbook
@@ -103,6 +103,13 @@ Don't end list with comment 2:
[endsect]
+[section List immediately following markup 2]
+* One
+[section Nested section]
+* Two
+[endsect]
+[endsect]
+
[section Paragraphs in list items]
* A1
@@ -125,4 +132,16 @@ Don't end list with comment 2:
D2
-[endsect] \ No newline at end of file
+[endsect]
+
+[section Indented code blocks in lists]
+
+* A
+
+ B
+ C
+* D
+
+ E
+* F
+[endsect]
diff --git a/tools/quickbook/test/python/include_path.qbk b/tools/quickbook/test/python/include_path.qbk
new file mode 100644
index 0000000000..c9a4dcd981
--- /dev/null
+++ b/tools/quickbook/test/python/include_path.qbk
@@ -0,0 +1,4 @@
+[quickbook 1.5]
+[article Include Path]
+[include a.qbk]
+[include b.qbk]
diff --git a/tools/quickbook/test/python/include_path_deps.txt b/tools/quickbook/test/python/include_path_deps.txt
new file mode 100644
index 0000000000..994d776ee6
--- /dev/null
+++ b/tools/quickbook/test/python/include_path_deps.txt
@@ -0,0 +1,3 @@
+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
new file mode 100644
index 0000000000..aaffb8d13f
--- /dev/null
+++ b/tools/quickbook/test/python/include_path_locs.txt
@@ -0,0 +1,6 @@
++ include_path.qbk
+- a.qbk
++ sub1/a.qbk
+- b.qbk
+- sub1/b.qbk
++ sub2/b.qbk
diff --git a/tools/quickbook/test/python/missing_relative.qbk b/tools/quickbook/test/python/missing_relative.qbk
new file mode 100644
index 0000000000..8fdc0ee049
--- /dev/null
+++ b/tools/quickbook/test/python/missing_relative.qbk
@@ -0,0 +1,6 @@
+[quickbook 1.5]
+[article Missing Relative]
+
+[include ../missing.qbk]
+[include missing-dir/x.qbk]
+[include missing-dir/../../x.qbk]
diff --git a/tools/quickbook/test/python/missing_relative_deps.txt b/tools/quickbook/test/python/missing_relative_deps.txt
new file mode 100644
index 0000000000..a9de670365
--- /dev/null
+++ b/tools/quickbook/test/python/missing_relative_deps.txt
@@ -0,0 +1 @@
+missing_relative.qbk
diff --git a/tools/quickbook/test/python/missing_relative_locs.txt b/tools/quickbook/test/python/missing_relative_locs.txt
new file mode 100644
index 0000000000..69b51f28f4
--- /dev/null
+++ b/tools/quickbook/test/python/missing_relative_locs.txt
@@ -0,0 +1,4 @@
++ missing_relative.qbk
+- ../missing.qbk
+- missing-dir/x.qbk
+- missing-dir/../../x.qbk
diff --git a/tools/quickbook/test/python/output-deps.py b/tools/quickbook/test/python/output-deps.py
new file mode 100644
index 0000000000..7b77c27d84
--- /dev/null
+++ b/tools/quickbook/test/python/output-deps.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+
+import sys, os, subprocess, tempfile, re
+
+def main(args, directory):
+ if len(args) != 1:
+ print "Usage: output-deps.py quickbook-command"
+ exit(1)
+ quickbook_command = args[0]
+
+ failures = 0
+ failures += run_quickbook(quickbook_command, 'svg_missing.qbk',
+ deps_gold = 'svg_missing_deps.txt')
+ failures += run_quickbook(quickbook_command, 'svg_missing.qbk',
+ locations_gold = 'svg_missing_locs.txt')
+ failures += run_quickbook(quickbook_command, 'missing_relative.qbk',
+ deps_gold = 'missing_relative_deps.txt',
+ locations_gold = 'missing_relative_locs.txt')
+ failures += run_quickbook(quickbook_command, 'include_path.qbk',
+ deps_gold = 'include_path_deps.txt',
+ locations_gold = 'include_path_locs.txt',
+ input_path = ['sub1', 'sub2'])
+
+ if failures == 0:
+ print "Success"
+ else:
+ print "Failures:",failures
+ exit(failures)
+
+def run_quickbook(quickbook_command, filename, output_gold = None,
+ deps_gold = None, locations_gold = None, input_path = []):
+ failures = 0
+
+ command = [quickbook_command, '--debug', filename]
+
+ output_filename = None
+ if output_gold:
+ output_filename = temp_filename('.qbk')
+ command.extend(['--output-file', output_filename])
+
+ deps_filename = None
+ if deps_gold:
+ deps_filename = temp_filename('.txt')
+ command.extend(['--output-deps', deps_filename])
+
+ locations_filename = None
+ if locations_gold:
+ locations_filename = temp_filename('.txt')
+ command.extend(['--output-checked-locations', locations_filename])
+
+ try:
+ for path in input_path:
+ command.extend(['-I', path])
+ print 'Running: ' + ' '.join(command)
+ print
+ exit_code = subprocess.call(command)
+ print
+ success = not exit_code
+
+ if output_filename:
+ output = load_file(output_filename)
+ else:
+ output = None
+
+ if deps_filename:
+ deps = load_dependencies(deps_filename)
+ else:
+ deps = None
+
+ if locations_filename:
+ locations = load_locations(locations_filename)
+ else:
+ locations = None
+ finally:
+ if output_filename: os.unlink(output_filename)
+ if deps_filename: os.unlink(deps_filename)
+
+ if deps_gold:
+ gold = load_dependencies(deps_gold, adjust_paths = True)
+ if deps != gold:
+ failures = failures + 1
+ print "Dependencies don't match:"
+ print "Gold:", gold
+ print "Result:", deps
+ print
+
+ if locations_gold:
+ gold = load_locations(locations_gold, adjust_paths = True)
+ if locations != gold:
+ failures = failures + 1
+ print "Dependencies don't match:"
+ print "Gold:", gold
+ print "Result:", locations
+ print
+
+ if output_gold:
+ gold = load_file(output_gold)
+ if gold != output:
+ failures = failures + 1
+ print "Output doesn't match:"
+ print
+ print gold
+ print
+ print output
+ print
+
+ return failures
+
+def load_dependencies(filename, adjust_paths = False):
+ dependencies = set()
+ f = open(filename, 'r')
+ for path in f:
+ if adjust_paths:
+ path = os.path.realpath(path)
+ if path in dependencies:
+ raise Exception("Duplicate path (%1s) in %2s" % (path, filename))
+ dependencies.add(path)
+ return dependencies
+
+def load_locations(filename, adjust_paths = False):
+ line_matcher = re.compile("^([+-]) (.*)$")
+ dependencies = {}
+ f = open(filename, 'r')
+ for line in f:
+ 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
+
+def temp_filename(extension):
+ file = tempfile.mkstemp(suffix = extension)
+ os.close(file[0])
+ return file[1]
+
+def load_file(filename):
+ f = open(filename, 'r')
+ try:
+ return f.read()
+ finally:
+ f.close()
+
+ return None
+
+main(sys.argv[1:], os.path.dirname(sys.argv[0]))
diff --git a/tools/quickbook/test/python/sub1/a.qbk b/tools/quickbook/test/python/sub1/a.qbk
new file mode 100644
index 0000000000..7898192261
--- /dev/null
+++ b/tools/quickbook/test/python/sub1/a.qbk
@@ -0,0 +1 @@
+a
diff --git a/tools/quickbook/test/python/sub2/b.qbk b/tools/quickbook/test/python/sub2/b.qbk
new file mode 100644
index 0000000000..6178079822
--- /dev/null
+++ b/tools/quickbook/test/python/sub2/b.qbk
@@ -0,0 +1 @@
+b
diff --git a/tools/quickbook/test/python/svg_missing.qbk b/tools/quickbook/test/python/svg_missing.qbk
new file mode 100644
index 0000000000..2b25c2f3b6
--- /dev/null
+++ b/tools/quickbook/test/python/svg_missing.qbk
@@ -0,0 +1,3 @@
+[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
new file mode 100644
index 0000000000..25d1c0e502
--- /dev/null
+++ b/tools/quickbook/test/python/svg_missing_deps.txt
@@ -0,0 +1 @@
+svg_missing.qbk
diff --git a/tools/quickbook/test/python/svg_missing_locs.txt b/tools/quickbook/test/python/svg_missing_locs.txt
new file mode 100644
index 0000000000..379d4142f0
--- /dev/null
+++ b/tools/quickbook/test/python/svg_missing_locs.txt
@@ -0,0 +1,2 @@
+- html/missing.svg
++ svg_missing.qbk
diff --git a/tools/quickbook/test/source_mode-1_7.gold b/tools/quickbook/test/source_mode-1_7.gold
new file mode 100644
index 0000000000..e40bae8608
--- /dev/null
+++ b/tools/quickbook/test/source_mode-1_7.gold
@@ -0,0 +1,38 @@
+<?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="source_mode_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Source Mode Test</title>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </entry>
+ <entry>
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+<programlisting>Plain text...</programlisting>
+ <para>
+ <code><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase
+ role="special">()</phrase> <phrase role="special">{}</phrase></code> but <code>plain
+ text</code>.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Sadly this doesn't work.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <code>int main() {}</code>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+</article>
diff --git a/tools/quickbook/test/source_mode-1_7.quickbook b/tools/quickbook/test/source_mode-1_7.quickbook
new file mode 100644
index 0000000000..f5b9ee37fe
--- /dev/null
+++ b/tools/quickbook/test/source_mode-1_7.quickbook
@@ -0,0 +1,12 @@
+[quickbook 1.7]
+[source-mode teletype]
+[article Source Mode Test]
+
+[!c++][table [[``int main() {}``][``void foo() {}``]]]
+``Plain text...``
+
+[!c++]`int main() {}` but `plain text`.
+
+[!c++]
+* Sadly this doesn't work.
+* `int main() {}`
diff --git a/tools/quickbook/test/unit/Jamfile.v2 b/tools/quickbook/test/unit/Jamfile.v2
index ea60b90404..0b583b796b 100644
--- a/tools/quickbook/test/unit/Jamfile.v2
+++ b/tools/quickbook/test/unit/Jamfile.v2
@@ -13,6 +13,11 @@ project quickbook-unit-tests
<include>../../src
<warnings>all
<library>/boost//filesystem
+ <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
;
run values_test.cpp ../../src/values.cpp ../../src/files.cpp ../../src/string_ref.cpp ;
@@ -20,4 +25,4 @@ run post_process_test.cpp ../../src/post_process.cpp ;
# Copied from spirit
run symbols_tests.cpp ;
-run symbols_find_null.cpp ; \ No newline at end of file
+run symbols_find_null.cpp ;
diff --git a/tools/quickbook/test/version-1_7-fail.quickbook b/tools/quickbook/test/version-1_8-fail.quickbook
index 9820b7435c..4311034ba7 100644
--- a/tools/quickbook/test/version-1_7-fail.quickbook
+++ b/tools/quickbook/test/version-1_8-fail.quickbook
@@ -1,5 +1,5 @@
[article Future version of quickbook
- [quickbook 1.7]
+ [quickbook 1.8]
]
This should fail... \ No newline at end of file