upload tizen2.0 source 2.0alpha master 2.0_alpha submit/master/20120920.151152
authorBoram Park <boram1288.park@samsung.com>
Tue, 21 Aug 2012 09:03:51 +0000 (18:03 +0900)
committerBoram Park <boram1288.park@samsung.com>
Tue, 21 Aug 2012 09:03:51 +0000 (18:03 +0900)
23 files changed:
INSTALL [new file with mode: 0644]
Makefile.am
NEWS [changed mode: 0755->0644]
acinclude.m4 [changed mode: 0755->0644]
configure.ac [changed mode: 0755->0644]
doc/Makefile.am
doc/tutorial/index.html [changed mode: 0755->0644]
doc/xkb_internals [new file with mode: 0644]
doc/xkb_issues [new file with mode: 0644]
packaging/libxcb.spec
src/Makefile.am
src/c-client.xsl [deleted file]
src/c_client.py [changed mode: 0755->0644]
src/xcb.h
src/xcb_auth.c [changed mode: 0755->0644]
src/xcb_conn.c [changed mode: 0755->0644]
src/xcb_in.c [changed mode: 0755->0644]
src/xcb_out.c [changed mode: 0755->0644]
src/xcb_util.c [changed mode: 0755->0644]
src/xcb_windefs.h [new file with mode: 0644]
src/xcbext.h
src/xcbint.h [changed mode: 0755->0644]
xcb-xkb.pc.in [new file with mode: 0644]

diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..54caf7c
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,229 @@
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+   This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
index ff9dea1..1f88b72 100644 (file)
@@ -58,6 +58,9 @@ endif
 if BUILD_XINPUT
 pkgconfig_DATA += xcb-xinput.pc
 endif
+if BUILD_XKB
+pkgconfig_DATA += xcb-xkb.pc
+endif
 if BUILD_XPRINT
 pkgconfig_DATA += xcb-xprint.pc
 endif
diff --git a/NEWS b/NEWS
old mode 100755 (executable)
new mode 100644 (file)
index 7969813..66d6253
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,58 @@
+Release 1.8.1 (2012-03-09)
+==========================
+- Fix a busy loop on BSD and Mac OS
+- Bump xcb-proto requirement
+- Fallback to TCP if no protocol is specified and the UNIX connection fails
+- Update use of error_connection under WIN32 to _xcb_conn_ret_error()
+- Fix build of xcb_auth.c with XDMCP on WIN32
+- Revert "Fix include order with Xdmcp on WIN32"
+- darwin: Use read(2) rather than recv(2)
+- Add xkb_internals and xkb_issues to EXTRA_DIST.
+
+Release 1.8 (2012-01-11)
+========================
+- xcb_disconnect: call shutdown() to force a disconnect
+- Use special path to sockets when running under Solaris Trusted Extensions
+- Remove unused DECnet code
+- Add #include <sys/socket.h> to xcb_conn.c
+- Make launchd code in xcb_util.c match surrounding code indent levels
+- If protocol is "unix", use a Unix domain socket, not TCP
+- Added more error states and removed global error_connection
+- Handle XGE events with the "send event" flag
+- added xcb_sumof() with restriction to uint8_t
+- xkb: updated configure.ac/Makefile.am
+- xkb: added pkg config file
+- special case 'intermixed variable and fixed size fields': fixed reply side, needs testing
+- added accessors for special cases
+- Add support for building with Python 3
+- Insert, not append explicit xcbgen dir python path
+- xcb_request_check: Sync even if an event was read for this sequence.
+- _xcb_conn_wait: Shut down the connection on unexpected poll() events.
+- xcb_send_request: Send all requests using a common internal send_request.
+- xcb_request_check: Hold the I/O lock while deciding to sync.
+- xcb_discard_reply: Simplify by re-using poll_for_reply helper.
+- xcb_in: Use 64-bit sequence numbers internally everywhere.
+- Enable AM_SILENT_RULES on automake 1.11 or newer.
+- Factor reader_list management out of wait_for_reply.
+- Dequeue readers that can't receive any new responses.
+- Delete the old c-client.xsl.
+- Keep ALIGNOF definition out of the public namespace.
+- darwin: Don't use poll() when expected to run on darwin10 and prior
+- Add Win32
+- Allow disconnecting connections that are in error state.
+- Make xcb_take_socket keep flushing until idle
+- Support pre-IPv6 systems (without getaddrinfo)
+- Drop AI_ADDRCONFIG when resolving TCP addresses
+- xcb_auth: Fix memory leak in _xcb_get_auth_info.
+- Don't emit out-of-module sizeof definitions
+- Clean up a couple of warnings in xprint
+- Prevent reply waiters from being blocked.
+- Prevent theoretical double free and leak on get_peer_sock_name.
+- Introduce a variant of xcb_poll_for_event for examining event queue.
+- xcb_take_socket: Document sequence wrap requirements
+- Compute alignment correctly
+- Fix a dead-lock due to xcb_poll_for_reply
+
 Release 1.7 (2010-08-13)
 ========================
 - Always wake up readers after writing
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 4178989..e94e32c
@@ -3,18 +3,20 @@
 
 AC_PREREQ(2.57)
 AC_INIT([libxcb],
-        1.7,
+        1.8.1,
         [xcb@lists.freedesktop.org])
 AC_CONFIG_SRCDIR([xcb.pc.in])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
-AM_PATH_PYTHON([2.5])
+AM_PATH_PYTHON([2.6])
 
 PKG_CHECK_MODULES(CHECK, [check >= 0.9.4], [HAVE_CHECK=yes], [HAVE_CHECK=no])
 AM_CONDITIONAL(HAVE_CHECK, test x$HAVE_CHECK = xyes)
 
 AC_CONFIG_HEADERS([src/config.h])
 
+AC_LIBTOOL_WIN32_DLL
 AC_PROG_LIBTOOL
 AC_PROG_CC
 
@@ -32,7 +34,7 @@ fi
 AC_SUBST(HTML_CHECK_RESULT)
 
 # Checks for pkg-config packages
-PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.6)
+PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.7)
 NEEDED="pthread-stubs xau >= 0.99.2"
 PKG_CHECK_MODULES(NEEDED, $NEEDED)
 
@@ -72,12 +74,21 @@ AC_HEADER_STDC
 AC_SEARCH_LIBS(getaddrinfo, socket)
 AC_SEARCH_LIBS(connect, socket)
 
+have_win32="no"
+lt_enable_auto_import=""
 case $host_os in
+mingw*)
+       have_win32="yes"
+       lt_enable_auto_import="-Wl,--enable-auto-import"
+       ;;
 linux*)
        AC_DEFINE([HAVE_ABSTRACT_SOCKETS], 1, [Define if your platform supports abstract sockets])
        ;;
 esac
 
+AC_SUBST(lt_enable_auto_import)
+AM_CONDITIONAL([XCB_HAVE_WIN32], [test "x${have_win32}" = "xyes"])
+
 dnl define buffer queue size
 AC_ARG_WITH([queue-size],
             AC_HELP_STRING([--with-queue-size=SIZE],
@@ -95,6 +106,10 @@ AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
                  #include <sys/un.h>
                ])
 
+dnl check for support for Solaris Trusted Extensions
+AC_CHECK_HEADERS([tsol/label.h])
+AC_CHECK_FUNCS([is_system_labeled])
+
 xcbincludedir='${includedir}/xcb'
 AC_SUBST(xcbincludedir)
 
@@ -120,9 +135,26 @@ AC_PREREQ([2.59c], [], [AC_SUBST([htmldir], [m4_ifset([AC_PACKAGE_TARNAME],
 
 XCB_CHECK_DOXYGEN()
 
+AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAVE_GETADDRINFO, 1, [getaddrinfo() function is available])], )
+
 case $host_os in
-       # darwin has poll() but can't be used to poll character devices (atleast through SnowLeopard)
-       darwin*) ;;
+       # darwin through Snow Leopard has poll() but can't be used to poll character devices.
+       darwin@<:@789@:>@*|darwin10*) ;;
+       darwin*)
+               _ac_xorg_macosx_version_min=""
+               if echo $CPPFLAGS $CFLAGS | grep -q mmacosx-version-min ; then
+                       _ac_xorg_macosx_version_min=`echo $CPPFLAGS $CFLAGS | sed 's/^.*-mmacosx-version-min=\(@<:@^ @:>@*\).*$/\1/'`
+               else
+                       _ac_xorg_macosx_version_min=$MACOSX_DEPLOYMENT_TARGET
+               fi
+               case $_ac_xorg_macosx_version_min in
+                       10.@<:@0123456@:>@|10.@<:@0123456@:>@.*) ;;
+                       *)
+                               AC_CHECK_FUNC(poll, [AC_DEFINE(USE_POLL, 1, [poll() function is available])], )
+                       ;;
+               esac
+               unset _ac_xorg_macosx_version_min
+               ;;
        *)
                AC_CHECK_FUNC(poll, [AC_DEFINE(USE_POLL, 1, [poll() function is available])], )
        ;;
@@ -146,6 +178,7 @@ XCB_EXTENSION(XFixes, "yes")
 XCB_EXTENSION(XFree86-DRI, "yes")
 XCB_EXTENSION(Xinerama, "yes")
 XCB_EXTENSION(XInput, "no")
+XCB_EXTENSION(XKB, "no")
 XCB_EXTENSION(Xprint, "yes")
 XCB_EXTENSION(SELinux, "no")
 XCB_EXTENSION(XTest, "yes")
@@ -189,6 +222,7 @@ xcb-xf86dri.pc
 xcb-xfixes.pc
 xcb-xinerama.pc
 xcb-xinput.pc
+xcb-xkb.pc
 xcb-xprint.pc
 xcb-xselinux.pc
 xcb-xtest.pc
@@ -232,6 +266,7 @@ echo "    Xfixes..............: ${BUILD_XFIXES}"
 echo "    Xfree86-dri.........: ${BUILD_XFREE86_DRI}"
 echo "    xinerama............: ${BUILD_XINERAMA}"
 echo "    xinput..............: ${BUILD_XINPUT}"
+echo "    xkb.................: ${BUILD_XKB}"
 echo "    xprint..............: ${BUILD_XPRINT}"
 echo "    xtest...............: ${BUILD_XTEST}"
 echo "    xv..................: ${BUILD_XV}"
index 1925519..dbe2e0b 100644 (file)
@@ -2,7 +2,9 @@
 EXTRA_DIST = \
 tutorial/index.html \
 tutorial/xcb.css \
-xcb.doxygen.in
+xcb.doxygen.in \
+xkb_internals \
+xkb_issues
 
 docdirs = $(srcdir)/tutorial
 
