31b6de5a9274431d7c96cf515b2429788e6bb1b7
[free-sw/xcb/libxcb] / src / c-client.xsl
1 <?xml version="1.0" encoding="utf-8"?>
2 <!--
3 Copyright (C) 2004 Josh Triplett.  All Rights Reserved.
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the names of the authors or their
23 institutions shall not be used in advertising or otherwise to promote the
24 sale, use or other dealings in this Software without prior written
25 authorization from the authors.
26 -->
27 <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
28                version="1.0"
29                xmlns:e="http://exslt.org/common"
30                xmlns:func="http://exslt.org/functions"
31                xmlns:str="http://exslt.org/strings"
32                xmlns:xcb="http://xcb.freedesktop.org"
33                extension-element-prefixes="func str xcb">
34   
35   <xsl:output method="text" />
36
37   <xsl:strip-space elements="*" />
38
39   <!-- "header" or "source" -->
40   <xsl:param name="mode" />
41
42   <!-- Path to the core protocol descriptions. -->
43   <xsl:param name="base-path" />
44
45   <!-- Path to the extension protocol descriptions. -->
46   <xsl:param name="extension-path" select="$base-path" />
47
48   <xsl:variable name="h" select="$mode = 'header'" />
49   <xsl:variable name="c" select="$mode = 'source'" />
50   
51   <!-- String used to indent lines of code. -->
52   <xsl:variable name="indent-string" select="'    '" />
53
54   <xsl:variable name="ucase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
55   <xsl:variable name="lcase" select="'abcdefghijklmnopqrstuvwxyz'" />
56   <xsl:variable name="letters" select="concat($ucase, $lcase)" />
57   <xsl:variable name="digits" select="'0123456789'" />
58
59   <xsl:variable name="header" select="/xcb/@header" />
60   <xsl:variable name="ucase-header"
61                 select="translate($header,$lcase,$ucase)" />
62
63   <xsl:variable name="ext" select="/xcb/@extension-name" />
64
65   <!-- Other protocol descriptions to search for types in, after checking the
66        current protocol description. -->
67   <xsl:variable name="search-path-rtf">
68     <xsl:for-each select="/xcb/import">
69       <path><xsl:value-of select="concat($extension-path, ., '.xml')" /></path>
70     </xsl:for-each>
71   </xsl:variable>
72   <xsl:variable name="search-path" select="e:node-set($search-path-rtf)/path"/>
73
74   <xsl:variable name="root" select="/" />
75   
76   <!-- First pass: Store everything in a variable. -->
77   <xsl:variable name="pass1-rtf">
78     <xsl:apply-templates select="/" mode="pass1" />
79   </xsl:variable>
80   <xsl:variable name="pass1" select="e:node-set($pass1-rtf)" />
81   
82   <xsl:template match="xcb" mode="pass1">
83     <xcb>
84       <xsl:copy-of select="@*" />
85       <xsl:if test="$ext">
86         <constant type="xcb_extension_t" name="{xcb:xcb-prefix()}_id">
87           <xsl:attribute name="value">{ "<xsl:value-of select="@extension-xname" />" }</xsl:attribute>
88         </constant>
89       </xsl:if>
90       <xsl:apply-templates mode="pass1" />
91     </xcb>
92   </xsl:template>
93
94   <func:function name="xcb:xcb-prefix">
95     <xsl:param name="name" />
96     <func:result>
97       <xsl:text>xcb</xsl:text>
98       <xsl:choose>
99         <xsl:when test="/xcb/@extension-name = 'RandR'">
100           <xsl:text>_randr</xsl:text>
101         </xsl:when>
102         <xsl:when test="/xcb/@extension-name = 'ScreenSaver'">
103           <xsl:text>_screensaver</xsl:text>
104         </xsl:when>
105         <xsl:when test="/xcb/@extension-name = 'XF86Dri'">
106           <xsl:text>_xf86dri</xsl:text>
107         </xsl:when>
108         <xsl:when test="/xcb/@extension-name = 'XFixes'">
109           <xsl:text>_xfixes</xsl:text>
110         </xsl:when>
111         <xsl:when test="/xcb/@extension-name = 'XvMC'">
112           <xsl:text>_xvmc</xsl:text>
113         </xsl:when>
114         <xsl:when test="/xcb/@extension-name">
115           <xsl:text>_</xsl:text>
116           <xsl:call-template name="camelcase-to-underscore">
117             <xsl:with-param name="camelcase" select="/xcb/@extension-name" />
118           </xsl:call-template>
119         </xsl:when>
120         <xsl:otherwise>
121         </xsl:otherwise>
122       </xsl:choose>
123       <xsl:if test="$name">
124         <xsl:text>_</xsl:text>
125         <xsl:call-template name="camelcase-to-underscore">
126           <xsl:with-param name="camelcase" select="$name" />
127         </xsl:call-template>
128       </xsl:if>
129     </func:result>
130   </func:function>
131
132   <func:function name="xcb:lowercase">
133     <xsl:param name="name" />
134     <func:result>
135       <xsl:call-template name="camelcase-to-underscore">
136         <xsl:with-param name="camelcase" select="$name" />
137       </xsl:call-template>
138     </func:result>
139   </func:function>
140
141   <func:function name="xcb:get-char-void">
142     <xsl:param name="name" />
143     <xsl:variable name="ctype" select="substring-before($name, '_t')" />
144     <func:result>
145       <xsl:choose>
146         <xsl:when test="$ctype = 'char' or $ctype = 'void' or $ctype = 'float' or $ctype = 'double'">
147           <xsl:value-of select="$ctype" />    
148         </xsl:when>
149         <xsl:otherwise>
150           <xsl:value-of select="$name" />
151         </xsl:otherwise>
152       </xsl:choose>
153     </func:result>
154   </func:function>
155
156   <func:function name="xcb:remove-void">
157     <xsl:param name="name" />
158     <xsl:variable name="ctype" select="substring-before($name, '_t')" />
159     <func:result>
160       <xsl:choose>
161         <xsl:when test="$ctype = 'char' or $ctype = 'void' or $ctype = 'float' or $ctype = 'double'">
162           <xsl:choose>
163             <xsl:when test="$ctype = 'void'">
164               <xsl:text>char</xsl:text>
165             </xsl:when>
166             <xsl:otherwise>
167               <xsl:value-of select="$ctype" />
168             </xsl:otherwise>
169           </xsl:choose>
170         </xsl:when>
171         <xsl:otherwise>
172           <xsl:value-of select="$name" />
173         </xsl:otherwise>
174       </xsl:choose>
175     </func:result>
176   </func:function>
177
178   <!-- split camel case into words and insert underscore -->
179   <xsl:template name="camelcase-to-underscore">
180     <xsl:param name="camelcase"/>
181     <xsl:choose>
182       <xsl:when test="$camelcase='CHAR2B' or $camelcase='INT64'
183                       or $camelcase='FLOAT32' or $camelcase='FLOAT64'
184                       or $camelcase='BOOL32' or $camelcase='STRING8'
185                       or $camelcase='Family_DECnet'">
186         <xsl:value-of select="translate($camelcase, $ucase, $lcase)"/>
187       </xsl:when>
188       <xsl:otherwise>
189         <xsl:for-each select="str:split($camelcase, '')">
190           <xsl:variable name="a" select="."/>
191           <xsl:variable name="b" select="following::*[1]"/>
192           <xsl:variable name="c" select="following::*[2]"/>
193           <xsl:value-of select="translate(., $ucase, $lcase)"/>
194           <xsl:if test="($b and contains($lcase, $a) and contains($ucase, $b))
195                         or ($b and contains($digits, $a)
196                             and contains($letters, $b))
197                         or ($b and contains($letters, $a)
198                             and contains($digits, $b))
199                         or ($c and contains($ucase, $a)
200                             and contains($ucase, $b)
201                             and contains($lcase, $c))">
202             <xsl:text>_</xsl:text>
203           </xsl:if>
204         </xsl:for-each>
205       </xsl:otherwise>
206     </xsl:choose>
207   </xsl:template>
208
209   <!-- Modify names that conflict with C++ keywords by prefixing them with an
210        underscore.  If the name parameter is not specified, it defaults to the
211        value of the name attribute on the context node. -->
212   <xsl:template name="canonical-var-name">
213     <xsl:param name="name" select="@name" />
214     <xsl:if test="$name='new' or $name='delete'
215                   or $name='class' or $name='operator'">
216       <xsl:text>_</xsl:text>
217     </xsl:if>
218     <xsl:value-of select="$name" />
219   </xsl:template>
220
221   <!-- List of core types, for use in canonical-type-name. -->
222   <xsl:variable name="core-types-rtf">
223     <type name="BOOL" newname="uint8" />
224     <type name="BYTE" newname="uint8" />
225     <type name="CARD8" newname="uint8" />
226     <type name="CARD16" newname="uint16" />
227     <type name="CARD32" newname="uint32" />
228     <type name="INT8" newname="int8" />
229     <type name="INT16" newname="int16" />
230     <type name="INT32" newname="int32" />
231
232     <type name="char" newname="char" />
233     <type name="void" newname="void" />
234     <type name="float" newname="float" />
235     <type name="double" newname="double" />
236   </xsl:variable>
237   <xsl:variable name="core-types" select="e:node-set($core-types-rtf)" />
238
239   <!--
240     Output the canonical name for a type.  This will be
241     xcb_{extension-containing-type-if-any}_type, wherever the type is found in
242     the search path, or just type if not found.  If the type parameter is not
243     specified, it defaults to the value of the type attribute on the context
244     node.
245   -->
246   <xsl:template name="canonical-type-name">
247     <xsl:param name="type" select="string(@type)" />
248
249     <xsl:variable name="is-unqualified" select="not(contains($type, ':'))"/>
250     <xsl:variable name="namespace" select="substring-before($type, ':')" />
251     <xsl:variable name="unqualified-type">
252       <xsl:choose>
253         <xsl:when test="$is-unqualified">
254           <xsl:value-of select="$type" />
255         </xsl:when>
256         <xsl:otherwise>
257           <xsl:value-of select="substring-after($type, ':')" />
258         </xsl:otherwise>
259       </xsl:choose>
260     </xsl:variable>
261
262     <xsl:choose>
263       <xsl:when test="$is-unqualified and $core-types/type[@name=$type]">
264         <xsl:value-of select="$core-types/type[@name=$type]/@newname" />
265       </xsl:when>
266       <xsl:otherwise>
267         <xsl:variable name="type-definitions"
268                       select="(/xcb|document($search-path)/xcb
269                               )[$is-unqualified or @header=$namespace]
270                                /*[((self::struct or self::union or self::enum
271                                     or self::xidtype or self::xidunion
272                                     or self::event or self::eventcopy
273                                     or self::error or self::errorcopy)
274                                    and @name=$unqualified-type)
275                                   or (self::typedef
276                                       and @newname=$unqualified-type)]" />
277         <xsl:choose>
278           <xsl:when test="count($type-definitions) = 1">
279             <xsl:for-each select="$type-definitions">
280               <xsl:value-of select="xcb:xcb-prefix($unqualified-type)" />
281             </xsl:for-each>
282           </xsl:when>
283           <xsl:when test="count($type-definitions) > 1">
284             <xsl:message terminate="yes">
285               <xsl:text>Multiple definitions of type "</xsl:text>
286               <xsl:value-of select="$type" />
287               <xsl:text>" found.</xsl:text>
288               <xsl:if test="$is-unqualified">
289                 <xsl:for-each select="$type-definitions">
290                   <xsl:text>
291     </xsl:text>
292                   <xsl:value-of select="concat(/xcb/@header, ':', $type)" />
293                 </xsl:for-each>
294               </xsl:if>
295             </xsl:message>
296           </xsl:when>
297           <xsl:otherwise>
298             <xsl:message terminate="yes">
299               <xsl:text>No definitions of type "</xsl:text>
300               <xsl:value-of select="$type" />
301               <xsl:text>" found</xsl:text>
302               <xsl:if test="$is-unqualified">
303                 <xsl:text>, and it is not a known core type</xsl:text>
304               </xsl:if>
305               <xsl:text>.</xsl:text>
306             </xsl:message>
307           </xsl:otherwise>
308         </xsl:choose>   
309       </xsl:otherwise>
310     </xsl:choose>
311   </xsl:template>
312   
313   <!-- Helper template for requests, that outputs the cookie type.  The
314        parameter "request" must be the request node, which defaults to the
315        context node. -->
316   <xsl:template name="cookie-type">
317     <xsl:param name="request" select="." />
318     <xsl:choose>
319       <xsl:when test="$request/reply">
320         <xsl:value-of select="xcb:xcb-prefix($request/@name)" />
321       </xsl:when>
322       <xsl:otherwise>
323         <xsl:text>xcb_void</xsl:text>
324       </xsl:otherwise>
325     </xsl:choose>
326     <xsl:text>_cookie_t</xsl:text>
327   </xsl:template>
328
329   <xsl:template name="request-function">
330     <xsl:param name="checked" />
331     <xsl:param name="req" />
332     <function>
333       <xsl:attribute name="name">
334         <xsl:value-of select="xcb:xcb-prefix($req/@name)" />
335         <xsl:if test="$checked='true' and not($req/reply)">_checked</xsl:if>
336         <xsl:if test="$checked='false' and $req/reply">_unchecked</xsl:if>
337       </xsl:attribute>
338       <xsl:attribute name="type">
339         <xsl:call-template name="cookie-type">
340           <xsl:with-param name="request" select="$req" />
341         </xsl:call-template>
342       </xsl:attribute>
343       <field type="xcb_connection_t *" name="c" />
344       <xsl:apply-templates select="$req/*[not(self::reply)]" mode="param" />
345       <do-request ref="{xcb:xcb-prefix($req/@name)}_request_t" opcode="{translate(xcb:xcb-prefix($req/@name), $lcase, $ucase)}"
346                   checked="{$checked}">
347         <xsl:if test="$req/reply">
348           <xsl:attribute name="has-reply">true</xsl:attribute>
349         </xsl:if>
350       </do-request>
351     </function>
352   </xsl:template>
353   
354   <xsl:template match="request" mode="pass1">
355     <xsl:variable name="req" select="." />
356     <xsl:if test="reply">
357       <struct name="{xcb:xcb-prefix(@name)}_cookie_t">
358         <field type="unsigned int" name="sequence" />
359       </struct>
360     </xsl:if>
361     <constant type="number" name="{xcb:xcb-prefix($req/@name)}" value="{$req/@opcode}" />
362     <struct name="{xcb:xcb-prefix(@name)}_request_t">
363       <field type="uint8_t" name="major_opcode" no-assign="true" />
364       <xsl:if test="$ext">
365         <field type="uint8_t" name="minor_opcode" no-assign="true" />
366       </xsl:if>
367       <xsl:apply-templates select="*[not(self::reply)]" mode="field" />
368       <middle>
369         <field type="uint16_t" name="length" no-assign="true" />
370       </middle>
371     </struct>
372     <xsl:call-template name="request-function">
373       <xsl:with-param name="checked" select="'true'" />
374       <xsl:with-param name="req" select="$req" />
375     </xsl:call-template>
376     <xsl:call-template name="request-function">
377       <xsl:with-param name="checked" select="'false'" />
378       <xsl:with-param name="req" select="$req" />
379     </xsl:call-template>
380     <xsl:if test="reply">
381       <struct name="{xcb:xcb-prefix(@name)}_reply_t">
382         <field type="uint8_t" name="response_type" />
383         <xsl:apply-templates select="reply/*" mode="field" />
384         <middle>
385           <field type="uint16_t" name="sequence" />
386           <field type="uint32_t" name="length" />
387         </middle>
388       </struct>
389       <iterator-functions ref="{xcb:xcb-prefix(@name)}" kind="_reply" />
390       <function type="{xcb:xcb-prefix(@name)}_reply_t *" name="{xcb:xcb-prefix(@name)}_reply">
391         <field type="xcb_connection_t *" name="c" />
392         <field name="cookie">
393           <xsl:attribute name="type">
394             <xsl:call-template name="cookie-type" />
395           </xsl:attribute>
396         </field>
397         <field type="xcb_generic_error_t **" name="e" />
398         <l>return (<xsl:value-of select="xcb:xcb-prefix(@name)" />_reply_t *)<!--
399         --> xcb_wait_for_reply(c, cookie.sequence, e);</l>
400       </function>
401     </xsl:if>
402   </xsl:template>
403
404   <xsl:template match="xidtype|xidunion" mode="pass1">
405     <typedef oldname="uint32_t" newname="{xcb:xcb-prefix(@name)}_t" />
406     <iterator ref="{xcb:xcb-prefix(@name)}" />
407     <iterator-functions ref="{xcb:xcb-prefix(@name)}" />
408   </xsl:template>
409
410   <xsl:template match="struct|union" mode="pass1">
411     <struct name="{xcb:xcb-prefix(@name)}_t">
412       <xsl:if test="self::union">
413         <xsl:attribute name="kind">union</xsl:attribute>
414       </xsl:if>
415       <xsl:apply-templates select="*" mode="field" />
416     </struct>
417     <iterator ref="{xcb:xcb-prefix(@name)}" />
418     <iterator-functions ref="{xcb:xcb-prefix(@name)}" />
419   </xsl:template>
420
421   <xsl:template match="event|eventcopy|error|errorcopy" mode="pass1">
422     <xsl:variable name="suffix">
423       <xsl:choose>
424         <xsl:when test="self::event|self::eventcopy">
425           <xsl:text>_event_t</xsl:text>
426         </xsl:when>
427         <xsl:when test="self::error|self::errorcopy">
428           <xsl:text>_error_t</xsl:text>
429         </xsl:when>
430       </xsl:choose>
431     </xsl:variable>
432     <constant type="number" name="{xcb:xcb-prefix(@name)}" value="{@number}" />
433     <xsl:choose>
434       <xsl:when test="self::event|self::error">
435         <struct name="{xcb:xcb-prefix(@name)}{$suffix}">
436           <field type="uint8_t" name="response_type" />
437           <xsl:if test="self::error">
438             <field type="uint8_t" name="error_code" />
439           </xsl:if>
440           <xsl:apply-templates select="*" mode="field" />
441           <xsl:if test="not(self::event and boolean(@no-sequence-number))">
442             <middle>
443               <field type="uint16_t" name="sequence" />
444             </middle>
445           </xsl:if>
446         </struct>
447       </xsl:when>
448       <xsl:when test="self::eventcopy|self::errorcopy">
449         <typedef newname="{xcb:xcb-prefix(@name)}{$suffix}">
450           <xsl:attribute name="oldname">
451             <xsl:call-template name="canonical-type-name">
452               <xsl:with-param name="type" select="@ref" />
453             </xsl:call-template>
454             <xsl:value-of select="$suffix" />
455           </xsl:attribute>
456         </typedef>
457       </xsl:when>
458     </xsl:choose>
459   </xsl:template>
460
461   <xsl:template match="typedef" mode="pass1">
462     <typedef>
463       <xsl:attribute name="oldname">
464         <xsl:call-template name="canonical-type-name">
465           <xsl:with-param name="type" select="@oldname" />
466         </xsl:call-template>
467         <xsl:text>_t</xsl:text>
468       </xsl:attribute>
469       <xsl:attribute name="newname">
470         <xsl:call-template name="canonical-type-name">
471           <xsl:with-param name="type" select="@newname" />
472         </xsl:call-template>
473         <xsl:text>_t</xsl:text>
474       </xsl:attribute>
475     </typedef>
476     <iterator ref="{xcb:xcb-prefix(@newname)}" />
477     <iterator-functions ref="{xcb:xcb-prefix(@newname)}" />
478   </xsl:template>
479
480   <xsl:template match="enum" mode="pass1">
481     <enum name="{xcb:xcb-prefix(@name)}_t">
482       <xsl:for-each select="item">
483         <item name="{translate(xcb:xcb-prefix(concat(../@name, concat('_', @name))), $lcase, $ucase)}">
484           <xsl:copy-of select="*" />
485         </item>
486       </xsl:for-each>
487     </enum>
488   </xsl:template>
489
490   <!--
491     Templates for processing fields.
492   -->
493
494   <xsl:template match="pad" mode="field">
495     <xsl:copy-of select="." />
496   </xsl:template>
497   
498   <xsl:template match="field|exprfield" mode="field">
499     <xsl:copy>
500       <xsl:attribute name="type">
501         <xsl:call-template name="canonical-type-name" />
502         <xsl:text>_t</xsl:text>
503       </xsl:attribute>
504       <xsl:attribute name="name">
505         <xsl:call-template name="canonical-var-name" />
506       </xsl:attribute>
507       <xsl:copy-of select="*" />
508     </xsl:copy>
509   </xsl:template>
510
511   <xsl:template match="list" mode="field">
512     <xsl:variable name="type"><!--
513       --><xsl:call-template name="canonical-type-name" />
514         <xsl:text>_t</xsl:text><!--
515     --></xsl:variable>
516     <list type="{$type}">
517       <xsl:attribute name="name">
518         <xsl:call-template name="canonical-var-name" />
519       </xsl:attribute>
520       <xsl:if test="not(parent::request) and node()
521                     and not(.//*[not(self::value or self::op)])">
522         <xsl:attribute name="fixed">true</xsl:attribute>
523       </xsl:if>
524       <!-- Handle lists with no length expressions. -->
525       <xsl:if test="not(node())">
526         <xsl:choose>
527           <!-- In a request, refer to an implicit localparam for length. -->
528           <xsl:when test="parent::request">
529             <fieldref>
530               <xsl:value-of select="concat(@name, '_len')" />
531             </fieldref>
532           </xsl:when>
533           <!-- In a reply, use the length of the reply to determine the length
534                of the list. -->
535           <xsl:when test="parent::reply">
536             <op op="/">
537               <op op="&lt;&lt;">
538                 <fieldref>length</fieldref>
539                 <value>2</value>
540               </op>
541               <function-call name="sizeof">
542                 <param><xsl:value-of select="$type" /></param>
543               </function-call>
544             </op>
545           </xsl:when>
546           <!-- Other cases generate an error. -->
547           <xsl:otherwise>
548             <xsl:message terminate="yes"><!--
549               -->Encountered a list with no length expresssion outside a<!--
550               --> request or reply.<!--
551             --></xsl:message>
552           </xsl:otherwise>
553         </xsl:choose>
554       </xsl:if>
555       <xsl:copy-of select="*" />
556     </list>
557   </xsl:template>
558
559   <xsl:template match="valueparam" mode="field">
560     <field>
561       <xsl:attribute name="type">
562         <xsl:call-template name="canonical-type-name">
563           <xsl:with-param name="type" select="@value-mask-type" />
564         </xsl:call-template>
565         <xsl:text>_t</xsl:text>
566       </xsl:attribute>
567       <xsl:attribute name="name">
568         <xsl:call-template name="canonical-var-name">
569           <xsl:with-param name="name" select="@value-mask-name" />
570         </xsl:call-template>
571       </xsl:attribute>
572     </field>
573     <list type="uint32_t">
574       <xsl:attribute name="name">
575         <xsl:call-template name="canonical-var-name">
576           <xsl:with-param name="name" select="@value-list-name" />
577         </xsl:call-template>
578       </xsl:attribute>
579       <function-call name="xcb_popcount">
580         <param>
581           <fieldref>
582             <xsl:call-template name="canonical-var-name">
583               <xsl:with-param name="name" select="@value-mask-name" />
584             </xsl:call-template>
585           </fieldref>
586         </param>
587       </function-call>
588     </list>
589   </xsl:template>
590
591   <xsl:template match="field|localfield" mode="param">
592     <field>
593       <xsl:attribute name="type">
594         <xsl:call-template name="canonical-type-name" />
595         <xsl:text>_t</xsl:text>
596       </xsl:attribute>
597       <xsl:attribute name="name">
598         <xsl:call-template name="canonical-var-name" />
599       </xsl:attribute>
600     </field>
601   </xsl:template>
602
603   <xsl:template match="list" mode="param">
604     <!-- If no length expression is provided, use a CARD32 localfield. -->
605     <xsl:if test="not(node())">
606       <field type="uint32_t" name="{@name}_len" />
607     </xsl:if>
608     <field>
609       <xsl:variable name="ctype">
610         <xsl:call-template name="canonical-type-name" />
611       </xsl:variable>
612       <xsl:attribute name="type">
613         <xsl:text>const </xsl:text>
614         <xsl:call-template name="canonical-type-name" />
615         <xsl:if test="not($ctype='char') and not($ctype='void')">
616           <xsl:text>_t</xsl:text>
617         </xsl:if>
618         <xsl:text> *</xsl:text>
619       </xsl:attribute>
620       <xsl:attribute name="name">
621         <xsl:call-template name="canonical-var-name" />
622       </xsl:attribute>
623     </field>
624   </xsl:template>
625
626   <xsl:template match="valueparam" mode="param">
627     <field>
628       <xsl:attribute name="type">
629         <xsl:call-template name="canonical-type-name">
630           <xsl:with-param name="type" select="@value-mask-type" />
631         </xsl:call-template>
632         <xsl:text>_t</xsl:text>
633       </xsl:attribute>
634       <xsl:attribute name="name">
635         <xsl:call-template name="canonical-var-name">
636           <xsl:with-param name="name" select="@value-mask-name" />
637         </xsl:call-template>
638       </xsl:attribute>
639     </field>
640     <field type="const uint32_t *">
641       <xsl:attribute name="name">
642         <xsl:call-template name="canonical-var-name">
643           <xsl:with-param name="name" select="@value-list-name" />
644         </xsl:call-template>
645       </xsl:attribute>
646     </field>
647   </xsl:template>
648
649   <!-- Second pass: Process the variable. -->
650   <xsl:variable name="result-rtf">
651     <xsl:apply-templates select="$pass1/*" mode="pass2" />
652   </xsl:variable>
653   <xsl:variable name="result" select="e:node-set($result-rtf)" />
654
655   <xsl:template match="xcb" mode="pass2">
656     <xcb>
657       <xsl:copy-of select="@*" />
658       <xsl:apply-templates mode="pass2"
659                            select="constant|enum|struct|typedef|iterator" />
660       <xsl:apply-templates mode="pass2"
661                            select="function|iterator-functions" />
662     </xcb>
663   </xsl:template>
664
665   <!-- Generic rules for nodes that don't need further processing: copy node
666        with attributes, and recursively process the child nodes. -->
667   <xsl:template match="*" mode="pass2">
668     <xsl:copy>
669       <xsl:copy-of select="@*" />
670       <xsl:apply-templates mode="pass2" />
671     </xsl:copy>
672   </xsl:template>
673
674   <xsl:template match="struct" mode="pass2">
675     <xsl:if test="@kind='union' and list[not(@fixed)]">
676       <xsl:message terminate="yes">Unions must be fixed length.</xsl:message>
677     </xsl:if>
678     <struct name="{@name}">
679       <xsl:if test="@kind">
680         <xsl:attribute name="kind">
681           <xsl:value-of select="@kind" />
682         </xsl:attribute>
683       </xsl:if>
684       <!-- FIXME: This should go by size, not number of fields. -->
685       <xsl:copy-of select="node()[not(self::middle)
686                    and position() &lt; 3]" />
687       <xsl:if test="middle and (count(*[not(self::middle)]) &lt; 2)">
688         <pad bytes="{2 - count(*[not(self::middle)])}" />
689       </xsl:if>
690       <xsl:copy-of select="middle/*" />
691       <xsl:copy-of select="node()[not(self::middle) and (position() > 2)]" />
692     </struct>
693   </xsl:template>
694
695   <xsl:template match="do-request" mode="pass2">
696     <xsl:variable name="struct"
697                   select="$pass1/xcb/struct[@name=current()/@ref]" />
698
699     <xsl:variable name="num-parts" select="(1+count($struct/list))*2" />
700
701     <l>static const xcb_protocol_request_t xcb_req = {</l>
702     <indent>
703       <l>/* count */ <xsl:value-of select="$num-parts" />,</l>
704       <l>/* ext */ <xsl:choose>
705                      <xsl:when test="$ext">
706                        <xsl:text>&amp;</xsl:text>
707                        <xsl:value-of select="xcb:xcb-prefix()" />
708                        <xsl:text>_id</xsl:text>
709                      </xsl:when>
710                      <xsl:otherwise>0</xsl:otherwise>
711                    </xsl:choose>,</l>
712       <l>/* opcode */ <xsl:value-of select="@opcode" />,</l>
713       <l>/* isvoid */ <xsl:value-of select="1-boolean(@has-reply)" /></l>
714     </indent>
715     <l>};</l>
716
717     <l />
718     <l>struct iovec xcb_parts[<xsl:value-of select="$num-parts+2" />];</l>
719     <l><xsl:value-of select="../@type" /> xcb_ret;</l>
720     <l><xsl:value-of select="@ref" /> xcb_out;</l>
721
722     <l />
723     <xsl:apply-templates select="$struct//*[(self::field or self::exprfield)
724                                             and not(boolean(@no-assign))]"
725                          mode="assign" />
726
727     <l />
728     <l>xcb_parts[2].iov_base = (char *) &amp;xcb_out;</l>
729     <l>xcb_parts[2].iov_len = sizeof(xcb_out);</l>
730     <l>xcb_parts[3].iov_base = 0;</l>
731     <l>xcb_parts[3].iov_len = -xcb_parts[2].iov_len &amp; 3;</l>
732
733     <xsl:for-each select="$struct/list">
734       <l>xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_base = (char *) <!--
735       --><xsl:value-of select="@name" />;</l>
736       <l>xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_len = <!--
737       --><xsl:apply-templates mode="output-expression" />
738       <xsl:if test="not(@type = 'void_t')">
739         <xsl:text> * sizeof(</xsl:text>
740           <xsl:choose>
741           <xsl:when test="@type='char_t'">
742             <xsl:text>char</xsl:text>
743           </xsl:when>
744           <xsl:otherwise>
745             <xsl:value-of select="@type" />
746           </xsl:otherwise>
747         </xsl:choose>
748         <xsl:text>)</xsl:text>
749       </xsl:if>;</l>
750       <l>xcb_parts[<xsl:value-of select="3 + position() * 2"/>].iov_base = 0;</l>
751       <l>xcb_parts[<xsl:value-of select="3 + position() * 2"/>].iov_len = -xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_len &amp; 3;</l>
752     </xsl:for-each>
753
754     <l>xcb_ret.sequence = xcb_send_request(c, <!--
755     --><xsl:choose>
756          <xsl:when test="@checked='true'">XCB_REQUEST_CHECKED</xsl:when>
757          <xsl:otherwise>0</xsl:otherwise>
758        </xsl:choose>, xcb_parts + 2, &amp;xcb_req);</l>
759     <l>return xcb_ret;</l>
760   </xsl:template>
761
762   <xsl:template match="field" mode="assign">
763     <l>
764       <xsl:text>xcb_out.</xsl:text>
765       <xsl:value-of select="@name" />
766       <xsl:text> = </xsl:text>
767       <xsl:value-of select="@name" />
768       <xsl:text>;</xsl:text>
769     </l>
770   </xsl:template>
771
772   <xsl:template match="exprfield" mode="assign">
773     <l>
774       <xsl:text>xcb_out.</xsl:text>
775       <xsl:value-of select="@name" />
776       <xsl:text> = </xsl:text>
777       <xsl:apply-templates mode="output-expression" />
778       <xsl:text>;</xsl:text>
779     </l>
780   </xsl:template>
781
782   <xsl:template match="iterator" mode="pass2">
783     <struct name="{@ref}_iterator_t">
784       <field type="{@ref}_t *" name="data" />
785       <field type="int" name="rem" />
786       <field type="int" name="index" />
787     </struct>
788   </xsl:template>
789
790   <xsl:template match="iterator-functions" mode="pass2">
791     <xsl:variable name="ref" select="@ref" />
792     <xsl:variable name="kind" select="@kind" />
793     <xsl:variable name="struct"
794                   select="$pass1/xcb/struct[@name=concat($ref, $kind, '_t')]" />
795     <xsl:variable name="nextfields-rtf">
796       <nextfield>R + 1</nextfield>
797       <xsl:for-each select="$struct/list[not(@fixed)]">
798         <xsl:choose>
799           <xsl:when test="substring(@type, 1, 3) = 'xcb'">
800             <nextfield><xsl:value-of select="substring(@type, 1, string-length(@type)-2)" />_end(<!--
801             --><xsl:value-of select="$ref" />_<!--
802             --><xsl:value-of select="string(@name)" />_iterator(R))</nextfield>
803           </xsl:when>
804           <xsl:otherwise>
805             <nextfield><xsl:value-of select="$ref" />_<!--
806             --><xsl:value-of select="string(@name)" />_end(R)</nextfield>
807           </xsl:otherwise>
808         </xsl:choose>
809       </xsl:for-each>
810     </xsl:variable>
811     <xsl:variable name="nextfields" select="e:node-set($nextfields-rtf)" />
812     <xsl:for-each select="$struct/list[not(@fixed)]">
813       <xsl:variable name="number"
814                     select="1+count(preceding-sibling::list[not(@fixed)])" />
815       <xsl:variable name="nextfield" select="$nextfields/nextfield[$number]" />
816       <xsl:variable name="is-first"
817                     select="not(preceding-sibling::list[not(@fixed)])" />
818       <xsl:variable name="field-name" select="@name" />
819       <xsl:variable name="is-variable"
820                     select="$pass1/xcb/struct[@name=current()/@type]/list
821                             or document($search-path)/xcb
822                                /struct[concat(xcb:xcb-prefix(@name), '_t')
823                                        = current()/@type]
824                                /*[self::valueparam
825                                   or self::list[.//*[not(self::value
826                                                          or self::op)]]]" />
827       <xsl:if test="not($is-variable)">
828         <function type="{xcb:get-char-void(@type)} *" name="{$ref}_{xcb:lowercase($field-name)}">
829           <field type="const {$ref}{$kind}_t *" name="R" />
830           <xsl:choose>
831             <xsl:when test="$is-first">
832               <l>return (<xsl:value-of select="xcb:get-char-void(@type)" /> *) <!--
833               -->(<xsl:value-of select="$nextfield" />);</l>
834             </xsl:when>
835             <xsl:otherwise>
836               <l>xcb_generic_iterator_t prev = <!--
837               --><xsl:value-of select="$nextfield" />;</l>
838               <l>return (<xsl:value-of select="xcb:get-char-void(@type)" /> *) <!--
839               -->((char *) prev.data + XCB_TYPE_PAD(<!--
840               --><xsl:value-of select="xcb:get-char-void(@type)" />, prev.index));</l>
841             </xsl:otherwise>
842           </xsl:choose>
843         </function>
844       </xsl:if>
845       <function type="int" name="{$ref}_{xcb:lowercase($field-name)}_length">
846         <field type="const {$ref}{$kind}_t *" name="R" />
847         <l>return <xsl:apply-templates mode="output-expression">
848                     <xsl:with-param name="field-prefix" select="'R->'" />
849                   </xsl:apply-templates>;</l>
850       </function>
851       <xsl:choose>
852         <xsl:when test="substring(@type, 1, 3) = 'xcb'">
853           <function type="{substring(@type, 1, string-length(@type)-2)}_iterator_t" name="{$ref}_{xcb:lowercase($field-name)}_iterator">
854             <field type="const {$ref}{$kind}_t *" name="R" />
855             <l><xsl:value-of select="substring(@type, 1, string-length(@type)-2)" />_iterator_t i;</l>
856             <xsl:choose>
857               <xsl:when test="$is-first">
858                 <l>i.data = (<xsl:value-of select="@type" /> *) <!--
859                 -->(<xsl:value-of select="$nextfield" />);</l>
860               </xsl:when>
861               <xsl:otherwise>
862                 <l>xcb_generic_iterator_t prev = <!--
863                 --><xsl:value-of select="$nextfield" />;</l>
864                 <l>i.data = (<xsl:value-of select="@type" /> *) <!--
865                 -->((char *) prev.data + XCB_TYPE_PAD(<!--
866                 --><xsl:value-of select="@type" />, prev.index));</l>
867               </xsl:otherwise>
868             </xsl:choose>
869             <l>i.rem = <xsl:apply-templates mode="output-expression">
870                          <xsl:with-param name="field-prefix" select="'R->'" />
871                        </xsl:apply-templates>;</l>
872             <l>i.index = (char *) i.data - (char *) R;</l>
873             <l>return i;</l>
874           </function>
875         </xsl:when>
876         <xsl:otherwise>
877           <xsl:variable name="cast">
878             <xsl:choose>
879               <xsl:when test="@type='void'">char</xsl:when>
880               <xsl:otherwise><xsl:value-of select="@type" /></xsl:otherwise>
881             </xsl:choose>
882           </xsl:variable>
883           <function type="xcb_generic_iterator_t" name="{$ref}_{xcb:lowercase($field-name)}_end">
884             <field type="const {$ref}{$kind}_t *" name="R" />
885             <l>xcb_generic_iterator_t i;</l>
886             <xsl:choose>
887               <xsl:when test="$is-first">
888                 <l>i.data = ((<xsl:value-of select="xcb:remove-void($cast)" /> *) <!--
889                 -->(<xsl:value-of select="$nextfield" />)) + (<!--
890                 --><xsl:apply-templates mode="output-expression">
891                      <xsl:with-param name="field-prefix" select="'R->'" />
892                    </xsl:apply-templates>);</l>
893               </xsl:when>
894               <xsl:otherwise>
895                 <l>xcb_generic_iterator_t child = <!--
896                 --><xsl:value-of select="$nextfield" />;</l>
897                 <l>i.data = ((<xsl:value-of select="xcb:get-char-void($cast)" /> *) <!--
898                 -->child.data) + (<!--
899                 --><xsl:apply-templates mode="output-expression">
900                      <xsl:with-param name="field-prefix" select="'R->'" />
901                    </xsl:apply-templates>);</l>
902               </xsl:otherwise>
903             </xsl:choose>
904             <l>i.rem = 0;</l>
905             <l>i.index = (char *) i.data - (char *) R;</l>
906             <l>return i;</l>
907           </function>
908         </xsl:otherwise>
909       </xsl:choose>
910     </xsl:for-each>
911     <xsl:if test="not($kind)">
912       <function type="void" name="{$ref}_next">
913         <field type="{$ref}_iterator_t *" name="i" />
914         <xsl:choose>
915           <xsl:when test="$struct/list[not(@fixed)]">
916             <l><xsl:value-of select="$ref" />_t *R = i->data;</l>
917             <l>xcb_generic_iterator_t child = <!--
918             --><xsl:value-of select="$nextfields/nextfield[last()]" />;</l>
919             <l>--i->rem;</l>
920             <l>i->data = (<xsl:value-of select="$ref" />_t *) child.data;</l>
921             <l>i->index = child.index;</l>
922           </xsl:when>
923           <xsl:otherwise>
924             <l>--i->rem;</l>
925             <l>++i->data;</l>
926             <l>i->index += sizeof(<xsl:value-of select="$ref" />_t);</l>
927           </xsl:otherwise>
928         </xsl:choose>
929       </function>
930       <function type="xcb_generic_iterator_t" name="{$ref}_end">
931         <field type="{$ref}_iterator_t" name="i" />
932         <l>xcb_generic_iterator_t ret;</l>
933         <xsl:choose>
934           <xsl:when test="$struct/list[not(@fixed)]">
935             <l>while(i.rem > 0)</l>
936             <indent>
937               <l><xsl:value-of select="$ref" />_next(&amp;i);</l>
938             </indent>
939             <l>ret.data = i.data;</l>
940             <l>ret.rem = i.rem;</l>
941             <l>ret.index = i.index;</l>
942           </xsl:when>
943           <xsl:otherwise>
944             <l>ret.data = i.data + i.rem;</l>
945             <l>ret.index = i.index + ((char *) ret.data - (char *) i.data);</l>
946             <l>ret.rem = 0;</l>
947           </xsl:otherwise>
948         </xsl:choose>
949         <l>return ret;</l>
950       </function>
951     </xsl:if>
952   </xsl:template>
953
954   <!-- Output the results. -->
955   <xsl:template match="/">
956     <xsl:if test="not(function-available('e:node-set'))">
957       <xsl:message terminate="yes"><!--
958         -->Error: This stylesheet requires the EXSL node-set extension.<!--
959       --></xsl:message>
960     </xsl:if>
961
962     <xsl:if test="not($h) and not($c)">
963       <xsl:message terminate="yes"><!--
964         -->Error: Parameter "mode" must be "header" or "source".<!--
965       --></xsl:message>
966     </xsl:if>
967
968     <xsl:apply-templates select="$result/*" mode="output" />
969   </xsl:template>
970
971   <xsl:template match="xcb" mode="output">
972     <xsl:variable name="guard"><!--
973       -->__<xsl:value-of select="$ucase-header" />_H<!--
974     --></xsl:variable>
975
976 <xsl:text>/**
977  * @file </xsl:text><xsl:value-of select="$header" /><xsl:text>.h
978  **/
979 </xsl:text>
980 <xsl:text>
981 /**
982  * @defgroup XCB_</xsl:text><xsl:value-of select="$ext" /><xsl:text>_API XCB </xsl:text><xsl:value-of select="$ext" /><xsl:text> API
983  * @brief </xsl:text><xsl:value-of select="$ext" /><xsl:text> XCB Protocol Implementation.</xsl:text>
984 <xsl:text>
985  * @{
986  **/
987 </xsl:text>
988 <xsl:text>/*
989  * This file generated automatically from </xsl:text>
990 <xsl:value-of select="$header" /><xsl:text>.xml by c-client.xsl using XSLT.
991  * Edit at your peril.
992  */
993 </xsl:text>
994
995 <xsl:if test="$h"><xsl:text>
996 #ifndef </xsl:text><xsl:value-of select="$guard" /><xsl:text>
997 #define </xsl:text><xsl:value-of select="$guard" /><xsl:text>
998 </xsl:text>
999 #include "xcb.h"
1000 <xsl:for-each select="$root/xcb/import">
1001 <xsl:text>#include "</xsl:text><xsl:value-of select="." /><xsl:text>.h"
1002 </xsl:text>
1003 </xsl:for-each>
1004 <xsl:text>
1005 </xsl:text>
1006 </xsl:if>
1007 <xsl:if test="$h">
1008     <xsl:choose>
1009         <xsl:when test="string($ext)">
1010   <xsl:text>#define XCB_</xsl:text><xsl:value-of select="translate($ext, $lcase, $ucase)"/><xsl:text>_MAJOR_VERSION </xsl:text><xsl:value-of select="/xcb/@major-version" /><xsl:text>
1011 </xsl:text>
1012   <xsl:text>#define XCB_</xsl:text><xsl:value-of select="translate($ext, $lcase, $ucase)"/><xsl:text>_MINOR_VERSION </xsl:text><xsl:value-of select="/xcb/@minor-version" />
1013   <xsl:text>
1014   
1015 </xsl:text>
1016     </xsl:when>
1017   </xsl:choose>
1018 </xsl:if>
1019
1020 <xsl:if test="$c"><xsl:text>
1021 #include &lt;assert.h&gt;
1022 #include "xcbext.h"
1023 #include "</xsl:text><xsl:value-of select="$header" /><xsl:text>.h"
1024
1025 </xsl:text></xsl:if>
1026
1027     <xsl:apply-templates mode="output" />
1028
1029 <xsl:if test="$h">
1030 <xsl:text>
1031 /**
1032  * @}
1033  */
1034 #endif
1035 </xsl:text>
1036 </xsl:if>
1037   </xsl:template>
1038
1039   <xsl:template match="constant" mode="output">
1040     <xsl:choose>
1041       <xsl:when test="@type = 'number'">
1042         <xsl:if test="$h">
1043           <xsl:text>/** Opcode for </xsl:text><xsl:value-of select="@name"/><xsl:text>. */
1044 </xsl:text>
1045           <xsl:text>#define </xsl:text>
1046           <xsl:value-of select="translate(@name, $lcase, $ucase)" />
1047           <xsl:text> </xsl:text>
1048           <xsl:value-of select="@value" />
1049           <xsl:text>
1050
1051 </xsl:text>
1052         </xsl:if>
1053       </xsl:when>
1054       <xsl:when test="@type = 'string'">
1055         <xsl:if test="$h">
1056           <xsl:text>extern </xsl:text>
1057         </xsl:if>
1058         <xsl:text>const char </xsl:text>
1059         <xsl:value-of select="@name" />
1060         <xsl:text>[]</xsl:text>
1061         <xsl:if test="$c">
1062           <xsl:text> = "</xsl:text>
1063           <xsl:value-of select="@value" />
1064           <xsl:text>"</xsl:text>
1065         </xsl:if>
1066         <xsl:text>;
1067
1068 </xsl:text>
1069       </xsl:when>
1070       <xsl:otherwise>
1071         <xsl:if test="$h">
1072           <xsl:text>extern </xsl:text>
1073         </xsl:if>
1074         <xsl:call-template name="type-and-name" />
1075         <xsl:if test="$c">
1076           <xsl:text> = </xsl:text>
1077           <xsl:value-of select="@value" />
1078         </xsl:if>
1079         <xsl:text>;
1080
1081 </xsl:text>
1082       </xsl:otherwise>
1083     </xsl:choose>
1084   </xsl:template>
1085
1086   <xsl:template match="typedef" mode="output">
1087     <xsl:if test="$h">
1088       <xsl:text>typedef </xsl:text>
1089       <xsl:value-of select="xcb:get-char-void(@oldname)" />
1090       <xsl:text> </xsl:text>
1091       <xsl:value-of select="@newname" />
1092       <xsl:text>;
1093
1094 </xsl:text>
1095     </xsl:if>
1096   </xsl:template>
1097
1098   <xsl:template match="struct" mode="output">
1099     <xsl:if test="$h">
1100       <xsl:variable name="type-lengths">
1101         <xsl:call-template name="type-lengths">
1102           <xsl:with-param name="items" select="field/@type" />
1103         </xsl:call-template>
1104       </xsl:variable>
1105       <xsl:text>/**
1106  * @brief </xsl:text><xsl:value-of select="@name" /><xsl:text>
1107  **/
1108 </xsl:text>
1109       <xsl:text>typedef </xsl:text>
1110       <xsl:if test="not(@kind)">struct</xsl:if><xsl:value-of select="@kind" />
1111       <xsl:text> </xsl:text>
1112       <xsl:value-of select="@name" />
1113       <xsl:text> {
1114 </xsl:text>
1115       <xsl:for-each select="exprfield|field|list[@fixed]|pad">
1116         <xsl:text>    </xsl:text>
1117         <xsl:apply-templates select=".">
1118           <xsl:with-param name="type-lengths" select="$type-lengths" />
1119         </xsl:apply-templates>
1120         <xsl:text>; /**&lt; </xsl:text><xsl:text> */
1121 </xsl:text>
1122       </xsl:for-each>
1123       <xsl:text>} </xsl:text>
1124       <xsl:value-of select="@name" />
1125       <xsl:text>;
1126
1127 </xsl:text>
1128     </xsl:if>
1129   </xsl:template>
1130
1131   <xsl:template match="enum" mode="output">
1132     <xsl:if test="$h">
1133       <xsl:text>typedef enum </xsl:text>
1134       <xsl:value-of select="@name" />
1135       <xsl:text> {
1136     </xsl:text>
1137       <xsl:call-template name="list">
1138         <xsl:with-param name="separator"><xsl:text>,
1139     </xsl:text></xsl:with-param>
1140         <xsl:with-param name="items">
1141           <xsl:for-each select="item">
1142             <item>
1143               <xsl:value-of select="@name" />
1144               <xsl:if test="node()"> <!-- If there is an expression -->
1145                 <xsl:text> = </xsl:text>
1146                 <xsl:apply-templates mode="output-expression" />
1147               </xsl:if>
1148             </item>
1149           </xsl:for-each>
1150         </xsl:with-param>
1151       </xsl:call-template>
1152       <xsl:text>
1153 } </xsl:text><xsl:value-of select="@name" /><xsl:text>;
1154
1155 </xsl:text>
1156     </xsl:if>
1157   </xsl:template>
1158
1159   <xsl:template match="function" mode="output">
1160     <xsl:variable name="decl-open" select="concat(@name, ' (')" />
1161     <xsl:variable name="type-lengths">
1162       <xsl:call-template name="type-lengths">
1163         <xsl:with-param name="items" select="field/@type" />
1164       </xsl:call-template>
1165   </xsl:variable>
1166   <!-- Doxygen for functions in header. -->
1167 /*****************************************************************************
1168  **
1169  ** <xsl:value-of select="@type" />
1170  <xsl:text> </xsl:text>
1171  <xsl:value-of select="@name" />
1172  ** <xsl:call-template name="list">
1173      <xsl:with-param name="items">
1174          <xsl:for-each select="field">
1175              <item>
1176                  <xsl:text>
1177  ** @param </xsl:text>
1178                  <xsl:apply-templates select=".">
1179                      <xsl:with-param name="type-lengths" select="$type-lengths" />
1180                  </xsl:apply-templates>
1181              </item>
1182          </xsl:for-each>
1183      </xsl:with-param>
1184  </xsl:call-template>
1185  ** @returns <xsl:value-of select="@type" />
1186  **
1187  *****************************************************************************/
1188  
1189 <xsl:value-of select="@type" />
1190     <xsl:text>
1191 </xsl:text>
1192     <xsl:value-of select="$decl-open" />
1193     <xsl:call-template name="list">
1194       <xsl:with-param name="separator">
1195         <xsl:text>,
1196 </xsl:text>
1197         <xsl:call-template name="repeat">
1198           <xsl:with-param name="count" select="string-length($decl-open)" />
1199         </xsl:call-template>
1200       </xsl:with-param>
1201       <xsl:with-param name="items">
1202         <xsl:for-each select="field">
1203           <item>
1204             <xsl:apply-templates select=".">
1205               <xsl:with-param name="type-lengths" select="$type-lengths" />
1206             </xsl:apply-templates>
1207             <xsl:text>  /**&lt; */</xsl:text>
1208           </item>
1209         </xsl:for-each>
1210       </xsl:with-param>
1211     </xsl:call-template>
1212     <xsl:text>)</xsl:text>
1213
1214     <xsl:if test="$h"><xsl:text>;
1215
1216 </xsl:text></xsl:if>
1217
1218     <xsl:if test="$c">
1219       <xsl:text>
1220 {
1221 </xsl:text>
1222       <xsl:apply-templates select="l|indent" mode="function-body">
1223         <xsl:with-param name="indent" select="$indent-string" />
1224       </xsl:apply-templates>
1225       <xsl:text>}
1226
1227 </xsl:text>
1228     </xsl:if>
1229   </xsl:template>
1230
1231   <xsl:template match="l" mode="function-body">
1232     <xsl:param name="indent" />
1233     <xsl:value-of select="concat($indent, .)" /><xsl:text>
1234 </xsl:text>
1235   </xsl:template>
1236
1237   <xsl:template match="indent" mode="function-body">
1238     <xsl:param name="indent" />
1239     <xsl:apply-templates select="l|indent" mode="function-body">
1240       <xsl:with-param name="indent" select="concat($indent, $indent-string)" />
1241     </xsl:apply-templates>
1242   </xsl:template>
1243
1244   <xsl:template match="value" mode="output-expression">
1245     <xsl:value-of select="." />
1246   </xsl:template>
1247
1248   <xsl:template match="fieldref" mode="output-expression">
1249     <xsl:param name="field-prefix" />
1250     <xsl:value-of select="concat($field-prefix, .)" />
1251   </xsl:template>
1252
1253   <xsl:template match="op" mode="output-expression">
1254     <xsl:param name="field-prefix" />
1255     <xsl:text>(</xsl:text>
1256     <xsl:apply-templates select="node()[1]" mode="output-expression">
1257       <xsl:with-param name="field-prefix" select="$field-prefix" />
1258     </xsl:apply-templates>
1259     <xsl:text> </xsl:text>
1260     <xsl:value-of select="@op" />
1261     <xsl:text> </xsl:text>
1262     <xsl:apply-templates select="node()[2]" mode="output-expression">
1263       <xsl:with-param name="field-prefix" select="$field-prefix" />
1264     </xsl:apply-templates>
1265     <xsl:text>)</xsl:text>
1266   </xsl:template>
1267
1268   <xsl:template match="bit" mode="output-expression">
1269     <xsl:text>(1 &lt;&lt; </xsl:text>
1270     <xsl:value-of select="." />
1271     <xsl:text>)</xsl:text>
1272   </xsl:template>
1273
1274   <xsl:template match="function-call" mode="output-expression">
1275     <xsl:param name="field-prefix" />
1276     <xsl:value-of select="@name" />
1277     <xsl:text>(</xsl:text>
1278     <xsl:call-template name="list">
1279       <xsl:with-param name="separator" select="', '" />
1280       <xsl:with-param name="items">
1281         <xsl:for-each select="param">
1282           <item><xsl:apply-templates mode="output-expression">
1283             <xsl:with-param name="field-prefix" select="$field-prefix" />
1284           </xsl:apply-templates></item>
1285         </xsl:for-each>
1286       </xsl:with-param>
1287     </xsl:call-template>
1288     <xsl:text>)</xsl:text>
1289   </xsl:template>
1290
1291   <!-- Catch invalid elements in expressions. -->
1292   <xsl:template match="*" mode="output-expression">
1293     <xsl:message terminate="yes">
1294       <xsl:text>Invalid element in expression: </xsl:text>
1295       <xsl:value-of select="name()" />
1296     </xsl:message>
1297   </xsl:template>
1298
1299   <xsl:template match="field|exprfield">
1300     <xsl:param name="type-lengths" select="0" />
1301     <xsl:call-template name="type-and-name">
1302       <xsl:with-param name="type-lengths" select="$type-lengths" />
1303     </xsl:call-template>
1304   </xsl:template>
1305
1306   <xsl:template match="list[@fixed]">
1307     <xsl:param name="type-lengths" select="0" />
1308     <xsl:call-template name="type-and-name">
1309       <xsl:with-param name="type-lengths" select="$type-lengths" />
1310     </xsl:call-template>
1311     <xsl:text>[</xsl:text>
1312     <xsl:apply-templates mode="output-expression" />
1313     <xsl:text>]</xsl:text>
1314   </xsl:template>
1315
1316   <xsl:template match="pad">
1317     <xsl:param name="type-lengths" select="0" />
1318
1319     <xsl:variable name="padnum"><xsl:number /></xsl:variable>
1320
1321     <xsl:call-template name="type-and-name">
1322       <xsl:with-param name="type" select="'uint8_t'" />
1323       <xsl:with-param name="name">
1324         <xsl:text>pad</xsl:text>
1325         <xsl:value-of select="$padnum - 1" />
1326       </xsl:with-param>
1327       <xsl:with-param name="type-lengths" select="$type-lengths" />
1328     </xsl:call-template>
1329     <xsl:if test="@bytes > 1">
1330       <xsl:text>[</xsl:text>
1331       <xsl:value-of select="@bytes" />
1332       <xsl:text>]</xsl:text>
1333     </xsl:if>
1334   </xsl:template>
1335
1336   <!-- Output the given type and name (defaulting to the corresponding
1337        attributes of the context node), with the appropriate spacing.  The
1338        type must consist of a base type (which may contain spaces), then
1339        optionally a single space and a suffix of one or more '*' characters.
1340        If the type-lengths parameter is provided, use it to line up the base
1341        types and suffixs of the type declarations. -->
1342   <xsl:template name="type-and-name">
1343     <xsl:param name="type" select="@type" />
1344     <xsl:param name="name" select="@name" />
1345     <xsl:param name="type-lengths">
1346       <max-type-length>0</max-type-length>
1347       <max-suffix-length>0</max-suffix-length>
1348     </xsl:param>
1349     
1350     <xsl:variable name="type-lengths-ns" select="e:node-set($type-lengths)" />
1351     <xsl:variable name="min-type-length"
1352                   select="$type-lengths-ns/max-type-length" />
1353     <xsl:variable name="min-suffix-length"
1354                   select="$type-lengths-ns/max-suffix-length" />
1355
1356     <xsl:variable name="base-type">
1357       <xsl:choose>
1358         <xsl:when test="contains($type, ' *')">
1359           <xsl:value-of select="substring-before($type, ' *')" />
1360         </xsl:when>
1361         <xsl:otherwise>
1362           <xsl:value-of select="$type" />
1363         </xsl:otherwise>
1364       </xsl:choose>
1365     </xsl:variable>
1366     <xsl:variable name="suffix">
1367       <xsl:if test="contains($type, ' *')">
1368         <xsl:text>*</xsl:text>
1369         <xsl:value-of select="substring-after($type, ' *')" />
1370       </xsl:if>
1371     </xsl:variable>
1372
1373     <xsl:value-of select="$base-type" />
1374     <xsl:if test="string-length($base-type) &lt; $min-type-length">
1375       <xsl:call-template name="repeat">
1376         <xsl:with-param name="count" select="$min-type-length
1377                                              - string-length($base-type)" />
1378       </xsl:call-template>
1379     </xsl:if>
1380     <xsl:text> </xsl:text>
1381     <xsl:if test="string-length($suffix) &lt; $min-suffix-length">
1382       <xsl:call-template name="repeat">
1383         <xsl:with-param name="count" select="$min-suffix-length
1384                                              - string-length($suffix)" />
1385       </xsl:call-template>
1386     </xsl:if>
1387     <xsl:value-of select="$suffix" />
1388     <xsl:value-of select="$name" />
1389   </xsl:template>
1390
1391   <!-- Output a list with a given separator.  Empty items are skipped. -->
1392   <xsl:template name="list">
1393     <xsl:param name="separator" />
1394     <xsl:param name="items" />
1395
1396     <xsl:for-each select="e:node-set($items)/*">
1397       <xsl:value-of select="." />
1398       <xsl:if test="not(position() = last())">
1399         <xsl:value-of select="$separator" />
1400       </xsl:if>
1401     </xsl:for-each>
1402   </xsl:template>
1403
1404   <!-- Repeat a string (space by default) a given number of times. -->
1405   <xsl:template name="repeat">
1406     <xsl:param name="str" select="' '" />
1407     <xsl:param name="count" />
1408
1409     <xsl:if test="$count &gt; 0">
1410       <xsl:value-of select="$str" />
1411       <xsl:call-template name="repeat">
1412         <xsl:with-param name="str"   select="$str" />
1413         <xsl:with-param name="count" select="$count - 1" />
1414       </xsl:call-template>
1415     </xsl:if>
1416   </xsl:template>
1417
1418   <!-- Record the maximum type lengths of a set of types for use as the
1419        max-type-lengths parameter of type-and-name. -->
1420   <xsl:template name="type-lengths">
1421     <xsl:param name="items" />
1422     <xsl:variable name="type-lengths-rtf">
1423       <xsl:for-each select="$items">
1424         <item>
1425           <xsl:choose>
1426             <xsl:when test="contains(., ' *')">
1427               <xsl:value-of select="string-length(
1428                                     substring-before(., ' *'))" />
1429             </xsl:when>
1430             <xsl:otherwise>
1431               <xsl:value-of select="string-length(.)" />
1432             </xsl:otherwise>
1433           </xsl:choose>
1434         </item>
1435       </xsl:for-each>
1436     </xsl:variable>
1437     <xsl:variable name="suffix-lengths-rtf">
1438       <xsl:for-each select="$items">
1439         <item>
1440           <xsl:choose>
1441             <xsl:when test="contains(., ' *')">
1442               <xsl:value-of select="string-length(substring-after(., ' *'))
1443                                     + 1" />
1444             </xsl:when>
1445             <xsl:otherwise>
1446               <xsl:text>0</xsl:text>
1447             </xsl:otherwise>
1448           </xsl:choose>
1449         </item>
1450       </xsl:for-each>
1451     </xsl:variable>
1452     <max-type-length>
1453       <xsl:call-template name="max">
1454         <xsl:with-param name="items"
1455                         select="e:node-set($type-lengths-rtf)/*" />
1456       </xsl:call-template>
1457     </max-type-length>
1458     <max-suffix-length>
1459       <xsl:call-template name="max">
1460         <xsl:with-param name="items"
1461                         select="e:node-set($suffix-lengths-rtf)/*" />
1462       </xsl:call-template>
1463     </max-suffix-length>
1464   </xsl:template>
1465
1466   <!-- Return the maximum number in a set of numbers. -->
1467   <xsl:template name="max">
1468     <xsl:param name="items" />
1469     <xsl:choose>
1470       <xsl:when test="count($items) = 0">
1471         <xsl:text>0</xsl:text>
1472       </xsl:when>
1473       <xsl:otherwise>
1474         <xsl:variable name="head" select="number($items[1])" />
1475         <xsl:variable name="tail-max">
1476           <xsl:call-template name="max">
1477             <xsl:with-param name="items" select="$items[position() > 1]" />
1478           </xsl:call-template>
1479         </xsl:variable>
1480         <xsl:choose>
1481           <xsl:when test="$head > number($tail-max)">
1482             <xsl:value-of select="$head" />
1483           </xsl:when>
1484           <xsl:otherwise>
1485             <xsl:value-of select="$tail-max" />
1486           </xsl:otherwise>
1487         </xsl:choose>
1488       </xsl:otherwise>
1489     </xsl:choose>
1490   </xsl:template>
1491 </xsl:transform>