diff options
author | Ian Campbell <ian.campbell@citrix.com> | 2011-10-07 11:05:45 +0100 |
---|---|---|
committer | Ian Campbell <ian.campbell@citrix.com> | 2011-10-07 11:05:45 +0100 |
commit | 93e240f0966324dee6b02d249f3e3a9e5ecf9d19 (patch) | |
tree | ec76c5e9da6c2cfc58233be168aa9c83934e34a2 /tools/libxl/gentypes.py | |
parent | ee3665984b795ee3a4f56cf3d93ca697ce857f6f (diff) | |
download | xen-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.py | 102 |
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() |