[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen master] tools/libxl: move libxenlight to tools/libs/light



commit 41aea82de2b581c61482aeddab151ecf3b1bca25
Author:     Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Wed Sep 23 06:57:20 2020 +0200
Commit:     Juergen Gross <jgross@xxxxxxxx>
CommitDate: Thu Oct 1 13:26:09 2020 +0200

    tools/libxl: move libxenlight to tools/libs/light
    
    Carve out all libxenlight related sources and move them to
    tools/libs/light in order to use the generic library build environment.
    
    The closely related sources for libxl-save-helper and the libxl test
    environment are being moved, too.
    
    Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
    Acked-by: Wei Liu <wl@xxxxxxx>
---
 .gitignore                                  |   31 +-
 tools/Rules.mk                              |   11 +-
 tools/configure                             |    2 +-
 tools/configure.ac                          |    2 +-
 tools/golang/xenlight/Makefile              |    2 +-
 tools/libs/Makefile                         |    1 +
 tools/libs/light/CODING_STYLE               |  330 ++
 tools/libs/light/Makefile                   |  277 ++
 tools/libs/light/check-libxl-api-rules      |   23 +
 tools/libs/light/flexarray.c                |  124 +
 tools/libs/light/flexarray.h                |   54 +
 tools/libs/light/gentest.py                 |  374 +++
 tools/libs/light/gentypes.py                |  797 +++++
 tools/libs/light/idl.py                     |  377 +++
 tools/libs/light/idl.txt                    |  214 ++
 tools/libs/light/include/libxl.h            | 2732 +++++++++++++++
 tools/libs/light/include/libxl_event.h      |  632 ++++
 tools/libs/light/include/libxl_json.h       |   96 +
 tools/libs/light/include/libxl_utils.h      |  194 ++
 tools/libs/light/include/libxl_uuid.h       |   80 +
 tools/libs/light/libxl.c                    |  831 +++++
 tools/libs/light/libxl_9pfs.c               |   52 +
 tools/libs/light/libxl_aoutils.c            |  667 ++++
 tools/libs/light/libxl_arch.h               |   96 +
 tools/libs/light/libxl_arm.c                | 1230 +++++++
 tools/libs/light/libxl_arm.h                |   48 +
 tools/libs/light/libxl_arm_acpi.c           |  413 +++
 tools/libs/light/libxl_arm_no_acpi.c        |   40 +
 tools/libs/light/libxl_bootloader.c         |  680 ++++
 tools/libs/light/libxl_checkpoint_device.c  |  278 ++
 tools/libs/light/libxl_colo.h               |  148 +
 tools/libs/light/libxl_colo_nic.c           |  316 ++
 tools/libs/light/libxl_colo_proxy.c         |  438 +++
 tools/libs/light/libxl_colo_qdisk.c         |  230 ++
 tools/libs/light/libxl_colo_restore.c       | 1093 ++++++
 tools/libs/light/libxl_colo_save.c          |  714 ++++
 tools/libs/light/libxl_console.c            |  802 +++++
 tools/libs/light/libxl_convert_callout.c    |  173 +
 tools/libs/light/libxl_cpuid.c              |  628 ++++
 tools/libs/light/libxl_cpupool.c            |  452 +++
 tools/libs/light/libxl_create.c             | 2310 +++++++++++++
 tools/libs/light/libxl_device.c             | 2090 ++++++++++++
 tools/libs/light/libxl_disk.c               | 1390 ++++++++
 tools/libs/light/libxl_dm.c                 | 3795 +++++++++++++++++++++
 tools/libs/light/libxl_dom.c                | 1469 ++++++++
 tools/libs/light/libxl_dom_save.c           |  564 ++++
 tools/libs/light/libxl_dom_suspend.c        |  677 ++++
 tools/libs/light/libxl_domain.c             | 2462 ++++++++++++++
 tools/libs/light/libxl_event.c              | 2467 ++++++++++++++
 tools/libs/light/libxl_exec.c               |  473 +++
 tools/libs/light/libxl_flask.c              |   79 +
 tools/libs/light/libxl_fork.c               |  734 ++++
 tools/libs/light/libxl_freebsd.c            |  252 ++
 tools/libs/light/libxl_genid.c              |  117 +
 tools/libs/light/libxl_internal.c           |  806 +++++
 tools/libs/light/libxl_internal.h           | 4859 +++++++++++++++++++++++++++
 tools/libs/light/libxl_json.c               | 1191 +++++++
 tools/libs/light/libxl_libfdt_compat.c      |   94 +
 tools/libs/light/libxl_libfdt_compat.h      |   90 +
 tools/libs/light/libxl_linux.c              |  375 +++
 tools/libs/light/libxl_mem.c                |  651 ++++
 tools/libs/light/libxl_netbsd.c             |  131 +
 tools/libs/light/libxl_netbuffer.c          |  532 +++
 tools/libs/light/libxl_nic.c                |  544 +++
 tools/libs/light/libxl_no_colo.c            |   62 +
 tools/libs/light/libxl_no_convert_callout.c |   35 +
 tools/libs/light/libxl_nocpuid.c            |   67 +
 tools/libs/light/libxl_nonetbuffer.c        |   54 +
 tools/libs/light/libxl_numa.c               |  535 +++
 tools/libs/light/libxl_osdeps.h             |  130 +
 tools/libs/light/libxl_paths.c              |   71 +
 tools/libs/light/libxl_pci.c                | 2508 ++++++++++++++
 tools/libs/light/libxl_psr.c                |  562 ++++
 tools/libs/light/libxl_pvcalls.c            |   37 +
 tools/libs/light/libxl_qmp.c                | 1934 +++++++++++
 tools/libs/light/libxl_remus.c              |  425 +++
 tools/libs/light/libxl_remus_disk_drbd.c    |  232 ++
 tools/libs/light/libxl_save_callout.c       |  430 +++
 tools/libs/light/libxl_save_helper.c        |  303 ++
 tools/libs/light/libxl_save_msgs_gen.pl     |  396 +++
 tools/libs/light/libxl_sched.c              |  986 ++++++
 tools/libs/light/libxl_sr_stream_format.h   |   69 +
 tools/libs/light/libxl_stream_read.c        |  977 ++++++
 tools/libs/light/libxl_stream_write.c       |  727 ++++
 tools/libs/light/libxl_test_fdevent.c       |   79 +
 tools/libs/light/libxl_test_fdevent.h       |   12 +
 tools/libs/light/libxl_test_timedereg.c     |  100 +
 tools/libs/light/libxl_test_timedereg.h     |    9 +
 tools/libs/light/libxl_tmem.c               |   76 +
 tools/libs/light/libxl_types.idl            | 1224 +++++++
 tools/libs/light/libxl_types_internal.idl   |   57 +
 tools/libs/light/libxl_usb.c                | 2158 ++++++++++++
 tools/libs/light/libxl_utils.c              | 1272 +++++++
 tools/libs/light/libxl_uuid.c               |  163 +
 tools/libs/light/libxl_vdispl.c             |  222 ++
 tools/libs/light/libxl_vkb.c                |  353 ++
 tools/libs/light/libxl_vnuma.c              |  327 ++
 tools/libs/light/libxl_vsnd.c               |  686 ++++
 tools/libs/light/libxl_vtpm.c               |  248 ++
 tools/libs/light/libxl_x86.c                |  852 +++++
 tools/libs/light/libxl_x86_acpi.c           |  252 ++
 tools/libs/light/libxl_x86_acpi.h           |   35 +
 tools/libs/light/libxl_xshelp.c             |  329 ++
 tools/libs/light/osdeps.c                   |   76 +
 tools/libs/light/test_common.c              |   57 +
 tools/libs/light/test_common.h              |   29 +
 tools/libs/light/test_fdderegrace.c         |   56 +
 tools/libs/light/test_timedereg.c           |   11 +
 tools/libs/uselibs.mk                       |    2 +
 tools/libxl/Makefile                        |  278 +-
 tools/libxl/check-libxl-api-rules           |   23 -
 tools/libxl/flexarray.c                     |  124 -
 tools/libxl/flexarray.h                     |   54 -
 tools/libxl/gentest.py                      |  374 ---
 tools/libxl/gentypes.py                     |  797 -----
 tools/libxl/idl.py                          |  377 ---
 tools/libxl/idl.txt                         |  214 --
 tools/libxl/libxl.c                         |  831 -----
 tools/libxl/libxl.h                         | 2732 ---------------
 tools/libxl/libxl_9pfs.c                    |   52 -
 tools/libxl/libxl_aoutils.c                 |  667 ----
 tools/libxl/libxl_arch.h                    |   96 -
 tools/libxl/libxl_arm.c                     | 1230 -------
 tools/libxl/libxl_arm.h                     |   48 -
 tools/libxl/libxl_arm_acpi.c                |  413 ---
 tools/libxl/libxl_arm_no_acpi.c             |   40 -
 tools/libxl/libxl_bootloader.c              |  680 ----
 tools/libxl/libxl_checkpoint_device.c       |  278 --
 tools/libxl/libxl_colo.h                    |  148 -
 tools/libxl/libxl_colo_nic.c                |  316 --
 tools/libxl/libxl_colo_proxy.c              |  438 ---
 tools/libxl/libxl_colo_qdisk.c              |  230 --
 tools/libxl/libxl_colo_restore.c            | 1093 ------
 tools/libxl/libxl_colo_save.c               |  714 ----
 tools/libxl/libxl_console.c                 |  802 -----
 tools/libxl/libxl_convert_callout.c         |  173 -
 tools/libxl/libxl_cpuid.c                   |  628 ----
 tools/libxl/libxl_cpupool.c                 |  452 ---
 tools/libxl/libxl_create.c                  | 2310 -------------
 tools/libxl/libxl_device.c                  | 2090 ------------
 tools/libxl/libxl_disk.c                    | 1390 --------
 tools/libxl/libxl_dm.c                      | 3795 ---------------------
 tools/libxl/libxl_dom.c                     | 1469 --------
 tools/libxl/libxl_dom_save.c                |  564 ----
 tools/libxl/libxl_dom_suspend.c             |  677 ----
 tools/libxl/libxl_domain.c                  | 2462 --------------
 tools/libxl/libxl_event.c                   | 2467 --------------
 tools/libxl/libxl_event.h                   |  632 ----
 tools/libxl/libxl_exec.c                    |  473 ---
 tools/libxl/libxl_flask.c                   |   79 -
 tools/libxl/libxl_fork.c                    |  734 ----
 tools/libxl/libxl_freebsd.c                 |  252 --
 tools/libxl/libxl_genid.c                   |  117 -
 tools/libxl/libxl_internal.c                |  806 -----
 tools/libxl/libxl_internal.h                | 4859 ---------------------------
 tools/libxl/libxl_json.c                    | 1191 -------
 tools/libxl/libxl_json.h                    |   96 -
 tools/libxl/libxl_libfdt_compat.c           |   94 -
 tools/libxl/libxl_libfdt_compat.h           |   90 -
 tools/libxl/libxl_linux.c                   |  375 ---
 tools/libxl/libxl_mem.c                     |  651 ----
 tools/libxl/libxl_netbsd.c                  |  131 -
 tools/libxl/libxl_netbuffer.c               |  532 ---
 tools/libxl/libxl_nic.c                     |  544 ---
 tools/libxl/libxl_no_colo.c                 |   62 -
 tools/libxl/libxl_no_convert_callout.c      |   35 -
 tools/libxl/libxl_nocpuid.c                 |   67 -
 tools/libxl/libxl_nonetbuffer.c             |   54 -
 tools/libxl/libxl_numa.c                    |  535 ---
 tools/libxl/libxl_osdeps.h                  |  130 -
 tools/libxl/libxl_paths.c                   |   71 -
 tools/libxl/libxl_pci.c                     | 2508 --------------
 tools/libxl/libxl_psr.c                     |  562 ----
 tools/libxl/libxl_pvcalls.c                 |   37 -
 tools/libxl/libxl_qmp.c                     | 1934 -----------
 tools/libxl/libxl_remus.c                   |  425 ---
 tools/libxl/libxl_remus_disk_drbd.c         |  232 --
 tools/libxl/libxl_save_callout.c            |  430 ---
 tools/libxl/libxl_save_helper.c             |  303 --
 tools/libxl/libxl_save_msgs_gen.pl          |  396 ---
 tools/libxl/libxl_sched.c                   |  986 ------
 tools/libxl/libxl_sr_stream_format.h        |   69 -
 tools/libxl/libxl_stream_read.c             |  977 ------
 tools/libxl/libxl_stream_write.c            |  727 ----
 tools/libxl/libxl_test_fdevent.c            |   79 -
 tools/libxl/libxl_test_fdevent.h            |   12 -
 tools/libxl/libxl_test_timedereg.c          |  100 -
 tools/libxl/libxl_test_timedereg.h          |    9 -
 tools/libxl/libxl_tmem.c                    |   76 -
 tools/libxl/libxl_types.idl                 | 1224 -------
 tools/libxl/libxl_types_internal.idl        |   57 -
 tools/libxl/libxl_usb.c                     | 2158 ------------
 tools/libxl/libxl_utils.c                   | 1272 -------
 tools/libxl/libxl_utils.h                   |  194 --
 tools/libxl/libxl_uuid.c                    |  163 -
 tools/libxl/libxl_uuid.h                    |   80 -
 tools/libxl/libxl_vdispl.c                  |  222 --
 tools/libxl/libxl_vkb.c                     |  353 --
 tools/libxl/libxl_vnuma.c                   |  327 --
 tools/libxl/libxl_vsnd.c                    |  686 ----
 tools/libxl/libxl_vtpm.c                    |  248 --
 tools/libxl/libxl_x86.c                     |  852 -----
 tools/libxl/libxl_x86_acpi.c                |  252 --
 tools/libxl/libxl_x86_acpi.h                |   35 -
 tools/libxl/libxl_xshelp.c                  |  329 --
 tools/libxl/osdeps.c                        |   76 -
 tools/libxl/test_common.c                   |   57 -
 tools/libxl/test_common.h                   |   29 -
 tools/libxl/test_fdderegrace.c              |   56 -
 tools/libxl/test_timedereg.c                |   11 -
 tools/ocaml/libs/xl/Makefile                |    8 +-
 211 files changed, 63046 insertions(+), 62700 deletions(-)

diff --git a/.gitignore b/.gitignore
index 5e8c47e2db..f30550255f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -128,6 +128,22 @@ tools/libs/guest/xc_core.h
 tools/libs/guest/xc_core_arm.h
 tools/libs/guest/xc_core_x86.h
 tools/libs/guest/xc_private.h
