return "Wrap" + interface.expr
+
+class ExpanderMixin:
+ '''Mixin class that provides a bunch of methods to expand C expressions
+ from the specifications.'''
+
+ __structs = None
+ __indices = None
+
+ def expand(self, expr):
+ # Expand a C expression, replacing certain variables
+ if not isinstance(expr, basestring):
+ return expr
+ variables = {}
+
+ if self.__structs is not None:
+ variables['self'] = '(%s)' % self.__structs[0]
+ if self.__indices is not None:
+ variables['i'] = self.__indices[0]
+
+ expandedExpr = expr.format(**variables)
+ if expandedExpr != expr and 0:
+ sys.stderr.write(" %r -> %r\n" % (expr, expandedExpr))
+ return expandedExpr
+
+ def visitMember(self, structInstance, member_type, *args, **kwargs):
+ self.__structs = (structInstance, self.__structs)
+ try:
+ return self.visit(member_type, *args, **kwargs)
+ finally:
+ _, self.__structs = self.__structs
+
+ def visitElement(self, element_index, element_type, *args, **kwargs):
+ self.__indices = (element_index, self.__indices)
+ try:
+ return self.visit(element_type, *args, **kwargs)
+ finally:
+ _, self.__indices = self.__indices
+
+
class ComplexValueSerializer(stdapi.OnceVisitor):
'''Type visitors which generates serialization functions for
complex types.
print
-class ValueSerializer(stdapi.Visitor):
+class ValueSerializer(stdapi.Visitor, ExpanderMixin):
'''Visitor which generates code to serialize any type.
Simple types are serialized inline here, whereas the serialization of
self.indices = []
self.instances = []
- def expand(self, expr):
- # Expand a C expression, replacing certain variables
- variables = {}
- try:
- variables['self'] = self.instances[-1]
- except IndexError:
- pass
- try:
- variables['i'] = self.indices[-1]
- except IndexError:
- pass
- expandedExpr = expr.format(**variables)
- if expandedExpr != expr:
- sys.stderr.write(" %r -> %r\n" % (expr, expandedExpr))
- return expandedExpr
-
def visitLiteral(self, literal, instance):
print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
def visitStruct(self, struct, instance):
print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
- self.instances.append(instance)
- try:
- for type, name in struct.members:
- self.visit(type, '(%s).%s' % (instance, name,))
- finally:
- self.instances.pop()
+ for type, name in struct.members:
+ self.visitMember(instance, type, '(%s).%s' % (instance, name,))
print ' trace::localWriter.endStruct();'
def visitArray(self, array, instance):
length = '_c' + array.type.tag
index = '_i' + array.type.tag
+ array_length = self.expand(array.length)
print ' if (%s) {' % instance
- print ' size_t %s = %s > 0 ? %s : 0;' % (length, array.length, array.length)
+ print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
print ' trace::localWriter.beginArray(%s);' % length
print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
print ' trace::localWriter.beginElement();'
- self.indices.append(index)
- try:
- self.visit(array.type, '(%s)[%s]' % (instance, index))
- finally:
- self.indices.pop()
+ self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
print ' trace::localWriter.endElement();'
print ' }'
print ' trace::localWriter.endArray();'
self.needsWrapping = True
-class ValueWrapper(stdapi.Traverser):
+class ValueWrapper(stdapi.Traverser, ExpanderMixin):
'''Type visitor which will generate the code to wrap an instance.
Wrapping is necessary mostly for interfaces, however interface pointers can
def visitStruct(self, struct, instance):
for type, name in struct.members:
- self.visit(type, "(%s).%s" % (instance, name))
+ self.visitMember(instance, type, "(%s).%s" % (instance, name))
def visitArray(self, array, instance):
+ array_length = self.expand(array.length)
print " if (%s) {" % instance
- print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
- self.visit(array.type, instance + "[_i]")
+ print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
+ self.visitElement('_i', array.type, instance + "[_i]")
print " }"
print " }"
elem_type = pointer.type.mutable()
if isinstance(elem_type, stdapi.Interface):
self.visitInterfacePointer(elem_type, instance)
+ elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
+ self.visitInterfacePointer(elem_type.type, instance)
else:
self.visitPointer(pointer, instance)
allocated = False
+ def visitStruct(self, struct, instance):
+ if not self.allocated:
+ # Argument is constant. We need to create a non const
+ print ' {'
+ print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
+ print ' *_t = %s;' % (instance,)
+ assert instance.startswith('*')
+ print ' %s = _t;' % (instance[1:],)
+ instance = '*_t'
+ self.allocated = True
+ try:
+ return ValueWrapper.visitStruct(self, struct, instance)
+ finally:
+ print ' }'
+ else:
+ return ValueWrapper.visitStruct(self, struct, instance)
+
def visitArray(self, array, instance):
if self.allocated or isinstance(instance, stdapi.Interface):
return ValueWrapper.visitArray(self, array, instance)
+ array_length = self.expand(array.length)
elem_type = array.type.mutable()
- print " if (%s && %s) {" % (instance, array.length)
- print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array.length)
- print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
+ print " if (%s && %s) {" % (instance, array_length)
+ print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
+ print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
print " _t[_i] = %s[_i];" % instance
self.allocated = True
self.visit(array.type, "_t[_i]")
self.header(api)
# Includes
- for header in api.headers:
- print header
+ for module in api.modules:
+ for header in module.headers:
+ print header
print
# Generate the serializer functions
# Function wrappers
self.interface = None
self.base = None
- map(self.traceFunctionDecl, api.functions)
- map(self.traceFunctionImpl, api.functions)
+ for function in api.getAllFunctions():
+ self.traceFunctionDecl(function)
+ for function in api.getAllFunctions():
+ self.traceFunctionImpl(function)
print
self.footer(api)
self.invokeFunction(function)
if not function.internal:
print ' trace::localWriter.beginLeave(_call);'
+ print ' if (%s) {' % self.wasFunctionSuccessful(function)
for arg in function.args:
if arg.output:
self.serializeArg(function, arg)
self.wrapArg(function, arg)
+ print ' }'
if function.type is not stdapi.Void:
self.serializeRet(function, "_result")
print ' trace::localWriter.endLeave();'
dispatch = prefix + function.name + suffix
print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
+ def wasFunctionSuccessful(self, function):
+ if function.type is stdapi.Void:
+ return 'true'
+ if str(function.type) == 'HRESULT':
+ return 'SUCCEEDED(_result)'
+ return 'false'
+
def serializeArg(self, function, arg):
print ' trace::localWriter.beginArg(%u);' % (arg.index,)
self.serializeArgValue(function, arg)
self.invokeMethod(interface, base, method)
print ' trace::localWriter.beginLeave(_call);'
+
+ print ' if (%s) {' % self.wasFunctionSuccessful(method)
for arg in method.args:
if arg.output:
self.serializeArg(method, arg)
self.wrapArg(method, arg)
+ print ' }'
if method.type is not stdapi.Void:
self.serializeRet(method, '_result')