summaryrefslogtreecommitdiffstats
path: root/src/boost/tools/docca
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/boost/tools/docca
parentInitial commit. (diff)
downloadceph-b26c4052f3542036551aa9dec9caa4226e456195.tar.xz
ceph-b26c4052f3542036551aa9dec9caa4226e456195.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/tools/docca')
-rw-r--r--src/boost/tools/docca/CHANGELOG.md1
-rw-r--r--src/boost/tools/docca/LICENSE_1_0.txt23
-rw-r--r--src/boost/tools/docca/README.md26
-rw-r--r--src/boost/tools/docca/docca.jam231
-rw-r--r--src/boost/tools/docca/example/Jamfile129
-rw-r--r--src/boost/tools/docca/example/boostbook.dtd439
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_101.hpp22
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_33.hpp27
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_34.hpp37
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_38.hpp35
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_44.hpp60
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_47.hpp34
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_48.hpp47
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_52.hpp35
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_53.hpp44
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_55.hpp26
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_63.hpp41
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_69.hpp27
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_70.hpp32
-rw-r--r--src/boost/tools/docca/example/include/docca/issue_78.hpp27
-rw-r--r--src/boost/tools/docca/example/index.xml14
-rw-r--r--src/boost/tools/docca/example/main.qbk31
-rw-r--r--src/boost/tools/docca/example/makeqbk.sh13
-rw-r--r--src/boost/tools/docca/example/reference.xsl14
-rw-r--r--src/boost/tools/docca/example/xsl/custom-overrides.xsl25
-rw-r--r--src/boost/tools/docca/include/docca/assemble-quickbook.xsl20
-rw-r--r--src/boost/tools/docca/include/docca/base-config.xsl47
-rw-r--r--src/boost/tools/docca/include/docca/base-extract-xml-pages.xsl476
-rw-r--r--src/boost/tools/docca/include/docca/base-stage1.xsl635
-rw-r--r--src/boost/tools/docca/include/docca/base-stage2.xsl278
-rw-r--r--src/boost/tools/docca/include/docca/common.xsl107
-rw-r--r--src/boost/tools/docca/include/docca/debug-friendly-quickbook.xsl23
-rw-r--r--src/boost/tools/docca/include/docca/extract-xml-pages.xsl13
-rw-r--r--src/boost/tools/docca/include/docca/stage1.xsl13
-rw-r--r--src/boost/tools/docca/include/docca/stage2.xsl12
-rw-r--r--src/boost/tools/docca/util/comparison/README.md28
-rwxr-xr-xsrc/boost/tools/docca/util/comparison/build-and-compare.sh24
-rwxr-xr-xsrc/boost/tools/docca/util/comparison/compare-all.sh27
-rw-r--r--src/boost/tools/docca/util/comparison/grep-expressions4
-rw-r--r--src/boost/tools/docca/util/comparison/sed-commands2
-rwxr-xr-xsrc/boost/tools/docca/util/comparison/update-all-baselines.sh16
-rwxr-xr-xsrc/boost/tools/docca/util/comparison/update-baseline-html.sh19
-rwxr-xr-xsrc/boost/tools/docca/util/comparison/watch-all-builds.sh6
43 files changed, 3190 insertions, 0 deletions
diff --git a/src/boost/tools/docca/CHANGELOG.md b/src/boost/tools/docca/CHANGELOG.md
new file mode 100644
index 000000000..637b66c87
--- /dev/null
+++ b/src/boost/tools/docca/CHANGELOG.md
@@ -0,0 +1 @@
+* Version 1
diff --git a/src/boost/tools/docca/LICENSE_1_0.txt b/src/boost/tools/docca/LICENSE_1_0.txt
new file mode 100644
index 000000000..36b7cd93c
--- /dev/null
+++ b/src/boost/tools/docca/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/src/boost/tools/docca/README.md b/src/boost/tools/docca/README.md
new file mode 100644
index 000000000..03e050eab
--- /dev/null
+++ b/src/boost/tools/docca/README.md
@@ -0,0 +1,26 @@
+# docca
+
+Docca is a set of XSLT transformations which converts Doxygen
+XML extracted from Javadoc comments in C++ source code, into
+Boost.Quickbook output
+
+These scripts are used by
+[Boost.Beast](https://github.com/boostorg/beast/)
+to generate the reference.
+For example, this
+[Javadoc comment](https://github.com/boostorg/beast/blob/b7230f12f16fe7a9f7a1ece5be1f607c8552448a/include/boost/beast/core/buffers_cat.hpp#L68])
+is extracted by Doxygen into an intermediate XML representation,
+then processed by the XSLT script via Saxon-HE to produce this
+[Boost.Quickbook page](https://www.boost.org/doc/libs/1_71_0/libs/beast/doc/html/beast/ref/boost__beast__buffers_cat.html).
+
+## Usage
+
+The following Doxygen configuration settings must be set as indicated:
+
+ DISTRIBUTE_GROUP_DOC = YES
+
+## License
+
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file [LICENSE_1_0.txt](LICENSE_1_0.txt) or copy at
+https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/boost/tools/docca/docca.jam b/src/boost/tools/docca/docca.jam
new file mode 100644
index 000000000..94028d880
--- /dev/null
+++ b/src/boost/tools/docca/docca.jam
@@ -0,0 +1,231 @@
+#
+# Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
+# Copyright (c) 2021 Dmitry Arkhipov (grisumbras@gmail.com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+# Official repository: https://github.com/cppalliance/json
+#
+
+
+import "class" : new ;
+import doxygen ;
+import param ;
+import path ;
+import project ;
+import property-set ;
+import quickbook ;
+import saxonhe ;
+import sequence ;
+import toolset ;
+import type ;
+
+
+.here = [ path.make [ modules.binding $(__name__) ] ] ;
+.here = $(.here:D) ;
+
+
+rule reference ( target : sources * : requirements * : default-build *
+ : usage-requirements * )
+{
+ param.handle-named-params
+ sources requirements default-build usage-requirements ;
+
+ local overrides = $(sources[1]) ;
+ sources = $(sources[2-]) ;
+
+ local project = [ project.current ] ;
+ local target-dir = $(target:S=) ;
+ target-dir = $(target-dir:B=_$(target-dir:B)-dir) ;
+
+ # Generate doxygen configuration file from sources
+ sources = [ sequence.transform fix-source $(project) : $(sources) ] ;
+ doxyfile $(target-dir)/sources.dox
+ : $(sources)
+ : $(requirements)
+ <doxygen:param>GENERATE_HTML=NO
+ <doxygen:param>GENERATE_XML=YES
+ <doxygen:param>XML_OUTPUT=$(target-dir)
+ : $(default-build)
+ ;
+ $(project).mark-target-as-explicit $(target-dir)/sources.dox ;
+
+ #--------------------------------------------------------------------------
+ #
+ # Invoke Doxygen to process the header files and produce the XML
+ # containing the description of the C++ declarations and extracted
+ # Javadoc comments.
+ doxygen-xml-multifile $(target-dir)/stamp
+ : $(target-dir)/sources.dox
+ : $(requirements)
+ : $(default-build)
+ ;
+ $(project).mark-target-as-explicit $(target-dir)/stamp ;
+
+
+ # Adopt as a target index.xml which was created as a side-effect
+ make-explicit $(target-dir)/index.xml $(project)
+ : $(target-dir)/stamp
+ : @docca.null-action
+ ;
+
+ #--------------------------------------------------------------------------
+ #
+ # Copy the project-specific config XSLT
+ copy-xsl $(overrides) $(project) $(target-dir)/custom-overrides.xsl ;
+
+ # Copy all the XSLT modules to the target directory.
+ # Also, specify their dependencies.
+ local src-dir = $(.here)/include/docca ;
+ copy-xsl $(src-dir)/common.xsl $(project) $(target-dir) ;
+ copy-xsl $(src-dir)/base-config.xsl $(project) $(target-dir) ;
+ copy-xsl $(src-dir)/assemble-quickbook.xsl $(project) $(target-dir) ;
+
+ copy-xsl $(src-dir)/base-extract-xml-pages.xsl $(project) $(target-dir)
+ : common.xsl
+ ;
+
+ copy-xsl $(src-dir)/base-stage1.xsl $(project) $(target-dir)
+ : common.xsl
+ ;
+
+ copy-xsl $(src-dir)/extract-xml-pages.xsl $(project) $(target-dir)
+ : base-extract-xml-pages.xsl
+ base-config.xsl
+ custom-overrides.xsl
+ ;
+
+ copy-xsl $(src-dir)/stage1.xsl $(project) $(target-dir)
+ : base-stage1.xsl
+ base-config.xsl
+ custom-overrides.xsl
+ ;
+
+ copy-xsl $(src-dir)/base-stage2.xsl $(project) $(target-dir)
+ : common.xsl
+ ;
+
+ copy-xsl $(src-dir)/stage2.xsl $(project) $(target-dir)
+ : base-stage2.xsl
+ base-config.xsl
+ custom-overrides.xsl
+ ;
+
+ #-------------------------------------------------------------------------------
+ #
+ # Run index.xml through the first transformation stage
+ # (assembling and splitting the XML into page-specific files).
+ #
+ make-explicit $(target-dir)/xml-pages.xml $(project)
+ : $(target-dir)/index.xml
+ $(target-dir)/extract-xml-pages.xsl
+ : @saxonhe.saxonhe
+ ;
+
+ # Adopt as a target xml-pages directory which was created as a side-effect
+ make-explicit $(target-dir)/xml-pages $(project)
+ : $(target-dir)/xml-pages.xml
+ : @docca.null-action
+ ;
+
+ make-explicit $(target-dir)/stage1/results $(project)
+ : $(target-dir)/xml-pages
+ $(target-dir)/stage1.xsl
+ : @saxonhe.saxonhe_dir
+ : $(requirements)
+ ;
+
+ make-explicit $(target-dir)/stage2/results $(project)
+ : $(target-dir)/stage1/results
+ $(target-dir)/stage2.xsl
+ : @saxonhe.saxonhe_dir
+ : $(requirements)
+ ;
+
+ generate $(target)
+ : $(target-dir)/xml-pages.xml
+ $(target-dir)/assemble-quickbook.xsl
+
+ # TODO: make this input to the XSLT somehow
+ # rather than relying on it being hard-coded
+ # in the XSLT (which it is!)
+ $(target-dir)/stage2/results
+ : <generating-rule>@docca.make-qbk
+ $(requirements)
+ : $(default-build)
+ : $(usage-requirements)
+ ;
+}
+
+
+rule make-qbk ( project name : property-set : sources * )
+{
+ local action-name = saxonhe.saxonhe ;
+ local relevant = [ toolset.relevant $(action-name) ] ;
+ local action = [
+ new action $(sources)
+ : $(action-name)
+ : [ $(property-set).relevant $(relevant) ]
+ ] ;
+ local target = [
+ new file-target $(name) exact
+ : [ type.type $(name) ]
+ : $(project)
+ : $(action)
+ ] ;
+ local path = [ path.root $(name) [ $(target).path ] ] ;
+ return [ property-set.create <include>$(path:D) ] $(target) ;
+}
+
+
+local rule copy-xsl ( source project target-or-dir : dependencies * )
+{
+ local target ;
+ local dir ;
+ if .xsl = $(target-or-dir:S)
+ {
+ dir = $(target-or-dir:D) ;
+ target = $(target-or-dir:D=) ;
+ }
+ else
+ {
+ dir = $(target-or-dir) ;
+ target = $(source:D=) ;
+ }
+
+ make-explicit $(target:TD=$(dir)) $(project)
+ : $(source)
+ : @common.copy
+ : <dependency>$(dependencies:TD=$(dir))
+ ;
+}
+
+
+local rule make-explicit ( target project : sources * : make-rule + : reqs *
+ : ureqs * )
+{
+ make $(target) : $(sources) : $(make-rule) : $(reqs) : $(ureqs) ;
+ $(project).mark-target-as-explicit $(target) ;
+}
+
+
+local rule fix-source ( project path )
+{
+ # Unfortunately, rule doxygen.run was written with the assumption that
+ # current project is located in the current directory (which is very likely
+ # to not be the case). We have to convert paths into a form that is both
+ # usable by doxygen and usable by b2 from the current project. This
+ # effectively means absolute paths.
+ #
+ # NOTE: doxygen.run should really do this by itself.
+
+ path = [ path.root $(path) [ $(project).location ] ] ;
+ path = [ path.root $(path) [ path.pwd ] ] ;
+ return $(path) ;
+}
+
+
+rule null-action
+{
+}
diff --git a/src/boost/tools/docca/example/Jamfile b/src/boost/tools/docca/example/Jamfile
new file mode 100644
index 000000000..4a68cc56b
--- /dev/null
+++ b/src/boost/tools/docca/example/Jamfile
@@ -0,0 +1,129 @@
+#
+# Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
+# Copyright (c) 2021 Dmitry Arkhipov (grisumbras@gmail.com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+# Official repository: https://github.com/cppalliance/json
+#
+
+project json/doc ;
+
+import boostbook ;
+import ../../../tools/docca/docca.jam ;
+
+
+# Produce the reference.qbk from C++ sources
+docca.reference reference.qbk
+ : xsl/custom-overrides.xsl
+ [ glob-tree-ex include/docca : *.hpp ]
+ : <doxygen:param>PROJECT_NAME=docca
+ <doxygen:param>PROJECT_NUMBER=
+ <doxygen:param>PROJECT_BRIEF="Documentation Library"
+ <doxygen:param>ABBREVIATE_BRIEF=
+ <doxygen:param>ALWAYS_DETAILED_SEC=YES
+ <doxygen:param>INLINE_INHERITED_MEMB=YES
+ <doxygen:param>FULL_PATH_NAMES=NO
+ <doxygen:param>JAVADOC_AUTOBRIEF=YES
+ <doxygen:param>MULTILINE_CPP_IS_BRIEF=YES
+ <doxygen:param>DISTRIBUTE_GROUP_DOC=YES
+ <doxygen:param>EXTRACT_ALL=YES
+ <doxygen:param>EXTRACT_PRIVATE=YES
+ <doxygen:param>EXTRACT_STATIC=YES
+ <doxygen:param>EXTRACT_LOCAL_CLASSES=NO
+ <doxygen:param>SHOW_INCLUDE_FILES=NO
+ <doxygen:param>INLINE_INFO=NO
+ <doxygen:param>SORT_MEMBER_DOCS=NO
+ <doxygen:param>SORT_MEMBERS_CTORS_1ST=YES
+ <doxygen:param>GENERATE_TODOLIST=NO
+ <doxygen:param>GENERATE_TESTLIST=NO
+ <doxygen:param>GENERATE_BUGLIST=NO
+ <doxygen:param>GENERATE_DEPRECATEDLIST=NO
+ <doxygen:param>SHOW_USED_FILES=NO
+ <doxygen:param>SHOW_FILES=NO
+ <doxygen:param>SHOW_NAMESPACES=NO
+ <doxygen:param>FILE_PATTERNS=
+ <doxygen:param>EXAMPLE_PATTERNS=
+ <doxygen:param>MACRO_EXPANSION=YES
+ <doxygen:param>EXPAND_ONLY_PREDEF=YES
+ <doxygen:param>PREDEFINED="\\
+ DOXYGEN \\
+ GENERATING_DOCS \\
+ _MSC_VER"
+ <doxygen:param>CLASS_DIAGRAMS=NO
+ #<doxygen:param>STRIP_FROM_PATH=$(EXAMPLE_DIR)/include/docca
+ #<doxygen:param>STRIP_FROM_INC_PATH=$(EXAMPLE_DIR)/include/docca
+ ;
+
+#-------------------------------------------------------------------------------
+#
+# Produce the reference.qbk file by running
+# the reference xml through the transform.
+#
+#make reference.qbk
+# :
+# reference.xml
+# transform.xsl
+# :
+# saxonhe.saxonhe
+# ;
+
+#-------------------------------------------------------------------------------
+#
+# Produce the Boost.Book XML from the QuickBook
+#
+
+install images
+ :
+ [ glob images/*.png ]
+ :
+ <location>html/json/images
+ ;
+
+explicit images ;
+
+xml json_doc
+ :
+ main.qbk
+ :
+ <use>reference.qbk
+ <dependency>images
+ ;
+
+explicit json_doc ;
+
+#-------------------------------------------------------------------------------
+#
+# HTML documentation for $(BOOST_ROOT)/doc/html
+#
+#-------------------------------------------------------------------------------
+
+boostbook json
+ :
+ json_doc
+ :
+ <xsl:param>boost.root=../../../..
+ <xsl:param>chapter.autolabel=1
+ <xsl:param>chunk.section.depth=8 # Depth to which sections should be chunked
+ <xsl:param>chunk.first.sections=1 # Chunk the first top-level section?
+ <xsl:param>toc.section.depth=2 # How deep should recursive sections appear in the TOC?
+ <xsl:param>toc.max.depth=8 # How many levels should be created for each TOC?
+ <xsl:param>generate.section.toc.level=8 # Control depth of TOC generation in sections
+ <xsl:param>generate.toc="chapter toc,title section nop reference nop"
+ <include>../../../tools/boostbook/dtd
+ :
+ <dependency>images
+ ;
+
+#-------------------------------------------------------------------------------
+#
+# These are used to inform the build system of the
+# means to build the integrated and stand-alone docs.
+#
+
+alias boostdoc ;
+explicit boostdoc ;
+
+alias boostrelease : json ;
+explicit boostrelease ;
diff --git a/src/boost/tools/docca/example/boostbook.dtd b/src/boost/tools/docca/example/boostbook.dtd
new file mode 100644
index 000000000..bd4c3f871
--- /dev/null
+++ b/src/boost/tools/docca/example/boostbook.dtd
@@ -0,0 +1,439 @@
+<!--
+ BoostBook DTD - development version
+
+ For further information, see: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost_Documentation_Format
+
+ Copyright (c) 2002 by Peter Simons <simons@cryp.to>
+ Copyright (c) 2003-2004 by Douglas Gregor <doug.gregor -at- gmail.com>
+ Copyright (c) 2007 by Frank Mori Hess <fmhess@users.sourceforge.net>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+ The latest stable DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+ PUBLIC "-//Boost//DTD BoostBook XML V1.1//EN"
+ SYSTEM "http://www.boost.org/tools/boostbook/dtd/1.1/boostbook.dtd"
+
+ $Revision$
+ $Date$
+-->
+
+<!--========== Define XInclude features. ==========-->
+<!-- This is not really integrated into the DTD yet. Needs more
+ research. -->
+<!--
+<!ELEMENT xi:include (xi:fallback)?>
+<!ATTLIST xi:include
+ xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
+ href CDATA #REQUIRED
+ parse (xml|text) "xml"
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT xi:fallback ANY>
+<!ATTLIST xi:fallback
+ xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
+ -->
+
+<!ENTITY % local.common.attrib "last-revision CDATA #IMPLIED">
+
+<!--========== Define the BoostBook extensions ==========-->
+<!ENTITY % boost.common.attrib "%local.common.attrib;
+ id CDATA #IMPLIED">
+
+<!ENTITY % boost.namespace.mix
+ "class|class-specialization|struct|struct-specialization|
+ union|union-specialization|typedef|enum|
+ free-function-group|function|overloaded-function|
+ namespace">
+
+<!ENTITY % boost.template.mix
+ "template-type-parameter|template-nontype-parameter|template-varargs">
+
+<!ENTITY % boost.class.members
+ "static-constant|typedef|enum|
+ copy-assignment|constructor|destructor|method-group|
+ method|overloaded-method|data-member|class|class-specialization|struct|
+ struct-specialization|union|union-specialization">
+
+<!ENTITY % boost.class.mix
+ "%boost.class.members;|free-function-group|function|overloaded-function">
+
+<!ENTITY % boost.class.content
+ "template?, inherit*, purpose?, description?,
+ (%boost.class.mix;|access)*">
+
+<!ENTITY % boost.class-specialization.content
+ "template?, specialization?, inherit?, purpose?, description?,
+ (%boost.class.mix;|access)*">
+
+<!ENTITY % boost.function.semantics
+ "purpose?, description?, requires?, effects?, postconditions?,
+ returns?, throws?, complexity?, notes?, rationale?">
+
+<!ENTITY % library.content
+ "libraryinfo, (title, ((section|library-reference|testsuite))+)?">
+
+<!ELEMENT library (%library.content;)>
+<!ATTLIST library
+ name CDATA #REQUIRED
+ dirname CDATA #REQUIRED
+ html-only CDATA #IMPLIED
+ url CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT boostbook (title, (chapter|library)*)>
+<!ATTLIST boostbook %boost.common.attrib;>
+
+<!ELEMENT libraryinfo (author+, copyright*, legalnotice*, librarypurpose, librarycategory*)>
+<!ATTLIST libraryinfo %boost.common.attrib;>
+
+<!ELEMENT librarypurpose (#PCDATA|code|ulink|functionname|methodname|classname|macroname|headername|enumname|globalname)*>
+<!ATTLIST librarypurpose %boost.common.attrib;>
+
+<!ELEMENT librarycategory (#PCDATA)>
+<!ATTLIST librarycategory
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT libraryname (#PCDATA)>
+<!ATTLIST libraryname %boost.common.attrib;>
+
+<!ELEMENT library-reference ANY>
+<!ATTLIST library-reference
+ %boost.common.attrib;>
+
+<!ELEMENT librarylist EMPTY>
+<!ATTLIST librarylist %boost.common.attrib;>
+
+<!ELEMENT librarycategorylist (librarycategorydef)*>
+<!ATTLIST librarycategorylist %boost.common.attrib;>
+
+<!ELEMENT librarycategorydef (#PCDATA)>
+<!ATTLIST librarycategorydef
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT header ANY>
+<!ATTLIST header
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT namespace (%boost.namespace.mix;)*>
+<!ATTLIST namespace
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT class (%boost.class.content;)>
+<!ATTLIST class
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT struct (%boost.class.content;)>
+<!ATTLIST struct
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT union (%boost.class.content;)>
+<!ATTLIST union
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT class-specialization (%boost.class-specialization.content;)>
+<!ATTLIST class-specialization
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT struct-specialization (%boost.class-specialization.content;)>
+<!ATTLIST struct-specialization
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT union-specialization (%boost.class-specialization.content;)>
+<!ATTLIST union-specialization
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT access (%boost.class.members;)+>
+<!ATTLIST access
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!--========= C++ Templates =========-->
+<!ELEMENT template (%boost.template.mix;)*>
+<!ATTLIST template %boost.common.attrib;>
+
+<!ELEMENT template-type-parameter (default?, purpose?)>
+<!ATTLIST template-type-parameter
+ name CDATA #REQUIRED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT template-nontype-parameter (type, default?, purpose?)>
+<!ATTLIST template-nontype-parameter
+ name CDATA #REQUIRED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT template-varargs EMPTY>
+<!ATTLIST template-varargs %boost.common.attrib;>
+
+<!ELEMENT specialization (template-arg)*>
+<!ATTLIST specialization %boost.common.attrib;>
+
+<!ELEMENT template-arg ANY>
+<!ATTLIST template-arg
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT default ANY>
+<!ATTLIST default %boost.common.attrib;>
+
+<!ELEMENT inherit (type, purpose?)>
+<!ATTLIST inherit
+ access CDATA #IMPLIED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT purpose ANY>
+<!ATTLIST purpose %boost.common.attrib;>
+
+<!ELEMENT description ANY>
+<!ATTLIST description %boost.common.attrib;>
+
+<!ELEMENT type ANY>
+<!ATTLIST type %boost.common.attrib;>
+
+<!ELEMENT typedef (type, purpose?, description?)>
+<!ATTLIST typedef
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT enum (enumvalue*, purpose?, description?)>
+<!ATTLIST enum
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT enumvalue (default?, purpose?, description?)>
+<!ATTLIST enumvalue
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT static-constant (type, default, purpose?, description?)>
+<!ATTLIST static-constant
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT data-member (type, purpose?, description?)>
+<!ATTLIST data-member
+ name CDATA #REQUIRED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT paramtype ANY>
+<!ATTLIST paramtype %boost.common.attrib;>
+
+<!ELEMENT effects ANY>
+<!ATTLIST effects %boost.common.attrib;>
+
+<!ELEMENT postconditions ANY>
+<!ATTLIST postconditions %boost.common.attrib;>
+
+<!ELEMENT method-group (method|overloaded-method)*>
+<!ATTLIST method-group
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT constructor (template?, parameter*, %boost.function.semantics;)>
+<!ATTLIST constructor
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT destructor (%boost.function.semantics;)>
+<!ATTLIST destructor
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT method (template?, type, parameter*, %boost.function.semantics;)>
+<!ATTLIST method
+ name CDATA #REQUIRED
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT function (template?, type, parameter*, %boost.function.semantics;)>
+<!ATTLIST function
+ name CDATA #REQUIRED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT overloaded-method (signature*, %boost.function.semantics;)>
+<!ATTLIST overloaded-method
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT overloaded-function (signature*, %boost.function.semantics;)>
+<!ATTLIST overloaded-function
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT signature (template?, type, parameter*)>
+<!ATTLIST signature
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT requires ANY>
+<!ATTLIST requires %boost.common.attrib;>
+
+<!ELEMENT returns ANY>
+<!ATTLIST returns %boost.common.attrib;>
+
+<!ELEMENT throws ANY>
+<!ATTLIST throws %boost.common.attrib;>
+
+<!ELEMENT complexity ANY>
+<!ATTLIST complexity %boost.common.attrib;>
+
+<!ELEMENT notes ANY>
+<!ATTLIST notes %boost.common.attrib;>
+
+<!ELEMENT rationale ANY>
+<!ATTLIST rationale %boost.common.attrib;>
+
+<!ELEMENT functionname (#PCDATA)>
+<!ATTLIST functionname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT enumname (#PCDATA)>
+<!ATTLIST enumname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT macroname (#PCDATA)>
+<!ATTLIST macroname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT headername (#PCDATA)>
+<!ATTLIST headername
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT globalname (#PCDATA)>
+<!ATTLIST globalname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT copy-assignment
+ (template?, type?, parameter*, %boost.function.semantics;)>
+<!ATTLIST copy-assignment
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT free-function-group (function|overloaded-function)*>
+<!ATTLIST free-function-group
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT precondition ANY>
+<!ATTLIST precondition %boost.common.attrib;>
+
+<!ELEMENT code ANY>
+<!ATTLIST code %boost.common.attrib;>
+
+<!ELEMENT using-namespace EMPTY>
+<!ATTLIST using-namespace
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT using-class EMPTY>
+<!ATTLIST using-class
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!--========== Boost Testsuite Extensions ==========-->
+<!ENTITY % boost.testsuite.tests
+ "compile-test|link-test|run-test|
+ compile-fail-test|link-fail-test|run-fail-test">
+<!ENTITY % boost.testsuite.test.content
+ "source*, lib*, requirement*, purpose, if-fails?">
+
+<!ELEMENT testsuite ((%boost.testsuite.tests;)+)>
+<!ATTLIST testsuite %boost.common.attrib;>
+
+<!ELEMENT compile-test (%boost.testsuite.test.content;)>
+<!ATTLIST compile-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link-test (%boost.testsuite.test.content;)>
+<!ATTLIST link-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT run-test (%boost.testsuite.test.content;)>
+<!ATTLIST run-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT compile-fail-test (%boost.testsuite.test.content;)>
+<!ATTLIST compile-fail-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link-fail-test (%boost.testsuite.test.content;)>
+<!ATTLIST link-fail-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT run-fail-test (%boost.testsuite.test.content;)>
+<!ATTLIST run-fail-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT source (#PCDATA|snippet)*>
+
+<!ELEMENT snippet EMPTY>
+<!ATTLIST snippet
+ name CDATA #REQUIRED>
+
+<!ELEMENT lib (#PCDATA)>
+
+<!ELEMENT requirement (#PCDATA)>
+<!ATTLIST requirement
+ name CDATA #REQUIRED>
+
+<!ELEMENT if-fails ANY>
+
+<!ELEMENT parameter (paramtype, default?, description?)>
+<!ATTLIST parameter
+ name CDATA #IMPLIED
+ pack CDATA #IMPLIED>
+
+<!ELEMENT programlisting ANY>
+<!ATTLIST programlisting
+ name CDATA #IMPLIED>
+
+<!--========== Customize the DocBook DTD ==========-->
+<!ENTITY % local.tech.char.class "|functionname|libraryname|enumname|headername|macroname|code">
+<!ENTITY % local.para.class
+ "|using-namespace|using-class|librarylist|librarycategorylist">
+<!ENTITY % local.descobj.class "|libraryinfo">
+<!ENTITY % local.classname.attrib "alt CDATA #IMPLIED">
+<!ENTITY % local.methodname.attrib "alt CDATA #IMPLIED">
+<!ENTITY % local.refentry.class "|library-reference|testsuite">
+<!ENTITY % local.title.char.mix "">
+<!ENTITY % programlisting.module "IGNORE">
+<!ENTITY % parameter.module "IGNORE">
+<!ENTITY % function.module "IGNORE">
+<!ENTITY % type.module "IGNORE">
+
+<!--========== Import DocBook DTD ==========-->
+<!ENTITY % DocBook PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+%DocBook;
diff --git a/src/boost/tools/docca/example/include/docca/issue_101.hpp b/src/boost/tools/docca/example/include/docca/issue_101.hpp
new file mode 100644
index 000000000..8b5b53991
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_101.hpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2021 Evan Lenz (evan@lenzconsulting.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_101_HPP
+#define EXAMPLE_ISSUE_101_HPP
+
+namespace example {
+
+/** Issue 101
+
+ `typename` parameters should be handled (without generating an error).
+*/
+template<typename charT, typename traits>
+class issue_101;
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_33.hpp b/src/boost/tools/docca/example/include/docca/issue_33.hpp
new file mode 100644
index 000000000..8323356c9
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_33.hpp
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_33_HPP
+#define EXAMPLE_ISSUE_33_HPP
+
+namespace example {
+
+/** Issue 33
+
+ The Note and See Also sections should be distinct.
+
+ @note This is a note
+
+ @see https://boost.org
+*/
+struct issue_33
+{
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_34.hpp b/src/boost/tools/docca/example/include/docca/issue_34.hpp
new file mode 100644
index 000000000..c05f8058d
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_34.hpp
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_34_HPP
+#define EXAMPLE_ISSUE_34_HPP
+
+namespace example {
+
+/** Issue 34
+*/
+class issue_34
+{
+ /// Should not be displayed
+ struct P
+ {
+ };
+
+public:
+ /// Base of Q
+ struct R
+ {
+ };
+
+ /** Q should be derived only from R
+ */
+ struct Q : private P, R
+ {
+ };
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_38.hpp b/src/boost/tools/docca/example/include/docca/issue_38.hpp
new file mode 100644
index 000000000..eb515033d
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_38.hpp
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2020 Evan Lenz (evan@lenzconsulting.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_38_HPP
+#define EXAMPLE_ISSUE_38_HPP
+
+namespace example {
+
+/** Issue 38
+
+ Open: [a, b]
+ Half-open: [a, b)
+ Closed: (a, b)
+
+ @li Gracefully handle brackets in javadoc comments
+*/
+class issue_38
+{
+ int i_;
+
+public:
+ /** Half-open: [a, b)
+
+ first to last exclusive, i.e. [ first, last )
+ */
+ issue_38();
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_44.hpp b/src/boost/tools/docca/example/include/docca/issue_44.hpp
new file mode 100644
index 000000000..790f77f81
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_44.hpp
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2020 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_44_HPP
+#define EXAMPLE_ISSUE_44_HPP
+
+namespace example {
+
+/** Issue 44
+
+ @li All of the constructors should be
+ grouped together on the overload
+ resolution page.
+
+ @li The class page should show three
+ unique briefs for the constructor.
+*/
+class issue_44
+{
+ int i_;
+
+public:
+ /** Default constructor.
+
+ Description.
+ */
+ issue_44();
+
+ /** Constructor.
+
+ Description.
+ */
+ /** @{ */
+ issue_44(char);
+ issue_44(short, short);
+ /** @} */
+
+ /** Constructor.
+
+ Description.
+ */
+ /** @{ */
+ issue_44(char, int);
+ issue_44(long, long);
+ /** @} */
+
+ /** Void constructor
+
+ Description.
+ */
+ issue_44(void*);
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_47.hpp b/src/boost/tools/docca/example/include/docca/issue_47.hpp
new file mode 100644
index 000000000..03324e131
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_47.hpp
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2020 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_47_HPP
+#define EXAMPLE_ISSUE_47_HPP
+
+namespace example {
+
+/** Issue 47
+
+ The function `max_size` should be
+ listed as a static member.
+*/
+class issue_47
+{
+ int i_;
+
+public:
+ /** Member
+ */
+ void f();
+
+ /** Static Member
+ */
+ static int max_size() noexcept;
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_48.hpp b/src/boost/tools/docca/example/include/docca/issue_48.hpp
new file mode 100644
index 000000000..9f0b9ea9f
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_48.hpp
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_48_HPP
+#define EXAMPLE_ISSUE_48_HPP
+
+namespace example {
+
+class X
+{
+};
+
+struct Y
+{
+};
+
+/** Issue 48
+
+ The class should show one regular
+ public member function and two friend
+ functions.
+*/
+class issue_48
+{
+ /// This should not be emitted.
+ friend class X;
+
+ /// This should not be emitted.
+ friend struct Y;
+
+ /// This should be emitted
+ friend void g( issue_48 );
+
+public:
+ void f();
+
+ /// This should be emitted
+ friend void h( issue_48 );
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_52.hpp b/src/boost/tools/docca/example/include/docca/issue_52.hpp
new file mode 100644
index 000000000..a39cbd493
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_52.hpp
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2020 Evan Lenz (evan@lenzconsulting.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_52_HPP
+#define EXAMPLE_ISSUE_52_HPP
+
+namespace example {
+
+/** Issue 52
+
+ Constructor and destructor are annotated as such.
+*/
+class issue_52
+{
+public:
+ /** Default constructor.
+
+ Description
+ */
+ issue_52();
+
+ /** Destructor.
+
+ Description
+ */
+ ~issue_52();
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_53.hpp b/src/boost/tools/docca/example/include/docca/issue_53.hpp
new file mode 100644
index 000000000..53cfe7521
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_53.hpp
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2020 Evan Lenz (evan@lenzconsulting.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_53_HPP
+#define EXAMPLE_ISSUE_53_HPP
+
+namespace example {
+
+/** Issue 53
+
+ @li Distinct constructor descriptions
+ should be separated by a silver em dash.
+*/
+class issue_53
+{
+ int i_;
+
+public:
+ /** Default constructor.
+
+ Description.
+ */
+ issue_53();
+
+ /** Constructor.
+
+ Description.
+ */
+ issue_53(char);
+
+ /** Void constructor
+
+ Description.
+ */
+ issue_53(void*);
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_55.hpp b/src/boost/tools/docca/example/include/docca/issue_55.hpp
new file mode 100644
index 000000000..85628f445
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_55.hpp
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_55_HPP
+#define EXAMPLE_ISSUE_55_HPP
+
+namespace example {
+
+/** Issue 55
+
+ Clicking @ref f should lead to the
+ overload resolution landing page.
+*/
+struct issue_55
+{
+ void f(int);
+ void f(double);
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_63.hpp b/src/boost/tools/docca/example/include/docca/issue_63.hpp
new file mode 100644
index 000000000..5b2ab07a3
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_63.hpp
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2021 Evan Lenz (evan@lenzconsulting.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_63_HPP
+#define EXAMPLE_ISSUE_63_HPP
+
+namespace example {
+
+/** Issue 63
+
+ @li Markup (@ commands) in tables should be rendered
+*/
+enum class issue_63
+{
+ /**
+ * foo brief
+
+ foo description
+
+ @see issue_55
+ */
+ foo,
+
+ /**
+ * bar brief
+
+ bar description
+
+ @li First bullet referencing @ref issue_55
+ @li Second bullet
+ */
+ bar
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_69.hpp b/src/boost/tools/docca/example/include/docca/issue_69.hpp
new file mode 100644
index 000000000..28a0d9338
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_69.hpp
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2021 Evan Lenz (evan@lenzconsulting.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_69_HPP
+#define EXAMPLE_ISSUE_69_HPP
+
+namespace example {
+
+/** Issue 69
+
+ The brackets in the @ref operator[] page's
+ code block should not appear escaped. Nor
+ should they in that link just there (in this
+ sentence).
+*/
+struct issue_69
+{
+ operator[](string_view key);
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_70.hpp b/src/boost/tools/docca/example/include/docca/issue_70.hpp
new file mode 100644
index 000000000..89271d789
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_70.hpp
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2021 Evan Lenz (evan@lenzconsulting.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_70_HPP
+#define EXAMPLE_ISSUE_70_HPP
+
+namespace example {
+
+/** Issue 70
+
+ This reference, @ref issue_70_b::foo, should link to the issue_70_b page
+ (not issue_63).
+*/
+enum class issue_70
+{
+ foo,
+ bar
+};
+
+enum class issue_70_b
+{
+ foo,
+ bar
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/include/docca/issue_78.hpp b/src/boost/tools/docca/example/include/docca/issue_78.hpp
new file mode 100644
index 000000000..f1b090516
--- /dev/null
+++ b/src/boost/tools/docca/example/include/docca/issue_78.hpp
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2021 Evan Lenz (evan@lenzconsulting.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXAMPLE_ISSUE_78_HPP
+#define EXAMPLE_ISSUE_78_HPP
+
+namespace example {
+
+/** Issue 78
+
+ foo() should show up under the heading "Static Member Functions"
+ and bar should show up under the heading "Static Members"
+*/
+class issue_78
+{
+public:
+ static foo();
+ static bar;
+};
+
+} // example
+
+#endif
diff --git a/src/boost/tools/docca/example/index.xml b/src/boost/tools/docca/example/index.xml
new file mode 100644
index 000000000..c364e4ed2
--- /dev/null
+++ b/src/boost/tools/docca/example/index.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "boostbook.dtd">
+
+<!--
+ Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+-->
+
+<section id="docca.index">
+ <title>Index</title>
+ <index/>
+</section>
diff --git a/src/boost/tools/docca/example/main.qbk b/src/boost/tools/docca/example/main.qbk
new file mode 100644
index 000000000..d9938111a
--- /dev/null
+++ b/src/boost/tools/docca/example/main.qbk
@@ -0,0 +1,31 @@
+[/
+ Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[library docca
+ [quickbook 1.6]
+ [copyright 2016 Vinnie Falco]
+ [purpose Documentation Library]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+ ]
+ [category template]
+ [category generic]
+]
+
+[template mdash[] '''&mdash; ''']
+[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
+[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
+
+[template include_file[path][^<'''<ulink url="https://github.com/boostorg/docca/blob/master/example/include/'''[path]'''">'''[path]'''</ulink>'''>]]
+
+[section:ref Reference]
+[include reference.qbk]
+[endsect]
+
+[xinclude index.xml]
diff --git a/src/boost/tools/docca/example/makeqbk.sh b/src/boost/tools/docca/example/makeqbk.sh
new file mode 100644
index 000000000..e6fa0c30a
--- /dev/null
+++ b/src/boost/tools/docca/example/makeqbk.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/bash
+
+# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+mkdir -p temp
+doxygen source.dox
+cd temp
+xsltproc combine.xslt index.xml > all.xml
+xsltproc ../reference.xsl all.xml > ../reference.qbk
+
diff --git a/src/boost/tools/docca/example/reference.xsl b/src/boost/tools/docca/example/reference.xsl
new file mode 100644
index 000000000..de5675294
--- /dev/null
+++ b/src/boost/tools/docca/example/reference.xsl
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+<!-- Variables (Edit for your project) -->
+<xsl:variable name="doc-ref" select="'docca.ref.'"/>
+<xsl:variable name="doc-ns" select="'example'"/>
+<xsl:variable name="debug" select="0"/>
+<xsl:variable name="private" select="0"/>
+<!-- End Variables -->
+
+<xsl:include href="../include/docca/doxygen.xsl"/>
+
+</xsl:stylesheet>
+
diff --git a/src/boost/tools/docca/example/xsl/custom-overrides.xsl b/src/boost/tools/docca/example/xsl/custom-overrides.xsl
new file mode 100644
index 000000000..7f1a4d143
--- /dev/null
+++ b/src/boost/tools/docca/example/xsl/custom-overrides.xsl
@@ -0,0 +1,25 @@
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ exclude-result-prefixes="xs"
+ expand-text="yes">
+
+ <xsl:variable name="doc-ref" select="'docca.ref'"/>
+ <xsl:variable name="doc-ns" select="'example'"/>
+ <xsl:variable name="include-private-members" select="false()"/>
+
+ <xsl:template mode="includes-template-footer" match="location">
+ <xsl:variable name="convenience-header" as="xs:string?">
+ <xsl:apply-templates mode="convenience-header" select="@file"/>
+ </xsl:variable>
+ <xsl:if test="$convenience-header">
+ <xsl:text>{$nl}</xsl:text>
+ <xsl:text>Convenience header [include_file boost/{$convenience-header}]</xsl:text>
+ <xsl:text>{$nl}</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template mode="convenience-header" match="@file[contains(., 'boost/json')]">json.hpp</xsl:template>
+ <xsl:template mode="convenience-header" match="@file"/>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/assemble-quickbook.xsl b/src/boost/tools/docca/include/docca/assemble-quickbook.xsl
new file mode 100644
index 000000000..fe39870a0
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/assemble-quickbook.xsl
@@ -0,0 +1,20 @@
+<!-- Concatenate all the text files from a directory into one big file -->
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ exclude-result-prefixes="xs">
+
+ <xsl:output method="text"/>
+
+ <!-- TODO: remove this coupling; should be configured in the build file somehow
+ (add support for Saxon parameter-passing in the build?) -->
+ <xsl:param name="input-dir" select="'stage2/results'"/>
+
+ <xsl:template match="page">
+ <xsl:copy-of select="unparsed-text(concat($input-dir, '/', @href))"/>
+ <xsl:apply-templates select="page"/>
+ <!-- Two line breaks before to ensure it doesn't get absorbed into a preceding list -->
+ <xsl:text>&#xA;&#xA;[endsect]&#xA;</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/base-config.xsl b/src/boost/tools/docca/include/docca/base-config.xsl
new file mode 100644
index 000000000..b45f5bdb5
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/base-config.xsl
@@ -0,0 +1,47 @@
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:d="http://github.com/vinniefalco/docca"
+ exclude-result-prefixes="xs d"
+ expand-text="yes">
+
+ <!-- Projects should override these default values using a project-specific custom-overrides.xsl module -->
+ <xsl:variable name="doc-ref" select="'docca.ref'"/>
+ <xsl:variable name="doc-ns" select="'example'"/>
+
+ <xsl:variable name="include-private-members" select="false()"/>
+
+ <xsl:variable name="additional-id-replacements" as="element(replace)*">
+ <replace pattern="boost::asio::error" with=""/>
+ </xsl:variable>
+
+ <xsl:variable name="additional-type-replacements" as="element(replace)*">
+ <replace pattern="BOOST_ASIO_DECL ?(.*)" with="$1"/>
+ </xsl:variable>
+
+ <!-- TODO: refactor the stage-two-specific rules into a separate module that can't intefere with stage one -->
+ <xsl:template mode="includes-template" match="location"
+ >Defined in header [include_file {substring-after(@file, 'include/')}]
+ </xsl:template>
+
+ <xsl:function name="d:should-ignore-compound">
+ <xsl:param name="element" as="element(compound)"/>
+ <xsl:sequence select="contains($element/name, '::detail')"/> <!-- TODO: Confirm this should be custom and not built-in behavior -->
+ </xsl:function>
+
+ <xsl:function name="d:should-ignore-base">
+ <xsl:param name="element" as="element(basecompoundref)"/>
+ <xsl:sequence select="contains($element, '::detail')"/> <!-- TODO: Confirm this should be custom and not built-in behavior -->
+ </xsl:function>
+
+ <xsl:function name="d:should-ignore-inner-class">
+ <xsl:param name="element" as="element(innerclass)"/>
+ <xsl:sequence select="contains($element, '_handler')"/>
+ </xsl:function>
+
+ <xsl:function name="d:should-ignore-friend">
+ <xsl:param name="element" as="element(memberdef)"/>
+ <xsl:sequence select="contains($element, '_helper')"/>
+ </xsl:function>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/base-extract-xml-pages.xsl b/src/boost/tools/docca/include/docca/base-extract-xml-pages.xsl
new file mode 100644
index 000000000..bf9ba53c4
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/base-extract-xml-pages.xsl
@@ -0,0 +1,476 @@
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:d="http://github.com/vinniefalco/docca"
+ exclude-result-prefixes="xs d"
+ expand-text="yes">
+
+ <!-- TODO: make sure this doesn't screw up any formatting -->
+ <!-- NEW TODO: verify we don't need/want this -->
+ <!--
+ <xsl:output indent="yes"/>
+ -->
+
+ <xsl:include href="common.xsl"/>
+
+ <xsl:key name="visible-memberdefs-by-id"
+ match="memberdef[$include-private-members or not(@prot eq 'private')]"
+ use="@id"/>
+
+ <xsl:key name="elements-by-refid" match="compound | member" use="@refid"/>
+
+ <xsl:variable name="index-xml" select="/"/>
+
+ <xsl:template match="/">
+ <index>
+ <xsl:apply-templates select="/doxygenindex/compound"/>
+ </index>
+ <!-- Testing the ID-related functions
+ <xsl:value-of select="replace(d:extract-ns('put'), '::$', '')"/>
+ <xsl:text>&#xA;</xsl:text>
+ <xsl:value-of select="replace(d:extract-ns('foobar::parser::put'), '::$', '')"/>
+ <xsl:text>&#xA;</xsl:text>
+ <xsl:value-of select="d:extract-ns('foobar::parser::put&lt;foo::bar, bat::bang>')"/>
+ <xsl:text>&#xA;</xsl:text>
+ <xsl:value-of select="d:strip-ns('boost::beast::http::parser::basic_parser&lt; foo::isRequest, bar::parser &gt;')"/>
+ <xsl:text>&#xA;</xsl:text>
+ <xsl:value-of select="d:strip-doc-ns('boost::beast::http::parser::basic_parser&lt; foo::isRequest, bar::parser &gt;')"/>
+ <xsl:text>&#xA;</xsl:text>
+ <xsl:text>&#xA;</xsl:text>
+ <xsl:value-of select="d:make-id('boost::beast::http::parser::basic_parser&lt; foo::isRequest, bar::parser &gt;')"/>
+ -->
+ </xsl:template>
+
+ <!-- Default implementation; can be customized/overridden -->
+ <xsl:function name="d:should-ignore-compound">
+ <xsl:param name="compound" as="element(compound)"/>
+ <xsl:sequence select="false()"/>
+ </xsl:function>
+
+ <xsl:template match="compound[d:should-ignore-compound(.)]"/>
+ <xsl:template match="compound">
+ <!-- Load each input file only once -->
+ <xsl:variable name="source-doc" select="d:get-source-doc(.)"/>
+ <!-- Ignore private classes unless private members are enabled -->
+ <xsl:if test="$include-private-members or not($source-doc/doxygen/compounddef/@prot eq 'private')">
+ <!-- Look up memberdefs (and constrain by visibility) only once -->
+ <xsl:variable name="memberdefs" select="key('visible-memberdefs-by-id', member/@refid, $source-doc)"/>
+ <!-- Create a filtered copy of members within their minimal context, listing only the visible ones -->
+ <xsl:variable name="visible-members" as="element(member)*">
+ <xsl:variable name="compound" as="element()">
+ <compound kind="{@kind}" refid="{@refid}">
+ <name>{name}</name>
+ <xsl:copy-of select="member[@refid = $memberdefs/@id]"/>
+ </compound>
+ </xsl:variable>
+ <xsl:sequence select="$compound/member"/>
+ </xsl:variable>
+ <xsl:apply-templates mode="create-page" select=".">
+ <xsl:with-param name="source-doc" select="$source-doc" tunnel="yes"/>
+ <xsl:with-param name="memberdefs" select="$memberdefs" tunnel="yes"/>
+ <xsl:with-param name="visible-members" select="$visible-members" tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:function name="d:get-source-doc" as="document-node()">
+ <xsl:param name="compound" as="element(compound)"/>
+ <xsl:sequence select="document($compound/@refid||'.xml', $index-xml)"/>
+ </xsl:function>
+
+ <!-- Split up the content into class, struct, and member pages -->
+ <xsl:template mode="create-page" match="*"/>
+ <xsl:template mode="create-page" match="compound[@kind = 'namespace']">
+ <xsl:apply-templates mode="child-pages" select="."/>
+ </xsl:template>
+ <xsl:template mode="create-page" match="compound[@kind = ('class','struct')]
+ | compound/member">
+ <xsl:variable name="page-id" as="xs:string">
+ <xsl:apply-templates mode="page-id" select="."/>
+ </xsl:variable>
+ <page id="{$page-id}" href="{$page-id}.xml">
+ <xsl:result-document href="xml-pages/{$page-id}.xml">
+ <xsl:apply-templates mode="page-content" select=".">
+ <xsl:with-param name="page-id" select="$page-id" tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:result-document>
+ <xsl:apply-templates mode="child-pages" select="."/>
+ </page>
+ </xsl:template>
+
+ <!-- Create the member page for each child (or, if overloaded, the overload-list page) -->
+ <xsl:template mode="child-pages" match="compound">
+ <xsl:param name="visible-members" tunnel="yes"/>
+ <!-- Create a page for each unique member name -->
+ <xsl:for-each select="$visible-members[not(name = preceding-sibling::member/name)]">
+ <xsl:apply-templates mode="create-page" select=".">
+ <xsl:with-param name="is-overload-list-page" select="d:is-overloaded(.)" tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ </xsl:template>
+
+ <!-- A member page doesn't have children, unless it is an overload-list page -->
+ <xsl:template mode="child-pages" match="compound/member">
+ <xsl:param name="is-overload-list-page" tunnel="yes"/>
+ <xsl:if test="$is-overload-list-page">
+ <xsl:apply-templates mode="create-page" select="d:overloaded-members(.)">
+ <xsl:with-param name="is-overload-list-page" select="false()" tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template mode="page-id" match="compound">{d:make-id(name)}</xsl:template>
+ <xsl:template mode="page-id" match="member">
+ <xsl:param name="is-overload-list-page" tunnel="yes"/>
+ <xsl:value-of>
+ <xsl:apply-templates mode="base-member-page-id" select="."/>
+ <!-- Append the overload-specific suffix, if applicable -->
+ <xsl:if test="d:is-overloaded(.) and not($is-overload-list-page)">
+ <xsl:value-of select="d:make-id('.overload'||d:overload-position(.))"/>
+ </xsl:if>
+ </xsl:value-of>
+ </xsl:template>
+
+ <xsl:function name="d:is-overloaded" as="xs:boolean">
+ <xsl:param name="member" as="element(member)"/>
+ <xsl:sequence select="exists(d:overloaded-members($member)[2])"/>
+ </xsl:function>
+
+ <xsl:function name="d:overload-position" as="xs:integer">
+ <xsl:param name="member" as="element(member)"/>
+ <xsl:sequence select="1 + count($member/preceding-sibling::member[name eq $member/name])"/>
+ </xsl:function>
+
+ <xsl:function name="d:overloaded-members" as="element(member)+">
+ <xsl:param name="member" as="element(member)"/>
+ <xsl:sequence select="$member/../member[name eq $member/name]"/>
+ </xsl:function>
+
+
+ <xsl:template mode="base-member-page-id" priority="1"
+ match="compound[@kind eq 'namespace']
+ /member">{d:make-id(../name||'::'||name)}</xsl:template>
+ <xsl:template mode="base-member-page-id" match="compound/member">{d:make-id(../name||'.' ||name)}</xsl:template>
+
+
+ <!-- The content for a class or struct is the original source document, pared down some -->
+ <xsl:template mode="page-content" match="compound">
+ <xsl:param name="source-doc" tunnel="yes"/>
+ <xsl:apply-templates mode="compound-page" select="$source-doc"/>
+ </xsl:template>
+
+ <!-- By default, copy everything -->
+ <xsl:template mode="compound-page" match="@* | node()" name="copy-in-compound-page">
+ <xsl:copy>
+ <xsl:apply-templates mode="#current" select="@*"/>
+ <xsl:apply-templates mode="compound-page-insert" select="."/>
+ <xsl:apply-templates mode="#current"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- By default, don't insert anything -->
+ <xsl:template mode="compound-page-insert" match="*"/>
+
+ <xsl:template mode="compound-page" match="listofallmembers"/>
+
+ <xsl:template mode="compound-page" match="memberdef/@*"/>
+
+ <!-- But directly inside <memberdef>, don't copy anything... -->
+ <xsl:template mode="compound-page" match="memberdef/node()"/>
+
+ <!-- ...except for <name>, <briefdescription>, and <type> -->
+ <xsl:template mode="compound-page" match="memberdef/name
+ | memberdef/briefdescription
+ | memberdef/type" priority="1">
+ <xsl:call-template name="copy-in-compound-page"/>
+ </xsl:template>
+
+ <!-- Insert a reference to each child member's page ID -->
+ <xsl:template mode="compound-page-insert" match="memberdef">
+ <xsl:attribute name="d:page-refid" select="d:make-id(/doxygen/compounddef/compoundname||'.'||name)"/>
+ </xsl:template>
+
+ <!-- Alternative implementation in case we need to start controlling whitespace more
+ <xsl:template mode="compound-page" match="memberdef">
+ <memberdef>
+ <xsl:text>&#xA;</xsl:text>
+ <xsl:copy-of select="name"/>
+ <xsl:text>&#xA;</xsl:text>
+ <xsl:copy-of select="briefdescription"/>
+ </memberdef>
+ </xsl:template>
+ -->
+
+ <!-- The content for a member page is a subset of the source document -->
+ <xsl:template mode="page-content" match="compound/member">
+ <xsl:param name="is-overload-list-page" tunnel="yes"/>
+ <xsl:choose>
+ <xsl:when test="$is-overload-list-page">
+ <!-- For the overload list page, include the content for every like-named member -->
+ <xsl:apply-templates mode="list-page" select=".">
+ <xsl:with-param name="applicable-members" select="d:overloaded-members(.)" tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Otherwise, this page is just for one implementation (whether overloaded or not) -->
+ <xsl:apply-templates mode="member-page" select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template mode="list-page member-page" match="member" priority="2">
+ <xsl:param name="applicable-members" as="element(member)+" select="." tunnel="yes"/>
+ <xsl:param name="source-doc" tunnel="yes"/>
+ <xsl:param name="memberdefs" tunnel="yes"/>
+ <xsl:apply-templates mode="#current" select="$source-doc">
+ <xsl:with-param name="target-memberdefs"
+ select="$memberdefs[@id = $applicable-members/@refid]"
+ tunnel="yes"/>
+ <xsl:with-param name="member" select="." tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- Always copy the name of the parent compound -->
+ <xsl:template mode="list-page member-page" match="compoundname" priority="2">
+ <xsl:copy-of select="."/>
+ </xsl:template>
+
+ <!-- Otherwise, only copy an element if it's the target member or one of its ancestors -->
+ <xsl:template mode="list-page member-page" match="*" priority="1">
+ <xsl:param name="target-memberdefs" tunnel="yes"/>
+ <xsl:if test=". intersect $target-memberdefs/ancestor-or-self::*">
+ <xsl:next-match/>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- By default, copy everything -->
+ <xsl:template mode="list-page" match="@* | node()">
+ <xsl:copy>
+ <xsl:apply-templates mode="#current" select="@*"/>
+ <xsl:apply-templates mode="list-page-insert" select="."/>
+ <xsl:apply-templates mode="#current"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- By default, don't insert anything -->
+ <xsl:template mode="list-page-insert" match="*"/>
+
+
+ <!-- By default, copy everything -->
+ <xsl:template mode="member-page
+ copy-member-content" match="@* | node()">
+ <xsl:copy>
+ <xsl:apply-templates mode="#current" select="@*"/>
+ <xsl:apply-templates mode="member-page-insert" select="."/>
+ <xsl:apply-templates mode="#current"/>
+ <xsl:apply-templates mode="member-page-append" select="."/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- By default, don't insert or append anything -->
+ <xsl:template mode="member-page-insert
+ member-page-append" match="*"/>
+
+ <!-- Strip out extraneous whitespace -->
+ <xsl:template mode="list-page member-page" match="compounddef/text() | sectiondef/text()"/>
+
+ <!-- Switch to an unfiltered copy once we're done filtering out the undesired elements -->
+ <xsl:template mode="list-page member-page" match="memberdef/node()" priority="2">
+ <xsl:apply-templates mode="copy-member-content" select="."/>
+ </xsl:template>
+
+ <!-- Add the page ID to the top of all page types -->
+ <xsl:template mode="compound-page-insert
+ member-page-insert
+ list-page-insert" match="/doxygen" priority="2">
+ <xsl:param name="page-id" tunnel="yes"/>
+ <xsl:attribute name="d:page-id" select="$page-id"/>
+ <xsl:next-match/>
+ </xsl:template>
+
+ <!-- Also, if applicable, insert the overload position and/or base compound reference of this member -->
+ <xsl:template mode="member-page-insert" match="/doxygen" priority="1">
+ <xsl:param name="member" tunnel="yes"/>
+ <xsl:if test="d:is-overloaded($member)">
+ <xsl:attribute name="d:overload-position" select="d:overload-position($member)"/>
+ <xsl:attribute name="d:overload-size" select="count(d:overloaded-members($member))"/>
+ </xsl:if>
+ <xsl:if test="$member[not(starts-with(@refid, ../@refid))]">
+ <xsl:variable name="base-compound" select="$index-xml/*/compound[starts-with($member/@refid, @refid)]
+ [not(d:should-ignore-compound(.))]"/>
+ <xsl:apply-templates mode="base-compound-atts" select="$base-compound"/>
+ </xsl:if>
+ <xsl:next-match/>
+ </xsl:template>
+
+ <xsl:template mode="base-compound-atts" match="compound">
+ <xsl:attribute name="d:base-compound-name" select="d:strip-doc-ns(name)"/>
+ <xsl:attribute name="d:base-compound-refid">
+ <xsl:apply-templates mode="page-id" select="."/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <!-- Make data available for the typedef tables, if applicable -->
+ <xsl:template mode="member-page-append" match="memberdef[@kind eq 'typedef']
+ [type/ref]
+ [not(contains(type, '*'))]">
+ <xsl:for-each select="type/ref">
+ <d:referenced-typedef-class>
+ <xsl:variable name="compound" select="d:get-target-element(.)[self::compound]"/>
+ <xsl:apply-templates mode="compound-page" select="$compound ! d:get-source-doc(.)/*/compounddef"/>
+ </d:referenced-typedef-class>
+ </xsl:for-each>
+ </xsl:template>
+
+ <!-- Finally, add the page type -->
+ <xsl:template mode="compound-page-insert" match="/doxygen">
+ <xsl:attribute name="d:page-type" select="'compound'"/>
+ </xsl:template>
+ <xsl:template mode="member-page-insert" match="/doxygen">
+ <xsl:attribute name="d:page-type" select="'member'"/>
+ </xsl:template>
+ <xsl:template mode="list-page-insert" match="/doxygen">
+ <xsl:attribute name="d:page-type" select="'overload-list'"/>
+ </xsl:template>
+
+ <!-- For overload-list pages, include the page id for each member -->
+ <xsl:template mode="list-page-insert" match="memberdef">
+ <xsl:param name="applicable-members" tunnel="yes"/>
+ <xsl:variable name="this-id" select="@id"/>
+ <xsl:variable name="original-member" select="$applicable-members[@refid eq $this-id]"/>
+ <xsl:attribute name="d:page-refid">
+ <xsl:apply-templates mode="page-id" select="$original-member">
+ <xsl:with-param name="is-overload-list-page" select="false()" tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:attribute>
+ </xsl:template>
+
+ <!-- For public innerclasses, insert the referenced class inline -->
+ <xsl:template mode="compound-page-insert" match="innerclass[@prot eq 'public']">
+ <xsl:attribute name="d:page-refid" select="d:make-id(.)"/>
+ <d:referenced-inner-class>
+ <xsl:variable name="compound" select="d:get-target-element(.)" as="element(compound)"/>
+ <xsl:apply-templates mode="compound-page" select="d:get-source-doc($compound)/*/compounddef"/>
+ </d:referenced-inner-class>
+ </xsl:template>
+
+ <!-- Resolve the referenced page IDs for later link generation -->
+ <xsl:template mode="compound-page-insert member-page-insert" match="ref">
+ <xsl:attribute name="d:refid">
+ <xsl:apply-templates mode="page-id" select="d:get-target-element(.)">
+ <!-- For inline links to member pages, only link to the base page id (no overloads) -->
+ <xsl:with-param name="is-overload-list-page" select="true()" tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:attribute>
+ </xsl:template>
+
+ <xsl:function name="d:get-target-element" as="element()?"> <!-- to allow for partial builds -->
+ <!--
+ <xsl:function name="d:get-target-element" as="element()">
+ -->
+ <xsl:param name="ref" as="element()"/> <!-- <ref> or <innerclass> or... -->
+ <xsl:apply-templates mode="get-target-element" select="$ref">
+ <xsl:with-param name="ref" select="$ref" tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:function>
+
+ <xsl:template mode="get-target-element" match="*">
+ <xsl:param name="ref" as="element()" tunnel="yes"/>
+ <xsl:variable name="referenced-elements" select="key('elements-by-refid', $ref/@refid, $index-xml)"/>
+ <xsl:variable name="result" as="element()?">
+ <xsl:choose>
+ <!-- Handle the case where the referenced element appears two or more times in index.xml -->
+ <!-- If there's no ambiguity, we're done! -->
+ <xsl:when test="count($referenced-elements) eq 1">
+ <xsl:apply-templates mode="find-actual-target-element" select="$referenced-elements"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Otherwise, see if a namespace in the link text successfully disambiguates -->
+ <xsl:variable name="qualified-reference" as="element()*">
+ <xsl:variable name="parent-in-link-text"
+ select="if (contains($ref,'::'))
+ then d:extract-ns-without-suffix($ref)
+ else ''"/>
+ <xsl:sequence select="$referenced-elements[ends-with(parent::compound/name, '::'||$parent-in-link-text)]"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="count($qualified-reference) eq 1">
+ <xsl:apply-templates mode="find-actual-target-element" select="$qualified-reference"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Otherwise, favor the member that's in the same class or namespace as the current page -->
+ <xsl:variable name="sibling-reference" as="element()*">
+ <xsl:variable name="compound-for-current-page" select="root($ref)/doxygen/compounddef/compoundname/string()"/>
+ <xsl:sequence select="$referenced-elements[parent::compound/name eq $compound-for-current-page]"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="count($sibling-reference) eq 1">
+ <xsl:apply-templates mode="find-actual-target-element" select="$sibling-reference"/>
+ </xsl:when>
+ <!-- If all else fails, give up and just use the first one -->
+ <xsl:otherwise>
+ <xsl:apply-templates mode="find-actual-target-element" select="$referenced-elements[1]"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="not($result)">
+ <xsl:message>Unable to find referenced ID: <xsl:value-of select="$ref/@refid"/></xsl:message>
+ </xsl:if>
+ <xsl:sequence select="$result"/>
+ </xsl:template>
+
+ <xsl:template mode="find-actual-target-element" match="compound | member">
+ <xsl:sequence select="."/>
+ </xsl:template>
+
+ <!-- In the index XML, enumvalue "members" immediately follow the corresponding enum member -->
+ <xsl:template mode="find-actual-target-element" match="member[@kind eq 'enumvalue']">
+ <xsl:sequence select="d:enum-member(.)"/>
+ </xsl:template>
+
+ <xsl:function name="d:enum-member">
+ <xsl:param name="member"/>
+ <xsl:sequence select="$member/preceding-sibling::member[@kind eq 'enum'][1]"/>
+ </xsl:function>
+
+ <!-- Doxygen sometimes confuses refids of like values of enums in the same namespace;
+ based on a narrow heuristic, find the target it should have assigned instead -->
+ <xsl:template mode="find-actual-target-element"
+ match="member[@kind eq 'enumvalue']
+ [count(../member[@kind eq 'enumvalue']/name[. eq current()/name]) gt 1]"
+ priority="1">
+ <xsl:param name="ref" tunnel="yes"/>
+ <xsl:variable name="prefix-in-link-text" select="d:extract-ns-without-suffix($ref)"/>
+ <xsl:choose>
+ <xsl:when test="not($prefix-in-link-text)">
+ <!-- If there's no namespace in the link text, trust the refid that Doxygen assigned -->
+ <xsl:next-match/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Otherwise, see if a different target is a better match -->
+ <xsl:variable name="repeated-enum-values"
+ select="../member[@kind eq 'enumvalue'][name eq current()/name]"/>
+ <xsl:variable name="candidate-enums"
+ select="$repeated-enum-values/d:enum-member(.)"/>
+ <xsl:variable name="matching-enums"
+ select="$candidate-enums[name eq $prefix-in-link-text]"/>
+ <xsl:choose>
+ <xsl:when test="count($matching-enums) eq 1">
+ <!-- If we found exactly one match, use it instead of what Doxygen said -->
+ <xsl:sequence select="$matching-enums"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Otherwise, don't second-guess the refid Doxygen assigned -->
+ <xsl:next-match/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/base-stage1.xsl b/src/boost/tools/docca/include/docca/base-stage1.xsl
new file mode 100644
index 000000000..e57defe16
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/base-stage1.xsl
@@ -0,0 +1,635 @@
+<!DOCTYPE xsl:stylesheet [
+<!-- TODO: complete this list -->
+<!ENTITY BLOCK_LEVEL_ELEMENT "programlisting
+ | itemizedlist
+ | orderedlist
+ | parameterlist
+ | simplesect
+ | para
+ | table
+ | linebreak">
+]>
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:d="http://github.com/vinniefalco/docca"
+ exclude-result-prefixes="xs d"
+ expand-text="yes">
+
+ <xsl:include href="common.xsl"/>
+
+ <xsl:output indent="yes"/>
+
+ <xsl:template match="/doxygen" priority="1">
+ <page id="{@d:page-id}" type="{@d:page-type}">
+ <xsl:apply-templates mode="index-term-atts" select="."/>
+ <title>
+ <xsl:apply-templates mode="page-title" select="."/>
+ </title>
+ <xsl:apply-templates select="@d:base-compound-refid"/>
+ <xsl:next-match/>
+ </page>
+ </xsl:template>
+
+ <xsl:template match="@d:base-compound-refid">
+ <div>(Inherited from <ref d:refid="{.}">{../@d:base-compound-name}</ref>)</div>
+ </xsl:template>
+
+ <!-- Put an index term on every page except class (compound) and overloaded-member pages -->
+ <xsl:template mode="index-term-atts" match="doxygen[@d:page-type eq 'compound' or @d:overload-position]"/>
+ <xsl:template mode="index-term-atts" match="doxygen">
+ <xsl:attribute name="primary-index-term">
+ <xsl:apply-templates mode="primary-index-term" select="."/>
+ </xsl:attribute>
+ <xsl:apply-templates mode="secondary-index-term-att" select="."/>
+ </xsl:template>
+
+ <!-- By default, use the member name as the primary term... -->
+ <xsl:template mode="primary-index-term" match="doxygen">
+ <xsl:apply-templates mode="member-name" select="."/>
+ </xsl:template>
+ <!-- ...and the compound name as the secondary term. -->
+ <xsl:template mode="secondary-index-term-att" match="doxygen">
+ <xsl:attribute name="secondary-index-term">
+ <xsl:apply-templates mode="compound-name" select="."/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <!-- But with namespace members, use the fully-qualified name as the primary term... -->
+ <xsl:template mode="primary-index-term" match="doxygen[compounddef/@kind eq 'namespace']">
+ <xsl:apply-templates mode="compound-and-member-name" select="."/>
+ </xsl:template>
+ <!-- ...and no secondary term. -->
+ <xsl:template mode="secondary-index-term-att" match="doxygen[compounddef/@kind eq 'namespace']"/>
+
+ <xsl:template mode="compound-name" match="doxygen"
+ >{d:strip-doc-ns(compounddef/compoundname)}</xsl:template>
+
+ <xsl:template mode="member-name" match="doxygen"
+ >{(compounddef/sectiondef/memberdef/name)[1]}</xsl:template>
+
+ <xsl:template mode="compound-and-member-name" match="doxygen">
+ <xsl:variable name="compound-name" as="xs:string">
+ <xsl:apply-templates mode="compound-name" select="."/>
+ </xsl:variable>
+ <xsl:if test="$compound-name">{$compound-name}::</xsl:if>
+ <xsl:apply-templates mode="member-name" select="."/>
+ </xsl:template>
+
+ <xsl:template mode="page-title" match="doxygen[@d:page-type eq 'compound']">
+ <xsl:apply-templates mode="compound-name" select="."/>
+ </xsl:template>
+ <xsl:template mode="page-title" match="doxygen">
+ <xsl:apply-templates mode="compound-and-member-name" select="."/>
+ <xsl:apply-templates mode="overload-qualifier" select="."/>
+ </xsl:template>
+
+ <xsl:template mode="overload-qualifier" match="doxygen"/>
+ <xsl:template mode="overload-qualifier" match="doxygen[@d:overload-position]">
+ <xsl:text> (</xsl:text>
+ <xsl:value-of select="@d:overload-position"/>
+ <xsl:text> of </xsl:text>
+ <xsl:value-of select="@d:overload-size"/>
+ <xsl:text> overloads)</xsl:text>
+ </xsl:template>
+
+
+ <xsl:template match="/doxygen[@d:page-type eq 'compound']">
+ <xsl:apply-templates select="compounddef"/>
+ </xsl:template>
+
+ <xsl:template match="/doxygen[@d:page-type eq 'member']">
+ <xsl:apply-templates select="compounddef/sectiondef/memberdef"/> <!-- should just be one -->
+ </xsl:template>
+
+ <xsl:template match="/doxygen[@d:page-type eq 'overload-list']">
+ <xsl:apply-templates select="(compounddef/sectiondef/memberdef)[1]"/>
+ </xsl:template>
+
+ <xsl:template match="compounddef | memberdef" priority="2">
+ <xsl:next-match/>
+ <xsl:apply-templates mode="includes" select=".">
+ <xsl:with-param name="is-footer" select="true()"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- For convenience, pre-calculate some member sequences and tunnel them through -->
+ <xsl:template match="compounddef" priority="1">
+ <xsl:next-match>
+ <xsl:with-param name="public-types"
+ select="sectiondef[@kind eq 'public-type']/memberdef
+ | innerclass[@prot eq 'public'][not(d:should-ignore-inner-class(.))]"
+ tunnel="yes"/>
+ <xsl:with-param name="friends"
+ select="sectiondef[@kind eq 'friend']/memberdef[not(type = ('friend class','friend struct'))]
+ [not(d:should-ignore-friend(.))]"
+ tunnel="yes"/>
+ </xsl:next-match>
+ </xsl:template>
+
+ <xsl:template match="compounddef">
+ <xsl:param name="public-types" tunnel="yes"/>
+ <xsl:param name="friends" tunnel="yes"/>
+
+ <xsl:apply-templates select="briefdescription"/>
+
+ <xsl:apply-templates mode="section"
+ select=".,
+
+ ( $public-types/self::memberdef/..
+ | $public-types/self::innerclass
+ )[1],
+
+ sectiondef[@kind = ( 'public-func', 'public-static-func')],
+ sectiondef[@kind = ('protected-func','protected-static-func')],
+ sectiondef[@kind = ( 'private-func', 'private-static-func')][$include-private-members],
+
+ sectiondef[@kind = ( 'public-attrib', 'public-static-attrib')],
+ sectiondef[@kind = ('protected-attrib','protected-static-attrib')],
+ sectiondef[@kind = ( 'private-attrib', 'private-static-attrib')][$include-private-members],
+
+ $friends/..,
+
+ sectiondef[@kind eq 'related'],
+
+ detaileddescription
+ "/>
+ </xsl:template>
+
+ <xsl:template match="memberdef">
+ <xsl:apply-templates select="briefdescription"/>
+ <xsl:apply-templates mode="section" select="., detaileddescription"/>
+ </xsl:template>
+
+ <xsl:template match="memberdef[@kind eq 'enum']">
+ <xsl:apply-templates select="briefdescription"/>
+ <xsl:apply-templates mode="section" select="., parent::sectiondef, detaileddescription"/>
+ </xsl:template>
+
+ <xsl:template match="memberdef[/doxygen/@d:page-type eq 'overload-list']">
+ <xsl:for-each-group select="../../sectiondef/memberdef" group-by="briefdescription">
+ <xsl:apply-templates select="briefdescription"/>
+ <xsl:apply-templates mode="overload-list" select="current-group()"/>
+ </xsl:for-each-group>
+ </xsl:template>
+
+ <xsl:template mode="overload-list" match="memberdef">
+ <overloaded-member>
+ <xsl:apply-templates mode="normalize-params" select="templateparamlist"/>
+ <xsl:apply-templates mode="modifier" select="(@explicit, @friend, @static)[. eq 'yes'],
+ @virt[. eq 'virtual']"/>
+ <xsl:apply-templates select="type"/>
+ <ref d:refid="{@d:page-refid}">{name}</ref>
+ <params>
+ <xsl:apply-templates select="param"/>
+ </params>
+ <xsl:apply-templates mode="modifier" select="@const[. eq 'yes']"/>
+ </overloaded-member>
+ </xsl:template>
+
+ <xsl:template mode="modifier" match="@*">
+ <modifier>{local-name(.)}</modifier>
+ </xsl:template>
+ <xsl:template mode="modifier" match="@virt">
+ <modifier>virtual</modifier>
+ </xsl:template>
+
+
+ <xsl:template match="type">
+ <type>
+ <xsl:value-of select="d:cleanup-type(normalize-space(.))"/>
+ </type>
+ </xsl:template>
+
+ <!-- d:cleanup-param() may not be needed, and the above may suffice. (TODO: confirm this and remove d:cleanup-param() if so)
+ <xsl:template match="param/type">
+ <type>
+ <xsl:value-of select="d:cleanup-param(.)"/>
+ </type>
+ </xsl:template>
+ -->
+
+ <!-- TODO: Should this be a custom rule or built-in? -->
+ <xsl:template mode="section" match="simplesect[matches(title,'Concepts:?')]"/>
+
+ <!-- Omit description section if it has no body -->
+ <xsl:template mode="section" match="detaileddescription[not(normalize-space(.))]" priority="1"/>
+
+ <xsl:template mode="section" match="*">
+ <section>
+ <heading>
+ <xsl:apply-templates mode="section-heading" select="."/>
+ </heading>
+ <xsl:apply-templates mode="section-body" select="."/>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="simplesect | parameterlist">
+ <xsl:apply-templates mode="section" select="."/>
+ </xsl:template>
+
+ <xsl:template mode="section-heading" match="memberdef |
+ compounddef ">Synopsis</xsl:template>
+ <xsl:template mode="section-heading" match="detaileddescription">Description</xsl:template>
+
+ <xsl:template mode="section-heading" match="simplesect[@kind eq 'note' ]">Remarks</xsl:template>
+ <xsl:template mode="section-heading" match="simplesect[@kind eq 'see' ]">See Also</xsl:template>
+ <xsl:template mode="section-heading" match="simplesect[@kind eq 'return']">Return Value</xsl:template>
+ <xsl:template mode="section-heading" match="simplesect" >{title}</xsl:template>
+
+ <xsl:template mode="section-heading" match="parameterlist[@kind eq 'exception' ]">Exceptions</xsl:template>
+ <xsl:template mode="section-heading" match="parameterlist[@kind eq 'templateparam']">Template Parameters</xsl:template>
+ <xsl:template mode="section-heading" match="parameterlist ">Parameters</xsl:template>
+
+ <xsl:template mode="section-heading" match="innerclass">Types</xsl:template>
+
+ <xsl:template mode="section-heading" match="sectiondef[@kind eq 'friend' ]">Friends</xsl:template>
+ <xsl:template mode="section-heading" match="sectiondef[@kind eq 'related']">Related Functions</xsl:template>
+ <xsl:template mode="section-heading" match="sectiondef[@kind eq 'enum' ]">Values</xsl:template>
+
+ <xsl:template mode="section-heading" match="sectiondef">
+ <xsl:apply-templates mode="access-level" select="@kind"/>
+ <xsl:apply-templates mode="storage-class" select="@kind"/>
+ <xsl:apply-templates mode="member-kind" select="@kind"/>
+ </xsl:template>
+
+ <xsl:template mode="access-level" match="@kind[starts-with(.,'public-' )]"/>
+ <xsl:template mode="access-level" match="@kind[starts-with(.,'protected-')]">Protected </xsl:template>
+ <xsl:template mode="access-level" match="@kind[starts-with(.,'private-' )]">Private </xsl:template>
+
+ <xsl:template mode="storage-class" match="@*"/>
+ <xsl:template mode="storage-class" match="@kind[contains(.,'-static-')]">Static </xsl:template>
+
+ <xsl:template mode="member-kind" priority="1"
+ match="@kind[ends-with(.,'-static-attrib')]">Members</xsl:template>
+ <xsl:template mode="member-kind" match="@kind[ends-with(.,'-attrib' )]">Data Members</xsl:template>
+ <xsl:template mode="member-kind" match="@kind[ends-with(.,'-func' )]">Member Functions</xsl:template>
+ <xsl:template mode="member-kind" match="@kind[ends-with(.,'-type' )]">Types</xsl:template>
+
+
+ <xsl:template mode="section-body" match="sectiondef | innerclass | parameterlist">
+ <table>
+ <tr>
+ <th>
+ <xsl:apply-templates mode="column-1-name" select="."/>
+ </th>
+ <th>
+ <xsl:apply-templates mode="column-2-name" select="."/>
+ </th>
+ </tr>
+ <xsl:apply-templates mode="table-body" select="."/>
+ </table>
+ </xsl:template>
+
+ <xsl:template mode="column-1-name" match="*">Name</xsl:template>
+ <xsl:template mode="column-2-name" match="*">Description</xsl:template>
+
+ <xsl:template mode="column-1-name"
+ match="parameterlist[@kind = ('exception','templateparam')]">Type</xsl:template>
+
+ <xsl:template mode="column-2-name" match="parameterlist[@kind eq 'exception']">Thrown On</xsl:template>
+
+
+ <xsl:template mode="table-body" match="parameterlist">
+ <xsl:apply-templates mode="parameter-row" select="parameteritem"/>
+ </xsl:template>
+
+ <xsl:template mode="parameter-row" match="parameteritem">
+ <tr>
+ <td>
+ <code>
+ <!-- ASSUMPTION: <parameternamelist> only ever has one <parametername> child -->
+ <xsl:apply-templates select="parameternamelist/parametername/node()"/>
+ </code>
+ </td>
+ <td>
+ <xsl:apply-templates select="parameterdescription/node()"/>
+ </td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template mode="table-body" match="sectiondef[@kind eq 'enum']">
+ <xsl:apply-templates mode="enum-row" select="memberdef/enumvalue"/> <!-- Use input order for enum values -->
+ </xsl:template>
+
+ <xsl:template mode="enum-row" match="enumvalue">
+ <tr>
+ <td>
+ <code>{name}</code>
+ </td>
+ <td>
+ <xsl:apply-templates select="briefdescription, detaileddescription"/>
+ </td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template mode="table-body" match="sectiondef | innerclass">
+ <xsl:variable name="member-nodes" as="element()*">
+ <xsl:apply-templates mode="member-nodes" select="."/>
+ </xsl:variable>
+ <xsl:for-each-group select="$member-nodes" group-by="d:member-name(.)">
+ <xsl:sort select="current-grouping-key()"/>
+ <xsl:apply-templates mode="member-row" select="."/>
+ </xsl:for-each-group>
+ </xsl:template>
+
+ <xsl:template mode="member-nodes" match="innerclass | sectiondef[@kind eq 'public-type']">
+ <xsl:param name="public-types" tunnel="yes" select="()"/>
+ <xsl:sequence select="$public-types"/>
+ </xsl:template>
+
+ <xsl:template mode="member-nodes" match="sectiondef[@kind eq 'friend']">
+ <xsl:param name="friends" tunnel="yes"/>
+ <xsl:sequence select="$friends"/>
+ </xsl:template>
+
+ <xsl:template mode="member-nodes" match="sectiondef">
+ <!--
+ ASSUMPTION (for now): At least one member per section (table) must not be in a user-defined group.
+ Also, we may need a more robust mapping between a user-defined group's members and the sections
+ in which they belong. For now, we are using this partial test.
+ -->
+ <xsl:sequence select="memberdef,
+ ../sectiondef[@kind eq 'user-defined']/memberdef[(@kind||@prot||@static) =
+ current()/memberdef/(@kind||@prot||@static)]"/>
+ </xsl:template>
+
+
+ <xsl:function name="d:member-name">
+ <xsl:param name="element"/>
+ <xsl:apply-templates mode="member-name" select="$element"/>
+ </xsl:function>
+
+ <xsl:template mode="member-name" match="memberdef">
+ <xsl:sequence select="name"/>
+ </xsl:template>
+ <xsl:template mode="member-name" match="innerclass">
+ <xsl:sequence select="d:referenced-inner-class/compounddef/compoundname ! d:strip-ns(.)"/>
+ </xsl:template>
+
+
+ <xsl:template mode="member-row" match="*">
+ <tr>
+ <td>
+ <bold>
+ <ref d:refid="{@d:page-refid}">{current-grouping-key()}</ref>
+ <xsl:apply-templates mode="member-annotation" select="."/>
+ </bold>
+ </td>
+ <td>
+ <xsl:apply-templates mode="member-description" select="."/>
+ </td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template mode="member-annotation" match="*">
+ <xsl:variable name="member-name" select="current-grouping-key()"/>
+ <xsl:variable name="is-destructor" select="starts-with($member-name, '~')"/>
+ <xsl:variable name="is-constructor" select="$member-name = d:strip-ns(/doxygen/compounddef/compoundname)"/>
+ <xsl:if test="$is-destructor or $is-constructor">
+ <xsl:text>&#160;</xsl:text>
+ <role class="silver">
+ <xsl:choose>
+ <xsl:when test="$is-destructor">[destructor]</xsl:when>
+ <xsl:otherwise >[constructor]</xsl:otherwise>
+ </xsl:choose>
+ </role>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template mode="member-description" match="innerclass">
+ <xsl:apply-templates select="d:referenced-inner-class/compounddef/briefdescription"/>
+ </xsl:template>
+ <xsl:template mode="member-description" match="memberdef">
+ <xsl:variable name="descriptions" select="current-group()/briefdescription"/>
+ <!-- Pull in any overload descriptions but only if they vary -->
+ <xsl:for-each select="distinct-values($descriptions)">
+ <!-- ASSUMPTION: <briefdescription> always contains one <para> -->
+ <xsl:apply-templates select="$descriptions[. eq current()][1]/para/node()"/>
+ <xsl:if test="position() ne last()">
+ <br/>
+ <role class="silver">—</role>
+ <br/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+
+
+ <xsl:template mode="section-body" match="detaileddescription | simplesect">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template mode="section-body" match="compounddef | memberdef" priority="1">
+ <xsl:apply-templates mode="includes" select="."/>
+ <xsl:next-match/>
+ </xsl:template>
+
+ <xsl:template mode="section-body" match="compounddef">
+ <compound>
+ <xsl:apply-templates mode="normalize-params" select="templateparamlist"/>
+ <kind>{@kind}</kind>
+ <name>{d:strip-ns(compoundname)}</name>
+ <xsl:for-each select="basecompoundref[not(d:should-ignore-base(.))]
+ [not(@prot eq 'private')]">
+ <base>
+ <prot>{@prot}</prot>
+ <name>{d:strip-doc-ns(.)}</name>
+ </base>
+ </xsl:for-each>
+ </compound>
+ </xsl:template>
+
+ <xsl:template mode="section-body" match="memberdef[@kind eq 'typedef']">
+ <typedef>
+ <xsl:apply-templates mode="normalize-params" select="templateparamlist"/>
+ <xsl:apply-templates select="name, type"/>
+ </typedef>
+ <!-- Nested compounddefs were derived from refs in the typedef's type -->
+ <xsl:apply-templates select="d:referenced-typedef-class/compounddef"/>
+ </xsl:template>
+
+ <!-- Suppress the display of several aspects of referenced typedef classes -->
+
+ <!-- Don't show the briefdescription -->
+ <xsl:template match="d:referenced-typedef-class/compounddef/briefdescription"/>
+
+ <!-- Don't show the Synopsis -->
+ <xsl:template mode="section" match="d:referenced-typedef-class/compounddef"/>
+
+ <!-- Exclude the "Description" heading (only show the body) -->
+ <xsl:template mode="section" match="d:referenced-typedef-class/compounddef/detaileddescription">
+ <xsl:apply-templates mode="section-body" select="."/>
+ </xsl:template>
+
+ <!-- Don't show the includes header or footer -->
+ <xsl:template mode="includes" match="d:referenced-typedef-class/compounddef"/>
+
+
+ <xsl:template mode="section-body" match="memberdef[@kind eq 'enum']">
+ <enum>
+ <xsl:apply-templates select="name"/>
+ </enum>
+ </xsl:template>
+
+ <xsl:template mode="section-body" match="memberdef[@kind eq 'variable']">
+ <variable>
+ <xsl:apply-templates mode="modifier" select="@static[. eq 'yes']"/>
+ <xsl:apply-templates select="type, name"/>
+ <xsl:apply-templates select="initializer[count(../initializer) eq 1]"/>
+ </variable>
+ </xsl:template>
+
+ <xsl:template mode="section-body" match="memberdef[@kind = ('function','friend')]">
+ <function>
+ <xsl:apply-templates mode="normalize-params" select="templateparamlist"/>
+ <xsl:apply-templates mode="modifier" select="@static[. eq 'yes'],
+ @virt [. eq 'virtual']"/>
+ <xsl:apply-templates select="type, name"/>
+ <params>
+ <xsl:apply-templates select="param"/>
+ </params>
+ <xsl:apply-templates mode="modifier" select="@const[. eq 'yes']"/>
+ </function>
+ </xsl:template>
+
+ <!-- Extract <declname> when Doxygen hides it in the <type> -->
+ <xsl:template mode="normalize-params" match="templateparamlist/param/type[not(../declname)]
+ [starts-with(.,'class ') or
+ starts-with(.,'typename ')]"
+ priority="1">
+ <type>{substring-before(.,' ')}</type>
+ <declname>{substring-after(.,' ')}</declname>
+ </xsl:template>
+
+ <!-- Flag as error if no declname value could be found (unless the type is simply "class") -->
+ <xsl:template mode="normalize-params" match="templateparamlist/param/type[not(../declname)]
+ [not(. = 'class')]">
+ <ERROR message="param neither has a declname nor a 'class ' or 'typename ' prefix in the type"/>
+ </xsl:template>
+
+ <xsl:template mode="normalize-params" match="templateparamlist/param/defname"/>
+
+
+ <!-- We only need to keep the @file attribute -->
+ <xsl:template match="location/@*[. except ../@file]"/>
+
+ <xsl:template match="briefdescription | detaileddescription">
+ <div>
+ <xsl:apply-templates/>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="simplesect/title"/>
+
+ <!-- TODO: verify we don't need this; it was causing duplicate headings in simplesect sections
+ <xsl:template match="title">
+ <heading>
+ <xsl:apply-templates/>
+ </heading>
+ </xsl:template>
+ -->
+
+ <!-- By default, don't output an includes header or footer -->
+ <xsl:template mode="includes" match="*"/>
+
+ <!-- TODO: Review; this is meant to effect what the previous code did, but I'm not sure it captures the original intentions -->
+ <xsl:template mode="includes" match="compounddef
+ | memberdef[@kind eq 'friend' or ../../@kind eq 'namespace']
+ [not(/doxygen/@d:page-type eq 'overload-list')]">
+ <xsl:param name="is-footer"/>
+ <para>
+ <xsl:choose>
+ <xsl:when test="$is-footer">
+ <footer>
+ <xsl:apply-templates select="location"/>
+ </footer>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="location"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </para>
+ </xsl:template>
+
+ <!-- Strip the project namespace prefix from link display names
+ (matching the text node so this will still work with the strip-leading-space mode/process below) -->
+ <!-- TODO: figure out if we need anything like this (maybe not).
+ <xsl:template match="ref/text()[starts-with(.,$doc-ns)]">
+ <xsl:value-of select="d:strip-doc-ns(.)"/>
+ </xsl:template>
+ -->
+
+
+ <!-- When a <para> directly contains a mix of inline nodes and block-level elements, normalize its content -->
+ <xsl:template match="para[&BLOCK_LEVEL_ELEMENT;]">
+ <para>
+ <xsl:for-each-group select="* | text()" group-adjacent="d:is-inline(.)">
+ <xsl:apply-templates mode="capture-ranges" select="."/>
+ </xsl:for-each-group>
+ </para>
+ </xsl:template>
+
+ <xsl:function name="d:is-inline">
+ <xsl:param name="node"/>
+ <xsl:sequence select="not($node/../(&BLOCK_LEVEL_ELEMENT;)[. is $node])"/>
+ </xsl:function>
+
+ <!-- Process the block-level elements as usual -->
+ <xsl:template mode="capture-ranges" match="node()">
+ <xsl:apply-templates select="current-group()"/>
+ </xsl:template>
+
+ <!-- Wrap contiguous ranges of inline children in a nested <para> -->
+ <xsl:template mode="capture-ranges" match="node()[d:is-inline(.)]">
+ <xsl:choose>
+ <!-- But only if it has text or if the group has more than one node -->
+ <xsl:when test="normalize-space(.) or current-group()[2]">
+ <para>
+ <xsl:apply-templates mode="strip-leading-space" select="."/>
+ </para>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:next-match/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- Strip leading whitespace from the nested paragraphs to prevent eventual interpretation as a code block -->
+ <xsl:template mode="strip-leading-space" match="*">
+ <xsl:copy>
+ <xsl:apply-templates mode="#current" select="@* | node()[1]"/>
+ </xsl:copy>
+ <xsl:apply-templates mode="#current" select="following-sibling::node()[1]
+ [ancestor-or-self::node() intersect current-group()]"/>
+ </xsl:template>
+
+ <xsl:template mode="strip-leading-space" match="@*">
+ <xsl:copy/>
+ </xsl:template>
+
+ <xsl:template mode="strip-leading-space" match="text()">
+ <xsl:param name="done-stripping" tunnel="yes" select="false()"/>
+ <xsl:choose>
+ <xsl:when test="$done-stripping">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:sequence select="replace(.,'^\s+','')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:apply-templates mode="#current" select="following-sibling::node()[1]
+ [ancestor-or-self::node() intersect current-group()]">
+ <xsl:with-param name="done-stripping" select="$done-stripping or normalize-space(.)" tunnel="yes"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <xsl:template mode="#default normalize-params" match="@* | node()">
+ <xsl:copy copy-namespaces="no">
+ <xsl:apply-templates mode="#current" select="@* | node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/base-stage2.xsl b/src/boost/tools/docca/include/docca/base-stage2.xsl
new file mode 100644
index 000000000..0dee970cc
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/base-stage2.xsl
@@ -0,0 +1,278 @@
+<!DOCTYPE xsl:stylesheet [
+<!ENTITY SYNTAX_BLOCK "*[ self::compound
+ | self::function
+ | self::typedef
+ | self::enum
+ | self::variable
+ | self::overloaded-member
+ ]">
+<!ENTITY CODE_BLOCK "*[ self::computeroutput[not(ref)]
+ | self::code
+ ]">
+]>
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:d="http://github.com/vinniefalco/docca"
+ expand-text="yes">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="text"/>
+
+ <xsl:param name="DEBUG" select="false()"/>
+
+ <!-- Can be overridden in library-specific configuration -->
+ <xsl:variable name="emphasized-template-parameter-types" select="()"/>
+
+ <xsl:variable name="list-indent-width" select="4"/>
+
+ <xsl:template mode="before" match="/page">
+ <xsl:text>{$nl}</xsl:text>
+ <xsl:text>[section:{tokenize(@id,'\.')[last()]} {d:qb-escape(title)}]</xsl:text>
+ <xsl:apply-templates mode="indexterm" select="."/>
+ </xsl:template>
+
+ <xsl:template mode="indexterm" match="page"/>
+ <xsl:template mode="indexterm" match="page[@primary-index-term]"
+ >{$nl}[indexterm1 {d:qb-escape(@primary-index-term)}]{$nl}</xsl:template>
+ <xsl:template mode="indexterm" match="page[@secondary-index-term]" priority="1"
+ >{$nl}[indexterm2 {d:qb-escape(@primary-index-term)}..{
+ d:qb-escape(@secondary-index-term)}]{$nl}</xsl:template>
+
+ <!-- Title is already included in section header -->
+ <xsl:template match="/page/title"/>
+
+ <xsl:template match="heading">{$nl}[heading {.}]</xsl:template>
+
+ <!-- Sections inside tables don't render well; just display the heading text inline (e.g. "See Also") -->
+ <xsl:template match="td//heading">{$nl}{.} </xsl:template>
+
+ <xsl:template match="location">
+ <xsl:apply-templates mode="includes-template" select="."/>
+ </xsl:template>
+
+ <xsl:template match="footer/location">
+ <xsl:apply-templates mode="includes-template-footer" select="."/>
+ </xsl:template>
+
+ <xsl:template mode="before" match="&SYNTAX_BLOCK;">{$nl}```{$nl}</xsl:template>
+ <xsl:template mode="after" match="&SYNTAX_BLOCK;">{$nl}```{$nl}</xsl:template>
+
+ <!-- Merge adjacent overloaded-members into one syntax block, separated by one blank line -->
+ <xsl:template mode="after" match="overloaded-member[following-sibling::*[1]/self::overloaded-member]" priority="1"/>
+ <xsl:template mode="before" match="overloaded-member[preceding-sibling::*[1]/self::overloaded-member]" priority="1"
+ >{$nl}{$nl}</xsl:template>
+
+ <xsl:template mode="after" match="overloaded-member/type[normalize-space(.)]
+ | function/type[normalize-space(.)]">{$nl}</xsl:template>
+
+ <xsl:template mode="append" match="function">;</xsl:template>
+
+ <xsl:template mode="append" match="overloaded-member">
+ <xsl:text>;{$nl}</xsl:text>
+ <xsl:variable name="more-link" as="element()">
+ <emphasis>'''&amp;raquo;''' <ref d:refid="{ref/@d:refid}">more...</ref></emphasis>
+ </xsl:variable>
+ <xsl:text> ``</xsl:text>
+ <xsl:apply-templates select="$more-link"/>
+ <xsl:text>``</xsl:text>
+ </xsl:template>
+
+ <xsl:template priority="1"
+ match="&SYNTAX_BLOCK;//ref">``[link {$doc-ref}.{@d:refid} {d:qb-escape(.)}]``</xsl:template>
+ <xsl:template match="td[1]//ref" >[link {$doc-ref}.{@d:refid} {d:qb-escape(.)}]</xsl:template>
+ <xsl:template match="ref" >[link {$doc-ref}.{@d:refid} `{.}`]</xsl:template>
+
+ <xsl:template mode="before" match="&CODE_BLOCK;">`</xsl:template>
+ <xsl:template mode="after" match="&CODE_BLOCK;">`</xsl:template>
+
+ <xsl:template mode="before" match="enum/name">enum </xsl:template>
+
+ <xsl:template mode="before" match="typedef/name">using </xsl:template>
+ <xsl:template mode="after" match="typedef/name"> = </xsl:template>
+ <xsl:template mode="after" match="typedef/type">;</xsl:template>
+
+ <xsl:template match="type[. eq '__implementation_defined__' ]">``['implementation-defined]``</xsl:template>
+ <xsl:template match="type[. eq '__see_below__' ]">``['see-below]``</xsl:template>
+ <xsl:template match="type[. = ('__deduced__','void_or_deduced')]">``__deduced__``</xsl:template>
+
+ <xsl:template mode="before" match="variable/name | variable/initializer">{' '}</xsl:template>
+ <xsl:template mode="append" match="variable">;</xsl:template>
+
+ <xsl:template mode="after" match="compound/kind">{' '}</xsl:template>
+
+ <xsl:template mode="before" match="base[1]"> :{$nl} </xsl:template>
+ <xsl:template mode="before" match="base" >{$nl} </xsl:template>
+ <xsl:template mode="after" match="base[position() ne last()]">,</xsl:template>
+
+ <xsl:template mode="after" match="base/prot">{' '}</xsl:template>
+
+ <xsl:template mode="before" match="templateparamlist">template&lt;</xsl:template>
+ <xsl:template mode="after" match="templateparamlist">>{$nl}</xsl:template>
+
+ <xsl:template mode="before" match="param">{$nl} </xsl:template>
+ <xsl:template mode="after" match="param[position() ne last()]">,</xsl:template>
+
+ <xsl:template mode="after" match="param[declname]/type">{' '}</xsl:template>
+
+
+ <xsl:template mode="before" match="params">(</xsl:template>
+ <xsl:template mode="after" match="params">)</xsl:template>
+
+ <xsl:template match="templateparamlist/param/declname[. = $emphasized-template-parameter-types]"
+ >__{translate(.,'_','')}__</xsl:template>
+
+ <xsl:template mode="before" match="defval"> = </xsl:template>
+
+ <xsl:template mode="before" match="modifier[. eq 'const']">{' '}</xsl:template>
+ <xsl:template mode="after" match="modifier[. eq 'const']"/>
+
+ <xsl:template mode="after" match="modifier">{$nl}</xsl:template>
+
+
+ <xsl:template mode="#all" match="ERROR">[role red error.{@message}]</xsl:template>
+
+ <xsl:template mode="before" match="table">{$nl}[table </xsl:template>
+ <xsl:template mode="after" match="table">{$nl}]</xsl:template>
+
+ <!-- ASSUMPTION: table rows have either <th> or <td>, not both -->
+ <xsl:template mode="before" match="tr[th] | th">[</xsl:template>
+ <xsl:template mode="after" match="tr[th] | th">]</xsl:template>
+
+ <xsl:template mode="before" match="tr">{$nl} [</xsl:template>
+ <xsl:template mode="after" match="tr">{$nl} ]</xsl:template>
+
+ <xsl:template mode="before" match="td">{$nl} [</xsl:template>
+ <xsl:template mode="after" match="td">{$nl} ]</xsl:template>
+
+ <xsl:template mode="before" match="bold">[*</xsl:template>
+ <xsl:template mode="after" match="bold">]</xsl:template>
+
+ <xsl:template mode="before" match="emphasis">['</xsl:template>
+ <xsl:template mode="after" match="emphasis">]</xsl:template>
+
+ <xsl:template mode="before" match="role">[role {@class} </xsl:template>
+ <xsl:template mode="after" match="role">]</xsl:template>
+
+ <xsl:template mode="before" match="ulink">[@{@url} </xsl:template>
+ <xsl:template mode="after" match="ulink">]</xsl:template>
+
+ <xsl:template mode="after" match="itemizedlist | orderedlist">{$nl}</xsl:template>
+
+ <xsl:template match="listitem">
+ <xsl:text>{$nl}</xsl:text>
+ <xsl:apply-templates mode="list-item-indent" select="."/>
+ <xsl:apply-templates mode="list-item-label" select=".."/>
+ <xsl:text> </xsl:text>
+ <!-- ASSUMPTION: <para> always appears as a child of list items -->
+ <xsl:apply-templates select="para/node()"/>
+ </xsl:template>
+
+ <!-- TODO: verify this works as expected (find an example of a nested list) -->
+ <xsl:template mode="list-item-indent"
+ match="listitem">{ancestor::listitem ! (1 to $list-indent-width) ! ' '}</xsl:template>
+
+ <xsl:template mode="list-item-label" match="itemizedlist">*</xsl:template>
+ <xsl:template mode="list-item-label" match="orderedlist" >#</xsl:template>
+
+ <!-- Lists inside a table cell require the use of "explicit list tags" for proper rendering -->
+ <xsl:template match="td//itemizedlist
+ | td//orderedlist">
+ <xsl:text>[</xsl:text>
+ <xsl:apply-templates mode="explicit-list-name" select="."/>
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates mode="explicit-list-item"/>
+ <xsl:text>]</xsl:text>
+ </xsl:template>
+
+ <xsl:template mode="explicit-list-name" match="itemizedlist">itemized_list</xsl:template>
+ <xsl:template mode="explicit-list-name" match="orderedlist">ordered_list</xsl:template>
+
+ <xsl:template mode="explicit-list-item" match="listitem">
+ <xsl:text>[</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>]</xsl:text>
+ </xsl:template>
+
+ <xsl:template mode="append" match="/page/div[1]">
+ <xsl:if test="$DEBUG">
+ <xsl:text>['</xsl:text>
+ <xsl:text>[role red \[Page type: [*{/*/@type}]\]] </xsl:text>
+ <xsl:text>[role green \[[@../../doc/html/{translate($doc-ref,'.','/')}/{
+ translate(/page/@id,'.','/')}.html [role green doc_build_html]]\]] </xsl:text>
+ <xsl:text>[@../build/xml-pages/{/page/@id}.xml [role blue [*\[doxygen_page_xml\]]]]</xsl:text>
+ <xsl:text>[@../build/stage1_visualized/visualized/{/page/@id}.html [role magenta ---stage1_visualized-->]]</xsl:text>
+ <xsl:text>[@../build/stage1_visualized/results/{ /page/@id}.xml [role blue [*\[docca_page_xml\]]]]</xsl:text>
+ <xsl:text>[@../build/stage2_visualized/visualized/{/page/@id}.html [role magenta ---stage2_visualized-->]]</xsl:text>
+ <xsl:text>[@../build/stage2_visualized/results/{ /page/@id}.txt [role blue [*\[quickbook_result\]]]]</xsl:text>
+ <xsl:text>]</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template mode="before" match="para | div">{$nl}</xsl:template>
+
+ <xsl:template match="sp">{' '}</xsl:template>
+
+ <xsl:template match="linebreak">{$nl}{$nl}</xsl:template>
+
+ <xsl:template match="br">[br]</xsl:template>
+
+ <xsl:template mode="before" match="programlisting">{$nl}```{$nl}</xsl:template>
+ <xsl:template mode="after" match="programlisting" >```{$nl}</xsl:template>
+
+ <xsl:template mode="after" match="codeline">{$nl}</xsl:template>
+
+ <!-- Ignore whitespace-only text nodes -->
+ <xsl:template match="text()[not(normalize-space())]" priority="1"/>
+
+ <!-- By default, escape Quickbook markup (square brackets) -->
+ <xsl:template match="text()">
+ <xsl:sequence select="d:qb-escape(.)"/>
+ </xsl:template>
+
+ <!-- But don't escape them in these contexts -->
+ <xsl:template match="&SYNTAX_BLOCK;//text()
+ | &CODE_BLOCK;//text()
+ | programlisting//text()">
+ <!--
+ This implementation (using <xsl:sequence> returning a string, instead of <xsl:value-of>) can
+ result in a contiguous sequence of strings, which gets converted to a text node having space
+ separators between the strings. This is desirable in some cases and not in others.
+
+ TODO: Tighten the rules so that we explicitly add the spaces where we need them but otherwise
+ strip them out (probably by using <xsl:value-of> for the rules matching text nodes).
+ -->
+ <xsl:sequence select="string(.)"/>
+ </xsl:template>
+
+ <!-- Boilerplate default rules for elements -->
+ <!-- Convention of this stylesheet is to favor use of just "before" and "after"
+ and to utilize "append" (and maybe "insert") only when a distinction is needed -->
+ <xsl:template match="*" priority="10">
+ <xsl:apply-templates mode="before" select="."/>
+ <!-- enable if needed/desired
+ <xsl:apply-templates mode="insert" select="."/> -->
+ <xsl:next-match/>
+ <xsl:apply-templates mode="append" select="."/>
+ <xsl:apply-templates mode="after" select="."/>
+ </xsl:template>
+
+ <!-- Default before/after/insert/append rules are to do nothing -->
+ <xsl:template mode="before" match="*"/>
+ <!-- enable if needed/desired
+ <xsl:template mode="insert" match="*"/> -->
+ <xsl:template mode="append" match="*"/>
+ <xsl:template mode="after" match="*"/>
+
+
+ <xsl:function name="d:qb-escape">
+ <xsl:param name="string"/>
+ <xsl:sequence select="replace(
+ replace($string, '\[', '\\['),
+ '\]',
+ '\\]'
+ )"/>
+ </xsl:function>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/common.xsl b/src/boost/tools/docca/include/docca/common.xsl
new file mode 100644
index 000000000..b557b124f
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/common.xsl
@@ -0,0 +1,107 @@
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:d="http://github.com/vinniefalco/docca"
+ exclude-result-prefixes="xs d">
+
+ <xsl:variable name="nl" select="'&#xA;'"/>
+
+ <xsl:variable name="leading-ns-regex" select="'^([^:&lt;]+::)+'"/>
+
+ <xsl:function name="d:extract-ns-without-suffix">
+ <xsl:param name="name"/>
+ <xsl:sequence select="replace(d:extract-ns($name), '::$', '')"/>
+ </xsl:function>
+
+ <xsl:function name="d:extract-ns">
+ <xsl:param name="name"/>
+ <xsl:sequence select="replace($name, '('||$leading-ns-regex||').*', '$1')"/>
+ </xsl:function>
+
+ <!-- Strip all C++ namespace prefixes that come at the beginning -->
+ <xsl:function name="d:strip-ns">
+ <xsl:param name="name"/>
+ <xsl:sequence select="replace($name, $leading-ns-regex, '')"/>
+ </xsl:function>
+
+ <!-- Strip the common C++ namespace prefix for the docs as a whole -->
+ <!-- ASSUMPTION: $doc-ns is defined in the customizing stylesheet -->
+ <xsl:function name="d:strip-doc-ns">
+ <xsl:param name="name"/>
+ <xsl:sequence select="if ($name eq $doc-ns)
+ then ''
+ else replace($name, '^'||$doc-ns||'::', '')"/>
+ </xsl:function>
+
+ <xsl:function name="d:make-id">
+ <xsl:param name="name"/>
+ <xsl:sequence select="d:perform-replacements($name, $id-replacements)"/>
+ </xsl:function>
+
+ <xsl:function name="d:perform-replacements">
+ <xsl:param name="name"/>
+ <xsl:param name="replacements"/>
+ <xsl:variable name="next" select="head($replacements)"/>
+ <xsl:variable name="rest" select="tail($replacements)"/>
+ <xsl:sequence select="if (exists($next))
+ then d:perform-replacements(replace($name, $next/@pattern, $next/@with), $rest)
+ else $name"/>
+ </xsl:function>
+
+ <xsl:variable name="id-replacements" select="$additional-id-replacements, $base-id-replacements"/>
+
+ <!-- Can be overridden by a customizing stylesheet -->
+ <xsl:variable name="additional-id-replacements" as="element(replace)*" select="()"/>
+
+ <xsl:variable name="base-id-replacements" as="element(replace)+">
+ <replace pattern="::" with="__"/>
+ <replace pattern="=" with="_eq_"/>
+ <replace pattern="!" with="_not_"/>
+ <replace pattern="->" with="_arrow_"/>
+ <replace pattern="&lt;" with="_lt_"/>
+ <replace pattern=">" with="_gt_"/>
+ <replace pattern="~$" with="_bnot_"/> <!-- bitwise NOT -->
+ <replace pattern="~" with="_dtor_"/> <!-- destructor -->
+ <replace pattern="\[" with="_lb_"/>
+ <replace pattern="\]" with="_rb_"/>
+ <replace pattern="\(" with="_lp_"/>
+ <replace pattern="\)" with="_rp_"/>
+ <replace pattern="\+" with="_plus_"/>
+ <replace pattern="-" with="_minus_"/>
+ <replace pattern="\*" with="_star_"/>
+ <replace pattern="/" with="_slash_"/>
+ <replace pattern=" " with="_"/>
+ </xsl:variable>
+
+ <xsl:function name="d:cleanup-param">
+ <xsl:param name="name"/>
+ <xsl:sequence select="d:perform-replacements($name, $param-replacements)"/>
+ </xsl:function>
+
+ <xsl:function name="d:cleanup-type">
+ <xsl:param name="name"/>
+ <xsl:sequence select="d:perform-replacements($name, $type-replacements)"/>
+ </xsl:function>
+
+ <xsl:variable name="param-replacements" select="$additional-param-replacements, $base-param-replacements"/>
+
+ <!-- Can be overridden by a customizing stylesheet -->
+ <xsl:variable name="additional-param-replacements" as="element(replace)*" select="()"/>
+
+ <xsl:variable name="base-param-replacements" as="element(replace)*">
+ <!-- Reformats '*', '&', and '...' in parameters, e.g. "void const*" -->
+ <replace pattern=" \*$" with="*"/>
+ <replace pattern=" (&amp;&amp;?)(\.{{3}})?$" with="$1$2"/>
+ </xsl:variable>
+
+ <!-- NOTE: $type-replacements includes $param-replacements -->
+ <xsl:variable name="type-replacements" select="$additional-type-replacements, $base-type-replacements, $param-replacements"/>
+
+ <!-- Can be overridden by a customizing stylesheet -->
+ <xsl:variable name="additional-type-replacements" as="element(replace)*" select="()"/>
+
+ <xsl:variable name="base-type-replacements" as="element(replace)*">
+ <replace pattern="^virtual$" with=""/>
+ </xsl:variable>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/debug-friendly-quickbook.xsl b/src/boost/tools/docca/include/docca/debug-friendly-quickbook.xsl
new file mode 100644
index 000000000..4d2cb7393
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/debug-friendly-quickbook.xsl
@@ -0,0 +1,23 @@
+<!--
+ All this stylesheet does is output a .txt file for each (erroneously-but-unavoidably-named)
+ .xml file that actually contains a fragment of Quickbook content. This isn't needed for the
+ regular build, but it's useful for viewing in the browser when debugging.
+-->
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ exclude-result-prefixes="xs">
+
+ <xsl:output method="text"/>
+
+ <xsl:param name="input-dir"/>
+
+ <xsl:template match="page">
+ <xsl:variable name="input-uri" select="$input-dir||'/'||@href"/>
+ <xsl:result-document href="{replace($input-uri, '\.xml$', '.txt')}">
+ <xsl:copy-of select="unparsed-text($input-uri)"/>
+ </xsl:result-document>
+ <xsl:apply-templates select="page"/>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/extract-xml-pages.xsl b/src/boost/tools/docca/include/docca/extract-xml-pages.xsl
new file mode 100644
index 000000000..6a3721d2a
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/extract-xml-pages.xsl
@@ -0,0 +1,13 @@
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:d="http://github.com/vinniefalco/docca"
+ exclude-result-prefixes="xs d">
+
+ <xsl:import href="base-extract-xml-pages.xsl"/>
+ <xsl:import href="base-config.xsl"/>
+
+ <!-- Custom config module copied from project-specific directory -->
+ <xsl:include href="custom-overrides.xsl"/>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/stage1.xsl b/src/boost/tools/docca/include/docca/stage1.xsl
new file mode 100644
index 000000000..b1331cae9
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/stage1.xsl
@@ -0,0 +1,13 @@
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ exclude-result-prefixes="xs"
+ expand-text="yes">
+
+ <xsl:import href="base-stage1.xsl"/>
+ <xsl:import href="base-config.xsl"/>
+
+ <!-- Custom config module copied from project-specific directory -->
+ <xsl:include href="custom-overrides.xsl"/>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/include/docca/stage2.xsl b/src/boost/tools/docca/include/docca/stage2.xsl
new file mode 100644
index 000000000..6bd01b3c1
--- /dev/null
+++ b/src/boost/tools/docca/include/docca/stage2.xsl
@@ -0,0 +1,12 @@
+<xsl:stylesheet version="3.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ exclude-result-prefixes="xs">
+
+ <xsl:import href="base-stage2.xsl"/>
+ <xsl:import href="base-config.xsl"/>
+
+ <!-- Custom config module copied from project-specific directory -->
+ <xsl:include href="custom-overrides.xsl"/>
+
+</xsl:stylesheet>
diff --git a/src/boost/tools/docca/util/comparison/README.md b/src/boost/tools/docca/util/comparison/README.md
new file mode 100644
index 000000000..0c869e0d9
--- /dev/null
+++ b/src/boost/tools/docca/util/comparison/README.md
@@ -0,0 +1,28 @@
+# Docca comparison scripts
+
+The scripts in this directory help guard against docca regressions by
+comparing a previous doc build's output with the latest output
+(after normalizing/scrubbing the results to eliminate non-substantive
+changes).
+
+Probably the easiest thing to do is add this directory to your PATH
+(or create an alias to the two scripts herein).
+
+The normal sequence goes like this:
+
+1. Run a baseline build from inside your project's doc directory by invoking
+ *update-baseline-html.sh*
+2. Implement new feature or bug fix in docca (usually by updating XSLT)
+3. Run a comparison build from inside your project's doc directory by invoking
+ *build-and-compare.sh*
+4. Review the output (in diffs.txt) to make sure everything looks good and nothing broke
+5. Otherwise, fix the regression and try again!
+
+This utility can also be useful for examining the impacts of other changes
+(such as a Doxygen upgrade!).
+
+## Implementation details
+
+The file named *grep-expressions* is used to filter out all but the matching files
+that need scrubbing. The resulting files are passed to sed and updated *in situ* based
+on the commands in the file named *sed-commands*.
diff --git a/src/boost/tools/docca/util/comparison/build-and-compare.sh b/src/boost/tools/docca/util/comparison/build-and-compare.sh
new file mode 100755
index 000000000..182f5da9c
--- /dev/null
+++ b/src/boost/tools/docca/util/comparison/build-and-compare.sh
@@ -0,0 +1,24 @@
+# This script runs a build and compares the scrubbed/normalized
+# results against the scrubbed results of a previous build (run using
+# update-baseline-html.sh). It is primarily used to guard against
+# XSLT regressions in docca.
+
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
+
+! test -d htmlPREVIOUS_SCRUBBED && echo "First run update-baseline-html.sh" && exit
+
+rm -rf html_SCRUBBED
+
+echo "Running clean build..."
+b2 clean
+b2
+
+echo "Scrubbing results and storing as html_SCRUBBED..."
+cp -r html html_SCRUBBED
+cd html_SCRUBBED
+grep -rl -f ${SCRIPT_DIR}/grep-expressions . | xargs sed -i -f ${SCRIPT_DIR}/sed-commands
+
+echo "Showing diffs from previous build (stored in diffs.txt):"
+cd ..
+diff -r htmlPREVIOUS_SCRUBBED html_SCRUBBED >diffs.txt
+cat diffs.txt
diff --git a/src/boost/tools/docca/util/comparison/compare-all.sh b/src/boost/tools/docca/util/comparison/compare-all.sh
new file mode 100755
index 000000000..1a8dbd9d9
--- /dev/null
+++ b/src/boost/tools/docca/util/comparison/compare-all.sh
@@ -0,0 +1,27 @@
+cd ~/boost/tools/docca/example
+build-and-compare.sh 2>&1 &
+
+cd ~/boost/libs/static_string/doc
+build-and-compare.sh 2>&1 &
+
+cd ~/boost/libs/url/doc
+build-and-compare.sh 2>&1 &
+
+cd ~/boost/libs/json/doc
+build-and-compare.sh 2>&1 &
+
+cd ~/boost/libs/beast/doc
+build-and-compare.sh 2>&1 &
+
+wait
+
+echo "~/boost/tools/docca/example/diffs.txt:"
+cat ~/boost/tools/docca/example/diffs.txt
+echo "~/boost/libs/static_string/doc/diffs.txt:"
+cat ~/boost/libs/static_string/doc/diffs.txt
+echo "~/boost/libs/url/doc/diffs.txt:"
+cat ~/boost/libs/url/doc/diffs.txt
+echo "~/boost/libs/json/doc/diffs.txt:"
+cat ~/boost/libs/json/doc/diffs.txt
+echo "~/boost/libs/beast/doc/diffs.txt:"
+cat ~/boost/libs/beast/doc/diffs.txt
diff --git a/src/boost/tools/docca/util/comparison/grep-expressions b/src/boost/tools/docca/util/comparison/grep-expressions
new file mode 100644
index 000000000..5b47be5f6
--- /dev/null
+++ b/src/boost/tools/docca/util/comparison/grep-expressions
@@ -0,0 +1,4 @@
+<dt id="ientry-id
+<a class="indexterm" name="id
+<a name="id
+<td align="left"><p><small>Last revised:
diff --git a/src/boost/tools/docca/util/comparison/sed-commands b/src/boost/tools/docca/util/comparison/sed-commands
new file mode 100644
index 000000000..3e2da7bf3
--- /dev/null
+++ b/src/boost/tools/docca/util/comparison/sed-commands
@@ -0,0 +1,2 @@
+s/\(<dt id="ientry-id\|<a class="indexterm" name="id\|<a name="id\)[0-9]\+/\1/g
+s/\(<td align="left"><p><small>Last revised: \)[^<]\+/\1/g
diff --git a/src/boost/tools/docca/util/comparison/update-all-baselines.sh b/src/boost/tools/docca/util/comparison/update-all-baselines.sh
new file mode 100755
index 000000000..23928710c
--- /dev/null
+++ b/src/boost/tools/docca/util/comparison/update-all-baselines.sh
@@ -0,0 +1,16 @@
+cd ~/boost/tools/docca/example
+update-baseline-html.sh 2>&1 &
+
+cd ~/boost/libs/static_string/doc
+update-baseline-html.sh >build_output.txt 2>&1 &
+
+cd ~/boost/libs/url/doc
+update-baseline-html.sh >build_output.txt 2>&1 &
+
+cd ~/boost/libs/json/doc
+update-baseline-html.sh >build_output.txt 2>&1 &
+
+cd ~/boost/libs/beast/doc
+update-baseline-html.sh >build_output.txt 2>&1 &
+
+wait
diff --git a/src/boost/tools/docca/util/comparison/update-baseline-html.sh b/src/boost/tools/docca/util/comparison/update-baseline-html.sh
new file mode 100755
index 000000000..8306cfc9e
--- /dev/null
+++ b/src/boost/tools/docca/util/comparison/update-baseline-html.sh
@@ -0,0 +1,19 @@
+# This script runs a new build and moves the results so they
+# can be used as a comparison baseline against subsequent builds
+# that are run using build-and-compare.sh
+
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
+
+rm -rf htmlPREVIOUS htmlPREVIOUS_SCRUBBED
+
+echo "Running clean build..."
+b2 clean
+b2
+
+echo "Moving results to htmlPREVIOUS..."
+mv html htmlPREVIOUS
+
+echo "Scrubbing htmlPREVIOUS and storing as htmlPREVIOUS_SCRUBBED for use by build-and-compare.sh..."
+cp -r htmlPREVIOUS htmlPREVIOUS_SCRUBBED
+cd htmlPREVIOUS_SCRUBBED
+grep -rl -f ${SCRIPT_DIR}/grep-expressions . | xargs sed -i -f ${SCRIPT_DIR}/sed-commands
diff --git a/src/boost/tools/docca/util/comparison/watch-all-builds.sh b/src/boost/tools/docca/util/comparison/watch-all-builds.sh
new file mode 100755
index 000000000..cf6f9fbcd
--- /dev/null
+++ b/src/boost/tools/docca/util/comparison/watch-all-builds.sh
@@ -0,0 +1,6 @@
+tail -f \
+~/boost/tools/docca/example/build_output.txt \
+~/boost/libs/static_string/doc/build_output.txt \
+~/boost/libs/url/doc/build_output.txt \
+~/boost/libs/json/doc/build_output.txt \
+~/boost/libs/beast/doc/build_output.txt