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