aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl/gentypes.py
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2011-10-07 11:05:45 +0100
committerIan Campbell <ian.campbell@citrix.com>2011-10-07 11:05:45 +0100
commit93e240f0966324dee6b02d249f3e3a9e5ecf9d19 (patch)
treeec76c5e9da6c2cfc58233be168aa9c83934e34a2 /tools/libxl/gentypes.py
parentee3665984b795ee3a4f56cf3d93ca697ce857f6f (diff)
downloadxen-93e240f0966324dee6b02d249f3e3a9e5ecf9d19.tar.gz
xen-93e240f0966324dee6b02d249f3e3a9e5ecf9d19.tar.bz2
xen-93e240f0966324dee6b02d249f3e3a9e5ecf9d19.zip
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> Acked-by: Ian Jackson <ian.jackson.citrix.com> Committed-by: Ian Jackson <ian.jackson.citrix.com>
Diffstat (limited to 'tools/libxl/gentypes.py')
-rw-r--r--tools/libxl/gentypes.py102
1 files changed, 96 insertions, 6 deletions
diff --git a/tools/libxl/gentypes.py b/tools/libxl/gentypes.py
index ecf5f152c4..e82b70673b 100644
--- a/tools/libxl/gentypes.py
+++ b/tools/libxl/gentypes.py
@@ -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:
@@ -100,6 +98,60 @@ def libxl_C_type_destroy(ty, v, indent = " ", parent = None):
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 += "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, libxltypes.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
+ s += libxl_C_type_gen_json(f.type, fexpr, indent + " ", nparent)
+ s += " break;\n"
+ 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
@@ -138,13 +190,13 @@ def libxl_C_enum_from_string(ty, str, e, indent = " "):
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)
+ (builtins,types) = libxltypes.parse(idl)
print "outputting libxl type definitions to %s" % header
@@ -167,6 +219,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)))
@@ -176,6 +230,30 @@ if __name__ == '__main__':
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+builtins 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 /* %s */\n""" % header_json_define)
+ f.close()
+
print "outputting libxl type implementations to %s" % impl
f = open(impl, "w")
@@ -222,5 +300,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()