old mode 100755 (executable)
new mode 100644 (file)
index aa3ae17..adec0ac
@@ -1453,7 +1453,7 @@ typedef enum {
 </pre>
         <p>
         If the window has already been created, we can use the
-        <span class="code">xcb_configure_window()</span> function to set
+        <span class="code">xcb_change_window_attributes()</span> function to set
         the events that the window will receive. The subsection
         <a href="#winconf">Configuring a window</a> shows its
         prototype. As an example, here is a piece of code that
@@ -1466,7 +1466,7 @@ const static uint32_t values[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTT
 
 /* The connection c and the window win are supposed to be defined */
 
-xcb_configure_window (c, win, XCB_CW_EVENT_MASK, values);
+xcb_change_window_attributes (c, win, XCB_CW_EVENT_MASK, values);
 </pre>
         <div class="emph">
         <p>
diff --git a/doc/xkb_internals b/doc/xkb_internals
new file mode 100644 (file)
index 0000000..93c6d01
--- /dev/null
@@ -0,0 +1,49 @@
+
+XKB introduces several uncommon data structures:
+ - switch allows conditional inclusion of fields
+ - several complex objects intermix variable and fixed size fields
+ - lists with a variable number of variable size objects
+
+To handle these objects, a number of new functions is generated:
+ - _serialize() turns a structured object into a byte stream, 
+   (re)ordering or including fields according to the protocol
+ - _unserialize() rewrites data from a buffer into a structured object
+ - _unpack() expands a buffer representing a switch object into 
+   a special structured type, all flags needed to resolve the switch
+   expression have to given as parameters
+ - _sizeof() calculates the size of a serialized object, often by calling
+   _unserialize()/_unpack() internally
+
+The new structured data type for switch is special as it contains fixed 
+and variable size fields. Variable size fields can be accessed via pointers. 
+
+If switch appears in a request, an additional set of request helpers is 
+generated with the suffix _aux or _aux_(un)checked. While the 'common'
+request functions require that switch has been serialized before, the _aux
+variants take the structured data type. They are especially designed to 
+replace certain functions in xcb-util/aux. 
+
+Accessors for switch members need two parameters, where the first is usually
+a pointer to the respective request or reply structure, while the second 
+is a pointer to the unpacked switch data structure. 
+
+Functions from the serialize family that take a double pointer can allocate 
+memory on their own, which is useful if the size of a buffer has to be 
+calculated depending on the data within. These functions call malloc() when 
+the double pointer is given as the address of a pointer that has been 
+initialized to 0. It is the responsibility of the user to free any allocated
+memory. 
+
+Intermixed variable and fixed size fields are an important special case in XKB. 
+The current implementation resolves the issue by reordering the fields before
+sending them on the wire as well as before returning a reply. That means that 
+these objects look like 'common' XCB data types and they can be accessed as such 
+(i.e. fixed size fields directly via the structured type and variable size fields
+via accessors/iterators).  
+
+In case a list with variable size elements needs to be accessed, it is necessary 
+to use iterators. The iterator functions take care of determining the actual 
+object size for each element automatically. 
+
+A small and preliminary set of auxiliary functions is available in xkb_util.c 
+in the check_xkb module.  
diff --git a/doc/xkb_issues b/doc/xkb_issues
new file mode 100644 (file)
index 0000000..80efcc1
--- /dev/null
@@ -0,0 +1,38 @@
+
+There are a number of problematic special cases in XKB. The issues 
+mentioned here are at most partly resolved.
+1. The are several XxxDoodad structures defined in xkb.xml. They are used
+   in a few lists, but in a rather special way: 
+   The struct "CommonDoodad" is supposed to be a rather generic data type, 
+   combining the most basic Doodad fields that are common in all these structures. 
+   All Doodads are encapsulated in a union type simply called "Doodad". 
+   Now this union is used in subsequent list definitions, aiming at a kind of 
+   'polymorphism': From inspection of the protocol and Xlib, the Doodads are to 
+   be discriminated based on their type field.
+   However the special meaning of the type field is not encoded in the protocol. 
+   Furthermore the TextDoodad and the LogoDoodad are variable size types due to
+   some fields of type CountedString16, thereby turning the union into a 
+   possibly variable size type as well. 
+   However, for lists with variable size elements, special sizeof functions are 
+   required. These cannot be autogenerated as it cannot be referred which 
+   Doodad type to use for the union. 
+   Therefore, the Doodad type structures are unsupported at the moment. 
+
+2. There are still some bugs in xkb.xml: Either certain fields are missing
+   that are required by the protocol, or Xlib simply has another understanding
+   of the protocol. 
+
+3. The interface for accessors should be reviewed. 
+
+4. Currently some bitcases carry 'name' attributes. These could be avoided if 
+   the data within would consist of a singe struct field only. 
+
+5. switch could get a 'fixed_size' attribute, so when rewriting valueparam to switch, 
+   an uint32_t * pointer could be used instead of void *. 
+
+6. The automatic inclusion of padding requires some complicated coding in the 
+   generator. This is errorprone and could be avoided if all padding is explicitly
+   given in the protocol definition. For variable size fields that require padding, 
+   the pad tag could get a 'fieldref' attribute. That way padding could be handled
+   a lot easier in the autogenerator. 
\ No newline at end of file
index b7eb978..f76dafd 100644 (file)
@@ -1,82 +1,86 @@
-Name:       libxcb
-Summary:    A C binding to the X11 protocol
-Version: 1.7
-Release:    0
-Group:      System/Libraries
-License:    MIT
-URL:        http://xcb.freedesktop.org/
-Source0:    http://xcb.freedesktop.org/dist/%{name}-%{version}.tar.gz
-Requires(post): /sbin/ldconfig
-Requires(postun): /sbin/ldconfig
-BuildRequires:  pkgconfig(xorg-macros)
-BuildRequires:  pkgconfig(pthread-stubs)
-BuildRequires:  pkgconfig(xcb-proto)
-BuildRequires:  pkgconfig(xau)
+Name:    libxcb
+Summary: A C binding to the X11 protocol
+Version: 1.8.1
+Release: 1
+Group:   System/Libraries
+License: MIT
+URL:     http://xcb.freedesktop.org/
+Source0: http://xcb.freedesktop.org/dist/%{name}-%{version}.tar.gz
+
+BuildRequires:  xorg-x11-xutils-dev
+BuildRequires:  libpthread-stubs
+BuildRequires:  libXau-devel
 BuildRequires:  pkgconfig(xproto)
+BuildRequires:  xcb-proto >= 1.6
 BuildRequires:  libxslt
 BuildRequires:  python
 BuildRequires:  python-xml
 
+Requires(post):   /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
 
 %description
 Description: %{summary}
-
+The X protocol C-language Binding (XCB) is a replacement for Xlib featuring a
+small footprint, latency hiding, direct access to the protocol, improved
+threading support, and extensibility.
 
 %package devel
-Summary:    Development files for %{name}
-Group:      Development/Libraries
-Requires:   %{name} = %{version}-%{release}
-Requires:   libpthread-stubs
-BuildRequires:  pkgconfig(xau)
+Summary: Development files for %{name}
+Group:   Development/Libraries
 
-%description devel
-Description: %{summary}
+BuildRequires: libXau-devel
 
-%package doc
-Summary:    Documentation for %{name}
-Group:      Documentation
-Requires:   %{name} = %{version}-%{release}
+Requires: %{name} = %{version}-%{release}
+Requires: libpthread-stubs
 
-%description doc
-Description: %{summary}
+%description    devel
+The %{name}-devel package contains libraries and header files for
+developing applications that use %{name}.
 
+%package        doc
+Summary:        Documentation for %{name}
+Group:          Documentation
+BuildArch:     noarch
+
+%description    doc
+The %{name}-doc package contains documentation for the %{name} library.
 
 %prep
 %setup -q
 
-
 %build
 
+./autogen.sh
 %reconfigure \
     --disable-build-docs \
-    CFLAGS="-D_F_ENABLE_XI2_SENDEVENT_" \
-    LDFLAGS="-Wl,--hash-style=both -Wl,--as-needed"
-    
+    LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed"
 
+# Call make instruction with smp support
 make %{?jobs:-j%jobs}
 
 %install
 rm -rf %{buildroot}
-%make_install 
-
-
-
-
-%post -p /sbin/ldconfig
-
-%postun -p /sbin/ldconfig
-
+%make_install
 
+rm -f $RPM_BUILD_ROOT/%{_libdir}/libxcb-xprint.so*
+rm -f $RPM_BUILD_ROOT/%{_includedir}/xcb/xprint.h
 
+find $RPM_BUILD_ROOT -name '*.la' -delete
 
+%remove_docs
 
 
+%clean
+rm -rf $RPM_BUILD_ROOT
 
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
 
 %files
 %defattr(-,root,root,-)
-%{_libdir}/*.so.*
-
+%{_libdir}/libxcb.so.1*
+%{_libdir}/libxcb-*
 
 %files devel
 %defattr(-,root,root,-)
@@ -84,6 +88,6 @@ rm -rf %{buildroot}
 %{_libdir}/*.so
 %{_libdir}/pkgconfig/*.pc
 
-%files doc
-%defattr(-,root,root,-)
-%{_datadir}/doc/%{name}
+#%files doc
+#%defattr(-,root,root,-)
+#%{_datadir}/doc/%{name}
index f0bdeaa..950de5c 100644 (file)
@@ -18,7 +18,7 @@ nodist_libxcb_la_SOURCES = xproto.c bigreq.c xc_misc.c
 # * If you add an interface, increment current and age and set revision to 0.
 # * If you change or remove an interface, increment current and set revision
 #   and age to 0.
-libxcb_la_LDFLAGS = -version-info 2:0:1 -no-undefined
+libxcb_la_LDFLAGS = -version-info 2:0:1 -no-undefined @lt_enable_auto_import@
 
 XCB_LIBS = libxcb.la
 
@@ -27,7 +27,7 @@ XCB_LIBS = libxcb.la
 EXTSOURCES += composite.c
 if BUILD_COMPOSITE
 lib_LTLIBRARIES += libxcb-composite.la
-libxcb_composite_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_composite_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_composite_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_composite_la_SOURCES = composite.c composite.h
 endif
@@ -35,7 +35,7 @@ endif
 EXTSOURCES += damage.c
 if BUILD_DAMAGE
 lib_LTLIBRARIES += libxcb-damage.la
-libxcb_damage_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_damage_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_damage_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_damage_la_SOURCES = damage.c damage.h
 endif
@@ -43,7 +43,7 @@ endif
 EXTSOURCES += dpms.c
 if BUILD_DPMS
 lib_LTLIBRARIES += libxcb-dpms.la
-libxcb_dpms_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_dpms_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_dpms_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_dpms_la_SOURCES = dpms.c dpms.h
 endif
@@ -51,7 +51,7 @@ endif
 EXTSOURCES += dri2.c
 if BUILD_DRI2
 lib_LTLIBRARIES += libxcb-dri2.la
-libxcb_dri2_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_dri2_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_dri2_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_dri2_la_SOURCES = dri2.c dri2.h
 endif
@@ -59,7 +59,7 @@ endif
 EXTSOURCES += glx.c
 if BUILD_GLX
 lib_LTLIBRARIES += libxcb-glx.la
-libxcb_glx_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_glx_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_glx_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_glx_la_SOURCES = glx.c glx.h
 endif
@@ -67,7 +67,7 @@ endif
 EXTSOURCES += randr.c
 if BUILD_RANDR
 lib_LTLIBRARIES += libxcb-randr.la
-libxcb_randr_la_LDFLAGS = -version-info 1:0:1 -no-undefined
+libxcb_randr_la_LDFLAGS = -version-info 1:0:1 -no-undefined @lt_enable_auto_import@
 libxcb_randr_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_randr_la_SOURCES = randr.c randr.h
 endif
@@ -75,7 +75,7 @@ endif
 EXTSOURCES += record.c
 if BUILD_RECORD
 lib_LTLIBRARIES += libxcb-record.la
-libxcb_record_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_record_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_record_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_record_la_SOURCES = record.c record.h
 endif
@@ -83,7 +83,7 @@ endif
 EXTSOURCES += render.c
 if BUILD_RENDER
 lib_LTLIBRARIES += libxcb-render.la
-libxcb_render_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_render_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_render_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_render_la_SOURCES = render.c render.h
 endif
@@ -91,7 +91,7 @@ endif
 EXTSOURCES += res.c
 if BUILD_RESOURCE
 lib_LTLIBRARIES += libxcb-res.la
-libxcb_res_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_res_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_res_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_res_la_SOURCES = res.c res.h
 endif
@@ -99,7 +99,7 @@ endif
 EXTSOURCES += screensaver.c
 if BUILD_SCREENSAVER
 lib_LTLIBRARIES += libxcb-screensaver.la
-libxcb_screensaver_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_screensaver_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_screensaver_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_screensaver_la_SOURCES = screensaver.c screensaver.h
 endif
@@ -107,7 +107,7 @@ endif
 EXTSOURCES += shape.c
 if BUILD_SHAPE
 lib_LTLIBRARIES += libxcb-shape.la
-libxcb_shape_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_shape_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_shape_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_shape_la_SOURCES = shape.c shape.h
 endif
@@ -115,7 +115,7 @@ endif
 EXTSOURCES += shm.c
 if BUILD_SHM
 lib_LTLIBRARIES += libxcb-shm.la
-libxcb_shm_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_shm_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_shm_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_shm_la_SOURCES = shm.c shm.h
 endif
@@ -123,7 +123,7 @@ endif
 EXTSOURCES += sync.c
 if BUILD_SYNC
 lib_LTLIBRARIES += libxcb-sync.la
-libxcb_sync_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_sync_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_sync_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_sync_la_SOURCES = sync.c sync.h
 endif
@@ -131,7 +131,7 @@ endif
 EXTSOURCES += xevie.c
 if BUILD_XEVIE
 lib_LTLIBRARIES += libxcb-xevie.la
-libxcb_xevie_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xevie_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xevie_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xevie_la_SOURCES = xevie.c xevie.h
 endif
@@ -139,7 +139,7 @@ endif
 EXTSOURCES += xf86dri.c
 if BUILD_XFREE86_DRI
 lib_LTLIBRARIES += libxcb-xf86dri.la
-libxcb_xf86dri_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xf86dri_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xf86dri_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xf86dri_la_SOURCES = xf86dri.c xf86dri.h
 endif
@@ -147,7 +147,7 @@ endif
 EXTSOURCES += xfixes.c
 if BUILD_XFIXES
 lib_LTLIBRARIES += libxcb-xfixes.la
-libxcb_xfixes_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xfixes_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xfixes_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xfixes_la_SOURCES = xfixes.c xfixes.h
 endif
@@ -155,7 +155,7 @@ endif
 EXTSOURCES += xinerama.c
 if BUILD_XINERAMA
 lib_LTLIBRARIES += libxcb-xinerama.la
-libxcb_xinerama_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xinerama_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xinerama_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xinerama_la_SOURCES = xinerama.c xinerama.h
 endif
@@ -163,15 +163,23 @@ endif
 EXTSOURCES += xinput.c
 if BUILD_XINPUT
 lib_LTLIBRARIES += libxcb-xinput.la
-libxcb_xinput_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xinput_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xinput_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xinput_la_SOURCES = xinput.c xinput.h
 endif
 
+EXTSOURCES += xkb.c
+if BUILD_XKB
+lib_LTLIBRARIES += libxcb-xkb.la
+libxcb_xkb_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xkb_la_LIBADD = $(XCB_LIBS)
+nodist_libxcb_xkb_la_SOURCES = xkb.c xkb.h
+endif
+
 EXTSOURCES += xprint.c
 if BUILD_XPRINT
 lib_LTLIBRARIES += libxcb-xprint.la
-libxcb_xprint_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xprint_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xprint_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xprint_la_SOURCES = xprint.c xprint.h
 endif
@@ -179,7 +187,7 @@ endif
 EXTSOURCES += xselinux.c
 if BUILD_SELINUX
 lib_LTLIBRARIES += libxcb-xselinux.la
-libxcb_xselinux_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xselinux_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xselinux_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xselinux_la_SOURCES = xselinux.c xselinux.h
 endif
@@ -187,7 +195,7 @@ endif
 EXTSOURCES += xtest.c
 if BUILD_XTEST
 lib_LTLIBRARIES += libxcb-xtest.la
-libxcb_xtest_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xtest_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xtest_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xtest_la_SOURCES = xtest.c xtest.h
 endif
@@ -195,7 +203,7 @@ endif
 EXTSOURCES += xv.c
 if BUILD_XV
 lib_LTLIBRARIES += libxcb-xv.la
-libxcb_xv_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xv_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xv_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xv_la_SOURCES = xv.c xv.h
 endif
@@ -203,7 +211,7 @@ endif
 EXTSOURCES += xvmc.c
 if BUILD_XVMC
 lib_LTLIBRARIES += libxcb-xvmc.la
-libxcb_xvmc_la_LDFLAGS = -version-info 0:0:0 -no-undefined
+libxcb_xvmc_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
 libxcb_xvmc_la_LIBADD = $(XCB_LIBS)
 nodist_libxcb_xvmc_la_SOURCES = xvmc.c xvmc.h
 endif
@@ -211,6 +219,9 @@ endif
 
 EXTHEADERS=$(EXTSOURCES:.c=.h)
 xcbinclude_HEADERS = xcb.h xcbext.h
+if XCB_HAVE_WIN32
+xcbinclude_HEADERS += xcb_windefs.h
+endif
 nodist_xcbinclude_HEADERS = $(EXTHEADERS)
 noinst_HEADERS = xcbint.h
 
diff --git a/src/c-client.xsl b/src/c-client.xsl
deleted file mode 100755 (executable)
index a15d824..0000000
+++ /dev/null
@@ -1,1551 +0,0 @@
-<?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="&lt;&lt;">
-                <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() &lt; 3]" />
-      <xsl:if test="middle and (count(*[not(self::middle)]) &lt; 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>&amp;</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 *) &amp;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 &amp; 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 &amp; 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, &amp;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(&amp;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 &lt;string.h&gt;</xsl:if>
-<xsl:text>
-#include &lt;assert.h&gt;
-#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>; /**&lt; </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>  /**&lt; */</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 &lt;&lt; </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) &lt; $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) &lt; $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 &gt; 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>
old mode 100755 (executable)
new mode 100644 (file)
index 4f3b089..ad3ea22
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 from xml.etree.cElementTree import *
 from os.path import basename
+from functools import reduce
 import getopt
 import sys
 import re
@@ -16,6 +17,7 @@ _extension_special_cases = ['XPrint', 'XCMisc', 'BigRequests']
 _cplusplus_annoyances = {'class' : '_class',
                          'new'   : '_new',
                          'delete': '_delete'}
+_c_keywords = {'default' : '_default'}
 
 _hlines = []
 _hlevel = 0
@@ -23,6 +25,12 @@ _clines = []
 _clevel = 0
 _ns = None
 
+# global variable to keep track of serializers and 
+# switch data types due to weird dependencies
+finished_serializers = []
+finished_sizeof = []
+finished_switch = []
+
 def _h(fmt, *args):
     '''
     Writes the given line to the header file.
@@ -81,6 +89,8 @@ def _cpp(str):
     '''
     if str in _cplusplus_annoyances:
         return _cplusplus_annoyances[str]
+    elif str in _c_keywords:
+        return  _c_keywords[str]
     else:
         return str
 
@@ -158,11 +168,16 @@ def c_open(self):
     _h('')
     _h('#include "xcb.h"')
 
+    _c('#include <stdlib.h>')
     _c('#include <string.h>')
     _c('#include <assert.h>')
+    _c('#include <stddef.h>  /* for offsetof() */')
     _c('#include "xcbext.h"')
     _c('#include "%s.h"', _ns.header)
         
+    _c('')
+    _c('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)')
+
     if _ns.is_ext:
         for (n, h) in self.imports:
             _hc('#include "%s.h"', h)
@@ -273,7 +288,30 @@ def _c_type_setup(self, name, postfix):
     self.c_reply_type = _t(name + ('reply',))
     self.c_cookie_type = _t(name + ('cookie',))
 
-    if self.is_container:
+    self.need_aux = False
+    self.need_serialize = False
+    self.need_sizeof = False
+
+    self.c_aux_name = _n(name + ('aux',))
+    self.c_aux_checked_name = _n(name + ('aux', 'checked'))
+    self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
+    self.c_serialize_name = _n(name + ('serialize',))
+    self.c_unserialize_name = _n(name + ('unserialize',))
+    self.c_unpack_name = _n(name + ('unpack',))
+    self.c_sizeof_name = _n(name + ('sizeof',))
+
+    # special case: structs where variable size fields are followed by fixed size fields
+    self.var_followed_by_fixed_fields = False
+
+    if self.is_switch:
+        self.need_serialize = True
+        self.c_container = 'struct'
+        for bitcase in self.bitcases:
+            bitcase.c_field_name = _cpp(bitcase.field_name)
+            bitcase_name = bitcase.field_type if bitcase.type.has_name else name
+            _c_type_setup(bitcase.type, bitcase_name, ())
+
+    elif self.is_container:
 
         self.c_container = 'union' if self.is_union else 'struct'
         prev_varsized_field = None
@@ -284,13 +322,28 @@ def _c_type_setup(self, name, postfix):
             _c_type_setup(field.type, field.field_type, ())
             if field.type.is_list:
                 _c_type_setup(field.type.member, field.field_type, ())
+                if (field.type.nmemb is None): 
+                    self.need_sizeof = True
 
             field.c_field_type = _t(field.field_type)
             field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
             field.c_field_name = _cpp(field.field_name)
-            field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
+            field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
             field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
 
+            # correct the c_pointer field for variable size non-list types
+            if not field.type.fixed_size() and field.c_pointer == ' ':
+                field.c_pointer = '*'
+            if field.type.is_list and not field.type.member.fixed_size():
+                field.c_pointer = '*'
+
+            if field.type.is_switch:
+                field.c_pointer = '*'
+                field.c_field_const_type = 'const ' + field.c_field_type
+                self.need_aux = True
+            elif not field.type.fixed_size() and not field.type.is_bitcase:
+                self.need_sizeof = True
+
             field.c_iterator_type = _t(field.field_type + ('iterator',))      # xcb_fieldtype_iterator_t
             field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
             field.c_accessor_name = _n(name + (field.field_name,))            # xcb_container_field
@@ -306,10 +359,889 @@ def _c_type_setup(self, name, postfix):
 
             if field.type.fixed_size():
                 prev_varsized_offset += field.type.size
+                # special case: intermixed fixed and variable size fields
+                if prev_varsized_field is not None and not field.type.is_pad and field.wire:
+                    if not self.is_union:
+                        self.need_serialize = True
+                        self.var_followed_by_fixed_fields = True
             else:
                 self.last_varsized_field = field
                 prev_varsized_field = field
