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