|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |