aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl/idl.py
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2012-01-31 16:34:38 +0000
committerIan Campbell <ian.campbell@citrix.com>2012-01-31 16:34:38 +0000
commita6beb5286e7ca1d478ef391396be49b4f6d2ca35 (patch)
treee649090f00988dde2ca2b569980a1b8f5f330131 /tools/libxl/idl.py
parent15873321439d3588e0276c7cfddb0a11f71c897d (diff)
downloadxen-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.py294
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)