-                prev_varsized_offset = 0
+                prev_varsized_offset = 0                    
+
+            if self.var_followed_by_fixed_fields:
+                if field.type.fixed_size():
+                    field.prev_varsized_field = None
+                            
+    if self.need_serialize:
+        # when _unserialize() is wanted, create _sizeof() as well for consistency reasons 
+        self.need_sizeof = True
+
+    # as switch does never appear at toplevel, 
+    # continue here with type construction
+    if self.is_switch:
+        if self.c_type not in finished_switch:
+            finished_switch.append(self.c_type)
+            # special: switch C structs get pointer fields for variable-sized members
+            _c_complex(self)
+            for bitcase in self.bitcases:
+                bitcase_name = bitcase.type.name if bitcase.type.has_name else name
+                _c_accessors(bitcase.type, bitcase_name, bitcase_name)
+                # no list with switch as element, so no call to 
+                # _c_iterator(field.type, field_name) necessary
+
+    if not self.is_bitcase:
+        if self.need_serialize:
+            if self.c_serialize_name not in finished_serializers:
+                finished_serializers.append(self.c_serialize_name)
+                _c_serialize('serialize', self)
+
+                # _unpack() and _unserialize() are only needed for special cases:
+                #   switch -> unpack
+                #   special cases -> unserialize
+                if self.is_switch or self.var_followed_by_fixed_fields:
+                    _c_serialize('unserialize', self)
+                    
+        if self.need_sizeof:
+            if self.c_sizeof_name not in finished_sizeof:
+                if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
+                    finished_sizeof.append(self.c_sizeof_name)
+                    _c_serialize('sizeof', self)
+# _c_type_setup()
+
+def _c_helper_absolute_name(prefix, field=None):
+    """
+    turn prefix, which is a list of tuples (name, separator, Type obj) into a string
+    representing a valid name in C (based on the context)
+    if field is not None, append the field name as well
+    """
+    prefix_str = ''
+    for name, sep, obj in prefix:
+        prefix_str += name
+        if '' == sep:
+            sep = '->'
+            if ((obj.is_bitcase and obj.has_name) or     # named bitcase
+                (obj.is_switch and len(obj.parents)>1)):
+                sep = '.'
+        prefix_str += sep
+    if field is not None:
+        prefix_str += _cpp(field.field_name)
+    return prefix_str
+# _c_absolute_name
+    
+def _c_helper_field_mapping(complex_type, prefix, flat=False):
+    """
+    generate absolute names, based on prefix, for all fields starting from complex_type
+    if flat == True, nested complex types are not taken into account
+    """
+    all_fields = {}
+    if complex_type.is_switch:
+        for b in complex_type.bitcases:
+            if b.type.has_name:
+                switch_name, switch_sep, switch_type = prefix[-1]
+                bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
+            else:
+                bitcase_prefix = prefix 
+
+            if (True==flat and not b.type.has_name) or False==flat:
+                all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
+    else:
+        for f in complex_type.fields:
+            fname = _c_helper_absolute_name(prefix, f)
+            if f.field_name in all_fields:
+                raise Exception("field name %s has been registered before" % f.field_name)
+
+            all_fields[f.field_name] = (fname, f)
+            if f.type.is_container and flat==False:
+                if f.type.is_bitcase and not f.type.has_name:
+                    new_prefix = prefix
+                elif f.type.is_switch and len(f.type.parents)>1:
+                    # nested switch gets another separator
+                    new_prefix = prefix+[(f.c_field_name, '.', f.type)]
+                else:
+                    new_prefix = prefix+[(f.c_field_name, '->', f.type)]
+                all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
+
+    return all_fields
+# _c_field_mapping()
+
+def _c_helper_resolve_field_names (prefix):
+    """
+    get field names for all objects in the prefix array
+    """
+    all_fields = {}
+    tmp_prefix = []
+    # look for fields in the remaining containers
+    for idx, p in enumerate(prefix):
+        name, sep, obj = p
+        if ''==sep:
+            # sep can be preset in prefix, if not, make a sensible guess
+            sep = '.' if (obj.is_switch or obj.is_bitcase) else '->'
+            # exception: 'toplevel' object (switch as well!) always have sep '->'
+            sep = '->' if idx<1 else sep
+        if not obj.is_bitcase or (obj.is_bitcase and obj.has_name):
+            tmp_prefix.append((name, sep, obj))
+        all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
+
+    return all_fields
+# _c_helper_resolve_field_names
+
+def get_expr_fields(self):
+    """
+    get the Fields referenced by switch or list expression 
+    """
+    def get_expr_field_names(expr):
+        if expr.op is None:
+            if expr.lenfield_name is not None:
+                return [expr.lenfield_name]
+            else:
+                # constant value expr
+                return []
+        else:
+            if expr.op == '~':
+                return get_expr_field_names(expr.rhs)
+            elif expr.op == 'popcount':
+                return get_expr_field_names(expr.rhs)
+            elif expr.op == 'sumof':
+                # sumof expr references another list, 
+                # we need that list's length field here
+                field = None
+                for f in expr.lenfield_parent.fields:
+                    if f.field_name == expr.lenfield_name:
+                        field = f
+                        break
+                if field is None:
+                    raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
+                # referenced list + its length field
+                return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
+            elif expr.op == 'enumref':
+                return []
+            else:
+                return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
+    # get_expr_field_names()
+    
+    # resolve the field names with the parent structure(s)
+    unresolved_fields_names = get_expr_field_names(self.expr)
+
+    # construct prefix from self
+    prefix = [('', '', p) for p in self.parents]
+    if self.is_container:
+        prefix.append(('', '', self))
+
+    all_fields = _c_helper_resolve_field_names (prefix)
+    resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
+    if len(unresolved_fields_names) != len(resolved_fields_names):
+        raise Exception("could not resolve all fields for %s" % self.name)
+    
+    resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
+    return resolved_fields
+# get_expr_fields()
+
+def resolve_expr_fields(complex_obj):
+    """
+    find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
+    these are normally fields that need to be given as function parameters
+    """
+    all_fields = []
+    expr_fields = []
+    unresolved = []
+
+    for field in complex_obj.fields:
+        all_fields.append(field)
+        if field.type.is_switch or field.type.is_list:
+            expr_fields += get_expr_fields(field.type)
+        if field.type.is_container:
+            expr_fields += resolve_expr_fields(field.type)
+
+    # try to resolve expr fields
+    for e in expr_fields:
+        if e not in all_fields and e not in unresolved:
+            unresolved.append(e)
+    return unresolved
+# resolve_expr_fields()
+            
+def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
+    """
+    functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
+    E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch 
+    expression. This function tries to resolve all fields within a structure, and returns the 
+    unresolved fields as the list of external parameters. 
+    """
+    def add_param(params, param):
+        if param not in params:
+            params.append(param)
+
+    # collect all fields into param_fields
+    param_fields = []
+    wire_fields = []
+
+    for field in self.fields:
+        if field.visible:
+            # the field should appear as a parameter in the function call
+            param_fields.append(field)
+        if field.wire and not field.auto:
+            if field.type.fixed_size() and not self.is_switch:
+                # field in the xcb_out structure
+                wire_fields.append(field)
+        # fields like 'pad0' are skipped!
+               
+    # in case of switch, parameters always contain any fields referenced in the switch expr
+    # we do not need any variable size fields here, as the switch data type contains both 
+    # fixed and variable size fields
+    if self.is_switch:
+        param_fields = get_expr_fields(self)
+
+    # _serialize()/_unserialize()/_unpack() function parameters
+    # note: don't use set() for params, it is unsorted
+    params = []
+    
+    # 1. the parameter for the void * buffer
+    if  'serialize' == context:
+        params.append(('void', '**', buffer_var))
+    elif context in ('unserialize', 'unpack', 'sizeof'):
+        params.append(('const void', '*', buffer_var))
+
+    # 2. any expr fields that cannot be resolved within self and descendants
+    unresolved_fields = resolve_expr_fields(self)
+    for f in unresolved_fields:
+        add_param(params, (f.c_field_type, '', f.c_field_name))
+
+    # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
+    #    that do not appear in the data type struct
+    for p in param_fields:
+        if self.is_switch:
+            typespec = p.c_field_const_type
+            pointerspec = p.c_pointer 
+            add_param(params, (typespec, pointerspec, p.c_field_name))
+        else:
+            if p.visible and not p.wire and not p.auto:
+                typespec = p.c_field_type
+                pointerspec = ''
+                add_param(params, (typespec, pointerspec, p.c_field_name))
+  
+    # 4. aux argument
+    if 'serialize' == context:
+        add_param(params, ('const %s' % self.c_type, '*', aux_var))
+    elif 'unserialize' == context: 
+        add_param(params, ('%s' % self.c_type, '**', aux_var))
+    elif 'unpack' == context:
+        add_param(params, ('%s' % self.c_type, '*', aux_var))
+
+    # 5. switch contains all variable size fields as struct members
+    #    for other data types though, these have to be supplied separately
+    #    this is important for the special case of intermixed fixed and 
+    #    variable size fields
+    if not self.is_switch and 'serialize' == context:
+        for p in param_fields:
+            if not p.type.fixed_size():
+                add_param(params, (p.c_field_const_type, '*', p.c_field_name))
+
+    return (param_fields, wire_fields, params)
+# get_serialize_params()
+
+def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
+    code_lines.append('%s    /* insert padding */' % space)
+    code_lines.append('%s    xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
+#    code_lines.append('%s    printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
+    code_lines.append('%s    xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
+
+    if not postpone:
+        code_lines.append('%s    if (0 != xcb_pad) {' % space)
+
+        if 'serialize' == context:
+            code_lines.append('%s        xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
+            code_lines.append('%s        xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
+            code_lines.append('%s        xcb_parts_idx++;' % space)
+        elif context in ('unserialize', 'unpack', 'sizeof'):
+            code_lines.append('%s        xcb_tmp += xcb_pad;' % space)
+
+        code_lines.append('%s        xcb_pad = 0;' % space)
+        code_lines.append('%s    }' % space)
+        
+    code_lines.append('%s    xcb_block_len = 0;' % space)
+
+    # keep tracking of xcb_parts entries for serialize
+    return 1
+# _c_serialize_helper_insert_padding()
+
+def _c_serialize_helper_switch(context, self, complex_name, 
+                               code_lines, temp_vars, 
+                               space, prefix):
+    count = 0
+    switch_expr = _c_accessor_get_expr(self.expr, None)
+
+    for b in self.bitcases:            
+        bitcase_expr = _c_accessor_get_expr(b.type.expr, None)
+        code_lines.append('    if(%s & %s) {' % (switch_expr, bitcase_expr))
+#        code_lines.append('        printf("switch %s: entering bitcase section %s (mask=%%%%d)...\\n", %s);' % 
+#                          (self.name[-1], b.type.name[-1], bitcase_expr))
+        b_prefix = prefix
+        if b.type.has_name:
+            b_prefix = prefix + [(b.c_field_name, '.', b.type)]
+            
+        count += _c_serialize_helper_fields(context, b.type, 
+                                            code_lines, temp_vars, 
+                                            "%s    " % space, 
+                                            b_prefix, 
+                                            is_bitcase = True)
+        code_lines.append('    }')
+
+#    if 'serialize' == context:
+#        count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
+#    elif context in ('unserialize', 'unpack', 'sizeof'):
+#        # padding
+#        code_lines.append('%s    xcb_pad = -xcb_block_len & 3;' % space)
+#        code_lines.append('%s    xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
+   
+    return count
+# _c_serialize_helper_switch
+
+def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
+    """
+    handle switch by calling _serialize() or _unpack(), depending on context
+    """
+    # switch is handled by this function as a special case
+    param_fields, wire_fields, params = get_serialize_params(context, self)
+    field_mapping = _c_helper_field_mapping(self, prefix)
+    prefix_str = _c_helper_absolute_name(prefix)
+
+    # find the parameters that need to be passed to _serialize()/_unpack():
+    # all switch expr fields must be given as parameters
+    args = get_expr_fields(field.type)
+    # length fields for variable size types in switch, normally only some of need 
+    # need to be passed as parameters
+    switch_len_fields = resolve_expr_fields(field.type)
+
+    # a switch field at this point _must_ be a bitcase field
+    # we require that bitcases are "self-contiguous"
+    bitcase_unresolved = resolve_expr_fields(self)
+    if len(bitcase_unresolved) != 0:
+        raise Exception('unresolved fields within bitcase is not supported at this point')
+
+    # get the C names for the parameters  
+    c_field_names = ''
+    for a in switch_len_fields:
+        c_field_names += "%s, " % field_mapping[a.c_field_name][0]
+    for a in args:
+        c_field_names += "%s, " % field_mapping[a.c_field_name][0]
+
+    # call _serialize()/_unpack() to determine the actual size
+    if 'serialize' == context:
+        length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
+                                       c_field_names, prefix_str, field.c_field_name) 
+    elif context in ('unserialize', 'unpack'):
+        length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name, 
+                                           c_field_names, prefix_str, field.c_field_name)
+
+    return length
+# _c_serialize_helper_switch_field()
+
+def _c_serialize_helper_list_field(context, self, field, 
+                                   code_lines, temp_vars, 
+                                   space, prefix):
+    """
+    helper function to cope with lists of variable length
+    """
+    expr = field.type.expr
+    prefix_str = _c_helper_absolute_name(prefix)
+    param_fields, wire_fields, params = get_serialize_params('sizeof', self)
+    param_names = [p[2] for p in params]
+    
+    expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
+    resolved = list(filter(lambda x: x in param_names, expr_fields_names))
+    unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
+    
+    field_mapping = {}
+    for r in resolved:
+        field_mapping[r] = (r, None)
+    
+    if len(unresolved)>0:
+        tmp_prefix = prefix
+        if len(tmp_prefix)==0:
+            raise Exception("found an empty prefix while resolving expr field names for list %s", 
+                            field.c_field_name)        
+        
+        field_mapping.update(_c_helper_resolve_field_names(prefix))
+        resolved += list(filter(lambda x: x in field_mapping, unresolved))
+        unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
+        if len(unresolved)>0:
+            raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
+
+    list_length = _c_accessor_get_expr(expr, field_mapping)
+
+    # default: list with fixed size elements
+    length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
+
+    # list with variable-sized elements 
+    if not field.type.member.fixed_size():
+        length = ''
+        if context in ('unserialize', 'sizeof', 'unpack'):
+            int_i = '    unsigned int i;'
+            xcb_tmp_len = '    unsigned int xcb_tmp_len;'
+            if int_i not in temp_vars:
+                temp_vars.append(int_i)
+            if xcb_tmp_len not in temp_vars:
+                temp_vars.append(xcb_tmp_len)
+            # loop over all list elements and call sizeof repeatedly
+            # this should be a bit faster than using the iterators
+            code_lines.append("%s    for(i=0; i<%s; i++) {" % (space, list_length))
+            code_lines.append("%s        xcb_tmp_len = %s(xcb_tmp);" % 
+                              (space, field.type.c_sizeof_name))
+            code_lines.append("%s        xcb_block_len += xcb_tmp_len;" % space)
+            code_lines.append("%s        xcb_tmp += xcb_tmp_len;" % space)
+            code_lines.append("%s    }" % space)                  
+      
+        elif 'serialize' == context:
+            code_lines.append('%s    xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
+            code_lines.append('%s    xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
+            code_lines.append('%s    for(i=0; i<%s; i++) { ' % (space, list_length))
+            code_lines.append('%s        xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
+            code_lines.append('%s        xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
+            code_lines.append('%s    }' % space)
+            code_lines.append('%s    xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
+            
+    return length
+# _c_serialize_helper_list_field()
+
+def _c_serialize_helper_fields_fixed_size(context, self, field, 
+                                          code_lines, temp_vars, 
+                                          space, prefix):
+    # keep the C code a bit more readable by giving the field name
+    if not self.is_bitcase:
+        code_lines.append('%s    /* %s.%s */' % (space, self.c_type, field.c_field_name))
+    else:
+        scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
+        typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
+        code_lines.append('%s    /* %s.%s */' % (space, typename, field.c_field_name))
+
+    abs_field_name = _c_helper_absolute_name(prefix, field)
+    # default for simple cases: call sizeof()
+    length = "sizeof(%s)" % field.c_field_type
+
+    if context in ('unserialize', 'unpack', 'sizeof'):
+        # default: simple cast
+        value = '    %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type) 
+        
+        # padding - we could probably just ignore it
+        if field.type.is_pad and field.type.nmemb > 1:
+            value = ''
+            for i in range(field.type.nmemb):
+                code_lines.append('%s    %s[%d] = *(%s *)xcb_tmp;' % 
+                                  (space, abs_field_name, i, field.c_field_type)) 
+            # total padding = sizeof(pad0) * nmemb
+            length += " * %d" % field.type.nmemb
+
+        if field.type.is_list:
+            # no such case in the protocol, cannot be tested and therefore ignored for now
+            raise Exception('list with fixed number of elemens unhandled in _unserialize()')
+
+    elif 'serialize' == context:
+        value = '    xcb_parts[xcb_parts_idx].iov_base = (char *) ' 
+
+        if field.type.is_expr:
+            # need to register a temporary variable for the expression in case we know its type
+            if field.type.c_type is None:
+                raise Exception("type for field '%s' (expression '%s') unkown" % 
+                                (field.field_name, _c_accessor_get_expr(field.type.expr)))
+            
+            temp_vars.append('    %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name), 
+                                                           _c_accessor_get_expr(field.type.expr, prefix)))
+            value += "&xcb_expr_%s;" % _cpp(field.field_name)
+
+        elif field.type.is_pad:
+            if field.type.nmemb == 1:
+                value += "&xcb_pad;"
+            else:
+                # we could also set it to 0, see definition of xcb_send_request()
+                value = '    xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
+                length += "*%d" % field.type.nmemb
+
+        else:
+            # non-list type with fixed size
+            if field.type.nmemb == 1:
+                value += "&%s;" % (abs_field_name)
+
+            # list with nmemb (fixed size) elements
+            else:
+                value += '%s;' % (abs_field_name)
+                length = '%d' % field.type.nmemb
+
+    return (value, length)
+# _c_serialize_helper_fields_fixed_size()
+
+def _c_serialize_helper_fields_variable_size(context, self, field, 
+                                             code_lines, temp_vars, 
+                                             space, prefix):
+    prefix_str = _c_helper_absolute_name(prefix)
+
+    if context in ('unserialize', 'unpack', 'sizeof'):
+        value = ''
+        var_field_name = 'xcb_tmp'
+        
+        # special case: intermixed fixed and variable size fields
+        if self.var_followed_by_fixed_fields and 'unserialize' == context:
+            value = '    %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
+            temp_vars.append('    %s *%s;' % (field.type.c_type, field.c_field_name))
+        # special case: switch
+        if 'unpack' == context:
+            value = '    %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
+            
+    elif 'serialize' == context:
+        # variable size fields appear as parameters to _serialize() if the 
+        # 'toplevel' container is not a switch
+        prefix_string = prefix_str if prefix[0][2].is_switch else ''
+        var_field_name = "%s%s" % (prefix_string, field.c_field_name)
+        value = '    xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
+
+    length = ''
+
+    code_lines.append('%s    /* %s */' % (space, field.c_field_name))
+
+    if field.type.is_list:
+        if value != '':
+            # in any context, list is already a pointer, so the default assignment is ok
+            code_lines.append("%s%s" % (space, value))
+            value = ''
+        length = _c_serialize_helper_list_field(context, self, field, 
+                                                code_lines, temp_vars, 
+                                                space, prefix)
+        
+    elif field.type.is_switch:
+        value = ''
+        if context == 'serialize':
+            # the _serialize() function allocates the correct amount memory if given a NULL pointer
+            value = '    xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
+        length = _c_serialize_helper_switch_field(context, self, field, 
+                                                  'xcb_parts[xcb_parts_idx].iov_base', 
+                                                  prefix)
+        
+    else:
+        # in all remaining special cases - call _sizeof()
+        length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
+
+    return (value, length)
+# _c_serialize_helper_fields_variable_size
+
+def _c_serialize_helper_fields(context, self, 
+                               code_lines, temp_vars, 
+                               space, prefix, is_bitcase):
+    count = 0
+    need_padding = False
+    prev_field_was_variable = False
+
+    for field in self.fields:
+        if not field.visible:
+            if not ((field.wire and not field.auto) or 'unserialize' == context):
+                continue
+
+        # switch/bitcase: fixed size fields must be considered explicitly 
+        if field.type.fixed_size():
+            if self.is_bitcase or self.var_followed_by_fixed_fields:
+                if prev_field_was_variable and need_padding:
+                    # insert padding
+#                    count += _c_serialize_helper_insert_padding(context, code_lines, space, 
+#                                                                self.var_followed_by_fixed_fields)
+                    prev_field_was_variable = False
+
+                # prefix for fixed size fields
+                fixed_prefix = prefix
+
+                value, length = _c_serialize_helper_fields_fixed_size(context, self, field, 
+                                                                      code_lines, temp_vars, 
+                                                                      space, fixed_prefix)
+            else:
+                continue
+
+        # fields with variable size
+        else:
+            # switch/bitcase: always calculate padding before and after variable sized fields
+            if need_padding or is_bitcase:
+                count += _c_serialize_helper_insert_padding(context, code_lines, space, 
+                                                            self.var_followed_by_fixed_fields)
+
+            value, length = _c_serialize_helper_fields_variable_size(context, self, field, 
+                                                                     code_lines, temp_vars, 
+                                                                     space, prefix)
+            prev_field_was_variable = True
+        
+        # save (un)serialization C code
+        if '' != value:
+            code_lines.append('%s%s' % (space, value))    
+        
+        if field.type.fixed_size():
+            if is_bitcase or self.var_followed_by_fixed_fields:
+                # keep track of (un)serialized object's size
+                code_lines.append('%s    xcb_block_len += %s;' % (space, length))
+                if context in ('unserialize', 'unpack', 'sizeof'):
+                    code_lines.append('%s    xcb_tmp += %s;' % (space, length))
+        else: 
+            # variable size objects or bitcase:
+            #   value & length might have been inserted earlier for special cases
+            if '' != length:
+                # special case: intermixed fixed and variable size fields
+                if (not field.type.fixed_size() and 
+                    self.var_followed_by_fixed_fields and 'unserialize' == context):
+                    temp_vars.append('    int %s_len;' % field.c_field_name)
+                    code_lines.append('%s    %s_len = %s;' % (space, field.c_field_name, length))
+                    code_lines.append('%s    xcb_block_len += %s_len;' % (space, field.c_field_name))
+                    code_lines.append('%s    xcb_tmp += %s_len;' % (space, field.c_field_name))
+                else:
+                    code_lines.append('%s    xcb_block_len += %s;' % (space, length))
+                    # increase pointer into the byte stream accordingly
+                    if context in ('unserialize', 'sizeof', 'unpack'):
+                        code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
+                        
+        if 'serialize' == context:
+            if '' != length:
+                code_lines.append('%s    xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
+            code_lines.append('%s    xcb_parts_idx++;' % space)
+            count += 1
+
+        code_lines.append('%s    xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
+
+        need_padding = True
+        if self.var_followed_by_fixed_fields:
+            need_padding = False
+        
+    return count
+# _c_serialize_helper_fields()    
+
+def _c_serialize_helper(context, complex_type, 
+                        code_lines, temp_vars, 
+                        space='', prefix=[]):
+    # count tracks the number of fields to serialize
+    count = 0
+
+    if hasattr(complex_type, 'type'):
+        self = complex_type.type
+        complex_name = complex_type.name
+    else:
+        self = complex_type
+        if self.var_followed_by_fixed_fields and 'unserialize' == context:
+            complex_name = 'xcb_out'
+        else:
+            complex_name = '_aux'
+    
+    # special case: switch is serialized by evaluating each bitcase separately
+    if self.is_switch:
+        count += _c_serialize_helper_switch(context, self, complex_name, 
+                                            code_lines, temp_vars, 
+                                            space, prefix)
+
+    # all other data types can be evaluated one field a time
+    else: 
+        # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
+        if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
+            code_lines.append('%s    xcb_block_len += sizeof(%s);' % (space, self.c_type))
+            code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
+            # probably not needed
+            #_c_serialize_helper_insert_padding(context, code_lines, space, False)
+
+        count += _c_serialize_helper_fields(context, self, 
+                                            code_lines, temp_vars, 
+                                            space, prefix, False)
+    # "final padding"
+    count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
+
+    return count    
+# _c_serialize_helper()
+
+def _c_serialize(context, self):
+    """
+    depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof() 
+    for the ComplexType variable self
+    """
+    _h_setlevel(1)
+    _c_setlevel(1)
+
+    _hc('')
+    # _serialize() returns the buffer size
+    _hc('int')
+
+    if self.is_switch and 'unserialize' == context:
+        context = 'unpack'
+
+    cases = { 'serialize'   : self.c_serialize_name, 
+              'unserialize' : self.c_unserialize_name, 
+              'unpack'      : self.c_unpack_name, 
+              'sizeof'      : self.c_sizeof_name }
+    func_name = cases[context]
+            
+    param_fields, wire_fields, params = get_serialize_params(context, self)
+    variable_size_fields = 0
+    # maximum space required for type definition of function arguments
+    maxtypelen = 0
+
+    # determine N(variable_fields) 
+    for field in param_fields:
+        # if self.is_switch, treat all fields as if they are variable sized
+        if not field.type.fixed_size() or self.is_switch:
+            variable_size_fields += 1
+    # determine maxtypelen
+    for p in params:
+        maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))    
+
+    # write to .c/.h
+    indent = ' '*(len(func_name)+2)
+    param_str = []
+    for p in params:
+        typespec, pointerspec, field_name = p
+        spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
+        param_str.append("%s%s%s  %s%s  /**< */" % (indent, typespec, spacing, pointerspec, field_name))
+    # insert function name
+    param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
+    param_str = list(map(lambda x: "%s," % x, param_str))
+    for s in param_str[:-1]:
+        _hc(s)
+    _h("%s);" % param_str[-1].rstrip(','))
+    _c("%s)" % param_str[-1].rstrip(','))
+    _c('{')
+
+    code_lines = []
+    temp_vars = []
+    prefix = []
+
+    if 'serialize' == context:
+        if not self.is_switch and not self.var_followed_by_fixed_fields:
+            _c('    %s *xcb_out = *_buffer;', self.c_type)
+            _c('    unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
+            _c('    unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
+            _c('    unsigned int xcb_align_to;')
+        else:
+            _c('    char *xcb_out = *_buffer;')
+            _c('    unsigned int xcb_buffer_len = 0;')
+            _c('    unsigned int xcb_align_to;')
+        prefix = [('_aux', '->', self)]
+        aux_ptr = 'xcb_out'
+
+    elif context in ('unserialize', 'unpack'):
+        _c('    char *xcb_tmp = (char *)_buffer;')
+        if not self.is_switch:
+            if not self.var_followed_by_fixed_fields:
+                _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
+                prefix = [('_aux', '->', self)]
+            else:
+                _c('    %s xcb_out;', self.c_type)
+                prefix = [('xcb_out', '.', self)]
+        else:
+            aux_var = '_aux' # default for unpack: single pointer
+            # note: unserialize not generated for switch
+            if 'unserialize' == context:
+                aux_var = '(*_aux)' # unserialize: double pointer (!)
+            prefix = [(aux_var, '->', self)]
+        aux_ptr = '*_aux'
+        _c('    unsigned int xcb_buffer_len = 0;')
+        _c('    unsigned int xcb_block_len = 0;')
+        _c('    unsigned int xcb_pad = 0;')
+        _c('    unsigned int xcb_align_to;')
+
+    elif 'sizeof' == context:
+        param_names = [p[2] for p in params]
+        if self.is_switch:
+            # switch: call _unpack()
+            _c('    %s _aux;', self.c_type)
+            _c('    return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
+            _c('}')
+            return
+        elif self.var_followed_by_fixed_fields:
+            # special case: call _unserialize()
+            _c('    return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
+            _c('}')
+            return
+        else:
+            _c('    char *xcb_tmp = (char *)_buffer;')
+            prefix = [('_aux', '->', self)]
+
+    count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
+    # update variable size fields (only important for context=='serialize'
+    variable_size_fields = count
+    if 'serialize' == context:
+        temp_vars.append('    unsigned int xcb_pad = 0;')
+        temp_vars.append('    char xcb_pad0[3] = {0, 0, 0};') 
+        temp_vars.append('    struct iovec xcb_parts[%d];' % count)
+        temp_vars.append('    unsigned int xcb_parts_idx = 0;')
+        temp_vars.append('    unsigned int xcb_block_len = 0;')
+        temp_vars.append('    unsigned int i;')
+        temp_vars.append('    char *xcb_tmp;')
+    elif 'sizeof' == context:
+        # neither switch nor intermixed fixed and variable size fields:
+        # evaluate parameters directly
+        if not (self.is_switch or self.var_followed_by_fixed_fields):
+
+            # look if we have to declare an '_aux' variable at all
+            if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
+                if not self.var_followed_by_fixed_fields:
+                    _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
+                else:
+                    _c('    %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
+
+            _c('    unsigned int xcb_buffer_len = 0;')
+            _c('    unsigned int xcb_block_len = 0;')
+            _c('    unsigned int xcb_pad = 0;')        
+            _c('    unsigned int xcb_align_to;')
+
+    _c('')
+    for t in temp_vars:
+        _c(t)
+    _c('')
+    for l in code_lines:
+        _c(l)
+
+    # variable sized fields have been collected, now
+    # allocate memory and copy everything into a continuous memory area 
+    # note: this is not necessary in case of unpack
+    if context in ('serialize', 'unserialize'):
+        # unserialize: check for sizeof-only invocation
+        if 'unserialize' == context:
+            _c('')
+            _c('    if (NULL == _aux)')
+            _c('        return xcb_buffer_len;')
+
+        _c('')
+        _c('    if (NULL == %s) {', aux_ptr)
+        _c('        /* allocate memory */')
+        _c('        %s = malloc(xcb_buffer_len);', aux_ptr)
+        if 'serialize' == context:
+            _c('        *_buffer = xcb_out;')
+        _c('    }')
+        _c('')
+
+        # serialize: handle variable size fields in a loop
+        if 'serialize' == context:
+            if not self.is_switch and not self.var_followed_by_fixed_fields:
+                if len(wire_fields)>0:
+                    _c('    *xcb_out = *_aux;')
+            # copy variable size fields into the buffer
+            if variable_size_fields > 0:
+                # xcb_out padding
+                if not self.is_switch and not self.var_followed_by_fixed_fields:
+                    _c('    xcb_tmp = (char*)++xcb_out;')
+                    _c('    xcb_tmp += xcb_out_pad;')
+                else:
+                    _c('    xcb_tmp = xcb_out;')
+
+                # variable sized fields
+                _c('    for(i=0; i<xcb_parts_idx; i++) {')
+                _c('        if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
+                _c('            memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
+                _c('        if (0 != xcb_parts[i].iov_len)')
+                _c('            xcb_tmp += xcb_parts[i].iov_len;')
+                _c('    }')
+            
+        # unserialize: assign variable size fields individually
+        if 'unserialize' == context:
+            _c('    xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
+            param_fields.reverse()
+            for field in param_fields:
+                if not field.type.fixed_size():
+                    _c('    xcb_tmp -= %s_len;', field.c_field_name)
+                    _c('    memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
+            _c('    *%s = xcb_out;', aux_ptr)
+    _c('')
+    _c('    return xcb_buffer_len;')
+    _c('}')
+# _c_serialize()
 
 def _c_iterator_get_end(field, accum):
     '''
@@ -319,7 +1251,6 @@ def _c_iterator_get_end(field, accum):
     '''
     if field.type.is_container:
         accum = field.c_accessor_name + '(' + accum + ')'
-        # XXX there could be fixed-length fields at the end
         return _c_iterator_get_end(field.type.last_varsized_field, accum)
     if field.type.is_list:
         # XXX we can always use the first way
@@ -372,10 +1303,22 @@ def _c_iterator(self, name):
 
     if not self.fixed_size():
         _c('    %s *R = i->data;', self.c_type)
-        _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
-        _c('    --i->rem;')
-        _c('    i->data = (%s *) child.data;', self.c_type)
-        _c('    i->index = child.index;')
+
+        if self.is_union:
+            # FIXME - how to determine the size of a variable size union??
+            _c('    /* FIXME - determine the size of the union %s */', self.c_type)            
+        else:
+            if self.need_sizeof:
+                _c('    xcb_generic_iterator_t child;')
+                _c('    child.data = (%s *)(((char *)R) + %s(R));', 
+                   self.c_type, self.c_sizeof_name)
+                _c('    i->index = (char *) child.data - (char *) i->data;')
+            else:
+                _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
+                _c('    i->index = child.index;')
+            _c('    --i->rem;')
+            _c('    i->data = (%s *) child.data;', self.c_type)
+
     else:
         _c('    --i->rem;')
         _c('    ++i->data;')
@@ -424,61 +1367,113 @@ def _c_iterator(self, name):
     _c('    return ret;')
     _c('}')
 
-def _c_accessor_get_length(expr, prefix=''):
+def _c_accessor_get_length(expr, field_mapping=None):
     '''
     Figures out what C code is needed to get a length field.
+    The field_mapping parameter can be used to change the absolute name of a length field. 
     For fields that follow a variable-length field, use the accessor.
     Otherwise, just reference the structure field directly.
     '''
-    prefarrow = '' if prefix == '' else prefix + '->'
 
-    if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
-        return expr.lenfield.c_accessor_name + '(' + prefix + ')'
-    elif expr.lenfield_name != None:
-        return prefarrow + expr.lenfield_name
+    lenfield_name = expr.lenfield_name
+    if lenfield_name is not None:
+        if field_mapping is not None:
+            lenfield_name = field_mapping[lenfield_name][0]
+    if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
+        # special case: variable and fixed size fields are intermixed
+        # if the lenfield is among the fixed size fields, there is no need
+        # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
+        return field_mapping(expr.lenfield_name)
+    elif expr.lenfield_name is not None:
+        return lenfield_name
     else:
         return str(expr.nmemb)
 
-def _c_accessor_get_expr(expr, prefix=''):
+def _c_accessor_get_expr(expr, field_mapping):
     '''
     Figures out what C code is needed to get the length of a list field.
+    The field_mapping parameter can be used to change the absolute name of a length field. 
     Recurses for math operations.
     Returns bitcount for value-mask fields.
     Otherwise, uses the value of the length field.
     '''
-    lenexp = _c_accessor_get_length(expr, prefix)
+    lenexp = _c_accessor_get_length(expr, field_mapping)
 
     if expr.op == '~':
-        return '(' + '~' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
+        return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
+    elif expr.op == 'popcount':
+        return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
+    elif expr.op == 'enumref':
+        enum_name = expr.lenfield_type.name
+        constant_name = expr.lenfield_name
+        c_name = _n(enum_name + (constant_name,)).upper()
+        return c_name
+    elif expr.op == 'sumof':
+        # locate the referenced list object
+        list_obj = expr.lenfield_type
+        field = None
+        for f in expr.lenfield_parent.fields:
+            if f.field_name == expr.lenfield_name:
+                field = f
+                break
+
+        if field is None:
+            raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
+        list_name = field_mapping[field.c_field_name][0]
+        c_length_func = "%s(%s)" % (field.c_length_name, list_name)
+        # note: xcb_sumof() has only been defined for integers
+        c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
+        return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
     elif expr.op != None:
-        return '(' + _c_accessor_get_expr(expr.lhs, prefix) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
+        return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) + 
+                ' ' + expr.op + ' ' + 
+                _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
     elif expr.bitfield:
         return 'xcb_popcount(' + lenexp + ')'
     else:
         return lenexp
 
+def type_pad_type(type):
+    if type == 'void':
+        return 'char'
+    return type
+
 def _c_accessors_field(self, field):
     '''
     Declares the accessor functions for a non-list field that follows a variable-length field.
     '''
+    c_type = self.c_type
+
+    # special case: switch
+    switch_obj = self if self.is_switch else None
+    if self.is_bitcase:
+        switch_obj = self.parents[-1]
+    if switch_obj is not None:
+        c_type = switch_obj.c_type
+
     if field.type.is_simple:
         _hc('')
         _hc('')
         _hc('/*****************************************************************************')
-        _hc(' **')
+        _hc(' ** ')
         _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
         _hc(' ** ')
-        _hc(' ** @param const %s *R', self.c_type)
+        _hc(' ** @param const %s *R', c_type)
         _hc(' ** @returns %s', field.c_field_type)
         _hc(' **')
         _hc(' *****************************************************************************/')
         _hc(' ')
         _hc('%s', field.c_field_type)
-        _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
-        _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
+        _h('%s (const %s *R  /**< */);', field.c_accessor_name, c_type)
+        _c('%s (const %s *R  /**< */)', field.c_accessor_name, c_type)
         _c('{')
-        _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
-        _c('    return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
+        if field.prev_varsized_field is None:
+            _c('    return (%s *) (R + 1);', field.c_field_type)
+        else:
+            _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
+            _c('    return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', 
+               field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
         _c('}')
     else:
         _hc('')
@@ -487,18 +1482,31 @@ def _c_accessors_field(self, field):
         _hc(' **')
         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
         _hc(' ** ')
-        _hc(' ** @param const %s *R', self.c_type)
+        _hc(' ** @param const %s *R', c_type)
         _hc(' ** @returns %s *', field.c_field_type)
         _hc(' **')
         _hc(' *****************************************************************************/')
         _hc(' ')
-        _hc('%s *', field.c_field_type)
-        _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
-        _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
+        if field.type.is_switch and switch_obj is None:
+            return_type = 'void *'
+        else:
+            return_type = '%s *' % field.c_field_type
+
+        _hc(return_type)
+        _h('%s (const %s *R  /**< */);', field.c_accessor_name, c_type)
+        _c('%s (const %s *R  /**< */)', field.c_accessor_name, c_type)
         _c('{')
-        _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
-        _c('    return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
+        if field.prev_varsized_field is None:
+            _c('    return (%s) (R + 1);', return_type)
+            # note: the special case 'variable fields followed by fixed size fields'
+            #       is not of any consequence here, since the ordering gets 
+            #       'corrected' in the reply function
+        else:
+            _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
+            _c('    return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', 
+               return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
         _c('}')
+
     
 def _c_accessors_list(self, field):
     '''
@@ -507,32 +1515,83 @@ def _c_accessors_list(self, field):
     Declares length and get-iterator functions always.
     '''
     list = field.type
+    c_type = self.c_type
+
+    # special case: switch
+    # in case of switch, 2 params have to be supplied to certain accessor functions:
+    #   1. the anchestor object (request or reply)
+    #   2. the (anchestor) switch object
+    # the reason is that switch is either a child of a request/reply or nested in another switch, 
+    # so whenever we need to access a length field, we might need to refer to some anchestor type
+    switch_obj = self if self.is_switch else None
+    if self.is_bitcase:
+        switch_obj = self.parents[-1]
+    if switch_obj is not None:
+        c_type = switch_obj.c_type
+
+    params = []
+    fields = {}
+    parents = self.parents if hasattr(self, 'parents') else [self]
+    # 'R': parents[0] is always the 'toplevel' container type 
+    params.append(('const %s *R' % parents[0].c_type, parents[0]))
+    fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
+    # auxiliary object for 'R' parameters
+    R_obj = parents[0]
+
+    if switch_obj is not None:
+        # now look where the fields are defined that are needed to evaluate 
+        # the switch expr, and store the parent objects in accessor_params and
+        # the fields in switch_fields
+
+        # 'S': name for the 'toplevel' switch
+        toplevel_switch = parents[1]
+        params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
+        fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
+
+        # initialize prefix for everything "below" S
+        prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
+        prefix = [(prefix_str, '->', toplevel_switch)]
+
+        # look for fields in the remaining containers
+        for p in parents[2:] + [self]:
+            # the separator between parent and child is always '.' here, 
+            # because of nested switch statements
+            if not p.is_bitcase or (p.is_bitcase and p.has_name):
+                prefix.append((p.name[-1], '.', p))
+            fields.update(_c_helper_field_mapping(p, prefix, flat=True))
+
+        # auxiliary object for 'S' parameter
+        S_obj = parents[1]
 
     _h_setlevel(1)
     _c_setlevel(1)
     if list.member.fixed_size():
+        idx = 1 if switch_obj is not None else 0
         _hc('')
         _hc('')
         _hc('/*****************************************************************************')
         _hc(' **')
         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
         _hc(' ** ')
-        _hc(' ** @param const %s *R', self.c_type)
+        _hc(' ** @param %s', params[idx][0])
         _hc(' ** @returns %s *', field.c_field_type)
         _hc(' **')
         _hc(' *****************************************************************************/')
         _hc(' ')
         _hc('%s *', field.c_field_type)
-        _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
-        _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
-        _c('{')
 
-        if field.prev_varsized_field == None:
+        _h('%s (%s  /**< */);', field.c_accessor_name, params[idx][0])
+        _c('%s (%s  /**< */)', field.c_accessor_name, params[idx][0])
+
+        _c('{')
+        if switch_obj is not None:
+            _c('    return %s;', fields[field.c_field_name][0])
+        elif field.prev_varsized_field is None:
             _c('    return (%s *) (R + 1);', field.c_field_type)
         else:
             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
-            _c('    return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
-
+            _c('    return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', 
+               field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
         _c('}')
 
     _hc('')
@@ -541,16 +1600,24 @@ def _c_accessors_list(self, field):
     _hc(' **')
     _hc(' ** int %s', field.c_length_name)
     _hc(' ** ')
-    _hc(' ** @param const %s *R', self.c_type)
+    _hc(' ** @param const %s *R', c_type)
     _hc(' ** @returns int')
     _hc(' **')
     _hc(' *****************************************************************************/')
     _hc(' ')
     _hc('int')
-    _h('%s (const %s *R  /**< */);', field.c_length_name, self.c_type)
-    _c('%s (const %s *R  /**< */)', field.c_length_name, self.c_type)
+    if switch_obj is not None:
+        _hc('%s (const %s *R  /**< */,', field.c_length_name, R_obj.c_type)
+        spacing = ' '*(len(field.c_length_name)+2)
+        _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
+        _c('%sconst %s *S  /**< */)', spacing, S_obj.c_type)
+        length = _c_accessor_get_expr(field.type.expr, fields)
+    else:
+        _h('%s (const %s *R  /**< */);', field.c_length_name, c_type)
+        _c('%s (const %s *R  /**< */)', field.c_length_name, c_type)
+        length = _c_accessor_get_expr(field.type.expr, fields)
     _c('{')
-    _c('    return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
+    _c('    return %s;', length)
     _c('}')
 
     if field.type.member.is_simple:
@@ -560,25 +1627,38 @@ def _c_accessors_list(self, field):
         _hc(' **')
         _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
         _hc(' ** ')
-        _hc(' ** @param const %s *R', self.c_type)
+        _hc(' ** @param const %s *R', c_type)
         _hc(' ** @returns xcb_generic_iterator_t')
         _hc(' **')
         _hc(' *****************************************************************************/')
         _hc(' ')
         _hc('xcb_generic_iterator_t')
-        _h('%s (const %s *R  /**< */);', field.c_end_name, self.c_type)
-        _c('%s (const %s *R  /**< */)', field.c_end_name, self.c_type)
+        if switch_obj is not None:
+            _hc('%s (const %s *R  /**< */,', field.c_end_name, R_obj.c_type)
+            spacing = ' '*(len(field.c_end_name)+2)
+            _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
+            _c('%sconst %s *S  /**< */)', spacing, S_obj.c_type)
+        else:
+            _h('%s (const %s *R  /**< */);', field.c_end_name, c_type)
+            _c('%s (const %s *R  /**< */)', field.c_end_name, c_type)
         _c('{')
         _c('    xcb_generic_iterator_t i;')
-
-        if field.prev_varsized_field == None:
-            _c('    i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
+        
+        param = 'R' if switch_obj is None else 'S'
+        if switch_obj is not None:
+            _c('    i.data = %s + %s;', fields[field.c_field_name][0], 
+               _c_accessor_get_expr(field.type.expr, fields))
+        elif field.prev_varsized_field == None:
+            _c('    i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, 
+               _c_accessor_get_expr(field.type.expr, fields))
         else:
-            _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
-            _c('    i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
+            _c('    xcb_generic_iterator_t child = %s;', 
+               _c_iterator_get_end(field.prev_varsized_field, 'R'))
+            _c('    i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, 
+               _c_accessor_get_expr(field.type.expr, fields))
 
         _c('    i.rem = 0;')
-        _c('    i.index = (char *) i.data - (char *) R;')
+        _c('    i.index = (char *) i.data - (char *) %s;', param)
         _c('    return i;')
         _c('}')
 
@@ -589,25 +1669,36 @@ def _c_accessors_list(self, field):
         _hc(' **')
         _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
         _hc(' ** ')
-        _hc(' ** @param const %s *R', self.c_type)
+        _hc(' ** @param const %s *R', c_type)
         _hc(' ** @returns %s', field.c_iterator_type)
         _hc(' **')
         _hc(' *****************************************************************************/')
         _hc(' ')
+
         _hc('%s', field.c_iterator_type)
-        _h('%s (const %s *R  /**< */);', field.c_iterator_name, self.c_type)
-        _c('%s (const %s *R  /**< */)', field.c_iterator_name, self.c_type)
+        if switch_obj is not None:
+            _hc('%s (const %s *R  /**< */,', field.c_iterator_name, R_obj.c_type)
+            spacing = ' '*(len(field.c_iterator_name)+2)
+            _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
+            _c('%sconst %s *S  /**< */)', spacing, S_obj.c_type)
+        else:
+            _h('%s (const %s *R  /**< */);', field.c_iterator_name, c_type)
+            _c('%s (const %s *R  /**< */)', field.c_iterator_name, c_type)
         _c('{')
         _c('    %s i;', field.c_iterator_type)
 
-        if field.prev_varsized_field == None:
+        if switch_obj is not None:
+            _c('    i.data = %s;', fields[field.c_field_name][0])
+            _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
+        elif field.prev_varsized_field == None:
             _c('    i.data = (%s *) (R + 1);', field.c_field_type)
         else:
             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
-            _c('    i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
-
-        _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
-        _c('    i.index = (char *) i.data - (char *) R;')
+            _c('    i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', 
+               field.c_field_type, type_pad_type(field.c_field_type))
+        if switch_obj is None:
+            _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
+        _c('    i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
         _c('    return i;')
         _c('}')
 
@@ -615,11 +1706,17 @@ def _c_accessors(self, name, base):
     '''
     Declares the accessor functions for the fields of a structure.
     '''
-    for field in self.fields:
-        if field.type.is_list and not field.type.fixed_size():
-            _c_accessors_list(self, field)
-        elif field.prev_varsized_field != None:
-            _c_accessors_field(self, field)
+    # no accessors for switch itself - 
+    # switch always needs to be unpacked explicitly
+#    if self.is_switch:
+#        pass
+#    else:
+    if True:
+        for field in self.fields:
+            if field.type.is_list and not field.type.fixed_size():
+                _c_accessors_list(self, field)
+            elif field.prev_varsized_field is not None or not field.type.fixed_size():
+                _c_accessors_field(self, field)
 
 def c_simple(self, name):
     '''
@@ -655,23 +1752,43 @@ def _c_complex(self):
 
     varfield = None
     for field in self.fields:
-        if not field.type.fixed_size():
+        if not field.type.fixed_size() and not self.is_switch and not self.is_union:
             varfield = field.c_field_name
             continue
-        if varfield != None and not field.type.is_pad and field.wire:
-            errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
-            sys.stderr.write(errmsg)
-            # sys.exit(1)
         if field.wire:
             struct_fields.append(field)
-        
+    
     for field in struct_fields:
-        if len(field.c_field_type) > maxtypelen:
-            maxtypelen = len(field.c_field_type)
+        length = len(field.c_field_type)
+        # account for '*' pointer_spec
+        if not field.type.fixed_size():
+            length += 1
+        maxtypelen = max(maxtypelen, length)
+
+    def _c_complex_field(self, field, space=''):
+        if (field.type.fixed_size() or 
+            # in case of switch with switch children, don't make the field a pointer
+            # necessary for unserialize to work
+            (self.is_switch and field.type.is_switch)):
+            spacing = ' ' * (maxtypelen - len(field.c_field_type))
+            _h('%s    %s%s %s%s; /**<  */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
+        else:
+            spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
+            _h('%s    %s%s *%s%s; /**<  */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
 
-    for field in struct_fields:
-        spacing = ' ' * (maxtypelen - len(field.c_field_type))
-        _h('    %s%s %s%s; /**<  */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
+    if not self.is_switch:
+        for field in struct_fields:
+            _c_complex_field(self, field)
+    else:
+        for b in self.bitcases:
+            space = ''
+            if b.type.has_name:
+                _h('    struct _%s {', b.c_field_name)
+                space = '    '
+            for field in b.type.fields:
+                _c_complex_field(self, field, space)
+            if b.type.has_name:
+                _h('    } %s;', b.c_field_name)
 
     _h('} %s;', self.c_type)
 
@@ -692,7 +1809,7 @@ def c_union(self, name):
     _c_complex(self)
     _c_iterator(self, name)
 
-def _c_request_helper(self, name, cookie_type, void, regular):
+def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
     '''
     Declares a request function.
     '''
@@ -725,15 +1842,18 @@ def _c_request_helper(self, name, cookie_type, void, regular):
     func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
 
     # What our function name is
-    func_name = self.c_request_name
+    func_name = self.c_request_name if not aux else self.c_aux_name
     if checked:
-        func_name = self.c_checked_name
+        func_name = self.c_checked_name if not aux else self.c_aux_checked_name
     if unchecked:
-        func_name = self.c_unchecked_name
+        func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
 
     param_fields = []
     wire_fields = []
     maxtypelen = len('xcb_connection_t')
+    serial_fields = []
+    # special case: list with variable size elements
+    list_with_var_size_elems = False
 
     for field in self.fields:
         if field.visible:
@@ -742,10 +1862,17 @@ def _c_request_helper(self, name, cookie_type, void, regular):
         if field.wire and not field.auto:
             # We need to set the field up in the structure
             wire_fields.append(field)
+        if field.type.need_serialize or field.type.need_sizeof:
+            serial_fields.append(field)
         
     for field in param_fields:
-        if len(field.c_field_const_type) > maxtypelen:
-            maxtypelen = len(field.c_field_const_type)
+        c_field_const_type = field.c_field_const_type 
+        if field.type.need_serialize and not aux:
+            c_field_const_type = "const void"
+        if len(c_field_const_type) > maxtypelen:
+            maxtypelen = len(c_field_const_type)
+        if field.type.is_list and not field.type.member.fixed_size():
+            list_with_var_size_elems = True
 
     _h_setlevel(1)
     _c_setlevel(1)
@@ -777,8 +1904,11 @@ def _c_request_helper(self, name, cookie_type, void, regular):
     _hc(' ** @param xcb_connection_t%s *c', spacing)
 
     for field in param_fields:
-        spacing = ' ' * (maxtypelen - len(field.c_field_const_type))
-        _hc(' ** @param %s%s %s%s', field.c_field_const_type, spacing, field.c_pointer, field.c_field_name)
+        c_field_const_type = field.c_field_const_type 
+        if field.type.need_serialize and not aux:
+            c_field_const_type = "const void"
+        spacing = ' ' * (maxtypelen - len(c_field_const_type))
+        _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
 
     _hc(' ** @returns %s', cookie_type)
     _hc(' **')
@@ -796,16 +1926,28 @@ def _c_request_helper(self, name, cookie_type, void, regular):
     count = len(param_fields)
     for field in param_fields:
         count = count - 1
-        spacing = ' ' * (maxtypelen - len(field.c_field_const_type))
+        c_field_const_type = field.c_field_const_type 
+        c_pointer = field.c_pointer
+        if field.type.need_serialize and not aux:
+            c_field_const_type = "const void"
+            c_pointer = '*'
+        spacing = ' ' * (maxtypelen - len(c_field_const_type))
         comma = ',' if count else ');'
-        _h('%s%s%s %s%s  /**< */%s', func_spacing, field.c_field_const_type, spacing, field.c_pointer, field.c_field_name, comma)
+        _h('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type, 
+           spacing, c_pointer, field.c_field_name, comma)
         comma = ',' if count else ')'
-        _c('%s%s%s %s%s  /**< */%s', func_spacing, field.c_field_const_type, spacing, field.c_pointer, field.c_field_name, comma)
+        _c('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type, 
+           spacing, c_pointer, field.c_field_name, comma)
 
     count = 2
-    for field in param_fields:
-        if not field.type.fixed_size():
-            count = count + 2
+    if not self.var_followed_by_fixed_fields:
+        for field in param_fields:
+            if not field.type.fixed_size():
+                count = count + 2
+                if field.type.need_serialize:
+                    # _serialize() keeps track of padding automatically
+                    count -= 1
+    dimension = count + 2
 
     _c('{')
     _c('    static const xcb_protocol_request_t xcb_req = {')
@@ -815,16 +1957,31 @@ def _c_request_helper(self, name, cookie_type, void, regular):
     _c('        /* isvoid */ %d', 1 if void else 0)
     _c('    };')
     _c('    ')
-    _c('    struct iovec xcb_parts[%d];', count + 2)
+
+    _c('    struct iovec xcb_parts[%d];', dimension)
     _c('    %s xcb_ret;', func_cookie)
     _c('    %s xcb_out;', self.c_type)
-    _c('    ')
+    if self.var_followed_by_fixed_fields:
+        _c('    /* in the protocol description, variable size fields are followed by fixed size fields */')
+        _c('    void *xcb_aux = 0;')
+        
 
+    for idx, f in enumerate(serial_fields):
+        if aux:
+            _c('    void *xcb_aux%d = 0;' % (idx))
+    if list_with_var_size_elems:
+        _c('    unsigned int i;')
+        _c('    unsigned int xcb_tmp_len;')
+        _c('    char *xcb_tmp;')
+    _c('    ')
+    # simple request call tracing
+#    _c('    printf("in function %s\\n");' % func_name)     
+    # fixed size fields
     for field in wire_fields:
         if field.type.fixed_size():
             if field.type.is_expr:
-                _c('    xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
-
+                _c('    xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
             elif field.type.is_pad:
                 if field.type.nmemb == 1:
                     _c('    xcb_out.%s = 0;', field.c_field_name)
@@ -836,25 +1993,94 @@ def _c_request_helper(self, name, cookie_type, void, regular):
                 else:
                     _c('    memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
 
-    _c('    ')
-    _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
-    _c('    xcb_parts[2].iov_len = sizeof(xcb_out);')
-    _c('    xcb_parts[3].iov_base = 0;')
-    _c('    xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
+    def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
+        serialize_args = get_serialize_params(context, type_obj, 
+                                              c_field_name, 
+                                              aux_var)[2]
+        return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
 
-    count = 4
-    for field in param_fields:
-        if not field.type.fixed_size():
-            _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
-            if field.type.is_list:
-                _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
-            else:
-                _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, 'Uh oh', field.type.c_wiretype)
-            _c('    xcb_parts[%d].iov_base = 0;', count + 1)
-            _c('    xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count + 1, count)
-            count = count + 2
+    # calls in order to free dyn. all. memory
+    free_calls = []
 
+    _c('    ')
+    if not self.var_followed_by_fixed_fields:
+        _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
+        _c('    xcb_parts[2].iov_len = sizeof(xcb_out);')
+        _c('    xcb_parts[3].iov_base = 0;')
+        _c('    xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
+
+        count = 4
+
+        for field in param_fields:
+            if not field.type.fixed_size():
+                _c('    /* %s %s */', field.type.c_type, field.c_field_name)
+                # default: simple cast to char *
+                if not field.type.need_serialize and not field.type.need_sizeof:
+                    _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
+                    if field.type.is_list:
+                        if field.type.member.fixed_size():
+                            _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, 
+                               _c_accessor_get_expr(field.type.expr, None), 
+                               field.type.member.c_wiretype)
+                        else:
+                            list_length = _c_accessor_get_expr(field.type.expr, None)
+    
+                            length = ''
+                            _c("    xcb_parts[%d].iov_len = 0;" % count)
+                            _c("    xcb_tmp = (char *)%s;", field.c_field_name)
+                            _c("    for(i=0; i<%s; i++) {" % list_length)
+                            _c("        xcb_tmp_len = %s(xcb_tmp);" % 
+                                              (field.type.c_sizeof_name))
+                            _c("        xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
+                            _c("        xcb_tmp += xcb_tmp_len;")
+                            _c("    }")                        
+                    else:
+                        # not supposed to happen
+                        raise Exception("unhandled variable size field %s" % field.c_field_name)
+                else:
+                    if not aux:
+                        _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
+                    idx = serial_fields.index(field)
+                    aux_var = '&xcb_aux%d' % idx
+                    context = 'serialize' if aux else 'sizeof'
+                    _c('    xcb_parts[%d].iov_len = ', count)
+                    if aux:
+                        serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
+                        _c('      %s (%s);', field.type.c_serialize_name, serialize_args)
+                        _c('    xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
+                        free_calls.append('    free(xcb_aux%d);' % idx)
+                    else:
+                        serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
+                        func_name = field.type.c_sizeof_name
+                        _c('      %s (%s);', func_name, serialize_args)
+
+                count += 1
+                if not (field.type.need_serialize or field.type.need_sizeof):
+                    # the _serialize() function keeps track of padding automatically
+                    _c('    xcb_parts[%d].iov_base = 0;', count)
+                    _c('    xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
+                    count += 1
+
+    # elif self.var_followed_by_fixed_fields:
+    else:
+        _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
+        # request header: opcodes + length
+        _c('    xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);') 
+        count += 1
+        # call _serialize()
+        buffer_var = '&xcb_aux'
+        serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
+        _c('    xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
+        _c('    xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
+        free_calls.append('    free(xcb_aux);')
+        # no padding necessary - _serialize() keeps track of padding automatically
+
+    _c('    ')
     _c('    xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
+    
+    # free dyn. all. data, if any
+    for f in free_calls:
+        _c(f)
     _c('    return xcb_ret;')
     _c('}')
 
@@ -865,7 +2091,29 @@ def _c_reply(self, name):
     spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
     spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
     spacing3 = ' ' * (len(self.c_reply_name) + 2)
-
+    
+    # check if _unserialize() has to be called for any field
+    def look_for_special_cases(complex_obj):
+        unserialize_fields = []
+        # no unserialize call in case of switch
+        if not complex_obj.is_switch:
+            for field in complex_obj.fields:
+                # three cases: 1. field with special case
+                #              2. container that contains special case field
+                #              3. list with special case elements
+                if field.type.var_followed_by_fixed_fields:
+                    unserialize_fields.append(field)
+                elif field.type.is_container:
+                    unserialize_fields += look_for_special_cases(field.type)
+                elif field.type.is_list:
+                    if field.type.member.var_followed_by_fixed_fields:
+                        unserialize_fields.append(field)
+                    if field.type.member.is_container:
+                        unserialize_fields += look_for_special_cases(field.type.member)
+        return unserialize_fields
+    
+    unserialize_fields = look_for_special_cases(self.reply)
+    
     _h('')
     _h('/**')
     _h(' * Return the reply')
@@ -900,7 +2148,35 @@ def _c_reply(self, name):
     _h('%sxcb_generic_error_t%s **e  /**< */);', spacing3, spacing2)
     _c('%sxcb_generic_error_t%s **e  /**< */)', spacing3, spacing2)
     _c('{')
-    _c('    return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
+    
+    if len(unserialize_fields)>0:
+        # certain variable size fields need to be unserialized explicitly
+        _c('    %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', 
+           self.c_reply_type, self.c_reply_type)
+        _c('    int i;')
+        for field in unserialize_fields:
+            if field.type.is_list:
+                _c('    %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
+                _c('    int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
+                _c('    %s *%s_data;', field.c_field_type, field.c_field_name)
+            else:
+                raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
+        # call _unserialize(), using the reply as source and target buffer
+        _c('    /* special cases: transform parts of the reply to match XCB data structures */')
+        for field in unserialize_fields:
+            if field.type.is_list:
+                _c('    for(i=0; i<%s_len; i++) {', field.c_field_name)
+                _c('        %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
+                _c('        %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name, 
+                   field.c_field_name, field.c_field_name)
+                _c('        %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
+                _c('    }')
+        # return the transformed reply
+        _c('    return reply;')
+    
+    else:
+        _c('    return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
+
     _c('}')
 
 def _c_opcode(name, opcode):
@@ -948,6 +2224,9 @@ def c_request(self, name):
         # Request prototypes
         _c_request_helper(self, name, self.c_cookie_type, False, True)
         _c_request_helper(self, name, self.c_cookie_type, False, False)
+        if self.need_aux:
+            _c_request_helper(self, name, self.c_cookie_type, False, True, True)
+            _c_request_helper(self, name, self.c_cookie_type, False, False, True)
         # Reply accessors
         _c_accessors(self.reply, name + ('reply',), name)
         _c_reply(self, name)
@@ -955,6 +2234,10 @@ def c_request(self, name):
         # Request prototypes
         _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
         _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
+        if self.need_aux:
+            _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
+            _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
+
 
 def c_event(self, name):
     '''
@@ -1002,7 +2285,7 @@ output = {'open'    : c_open,
           'union'   : c_union,
           'request' : c_request,
           'event'   : c_event,
-          'error'   : c_error
+          'error'   : c_error
           }
 
 # Boilerplate below this point
@@ -1010,26 +2293,26 @@ output = {'open'    : c_open,
 # Check for the argument that specifies path to the xcbgen python package.
 try:
     opts, args = getopt.getopt(sys.argv[1:], 'p:')
-except getopt.GetoptError, err:
-    print str(err)
-    print 'Usage: c_client.py [-p path] file.xml'
+except getopt.GetoptError as err:
+    print(err)
+    print('Usage: c_client.py [-p path] file.xml')
     sys.exit(1)
 
 for (opt, arg) in opts:
     if opt == '-p':
-        sys.path.append(arg)
+        sys.path.insert(1, arg)
 
 # Import the module class
 try:
     from xcbgen.state import Module
 except ImportError:
-    print ''
-    print 'Failed to load the xcbgen Python package!'
-    print 'Make sure that xcb/proto installed it on your Python path.'
-    print 'If not, you will need to create a .pth file or define $PYTHONPATH'
-    print 'to extend the path.'
-    print 'Refer to the README file in xcb/proto for more info.'
-    print ''
+    print('''
+Failed to load the xcbgen Python package!
+Make sure that xcb/proto installed it on your Python path.
+If not, you will need to create a .pth file or define $PYTHONPATH
+to extend the path.
+Refer to the README file in xcb/proto for more info.
+''')
     raise
 
 # Parse the xml header
index 35d8768..44f650a 100644 (file)
--- a/src/xcb.h
+++ b/src/xcb.h
 #include <stdint.h>
 #endif
 
+#ifndef _WIN32
 #include <sys/uio.h>
+#else
+#include "xcb_windefs.h"
+#endif
 #include <pthread.h>
 
 
@@ -65,6 +69,21 @@ extern "C" {
 /** X_TCP_PORT + display number = server port for TCP transport */
 #define X_TCP_PORT 6000
 
+/** xcb connection errors because of socket, pipe and other stream errors. */
+#define XCB_CONN_ERROR 1
+
+/** xcb connection shutdown because of extension not sppported */
+#define XCB_CONN_CLOSED_EXT_NOTSUPPORTED 2
+
+/** malloc(), calloc() and realloc() error upon failure, for eg ENOMEM */
+#define XCB_CONN_CLOSED_MEM_INSUFFICIENT 3
+
+/** Connection closed, exceeding request length that server accepts. */
+#define XCB_CONN_CLOSED_REQ_LEN_EXCEED 4
+
+/** Connection closed, error during parsing display string. */
+#define XCB_CONN_CLOSED_PARSE_ERR 5
+
 #define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1))
 
 /* Opaque structures */
@@ -268,6 +287,22 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c);
 xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c);
 
 /**
+ * @brief Returns the next event without reading from the connection.
+ * @param c: The connection to the X server.
+ * @return The next already queued event from the server.
+ *
+ * This is a version of xcb_poll_for_event that only examines the
+ * event queue for new events. The function doesn't try to read new
+ * events from the connection if no queued events are found.
+ *
+ * This function is useful for callers that know in advance that all
+ * interesting events have already been read from the connection. For
+ * example, callers might use xcb_wait_for_reply and be interested
+ * only of events that preceded a specific reply.
+ */
+xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c);
+
+/**
  * @brief Return the error for a request, or NULL if none can ever arrive.
  * @param c: The connection to the X server.
  * @param cookie: The request cookie.
@@ -376,15 +411,18 @@ int xcb_get_file_descriptor(xcb_connection_t *c);
 /**
  * @brief Test whether the connection has shut down due to a fatal error.
  * @param c: The connection.
- * @return 1 if the connection is in an error state; 0 otherwise.
+ * @return > 0 if the connection is in an error state; 0 otherwise.
  *
  * Some errors that occur in the context of an xcb_connection_t
  * are unrecoverable. When such an error occurs, the
  * connection is shut down and further operations on the
  * xcb_connection_t have no effect.
  *
- * @todo Other functions should document the conditions in
- * which they shut down the connection.
+ * @return XCB_CONN_ERROR, because of socket errors, pipe errors or other stream errors.
+ * @return XCB_CONN_CLOSED_EXT_NOTSUPPORTED, when extension not supported.
+ * @return XCB_CONN_CLOSED_MEM_INSUFFICIENT, when memory not available.
+ * @return XCB_CONN_CLOSED_REQ_LEN_EXCEED, exceeding request length that server accepts.
+ * @return XCB_CONN_CLOSED_PARSE_ERR, error during parsing display string.
  */
 int xcb_connection_has_error(xcb_connection_t *c);
 
old mode 100755 (executable)
new mode 100644 (file)
index d774d10..a5b730c
 
 /* Authorization systems for the X protocol. */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <assert.h>
 #include <X11/Xauth.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/un.h>
 #include <sys/param.h>
 #include <unistd.h>
 #include <stdlib.h>
 
+#ifdef __INTERIX
+/* _don't_ ask. interix has INADDR_LOOPBACK in here. */
+#include <rpc/types.h>
+#endif
+
+#ifdef _WIN32
+#ifdef HASXDMAUTH
+/* We must include the wrapped windows.h before any system header which includes
+   it unwrapped, to avoid conflicts with types defined in X headers */
+#include <X11/Xwindows.h>
+#endif
+#include "xcb_windefs.h"
+#else
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#endif /* _WIN32 */
+
 #include "xcb.h"
 #include "xcbint.h"
 
@@ -256,7 +276,7 @@ static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
 {
     socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
     socklen_t actual_socknamelen = socknamelen;
-    struct sockaddr *sockname = malloc(socknamelen), *new_sockname = NULL;
+    struct sockaddr *sockname = malloc(socknamelen);
 
     if (sockname == NULL)
         return NULL;
@@ -269,14 +289,17 @@ static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
 
     if (actual_socknamelen > socknamelen)
     {
+        struct sockaddr *new_sockname = NULL;
         socknamelen = actual_socknamelen;
 
-        if ((new_sockname = realloc(sockname, actual_socknamelen)) == NULL ||
-            socket_func(fd, new_sockname, &actual_socknamelen) == -1 ||
-            actual_socknamelen > socknamelen) 
+        if ((new_sockname = realloc(sockname, actual_socknamelen)) == NULL)
             goto sock_or_realloc_error;
 
         sockname = new_sockname;
+
+        if (socket_func(fd, sockname, &actual_socknamelen) == -1 ||
+            actual_socknamelen > socknamelen)
+            goto sock_or_realloc_error;
     }
 
     return sockname;
@@ -322,10 +345,15 @@ int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display)
     if (!info->namelen)
         goto no_auth;   /* out of memory */
 
-    if (!gotsockname && (sockname = get_peer_sock_name(getsockname, fd)) == NULL)
+    if (!gotsockname)
     {
-        free(info->name);
-        goto no_auth;   /* can only authenticate sockets */
+        free(sockname);
+
+        if ((sockname = get_peer_sock_name(getsockname, fd)) == NULL)
+        {
+            free(info->name);
+            goto no_auth;   /* can only authenticate sockets */
+        }
     }
 
     ret = compute_auth(info, authptr, sockname);
old mode 100755 (executable)
new mode 100644 (file)
index 7e18891..725502a
@@ -30,7 +30,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <netinet/in.h>
 #include <fcntl.h>
 #include <errno.h>
 
 #include "xcbint.h"
 #if USE_POLL
 #include <poll.h>
-#else
+#elif !defined _WIN32
 #include <sys/select.h>
 #endif
 
+#ifdef _WIN32
+#include "xcb_windefs.h"
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif /* _WIN32 */
+
+/* SHUT_RDWR is fairly recent and is not available on all platforms */
+#if !defined(SHUT_RDWR)
+#define SHUT_RDWR 2
+#endif
+
 typedef struct {
     uint8_t  status;
     uint8_t  pad0[5];
     uint16_t length;
 } xcb_setup_generic_t;
 
-static const int error_connection = 1;
+static const int xcb_con_error = XCB_CONN_ERROR;
+static const int xcb_con_closed_mem_er = XCB_CONN_CLOSED_MEM_INSUFFICIENT;
+static const int xcb_con_closed_parse_er = XCB_CONN_CLOSED_PARSE_ERR;
 
 static int set_fd_flags(const int fd)
 {
+/* Win32 doesn't have file descriptors and the fcntl function. This block sets the socket in non-blocking mode */
+
+#ifdef _WIN32
+   u_long iMode = 1; /* non-zero puts it in non-blocking mode, 0 in blocking mode */   
+   int ret = 0;
+
+   ret = ioctlsocket(fd, FIONBIO, &iMode);
+   if(ret != 0) 
+       return 0;
+   return 1;
+#else
     int flags = fcntl(fd, F_GETFL, 0);
     if(flags == -1)
         return 0;
@@ -61,6 +85,7 @@ static int set_fd_flags(const int fd)
     if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
         return 0;
     return 1;
+#endif /* _WIN32 */
 }
 
 static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info)
@@ -153,12 +178,40 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
 {
     int n;
     assert(!c->out.queue_len);
+
+#ifdef _WIN32
+    int i = 0;
+    int ret = 0,err = 0;
+    struct iovec *vec;
+    n = 0;
+
+    /* Could use the WSASend win32 function for scatter/gather i/o but setting up the WSABUF struct from
+       an iovec would require more work and I'm not sure of the benefit....works for now */
+    vec = *vector;
+    while(i < *count)
+    {           
+         ret = send(c->fd,vec->iov_base,vec->iov_len,0);        
+         if(ret == SOCKET_ERROR)
+         {
+             err  = WSAGetLastError();
+             if(err == WSAEWOULDBLOCK)
+             {
+                 return 1;
+             }
+         }
+         n += ret;
+         *vec++;
+         i++;
+    }
+#else
     n = writev(c->fd, *vector, *count);
     if(n < 0 && errno == EAGAIN)
         return 1;
+#endif /* _WIN32 */    
+
     if(n <= 0)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, XCB_CONN_ERROR);
         return 0;
     }
 
@@ -207,18 +260,20 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
 {
     xcb_connection_t* c;
 
+#ifndef _WIN32
 #ifndef USE_POLL
     if(fd >= FD_SETSIZE) /* would overflow in FD_SET */
     {
         close(fd);
-        return (xcb_connection_t *) &error_connection;
+        return _xcb_conn_ret_error(XCB_CONN_ERROR);
     }
 #endif
+#endif /* !_WIN32*/
 
     c = calloc(1, sizeof(xcb_connection_t));
     if(!c) {
         close(fd);
-        return (xcb_connection_t *) &error_connection;
+        return _xcb_conn_ret_error(XCB_CONN_CLOSED_MEM_INSUFFICIENT) ;
     }
 
     c->fd = fd;
@@ -235,7 +290,7 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
         ))
     {
         xcb_disconnect(c);
-        return (xcb_connection_t *) &error_connection;
+        return _xcb_conn_ret_error(XCB_CONN_ERROR);
     }
 
     return c;
@@ -247,6 +302,9 @@ void xcb_disconnect(xcb_connection_t *c)
         return;
 
     free(c->setup);
+
+    /* disallow further sends and receives */
+    shutdown(c->fd, SHUT_RDWR);
     close(c->fd);
 
     pthread_mutex_destroy(&c->iolock);
@@ -257,13 +315,42 @@ void xcb_disconnect(xcb_connection_t *c)
     _xcb_xid_destroy(c);
 
     free(c);
+
+#ifdef _WIN32
+    WSACleanup();
+#endif
 }
 
 /* Private interface */
 
-void _xcb_conn_shutdown(xcb_connection_t *c)
+void _xcb_conn_shutdown(xcb_connection_t *c, int err)
 {
-    c->has_error = 1;
+    c->has_error = err;
+}
+
+/* Return connection error state.
+ * To make thread-safe, I need a seperate static
+ * variable for every possible error.
+ */
+xcb_connection_t *_xcb_conn_ret_error(int err)
+{
+
+    switch(err)
+    {
+        case XCB_CONN_CLOSED_MEM_INSUFFICIENT:
+        {
+            return (xcb_connection_t *) &xcb_con_closed_mem_er;
+        }
+        case XCB_CONN_CLOSED_PARSE_ERR:
+        {
+            return (xcb_connection_t *) &xcb_con_closed_parse_er;
+        }
+        case XCB_CONN_ERROR:
+        default:
+        {
+            return (xcb_connection_t *) &xcb_con_error;
+        }
+    }
 }
 
 int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count)
@@ -311,13 +398,20 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
     do {
 #if USE_POLL
         ret = poll(&fd, 1, -1);
+        /* If poll() returns an event we didn't expect, such as POLLNVAL, treat
+         * it as if it failed. */
+        if(ret >= 0 && (fd.revents & ~fd.events))
+        {
+            ret = -1;
+            break;
+        }
 #else
         ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
 #endif
     } while (ret == -1 && errno == EINTR);
     if(ret < 0)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, XCB_CONN_ERROR);
         ret = 0;
     }
     pthread_mutex_lock(&c->iolock);
old mode 100755 (executable)
new mode 100644 (file)
index a644c63..4998cdd
 #include "xcbint.h"
 #if USE_POLL
 #include <poll.h>
-#else
+#endif
+#ifndef _WIN32
 #include <sys/select.h>
+#include <sys/socket.h>
 #endif
 
+#ifdef _WIN32
+#include "xcb_windefs.h"
+#endif /* _WIN32 */
+
 #define XCB_ERROR 0
 #define XCB_REPLY 1
 #define XCB_XGE_EVENT 35
@@ -64,11 +70,22 @@ typedef struct pending_reply {
 } pending_reply;
 
 typedef struct reader_list {
-    unsigned int request;
+    uint64_t request;
     pthread_cond_t *data;
     struct reader_list *next;
 } reader_list;
 
+static void remove_finished_readers(reader_list **prev_reader, uint64_t completed)
+{
+    while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, completed))
+    {
+        /* If you don't have what you're looking for now, you never
+         * will. Wake up and leave me alone. */
+        pthread_cond_signal((*prev_reader)->data);
+        *prev_reader = (*prev_reader)->next;
+    }
+}
+
 static int read_packet(xcb_connection_t *c)
 {
     xcb_generic_reply_t genrep;
@@ -119,6 +136,8 @@ static int read_packet(xcb_connection_t *c)
 
         if(genrep.response_type == XCB_ERROR)
             c->in.request_completed = c->in.request_read;
+
+        remove_finished_readers(&c->in.readers, c->in.request_completed);
     }
 
     if(genrep.response_type == XCB_ERROR || genrep.response_type == XCB_REPLY)
@@ -143,20 +162,14 @@ static int read_packet(xcb_connection_t *c)
     }
 
     /* XGE events may have sizes > 32 */
-#ifndef _F_ENABLE_XI2_SENDEVENT_
-    if (genrep.response_type == XCB_XGE_EVENT)
-#else//_F_ENABLE_XI2_SENDEVENT_
     if ((genrep.response_type & 0x7f) == XCB_XGE_EVENT)
-#endif//_F_ENABLE_XI2_SENDEVENT_
-    {
         eventlength = genrep.length * 4;
-    }
 
     buf = malloc(length + eventlength +
             (genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t)));
     if(!buf)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
         return 0;
     }
 
@@ -189,11 +202,10 @@ static int read_packet(xcb_connection_t *c)
     if( genrep.response_type == XCB_REPLY ||
        (genrep.response_type == XCB_ERROR && pend && (pend->flags & XCB_REQUEST_CHECKED)))
     {
-        reader_list *reader;
         struct reply_list *cur = malloc(sizeof(struct reply_list));
         if(!cur)
         {
-            _xcb_conn_shutdown(c);
+            _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
             free(buf);
             return 0;
         }
@@ -201,17 +213,8 @@ static int read_packet(xcb_connection_t *c)
         cur->next = 0;
         *c->in.current_reply_tail = cur;
         c->in.current_reply_tail = &cur->next;
-        for(reader = c->in.readers; 
-           reader && 
-           XCB_SEQUENCE_COMPARE_32(reader->request, <=, c->in.request_read);
-           reader = reader->next)
-       {
-            if(XCB_SEQUENCE_COMPARE_32(reader->request, ==, c->in.request_read))
-            {
-                pthread_cond_signal(reader->data);
-                break;
-            }
-       }
+        if(c->in.readers && c->in.readers->request == c->in.request_read)
+            pthread_cond_signal(c->in.readers->data);
         return 1;
     }
 
@@ -219,7 +222,7 @@ static int read_packet(xcb_connection_t *c)
     event = malloc(sizeof(struct event_list));
     if(!event)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
         free(buf);
         return 0;
     }
@@ -261,10 +264,14 @@ static int read_block(const int fd, void *buf, const ssize_t len)
     int done = 0;
     while(done < len)
     {
-        int ret = read(fd, ((char *) buf) + done, len - done);
+        int ret = recv(fd, ((char *) buf) + done, len - done, 0);
         if(ret > 0)
             done += ret;
+#ifndef _WIN32
         if(ret < 0 && errno == EAGAIN)
+#else
+        if(ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
+#endif /* !_Win32 */
         {
 #if USE_POLL
             struct pollfd pfd;
@@ -278,10 +285,13 @@ static int read_block(const int fd, void *buf, const ssize_t len)
             fd_set fds;
             FD_ZERO(&fds);
             FD_SET(fd, &fds);
+
+           /* Initializing errno here makes sure that for Win32 this loop will execute only once */
+           errno = 0;  
            do {
                ret = select(fd + 1, &fds, 0, 0, 0);
            } while (ret == -1 && errno == EINTR);
-#endif
+#endif /* USE_POLL */
         }
         if(ret <= 0)
             return ret;
@@ -289,7 +299,7 @@ static int read_block(const int fd, void *buf, const ssize_t len)
     return len;
 }
 
-static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, xcb_generic_error_t **error)
+static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, xcb_generic_error_t **error)
 {
     struct reply_list *head;
 
@@ -298,7 +308,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
         head = 0;
     /* 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. */
-    else if(XCB_SEQUENCE_COMPARE_32(request, <, c->in.request_read))
+    else if(XCB_SEQUENCE_COMPARE(request, <, c->in.request_read))
     {
         head = _xcb_map_remove(c->in.replies, request);
         if(head && head->next)
@@ -306,7 +316,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
     }
     /* We're currently processing the responses to the request we want, and we
      * have a reply ready to return. So just return it without blocking. */
-    else if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_read) && c->in.current_reply)
+    else if(request == c->in.request_read && c->in.current_reply)
     {
         head = c->in.current_reply;
         c->in.current_reply = head->next;
@@ -315,7 +325,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
     }
     /* We know this request can't have any more replies, and we've already
      * established it doesn't have a reply now. Don't bother blocking. */
-    else if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_completed))
+    else if(request == c->in.request_completed)
         head = 0;
     /* We may have more replies on the way for this request: block until we're
      * sure. */
@@ -344,61 +354,70 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
     return 1;
 }
 
-/* Public interface */
-
-void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
+static void insert_reader(reader_list **prev_reader, reader_list *reader, uint64_t request, pthread_cond_t *cond)
 {
-    uint64_t widened_request;
-    void *ret = 0;
-    if(e)
-        *e = 0;
-    if(c->has_error)
-        return 0;
+    while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request))
+        prev_reader = &(*prev_reader)->next;
+    reader->request = request;
+    reader->data = cond;
+    reader->next = *prev_reader;
+    *prev_reader = reader;
+}
 
-    pthread_mutex_lock(&c->iolock);
+static void remove_reader(reader_list **prev_reader, reader_list *reader)
+{
+    while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, reader->request))
+        if(*prev_reader == reader)
+        {
+            *prev_reader = (*prev_reader)->next;
+            break;
+        }
+}
 
-    widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
-    if(widened_request > c->out.request)
-        widened_request -= UINT64_C(1) << 32;
+static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e)
+{
+    void *ret = 0;
 
     /* If this request has not been written yet, write it. */
-    if(c->out.return_socket || _xcb_out_flush_to(c, widened_request))
+    if(c->out.return_socket || _xcb_out_flush_to(c, request))
     {
         pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
         reader_list reader;
-        reader_list **prev_reader;
-
-        for(prev_reader = &c->in.readers; 
-           *prev_reader && 
-           XCB_SEQUENCE_COMPARE_32((*prev_reader)->request, <=, request);
-           prev_reader = &(*prev_reader)->next)
-       {
-            /* empty */;
-       }
-        reader.request = request;
-        reader.data = &cond;
-        reader.next = *prev_reader;
-        *prev_reader = &reader;
+
+        insert_reader(&c->in.readers, &reader, request, &cond);
 
         while(!poll_for_reply(c, request, &ret, e))
             if(!_xcb_conn_wait(c, &cond, 0, 0))
                 break;
 
-        for(prev_reader = &c->in.readers;
-           *prev_reader && 
-           XCB_SEQUENCE_COMPARE_32((*prev_reader)->request, <=, request);
-           prev_reader = &(*prev_reader)->next)
-       {
-            if(*prev_reader == &reader)
-            {
-                *prev_reader = (*prev_reader)->next;
-                break;
-            }
-       }
+        remove_reader(&c->in.readers, &reader);
         pthread_cond_destroy(&cond);
     }
 
     _xcb_in_wake_up_next_reader(c);
+    return ret;
+}
+
+static uint64_t widen(xcb_connection_t *c, unsigned int request)
+{
+    uint64_t widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
+    if(widened_request > c->out.request)
+        widened_request -= UINT64_C(1) << 32;
+    return widened_request;
+}
+
+/* Public interface */
+
+void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
+{
+    void *ret;
+    if(e)
+        *e = 0;
+    if(c->has_error)
+        return 0;
+
+    pthread_mutex_lock(&c->iolock);
+    ret = wait_for_reply(c, widen(c, request), e);
     pthread_mutex_unlock(&c->iolock);
     return ret;
 }
@@ -409,7 +428,7 @@ static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_nex
     pend = malloc(sizeof(*pend));
     if(!pend)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
         return;
     }
 
@@ -424,66 +443,27 @@ static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_nex
         c->in.pending_replies_tail = &pend->next;
 }
 
-static void discard_reply(xcb_connection_t *c, unsigned int request)
+static void discard_reply(xcb_connection_t *c, uint64_t request)
 {
-    pending_reply *pend = 0;
+    void *reply;
     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);
+    /* Free any replies or errors that we've already read. Stop if
+     * xcb_wait_for_reply would block or we've run out of replies. */
+    while(poll_for_reply(c, request, &reply, 0) && reply)
+        free(reply);
 
+    /* If we've proven there are no more responses coming, we're done. */
+    if(XCB_SEQUENCE_COMPARE(request, <=, c->in.request_completed))
         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))
+        if(XCB_SEQUENCE_COMPARE((*prev_pend)->first_request, >, request))
             break;
 
-        if(XCB_SEQUENCE_COMPARE_32((*prev_pend)->first_request, ==, request))
+        if((*prev_pend)->first_request == request)
         {
             /* Pending reply found. Mark for discard: */
             (*prev_pend)->flags |= XCB_REQUEST_DISCARD_REPLY;
@@ -492,11 +472,7 @@ static void discard_reply(xcb_connection_t *c, unsigned int request)
     }
 
     /* 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);
+    insert_pending_discard(c, prev_pend, request);
 }
 
 void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence)
@@ -509,7 +485,7 @@ void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence)
         return;
 
     pthread_mutex_lock(&c->iolock);
-    discard_reply(c, sequence);
+    discard_reply(c, widen(c, sequence));
     pthread_mutex_unlock(&c->iolock);
 }
 
@@ -525,7 +501,7 @@ int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply,
     }
     assert(reply != 0);
     pthread_mutex_lock(&c->iolock);
-    ret = poll_for_reply(c, request, reply, error);
+    ret = poll_for_reply(c, widen(c, request), reply, error);
     pthread_mutex_unlock(&c->iolock);
     return ret;
 }
@@ -546,7 +522,7 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c)
     return ret;
 }
 
-xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
+static xcb_generic_event_t *poll_for_next_event(xcb_connection_t *c, int queued)
 {
     xcb_generic_event_t *ret = 0;
     if(!c->has_error)
@@ -554,30 +530,41 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
         pthread_mutex_lock(&c->iolock);
         /* FIXME: follow X meets Z architecture changes. */
         ret = get_event(c);
