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