]> git.cworth.org Git - apitrace/blobdiff - wrappers/trace.py
Introduce AttribArray, a code generator for pseudo-type attrib_list.
[apitrace] / wrappers / trace.py
index de020869db76089b3abc2caefbbb7e0139fc736a..17e4e9c9baf03a0158dbc4ebf02ee6a3afdd02f8 100644 (file)
@@ -83,6 +83,9 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
     def visitArray(self, array):
         self.visit(array.type)
 
+    def visitAttribArray(self, array):
+        pass
+
     def visitBlob(self, array):
         pass
 
@@ -138,7 +141,7 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
     def visitPolymorphic(self, polymorphic):
         if not polymorphic.contextLess:
             return
-        print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
+        print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
         print '    switch (selector) {'
         for cases, type in polymorphic.iterSwitch():
             for case in cases:
@@ -203,6 +206,57 @@ class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
         print '        trace::localWriter.writeNull();'
         print '    }'
 
+    def visitAttribArray(self, array, instance):
+        # iterate element by element and for each, decide if it is a key or value (which depends on the
+        # previous key). If it is a value, look up what it means and store it as the right type - usually
+        # int, some bitfield, or some enum.
+
+        # determine the array length, which is unfortunately needed by writeArray() up front
+        count = '_c' + array.keyType.tag
+        print '    int %s;' % count
+        print '    for (%(c)s = 0; %(array)s && %(array)s[%(c)s]; %(c)s++) {' % {'c': count, 'array': instance}
+        print '        switch (%(array)s[%(c)s]) {' % {'array': instance, 'c': count}
+        for key, valueType in array.valueTypes:
+            if valueType is not None:
+                print '        case %s:' % key
+        print '            %s++;' % count # only a null key marks the end; skip null values
+        print '            break;'
+        print '        }'
+        print '    }'
+        # ### not handling null attrib_list differently from empty
+        print '    trace::localWriter.beginArray(%s);' % count
+
+        # for each key / key-value pair write the key and the value, if the key requires one
+
+        index = '_i' + array.keyType.tag
+        print '    for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
+        self.visitEnum(array.keyType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
+        print '        switch (%(array)s[%(i)s]) {' % {'array': instance, 'i': index}
+        # write generic value the usual way
+        for key, valueType in array.valueTypes:
+            if valueType is not None:
+                print '        case %s:' % key
+                print '            %s++;' % index
+                print '            trace::localWriter.beginElement();'
+                self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
+                print '            trace::localWriter.endElement();'
+                print '            break;'
+        # unknown key, write an int value
+        print '        default:'
+        print '            %s++;' % index
+        print '            trace::localWriter.beginElement();'
+        print '            trace::localWriter.writeSInt(%(array)s[%(i)s]);'  % {'array': instance, 'i': index}
+        print '            trace::localWriter.endElement();'
+        # known key with no value, do nothing
+        for key, valueType in array.valueTypes:
+            if valueType is None:
+                print '        case %s:' % key
+        print '            break;'
+        print '        }'
+        print '    }'
+        print '    trace::localWriter.endArray();'
+
+
     def visitBlob(self, blob, instance):
         print '    trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
 
@@ -474,7 +528,7 @@ class Tracer:
 
         # No-op if tracing is disabled
         print '    if (!trace::isTracingEnabled()) {'
-        Tracer.invokeFunction(self, function)
+        self.doInvokeFunction(function)
         if function.type is not stdapi.Void:
             print '        return _result;'
         else:
@@ -493,6 +547,8 @@ class Tracer:
             for arg in function.args:
                 if not arg.output:
                     self.unwrapArg(function, arg)
+            for arg in function.args:
+                if not arg.output:
                     self.serializeArg(function, arg)
             print '    trace::localWriter.endEnter();'
         self.invokeFunction(function)
@@ -510,7 +566,11 @@ class Tracer:
                 self.wrapRet(function, "_result")
             print '    trace::localWriter.endLeave();'
 
-    def invokeFunction(self, function, prefix='_', suffix=''):
+    def invokeFunction(self, function):
+        self.doInvokeFunction(function)
+
+    def doInvokeFunction(self, function, prefix='_', suffix=''):
+        # Same as invokeFunction() but called both when trace is enabled or disabled.
         if function.type is stdapi.Void:
             result = ''
         else:
@@ -564,9 +624,6 @@ class Tracer:
     def wrapRet(self, function, instance):
         self.wrapValue(function.type, instance)
 
-    def unwrapRet(self, function, instance):
-        self.unwrapValue(function.type, instance)
-
     def needsWrapping(self, type):
         visitor = WrapDecider()
         visitor.visit(type)
@@ -628,7 +685,8 @@ class Tracer:
         # Private constructor
         print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
         for type, name, value in self.enumWrapperInterfaceVariables(interface):
-            print '    %s = %s;' % (name, value)
+            if value is not None:
+                print '    %s = %s;' % (name, value)
         print '}'
         print
 
@@ -697,6 +755,8 @@ class Tracer:
         for arg in method.args:
             if not arg.output:
                 self.unwrapArg(method, arg)
+        for arg in method.args:
+            if not arg.output:
                 self.serializeArg(method, arg)
         print '    trace::localWriter.endEnter();'
         
@@ -781,7 +841,7 @@ class Tracer:
         print '    %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
     
     def emit_memcpy(self, dest, src, length):
-        print '        unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
+        print '        unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig, true);'
         print '        trace::localWriter.beginArg(0);'
         print '        trace::localWriter.writePointer((uintptr_t)%s);' % dest
         print '        trace::localWriter.endArg();'