-        if(!ret && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */
+        if(!ret && !queued && c->in.reading == 0 && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */
             ret = get_event(c);
         pthread_mutex_unlock(&c->iolock);
     }
     return ret;
 }
 
+xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
+{
+    return poll_for_next_event(c, 0);
+}
+
+xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c)
+{
+    return poll_for_next_event(c, 1);
+}
+
 xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie)
 {
-    /* FIXME: this could hold the lock to avoid syncing unnecessarily, but
-     * that would require factoring the locking out of xcb_get_input_focus,
-     * xcb_get_input_focus_reply, and xcb_wait_for_reply. */
-    xcb_generic_error_t *ret;
+    uint64_t request;
+    xcb_generic_error_t *ret = 0;
     void *reply;
     if(c->has_error)
         return 0;
-    if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_expected)
-       && XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_completed))
+    pthread_mutex_lock(&c->iolock);
+    request = widen(c, cookie.sequence);
+    if(XCB_SEQUENCE_COMPARE(request, >=, c->in.request_expected)
+       && XCB_SEQUENCE_COMPARE(request, >, c->in.request_completed))
     {
-        free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), &ret));
-        assert(!ret);
+        _xcb_out_send_sync(c);
+        _xcb_out_flush_to(c, c->out.request);
     }
