diff options
Diffstat (limited to 'libxcb/src')
-rw-r--r-- | libxcb/src/Makefile.am | 72 | ||||
-rw-r--r-- | libxcb/src/c-client.xsl | 1551 | ||||
-rw-r--r-- | libxcb/src/xcb.h | 16 | ||||
-rw-r--r-- | libxcb/src/xcb_auth.c | 4 | ||||
-rw-r--r-- | libxcb/src/xcb_conn.c | 4 | ||||
-rw-r--r-- | libxcb/src/xcb_in.c | 110 | ||||
-rw-r--r-- | libxcb/src/xcb_util.c | 25 |
7 files changed, 1708 insertions, 74 deletions
diff --git a/libxcb/src/Makefile.am b/libxcb/src/Makefile.am index 8bec61387..f0bdeaa46 100644 --- a/libxcb/src/Makefile.am +++ b/libxcb/src/Makefile.am @@ -1,14 +1,8 @@ lib_LTLIBRARIES = libxcb.la -EXTHEADERS = xproto.h \ - bigreq.h \ - xc_misc.h EXTSOURCES = xproto.c \ bigreq.c \ xc_misc.c -EXTENSION_XML = xproto.xml \ - bigreq.xml \ - xc_misc.xml AM_CFLAGS = $(CWARNFLAGS) $(NEEDED_CFLAGS) $(XDMCP_CFLAGS) libxcb_la_LIBADD = $(NEEDED_LIBS) $(XDMCP_LIBS) @@ -30,9 +24,7 @@ XCB_LIBS = libxcb.la # FIXME: find a way to autogenerate this from the XML files. -EXTHEADERS += composite.h EXTSOURCES += composite.c -EXTENSION_XML += composite.xml if BUILD_COMPOSITE lib_LTLIBRARIES += libxcb-composite.la libxcb_composite_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -40,9 +32,7 @@ libxcb_composite_la_LIBADD = $(XCB_LIBS) nodist_libxcb_composite_la_SOURCES = composite.c composite.h endif -EXTHEADERS += damage.h EXTSOURCES += damage.c -EXTENSION_XML += damage.xml if BUILD_DAMAGE lib_LTLIBRARIES += libxcb-damage.la libxcb_damage_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -50,9 +40,7 @@ libxcb_damage_la_LIBADD = $(XCB_LIBS) nodist_libxcb_damage_la_SOURCES = damage.c damage.h endif -EXTHEADERS += dpms.h EXTSOURCES += dpms.c -EXTENSION_XML += dpms.xml if BUILD_DPMS lib_LTLIBRARIES += libxcb-dpms.la libxcb_dpms_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -60,9 +48,7 @@ libxcb_dpms_la_LIBADD = $(XCB_LIBS) nodist_libxcb_dpms_la_SOURCES = dpms.c dpms.h endif -EXTHEADERS += dri2.h EXTSOURCES += dri2.c -EXTENSION_XML += dri2.xml if BUILD_DRI2 lib_LTLIBRARIES += libxcb-dri2.la libxcb_dri2_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -70,9 +56,7 @@ libxcb_dri2_la_LIBADD = $(XCB_LIBS) nodist_libxcb_dri2_la_SOURCES = dri2.c dri2.h endif -EXTHEADERS += glx.h EXTSOURCES += glx.c -EXTENSION_XML += glx.xml if BUILD_GLX lib_LTLIBRARIES += libxcb-glx.la libxcb_glx_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -80,9 +64,7 @@ libxcb_glx_la_LIBADD = $(XCB_LIBS) nodist_libxcb_glx_la_SOURCES = glx.c glx.h endif -EXTHEADERS += randr.h EXTSOURCES += randr.c -EXTENSION_XML += randr.xml if BUILD_RANDR lib_LTLIBRARIES += libxcb-randr.la libxcb_randr_la_LDFLAGS = -version-info 1:0:1 -no-undefined @@ -90,9 +72,7 @@ libxcb_randr_la_LIBADD = $(XCB_LIBS) nodist_libxcb_randr_la_SOURCES = randr.c randr.h endif -EXTHEADERS += record.h EXTSOURCES += record.c -EXTENSION_XML += record.xml if BUILD_RECORD lib_LTLIBRARIES += libxcb-record.la libxcb_record_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -100,9 +80,7 @@ libxcb_record_la_LIBADD = $(XCB_LIBS) nodist_libxcb_record_la_SOURCES = record.c record.h endif -EXTHEADERS += render.h EXTSOURCES += render.c -EXTENSION_XML += render.xml if BUILD_RENDER lib_LTLIBRARIES += libxcb-render.la libxcb_render_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -110,9 +88,7 @@ libxcb_render_la_LIBADD = $(XCB_LIBS) nodist_libxcb_render_la_SOURCES = render.c render.h endif -EXTHEADERS += res.h EXTSOURCES += res.c -EXTENSION_XML += res.xml if BUILD_RESOURCE lib_LTLIBRARIES += libxcb-res.la libxcb_res_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -120,9 +96,7 @@ libxcb_res_la_LIBADD = $(XCB_LIBS) nodist_libxcb_res_la_SOURCES = res.c res.h endif -EXTHEADERS += screensaver.h EXTSOURCES += screensaver.c -EXTENSION_XML += screensaver.xml if BUILD_SCREENSAVER lib_LTLIBRARIES += libxcb-screensaver.la libxcb_screensaver_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -130,9 +104,7 @@ libxcb_screensaver_la_LIBADD = $(XCB_LIBS) nodist_libxcb_screensaver_la_SOURCES = screensaver.c screensaver.h endif -EXTHEADERS += shape.h EXTSOURCES += shape.c -EXTENSION_XML += shape.xml if BUILD_SHAPE lib_LTLIBRARIES += libxcb-shape.la libxcb_shape_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -140,9 +112,7 @@ libxcb_shape_la_LIBADD = $(XCB_LIBS) nodist_libxcb_shape_la_SOURCES = shape.c shape.h endif -EXTHEADERS += shm.h EXTSOURCES += shm.c -EXTENSION_XML += shm.xml if BUILD_SHM lib_LTLIBRARIES += libxcb-shm.la libxcb_shm_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -150,9 +120,7 @@ libxcb_shm_la_LIBADD = $(XCB_LIBS) nodist_libxcb_shm_la_SOURCES = shm.c shm.h endif -EXTHEADERS += sync.h EXTSOURCES += sync.c -EXTENSION_XML += sync.xml if BUILD_SYNC lib_LTLIBRARIES += libxcb-sync.la libxcb_sync_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -160,9 +128,7 @@ libxcb_sync_la_LIBADD = $(XCB_LIBS) nodist_libxcb_sync_la_SOURCES = sync.c sync.h endif -EXTHEADERS += xevie.h EXTSOURCES += xevie.c -EXTENSION_XML += xevie.xml if BUILD_XEVIE lib_LTLIBRARIES += libxcb-xevie.la libxcb_xevie_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -170,9 +136,7 @@ libxcb_xevie_la_LIBADD = $(XCB_LIBS) nodist_libxcb_xevie_la_SOURCES = xevie.c xevie.h endif -EXTHEADERS += xf86dri.h EXTSOURCES += xf86dri.c -EXTENSION_XML += xf86dri.xml if BUILD_XFREE86_DRI lib_LTLIBRARIES += libxcb-xf86dri.la libxcb_xf86dri_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -180,9 +144,7 @@ libxcb_xf86dri_la_LIBADD = $(XCB_LIBS) nodist_libxcb_xf86dri_la_SOURCES = xf86dri.c xf86dri.h endif -EXTHEADERS += xfixes.h EXTSOURCES += xfixes.c -EXTENSION_XML += xfixes.xml if BUILD_XFIXES lib_LTLIBRARIES += libxcb-xfixes.la libxcb_xfixes_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -190,9 +152,7 @@ libxcb_xfixes_la_LIBADD = $(XCB_LIBS) nodist_libxcb_xfixes_la_SOURCES = xfixes.c xfixes.h endif -EXTHEADERS += xinerama.h EXTSOURCES += xinerama.c -EXTENSION_XML += xinerama.xml if BUILD_XINERAMA lib_LTLIBRARIES += libxcb-xinerama.la libxcb_xinerama_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -200,9 +160,7 @@ libxcb_xinerama_la_LIBADD = $(XCB_LIBS) nodist_libxcb_xinerama_la_SOURCES = xinerama.c xinerama.h endif -EXTHEADERS += xinput.h EXTSOURCES += xinput.c -EXTENSION_XML += xinput.xml if BUILD_XINPUT lib_LTLIBRARIES += libxcb-xinput.la libxcb_xinput_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -210,9 +168,7 @@ libxcb_xinput_la_LIBADD = $(XCB_LIBS) nodist_libxcb_xinput_la_SOURCES = xinput.c xinput.h endif -EXTHEADERS += xprint.h EXTSOURCES += xprint.c -EXTENSION_XML += xprint.xml if BUILD_XPRINT lib_LTLIBRARIES += libxcb-xprint.la libxcb_xprint_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -220,9 +176,7 @@ libxcb_xprint_la_LIBADD = $(XCB_LIBS) nodist_libxcb_xprint_la_SOURCES = xprint.c xprint.h endif -EXTHEADERS += xselinux.h EXTSOURCES += xselinux.c -EXTENSION_XML += xselinux.xml if BUILD_SELINUX lib_LTLIBRARIES += libxcb-xselinux.la libxcb_xselinux_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -230,9 +184,7 @@ libxcb_xselinux_la_LIBADD = $(XCB_LIBS) nodist_libxcb_xselinux_la_SOURCES = xselinux.c xselinux.h endif -EXTHEADERS += xtest.h EXTSOURCES += xtest.c -EXTENSION_XML += xtest.xml if BUILD_XTEST lib_LTLIBRARIES += libxcb-xtest.la libxcb_xtest_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -240,9 +192,7 @@ libxcb_xtest_la_LIBADD = $(XCB_LIBS) nodist_libxcb_xtest_la_SOURCES = xtest.c xtest.h endif -EXTHEADERS += xv.h EXTSOURCES += xv.c -EXTENSION_XML += xv.xml if BUILD_XV lib_LTLIBRARIES += libxcb-xv.la libxcb_xv_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -250,9 +200,7 @@ libxcb_xv_la_LIBADD = $(XCB_LIBS) nodist_libxcb_xv_la_SOURCES = xv.c xv.h endif -EXTHEADERS += xvmc.h EXTSOURCES += xvmc.c -EXTENSION_XML += xvmc.xml if BUILD_XVMC lib_LTLIBRARIES += libxcb-xvmc.la libxcb_xvmc_la_LDFLAGS = -version-info 0:0:0 -no-undefined @@ -261,23 +209,13 @@ nodist_libxcb_xvmc_la_SOURCES = xvmc.c xvmc.h endif - +EXTHEADERS=$(EXTSOURCES:.c=.h) xcbinclude_HEADERS = xcb.h xcbext.h nodist_xcbinclude_HEADERS = $(EXTHEADERS) noinst_HEADERS = xcbint.h -BUILT_SOURCES = $(EXTSOURCES) $(EXTHEADERS) -CLEANFILES = $(EXTSOURCES) $(EXTHEADERS) $(EXTENSION_XML) - -$(EXTHEADERS) $(EXTSOURCES): c_client.py - -SUFFIXES = .xml - -.xml.h: - $(PYTHON) $(srcdir)/c_client.py -p $(XCBPROTO_XCBPYTHONDIR) $(XCBPROTO_XCBINCLUDEDIR)/$< - -.xml.c: - $(PYTHON) $(srcdir)/c_client.py -p $(XCBPROTO_XCBPYTHONDIR) $(XCBPROTO_XCBINCLUDEDIR)/$< +BUILT_SOURCES = $(EXTSOURCES) +CLEANFILES = $(EXTSOURCES) $(EXTHEADERS) -$(EXTENSION_XML): - $(LN_S) -f $(XCBPROTO_XCBINCLUDEDIR)/$@ $@ +$(EXTSOURCES): c_client.py + $(PYTHON) $(srcdir)/c_client.py -p $(XCBPROTO_XCBPYTHONDIR) $(XCBPROTO_XCBINCLUDEDIR)/$(@:.c=.xml) diff --git a/libxcb/src/c-client.xsl b/libxcb/src/c-client.xsl new file mode 100644 index 000000000..a15d824a1 --- /dev/null +++ b/libxcb/src/c-client.xsl @@ -0,0 +1,1551 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (C) 2004 Josh Triplett. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the names of the authors or their +institutions shall not be used in advertising or otherwise to promote the +sale, use or other dealings in this Software without prior written +authorization from the authors. +--> +<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + version="1.0" + xmlns:e="http://exslt.org/common" + xmlns:func="http://exslt.org/functions" + xmlns:str="http://exslt.org/strings" + xmlns:xcb="http://xcb.freedesktop.org" + extension-element-prefixes="func str xcb"> + + <xsl:output method="text" /> + + <xsl:strip-space elements="*" /> + + <!-- "header" or "source" --> + <xsl:param name="mode" /> + + <!-- Path to the core protocol descriptions. --> + <xsl:param name="base-path" /> + + <!-- Path to the extension protocol descriptions. --> + <xsl:param name="extension-path" select="$base-path" /> + + <xsl:variable name="h" select="$mode = 'header'" /> + <xsl:variable name="c" select="$mode = 'source'" /> + + <xsl:variable name="need-string-h" select="//request/pad[@bytes != 1]" /> + + <!-- String used to indent lines of code. --> + <xsl:variable name="indent-string" select="' '" /> + + <xsl:variable name="ucase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" /> + <xsl:variable name="lcase" select="'abcdefghijklmnopqrstuvwxyz'" /> + <xsl:variable name="letters" select="concat($ucase, $lcase)" /> + <xsl:variable name="digits" select="'0123456789'" /> + + <xsl:variable name="header" select="/xcb/@header" /> + <xsl:variable name="ucase-header" + select="translate($header,$lcase,$ucase)" /> + + <xsl:variable name="ext" select="/xcb/@extension-name" /> + + <!-- Other protocol descriptions to search for types in, after checking the + current protocol description. --> + <xsl:variable name="search-path-rtf"> + <xsl:for-each select="/xcb/import"> + <path><xsl:value-of select="concat($extension-path, ., '.xml')" /></path> + </xsl:for-each> + </xsl:variable> + <xsl:variable name="search-path" select="e:node-set($search-path-rtf)/path"/> + + <xsl:variable name="root" select="/" /> + + <!-- First pass: Store everything in a variable. --> + <xsl:variable name="pass1-rtf"> + <xsl:apply-templates select="/" mode="pass1" /> + </xsl:variable> + <xsl:variable name="pass1" select="e:node-set($pass1-rtf)" /> + + <xsl:template match="xcb" mode="pass1"> + <xcb> + <xsl:copy-of select="@*" /> + <xsl:if test="$ext"> + <constant type="xcb_extension_t" name="{xcb:xcb-prefix()}_id"> + <xsl:attribute name="value">{ "<xsl:value-of select="@extension-xname" />" }</xsl:attribute> + </constant> + </xsl:if> + <xsl:apply-templates mode="pass1" /> + </xcb> + </xsl:template> + + <func:function name="xcb:xcb-prefix"> + <xsl:param name="name" /> + <func:result> + <xsl:text>xcb</xsl:text> + <xsl:if test="/xcb/@extension-name"> + <xsl:text>_</xsl:text> + <xsl:choose> + <xsl:when test="/xcb/@extension-multiword = 'true' or /xcb/@extension-multiword = '1'"> + <xsl:call-template name="camelcase-to-underscore"> + <xsl:with-param name="camelcase" select="/xcb/@extension-name" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="translate(/xcb/@extension-name, $ucase, $lcase)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + <xsl:if test="$name"> + <xsl:text>_</xsl:text> + <xsl:call-template name="camelcase-to-underscore"> + <xsl:with-param name="camelcase" select="$name" /> + </xsl:call-template> + </xsl:if> + </func:result> + </func:function> + + <func:function name="xcb:lowercase"> + <xsl:param name="name" /> + <func:result> + <xsl:call-template name="camelcase-to-underscore"> + <xsl:with-param name="camelcase" select="$name" /> + </xsl:call-template> + </func:result> + </func:function> + + <func:function name="xcb:get-char-void"> + <xsl:param name="name" /> + <xsl:variable name="ctype" select="substring-before($name, '_t')" /> + <func:result> + <xsl:choose> + <xsl:when test="$ctype = 'char' or $ctype = 'void' or $ctype = 'float' or $ctype = 'double'"> + <xsl:value-of select="$ctype" /> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$name" /> + </xsl:otherwise> + </xsl:choose> + </func:result> + </func:function> + + <func:function name="xcb:remove-void"> + <xsl:param name="name" /> + <xsl:variable name="ctype" select="substring-before($name, '_t')" /> + <func:result> + <xsl:choose> + <xsl:when test="$ctype = 'char' or $ctype = 'void' or $ctype = 'float' or $ctype = 'double'"> + <xsl:choose> + <xsl:when test="$ctype = 'void'"> + <xsl:text>char</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$ctype" /> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$name" /> + </xsl:otherwise> + </xsl:choose> + </func:result> + </func:function> + + <!-- split camel case into words and insert underscore --> + <xsl:template name="camelcase-to-underscore"> + <xsl:param name="camelcase"/> + <xsl:choose> + <xsl:when test="$camelcase='CHAR2B' or $camelcase='INT64' + or $camelcase='FLOAT32' or $camelcase='FLOAT64' + or $camelcase='BOOL32' or $camelcase='STRING8' + or $camelcase='Family_DECnet'"> + <xsl:value-of select="translate($camelcase, $ucase, $lcase)"/> + </xsl:when> + <xsl:otherwise> + <xsl:for-each select="str:split($camelcase, '')"> + <xsl:variable name="a" select="."/> + <xsl:variable name="b" select="following::*[1]"/> + <xsl:variable name="c" select="following::*[2]"/> + <xsl:value-of select="translate(., $ucase, $lcase)"/> + <xsl:if test="($b and contains($lcase, $a) and contains($ucase, $b)) + or ($b and contains($digits, $a) + and contains($letters, $b)) + or ($b and contains($letters, $a) + and contains($digits, $b)) + or ($c and contains($ucase, $a) + and contains($ucase, $b) + and contains($lcase, $c))"> + <xsl:text>_</xsl:text> + </xsl:if> + </xsl:for-each> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Modify names that conflict with C++ keywords by prefixing them with an + underscore. If the name parameter is not specified, it defaults to the + value of the name attribute on the context node. --> + <xsl:template name="canonical-var-name"> + <xsl:param name="name" select="@name" /> + <xsl:if test="$name='new' or $name='delete' + or $name='class' or $name='operator'"> + <xsl:text>_</xsl:text> + </xsl:if> + <xsl:value-of select="$name" /> + </xsl:template> + + <!-- List of core types, for use in canonical-type-name. --> + <xsl:variable name="core-types-rtf"> + <type name="BOOL" newname="uint8" /> + <type name="BYTE" newname="uint8" /> + <type name="CARD8" newname="uint8" /> + <type name="CARD16" newname="uint16" /> + <type name="CARD32" newname="uint32" /> + <type name="INT8" newname="int8" /> + <type name="INT16" newname="int16" /> + <type name="INT32" newname="int32" /> + + <type name="char" newname="char" /> + <type name="void" newname="void" /> + <type name="float" newname="float" /> + <type name="double" newname="double" /> + </xsl:variable> + <xsl:variable name="core-types" select="e:node-set($core-types-rtf)" /> + + <!-- + Output the canonical name for a type. This will be + xcb_{extension-containing-type-if-any}_type, wherever the type is found in + the search path, or just type if not found. If the type parameter is not + specified, it defaults to the value of the type attribute on the context + node. + --> + <xsl:template name="canonical-type-name"> + <xsl:param name="type" select="string(@type)" /> + + <xsl:variable name="is-unqualified" select="not(contains($type, ':'))"/> + <xsl:variable name="namespace" select="substring-before($type, ':')" /> + <xsl:variable name="unqualified-type"> + <xsl:choose> + <xsl:when test="$is-unqualified"> + <xsl:value-of select="$type" /> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="substring-after($type, ':')" /> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:choose> + <xsl:when test="$is-unqualified and $core-types/type[@name=$type]"> + <xsl:value-of select="$core-types/type[@name=$type]/@newname" /> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="type-definitions" + select="(/xcb|document($search-path)/xcb + )[$is-unqualified or @header=$namespace] + /*[((self::struct or self::union or self::enum + or self::xidtype or self::xidunion + or self::event or self::eventcopy + or self::error or self::errorcopy) + and @name=$unqualified-type) + or (self::typedef + and @newname=$unqualified-type)]" /> + <xsl:choose> + <xsl:when test="count($type-definitions) = 1"> + <xsl:for-each select="$type-definitions"> + <xsl:value-of select="xcb:xcb-prefix($unqualified-type)" /> + </xsl:for-each> + </xsl:when> + <xsl:when test="count($type-definitions) > 1"> + <xsl:message terminate="yes"> + <xsl:text>Multiple definitions of type "</xsl:text> + <xsl:value-of select="$type" /> + <xsl:text>" found.</xsl:text> + <xsl:if test="$is-unqualified"> + <xsl:for-each select="$type-definitions"> + <xsl:text> + </xsl:text> + <xsl:value-of select="concat(/xcb/@header, ':', $type)" /> + </xsl:for-each> + </xsl:if> + </xsl:message> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>No definitions of type "</xsl:text> + <xsl:value-of select="$type" /> + <xsl:text>" found</xsl:text> + <xsl:if test="$is-unqualified"> + <xsl:text>, and it is not a known core type</xsl:text> + </xsl:if> + <xsl:text>.</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Helper template for requests, that outputs the cookie type. The + parameter "request" must be the request node, which defaults to the + context node. --> + <xsl:template name="cookie-type"> + <xsl:param name="request" select="." /> + <xsl:choose> + <xsl:when test="$request/reply"> + <xsl:value-of select="xcb:xcb-prefix($request/@name)" /> + </xsl:when> + <xsl:otherwise> + <xsl:text>xcb_void</xsl:text> + </xsl:otherwise> + </xsl:choose> + <xsl:text>_cookie_t</xsl:text> + </xsl:template> + + <xsl:template name="request-function"> + <xsl:param name="checked" /> + <xsl:param name="req" /> + <function> + <xsl:attribute name="name"> + <xsl:value-of select="xcb:xcb-prefix($req/@name)" /> + <xsl:if test="$checked='true' and not($req/reply)">_checked</xsl:if> + <xsl:if test="$checked='false' and $req/reply">_unchecked</xsl:if> + </xsl:attribute> + <xsl:attribute name="type"> + <xsl:call-template name="cookie-type"> + <xsl:with-param name="request" select="$req" /> + </xsl:call-template> + </xsl:attribute> + <doc>/**</doc> + <doc> * Delivers a request to the X server</doc> + <doc> * @param c The connection</doc> + <doc> * @return A cookie</doc> + <doc> *</doc> + <doc> * Delivers a request to the X server.</doc> + <doc> * </doc> + <xsl:if test="$checked='true' and not($req/reply)"> + <doc> * This form can be used only if the request will not cause</doc> + <doc> * a reply to be generated. Any returned error will be</doc> + <doc> * saved for handling by xcb_request_check().</doc> + </xsl:if> + <xsl:if test="$checked='false' and $req/reply"> + <doc> * This form can be used only if the request will cause</doc> + <doc> * a reply to be generated. Any returned error will be</doc> + <doc> * placed in the event queue.</doc> + </xsl:if> + <doc> */</doc> + <field type="xcb_connection_t *" name="c" /> + <xsl:apply-templates select="$req/*[not(self::reply)]" mode="param" /> + <do-request ref="{xcb:xcb-prefix($req/@name)}_request_t" opcode="{translate(xcb:xcb-prefix($req/@name), $lcase, $ucase)}" + checked="{$checked}"> + <xsl:if test="$req/reply"> + <xsl:attribute name="has-reply">true</xsl:attribute> + </xsl:if> + </do-request> + </function> + </xsl:template> + + <xsl:template match="request" mode="pass1"> + <xsl:variable name="req" select="." /> + <xsl:if test="reply"> + <struct name="{xcb:xcb-prefix(@name)}_cookie_t"> + <field type="unsigned int" name="sequence" /> + </struct> + </xsl:if> + <constant type="number" name="{xcb:xcb-prefix($req/@name)}" value="{$req/@opcode}" /> + <struct name="{xcb:xcb-prefix(@name)}_request_t"> + <field type="uint8_t" name="major_opcode" no-assign="true" /> + <xsl:if test="$ext"> + <field type="uint8_t" name="minor_opcode" no-assign="true" /> + </xsl:if> + <xsl:apply-templates select="*[not(self::reply)]" mode="field" /> + <middle> + <field type="uint16_t" name="length" no-assign="true" /> + </middle> + </struct> + <xsl:call-template name="request-function"> + <xsl:with-param name="checked" select="'true'" /> + <xsl:with-param name="req" select="$req" /> + </xsl:call-template> + <xsl:call-template name="request-function"> + <xsl:with-param name="checked" select="'false'" /> + <xsl:with-param name="req" select="$req" /> + </xsl:call-template> + <xsl:if test="reply"> + <struct name="{xcb:xcb-prefix(@name)}_reply_t"> + <field type="uint8_t" name="response_type" /> + <xsl:apply-templates select="reply/*" mode="field" /> + <middle> + <field type="uint16_t" name="sequence" /> + <field type="uint32_t" name="length" /> + </middle> + </struct> + <iterator-functions ref="{xcb:xcb-prefix(@name)}" kind="_reply" /> + <function type="{xcb:xcb-prefix(@name)}_reply_t *" name="{xcb:xcb-prefix(@name)}_reply"> + <doc>/**</doc> + <doc> * Return the reply</doc> + <doc> * @param c The connection</doc> + <doc> * @param cookie The cookie</doc> + <doc> * @param e The xcb_generic_error_t supplied</doc> + <doc> *</doc> + <doc> * Returns the reply of the request asked by</doc> + <doc> * </doc> + <doc> * The parameter @p e supplied to this function must be NULL if</doc> + <doc> * <xsl:value-of select="xcb:xcb-prefix(@name)" />_unchecked(). is used.</doc> + <doc> * Otherwise, it stores the error if any.</doc> + <doc> *</doc> + <doc> * The returned value must be freed by the caller using free().</doc> + <doc> */</doc> + <field type="xcb_connection_t *" name="c" /> + <field name="cookie"> + <xsl:attribute name="type"> + <xsl:call-template name="cookie-type" /> + </xsl:attribute> + </field> + <field type="xcb_generic_error_t **" name="e" /> + <l>return (<xsl:value-of select="xcb:xcb-prefix(@name)" />_reply_t *)<!-- + --> xcb_wait_for_reply(c, cookie.sequence, e);</l> + </function> + </xsl:if> + </xsl:template> + + <xsl:template match="xidtype|xidunion" mode="pass1"> + <typedef oldname="uint32_t" newname="{xcb:xcb-prefix(@name)}_t" /> + <iterator ref="{xcb:xcb-prefix(@name)}" /> + <iterator-functions ref="{xcb:xcb-prefix(@name)}" /> + </xsl:template> + + <xsl:template match="struct|union" mode="pass1"> + <struct name="{xcb:xcb-prefix(@name)}_t"> + <xsl:if test="self::union"> + <xsl:attribute name="kind">union</xsl:attribute> + </xsl:if> + <xsl:apply-templates select="*" mode="field" /> + </struct> + <iterator ref="{xcb:xcb-prefix(@name)}" /> + <iterator-functions ref="{xcb:xcb-prefix(@name)}" /> + </xsl:template> + + <xsl:template match="event|eventcopy|error|errorcopy" mode="pass1"> + <xsl:variable name="suffix"> + <xsl:choose> + <xsl:when test="self::event|self::eventcopy"> + <xsl:text>_event_t</xsl:text> + </xsl:when> + <xsl:when test="self::error|self::errorcopy"> + <xsl:text>_error_t</xsl:text> + </xsl:when> + </xsl:choose> + </xsl:variable> + <constant type="number" name="{xcb:xcb-prefix(@name)}" value="{@number}" /> + <xsl:choose> + <xsl:when test="self::event|self::error"> + <struct name="{xcb:xcb-prefix(@name)}{$suffix}"> + <field type="uint8_t" name="response_type" /> + <xsl:if test="self::error"> + <field type="uint8_t" name="error_code" /> + </xsl:if> + <xsl:apply-templates select="*" mode="field" /> + <xsl:if test="not(self::event and boolean(@no-sequence-number))"> + <middle> + <field type="uint16_t" name="sequence" /> + </middle> + </xsl:if> + </struct> + </xsl:when> + <xsl:when test="self::eventcopy|self::errorcopy"> + <typedef newname="{xcb:xcb-prefix(@name)}{$suffix}"> + <xsl:attribute name="oldname"> + <xsl:call-template name="canonical-type-name"> + <xsl:with-param name="type" select="@ref" /> + </xsl:call-template> + <xsl:value-of select="$suffix" /> + </xsl:attribute> + </typedef> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template match="typedef" mode="pass1"> + <typedef> + <xsl:attribute name="oldname"> + <xsl:call-template name="canonical-type-name"> + <xsl:with-param name="type" select="@oldname" /> + </xsl:call-template> + <xsl:text>_t</xsl:text> + </xsl:attribute> + <xsl:attribute name="newname"> + <xsl:call-template name="canonical-type-name"> + <xsl:with-param name="type" select="@newname" /> + </xsl:call-template> + <xsl:text>_t</xsl:text> + </xsl:attribute> + </typedef> + <iterator ref="{xcb:xcb-prefix(@newname)}" /> + <iterator-functions ref="{xcb:xcb-prefix(@newname)}" /> + </xsl:template> + + <xsl:template match="enum" mode="pass1"> + <enum name="{xcb:xcb-prefix(@name)}_t"> + <xsl:for-each select="item"> + <item name="{translate(xcb:xcb-prefix(concat(../@name, concat('_', @name))), $lcase, $ucase)}"> + <xsl:copy-of select="*" /> + </item> + </xsl:for-each> + </enum> + </xsl:template> + + <!-- + Templates for processing fields. + --> + + <xsl:template match="pad" mode="field"> + <xsl:copy-of select="." /> + </xsl:template> + + <xsl:template match="field|exprfield" mode="field"> + <xsl:copy> + <xsl:attribute name="type"> + <xsl:call-template name="canonical-type-name" /> + <xsl:text>_t</xsl:text> + </xsl:attribute> + <xsl:attribute name="name"> + <xsl:call-template name="canonical-var-name" /> + </xsl:attribute> + <xsl:copy-of select="*" /> + </xsl:copy> + </xsl:template> + + <xsl:template match="list" mode="field"> + <xsl:variable name="type"><!-- + --><xsl:call-template name="canonical-type-name" /> + <xsl:text>_t</xsl:text><!-- + --></xsl:variable> + <list type="{$type}"> + <xsl:attribute name="name"> + <xsl:call-template name="canonical-var-name" /> + </xsl:attribute> + <xsl:if test="not(parent::request) and node() + and not(.//*[not(self::value or self::op)])"> + <xsl:attribute name="fixed">true</xsl:attribute> + </xsl:if> + <!-- Handle lists with no length expressions. --> + <xsl:if test="not(node())"> + <xsl:choose> + <!-- In a request, refer to an implicit localparam for length. --> + <xsl:when test="parent::request"> + <fieldref> + <xsl:value-of select="concat(@name, '_len')" /> + </fieldref> + </xsl:when> + <!-- In a reply, use the length of the reply to determine the length + of the list. --> + <xsl:when test="parent::reply"> + <op op="/"> + <op op="<<"> + <fieldref>length</fieldref> + <value>2</value> + </op> + <function-call name="sizeof"> + <param><xsl:value-of select="$type" /></param> + </function-call> + </op> + </xsl:when> + <!-- Other cases generate an error. --> + <xsl:otherwise> + <xsl:message terminate="yes"><!-- + -->Encountered a list with no length expresssion outside a<!-- + --> request or reply.<!-- + --></xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + <xsl:copy-of select="*" /> + </list> + </xsl:template> + + <xsl:template match="valueparam" mode="field"> + <field> + <xsl:attribute name="type"> + <xsl:call-template name="canonical-type-name"> + <xsl:with-param name="type" select="@value-mask-type" /> + </xsl:call-template> + <xsl:text>_t</xsl:text> + </xsl:attribute> + <xsl:attribute name="name"> + <xsl:call-template name="canonical-var-name"> + <xsl:with-param name="name" select="@value-mask-name" /> + </xsl:call-template> + </xsl:attribute> + </field> + <list type="uint32_t"> + <xsl:attribute name="name"> + <xsl:call-template name="canonical-var-name"> + <xsl:with-param name="name" select="@value-list-name" /> + </xsl:call-template> + </xsl:attribute> + <function-call name="xcb_popcount"> + <param> + <fieldref> + <xsl:call-template name="canonical-var-name"> + <xsl:with-param name="name" select="@value-mask-name" /> + </xsl:call-template> + </fieldref> + </param> + </function-call> + </list> + </xsl:template> + + <xsl:template match="field" mode="param"> + <field> + <xsl:attribute name="type"> + <xsl:call-template name="canonical-type-name" /> + <xsl:text>_t</xsl:text> + </xsl:attribute> + <xsl:attribute name="name"> + <xsl:call-template name="canonical-var-name" /> + </xsl:attribute> + </field> + </xsl:template> + + <xsl:template match="list" mode="param"> + <!-- If no length expression is provided, use a CARD32 localfield. --> + <xsl:if test="not(node())"> + <field type="uint32_t" name="{@name}_len" /> + </xsl:if> + <field> + <xsl:variable name="ctype"> + <xsl:call-template name="canonical-type-name" /> + </xsl:variable> + <xsl:attribute name="type"> + <xsl:text>const </xsl:text> + <xsl:call-template name="canonical-type-name" /> + <xsl:if test="not($ctype='char') and not($ctype='void')"> + <xsl:text>_t</xsl:text> + </xsl:if> + <xsl:text> *</xsl:text> + </xsl:attribute> + <xsl:attribute name="name"> + <xsl:call-template name="canonical-var-name" /> + </xsl:attribute> + </field> + </xsl:template> + + <xsl:template match="valueparam" mode="param"> + <field> + <xsl:attribute name="type"> + <xsl:call-template name="canonical-type-name"> + <xsl:with-param name="type" select="@value-mask-type" /> + </xsl:call-template> + <xsl:text>_t</xsl:text> + </xsl:attribute> + <xsl:attribute name="name"> + <xsl:call-template name="canonical-var-name"> + <xsl:with-param name="name" select="@value-mask-name" /> + </xsl:call-template> + </xsl:attribute> + </field> + <field type="const uint32_t *"> + <xsl:attribute name="name"> + <xsl:call-template name="canonical-var-name"> + <xsl:with-param name="name" select="@value-list-name" /> + </xsl:call-template> + </xsl:attribute> + </field> + </xsl:template> + + <!-- Second pass: Process the variable. --> + <xsl:variable name="result-rtf"> + <xsl:apply-templates select="$pass1/*" mode="pass2" /> + </xsl:variable> + <xsl:variable name="result" select="e:node-set($result-rtf)" /> + + <xsl:template match="xcb" mode="pass2"> + <xcb> + <xsl:copy-of select="@*" /> + <xsl:apply-templates mode="pass2" + select="constant|enum|struct|typedef|iterator" /> + <xsl:apply-templates mode="pass2" + select="function|iterator-functions" /> + </xcb> + </xsl:template> + + <!-- Generic rules for nodes that don't need further processing: copy node + with attributes, and recursively process the child nodes. --> + <xsl:template match="*" mode="pass2"> + <xsl:copy> + <xsl:copy-of select="@*" /> + <xsl:apply-templates mode="pass2" /> + </xsl:copy> + </xsl:template> + + <xsl:template match="struct" mode="pass2"> + <xsl:if test="@kind='union' and list[not(@fixed)]"> + <xsl:message terminate="yes">Unions must be fixed length.</xsl:message> + </xsl:if> + <struct name="{@name}"> + <xsl:if test="@kind"> + <xsl:attribute name="kind"> + <xsl:value-of select="@kind" /> + </xsl:attribute> + </xsl:if> + <!-- FIXME: This should go by size, not number of fields. --> + <xsl:copy-of select="node()[not(self::middle) + and position() < 3]" /> + <xsl:if test="middle and (count(*[not(self::middle)]) < 2)"> + <pad bytes="{2 - count(*[not(self::middle)])}" /> + </xsl:if> + <xsl:copy-of select="middle/*" /> + <xsl:copy-of select="node()[not(self::middle) and (position() > 2)]" /> + </struct> + </xsl:template> + + <xsl:template match="do-request" mode="pass2"> + <xsl:variable name="struct" + select="$pass1/xcb/struct[@name=current()/@ref]" /> + + <xsl:variable name="num-parts" select="(1+count($struct/list))*2" /> + + <l>static const xcb_protocol_request_t xcb_req = {</l> + <indent> + <l>/* count */ <xsl:value-of select="$num-parts" />,</l> + <l>/* ext */ <xsl:choose> + <xsl:when test="$ext"> + <xsl:text>&</xsl:text> + <xsl:value-of select="xcb:xcb-prefix()" /> + <xsl:text>_id</xsl:text> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose>,</l> + <l>/* opcode */ <xsl:value-of select="@opcode" />,</l> + <l>/* isvoid */ <xsl:value-of select="1-boolean(@has-reply)" /></l> + </indent> + <l>};</l> + + <l /> + <l>struct iovec xcb_parts[<xsl:value-of select="$num-parts+2" />];</l> + <l><xsl:value-of select="../@type" /> xcb_ret;</l> + <l><xsl:value-of select="@ref" /> xcb_out;</l> + + <l /> + <xsl:if test="not ($ext) and not($struct//*[(self::field or self::exprfield or self::pad) + and not(boolean(@no-assign))])"> + <l>xcb_out.pad0 = 0;</l> + </xsl:if> + <xsl:apply-templates select="$struct//*[(self::field or self::exprfield or self::pad) + and not(boolean(@no-assign))]" + mode="assign" /> + + <l /> + <l>xcb_parts[2].iov_base = (char *) &xcb_out;</l> + <l>xcb_parts[2].iov_len = sizeof(xcb_out);</l> + <l>xcb_parts[3].iov_base = 0;</l> + <l>xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;</l> + + <xsl:for-each select="$struct/list"> + <l>xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_base = (char *) <!-- + --><xsl:value-of select="@name" />;</l> + <l>xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_len = <!-- + --><xsl:apply-templates mode="output-expression" /> + <xsl:if test="not(@type = 'void_t')"> + <xsl:text> * sizeof(</xsl:text> + <xsl:choose> + <xsl:when test="@type='char_t'"> + <xsl:text>char</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@type" /> + </xsl:otherwise> + </xsl:choose> + <xsl:text>)</xsl:text> + </xsl:if>;</l> + <l>xcb_parts[<xsl:value-of select="3 + position() * 2"/>].iov_base = 0;</l> + <l>xcb_parts[<xsl:value-of select="3 + position() * 2"/>].iov_len = -xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_len & 3;</l> + </xsl:for-each> + + <l>xcb_ret.sequence = xcb_send_request(c, <!-- + --><xsl:choose> + <xsl:when test="@checked='true'">XCB_REQUEST_CHECKED</xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose>, xcb_parts + 2, &xcb_req);</l> + <l>return xcb_ret;</l> + </xsl:template> + + <xsl:template match="field" mode="assign"> + <l> + <xsl:text>xcb_out.</xsl:text> + <xsl:value-of select="@name" /> + <xsl:text> = </xsl:text> + <xsl:value-of select="@name" /> + <xsl:text>;</xsl:text> + </l> + </xsl:template> + + <xsl:template match="exprfield" mode="assign"> + <l> + <xsl:text>xcb_out.</xsl:text> + <xsl:value-of select="@name" /> + <xsl:text> = </xsl:text> + <xsl:apply-templates mode="output-expression" /> + <xsl:text>;</xsl:text> + </l> + </xsl:template> + + <xsl:template match="pad" mode="assign"> + <xsl:variable name="padnum"><xsl:number /></xsl:variable> + <l><xsl:choose> + <xsl:when test="@bytes = 1">xcb_out.pad<xsl:value-of select="$padnum - 1" /> = 0;</xsl:when> + <xsl:otherwise>memset(xcb_out.pad<xsl:value-of select="$padnum - 1" />, 0, <xsl:value-of select="@bytes" />);</xsl:otherwise> + </xsl:choose></l> + </xsl:template> + + <xsl:template match="iterator" mode="pass2"> + <struct name="{@ref}_iterator_t"> + <field type="{@ref}_t *" name="data" /> + <field type="int" name="rem" /> + <field type="int" name="index" /> + </struct> + </xsl:template> + + <xsl:template match="iterator-functions" mode="pass2"> + <xsl:variable name="ref" select="@ref" /> + <xsl:variable name="kind" select="@kind" /> + <xsl:variable name="struct" + select="$pass1/xcb/struct[@name=concat($ref, $kind, '_t')]" /> + <xsl:variable name="nextfields-rtf"> + <nextfield>R + 1</nextfield> + <xsl:for-each select="$struct/list[not(@fixed)]"> + <xsl:choose> + <xsl:when test="substring(@type, 1, 3) = 'xcb'"> + <nextfield><xsl:value-of select="substring(@type, 1, string-length(@type)-2)" />_end(<!-- + --><xsl:value-of select="$ref" />_<!-- + --><xsl:value-of select="string(@name)" />_iterator(R))</nextfield> + </xsl:when> + <xsl:otherwise> + <nextfield><xsl:value-of select="$ref" />_<!-- + --><xsl:value-of select="string(@name)" />_end(R)</nextfield> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:variable> + <xsl:variable name="nextfields" select="e:node-set($nextfields-rtf)" /> + <xsl:for-each select="$struct/list[not(@fixed)]"> + <xsl:variable name="number" + select="1+count(preceding-sibling::list[not(@fixed)])" /> + <xsl:variable name="nextfield" select="$nextfields/nextfield[$number]" /> + <xsl:variable name="is-first" + select="not(preceding-sibling::list[not(@fixed)])" /> + <xsl:variable name="field-name" select="@name" /> + <xsl:variable name="is-variable" + select="$pass1/xcb/struct[@name=current()/@type]/list + or document($search-path)/xcb + /struct[concat(xcb:xcb-prefix(@name), '_t') + = current()/@type] + /*[self::valueparam + or self::list[.//*[not(self::value + or self::op)]]]" /> + <xsl:if test="not($is-variable)"> + <function type="{xcb:get-char-void(@type)} *" name="{$ref}_{xcb:lowercase($field-name)}"> + <field type="const {$ref}{$kind}_t *" name="R" /> + <xsl:choose> + <xsl:when test="$is-first"> + <l>return (<xsl:value-of select="xcb:get-char-void(@type)" /> *) <!-- + -->(<xsl:value-of select="$nextfield" />);</l> + </xsl:when> + <xsl:otherwise> + <l>xcb_generic_iterator_t prev = <!-- + --><xsl:value-of select="$nextfield" />;</l> + <l>return (<xsl:value-of select="xcb:get-char-void(@type)" /> *) <!-- + -->((char *) prev.data + XCB_TYPE_PAD(<!-- + --><xsl:value-of select="xcb:get-char-void(@type)" />, prev.index));</l> + </xsl:otherwise> + </xsl:choose> + </function> + </xsl:if> + <function type="int" name="{$ref}_{xcb:lowercase($field-name)}_length"> + <field type="const {$ref}{$kind}_t *" name="R" /> + <l>return <xsl:apply-templates mode="output-expression"> + <xsl:with-param name="field-prefix" select="'R->'" /> + </xsl:apply-templates>;</l> + </function> + <xsl:choose> + <xsl:when test="substring(@type, 1, 3) = 'xcb'"> + <function type="{substring(@type, 1, string-length(@type)-2)}_iterator_t" name="{$ref}_{xcb:lowercase($field-name)}_iterator"> + <field type="const {$ref}{$kind}_t *" name="R" /> + <l><xsl:value-of select="substring(@type, 1, string-length(@type)-2)" />_iterator_t i;</l> + <xsl:choose> + <xsl:when test="$is-first"> + <l>i.data = (<xsl:value-of select="@type" /> *) <!-- + -->(<xsl:value-of select="$nextfield" />);</l> + </xsl:when> + <xsl:otherwise> + <l>xcb_generic_iterator_t prev = <!-- + --><xsl:value-of select="$nextfield" />;</l> + <l>i.data = (<xsl:value-of select="@type" /> *) <!-- + -->((char *) prev.data + XCB_TYPE_PAD(<!-- + --><xsl:value-of select="@type" />, prev.index));</l> + </xsl:otherwise> + </xsl:choose> + <l>i.rem = <xsl:apply-templates mode="output-expression"> + <xsl:with-param name="field-prefix" select="'R->'" /> + </xsl:apply-templates>;</l> + <l>i.index = (char *) i.data - (char *) R;</l> + <l>return i;</l> + </function> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="cast"> + <xsl:choose> + <xsl:when test="@type='void'">char</xsl:when> + <xsl:otherwise><xsl:value-of select="@type" /></xsl:otherwise> + </xsl:choose> + </xsl:variable> + <function type="xcb_generic_iterator_t" name="{$ref}_{xcb:lowercase($field-name)}_end"> + <field type="const {$ref}{$kind}_t *" name="R" /> + <l>xcb_generic_iterator_t i;</l> + <xsl:choose> + <xsl:when test="$is-first"> + <l>i.data = ((<xsl:value-of select="xcb:remove-void($cast)" /> *) <!-- + -->(<xsl:value-of select="$nextfield" />)) + (<!-- + --><xsl:apply-templates mode="output-expression"> + <xsl:with-param name="field-prefix" select="'R->'" /> + </xsl:apply-templates>);</l> + </xsl:when> + <xsl:otherwise> + <l>xcb_generic_iterator_t child = <!-- + --><xsl:value-of select="$nextfield" />;</l> + <l>i.data = ((<xsl:value-of select="xcb:get-char-void($cast)" /> *) <!-- + -->child.data) + (<!-- + --><xsl:apply-templates mode="output-expression"> + <xsl:with-param name="field-prefix" select="'R->'" /> + </xsl:apply-templates>);</l> + </xsl:otherwise> + </xsl:choose> + <l>i.rem = 0;</l> + <l>i.index = (char *) i.data - (char *) R;</l> + <l>return i;</l> + </function> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + <xsl:if test="not($kind)"> + <function type="void" name="{$ref}_next"> + <doc>/**</doc> + <doc> * Get the next element of the iterator</doc> + <doc> * @param i Pointer to a <xsl:value-of select="$ref" />_iterator_t</doc> + <doc> *</doc> + <doc> * Get the next element in the iterator. The member rem is</doc> + <doc> * decreased by one. The member data points to the next</doc> + <doc> * element. The member index is increased by sizeof(<xsl:value-of select="$ref" />_t)</doc> + <doc> */</doc> + <field type="{$ref}_iterator_t *" name="i" /> + <xsl:choose> + <xsl:when test="$struct/list[not(@fixed)]"> + <l><xsl:value-of select="$ref" />_t *R = i->data;</l> + <l>xcb_generic_iterator_t child = <!-- + --><xsl:value-of select="$nextfields/nextfield[last()]" />;</l> + <l>--i->rem;</l> + <l>i->data = (<xsl:value-of select="$ref" />_t *) child.data;</l> + <l>i->index = child.index;</l> + </xsl:when> + <xsl:otherwise> + <l>--i->rem;</l> + <l>++i->data;</l> + <l>i->index += sizeof(<xsl:value-of select="$ref" />_t);</l> + </xsl:otherwise> + </xsl:choose> + </function> + <function type="xcb_generic_iterator_t" name="{$ref}_end"> + <doc>/**</doc> + <doc> * Return the iterator pointing to the last element</doc> + <doc> * @param i An <xsl:value-of select="$ref" />_iterator_t</doc> + <doc> * @return The iterator pointing to the last element</doc> + <doc> *</doc> + <doc> * Set the current element in the iterator to the last element.</doc> + <doc> * The member rem is set to 0. The member data points to the</doc> + <doc> * last element.</doc> + <doc> */</doc> + <field type="{$ref}_iterator_t" name="i" /> + <l>xcb_generic_iterator_t ret;</l> + <xsl:choose> + <xsl:when test="$struct/list[not(@fixed)]"> + <l>while(i.rem > 0)</l> + <indent> + <l><xsl:value-of select="$ref" />_next(&i);</l> + </indent> + <l>ret.data = i.data;</l> + <l>ret.rem = i.rem;</l> + <l>ret.index = i.index;</l> + </xsl:when> + <xsl:otherwise> + <l>ret.data = i.data + i.rem;</l> + <l>ret.index = i.index + ((char *) ret.data - (char *) i.data);</l> + <l>ret.rem = 0;</l> + </xsl:otherwise> + </xsl:choose> + <l>return ret;</l> + </function> + </xsl:if> + </xsl:template> + + <!-- Output the results. --> + <xsl:template match="/"> + <xsl:if test="not(function-available('e:node-set'))"> + <xsl:message terminate="yes"><!-- + -->Error: This stylesheet requires the EXSL node-set extension.<!-- + --></xsl:message> + </xsl:if> + + <xsl:if test="not($h) and not($c)"> + <xsl:message terminate="yes"><!-- + -->Error: Parameter "mode" must be "header" or "source".<!-- + --></xsl:message> + </xsl:if> + + <xsl:apply-templates select="$result/*" mode="output" /> + </xsl:template> + + <xsl:template match="xcb" mode="output"> + <xsl:variable name="guard"><!-- + -->__<xsl:value-of select="$ucase-header" />_H<!-- + --></xsl:variable> + +<xsl:text>/* + * This file generated automatically from </xsl:text> +<xsl:value-of select="$header" /><xsl:text>.xml by c-client.xsl using XSLT. + * Edit at your peril. + */ +</xsl:text> +<xsl:if test="$h"><xsl:text> +/** + * @defgroup XCB_</xsl:text><xsl:value-of select="$ext" /><xsl:text>_API XCB </xsl:text><xsl:value-of select="$ext" /><xsl:text> API + * @brief </xsl:text><xsl:value-of select="$ext" /><xsl:text> XCB Protocol Implementation.</xsl:text> +<xsl:text> + * @{ + **/ +</xsl:text> + +<xsl:text> +#ifndef </xsl:text><xsl:value-of select="$guard" /><xsl:text> +#define </xsl:text><xsl:value-of select="$guard" /><xsl:text> +</xsl:text> +#include "xcb.h" +<xsl:for-each select="$root/xcb/import"> +<xsl:text>#include "</xsl:text><xsl:value-of select="." /><xsl:text>.h" +</xsl:text> +</xsl:for-each> +<xsl:text> +</xsl:text> +</xsl:if> +<xsl:if test="$h"> + <xsl:choose> + <xsl:when test="string($ext)"> + <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> +</xsl:text> + <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" /> + <xsl:text> + +</xsl:text> + </xsl:when> + </xsl:choose> +</xsl:if> + +<xsl:if test="$c"> +<xsl:if test="$need-string-h"> +#include <string.h></xsl:if> +<xsl:text> +#include <assert.h> +#include "xcbext.h" +#include "</xsl:text><xsl:value-of select="$header" /><xsl:text>.h" + +</xsl:text></xsl:if> + + <xsl:apply-templates mode="output" /> + +<xsl:if test="$h"> +<xsl:text> +#endif + +/** + * @} + */ +</xsl:text> +</xsl:if> + </xsl:template> + + <xsl:template match="constant" mode="output"> + <xsl:choose> + <xsl:when test="@type = 'number'"> + <xsl:if test="$h"> + <xsl:text>/** Opcode for </xsl:text><xsl:value-of select="@name"/><xsl:text>. */ +</xsl:text> + <xsl:text>#define </xsl:text> + <xsl:value-of select="translate(@name, $lcase, $ucase)" /> + <xsl:text> </xsl:text> + <xsl:value-of select="@value" /> + <xsl:text> + +</xsl:text> + </xsl:if> + </xsl:when> + <xsl:when test="@type = 'string'"> + <xsl:if test="$h"> + <xsl:text>extern </xsl:text> + </xsl:if> + <xsl:text>const char </xsl:text> + <xsl:value-of select="@name" /> + <xsl:text>[]</xsl:text> + <xsl:if test="$c"> + <xsl:text> = "</xsl:text> + <xsl:value-of select="@value" /> + <xsl:text>"</xsl:text> + </xsl:if> + <xsl:text>; + +</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:if test="$h"> + <xsl:text>extern </xsl:text> + </xsl:if> + <xsl:call-template name="type-and-name" /> + <xsl:if test="$c"> + <xsl:text> = </xsl:text> + <xsl:value-of select="@value" /> + </xsl:if> + <xsl:text>; + +</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="typedef" mode="output"> + <xsl:if test="$h"> + <xsl:text>typedef </xsl:text> + <xsl:value-of select="xcb:get-char-void(@oldname)" /> + <xsl:text> </xsl:text> + <xsl:value-of select="@newname" /> + <xsl:text>; + +</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="struct" mode="output"> + <xsl:if test="$h"> + <xsl:variable name="type-lengths"> + <xsl:call-template name="type-lengths"> + <xsl:with-param name="items" select="field/@type" /> + </xsl:call-template> + </xsl:variable> + <xsl:text>/** + * @brief </xsl:text><xsl:value-of select="@name" /><xsl:text> + **/ +</xsl:text> + <xsl:text>typedef </xsl:text> + <xsl:if test="not(@kind)">struct</xsl:if><xsl:value-of select="@kind" /> + <xsl:text> </xsl:text> + <xsl:value-of select="@name" /> + <xsl:text> { +</xsl:text> + <xsl:for-each select="exprfield|field|list[@fixed]|pad"> + <xsl:text> </xsl:text> + <xsl:apply-templates select="."> + <xsl:with-param name="type-lengths" select="$type-lengths" /> + </xsl:apply-templates> + <xsl:text>; /**< </xsl:text><xsl:text> */ +</xsl:text> + </xsl:for-each> + <xsl:text>} </xsl:text> + <xsl:value-of select="@name" /> + <xsl:text>; + +</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="enum" mode="output"> + <xsl:if test="$h"> + <xsl:text>typedef enum </xsl:text> + <xsl:value-of select="@name" /> + <xsl:text> { + </xsl:text> + <xsl:call-template name="list"> + <xsl:with-param name="separator"><xsl:text>, + </xsl:text></xsl:with-param> + <xsl:with-param name="items"> + <xsl:for-each select="item"> + <item> + <xsl:value-of select="@name" /> + <xsl:if test="node()"> <!-- If there is an expression --> + <xsl:text> = </xsl:text> + <xsl:apply-templates mode="output-expression" /> + </xsl:if> + </item> + </xsl:for-each> + </xsl:with-param> + </xsl:call-template> + <xsl:text> +} </xsl:text><xsl:value-of select="@name" /><xsl:text>; + +</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="function" mode="output"> + <xsl:variable name="decl-open" select="concat(@name, ' (')" /> + <xsl:variable name="type-lengths"> + <xsl:call-template name="type-lengths"> + <xsl:with-param name="items" select="field/@type" /> + </xsl:call-template> + </xsl:variable> + <!-- Doxygen for functions in header. --> + <xsl:if test="$h"> + <xsl:apply-templates select="doc" mode="function-doc"> + </xsl:apply-templates> + </xsl:if> +/***************************************************************************** + ** + ** <xsl:value-of select="@type" /> + <xsl:text> </xsl:text> + <xsl:value-of select="@name" /> + ** <xsl:call-template name="list"> + <xsl:with-param name="items"> + <xsl:for-each select="field"> + <item> + <xsl:text> + ** @param </xsl:text> + <xsl:apply-templates select="."> + <xsl:with-param name="type-lengths" select="$type-lengths" /> + </xsl:apply-templates> + </item> + </xsl:for-each> + </xsl:with-param> + </xsl:call-template> + ** @returns <xsl:value-of select="@type" /> + ** + *****************************************************************************/ + +<xsl:value-of select="@type" /> + <xsl:text> +</xsl:text> + <xsl:value-of select="$decl-open" /> + <xsl:call-template name="list"> + <xsl:with-param name="separator"> + <xsl:text>, +</xsl:text> + <xsl:call-template name="repeat"> + <xsl:with-param name="count" select="string-length($decl-open)" /> + </xsl:call-template> + </xsl:with-param> + <xsl:with-param name="items"> + <xsl:for-each select="field"> + <item> + <xsl:apply-templates select="."> + <xsl:with-param name="type-lengths" select="$type-lengths" /> + </xsl:apply-templates> + <xsl:text> /**< */</xsl:text> + </item> + </xsl:for-each> + </xsl:with-param> + </xsl:call-template> + <xsl:text>)</xsl:text> + + <xsl:if test="$h"><xsl:text>; + +</xsl:text></xsl:if> + + <xsl:if test="$c"> + <xsl:text> +{ +</xsl:text> + <xsl:apply-templates select="l|indent" mode="function-body"> + <xsl:with-param name="indent" select="$indent-string" /> + </xsl:apply-templates> + <xsl:text>} + +</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="doc" mode="function-doc"> + <xsl:value-of select="." /><xsl:text> +</xsl:text> + </xsl:template> + + <xsl:template match="l" mode="function-body"> + <xsl:param name="indent" /> + <xsl:value-of select="concat($indent, .)" /><xsl:text> +</xsl:text> + </xsl:template> + + <xsl:template match="indent" mode="function-body"> + <xsl:param name="indent" /> + <xsl:apply-templates select="l|indent" mode="function-body"> + <xsl:with-param name="indent" select="concat($indent, $indent-string)" /> + </xsl:apply-templates> + </xsl:template> + + <xsl:template match="value" mode="output-expression"> + <xsl:value-of select="." /> + </xsl:template> + + <xsl:template match="fieldref" mode="output-expression"> + <xsl:param name="field-prefix" /> + <xsl:value-of select="concat($field-prefix, .)" /> + </xsl:template> + + <xsl:template match="op" mode="output-expression"> + <xsl:param name="field-prefix" /> + <xsl:text>(</xsl:text> + <xsl:apply-templates select="node()[1]" mode="output-expression"> + <xsl:with-param name="field-prefix" select="$field-prefix" /> + </xsl:apply-templates> + <xsl:text> </xsl:text> + <xsl:value-of select="@op" /> + <xsl:text> </xsl:text> + <xsl:apply-templates select="node()[2]" mode="output-expression"> + <xsl:with-param name="field-prefix" select="$field-prefix" /> + </xsl:apply-templates> + <xsl:text>)</xsl:text> + </xsl:template> + + <xsl:template match="bit" mode="output-expression"> + <xsl:text>(1 << </xsl:text> + <xsl:value-of select="." /> + <xsl:text>)</xsl:text> + </xsl:template> + + <xsl:template match="function-call" mode="output-expression"> + <xsl:param name="field-prefix" /> + <xsl:value-of select="@name" /> + <xsl:text>(</xsl:text> + <xsl:call-template name="list"> + <xsl:with-param name="separator" select="', '" /> + <xsl:with-param name="items"> + <xsl:for-each select="param"> + <item><xsl:apply-templates mode="output-expression"> + <xsl:with-param name="field-prefix" select="$field-prefix" /> + </xsl:apply-templates></item> + </xsl:for-each> + </xsl:with-param> + </xsl:call-template> + <xsl:text>)</xsl:text> + </xsl:template> + + <!-- Catch invalid elements in expressions. --> + <xsl:template match="*" mode="output-expression"> + <xsl:message terminate="yes"> + <xsl:text>Invalid element in expression: </xsl:text> + <xsl:value-of select="name()" /> + </xsl:message> + </xsl:template> + + <xsl:template match="field|exprfield"> + <xsl:param name="type-lengths" select="0" /> + <xsl:call-template name="type-and-name"> + <xsl:with-param name="type-lengths" select="$type-lengths" /> + </xsl:call-template> + </xsl:template> + + <xsl:template match="list[@fixed]"> + <xsl:param name="type-lengths" select="0" /> + <xsl:call-template name="type-and-name"> + <xsl:with-param name="type-lengths" select="$type-lengths" /> + </xsl:call-template> + <xsl:text>[</xsl:text> + <xsl:apply-templates mode="output-expression" /> + <xsl:text>]</xsl:text> + </xsl:template> + + <xsl:template match="pad"> + <xsl:param name="type-lengths" select="0" /> + + <xsl:variable name="padnum"><xsl:number /></xsl:variable> + + <xsl:call-template name="type-and-name"> + <xsl:with-param name="type" select="'uint8_t'" /> + <xsl:with-param name="name"> + <xsl:text>pad</xsl:text> + <xsl:value-of select="$padnum - 1" /> + </xsl:with-param> + <xsl:with-param name="type-lengths" select="$type-lengths" /> + </xsl:call-template> + <xsl:if test="@bytes > 1"> + <xsl:text>[</xsl:text> + <xsl:value-of select="@bytes" /> + <xsl:text>]</xsl:text> + </xsl:if> + </xsl:template> + + <!-- Output the given type and name (defaulting to the corresponding + attributes of the context node), with the appropriate spacing. The + type must consist of a base type (which may contain spaces), then + optionally a single space and a suffix of one or more '*' characters. + If the type-lengths parameter is provided, use it to line up the base + types and suffixs of the type declarations. --> + <xsl:template name="type-and-name"> + <xsl:param name="type" select="@type" /> + <xsl:param name="name" select="@name" /> + <xsl:param name="type-lengths"> + <max-type-length>0</max-type-length> + <max-suffix-length>0</max-suffix-length> + </xsl:param> + + <xsl:variable name="type-lengths-ns" select="e:node-set($type-lengths)" /> + <xsl:variable name="min-type-length" + select="$type-lengths-ns/max-type-length" /> + <xsl:variable name="min-suffix-length" + select="$type-lengths-ns/max-suffix-length" /> + + <xsl:variable name="base-type"> + <xsl:choose> + <xsl:when test="contains($type, ' *')"> + <xsl:value-of select="substring-before($type, ' *')" /> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$type" /> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="suffix"> + <xsl:if test="contains($type, ' *')"> + <xsl:text>*</xsl:text> + <xsl:value-of select="substring-after($type, ' *')" /> + </xsl:if> + </xsl:variable> + + <xsl:value-of select="$base-type" /> + <xsl:if test="string-length($base-type) < $min-type-length"> + <xsl:call-template name="repeat"> + <xsl:with-param name="count" select="$min-type-length + - string-length($base-type)" /> + </xsl:call-template> + </xsl:if> + <xsl:text> </xsl:text> + <xsl:if test="string-length($suffix) < $min-suffix-length"> + <xsl:call-template name="repeat"> + <xsl:with-param name="count" select="$min-suffix-length + - string-length($suffix)" /> + </xsl:call-template> + </xsl:if> + <xsl:value-of select="$suffix" /> + <xsl:value-of select="$name" /> + </xsl:template> + + <!-- Output a list with a given separator. Empty items are skipped. --> + <xsl:template name="list"> + <xsl:param name="separator" /> + <xsl:param name="items" /> + + <xsl:for-each select="e:node-set($items)/*"> + <xsl:value-of select="." /> + <xsl:if test="not(position() = last())"> + <xsl:value-of select="$separator" /> + </xsl:if> + </xsl:for-each> + </xsl:template> + + <!-- Repeat a string (space by default) a given number of times. --> + <xsl:template name="repeat"> + <xsl:param name="str" select="' '" /> + <xsl:param name="count" /> + + <xsl:if test="$count > 0"> + <xsl:value-of select="$str" /> + <xsl:call-template name="repeat"> + <xsl:with-param name="str" select="$str" /> + <xsl:with-param name="count" select="$count - 1" /> + </xsl:call-template> + </xsl:if> + </xsl:template> + + <!-- Record the maximum type lengths of a set of types for use as the + max-type-lengths parameter of type-and-name. --> + <xsl:template name="type-lengths"> + <xsl:param name="items" /> + <xsl:variable name="type-lengths-rtf"> + <xsl:for-each select="$items"> + <item> + <xsl:choose> + <xsl:when test="contains(., ' *')"> + <xsl:value-of select="string-length( + substring-before(., ' *'))" /> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="string-length(.)" /> + </xsl:otherwise> + </xsl:choose> + </item> + </xsl:for-each> + </xsl:variable> + <xsl:variable name="suffix-lengths-rtf"> + <xsl:for-each select="$items"> + <item> + <xsl:choose> + <xsl:when test="contains(., ' *')"> + <xsl:value-of select="string-length(substring-after(., ' *')) + + 1" /> + </xsl:when> + <xsl:otherwise> + <xsl:text>0</xsl:text> + </xsl:otherwise> + </xsl:choose> + </item> + </xsl:for-each> + </xsl:variable> + <max-type-length> + <xsl:call-template name="max"> + <xsl:with-param name="items" + select="e:node-set($type-lengths-rtf)/*" /> + </xsl:call-template> + </max-type-length> + <max-suffix-length> + <xsl:call-template name="max"> + <xsl:with-param name="items" + select="e:node-set($suffix-lengths-rtf)/*" /> + </xsl:call-template> + </max-suffix-length> + </xsl:template> + + <!-- Return the maximum number in a set of numbers. --> + <xsl:template name="max"> + <xsl:param name="items" /> + <xsl:choose> + <xsl:when test="count($items) = 0"> + <xsl:text>0</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="head" select="number($items[1])" /> + <xsl:variable name="tail-max"> + <xsl:call-template name="max"> + <xsl:with-param name="items" select="$items[position() > 1]" /> + </xsl:call-template> + </xsl:variable> + <xsl:choose> + <xsl:when test="$head > number($tail-max)"> + <xsl:value-of select="$head" /> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$tail-max" /> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> +</xsl:transform> diff --git a/libxcb/src/xcb.h b/libxcb/src/xcb.h index f95127665..35d876883 100644 --- a/libxcb/src/xcb.h +++ b/libxcb/src/xcb.h @@ -285,6 +285,22 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c); */ xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie); +/** + * @brief Discards the reply for a request. + * @param c: The connection to the X server. + * @param sequence: The request sequence number from a cookie. + * + * Discards the reply for a request. Additionally, any error generated + * by the request is also discarded (unless it was an _unchecked request + * and the error has already arrived). + * + * This function will not block even if the reply is not yet available. + * + * Note that the sequence really does have to come from an xcb cookie; + * this function is not designed to operate on socket-handoff replies. + */ +void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence); + /* xcb_ext.c */ diff --git a/libxcb/src/xcb_auth.c b/libxcb/src/xcb_auth.c index 104f2f07b..00aad23c5 100644 --- a/libxcb/src/xcb_auth.c +++ b/libxcb/src/xcb_auth.c @@ -260,10 +260,10 @@ int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display) * case anyway.*/ if (getpeername(fd, sockname, &socknamelen) == -1) { - if (sockname->sa_family != AF_UNIX) - return 0; /* except for AF_UNIX, sockets should have peernames */ if (getsockname(fd, sockname, &socknamelen) == -1) return 0; /* can only authenticate sockets */ + if (sockname->sa_family != AF_UNIX) + return 0; /* except for AF_UNIX, sockets should have peernames */ gotsockname = 1; } diff --git a/libxcb/src/xcb_conn.c b/libxcb/src/xcb_conn.c index 251d62e01..ed2153d27 100644 --- a/libxcb/src/xcb_conn.c +++ b/libxcb/src/xcb_conn.c @@ -211,8 +211,10 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info) xcb_connection_t* c; c = calloc(1, sizeof(xcb_connection_t)); - if(!c) + if(!c) { + close(fd); return (xcb_connection_t *) &error_connection; + } c->fd = fd; diff --git a/libxcb/src/xcb_in.c b/libxcb/src/xcb_in.c index 26ab3581f..80f55232e 100644 --- a/libxcb/src/xcb_in.c +++ b/libxcb/src/xcb_in.c @@ -409,6 +409,116 @@ void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_ return ret; } +static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_next, uint64_t seq) +{ + pending_reply *pend; + pend = malloc(sizeof(*pend)); + if(!pend) + { + _xcb_conn_shutdown(c); + return; + } + + pend->first_request = seq; + pend->last_request = seq; + pend->workaround = 0; + pend->flags = XCB_REQUEST_DISCARD_REPLY; + pend->next = *prev_next; + *prev_next = pend; + + if(!pend->next) + c->in.pending_replies_tail = &pend->next; +} + +static void discard_reply(xcb_connection_t *c, unsigned int request) +{ + pending_reply *pend = 0; + pending_reply **prev_pend; + uint64_t widened_request; + + /* We've read requests past the one we want, so if it has replies we have + * them all and they're in the replies map. */ + if(XCB_SEQUENCE_COMPARE_32(request, <, c->in.request_read)) + { + struct reply_list *head; + head = _xcb_map_remove(c->in.replies, request); + while (head) + { + struct reply_list *next = head->next; + free(head->reply); + free(head); + head = next; + } + return; + } + + /* We're currently processing the responses to the request we want, and we + * have a reply ready to return. Free it, and mark the pend to free any further + * replies. */ + if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_read) && c->in.current_reply) + { + struct reply_list *head; + head = c->in.current_reply; + c->in.current_reply = NULL; + c->in.current_reply_tail = &c->in.current_reply; + while (head) + { + struct reply_list *next = head->next; + free(head->reply); + free(head); + head = next; + } + + pend = c->in.pending_replies; + if(pend && + !(XCB_SEQUENCE_COMPARE(pend->first_request, <=, c->in.request_read) && + (pend->workaround == WORKAROUND_EXTERNAL_SOCKET_OWNER || + XCB_SEQUENCE_COMPARE(c->in.request_read, <=, pend->last_request)))) + pend = 0; + if(pend) + pend->flags |= XCB_REQUEST_DISCARD_REPLY; + else + insert_pending_discard(c, &c->in.pending_replies, c->in.request_read); + + return; + } + + /* Walk the list of pending requests. Mark the first match for deletion. */ + for(prev_pend = &c->in.pending_replies; *prev_pend; prev_pend = &(*prev_pend)->next) + { + if(XCB_SEQUENCE_COMPARE_32((*prev_pend)->first_request, >, request)) + break; + + if(XCB_SEQUENCE_COMPARE_32((*prev_pend)->first_request, ==, request)) + { + /* Pending reply found. Mark for discard: */ + (*prev_pend)->flags |= XCB_REQUEST_DISCARD_REPLY; + return; + } + } + + /* Pending reply not found (likely due to _unchecked request). Create one: */ + widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request; + if(widened_request > c->out.request) + widened_request -= UINT64_C(1) << 32; + + insert_pending_discard(c, prev_pend, widened_request); +} + +void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence) +{ + if(c->has_error) + return; + + /* If an error occurred when issuing the request, fail immediately. */ + if(!sequence) + return; + + pthread_mutex_lock(&c->iolock); + discard_reply(c, sequence); + pthread_mutex_unlock(&c->iolock); +} + int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, xcb_generic_error_t **error) { int ret; diff --git a/libxcb/src/xcb_util.c b/libxcb/src/xcb_util.c index c3cbfa6c1..996ff2518 100644 --- a/libxcb/src/xcb_util.c +++ b/libxcb/src/xcb_util.c @@ -41,6 +41,7 @@ #include <stdlib.h> #include <stddef.h> #include <unistd.h> +#include <fcntl.h> #include <string.h> #include "xcb.h" @@ -177,6 +178,22 @@ static int _xcb_open(char *host, char *protocol, const int display) return _xcb_open_unix(protocol, file); } +static int _xcb_socket(int family, int type, int proto) +{ + int fd; + +#ifdef SOCK_CLOEXEC + fd = socket(family, type | SOCK_CLOEXEC, proto); + if (fd == -1 && errno == EINVAL) +#endif + { + fd = socket(family, type, proto); + if (fd >= 0) + fcntl(fd, F_SETFD, FD_CLOEXEC); + } + return fd; +} + #ifdef DNETCONN static int _xcb_open_decnet(const char *host, const char *protocol, const unsigned short port) { @@ -199,7 +216,7 @@ static int _xcb_open_decnet(const char *host, const char *protocol, const unsign return -1; addr.sdn_objnum = 0; - fd = socket(PF_DECnet, SOCK_STREAM, 0); + fd = _xcb_socket(PF_DECnet, SOCK_STREAM, 0); if(fd == -1) return -1; @@ -256,7 +273,7 @@ static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port) for(addr = results; addr; addr = addr->ai_next) { - fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if(fd >= 0) { int on = 1; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); @@ -285,7 +302,7 @@ static int _xcb_open_unix(char *protocol, const char *file) #ifdef HAVE_SOCKADDR_SUN_LEN addr.sun_len = SUN_LEN(&addr); #endif - fd = socket(AF_UNIX, SOCK_STREAM, 0); + fd = _xcb_socket(AF_UNIX, SOCK_STREAM, 0); if(fd == -1) return -1; if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) { @@ -311,7 +328,7 @@ static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen) #ifdef HAVE_SOCKADDR_SUN_LEN addr.sun_len = 1 + filelen; #endif - fd = socket(AF_UNIX, SOCK_STREAM, 0); + fd = _xcb_socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) return -1; if (connect(fd, (struct sockaddr *) &addr, namelen) == -1) { |