Ian Campbell
2011-Jun-23 16:20 UTC
[Xen-devel] [PATCH 00 of 10] libxl: IDL improvements and JSON generation
This patch series makes some improvements to the IDL language and generator and then goes on to implement JSON generation for IDL defined datatypes. _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:20 UTC
[Xen-devel] [PATCH 01 of 10] build: define "move-if-changed" make macro
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308843343 -3600
# Node ID edb8e868a964365a3ffe5c7d17467f9f08bf2803
# Parent 4fa92ff6c6156c2723d716a48c041dcb2c92938b
build: define "move-if-changed" make macro.
Use it to replace various places which (should) use the
if ! cmp -s ...; then mv ....; fi
pattern.
Also add an else clause to cleanup the unchanged temporary file.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r 4fa92ff6c615 -r edb8e868a964 Config.mk
--- a/Config.mk Thu Jun 23 16:35:43 2011 +0100
+++ b/Config.mk Thu Jun 23 16:35:43 2011 +0100
@@ -118,6 +118,16 @@ define buildmakevars2shellvars
export XEN_ROOT="$(XEN_ROOT)"
endef
+#
+# Compare $(1) and $(2) and replace $(2) with $(1) if they differ
+#
+# Typically $(1) is a newly generated file and $(2) is the target file
+# being regenerated. This prevents changing the timestamp of $(2) only
+# due to being auto regenereated with the same contents.
+define move-if-changed
+ if ! cmp -s $(1) $(2); then mv -f $(1) $(2); else rm -f $(1); fi
+endef
+
buildmakevars2file = $(eval $(call buildmakevars2file-closure,$(1)))
define buildmakevars2file-closure
.PHONY: genpath
@@ -133,7 +143,7 @@ define buildmakevars2file-closure
echo "XEN_CONFIG_DIR=\"$(XEN_CONFIG_DIR)\"" >>
$(1).tmp; \
echo "XEN_SCRIPT_DIR=\"$(XEN_SCRIPT_DIR)\"" >>
$(1).tmp; \
echo "XEN_LOCK_DIR=\"$(XEN_LOCK_DIR)\"" >> $(1).tmp;
\
- if ! cmp $(1).tmp $(1); then mv -f $(1).tmp $(1); fi
+ $(call move-if-changed,$(1).tmp,$(1))
endef
ifeq ($(debug),y)
diff -r 4fa92ff6c615 -r edb8e868a964 tools/libxl/Makefile
--- a/tools/libxl/Makefile Thu Jun 23 16:35:43 2011 +0100
+++ b/tools/libxl/Makefile Thu Jun 23 16:35:43 2011 +0100
@@ -74,7 +74,8 @@ genpath-target = $(call buildmakevars2fi
_libxl_paths.h: genpath
sed -e "s/\([^=]*\)=\(.*\)/#define \1 \2/g" $@.tmp >$@.2.tmp
- if ! cmp -s $@.2.tmp $@; then mv -f $@.2.tmp $@; fi
+ rm -f $@.tmp
+ $(call move-if-changed,$@.2.tmp,$@)
libxl_paths.c: _libxl_paths.h
@@ -84,8 +85,8 @@ libxl.h: _libxl_types.h
_libxl_%.h _libxl_%.c: libxl.idl gen%.py libxl%.py
$(PYTHON) gen$*.py libxl.idl __libxl_$*.h __libxl_$*.c
- mv __libxl_$*.h _libxl_$*.h
- mv __libxl_$*.c _libxl_$*.c
+ $(call move-if-changed,__libxl_$*.h,_libxl_$*.h)
+ $(call move-if-changed,__libxl_$*.c,_libxl_$*.c)
libxenlight.so: libxenlight.so.$(MAJOR)
ln -sf $< $@
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:20 UTC
[Xen-devel] [PATCH 02 of 10] libxl: IDL: s/anonynous/anonymous/
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308845904 -3600
# Node ID ba383ce75f8bba3e08a84c660c8383c26d23aaa8
# Parent edb8e868a964365a3ffe5c7d17467f9f08bf2803
libxl: IDL: s/anonynous/anonymous/
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r edb8e868a964 -r ba383ce75f8b tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py Thu Jun 23 16:35:43 2011 +0100
+++ b/tools/libxl/gentypes.py Thu Jun 23 17:18:24 2011 +0100
@@ -101,7 +101,7 @@ def libxl_C_type_destroy(ty, v, indent elif
isinstance(ty, libxltypes.Struct) and (parent is None or ty.destructor_fn is
None):
for f in [f for f in ty.fields if not f.const]:
- if f.name is None: # Anonynous struct
+ if f.name is None: # Anonymous struct
s += libxl_C_type_destroy(f.type, deref, "", deref)
else:
s += libxl_C_type_destroy(f.type, deref + f.name, "",
deref)
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:20 UTC
[Xen-devel] [PATCH 03 of 10] libxl: IDL: handle generation of pass-by-reference arguments
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308845917 -3600
# Node ID 4186a6ca6799797e24fafa5fe39e55b474b86bf0
# Parent ba383ce75f8bba3e08a84c660c8383c26d23aaa8
libxl: IDL: handle generation of pass-by-reference arguments.
Up until now everything with a destructor function happened to be
pass-by-reference so the current code worked but this will not be the case for
*_to_string and *_to_json. Put some infrastructure in place and use it.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r ba383ce75f8b -r 4186a6ca6799 tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py Thu Jun 23 17:18:24 2011 +0100
+++ b/tools/libxl/gentypes.py Thu Jun 23 17:18:37 2011 +0100
@@ -178,10 +178,10 @@ if __name__ == ''__main__'':
for ty in types:
f.write(libxl_C_type_define(ty) + ";\n")
if ty.destructor_fn is not None:
- f.write("void %s(%s *p);\n" % (ty.destructor_fn,
ty.typename))
+ f.write("void %s(%s);\n" % (ty.destructor_fn,
ty.make_arg("p")))
if isinstance(ty, libxltypes.Enumeration):
- f.write("const char *%s_to_string(%s e);\n" %
(ty.typename, ty.typename))
- f.write("int %s_from_string(const char *s, %s *e);\n" %
(ty.typename, ty.typename))
+ f.write("const char *%s_to_string(%s);\n" % (ty.typename,
ty.make_arg("p")))
+ f.write("int %s_from_string(const char *s, %s);\n" %
(ty.typename, ty.make_arg("e", passby=libxltypes.PASS_BY_REFERENCE)))
f.write("extern libxl_enum_string_table
%s_string_table[];\n" % (ty.typename))
f.write("\n")
@@ -213,7 +213,7 @@ if __name__ == ''__main__'':
""" % " ".join(sys.argv))
for ty in [t for t in types if t.destructor_fn is not None and
t.autogenerate_destructor]:
- f.write("void %s(%s *p)\n" % (ty.destructor_fn, ty.typename))
+ f.write("void %s(%s)\n" % (ty.destructor_fn,
ty.make_arg("p")))
f.write("{\n")
f.write(libxl_C_type_destroy(ty, "p"))
f.write(" memset(p, LIBXL_DTOR_POISON, sizeof(*p));\n")
diff -r ba383ce75f8b -r 4186a6ca6799 tools/libxl/libxl.idl
--- a/tools/libxl/libxl.idl Thu Jun 23 17:18:24 2011 +0100
+++ b/tools/libxl/libxl.idl Thu Jun 23 17:18:37 2011 +0100
@@ -4,8 +4,8 @@
#
libxl_domid = Builtin("domid")
-libxl_uuid = Builtin("uuid")
-libxl_mac = Builtin("mac")
+libxl_uuid = Builtin("uuid", passby=PASS_BY_REFERENCE)
+libxl_mac = Builtin("mac", passby=PASS_BY_REFERENCE)
libxl_cpumap = Builtin("cpumap",
destructor_fn="libxl_cpumap_destroy", passby=PASS_BY_REFERENCE)
libxl_cpuarray = Builtin("cpuarray",
destructor_fn="libxl_cpuarray_destroy", passby=PASS_BY_REFERENCE)
libxl_cpuid_policy_list = Builtin("cpuid_policy_list",
destructor_fn="libxl_cpuid_destroy", passby=PASS_BY_REFERENCE)
diff -r ba383ce75f8b -r 4186a6ca6799 tools/libxl/libxltypes.py
--- a/tools/libxl/libxltypes.py Thu Jun 23 17:18:24 2011 +0100
+++ b/tools/libxl/libxltypes.py Thu Jun 23 17:18:37 2011 +0100
@@ -42,6 +42,14 @@ class Type(object):
def marshal_out(self):
return self.dir in [DIR_OUT, DIR_BOTH]
+ 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)
+
class Builtin(Type):
"""Builtin type"""
def __init__(self, typename, **kwargs):
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:20 UTC
[Xen-devel] [PATCH 04 of 10] libxl: IDL: refactor code to massage a type into a function argument
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308845927 -3600
# Node ID 34279f2359cbaaef7c16287e023cae1b023f02d3
# Parent 4186a6ca6799797e24fafa5fe39e55b474b86bf0
libxl: IDL: refactor code to massage a type into a function argument
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r 4186a6ca6799 -r 34279f2359cb tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py Thu Jun 23 17:18:37 2011 +0100
+++ b/tools/libxl/gentypes.py Thu Jun 23 17:18:47 2011 +0100
@@ -84,11 +84,6 @@ def libxl_C_type_destroy(ty, v, indent else:
deref = v + "."
- if ty.passby == libxltypes.PASS_BY_REFERENCE and parent is not None:
- makeref = "&"
- else:
- makeref = ""
-
s = ""
if isinstance(ty, libxltypes.KeyedUnion):
if parent is None:
@@ -107,7 +102,7 @@ def libxl_C_type_destroy(ty, v, indent s +=
libxl_C_type_destroy(f.type, deref + f.name, "", deref)
else:
if ty.destructor_fn is not None:
- s += "%s(%s);\n" % (ty.destructor_fn, makeref + v)
+ s += "%s(%s);\n" % (ty.destructor_fn, ty.pass_arg(v,
parent is None))
if s != "":
s = indent + s
diff -r 4186a6ca6799 -r 34279f2359cb tools/libxl/libxltypes.py
--- a/tools/libxl/libxltypes.py Thu Jun 23 17:18:37 2011 +0100
+++ b/tools/libxl/libxltypes.py Thu Jun 23 17:18:47 2011 +0100
@@ -50,6 +50,21 @@ class Type(object):
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):
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:20 UTC
[Xen-devel] [PATCH 05 of 10] libxl: IDL: remove libxl_C_type_of
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308845928 -3600
# Node ID 2b91546fb417458d3fa29da85aed44bddb91854f
# Parent 34279f2359cbaaef7c16287e023cae1b023f02d3
libxl: IDL: remove libxl_C_type_of
It''s not really adding much...
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r 34279f2359cb -r 2b91546fb417 tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py Thu Jun 23 17:18:47 2011 +0100
+++ b/tools/libxl/gentypes.py Thu Jun 23 17:18:48 2011 +0100
@@ -17,10 +17,7 @@ def format_comment(level, comment):
s += "%s */" % indent
s += "\n"
return s
-
-def libxl_C_type_of(ty):
- return ty.typename
-
+
def libxl_C_instance_of(ty, instancename):
if isinstance(ty, libxltypes.Aggregate) and ty.typename is None:
if instancename is None:
@@ -28,7 +25,7 @@ def libxl_C_instance_of(ty, instancename
else:
return libxl_C_type_define(ty) + " " + instancename
else:
- return libxl_C_type_of(ty) + " " + instancename
+ return ty.typename + " " + instancename
def libxl_C_type_define(ty, indent = ""):
s = ""
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:20 UTC
[Xen-devel] [PATCH 06 of 10] libxl: IDL: add helper to generate references to Aggregate type members
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308845933 -3600
# Node ID 273be439b67afbeefdf00e68efb5b09412a25c82
# Parent 2b91546fb417458d3fa29da85aed44bddb91854f
libxl: IDL: add helper to generate references to Aggregate type members.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r 2b91546fb417 -r 273be439b67a tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py Thu Jun 23 17:18:48 2011 +0100
+++ b/tools/libxl/gentypes.py Thu Jun 23 17:18:53 2011 +0100
@@ -76,27 +76,21 @@ def libxl_C_type_define(ty, indent = "")
return s.replace("\n", "\n%s" % indent)
def libxl_C_type_destroy(ty, v, indent = " ", parent = None):
- if parent is None:
- deref = v + "->"
- else:
- deref = v + "."
s = ""
if isinstance(ty, libxltypes.KeyedUnion):
if parent is None:
raise Exception("KeyedUnion type must have a parent")
for f in ty.fields:
+ (nparent,fexpr) = ty.member(v, f, parent is None)
keyvar_expr = f.keyvar_expr % (parent + ty.keyvar_name)
s += "if (" + keyvar_expr + ") {\n"
- s += libxl_C_type_destroy(f.type, deref + f.name, indent + "
", deref)
+ s += libxl_C_type_destroy(f.type, fexpr, indent + " ",
nparent)
s += "}\n"
elif isinstance(ty, libxltypes.Struct) and (parent is None or
ty.destructor_fn is None):
for f in [f for f in ty.fields if not f.const]:
-
- if f.name is None: # Anonymous struct
- s += libxl_C_type_destroy(f.type, deref, "", deref)
- else:
- s += libxl_C_type_destroy(f.type, deref + f.name, "",
deref)
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ s += libxl_C_type_destroy(f.type, fexpr, "", nparent)
else:
if ty.destructor_fn is not None:
s += "%s(%s);\n" % (ty.destructor_fn, ty.pass_arg(v,
parent is None))
diff -r 2b91546fb417 -r 273be439b67a tools/libxl/libxltypes.py
--- a/tools/libxl/libxltypes.py Thu Jun 23 17:18:48 2011 +0100
+++ b/tools/libxl/libxltypes.py Thu Jun 23 17:18:53 2011 +0100
@@ -147,6 +147,24 @@ class Aggregate(Type):
n,t,const,comment = f
self.fields.append(Field(t,n,const=const,comment=comment))
+ # 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)
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:20 UTC
[Xen-devel] [PATCH 07 of 10] libxl: IDL: bring command line handling in genwrap.py into one place
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308845948 -3600
# Node ID 956eef6b25e72a6fb76c43813c4367c29a9860cb
# Parent 273be439b67afbeefdf00e68efb5b09412a25c82
libxl: IDL: bring command line handling in genwrap.py into one place.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r 273be439b67a -r 956eef6b25e7 tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py Thu Jun 23 17:18:53 2011 +0100
+++ b/tools/libxl/gentypes.py Thu Jun 23 17:19:08 2011 +0100
@@ -137,14 +137,14 @@ def libxl_C_enum_from_string(ty, str, e,
if __name__ == ''__main__'':
- if len(sys.argv) < 4:
+ if len(sys.argv) != 4:
print >>sys.stderr, "Usage: gentypes.py <idl>
<header> <implementation>"
sys.exit(1)
- idl = sys.argv[1]
+ (_, idl, header, impl) = sys.argv
+
(_,types) = libxltypes.parse(idl)
- header = sys.argv[2]
print "outputting libxl type definitions to %s" % header
f = open(header, "w")
@@ -174,7 +174,6 @@ if __name__ == ''__main__'':
f.write("""#endif /* __LIBXL_TYPES_H */\n""")
f.close()
- impl = sys.argv[3]
print "outputting libxl type implementations to %s" % impl
f = open(impl, "w")
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:20 UTC
[Xen-devel] [PATCH 08 of 10] libxl: rename testenum->testidl
# HG changeset patch # User Ian Campbell <ian.campbell@citrix.com> # Date 1308845949 -3600 # Node ID dea9208b98db2b1b301a17b13d21558fa0a0edc7 # Parent 956eef6b25e72a6fb76c43813c4367c29a9860cb libxl: rename testenum->testidl I plan to add some non-Enumeration tests. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> diff -r 956eef6b25e7 -r dea9208b98db .hgignore --- a/.hgignore Thu Jun 23 17:19:08 2011 +0100 +++ b/.hgignore Thu Jun 23 17:19:09 2011 +0100 @@ -187,8 +187,8 @@ ^tools/libxl/_.*\.c$ ^tools/libxl/libxlu_cfg_y\.output$ ^tools/libxl/xl$ -^tools/libxl/testenum$ -^tools/libxl/testenum\.c$ +^tools/libxl/testidl$ +^tools/libxl/testidl\.c$ ^tools/libaio/src/.*\.ol$ ^tools/libaio/src/.*\.os$ ^tools/misc/cpuperf/cpuperf-perfcntr$ diff -r 956eef6b25e7 -r dea9208b98db tools/libxl/Makefile --- a/tools/libxl/Makefile Thu Jun 23 17:19:08 2011 +0100 +++ b/tools/libxl/Makefile Thu Jun 23 17:19:09 2011 +0100 @@ -44,16 +44,16 @@ AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c LIBXLU_OBJS = libxlu_cfg_y.o libxlu_cfg_l.o libxlu_cfg.o $(LIBXLU_OBJS): CFLAGS += $(CFLAGS_libxenctrl) # For xentoollog.h -CLIENTS = xl testenum +CLIENTS = xl testidl XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o $(XL_OBJS): CFLAGS += $(CFLAGS_libxenctrl) # For xentoollog.h $(XL_OBJS): CFLAGS += $(CFLAGS_libxenlight) -testenum.o: CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenlight) -testenum.c: libxl.idl gentest.py - $(PYTHON) gentest.py libxl.idl testenum.c.new - mv testenum.c.new testenum.c +testidl.o: CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenlight) +testidl.c: libxl.idl gentest.py + $(PYTHON) gentest.py libxl.idl testidl.c.new + mv testidl.c.new testidl.c .PHONY: all all: $(CLIENTS) libxenlight.so libxenlight.a libxlutil.so libxlutil.a \ @@ -115,8 +115,8 @@ libxlutil.a: $(LIBXLU_OBJS) xl: $(XL_OBJS) libxlutil.so libxenlight.so $(CC) $(LDFLAGS) -o $@ $(XL_OBJS) libxlutil.so $(LDLIBS_libxenlight) $(LDLIBS_libxenctrl) -testenum: testenum.o libxlutil.so libxenlight.so - $(CC) $(LDFLAGS) -o $@ testenum.o libxlutil.so $(LDLIBS_libxenlight) $(LDLIBS_libxenctrl) +testidl: testidl.o libxlutil.so libxenlight.so + $(CC) $(LDFLAGS) -o $@ testidl.o libxlutil.so $(LDLIBS_libxenlight) $(LDLIBS_libxenctrl) .PHONY: install install: all _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:21 UTC
[Xen-devel] [PATCH 09 of 10] libxl: add LIBXL_MAC_{FMT, FMTLEN, BYTES}
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308845956 -3600
# Node ID 4e751a05df3c323aea8fb291961a21d13de4afda
# Parent dea9208b98db2b1b301a17b13d21558fa0a0edc7
libxl: add LIBXL_MAC_{FMT,FMTLEN,BYTES}
Modelled after LIBXL_UUID_... (where I also add FMTLEN).
signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r dea9208b98db -r 4e751a05df3c tools/libxl/libxl.c
--- a/tools/libxl/libxl.c Thu Jun 23 17:19:09 2011 +0100
+++ b/tools/libxl/libxl.c Thu Jun 23 17:19:16 2011 +0100
@@ -1284,9 +1284,8 @@ int libxl_device_nic_add(libxl_ctx *ctx,
nic->script));
}
flexarray_append(back, "mac");
- flexarray_append(back, libxl__sprintf(&gc,
"%02x:%02x:%02x:%02x:%02x:%02x",
- nic->mac[0],
nic->mac[1], nic->mac[2],
- nic->mac[3],
nic->mac[4], nic->mac[5]));
+ flexarray_append(back,libxl__sprintf(&gc,
+ LIBXL_MAC_FMT,
LIBXL_MAC_BYTES(nic->mac)));
if (nic->ip) {
flexarray_append(back, "ip");
flexarray_append(back, libxl__strdup(&gc, nic->ip));
@@ -1304,9 +1303,8 @@ int libxl_device_nic_add(libxl_ctx *ctx,
flexarray_append(front, "handle");
flexarray_append(front, libxl__sprintf(&gc, "%d",
nic->devid));
flexarray_append(front, "mac");
- flexarray_append(front, libxl__sprintf(&gc,
"%02x:%02x:%02x:%02x:%02x:%02x",
- nic->mac[0],
nic->mac[1], nic->mac[2],
- nic->mac[3],
nic->mac[4], nic->mac[5]));
+ flexarray_append(front, libxl__sprintf(&gc,
+ LIBXL_MAC_FMT,
LIBXL_MAC_BYTES(nic->mac)));
libxl__device_generic_add(&gc, &device,
libxl__xs_kvs_of_flexarray(&gc, back,
back->count),
libxl__xs_kvs_of_flexarray(&gc, front,
front->count));
diff -r dea9208b98db -r 4e751a05df3c tools/libxl/libxl.h
--- a/tools/libxl/libxl.h Thu Jun 23 17:19:09 2011 +0100
+++ b/tools/libxl/libxl.h Thu Jun 23 17:19:16 2011 +0100
@@ -139,6 +139,9 @@
#include <libxl_uuid.h>
typedef uint8_t libxl_mac[6];
+#define LIBXL_MAC_FMT "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx"
+#define LIBXL_MAC_FMTLEN ((2*6)+5) /* 6 hex bytes plus 5 colons */
+#define LIBXL_MAC_BYTES(mac) mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
typedef char **libxl_string_list;
void libxl_string_list_destroy(libxl_string_list *sl);
diff -r dea9208b98db -r 4e751a05df3c tools/libxl/libxl_dm.c
--- a/tools/libxl/libxl_dm.c Thu Jun 23 17:19:09 2011 +0100
+++ b/tools/libxl/libxl_dm.c Thu Jun 23 17:19:16 2011 +0100
@@ -177,9 +177,8 @@ static char ** libxl__build_device_model
}
for (i = 0; i < num_vifs; i++) {
if (vifs[i].nictype == LIBXL_NIC_TYPE_IOEMU) {
- char *smac = libxl__sprintf(gc,
"%02x:%02x:%02x:%02x:%02x:%02x",
- vifs[i].mac[0], vifs[i].mac[1],
vifs[i].mac[2],
- vifs[i].mac[3], vifs[i].mac[4],
vifs[i].mac[5]);
+ char *smac = libxl__sprintf(gc,
+ LIBXL_MAC_FMT,
LIBXL_MAC_BYTES(vifs[i].mac));
char *ifname;
if (!vifs[i].ifname)
ifname = libxl__sprintf(gc, "tap%d.%d",
info->domid, vifs[i].devid);
@@ -368,9 +367,8 @@ static char ** libxl__build_device_model
}
for (i = 0; i < num_vifs; i++) {
if (vifs[i].nictype == LIBXL_NIC_TYPE_IOEMU) {
- char *smac = libxl__sprintf(gc,
"%02x:%02x:%02x:%02x:%02x:%02x",
- vifs[i].mac[0], vifs[i].mac[1],
vifs[i].mac[2],
- vifs[i].mac[3], vifs[i].mac[4],
vifs[i].mac[5]);
+ char *smac = libxl__sprintf(gc,
+ LIBXL_MAC_FMT, LIBXL_MAC_BYTES(vifs[i].mac));
char *ifname;
if (!vifs[i].ifname) {
ifname = libxl__sprintf(gc, "tap%d.%d",
info->domid, vifs[i].devid);
diff -r dea9208b98db -r 4e751a05df3c tools/libxl/libxl_uuid.h
--- a/tools/libxl/libxl_uuid.h Thu Jun 23 17:19:09 2011 +0100
+++ b/tools/libxl/libxl_uuid.h Thu Jun 23 17:19:16 2011 +0100
@@ -16,6 +16,7 @@
#define __LIBXL_UUID_H__
#define LIBXL_UUID_FMT
"%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+#define LIBXL_UUID_FMTLEN ((2*16)+4) /* 16 hex bytes plus 4 hypens */
#define LIBXL__UUID_BYTES(uuid) uuid[0], uuid[1], uuid[2], uuid[3], \
uuid[4], uuid[5], uuid[6], uuid[7], \
uuid[8], uuid[9], uuid[10], uuid[11], \
diff -r dea9208b98db -r 4e751a05df3c tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c Thu Jun 23 17:19:09 2011 +0100
+++ b/tools/libxl/xl_cmdimpl.c Thu Jun 23 17:19:16 2011 +0100
@@ -4094,9 +4094,7 @@ int main_networklist(int argc, char **ar
/* Idx BE */
printf("%-3d %-2d ", nics[i].devid, nics[i].backend_id);
/* MAC */
- printf("%02x:%02x:%02x:%02x:%02x:%02x ",
- nics[i].mac[0], nics[i].mac[1], nics[i].mac[2],
- nics[i].mac[3], nics[i].mac[4], nics[i].mac[5]);
+ printf(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nics[i].mac));
/* Hdl Sta evch txr/rxr BE-path */
printf("%6d %5d %6d %5d/%-11d %-30s\n",
nics[i].devid, nics[i].state, nics[i].evtch,
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:21 UTC
[Xen-devel] [PATCH 10 of 10] libxl: IDL: autogenerate functions to produce JSON from libxl data structures
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308845967 -3600
# Node ID f004439ac18259226136d68d533407661dd55232
# Parent 4e751a05df3c323aea8fb291961a21d13de4afda
libxl: IDL: autogenerate functions to produce JSON from libxl data structures.
Two functions are provided. TYPE_gen_json exposes an interface which is
compatible with the YAGL generator infrastructure. TYPE_to_string uses this to
produce a pretty printed string.
The TYPE_gen_json functions are defined in a new header libxl_json.h which is
not exposed via libxl.h due to the use of YAGL datatypes to avoid poluting the
namespace us libxl users which don''t use the library themselves. If a
libxl
user is interested in integrating at the YAGL level then it should #include
this file itself.
Also update testidl to generate a random version of each IDL datastructure and
convert it to JSON. Unfortunately this requires a libxl_ctx and therefore the
test must be run on a Xen system now.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/Makefile
--- a/tools/libxl/Makefile Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/Makefile Thu Jun 23 17:19:27 2011 +0100
@@ -32,9 +32,12 @@ endif
LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o
LIBXL_OBJS-$(CONFIG_IA64) += libxl_nocpuid.o
+LIBXL_LIBS += -lyajl
+
LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o \
- libxl_internal.o libxl_utils.o libxl_uuid.o $(LIBXL_OBJS-y)
+ libxl_internal.o libxl_utils.o libxl_uuid.o libxl_json.o \
+ $(LIBXL_OBJS-y)
LIBXL_OBJS += _libxl_types.o libxl_flask.o
$(LIBXL_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
$(CFLAGS_libxenstore) $(CFLAGS_libblktapctl)
@@ -81,11 +84,14 @@ libxl_paths.c: _libxl_paths.h
libxl.h: _libxl_types.h
+libxl_json.h: _libxl_types_json.h
+
$(LIBXL_OBJS) $(LIBXLU_OBJS) $(XL_OBJS): libxl.h
-_libxl_%.h _libxl_%.c: libxl.idl gen%.py libxl%.py
- $(PYTHON) gen$*.py libxl.idl __libxl_$*.h __libxl_$*.c
+_libxl_%.h _libxl_%_json.h _libxl_%.c: libxl.idl gen%.py libxltypes.py
+ $(PYTHON) gen$*.py libxl.idl __libxl_$*.h __libxl_$*_json.h __libxl_$*.c
$(call move-if-changed,__libxl_$*.h,_libxl_$*.h)
+ $(call move-if-changed,__libxl_$*_json.h,_libxl_$*_json.h)
$(call move-if-changed,__libxl_$*.c,_libxl_$*.c)
libxenlight.so: libxenlight.so.$(MAJOR)
@@ -133,7 +139,7 @@ install: all
ln -sf libxlutil.so.$(XLUMAJOR).$(XLUMINOR)
$(DESTDIR)$(LIBDIR)/libxlutil.so.$(XLUMAJOR)
ln -sf libxlutil.so.$(XLUMAJOR) $(DESTDIR)$(LIBDIR)/libxlutil.so
$(INSTALL_DATA) libxlutil.a $(DESTDIR)$(LIBDIR)
- $(INSTALL_DATA) libxl.h _libxl_types.h libxl_utils.h libxl_uuid.h
$(DESTDIR)$(INCLUDEDIR)
+ $(INSTALL_DATA) libxl.h libxl_json.h _libxl_types.h _libxl_types_json.h
libxl_utils.h libxl_uuid.h $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_DATA) bash-completion $(DESTDIR)$(BASH_COMPLETION_DIR)/xl.sh
.PHONY: clean
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/gentest.py
--- a/tools/libxl/gentest.py Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/gentest.py Thu Jun 23 17:19:27 2011 +0100
@@ -5,6 +5,7 @@ import re
import random
import libxltypes
+
def randomize_char(c):
if random.random() < 0.5:
return str.lower(c)
@@ -15,6 +16,49 @@ 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_cpumap", "libxl_key_value_list",
+ "libxl_cpuid_policy_list",
"libxl_file_reference",
+ "libxl_string_list", "libxl_cpuarray"]
+
+def gen_rand_init(ty, v, indent = " ", parent = None):
+ s = ""
+ if isinstance(ty, libxltypes.Enumeration):
+ s += "%s = %s;\n" % (ty.pass_arg(v, parent is None),
randomize_enum(ty))
+ elif isinstance(ty, libxltypes.KeyedUnion):
+ if parent is None:
+ raise Exception("KeyedUnion type must have a parent")
+ for f in ty.fields:
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ keyvar_expr = f.keyvar_expr % (parent + ty.keyvar_name)
+ s += "if (" + keyvar_expr + ") {\n"
+ s += gen_rand_init(f.type, fexpr, indent + " ",
nparent)
+ s += "}\n"
+ elif isinstance(ty, libxltypes.Struct) and (parent is None or ty.json_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=libxltypes.PASS_BY_REFERENCE))
+ elif ty.typename in ["libxl_uuid", "libxl_mac",
"libxl_hwcap"]:
+ s += "rand_bytes((uint8_t *)%s, sizeof(*%s));\n" % (v,v)
+ elif ty.typename in ["libxl_domid"] or isinstance(ty,
libxltypes.Number):
+ s += "%s = 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 = rand() %% 2;\n" % v
+ elif ty.typename in ["char *"]:
+ s += "%s = rand_str();\n" % v
+ 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 >>sys.stderr, "Usage: gentest.py <idl>
<implementation>"
@@ -23,23 +67,191 @@ if __name__ == ''__main__'':
random.seed()
idl = sys.argv[1]
- (_,types) = libxltypes.parse(idl)
+ (builtins,types) = libxltypes.parse(idl)
impl = sys.argv[2]
f = open(impl, "w")
f.write("""
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#include \"libxl.h\"
+#include \"libxl_utils.h\"
+static char *rand_str(void)
+{
+ int i, sz = rand() % 32;
+ char *s = malloc(sz+1);
+ for (i=0; i<sz; i++)
+ s[i] = ''a'' + (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] = rand() % 256;
+ //p[i] = i;
+}
+
+static void libxl_cpumap_rand_init(libxl_cpumap *cpumap)
+{
+ int i;
+ cpumap->size = rand() % 16;
+ cpumap->map = calloc(cpumap->size, sizeof(*cpumap->map));
+ libxl_for_each_cpu(i, *cpumap) {
+ if (rand() % 2)
+ libxl_cpumap_set(cpumap, i);
+ else
+ libxl_cpumap_reset(cpumap, i);
+ }
+}
+
+static void libxl_key_value_list_rand_init(libxl_key_value_list *pkvl)
+{
+ int i, nr_kvp = rand() % 16;
+ libxl_key_value_list kvl = calloc(nr_kvp+1, 2*sizeof(char *));
+
+ for (i = 0; i<2*nr_kvp; i += 2) {
+ kvl[i] = rand_str();
+ if (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 = 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 = rand() % nr_options;
+ int val = 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_file_reference_rand_init(libxl_file_reference *p)
+{
+ memset(p, 0, sizeof(*p));
+ if (rand() % 8)
+ p->path = rand_str();
+}
+
+static void libxl_string_list_rand_init(libxl_string_list *p)
+{
+ int i, nr = rand() % 16;
+ libxl_string_list l = calloc(nr+1, sizeof(char *));
+
+ for (i = 0; i<nr; i++) {
+ l[i] = rand_str();
+ }
+ l[i] = NULL;
+ *p = l;
+}
+
+static void libxl_cpuarray_rand_init(libxl_cpuarray *p)
+{
+ int i;
+ /* Up to 16 VCPUs on 32 PCPUS */
+ p->entries = rand() % 16;
+ p->array = calloc(p->entries, sizeof(*p->array));
+ for (i = 0; i < p->entries; i++) {
+ int r = rand() % 32*1.5; /* 2:1 valid:invalid */
+ if (r >= 32)
+ p->array[i] = LIBXL_CPUARRAY_INVALID_ENTRY;
+ else
+ p->array[i] = r;
+ }
+}
+""")
+ for ty in builtins + types:
+ if ty.typename not in handcoded:
+ f.write("static void %s_rand_init(%s);\n" % (ty.typename,
ty.make_arg("p", passby=libxltypes.PASS_BY_REFERENCE)))
+ f.write("static void %s_rand_init(%s)\n" % (ty.typename,
ty.make_arg("p", passby=libxltypes.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 [t for t in types if isinstance(t,libxltypes.Enumeration)]:
+ for ty in types:
f.write(" %s %s_val;\n" % (ty.typename, ty.typename))
- f.write(" int rc;\n")
- f.write("\n")
-
+ f.write("""
+ int rc;
+ char *s;
+ 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, (xentoollog_logger*)logger)) {
+ fprintf(stderr, "cannot init xl context\\n");
+ exit(1);
+ }
+""")
+ f.write(" printf(\"Testing TYPE_to_json()\\n\");\n")
+ f.write(" printf(\"----------------------\\n\");\n")
+ f.write(" printf(\"\\n\");\n")
+ for ty in [t for t in types if t.json_fn is not None]:
+ arg = ty.typename + "_val"
+ f.write(" %s_rand_init(%s);\n" % (ty.typename,
ty.pass_arg(arg, isref=False, passby=libxltypes.PASS_BY_REFERENCE)))
+ 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(" free(s);\n")
+ if ty.destructor_fn is not None:
+ f.write(" %s(&%s_val);\n" % (ty.destructor_fn,
ty.typename))
+ f.write("\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,libxltypes.Enumeration)]:
f.write(" printf(\"%s -- to string:\\n\");\n" %
(ty.typename))
for v in ty.values:
@@ -47,6 +259,12 @@ int main(int argc, char **argv)
(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(" printf(\"\\t%s = %%d = %%s\", %s,
%s_to_json(ctx, %s));\n" %\
+ (v.valuename, v.name, ty.typename, v.name))
+ 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)
@@ -58,6 +276,11 @@ int main(int argc, char **argv)
(v, n, ty.typename))
f.write("\n")
- f.write("""return 0;
+ f.write("""
+
+ libxl_ctx_free(ctx);
+ xtl_logger_destroy((xentoollog_logger*)logger);
+
+ return 0;
}
""")
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/gentypes.py Thu Jun 23 17:19:27 2011 +0100
@@ -29,7 +29,6 @@ def libxl_C_instance_of(ty, instancename
def libxl_C_type_define(ty, indent = ""):
s = ""
-
if isinstance(ty, libxltypes.Enumeration):
if ty.comment is not None:
s += format_comment(0, ty.comment)
@@ -76,7 +75,6 @@ def libxl_C_type_define(ty, indent = "")
return s.replace("\n", "\n%s" % indent)
def libxl_C_type_destroy(ty, v, indent = " ", parent = None):
-
s = ""
if isinstance(ty, libxltypes.KeyedUnion):
if parent is None:
@@ -99,6 +97,65 @@ def libxl_C_type_destroy(ty, v, indent s = indent +
s
return s.replace("\n", "\n%s" % indent).rstrip(indent)
+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, libxltypes.Enumeration):
+ s += "{\n"
+ s += " const char *se = %s_to_string(%s);\n" %
(ty.typename, ty.pass_arg(v, parent is None))
+ s += " if (se)\n"
+ s += " s = yajl_gen_string(hand, (const unsigned char *)se,
strlen(se));\n"
+ s += " else\n"
+ s += " s = yajl_gen_null(hand);\n"
+ s += " if (s != yajl_gen_status_ok)\n"
+ s += " goto out;\n"
+ s += "}\n"
+ elif isinstance(ty, libxltypes.KeyedUnion):
+ if parent is None:
+ raise Exception("KeyedUnion type must have a parent")
+ for f in ty.fields:
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ keyvar_expr = f.keyvar_expr % (parent + ty.keyvar_name)
+ s += "if (" + keyvar_expr + ") {\n"
+ s += libxl_C_type_gen_json(f.type, fexpr, indent + "
", nparent)
+ s += "}\n"
+ elif isinstance(ty, libxltypes.Struct) and (parent is None or ty.json_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]:
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ 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"
+ s += libxl_C_type_gen_json(f.type, fexpr, "", nparent)
+ s += "s = yajl_gen_map_close(hand);\n"
+ s += "if (s != yajl_gen_status_ok)\n"
+ s += " goto out;\n"
+ else:
+ if ty.json_fn is not None:
+ s += "s = %s(hand, %s);\n" % (ty.json_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=libxltypes.PASS_BY_REFERENCE))
+
+ 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
@@ -137,11 +194,11 @@ def libxl_C_enum_from_string(ty, str, e,
if __name__ == ''__main__'':
- if len(sys.argv) != 4:
- print >>sys.stderr, "Usage: gentypes.py <idl>
<header> <implementation>"
+ if len(sys.argv) != 5:
+ print >>sys.stderr, "Usage: gentypes.py <idl>
<header> <header-json> <implementation>"
sys.exit(1)
- (_, idl, header, impl) = sys.argv
+ (_, idl, header, header_json, impl) = sys.argv
(_,types) = libxltypes.parse(idl)
@@ -165,6 +222,8 @@ if __name__ == ''__main__'':
f.write(libxl_C_type_define(ty) + ";\n")
if ty.destructor_fn is not None:
f.write("void %s(%s);\n" % (ty.destructor_fn,
ty.make_arg("p")))
+ if ty.json_fn is not None:
+ f.write("char *%s_to_json(libxl_ctx *ctx, %s);\n" %
(ty.typename, ty.make_arg("p")))
if isinstance(ty, libxltypes.Enumeration):
f.write("const char *%s_to_string(%s);\n" % (ty.typename,
ty.make_arg("p")))
f.write("int %s_from_string(const char *s, %s);\n" %
(ty.typename, ty.make_arg("e", passby=libxltypes.PASS_BY_REFERENCE)))
@@ -174,6 +233,29 @@ if __name__ == ''__main__'':
f.write("""#endif /* __LIBXL_TYPES_H */\n""")
f.close()
+ print "outputting libxl JSON definitions to %s" % header_json
+
+ f = open(header_json, "w")
+
+ f.write("""#ifndef __LIBXL_TYPES_JSON_H
+#define __LIBXL_TYPES_JSON_H
+
+/*
+ * DO NOT EDIT.
+ *
+ * This file is autogenerated by
+ * "%s"
+ */
+
+""" % " ".join(sys.argv))
+
+ for ty in [ty for ty in types if ty.json_fn is not None]:
+ f.write("yajl_gen_status %s_gen_json(yajl_gen hand, %s);\n" %
(ty.typename, ty.make_arg("p", passby=libxltypes.PASS_BY_REFERENCE)))
+
+ f.write("\n")
+ f.write("""#endif /* __LIBXL_TYPES_JSON_H
*/\n""")
+ f.close()
+
print "outputting libxl type implementations to %s" % impl
f = open(impl, "w")
@@ -220,5 +302,17 @@ if __name__ == ''__main__'':
f.write("}\n")
f.write("\n")
+ for ty in [t for t in types if t.json_fn is not None]:
+ f.write("yajl_gen_status %s_gen_json(yajl_gen hand, %s)\n" %
(ty.typename, ty.make_arg("p", passby=libxltypes.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")
f.close()
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/idl.txt
--- a/tools/libxl/idl.txt Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/idl.txt Thu Jun 23 17:19:27 2011 +0100
@@ -49,6 +49,15 @@ Type.autogenerate_destructor: (default:
Indicates if the above named Type.destructor_fn should be
autogenerated.
+Type.json_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.autogenerate_json: (default: True)
+
+ Indicates if the above named Type.json_fn should be autogenerated.
+
Other simple type-Classes
-------------------------
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/libxl.h Thu Jun 23 17:19:27 2011 +0100
@@ -199,10 +199,10 @@ typedef struct {
int v;
} libxl_enum_string_table;
+typedef struct libxl__ctx libxl_ctx;
+
#include "_libxl_types.h"
-typedef struct libxl__ctx libxl_ctx;
-
const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx);
typedef struct {
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/libxl.idl
--- a/tools/libxl/libxl.idl Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/libxl.idl Thu Jun 23 17:19:27 2011 +0100
@@ -3,7 +3,8 @@
# Builtin libxl types
#
-libxl_domid = Builtin("domid")
+libxl_domid = Builtin("domid", json_fn =
"yajl_gen_integer", autogenerate_json = False)
+
libxl_uuid = Builtin("uuid", passby=PASS_BY_REFERENCE)
libxl_mac = Builtin("mac", passby=PASS_BY_REFERENCE)
libxl_cpumap = Builtin("cpumap",
destructor_fn="libxl_cpumap_destroy", passby=PASS_BY_REFERENCE)
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/libxl_internal.h Thu Jun 23 17:19:27 2011 +0100
@@ -35,6 +35,7 @@
#include "flexarray.h"
#include "libxl_utils.h"
+#include "libxl_json.h"
#define LIBXL_DESTROY_TIMEOUT 10
#define LIBXL_DEVICE_MODEL_START_TIMEOUT 10
@@ -328,6 +329,12 @@ _hidden char *libxl__cpupoolid_to_name(l
_hidden int libxl__enum_from_string(const libxl_enum_string_table *t,
const char *s, int *e);
+_hidden yajl_gen_status libxl__string_gen_json(yajl_gen hand, const char *p);
+
+typedef yajl_gen_status (*libxl__gen_json_callback)(yajl_gen hand, void *);
+_hidden char *libxl__object_to_json(libxl_ctx *ctx, const char *type,
+ libxl__gen_json_callback gen, void *p);
+
/* holds the CPUID response for a single CPUID leaf
* input contains the value of the EAX and ECX register,
* and each policy string contains a filter to apply to
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/libxl_json.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_json.c Thu Jun 23 17:19:27 2011 +0100
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2011 Citrix Ltd.
+ *
+ * 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 <string.h>
+
+#include <libxl.h>
+#include <libxl_internal.h>
+
+yajl_gen_status yajl_gen_asciiz(yajl_gen hand, const char *str)
+{
+ return yajl_gen_string(hand, (const unsigned char *)str, strlen(str));
+}
+
+yajl_gen_status libxl_uuid_gen_json(yajl_gen hand,
+ libxl_uuid *uuid)
+{
+ char buf[LIBXL_UUID_FMTLEN+1];
+ snprintf(buf, sizeof(buf), LIBXL_UUID_FMT, LIBXL_UUID_BYTES((*uuid)));
+ return yajl_gen_string(hand, (const unsigned char *)buf,
LIBXL_UUID_FMTLEN);
+}
+
+yajl_gen_status libxl_cpumap_gen_json(yajl_gen hand,
+ libxl_cpumap *cpumap)
+{
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ libxl_for_each_cpu(i, *cpumap) {
+ if (libxl_cpumap_test(cpumap, i)) {
+ s = yajl_gen_integer(hand, i);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ }
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_key_value_list_gen_json(yajl_gen hand,
+ libxl_key_value_list *pkvl)
+{
+ libxl_key_value_list kvl = *pkvl;
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_map_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ if (!kvl) goto empty;
+
+ for (i = 0; kvl[i] != NULL; i += 2) {
+ s = yajl_gen_asciiz(hand, kvl[i]);
+ if (s != yajl_gen_status_ok) goto out;
+ if (kvl[i + 1])
+ s = yajl_gen_asciiz(hand, kvl[i+1]);
+ else
+ s = yajl_gen_null(hand);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+empty:
+ s = yajl_gen_map_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand,
+ libxl_cpuid_policy_list *pcpuid)
+{
+ libxl_cpuid_policy_list cpuid = *pcpuid;
+ yajl_gen_status s;
+ const char *input_names[2] = { "leaf", "subleaf" };
+ const char *policy_names[4] = { "eax", "ebx",
"ecx", "edx" };
+ int i, j;
+
+ /*
+ * Aiming for:
+ * [
+ * { ''leaf'': ''val-eax'',
+ * ''subleaf'': ''val-edx'',
+ * ''ebx'': ''filter'',
+ * ''ecx'': ''filter'',
+ * ''edx'': ''filter'' }, ],
+ * { ''leaf'': ''val-eax'', ...,
''eax'': ''filter'', ... },
+ * ... etc ...
+ * }
+ */
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ if (cpuid == NULL) goto empty;
+
+ for (i = 0; cpuid[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) {
+ s = yajl_gen_map_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ for (j = 0; j < 2; j++) {
+ if (cpuid[i].input[j] != XEN_CPUID_INPUT_UNUSED) {
+ s = yajl_gen_asciiz(hand, input_names[j]);
+ if (s != yajl_gen_status_ok) goto out;
+ s = yajl_gen_integer(hand, cpuid[i].input[j]);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ }
+
+ for (j = 0; j < 4; j++) {
+ if (cpuid[i].policy[j] != NULL) {
+ s = yajl_gen_asciiz(hand, policy_names[j]);
+ if (s != yajl_gen_status_ok) goto out;
+ s = yajl_gen_string(hand,
+ (const unsigned char *)cpuid[i].policy[j], 32);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ }
+ s = yajl_gen_map_close(hand);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+
+empty:
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_string_list_gen_json(yajl_gen hand, libxl_string_list
*pl)
+{
+ libxl_string_list l = *pl;
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ if (!l) goto empty;
+
+ for (i = 0; l[i] != NULL; i++) {
+ s = yajl_gen_asciiz(hand, l[i]);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+empty:
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_mac_gen_json(yajl_gen hand, libxl_mac *mac)
+{
+ char buf[LIBXL_MAC_FMTLEN+1];
+ snprintf(buf, sizeof(buf), LIBXL_MAC_FMT, LIBXL_MAC_BYTES((*mac)));
+ return yajl_gen_string(hand, (const unsigned char *)buf, LIBXL_MAC_FMTLEN);
+}
+
+yajl_gen_status libxl_hwcap_gen_json(yajl_gen hand,
+ libxl_hwcap p)
+{
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ for(i=0; i<4; i++) {
+ s = yajl_gen_integer(hand, p[i]);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_cpuarray_gen_json(yajl_gen hand,
+ libxl_cpuarray *cpuarray)
+{
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ for(i=0; i<cpuarray->entries; i++) {
+ if (cpuarray->array[i] == LIBXL_CPUARRAY_INVALID_ENTRY)
+ s = yajl_gen_null(hand);
+ else
+ s = yajl_gen_integer(hand, cpuarray->array[i]);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_file_reference_gen_json(yajl_gen hand,
+ libxl_file_reference *p)
+{
+ if (p->path)
+ return yajl_gen_asciiz(hand, p->path);
+ else
+ return yajl_gen_null(hand);
+}
+
+yajl_gen_status libxl__string_gen_json(yajl_gen hand,
+ const char *p)
+{
+ if (p)
+ return yajl_gen_asciiz(hand, p);
+ else
+ return yajl_gen_null(hand);
+}
+
+static const char *yajl_gen_status_to_string(yajl_gen_status s)
+{
+ switch (s) {
+ case yajl_gen_status_ok: abort();
+ case yajl_gen_keys_must_be_strings:
+ return "keys must be strings";
+ case yajl_max_depth_exceeded:
+ return "max depth exceeded";
+ case yajl_gen_in_error_state:
+ return "in error state";
+ case yajl_gen_generation_complete:
+ return "generation complete";
+ case yajl_gen_invalid_number:
+ return "invalid number";
+ case yajl_gen_no_buf:
+ return "no buffer";
+#if 0 /* This is in the docs but not implemented in the version I am running.
*/
+ case yajl_gen_invalid_string:
+ return "invalid string";
+#endif
+ default:
+ return "unknown error";
+ }
+}
+
+char *libxl__object_to_json(libxl_ctx *ctx, const char *type,
+ libxl__gen_json_callback gen, void *p)
+{
+ yajl_gen_config conf = { 1, " " };
+ const unsigned char *buf;
+ char *ret = NULL;
+ unsigned int len = 0;
+ yajl_gen_status s;
+ yajl_gen hand;
+
+ hand = yajl_gen_alloc(&conf, NULL);
+ if (!hand)
+ return NULL;
+
+ s = gen(hand, p);
+ if (s != yajl_gen_status_ok)
+ goto out;
+
+ s = yajl_gen_get_buf(hand, &buf, &len);
+ if (s != yajl_gen_status_ok)
+ goto out;
+ ret = strdup((const char *)buf);
+
+out:
+ yajl_gen_free(hand);
+
+ if (s != yajl_gen_status_ok) {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+ "unable to convert %s to JSON representation. "
+ "YAJL error code %d: %s", type,
+ s, yajl_gen_status_to_string(s));
+ } else if (!ret) {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+ "unable to allocate space for to JSON representation of
%s",
+ type);
+ }
+
+ return ret;
+}
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/libxl_json.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_json.h Thu Jun 23 17:19:27 2011 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 Citrix Ltd.
+ *
+ * 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 LIBXL_JSON_H
+#define LIBXL_JSON_H
+
+#include <yajl/yajl_gen.h>
+
+#include <_libxl_types_json.h>
+
+yajl_gen_status libxl_uuid_gen_json(yajl_gen hand,
+ libxl_uuid *p);
+yajl_gen_status libxl_cpumap_gen_json(yajl_gen hand,
+ libxl_cpumap *p);
+yajl_gen_status libxl_key_value_list_gen_json(yajl_gen hand,
+ libxl_key_value_list *p);
+yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand,
+ libxl_cpuid_policy_list *p);
+yajl_gen_status libxl_string_list_gen_json(yajl_gen hand,
+ libxl_string_list *p);
+yajl_gen_status libxl_mac_gen_json(yajl_gen hand,
+ libxl_mac *p);
+yajl_gen_status libxl_hwcap_gen_json(yajl_gen hand,
+ libxl_hwcap p);
+yajl_gen_status libxl_cpuarray_gen_json(yajl_gen hand,
+ libxl_cpuarray *p);
+yajl_gen_status libxl_file_reference_gen_json(yajl_gen hand,
+ libxl_file_reference *p);
+
+#endif /* LIBXL_JSON_H */
diff -r 4e751a05df3c -r f004439ac182 tools/libxl/libxltypes.py
--- a/tools/libxl/libxltypes.py Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/libxltypes.py Thu Jun 23 17:19:27 2011 +0100
@@ -37,6 +37,13 @@ class Type(object):
self.autogenerate_destructor =
kwargs.setdefault(''autogenerate_destructor'', True)
+ if self.typename is not None:
+ self.json_fn = kwargs.setdefault(''json_fn'',
self.typename + "_gen_json")
+ else:
+ self.json_fn = kwargs.setdefault(''json_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):
@@ -70,6 +77,7 @@ class Builtin(Type):
def __init__(self, typename, **kwargs):
kwargs.setdefault(''destructor_fn'', None)
kwargs.setdefault(''autogenerate_destructor'', False)
+ kwargs.setdefault(''autogenerate_json'', False)
Type.__init__(self, typename, **kwargs)
class Number(Builtin):
@@ -77,6 +85,7 @@ class Number(Builtin):
kwargs.setdefault(''namespace'', None)
kwargs.setdefault(''destructor_fn'', None)
kwargs.setdefault(''signed'', False)
+ kwargs.setdefault(''json_fn'',
"yajl_gen_integer")
self.signed = kwargs[''signed'']
Builtin.__init__(self, ctype, **kwargs)
@@ -145,6 +154,8 @@ class Aggregate(Type):
comment = None
else:
n,t,const,comment = f
+ if n is None:
+ raise ValueError
self.fields.append(Field(t,n,const=const,comment=comment))
# Returns a tuple (stem, field-expr)
@@ -199,7 +210,10 @@ class KeyedUnion(Aggregate):
#
void = Builtin("void *", namespace = None)
-bool = Builtin("bool", namespace = None)
+bool = Builtin("bool", namespace = None,
+ json_fn = "yajl_gen_bool",
+ autogenerate_json = False)
+
size_t = Number("size_t", namespace = None)
integer = Number("int", namespace = None, signed = True)
@@ -209,7 +223,9 @@ uint16 = UInt(16)
uint32 = UInt(32)
uint64 = UInt(64)
-string = Builtin("char *", namespace = None, destructor_fn =
"free")
+string = Builtin("char *", namespace = None, destructor_fn =
"free",
+ json_fn = "libxl__string_gen_json",
+ autogenerate_json = False)
class OrderedDict(dict):
"""A dictionary which remembers insertion order.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Campbell
2011-Jun-23 16:23 UTC
[Xen-devel] Re: [PATCH 10 of 10] libxl: IDL: autogenerate functions to produce JSON from libxl data structures
Minor update (missing "static") because I forgot to qrefresh before
sending.
I also forgot to mention that this uses the same library (YAJL) as
Anthony''s QMP patch, I made the Makefile bit look the same to keep any
conflict reslution minimal.
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1308846102 -3600
# Node ID fc8319c378641194e028a9ae3353b95b1c05539a
# Parent 4e751a05df3c323aea8fb291961a21d13de4afda
libxl: IDL: autogenerate functions to produce JSON from libxl data structures.
Two functions are provided. TYPE_gen_json exposes an interface which is
compatible with the YAGL generator infrastructure. TYPE_to_string uses this to
produce a pretty printed string.
The TYPE_gen_json functions are defined in a new header libxl_json.h which is
not exposed via libxl.h due to the use of YAGL datatypes to avoid poluting the
namespace us libxl users which don''t use the library themselves. If a
libxl
user is interested in integrating at the YAGL level then it should #include
this file itself.
Also update testidl to generate a random version of each IDL datastructure and
convert it to JSON. Unfortunately this requires a libxl_ctx and therefore the
test must be run on a Xen system now.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/Makefile
--- a/tools/libxl/Makefile Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/Makefile Thu Jun 23 17:21:42 2011 +0100
@@ -32,9 +32,12 @@ endif
LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o
LIBXL_OBJS-$(CONFIG_IA64) += libxl_nocpuid.o
+LIBXL_LIBS += -lyajl
+
LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o \
- libxl_internal.o libxl_utils.o libxl_uuid.o $(LIBXL_OBJS-y)
+ libxl_internal.o libxl_utils.o libxl_uuid.o libxl_json.o \
+ $(LIBXL_OBJS-y)
LIBXL_OBJS += _libxl_types.o libxl_flask.o
$(LIBXL_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
$(CFLAGS_libxenstore) $(CFLAGS_libblktapctl)
@@ -81,11 +84,14 @@ libxl_paths.c: _libxl_paths.h
libxl.h: _libxl_types.h
+libxl_json.h: _libxl_types_json.h
+
$(LIBXL_OBJS) $(LIBXLU_OBJS) $(XL_OBJS): libxl.h
-_libxl_%.h _libxl_%.c: libxl.idl gen%.py libxl%.py
- $(PYTHON) gen$*.py libxl.idl __libxl_$*.h __libxl_$*.c
+_libxl_%.h _libxl_%_json.h _libxl_%.c: libxl.idl gen%.py libxltypes.py
+ $(PYTHON) gen$*.py libxl.idl __libxl_$*.h __libxl_$*_json.h __libxl_$*.c
$(call move-if-changed,__libxl_$*.h,_libxl_$*.h)
+ $(call move-if-changed,__libxl_$*_json.h,_libxl_$*_json.h)
$(call move-if-changed,__libxl_$*.c,_libxl_$*.c)
libxenlight.so: libxenlight.so.$(MAJOR)
@@ -133,7 +139,7 @@ install: all
ln -sf libxlutil.so.$(XLUMAJOR).$(XLUMINOR)
$(DESTDIR)$(LIBDIR)/libxlutil.so.$(XLUMAJOR)
ln -sf libxlutil.so.$(XLUMAJOR) $(DESTDIR)$(LIBDIR)/libxlutil.so
$(INSTALL_DATA) libxlutil.a $(DESTDIR)$(LIBDIR)
- $(INSTALL_DATA) libxl.h _libxl_types.h libxl_utils.h libxl_uuid.h
$(DESTDIR)$(INCLUDEDIR)
+ $(INSTALL_DATA) libxl.h libxl_json.h _libxl_types.h _libxl_types_json.h
libxl_utils.h libxl_uuid.h $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_DATA) bash-completion $(DESTDIR)$(BASH_COMPLETION_DIR)/xl.sh
.PHONY: clean
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/gentest.py
--- a/tools/libxl/gentest.py Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/gentest.py Thu Jun 23 17:21:42 2011 +0100
@@ -5,6 +5,7 @@ import re
import random
import libxltypes
+
def randomize_char(c):
if random.random() < 0.5:
return str.lower(c)
@@ -15,6 +16,49 @@ 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_cpumap", "libxl_key_value_list",
+ "libxl_cpuid_policy_list",
"libxl_file_reference",
+ "libxl_string_list", "libxl_cpuarray"]
+
+def gen_rand_init(ty, v, indent = " ", parent = None):
+ s = ""
+ if isinstance(ty, libxltypes.Enumeration):
+ s += "%s = %s;\n" % (ty.pass_arg(v, parent is None),
randomize_enum(ty))
+ elif isinstance(ty, libxltypes.KeyedUnion):
+ if parent is None:
+ raise Exception("KeyedUnion type must have a parent")
+ for f in ty.fields:
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ keyvar_expr = f.keyvar_expr % (parent + ty.keyvar_name)
+ s += "if (" + keyvar_expr + ") {\n"
+ s += gen_rand_init(f.type, fexpr, indent + " ",
nparent)
+ s += "}\n"
+ elif isinstance(ty, libxltypes.Struct) and (parent is None or ty.json_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=libxltypes.PASS_BY_REFERENCE))
+ elif ty.typename in ["libxl_uuid", "libxl_mac",
"libxl_hwcap"]:
+ s += "rand_bytes((uint8_t *)%s, sizeof(*%s));\n" % (v,v)
+ elif ty.typename in ["libxl_domid"] or isinstance(ty,
libxltypes.Number):
+ s += "%s = 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 = rand() %% 2;\n" % v
+ elif ty.typename in ["char *"]:
+ s += "%s = rand_str();\n" % v
+ 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 >>sys.stderr, "Usage: gentest.py <idl>
<implementation>"
@@ -23,23 +67,191 @@ if __name__ == ''__main__'':
random.seed()
idl = sys.argv[1]
- (_,types) = libxltypes.parse(idl)
+ (builtins,types) = libxltypes.parse(idl)
impl = sys.argv[2]
f = open(impl, "w")
f.write("""
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#include \"libxl.h\"
+#include \"libxl_utils.h\"
+static char *rand_str(void)
+{
+ int i, sz = rand() % 32;
+ char *s = malloc(sz+1);
+ for (i=0; i<sz; i++)
+ s[i] = ''a'' + (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] = rand() % 256;
+ //p[i] = i;
+}
+
+static void libxl_cpumap_rand_init(libxl_cpumap *cpumap)
+{
+ int i;
+ cpumap->size = rand() % 16;
+ cpumap->map = calloc(cpumap->size, sizeof(*cpumap->map));
+ libxl_for_each_cpu(i, *cpumap) {
+ if (rand() % 2)
+ libxl_cpumap_set(cpumap, i);
+ else
+ libxl_cpumap_reset(cpumap, i);
+ }
+}
+
+static void libxl_key_value_list_rand_init(libxl_key_value_list *pkvl)
+{
+ int i, nr_kvp = rand() % 16;
+ libxl_key_value_list kvl = calloc(nr_kvp+1, 2*sizeof(char *));
+
+ for (i = 0; i<2*nr_kvp; i += 2) {
+ kvl[i] = rand_str();
+ if (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 = 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 = rand() % nr_options;
+ int val = 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_file_reference_rand_init(libxl_file_reference *p)
+{
+ memset(p, 0, sizeof(*p));
+ if (rand() % 8)
+ p->path = rand_str();
+}
+
+static void libxl_string_list_rand_init(libxl_string_list *p)
+{
+ int i, nr = rand() % 16;
+ libxl_string_list l = calloc(nr+1, sizeof(char *));
+
+ for (i = 0; i<nr; i++) {
+ l[i] = rand_str();
+ }
+ l[i] = NULL;
+ *p = l;
+}
+
+static void libxl_cpuarray_rand_init(libxl_cpuarray *p)
+{
+ int i;
+ /* Up to 16 VCPUs on 32 PCPUS */
+ p->entries = rand() % 16;
+ p->array = calloc(p->entries, sizeof(*p->array));
+ for (i = 0; i < p->entries; i++) {
+ int r = rand() % 32*1.5; /* 2:1 valid:invalid */
+ if (r >= 32)
+ p->array[i] = LIBXL_CPUARRAY_INVALID_ENTRY;
+ else
+ p->array[i] = r;
+ }
+}
+""")
+ for ty in builtins + types:
+ if ty.typename not in handcoded:
+ f.write("static void %s_rand_init(%s);\n" % (ty.typename,
ty.make_arg("p", passby=libxltypes.PASS_BY_REFERENCE)))
+ f.write("static void %s_rand_init(%s)\n" % (ty.typename,
ty.make_arg("p", passby=libxltypes.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 [t for t in types if isinstance(t,libxltypes.Enumeration)]:
+ for ty in types:
f.write(" %s %s_val;\n" % (ty.typename, ty.typename))
- f.write(" int rc;\n")
- f.write("\n")
-
+ f.write("""
+ int rc;
+ char *s;
+ 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, (xentoollog_logger*)logger)) {
+ fprintf(stderr, "cannot init xl context\\n");
+ exit(1);
+ }
+""")
+ f.write(" printf(\"Testing TYPE_to_json()\\n\");\n")
+ f.write(" printf(\"----------------------\\n\");\n")
+ f.write(" printf(\"\\n\");\n")
+ for ty in [t for t in types if t.json_fn is not None]:
+ arg = ty.typename + "_val"
+ f.write(" %s_rand_init(%s);\n" % (ty.typename,
ty.pass_arg(arg, isref=False, passby=libxltypes.PASS_BY_REFERENCE)))
+ 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(" free(s);\n")
+ if ty.destructor_fn is not None:
+ f.write(" %s(&%s_val);\n" % (ty.destructor_fn,
ty.typename))
+ f.write("\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,libxltypes.Enumeration)]:
f.write(" printf(\"%s -- to string:\\n\");\n" %
(ty.typename))
for v in ty.values:
@@ -47,6 +259,12 @@ int main(int argc, char **argv)
(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(" printf(\"\\t%s = %%d = %%s\", %s,
%s_to_json(ctx, %s));\n" %\
+ (v.valuename, v.name, ty.typename, v.name))
+ 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)
@@ -58,6 +276,11 @@ int main(int argc, char **argv)
(v, n, ty.typename))
f.write("\n")
- f.write("""return 0;
+ f.write("""
+
+ libxl_ctx_free(ctx);
+ xtl_logger_destroy((xentoollog_logger*)logger);
+
+ return 0;
}
""")
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/gentypes.py Thu Jun 23 17:21:42 2011 +0100
@@ -29,7 +29,6 @@ def libxl_C_instance_of(ty, instancename
def libxl_C_type_define(ty, indent = ""):
s = ""
-
if isinstance(ty, libxltypes.Enumeration):
if ty.comment is not None:
s += format_comment(0, ty.comment)
@@ -76,7 +75,6 @@ def libxl_C_type_define(ty, indent = "")
return s.replace("\n", "\n%s" % indent)
def libxl_C_type_destroy(ty, v, indent = " ", parent = None):
-
s = ""
if isinstance(ty, libxltypes.KeyedUnion):
if parent is None:
@@ -99,6 +97,65 @@ def libxl_C_type_destroy(ty, v, indent s = indent +
s
return s.replace("\n", "\n%s" % indent).rstrip(indent)
+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, libxltypes.Enumeration):
+ s += "{\n"
+ s += " const char *se = %s_to_string(%s);\n" %
(ty.typename, ty.pass_arg(v, parent is None))
+ s += " if (se)\n"
+ s += " s = yajl_gen_string(hand, (const unsigned char *)se,
strlen(se));\n"
+ s += " else\n"
+ s += " s = yajl_gen_null(hand);\n"
+ s += " if (s != yajl_gen_status_ok)\n"
+ s += " goto out;\n"
+ s += "}\n"
+ elif isinstance(ty, libxltypes.KeyedUnion):
+ if parent is None:
+ raise Exception("KeyedUnion type must have a parent")
+ for f in ty.fields:
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ keyvar_expr = f.keyvar_expr % (parent + ty.keyvar_name)
+ s += "if (" + keyvar_expr + ") {\n"
+ s += libxl_C_type_gen_json(f.type, fexpr, indent + "
", nparent)
+ s += "}\n"
+ elif isinstance(ty, libxltypes.Struct) and (parent is None or ty.json_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]:
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ 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"
+ s += libxl_C_type_gen_json(f.type, fexpr, "", nparent)
+ s += "s = yajl_gen_map_close(hand);\n"
+ s += "if (s != yajl_gen_status_ok)\n"
+ s += " goto out;\n"
+ else:
+ if ty.json_fn is not None:
+ s += "s = %s(hand, %s);\n" % (ty.json_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=libxltypes.PASS_BY_REFERENCE))
+
+ 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
@@ -137,11 +194,11 @@ def libxl_C_enum_from_string(ty, str, e,
if __name__ == ''__main__'':
- if len(sys.argv) != 4:
- print >>sys.stderr, "Usage: gentypes.py <idl>
<header> <implementation>"
+ if len(sys.argv) != 5:
+ print >>sys.stderr, "Usage: gentypes.py <idl>
<header> <header-json> <implementation>"
sys.exit(1)
- (_, idl, header, impl) = sys.argv
+ (_, idl, header, header_json, impl) = sys.argv
(_,types) = libxltypes.parse(idl)
@@ -165,6 +222,8 @@ if __name__ == ''__main__'':
f.write(libxl_C_type_define(ty) + ";\n")
if ty.destructor_fn is not None:
f.write("void %s(%s);\n" % (ty.destructor_fn,
ty.make_arg("p")))
+ if ty.json_fn is not None:
+ f.write("char *%s_to_json(libxl_ctx *ctx, %s);\n" %
(ty.typename, ty.make_arg("p")))
if isinstance(ty, libxltypes.Enumeration):
f.write("const char *%s_to_string(%s);\n" % (ty.typename,
ty.make_arg("p")))
f.write("int %s_from_string(const char *s, %s);\n" %
(ty.typename, ty.make_arg("e", passby=libxltypes.PASS_BY_REFERENCE)))
@@ -174,6 +233,29 @@ if __name__ == ''__main__'':
f.write("""#endif /* __LIBXL_TYPES_H */\n""")
f.close()
+ print "outputting libxl JSON definitions to %s" % header_json
+
+ f = open(header_json, "w")
+
+ f.write("""#ifndef __LIBXL_TYPES_JSON_H
+#define __LIBXL_TYPES_JSON_H
+
+/*
+ * DO NOT EDIT.
+ *
+ * This file is autogenerated by
+ * "%s"
+ */
+
+""" % " ".join(sys.argv))
+
+ for ty in [ty for ty in types if ty.json_fn is not None]:
+ f.write("yajl_gen_status %s_gen_json(yajl_gen hand, %s);\n" %
(ty.typename, ty.make_arg("p", passby=libxltypes.PASS_BY_REFERENCE)))
+
+ f.write("\n")
+ f.write("""#endif /* __LIBXL_TYPES_JSON_H
*/\n""")
+ f.close()
+
print "outputting libxl type implementations to %s" % impl
f = open(impl, "w")
@@ -220,5 +302,17 @@ if __name__ == ''__main__'':
f.write("}\n")
f.write("\n")
+ for ty in [t for t in types if t.json_fn is not None]:
+ f.write("yajl_gen_status %s_gen_json(yajl_gen hand, %s)\n" %
(ty.typename, ty.make_arg("p", passby=libxltypes.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")
f.close()
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/idl.txt
--- a/tools/libxl/idl.txt Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/idl.txt Thu Jun 23 17:21:42 2011 +0100
@@ -49,6 +49,15 @@ Type.autogenerate_destructor: (default:
Indicates if the above named Type.destructor_fn should be
autogenerated.
+Type.json_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.autogenerate_json: (default: True)
+
+ Indicates if the above named Type.json_fn should be autogenerated.
+
Other simple type-Classes
-------------------------
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/libxl.h Thu Jun 23 17:21:42 2011 +0100
@@ -199,10 +199,10 @@ typedef struct {
int v;
} libxl_enum_string_table;
+typedef struct libxl__ctx libxl_ctx;
+
#include "_libxl_types.h"
-typedef struct libxl__ctx libxl_ctx;
-
const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx);
typedef struct {
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/libxl.idl
--- a/tools/libxl/libxl.idl Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/libxl.idl Thu Jun 23 17:21:42 2011 +0100
@@ -3,7 +3,8 @@
# Builtin libxl types
#
-libxl_domid = Builtin("domid")
+libxl_domid = Builtin("domid", json_fn =
"yajl_gen_integer", autogenerate_json = False)
+
libxl_uuid = Builtin("uuid", passby=PASS_BY_REFERENCE)
libxl_mac = Builtin("mac", passby=PASS_BY_REFERENCE)
libxl_cpumap = Builtin("cpumap",
destructor_fn="libxl_cpumap_destroy", passby=PASS_BY_REFERENCE)
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/libxl_internal.h Thu Jun 23 17:21:42 2011 +0100
@@ -35,6 +35,7 @@
#include "flexarray.h"
#include "libxl_utils.h"
+#include "libxl_json.h"
#define LIBXL_DESTROY_TIMEOUT 10
#define LIBXL_DEVICE_MODEL_START_TIMEOUT 10
@@ -328,6 +329,12 @@ _hidden char *libxl__cpupoolid_to_name(l
_hidden int libxl__enum_from_string(const libxl_enum_string_table *t,
const char *s, int *e);
+_hidden yajl_gen_status libxl__string_gen_json(yajl_gen hand, const char *p);
+
+typedef yajl_gen_status (*libxl__gen_json_callback)(yajl_gen hand, void *);
+_hidden char *libxl__object_to_json(libxl_ctx *ctx, const char *type,
+ libxl__gen_json_callback gen, void *p);
+
/* holds the CPUID response for a single CPUID leaf
* input contains the value of the EAX and ECX register,
* and each policy string contains a filter to apply to
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/libxl_json.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_json.c Thu Jun 23 17:21:42 2011 +0100
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2011 Citrix Ltd.
+ *
+ * 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 <string.h>
+
+#include <libxl.h>
+#include <libxl_internal.h>
+
+static yajl_gen_status yajl_gen_asciiz(yajl_gen hand, const char *str)
+{
+ return yajl_gen_string(hand, (const unsigned char *)str, strlen(str));
+}
+
+yajl_gen_status libxl_uuid_gen_json(yajl_gen hand,
+ libxl_uuid *uuid)
+{
+ char buf[LIBXL_UUID_FMTLEN+1];
+ snprintf(buf, sizeof(buf), LIBXL_UUID_FMT, LIBXL_UUID_BYTES((*uuid)));
+ return yajl_gen_string(hand, (const unsigned char *)buf,
LIBXL_UUID_FMTLEN);
+}
+
+yajl_gen_status libxl_cpumap_gen_json(yajl_gen hand,
+ libxl_cpumap *cpumap)
+{
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ libxl_for_each_cpu(i, *cpumap) {
+ if (libxl_cpumap_test(cpumap, i)) {
+ s = yajl_gen_integer(hand, i);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ }
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_key_value_list_gen_json(yajl_gen hand,
+ libxl_key_value_list *pkvl)
+{
+ libxl_key_value_list kvl = *pkvl;
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_map_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ if (!kvl) goto empty;
+
+ for (i = 0; kvl[i] != NULL; i += 2) {
+ s = yajl_gen_asciiz(hand, kvl[i]);
+ if (s != yajl_gen_status_ok) goto out;
+ if (kvl[i + 1])
+ s = yajl_gen_asciiz(hand, kvl[i+1]);
+ else
+ s = yajl_gen_null(hand);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+empty:
+ s = yajl_gen_map_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand,
+ libxl_cpuid_policy_list *pcpuid)
+{
+ libxl_cpuid_policy_list cpuid = *pcpuid;
+ yajl_gen_status s;
+ const char *input_names[2] = { "leaf", "subleaf" };
+ const char *policy_names[4] = { "eax", "ebx",
"ecx", "edx" };
+ int i, j;
+
+ /*
+ * Aiming for:
+ * [
+ * { ''leaf'': ''val-eax'',
+ * ''subleaf'': ''val-edx'',
+ * ''ebx'': ''filter'',
+ * ''ecx'': ''filter'',
+ * ''edx'': ''filter'' }, ],
+ * { ''leaf'': ''val-eax'', ...,
''eax'': ''filter'', ... },
+ * ... etc ...
+ * }
+ */
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ if (cpuid == NULL) goto empty;
+
+ for (i = 0; cpuid[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) {
+ s = yajl_gen_map_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ for (j = 0; j < 2; j++) {
+ if (cpuid[i].input[j] != XEN_CPUID_INPUT_UNUSED) {
+ s = yajl_gen_asciiz(hand, input_names[j]);
+ if (s != yajl_gen_status_ok) goto out;
+ s = yajl_gen_integer(hand, cpuid[i].input[j]);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ }
+
+ for (j = 0; j < 4; j++) {
+ if (cpuid[i].policy[j] != NULL) {
+ s = yajl_gen_asciiz(hand, policy_names[j]);
+ if (s != yajl_gen_status_ok) goto out;
+ s = yajl_gen_string(hand,
+ (const unsigned char *)cpuid[i].policy[j], 32);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ }
+ s = yajl_gen_map_close(hand);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+
+empty:
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_string_list_gen_json(yajl_gen hand, libxl_string_list
*pl)
+{
+ libxl_string_list l = *pl;
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ if (!l) goto empty;
+
+ for (i = 0; l[i] != NULL; i++) {
+ s = yajl_gen_asciiz(hand, l[i]);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+empty:
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_mac_gen_json(yajl_gen hand, libxl_mac *mac)
+{
+ char buf[LIBXL_MAC_FMTLEN+1];
+ snprintf(buf, sizeof(buf), LIBXL_MAC_FMT, LIBXL_MAC_BYTES((*mac)));
+ return yajl_gen_string(hand, (const unsigned char *)buf, LIBXL_MAC_FMTLEN);
+}
+
+yajl_gen_status libxl_hwcap_gen_json(yajl_gen hand,
+ libxl_hwcap p)
+{
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ for(i=0; i<4; i++) {
+ s = yajl_gen_integer(hand, p[i]);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_cpuarray_gen_json(yajl_gen hand,
+ libxl_cpuarray *cpuarray)
+{
+ yajl_gen_status s;
+ int i;
+
+ s = yajl_gen_array_open(hand);
+ if (s != yajl_gen_status_ok) goto out;
+
+ for(i=0; i<cpuarray->entries; i++) {
+ if (cpuarray->array[i] == LIBXL_CPUARRAY_INVALID_ENTRY)
+ s = yajl_gen_null(hand);
+ else
+ s = yajl_gen_integer(hand, cpuarray->array[i]);
+ if (s != yajl_gen_status_ok) goto out;
+ }
+ s = yajl_gen_array_close(hand);
+out:
+ return s;
+}
+
+yajl_gen_status libxl_file_reference_gen_json(yajl_gen hand,
+ libxl_file_reference *p)
+{
+ if (p->path)
+ return yajl_gen_asciiz(hand, p->path);
+ else
+ return yajl_gen_null(hand);
+}
+
+yajl_gen_status libxl__string_gen_json(yajl_gen hand,
+ const char *p)
+{
+ if (p)
+ return yajl_gen_asciiz(hand, p);
+ else
+ return yajl_gen_null(hand);
+}
+
+static const char *yajl_gen_status_to_string(yajl_gen_status s)
+{
+ switch (s) {
+ case yajl_gen_status_ok: abort();
+ case yajl_gen_keys_must_be_strings:
+ return "keys must be strings";
+ case yajl_max_depth_exceeded:
+ return "max depth exceeded";
+ case yajl_gen_in_error_state:
+ return "in error state";
+ case yajl_gen_generation_complete:
+ return "generation complete";
+ case yajl_gen_invalid_number:
+ return "invalid number";
+ case yajl_gen_no_buf:
+ return "no buffer";
+#if 0 /* This is in the docs but not implemented in the version I am running.
*/
+ case yajl_gen_invalid_string:
+ return "invalid string";
+#endif
+ default:
+ return "unknown error";
+ }
+}
+
+char *libxl__object_to_json(libxl_ctx *ctx, const char *type,
+ libxl__gen_json_callback gen, void *p)
+{
+ yajl_gen_config conf = { 1, " " };
+ const unsigned char *buf;
+ char *ret = NULL;
+ unsigned int len = 0;
+ yajl_gen_status s;
+ yajl_gen hand;
+
+ hand = yajl_gen_alloc(&conf, NULL);
+ if (!hand)
+ return NULL;
+
+ s = gen(hand, p);
+ if (s != yajl_gen_status_ok)
+ goto out;
+
+ s = yajl_gen_get_buf(hand, &buf, &len);
+ if (s != yajl_gen_status_ok)
+ goto out;
+ ret = strdup((const char *)buf);
+
+out:
+ yajl_gen_free(hand);
+
+ if (s != yajl_gen_status_ok) {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+ "unable to convert %s to JSON representation. "
+ "YAJL error code %d: %s", type,
+ s, yajl_gen_status_to_string(s));
+ } else if (!ret) {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+ "unable to allocate space for to JSON representation of
%s",
+ type);
+ }
+
+ return ret;
+}
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/libxl_json.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_json.h Thu Jun 23 17:21:42 2011 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 Citrix Ltd.
+ *
+ * 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 LIBXL_JSON_H
+#define LIBXL_JSON_H
+
+#include <yajl/yajl_gen.h>
+
+#include <_libxl_types_json.h>
+
+yajl_gen_status libxl_uuid_gen_json(yajl_gen hand,
+ libxl_uuid *p);
+yajl_gen_status libxl_cpumap_gen_json(yajl_gen hand,
+ libxl_cpumap *p);
+yajl_gen_status libxl_key_value_list_gen_json(yajl_gen hand,
+ libxl_key_value_list *p);
+yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand,
+ libxl_cpuid_policy_list *p);
+yajl_gen_status libxl_string_list_gen_json(yajl_gen hand,
+ libxl_string_list *p);
+yajl_gen_status libxl_mac_gen_json(yajl_gen hand,
+ libxl_mac *p);
+yajl_gen_status libxl_hwcap_gen_json(yajl_gen hand,
+ libxl_hwcap p);
+yajl_gen_status libxl_cpuarray_gen_json(yajl_gen hand,
+ libxl_cpuarray *p);
+yajl_gen_status libxl_file_reference_gen_json(yajl_gen hand,
+ libxl_file_reference *p);
+
+#endif /* LIBXL_JSON_H */
diff -r 4e751a05df3c -r fc8319c37864 tools/libxl/libxltypes.py
--- a/tools/libxl/libxltypes.py Thu Jun 23 17:19:16 2011 +0100
+++ b/tools/libxl/libxltypes.py Thu Jun 23 17:21:42 2011 +0100
@@ -37,6 +37,13 @@ class Type(object):
self.autogenerate_destructor =
kwargs.setdefault(''autogenerate_destructor'', True)
+ if self.typename is not None:
+ self.json_fn = kwargs.setdefault(''json_fn'',
self.typename + "_gen_json")
+ else:
+ self.json_fn = kwargs.setdefault(''json_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):
@@ -70,6 +77,7 @@ class Builtin(Type):
def __init__(self, typename, **kwargs):
kwargs.setdefault(''destructor_fn'', None)
kwargs.setdefault(''autogenerate_destructor'', False)
+ kwargs.setdefault(''autogenerate_json'', False)
Type.__init__(self, typename, **kwargs)
class Number(Builtin):
@@ -77,6 +85,7 @@ class Number(Builtin):
kwargs.setdefault(''namespace'', None)
kwargs.setdefault(''destructor_fn'', None)
kwargs.setdefault(''signed'', False)
+ kwargs.setdefault(''json_fn'',
"yajl_gen_integer")
self.signed = kwargs[''signed'']
Builtin.__init__(self, ctype, **kwargs)
@@ -145,6 +154,8 @@ class Aggregate(Type):
comment = None
else:
n,t,const,comment = f
+ if n is None:
+ raise ValueError
self.fields.append(Field(t,n,const=const,comment=comment))
# Returns a tuple (stem, field-expr)
@@ -199,7 +210,10 @@ class KeyedUnion(Aggregate):
#
void = Builtin("void *", namespace = None)
-bool = Builtin("bool", namespace = None)
+bool = Builtin("bool", namespace = None,
+ json_fn = "yajl_gen_bool",
+ autogenerate_json = False)
+
size_t = Number("size_t", namespace = None)
integer = Number("int", namespace = None, signed = True)
@@ -209,7 +223,9 @@ uint16 = UInt(16)
uint32 = UInt(32)
uint64 = UInt(64)
-string = Builtin("char *", namespace = None, destructor_fn =
"free")
+string = Builtin("char *", namespace = None, destructor_fn =
"free",
+ json_fn = "libxl__string_gen_json",
+ autogenerate_json = False)
class OrderedDict(dict):
"""A dictionary which remembers insertion order.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Ian Jackson
2011-Jun-24 14:54 UTC
Re: [Xen-devel] [PATCH 00 of 10] libxl: IDL improvements and JSON generation
Ian Campbell writes ("[Xen-devel] [PATCH 00 of 10] libxl: IDL improvements
and JSON generation"):> This patch series makes some improvements to the IDL language and
> generator and then goes on to implement JSON generation for IDL
> defined datatypes.
Nice work.
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
If there are no adverse comments or last-minute changes :-) I will
apply this early next week.
Ian.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel