| <?xml version="1.0" encoding="utf-8"?> |
| <!-- |
| Copyright (c) 2002 Douglas Gregor <doug.gregor -at- 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) |
| --> |
| <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" |
| version="1.0"> |
| |
| <!-- Maximum length of directory and file names is 31 characters. |
| '.html' uses 5 characters. |
| 31 - 5 = 26 --> |
| <xsl:param name="boost.max.id.part.length">26</xsl:param> |
| |
| <!-- Generate an ID for the entity referenced --> |
| <xsl:template name="generate.id"> |
| <xsl:param name="node" select="."/> |
| <xsl:apply-templates select="$node" mode="generate.id"/> |
| </xsl:template> |
| |
| <xsl:template match="*" mode="generate.id"> |
| <xsl:value-of select="generate-id(.)"/> |
| <xsl:text>-bb</xsl:text> |
| </xsl:template> |
| |
| <xsl:template name="strip-qualifiers-non-template"> |
| <xsl:param name="name"/> |
| <xsl:choose> |
| <xsl:when test="contains($name, '>')"> |
| <xsl:call-template name="strip-qualifiers-non-template"> |
| <xsl:with-param name="name" select="substring-after($name, '>')"/> |
| </xsl:call-template> |
| </xsl:when> |
| <xsl:when test="contains($name, '::')"> |
| <xsl:call-template name="strip-qualifiers-non-template"> |
| <xsl:with-param name="name" select="substring-after($name, '::')"/> |
| </xsl:call-template> |
| </xsl:when> |
| <xsl:otherwise> |
| <xsl:value-of select="$name"/> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:template> |
| |
| <xsl:template name="strip-balanced"> |
| <xsl:param name="name"/> |
| <xsl:param name="open" select="'<'"/> |
| <xsl:param name="close" select="'>'"/> |
| <xsl:param name="depth" select="0"/> |
| <xsl:choose> |
| <xsl:when test="contains($name, $open) |
| and not(contains(substring-before($name, $open), $close))"> |
| <xsl:call-template name="strip-balanced"> |
| <xsl:with-param name="name" select="substring-after($name, $open)"/> |
| <xsl:with-param name="open" select="$open"/> |
| <xsl:with-param name="close" select="$close"/> |
| <xsl:with-param name="depth" select="$depth + 1"/> |
| </xsl:call-template> |
| </xsl:when> |
| <xsl:when test="contains($name, $close) and ($depth > 1)"> |
| <xsl:call-template name="strip-balanced"> |
| <xsl:with-param name="name" select="substring-after($name, $close)"/> |
| <xsl:with-param name="open" select="$open"/> |
| <xsl:with-param name="close" select="$close"/> |
| <xsl:with-param name="depth" select="$depth - 1"/> |
| </xsl:call-template> |
| </xsl:when> |
| <xsl:otherwise> |
| <xsl:value-of select="substring-after($name, $close)"/> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:template> |
| |
| <xsl:template name="strip-qualifiers-template"> |
| <xsl:param name="name"/> |
| <xsl:choose> |
| <xsl:when test="contains($name, '::') |
| and not(contains(substring-before($name, '::'), '<'))"> |
| <xsl:call-template name="strip-qualifiers-template"> |
| <xsl:with-param name="name" select="substring-after($name, '::')"/> |
| </xsl:call-template> |
| </xsl:when> |
| <xsl:otherwise> |
| <xsl:variable name="rest"> |
| <xsl:call-template name="strip-balanced"> |
| <xsl:with-param name="name" select="$name"/> |
| </xsl:call-template> |
| </xsl:variable> |
| <xsl:choose> |
| <xsl:when test="$rest != ''"> |
| <xsl:call-template name="strip-qualifiers-template"> |
| <xsl:with-param name="name" select="$rest"/> |
| </xsl:call-template> |
| </xsl:when> |
| <xsl:otherwise> |
| <xsl:value-of select="$name"/> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:template> |
| |
| <!-- Strip the qualifiers off a qualified name and return the unqualified |
| name. For instance, "boost::python::function" would become just |
| "function". |
| Must handle ns::foo -> foo |
| Must handle ns::foo<bar::baz> -> foo<bar::baz> |
| Must handle ns::foo<bar::baz>::nested -> nested |
| Must handle ns::foo<x>::bar<y> -> bar<y> --> |
| <xsl:template name="strip-qualifiers"> |
| <xsl:param name="name"/> |
| <xsl:choose> |
| <xsl:when test="substring($name, string-length($name)) = '>'"> |
| <xsl:call-template name="strip-qualifiers-template"> |
| <xsl:with-param name="name" select="$name"/> |
| </xsl:call-template> |
| </xsl:when> |
| <xsl:otherwise> |
| <xsl:call-template name="strip-qualifiers-non-template"> |
| <xsl:with-param name="name" select="$name"/> |
| </xsl:call-template> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:template> |
| |
| <!-- Build the fully-qualified id of the given node --> |
| <xsl:template name="fully-qualified-id"> |
| <xsl:param name="node"/> |
| |
| <xsl:apply-templates select="$node" mode="fully-qualified-name"> |
| <xsl:with-param name="is.id" select="true()"/> |
| </xsl:apply-templates> |
| </xsl:template> |
| |
| <!-- Build the fully-qualified name of the given node --> |
| <xsl:template name="fully-qualified-name"> |
| <xsl:param name="node"/> |
| <xsl:apply-templates select="$node" mode="fully-qualified-name"/> |
| </xsl:template> |
| |
| <!-- Hack to make the node we are building the current node so that the |
| ancestor:: syntax will work --> |
| <xsl:template match="*" mode="fully-qualified-name"> |
| <xsl:param name="is.id" select="false()" /> |
| <xsl:call-template name="build-fully-qualified-name"> |
| <xsl:with-param name="is.id" select="$is.id"/> |
| </xsl:call-template> |
| </xsl:template> |
| |
| <!-- The real routine that builds a fully-qualified name for the current |
| node. --> |
| <xsl:template name="build-fully-qualified-name"> |
| <xsl:param name="is.id" select="false()" /> |
| |
| <!-- The depth of qualified name element that we will print now--> |
| <xsl:param name="depth" select="1"/> |
| |
| <!-- Determine the set of ancestor namespaces --> |
| <xsl:variable name="ancestors" |
| select="ancestor::namespace| |
| ancestor::class|ancestor::struct|ancestor::union| |
| ancestor::class-specialization|ancestor::struct-specialization|ancestor::union-specialization"/> |
| |
| <xsl:choose> |
| <xsl:when test="$depth > count($ancestors)"> |
| <xsl:apply-templates select="." mode="print-id-part"> |
| <xsl:with-param name="is.id" select="$is.id"/> |
| </xsl:apply-templates> |
| </xsl:when> |
| <xsl:otherwise> |
| <xsl:if test="name($ancestors[$depth])='namespace' or |
| count(ancestor::free-function-group)=0"> |
| <xsl:apply-templates select="$ancestors[$depth]" mode="print-id-part"> |
| <xsl:with-param name="is.id" select="$is.id"/> |
| </xsl:apply-templates> |
| <xsl:choose> |
| <xsl:when test="$is.id"><xsl:text>.</xsl:text></xsl:when> |
| <xsl:otherwise><xsl:text>::</xsl:text></xsl:otherwise> |
| </xsl:choose> |
| </xsl:if> |
| <xsl:call-template name="build-fully-qualified-name"> |
| <xsl:with-param name="is.id" select="$is.id"/> |
| <xsl:with-param name="depth" select="$depth + 1"/> |
| </xsl:call-template> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:template> |
| |
| <!-- Print the part of a fully qualified name for a single element --> |
| <xsl:template match="*" mode="print-id-part"> |
| <xsl:param name="is.id"/> |
| |
| <xsl:variable name="part"> |
| <xsl:apply-templates select="." mode="print-name"/> |
| </xsl:variable> |
| |
| <xsl:variable name="unique-name"> |
| <xsl:apply-templates select="." mode="unique.name"/> |
| </xsl:variable> |
| |
| <xsl:choose> |
| <xsl:when test= |
| "$is.id and ( |
| string-length($part) > $boost.max.id.part.length or |
| $unique-name = 0 or |
| translate($part, '.<>;\:*?"| ', '') != $part |
| )"> |
| <xsl:variable name="normalized" select="translate(normalize-space(translate($part, '.<>;\:*?"|_', ' ')), ' ', '_')"/> |
| <xsl:value-of select = |
| "concat( |
| substring($normalized, 1, $boost.max.id.part.length - string-length(generate-id(.) - 1)), |
| concat('_', generate-id(.)))"/> |
| </xsl:when> |
| <xsl:otherwise> |
| <xsl:value-of select="$part"/> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:template> |
| |
| <!-- Override this if an id might not be unique --> |
| <xsl:template match="*" mode="unique.name"> |
| <xsl:value-of select="1"/> |
| </xsl:template> |
| |
| <xsl:template match="function|overloaded-function" mode="unique.name"> |
| <xsl:value-of select="number(count(key('named-entities', |
| translate(@name, $uppercase-letters, $lowercase-letters))) = 1)"/> |
| </xsl:template> |
| |
| <!-- Print the name of the current node --> |
| <xsl:template match="*" mode="print-name"> |
| <xsl:value-of select="@name"/> |
| </xsl:template> |
| |
| <xsl:template match="template-arg" mode="print-name"> |
| <xsl:if test="position() > 1"> |
| <xsl:text>, </xsl:text> |
| </xsl:if> |
| <xsl:value-of select="text()"/> |
| <xsl:if test="@pack=1"> |
| <xsl:text>...</xsl:text> |
| </xsl:if> |
| </xsl:template> |
| |
| <xsl:template |
| match="struct-specialization|class-specialization|union-specialization" |
| mode="print-name"> |
| <xsl:value-of select="@name"/> |
| <xsl:text><</xsl:text> |
| <xsl:apply-templates select="specialization/template-arg" mode="print-name"/> |
| <xsl:text>></xsl:text> |
| </xsl:template> |
| |
| <xsl:template name="name-matches-node"> |
| <!-- The name we are looking for --> |
| <xsl:param name="name"/> |
| |
| <!-- The name to display --> |
| <xsl:param name="display-name" select="$name"/> |
| |
| <!-- The context in which this name occurs --> |
| <xsl:param name="context"/> |
| |
| <!-- The node that we are checking against --> |
| <xsl:param name="node"/> |
| |
| <!-- The mode we are in. Can be one of: |
| matches: emits the matches as they are found (for debugging) |
| link: link to the node that was found |
| --> |
| <xsl:param name="mode" select="'matches'"/> |
| |
| <!-- The index into the list of using directives for the context node --> |
| <xsl:param name="index" select="1"/> |
| |
| <!-- The prefix we should append to the name when checking this node --> |
| <xsl:param name="prefix" select="''"/> |
| |
| <xsl:choose> |
| <xsl:when test="count($node) > 1"> |
| <xsl:variable name="matches"> |
| <xsl:call-template name="count-matches"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="context" select="$context"/> |
| <xsl:with-param name="nodes" select="$node[position() = 1]"/> |
| </xsl:call-template> |
| </xsl:variable> |
| |
| <xsl:choose> |
| <xsl:when test="$matches = 0"> |
| <xsl:call-template name="name-matches-node"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="display-name" select="$display-name"/> |
| <xsl:with-param name="context" select="$context"/> |
| <xsl:with-param name="node" select="$node[position() > 1]"/> |
| <xsl:with-param name="mode" select="$mode"/> |
| </xsl:call-template> |
| </xsl:when> |
| <xsl:otherwise> |
| <xsl:call-template name="name-matches-node"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="display-name" select="$display-name"/> |
| <xsl:with-param name="context" select="$context"/> |
| <xsl:with-param name="node" select="$node[position() = 1]"/> |
| <xsl:with-param name="mode" select="$mode"/> |
| </xsl:call-template> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:when> |
| <xsl:when test="count($node) = 1"> |
| <!-- The fully-qualified name of the node we are checking against --> |
| <xsl:variable name="fully-qualified-name"> |
| <xsl:call-template name="fully-qualified-name"> |
| <xsl:with-param name="node" select="$node"/> |
| </xsl:call-template> |
| </xsl:variable> |
| |
| <!-- The set of using directives for this context node --> |
| <xsl:variable name="directives" |
| select="$context/ancestor::*/using-namespace | |
| $context/ancestor::namespace | |
| $context/ancestor::*/using-class | |
| $context/ancestor::class | |
| $context/ancestor::struct"/> |
| |
| <!-- The name of the current directive --> |
| <xsl:variable name="this-context"> |
| <xsl:apply-templates select="$directives[$index]" mode="print-name"/> |
| </xsl:variable> |
| |
| <!-- Check if we have a match --> |
| <xsl:variable name="have-match" |
| select="$fully-qualified-name = concat($prefix, $name)"/> |
| |
| <xsl:if test="$have-match"> |
| <xsl:choose> |
| <xsl:when test="$mode='matches'"> |
| Match in namespace ::<xsl:value-of select="$prefix"/> |
| </xsl:when> |
| <xsl:when test="$mode='link'"> |
| <xsl:call-template name="internal-link"> |
| <xsl:with-param name="to"> |
| <xsl:call-template name="generate.id"> |
| <xsl:with-param name="node" select="$node"/> |
| </xsl:call-template> |
| </xsl:with-param> |
| <xsl:with-param name="text" select="$display-name"/> |
| </xsl:call-template> |
| </xsl:when> |
| </xsl:choose> |
| </xsl:if> |
| |
| <xsl:if test="(not($index > count($directives))) and |
| (not($have-match) or ($mode = 'matches'))"> |
| <xsl:variable name="first-branch"> |
| <xsl:if test="not ($prefix = '')"> |
| <!-- Recurse and append the current context node to the prefix --> |
| <xsl:call-template name="name-matches-node"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="display-name" select="$display-name"/> |
| <xsl:with-param name="context" select="$context"/> |
| <xsl:with-param name="node" select="$node"/> |
| <xsl:with-param name="mode" select="$mode"/> |
| <xsl:with-param name="index" select="$index + 1"/> |
| <xsl:with-param name="prefix" |
| select="concat($prefix, $this-context, '::')"/> |
| </xsl:call-template> |
| </xsl:if> |
| </xsl:variable> |
| |
| <xsl:choose> |
| <xsl:when test="string($first-branch) != ''"> |
| <xsl:copy-of select="$first-branch"/> |
| </xsl:when> |
| <xsl:otherwise> |
| <!-- Recurse with just the current context node --> |
| <xsl:call-template name="name-matches-node"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="display-name" select="$display-name"/> |
| <xsl:with-param name="context" select="$context"/> |
| <xsl:with-param name="node" select="$node"/> |
| <xsl:with-param name="mode" select="$mode"/> |
| <xsl:with-param name="index" select="$index + 1"/> |
| <xsl:with-param name="prefix" |
| select="concat($this-context, '::')"/> |
| </xsl:call-template> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:if> |
| </xsl:when> |
| </xsl:choose> |
| </xsl:template> |
| |
| <!-- Count the number of nodes in the set that match the given name and |
| lookup context --> |
| <xsl:template name="count-matches"> |
| <xsl:param name="name"/> |
| <xsl:param name="context"/> |
| <xsl:param name="nodes"/> |
| |
| <xsl:variable name="match-string"> |
| <xsl:for-each select="$nodes"> |
| <xsl:variable name="does-match"> |
| <xsl:call-template name="name-matches-node"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="context" select="$context"/> |
| <xsl:with-param name="node" select="."/> |
| </xsl:call-template> |
| </xsl:variable> |
| <xsl:if test="not($does-match='')">X</xsl:if> |
| </xsl:for-each> |
| </xsl:variable> |
| <xsl:value-of select="string-length($match-string)"/> |
| </xsl:template> |
| |
| <xsl:template name="cxx-link-name"> |
| <!-- The actual lookup node --> |
| <xsl:param name="lookup"/> |
| |
| <!-- The type of name to lookup (e.g., class) --> |
| <xsl:param name="type"/> |
| |
| <!-- The name we are looking for --> |
| <xsl:param name="name"/> |
| |
| <!-- The name we will display --> |
| <xsl:param name="display-name"/> |
| |
| <!-- The name we are looking for (unqualified)--> |
| <xsl:param name="unqualified-name"/> |
| |
| <!-- The list of nodes that match the lookup node in both name and type --> |
| <xsl:param name="nodes"/> |
| |
| <!-- Count the number of nodes that match --> |
| <xsl:variable name="matches"> |
| <xsl:call-template name="count-matches"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="context" select="$lookup"/> |
| <xsl:with-param name="nodes" select="$nodes"/> |
| </xsl:call-template> |
| </xsl:variable> |
| |
| <xsl:choose> |
| <xsl:when test="$matches = 0"> |
| <xsl:message> |
| <xsl:text>Cannot find </xsl:text> |
| <xsl:value-of select="$type"/> |
| <xsl:text> named '</xsl:text> |
| <xsl:value-of select="$name"/> |
| <xsl:text>'</xsl:text> |
| </xsl:message> |
| <xsl:value-of select="$display-name"/> |
| </xsl:when> |
| <xsl:when test="$matches = 1"> |
| <xsl:for-each select="$nodes"> |
| <xsl:call-template name="name-matches-node"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="display-name" select="$display-name"/> |
| <xsl:with-param name="context" select="$lookup"/> |
| <xsl:with-param name="node" select="."/> |
| <xsl:with-param name="mode" select="'link'"/> |
| </xsl:call-template> |
| </xsl:for-each> |
| </xsl:when> |
| <xsl:otherwise> |
| <xsl:message> |
| <xsl:text>Reference to </xsl:text> |
| <xsl:value-of select="$type"/> |
| <xsl:text> '</xsl:text> |
| <xsl:value-of select="$name"/> |
| <xsl:text>' is ambiguous. Found:</xsl:text> |
| <xsl:for-each select="$nodes"> |
| <xsl:call-template name="name-matches-node"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="context" select="$lookup"/> |
| <xsl:with-param name="node" select="."/> |
| <xsl:with-param name="mode" select="'matches'"/> |
| </xsl:call-template> |
| </xsl:for-each> |
| </xsl:message> |
| <xsl:call-template name="name-matches-node"> |
| <xsl:with-param name="name" select="$name"/> |
| <xsl:with-param name="display-name" select="$display-name"/> |
| <xsl:with-param name="context" select="$lookup"/> |
| <xsl:with-param name="node" select="$nodes"/> |
| <xsl:with-param name="mode" select="'link'"/> |
| </xsl:call-template> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:template> |
| </xsl:stylesheet> |