-    reply = xcb_wait_for_reply(c, cookie.sequence, &ret);
+    reply = wait_for_reply(c, request, &ret);
     assert(!reply);
+    pthread_mutex_unlock(&c->iolock);
     return ret;
 }
 
@@ -641,7 +628,7 @@ int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds
     assert(workaround != WORKAROUND_NONE || flags != 0);
     if(!pend)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
         return 0;
     }
     pend->first_request = pend->last_request = request;
@@ -669,14 +656,18 @@ void _xcb_in_replies_done(xcb_connection_t *c)
 
 int _xcb_in_read(xcb_connection_t *c)
 {
-    int n = read(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len);
+    int n = recv(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len, 0);
     if(n > 0)
         c->in.queue_len += n;
     while(read_packet(c))
         /* empty */;
+#ifndef _WIN32
     if((n > 0) || (n < 0 && errno == EAGAIN))
+#else
+    if((n > 0) || (n < 0 && WSAGetLastError() == WSAEWOULDBLOCK))
+#endif /* !_WIN32 */
         return 1;
-    _xcb_conn_shutdown(c);
+    _xcb_conn_shutdown(c, XCB_CONN_ERROR);
     return 0;
 }
 
@@ -695,7 +686,7 @@ int _xcb_in_read_block(xcb_connection_t *c, void *buf, int len)
         int ret = read_block(c->fd, (char *) buf + done, len - done);
         if(ret <= 0)
         {
-            _xcb_conn_shutdown(c);
+            _xcb_conn_shutdown(c, XCB_CONN_ERROR);
             return ret;
         }
     }
