mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
308 lines
9.5 KiB
Python
308 lines
9.5 KiB
Python
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)
|
|
|
|
self.init_fn = kwargs.setdefault('init_fn', None)
|
|
self.init_val = kwargs.setdefault('init_val', None)
|
|
self.autogenerate_init_fn = kwargs.setdefault('autogenerate_init_fn', False)
|
|
|
|
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)
|
|
self.init_val = kwargs.setdefault('init_val', None)
|
|
|
|
class Aggregate(Type):
|
|
"""A type containing a collection of other types"""
|
|
def __init__(self, kind, typename, fields, **kwargs):
|
|
Type.__init__(self, typename, **kwargs)
|
|
|
|
if self.typename is not None:
|
|
self.init_fn = kwargs.setdefault('init_fn', self.typename + "_init")
|
|
else:
|
|
self.init_fn = kwargs.setdefault('init_fn', None)
|
|
|
|
self.autogenerate_init_fn = kwargs.setdefault('autogenerate_init_fn', True)
|
|
|
|
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
|
|
|
|
kv_kwargs = dict([(x.lstrip('keyvar_'),y) for (x,y) in kwargs.items() if x.startswith('keyvar_')])
|
|
|
|
self.keyvar = Field(keyvar_type, keyvar_name, **kv_kwargs)
|
|
|
|
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)
|