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