old mode 100755 (executable)
new mode 100644 (file)
index fbce7a0..c0601f2
 #include "xcbint.h"
 #include "bigreq.h"
 
-static int write_block(xcb_connection_t *c, struct iovec *vector, int count)
+static inline void send_request(xcb_connection_t *c, int isvoid, enum workarounds workaround, int flags, struct iovec *vector, int count)
 {
+    if(c->has_error)
+        return;
+
+    ++c->out.request;
+    if(!isvoid)
+        c->in.request_expected = c->out.request;
+    if(workaround != WORKAROUND_NONE || flags != 0)
+        _xcb_in_expect_reply(c, c->out.request, workaround, flags);
+
     while(count && c->out.queue_len + vector[0].iov_len <= sizeof(c->out.queue))
     {
         memcpy(c->out.queue + c->out.queue_len, vector[0].iov_base, vector[0].iov_len);
@@ -46,13 +55,29 @@ static int write_block(xcb_connection_t *c, struct iovec *vector, int count)
         ++vector, --count;
     }
     if(!count)
-        return 1;
+        return;
 
     --vector, ++count;
     vector[0].iov_base = c->out.queue;
     vector[0].iov_len = c->out.queue_len;
     c->out.queue_len = 0;
-    return _xcb_out_send(c, vector, count);
+    _xcb_out_send(c, vector, count);
+}
+
+static void send_sync(xcb_connection_t *c)
+{
+    static const union {
+        struct {
+            uint8_t major;
+            uint8_t pad;
+            uint16_t len;
+        } fields;
+        uint32_t packet;
+    } sync_req = { { /* GetInputFocus */ 43, 0, 1 } };
+    struct iovec vector[2];
+    vector[1].iov_base = (char *) &sync_req;
+    vector[1].iov_len = sizeof(sync_req);
+    send_request(c, 0, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY, vector + 1, 1);
 }
 
 static void get_socket_back(xcb_connection_t *c)
