• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?xml version="1.0" encoding="utf-8"?>
2<!--
3   Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
4
5   Distributed under the Boost Software License, Version 1.0.
6   (See accompanying file LICENSE_1_0.txt or copy at
7   http://www.boost.org/LICENSE_1_0.txt)
8  -->
9<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
10                xmlns:exsl="http://exslt.org/common"
11                version="1.0">
12
13  <!-- Maximum length of directory and file names is 31 characters.
14       '.html' uses 5 characters.
15       31 - 5 = 26 -->
16  <xsl:param name="boost.max.id.part.length">26</xsl:param>
17
18  <!-- Generate an ID for the entity referenced -->
19  <xsl:template name="generate.id">
20    <xsl:param name="node" select="."/>
21    <xsl:apply-templates select="$node" mode="generate.id"/>
22  </xsl:template>
23
24  <xsl:template match="*" mode="generate.id">
25    <xsl:variable name="raw.id"><xsl:call-template name="object.id"/></xsl:variable>
26    <xsl:value-of select="translate($raw.id, '.', '_')"/>
27    <xsl:text>-bb</xsl:text>
28  </xsl:template>
29
30  <xsl:template name="postfix.id">
31    <xsl:variable name="raw.id"><xsl:call-template name="object.id"/></xsl:variable>
32    <xsl:choose>
33      <xsl:when test="starts-with($raw.id, 'id-')">
34        <xsl:value-of select="translate(substring-after($raw.id, 'id-'), '.', '_')"/>
35      </xsl:when>
36      <xsl:otherwise>
37        <xsl:value-of select="$raw.id"/>
38      </xsl:otherwise>
39    </xsl:choose>
40  </xsl:template>
41
42  <xsl:template name="strip-qualifiers-non-template">
43    <xsl:param name="name"/>
44    <xsl:choose>
45      <xsl:when test="contains($name, '&gt;')">
46        <xsl:call-template name="strip-qualifiers-non-template">
47          <xsl:with-param name="name" select="substring-after($name, '&gt;')"/>
48        </xsl:call-template>
49      </xsl:when>
50      <xsl:when test="contains($name, '::')">
51        <xsl:call-template name="strip-qualifiers-non-template">
52          <xsl:with-param name="name" select="substring-after($name, '::')"/>
53        </xsl:call-template>
54      </xsl:when>
55      <xsl:otherwise>
56        <xsl:value-of select="$name"/>
57      </xsl:otherwise>
58    </xsl:choose>
59  </xsl:template>
60
61  <xsl:template name="strip-balanced">
62    <xsl:param name="name"/>
63    <xsl:param name="open" select="'&lt;'"/>
64    <xsl:param name="close" select="'&gt;'"/>
65    <xsl:param name="depth" select="0"/>
66    <xsl:choose>
67      <xsl:when test="contains($name, $open)
68                and not(contains(substring-before($name, $open), $close))">
69        <xsl:call-template name="strip-balanced">
70          <xsl:with-param name="name" select="substring-after($name, $open)"/>
71          <xsl:with-param name="open" select="$open"/>
72          <xsl:with-param name="close" select="$close"/>
73          <xsl:with-param name="depth" select="$depth + 1"/>
74        </xsl:call-template>
75      </xsl:when>
76      <xsl:when test="contains($name, $close) and ($depth &gt; 1)">
77        <xsl:call-template name="strip-balanced">
78          <xsl:with-param name="name" select="substring-after($name, $close)"/>
79          <xsl:with-param name="open" select="$open"/>
80          <xsl:with-param name="close" select="$close"/>
81          <xsl:with-param name="depth" select="$depth - 1"/>
82        </xsl:call-template>
83      </xsl:when>
84      <xsl:otherwise>
85        <xsl:value-of select="substring-after($name, $close)"/>
86      </xsl:otherwise>
87    </xsl:choose>
88  </xsl:template>
89
90  <xsl:template name="strip-qualifiers-template">
91    <xsl:param name="name"/>
92    <xsl:choose>
93      <xsl:when test="contains($name, '::')
94                and not(contains(substring-before($name, '::'), '&lt;'))">
95        <xsl:call-template name="strip-qualifiers-template">
96          <xsl:with-param name="name" select="substring-after($name, '::')"/>
97        </xsl:call-template>
98      </xsl:when>
99      <xsl:otherwise>
100        <xsl:variable name="rest">
101          <xsl:call-template name="strip-balanced">
102            <xsl:with-param name="name" select="$name"/>
103          </xsl:call-template>
104        </xsl:variable>
105        <xsl:choose>
106          <xsl:when test="$rest != ''">
107            <xsl:call-template name="strip-qualifiers-template">
108              <xsl:with-param name="name" select="$rest"/>
109            </xsl:call-template>
110          </xsl:when>
111          <xsl:otherwise>
112            <xsl:value-of select="$name"/>
113          </xsl:otherwise>
114        </xsl:choose>
115      </xsl:otherwise>
116    </xsl:choose>
117  </xsl:template>
118
119  <!-- Strip the qualifiers off a qualified name and return the unqualified
120       name. For instance, "boost::python::function" would become just
121       "function".
122       Must handle ns::foo                    -> foo
123       Must handle ns::foo<bar::baz>          -> foo<bar::baz>
124       Must handle ns::foo<bar::baz>::nested  -> nested
125       Must handle ns::foo<x>::bar<y>         -> bar<y> -->
126  <xsl:template name="strip-qualifiers">
127    <xsl:param name="name"/>
128    <xsl:choose>
129      <xsl:when test="substring($name, string-length($name)) = '&gt;'">
130        <xsl:call-template name="strip-qualifiers-template">
131          <xsl:with-param name="name" select="$name"/>
132        </xsl:call-template>
133      </xsl:when>
134      <xsl:otherwise>
135        <xsl:call-template name="strip-qualifiers-non-template">
136          <xsl:with-param name="name" select="$name"/>
137        </xsl:call-template>
138      </xsl:otherwise>
139    </xsl:choose>
140  </xsl:template>
141
142  <!-- Build the fully-qualified id of the given node -->
143  <xsl:template name="fully-qualified-id">
144    <xsl:param name="node"/>
145
146    <xsl:apply-templates select="$node" mode="fully-qualified-name">
147      <xsl:with-param name="is.id" select="true()"/>
148    </xsl:apply-templates>
149  </xsl:template>
150
151  <!-- Build the fully-qualified name of the given node -->
152  <xsl:template name="fully-qualified-name">
153    <xsl:param name="node"/>
154    <xsl:apply-templates select="$node" mode="fully-qualified-name"/>
155  </xsl:template>
156
157  <!-- Hack to make the node we are building the current node so that the
158       ancestor:: syntax will work -->
159  <xsl:template match="*" mode="fully-qualified-name">
160    <xsl:param name="is.id" select="false()" />
161    <xsl:call-template name="build-fully-qualified-name">
162      <xsl:with-param name="is.id" select="$is.id"/>
163    </xsl:call-template>
164  </xsl:template>
165
166  <!-- The real routine that builds a fully-qualified name for the current
167       node. -->
168  <xsl:template name="build-fully-qualified-name">
169    <xsl:param name="is.id" select="false()" />
170
171    <!-- Determine the set of ancestor namespaces -->
172    <xsl:variable name="ancestors"
173      select="ancestor::namespace|
174                  ancestor::class|ancestor::struct|ancestor::union|
175                  ancestor::class-specialization|ancestor::struct-specialization|ancestor::union-specialization"/>
176
177    <xsl:for-each select="$ancestors">
178      <xsl:apply-templates select="." mode="fast-print-id-part">
179        <xsl:with-param name="is.id" select="$is.id"/>
180      </xsl:apply-templates>
181      <xsl:choose>
182        <xsl:when test="$is.id"><xsl:text>.</xsl:text></xsl:when>
183        <xsl:otherwise><xsl:text>::</xsl:text></xsl:otherwise>
184      </xsl:choose>
185    </xsl:for-each>
186    <xsl:apply-templates select="." mode="fast-print-id-part">
187      <xsl:with-param name="is.id" select="$is.id"/>
188    </xsl:apply-templates>
189  </xsl:template>
190
191  <xsl:variable name="elements-with-ids">
192    <xsl:apply-templates select="namespace|class|struct|union|class-specialization|struct-specialization|union-specialization"
193                         mode="preprocess-ids"/>
194  </xsl:variable>
195
196  <xsl:variable name="fast-elements" select="exsl:node-set($elements-with-ids)"/>
197
198  <xsl:template match="*" mode="preprocess-ids">
199    <element>
200      <xsl:attribute name="id">
201        <xsl:value-of select="generate-id()"/>
202      </xsl:attribute>
203      <xsl:attribute name="part-id">
204        <xsl:call-template name="print-id-part"/>
205      </xsl:attribute>
206    </element>
207  </xsl:template>
208
209  <xsl:template name="print-id-part">
210    <xsl:apply-templates select="." mode="print-id-part"/>
211  </xsl:template>
212
213  <xsl:template match="*" mode="fast-print-id-part">
214    <xsl:param name="is.id"/>
215    <xsl:choose>
216      <xsl:when test="not($is.id)">
217        <xsl:apply-templates select="." mode="print-name"/>
218      </xsl:when>
219      <xsl:when test="$fast-elements[@id=generate-id()]">
220        <xsl:value-of select="$fast-elements[@id=generate-id()]/@part-id"/>
221      </xsl:when>
222      <xsl:otherwise>
223        <xsl:apply-templates select="." mode="print-id-part">
224          <xsl:with-param name="is.id" select="$is.id"/>
225        </xsl:apply-templates>
226      </xsl:otherwise>
227    </xsl:choose>
228  </xsl:template>
229
230  <!-- Print the part of a fully qualified name for a single element -->
231  <xsl:template match="*" mode="print-id-part">
232    <xsl:param name="is.id"/>
233
234    <xsl:variable name="part">
235      <xsl:apply-templates select="." mode="print-name"/>
236    </xsl:variable>
237
238    <xsl:variable name="unique-name">
239      <xsl:apply-templates select="." mode="unique.name"/>
240    </xsl:variable>
241
242    <xsl:choose>
243      <xsl:when test=
244        "$is.id and (
245          string-length($part) &gt; $boost.max.id.part.length or
246          $unique-name = 0 or
247          translate($part, '.&lt;&gt;;\:*?&quot;| ', '') != $part
248        )">
249        <xsl:variable name="normalized" select="translate(normalize-space(translate($part, '.&lt;&gt;;\:*?&quot;|_', '            ')), ' ', '_')"/>
250        <xsl:variable name="id"><xsl:call-template name="postfix.id"/></xsl:variable>
251        <xsl:value-of select =
252          "concat(
253            substring($normalized, 1, $boost.max.id.part.length - string-length($id) - 1),
254            concat('_', $id))"/>
255      </xsl:when>
256      <xsl:otherwise>
257        <xsl:value-of select="$part"/>
258      </xsl:otherwise>
259    </xsl:choose>
260  </xsl:template>
261
262  <!-- Override this if an id might not be unique -->
263  <xsl:template match="*" mode="unique.name">
264    <xsl:value-of select="1"/>
265  </xsl:template>
266
267  <xsl:template match="function|overloaded-function" mode="unique.name">
268    <xsl:variable name="func-name">
269      <xsl:call-template name="fully-qualified-name">
270        <xsl:with-param name="node" select="."/>
271      </xsl:call-template>
272    </xsl:variable>
273
274    <!-- Count the number of elements with the same qualified name -->
275    <xsl:variable name="count-elements">
276      <xsl:for-each select="key('named-entities', translate(@name, $uppercase-letters, $lowercase-letters))">
277        <xsl:variable name="other-name">
278          <xsl:call-template name="fully-qualified-name">
279            <xsl:with-param name="node" select="."/>
280          </xsl:call-template>
281        </xsl:variable>
282        <xsl:if test="$func-name = $other-name">
283          <xsl:text> </xsl:text>
284        </xsl:if>
285      </xsl:for-each>
286    </xsl:variable>
287
288    <xsl:value-of select="number(string-length($count-elements) = 1)"/>
289  </xsl:template>
290
291  <!-- Print the name of the current node -->
292  <xsl:template match="*" mode="print-name">
293    <xsl:value-of select="@name"/>
294  </xsl:template>
295
296  <xsl:template match="template-arg" mode="print-name">
297    <xsl:if test="position() &gt; 1">
298      <xsl:text>, </xsl:text>
299    </xsl:if>
300    <xsl:value-of select="text()"/>
301    <xsl:if test="@pack=1">
302      <xsl:text>...</xsl:text>
303    </xsl:if>
304  </xsl:template>
305
306  <xsl:template
307      match="struct-specialization|class-specialization|union-specialization"
308      mode="print-name">
309    <xsl:value-of select="@name"/>
310    <xsl:text>&lt;</xsl:text>
311    <xsl:apply-templates select="specialization/template-arg" mode="print-name"/>
312    <xsl:text>&gt;</xsl:text>
313  </xsl:template>
314
315  <xsl:template name="concat-directives">
316    <xsl:param name="directives"/>
317    <xsl:for-each select="$directives">
318      <xsl:apply-templates select="." mode="print-name"/>
319      <xsl:text>::</xsl:text>
320    </xsl:for-each>
321  </xsl:template>
322
323  <xsl:template name="find-nodes-matching-name">
324    <!-- The name we are looking for -->
325    <xsl:param name="name"/>
326
327    <!-- The context in which this name occurs -->
328    <xsl:param name="context"/>
329
330    <!-- The node that we are checking against -->
331    <xsl:param name="nodes"/>
332
333    <!-- The set of using directives for this context node -->
334    <xsl:variable name="directives"
335      select="$context/ancestor::*/using-namespace |
336                  $context/ancestor::namespace |
337                  $context/ancestor::*/using-class |
338                  $context/ancestor::class |
339                  $context/ancestor::struct"/>
340
341    <xsl:variable name="directives-str">
342      <xsl:call-template name="concat-directives">
343        <xsl:with-param name="directives" select="$directives"/>
344      </xsl:call-template>
345    </xsl:variable>
346
347    <xsl:apply-templates select="$nodes" mode="generate-cxx-links">
348      <xsl:with-param name="name" select="$name"/>
349      <xsl:with-param name="directives-str" select="$directives-str"/>
350    </xsl:apply-templates>
351  </xsl:template>
352
353  <xsl:template match="*" mode="generate-cxx-links">
354    <xsl:param name="name"/>
355    <xsl:param name="directives-str"/>
356
357    <xsl:variable name="node-name">
358      <xsl:call-template name="fully-qualified-name">
359        <xsl:with-param name="node" select="."/>
360      </xsl:call-template>
361    </xsl:variable>
362
363    <xsl:variable name="leading-chars"
364                  select="string-length($node-name) - string-length($name)"/>
365
366    <!-- Check if this node matches any visible namespace -->
367    <xsl:if test="string-length($node-name) &gt;= string-length($name) and
368                  substring($node-name, $leading-chars + 1,
369                                        string-length($name)) = $name">
370      <xsl:variable name="qualifiers"
371                    select="substring($node-name, 1, $leading-chars)"/>
372      <xsl:if test="contains($directives-str, $qualifiers)">
373        <xsl:variable name="myid">
374          <xsl:call-template name="generate.id">
375            <xsl:with-param name="node" select="."/>
376          </xsl:call-template>
377        </xsl:variable>
378        <cxx-link-helper>
379          <xsl:attribute name="id">
380            <xsl:value-of select="$myid"/>
381          </xsl:attribute>
382          <xsl:attribute name="namespace">
383            <xsl:value-of select="$qualifiers"/>
384          </xsl:attribute>
385          <xsl:text>random text</xsl:text>
386        </cxx-link-helper>
387      </xsl:if>
388    </xsl:if>
389  </xsl:template>
390
391  <xsl:template name="cxx-link-name">
392    <!-- The actual lookup node -->
393    <xsl:param name="lookup"/>
394
395    <!-- The type of name to lookup (e.g., class) -->
396    <xsl:param name="type"/>
397
398    <!-- The name we are looking for -->
399    <xsl:param name="name"/>
400
401    <!-- The name we will display  -->
402    <xsl:param name="display-name"/>
403
404    <!-- The name we are looking for (unqualified)-->
405    <xsl:param name="unqualified-name"/>
406
407    <!-- The list of nodes that match the lookup node in both name and type -->
408    <xsl:param name="nodes"/>
409
410    <!-- Filter the nodes to leave only the ones that are in scope. -->
411    <xsl:variable name="matches1">
412      <xsl:call-template name="find-nodes-matching-name">
413        <xsl:with-param name="name" select="$name"/>
414        <xsl:with-param name="nodes" select="$nodes"/>
415        <xsl:with-param name="context" select="$lookup"/>
416      </xsl:call-template>
417    </xsl:variable>
418
419    <xsl:variable name="matches" select="exsl:node-set($matches1)//cxx-link-helper"/>
420
421    <xsl:choose>
422      <xsl:when test="count($matches) = 0">
423        <xsl:message>
424          <xsl:text>Cannot find </xsl:text>
425          <xsl:value-of select="$type"/>
426          <xsl:text> named '</xsl:text>
427          <xsl:value-of select="$name"/>
428          <xsl:text>'</xsl:text>
429        </xsl:message>
430        <xsl:value-of select="$display-name"/>
431      </xsl:when>
432      <xsl:otherwise>
433        <!-- If we found more than one, print a message and take the first -->
434        <xsl:if test="count($matches) &gt; 1">
435          <xsl:message>
436            <xsl:text>Reference to </xsl:text>
437            <xsl:value-of select="$type"/>
438            <xsl:text> '</xsl:text>
439            <xsl:value-of select="$name"/>
440            <xsl:text>' is ambiguous. Found:</xsl:text>
441            <xsl:for-each select="$matches">
442              <xsl:text>
443              Match in namespace ::</xsl:text>
444              <xsl:value-of select="@namespace"/>
445            </xsl:for-each>
446          </xsl:message>
447        </xsl:if>
448        <xsl:call-template name="internal-link">
449          <xsl:with-param name="to">
450            <xsl:value-of select="$matches[position() = 1]/@id"/>
451          </xsl:with-param>
452          <xsl:with-param name="text" select="$display-name"/>
453        </xsl:call-template>
454      </xsl:otherwise>
455    </xsl:choose>
456  </xsl:template>
457</xsl:stylesheet>
458