+tools/libs/light/_*.[ch]
+tools/libs/light/*.pyc
+tools/libs/light/_libxl.api-for-check
+tools/libs/light/*.api-ok
+tools/libs/light/libxenlight.map
+tools/libs/light/libxl-save-helper
+tools/libs/light/dsdt*
+tools/libs/light/mk_dsdt
+tools/libs/light/ssdt*
+tools/libs/light/testidl
+tools/libs/light/testidl.c
+tools/libs/light/test_timedereg
+tools/libs/light/test_fdderegrace
+tools/libs/light/tmp.*
+tools/libs/light/xenlight.pc
+tools/libs/light/include/_*.h
 tools/libs/stat/_paths.h
 tools/libs/stat/headers.chk
 tools/libs/stat/libxenstat.map
@@ -216,16 +232,8 @@ tools/include/xen/*
 tools/include/xen-xsm/*
 tools/include/xen-foreign/*.(c|h|size)
 tools/include/xen-foreign/checker
-tools/libxl/_libxl.api-for-check
-tools/libxl/*.api-ok
 tools/libxl/*.pc
-tools/libxl/dsdt*
 tools/libxl/libxlu_cfg_y.output
-tools/libxl/mk_dsdt
-tools/libxl/ssdt*
-tools/libxl/testenum
-tools/libxl/testenum.c
-tools/libxl/tmp.*
 tools/misc/cpuperf/cpuperf-perfcntr
 tools/misc/cpuperf/cpuperf-xen
 tools/misc/xc_shadow
@@ -380,13 +388,6 @@ tools/include/xen-foreign/arm64.h
 tools/misc/xen-hptool
 tools/misc/xen-mfndump
 tools/libs/toolcore/include/_*.h
-tools/libxl/_*.[ch]
-tools/libxl/testidl
-tools/libxl/testidl.c
-tools/libxl/*.pyc
-tools/libxl/libxl-save-helper
-tools/libxl/test_timedereg
-tools/libxl/test_fdderegrace
 tools/firmware/etherboot/eb-roms.h
 tools/firmware/etherboot/gpxe-git-snapshot.tar.gz
 tools/misc/xenhypfs
diff --git a/tools/Rules.mk b/tools/Rules.mk
index a71abb2e4f..a68dbb9de8 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -15,9 +15,7 @@ XEN_INCLUDE        = $(XEN_ROOT)/tools/include
 
 include $(XEN_ROOT)/tools/libs/uselibs.mk
 
-XEN_libxenlight    = $(XEN_ROOT)/tools/libxl
-# Currently libxlutil lives in the same directory as libxenlight
-XEN_libxlutil      = $(XEN_libxenlight)
+XEN_libxlutil      = $(XEN_ROOT)/tools/libxl
 
 CFLAGS_xeninclude = -I$(XEN_INCLUDE)
 
@@ -107,6 +105,8 @@ ifeq ($(CONFIG_Linux),y)
 LDLIBS_libxenstore += -ldl
 endif
 
+CFLAGS_libxenlight += $(CFLAGS_libxenctrl)
+
 ifeq ($(debug),y)
 # Disable optimizations
 CFLAGS += -O0 -fno-omit-frame-pointer
@@ -116,11 +116,6 @@ else
 CFLAGS += -O2 -fomit-frame-pointer
 endif
 
-CFLAGS_libxenlight = -I$(XEN_libxenlight) $(CFLAGS_libxenctrl) 
$(CFLAGS_xeninclude)
-SHDEPS_libxenlight = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) 
$(SHLIB_libxenhypfs) $(SHLIB_libxenguest)
-LDLIBS_libxenlight = $(SHDEPS_libxenlight) 
$(XEN_libxenlight)/libxenlight$(libextension)
-SHLIB_libxenlight  = $(SHDEPS_libxenlight) -Wl,-rpath-link=$(XEN_libxenlight)
-
 CFLAGS_libxlutil = -I$(XEN_libxlutil)
 SHDEPS_libxlutil = $(SHLIB_libxenlight)
 LDLIBS_libxlutil = $(SHDEPS_libxlutil) 
$(XEN_libxlutil)/libxlutil$(libextension)
diff --git a/tools/configure b/tools/configure
index edcdcf4f73..8a708e9baa 100755
--- a/tools/configure
+++ b/tools/configure
@@ -585,7 +585,7 @@ PACKAGE_STRING='Xen Hypervisor Tools 4.15'
 PACKAGE_BUGREPORT='xen-devel@xxxxxxxxxxxxx'
 PACKAGE_URL='https://www.xen.org/'
 
-ac_unique_file="libxl/libxl.c"
+ac_unique_file="libs/light/libxl.c"
 # Factoring default headers for most tests.
 ac_includes_default="\
 #include <stdio.h>
diff --git a/tools/configure.ac b/tools/configure.ac
index 6614a4f130..ee8ba5ff24 100644
--- a/tools/configure.ac
+++ b/tools/configure.ac
@@ -4,7 +4,7 @@
 AC_PREREQ([2.67])
 AC_INIT([Xen Hypervisor Tools], m4_esyscmd([../version.sh ../xen/Makefile]),
     [xen-devel@xxxxxxxxxxxxx], [xen], [https://www.xen.org/])
-AC_CONFIG_SRCDIR([libxl/libxl.c])
+AC_CONFIG_SRCDIR([libs/light/libxl.c])
 AC_CONFIG_FILES([
 ../config/Tools.mk
 hotplug/FreeBSD/rc.d/xencommons
diff --git a/tools/golang/xenlight/Makefile b/tools/golang/xenlight/Makefile
index b17095e64b..fd8e4893db 100644
--- a/tools/golang/xenlight/Makefile
+++ b/tools/golang/xenlight/Makefile
@@ -8,7 +8,7 @@ GOXL_INSTALL_DIR = $(GOCODE_DIR)/src/$(XEN_GOCODE_URL)/xenlight/
 
 GO ?= go
 
-LIBXL_SRC_DIR = ../../libxl
+LIBXL_SRC_DIR = $(XEN_ROOT)/tools/libs/light
 
 .PHONY: all
 all: build
diff --git a/tools/libs/Makefile b/tools/libs/Makefile
index e8fcd59214..c41455c604 100644
--- a/tools/libs/Makefile
+++ b/tools/libs/Makefile
@@ -15,6 +15,7 @@ SUBDIRS-y += hypfs
 SUBDIRS-y += store
 SUBDIRS-y += stat
 SUBDIRS-$(CONFIG_Linux) += vchan
+SUBDIRS-y += light
 
 ifeq ($(CONFIG_RUMP),y)
 SUBDIRS-y := toolcore
diff --git a/tools/libs/light/CODING_STYLE b/tools/libs/light/CODING_STYLE
new file mode 100644
index 0000000000..3d572f6925
--- /dev/null
+++ b/tools/libs/light/CODING_STYLE
@@ -0,0 +1,330 @@
+LIBXENLIGHT CODING STYLE
+========================
+
+
+AN APOLOGY AND WARNING
+----------------------
+
+Much of the code in libxl does not yet follow this coding style
+document in every respect.  However, new code is expected to conform.
+
+Patches to improve the style of existing code are welcome.  Please
+separate these out from functional changes.
+
+If it is not feasible to conform fully to the style while patching old
+code, without doing substantial style reengineering first, we may
+accept patches which contain nonconformant elements, provided that
+they don't make the coding style problem worse overall.
+
+In this case, the new code should conform to the prevailing style in
+the area being touched.
+
+
+MEMORY ALLOCATION
+-----------------
+
+Memory allocation for libxl-internal purposes should normally be done
+with the provided gc mechanisms; there is then no need to free.  See
+"libxl memory management" in libxl.h.
+
+
+CONVENTIONAL VARIABLE NAMES
+---------------------------
+
+The following local variable names should be used where applicable:
+
+  int rc;    /* a libxl error code - and not anything else */
+  int r;     /* the return value from a system call (or libxc call) */
+  bool ok;   /* the success return value from a boolean function */
+
+  uint32_t domid;
+  libxl__gc *gc;
+  libxl__egc *egc;
+  libxl__ao *ao;
+
+  libxl_foo_bar_state *fbs;    /* local variable */
+  libxl_foo_bar_state foo_bar; /* inside another state struct */
+
+
+CONVENIENCE MACROS
+------------------
+
+There are a number of convenience macros which shorten the program and
+avoid opportunity for mistakes.  In some cases non-use of the macros
+produces functional bugs or incorrect error handling.  Use the macros
+whenever they are applicable.  For example:
+
+ Usually, don't use:     Instead, use (see libxl_internal.h):
+  libxl__log[v]           LOG, LOGE, LOGEV
+  libxl__sprintf          GCSPRINTF
+  libxl__*alloc et al.    GCNEW, GCNEW_ARRAY, GCREALLOC_ARRAY
+  isalnum etc. directly   CTYPE
+  libxl__ctx_[un]lock     CTX_LOCK, CTX_UNLOCK
+  gc=...; ao=...;         EGC_GC, AO_GC, STATE_AO_GC
+  explicit gc creation    GC_INIT, GC_FREE
+  memset(..,0,sizeof..)   FILLZERO
+
+Instead of malloc et al one should (as an exception to the above) use
+libxl__{zalloc,calloc,realloc} etc but passing NOGC.
+
+ERROR HANDLING
+--------------
+
+Unless, there are good reasons to do otherwise, the following error
+handling and cleanup paradigm should be used:
+
+  * All local variables referring to resources which might need
+    cleaning up are declared at the top of the function, and
+    initialised to a sentinel value indicating "nothing allocated".
+    For example,
+            libxl_evgen_disk_eject *evg = NULL;
+            int nullfd = -1;
+
+  * If the function is to return a libxl error value, `rc' is
+    used to contain the error code, but it is NOT initialised:
+            int rc;
+
+  * There is only one error cleanup path out of the function.  It
+    starts with a label `out:'.  That error cleanup path checks for
+    each allocated resource and frees it iff necessary.  It then
+    returns rc.  For example,
+         out:
+             if (evg) libxl__evdisable_disk_eject(gc, evg);
+             if (nullfd >= 0) close(nullfd);
+             return rc;
+
+  * Function calls which might fail (ie most function calls) are
+    handled by putting the return/status value into a variable, and
+    then checking it in a separate statement:
+            char *dompath = libxl__xs_get_dompath(gc, bl->domid);
+            if (!dompath) { rc = ERROR_FAIL; goto out; }
+
+  * If a resource is freed in the main body of the function (for
+    example, in a loop), the corresponding variable has to be reset to
+    the sentinel at the point where it's freed.
+
+Whether to use the `out' path for successful returns as well as error
+returns is a matter of taste and convenience for the specific
+function.  Not reusing the out path is fine if the duplicated function
+exit code is only `CTX_UNLOCK; GC_FREE;' (or similar).
+
+If you reuse the `out' path for successful returns, there may be
+resources which are to be returned to the caller rather than freed.
+In that case you have to reset the local variable to `nothing here',
+to avoid the resource being freed on the out path.  That resetting
+should be done immediately after the resource value is stored at the
+applicable _r function parameter (or equivalent).  Do not test `rc' in
+the out section, to discover whether to free things.
+
+The uses of the single-line formatting in the examples above are
+permitted exceptions to the usual libxl code formatting rules.
+
+
+
+IDEMPOTENT DATA STRUCTURE CONSTRUCTION/DESTRUCTION
+--------------------------------------------------
+
+Nontrivial data structures (in structs) should come with an idempotent
+_dispose function, which must free all resources associated with the
+data structure (but not free the struct itself).
+
+Such a struct should also come with an _init function which
+initialises the struct so that _dispose is a no-op.
+
+
+ASYNCHRONOUS/LONG-RUNNING OPERATIONS
+------------------------------------
+
+All long-running operations in libxl need to use the asynchronous
+operation machinery.  Consult the programmer documentation in
+libxl_internal.h for details - search for "Machinery for asynchronous
+operations".
+
+The code for asynchronous operations should be laid out in
+chronological order.  That is, where there is a chain of callback
+functions, each subsequent function should be, textually, the next
+function in the file.  This will normally involve predeclaring the
+callback functions.  Synchronous helper functions should be separated
+out into a section preceding the main callback chain.
+
+Control flow arrangements in asynchronous operations should be made as
+simple as possible, because it can otherwise be very hard to see
+through the tangle.
+
+
+When inventing a new sub-operation in asynchronous code, consider
+whether to structure it formally as a sub-operation with its own state
+structure.  (See, for example, libxl__datacopier_*.)
+
+An ao-suboperation state structure should contain, in this order:
+  * fields that the caller must fill in, and which are,
+    effectively, the parameters to the operation, including:
+      - libxl__ao *ao
+      - the callback function pointer(s), which
+        should be named callback or callback_*.
+  * shared information fields or ones used for returning information
+    to the calling operation
+  * private fields
+These sections should be clearly demarcated by comments.
+
+An asynchronous operation should normally have an idempotent stop or
+cancel function.  It should normally also have an _init function for
+its state struct, which arranges that the stop is a no-op.
+
+The permitted order of calls into your ao operation's methods must be
+documented in comments, if it is nontrivial.
+
+
+When using an ao sub-operation, you should normally:
+ * Physically include the sub-operation state struct in your
+   own state struct;
+ * Use CONTAINER_OF to find your own state struct at the start of
+   your implementations of the sub-operation callback functions;
+ * Unconditionally initialise the sub-operation's struct (with its
+   _init method) in your own _init method.
+ * Unconditionally cancel or destroy the sub-operation in your own
+   cancel or destroy method.
+
+
+FORMATTING AND NAMING
+---------------------
+
+Blatantly copied from qemu and linux with few modifications.
+
+
+1. Whitespace
+
+Of course, the most important aspect in any coding style is whitespace.
+Crusty old coders who have trouble spotting the glasses on their noses
+can tell the difference between a tab and eight spaces from a distance
+of approximately fifteen parsecs.  Many a flamewar have been fought and
+lost on this issue.
+
+Libxenlight indents are four spaces.  Tabs are never used, except in
+Makefiles where they have been irreversibly coded into the syntax.
+Spaces of course are superior to tabs because:
+
+ - You have just one way to specify whitespace, not two.  Ambiguity breeds
+   mistakes.
+ - The confusion surrounding 'use tabs to indent, spaces to justify' is gone.
+ - Tab indents push your code to the right, making your screen seriously
+   unbalanced.
+ - Tabs will be rendered incorrectly on editors who are misconfigured not
+   to use tab stops of eight positions.
+ - Tabs are rendered badly in patches, causing off-by-one errors in almost
+   every line.
+ - It is the libxenlight coding style.
+
+Do not leave whitespace dangling off the ends of lines.
+
+
+2. Line width
+
+Lines are limited to 75 characters.
+
+Rationale:
+ - Some people like to tile their 24" screens with a 6x4 matrix of 80x24
+   xterms and use vi in all of them.  The best way to punish them is to
+   let them keep doing it.
+ - In an 80 column terminal, some room needs to be left for > quoting
+   characters, +/- diff characters, and so on, in emails.
+ - Code and especially patches is much more readable if limited to a sane
+   line length.  Eighty is traditional.
+ - It is the libxenlight coding style.
+
+
+3. Naming
+
+C is a Spartan language, and so should your naming be.  Unlike Modula-2
+and Pascal programmers, C programmers do not use cute names like
+ThisVariableIsATemporaryCounter.  A C programmer would call that
+variable "tmp", which is much easier to write, and not the least more
+difficult to understand.
+
+HOWEVER, while mixed-case names are frowned upon, descriptive names for
+global variables are a must.  To call a global function "foo" is a
+shooting offense.
+
+GLOBAL variables (to be used only if you _really_ need them) need to
+have descriptive names, as do global functions.  If you have a function
+that counts the number of active users, you should call that
+"count_active_users()" or similar, you should _not_ call it "cntusr()".
+
+Encoding the type of a function into the name (so-called Hungarian
+notation) is brain damaged - the compiler knows the types anyway and can
+check those, and it only confuses the programmer.
+
+LOCAL variable names should be short, and to the point.  If you have
+some random integer loop counter, it should probably be called "i".
+Calling it "loop_counter" is non-productive, if there is no chance of it
+being mis-understood.  Similarly, "tmp" can be just about any type of
+variable that is used to hold a temporary value.
+
+Local variables used to store return values should have descriptive name
+like "rc" or "ret". Following the same reasoning the label used as exit
+path should be called "out".
+
+Function arguments which are used to return values to the caller
+should be suffixed `_r' or `_out'.
+
+Variables, type names and function names are
+lower_case_with_underscores.
+Type names and function names use the prefix libxl__ when internal to
+libxenlight and libxl_ when exported in libxl.h.
+Xl should avoid using libxl_ and libxl__ as prefix for its own function
+names.
+
+When wrapping standard library functions, use the prefix libxl_ to alert
+readers that they are seeing a wrapped version; otherwise avoid this prefix.
+
+Typedefs are used to eliminate the redundant 'struct' keyword.
+It is the libxenlight coding style.
+
+
+4. Statements
+
+Don't put multiple statements on a single line.
+Don't put multiple assignments on a single line either.
+Error code paths with an if statement and a goto or a return on the same
+line are allowed. Examples:
+
+    if (rc) goto out;
+    if (rc < 0) return;
+
+Libxenlight coding style is super simple.  Avoid tricky expressions.
+
+
+5. Block structure
+
+Every indented statement is braced, but blocks that contain just one
+statement may have the braces omitted.  To avoid confusion, either all
+the blocks in an if...else chain have braces, or none of them do.
+
+The opening brace is on the line that contains the control flow
+statement that introduces the new block; the closing brace is on the
+same line as the else keyword, or on a line by itself if there is no
+else keyword.  Examples:
+
+    if (a == 5) {
+        printf("a was 5.\n");
+    } else if (a == 6) {
+        printf("a was 6.\n");
+    } else {
+        printf("a was something else entirely.\n");
+    }
+
+    if (a == 5)
+        printf("a was 5.\n");
+
+An exception is the opening brace for a function; for reasons of tradition
+and clarity it comes on a line by itself:
+
+    void a_function(void)
+    {
+        do_something();
+    }
+
+Rationale: a consistent (except for functions...) bracing style reduces
+ambiguity and avoids needless churn when lines are added or removed.
+Furthermore, it is the libxenlight coding style.
+
diff --git a/tools/libs/light/Makefile b/tools/libs/light/Makefile
new file mode 100644
index 0000000000..f58a3214e5
--- /dev/null
+++ b/tools/libs/light/Makefile
@@ -0,0 +1,277 @@
+XEN_ROOT = $(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+SRCS-y += osdeps.c
+SRCS-y += libxl_paths.c
+SRCS-y += libxl_bootloader.c
+SRCS-y += flexarray.c
+ifeq ($(CONFIG_LIBNL),y)
+SRCS-y += libxl_netbuffer.c
+else
+SRCS-y += libxl_nonetbuffer.c
+endif
+ifeq ($(CONFIG_X86),y)
+SRCS-y += libxl_convert_callout.c
+else
+SRCS-y += libxl_no_convert_callout.c
+endif
+SRCS-y += libxl_remus.c
+SRCS-y += libxl_checkpoint_device.c
+SRCS-y += libxl_remus_disk_drbd.c
+ifeq ($(CONFIG_LIBNL),y)
+SRCS-y += libxl_colo_restore.c
+SRCS-y += libxl_colo_save.c
+SRCS-y += libxl_colo_qdisk.c
+SRCS-y += libxl_colo_proxy.c
+SRCS-y += libxl_colo_nic.c
+else
+SRCS-y += libxl_no_colo.c
+endif
+
+ACPI_PATH  = $(XEN_ROOT)/tools/libacpi
+DSDT_FILES-$(CONFIG_X86) = dsdt_pvh.c
+ACPI_OBJS  = $(patsubst %.c,%.o,$(DSDT_FILES-y)) build.o static_tables.o
+ACPI_PIC_OBJS = $(patsubst %.o,%.opic,$(ACPI_OBJS))
+$(DSDT_FILES-y): acpi
+vpath build.c $(ACPI_PATH)/
+vpath static_tables.c $(ACPI_PATH)/
+
+.PHONY: acpi
+acpi:
+       $(MAKE) -C $(ACPI_PATH) ACPI_BUILD_DIR=$(CURDIR) 
DSDT_FILES="$(DSDT_FILES-y)"
+
+SRCS-$(CONFIG_X86) += $(ACPI_OBJS:.o=.c)
+
+CFLAGS += -Wno-format-zero-length -Wmissing-declarations \
+       -Wno-declaration-after-statement -Wformat-nonliteral
+CFLAGS += -I.
+
+SRCS-$(CONFIG_X86) += libxl_cpuid.c
+SRCS-$(CONFIG_X86) += libxl_x86.c
+SRCS-$(CONFIG_X86) += libxl_psr.c
+SRCS-$(CONFIG_X86) += libxl_x86_acpi.c
+SRCS-$(CONFIG_ARM) += libxl_nocpuid.c
+SRCS-$(CONFIG_ARM) += libxl_arm.c
+SRCS-$(CONFIG_ARM) += libxl_libfdt_compat.c
+ifeq ($(CONFIG_ARM_64),y)
+DSDT_FILES-y = dsdt_anycpu_arm.c
+SRCS-y += libxl_arm_acpi.c
+SRCS-y += $(DSDT_FILES-y)
+dsdt_anycpu_arm.c:
+       $(MAKE) -C $(ACPI_PATH) ACPI_BUILD_DIR=$(CURDIR) 
DSDT_FILES="$(DSDT_FILES-y)"
+else
+SRCS-$(CONFIG_ARM) += libxl_arm_no_acpi.c
+endif
+
+SRCS-OS-$(CONFIG_NetBSD) = libxl_netbsd.c
+SRCS-OS-$(CONFIG_Linux) = libxl_linux.c
+SRCS-OS-$(CONFIG_FreeBSD) = libxl_freebsd.c
+ifeq ($(SRCS-OS-y),)
+$(error Your Operating System is not supported by libxenlight, \
+please check libxl_linux.c and libxl_netbsd.c to see how to get it ported)
+endif
+SRCS-y += $(SRCS-OS-y)
+
+SRCS-y += libxl.c
+SRCS-y += libxl_create.c
+SRCS-y += libxl_dm.c
+SRCS-y += libxl_pci.c
+SRCS-y += libxl_dom.c
+SRCS-y += libxl_exec.c
+SRCS-y += libxl_xshelp.c
+SRCS-y += libxl_device.c
+SRCS-y += libxl_internal.c
+SRCS-y += libxl_utils.c
+SRCS-y += libxl_uuid.c
+SRCS-y += libxl_json.c
+SRCS-y += libxl_aoutils.c
+SRCS-y += libxl_numa.c
+SRCS-y += libxl_vnuma.c
+SRCS-y += libxl_stream_read.c
+SRCS-y += libxl_stream_write.c
+SRCS-y += libxl_save_callout.c
+SRCS-y += _libxl_save_msgs_callout.c
+SRCS-y += libxl_qmp.c
+SRCS-y += libxl_event.c
+SRCS-y += libxl_fork.c
+SRCS-y += libxl_dom_suspend.c
+SRCS-y += libxl_dom_save.c
+SRCS-y += libxl_usb.c
+SRCS-y += libxl_vtpm.c
+SRCS-y += libxl_nic.c
+SRCS-y += libxl_disk.c
+SRCS-y += libxl_console.c
+SRCS-y += libxl_cpupool.c
+SRCS-y += libxl_mem.c
+SRCS-y += libxl_sched.c
+SRCS-y += libxl_tmem.c
+SRCS-y += libxl_9pfs.c
+SRCS-y += libxl_domain.c
+SRCS-y += libxl_vdispl.c
+SRCS-y += libxl_pvcalls.c
+SRCS-y += libxl_vsnd.c
+SRCS-y += libxl_vkb.c
+SRCS-y += libxl_genid.c
+SRCS-y += _libxl_types.c
+SRCS-y += libxl_flask.c
+SRCS-y += _libxl_types_internal.c
+
+ifeq ($(CONFIG_LIBNL),y)
+CFLAGS_LIBXL += $(LIBNL3_CFLAGS)
+endif
+CFLAGS_LIBXL += -Wshadow
+ifeq ($(debug),y)
+CFLAGS_LIBXL += -DCONFIG_DEBUG
+endif
+
+CFLAGS += $(PTHREAD_CFLAGS)
+LDFLAGS += $(PTHREAD_LDFLAGS)
+
+LIBXL_TESTS += timedereg
+LIBXL_TESTS_PROGS = $(LIBXL_TESTS) fdderegrace
+LIBXL_TESTS_INSIDE = $(LIBXL_TESTS) fdevent
+
+# Each entry FOO in LIBXL_TESTS has two main .c files:
+#   libxl_test_FOO.c  "inside libxl" code to support the test case
+#   test_FOO.c        "outside libxl" code to exercise the test case
+# Conventionally there will also be:
+#   libxl_test_FOO.h  interface between the "inside" and "outside" parts
+# The "inside libxl" file is compiled exactly like a piece of libxl, and the
+# "outside libxl" file is compiled exactly like a piece of application
+# code.  They must share information via explicit libxl entrypoints.
+# Unlike proper parts of libxl, it is permissible for libxl_test_FOO.c
+# to use private global variables for its state.  Note that all the
+# "inside" parts are compiled into a single test library, so their
+# symbol names must be unique.
+#
+# To run these tests, either use LD_PRELOAD to get libxenlight_test.so
+# loaded, or rename it to libxenlight.so so it is the target of the
+# appropriate symlinks.
+
+LIBXL_TEST_OBJS += $(foreach t, $(LIBXL_TESTS_INSIDE),libxl_test_$t.opic)
+TEST_PROG_OBJS += $(foreach t, $(LIBXL_TESTS_PROGS),test_$t.o) test_common.o
+TEST_PROGS += $(foreach t, $(LIBXL_TESTS_PROGS),test_$t)
+
+AUTOINCS = _libxl_list.h _paths.h _libxl_save_msgs_callout.h 
_libxl_save_msgs_helper.h
+AUTOSRCS = _libxl_save_msgs_callout.c _libxl_save_msgs_helper.c
+
+CLIENTS = testidl libxl-save-helper
+
+SAVE_HELPER_OBJS = libxl_save_helper.o _libxl_save_msgs_helper.o
+
+LIBHEADER := libxl.h libxl_event.h libxl_json.h _libxl_types.h 
_libxl_types_json.h _libxl_list.h libxl_utils.h libxl_uuid.h
+
+NO_HEADERS_CHK := y
+
+include $(XEN_ROOT)/tools/libs/libs.mk
+
+$(PKG_CONFIG_LOCAL): PKG_CONFIG_INCDIR = $(CURDIR)
+$(PKG_CONFIG_LOCAL): PKG_CONFIG_CFLAGS_LOCAL = $(CFLAGS_xeninclude)
+
+LDUSELIBS-y += $(PTYFUNCS_LIBS)
+LDUSELIBS-$(CONFIG_LIBNL) += $(LIBNL3_LIBS)
+LDUSELIBS-$(CONFIG_Linux) += -luuid
+LDUSELIBS-$(CONFIG_Linux) += -lrt
+LDUSELIBS-$(CONFIG_ARM) += -lfdt
+LDUSELIBS-y += $(PTHREAD_LIBS)
+LDUSELIBS-y += -lyajl
+LDUSELIBS += $(LDUSELIBS-y)
+
+$(LIB_OBJS) $(PIC_OBJS) $(LIBXL_TEST_OBJS): CFLAGS += $(CFLAGS_LIBXL) -include 
$(XEN_ROOT)/tools/config.h
+$(ACPI_OBJS) $(ACPI_PIC_OBJS): CFLAGS += -I. 
-DLIBACPI_STDUTILS=\"$(CURDIR)/libxl_x86_acpi.h\"
+$(TEST_PROG_OBJS) _libxl.api-for-check: CFLAGS += $(CFLAGS_libxentoollog) 
$(CFLAGS_libxentoolcore)
+libxl_dom.o libxl_dom.opic: CFLAGS += -I$(XEN_ROOT)/tools  # include 
libacpi/x86.h
+libxl_x86_acpi.o libxl_x86_acpi.opic: CFLAGS += -I$(XEN_ROOT)/tools
+$(SAVE_HELPER_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenevtchn) 
$(CFLAGS_libxenguest)
+
+testidl.o: CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenlight)
+testidl.c: libxl_types.idl gentest.py include/libxl.h $(AUTOINCS)
+       $(PYTHON) gentest.py libxl_types.idl testidl.c.new
+       mv testidl.c.new testidl.c
+
+build: $(CLIENTS) $(TEST_PROGS) $(AUTOSRCS) $(AUTOINCS)
+
+$(LIB_OBJS) $(PIC_OBJS) $(SAVE_HELPER_OBJS) $(LIBXL_TEST_OBJS) 
$(TEST_PROG_OBJS): $(AUTOINCS) libxl.api-ok
+
+genpath-target = $(call buildmakevars2header,_paths.h)
+$(eval $(genpath-target))
+
+libxl.api-ok: check-libxl-api-rules _libxl.api-for-check
+       $(PERL) $^
+       touch $@
+
+_%.api-for-check: include/%.h $(AUTOINCS)
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_$*.o) -c -E $< $(APPEND_CFLAGS) \
+               -DLIBXL_EXTERNAL_CALLERS_ONLY=LIBXL_EXTERNAL_CALLERS_ONLY \
+               >$@.new
+       mv -f $@.new $@
+
+_libxl_list.h: $(XEN_INCLUDE)/xen-external/bsd-sys-queue-h-seddery 
$(XEN_INCLUDE)/xen-external/bsd-sys-queue.h
+       $(PERL) $^ --prefix=libxl >$@.new
+       $(call move-if-changed,$@.new,$@)
+
+_libxl_save_msgs_helper.c _libxl_save_msgs_callout.c \
+_libxl_save_msgs_helper.h _libxl_save_msgs_callout.h: \
+               libxl_save_msgs_gen.pl
+       $(PERL) -w $< $@ >$@.new
+       $(call move-if-changed,$@.new,$@)
+
+include/libxl.h: _libxl_types.h _libxl_list.h
+include/libxl_json.h: _libxl_types_json.h
+libxl_internal.h: _libxl_types_internal.h _libxl_types_private.h 
_libxl_types_internal_private.h _paths.h
+libxl_internal_json.h: _libxl_types_internal_json.h
+xl.h: _paths.h
+
+$(LIB_OBJS) $(PIC_OBJS) $(LIBXL_TEST_OBJS) $(TEST_PROG_OBJS) 
$(SAVE_HELPER_OBJS): include/libxl.h
+$(LIB_OBJS) $(PIC_OBJS) $(LIBXL_TEST_OBJS): libxl_internal.h
+
+_libxl_type%.h _libxl_type%_json.h _libxl_type%_private.h _libxl_type%.c: 
libxl_type%.idl gentypes.py idl.py
+       $(eval stem = $(notdir $*))
+       $(PYTHON) gentypes.py libxl_type$(stem).idl __libxl_type$(stem).h 
__libxl_type$(stem)_private.h \
+               __libxl_type$(stem)_json.h  __libxl_type$(stem).c
+       $(call move-if-changed,__libxl_type$(stem).h,_libxl_type$(stem).h)
+       $(call 
move-if-changed,__libxl_type$(stem)_private.h,_libxl_type$(stem)_private.h)
+       $(call 
move-if-changed,__libxl_type$(stem)_json.h,_libxl_type$(stem)_json.h)
+       $(call move-if-changed,__libxl_type$(stem).c,_libxl_type$(stem).c)
+
+include/_%.h: _%.h
+       cp $< $@
+
+libxenlight_test.so: $(PIC_OBJS) $(LIBXL_TEST_OBJS)
+       $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenlight.so.$(MAJOR) 
$(SHLIB_LDFLAGS) -o $@ $^ $(LDUSELIBS) $(APPEND_LDFLAGS)
+
+test_%: test_%.o test_common.o libxenlight_test.so
+       $(CC) $(LDFLAGS) -o $@ $^ $(filter-out %libxenlight.so, 
$(LDLIBS_libxenlight)) $(LDLIBS_libxentoollog) $(LDLIBS_libxentoolcore) -lyajl 
$(APPEND_LDFLAGS)
+
+libxl-save-helper: $(SAVE_HELPER_OBJS) libxenlight.so
+       $(CC) $(LDFLAGS) -o $@ $(SAVE_HELPER_OBJS) $(LDLIBS_libxentoollog) 
$(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxentoolcore) 
$(APPEND_LDFLAGS)
+
+testidl: testidl.o libxenlight.so
+       $(CC) $(LDFLAGS) -o $@ testidl.o $(LDLIBS_libxenlight) 
$(LDLIBS_libxentoollog) $(LDLIBS_libxentoolcore) $(APPEND_LDFLAGS)
+
+install: installlocal $(LIBHEADERS)
+
+.PHONY: installlocal
+installlocal: libxl-save-helper
+       $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
+       $(INSTALL_PROG) libxl-save-helper $(DESTDIR)$(LIBEXEC_BIN)
+
+uninstall: uninstalllocal
+
+.PHONY: uninstalllocal
+uninstalllocal:
+       rm -f $(DESTDIR)$(LIBEXEC_BIN)/libxl-save-helper
+
+clean: cleanlocal
+
+.PHONY: cleanlocal
+cleanlocal:
+       $(RM) -f _*.h *.o $(CLIENTS)
+       $(RM) -f _*.c *.pyc _paths.*.tmp _*.api-for-check
+       $(RM) -f testidl.c.new testidl.c *.api-ok
+       $(RM) -f $(TEST_PROGS)
+       $(RM) -rf __pycache__
+       $(RM) -f include/_*.h
+       $(RM) -f libxenlight.map
+       $(RM) -f $(AUTOSRCS) $(AUTOINCS)
+       $(MAKE) -C $(ACPI_PATH) ACPI_BUILD_DIR=$(CURDIR) clean
diff --git a/tools/libs/light/check-libxl-api-rules 
b/tools/libs/light/check-libxl-api-rules
new file mode 100755
index 0000000000..18ff39ca5f
--- /dev/null
+++ b/tools/libs/light/check-libxl-api-rules
@@ -0,0 +1,23 @@
+#!/usr/bin/perl -w
+use strict;
+our $needed=0;
+our $speclineoffset=0;
+our $specfile;
+while (<>) {
+    if (m/^\# (\d+) \"(.*)\"$/) {
+        $speclineoffset = $1 - $. -1;
+        $specfile = $2;
+    }
+    my $file = defined($specfile) ? $specfile : $ARGV;
+    my $line = $speclineoffset + $.;
+    if (m/libxl_asyncop_how[^;]/) {
+        $needed=1;
+    }
+    if (m/LIBXL_EXTERNAL_CALLERS_ONLY/) {
+        $needed=0;
+    }
+    next unless $needed;
+    if (m/\;/) {
+        die "$file:$line:missing LIBXL_EXTERNAL_CALLERS_ONLY";
+    }
+}
diff --git a/tools/libs/light/flexarray.c b/tools/libs/light/flexarray.c
new file mode 100644
index 0000000000..fe40e762e4
--- /dev/null
+++ b/tools/libs/light/flexarray.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_internal.h"
+#include <stdarg.h>
+
+/*
+ * It is safe to store gc in the struct because:
+ * - If it an actual gc, then the flexarray should not be used after the gc
+ *   have been freed.
+ * - If it is a NOGC, then this point to a structure embedded in libxl_ctx,
+ *   therefore will survive across several libxl calls.
+ */
+
+flexarray_t *flexarray_make(libxl__gc *gc, int size, int autogrow)
+{
+    flexarray_t *array;
+
+    GCNEW(array);
+    array->size = size;
+    array->autogrow = autogrow;
+    array->count = 0;
+    array->gc = gc;
+    GCNEW_ARRAY(array->data, size);
+
+    return array;
+}
+
+void flexarray_free(flexarray_t *array)
+{
+    assert(!libxl__gc_is_real(array->gc));
+    free(array->data);
+    free(array);
+}
+
+void flexarray_grow(flexarray_t *array, int extents)
+{
+    int newsize;
+    libxl__gc *gc = array->gc;
+
+    newsize = array->size + extents;
+    GCREALLOC_ARRAY(array->data, newsize);
+    array->size += extents;
+}
+
+int flexarray_set(flexarray_t *array, unsigned int idx, void *ptr)
+{
+    if (idx >= array->size) {
+        int newsize;
+        if (!array->autogrow)
+            return 1;
+        newsize = (array->size * 2 < idx) ? idx + 1 : array->size * 2;
+        flexarray_grow(array, newsize - array->size);
+    }
+    if ( idx + 1 > array->count )
+        array->count = idx + 1;
+    array->data[idx] = ptr;
+    return 0;
+}
+
+int flexarray_append(flexarray_t *array, void *ptr)
+{
+    return flexarray_set(array, array->count, ptr);
+}
+
+int flexarray_append_pair(flexarray_t *array, void *ptr1, void *ptr2)
+{
+    int rc = flexarray_append(array, ptr1);
+    if (!rc)
+        rc = flexarray_append(array, ptr2);
+    return rc;
+}
+
+int flexarray_vappend(flexarray_t *array, ...)
+{
+    va_list va;
+    void *ptr;
+    int ret;
+
+    va_start(va, array);
+    for(ret = 0; (ptr = va_arg(va, void *)); ret++) {
+        if ( flexarray_append(array, ptr) )
+            break;
+    }
+    va_end(va);
+    return ret;
+}
+
+int flexarray_get(flexarray_t *array, int idx, void **ptr)
+{
+    if (idx >= array->size)
+        return 1;
+    *ptr = array->data[idx];
+    return 0;
+}
+
+void **flexarray_contents(flexarray_t *array)
+{
+    void **data;
+    data = array->data;
+    if (!libxl__gc_is_real(array->gc))
+        free(array);
+    return data;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/light/flexarray.h b/tools/libs/light/flexarray.h
new file mode 100644
index 0000000000..a1e86475c4
--- /dev/null
+++ b/tools/libs/light/flexarray.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#ifndef FLEXARRAY_H
+#define FLEXARRAY_H
+
+struct libxl__gc;
+
+typedef struct flexarray {
+    int size;
+    int autogrow;
+    unsigned int count;
+    void **data; /* array of pointer */
+    struct libxl__gc *gc;
+} flexarray_t;
+
+/*
+ * NOGC can be used with flexarrays, but flexarray_free will need to be called
+ * to free the struct. The content of the flexarray will not be freed through
+ * flexarray_free.
+ */
+_hidden flexarray_t *flexarray_make(struct libxl__gc *gc_opt,
+                                    int size, int autogrow);
+_hidden void flexarray_free(flexarray_t *array);
+_hidden void flexarray_grow(flexarray_t *array, int extents);
+_hidden int flexarray_set(flexarray_t *array, unsigned int index, void *ptr);
+_hidden int flexarray_append(flexarray_t *array, void *ptr);
+_hidden int flexarray_append_pair(flexarray_t *array, void *ptr1, void *ptr2);
+_hidden int flexarray_vappend(flexarray_t *array, ...);
+_hidden int flexarray_get(flexarray_t *array, int index, void **ptr);
+
+_hidden void **flexarray_contents(flexarray_t *array);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/light/gentest.py b/tools/libs/light/gentest.py
new file mode 100644
index 0000000000..1cc7eebc82
--- /dev/null
+++ b/tools/libs/light/gentest.py
@@ -0,0 +1,374 @@
+#!/usr/bin/python
+
+from __future__ import print_function
+
+import os
+import sys
+import re
+import random
+
+import idl
+
+def randomize_char(c):
+    if random.random() < 0.5:
+        return str.lower(c)
+    else:
+        return str.upper(c)
+
+def randomize_case(s):
+    r = [randomize_char(c) for c in s]
+    return "".join(r)
+
+def randomize_enum(e):
+    return random.choice([v.name for v in e.values])
+
+handcoded = ["libxl_bitmap", "libxl_key_value_list",
+             "libxl_cpuid_policy_list", "libxl_string_list"]
+
+def gen_rand_init(ty, v, indent = "    ", parent = None):
+    s = ""
+    if isinstance(ty, idl.Enumeration):
+        s += "%s = %s;\n" % (ty.pass_arg(v, parent is None), 
randomize_enum(ty))
+    elif isinstance(ty, idl.Array):
+        if parent is None:
+            raise Exception("Array type must have a parent")
+        s += "%s = test_rand(8);\n" % (parent + ty.lenvar.name)
+        s += "%s = calloc(%s, sizeof(*%s));\n" % \
+            (v, parent + ty.lenvar.name, v)
+        s += "assert(%s);\n" % (v, )
+        s += "{\n"
+        s += "    int i;\n"
+        s += "    for (i=0; i<%s; i++)\n" % (parent + ty.lenvar.name)
+        s += gen_rand_init(ty.elem_type, v+"[i]",
+                           indent + "        ", parent)
+        s += "}\n"
+    elif isinstance(ty, idl.KeyedUnion):
+        if parent is None:
+            raise Exception("KeyedUnion type must have a parent")
+        s += gen_rand_init(ty.keyvar.type, parent + ty.keyvar.name, indent, 
parent)
+        s += "switch (%s) {\n" % (parent + ty.keyvar.name)
+        for f in ty.fields:
+            (nparent,fexpr) = ty.member(v, f, parent is None)
+            s += "case %s:\n" % f.enumname
+            if f.type is not None:
+                s += gen_rand_init(f.type, fexpr, indent + "    ", nparent)
+            s += "    break;\n"
+        s += "}\n"
+    elif isinstance(ty, idl.Struct) \
+     and (parent is None or ty.json_gen_fn is None):
+        for f in [f for f in ty.fields if not f.const]:
+            (nparent,fexpr) = ty.member(v, f, parent is None)
+            s += gen_rand_init(f.type, fexpr, "", nparent)
+    elif hasattr(ty, "rand_init") and ty.rand_init is not None:
+        s += "%s(%s);\n" % (ty.rand_init,
+                            ty.pass_arg(v, isref=parent is None,
+                                        passby=idl.PASS_BY_REFERENCE))
+    elif ty.typename in ["libxl_uuid", "libxl_mac", "libxl_hwcap", 
"libxl_ms_vm_genid"]:
+        s += "rand_bytes((uint8_t *)%s, sizeof(*%s));\n" % (v,v)
+    elif ty.typename in ["libxl_domid", "libxl_devid"] or isinstance(ty, 
idl.Number):
+        s += "%s = test_rand(sizeof(%s) * 8);\n" % \
+             (ty.pass_arg(v, parent is None),
+              ty.pass_arg(v, parent is None))
+    elif ty.typename in ["bool"]:
+        s += "%s = test_rand(2);\n" % v
+    elif ty.typename in ["libxl_defbool"]:
+        s += "libxl_defbool_set(%s, test_rand(2));\n" % v
+    elif ty.typename in ["char *"]:
+        s += "%s = rand_str();\n" % v
+    elif ty.private:
+        pass
+    elif ty.typename in handcoded:
+        raise Exception("Gen for handcoded %s" % ty.typename)
+    else:
+        raise Exception("Cannot randomly init %s" % ty.typename)
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+if __name__ == '__main__':
+    if len(sys.argv) < 3:
+        print("Usage: gentest.py <idl> <implementation>", file=sys.stderr)
+        sys.exit(1)
+
+    random.seed(os.getenv('LIBXL_TESTIDL_SEED'))
+
+    (builtins,types) = idl.parse(sys.argv[1])
+
+    impl = sys.argv[2]
+    f = open(impl, "w")
+    f.write("""
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "libxl.h"
+#include "libxl_utils.h"
+
+static int test_rand(unsigned max)
+{
+    /* We are not using rand() for its cryptographic properies. */
+    return rand() % max;
+}
+
+static char *rand_str(void)
+{
+    int i, sz = test_rand(32);
+    char *s = malloc(sz+1);
+    assert(s);
+    for (i=0; i<sz; i++)
+        s[i] = 'a' + test_rand(26);
+    s[i] = '\\0';
+    return s;
+}
+
+static void rand_bytes(uint8_t *p, size_t sz)
+{
+    int i;
+    for (i=0; i<sz; i++)
+        p[i] = test_rand(256);
+}
+
+static void libxl_bitmap_rand_init(libxl_bitmap *bitmap)
+{
+    int i;
+    bitmap->size = test_rand(16);
+    bitmap->map = calloc(bitmap->size, sizeof(*bitmap->map));
+    assert(bitmap->map);
+    libxl_for_each_bit(i, *bitmap) {
+        if (test_rand(2))
+            libxl_bitmap_set(bitmap, i);
+        else
+            libxl_bitmap_reset(bitmap, i);
+    }
+}
+
+static void libxl_key_value_list_rand_init(libxl_key_value_list *pkvl)
+{
+    int i, nr_kvp = test_rand(16);
+    libxl_key_value_list kvl = calloc(nr_kvp+1, 2*sizeof(char *));
+    assert(kvl);
+
+    for (i = 0; i<2*nr_kvp; i += 2) {
+        kvl[i] = rand_str();
+        if (test_rand(8))
+            kvl[i+1] = rand_str();
+        else
+            kvl[i+1] = NULL;
+    }
+    kvl[i] = NULL;
+    kvl[i+1] = NULL;
+    *pkvl = kvl;
+}
+
+static void libxl_cpuid_policy_list_rand_init(libxl_cpuid_policy_list *pp)
+{
+    int i, nr_policies = test_rand(16);
+    struct {
+        const char *n;
+        int w;
+    } options[] = {
+      /* A random selection from libxl_cpuid_parse_config */
+        {"maxleaf",     32},
+        {"family",       8},
+        {"model",        8},
+        {"stepping",     4},
+        {"localapicid",  8},
+        {"proccount",    8},
+        {"clflush",      8},
+        {"brandid",      8},
+        {"f16c",         1},
+        {"avx",          1},
+        {"osxsave",      1},
+        {"xsave",        1},
+        {"aes",          1},
+        {"popcnt",       1},
+        {"movbe",        1},
+        {"x2apic",       1},
+        {"sse4.2",       1},
+        {"sse4.1",       1},
+        {"dca",          1},
+        {"pdcm",         1},
+        {"procpkg",      6},
+    };
+    const int nr_options = sizeof(options)/sizeof(options[0]);
+    char buf[64];
+    libxl_cpuid_policy_list p = NULL;
+
+    for (i = 0; i < nr_policies; i++) {
+        int opt = test_rand(nr_options);
+        int val = test_rand(1<<options[opt].w);
+        snprintf(buf, 64, \"%s=%#x\", options[opt].n, val);
+        libxl_cpuid_parse_config(&p, buf);
+    }
+    *pp = p;
+}
+
+static void libxl_string_list_rand_init(libxl_string_list *p)
+{
+    int i, nr = test_rand(16);
+    libxl_string_list l = calloc(nr+1, sizeof(char *));
+    assert(l);
+
+    for (i = 0; i<nr; i++) {
+        l[i] = rand_str();
+    }
+    l[i] = NULL;
+    *p = l;
+}
+""")
+    for ty in builtins + types:
+        if isinstance(ty, idl.Number): continue
+        if ty.typename not in handcoded:
+            f.write("static void %s_rand_init(%s);\n" % \
+                    (ty.typename,
+                     ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+            f.write("static void %s_rand_init(%s)\n" % \
+                    (ty.typename,
+                     ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+            f.write("{\n")
+            f.write(gen_rand_init(ty, "p"))
+            f.write("}\n")
+            f.write("\n")
+        ty.rand_init = "%s_rand_init" % ty.typename
+
+    f.write("""
+int main(int argc, char **argv)
+{
+""")
+
+    for ty in types:
+        f.write("    %s %s_val, %s_val_new;\n" % \
+                (ty.typename, ty.typename, ty.typename))
+    f.write("""
+    int rc;
+    char *s, *new_s, *json_string;
+    xentoollog_logger_stdiostream *logger;
+    libxl_ctx *ctx;
+
+    logger = xtl_createlogger_stdiostream(stderr, XTL_DETAIL, 0);
+    if (!logger) exit(1);
+
+    if (libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, (xentoollog_logger*)logger)) {
+        fprintf(stderr, "cannot init xl context\\n");
+        exit(1);
+    }
+""")
+    f.write("    printf(\"Testing TYPE_to/from_json()\\n\");\n")
+    f.write("    printf(\"----------------------\\n\");\n")
+    f.write("    printf(\"\\n\");\n")
+    for ty in [t for t in types if t.json_gen_fn is not None]:
+        arg = ty.typename + "_val"
+        f.write("    %s_rand_init(%s);\n" % (ty.typename, \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        if not isinstance(ty, idl.Enumeration):
+            iters = random.randrange(1,10)
+            while iters > 0:
+                f.write("    %s_init(%s_new);\n" % (ty.typename, \
+                    ty.pass_arg(arg, isref=False, 
passby=idl.PASS_BY_REFERENCE)))
+                iters -= 1
+        f.write("    s = %s_to_json(ctx, %s);\n" % \
+                (ty.typename, ty.pass_arg(arg, isref=False)))
+        f.write("    printf(\"%%s: %%s\\n\", \"%s\", s);\n" % ty.typename)
+        f.write("    if (s == NULL) abort();\n")
+        f.write("    rc = %s_from_json(ctx, &%s_val_new, s);\n" % \
+                (ty.typename, ty.typename))
+        f.write("    if (rc) abort();\n")
+        f.write("    new_s = %s_to_json(ctx, %s_new);\n" % \
+                (ty.typename, ty.pass_arg(arg, isref=False)))
+        f.write("    if (new_s == NULL) abort();\n")
+        f.write("    if (strcmp(s, new_s)) {\n")
+        f.write("        printf(\"Huh? Regenerated string different from 
original string.\\n\");\n")
+        f.write("        printf(\"Regenerated string: %s\\n\", new_s);\n")
+        f.write("        abort();\n")
+        f.write("    }\n")
+        f.write("    free(s);\n")
+        f.write("    free(new_s);\n")
+        if ty.dispose_fn is not None:
+            iters = random.randrange(1,10)
+            f.write("    %s(&%s_val);\n" % (ty.dispose_fn, ty.typename))
+            while iters > 0:
+                f.write("    %s(&%s_val_new);\n" % (ty.dispose_fn, 
ty.typename))
+                iters -= 1
+        f.write("\n")
+
+    f.write("    printf(\"Testing TYPE_copy()\\n\");\n")
+    f.write("    printf(\"----------------------\\n\");\n")
+    f.write("    printf(\"\\n\");\n")
+    for ty in [t for t in types if t.copy_fn is not None]:
+        f.write("    printf(\"Testing %s_copy, \");\n" % ty.typename)
+        arg = ty.typename + "_val"
+        f.write("    %s_init(%s);\n" % (ty.typename, \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        f.write("    %s_rand_init(%s);\n" % (ty.typename, \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        f.write("    %s_init(%s_new);\n" % (ty.typename, \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        f.write("    %s_copy(ctx, %s_new, %s);\n" % (ty.typename, \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE), \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        f.write("    s = %s_to_json(ctx, %s);\n" % \
+                (ty.typename, ty.pass_arg(arg, isref=False)))
+        f.write("    if (s == NULL) abort();\n")
+        f.write("    new_s = %s_to_json(ctx, %s_new);\n" % \
+                (ty.typename, ty.pass_arg(arg, isref=False)))
+        f.write("    if (new_s == NULL) abort();\n")
+        f.write("    if (strcmp(s, new_s)) {\n")
+        f.write("        printf(\"Huh? Deep copy for %s failed. Regenerated 
string different from original string.\\n\");\n" \
+                % ty.typename)
+        f.write("        printf(\"Original string: %s\\n\", s);\n")
+        f.write("        printf(\"Regenerated string: %s\\n\", new_s);\n")
+        f.write("        abort();\n")
+        f.write("    }\n")
+        f.write("    free(s);\n")
+        f.write("    free(new_s);\n")
+        if ty.dispose_fn is not None:
+            f.write("    %s(&%s_val);\n" % (ty.dispose_fn, ty.typename))
+            f.write("    %s(&%s_val_new);\n" % (ty.dispose_fn, ty.typename))
+        f.write("    printf(\"done\\n\");\n")
+        f.write("\n")
+
+    f.write("    printf(\"\\n\");\n")
+    f.write("    printf(\"Testing Enumerations\\n\");\n")
+    f.write("    printf(\"--------------------\\n\");\n")
+    f.write("    printf(\"\\n\");\n")
+    for ty in [t for t in types if isinstance(t,idl.Enumeration)]:
+        f.write("    printf(\"%s -- to string:\\n\");\n" % (ty.typename))
+        for v in ty.values:
+            f.write("    printf(\"\\t%s = %%d = \\\"%%s\\\"\\n\", " \
+                    "%s, %s_to_string(%s));\n" % \
+                    (v.valuename, v.name, ty.typename, v.name))
+        f.write("\n")
+
+        f.write("    printf(\"%s -- to JSON:\\n\");\n" % (ty.typename))
+        for v in ty.values:
+            f.write("    json_string = %s_to_json(ctx, %s);\n" % \
+                    (ty.typename, v.name))
+            f.write("    printf(\"\\t%s = %%d = %%s\", " \
+                    "%s, json_string);\n" %\
+                    (v.valuename, v.name))
+            f.write("    free(json_string);\n");
+            f.write("    json_string = NULL;\n");
+        f.write("\n")
+
+        f.write("    printf(\"%s -- from string:\\n\");\n" % (ty.typename))
+        for v in [v.valuename for v in ty.values] + ["AN INVALID VALUE"]:
+            n = randomize_case(v)
+            f.write("    %s_val = -1;\n" % (ty.typename))
+            f.write("    rc = %s_from_string(\"%s\", &%s_val);\n" %\
+                    (ty.typename, n, ty.typename))
+
+            f.write("    printf(\"\\t%s = \\\"%%s\\\" = %%d (rc %%d)\\n\", " \
+                    "\"%s\", %s_val, rc);\n" %\
+                    (v, n, ty.typename))
+        f.write("\n")
+
+    f.write("""
+
+    libxl_ctx_free(ctx);
+    xtl_logger_destroy((xentoollog_logger*)logger);
+
+    return 0;
+}
+""")
diff --git a/tools/libs/light/gentypes.py b/tools/libs/light/gentypes.py
new file mode 100644
index 0000000000..9a45e45acc
--- /dev/null
+++ b/tools/libs/light/gentypes.py
@@ -0,0 +1,797 @@
+#!/usr/bin/python
+
+from __future__ import print_function
+
+import sys
+import re
+
+import idl
+
+def libxl_C_instance_of(ty, instancename):
+    if isinstance(ty, idl.Aggregate) and ty.typename is None:
+        if instancename is None:
+            return libxl_C_type_define(ty)
+        else:
+            return libxl_C_type_define(ty) + " " + instancename
+
+    s = ""
+    if isinstance(ty, idl.Array):
+        s += libxl_C_instance_of(ty.lenvar.type, ty.lenvar.name) + ";\n"
+
+    return s + ty.typename + " " + instancename
+
+def libxl_C_type_define(ty, indent = ""):
+    s = ""
+    if isinstance(ty, idl.Enumeration):
+        if ty.typename is None:
+            s += "enum {\n"
+        else:
+            s += "typedef enum %s {\n" % ty.typename
+
+        for v in ty.values:
+            x = "%s = %d" % (v.name, v.value)
+            x = x.replace("\n", "\n    ")
+            s += "    " + x + ",\n"
+        if ty.typename is None:
+            s += "}"
+        else:
+            s += "} %s" % ty.typename
+
+    elif isinstance(ty, idl.Aggregate):
+        if isinstance(ty, idl.KeyedUnion):
+            s += libxl_C_instance_of(ty.keyvar.type, ty.keyvar.name) + ";\n"
+            
+        if ty.typename is None:
+            s += "%s {\n" % ty.kind
+        else:
+            s += "typedef %s %s {\n" % (ty.kind, ty.typename)
+
+        for f in ty.fields:
+            if isinstance(ty, idl.KeyedUnion) and f.type is None: continue
+            
+            x = libxl_C_instance_of(f.type, f.name)
+            if f.const:
+                x = "const " + x
+            x = x.replace("\n", "\n    ")
+            s += "    " + x + ";\n"
+        if ty.typename is None:
+            s += "}"
+        else:
+            s += "} %s" % ty.typename
+    else:
+        raise NotImplementedError("%s" % type(ty))
+    return s.replace("\n", "\n%s" % indent)
+
+def libxl_C_type_dispose(ty, v, indent = "    ", parent = None):
+    s = ""
+    if isinstance(ty, idl.KeyedUnion):
+        if parent is None:
+            raise Exception("KeyedUnion type must have a parent")
+        s += "switch (%s) {\n" % (parent + ty.keyvar.name)
+        for f in ty.fields:
+            (nparent,fexpr) = ty.member(v, f, parent is None)
+            s += "case %s:\n" % f.enumname
+            if f.type is not None:
+                s += libxl_C_type_dispose(f.type, fexpr, indent + "    ", 
nparent)
+            s += "    break;\n"
+        s += "}\n"
+    elif isinstance(ty, idl.Array):
+        if parent is None:
+            raise Exception("Array type must have a parent")
+        if ty.elem_type.dispose_fn is not None:
+            s += "{\n"
+            s += "    int i;\n"
+            s += "    for (i=0; i<%s; i++)\n" % (parent + ty.lenvar.name)
+            s += libxl_C_type_dispose(ty.elem_type, v+"[i]",
+                                      indent + "        ", parent)
+        if ty.dispose_fn is not None:
+            if ty.elem_type.dispose_fn is not None:
+                s += "    "
+            s += "%s(%s);\n" % (ty.dispose_fn, ty.pass_arg(v, parent is None))
+        if ty.elem_type.dispose_fn is not None:
+            s += "}\n"
+    elif isinstance(ty, idl.Struct) and (parent is None or ty.dispose_fn is 
None):
+        for f in [f for f in ty.fields if not f.const]:
+            (nparent,fexpr) = ty.member(v, f, parent is None)
+            s += libxl_C_type_dispose(f.type, fexpr, "", nparent)
+    else:
+        if ty.dispose_fn is not None:
+            s += "%s(%s);\n" % (ty.dispose_fn, ty.pass_arg(v, parent is None))
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_type_copy(ty, v, w, indent = "    ", vparent = None, wparent = 
None):
+    s = ""
+
+    if vparent is None:
+        s += "GC_INIT(ctx);\n";
+
+    if isinstance(ty, idl.KeyedUnion):
+        if vparent is None or wparent is None:
+            raise Exception("KeyedUnion type must have a parent")
+        s += "%s = %s;\n" % ((vparent + ty.keyvar.name), (wparent + 
ty.keyvar.name))
+        s += "switch (%s) {\n" % (wparent + ty.keyvar.name)
+        for f in ty.fields:
+            (vnparent,vfexpr) = ty.member(v, f, vparent is None)
+            (wnparent,wfexpr) = ty.member(w, f, wparent is None)
+            s += "case %s:\n" % f.enumname
+            if f.type is not None:
+                s += libxl_C_type_copy(f.type, vfexpr, wfexpr, indent + "    ",
+                                       vnparent, wnparent)
+            s += "    break;\n"
+        s += "}\n"
+    elif isinstance(ty, idl.Array):
+        if vparent is None or wparent is None:
+            raise Exception("Array type must have a parent")
+        s += "%s = libxl__calloc(NOGC, %s, sizeof(*%s));\n" % (ty.pass_arg(v, 
vparent is None),
+                                                               (wparent + 
ty.lenvar.name),
+                                                               ty.pass_arg(w, 
wparent is None))
+        s += "%s = %s;\n" % ((vparent + ty.lenvar.name), (wparent + 
ty.lenvar.name))
+        s += "{\n"
+        s += "    int i;\n"
+        s += "    for (i=0; i<%s; i++)\n" % (wparent + ty.lenvar.name)
+        s += libxl_C_type_copy(ty.elem_type, v+"[i]", w+"[i]",
+                               indent + "        ", vparent, wparent)
+        s += "}\n"
+    elif isinstance(ty, idl.Struct) and ((vparent is None and wparent is None) 
or ty.copy_fn is None):
+        for f in [f for f in ty.fields if not f.const and not f.type.private]:
+            (vnparent,vfexpr) = ty.member(v, f, vparent is None)
+            (wnparent,wfexpr) = ty.member(w, f, wparent is None)
+            s += libxl_C_type_copy(f.type, vfexpr, wfexpr, "", vnparent, 
wnparent)
+    else:
+        if ty.copy_fn is not None:
+            s += "%s(ctx, %s, %s);\n" % (ty.copy_fn,
+                                         ty.pass_arg(v, vparent is None, 
passby=idl.PASS_BY_REFERENCE),
+                                         ty.pass_arg(w, wparent is None, 
passby=idl.PASS_BY_REFERENCE))
+
+        else:
+            s += "%s = %s;\n" % (ty.pass_arg(v, vparent is None, 
passby=idl.PASS_BY_VALUE),
+                                 ty.pass_arg(w, wparent is None, 
passby=idl.PASS_BY_VALUE))
+
+    if vparent is None:
+        s += "GC_FREE;\n"
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_init_members(ty, nesting = 0):
+    """Returns a list of members of ty which require a separate init"""
+
+    if isinstance(ty, idl.Aggregate):
+        return [f for f in ty.fields if not f.const and 
isinstance(f.type,idl.KeyedUnion)]
+    else:
+        return []
+    
+def libxl_C_type_do_init(ty, pass_arg, need_zero=True, indent="    "):
+    s=indent
+    if ty.init_val is not None:
+        s+= "%s = %s;\n" % (pass_arg(idl.PASS_BY_VALUE), ty.init_val)
+    elif ty.init_fn is not None:
+        s+= "%s(%s);\n" % (ty.init_fn, pass_arg(idl.PASS_BY_REFERENCE))
+    elif need_zero:
+        ptr = pass_arg(idl.PASS_BY_REFERENCE)
+        s+= "memset(%s, 0, sizeof(*%s));\n" % (ptr, ptr)
+    else:
+        s=""
+    return s
+
+def _libxl_C_type_init(ty, v, indent = "    ", parent = None, subinit=False):
+    s = ""
+    if isinstance(ty, idl.KeyedUnion):
+        if parent is None:
+            raise Exception("KeyedUnion type must have a parent")
+        if subinit:
+            s += "switch (%s) {\n" % (parent + ty.keyvar.name)
+            for f in ty.fields:
+                (nparent,fexpr) = ty.member(v, f, parent is None)
+                s += "case %s:\n" % f.enumname
+                if f.type is not None:
+                    s += _libxl_C_type_init(f.type, fexpr, "    ", nparent)
+                s += "    break;\n"
+            s += "}\n"
+        else:
+            if ty.keyvar.init_val:
+                s += "%s = %s;\n" % (parent + ty.keyvar.name, 
ty.keyvar.init_val)
+            elif ty.keyvar.type.init_val:
+                s += "%s = %s;\n" % (parent + ty.keyvar.name, 
ty.keyvar.type.init_val)
+    elif isinstance(ty, idl.Struct) and (parent is None or ty.init_fn is None):
+        for f in [f for f in ty.fields if not f.const]:
+            (nparent,fexpr) = ty.member(v, f, parent is None)
+            if f.init_val is not None:
+                s += "%s = %s;\n" % (fexpr, f.init_val)
+            else:
+                s += _libxl_C_type_init(f.type, fexpr, "", nparent)
+    else:
+        if ty.init_val is not None:
+            s += "%s = %s;\n" % (ty.pass_arg(v, parent is None), ty.init_val)
+        elif ty.init_fn is not None:
+            s += "%s(%s);\n" % (ty.init_fn, ty.pass_arg(v, parent is None))
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_type_init(ty):
+    s = ""
+    s += "void %s(%s)\n" % (ty.init_fn, ty.make_arg("p", 
passby=idl.PASS_BY_REFERENCE))
+    s += "{\n"
+    s += "    memset(p, '\\0', sizeof(*p));\n"
+    s += _libxl_C_type_init(ty, "p")
+    s += "}\n"
+    s += "\n"
+    return s
+
+def libxl_C_type_member_init(ty, field):
+    if not isinstance(field.type, idl.KeyedUnion):
+        raise Exception("Only KeyedUnion is supported for member init")
+
+    ku = field.type
+    
+    s = ""
+    s += "void %s(%s, %s)\n" % (ty.init_fn + "_" + ku.keyvar.name,
+                                ty.make_arg("p", passby=idl.PASS_BY_REFERENCE),
+                                ku.keyvar.type.make_arg(ku.keyvar.name))
+    s += "{\n"
+    
+    if ku.keyvar.init_val is not None:
+        init_val = ku.keyvar.init_val
+    elif ku.keyvar.type.init_val is not None:
+        init_val = ku.keyvar.type.init_val
+    else:
+        init_val = None
+        
+    (nparent,fexpr) = ty.member(ty.pass_arg("p"), ku.keyvar, isref=True)
+    if init_val is not None:
+        s += "    assert(%s == %s);\n" % (fexpr, init_val)
+    else:
+        s += "    assert(!%s);\n" % (fexpr)
+    s += "    %s = %s;\n" % (fexpr, ku.keyvar.name)
+
+    (nparent,fexpr) = ty.member(ty.pass_arg("p"), field, isref=True)
+    s += _libxl_C_type_init(ku, fexpr, parent=nparent, subinit=True)
+    s += "}\n"
+    s += "\n"
+    return s
+
+def libxl_C_type_gen_map_key(f, parent, indent = ""):
+    s = ""
+    if isinstance(f.type, idl.KeyedUnion):
+        s += "switch (%s) {\n" % (parent + f.type.keyvar.name)
+        for x in f.type.fields:
+            v = f.type.keyvar.name + "." + x.name
+            s += "case %s:\n" % x.enumname
+            s += "    s = yajl_gen_string(hand, (const unsigned char *)\"%s\", 
sizeof(\"%s\")-1);\n" % (v, v)
+            s += "    if (s != yajl_gen_status_ok)\n"
+            s += "        goto out;\n"
+            s += "    break;\n"
+        s += "}\n"
+    else:
+        s += "s = yajl_gen_string(hand, (const unsigned char *)\"%s\", 
sizeof(\"%s\")-1);\n" % (f.name, f.name)
+        s += "if (s != yajl_gen_status_ok)\n"
+        s += "    goto out;\n"
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_type_copy_deprecated(field, v, indent = "    ", vparent = None):
+    s = ""
+
+    if isinstance(field.type, idl.KeyedUnion):
+        if vparent is None:
+            raise Exception("KeyedUnion type must have a parent")
+        s += "switch (%s) {\n" % (vparent + field.type.keyvar.name)
+        for f in [f for f in field.type.fields if not f.const]:
+            (vnparent,vfexpr) = ty.member(v, f, vparent is None)
+            s += "case %s:\n" % f.enumname
+            if f.type is not None:
+                s += libxl_C_type_copy_deprecated(f, vfexpr, indent, vnparent)
+            s+= "    break;\n"
+        s+="}\n";
+    elif isinstance(field.type, idl.Array) and field.deprecated_by:
+        raise Exception("Array type is not supported for deprecation")
+    elif isinstance(field.type, idl.Struct) and field.type.copy_fn is None:
+        for f in [f for f in field.type.fields if not f.const]:
+            (vnparent,vfexpr) = ty.member(v, f, vparent is None)
+            s += libxl_C_type_copy_deprecated(f, vfexpr, "", vnparent)
+    elif field.deprecated_by is not None:
+        if field.type.check_default_fn is None:
+            raise Exception(
+"Deprecated field %s type doesn't have a default value checker" % field.name)
+        field_pass = lambda by: field.type.pass_arg(v, vparent is None,
+                                                    passby=by)
+        field_val = field_pass(idl.PASS_BY_VALUE)
+        field_ptr = field_pass(idl.PASS_BY_REFERENCE)
+        s+= "if (!%s(&p->%s) && !%s(%s))\n" % (field.type.check_default_fn,
+                                               field.deprecated_by,
+                                               field.type.check_default_fn,
+                                               field_ptr)
+        s+= "    return -EINVAL;\n"
+        s+="(void) (&p->%s == %s);\n" % (field.deprecated_by, field_ptr)
+        s+= "if (%s(&p->%s)) {\n" % (field.type.check_default_fn,
+                                     field.deprecated_by)
+        s+= "    "
+        if field.type.copy_fn is not None:
+            s+= "%s(ctx, &p->%s, %s);\n" % (field.type.copy_fn,
+                                            field.deprecated_by, field_ptr)
+        else:
+            s+= "p->%s = %s;\n" % (field.deprecated_by, field_val)
+
+        if field.type.dispose_fn is not None:
+            s+= "    %s(%s);\n" % (field.type.dispose_fn,
+                                   field.type.pass_arg(v, vparent is None))
+        s+=libxl_C_type_do_init(field.type, field_pass)
+        s+= "}\n"
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def get_init_val(f):
+    if f.init_val is not None:
+        return f.init_val
+    elif f.type.init_val is not None:
+        return f.type.init_val
+    return None
+
+def get_default_expr(f, nparent, fexpr):
+    if isinstance(f.type, idl.Aggregate):
+        return "1 /* always generate JSON output for aggregate type */"
+
+    if isinstance(f.type, idl.Array):
+        return "%s && %s" % (fexpr, nparent + f.type.lenvar.name)
+
+    init_val = get_init_val(f)
+    if init_val is not None:
+        return "%s != %s" % (fexpr, init_val)
+
+    if f.type.check_default_fn:
+        return "!%s(&%s)" % (f.type.check_default_fn, fexpr)
+
+    return "%s" % fexpr
+
+def libxl_C_type_gen_json(ty, v, indent = "    ", parent = None):
+    s = ""
+    if parent is None:
+        s += "yajl_gen_status s;\n"
+
+    if isinstance(ty, idl.Array):
+        if parent is None:
+            raise Exception("Array type must have a parent")
+        s += "{\n"
+        s += "    int i;\n"
+        s += "    s = yajl_gen_array_open(hand);\n"
+        s += "    if (s != yajl_gen_status_ok)\n"
+        s += "        goto out;\n"
+        s += "    for (i=0; i<%s; i++) {\n" % (parent + ty.lenvar.name)
+        s += libxl_C_type_gen_json(ty.elem_type, v+"[i]",
+                                   indent + "        ", parent)
+        s += "    }\n"
+        s += "    s = yajl_gen_array_close(hand);\n"
+        s += "    if (s != yajl_gen_status_ok)\n"
+        s += "        goto out;\n"
+        s += "}\n"
+    elif isinstance(ty, idl.Enumeration):
+        s += "s = libxl__yajl_gen_enum(hand, %s_to_string(%s));\n" % 
(ty.typename, ty.pass_arg(v, parent is None))
+        s += "if (s != yajl_gen_status_ok)\n"
+        s += "    goto out;\n"
+    elif isinstance(ty, idl.KeyedUnion):
+        if parent is None:
+            raise Exception("KeyedUnion type must have a parent")
+        s += "switch (%s) {\n" % (parent + ty.keyvar.name)
+        for f in ty.fields:
+            (nparent,fexpr) = ty.member(v, f, parent is None)
+            s += "case %s:\n" % f.enumname
+            if f.type is not None:
+                s += libxl_C_type_gen_json(f.type, fexpr, indent + "    ", 
nparent)
+            else:
+                s += "    s = yajl_gen_map_open(hand);\n"
+                s += "    if (s != yajl_gen_status_ok)\n"
+                s += "        goto out;\n"
+                s += "    s = yajl_gen_map_close(hand);\n"
+                s += "    if (s != yajl_gen_status_ok)\n"
+                s += "        goto out;\n"
+            s += "    break;\n"
+        s += "}\n"
+    elif isinstance(ty, idl.Struct) and (parent is None or ty.json_gen_fn is 
None):
+        s += "s = yajl_gen_map_open(hand);\n"
+        s += "if (s != yajl_gen_status_ok)\n"
+        s += "    goto out;\n"
+        for f in [f for f in ty.fields if not f.const and not f.type.private]:
+            (nparent,fexpr) = ty.member(v, f, parent is None)
+            default_expr = get_default_expr(f, nparent, fexpr)
+            s += "if (%s) {\n" % default_expr
+
+            s += libxl_C_type_gen_map_key(f, nparent, "    ")
+            s += libxl_C_type_gen_json(f.type, fexpr, "    ", nparent)
+
+            s += "}\n"
+
+        s += "s = yajl_gen_map_close(hand);\n"
+        s += "if (s != yajl_gen_status_ok)\n"
+        s += "    goto out;\n"
+    else:
+        if ty.json_gen_fn is not None:
+            s += "s = %s(hand, %s);\n" % (ty.json_gen_fn, ty.pass_arg(v, 
parent is None))
+            s += "if (s != yajl_gen_status_ok)\n"
+            s += "    goto out;\n"
+
+    if parent is None:
+        s += "out:\n"
+        s += "return s;\n"
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_type_to_json(ty, v, indent = "    "):
+    s = ""
+    gen = "(libxl__gen_json_callback)&%s_gen_json" % ty.typename
+    s += "return libxl__object_to_json(ctx, \"%s\", %s, (void *)%s);\n" % 
(ty.typename, gen, ty.pass_arg(v, passby=idl.PASS_BY_REFERENCE))
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_type_parse_json(ty, w, v, indent = "    ", parent = None, 
discriminator = None):
+    s = ""
+    if parent is None:
+        s += "int rc = 0;\n"
+        s += "const libxl__json_object *x __attribute__((__unused__)) = o;\n"
+
+    if isinstance(ty, idl.Array):
+        if parent is None:
+            raise Exception("Array type must have a parent")
+        if discriminator is not None:
+            raise Exception("Only KeyedUnion can have discriminator")
+        lenvar = parent + ty.lenvar.name
+        s += "{\n"
+        s += "    libxl__json_object *t;\n"
+        s += "    int i;\n"
+        s += "    if (!libxl__json_object_is_array(x)) {\n"
+        s += "        rc = -1;\n"
+        s += "        goto out;\n"
+        s += "    }\n"
+        s += "    %s = x->u.array->count;\n" % lenvar
+        s += "    %s = libxl__calloc(NOGC, %s, sizeof(*%s));\n" % (v, lenvar, 
v)
+        s += "    if (!%s && %s != 0) {\n" % (v, lenvar)
+        s += "        rc = -1;\n"
+        s += "        goto out;\n"
+        s += "    }\n"
+        s += "    for (i=0; (t=libxl__json_array_get(x,i)); i++) {\n"
+        s += libxl_C_type_do_init(ty.elem_type,
+                    lambda by: ("&" if by == idl.PASS_BY_REFERENCE else "")+
+                               ("%s[i]" % v),
+                                  need_zero=False, indent=indent+"    ")
+        s += libxl_C_type_parse_json(ty.elem_type, "t", v+"[i]",
+                                     indent + "    ", parent)
+        s += "    }\n"
+        s += "    if (i != %s) {\n" % lenvar
+        s += "        rc = -1;\n"
+        s += "        goto out;\n"
+        s += "    }\n"
+        s += "}\n"
+    elif isinstance(ty, idl.Enumeration):
+        if discriminator is not None:
+            raise Exception("Only KeyedUnion can have discriminator")
+        s += "{\n"
+        s += "    const char *enum_str;\n"
+        s += "    if (!libxl__json_object_is_string(%s)) {\n" % w
+        s += "        rc = -1;\n"
+        s += "        goto out;\n"
+        s += "    }\n"
+        s += "    enum_str = libxl__json_object_get_string(%s);\n" % w
+        s += "    rc = %s_from_string(enum_str, %s);\n" % (ty.typename, 
ty.pass_arg(v, parent is None, idl.PASS_BY_REFERENCE))
+        s += "    if (rc)\n"
+        s += "        goto out;\n"
+        s += "}\n"
+    elif isinstance(ty, idl.KeyedUnion):
+        if parent is None:
+            raise Exception("KeyedUnion type must have a parent")
+        if discriminator is None:
+            raise Excpetion("KeyedUnion type must have a discriminator")
+        for f in ty.fields:
+            if f.enumname != discriminator:
+                continue
+            (nparent,fexpr) = ty.member(v, f, parent is None)
+            if f.type is not None:
+                s += libxl_C_type_parse_json(f.type, w, fexpr, indent + "    
", nparent)
+    elif isinstance(ty, idl.Struct) and (parent is None or ty.json_parse_fn is 
None):
+        if discriminator is not None:
+            raise Exception("Only KeyedUnion can have discriminator")
+        for f in [f for f in ty.fields if not f.const and not f.type.private]:
+            saved_var_name = "saved_%s" % f.name
+            s += "{\n"
+            s += "    const libxl__json_object *%s = x;\n" % saved_var_name
+            if isinstance(f.type, idl.KeyedUnion):
+                for x in f.type.fields:
+                    s += "    x = libxl__json_map_get(\"%s\", %s, 
JSON_MAP);\n" % \
+                         (f.type.keyvar.name + "." + x.name, w)
+                    s += "    if (x) {\n"
+                    (nparent, fexpr) = ty.member(v, f.type.keyvar, parent is 
None)
+                    s += "        %s_init_%s(%s, %s);\n" % (ty.typename, 
f.type.keyvar.name, v, x.enumname)
+                    (nparent,fexpr) = ty.member(v, f, parent is None)
+                    s += libxl_C_type_parse_json(f.type, "x", fexpr, "  ", 
nparent, x.enumname)
+                    s += "    }\n"
+            else:
+                s += "    x = libxl__json_map_get(\"%s\", %s, %s);\n" % 
(f.name, w, f.type.json_parse_type)
+                s += "    if (x) {\n"
+                (nparent,fexpr) = ty.member(v, f, parent is None)
+                s += libxl_C_type_parse_json(f.type, "x", fexpr, "        ", 
nparent)
+                s += "    }\n"
+            s += "    x = %s;\n" % saved_var_name
+            s += "}\n"
+    else:
+        if discriminator is not None:
+            raise Exception("Only KeyedUnion can have discriminator")
+        if ty.json_parse_fn is not None:
+            s += "rc = %s(gc, %s, &%s);\n" % (ty.json_parse_fn, w, v)
+            s += "if (rc)\n"
+            s += "    goto out;\n"
+
+    if parent is None:
+        s += "out:\n"
+        s += "return rc;\n"
+
+    if s != "":
+        s = indent +s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_type_from_json(ty, v, w, indent = "    "):
+    s = ""
+    parse = "(libxl__json_parse_callback)&%s_parse_json" % (ty.namespace + "_" 
+ ty.rawname)
+    s += "return libxl__object_from_json(ctx, \"%s\", %s, %s, %s);\n" % 
(ty.typename, parse, v, w)
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_enum_to_string(ty, e, indent = "    "):
+    s = ""
+    s += "switch(%s) {\n" % e
+    for v in ty.values:
+        s += "    case %s:\n" % (v.name)
+        s += "        return \"%s\";\n" % (v.valuename.lower())
+    s += "    default:\n "
+    s += "        return NULL;\n"
+    s += "}\n"
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_enum_strings(ty, indent=""):
+    s = ""
+    s += "libxl_enum_string_table %s_string_table[] = {\n" % (ty.typename)
+    for v in ty.values:
+        s += "    { .s = \"%s\", .v = %s },\n" % (v.valuename.lower(), v.name)
+    s += "    { NULL, -1 },\n"
+    s += "};\n"
+    s += "\n"
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_enum_from_string(ty, str, e, indent = "    "):
+    s = ""
+    s += "return libxl__enum_from_string(%s_string_table,\n" % ty.typename
+    s += "                               %s, (int *)%s);\n" % (str, e)
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+
+if __name__ == '__main__':
+    if len(sys.argv) != 6:
+        print("Usage: gentypes.py <idl> <header> <header-private> 
<header-json> <implementation>", file=sys.stderr)
+        sys.exit(1)
+
+    (_, idlname, header, header_private, header_json, impl) = sys.argv
+
+    (builtins,types) = idl.parse(idlname)
+
+    print("outputting libxl type definitions to %s" % header)
+
+    f = open(header, "w")
+
+    header_define = header.upper().replace('.','_')
+    f.write("""#ifndef %s
+#define %s
+
+/*
+ * DO NOT EDIT.
+ *
+ * This file is autogenerated by
+ * "%s"
+ */
+
+""" % (header_define, header_define, " ".join(sys.argv)))
+
+    for ty in types:
+        f.write(libxl_C_type_define(ty) + ";\n")
+        if ty.dispose_fn is not None:
+            f.write("%svoid %s(%s);\n" % (ty.hidden(), ty.dispose_fn, 
ty.make_arg("p")))
+        if ty.copy_deprecated_fn is not None:
+            f.write("%sint %s(libxl_ctx *ctx, %s);\n" % (ty.hidden(),
+                                                         ty.copy_deprecated_fn,
+                                                         ty.make_arg("p")))
+        if ty.copy_fn is not None:
+            f.write("%svoid %s(libxl_ctx *ctx, %s, const %s);\n" % 
(ty.hidden(), ty.copy_fn,
+                                              ty.make_arg("dst"), 
ty.make_arg("src")))
+        if ty.init_fn is not None:
+            f.write("%svoid %s(%s);\n" % (ty.hidden(), ty.init_fn, 
ty.make_arg("p")))
+            for field in libxl_init_members(ty):
+                if not isinstance(field.type, idl.KeyedUnion):
+                    raise Exception("Only KeyedUnion is supported for member 
init")
+                ku = field.type
+                f.write("%svoid %s(%s, %s);\n" % (ty.hidden(), ty.init_fn + 
"_" + ku.keyvar.name,
+                                               ty.make_arg("p"),
+                                               
ku.keyvar.type.make_arg(ku.keyvar.name)))
+        if ty.json_gen_fn is not None:
+            f.write("%schar *%s_to_json(libxl_ctx *ctx, %s);\n" % 
(ty.hidden(), ty.typename, ty.make_arg("p")))
+        if ty.json_parse_fn is not None:
+            f.write("%sint %s_from_json(libxl_ctx *ctx, %s, const char *s);\n" 
% (ty.hidden(), ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+        if isinstance(ty, idl.Enumeration):
+            f.write("%sconst char *%s_to_string(%s);\n" % (ty.hidden(), 
ty.typename, ty.make_arg("p")))
+            f.write("%sint %s_from_string(const char *s, %s);\n" % 
(ty.hidden(), ty.typename, ty.make_arg("e", passby=idl.PASS_BY_REFERENCE)))
+            f.write("%sextern libxl_enum_string_table %s_string_table[];\n" % 
(ty.hidden(), ty.typename))
+        f.write("\n")
+
+    f.write("""#endif /* %s */\n""" % (header_define))
+    f.close()
+
+    print("outputting libxl JSON definitions to %s" % header_json)
+
+    f = open(header_json, "w")
+
+    header_json_define = header_json.upper().replace('.','_')
+    f.write("""#ifndef %s
+#define %s
+
+/*
+ * DO NOT EDIT.
+ *
+ * This file is autogenerated by
+ * "%s"
+ */
+
+""" % (header_json_define, header_json_define, " ".join(sys.argv)))
+
+    for ty in [ty for ty in types if ty.json_gen_fn is not None]:
+        f.write("%syajl_gen_status %s_gen_json(yajl_gen hand, %s);\n" % 
(ty.hidden(), ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+
+    f.write("\n")
+    f.write("""#endif /* %s */\n""" % header_json_define)
+    f.close()
+
+    print("outputting libxl type internal definitions to %s" % header_private)
+
+    f = open(header_private, "w")
+
+    header_private_define = header_private.upper().replace('.','_')
+    f.write("""#ifndef %s
+#define %s
+
+/*
+ * DO NOT EDIT.
+ *
+ * This file is autogenerated by
+ * "%s"
+ */
+
+""" % (header_private_define, header_private_define, " ".join(sys.argv)))
+
+    for ty in [ty for ty in types if ty.json_parse_fn is not None]:
+        f.write("%sint %s_parse_json(libxl__gc *gc, const libxl__json_object 
*o, %s);\n" % \
+                (ty.hidden(), ty.namespace + "_" + ty.rawname,
+                 ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+
+    f.write("\n")
+    f.write("""#endif /* %s */\n""" % header_json_define)
+    f.close()
+
+    print("outputting libxl type implementations to %s" % impl)
+
+    f = open(impl, "w")
+    f.write("""
+/* DO NOT EDIT.
+ *
+ * This file is autogenerated by
+ * "%s"
+ */
+
+#include "libxl_osdeps.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libxl_internal.h"
+
+
+""" % " ".join(sys.argv))
+
+    for ty in [t for t in types if t.dispose_fn is not None and 
t.autogenerate_dispose_fn]:
+        f.write("void %s(%s)\n" % (ty.dispose_fn, ty.make_arg("p")))
+        f.write("{\n")
+        f.write("    if (!p) return;\n")
+        f.write(libxl_C_type_dispose(ty, "p"))
+        f.write("    memset(p, 0, sizeof(*p));\n")
+        f.write("}\n")
+        f.write("\n")
+
+    for ty in [t for t in types if t.copy_fn and t.autogenerate_copy_fn]:
+        f.write("void %s(libxl_ctx *ctx, %s, const %s)\n" % (ty.copy_fn,
+                                       ty.make_arg("dst", 
passby=idl.PASS_BY_REFERENCE),
+                                       ty.make_arg("src", 
passby=idl.PASS_BY_REFERENCE)))
+        f.write("{\n")
+        f.write(libxl_C_type_copy(ty, "dst", "src"))
+        f.write("}\n")
+        f.write("\n")
+        
+    for ty in [t for t in types if t.copy_deprecated_fn]:
+        f.write("int %s(libxl_ctx *ctx, %s)\n" % (ty.copy_deprecated_fn,
+            ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+        f.write("{\n")
+        for field in [field for field in ty.fields if not field.const]:
+            (vnparent,vfexpr) = ty.member("p", field, True)
+            f.write(libxl_C_type_copy_deprecated(field, vfexpr,
+                                                 vparent = vnparent))
+        f.write("    return 0;\n")
+        f.write("}\n")
+        f.write("\n")
+
+    for ty in [t for t in types if t.init_fn is not None and 
t.autogenerate_init_fn]:
+        f.write(libxl_C_type_init(ty))
+        for field in libxl_init_members(ty):
+            f.write(libxl_C_type_member_init(ty, field))
+
+    for ty in [t for t in types if isinstance(t,idl.Enumeration)]:
+        f.write("const char *%s_to_string(%s e)\n" % (ty.typename, 
ty.typename))
+        f.write("{\n")
+        f.write(libxl_C_enum_to_string(ty, "e"))
+        f.write("}\n")
+        f.write("\n")
+
+        f.write(libxl_C_enum_strings(ty))
+
+        f.write("int %s_from_string(const char *s, %s *e)\n" % (ty.typename, 
ty.typename))
+        f.write("{\n")
+        f.write(libxl_C_enum_from_string(ty, "s", "e"))
+        f.write("}\n")
+        f.write("\n")
+
+    for ty in [t for t in types if t.json_gen_fn is not None]:
+        f.write("yajl_gen_status %s_gen_json(yajl_gen hand, %s)\n" % 
(ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+        f.write("{\n")
+        f.write(libxl_C_type_gen_json(ty, "p"))
+        f.write("}\n")
+        f.write("\n")
+
+        f.write("char *%s_to_json(libxl_ctx *ctx, %s)\n" % (ty.typename, 
ty.make_arg("p")))
+        f.write("{\n")
+        f.write(libxl_C_type_to_json(ty, "p"))
+        f.write("}\n")
+        f.write("\n")
+
+    for ty in [t for t in types if t.json_parse_fn is not None]:
+        f.write("int %s_parse_json(libxl__gc *gc, const libxl__json_object 
*%s, %s)\n" % \
+                (ty.namespace + "_" + ty.rawname,"o",ty.make_arg("p", 
passby=idl.PASS_BY_REFERENCE)))
+        f.write("{\n")
+        f.write(libxl_C_type_parse_json(ty, "o", "p"))
+        f.write("}\n")
+        f.write("\n")
+
+        f.write("int %s_from_json(libxl_ctx *ctx, %s, const char *s)\n" % 
(ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+        f.write("{\n")
+        if not isinstance(ty, idl.Enumeration):
+            f.write("    %s_init(p);\n" % ty.typename)
+        f.write(libxl_C_type_from_json(ty, "p", "s"))
+        f.write("}\n")
+        f.write("\n")
+
+    f.close()
diff --git a/tools/libs/light/idl.py b/tools/libs/light/idl.py
new file mode 100644
index 0000000000..d7367503b4
--- /dev/null
+++ b/tools/libs/light/idl.py
@@ -0,0 +1,377 @@
+from __future__ import print_function
+
+import sys
+
+PASS_BY_VALUE = 1
+PASS_BY_REFERENCE = 2
+
+DIR_NONE = 0
+DIR_IN   = 1
+DIR_OUT  = 2
+DIR_BOTH = 3
+
+_default_namespace = ""
+def namespace(s):
+    if type(s) != str:
+        raise TypeError("Require a string for the default namespace.")
+    global _default_namespace
+    _default_namespace = s
+
+def _get_default_namespace():
+    global _default_namespace
+    return _default_namespace
+
+_default_hidden = False
+def hidden(b):
+    global _default_hidden
+    _default_hidden = b
+
+def _get_default_hidden():
+    global _default_hidden
+    return _default_hidden
+
+class Type(object):
+    def __init__(self, typename, **kwargs):
+        self.namespace = kwargs.setdefault('namespace',
+                _get_default_namespace())
+        self._hidden = kwargs.setdefault('hidden', _get_default_hidden())
+        self.dir = kwargs.setdefault('dir', DIR_BOTH)
+        if self.dir not in [DIR_NONE, DIR_IN, DIR_OUT, DIR_BOTH]:
+            raise ValueError
+
+        self.passby = kwargs.setdefault('passby', PASS_BY_VALUE)
+        if self.passby not in [PASS_BY_VALUE, PASS_BY_REFERENCE]:
+            raise ValueError
+
+        self.private = kwargs.setdefault('private', False)
+
+        if typename is None: # Anonymous type
+            self.typename = None
+            self.rawname = None
+        elif self.namespace is None: # e.g. system provided types
+            self.typename = typename
+            self.rawname = typename
+        else:
+            self.typename = self.namespace + typename
+            self.rawname = typename
+
+        if self.typename is not None:
+            self.dispose_fn = kwargs.setdefault('dispose_fn', self.typename + 
"_dispose")
+        else:
+            self.dispose_fn = kwargs.setdefault('dispose_fn', None)
+
+        self.autogenerate_dispose_fn = 
kwargs.setdefault('autogenerate_dispose_fn', True)
+
+        if self.typename is not None:
+            self.copy_fn = kwargs.setdefault('copy_fn', self.typename + 
"_copy")
+        else:
+            self.copy_fn = kwargs.setdefault('copy_fn', None)
+
+        self.autogenerate_copy_fn = kwargs.setdefault('autogenerate_copy_fn', 
True)
+
+        self.init_fn = kwargs.setdefault('init_fn', None)
+        self.init_val = kwargs.setdefault('init_val', None)
+        self.autogenerate_init_fn = kwargs.setdefault('autogenerate_init_fn', 
False)
+
+        self.check_default_fn = kwargs.setdefault('check_default_fn', None)
+        self.copy_deprecated_fn = kwargs.setdefault('copy_deprecated_fn',
+                                                    None)
+
+        if self.typename is not None and not self.private:
+            self.json_gen_fn = kwargs.setdefault('json_gen_fn', self.typename 
+ "_gen_json")
+            self.json_parse_type = kwargs.setdefault('json_parse_type', 
"JSON_ANY")
+            if self.namespace is not None:
+                self.json_parse_fn = kwargs.setdefault('json_parse_fn',
+                                                       self.namespace + "_" + 
self.rawname  + "_parse_json")
+            else:
+                self.json_parse_fn = kwargs.setdefault('json_parse_fn',
+                                                       self.typename + 
"_parse_json")
+        else:
+            self.json_gen_fn = kwargs.setdefault('json_gen_fn', None)
+            self.json_parse_type = kwargs.setdefault('json_parse_type', None)
+            self.json_parse_fn = kwargs.setdefault('json_parse_fn', None)
+
+        self.autogenerate_json = kwargs.setdefault('autogenerate_json', True)
+
+    def marshal_in(self):
+        return self.dir in [DIR_IN, DIR_BOTH]
+    def marshal_out(self):
+        return self.dir in [DIR_OUT, DIR_BOTH]
+
+    def hidden(self):
+        if self._hidden:
+            return "_hidden "
+        else:
+            return ""
+
+    def make_arg(self, n, passby=None):
+        if passby is None: passby = self.passby
+
+        if passby == PASS_BY_REFERENCE:
+            return "%s *%s" % (self.typename, n)
+        else:
+            return "%s %s" % (self.typename, n)
+
+    def pass_arg(self, n, isref=None, passby=None):
+        if passby is None: passby = self.passby
+        if isref is None: isref = self.passby == PASS_BY_REFERENCE
+
+        if passby == PASS_BY_REFERENCE:
+            if isref:
+                return "%s" % (n)
+            else:
+                return "&%s" % (n)
+        else:
+            if isref:
+                return "*%s" % (n)
+            else:
+                return "%s" % (n)
+
+class Builtin(Type):
+    """Builtin type"""
+    def __init__(self, typename, **kwargs):
+        kwargs.setdefault('dispose_fn', None)
+        kwargs.setdefault('autogenerate_dispose_fn', False)
+        kwargs.setdefault('autogenerate_json', False)
+        Type.__init__(self, typename, **kwargs)
+
+class Number(Builtin):
+    def __init__(self, ctype, **kwargs):
+        kwargs.setdefault('namespace', None)
+        kwargs.setdefault('dispose_fn', None)
+        kwargs.setdefault('copy_fn', None)
+        kwargs.setdefault('signed', False)
+        kwargs.setdefault('json_gen_fn', "yajl_gen_integer")
+        kwargs.setdefault('json_parse_type', "JSON_INTEGER")
+        # json_parse_fn might be overriden on specific type
+        kwargs.setdefault('json_parse_fn', "libxl__int_parse_json")
+        self.signed = kwargs['signed']
+        Builtin.__init__(self, ctype, **kwargs)
+
+class UInt(Number):
+    def __init__(self, w, **kwargs):
+        kwargs.setdefault('namespace', None)
+        kwargs.setdefault('dispose_fn', None)
+        kwargs.setdefault('json_parse_fn', "libxl__uint%d_parse_json" % w)
+        kwargs.setdefault('copy_fn', None)
+        Number.__init__(self, "uint%d_t" % w, **kwargs)
+
+        self.width = w
+
+class EnumerationValue(object):
+    def __init__(self, enum, value, name, **kwargs):
+        self.enum = enum
+
+        self.valuename = str.upper(name)
+        self.rawname = str.upper(enum.rawname) + "_" + self.valuename
+        self.name = str.upper(enum.value_namespace) + self.rawname
+        self.value = value
+
+class Enumeration(Type):
+    def __init__(self, typename, values, **kwargs):
+        kwargs.setdefault('dispose_fn', None)
+        kwargs.setdefault('copy_fn', None)
+        kwargs.setdefault('json_parse_type', "JSON_STRING")
+        Type.__init__(self, typename, **kwargs)
+
+        self.value_namespace = kwargs.setdefault('value_namespace',
+            self.namespace)
+
+        self.values = []
+        for v in values:
+            # (value, name)
+            (num,name) = v
+            self.values.append(EnumerationValue(self, num, name,
+                                                typename=self.rawname))
+    def lookup(self, name):
+        for v in self.values:
+            if v.valuename == str.upper(name):
+                return v
+        return ValueError
+
+class Field(object):
+    """An element of an Aggregate type"""
+    def __init__(self, type, name, **kwargs):
+        self.type = type
+        self.name = name
+        self.const = kwargs.setdefault('const', False)
+        self.enumname = kwargs.setdefault('enumname', None)
+        self.init_val = kwargs.setdefault('init_val', None)
+        self.deprecated_by = kwargs.setdefault('deprecated_by', None)
+
+class Aggregate(Type):
+    """A type containing a collection of other types"""
+    def __init__(self, kind, typename, fields, **kwargs):
+        kwargs.setdefault('json_parse_type', "JSON_MAP")
+        Type.__init__(self, typename, **kwargs)
+
+        if self.typename is not None:
+            self.init_fn = kwargs.setdefault('init_fn', self.typename + 
"_init")
+        else:
+            self.init_fn = kwargs.setdefault('init_fn', None)
+
+        self.autogenerate_init_fn = kwargs.setdefault('autogenerate_init_fn', 
True)
+
+        self.kind = kind
+
+        self.fields = []
+        for f in fields:
+            # (name, type[, {kw args}])
+            if len(f) == 2:
+                n,t = f
+                kw = {}
+            elif len(f) == 3:
+                n,t,kw = f
+            else:
+                raise ValueError
+            if n is None:
+                raise ValueError
+            self.fields.append(Field(t,n,**kw))
+
+    # Returns a tuple (stem, field-expr)
+    #
+    # field-expr is a C expression for a field "f" within the struct
+    # "v".
+    #
+    # stem is the stem common to both "f" and any other sibbling field
+    # within the "v".
+    def member(self, v, f, isref):
+        if isref:
+            deref = v + "->"
+        else:
+            deref = v + "."
+
+        if f.name is None: # Anonymous
+            return (deref, deref)
+        else:
+            return (deref, deref + f.name)
+
+class Struct(Aggregate):
+    def __init__(self, name, fields, **kwargs):
+        kwargs.setdefault('passby', PASS_BY_REFERENCE)
+        Aggregate.__init__(self, "struct", name, fields, **kwargs)
+
+    def has_fields(self):
+        return len(self.fields) != 0
+
+class Union(Aggregate):
+    def __init__(self, name, fields, **kwargs):
+        # Generally speaking some intelligence is required to free a
+        # union therefore any specific instance of this class will
+        # need to provide an explicit destructor function.
+        kwargs.setdefault('passby', PASS_BY_REFERENCE)
+        kwargs.setdefault('dispose_fn', None)
+        Aggregate.__init__(self, "union", name, fields, **kwargs)
+
+class KeyedUnion(Aggregate):
+    """A union which is keyed of another variable in the parent structure"""
+    def __init__(self, name, keyvar_type, keyvar_name, fields, **kwargs):
+        Aggregate.__init__(self, "union", name, [], **kwargs)
+
+        if not isinstance(keyvar_type, Enumeration):
+            raise ValueError
+
+        kv_kwargs = dict([(x.lstrip('keyvar_'),y) for (x,y) in kwargs.items() 
if x.startswith('keyvar_')])
+        
+        self.keyvar = Field(keyvar_type, keyvar_name, **kv_kwargs)
+
+        for f in fields:
+            # (name, enum, type)
+            e, ty = f
+            ev = keyvar_type.lookup(e)
+            en = ev.name
+            self.fields.append(Field(ty, e, enumname=en))
+
+#
+# Standard Types
+#
+
+void = Builtin("void *", namespace = None)
+bool = Builtin("bool", namespace = None,
+               copy_fn=None,
+               json_gen_fn = "yajl_gen_bool",
+               json_parse_type = "JSON_BOOL",
+               json_parse_fn = "libxl__bool_parse_json",
+               autogenerate_json = False)
+
+size_t = Number("size_t", namespace = None)
+
+integer = Number("int", namespace = None, signed = True)
+
+uint8 = UInt(8)
+uint16 = UInt(16)
+uint32 = UInt(32)
+uint64 = UInt(64, json_gen_fn = "libxl__uint64_gen_json")
+
+string = Builtin("char *", namespace = None, copy_fn = "libxl_string_copy", 
dispose_fn = "free",
+                 json_gen_fn = "libxl__string_gen_json",
+                 json_parse_type = "JSON_STRING | JSON_NULL",
+                 json_parse_fn = "libxl__string_parse_json",
+                 autogenerate_json = False,
+                 check_default_fn="libxl__string_is_default")
+
+class Array(Type):
+    """An array of the same type"""
+    def __init__(self, elem_type, lenvar_name, **kwargs):
+        kwargs.setdefault('dispose_fn', 'free')
+        kwargs.setdefault('json_parse_type', 'JSON_ARRAY')
+        Type.__init__(self, namespace=elem_type.namespace, 
typename=elem_type.rawname + " *", **kwargs)
+
+        lv_kwargs = dict([(x.lstrip('lenvar_'),y) for (x,y) in kwargs.items() 
if x.startswith('lenvar_')])
+
+        self.lenvar = Field(integer, lenvar_name, **lv_kwargs)
+        self.elem_type = elem_type
+
+class OrderedDict(dict):
+    """A dictionary which remembers insertion order.
+
+       push to back on duplicate insertion"""
+
+    def __init__(self):
+        dict.__init__(self)
+        self.__ordered = []
+
+    def __setitem__(self, key, value):
+        try:
+            self.__ordered.remove(key)
+        except ValueError:
+            pass
+
+        self.__ordered.append(key)
+        dict.__setitem__(self, key, value)
+
+    def ordered_keys(self):
+        return self.__ordered
+    def ordered_values(self):
+        return [self[x] for x in self.__ordered]
+    def ordered_items(self):
+        return [(x,self[x]) for x in self.__ordered]
+
+def parse(f):
+    print("Parsing %s" % f, file=sys.stderr)
+
+    globs = {}
+    locs = OrderedDict()
+
+    for n,t in globals().items():
+        if isinstance(t, Type):
+            globs[n] = t
+        elif isinstance(t,type(object)) and issubclass(t, Type):
+            globs[n] = t
+        elif n in ['PASS_BY_REFERENCE', 'PASS_BY_VALUE',
+                   'DIR_NONE', 'DIR_IN', 'DIR_OUT', 'DIR_BOTH',
+                   'namespace', 'hidden']:
+            globs[n] = t
+
+    try:
+        exec(compile(open(f).read(), f, 'exec'), globs, locs)
+    except SyntaxError as e:
+        raise SyntaxError("Errors were found at line %d while processing 
%s:\n\t%s"
+                          % (e.lineno, f, e.text))
+
+    types = [t for t in locs.ordered_values() if isinstance(t,Type)]
+
+    builtins = [t for t in types if isinstance(t,Builtin)]
+    types = [t for t in types if not isinstance(t,Builtin)]
+
+    return (builtins,types)
diff --git a/tools/libs/light/idl.txt b/tools/libs/light/idl.txt
new file mode 100644
index 0000000000..7440fb3b76
--- /dev/null
+++ b/tools/libs/light/idl.txt
@@ -0,0 +1,214 @@
+libxl IDL
+---------
+
+Each type in the libxl interface is represented by an object of type
+idl.Type (or a subclass thereof). Every local variable defined by the
+.idl file must be an instance of idl.Type (e.g. you may not define
+Python functions or any other construct other than defining variables)
+
+The name of the type must be passed as the first argument to the
+constructor when defining a new type. The name given should not
+contain the initial namespace element (e.g. "libxl_"). See below for
+how to specify a namespace.
+
+The Type.typename contains the C name of the type _including_ the
+namespace element while Type.rawname is always set to the 'base' name
+of the type.
+
+The idl.Type base class has several other properties which apply to
+all types. The properties are set by passing a named parameter to the
+constructor.
+
+Type.namespace: (default: "libxl_")
+
+ The namespace in which the type resides. Usually this is "libxl_" but
+ system defined and builtin types may differ.
+
+ If the typename is not None then the namespace is prepended to the
+ type.
+ 
+Type.passby: (default: idl.PASS_BY_VALUE)
+
+ Defines the manner in which a type should be passed to C
+ functions. Valid values for this fields are:
+   idl.PASS_BY_VALUE
+   idl.PASS_BY_REFERENCE
+
+Type.dispose_fn: (default: typename + "_dispose" or None if type == None)
+
+ The name of the C function which will free all dynamically allocated
+ memory contained within this type (but not the type itself).
+
+Type.autogenerate_dispose_fn: (default: True)
+
+ Indicates if the above named Type.dispose_fn should be
+ autogenerated.
+
+Type.copy_fn: (default: typename + "_copy" or None if type == None)
+
+ The name of the C function which will deep copy all fields within
+ this type.
+
+Type.autogenerate_copy_fn: (default: True)
+
+ Indicates if the above named Type.copy_fn should be
+ autogenerated.
+
+Type.autogenerate_copy_fn
+
+Type.init_val: (default: None)
+
+ C expression for the value to initialise instances of this type to.
+
+ If present takes precendence over init_fn (see below).
+
+Type.init_fn: (default: typename + "_init" if dir in [IN, BOTH] and
+                        type != None)
+
+ The name of the C function which will initialist Type.
+
+Type.autogenerate_init_fn: (default: True if dir in [IN, BOTH])
+
+ Indicates if the above named Type.init_fn should be
+ autogenerated.
+
+Type.json_gen_fn: (default: typename + "_gen_json" or None if type == None)
+
+ The name of the C function which will generate a YAJL data structure
+ representing this type.
+
+Type.json_parse_fn: (default: typename + "_parse_json" or None if type == None)
+
+ The name of the C function which will parse a libxl JSON structure
+ representing this type to C type.
+
+Type.autogenerate_json: (default: True)
+
+ Indicates if the above named Type.json_*_fn should be autogenerated.
+
+Type.check_default_fn:
+
+ If it's set then calling this function shall return true if this type
+ has been set to default value (internal libxl implementation).
+
+ If this is not set, that means we can check the type against init_val
+ (if it has one) or zero to determine whether the value is default
+ value.
+
+Other simple type-Classes
+-------------------------
+
+idl.Builtin
+
+ Instances of this class represent types which are predefined within
+ the system.
+
+idl.UInt
+
+ Instances of this class represent the standard uint<N>_t types.
+
+ The <N> for a given instance must be passed to the constructor and is
+ then available in UInt.width
+
+Complex type-Classes
+--------------------
+
+idl.Enumeration
+
+  A class representing an enumeration (named integer values).
+  This class has one property besides the ones defined for the Type
+  class:
+
+  Enumeration.value_namespace: (default: namespace)
+
+    The namespace in which the values of the Enumeration (see below) reside.
+    This prefix is prepended to the name of the value.
+
+  The values are available in the list Enumeration.values. Each
+  element in the list is of type idl.EnumerationValue.
+
+  Each EnumerationValue has the following properties:
+
+    EnumerationValue.enum       Reference to containing Enumeration
+    EnumerationValue.name       The C name of this value, including
+                                    the namespace and typename of the
+                                    containing Enumeration (e.g.
+                                    "LIBXL_FOOENUM_VALUE")
+    EnumerationValue.rawname    The C name of this value, excluding
+                                    the namespace but including the
+                                    typename of the containing
+                                    Enumeration (e.g. "FOOENUM_VALUE")
+    EnumerationValue.valuename  The name of this value, excluding the
+                                    name of the containing Enumeration
+                                    and any namespace (e.g. "VALUE")
+    EnumerationValue.value      The integer value associated with this name.
+
+idl.Aggregate
+
+ Base class for type-Classes which contain a number of other types
+ (e.g. structs and unions).
+
+ The contained types are available in the list Aggregate.fields. Each
+ element in the list is of type idl.Field representing a member of the
+ aggregate.
+
+ Each field has the following properties:
+
+  Field.type     The type of the member (a idl.Type).
+  Field.name     The name of the member (can be None for anonymous
+                 fields).
+  Field.const    Boolean, true if the member is const.
+  Field.init_val The initialisation value for this field. Takes
+                 precendence over both Field.type.init_val and
+                 Field.type.init_fn.
+
+idl.Struct
+
+ A subclass of idl.Aggregate representing the C struct type.
+
+ Struct.kind == "struct"
+
+idl.Union
+
+ A subclass of idl.Aggregate representing the C union type.
+
+ Union.kind == "union"
+
+idl.KeyedUnion
+
+ A subclass of idl.Aggregate which represents the C union type
+ where the currently valid member of the union can be determined based
+ upon another member in the containing type. An idl.KeyedUnion must
+ always be a member of a containing idl.Aggregate type.
+
+ The KeyedUnion.keyvar contains an idl.Field, this is the member of
+ the containing type which determines the valid member of the
+ union. The idl.Field.type of the keyvar must be an Enumeration type.
+
+idl.Array
+
+  A class representing an array of similar elements. An idl.Array must
+  always be an idl.Field of a containing idl.Aggregate.
+
+  idl.Array.elem_type contains an idl.Type which is the type of each
+  element of the array.
+
+  idl.Array.len_var contains an idl.Field which is added to the parent
+  idl.Aggregate and will contain the length of the array. The field
+  MUST be named num_ARRAYNAME.
+
+Standard Types
+--------------
+
+Several standard types a predefined. They are
+
+void                    (void pointer type)
+bool
+size_t
+integer                 24 bit signed integer.
+
+uint{8,16,32,64}        uint{8,16,32,64}_t



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.