diff options
author | Ian Campbell <ian.campbell@citrix.com> | 2012-01-31 16:34:38 +0000 |
---|---|---|
committer | Ian Campbell <ian.campbell@citrix.com> | 2012-01-31 16:34:38 +0000 |
commit | a6beb5286e7ca1d478ef391396be49b4f6d2ca35 (patch) | |
tree | e649090f00988dde2ca2b569980a1b8f5f330131 /tools/libxl/idl.py | |
parent | 15873321439d3588e0276c7cfddb0a11f71c897d (diff) | |
download | xen-a6beb5286e7ca1d478ef391396be49b4f6d2ca35.tar.gz xen-a6beb5286e7ca1d478ef391396be49b4f6d2ca35.tar.bz2 xen-a6beb5286e7ca1d478ef391396be49b4f6d2ca35.zip |
libxl: Rename libxl IDL infrastructure.
Originally libxltypes.py provided the infrastructure and libxl.idl provided the
specific types.
In 23887:a543e10211f7 libxl.idl became libxl_types.idl (to allow for
libxl_types_internal.idl) which means we now have libxl_types.FOO and
libxltypes.FOO providing different things and annoying people in tab
completion.
Rename the infrastructure as idl.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Committed-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Diffstat (limited to 'tools/libxl/idl.py')
-rw-r--r-- | tools/libxl/idl.py | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/tools/libxl/idl.py b/tools/libxl/idl.py new file mode 100644 index 0000000000..880b7ca71d --- /dev/null +++ b/tools/libxl/idl.py @@ -0,0 +1,294 @@ +import sys + +PASS_BY_VALUE = 1 +PASS_BY_REFERENCE = 2 + +DIR_NONE = 0 +DIR_IN = 1 +DIR_OUT = 2 +DIR_BOTH = 3 + +_default_namespace = "" +def namespace(s): + if type(s) != str: + raise TypeError, "Require a string for the default namespace." + global _default_namespace + _default_namespace = s + +def _get_default_namespace(): + global _default_namespace + return _default_namespace + + +class Type(object): + def __init__(self, typename, **kwargs): + self.namespace = kwargs.setdefault('namespace', + _get_default_namespace()) + self.dir = kwargs.setdefault('dir', DIR_BOTH) + if self.dir not in [DIR_NONE, DIR_IN, DIR_OUT, DIR_BOTH]: + raise ValueError + + self.passby = kwargs.setdefault('passby', PASS_BY_VALUE) + if self.passby not in [PASS_BY_VALUE, PASS_BY_REFERENCE]: + raise ValueError + + self.private = kwargs.setdefault('private', False) + + if typename is None: # Anonymous type + self.typename = None + self.rawname = None + elif self.namespace is None: # e.g. system provided types + self.typename = typename + self.rawname = typename + else: + self.typename = self.namespace + typename + self.rawname = typename + + if self.typename is not None: + self.dispose_fn = kwargs.setdefault('dispose_fn', self.typename + "_dispose") + else: + self.dispose_fn = kwargs.setdefault('dispose_fn', None) + + self.autogenerate_dispose_fn = kwargs.setdefault('autogenerate_dispose_fn', True) + + if self.typename is not None and not self.private: + 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): + 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) + + def pass_arg(self, n, isref=None, passby=None): + if passby is None: passby = self.passby + if isref is None: isref = self.passby == PASS_BY_REFERENCE + + if passby == PASS_BY_REFERENCE: + if isref: + return "%s" % (n) + else: + return "&%s" % (n) + else: + if isref: + return "*%s" % (n) + else: + return "%s" % (n) + +class Builtin(Type): + """Builtin type""" + def __init__(self, typename, **kwargs): + kwargs.setdefault('dispose_fn', None) + kwargs.setdefault('autogenerate_dispose_fn', False) + kwargs.setdefault('autogenerate_json', False) + Type.__init__(self, typename, **kwargs) + +class Number(Builtin): + def __init__(self, ctype, **kwargs): + kwargs.setdefault('namespace', None) + kwargs.setdefault('dispose_fn', None) + kwargs.setdefault('signed', False) + kwargs.setdefault('json_fn', "yajl_gen_integer") + self.signed = kwargs['signed'] + Builtin.__init__(self, ctype, **kwargs) + +class UInt(Number): + def __init__(self, w, **kwargs): + kwargs.setdefault('namespace', None) + kwargs.setdefault('dispose_fn', None) + Number.__init__(self, "uint%d_t" % w, **kwargs) + + self.width = w + +class EnumerationValue(object): + def __init__(self, enum, value, name, **kwargs): + self.enum = enum + + self.valuename = str.upper(name) + self.rawname = str.upper(enum.rawname) + "_" + self.valuename + self.name = str.upper(enum.namespace) + self.rawname + self.value = value + +class Enumeration(Type): + def __init__(self, typename, values, **kwargs): + kwargs.setdefault('dispose_fn', None) + Type.__init__(self, typename, **kwargs) + + self.values = [] + for v in values: + # (value, name) + (num,name) = v + self.values.append(EnumerationValue(self, num, name, + typename=self.rawname)) + def lookup(self, name): + for v in self.values: + if v.valuename == str.upper(name): + return v + return ValueError + +class Field(object): + """An element of an Aggregate type""" + def __init__(self, type, name, **kwargs): + self.type = type + self.name = name + self.const = kwargs.setdefault('const', False) + self.enumname = kwargs.setdefault('enumname', None) + +class Aggregate(Type): + """A type containing a collection of other types""" + def __init__(self, kind, typename, fields, **kwargs): + Type.__init__(self, typename, **kwargs) + + self.kind = kind + + self.fields = [] + for f in fields: + # (name, type[, {kw args}]) + if len(f) == 2: + n,t = f + kw = {} + elif len(f) == 3: + n,t,kw = f + else: + raise ValueError + if n is None: + raise ValueError + self.fields.append(Field(t,n,**kw)) + + # Returns a tuple (stem, field-expr) + # + # field-expr is a C expression for a field "f" within the struct + # "v". + # + # stem is the stem common to both "f" and any other sibbling field + # within the "v". + def member(self, v, f, isref): + if isref: + deref = v + "->" + else: + deref = v + "." + + if f.name is None: # Anonymous + return (deref, deref) + else: + return (deref, deref + f.name) + +class Struct(Aggregate): + def __init__(self, name, fields, **kwargs): + kwargs.setdefault('passby', PASS_BY_REFERENCE) + Aggregate.__init__(self, "struct", name, fields, **kwargs) + +class Union(Aggregate): + def __init__(self, name, fields, **kwargs): + # Generally speaking some intelligence is required to free a + # union therefore any specific instance of this class will + # need to provide an explicit destructor function. + kwargs.setdefault('passby', PASS_BY_REFERENCE) + kwargs.setdefault('dispose_fn', None) + Aggregate.__init__(self, "union", name, fields, **kwargs) + +class KeyedUnion(Aggregate): + """A union which is keyed of another variable in the parent structure""" + def __init__(self, name, keyvar_type, keyvar_name, fields, **kwargs): + Aggregate.__init__(self, "union", name, [], **kwargs) + + if not isinstance(keyvar_type, Enumeration): + raise ValueError + + self.keyvar_name = keyvar_name + self.keyvar_type = keyvar_type + + for f in fields: + # (name, enum, type) + e, ty = f + ev = keyvar_type.lookup(e) + en = ev.name + self.fields.append(Field(ty, e, enumname=en)) + +# +# Standard Types +# + +void = Builtin("void *", namespace = None) +bool = Builtin("bool", namespace = None, + json_fn = "yajl_gen_bool", + autogenerate_json = False) + +size_t = Number("size_t", namespace = None) + +integer = Number("int", namespace = None, signed = True) + +uint8 = UInt(8) +uint16 = UInt(16) +uint32 = UInt(32) +uint64 = UInt(64) + +string = Builtin("char *", namespace = None, dispose_fn = "free", + json_fn = "libxl__string_gen_json", + autogenerate_json = False) + +class OrderedDict(dict): + """A dictionary which remembers insertion order. + + push to back on duplicate insertion""" + + def __init__(self): + dict.__init__(self) + self.__ordered = [] + + def __setitem__(self, key, value): + try: + self.__ordered.remove(key) + except ValueError: + pass + + self.__ordered.append(key) + dict.__setitem__(self, key, value) + + def ordered_keys(self): + return self.__ordered + def ordered_values(self): + return [self[x] for x in self.__ordered] + def ordered_items(self): + return [(x,self[x]) for x in self.__ordered] + +def parse(f): + print >>sys.stderr, "Parsing %s" % f + + globs = {} + locs = OrderedDict() + + for n,t in globals().items(): + if isinstance(t, Type): + globs[n] = t + elif isinstance(t,type(object)) and issubclass(t, Type): + globs[n] = t + elif n in ['PASS_BY_REFERENCE', 'PASS_BY_VALUE', + 'DIR_NONE', 'DIR_IN', 'DIR_OUT', 'DIR_BOTH', + 'namespace']: + globs[n] = t + + try: + execfile(f, globs, locs) + except SyntaxError,e: + raise SyntaxError, \ + "Errors were found at line %d while processing %s:\n\t%s"\ + %(e.lineno,f,e.text) + + types = [t for t in locs.ordered_values() if isinstance(t,Type)] + + builtins = [t for t in types if isinstance(t,Builtin)] + types = [t for t in types if not isinstance(t,Builtin)] + + return (builtins,types) |