@@ -123,16 +148,8 @@ uint32_t xcb_get_maximum_request_length(xcb_connection_t *c)
 
 unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
 {
-    static const union {
-        struct {
-            uint8_t major;
-            uint8_t pad;
-            uint16_t len;
-        } fields;
-        uint32_t packet;
-    } sync_req = { { /* GetInputFocus */ 43, 0, 1 } };
     uint64_t request;
-    uint32_t prefix[3] = { 0 };
+    uint32_t prefix[2];
     int veclen = req->count;
     enum workarounds workaround = WORKAROUND_NONE;
 
@@ -156,7 +173,7 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
             const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext);
             if(!(extension && extension->present))
             {
-                _xcb_conn_shutdown(c);
+                _xcb_conn_shutdown(c, XCB_CONN_CLOSED_EXT_NOTSUPPORTED);
                 return 0;
             }
             ((uint8_t *) vector[0].iov_base)[0] = extension->major_opcode;
@@ -186,14 +203,22 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
         }
         else if(longlen > xcb_get_maximum_request_length(c))
         {
-            _xcb_conn_shutdown(c);
+            _xcb_conn_shutdown(c, XCB_CONN_CLOSED_REQ_LEN_EXCEED);
             return 0; /* server can't take this; maybe need BIGREQUESTS? */
         }
 
         /* set the length field. */
         ((uint16_t *) vector[0].iov_base)[1] = shortlen;
         if(!shortlen)
-            prefix[2] = ++longlen;
+        {
+            prefix[0] = ((uint32_t *) vector[0].iov_base)[0];
+            prefix[1] = ++longlen;
+            vector[0].iov_base = (uint32_t *) vector[0].iov_base + 1;
+            vector[0].iov_len -= sizeof(uint32_t);
+            --vector, ++veclen;
+            vector[0].iov_base = prefix;
+            vector[0].iov_len = sizeof(prefix);
+        }
     }
     flags &= ~XCB_REQUEST_RAW;
 
@@ -212,45 +237,21 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
         pthread_cond_wait(&c->out.cond, &c->iolock);
     get_socket_back(c);
 
-    request = ++c->out.request;
     /* send GetInputFocus (sync_req) when 64k-2 requests have been sent without
-     * a reply.
-     * Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
+     * a reply. */
+    if(req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2)
+        send_sync(c);
+    /* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
      * applications see sequence 0 as that is used to indicate
      * an error in sending the request */
-    while((req->isvoid &&
-       c->out.request == c->in.request_expected + (1 << 16) - 1) ||
-       request == 0)
-    {
-        prefix[0] = sync_req.packet;
-        _xcb_in_expect_reply(c, request, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY);
-        c->in.request_expected = c->out.request;
-       request = ++c->out.request;
-    }
-
-    if(workaround != WORKAROUND_NONE || flags != 0)
-        _xcb_in_expect_reply(c, request, workaround, flags);
-    if(!req->isvoid)
-        c->in.request_expected = c->out.request;
-
-    if(prefix[0] || prefix[2])
-    {
-        --vector, ++veclen;
-        if(prefix[2])
-        {
-            prefix[1] = ((uint32_t *) vector[1].iov_base)[0];
-            vector[1].iov_base = (uint32_t *) vector[1].iov_base + 1;
-            vector[1].iov_len -= sizeof(uint32_t);
-        }
-        vector[0].iov_len = sizeof(uint32_t) * ((prefix[0] ? 1 : 0) + (prefix[2] ? 2 : 0));
-        vector[0].iov_base = prefix + !prefix[0];
-    }
-
-    if(!write_block(c, vector, veclen))
-    {
-        _xcb_conn_shutdown(c);
-        request = 0;
-    }
+    if((unsigned int) (c->out.request + 1) == 0)
+        send_sync(c);
+
+    /* The above send_sync calls could drop the I/O lock, but this
+     * thread will still exclude any other thread that tries to write,
+     * so the sequence number postconditions still hold. */
+    send_request(c, req->isvoid, workaround, flags, vector, veclen);
+    request = c->has_error ? 0 : c->out.request;
     pthread_mutex_unlock(&c->iolock);
     return request;
 }
@@ -262,7 +263,13 @@ int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), v
         return 0;
     pthread_mutex_lock(&c->iolock);
     get_socket_back(c);
-    ret = _xcb_out_flush_to(c, c->out.request);
+
+    /* _xcb_out_flush may drop the iolock allowing other threads to
+     * write requests, so keep flushing until we're done
+     */
+    do
+           ret = _xcb_out_flush_to(c, c->out.request);
+    while (ret && c->out.request != c->out.request_written);
     if(ret)
     {
         c->out.return_socket = return_socket;
@@ -342,6 +349,15 @@ int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
     return ret;
 }
 
+void _xcb_out_send_sync(xcb_connection_t *c)
+{
+    /* wait for other writing threads to get out of my way. */
+    while(c->out.writing)
+        pthread_cond_wait(&c->out.cond, &c->iolock);
+    get_socket_back(c);
+    send_sync(c);
+}
+
 int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request)
 {
     assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request));
old mode 100755 (executable)
new mode 100644 (file)
index 5a82ac1..f17aa3c
 
 #include <assert.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <limits.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#ifdef DNETCONN
-#include <netdnet/dnetdb.h>
-#include <netdnet/dn.h>
-#endif
-#include <netdb.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <string.h>
 
+#ifdef _WIN32
+#include "xcb_windefs.h"
+#else
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <fcntl.h>
+#include <netdb.h>
+#endif /* _WIN32 */
+
 #include "xcb.h"
 #include "xcbext.h"
 #include "xcbint.h"
 
-static const int error_connection = 1;
+/* must be after "xcbint.h" to get autoconf #defines */
+#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED)
+# include <tsol/label.h>
+# include <sys/stat.h>
+#endif
 
 int xcb_popcount(uint32_t mask)
 {
@@ -59,6 +65,16 @@ int xcb_popcount(uint32_t mask)
     return ((y + (y >> 3)) & 030707070707) % 077;
 }
 
+int xcb_sumof(uint8_t *list, int len)
+{
+  int i, s = 0;
+  for(i=0; i<len; i++) {
+    s += *list;
+    list++;
+  }
+  return s;
+}
+
 static int _xcb_parse_display(const char *name, char **host, char **protocol,
                       int *displayp, int *screenp)
 {
@@ -139,10 +155,9 @@ int xcb_parse_display(const char *name, char **host, int *displayp,
 }
 
 static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port);
+#ifndef _WIN32
 static int _xcb_open_unix(char *protocol, const char *file);
-#ifdef DNETCONN
-static int _xcb_open_decnet(const char *host, char *protocol, const unsigned short port);
-#endif
+#endif /* !WIN32 */
 #ifdef HAVE_ABSTRACT_SOCKETS
 static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen);
 #endif
@@ -157,36 +172,37 @@ static int _xcb_open(const char *host, char *protocol, const int display)
     int actual_filelen;
 
 #ifdef HAVE_LAUNCHD
-        if(strncmp(host, "/tmp/launch", 11) == 0) {
-               base = host;
-               host = "";
-               protocol = NULL;
-        }
+    if(strncmp(host, "/tmp/launch", 11) == 0) {
+        base = host;
+        host = "";
+        protocol = NULL;
+    }
 #endif
 
-    if(*host || protocol)
+    /* If protocol or host is "unix", fall through to Unix socket code below */
+    if ((!protocol || (strcmp("unix",protocol) != 0)) &&
+        (*host != '\0') && (strcmp("unix",host) != 0))
     {
-#ifdef DNETCONN
-        /* DECnet displays have two colons, so _xcb_parse_display will have
-           left one at the end.  However, an IPv6 address can end with *two*
-           colons, so only treat this as a DECnet display if host ends with
-           exactly one colon. */
-        char *colon = strchr(host, ':');
-        if(colon && *(colon+1) == '\0')
-        {
-            *colon = '\0';
-            return _xcb_open_decnet(host, protocol, display);
-        }
-        else
-#endif
-            if (protocol
-                || strcmp("unix",host)) { /* follow the old unix: rule */
+        /* display specifies TCP */
+        unsigned short port = X_TCP_PORT + display;
+        return _xcb_open_tcp(host, protocol, port);
+    }
+
+#ifndef _WIN32
+#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED)
+    /* Check special path for Unix sockets under Solaris Trusted Extensions */
+    if (is_system_labeled())
+    {
+        struct stat sbuf;
+        const char *tsol_base = "/var/tsol/doors/.X11-unix/X";
+        char tsol_socket[PATH_MAX];
 
-                /* display specifies TCP */
-                unsigned short port = X_TCP_PORT + display;
-                return _xcb_open_tcp(host, protocol, port);
-            }
+        snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display);
+
+        if (stat(tsol_socket, &sbuf) == 0)
+            base = tsol_base;
     }
+#endif
 
     filelen = strlen(base) + 1 + sizeof(display) * 3 + 1;
     file = malloc(filelen);
@@ -219,7 +235,14 @@ static int _xcb_open(const char *host, char *protocol, const int display)
     fd = _xcb_open_unix(protocol, file);
     free(file);
 
+    if (fd < 0 && !protocol && *host == '\0') {
+           unsigned short port = X_TCP_PORT + display;
+           fd = _xcb_open_tcp(host, protocol, port);
+    }
+
     return fd;
+#endif /* !_WIN32 */
+    return -1; /* if control reaches here then something has gone wrong */
 }
 
 static int _xcb_socket(int family, int type, int proto)
@@ -232,59 +255,36 @@ static int _xcb_socket(int family, int type, int proto)
 #endif
     {
        fd = socket(family, type, proto);
+#ifndef _WIN32
        if (fd >= 0)
            fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
     }
     return fd;
 }
 
-#ifdef DNETCONN
-static int _xcb_open_decnet(const char *host, const char *protocol, const unsigned short port)
-{
-    int fd;
-    struct sockaddr_dn addr;
-    struct accessdata_dn accessdata;
-    struct nodeent *nodeaddr = getnodebyname(host);
-
-    if(!nodeaddr)
-        return -1;
-    if (protocol && strcmp("dnet",protocol))
-        return -1;
-    addr.sdn_family = AF_DECnet;
 
-    addr.sdn_add.a_len = nodeaddr->n_length;
-    memcpy(addr.sdn_add.a_addr, nodeaddr->n_addr, addr.sdn_add.a_len);
+static int _xcb_do_connect(int fd, const struct sockaddr* addr, int addrlen) {
+       int on = 1;
 
-    addr.sdn_objnamel = sprintf((char *)addr.sdn_objname, "X$X%d", port);
-    if(addr.sdn_objnamel < 0)
-        return -1;
-    addr.sdn_objnum = 0;
+       if(fd < 0)
+               return -1;
 
-    fd = _xcb_socket(PF_DECnet, SOCK_STREAM, 0);
-    if(fd == -1)
-        return -1;
+       setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+       setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
 
-    memset(&accessdata, 0, sizeof(accessdata));
-    accessdata.acc_accl = sprintf((char*)accessdata.acc_acc, "%d", getuid());
-    if(accessdata.acc_accl < 0)
-        return -1;
-    setsockopt(fd, DNPROTO_NSP, SO_CONACCESS, &accessdata, sizeof(accessdata));
-
-    if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
-        close(fd);
-        return -1;
-    }
-    return fd;
+       return connect(fd, addr, addrlen);
 }
-#endif
 
 static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port)
 {
     int fd = -1;
+#if HAVE_GETADDRINFO
     struct addrinfo hints;
     char service[6]; /* "65535" with the trailing '\0' */
     struct addrinfo *results, *addr;
     char *bracket;
+#endif
 
     if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
 #ifdef AF_INET6
@@ -296,10 +296,8 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
     if (*host == '\0')
        host = "localhost";
 
+#if HAVE_GETADDRINFO
     memset(&hints, 0, sizeof(hints));
-#ifdef AI_ADDRCONFIG
-    hints.ai_flags |= AI_ADDRCONFIG;
-#endif
 #ifdef AI_NUMERICSERV
     hints.ai_flags |= AI_NUMERICSERV;
 #endif
@@ -325,21 +323,45 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
     for(addr = results; addr; addr = addr->ai_next)
     {
         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));
-           setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
+        if (_xcb_do_connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
+            break;
+        close(fd);
+        fd = -1;
+    }
+    freeaddrinfo(results);
+    return fd;
+#else
+    {
+        struct hostent* _h;
+        struct sockaddr_in _s;
+        struct in_addr ** _c;
+
+        if((_h = gethostbyname(host)) == NULL)
+            return -1;
+
+        _c = (struct in_addr**)_h->h_addr_list;
+        fd = -1;
 
-            if (connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
+        while(*_c) {
+            _s.sin_family = AF_INET;
+            _s.sin_port = htons(port);
+            _s.sin_addr = *(*_c);
+
+            fd = _xcb_socket(_s.sin_family, SOCK_STREAM, 0);
+            if(_xcb_do_connect(fd, (struct sockaddr*)&_s, sizeof(_s)) >= 0)
                 break;
+
             close(fd);
             fd = -1;
+            ++_c;
         }
+
+        return fd;
     }
-    freeaddrinfo(results);
-    return fd;
+#endif
 }
 
+#ifndef _WIN32
 static int _xcb_open_unix(char *protocol, const char *file)
 {
     int fd;
@@ -362,6 +384,7 @@ static int _xcb_open_unix(char *protocol, const char *file)
     }
     return fd;
 }
+#endif /* !_WIN32 */
 
 #ifdef HAVE_ABSTRACT_SOCKETS
 static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen)
@@ -406,13 +429,24 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname,
     int parsed = _xcb_parse_display(displayname, &host, &protocol, &display, screenp);
     
     if(!parsed) {
-        c = (xcb_connection_t *) &error_connection;
+        c = _xcb_conn_ret_error(XCB_CONN_CLOSED_PARSE_ERR);
         goto out;
-    } else
+    } else {
+#ifdef _WIN32
+        WSADATA wsaData;
+        if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
+            c = _xcb_conn_ret_error(XCB_CONN_ERROR);
+            goto out;
+        }
+#endif
         fd = _xcb_open(host, protocol, display);
+    }
 
     if(fd == -1) {
-        c = (xcb_connection_t *) &error_connection;
+        c = _xcb_conn_ret_error(XCB_CONN_ERROR);
+#ifdef _WIN32
+        WSACleanup();
+#endif
         goto out;
     }
 
diff --git a/src/xcb_windefs.h b/src/xcb_windefs.h
new file mode 100644 (file)
index 0000000..d6c7329
--- /dev/null
@@ -0,0 +1,45 @@
+/* Copyright (C) 2009 Jatin Golani.
+ *
+ * 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.
+ */
+
+
+#ifndef _XCB_WINDEFS_H
+#define _XCB_WINDEFS_H
+
+#ifndef WINVER
+#define WINVER 0x0501 /* required for getaddrinfo/freeaddrinfo defined only for WinXP and above */
+#endif
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windef.h>
+
+struct iovec  {
+    void *iov_base;    /* Pointer to data.  */
+    int iov_len;       /* Length of data.  */ 
+};
+
+typedef unsigned int in_addr_t;
+
+#endif /* xcb_windefs.h */
index 2e10ba2..98b3c93 100644 (file)
@@ -65,15 +65,22 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
  * request XCB sent. The caller of xcb_take_socket must supply a
  * callback which XCB can call when it wants the write side of the
  * socket back to make a request. This callback synchronizes with the
- * external socket owner, flushes any output queues if appropriate, and
- * then returns the sequence number of the last request sent over the
- * socket. */
+ * external socket owner and flushes any output queues if appropriate.
+ * If you are sending requests which won't cause a reply, please note the
+ * comment for xcb_writev which explains some sequence number wrap issues.
+ * */
 int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent);
 
 /* You must own the write-side of the socket (you've called
  * xcb_take_socket, and haven't returned from return_socket yet) to call
  * xcb_writev. Also, the iovec must have at least 1 byte of data in it.
- * */
+ * You have to make sure that xcb can detect sequence number wraps correctly.
+ * This means that the first request you send after xcb_take_socket must cause a
+ * reply (e.g. just insert a GetInputFocus request). After every (1 << 16) - 1
+ * requests without a reply, you have to insert a request which will cause a
+ * reply. You can again use GetInputFocus for this. You do not have to wait for
+ * any of the GetInputFocus replies, but can instead handle them via
+ * xcb_discard_reply(). */
 int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t requests);
 
 
@@ -86,6 +93,7 @@ int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply,
 /* xcb_util.c */
 
 int xcb_popcount(uint32_t mask);
+int xcb_sumof(uint8_t *list, int len);
 
 #ifdef __cplusplus
 }
old mode 100755 (executable)
new mode 100644 (file)
index f07add8..f9e5a52
@@ -54,7 +54,6 @@ enum lazy_reply_tag
 #define XCB_PAD(i) (-(i) & 3)
 
 #define XCB_SEQUENCE_COMPARE(a,op,b)   ((int64_t) ((a) - (b)) op 0)
-#define XCB_SEQUENCE_COMPARE_32(a,op,b)        (((int) (a) - (int) (b)) op 0)
 
 #ifndef offsetof
 #define offsetof(type,member) ((size_t) &((type *)0)->member)
@@ -107,6 +106,7 @@ int _xcb_out_init(_xcb_out *out);
 void _xcb_out_destroy(_xcb_out *out);
 
 int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count);
+void _xcb_out_send_sync(xcb_connection_t *c);
 int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request);
 
 
@@ -191,7 +191,10 @@ struct xcb_connection_t {
     _xcb_xid xid;
 };
 
-void _xcb_conn_shutdown(xcb_connection_t *c);
+void _xcb_conn_shutdown(xcb_connection_t *c, int err);
+
+xcb_connection_t *_xcb_conn_ret_error(int err);
+
 int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count);
 
 
diff --git a/xcb-xkb.pc.in b/xcb-xkb.pc.in
new file mode 100644 (file)
index 0000000..6ed0035
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: XCB XKB
+Description: XCB Keyboard Extension (EXPERIMENTAL)
+Version: @PACKAGE_VERSION@
+Requires: xcb
+Libs: -L${libdir} -lxcb-xkb
+Cflags: -I${includedir}