#!/usr/bin/python import sys import re import libxltypes def format_comment(level, comment): indent = reduce(lambda x,y: x + " ", range(level), "") s = "%s/*\n" % indent s += "%s * " % indent comment = comment.replace("\n", "\n%s * " % indent) x = re.compile(r'^%s \* $' % indent, re.MULTILINE) comment = x.sub("%s *" % indent, comment) s += comment s += "\n" 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.BitField): return libxl_C_type_of(ty) + " " + instancename + ":%d" % ty.width elif isinstance(ty, libxltypes.Aggregate) and ty.typename is None: if instancename is None: return libxl_C_type_define(ty) else: return libxl_C_type_define(ty) + " " + instancename else: return libxl_C_type_of(ty) + " " + instancename def libxl_C_type_define(ty, indent = ""): s = "" if isinstance(ty, libxltypes.Aggregate): if ty.comment is not None: s += format_comment(0, ty.comment) if ty.typename is None: s += "%s {\n" % ty.kind else: s += "typedef %s {\n" % ty.kind for f in ty.fields: if f.comment is not None: s += format_comment(4, f.comment) x = libxl_C_instance_of(f.type, f.name) if f.const: x = "const " + x x = x.replace("\n", "\n ") s += " " + x + ";\n" if ty.typename is None: s += "}" else: s += "} %s" % ty.typename else: raise NotImplementedError("%s" % type(ty)) return s.replace("\n", "\n%s" % indent) def libxl_C_type_destroy(ty, v, reference, indent = " ", parent = None): if reference: deref = v + "->" else: deref = v + "." if ty.passby == libxltypes.PASS_BY_REFERENCE and not reference: makeref = "&" else: makeref = "" s = "" if isinstance(ty, libxltypes.KeyedUnion): if parent is None: raise Exception("KeyedUnion type must have a parent") for f in ty.fields: keyvar_expr = f.keyvar_expr % (parent + ty.keyvar_name) s += "if (" + keyvar_expr + ") {\n" s += libxl_C_type_destroy(f.type, deref + f.name, False, indent + " ", deref) s += "}\n" elif isinstance(ty, libxltypes.Reference): s += libxl_C_type_destroy(ty.ref_type, v, True, indent, v) if ty.destructor_fn is not None: s += "%s(%s);\n" % (ty.destructor_fn, makeref + v) 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 s += libxl_C_type_destroy(f.type, deref, False, "", deref) else: s += libxl_C_type_destroy(f.type, deref + f.name, False, "", deref) else: if ty.destructor_fn is not None: s += "%s(%s);\n" % (ty.destructor_fn, makeref + v) if s != "": s = indent + s return s.replace("\n", "\n%s" % indent).rstrip(indent) if __name__ == '__main__': if len(sys.argv) < 4: print >>sys.stderr, "Usage: gentypes.py
" sys.exit(1) idl = sys.argv[1] (_,types) = libxltypes.parse(idl) header = sys.argv[2] print "outputting libxl type definitions to %s" % header f = open(header, "w") f.write("""#ifndef __LIBXL_TYPES_H #define __LIBXL_TYPES_H /* * DO NOT EDIT. * * This file is autogenerated by * "%s" */ """ % " ".join(sys.argv)) 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("\n") 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") f.write(""" /* DO NOT EDIT. * * This file is autogenerated by * "%s" */ #include "libxl_osdeps.h" #include #include #include #include "libxl.h" #define LIBXL_DTOR_POISON 0xa5 """ % " ".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("{\n") f.write(libxl_C_type_destroy(ty, "p", True)) f.write(" memset(p, LIBXL_DTOR_POISON, sizeof(*p));\n") f.write("}\n") f.write("\n") f.close()