]> code.ossystems Code Review - meta-freescale.git/commitdiff
imx-gpu-apitrace: update recipe to use python3
authorAndrey Zhizhikin <andrey.z@gmail.com>
Wed, 22 Jan 2020 16:33:07 +0000 (16:33 +0000)
committerOtavio Salvador <otavio@ossystems.com.br>
Thu, 23 Jan 2020 20:51:00 +0000 (17:51 -0300)
Add component patches to be able to build it with python3. Python2 has
been dropped in oe-core, therefore the package source should be updated
to include python3 support.

Patches were cherry-picked from the upstream at
[https://github.com/apitrace/apitrace] from the [python3] branch.

Signed-off-by: Andrey Zhizhikin <andrey.zhizhikin@leica-geosystems.com>
recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0001-switch-from-python2-to-python3.patch [new file with mode: 0644]
recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0002-specs-Tie-Python-2-3-conversion-loose-ends.patch [new file with mode: 0644]
recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0003-scripts-Tie-Python-2-3-conversion-loose-ends.patch [new file with mode: 0644]
recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0004-scripts-Tie-a-few-more-Python-2-to-3-conversion-loos.patch [new file with mode: 0644]
recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace_7.1.0.bb

diff --git a/recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0001-switch-from-python2-to-python3.patch b/recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0001-switch-from-python2-to-python3.patch
new file mode 100644 (file)
index 0000000..27382c3
--- /dev/null
@@ -0,0 +1,10004 @@
+From bfa1b7c7e675f198f4573325f1252e91f80f0b4d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Piotr=20Podsiad=C5=82y?= <ppodsiadly@mykolab.com>
+Date: Thu, 3 Jan 2019 20:39:55 +0100
+Subject: [PATCH 1/4] switch from python2 to python3
+
+Upstream-Status: Backport [https://github.com/apitrace/apitrace/commit/0b8b019952f2668a5e8786cc2d331062b958f02e]
+
+(cherry picked from commit 0b8b019952f2668a5e8786cc2d331062b958f02e)
+Signed-off-by: Andrey Zhizhikin <andrey.zhizhikin@leica-geosystems.com>
+---
+ CMakeLists.txt                |    7 +-
+ cli/CMakeLists.txt            |    2 +-
+ dispatch/CMakeLists.txt       |    2 +-
+ dispatch/__init__.py          |    2 +-
+ dispatch/dispatch.py          |   56 +-
+ dispatch/glproc.py            |  204 +++----
+ retrace/CMakeLists.txt        |   14 +-
+ retrace/d3d9retrace.py        |  248 ++++----
+ retrace/ddrawretrace.py       |  102 ++--
+ retrace/dllretrace.py         |   46 +-
+ retrace/dxgiretrace.py        |  370 +++++------
+ retrace/dxgistate_so.py       |   98 +--
+ retrace/glretrace.py          |  660 ++++++++++----------
+ retrace/glstate_params.py     |  556 ++++++++---------
+ retrace/retrace.py            |  300 ++++-----
+ scripts/convert.py            |    4 +-
+ scripts/jsondiff.py           |   16 +-
+ scripts/jsonextractimages.py  |    2 +-
+ scripts/leaks.py              |  163 +++++
+ scripts/profileshader.py      |   18 +-
+ scripts/retracediff.py        |    6 +-
+ scripts/snapdiff.py           |    7 +-
+ scripts/tracediff.py          |   16 +-
+ scripts/unpickle.py           |   16 +-
+ specs/cglapi.py               |    6 +-
+ specs/d2d1.py                 |    6 +-
+ specs/d3d.py                  |    8 +-
+ specs/d3d10.py                |    4 +-
+ specs/d3d10sdklayers.py       |    2 +-
+ specs/d3d11.py                |    4 +-
+ specs/d3d11sdklayers.py       |    2 +-
+ specs/d3d8.py                 |    6 +-
+ specs/d3d8caps.py             |    4 +-
+ specs/d3d8types.py            |    2 +-
+ specs/d3d9.py                 |    6 +-
+ specs/d3d9caps.py             |    4 +-
+ specs/d3d9types.py            |    2 +-
+ specs/d3dcaps.py              |    4 +-
+ specs/d3dtypes.py             |    2 +-
+ specs/dcommon.py              |    2 +-
+ specs/dcomp.py                |  303 +++++++++
+ specs/ddraw.py                |    2 +-
+ specs/debug.py                |    2 +-
+ specs/dwrite.py               |    4 +-
+ specs/dxgi.py                 |    2 +-
+ specs/dxva2.py                |    2 +-
+ specs/eglapi.py               |    6 +-
+ specs/eglenum.py              |    2 +-
+ specs/glapi.py                |    6 +-
+ specs/glparams.py             |    4 +-
+ specs/gltypes.py              |    2 +-
+ specs/glxapi.py               |    4 +-
+ specs/scripts/c2api.py        |   40 +-
+ specs/scripts/cxx2api.py      |  488 +++++++++++++++
+ specs/scripts/spec2api.py     |    6 +-
+ specs/scripts/txt2api.py      |    8 +-
+ specs/scripts/xml2api.py      |    6 +-
+ specs/scripts/xml2enum.py     |    4 +-
+ specs/scripts/xml2glparams.py |    4 +-
+ specs/stdapi.py               |   43 +-
+ specs/wglapi.py               |    6 +-
+ specs/wglenum.py              |    2 +-
+ specs/winapi.py               |    2 +-
+ wrappers/CMakeLists.txt       |   18 +-
+ wrappers/cgltrace.py          |   74 +--
+ wrappers/d2d1trace.py         |   18 +-
+ wrappers/d3d8trace.py         |   36 +-
+ wrappers/d3d9trace.py         |   62 +-
+ wrappers/ddrawtrace.py        |   12 +-
+ wrappers/dlltrace.py          |   36 +-
+ wrappers/dxgitrace.py         |   98 +--
+ wrappers/egltrace.py          |  420 ++++++-------
+ wrappers/gltrace.py           | 1080 ++++++++++++++++-----------------
+ wrappers/glxtrace.py          |   54 +-
+ wrappers/trace.py             |  707 ++++++++++-----------
+ wrappers/wgltrace.py          |   86 +--
+ 76 files changed, 3803 insertions(+), 2825 deletions(-)
+ create mode 100755 scripts/leaks.py
+ create mode 100644 specs/dcomp.py
+ create mode 100755 specs/scripts/cxx2api.py
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 900028c6..03ffd07c 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -104,10 +104,7 @@ else ()
+     endmacro()
+ endif ()
+-find_host_package (PythonInterp 2.7 REQUIRED)
+-if (NOT PYTHON_VERSION_MAJOR EQUAL 2)
+-    message (FATAL_ERROR "Python 2.x required and requested, but Python ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} found.")
+-endif ()
++find_host_package(Python3 COMPONENTS Interpreter REQUIRED)
+ find_package (Threads)
+@@ -591,7 +588,7 @@ set (CPACK_PACKAGE_VERSION_MINOR "0")
+ # Use current date in YYYYMMDD format as patch number 
+ execute_process (
+-    COMMAND ${PYTHON_EXECUTABLE} -c "import time, sys; sys.stdout.write(time.strftime('%Y%m%d'))"
++    COMMAND ${Python3_EXECUTABLE} -c "import time, sys; sys.stdout.write(time.strftime('%Y%m%d'))"
+     OUTPUT_VARIABLE CPACK_PACKAGE_VERSION_PATCH
+ )
+diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt
+index 9b621bb1..eb5d485d 100644
+--- a/cli/CMakeLists.txt
++++ b/cli/CMakeLists.txt
+@@ -13,7 +13,7 @@ add_definitions(
+ if (WIN32)
+     add_definitions (-DAPITRACE_PYTHON_EXECUTABLE="python")
+ else ()
+-    add_definitions (-DAPITRACE_PYTHON_EXECUTABLE="${PYTHON_EXECUTABLE}")
++    add_definitions (-DAPITRACE_PYTHON_EXECUTABLE="${Python3_EXECUTABLE}")
+ endif ()
+ add_executable (apitrace
+diff --git a/dispatch/CMakeLists.txt b/dispatch/CMakeLists.txt
+index d023e6e9..e51eec48 100644
+--- a/dispatch/CMakeLists.txt
++++ b/dispatch/CMakeLists.txt
+@@ -7,7 +7,7 @@ add_custom_command (
+     OUTPUT
+         ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
+         ${CMAKE_CURRENT_BINARY_DIR}/glproc.cpp
+-    COMMAND ${PYTHON_EXECUTABLE}
++    COMMAND ${Python3_EXECUTABLE}
+         ${CMAKE_CURRENT_SOURCE_DIR}/glproc.py
+         ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
+         ${CMAKE_CURRENT_BINARY_DIR}/glproc.cpp
+diff --git a/dispatch/__init__.py b/dispatch/__init__.py
+index b872135e..d8e8596e 100644
+--- a/dispatch/__init__.py
++++ b/dispatch/__init__.py
+@@ -1 +1 @@
+-from dispatch import *
++from .dispatch import *
+diff --git a/dispatch/dispatch.py b/dispatch/dispatch.py
+index 9e778561..e1dd8bc9 100644
+--- a/dispatch/dispatch.py
++++ b/dispatch/dispatch.py
+@@ -58,18 +58,18 @@ class Dispatcher:
+         # define standard name aliases for convenience, but only when not
+         # tracing, as that would cause symbol clashing with the tracing
+         # functions
+-        print '#ifdef RETRACE'
++        print('#ifdef RETRACE')
+         for function in module.functions:
+-            print '#define %s _%s' % (function.name, function.name)
+-        print '#endif /* RETRACE */'
+-        print
++            print('#define %s _%s' % (function.name, function.name))
++        print('#endif /* RETRACE */')
++        print()
+     
+     def dispatchFunctionDecl(self, module, function):
+         ptype = function_pointer_type(function)
+         pvalue = function_pointer_value(function)
+-        print 'typedef ' + function.prototype('* %s' % ptype) + ';'
+-        print 'extern %s %s;' % (ptype, pvalue)
+-        print
++        print('typedef ' + function.prototype('* %s' % ptype) + ';')
++        print('extern %s %s;' % (ptype, pvalue))
++        print()
+     def dispatchModuleImpl(self, module):
+         for function in module.functions:
+@@ -84,19 +84,19 @@ class Dispatcher:
+         else:
+             ret = 'return '
+-        print 'static ' + function.prototype('_fail_' + function.name) + ' {'
++        print('static ' + function.prototype('_fail_' + function.name) + ' {')
+         self.failFunction(function)
+-        print '}'
+-        print
++        print('}')
++        print()
+-        print 'static ' + function.prototype('_get_' + function.name) + ' {'
++        print('static ' + function.prototype('_get_' + function.name) + ' {')
+         self.invokeGetProcAddress(module, function)
+-        print '    %s%s(%s);' % (ret, pvalue, ', '.join([str(arg.name) for arg in function.args]))
+-        print '}'
+-        print
++        print('    %s%s(%s);' % (ret, pvalue, ', '.join([str(arg.name) for arg in function.args])))
++        print('}')
++        print()
+-        print '%s %s = &%s;' % (ptype, pvalue, '_get_' + function.name)
+-        print
++        print('%s %s = &%s;' % (ptype, pvalue, '_get_' + function.name))
++        print()
+     def getProcAddressName(self, module, function):
+         raise NotImplementedError
+@@ -105,25 +105,25 @@ class Dispatcher:
+         ptype = function_pointer_type(function)
+         pvalue = function_pointer_value(function)
+         getProcAddressName = self.getProcAddressName(module, function)
+-        print '    %s _ptr;' % (ptype,)
+-        print '    _ptr = (%s)%s("%s");' % (ptype, getProcAddressName, function.name)
+-        print '    if (!_ptr) {'
+-        print '        _ptr = &%s;' % ('_fail_' + function.name)
+-        print '    }'
+-        print '    %s = _ptr;' % (pvalue,)
++        print('    %s _ptr;' % (ptype,))
++        print('    _ptr = (%s)%s("%s");' % (ptype, getProcAddressName, function.name))
++        print('    if (!_ptr) {')
++        print('        _ptr = &%s;' % ('_fail_' + function.name))
++        print('    }')
++        print('    %s = _ptr;' % (pvalue,))
+     def failFunction(self, function):
+-        print r'    const char *_name = "%s";' % function.name
++        print(r'    const char *_name = "%s";' % function.name)
+         if function.type is stdapi.Void or function.fail is not None:
+-            print r'    os::log("warning: ignoring call to unavailable function %s\n", _name);'
++            print(r'    os::log("warning: ignoring call to unavailable function %s\n", _name);')
+             if function.type is stdapi.Void:
+                 assert function.fail is None
+-                print '    return;' 
++                print('    return;') 
+             else:
+                 assert function.fail is not None
+-                print '    return %s;' % function.fail
++                print('    return %s;' % function.fail)
+         else:
+-            print r'    os::log("error: unavailable function %s\n", _name);'
+-            print r'    os::abort();'
++            print(r'    os::log("error: unavailable function %s\n", _name);')
++            print(r'    os::abort();')
+diff --git a/dispatch/glproc.py b/dispatch/glproc.py
+index f26a4f7d..93bba232 100644
+--- a/dispatch/glproc.py
++++ b/dispatch/glproc.py
+@@ -506,15 +506,15 @@ class GlDispatcher(Dispatcher):
+         if sys.platform == 'darwin':
+             # Fallback to EXT_debug_label on MacOSX, some enums need to be translated.
+             if function.name in ('glObjectLabel', 'glObjectLabelKHR'):
+-                print r'    if (translateDebugLabelIdentifier(identifier)) {'
+-                print r'        _glLabelObjectEXT(identifier, name, length < 0 ? 0 : length, length == 0 ? "" : label);'
+-                print r'        return;'
+-                print r'    }'
++                print(r'    if (translateDebugLabelIdentifier(identifier)) {')
++                print(r'        _glLabelObjectEXT(identifier, name, length < 0 ? 0 : length, length == 0 ? "" : label);')
++                print(r'        return;')
++                print(r'    }')
+             if function.name in ('glGetObjectLabel', 'glGetObjectLabelKHR'):
+-                print r'    if (translateDebugLabelIdentifier(identifier)) {'
+-                print r'        _glGetObjectLabelEXT(identifier, name, bufSize, length, label);'
+-                print r'        return;'
+-                print r'    }'
++                print(r'    if (translateDebugLabelIdentifier(identifier)) {')
++                print(r'        _glGetObjectLabelEXT(identifier, name, bufSize, length, label);')
++                print(r'        return;')
++                print(r'    }')
+         if function.name in (
+             # GL_KHR_debug
+             'glDebugMessageControl',
+@@ -549,25 +549,25 @@ class GlDispatcher(Dispatcher):
+         ):
+             return
+         if function.name.startswith('glGetObjectLabel'):
+-            print r'    if (length != 0) *length = 0;'
+-            print r'    if (label != 0 && bufSize > 0) *label = 0;'
++            print(r'    if (length != 0) *length = 0;')
++            print(r'    if (label != 0 && bufSize > 0) *label = 0;')
+             return
+         if function.name == 'glGetDebugMessageLogAMD':
+-            print r'    if (categories != 0) *categories = 0;'
+-            print r'    if (ids != 0) *ids = 0;'
+-            print r'    if (severities != 0) *severities = 0;'
+-            print r'    if (lengths != 0) *lengths = 0;'
+-            print r'    if (message != 0 && bufsize > 0) *message = 0;'
+-            print r'    return 0;'
++            print(r'    if (categories != 0) *categories = 0;')
++            print(r'    if (ids != 0) *ids = 0;')
++            print(r'    if (severities != 0) *severities = 0;')
++            print(r'    if (lengths != 0) *lengths = 0;')
++            print(r'    if (message != 0 && bufsize > 0) *message = 0;')
++            print(r'    return 0;')
+             return
+         if function.name.startswith('glGetDebugMessageLog'):
+-            print r'    if (sources != 0) *sources = 0;'
+-            print r'    if (types != 0) *types = 0;'
+-            print r'    if (ids != 0) *ids = 0;'
+-            print r'    if (severities != 0) *severities = 0;'
+-            print r'    if (lengths != 0) *lengths = 0;'
+-            print r'    if (messageLog != 0 && bufsize > 0) *messageLog = 0;'
+-            print r'    return 0;'
++            print(r'    if (sources != 0) *sources = 0;')
++            print(r'    if (types != 0) *types = 0;')
++            print(r'    if (ids != 0) *ids = 0;')
++            print(r'    if (severities != 0) *severities = 0;')
++            print(r'    if (lengths != 0) *lengths = 0;')
++            print(r'    if (messageLog != 0 && bufsize > 0) *messageLog = 0;')
++            print(r'    return 0;')
+             return
+         Dispatcher.failFunction(self, function)
+@@ -577,96 +577,96 @@ if __name__ == '__main__':
+     decl, impl = sys.argv[1:]
+     sys.stdout = open(decl, 'wt')
+-    print
+-    print '#pragma once'
+-    print
+-    print '#include "glimports.hpp"'
+-    print
+-    print '#if defined(_WIN32)'
+-    print 'extern HMODULE _libGlHandle;'
+-    print '#else'
+-    print 'extern void * _libGlHandle;'
+-    print '#endif'
+-    print
+-    print 'void * _getPublicProcAddress(const char *procName);'
+-    print 'void * _getPrivateProcAddress(const char *procName);'
+-    print
++    print()
++    print('#pragma once')
++    print()
++    print('#include "glimports.hpp"')
++    print()
++    print('#if defined(_WIN32)')
++    print('extern HMODULE _libGlHandle;')
++    print('#else')
++    print('extern void * _libGlHandle;')
++    print('#endif')
++    print()
++    print('void * _getPublicProcAddress(const char *procName);')
++    print('void * _getPrivateProcAddress(const char *procName);')
++    print()
+     dispatcher = GlDispatcher()
+-    print
++    print()
+     dispatcher.dispatchModuleDecl(eglapi)
+-    print
+-    print '#if defined(_WIN32)'
+-    print
++    print()
++    print('#if defined(_WIN32)')
++    print()
+     dispatcher.dispatchModuleDecl(wglapi)
+-    print
+-    print '#elif defined(__APPLE__)'
+-    print
++    print()
++    print('#elif defined(__APPLE__)')
++    print()
+     dispatcher.dispatchModuleDecl(cglapi)
+-    print
+-    print '#elif defined(HAVE_X11)'
+-    print
++    print()
++    print('#elif defined(HAVE_X11)')
++    print()
+     dispatcher.dispatchModuleDecl(glxapi)
+-    print
+-    print '#endif'
+-    print
++    print()
++    print('#endif')
++    print()
+     dispatcher.dispatchModuleDecl(glapi)
+-    print
++    print()
+     sys.stdout = open(impl, 'wt')
+-    print
+-    print '#include "glproc.hpp"'
+-    print '#include "os.hpp"'
+-    print
++    print()
++    print('#include "glproc.hpp"')
++    print('#include "os.hpp"')
++    print()
+     dispatcher = GlDispatcher()
+-    print
++    print()
+     dispatcher.dispatchModuleImpl(eglapi)
+-    print
+-    print '#if defined(_WIN32)'
+-    print
++    print()
++    print('#if defined(_WIN32)')
++    print()
+     dispatcher.dispatchModuleImpl(wglapi)
+-    print
+-    print '#elif defined(__APPLE__)'
+-    print
+-    print 'static inline bool'
+-    print 'translateDebugLabelIdentifier(GLenum & identifier)'
+-    print '{'
+-    print '    switch (identifier) {'
+-    print '    case GL_TEXTURE:'
+-    print '    case GL_FRAMEBUFFER:'
+-    print '    case GL_RENDERBUFFER:'
+-    print '    case GL_SAMPLER:'
+-    print '    case GL_TRANSFORM_FEEDBACK:'
+-    print '       return true;'
+-    print '    case GL_BUFFER:'
+-    print '       identifier = GL_BUFFER_OBJECT_EXT;'
+-    print '       return true;'
+-    print '    case GL_SHADER:'
+-    print '       identifier = GL_SHADER_OBJECT_EXT;'
+-    print '       return true;'
+-    print '    case GL_PROGRAM:'
+-    print '       identifier = GL_PROGRAM_OBJECT_EXT;'
+-    print '       return true;'
+-    print '    case GL_VERTEX_ARRAY:'
+-    print '       identifier = GL_VERTEX_ARRAY_OBJECT_EXT;'
+-    print '       return true;'
+-    print '    case GL_QUERY:'
+-    print '       identifier = GL_QUERY_OBJECT_EXT;'
+-    print '       return true;'
+-    print '    case GL_PROGRAM_PIPELINE:'
+-    print '       identifier = GL_PROGRAM_PIPELINE_OBJECT_EXT;'
+-    print '       return true;'
+-    print '    default:'
+-    print '       return false;'
+-    print '    }'
+-    print '}'
+-    print
++    print()
++    print('#elif defined(__APPLE__)')
++    print()
++    print('static inline bool')
++    print('translateDebugLabelIdentifier(GLenum & identifier)')
++    print('{')
++    print('    switch (identifier) {')
++    print('    case GL_TEXTURE:')
++    print('    case GL_FRAMEBUFFER:')
++    print('    case GL_RENDERBUFFER:')
++    print('    case GL_SAMPLER:')
++    print('    case GL_TRANSFORM_FEEDBACK:')
++    print('       return true;')
++    print('    case GL_BUFFER:')
++    print('       identifier = GL_BUFFER_OBJECT_EXT;')
++    print('       return true;')
++    print('    case GL_SHADER:')
++    print('       identifier = GL_SHADER_OBJECT_EXT;')
++    print('       return true;')
++    print('    case GL_PROGRAM:')
++    print('       identifier = GL_PROGRAM_OBJECT_EXT;')
++    print('       return true;')
++    print('    case GL_VERTEX_ARRAY:')
++    print('       identifier = GL_VERTEX_ARRAY_OBJECT_EXT;')
++    print('       return true;')
++    print('    case GL_QUERY:')
++    print('       identifier = GL_QUERY_OBJECT_EXT;')
++    print('       return true;')
++    print('    case GL_PROGRAM_PIPELINE:')
++    print('       identifier = GL_PROGRAM_PIPELINE_OBJECT_EXT;')
++    print('       return true;')
++    print('    default:')
++    print('       return false;')
++    print('    }')
++    print('}')
++    print()
+     dispatcher.dispatchModuleImpl(cglapi)
+-    print
+-    print '#elif defined(HAVE_X11)'
+-    print
++    print()
++    print('#elif defined(HAVE_X11)')
++    print()
+     dispatcher.dispatchModuleImpl(glxapi)
+-    print
+-    print '#endif'
+-    print
++    print()
++    print('#endif')
++    print()
+     dispatcher.dispatchModuleImpl(glapi)
+-    print
++    print()
+diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt
+index c0c4f316..2475abb8 100644
+--- a/retrace/CMakeLists.txt
++++ b/retrace/CMakeLists.txt
+@@ -14,7 +14,7 @@ add_definitions (-DRETRACE)
+ add_custom_command (
+     OUTPUT glretrace_gl.cpp
+-    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/glretrace_gl.cpp
++    COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/glretrace_gl.cpp
+     DEPENDS
+         glretrace.py
+         retrace.py
+@@ -25,7 +25,7 @@ add_custom_command (
+ add_custom_command (
+     OUTPUT glstate_params.cpp
+-    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glstate_params.py > ${CMAKE_CURRENT_BINARY_DIR}/glstate_params.cpp
++    COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glstate_params.py > ${CMAKE_CURRENT_BINARY_DIR}/glstate_params.cpp
+     DEPENDS
+         glstate_params.py
+         ${CMAKE_SOURCE_DIR}/specs/glparams.py
+@@ -273,7 +273,7 @@ if (WIN32)
+         include_directories (BEFORE SYSTEM ${DirectX_D3D_INCLUDE_DIR})
+         add_custom_command (
+             OUTPUT d3dretrace_ddraw.cpp
+-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/ddrawretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_ddraw.cpp
++            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/ddrawretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_ddraw.cpp
+             DEPENDS
+                 ddrawretrace.py
+                 dllretrace.py
+@@ -306,7 +306,7 @@ if (WIN32)
+     endif ()
+     add_custom_command (
+         OUTPUT d3dretrace_d3d8.cpp
+-        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9retrace.py d3d8 ${HAVE_D3D8} > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d8.cpp
++        COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9retrace.py d3d8 ${HAVE_D3D8} > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d8.cpp
+         DEPENDS
+             d3d9retrace.py
+             dllretrace.py
+@@ -327,7 +327,7 @@ if (WIN32)
+     endif ()
+     add_custom_command (
+         OUTPUT d3dretrace_d3d9.cpp
+-        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9retrace.py d3d9 ${HAVE_D3D9} > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d9.cpp
++        COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9retrace.py d3d9 ${HAVE_D3D9} > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d9.cpp
+         DEPENDS
+             d3d9retrace.py
+             dllretrace.py
+@@ -359,7 +359,7 @@ if (WIN32)
+         )
+         add_custom_command (
+             OUTPUT dxgistate_so.cpp
+-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgistate_so.py > ${CMAKE_CURRENT_BINARY_DIR}/dxgistate_so.cpp
++            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgistate_so.py > ${CMAKE_CURRENT_BINARY_DIR}/dxgistate_so.cpp
+             DEPENDS
+                 ${CMAKE_CURRENT_SOURCE_DIR}/dxgistate_so.py
+                 ${CMAKE_SOURCE_DIR}/specs/d3d11.py
+@@ -372,7 +372,7 @@ if (WIN32)
+         )
+         add_custom_command (
+             OUTPUT d3dretrace_dxgi.cpp
+-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgiretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_dxgi.cpp
++            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgiretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_dxgi.cpp
+             DEPENDS
+                 dxgiretrace.py
+                 dllretrace.py
+diff --git a/retrace/d3d9retrace.py b/retrace/d3d9retrace.py
+index 7313acc9..22364476 100644
+--- a/retrace/d3d9retrace.py
++++ b/retrace/d3d9retrace.py
+@@ -35,32 +35,32 @@ from specs.stdapi import API
+ class D3DRetracer(Retracer):
+     def retraceApi(self, api):
+-        print '// Swizzling mapping for lock addresses'
+-        print 'typedef std::pair<void *, UINT> MappingKey;'
+-        print 'static std::map<MappingKey, void *> _maps;'
+-        print
++        print('// Swizzling mapping for lock addresses')
++        print('typedef std::pair<void *, UINT> MappingKey;')
++        print('static std::map<MappingKey, void *> _maps;')
++        print()
+         Retracer.retraceApi(self, api)
+     def invokeFunction(self, function):
+         if function.name in ('Direct3DCreate9', 'Direct3DCreate9Ex'):
+-            print 'if (retrace::debug >= 2 && !g_szD3D9DllName && LoadLibraryA("d3d9d.dll")) {'
+-            print '    /*'
+-            print '     * D3D9D only works for simple applications, it will often report bogus errors'
+-            print '     * on complex traces, or traces which use unofficial D3D9 features.'
+-            print '     */'
+-            print '    g_szD3D9DllName = "d3d9d.dll";'
+-            print '    SDKVersion |= 0x80000000;'
+-            print '} else {'
+-            print '    SDKVersion &= ~0x80000000;'
+-            print '}'
++            print('if (retrace::debug >= 2 && !g_szD3D9DllName && LoadLibraryA("d3d9d.dll")) {')
++            print('    /*')
++            print('     * D3D9D only works for simple applications, it will often report bogus errors')
++            print('     * on complex traces, or traces which use unofficial D3D9 features.')
++            print('     */')
++            print('    g_szD3D9DllName = "d3d9d.dll";')
++            print('    SDKVersion |= 0x80000000;')
++            print('} else {')
++            print('    SDKVersion &= ~0x80000000;')
++            print('}')
+         # d3d8d.dll can be found in the Aug 2007 DXSDK.  It works on XP, but
+         # not on Windows 7.
+         if function.name in ('Direct3DCreate8'):
+-            print 'if (retrace::debug >= 2 && !g_szD3D8DllName && LoadLibraryA("d3d8d.dll")) {'
+-            print '    g_szD3D8DllName = "d3d8d.dll";'
+-            print '}'
++            print('if (retrace::debug >= 2 && !g_szD3D8DllName && LoadLibraryA("d3d8d.dll")) {')
++            print('    g_szD3D8DllName = "d3d8d.dll";')
++            print('}')
+         Retracer.invokeFunction(self, function)
+@@ -73,37 +73,37 @@ class D3DRetracer(Retracer):
+         # keep track of the last used device for state dumping
+         if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'):
+             if method.name == 'Release':
+-                print r'    if (call.ret->toUInt() == 0) {'
+-                print r'        d3d9Dumper.unbindDevice(_this);'
+-                print r'    }'
++                print(r'    if (call.ret->toUInt() == 0) {')
++                print(r'        d3d9Dumper.unbindDevice(_this);')
++                print(r'    }')
+             else:
+-                print r'    d3d9Dumper.bindDevice(_this);'
++                print(r'    d3d9Dumper.bindDevice(_this);')
+         if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'):
+             if method.name == 'Release':
+-                print r'    if (call.ret->toUInt() == 0) {'
+-                print r'        d3d8Dumper.unbindDevice(_this);'
+-                print r'    }'
++                print(r'    if (call.ret->toUInt() == 0) {')
++                print(r'        d3d8Dumper.unbindDevice(_this);')
++                print(r'    }')
+             else:
+-                print r'    d3d8Dumper.bindDevice(_this);'
++                print(r'    d3d8Dumper.bindDevice(_this);')
+         # create windows as neccessary
+         if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'):
+-            print r'    HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);'
+-            print r'    pPresentationParameters->hDeviceWindow = hWnd;'
++            print(r'    HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);')
++            print(r'    pPresentationParameters->hDeviceWindow = hWnd;')
+             if 'hFocusWindow' in method.argNames():
+-                print r'    hFocusWindow = hWnd;'
++                print(r'    hFocusWindow = hWnd;')
+             # force windowed mode
+-            print r'    if (retrace::forceWindowed) {'
+-            print r'        pPresentationParameters->Windowed = TRUE;'
+-            print r'        pPresentationParameters->FullScreen_RefreshRateInHz = 0;'
++            print(r'    if (retrace::forceWindowed) {')
++            print(r'        pPresentationParameters->Windowed = TRUE;')
++            print(r'        pPresentationParameters->FullScreen_RefreshRateInHz = 0;')
+             if interface.name.startswith('IDirect3D8'):
+-                print r'        pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;'
+-            print r'    }'
++                print(r'        pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;')
++            print(r'    }')
+             if 'BehaviorFlags' in method.argNames():
+-                print r'    if (retrace::dumpingState) {'
+-                print r'        BehaviorFlags &= ~D3DCREATE_PUREDEVICE;'
+-                print r'    }'
++                print(r'    if (retrace::dumpingState) {')
++                print(r'        BehaviorFlags &= ~D3DCREATE_PUREDEVICE;')
++                print(r'    }')
+             # On D3D8, ensure we use BackBufferFormat compatible with the
+             # current DisplayFormat.
+@@ -113,76 +113,76 @@ class D3DRetracer(Retracer):
+             # valid values for BackBufferFormat include D3DFMT_X1R5G5B5 and
+             # D3DFMT_A1R5G5B5, but exclude D3DFMT_R5G6B5.
+             if interface.name.startswith('IDirect3D8'):
+-                print r'    if (pPresentationParameters->Windowed) {'
+-                print r'        D3DDISPLAYMODE Mode;'
+-                print r'        HRESULT hr;'
+-                print r'        hr = _this->GetAdapterDisplayMode(Adapter, &Mode);'
+-                print r'        assert(SUCCEEDED(hr));'
+-                print r'        hr = _this->CheckDeviceType(Adapter, DeviceType, Mode.Format, pPresentationParameters->BackBufferFormat, pPresentationParameters->Windowed);'
+-                print r'        if (hr == D3DERR_NOTAVAILABLE) {'
+-                print r'            retrace::warning(call) << "forcing back buffer format to match display mode format\n";'
+-                print r'            pPresentationParameters->BackBufferFormat = Mode.Format;'
+-                print r'        }'
+-                print r'    }'
++                print(r'    if (pPresentationParameters->Windowed) {')
++                print(r'        D3DDISPLAYMODE Mode;')
++                print(r'        HRESULT hr;')
++                print(r'        hr = _this->GetAdapterDisplayMode(Adapter, &Mode);')
++                print(r'        assert(SUCCEEDED(hr));')
++                print(r'        hr = _this->CheckDeviceType(Adapter, DeviceType, Mode.Format, pPresentationParameters->BackBufferFormat, pPresentationParameters->Windowed);')
++                print(r'        if (hr == D3DERR_NOTAVAILABLE) {')
++                print(r'            retrace::warning(call) << "forcing back buffer format to match display mode format\n";')
++                print(r'            pPresentationParameters->BackBufferFormat = Mode.Format;')
++                print(r'        }')
++                print(r'    }')
+         
+         if method.name in self.createDeviceMethodNames:
+             # override the device type
+-            print r'    switch (retrace::driver) {'
+-            print r'    case retrace::DRIVER_HARDWARE:'
+-            print r'        DeviceType = D3DDEVTYPE_HAL;'
+-            print r'        break;'
+-            print r'    case retrace::DRIVER_SOFTWARE:'
+-            print r'    case retrace::DRIVER_REFERENCE:'
+-            print r'        DeviceType = D3DDEVTYPE_REF;'
+-            print r'        break;'
+-            print r'    case retrace::DRIVER_NULL:'
++            print(r'    switch (retrace::driver) {')
++            print(r'    case retrace::DRIVER_HARDWARE:')
++            print(r'        DeviceType = D3DDEVTYPE_HAL;')
++            print(r'        break;')
++            print(r'    case retrace::DRIVER_SOFTWARE:')
++            print(r'    case retrace::DRIVER_REFERENCE:')
++            print(r'        DeviceType = D3DDEVTYPE_REF;')
++            print(r'        break;')
++            print(r'    case retrace::DRIVER_NULL:')
+             if interface.name.startswith('IDirect3D9'):
+-                print r'        DeviceType = D3DDEVTYPE_NULLREF;'
++                print(r'        DeviceType = D3DDEVTYPE_NULLREF;')
+             else:
+-                print r'        retrace::warning(call) << "null driver not supported\n";'
+-            print r'        break;'
+-            print r'    case retrace::DRIVER_MODULE:'
+-            print r'        retrace::warning(call) << "driver module not supported\n";'
+-            print r'        break;'
+-            print r'    default:'
+-            print r'        assert(0);'
+-            print r'        /* fall-through */'
+-            print r'    case retrace::DRIVER_DEFAULT:'
+-            print r'        break;'
+-            print r'    }'
++                print(r'        retrace::warning(call) << "null driver not supported\n";')
++            print(r'        break;')
++            print(r'    case retrace::DRIVER_MODULE:')
++            print(r'        retrace::warning(call) << "driver module not supported\n";')
++            print(r'        break;')
++            print(r'    default:')
++            print(r'        assert(0);')
++            print(r'        /* fall-through */')
++            print(r'    case retrace::DRIVER_DEFAULT:')
++            print(r'        break;')
++            print(r'    }')
+         if method.name in ('Reset', 'ResetEx'):
+             # force windowed mode
+-            print r'    if (retrace::forceWindowed) {'
+-            print r'        pPresentationParameters->Windowed = TRUE;'
+-            print r'        pPresentationParameters->FullScreen_RefreshRateInHz = 0;'
+-            print r'    }'
++            print(r'    if (retrace::forceWindowed) {')
++            print(r'        pPresentationParameters->Windowed = TRUE;')
++            print(r'        pPresentationParameters->FullScreen_RefreshRateInHz = 0;')
++            print(r'    }')
+             # resize window
+-            print r'    if (pPresentationParameters->Windowed) {'
+-            print r'        d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);'
+-            print r'    }'
++            print(r'    if (pPresentationParameters->Windowed) {')
++            print(r'        d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);')
++            print(r'    }')
+         # notify frame has been completed
+         if method.name in ('Present', 'PresentEx'):
+             if interface.name.startswith('IDirect3DSwapChain9'):
+-                print r'    d3d9scDumper.bindDevice(_this);'
+-            print r'    retrace::frameComplete(call);'
+-            print r'    hDestWindowOverride = NULL;'
++                print(r'    d3d9scDumper.bindDevice(_this);')
++            print(r'    retrace::frameComplete(call);')
++            print(r'    hDestWindowOverride = NULL;')
+         # Ensure textures can be locked when dumping
+         # TODO: Pre-check with CheckDeviceFormat
+         if method.name in ('CreateTexture', 'CreateCubeTexture', 'CreateVolumeTexture'):
+-            print r'    if (retrace::dumpingState &&'
+-            print r'        Pool == D3DPOOL_DEFAULT &&'
+-            print r'        !(Usage & (D3DUSAGE_RENDERTARGET|D3DUSAGE_DEPTHSTENCIL))) {'
+-            print r'        Usage |= D3DUSAGE_DYNAMIC;'
+-            print r'    }'
++            print(r'    if (retrace::dumpingState &&')
++            print(r'        Pool == D3DPOOL_DEFAULT &&')
++            print(r'        !(Usage & (D3DUSAGE_RENDERTARGET|D3DUSAGE_DEPTHSTENCIL))) {')
++            print(r'        Usage |= D3DUSAGE_DYNAMIC;')
++            print(r'    }')
+         if 'pSharedHandle' in method.argNames():
+-            print r'    if (pSharedHandle) {'
+-            print r'        retrace::warning(call) << "shared surfaces unsupported\n";'
+-            print r'        pSharedHandle = NULL;'
+-            print r'    }'
++            print(r'    if (pSharedHandle) {')
++            print(r'        retrace::warning(call) << "shared surfaces unsupported\n";')
++            print(r'        pSharedHandle = NULL;')
++            print(r'    }')
+         if method.name in ('Lock', 'LockRect', 'LockBox'):
+             # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no
+@@ -190,7 +190,7 @@ class D3DRetracer(Retracer):
+             mapFlagsArg = method.getArgByName('Flags')
+             for flag in mapFlagsArg.type.values:
+                 if flag.endswith('_DONOTWAIT'):
+-                    print r'    Flags &= ~%s;' % flag
++                    print(r'    Flags &= ~%s;' % flag)
+         Retracer.invokeInterfaceMethod(self, interface, method)
+@@ -201,7 +201,7 @@ class D3DRetracer(Retracer):
+         # process events after presents
+         if method.name == 'Present':
+-            print r'    d3dretrace::processEvents();'
++            print(r'    d3dretrace::processEvents();')
+         def mapping_subkey():
+             if 'Level' in method.argNames():
+@@ -210,35 +210,35 @@ class D3DRetracer(Retracer):
+                 return ('0',)
+         if method.name in ('Lock', 'LockRect', 'LockBox'):
+-            print '    VOID *_pbData = NULL;'
+-            print '    size_t _MappedSize = 0;'
+-            print '    if (!(Flags & D3DLOCK_READONLY)) {'
+-            print '        _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1])
+-            print '    }'
+-            print '    if (_MappedSize) {'
+-            print '        _maps[MappingKey(_this, %s)] = _pbData;' % mapping_subkey()
++            print('    VOID *_pbData = NULL;')
++            print('    size_t _MappedSize = 0;')
++            print('    if (!(Flags & D3DLOCK_READONLY)) {')
++            print('        _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]))
++            print('    }')
++            print('    if (_MappedSize) {')
++            print('        _maps[MappingKey(_this, %s)] = _pbData;' % mapping_subkey())
+             self.checkPitchMismatch(method)
+-            print '    } else {'
+-            print '        return;'
+-            print '    }'
++            print('    } else {')
++            print('        return;')
++            print('    }')
+         
+         if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'):
+-            print '    VOID *_pbData = 0;'
+-            print '    MappingKey _mappingKey(_this, %s);' % mapping_subkey()
+-            print '    _pbData = _maps[_mappingKey];'
+-            print '    if (_pbData) {'
+-            print '        retrace::delRegionByPointer(_pbData);'
+-            print '        _maps[_mappingKey] = 0;'
+-            print '    }'
++            print('    VOID *_pbData = 0;')
++            print('    MappingKey _mappingKey(_this, %s);' % mapping_subkey())
++            print('    _pbData = _maps[_mappingKey];')
++            print('    if (_pbData) {')
++            print('        retrace::delRegionByPointer(_pbData);')
++            print('        _maps[_mappingKey] = 0;')
++            print('    }')
+ def main():
+-    print r'#include <string.h>'
+-    print
+-    print r'#include <iostream>'
+-    print
+-    print r'#include "d3dretrace.hpp"'
+-    print
++    print(r'#include <string.h>')
++    print()
++    print(r'#include <iostream>')
++    print()
++    print(r'#include "d3dretrace.hpp"')
++    print()
+     moduleName = sys.argv[1]
+     support = int(sys.argv[2])
+@@ -249,24 +249,24 @@ def main():
+         if moduleName == 'd3d9':
+             from specs.d3d9 import d3d9, d3dperf
+             from specs.dxva2 import dxva2
+-            print r'#include "d3d9imports.hpp"'
+-            print r'#include "d3d9size.hpp"'
+-            print r'#include "dxva2imports.hpp"'
++            print(r'#include "d3d9imports.hpp"')
++            print(r'#include "d3d9size.hpp"')
++            print(r'#include "dxva2imports.hpp"')
+             d3d9.mergeModule(d3dperf)
+             api.addModule(d3d9)
+             api.addModule(dxva2)
+-            print
+-            print '''static d3dretrace::D3DDumper<IDirect3DDevice9> d3d9Dumper;'''
+-            print '''static d3dretrace::D3DDumper<IDirect3DSwapChain9> d3d9scDumper;'''
+-            print
++            print()
++            print('''static d3dretrace::D3DDumper<IDirect3DDevice9> d3d9Dumper;''')
++            print('''static d3dretrace::D3DDumper<IDirect3DSwapChain9> d3d9scDumper;''')
++            print()
+         elif moduleName == 'd3d8':
+             from specs.d3d8 import d3d8
+-            print r'#include "d3d8imports.hpp"'
+-            print r'#include "d3d8size.hpp"'
++            print(r'#include "d3d8imports.hpp"')
++            print(r'#include "d3d8size.hpp"')
+             api.addModule(d3d8)
+-            print
+-            print '''static d3dretrace::D3DDumper<IDirect3DDevice8> d3d8Dumper;'''
+-            print
++            print()
++            print('''static d3dretrace::D3DDumper<IDirect3DDevice8> d3d8Dumper;''')
++            print()
+         else:
+             assert False
+diff --git a/retrace/ddrawretrace.py b/retrace/ddrawretrace.py
+index 4f2ff944..863283fd 100644
+--- a/retrace/ddrawretrace.py
++++ b/retrace/ddrawretrace.py
+@@ -37,12 +37,12 @@ from specs.ddraw import DDCREATE_LPGUID
+ class D3DRetracer(Retracer):
+     def retraceApi(self, api):
+-        print '// Swizzling mapping for lock addresses'
+-        print 'static std::map<void *, void *> _maps;'
+-        print
++        print('// Swizzling mapping for lock addresses')
++        print('static std::map<void *, void *> _maps;')
++        print()
+         # TODO: Keep a table of windows
+-        print 'static HWND g_hWnd;'
+-        print
++        print('static HWND g_hWnd;')
++        print()
+         Retracer.retraceApi(self, api)
+@@ -50,20 +50,20 @@ class D3DRetracer(Retracer):
+         # keep track of the last used device for state dumping
+         if interface.name in ('IDirect3DDevice7',):
+             if method.name == 'Release':
+-                print r'    if (call.ret->toUInt() == 0) {'
+-                print r'        d3d7Dumper.unbindDevice(_this);'
+-                print r'    }'
++                print(r'    if (call.ret->toUInt() == 0) {')
++                print(r'        d3d7Dumper.unbindDevice(_this);')
++                print(r'    }')
+             else:
+-                print r'    d3d7Dumper.bindDevice(_this);'
++                print(r'    d3d7Dumper.bindDevice(_this);')
+         # create windows as neccessary
+         hWndArg = method.getArgByType(HWND)
+         if hWndArg is not None:
+             # FIXME: Try to guess the window size (e.g., from IDirectDrawSurface7::Blt)
+-            print r'    if (!g_hWnd) {'
+-            print r'        g_hWnd = d3dretrace::createWindow(512, 512);'
+-            print r'    }'
+-            print r'    %s = g_hWnd;' % hWndArg.name
++            print(r'    if (!g_hWnd) {')
++            print(r'        g_hWnd = d3dretrace::createWindow(512, 512);')
++            print(r'    }')
++            print(r'    %s = g_hWnd;' % hWndArg.name)
+         if method.name == 'Lock':
+@@ -71,74 +71,74 @@ class D3DRetracer(Retracer):
+             # way to cope with it (other than retry).
+             mapFlagsArg = method.getArgByName('dwFlags')
+             if mapFlagsArg is not None:
+-                print r'    dwFlags &= DDLOCK_DONOTWAIT;'
+-                print r'    dwFlags |= DDLOCK_WAIT;'
++                print(r'    dwFlags &= DDLOCK_DONOTWAIT;')
++                print(r'    dwFlags |= DDLOCK_WAIT;')
+         Retracer.invokeInterfaceMethod(self, interface, method)
+         if method.name == 'CreateDevice':
+-            print r'    if (FAILED(_result)) {'
+-            print r'        exit(1);'
+-            print r'    }'
++            print(r'    if (FAILED(_result)) {')
++            print(r'        exit(1);')
++            print(r'    }')
+         # notify frame has been completed
+         # process events after presents
+         if interface.name == 'IDirectDrawSurface7' and method.name == 'Blt':
+-            print r'    DDSCAPS2 ddsCaps;'
+-            print r'    if (SUCCEEDED(_this->GetCaps(&ddsCaps)) &&'
+-            print r'        (ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {'
+-            print r'        retrace::frameComplete(call);'
+-            print r'        d3dretrace::processEvents();'
+-            print r'    }'
++            print(r'    DDSCAPS2 ddsCaps;')
++            print(r'    if (SUCCEEDED(_this->GetCaps(&ddsCaps)) &&')
++            print(r'        (ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {')
++            print(r'        retrace::frameComplete(call);')
++            print(r'        d3dretrace::processEvents();')
++            print(r'    }')
+         if method.name == 'Lock':
+-            print '    VOID *_pbData = NULL;'
+-            print '    size_t _MappedSize = 0;'
++            print('    VOID *_pbData = NULL;')
++            print('    size_t _MappedSize = 0;')
+             # FIXME: determine the mapping size
+             #print '    _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1])
+-            print '    if (_MappedSize) {'
+-            print '        _maps[_this] = _pbData;'
++            print('    if (_MappedSize) {')
++            print('        _maps[_this] = _pbData;')
+             # TODO: check pitches match
+-            print '    } else {'
+-            print '        return;'
+-            print '    }'
++            print('    } else {')
++            print('        return;')
++            print('    }')
+         
+         if method.name == 'Unlock':
+-            print '    VOID *_pbData = 0;'
+-            print '    _pbData = _maps[_this];'
+-            print '    if (_pbData) {'
+-            print '        retrace::delRegionByPointer(_pbData);'
+-            print '        _maps[_this] = 0;'
+-            print '    }'
++            print('    VOID *_pbData = 0;')
++            print('    _pbData = _maps[_this];')
++            print('    if (_pbData) {')
++            print('        retrace::delRegionByPointer(_pbData);')
++            print('        _maps[_this] = 0;')
++            print('    }')
+     def extractArg(self, function, arg, arg_type, lvalue, rvalue):
+         # Handle DDCREATE_* flags
+         if arg.type is DDCREATE_LPGUID:
+-            print '    if (%s.toArray()) {' % rvalue
++            print('    if (%s.toArray()) {' % rvalue)
+             Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
+-            print '    } else {'
+-            print '        %s = static_cast<%s>(%s.toPointer());' % (lvalue, arg_type, rvalue)
+-            print '    }'
++            print('    } else {')
++            print('        %s = static_cast<%s>(%s.toPointer());' % (lvalue, arg_type, rvalue))
++            print('    }')
+             return
+         Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
+ def main():
+-    print r'#include <string.h>'
+-    print
+-    print r'#include <iostream>'
+-    print
+-    print r'#include "d3dretrace.hpp"'
+-    print
++    print(r'#include <string.h>')
++    print()
++    print(r'#include <iostream>')
++    print()
++    print(r'#include "d3dretrace.hpp"')
++    print()
+     api = API()
+     
+-    print r'#include "d3dimports.hpp"'
++    print(r'#include "d3dimports.hpp"')
+     api.addModule(ddraw)
+-    print
+-    print '''static d3dretrace::D3DDumper<IDirect3DDevice7> d3d7Dumper;'''
+-    print
++    print()
++    print('''static d3dretrace::D3DDumper<IDirect3DDevice7> d3d7Dumper;''')
++    print()
+     retracer = D3DRetracer()
+     retracer.table_name = 'd3dretrace::ddraw_callbacks'
+diff --git a/retrace/dllretrace.py b/retrace/dllretrace.py
+index c818b0a9..ad9db9a4 100644
+--- a/retrace/dllretrace.py
++++ b/retrace/dllretrace.py
+@@ -33,29 +33,29 @@ class DllDispatcher(Dispatcher):
+     def dispatchModule(self, module):
+         tag = module.name.upper()
+-        print r'const char *g_sz%sDllName = NULL;' % (tag,)
+-        print r'HMODULE g_h%sModule = NULL;' % (tag,)
+-        print r''
+-        print r'static PROC'
+-        print r'_get%sProcAddress(LPCSTR lpProcName) {' % tag
+-        print r'    if (!g_h%sModule) {' % tag
+-        print r'        if (g_sz%sDllName) {' % tag
+-        print r'            g_h%sModule = LoadLibraryA(g_sz%sDllName);' % (tag, tag)
+-        print r'            if (!g_h%sModule) {' % tag
+-        print r'                os::log("warning: failed to load %%s\n", g_sz%sDllName);' % tag 
+-        print r'            }'
+-        print r'        }'
+-        print r'        if (!g_h%sModule) {' % tag
+-        print r'            g_h%sModule = LoadLibraryA("%s.dll");' % (tag, module.name)
+-        print r'        }'
+-        print r'        if (!g_h%sModule) {' % tag
+-        print r'            os::log("error: failed to load %s.dll\n");' % module.name
+-        print r'            exit(1);'
+-        print r'        }'
+-        print r'    }'
+-        print r'    return GetProcAddress(g_h%sModule, lpProcName);' % tag
+-        print r'}'
+-        print r''
++        print(r'const char *g_sz%sDllName = NULL;' % (tag,))
++        print(r'HMODULE g_h%sModule = NULL;' % (tag,))
++        print(r'')
++        print(r'static PROC')
++        print(r'_get%sProcAddress(LPCSTR lpProcName) {' % tag)
++        print(r'    if (!g_h%sModule) {' % tag)
++        print(r'        if (g_sz%sDllName) {' % tag)
++        print(r'            g_h%sModule = LoadLibraryA(g_sz%sDllName);' % (tag, tag))
++        print(r'            if (!g_h%sModule) {' % tag)
++        print(r'                os::log("warning: failed to load %%s\n", g_sz%sDllName);' % tag) 
++        print(r'            }')
++        print(r'        }')
++        print(r'        if (!g_h%sModule) {' % tag)
++        print(r'            g_h%sModule = LoadLibraryA("%s.dll");' % (tag, module.name))
++        print(r'        }')
++        print(r'        if (!g_h%sModule) {' % tag)
++        print(r'            os::log("error: failed to load %s.dll\n");' % module.name)
++        print(r'            exit(1);')
++        print(r'        }')
++        print(r'    }')
++        print(r'    return GetProcAddress(g_h%sModule, lpProcName);' % tag)
++        print(r'}')
++        print(r'')
+         Dispatcher.dispatchModule(self, module)
+diff --git a/retrace/dxgiretrace.py b/retrace/dxgiretrace.py
+index 799e3df9..8986a767 100755
+--- a/retrace/dxgiretrace.py
++++ b/retrace/dxgiretrace.py
+@@ -40,10 +40,10 @@ from specs.d3d11 import d3d11
+ class D3DRetracer(Retracer):
+     def retraceApi(self, api):
+-        print '// Swizzling mapping for lock addresses, mapping a (pDeviceContext, pResource, Subresource) -> void *'
+-        print 'typedef std::pair< IUnknown *, UINT > SubresourceKey;'
+-        print 'static std::map< IUnknown *, std::map< SubresourceKey, void * > > g_Maps;'
+-        print
++        print('// Swizzling mapping for lock addresses, mapping a (pDeviceContext, pResource, Subresource) -> void *')
++        print('typedef std::pair< IUnknown *, UINT > SubresourceKey;')
++        print('static std::map< IUnknown *, std::map< SubresourceKey, void * > > g_Maps;')
++        print()
+         self.table_name = 'd3dretrace::dxgi_callbacks'
+         Retracer.retraceApi(self, api)
+@@ -61,41 +61,41 @@ class D3DRetracer(Retracer):
+         if function.name in self.createDeviceFunctionNames:
+             # create windows as neccessary
+             if 'pSwapChainDesc' in function.argNames():
+-                print r'    d3dretrace::createWindowForSwapChain(pSwapChainDesc);'
++                print(r'    d3dretrace::createWindowForSwapChain(pSwapChainDesc);')
+             # Compensate for the fact we don't trace DXGI object creation
+             if function.name.startswith('D3D11CreateDevice'):
+-                print r'    if (DriverType == D3D_DRIVER_TYPE_UNKNOWN && !pAdapter) {'
+-                print r'        DriverType = D3D_DRIVER_TYPE_HARDWARE;'
+-                print r'    }'
++                print(r'    if (DriverType == D3D_DRIVER_TYPE_UNKNOWN && !pAdapter) {')
++                print(r'        DriverType = D3D_DRIVER_TYPE_HARDWARE;')
++                print(r'    }')
+             if function.name.startswith('D3D10CreateDevice'):
+                 # Toggle debugging
+-                print r'    Flags &= ~D3D10_CREATE_DEVICE_DEBUG;'
+-                print r'    if (retrace::debug) {'
+-                print r'        HMODULE hD3d10SdkLayers = LoadLibraryA("d3d10sdklayers");'
+-                print r'        if (hD3d10SdkLayers) {'
+-                print r'            FreeLibrary(hD3d10SdkLayers);'
+-                print r'            Flags |= D3D10_CREATE_DEVICE_DEBUG;'
+-                print r'        } else {'
+-                print r'            retrace::warning(call) << "Direct3D 10.x SDK Debug Layer (d3d10sdklayers.dll) not available, continuing without debug output\n";'
+-                print r'        }'
+-                print r'    }'
++                print(r'    Flags &= ~D3D10_CREATE_DEVICE_DEBUG;')
++                print(r'    if (retrace::debug) {')
++                print(r'        HMODULE hD3d10SdkLayers = LoadLibraryA("d3d10sdklayers");')
++                print(r'        if (hD3d10SdkLayers) {')
++                print(r'            FreeLibrary(hD3d10SdkLayers);')
++                print(r'            Flags |= D3D10_CREATE_DEVICE_DEBUG;')
++                print(r'        } else {')
++                print(r'            retrace::warning(call) << "Direct3D 10.x SDK Debug Layer (d3d10sdklayers.dll) not available, continuing without debug output\n";')
++                print(r'        }')
++                print(r'    }')
+                 # Force driver
+                 self.forceDriver('D3D10_DRIVER_TYPE')
+             if function.name.startswith('D3D11CreateDevice'):
+                 # Toggle debugging
+-                print r'    Flags &= ~D3D11_CREATE_DEVICE_DEBUG;'
+-                print r'    if (retrace::debug) {'
+-                print r'        HRESULT hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, 0, D3D11_CREATE_DEVICE_DEBUG, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, NULL);'
+-                print r'        if (SUCCEEDED(hr)) {'
+-                print r'            Flags |= D3D11_CREATE_DEVICE_DEBUG;'
+-                print r'        } else {'
+-                print r'            retrace::warning(call) << "Direct3D 11.x SDK Debug Layer (d3d11*sdklayers.dll) not available, continuing without debug output\n";'
+-                print r'        }'
+-                print r'    }'
++                print(r'    Flags &= ~D3D11_CREATE_DEVICE_DEBUG;')
++                print(r'    if (retrace::debug) {')
++                print(r'        HRESULT hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, 0, D3D11_CREATE_DEVICE_DEBUG, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, NULL);')
++                print(r'        if (SUCCEEDED(hr)) {')
++                print(r'            Flags |= D3D11_CREATE_DEVICE_DEBUG;')
++                print(r'        } else {')
++                print(r'            retrace::warning(call) << "Direct3D 11.x SDK Debug Layer (d3d11*sdklayers.dll) not available, continuing without debug output\n";')
++                print(r'        }')
++                print(r'    }')
+                 # Force driver
+                 self.forceDriver('D3D_DRIVER_TYPE')
+@@ -108,15 +108,15 @@ class D3DRetracer(Retracer):
+             if interface is not None:
+                 getDeviceRemovedReasonMethod = interface.getMethodByName("GetDeviceRemovedReason")
+                 if getDeviceRemovedReasonMethod is not None:
+-                    print r'    if (FAILED(_result)) {'
+-                    print r'        retrace::failed(call, _result);'
+-                    print r'        if (_result == DXGI_ERROR_DEVICE_REMOVED) {'
+-                    print r'            HRESULT _reason = _this->GetDeviceRemovedReason();'
+-                    print r'            retrace::failed(call, _reason);'
+-                    print r'            exit(1);'
+-                    print r'        }'
+-                    print r'        return;'
+-                    print r'    }'
++                    print(r'    if (FAILED(_result)) {')
++                    print(r'        retrace::failed(call, _result);')
++                    print(r'        if (_result == DXGI_ERROR_DEVICE_REMOVED) {')
++                    print(r'            HRESULT _reason = _this->GetDeviceRemovedReason();')
++                    print(r'            retrace::failed(call, _reason);')
++                    print(r'            exit(1);')
++                    print(r'        }')
++                    print(r'        return;')
++                    print(r'    }')
+                     return
+         Retracer.checkResult(self, interface, methodOrFunction)
+@@ -124,112 +124,112 @@ class D3DRetracer(Retracer):
+     def forceDriver(self, enum):
+         # This can only work when pAdapter is NULL. For non-NULL pAdapter we
+         # need to override inside the EnumAdapters call below
+-        print r'    if (pAdapter == NULL) {'
+-        print r'        switch (retrace::driver) {'
+-        print r'        case retrace::DRIVER_HARDWARE:'
+-        print r'            DriverType = %s_HARDWARE;' % enum
+-        print r'            Software = NULL;'
+-        print r'            break;'
+-        print r'        case retrace::DRIVER_SOFTWARE:'
+-        print r'            DriverType = %s_WARP;' % enum
+-        print r'            Software = NULL;'
+-        print r'            break;'
+-        print r'        case retrace::DRIVER_REFERENCE:'
+-        print r'            DriverType = %s_REFERENCE;' % enum
+-        print r'            Software = NULL;'
+-        print r'            break;'
+-        print r'        case retrace::DRIVER_NULL:'
+-        print r'            DriverType = %s_NULL;' % enum
+-        print r'            Software = NULL;'
+-        print r'            break;'
+-        print r'        case retrace::DRIVER_MODULE:'
+-        print r'            DriverType = %s_SOFTWARE;' % enum
+-        print r'            Software = LoadLibraryA(retrace::driverModule);'
+-        print r'            if (!Software) {'
+-        print r'                retrace::warning(call) << "failed to load " << retrace::driverModule << "\n";'
+-        print r'            }'
+-        print r'            break;'
+-        print r'        default:'
+-        print r'            assert(0);'
+-        print r'            /* fall-through */'
+-        print r'        case retrace::DRIVER_DEFAULT:'
+-        print r'            if (DriverType == %s_SOFTWARE) {' % enum
+-        print r'                Software = LoadLibraryA("d3d10warp");'
+-        print r'                if (!Software) {'
+-        print r'                    retrace::warning(call) << "failed to load d3d10warp.dll\n";'
+-        print r'                }'
+-        print r'            }'
+-        print r'            break;'
+-        print r'        }'
+-        print r'    } else {'
+-        print r'        Software = NULL;'
+-        print r'    }'
++        print(r'    if (pAdapter == NULL) {')
++        print(r'        switch (retrace::driver) {')
++        print(r'        case retrace::DRIVER_HARDWARE:')
++        print(r'            DriverType = %s_HARDWARE;' % enum)
++        print(r'            Software = NULL;')
++        print(r'            break;')
++        print(r'        case retrace::DRIVER_SOFTWARE:')
++        print(r'            DriverType = %s_WARP;' % enum)
++        print(r'            Software = NULL;')
++        print(r'            break;')
++        print(r'        case retrace::DRIVER_REFERENCE:')
++        print(r'            DriverType = %s_REFERENCE;' % enum)
++        print(r'            Software = NULL;')
++        print(r'            break;')
++        print(r'        case retrace::DRIVER_NULL:')
++        print(r'            DriverType = %s_NULL;' % enum)
++        print(r'            Software = NULL;')
++        print(r'            break;')
++        print(r'        case retrace::DRIVER_MODULE:')
++        print(r'            DriverType = %s_SOFTWARE;' % enum)
++        print(r'            Software = LoadLibraryA(retrace::driverModule);')
++        print(r'            if (!Software) {')
++        print(r'                retrace::warning(call) << "failed to load " << retrace::driverModule << "\n";')
++        print(r'            }')
++        print(r'            break;')
++        print(r'        default:')
++        print(r'            assert(0);')
++        print(r'            /* fall-through */')
++        print(r'        case retrace::DRIVER_DEFAULT:')
++        print(r'            if (DriverType == %s_SOFTWARE) {' % enum)
++        print(r'                Software = LoadLibraryA("d3d10warp");')
++        print(r'                if (!Software) {')
++        print(r'                    retrace::warning(call) << "failed to load d3d10warp.dll\n";')
++        print(r'                }')
++        print(r'            }')
++        print(r'            break;')
++        print(r'        }')
++        print(r'    } else {')
++        print(r'        Software = NULL;')
++        print(r'    }')
+     def invokeInterfaceMethod(self, interface, method):
+         # keep track of the last used device for state dumping
+         if interface.name in ('ID3D10Device', 'ID3D10Device1'):
+             if method.name == 'Release':
+-                print r'    if (call.ret->toUInt() == 0) {'
+-                print r'        d3d10Dumper.unbindDevice(_this);'
+-                print r'    }'
++                print(r'    if (call.ret->toUInt() == 0) {')
++                print(r'        d3d10Dumper.unbindDevice(_this);')
++                print(r'    }')
+             else:
+-                print r'    d3d10Dumper.bindDevice(_this);'
++                print(r'    d3d10Dumper.bindDevice(_this);')
+         if interface.name.startswith('ID3D11DeviceContext'):
+             if method.name == 'Release':
+-                print r'    if (call.ret->toUInt() == 0) {'
+-                print r'        d3d11Dumper.unbindDevice(_this);'
+-                print r'    }'
++                print(r'    if (call.ret->toUInt() == 0) {')
++                print(r'        d3d11Dumper.unbindDevice(_this);')
++                print(r'    }')
+             else:
+-                print r'    if (_this->GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE) {'
+-                print r'        d3d11Dumper.bindDevice(_this);'
+-                print r'    }'
++                print(r'    if (_this->GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE) {')
++                print(r'        d3d11Dumper.bindDevice(_this);')
++                print(r'    }')
+         # intercept private interfaces
+         if method.name == 'QueryInterface':
+-            print r'    if (!d3dretrace::overrideQueryInterface(_this, riid, ppvObj, &_result)) {'
++            print(r'    if (!d3dretrace::overrideQueryInterface(_this, riid, ppvObj, &_result)) {')
+             Retracer.invokeInterfaceMethod(self, interface, method)
+-            print r'    }'
++            print(r'    }')
+             return
+         # create windows as neccessary
+         if method.name == 'CreateSwapChain':
+-            print r'    d3dretrace::createWindowForSwapChain(pDesc);'
++            print(r'    d3dretrace::createWindowForSwapChain(pDesc);')
+         if method.name == 'CreateSwapChainForHwnd':
+-            print r'    WindowHandle = d3dretrace::createWindow(pDesc->Width, pDesc->Height);'
+-            print r'    // DXGI_SCALING_NONE is only supported on Win8 and beyond'
+-            print r'    if (pDesc->Scaling == DXGI_SCALING_NONE && !IsWindows8OrGreater()) {'
+-            print r'        pDesc->Scaling = DXGI_SCALING_STRETCH;'
+-            print r'    }'
++            print(r'    WindowHandle = d3dretrace::createWindow(pDesc->Width, pDesc->Height);')
++            print(r'    // DXGI_SCALING_NONE is only supported on Win8 and beyond')
++            print(r'    if (pDesc->Scaling == DXGI_SCALING_NONE && !IsWindows8OrGreater()) {')
++            print(r'        pDesc->Scaling = DXGI_SCALING_STRETCH;')
++            print(r'    }')
+         if method.name == 'CreateSwapChainForComposition':
+-            print r'    HWND hWnd = d3dretrace::createWindow(pDesc->Width, pDesc->Height);'
+-            print r'    _result = _this->CreateSwapChainForHwnd(pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);'
++            print(r'    HWND hWnd = d3dretrace::createWindow(pDesc->Width, pDesc->Height);')
++            print(r'    _result = _this->CreateSwapChainForHwnd(pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);')
+             self.checkResult(interface, method)
+             return
+         if method.name == 'SetFullscreenState':
+-            print r'    if (retrace::forceWindowed) {'
+-            print r'         Fullscreen = FALSE;'
+-            print r'         pTarget = NULL;'
+-            print r'    }'
++            print(r'    if (retrace::forceWindowed) {')
++            print(r'         Fullscreen = FALSE;')
++            print(r'         pTarget = NULL;')
++            print(r'    }')
+         # notify frame has been completed
+         if interface.name.startswith('IDXGISwapChain') and method.name.startswith('Present'):
+             if interface.name.startswith('IDXGISwapChainDWM'):
+-                print r'    com_ptr<IDXGISwapChain> pSwapChain;'
+-                print r'    if (SUCCEEDED(_this->QueryInterface(IID_IDXGISwapChain, (void **) &pSwapChain))) {'
+-                print r'        dxgiDumper.bindDevice(pSwapChain);'
+-                print r'    } else {'
+-                print r'        assert(0);'
+-                print r'    }'
++                print(r'    com_ptr<IDXGISwapChain> pSwapChain;')
++                print(r'    if (SUCCEEDED(_this->QueryInterface(IID_IDXGISwapChain, (void **) &pSwapChain))) {')
++                print(r'        dxgiDumper.bindDevice(pSwapChain);')
++                print(r'    } else {')
++                print(r'        assert(0);')
++                print(r'    }')
+             else:
+-                print r'    dxgiDumper.bindDevice(_this);'
+-            print r'    retrace::frameComplete(call);'
++                print(r'    dxgiDumper.bindDevice(_this);')
++            print(r'    retrace::frameComplete(call);')
+         if 'pSharedResource' in method.argNames():
+-            print r'    if (pSharedResource) {'
+-            print r'        retrace::warning(call) << "shared surfaces unsupported\n";'
+-            print r'        pSharedResource = NULL;'
+-            print r'    }'
++            print(r'    if (pSharedResource) {')
++            print(r'        retrace::warning(call) << "shared surfaces unsupported\n";')
++            print(r'        pSharedResource = NULL;')
++            print(r'    }')
+         # Force driver
+         if interface.name.startswith('IDXGIFactory') and method.name.startswith('EnumAdapters'):
+@@ -260,31 +260,31 @@ class D3DRetracer(Retracer):
+             return
+         if interface.name.startswith('ID3D10Device') and method.name.startswith('OpenSharedResource'):
+-            print r'    retrace::warning(call) << "replacing shared resource with checker pattern\n";'
+-            print r'    _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);'
++            print(r'    retrace::warning(call) << "replacing shared resource with checker pattern\n";')
++            print(r'    _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);')
+             self.checkResult(interface, method)
+             return
+         if interface.name.startswith('ID3D11Device') and method.name == 'OpenSharedResource':
+             # Some applications (e.g., video playing in IE11) create shared resources within the same process.
+             # TODO: Generalize to other OpenSharedResource variants
+-            print r'    retrace::map<HANDLE>::const_iterator it = _shared_handle_map.find(hResource);'
+-            print r'    if (it == _shared_handle_map.end()) {'
+-            print r'        retrace::warning(call) << "replacing shared resource with checker pattern\n";'
+-            print r'        _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);'
++            print(r'    retrace::map<HANDLE>::const_iterator it = _shared_handle_map.find(hResource);')
++            print(r'    if (it == _shared_handle_map.end()) {')
++            print(r'        retrace::warning(call) << "replacing shared resource with checker pattern\n";')
++            print(r'        _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);')
+             self.checkResult(interface, method)
+-            print r'    } else {'
+-            print r'        hResource = it->second;'
++            print(r'    } else {')
++            print(r'        hResource = it->second;')
+             Retracer.invokeInterfaceMethod(self, interface, method)
+-            print r'    }'
++            print(r'    }')
+             return
+         if interface.name.startswith('ID3D11Device') and method.name.startswith('OpenSharedResource'):
+-            print r'    retrace::warning(call) << "replacing shared resource with checker pattern\n";'
+-            print r'    _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);'
++            print(r'    retrace::warning(call) << "replacing shared resource with checker pattern\n";')
++            print(r'    _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);')
+             if method.name == 'OpenSharedResourceByName':
+-                print r'    (void)lpName;'
+-                print r'    (void)dwDesiredAccess;'
++                print(r'    (void)lpName;')
++                print(r'    (void)dwDesiredAccess;')
+             else:
+-                print r'    (void)hResource;'
++                print(r'    (void)hResource;')
+             self.checkResult(interface, method)
+             return
+@@ -294,7 +294,7 @@ class D3DRetracer(Retracer):
+             mapFlagsArg = method.getArgByName('MapFlags')
+             for flag in mapFlagsArg.type.values:
+                 if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'):
+-                    print r'    MapFlags &= ~%s;' % flag
++                    print(r'    MapFlags &= ~%s;' % flag)
+         if method.name.startswith('UpdateSubresource'):
+             # The D3D10 debug layer is buggy (or at least inconsistent with the
+@@ -303,108 +303,108 @@ class D3DRetracer(Retracer):
+             # SrcDepthPitch is garbagge for non 3D textures.
+             # XXX: It also seems to expect padding bytes at the end of the last
+             # row, but we never record (or allocate) those...
+-            print r'    if (retrace::debug && pDstBox && pDstBox->front == 0 && pDstBox->back == 1) {'
+-            print r'        SrcDepthPitch = 0;'
+-            print r'    }'
++            print(r'    if (retrace::debug && pDstBox && pDstBox->front == 0 && pDstBox->back == 1) {')
++            print(r'        SrcDepthPitch = 0;')
++            print(r'    }')
+         if method.name == 'SetGammaControl':
+             # This method is only supported while in full-screen mode
+-            print r'    if (retrace::forceWindowed) {'
+-            print r'        return;'
+-            print r'    }'
++            print(r'    if (retrace::forceWindowed) {')
++            print(r'        return;')
++            print(r'    }')
+         Retracer.invokeInterfaceMethod(self, interface, method)
+         if method.name in ('AcquireSync', 'ReleaseSync'):
+-            print r'    if (SUCCEEDED(_result) && _result != S_OK) {'
+-            print r'        retrace::warning(call) << " returned " << _result << "\n";'
+-            print r'    }'
++            print(r'    if (SUCCEEDED(_result) && _result != S_OK) {')
++            print(r'        retrace::warning(call) << " returned " << _result << "\n";')
++            print(r'    }')
+         # process events after presents
+         if interface.name.startswith('IDXGISwapChain') and method.name.startswith('Present'):
+-            print r'    d3dretrace::processEvents();'
++            print(r'    d3dretrace::processEvents();')
+         if method.name in ('Map', 'Unmap'):
+             if interface.name.startswith('ID3D11DeviceContext'):
+-                print '    void * & _pbData = g_Maps[_this][SubresourceKey(pResource, Subresource)];'
++                print('    void * & _pbData = g_Maps[_this][SubresourceKey(pResource, Subresource)];')
+             else:
+                 subresourceArg = method.getArgByName('Subresource')
+                 if subresourceArg is None:
+-                    print '    UINT Subresource = 0;'
+-                print '    void * & _pbData = g_Maps[0][SubresourceKey(_this, Subresource)];'
++                    print('    UINT Subresource = 0;')
++                print('    void * & _pbData = g_Maps[0][SubresourceKey(_this, Subresource)];')
+         if method.name == 'Map':
+-            print '    _MAP_DESC _MapDesc;'
+-            print '    _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames())
+-            print '    size_t _MappedSize = _MapDesc.Size;'
+-            print '    if (_MapDesc.Size) {'
+-            print '        _pbData = _MapDesc.pData;'
++            print('    _MAP_DESC _MapDesc;')
++            print('    _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames()))
++            print('    size_t _MappedSize = _MapDesc.Size;')
++            print('    if (_MapDesc.Size) {')
++            print('        _pbData = _MapDesc.pData;')
+             if interface.name.startswith('ID3D11DeviceContext'):
+                 # Prevent false warnings on 1D and 2D resources, since the
+                 # pitches are often junk there...
+-                print '        _normalizeMap(pResource, pMappedResource);'
++                print('        _normalizeMap(pResource, pMappedResource);')
+                 self.checkPitchMismatch(method)
+             else:
+-                print '        _pbData = _MapDesc.pData;'
++                print('        _pbData = _MapDesc.pData;')
+                 self.checkPitchMismatch(method)
+-            print '    } else {'
+-            print '        return;'
+-            print '    }'
++            print('    } else {')
++            print('        return;')
++            print('    }')
+         
+         if method.name == 'Unmap':
+-            print '    if (_pbData) {'
+-            print '        retrace::delRegionByPointer(_pbData);'
+-            print '        _pbData = 0;'
+-            print '    }'
++            print('    if (_pbData) {')
++            print('        retrace::delRegionByPointer(_pbData);')
++            print('        _pbData = 0;')
++            print('    }')
+         # Attach shader byte code for lookup
+         if 'pShaderBytecode' in method.argNames():
+             ppShader = method.args[-1]
+             assert ppShader.output
+-            print r'    if (retrace::dumpingState && SUCCEEDED(_result)) {'
+-            print r'        (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name
+-            print r'    }'
++            print(r'    if (retrace::dumpingState && SUCCEEDED(_result)) {')
++            print(r'        (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name)
++            print(r'    }')
+     def extractArg(self, function, arg, arg_type, lvalue, rvalue):
+         # Set object names
+         if function.name == 'SetPrivateData' and arg.name == 'pData':
+             iid = function.args[0].name
+-            print r'    if (%s != WKPDID_D3DDebugObjectName) {' % iid
+-            print r'        return;'
+-            print r'    }'
++            print(r'    if (%s != WKPDID_D3DDebugObjectName) {' % iid)
++            print(r'        return;')
++            print(r'    }')
+             # Interpret argument as string
+             Retracer.extractArg(self, function, arg, LPCSTR, lvalue, rvalue)
+-            print r'    assert(pData);'
+-            print r'    assert(DataSize >= strlen((const char *)pData));'
+-            print r'    // Some applications include the trailing zero terminator in the data'
+-            print r'    DataSize = strlen((const char *)pData);'
++            print(r'    assert(pData);')
++            print(r'    assert(DataSize >= strlen((const char *)pData));')
++            print(r'    // Some applications include the trailing zero terminator in the data')
++            print(r'    DataSize = strlen((const char *)pData);')
+             return
+         Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
+ def main():
+-    print r'#define INITGUID'
+-    print
+-    print r'#include <string.h>'
+-    print
+-    print r'#include <iostream>'
+-    print
+-    print r'#include "d3dretrace.hpp"'
+-    print r'#include "os_version.hpp"'
+-    print
+-    print r'#include "d3dretrace_dxgi.hpp"'
+-    print r'#include "d3d10imports.hpp"'
+-    print r'#include "d3d10size.hpp"'
+-    print r'#include "d3d10state.hpp"'
+-    print r'#include "d3d11imports.hpp"'
+-    print r'#include "d3d11size.hpp"'
+-    print r'#include "d3dstate.hpp"'
+-    print
+-    print '''static d3dretrace::D3DDumper<IDXGISwapChain> dxgiDumper;'''
+-    print '''static d3dretrace::D3DDumper<ID3D10Device> d3d10Dumper;'''
+-    print '''static d3dretrace::D3DDumper<ID3D11DeviceContext> d3d11Dumper;'''
+-    print
++    print(r'#define INITGUID')
++    print()
++    print(r'#include <string.h>')
++    print()
++    print(r'#include <iostream>')
++    print()
++    print(r'#include "d3dretrace.hpp"')
++    print(r'#include "os_version.hpp"')
++    print()
++    print(r'#include "d3dretrace_dxgi.hpp"')
++    print(r'#include "d3d10imports.hpp"')
++    print(r'#include "d3d10size.hpp"')
++    print(r'#include "d3d10state.hpp"')
++    print(r'#include "d3d11imports.hpp"')
++    print(r'#include "d3d11size.hpp"')
++    print(r'#include "d3dstate.hpp"')
++    print()
++    print('''static d3dretrace::D3DDumper<IDXGISwapChain> dxgiDumper;''')
++    print('''static d3dretrace::D3DDumper<ID3D10Device> d3d10Dumper;''')
++    print('''static d3dretrace::D3DDumper<ID3D11DeviceContext> d3d11Dumper;''')
++    print()
+     api = API()
+     api.addModule(dxgi)
+diff --git a/retrace/dxgistate_so.py b/retrace/dxgistate_so.py
+index 86f6db57..33745c8f 100644
+--- a/retrace/dxgistate_so.py
++++ b/retrace/dxgistate_so.py
+@@ -48,9 +48,9 @@ class ValueDumper(stdapi.Visitor, stdapi.ExpanderMixin):
+     def visitLiteral(self, literal, instance):
+         if literal.kind in ('SInt', 'UInt'):
+-            print '    writer.writeInt(%s);' % (instance)
++            print('    writer.writeInt(%s);' % (instance))
+         elif literal.kind in ('Float',):
+-            print '    writer.writeFloat(%s);' % (instance)
++            print('    writer.writeFloat(%s);' % (instance))
+         else:
+             raise NotImplementedError
+@@ -66,36 +66,36 @@ class ValueDumper(stdapi.Visitor, stdapi.ExpanderMixin):
+             # reinterpret_cast is necessary for GLubyte * <=> char *
+             instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
+         assert string.length is None
+-        print '    writer.write%s(%s);' % (suffix, instance)
++        print('    writer.write%s(%s);' % (suffix, instance))
+     def visitConst(self, const, instance):
+         self.visit(const.type, instance)
+     def visitStruct(self, struct, instance):
+-        print '    writer.beginObject();'
++        print('    writer.beginObject();')
+         for member in struct.members:
+             memberType, memberName = member
+             if memberName is not None:
+-                print '    writer.beginMember("%s");' % memberName
++                print('    writer.beginMember("%s");' % memberName)
+             self.visitMember(member, instance)
+             if memberName is not None:
+-                print '    writer.endMember(); // %s' % memberName
+-        print '    writer.endObject();'
++                print('    writer.endMember(); // %s' % memberName)
++        print('    writer.endObject();')
+     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 '        writer.beginArray();'
+-        print '        for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
++        print('    if (%s) {' % instance)
++        print('        size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length))
++        print('        writer.beginArray();')
++        print('        for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index))
+         self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
+-        print '        }'
+-        print '        writer.endArray();'
+-        print '    } else {'
+-        print '        writer.writeNull();'
+-        print '    }'
++        print('        }')
++        print('        writer.endArray();')
++        print('    } else {')
++        print('        writer.writeNull();')
++        print('    }')
+     def visitAttribArray(self, array, instance):
+         raise NotImplementedError
+@@ -104,37 +104,37 @@ class ValueDumper(stdapi.Visitor, stdapi.ExpanderMixin):
+         raise NotImplementedError
+     def visitEnum(self, enum, instance):
+-        print '    switch (%s) {' % instance
++        print('    switch (%s) {' % instance)
+         for value in enum.values:
+-            print '    case %s:' % value
+-            print '        writer.writeString("%s");' % value
+-            print '        break;'
+-        print '    default:'
+-        print '        writer.writeInt(%s);' % instance
+-        print '        break;'
+-        print '    }'
++            print('    case %s:' % value)
++            print('        writer.writeString("%s");' % value)
++            print('        break;')
++        print('    default:')
++        print('        writer.writeInt(%s);' % instance)
++        print('        break;')
++        print('    }')
+     def visitBitmask(self, bitmask, instance):
+         # TODO
+         self.visit(bitmask.type, instance)
+     def visitPointer(self, pointer, instance):
+-        print '    if (%s) {' % instance
+-        print '        writer.beginArray();'
++        print('    if (%s) {' % instance)
++        print('        writer.beginArray();')
+         self.visit(pointer.type, "*" + instance)
+-        print '        writer.endArray();'
+-        print '    } else {'
+-        print '        writer.writeNull();'
+-        print '    }'
++        print('        writer.endArray();')
++        print('    } else {')
++        print('        writer.writeNull();')
++        print('    }')
+     def visitIntPointer(self, pointer, instance):
+-        print '    writer.writeInt((uintptr_t)%s);' % instance
++        print('    writer.writeInt((uintptr_t)%s);' % instance)
+     def visitObjPointer(self, pointer, instance):
+-        print '    writer.writeInt((uintptr_t)%s);' % instance
++        print('    writer.writeInt((uintptr_t)%s);' % instance)
+     def visitLinearPointer(self, pointer, instance):
+-        print '    writer.writeInt((uintptr_t)%s);' % instance
++        print('    writer.writeInt((uintptr_t)%s);' % instance)
+     def visitReference(self, reference, instance):
+         self.visit(reference.type, instance)
+@@ -146,23 +146,23 @@ class ValueDumper(stdapi.Visitor, stdapi.ExpanderMixin):
+         self.visit(alias.type, instance)
+     def visitOpaque(self, opaque, instance):
+-        print '    writer.writeInt((uintptr_t)%s);' % instance
++        print('    writer.writeInt((uintptr_t)%s);' % instance)
+     def visitInterface(self, interface, instance):
+         assert False
+     def visitPolymorphic(self, polymorphic, instance):
+         switchExpr = self.expand(polymorphic.switchExpr)
+-        print '    switch (static_cast<int>(%s)) {' % switchExpr
++        print('    switch (static_cast<int>(%s)) {' % switchExpr)
+         for cases, type in polymorphic.iterSwitch():
+             for case in cases:
+-                print '    %s:' % case
++                print('    %s:' % case)
+             caseInstance = instance
+             if type.expr is not None:
+                 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
+             self.visit(type, caseInstance)
+-            print '        break;'
+-        print '    }'
++            print('        break;')
++        print('    }')
+ class Dumper:
+@@ -187,8 +187,8 @@ class Dumper:
+         # Includes
+         for module in api.modules:
+             for header in module.headers:
+-                print header
+-        print
++                print(header)
++        print()
+         # Generate the dumper functions
+         types = api.getAllTypes()
+@@ -196,13 +196,13 @@ class Dumper:
+             self.dumpType(type)
+     def dumpType(self, type):
+-        print r'void'
+-        print r'dumpStateObject(StateWriter &writer, const %s & so)' % type
+-        print r'{'
++        print(r'void')
++        print(r'dumpStateObject(StateWriter &writer, const %s & so)' % type)
++        print(r'{')
+         visitor = self.dumperFactory()
+         visitor.visit(type, 'so')
+-        print r'}'
+-        print
++        print(r'}')
++        print()
+     def header(self):
+         pass
+@@ -212,10 +212,10 @@ class Dumper:
+ if __name__ == '__main__':
+-    print r'#include "dxgistate_so.hpp"'
+-    print
+-    print r'#include "state_writer.hpp"'
+-    print
++    print(r'#include "dxgistate_so.hpp"')
++    print()
++    print(r'#include "state_writer.hpp"')
++    print()
+     api = stdapi.API()
+     api.addModule(dxgi.dxgi)
+diff --git a/retrace/glretrace.py b/retrace/glretrace.py
+index 2ead195d..0dfe5c5b 100644
+--- a/retrace/glretrace.py
++++ b/retrace/glretrace.py
+@@ -127,190 +127,190 @@ class GlRetracer(Retracer):
+         # For backwards compatibility with old traces where non VBO drawing was supported
+         if (is_array_pointer or is_draw_arrays or is_draw_elements) and not is_draw_indirect:
+-            print '    if (retrace::parser->getVersion() < 1) {'
++            print('    if (retrace::parser->getVersion() < 1) {')
+             if is_array_pointer or is_draw_arrays:
+-                print '        GLint _array_buffer = 0;'
+-                print '        glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);'
+-                print '        if (!_array_buffer) {'
++                print('        GLint _array_buffer = 0;')
++                print('        glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);')
++                print('        if (!_array_buffer) {')
+                 self.failFunction(function)
+-                print '        }'
++                print('        }')
+             if is_draw_elements:
+-                print '        GLint _element_array_buffer = 0;'
+-                print '        glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &_element_array_buffer);'
+-                print '        if (!_element_array_buffer) {'
++                print('        GLint _element_array_buffer = 0;')
++                print('        glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &_element_array_buffer);')
++                print('        if (!_element_array_buffer) {')
+                 self.failFunction(function)
+-                print '        }'
++                print('        }')
+             
+-            print '    }'
++            print('    }')
+         # When no pack buffer object is bound, the pack functions are no-ops.
+         if self.pack_function_regex.match(function.name):
+-            print '    GLint _pack_buffer = 0;'
+-            print '    glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &_pack_buffer);'
+-            print '    if (!_pack_buffer) {'
+-            print '        return;'
+-            print '    }'
++            print('    GLint _pack_buffer = 0;')
++            print('    glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &_pack_buffer);')
++            print('    if (!_pack_buffer) {')
++            print('        return;')
++            print('    }')
+         # Pre-snapshots
+         if self.bind_framebuffer_function_regex.match(function.name):
+-            print '    assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);'
++            print('    assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);')
+         if function.name == 'glStringMarkerGREMEDY':
+             return
+         if function.name == 'glFrameTerminatorGREMEDY':
+-            print '    glretrace::frame_complete(call);'
++            print('    glretrace::frame_complete(call);')
+             return
+         Retracer.retraceFunctionBody(self, function)
+         # Post-snapshots
+         if function.name in ('glFlush', 'glFinish'):
+-            print '    if (!retrace::doubleBuffer) {'
+-            print '        glretrace::frame_complete(call);'
+-            print '    }'
++            print('    if (!retrace::doubleBuffer) {')
++            print('        glretrace::frame_complete(call);')
++            print('    }')
+         if is_draw_arrays or is_draw_elements or is_misc_draw:
+-            print '    assert(call.flags & trace::CALL_FLAG_RENDER);'
++            print('    assert(call.flags & trace::CALL_FLAG_RENDER);')
+     def invokeFunction(self, function):
+         if function.name == "glTexDirectVIVMap" or function.name == "glTexDirectMapVIV" or function.name == "glTexDirectTiledMapVIV":
+-            print '#if defined(HAVE_VIVANTE_G2D)'
+-            print '    GLint tex;'
+-            print '    glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);'
+-            print '    int32_t size = 0;'
+-            print '    switch(format){'
+-            print '    case GL_VIV_YV12:'
+-            print '    case GL_VIV_I420:'
+-            print '    case GL_VIV_NV12:'
+-            print '    case GL_VIV_NV21:'
+-            print '        size=width * height * 3 / 2;'
+-            print '        break;'
+-            print '    case GL_RGBA:'
+-            print '    case GL_BGRA_EXT:'
+-            print '        size=width * height * 4;'
+-            print '        break;'
+-            print '    case GL_RGB:'
+-            print '        size=width * height *3;'
+-            print '        break;'
+-            print '    case GL_VIV_YUY2:'
+-            print '    case GL_VIV_UYVY:'
+-            print '    case GL_RGB565_OES:'
+-            print '    case GL_LUMINANCE8_ALPHA8_EXT:'
+-            print '        size=width * height *2;'
+-            print '        break;'
+-            print '    case GL_ALPHA:'
+-            print '        size=width * height;'
+-            print '        break;'
+-            print '    default:'
+-            print '        break;'
+-            print '    }'
+-            print '    if(tex != 0)'
+-            print '    {'
+-            print '        GLuint pindex = *(GLuint*)Logical;'
+-            print '        TEXDIRECTVIVDATA &data = _directTextureDataMap[tex];'
+-            print '        if(data.privateData == 0) // new entry'
+-            print '        {'
+-            print '            data.privateData = alloc_dma_buffer(size, (uintptr_t*)&data.logical, &data.physical);'
+-            print '            data.index = pindex;'
+-            print '            data.size = size;'
+-            print '            retrace::addRegion(call,data.index,data.logical,size);'
+-            print '        }'
+-            print '        else // already have one; check size and index'
+-            print '        {'
+-            print '            if((size!=data.size)||(pindex!=data.index))'
+-            print '            {'
+-            print '                retrace::delRegionByPointer(data.logical);'
+-            print '                free_dma_buffer(data.privateData);'
+-            print '                data.privateData = alloc_dma_buffer(size, (uintptr_t*)&data.logical, &data.physical);'
+-            print '                data.index = pindex;'
+-            print '                data.size = size;'
+-            print '                retrace::addRegion(call,data.index,data.logical,size);'
+-            print '            }'
+-            print '        }'
+-            print '        *Logical = data.logical;'
+-            print '        *Physical = data.physical;'
+-            print '    }'
+-            print '#endif /* HAVE_VIVANTE_G2D */'
++            print('#if defined(HAVE_VIVANTE_G2D)')
++            print('    GLint tex;')
++            print('    glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);')
++            print('    int32_t size = 0;')
++            print('    switch(format){')
++            print('    case GL_VIV_YV12:')
++            print('    case GL_VIV_I420:')
++            print('    case GL_VIV_NV12:')
++            print('    case GL_VIV_NV21:')
++            print('        size=width * height * 3 / 2;')
++            print('        break;')
++            print('    case GL_RGBA:')
++            print('    case GL_BGRA_EXT:')
++            print('        size=width * height * 4;')
++            print('        break;')
++            print('    case GL_RGB:')
++            print('        size=width * height *3;')
++            print('        break;')
++            print('    case GL_VIV_YUY2:')
++            print('    case GL_VIV_UYVY:')
++            print('    case GL_RGB565_OES:')
++            print('    case GL_LUMINANCE8_ALPHA8_EXT:')
++            print('        size=width * height *2;')
++            print('        break;')
++            print('    case GL_ALPHA:')
++            print('        size=width * height;')
++            print('        break;')
++            print('    default:')
++            print('        break;')
++            print('    }')
++            print('    if(tex != 0)')
++            print('    {')
++            print('        GLuint pindex = *(GLuint*)Logical;')
++            print('        TEXDIRECTVIVDATA &data = _directTextureDataMap[tex];')
++            print('        if(data.privateData == 0) // new entry')
++            print('        {')
++            print('            data.privateData = alloc_dma_buffer(size, (uintptr_t*)&data.logical, &data.physical);')
++            print('            data.index = pindex;')
++            print('            data.size = size;')
++            print('            retrace::addRegion(call,data.index,data.logical,size);')
++            print('        }')
++            print('        else // already have one; check size and index')
++            print('        {')
++            print('            if((size!=data.size)||(pindex!=data.index))')
++            print('            {')
++            print('                retrace::delRegionByPointer(data.logical);')
++            print('                free_dma_buffer(data.privateData);')
++            print('                data.privateData = alloc_dma_buffer(size, (uintptr_t*)&data.logical, &data.physical);')
++            print('                data.index = pindex;')
++            print('                data.size = size;')
++            print('                retrace::addRegion(call,data.index,data.logical,size);')
++            print('            }')
++            print('        }')
++            print('        *Logical = data.logical;')
++            print('        *Physical = data.physical;')
++            print('    }')
++            print('#endif /* HAVE_VIVANTE_G2D */')
+         # Infer the drawable size from GL calls
+         if function.name == "glViewport":
+-            print '    glretrace::updateDrawable(x + width, y + height);'
++            print('    glretrace::updateDrawable(x + width, y + height);')
+         if function.name == "glViewportArray":
+             # We are concerned about drawables so only care for the first viewport
+-            print '    if (first == 0 && count > 0) {'
+-            print '        GLfloat x = v[0], y = v[1], w = v[2], h = v[3];'
+-            print '        glretrace::updateDrawable(x + w, y + h);'
+-            print '    }'
++            print('    if (first == 0 && count > 0) {')
++            print('        GLfloat x = v[0], y = v[1], w = v[2], h = v[3];')
++            print('        glretrace::updateDrawable(x + w, y + h);')
++            print('    }')
+         if function.name == "glViewportIndexedf":
+-            print '    if (index == 0) {'
+-            print '        glretrace::updateDrawable(x + w, y + h);'
+-            print '    }'
++            print('    if (index == 0) {')
++            print('        glretrace::updateDrawable(x + w, y + h);')
++            print('    }')
+         if function.name == "glViewportIndexedfv":
+-            print '    if (index == 0) {'
+-            print '        GLfloat x = v[0], y = v[1], w = v[2], h = v[3];'
+-            print '        glretrace::updateDrawable(x + w, y + h);'
+-            print '    }'
++            print('    if (index == 0) {')
++            print('        GLfloat x = v[0], y = v[1], w = v[2], h = v[3];')
++            print('        glretrace::updateDrawable(x + w, y + h);')
++            print('    }')
+         if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'):
+             # Some applications do all their rendering in a framebuffer, and
+             # then just blit to the drawable without ever calling glViewport.
+-            print '    glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));'
++            print('    glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));')
+         if function.name.startswith('gl') and not function.name.startswith('glX'):
+             # The Windows OpenGL runtime will skip calls when there's no
+             # context bound to the current context, but this might cause
+             # crashes on other systems, particularly with NVIDIA Linux drivers.
+-            print r'    glretrace::Context *currentContext = glretrace::getCurrentContext();'
+-            print r'    if (!currentContext) {'
+-            print r'        if (retrace::debug) {'
+-            print r'            retrace::warning(call) << "no current context\n";'
+-            print r'        }'
+-            print r'#ifndef _WIN32'
+-            print r'        return;'
+-            print r'#endif'
+-            print r'    }'
++            print(r'    glretrace::Context *currentContext = glretrace::getCurrentContext();')
++            print(r'    if (!currentContext) {')
++            print(r'        if (retrace::debug) {')
++            print(r'            retrace::warning(call) << "no current context\n";')
++            print(r'        }')
++            print(r'#ifndef _WIN32')
++            print(r'        return;')
++            print(r'#endif')
++            print(r'    }')
+         if function.name == "glEnd":
+-            print r'    if (currentContext) {'
+-            print r'        currentContext->insideBeginEnd = false;'
+-            print r'    }'
++            print(r'    if (currentContext) {')
++            print(r'        currentContext->insideBeginEnd = false;')
++            print(r'    }')
+         if function.name == 'memcpy':
+-            print '    if (!dest || !src || !n) return;'
++            print('    if (!dest || !src || !n) return;')
+         # Skip glEnable/Disable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) as we don't
+         # faithfully set the CONTEXT_DEBUG_BIT_ARB flags on context creation.
+         if function.name in ('glEnable', 'glDisable'):
+-            print '    if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) return;'
++            print('    if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) return;')
+         # Destroy the buffer mapping
+         if self.unmap_function_regex.match(function.name):
+-            print r'        GLvoid *ptr = NULL;'
++            print(r'        GLvoid *ptr = NULL;')
+             if function.name == 'glUnmapBuffer':
+-                print r'            glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);'
++                print(r'            glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);')
+             elif function.name == 'glUnmapBufferARB':
+-                print r'            glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);'
++                print(r'            glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);')
+             elif function.name == 'glUnmapBufferOES':
+-                print r'            glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);'
++                print(r'            glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);')
+             elif function.name == 'glUnmapNamedBuffer':
+-                print r'            glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &ptr);'
++                print(r'            glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &ptr);')
+             elif function.name == 'glUnmapNamedBufferEXT':
+-                print r'            glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);'
++                print(r'            glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);')
+             elif function.name == 'glUnmapObjectBufferATI':
+                 # TODO
+                 pass
+             else:
+                 assert False
+-            print r'        if (ptr) {'
+-            print r'            retrace::delRegionByPointer(ptr);'
+-            print r'        } else {'
+-            print r'            retrace::warning(call) << "failed to get mapped pointer\n";'
+-            print r'        }'
++            print(r'        if (ptr) {')
++            print(r'            retrace::delRegionByPointer(ptr);')
++            print(r'        } else {')
++            print(r'            retrace::warning(call) << "failed to get mapped pointer\n";')
++            print(r'        }')
+         if function.name in ('glBindProgramPipeline', 'glBindProgramPipelineEXT'):
+             # Note if glBindProgramPipeline has ever been called
+-            print r'    if (pipeline) {'
+-            print r'        _pipelineHasBeenBound = true;'
+-            print r'    }'
++            print(r'    if (pipeline) {')
++            print(r'        _pipelineHasBeenBound = true;')
++            print(r'    }')
+         is_draw_arrays = self.draw_arrays_function_regex.match(function.name) is not None
+         is_draw_elements = self.draw_elements_function_regex.match(function.name) is not None
+@@ -325,240 +325,240 @@ class GlRetracer(Retracer):
+         # Keep track of active program for call lists
+         if function.name in ('glUseProgram', 'glUseProgramObjectARB'):
+-            print r'    if (currentContext) {'
+-            print r'        currentContext->activeProgram = call.arg(0).toUInt();'
+-            print r'    }'
++            print(r'    if (currentContext) {')
++            print(r'        currentContext->activeProgram = call.arg(0).toUInt();')
++            print(r'    }')
+         # Only profile if not inside a list as the queries get inserted into list
+         if function.name == 'glNewList':
+-            print r'    if (currentContext) {'
+-            print r'        currentContext->insideList = true;'
+-            print r'    }'
++            print(r'    if (currentContext) {')
++            print(r'        currentContext->insideList = true;')
++            print(r'    }')
+         if function.name == 'glEndList':
+-            print r'    if (currentContext) {'
+-            print r'        currentContext->insideList = false;'
+-            print r'    }'
++            print(r'    if (currentContext) {')
++            print(r'        currentContext->insideList = false;')
++            print(r'    }')
+         if function.name == 'glBegin' or \
+            is_draw_arrays or \
+            is_draw_elements or \
+            function.name.startswith('glBeginTransformFeedback'):
+-            print r'    if (retrace::debug) {'
+-            print r'        _validateActiveProgram(call);'
+-            print r'    }'
++            print(r'    if (retrace::debug) {')
++            print(r'        _validateActiveProgram(call);')
++            print(r'    }')
+         if function.name != 'glEnd':
+-            print r'    if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {'
++            print(r'    if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {')
+             if profileDraw:
+-                print r'        glretrace::beginProfile(call, true);'
++                print(r'        glretrace::beginProfile(call, true);')
+             else:
+-                print r'        glretrace::beginProfile(call, false);'
+-            print r'    }'
++                print(r'        glretrace::beginProfile(call, false);')
++            print(r'    }')
+         if function.name in ('glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT'):
+             # When dumping state, break down glCreateShaderProgram* so that the
+             # shader source can be recovered.
+-            print r'    if (retrace::dumpingState) {'
+-            print r'        GLuint _shader = glCreateShader(type);'
+-            print r'        if (_shader) {'
++            print(r'    if (retrace::dumpingState) {')
++            print(r'        GLuint _shader = glCreateShader(type);')
++            print(r'        if (_shader) {')
+             if not function.name.startswith('glCreateShaderProgramv'):
+-                print r'            GLsizei count = 1;'
+-                print r'            const GLchar **strings = &string;'
+-            print r'            glShaderSource(_shader, count, strings, NULL);'
+-            print r'            glCompileShader(_shader);'
+-            print r'            const GLuint _program = glCreateProgram();'
+-            print r'            if (_program) {'
+-            print r'                GLint compiled = GL_FALSE;'
+-            print r'                glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled);'
++                print(r'            GLsizei count = 1;')
++                print(r'            const GLchar **strings = &string;')
++            print(r'            glShaderSource(_shader, count, strings, NULL);')
++            print(r'            glCompileShader(_shader);')
++            print(r'            const GLuint _program = glCreateProgram();')
++            print(r'            if (_program) {')
++            print(r'                GLint compiled = GL_FALSE;')
++            print(r'                glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled);')
+             if function.name == 'glCreateShaderProgramvEXT':
+-                print r'                glProgramParameteriEXT(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);'
++                print(r'                glProgramParameteriEXT(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);')
+             else:
+-                print r'                glProgramParameteri(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);'
+-            print r'                if (compiled) {'
+-            print r'                    glAttachShader(_program, _shader);'
+-            print r'                    glLinkProgram(_program);'
+-            print r'                    if (false) glDetachShader(_program, _shader);'
+-            print r'                }'
+-            print r'                // TODO: append shader info log to program info log'
+-            print r'            }'
+-            print r'            glDeleteShader(_shader);'
+-            print r'            _result = _program;'
+-            print r'        } else {'
+-            print r'            _result = 0;'
+-            print r'        }'
+-            print r'    } else {'
++                print(r'                glProgramParameteri(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);')
++            print(r'                if (compiled) {')
++            print(r'                    glAttachShader(_program, _shader);')
++            print(r'                    glLinkProgram(_program);')
++            print(r'                    if (false) glDetachShader(_program, _shader);')
++            print(r'                }')
++            print(r'                // TODO: append shader info log to program info log')
++            print(r'            }')
++            print(r'            glDeleteShader(_shader);')
++            print(r'            _result = _program;')
++            print(r'        } else {')
++            print(r'            _result = 0;')
++            print(r'        }')
++            print(r'    } else {')
+             Retracer.invokeFunction(self, function)
+-            print r'    }'
++            print(r'    }')
+         elif function.name in ('glDetachShader', 'glDetachObjectARB'):
+-            print r'    if (!retrace::dumpingState) {'
++            print(r'    if (!retrace::dumpingState) {')
+             Retracer.invokeFunction(self, function)
+-            print r'    }'
++            print(r'    }')
+         elif function.name == 'glClientWaitSync':
+-            print r'    _result = glretrace::clientWaitSync(call, sync, flags, timeout);'
+-            print r'    (void)_result;'
++            print(r'    _result = glretrace::clientWaitSync(call, sync, flags, timeout);')
++            print(r'    (void)_result;')
+         elif function.name == 'glGetSynciv':
+-            print r'    if (pname == GL_SYNC_STATUS &&'
+-            print r'        bufSize >= 1 &&'
+-            print r'        values != NULL &&'
+-            print r'        call.arg(4)[0].toSInt() == GL_SIGNALED) {'
+-            print r'        // Fence was signalled, so ensure it happened here'
+-            print r'        glretrace::blockOnFence(call, sync, GL_SYNC_FLUSH_COMMANDS_BIT);'
+-            print r'        (void)length;'
+-            print r'    }'
++            print(r'    if (pname == GL_SYNC_STATUS &&')
++            print(r'        bufSize >= 1 &&')
++            print(r'        values != NULL &&')
++            print(r'        call.arg(4)[0].toSInt() == GL_SIGNALED) {')
++            print(r'        // Fence was signalled, so ensure it happened here')
++            print(r'        glretrace::blockOnFence(call, sync, GL_SYNC_FLUSH_COMMANDS_BIT);')
++            print(r'        (void)length;')
++            print(r'    }')
+         else:
+             Retracer.invokeFunction(self, function)
+         if function.name == "glBegin":
+-            print '    if (currentContext) {'
+-            print '        currentContext->insideBeginEnd = true;'
+-            print '    }'
++            print('    if (currentContext) {')
++            print('        currentContext->insideBeginEnd = true;')
++            print('    }')
+         if function.name == "glTexDirectVIV":
+-            print '#if defined(HAVE_VIVANTE_G2D)'
+-            print '    int32_t ysize = 0;'
+-            print '    int32_t usize = 0;'
+-            print '    int32_t vsize = 0;'
+-            print '    switch(format){'
+-            print '    case GL_VIV_YV12:'
+-            print '    case GL_VIV_I420:'
+-            print '        ysize=width * height;'
+-            print '        usize=ysize/4;'
+-            print '        vsize=usize;'
+-            print '        break;'
+-            print '    case GL_VIV_NV12:'
+-            print '    case GL_VIV_NV21:'
+-            print '        ysize=width * height;'
+-            print '        usize=ysize/2;'
+-            print '        vsize=0;'
+-            print '        break;'
+-            print '    case GL_RGBA:'
+-            print '    case GL_BGRA_EXT:'
+-            print '        ysize=width * height *4;'
+-            print '        usize=0;'
+-            print '        vsize=0;'
+-            print '        break;'
+-            print '    case GL_RGB:'
+-            print '        ysize=width * height *3;'
+-            print '        usize=0;'
+-            print '        vsize=0;'
+-            print '        break;'
+-            print '    case GL_VIV_YUY2:'
+-            print '    case GL_VIV_UYVY:'
+-            print '    case GL_RGB565_OES:'
+-            print '        ysize=width * height *2;'
+-            print '        usize=0;'
+-            print '        vsize=0;'
+-            print '        break;'
+-            print '    default:'
+-            print '        break;'
+-            print '    }'
+-            print '    const trace::Array * arrayGLvoid = (call.arg(4)).toArray();'
+-            print '    if(ysize > 0)'
+-            print '        retrace::addRegion(call,(*arrayGLvoid->values[0]).toUInt(),(GLvoid*)pixels[0], ysize);'
+-            print '    if(usize > 0)'
+-            print '        retrace::addRegion(call,(*arrayGLvoid->values[1]).toUInt(),(GLvoid*)pixels[1], usize);'
+-            print '    if(vsize > 0)'
+-            print '        retrace::addRegion(call,(*arrayGLvoid->values[2]).toUInt(),(GLvoid*)pixels[2], vsize);'
+-            print '#endif /* HAVE_VIVANTE_G2D */'
+-
+-        print r'    if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {'
++            print('#if defined(HAVE_VIVANTE_G2D)')
++            print('    int32_t ysize = 0;')
++            print('    int32_t usize = 0;')
++            print('    int32_t vsize = 0;')
++            print('    switch(format){')
++            print('    case GL_VIV_YV12:')
++            print('    case GL_VIV_I420:')
++            print('        ysize=width * height;')
++            print('        usize=ysize/4;')
++            print('        vsize=usize;')
++            print('        break;')
++            print('    case GL_VIV_NV12:')
++            print('    case GL_VIV_NV21:')
++            print('        ysize=width * height;')
++            print('        usize=ysize/2;')
++            print('        vsize=0;')
++            print('        break;')
++            print('    case GL_RGBA:')
++            print('    case GL_BGRA_EXT:')
++            print('        ysize=width * height *4;')
++            print('        usize=0;')
++            print('        vsize=0;')
++            print('        break;')
++            print('    case GL_RGB:')
++            print('        ysize=width * height *3;')
++            print('        usize=0;')
++            print('        vsize=0;')
++            print('        break;')
++            print('    case GL_VIV_YUY2:')
++            print('    case GL_VIV_UYVY:')
++            print('    case GL_RGB565_OES:')
++            print('        ysize=width * height *2;')
++            print('        usize=0;')
++            print('        vsize=0;')
++            print('        break;')
++            print('    default:')
++            print('        break;')
++            print('    }')
++            print('    const trace::Array * arrayGLvoid = (call.arg(4)).toArray();')
++            print('    if(ysize > 0)')
++            print('        retrace::addRegion(call,(*arrayGLvoid->values[0]).toUInt(),(GLvoid*)pixels[0], ysize);')
++            print('    if(usize > 0)')
++            print('        retrace::addRegion(call,(*arrayGLvoid->values[1]).toUInt(),(GLvoid*)pixels[1], usize);')
++            print('    if(vsize > 0)')
++            print('        retrace::addRegion(call,(*arrayGLvoid->values[2]).toUInt(),(GLvoid*)pixels[2], vsize);')
++            print('#endif /* HAVE_VIVANTE_G2D */')
++
++        print(r'    if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {')
+         if profileDraw:
+-            print r'        glretrace::endProfile(call, true);'
++            print(r'        glretrace::endProfile(call, true);')
+         else:
+-            print r'        glretrace::endProfile(call, false);'
+-        print r'    }'
++            print(r'        glretrace::endProfile(call, false);')
++        print(r'    }')
+         # Error checking
+         if function.name.startswith('gl'):
+             # glGetError is not allowed inside glBegin/glEnd
+-            print '    if (retrace::debug && currentContext && !currentContext->insideBeginEnd) {'
+-            print '        glretrace::checkGlError(call);'
++            print('    if (retrace::debug && currentContext && !currentContext->insideBeginEnd) {')
++            print('        glretrace::checkGlError(call);')
+             if function.name in ('glProgramStringARB', 'glLoadProgramNV'):
+-                print r'        GLint error_position = -1;'
+-                print r'        glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);'
+-                print r'        if (error_position != -1) {'
+-                print r'            const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);'
+-                print r'            retrace::warning(call) << "error in position " << error_position << ": " << error_string << "\n";'
+-                print r'        }'
++                print(r'        GLint error_position = -1;')
++                print(r'        glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);')
++                print(r'        if (error_position != -1) {')
++                print(r'            const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);')
++                print(r'            retrace::warning(call) << "error in position " << error_position << ": " << error_string << "\n";')
++                print(r'        }')
+             if function.name == 'glCompileShader':
+-                print r'        GLint compile_status = 0;'
+-                print r'        glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);'
+-                print r'        if (!compile_status) {'
+-                print r'             retrace::warning(call) << "compilation failed\n";'
+-                print r'        }'
+-                print r'        GLint info_log_length = 0;'
+-                print r'        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
+-                print r'        if (info_log_length > 1) {'
+-                print r'             GLchar *infoLog = new GLchar[info_log_length];'
+-                print r'             glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);'
+-                print r'             retrace::warning(call) << infoLog << "\n";'
+-                print r'             delete [] infoLog;'
+-                print r'        }'
++                print(r'        GLint compile_status = 0;')
++                print(r'        glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);')
++                print(r'        if (!compile_status) {')
++                print(r'             retrace::warning(call) << "compilation failed\n";')
++                print(r'        }')
++                print(r'        GLint info_log_length = 0;')
++                print(r'        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);')
++                print(r'        if (info_log_length > 1) {')
++                print(r'             GLchar *infoLog = new GLchar[info_log_length];')
++                print(r'             glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);')
++                print(r'             retrace::warning(call) << infoLog << "\n";')
++                print(r'             delete [] infoLog;')
++                print(r'        }')
+             if function.name in ('glLinkProgram', 'glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT', 'glProgramBinary', 'glProgramBinaryOES'):
+                 if function.name.startswith('glCreateShaderProgram'):
+-                    print r'        GLuint program = _result;'
+-                print r'        GLint link_status = 0;'
+-                print r'        glGetProgramiv(program, GL_LINK_STATUS, &link_status);'
+-                print r'        if (!link_status) {'
+-                print r'             retrace::warning(call) << "link failed\n";'
+-                print r'        }'
+-                print r'        GLint info_log_length = 0;'
+-                print r'        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
+-                print r'        if (info_log_length > 1) {'
+-                print r'             GLchar *infoLog = new GLchar[info_log_length];'
+-                print r'             glGetProgramInfoLog(program, info_log_length, NULL, infoLog);'
+-                print r'             retrace::warning(call) << infoLog << "\n";'
+-                print r'             delete [] infoLog;'
+-                print r'        }'
++                    print(r'        GLuint program = _result;')
++                print(r'        GLint link_status = 0;')
++                print(r'        glGetProgramiv(program, GL_LINK_STATUS, &link_status);')
++                print(r'        if (!link_status) {')
++                print(r'             retrace::warning(call) << "link failed\n";')
++                print(r'        }')
++                print(r'        GLint info_log_length = 0;')
++                print(r'        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);')
++                print(r'        if (info_log_length > 1) {')
++                print(r'             GLchar *infoLog = new GLchar[info_log_length];')
++                print(r'             glGetProgramInfoLog(program, info_log_length, NULL, infoLog);')
++                print(r'             retrace::warning(call) << infoLog << "\n";')
++                print(r'             delete [] infoLog;')
++                print(r'        }')
+             if function.name == 'glCompileShaderARB':
+-                print r'        GLint compile_status = 0;'
+-                print r'        glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);'
+-                print r'        if (!compile_status) {'
+-                print r'             retrace::warning(call) << "compilation failed\n";'
+-                print r'        }'
+-                print r'        GLint info_log_length = 0;'
+-                print r'        glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
+-                print r'        if (info_log_length > 1) {'
+-                print r'             GLchar *infoLog = new GLchar[info_log_length];'
+-                print r'             glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);'
+-                print r'             retrace::warning(call) << infoLog << "\n";'
+-                print r'             delete [] infoLog;'
+-                print r'        }'
++                print(r'        GLint compile_status = 0;')
++                print(r'        glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);')
++                print(r'        if (!compile_status) {')
++                print(r'             retrace::warning(call) << "compilation failed\n";')
++                print(r'        }')
++                print(r'        GLint info_log_length = 0;')
++                print(r'        glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);')
++                print(r'        if (info_log_length > 1) {')
++                print(r'             GLchar *infoLog = new GLchar[info_log_length];')
++                print(r'             glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);')
++                print(r'             retrace::warning(call) << infoLog << "\n";')
++                print(r'             delete [] infoLog;')
++                print(r'        }')
+             if function.name == 'glLinkProgramARB':
+-                print r'        GLint link_status = 0;'
+-                print r'        glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);'
+-                print r'        if (!link_status) {'
+-                print r'             retrace::warning(call) << "link failed\n";'
+-                print r'        }'
+-                print r'        GLint info_log_length = 0;'
+-                print r'        glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
+-                print r'        if (info_log_length > 1) {'
+-                print r'             GLchar *infoLog = new GLchar[info_log_length];'
+-                print r'             glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);'
+-                print r'             retrace::warning(call) << infoLog << "\n";'
+-                print r'             delete [] infoLog;'
+-                print r'        }'
++                print(r'        GLint link_status = 0;')
++                print(r'        glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);')
++                print(r'        if (!link_status) {')
++                print(r'             retrace::warning(call) << "link failed\n";')
++                print(r'        }')
++                print(r'        GLint info_log_length = 0;')
++                print(r'        glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);')
++                print(r'        if (info_log_length > 1) {')
++                print(r'             GLchar *infoLog = new GLchar[info_log_length];')
++                print(r'             glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);')
++                print(r'             retrace::warning(call) << infoLog << "\n";')
++                print(r'             delete [] infoLog;')
++                print(r'        }')
+             if self.map_function_regex.match(function.name):
+-                print r'        if (!_result) {'
+-                print r'             retrace::warning(call) << "failed to map buffer\n";'
+-                print r'        }'
++                print(r'        if (!_result) {')
++                print(r'             retrace::warning(call) << "failed to map buffer\n";')
++                print(r'        }')
+             if self.unmap_function_regex.match(function.name) and function.type is not stdapi.Void:
+-                print r'        if (!_result) {'
+-                print r'             retrace::warning(call) << "failed to unmap buffer\n";'
+-                print r'        }'
++                print(r'        if (!_result) {')
++                print(r'             retrace::warning(call) << "failed to unmap buffer\n";')
++                print(r'        }')
+             if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'):
+-                print r'    GLint _origResult = call.ret->toSInt();'
+-                print r'    if (_result != _origResult) {'
+-                print r'        retrace::warning(call) << "vertex attrib location mismatch " << _origResult << " -> " << _result << "\n";'
+-                print r'    }'
++                print(r'    GLint _origResult = call.ret->toSInt();')
++                print(r'    if (_result != _origResult) {')
++                print(r'        retrace::warning(call) << "vertex attrib location mismatch " << _origResult << " -> " << _result << "\n";')
++                print(r'    }')
+             if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatus', 'glCheckNamedFramebufferStatusEXT'):
+-                print r'    GLint _origResult = call.ret->toSInt();'
+-                print r'    if (_origResult == GL_FRAMEBUFFER_COMPLETE &&'
+-                print r'        _result != GL_FRAMEBUFFER_COMPLETE) {'
+-                print r'        retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(_result) << ")\n";'
+-                print r'    }'
+-            print '    }'
++                print(r'    GLint _origResult = call.ret->toSInt();')
++                print(r'    if (_origResult == GL_FRAMEBUFFER_COMPLETE &&')
++                print(r'        _result != GL_FRAMEBUFFER_COMPLETE) {')
++                print(r'        retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(_result) << ")\n";')
++                print(r'    }')
++            print('    }')
+         # Query the buffer length for whole buffer mappings
+         if self.map_function_regex.match(function.name):
+@@ -566,23 +566,23 @@ class GlRetracer(Retracer):
+                 assert 'BufferRange' in function.name
+             else:
+                 assert 'BufferRange' not in function.name
+-                print r'    GLint length = 0;'
++                print(r'    GLint length = 0;')
+                 if function.name in ('glMapBuffer', 'glMapBufferOES'):
+-                    print r'    glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);'
++                    print(r'    glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);')
+                 elif function.name == 'glMapBufferARB':
+-                    print r'    glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);'
++                    print(r'    glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);')
+                 elif function.name == 'glMapNamedBuffer':
+-                    print r'    glGetNamedBufferParameteriv(buffer, GL_BUFFER_SIZE, &length);'
++                    print(r'    glGetNamedBufferParameteriv(buffer, GL_BUFFER_SIZE, &length);')
+                 elif function.name == 'glMapNamedBufferEXT':
+-                    print r'    glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);'
++                    print(r'    glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);')
+                 elif function.name == 'glMapObjectBufferATI':
+-                    print r'    glGetObjectBufferivATI(buffer, GL_OBJECT_BUFFER_SIZE_ATI, &length);'
++                    print(r'    glGetObjectBufferivATI(buffer, GL_OBJECT_BUFFER_SIZE_ATI, &length);')
+                 else:
+                     assert False
+     def extractArg(self, function, arg, arg_type, lvalue, rvalue):
+         if function.name in self.array_pointer_function_names and arg.name == 'pointer':
+-            print '    %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue)
++            print('    %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue))
+             return
+         if self.draw_elements_function_regex.match(function.name) and arg.name == 'indices' or\
+@@ -594,18 +594,18 @@ class GlRetracer(Retracer):
+         # object.
+         if self.pack_function_regex.match(function.name) and arg.output:
+             assert isinstance(arg_type, (stdapi.Pointer, stdapi.Array, stdapi.Blob, stdapi.Opaque))
+-            print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue)
++            print('    %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue))
+             return
+         if (arg.type.depends(glapi.GLlocation) or \
+             arg.type.depends(glapi.GLsubroutine)) \
+            and 'program' not in function.argNames():
+             # Determine the active program for uniforms swizzling
+-            print '    GLint program = _getActiveProgram();'
++            print('    GLint program = _getActiveProgram();')
+         if arg.type is glapi.GLlocationARB \
+            and 'programObj' not in function.argNames():
+-            print '    GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);'
++            print('    GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);')
+         Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
+@@ -613,28 +613,28 @@ class GlRetracer(Retracer):
+         if arg.name == 'samples':
+             if function.name == 'glRasterSamplesEXT':
+                 assert arg.type is glapi.GLuint
+-                print '    GLint max_samples = 0;'
+-                print '    glGetIntegerv(GL_MAX_RASTER_SAMPLES_EXT, &max_samples);'
+-                print '    if (samples > static_cast<GLuint>(max_samples)) {'
+-                print '        samples = static_cast<GLuint>(max_samples);'
+-                print '    }'
++                print('    GLint max_samples = 0;')
++                print('    glGetIntegerv(GL_MAX_RASTER_SAMPLES_EXT, &max_samples);')
++                print('    if (samples > static_cast<GLuint>(max_samples)) {')
++                print('        samples = static_cast<GLuint>(max_samples);')
++                print('    }')
+             else:
+                 assert arg.type is glapi.GLsizei
+-                print '    GLint max_samples = 0;'
+-                print '    glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
+-                print '    if (samples > max_samples) {'
+-                print '        samples = max_samples;'
+-                print '    }'
++                print('    GLint max_samples = 0;')
++                print('    glGetIntegerv(GL_MAX_SAMPLES, &max_samples);')
++                print('    if (samples > max_samples) {')
++                print('        samples = max_samples;')
++                print('    }')
+         # These parameters are referred beyond the call life-time
+         # TODO: Replace ad-hoc solution for bindable parameters with general one
+         if function.name in ('glFeedbackBuffer', 'glSelectBuffer') and arg.output:
+-            print '    _allocator.bind(%s);' % arg.name
++            print('    _allocator.bind(%s);' % arg.name)
+ if __name__ == '__main__':
+-    print r'''
++    print(r'''
+ #include <string.h>
+ #include "glproc.hpp"
+@@ -692,13 +692,13 @@ static void free_dma_buffer(void *buf)
+ #endif /* HAVE_VIVANTE_G2D */
+-'''
++''')
+     api = stdapi.API()
+     api.addModule(glapi.glapi)
+     retracer = GlRetracer()
+     retracer.retraceApi(api)
+-    print r'''
++    print(r'''
+ static GLint
+ _getActiveProgram(void)
+ {
+@@ -771,4 +771,4 @@ _validateActiveProgram(trace::Call &call)
+     }
+ }
+-'''
++''')
+diff --git a/retrace/glstate_params.py b/retrace/glstate_params.py
+index fb49ff9a..bc90f66b 100755
+--- a/retrace/glstate_params.py
++++ b/retrace/glstate_params.py
+@@ -134,17 +134,17 @@ class StateGetter(Visitor):
+         elem_type = self.inflector.reduced_type(type)
+         inflection = self.inflector.inflect(type)
+         if inflection.endswith('v' + self.inflector.suffix):
+-            print '    %s %s = 0;' % (elem_type, temp_name)
+-            print '    %s(%s, &%s);' % (inflection, ', '.join(args), temp_name)
++            print('    %s %s = 0;' % (elem_type, temp_name))
++            print('    %s(%s, &%s);' % (inflection, ', '.join(args), temp_name))
+         else:
+-            print '    %s %s = %s(%s);' % (elem_type, temp_name, inflection, ', '.join(args))
++            print('    %s %s = %s(%s);' % (elem_type, temp_name, inflection, ', '.join(args)))
+         return temp_name
+     def visitString(self, string, args):
+         temp_name = self.temp_name(args)
+         inflection = self.inflector.inflect(string)
+         assert not inflection.endswith('v' + self.inflector.suffix)
+-        print '    %s %s = (%s)%s(%s);' % (string, temp_name, string, inflection, ', '.join(args))
++        print('    %s %s = (%s)%s(%s);' % (string, temp_name, string, inflection, ', '.join(args)))
+         return temp_name
+     def visitAlias(self, alias, args):
+@@ -166,28 +166,28 @@ class StateGetter(Visitor):
+         array_length = array.length
+         if isinstance(array_length, int):
+             # Static integer length
+-            print '    %s %s[%s + 1];' % (elem_type, temp_name, array_length)
++            print('    %s %s[%s + 1];' % (elem_type, temp_name, array_length))
+         else:
+             # Put the length in a variable to avoid recomputing it every time
+-            print '    size_t _%s_length = %s;' % (temp_name, array_length)
++            print('    size_t _%s_length = %s;' % (temp_name, array_length))
+             array_length = '_%s_length' % temp_name
+             # Allocate a dynamic sized array
+-            print '    %s *%s = _allocator.alloc<%s>(%s + 1);' % (elem_type, temp_name, elem_type, array_length)
+-        print '    memset(%s, 0, %s * sizeof *%s);' % (temp_name, array_length, temp_name)
+-        print '    %s[%s] = (%s)0xdeadc0de;' % (temp_name, array_length, elem_type)
+-        print '    if (%s) {' % array_length
+-        print '        %s(%s, %s);' % (inflection, ', '.join(args), temp_name)
+-        print '    }'
++            print('    %s *%s = _allocator.alloc<%s>(%s + 1);' % (elem_type, temp_name, elem_type, array_length))
++        print('    memset(%s, 0, %s * sizeof *%s);' % (temp_name, array_length, temp_name))
++        print('    %s[%s] = (%s)0xdeadc0de;' % (temp_name, array_length, elem_type))
++        print('    if (%s) {' % array_length)
++        print('        %s(%s, %s);' % (inflection, ', '.join(args), temp_name))
++        print('    }')
+         # Simple buffer overflow detection
+-        print '    assert(%s[%s] == (%s)0xdeadc0de);' % (temp_name, array_length, elem_type)
++        print('    assert(%s[%s] == (%s)0xdeadc0de);' % (temp_name, array_length, elem_type))
+         return temp_name
+     def visitOpaque(self, pointer, args):
+         temp_name = self.temp_name(args)
+         inflection = self.inflector.inflect(pointer)
+         assert inflection.endswith('v' + self.inflector.suffix)
+-        print '    GLvoid *%s;' % temp_name
+-        print '    %s(%s, &%s);' % (inflection, ', '.join(args), temp_name)
++        print('    GLvoid *%s;' % temp_name)
++        print('    %s(%s, &%s);' % (inflection, ', '.join(args), temp_name))
+         return temp_name
+@@ -236,26 +236,26 @@ class JsonWriter(Visitor):
+     def visitLiteral(self, literal, instance):
+         if literal.kind == 'Bool':
+-            print '    writer.writeBool(%s);' % instance
++            print('    writer.writeBool(%s);' % instance)
+         elif literal.kind in ('SInt', 'Uint'):
+-            print '    writer.writeInt(%s);' % instance
++            print('    writer.writeInt(%s);' % instance)
+         elif literal.kind in ('Float', 'Double'):
+-            print '    writer.writeFloat(%s);' % instance
++            print('    writer.writeFloat(%s);' % instance)
+         else:
+             raise NotImplementedError
+     def visitString(self, string, instance):
+         assert string.length is None
+-        print '    writer.writeString((const char *)%s);' % instance
++        print('    writer.writeString((const char *)%s);' % instance)
+     def visitEnum(self, enum, instance):
+         if enum is GLboolean:
+-            print '    dumpBoolean(writer, %s);' % instance
++            print('    dumpBoolean(writer, %s);' % instance)
+         elif enum is GLenum:
+-            print '    dumpEnum(writer, %s);' % instance
++            print('    dumpEnum(writer, %s);' % instance)
+         else:
+             assert False
+-            print '    writer.writeInt(%s);' % instance
++            print('    writer.writeInt(%s);' % instance)
+     def visitBitmask(self, bitmask, instance):
+         raise NotImplementedError
+@@ -264,18 +264,18 @@ class JsonWriter(Visitor):
+         self.visit(alias.type, instance)
+     def visitOpaque(self, opaque, instance):
+-        print '    writer.writeInt((size_t)%s);' % instance
++        print('    writer.writeInt((size_t)%s);' % instance)
+     __index = 0
+     def visitArray(self, array, instance):
+         index = '_i%u' % JsonWriter.__index
+         JsonWriter.__index += 1
+-        print '    writer.beginArray();'
+-        print '    for (unsigned %s = 0; %s < %s; ++%s) {' % (index, index, array.length, index)
++        print('    writer.beginArray();')
++        print('    for (unsigned %s = 0; %s < %s; ++%s) {' % (index, index, array.length, index))
+         self.visit(array.type, '%s[%s]' % (instance, index))
+-        print '    }'
+-        print '    writer.endArray();'
++        print('    }')
++        print('    writer.endArray();')
+@@ -287,75 +287,75 @@ class StateDumper:
+         pass
+     def dump(self):
+-        print '#include <assert.h>'
+-        print '#include <string.h>'
+-        print
+-        print '#include "state_writer.hpp"'
+-        print '#include "scoped_allocator.hpp"'
+-        print '#include "glproc.hpp"'
+-        print '#include "glsize.hpp"'
+-        print '#include "glstate.hpp"'
+-        print '#include "glstate_internal.hpp"'
+-        print
+-        print 'namespace glstate {'
+-        print
+-
+-        print 'const char *'
+-        print 'enumToString(GLenum pname)'
+-        print '{'
+-        print '    switch (pname) {'
++        print('#include <assert.h>')
++        print('#include <string.h>')
++        print()
++        print('#include "state_writer.hpp"')
++        print('#include "scoped_allocator.hpp"')
++        print('#include "glproc.hpp"')
++        print('#include "glsize.hpp"')
++        print('#include "glstate.hpp"')
++        print('#include "glstate_internal.hpp"')
++        print()
++        print('namespace glstate {')
++        print()
++
++        print('const char *')
++        print('enumToString(GLenum pname)')
++        print('{')
++        print('    switch (pname) {')
+         for name in GLenum.values:
+-            print '    case %s:' % name
+-            print '        return "%s";' % name
+-        print '    default:'
+-        print '        return NULL;'
+-        print '    }'
+-        print '}'
+-        print
+-
+-        print 'static void'
+-        print 'dumpTextureTargetParameters(StateWriter &writer, Context &context, GLenum target, GLuint texture)'
+-        print '{'
+-        print '    writer.beginMember(enumToString(target));'
+-        print '    writer.beginObject();'
+-        print '    dumpObjectLabel(writer, context, GL_TEXTURE, texture, "GL_TEXTURE_LABEL");'
++            print('    case %s:' % name)
++            print('        return "%s";' % name)
++        print('    default:')
++        print('        return NULL;')
++        print('    }')
++        print('}')
++        print()
++
++        print('static void')
++        print('dumpTextureTargetParameters(StateWriter &writer, Context &context, GLenum target, GLuint texture)')
++        print('{')
++        print('    writer.beginMember(enumToString(target));')
++        print('    writer.beginObject();')
++        print('    dumpObjectLabel(writer, context, GL_TEXTURE, texture, "GL_TEXTURE_LABEL");')
+         # ARB_texture_buffer forbids glGetTexParameter and
+         # glGetTexLevelParameter for TEXTURE_BUFFER, but
+         # ARB_texture_buffer_range introduced parameters which can be queries
+         # with glGetTexLevelParameter...
+-        print '    if (target != GL_TEXTURE_BUFFER) {'
++        print('    if (target != GL_TEXTURE_BUFFER) {')
+         self.dump_atoms(glGetTexParameter, 'target')
+-        print '    }'
+-        print '    if (!context.ES) {'
+-        print '        GLenum levelTarget;'
+-        print '        if (target == GL_TEXTURE_CUBE_MAP ||'
+-        print '            target == GL_TEXTURE_CUBE_MAP_ARRAY) {'
+-        print '            // Must pick a face'
+-        print '            levelTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;'
+-        print '        } else {'
+-        print '            levelTarget = target;'
+-        print '        }'
++        print('    }')
++        print('    if (!context.ES) {')
++        print('        GLenum levelTarget;')
++        print('        if (target == GL_TEXTURE_CUBE_MAP ||')
++        print('            target == GL_TEXTURE_CUBE_MAP_ARRAY) {')
++        print('            // Must pick a face')
++        print('            levelTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;')
++        print('        } else {')
++        print('            levelTarget = target;')
++        print('        }')
+         self.dump_atoms(glGetTexLevelParameter, 'levelTarget', '0')
+-        print '    }'
+-        print '    writer.endObject();'
+-        print '    writer.endMember(); // target'
+-        print '}'
+-        print
+-
+-        print 'static void'
+-        print 'dumpFramebufferAttachementParameters(StateWriter &writer, Context &context, GLenum target, GLenum attachment)'
+-        print '{'
++        print('    }')
++        print('    writer.endObject();')
++        print('    writer.endMember(); // target')
++        print('}')
++        print()
++
++        print('static void')
++        print('dumpFramebufferAttachementParameters(StateWriter &writer, Context &context, GLenum target, GLenum attachment)')
++        print('{')
+         self.dump_attachment_parameters('target', 'attachment')
+-        print '}'
+-        print
+-
+-        print 'void dumpParameters(StateWriter &writer, Context &context)'
+-        print '{'
+-        print '    ScopedAllocator _allocator;'
+-        print '    (void)_allocator;'
+-        print
+-        print '    writer.beginMember("parameters");'
+-        print '    writer.beginObject();'
++        print('}')
++        print()
++
++        print('void dumpParameters(StateWriter &writer, Context &context)')
++        print('{')
++        print('    ScopedAllocator _allocator;')
++        print('    (void)_allocator;')
++        print()
++        print('    writer.beginMember("parameters");')
++        print('    writer.beginObject();')
+         
+         self.dump_atoms(glGet)
+         
+@@ -368,58 +368,58 @@ class StateDumper:
+         self.dump_framebuffer_parameters()
+         self.dump_labels()
+-        print '    writer.endObject();'
+-        print '    writer.endMember(); // parameters'
+-        print '}'
+-        print
++        print('    writer.endObject();')
++        print('    writer.endMember(); // parameters')
++        print('}')
++        print()
+         
+-        print '} /*namespace glstate */'
++        print('} /*namespace glstate */')
+     def dump_material_params(self):
+-        print '    if (!context.ES) {'
++        print('    if (!context.ES) {')
+         for face in ['GL_FRONT', 'GL_BACK']:
+-            print '    writer.beginMember("%s");' % face
+-            print '    writer.beginObject();'
++            print('    writer.beginMember("%s");' % face)
++            print('    writer.beginObject();')
+             self.dump_atoms(glGetMaterial, face)
+-            print '    writer.endObject();'
+-        print '    }'
+-        print
++            print('    writer.endObject();')
++        print('    }')
++        print()
+     def dump_light_params(self):
+-        print '    GLint max_lights = 0;'
+-        print '    _glGetIntegerv(GL_MAX_LIGHTS, &max_lights);'
+-        print '    for (GLint index = 0; index < max_lights; ++index) {'
+-        print '        GLenum light = GL_LIGHT0 + index;'
+-        print '        if (glIsEnabled(light)) {'
+-        print '            char name[32];'
+-        print '            snprintf(name, sizeof name, "GL_LIGHT%i", index);'
+-        print '            writer.beginMember(name);'
+-        print '            writer.beginObject();'
++        print('    GLint max_lights = 0;')
++        print('    _glGetIntegerv(GL_MAX_LIGHTS, &max_lights);')
++        print('    for (GLint index = 0; index < max_lights; ++index) {')
++        print('        GLenum light = GL_LIGHT0 + index;')
++        print('        if (glIsEnabled(light)) {')
++        print('            char name[32];')
++        print('            snprintf(name, sizeof name, "GL_LIGHT%i", index);')
++        print('            writer.beginMember(name);')
++        print('            writer.beginObject();')
+         self.dump_atoms(glGetLight, '    GL_LIGHT0 + index')
+-        print '            writer.endObject();'
+-        print '            writer.endMember(); // GL_LIGHTi'
+-        print '        }'
+-        print '    }'
+-        print
++        print('            writer.endObject();')
++        print('            writer.endMember(); // GL_LIGHTi')
++        print('        }')
++        print('    }')
++        print()
+     def dump_sampler_params(self):
+-        print '    // GL_SAMPLER_BINDING'
+-        print '    if (context.ARB_sampler_objects) {'
+-        print '        GLint sampler_binding = 0;'
+-        print '        glGetIntegerv(GL_SAMPLER_BINDING, &sampler_binding);'
+-        print '        writer.beginMember("GL_SAMPLER_BINDING");'
+-        print '        writer.writeInt(sampler_binding);'
+-        print '        writer.endMember();'
+-        print '        if (sampler_binding) {'
+-        print '            writer.beginMember("GL_SAMPLER");'
+-        print '            writer.beginObject();'
+-        print '            dumpObjectLabel(writer, context, GL_SAMPLER, sampler_binding, "GL_SAMPLER_LABEL");'
++        print('    // GL_SAMPLER_BINDING')
++        print('    if (context.ARB_sampler_objects) {')
++        print('        GLint sampler_binding = 0;')
++        print('        glGetIntegerv(GL_SAMPLER_BINDING, &sampler_binding);')
++        print('        writer.beginMember("GL_SAMPLER_BINDING");')
++        print('        writer.writeInt(sampler_binding);')
++        print('        writer.endMember();')
++        print('        if (sampler_binding) {')
++        print('            writer.beginMember("GL_SAMPLER");')
++        print('            writer.beginObject();')
++        print('            dumpObjectLabel(writer, context, GL_SAMPLER, sampler_binding, "GL_SAMPLER_LABEL");')
+         for _, _, name in glGetSamplerParameter.iter():
+             self.dump_atom(glGetSamplerParameter, 'sampler_binding', name)
+-        print '           writer.endObject();'
+-        print '           writer.endMember(); // GL_SAMPLER'
+-        print '       }'
+-        print '    }'
++        print('           writer.endObject();')
++        print('           writer.endMember(); // GL_SAMPLER')
++        print('       }')
++        print('    }')
+     def texenv_param_target(self, name):
+         if name == 'GL_TEXTURE_LOD_BIAS':
+@@ -431,34 +431,34 @@ class StateDumper:
+     def dump_texenv_params(self):
+         for target in ['GL_TEXTURE_ENV', 'GL_TEXTURE_FILTER_CONTROL', 'GL_POINT_SPRITE']:
+-            print '    if (!context.ES) {'
+-            print '        writer.beginMember("%s");' % target
+-            print '        writer.beginObject();'
++            print('    if (!context.ES) {')
++            print('        writer.beginMember("%s");' % target)
++            print('        writer.beginObject();')
+             for _, _, name in glGetTexEnv.iter():
+                 if self.texenv_param_target(name) == target:
+                     self.dump_atom(glGetTexEnv, target, name) 
+-            print '        writer.endObject();'
+-            print '    }'
++            print('        writer.endObject();')
++            print('    }')
+     def dump_vertex_attribs(self):
+-        print '    GLint max_vertex_attribs = 0;'
+-        print '    _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);'
+-        print '    for (GLint index = 0; index < max_vertex_attribs; ++index) {'
+-        print '        char name[32];'
+-        print '        snprintf(name, sizeof name, "GL_VERTEX_ATTRIB_ARRAY%i", index);'
+-        print '        writer.beginMember(name);'
+-        print '        writer.beginObject();'
++        print('    GLint max_vertex_attribs = 0;')
++        print('    _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);')
++        print('    for (GLint index = 0; index < max_vertex_attribs; ++index) {')
++        print('        char name[32];')
++        print('        snprintf(name, sizeof name, "GL_VERTEX_ATTRIB_ARRAY%i", index);')
++        print('        writer.beginMember(name);')
++        print('        writer.beginObject();')
+         self.dump_atoms(glGetVertexAttrib, 'index')
+         
+         # Dump vertex attrib buffer label
+-        print '        GLint buffer_binding = 0;'
+-        print '        glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_binding);'
+-        print '        dumpObjectLabel(writer, context, GL_BUFFER, buffer_binding, "GL_VERTEX_ATTRIB_ARRAY_BUFFER_LABEL");'
++        print('        GLint buffer_binding = 0;')
++        print('        glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_binding);')
++        print('        dumpObjectLabel(writer, context, GL_BUFFER, buffer_binding, "GL_VERTEX_ATTRIB_ARRAY_BUFFER_LABEL");')
+-        print '        writer.endObject();'
+-        print '        writer.endMember(); // GL_VERTEX_ATTRIB_ARRAYi'
+-        print '    }'
+-        print
++        print('        writer.endObject();')
++        print('        writer.endMember(); // GL_VERTEX_ATTRIB_ARRAYi')
++        print('    }')
++        print()
+     object_bindings = [
+         ('GL_BUFFER', 'GL_ARRAY_BUFFER_BINDING'),
+@@ -488,11 +488,11 @@ class StateDumper:
+             member_name = object_binding.replace('BINDING', 'LABEL')
+             if member_name == object_binding:
+                 member_name += '_LABEL'
+-            print '    {'
+-            print '        GLint binding = 0;'
+-            print '        glGetIntegerv(%s, &binding);' % object_binding
+-            print '        dumpObjectLabel(writer, context, %s, binding, "%s");' % (object_type, member_name)
+-            print '    }'
++            print('    {')
++            print('        GLint binding = 0;')
++            print('        glGetIntegerv(%s, &binding);' % object_binding)
++            print('        dumpObjectLabel(writer, context, %s, binding, "%s");' % (object_type, member_name))
++            print('    }')
+     program_targets = [
+         'GL_FRAGMENT_PROGRAM_ARB',
+@@ -501,12 +501,12 @@ class StateDumper:
+     def dump_program_params(self):
+         for target in self.program_targets:
+-            print '    if (glIsEnabled(%s)) {' % target
+-            print '        writer.beginMember("%s");' % target
+-            print '        writer.beginObject();'
++            print('    if (glIsEnabled(%s)) {' % target)
++            print('        writer.beginMember("%s");' % target)
++            print('        writer.beginObject();')
+             self.dump_atoms(glGetProgramARB, target)
+-            print '        writer.endObject();'
+-            print '    }'
++            print('        writer.endObject();')
++            print('    }')
+     buffer_targets = [
+         ('GL_ARRAY_BUFFER', 'GL_ARRAY_BUFFER_BINDING', None),
+@@ -529,135 +529,135 @@ class StateDumper:
+     def dump_buffer_parameters(self):
+         # general binding points
+         for target, binding, max_bindings in self.buffer_targets:
+-            print '    // %s' % target
+-            print '    {'
+-            print '        writer.beginMember("%s");' % target
+-            print '        writer.beginObject();'
+-            print '        GLint buffer = 0;'
+-            print '        glGetIntegerv(%s, &buffer);' % binding
+-            print '        if (buffer) {'
++            print('    // %s' % target)
++            print('    {')
++            print('        writer.beginMember("%s");' % target)
++            print('        writer.beginObject();')
++            print('        GLint buffer = 0;')
++            print('        glGetIntegerv(%s, &buffer);' % binding)
++            print('        if (buffer) {')
+             self.dump_atoms(glGetBufferParameter, target)
+-            print '        }'
++            print('        }')
+             if max_bindings is not None:
+                 # indexed binding points
+                 start = target + '_START'
+                 size = target + '_SIZE'
+-                print '        GLint max_bindings = 0;'
+-                print '        glGetIntegerv(%s, &max_bindings);' % max_bindings
+-                print '        if (max_bindings) {'
+-                print '            writer.beginMember("i");'
+-                print '            writer.beginArray();'
+-                print '            for (GLint i = 0; i < max_bindings; ++i) {'
+-                print '                writer.beginObject();'
++                print('        GLint max_bindings = 0;')
++                print('        glGetIntegerv(%s, &max_bindings);' % max_bindings)
++                print('        if (max_bindings) {')
++                print('            writer.beginMember("i");')
++                print('            writer.beginArray();')
++                print('            for (GLint i = 0; i < max_bindings; ++i) {')
++                print('                writer.beginObject();')
+                 for pname in [binding, start, size]:
+                     self.dump_atom(glGet_i, pname, 'i')
+-                print '                writer.endObject();'
+-                print '            }'
+-                print '            writer.endArray();'
+-                print '            writer.endMember();'
+-                print '        }'
++                print('                writer.endObject();')
++                print('            }')
++                print('            writer.endArray();')
++                print('            writer.endMember();')
++                print('        }')
+-            print '        writer.endObject();'
+-            print '        writer.endMember();'
+-            print '    }'
+-            print
++            print('        writer.endObject();')
++            print('        writer.endMember();')
++            print('    }')
++            print()
+     def dump_texture_parameters(self):
+-        print '    {'
+-        print '        GLint active_texture = GL_TEXTURE0;'
+-        print '        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
+-        print '        GLint max_texture_coords = 0;'
+-        print '        if (!context.core) {'
+-        print '            glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
+-        print '        }'
+-        print '        GLint max_combined_texture_image_units = 0;'
+-        print '        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
+-        print '        max_combined_texture_image_units = std::max(max_combined_texture_image_units, 2);'
+-        print '        GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
+-        print '        for (GLint unit = 0; unit < max_units; ++unit) {'
+-        print '            char name[32];'
+-        print '            snprintf(name, sizeof name, "GL_TEXTURE%i", unit);'
+-        print '            writer.beginMember(name);'
+-        print '            glActiveTexture(GL_TEXTURE0 + unit);'
+-        print '            writer.beginObject();'
+-        print
++        print('    {')
++        print('        GLint active_texture = GL_TEXTURE0;')
++        print('        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);')
++        print('        GLint max_texture_coords = 0;')
++        print('        if (!context.core) {')
++        print('            glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);')
++        print('        }')
++        print('        GLint max_combined_texture_image_units = 0;')
++        print('        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);')
++        print('        max_combined_texture_image_units = std::max(max_combined_texture_image_units, 2);')
++        print('        GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);')
++        print('        for (GLint unit = 0; unit < max_units; ++unit) {')
++        print('            char name[32];')
++        print('            snprintf(name, sizeof name, "GL_TEXTURE%i", unit);')
++        print('            writer.beginMember(name);')
++        print('            glActiveTexture(GL_TEXTURE0 + unit);')
++        print('            writer.beginObject();')
++        print()
+         self.dump_atoms(glGet_texture)
+-        print
+-        print '            for (unsigned i = 0; i < numTextureTargets; ++i) {'
+-        print '                GLenum target = textureTargets[i];'
+-        print '                GLboolean enabled = GL_FALSE;'
+-        print '                if (unit < max_texture_coords &&'
+-        print '                    (target == GL_TEXTURE_1D ||'
+-        print '                     target == GL_TEXTURE_2D ||'
+-        print '                     target == GL_TEXTURE_3D ||'
+-        print '                     target == GL_TEXTURE_CUBE_MAP ||'
+-        print '                     target == GL_TEXTURE_RECTANGLE)) {'
+-        print '                    glGetBooleanv(target, &enabled);'
+-        print '                    writer.beginMember(enumToString(target));'
+-        print '                    dumpBoolean(writer, enabled);'
+-        print '                    writer.endMember();'
+-        print '                }'
+-        print '                GLint texture = 0;'
+-        print '                GLenum binding = getTextureBinding(target);'
+-        print '                glGetIntegerv(binding, &texture);'
+-        print '                if (enabled || texture) {'
+-        print '                    dumpTextureTargetParameters(writer, context, target, texture);'
+-        print '                }'
+-        print '            }'
+-        print
++        print()
++        print('            for (unsigned i = 0; i < numTextureTargets; ++i) {')
++        print('                GLenum target = textureTargets[i];')
++        print('                GLboolean enabled = GL_FALSE;')
++        print('                if (unit < max_texture_coords &&')
++        print('                    (target == GL_TEXTURE_1D ||')
++        print('                     target == GL_TEXTURE_2D ||')
++        print('                     target == GL_TEXTURE_3D ||')
++        print('                     target == GL_TEXTURE_CUBE_MAP ||')
++        print('                     target == GL_TEXTURE_RECTANGLE)) {')
++        print('                    glGetBooleanv(target, &enabled);')
++        print('                    writer.beginMember(enumToString(target));')
++        print('                    dumpBoolean(writer, enabled);')
++        print('                    writer.endMember();')
++        print('                }')
++        print('                GLint texture = 0;')
++        print('                GLenum binding = getTextureBinding(target);')
++        print('                glGetIntegerv(binding, &texture);')
++        print('                if (enabled || texture) {')
++        print('                    dumpTextureTargetParameters(writer, context, target, texture);')
++        print('                }')
++        print('            }')
++        print()
+         self.dump_sampler_params()
+-        print
+-        print '            if (unit < max_texture_coords) {'
++        print()
++        print('            if (unit < max_texture_coords) {')
+         self.dump_texenv_params()
+-        print '            }'
+-        print '            writer.endObject();'
+-        print '            writer.endMember(); // GL_TEXTUREi'
+-        print '        }'
+-        print '        glActiveTexture(active_texture);'
+-        print '    }'
+-        print
++        print('            }')
++        print('            writer.endObject();')
++        print('            writer.endMember(); // GL_TEXTUREi')
++        print('        }')
++        print('        glActiveTexture(active_texture);')
++        print('    }')
++        print()
+     def dump_framebuffer_parameters(self):
+-        print '    {'
+-        print '        GLint max_color_attachments = 0;'
+-        print '        glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);'
+-        print '        GLint framebuffer;'
++        print('    {')
++        print('        GLint max_color_attachments = 0;')
++        print('        glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);')
++        print('        GLint framebuffer;')
+         for target, binding in framebuffer_targets:
+-            print '            // %s' % target
+-            print '            framebuffer = 0;'
+-            print '            glGetIntegerv(%s, &framebuffer);' % binding
+-            print '            if (framebuffer) {'
+-            print '                writer.beginMember("%s");' % target
+-            print '                writer.beginObject();'
+-            print '                dumpObjectLabel(writer, context, GL_FRAMEBUFFER, framebuffer, "GL_FRAMEBUFFER_LABEL");'
+-            print '                for (GLint i = 0; i < max_color_attachments; ++i) {'
+-            print '                    GLint color_attachment = GL_COLOR_ATTACHMENT0 + i;'
+-            print '                    dumpFramebufferAttachementParameters(writer, context, %s, color_attachment);' % target
+-            print '                }'
+-            print '                dumpFramebufferAttachementParameters(writer, context, %s, GL_DEPTH_ATTACHMENT);' % target
+-            print '                dumpFramebufferAttachementParameters(writer, context, %s, GL_STENCIL_ATTACHMENT);' % target
+-            print '                writer.endObject();'
+-            print '                writer.endMember(); // %s' % target
+-            print '            }'
+-            print
+-        print '    }'
+-        print
++            print('            // %s' % target)
++            print('            framebuffer = 0;')
++            print('            glGetIntegerv(%s, &framebuffer);' % binding)
++            print('            if (framebuffer) {')
++            print('                writer.beginMember("%s");' % target)
++            print('                writer.beginObject();')
++            print('                dumpObjectLabel(writer, context, GL_FRAMEBUFFER, framebuffer, "GL_FRAMEBUFFER_LABEL");')
++            print('                for (GLint i = 0; i < max_color_attachments; ++i) {')
++            print('                    GLint color_attachment = GL_COLOR_ATTACHMENT0 + i;')
++            print('                    dumpFramebufferAttachementParameters(writer, context, %s, color_attachment);' % target)
++            print('                }')
++            print('                dumpFramebufferAttachementParameters(writer, context, %s, GL_DEPTH_ATTACHMENT);' % target)
++            print('                dumpFramebufferAttachementParameters(writer, context, %s, GL_STENCIL_ATTACHMENT);' % target)
++            print('                writer.endObject();')
++            print('                writer.endMember(); // %s' % target)
++            print('            }')
++            print()
++        print('    }')
++        print()
+     def dump_attachment_parameters(self, target, attachment):
+-        print '            {'
+-        print '                GLint object_type = GL_NONE;'
+-        print '                glGetFramebufferAttachmentParameteriv(%s, %s, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);' % (target, attachment)
+-        print '                if (object_type != GL_NONE) {'
+-        print '                    writer.beginMember(enumToString(%s));' % attachment
+-        print '                    writer.beginObject();'
++        print('            {')
++        print('                GLint object_type = GL_NONE;')
++        print('                glGetFramebufferAttachmentParameteriv(%s, %s, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);' % (target, attachment))
++        print('                if (object_type != GL_NONE) {')
++        print('                    writer.beginMember(enumToString(%s));' % attachment)
++        print('                    writer.beginObject();')
+         self.dump_atoms(glGetFramebufferAttachmentParameter, target, attachment)
+-        print '                    GLint object_name = 0;'
+-        print '                    glGetFramebufferAttachmentParameteriv(%s, %s, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &object_name);' % (target, attachment)
+-        print '                    dumpObjectLabel(writer, context, object_type, object_name, "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_LABEL");'
+-        print '                    writer.endObject();'
+-        print '                    writer.endMember(); // GL_x_ATTACHMENT'
+-        print '                }'
+-        print '            }'
++        print('                    GLint object_name = 0;')
++        print('                    glGetFramebufferAttachmentParameteriv(%s, %s, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &object_name);' % (target, attachment))
++        print('                    dumpObjectLabel(writer, context, object_type, object_name, "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_LABEL");')
++        print('                    writer.endObject();')
++        print('                    writer.endMember(); // GL_x_ATTACHMENT')
++        print('                }')
++        print('            }')
+     def dump_atoms(self, getter, *args):
+         for _, _, name in getter.iter():
+@@ -666,20 +666,20 @@ class StateDumper:
+     def dump_atom(self, getter, *args):
+         name = args[getter.pnameIdx]
+-        print '        // %s' % name
+-        print '        {'
+-        print '            flushErrors();'
++        print('        // %s' % name)
++        print('        {')
++        print('            flushErrors();')
+         type, value = getter(*args)
+-        print '            if (glGetError() != GL_NO_ERROR) {'
++        print('            if (glGetError() != GL_NO_ERROR) {')
+         #print '                std::cerr << "warning: %s(%s) failed\\n";' % (inflection, name)
+-        print '                flushErrors();'
+-        print '            } else {'
+-        print '                writer.beginMember("%s");' % name
++        print('                flushErrors();')
++        print('            } else {')
++        print('                writer.beginMember("%s");' % name)
+         JsonWriter().visit(type, value)
+-        print '                writer.endMember();'
+-        print '            }'
+-        print '        }'
+-        print
++        print('                writer.endMember();')
++        print('            }')
++        print('        }')
++        print()
+ if __name__ == '__main__':
+diff --git a/retrace/retrace.py b/retrace/retrace.py
+index 164944ed..0149817c 100644
+--- a/retrace/retrace.py
++++ b/retrace/retrace.py
+@@ -69,10 +69,10 @@ class ValueAllocator(stdapi.Visitor):
+         pass
+     def visitArray(self, array, lvalue, rvalue):
+-        print '    %s = _allocator.allocArray<%s>(&%s);' % (lvalue, array.type, rvalue)
++        print('    %s = _allocator.allocArray<%s>(&%s);' % (lvalue, array.type, rvalue))
+     def visitPointer(self, pointer, lvalue, rvalue):
+-        print '    %s = _allocator.allocArray<%s>(&%s);' % (lvalue, pointer.type, rvalue)
++        print('    %s = _allocator.allocArray<%s>(&%s);' % (lvalue, pointer.type, rvalue))
+     def visitIntPointer(self, pointer, lvalue, rvalue):
+         pass
+@@ -109,7 +109,7 @@ class ValueAllocator(stdapi.Visitor):
+ class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
+     def visitLiteral(self, literal, lvalue, rvalue):
+-        print '    %s = (%s).to%s();' % (lvalue, rvalue, literal.kind)
++        print('    %s = (%s).to%s();' % (lvalue, rvalue, literal.kind))
+     def visitConst(self, const, lvalue, rvalue):
+         self.visit(const.type, lvalue, rvalue)
+@@ -118,7 +118,7 @@ class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
+         self.visit(alias.type, lvalue, rvalue)
+     
+     def visitEnum(self, enum, lvalue, rvalue):
+-        print '    %s = static_cast<%s>((%s).toSInt());' % (lvalue, enum, rvalue)
++        print('    %s = static_cast<%s>((%s).toSInt());' % (lvalue, enum, rvalue))
+     def visitBitmask(self, bitmask, lvalue, rvalue):
+         self.visit(bitmask.type, lvalue, rvalue)
+@@ -127,50 +127,50 @@ class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
+         tmp = '_a_' + array.tag + '_' + str(self.seq)
+         self.seq += 1
+-        print '    const trace::Array *%s = (%s).toArray();' % (tmp, rvalue)
+-        print '    if (%s) {' % (tmp,)
++        print('    const trace::Array *%s = (%s).toArray();' % (tmp, rvalue))
++        print('    if (%s) {' % (tmp,))
+         length = '%s->values.size()' % (tmp,)
+         if self.insideStruct:
+             if isinstance(array.length, int):
+                 # Member is an array
+-                print r'    static_assert( std::is_array< std::remove_reference< decltype( %s ) >::type >::value , "lvalue must be an array" );' % lvalue
+-                print r'    static_assert( std::extent< std::remove_reference< decltype( %s ) >::type >::value == %s, "array size mismatch" );' % (lvalue, array.length)
+-                print r'    assert( %s );' % (tmp,)
+-                print r'    assert( %s->size() == %s );' % (tmp, array.length)
++                print(r'    static_assert( std::is_array< std::remove_reference< decltype( %s ) >::type >::value , "lvalue must be an array" );' % lvalue)
++                print(r'    static_assert( std::extent< std::remove_reference< decltype( %s ) >::type >::value == %s, "array size mismatch" );' % (lvalue, array.length))
++                print(r'    assert( %s );' % (tmp,))
++                print(r'    assert( %s->size() == %s );' % (tmp, array.length))
+                 length = str(array.length)
+             else:
+                 # Member is a pointer to an array, hence must be allocated
+-                print r'    static_assert( std::is_pointer< std::remove_reference< decltype( %s ) >::type >::value , "lvalue must be a pointer" );' % lvalue
+-                print r'    %s = _allocator.allocArray<%s>(&%s);' % (lvalue, array.type, rvalue)
++                print(r'    static_assert( std::is_pointer< std::remove_reference< decltype( %s ) >::type >::value , "lvalue must be a pointer" );' % lvalue)
++                print(r'    %s = _allocator.allocArray<%s>(&%s);' % (lvalue, array.type, rvalue))
+         index = '_j' + array.tag
+-        print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
++        print('        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length))
+         try:
+             self.visit(array.type, '%s[%s]' % (lvalue, index), '*%s->values[%s]' % (tmp, index))
+         finally:
+-            print '        }'
+-            print '    }'
++            print('        }')
++            print('    }')
+     
+     def visitPointer(self, pointer, lvalue, rvalue):
+         tmp = '_a_' + pointer.tag + '_' + str(self.seq)
+         self.seq += 1
+-        print '    if (%s) {' % (lvalue,)
+-        print '        const trace::Array *%s = (%s).toArray();' % (tmp, rvalue)
++        print('    if (%s) {' % (lvalue,))
++        print('        const trace::Array *%s = (%s).toArray();' % (tmp, rvalue))
+         try:
+             self.visit(pointer.type, '%s[0]' % (lvalue,), '*%s->values[0]' % (tmp,))
+         finally:
+-            print '    }'
++            print('    }')
+     def visitIntPointer(self, pointer, lvalue, rvalue):
+-        print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, pointer, rvalue)
++        print('    %s = static_cast<%s>((%s).toPointer());' % (lvalue, pointer, rvalue))
+     def visitObjPointer(self, pointer, lvalue, rvalue):
+-        print '    %s = retrace::asObjPointer<%s>(call, %s);' % (lvalue, pointer.type, rvalue)
++        print('    %s = retrace::asObjPointer<%s>(call, %s);' % (lvalue, pointer.type, rvalue))
+     def visitLinearPointer(self, pointer, lvalue, rvalue):
+-        print '    %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, pointer, rvalue)
++        print('    %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, pointer, rvalue))
+     def visitReference(self, reference, lvalue, rvalue):
+         self.visit(reference.type, lvalue, rvalue);
+@@ -179,23 +179,23 @@ class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
+         #OpaqueValueDeserializer().visit(handle.type, lvalue, rvalue);
+         self.visit(handle.type, lvalue, rvalue);
+         new_lvalue = lookupHandle(handle, lvalue)
+-        print '    if (retrace::verbosity >= 2) {'
+-        print '        std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
+-        print '    }'
++        print('    if (retrace::verbosity >= 2) {')
++        print('        std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue))
++        print('    }')
+         if (new_lvalue.startswith('_program_map') or new_lvalue.startswith('_shader_map')):
+-            print 'if (glretrace::supportsARBShaderObjects) {'
+-            print '    %s = _handleARB_map[%s];' % (lvalue, lvalue)
+-            print '} else {'
+-            print '    %s = %s;' % (lvalue, new_lvalue)
+-            print '}'
++            print('if (glretrace::supportsARBShaderObjects) {')
++            print('    %s = _handleARB_map[%s];' % (lvalue, lvalue))
++            print('} else {')
++            print('    %s = %s;' % (lvalue, new_lvalue))
++            print('}')
+         else:
+-            print '    %s = %s;' % (lvalue, new_lvalue)
++            print('    %s = %s;' % (lvalue, new_lvalue))
+     
+     def visitBlob(self, blob, lvalue, rvalue):
+-        print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue)
++        print('    %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue))
+     
+     def visitString(self, string, lvalue, rvalue):
+-        print '    %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
++        print('    %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue))
+     seq = 0
+@@ -207,8 +207,8 @@ class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
+         self.insideStruct += 1
+-        print '    const trace::Struct *%s = (%s).toStruct();' % (tmp, rvalue)
+-        print '    assert(%s);' % (tmp)
++        print('    const trace::Struct *%s = (%s).toStruct();' % (tmp, rvalue))
++        print('    assert(%s);' % (tmp))
+         for i in range(len(struct.members)):
+             member = struct.members[i]
+             self.visitMember(member, lvalue, '*%s->members[%s]' % (tmp, i))
+@@ -218,24 +218,24 @@ class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
+     def visitPolymorphic(self, polymorphic, lvalue, rvalue):
+         if polymorphic.defaultType is None:
+             switchExpr = self.expand(polymorphic.switchExpr)
+-            print r'    switch (%s) {' % switchExpr
++            print(r'    switch (%s) {' % switchExpr)
+             for cases, type in polymorphic.iterSwitch():
+                 for case in cases:
+-                    print r'    %s:' % case
++                    print(r'    %s:' % case)
+                 caseLvalue = lvalue
+                 if type.expr is not None:
+                     caseLvalue = 'static_cast<%s>(%s)' % (type, caseLvalue)
+-                print r'        {'
++                print(r'        {')
+                 try:
+                     self.visit(type, caseLvalue, rvalue)
+                 finally:
+-                    print r'        }'
+-                print r'        break;'
++                    print(r'        }')
++                print(r'        break;')
+             if polymorphic.defaultType is None:
+-                print r'    default:'
+-                print r'        retrace::warning(call) << "unexpected polymorphic case" << %s << "\n";' % (switchExpr,)
+-                print r'        break;'
+-            print r'    }'
++                print(r'    default:')
++                print(r'        retrace::warning(call) << "unexpected polymorphic case" << %s << "\n";' % (switchExpr,))
++                print(r'        break;')
++            print(r'    }')
+         else:
+             self.visit(polymorphic.defaultType, lvalue, rvalue)
+     
+@@ -250,7 +250,7 @@ class OpaqueValueDeserializer(ValueDeserializer):
+     in the context of handles.'''
+     def visitOpaque(self, opaque, lvalue, rvalue):
+-        print '    %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, opaque, rvalue)
++        print('    %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, opaque, rvalue))
+ class SwizzledValueRegistrator(stdapi.Visitor, stdapi.ExpanderMixin):
+@@ -270,67 +270,67 @@ class SwizzledValueRegistrator(stdapi.Visitor, stdapi.ExpanderMixin):
+         pass
+     def visitArray(self, array, lvalue, rvalue):
+-        print '    const trace::Array *_a%s = (%s).toArray();' % (array.tag, rvalue)
+-        print '    if (_a%s) {' % (array.tag)
++        print('    const trace::Array *_a%s = (%s).toArray();' % (array.tag, rvalue))
++        print('    if (_a%s) {' % (array.tag))
+         length = '_a%s->values.size()' % array.tag
+         index = '_j' + array.tag
+-        print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
++        print('        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length))
+         try:
+             self.visit(array.type, '%s[%s]' % (lvalue, index), '*_a%s->values[%s]' % (array.tag, index))
+         finally:
+-            print '        }'
+-            print '    }'
++            print('        }')
++            print('    }')
+     
+     def visitPointer(self, pointer, lvalue, rvalue):
+-        print '    const trace::Array *_a%s = (%s).toArray();' % (pointer.tag, rvalue)
+-        print '    if (_a%s) {' % (pointer.tag)
++        print('    const trace::Array *_a%s = (%s).toArray();' % (pointer.tag, rvalue))
++        print('    if (_a%s) {' % (pointer.tag))
+         try:
+             self.visit(pointer.type, '%s[0]' % (lvalue,), '*_a%s->values[0]' % (pointer.tag,))
+         finally:
+-            print '    }'
++            print('    }')
+     
+     def visitIntPointer(self, pointer, lvalue, rvalue):
+         pass
+     
+     def visitObjPointer(self, pointer, lvalue, rvalue):
+-        print r'    retrace::addObj(call, %s, %s);' % (rvalue, lvalue)
++        print(r'    retrace::addObj(call, %s, %s);' % (rvalue, lvalue))
+     
+     def visitLinearPointer(self, pointer, lvalue, rvalue):
+         assert pointer.size is not None
+         if pointer.size is not None:
+-            print r'    retrace::addRegion(call, (%s).toUIntPtr(), %s, %s);' % (rvalue, lvalue, pointer.size)
++            print(r'    retrace::addRegion(call, (%s).toUIntPtr(), %s, %s);' % (rvalue, lvalue, pointer.size))
+     def visitReference(self, reference, lvalue, rvalue):
+         pass
+     
+     def visitHandle(self, handle, lvalue, rvalue):
+-        print '    %s _origResult;' % handle.type
++        print('    %s _origResult;' % handle.type)
+         OpaqueValueDeserializer().visit(handle.type, '_origResult', rvalue);
+         if handle.range is None:
+             rvalue = "_origResult"
+             entry = lookupHandle(handle, rvalue, True)
+             if (entry.startswith('_program_map') or entry.startswith('_shader_map')):
+-                print 'if (glretrace::supportsARBShaderObjects) {'
+-                print '    _handleARB_map[%s] = %s;' % (rvalue, lvalue)
+-                print '} else {'
+-                print '    %s = %s;' % (entry, lvalue)
+-                print '}'
++                print('if (glretrace::supportsARBShaderObjects) {')
++                print('    _handleARB_map[%s] = %s;' % (rvalue, lvalue))
++                print('} else {')
++                print('    %s = %s;' % (entry, lvalue))
++                print('}')
+             else:
+-                print "    %s = %s;" % (entry, lvalue)
+-            print '    if (retrace::verbosity >= 2) {'
+-            print '        std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
+-            print '    }'
++                print("    %s = %s;" % (entry, lvalue))
++            print('    if (retrace::verbosity >= 2) {')
++            print('        std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals()))
++            print('    }')
+         else:
+             i = '_h' + handle.tag
+             lvalue = "%s + %s" % (lvalue, i)
+             rvalue = "_origResult + %s" % (i,)
+             entry = lookupHandle(handle, rvalue) 
+-            print '    for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
+-            print '        {entry} = {lvalue};'.format(**locals())
+-            print '        if (retrace::verbosity >= 2) {'
+-            print '            std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals())
+-            print '        }'
+-            print '    }'
++            print('    for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals()))
++            print('        {entry} = {lvalue};'.format(**locals()))
++            print('        if (retrace::verbosity >= 2) {')
++            print('            std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals()))
++            print('        }')
++            print('    }')
+     
+     def visitBlob(self, blob, lvalue, rvalue):
+         pass
+@@ -344,9 +344,9 @@ class SwizzledValueRegistrator(stdapi.Visitor, stdapi.ExpanderMixin):
+         tmp = '_s_' + struct.tag + '_' + str(self.seq)
+         self.seq += 1
+-        print '    const trace::Struct *%s = (%s).toStruct();' % (tmp, rvalue)
+-        print '    assert(%s);' % (tmp,)
+-        print '    (void)%s;' % (tmp,)
++        print('    const trace::Struct *%s = (%s).toStruct();' % (tmp, rvalue))
++        print('    assert(%s);' % (tmp,))
++        print('    (void)%s;' % (tmp,))
+         for i in range(len(struct.members)):
+             member = struct.members[i]
+             self.visitMember(member, lvalue, '*%s->members[%s]' % (tmp, i))
+@@ -362,16 +362,16 @@ class SwizzledValueRegistrator(stdapi.Visitor, stdapi.ExpanderMixin):
+ class Retracer:
+     def retraceFunction(self, function):
+-        print 'static void retrace_%s(trace::Call &call) {' % function.name
++        print('static void retrace_%s(trace::Call &call) {' % function.name)
+         self.retraceFunctionBody(function)
+-        print '}'
+-        print
++        print('}')
++        print()
+     def retraceInterfaceMethod(self, interface, method):
+-        print 'static void retrace_%s__%s(trace::Call &call) {' % (interface.name, method.name)
++        print('static void retrace_%s__%s(trace::Call &call) {' % (interface.name, method.name))
+         self.retraceInterfaceMethodBody(interface, method)
+-        print '}'
+-        print
++        print('}')
++        print()
+     def retraceFunctionBody(self, function):
+         assert function.sideeffects
+@@ -409,38 +409,38 @@ class Retracer:
+         assert function.type is not stdapi.Void
+         if str(function.type) == 'HRESULT':
+-            print r'    if (call.ret && FAILED(call.ret->toSInt())) {'
+-            print r'        return;'
+-            print r'    }'
++            print(r'    if (call.ret && FAILED(call.ret->toSInt())) {')
++            print(r'        return;')
++            print(r'    }')
+     def deserializeThisPointer(self, interface):
+-        print r'    %s *_this;' % (interface.name,)
+-        print r'    _this = retrace::asObjPointer<%s>(call, call.arg(0));' % (interface.name,)
+-        print r'    if (!_this) {'
+-        print r'        return;'
+-        print r'    }'
++        print(r'    %s *_this;' % (interface.name,))
++        print(r'    _this = retrace::asObjPointer<%s>(call, call.arg(0));' % (interface.name,))
++        print(r'    if (!_this) {')
++        print(r'        return;')
++        print(r'    }')
+     def deserializeArgs(self, function):
+-        print '    retrace::ScopedAllocator _allocator;'
+-        print '    (void)_allocator;'
++        print('    retrace::ScopedAllocator _allocator;')
++        print('    (void)_allocator;')
+         success = True
+         for arg in function.args:
+             arg_type = arg.type.mutable()
+-            print '    %s %s;' % (arg_type, arg.name)
++            print('    %s %s;' % (arg_type, arg.name))
+             rvalue = 'call.arg(%u)' % (arg.index,)
+             lvalue = arg.name
+             try:
+                 self.extractArg(function, arg, arg_type, lvalue, rvalue)
+             except UnsupportedType:
+                 success =  False
+-                print '    memset(&%s, 0, sizeof %s); // FIXME' % (arg.name, arg.name)
+-            print
++                print('    memset(&%s, 0, sizeof %s); // FIXME' % (arg.name, arg.name))
++            print()
+         if not success:
+-            print '    if (1) {'
++            print('    if (1) {')
+             self.failFunction(function)
+             sys.stderr.write('warning: unsupported %s call\n' % function.name)
+-            print '    }'
++            print('    }')
+     def swizzleValues(self, function):
+         for arg in function.args:
+@@ -451,7 +451,7 @@ class Retracer:
+                 try:
+                     self.regiterSwizzledValue(arg_type, lvalue, rvalue)
+                 except UnsupportedType:
+-                    print '    // XXX: %s' % arg.name
++                    print('    // XXX: %s' % arg.name)
+         if function.type is not stdapi.Void:
+             rvalue = '*call.ret'
+             lvalue = '_result'
+@@ -459,15 +459,15 @@ class Retracer:
+                 self.regiterSwizzledValue(function.type, lvalue, rvalue)
+             except UnsupportedType:
+                 raise
+-                print '    // XXX: result'
++                print('    // XXX: result')
+     def failFunction(self, function):
+-        print '    if (retrace::verbosity >= 0) {'
+-        print '        retrace::unsupported(call);'
+-        print '    }'
++        print('    if (retrace::verbosity >= 0) {')
++        print('        retrace::unsupported(call);')
++        print('    }')
+         # MGS-469: GPU hangs when retracing OGLESParticles on mx6sx
+         # Workaround: do not `return`
+-        #print '    return;'
++        #print('    return;')
+     def extractArg(self, function, arg, arg_type, lvalue, rvalue):
+         ValueAllocator().visit(arg_type, lvalue, rvalue)
+@@ -487,22 +487,22 @@ class Retracer:
+     def declareRet(self, function):
+         if function.type is not stdapi.Void:
+-            print '    %s _result;' % (function.type)
++            print('    %s _result;' % (function.type))
+     def invokeFunction(self, function):
+         arg_names = ", ".join(function.argNames())
+         if function.type is not stdapi.Void:
+-            print '    _result = %s(%s);' % (function.name, arg_names)
++            print('    _result = %s(%s);' % (function.name, arg_names))
+             self.checkResult(None, function)
+         else:
+-            print '    %s(%s);' % (function.name, arg_names)
++            print('    %s(%s);' % (function.name, arg_names))
+     def invokeInterfaceMethod(self, interface, method):
+         arg_names = ", ".join(method.argNames())
+         if method.type is not stdapi.Void:
+-            print '    _result = _this->%s(%s);' % (method.name, arg_names)
++            print('    _result = _this->%s(%s);' % (method.name, arg_names))
+         else:
+-            print '    _this->%s(%s);' % (method.name, arg_names)
++            print('    _this->%s(%s);' % (method.name, arg_names))
+         # Adjust reference count when QueryInterface fails.  This is
+         # particularly useful when replaying traces on older Direct3D runtimes
+@@ -511,12 +511,12 @@ class Retracer:
+         #
+         # TODO: Generalize to other methods that return interfaces
+         if method.name == 'QueryInterface':
+-            print r'    if (FAILED(_result)) {'
+-            print r'        IUnknown *pObj = retrace::asObjPointer<IUnknown>(call, *call.arg(2).toArray()->values[0]);'
+-            print r'        if (pObj) {'
+-            print r'            pObj->AddRef();'
+-            print r'        }'
+-            print r'    }'
++            print(r'    if (FAILED(_result)) {')
++            print(r'        IUnknown *pObj = retrace::asObjPointer<IUnknown>(call, *call.arg(2).toArray()->values[0]);')
++            print(r'        if (pObj) {')
++            print(r'            pObj->AddRef();')
++            print(r'        }')
++            print(r'    }')
+         if method.type is not stdapi.Void:
+             self.checkResult(interface, method)
+@@ -524,28 +524,28 @@ class Retracer:
+         # Debug COM reference counting.  Disabled by default as reported
+         # reference counts depend on internal implementation details.
+         if method.name in ('AddRef', 'Release'):
+-            print r'    if (0) retrace::checkMismatch(call, "cRef", call.ret, _result);'
++            print(r'    if (0) retrace::checkMismatch(call, "cRef", call.ret, _result);')
+         # On release our reference when we reach Release() == 0 call in the
+         # trace.
+         if method.name == 'Release':
+-            print r'    ULONG _orig_result = call.ret->toUInt();'
+-            print r'    if (_orig_result == 0 || _result == 0) {'
+-            print r'        if (_orig_result != 0) {'
+-            print r'            retrace::warning(call) << "unexpected object destruction\n";'
+-            print r'        }'
+-            print r'        retrace::delObj(call.arg(0));'
+-            print r'    }'
++            print(r'    ULONG _orig_result = call.ret->toUInt();')
++            print(r'    if (_orig_result == 0 || _result == 0) {')
++            print(r'        if (_orig_result != 0) {')
++            print(r'            retrace::warning(call) << "unexpected object destruction\n";')
++            print(r'        }')
++            print(r'        retrace::delObj(call.arg(0));')
++            print(r'    }')
+     def checkResult(self, interface, methodOrFunction):
+         assert methodOrFunction.type is not stdapi.Void
+         if str(methodOrFunction.type) == 'HRESULT':
+-            print r'    if (FAILED(_result)) {'
+-            print r'        retrace::failed(call, _result);'
+-            print r'        return;'
+-            print r'    }'
++            print(r'    if (FAILED(_result)) {')
++            print(r'        retrace::failed(call, _result);')
++            print(r'        return;')
++            print(r'    }')
+         else:
+-            print r'    (void)_result;'
++            print(r'    (void)_result;')
+     def checkPitchMismatch(self, method):
+         # Warn for mismatches in 2D/3D mappings.
+@@ -554,19 +554,19 @@ class Retracer:
+             if outArg.output \
+                and isinstance(outArg.type, stdapi.Pointer) \
+                and isinstance(outArg.type.type, stdapi.Struct):
+-                print r'        const trace::Array *_%s = call.arg(%u).toArray();' % (outArg.name, outArg.index)
+-                print r'        if (%s) {' % outArg.name
+-                print r'            const trace::Struct *_struct = _%s->values[0]->toStruct();' % (outArg.name)
+-                print r'            if (_struct) {'
++                print(r'        const trace::Array *_%s = call.arg(%u).toArray();' % (outArg.name, outArg.index))
++                print(r'        if (%s) {' % outArg.name)
++                print(r'            const trace::Struct *_struct = _%s->values[0]->toStruct();' % (outArg.name))
++                print(r'            if (_struct) {')
+                 struct = outArg.type.type
+                 for memberIndex in range(len(struct.members)):
+                     memberType, memberName = struct.members[memberIndex]
+                     if memberName.endswith('Pitch'):
+-                        print r'                if (%s->%s) {' % (outArg.name, memberName)
+-                        print r'                    retrace::checkMismatch(call, "%s", _struct->members[%u], %s->%s);' % (memberName, memberIndex, outArg.name, memberName)
+-                        print r'                }'
+-                print r'            }'
+-                print r'        }'
++                        print(r'                if (%s->%s) {' % (outArg.name, memberName))
++                        print(r'                    retrace::checkMismatch(call, "%s", _struct->members[%u], %s->%s);' % (memberName, memberIndex, outArg.name, memberName))
++                        print(r'                }')
++                print(r'            }')
++                print(r'        }')
+     def filterFunction(self, function):
+         return True
+@@ -575,11 +575,11 @@ class Retracer:
+     def retraceApi(self, api):
+-        print '#include "os_time.hpp"'
+-        print '#include "trace_parser.hpp"'
+-        print '#include "retrace.hpp"'
+-        print '#include "retrace_swizzle.hpp"'
+-        print
++        print('#include "os_time.hpp"')
++        print('#include "trace_parser.hpp"')
++        print('#include "retrace.hpp"')
++        print('#include "retrace_swizzle.hpp"')
++        print()
+         types = api.getAllTypes()
+         handles = [type for type in types if isinstance(type, stdapi.Handle)]
+@@ -587,14 +587,14 @@ class Retracer:
+         for handle in handles:
+             if handle.name not in handle_names:
+                 if handle.key is None:
+-                    print 'static retrace::map<%s> _%s_map;' % (handle.type, handle.name)
++                    print('static retrace::map<%s> _%s_map;' % (handle.type, handle.name))
+                 else:
+                     key_name, key_type = handle.key
+-                    print 'static std::map<%s, retrace::map<%s> > _%s_map;' % (key_type, handle.type, handle.name)
++                    print('static std::map<%s, retrace::map<%s> > _%s_map;' % (key_type, handle.type, handle.name))
+                 handle_names.add(handle.name)
+-        print
++        print()
+-        functions = filter(self.filterFunction, api.getAllFunctions())
++        functions = list(filter(self.filterFunction, api.getAllFunctions()))
+         for function in functions:
+             if function.sideeffects and not function.internal:
+                 self.retraceFunction(function)
+@@ -604,20 +604,20 @@ class Retracer:
+                 if method.sideeffects and not method.internal:
+                     self.retraceInterfaceMethod(interface, method)
+-        print 'const retrace::Entry %s[] = {' % self.table_name
++        print('const retrace::Entry %s[] = {' % self.table_name)
+         for function in functions:
+             if not function.internal:
+                 if function.sideeffects:
+-                    print '    {"%s", &retrace_%s},' % (function.name, function.name)
++                    print('    {"%s", &retrace_%s},' % (function.name, function.name))
+                 else:
+-                    print '    {"%s", &retrace::ignore},' % (function.name,)
++                    print('    {"%s", &retrace::ignore},' % (function.name,))
+         for interface in interfaces:
+             for base, method in interface.iterBaseMethods():
+                 if method.sideeffects:
+-                    print '    {"%s::%s", &retrace_%s__%s},' % (interface.name, method.name, base.name, method.name)
++                    print('    {"%s::%s", &retrace_%s__%s},' % (interface.name, method.name, base.name, method.name))
+                 else:
+-                    print '    {"%s::%s", &retrace::ignore},' % (interface.name, method.name)
+-        print '    {NULL, NULL}'
+-        print '};'
+-        print
++                    print('    {"%s::%s", &retrace::ignore},' % (interface.name, method.name))
++        print('    {NULL, NULL}')
++        print('};')
++        print()
+diff --git a/scripts/convert.py b/scripts/convert.py
+index 5f338d80..83df70ce 100755
+--- a/scripts/convert.py
++++ b/scripts/convert.py
+@@ -100,9 +100,9 @@ def detectApiFromCsv(inCsv):
+     import csv
+     csvReader = csv.reader(open(inCsv, 'rt'), )
+     for row in csvReader:
+-        print row
++        print(row)
+         event = row[2]
+-        print event
++        print(event)
+         if event.startswith("Direct3DCreate9"):
+             return "d3d9"
+         if event.startswith("CreateDXGIFactory"):
+diff --git a/scripts/jsondiff.py b/scripts/jsondiff.py
+index 3b1f9110..25c4840e 100755
+--- a/scripts/jsondiff.py
++++ b/scripts/jsondiff.py
+@@ -36,7 +36,7 @@ import sys
+ def strip_object_hook(obj):
+     if '__class__' in obj:
+         return None
+-    for name in obj.keys():
++    for name in list(obj.keys()):
+         if name.startswith('__') and name.endswith('__'):
+             del obj[name]
+     return obj
+@@ -80,7 +80,7 @@ class Dumper(Visitor):
+     def visitObject(self, node):
+         self.enter_object()
+-        members = node.keys()
++        members = list(node.keys())
+         members.sort()
+         for i in range(len(members)):
+             name = members[i]
+@@ -148,8 +148,8 @@ class Comparer(Visitor):
+             return False
+         if len(a) != len(b) and not self.ignore_added:
+             return False
+-        ak = a.keys()
+-        bk = b.keys()
++        ak = list(a.keys())
++        bk = list(b.keys())
+         ak.sort()
+         bk.sort()
+         if ak != bk and not self.ignore_added:
+@@ -175,8 +175,8 @@ class Comparer(Visitor):
+         return True
+     def visitValue(self, a, b):
+-        if isinstance(a, float) and isinstance(b, (int, long, float)) or \
+-           isinstance(b, float) and isinstance(a, (int, long, float)):
++        if isinstance(a, float) and isinstance(b, (int, float)) or \
++           isinstance(b, float) and isinstance(a, (int, float)):
+             if a is b:
+                 # NaNs take this path
+                 return True
+@@ -208,7 +208,7 @@ class Differ(Visitor):
+             self.dumper.enter_object()
+             names = set(a.keys())
+             if not self.comparer.ignore_added:
+-                names.update(b.keys())
++                names.update(list(b.keys()))
+             names = list(names)
+             names.sort()
+@@ -284,7 +284,7 @@ class Differ(Visitor):
+         self.dumper.visit(b)
+     def isMultilineString(self, value):
+-        return isinstance(value, basestring) and '\n' in value
++        return isinstance(value, str) and '\n' in value
+ #
+diff --git a/scripts/jsonextractimages.py b/scripts/jsonextractimages.py
+index ea1c927d..917ee7e4 100755
+--- a/scripts/jsonextractimages.py
++++ b/scripts/jsonextractimages.py
+@@ -38,7 +38,7 @@ pngSignature = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"
+ def dumpSurfaces(state, memberName):
+-    for name, imageObj in state[memberName].iteritems():
++    for name, imageObj in state[memberName].items():
+         data = imageObj['__data__']
+         data = base64.b64decode(data)
+diff --git a/scripts/leaks.py b/scripts/leaks.py
+new file mode 100755
+index 00000000..325af1e2
+--- /dev/null
++++ b/scripts/leaks.py
+@@ -0,0 +1,163 @@
++#!/usr/bin/env python
++##########################################################################
++#
++# Copyright 2014-2016 VMware, Inc.
++# All Rights Reserved.
++#
++# Permission is hereby granted, free of charge, to any person obtaining a copy
++# of this software and associated documentation files (the "Software"), to deal
++# in the Software without restriction, including without limitation the rights
++# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++# copies of the Software, and to permit persons to whom the Software is
++# furnished to do so, subject to the following conditions:
++#
++# The above copyright notice and this permission notice shall be included in
++# all copies or substantial portions of the Software.
++#
++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
++# THE SOFTWARE.
++#
++##########################################################################/
++
++
++import subprocess
++import sys
++import os.path
++import optparse
++import re
++
++import unpickle
++
++
++class LeakDetector(unpickle.Unpickler):
++
++    def __init__(self, apitrace, trace):
++
++        cmd = [apitrace, 'pickle', '--symbolic', trace]
++        p = subprocess.Popen(args = cmd, stdout = subprocess.PIPE)
++
++        unpickle.Unpickler.__init__(self, p.stdout)
++
++        self.numContexts = 0
++
++        # a map of maps
++        self.objectDicts = {}
++
++    def parse(self):
++        unpickle.Unpickler.parse(self)
++
++        # Reached the end of the trace -- dump any live objects
++        self.dumpLeaks("<EOF>")
++
++    genDelRegExp = re.compile('^gl(Gen|Delete)(Buffers|Textures|FrameBuffers|RenderBuffers)[A-Z]*$')
++
++    def handleCall(self, call):
++        # Ignore calls without side effects
++        if call.flags & unpickle.CALL_FLAG_NO_SIDE_EFFECTS:
++            return
++
++        # Dump call for debugging:
++        if 0:
++            sys.stderr.write('%s\n' % call)
++
++        mo = self.genDelRegExp.match(call.functionName)
++        if mo:
++            verb = mo.group(1)
++            subject = mo.group(2)
++
++            subject = subject.lower().rstrip('s')
++            objectDict = self.objectDicts.setdefault(subject, {})
++
++            if verb == 'Gen':
++                self.handleGenerate(call, objectDict)
++            elif verb == 'Delete':
++                self.handleDelete(call, objectDict)
++            else:
++                assert 0
++
++        # TODO: Track labels via glObjectLabel* calls
++
++        if call.functionName in [
++            'CGLCreateContext',
++            'eglCreateContext',
++            'glXCreateContext',
++            'glXCreateNewContext',
++            'glXCreateContextAttribsARB',
++            'glXCreateContextWithConfigSGIX',
++            'wglCreateContext',
++            'wglCreateContextAttribsARB',
++        ]:
++            # FIXME: Ignore failing context creation calls
++            self.numContexts += 1
++
++        if call.functionName in [
++            'CGLDestroyContext',
++            'glXDestroyContext',
++            'eglDestroyContext',
++            'wglDeleteContext',
++        ]:
++            assert self.numContexts > 0
++            self.numContexts -= 1
++            if self.numContexts == 0:
++                self.dumpLeaks(call.no)
++
++    def handleGenerate(self, call, objectDict):
++        n, names = call.argValues()
++        for i in range(n):
++            name = names[i]
++            objectDict[name] = call.no
++            # TODO: Keep track of call stack backtrace too
++
++    def handleDelete(self, call, objectDict):
++        n, names = call.argValues()
++        for i in range(n):
++            name = names[i]
++            try:
++                del objectDict[name]
++            except KeyError:
++                # Ignore if texture name was never generated
++                pass
++
++    def dumpLeaks(self, currentCallNo):
++        for kind, objectDict in self.objectDicts.items():
++            self.dumpNamespaceLeaks(currentCallNo, objectDict, kind)
++
++    def dumpNamespaceLeaks(self, currentCallNo, objectDict, kind):
++        for name, creationCallNo in (sorted(iter(objectDict.items()),key=lambda t: t[1])):
++            sys.stderr.write('%u: error: %s %u was not destroyed until %s\n' % (creationCallNo, kind, name, currentCallNo))
++        objectDict.clear()
++
++
++def main():
++    '''Main program.
++    '''
++
++    # Parse command line options
++    optparser = optparse.OptionParser(
++        usage='\n\t%prog [options] TRACE',
++        version='%%prog')
++    optparser.add_option(
++        '-a', '--apitrace', metavar='PROGRAM',
++        type='string', dest='apitrace', default='apitrace',
++        help='apitrace command [default: %default]')
++
++    options, args = optparser.parse_args(sys.argv[1:])
++    if len(args) != 1:
++        optparser.error("incorrect number of arguments")
++
++    inTrace = args[0]
++    if not os.path.isfile(inTrace):
++        sys.stderr.write("error: `%s` does not exist\n" % inTrace)
++        sys.exit(1)
++
++    detector = LeakDetector(options.apitrace, inTrace)
++    detector.parse()
++
++
++if __name__ == '__main__':
++    main()
+diff --git a/scripts/profileshader.py b/scripts/profileshader.py
+index 3c490a0e..5c2a58fb 100755
+--- a/scripts/profileshader.py
++++ b/scripts/profileshader.py
+@@ -58,13 +58,13 @@ def process(stream, groupField):
+             continue
+         if fields[callCol] == 'call':
+-            callId = long(fields[callIdCol])
+-            duration = long(fields[gpuDuraCol])
++            callId = int(fields[callIdCol])
++            duration = int(fields[gpuDuraCol])
+             group = fields[groupCol]
+             maxGroupLen = max(maxGroupLen, len(group))
+-            if times.has_key(group):
++            if group in times:
+                 times[group]['draws'] += 1
+                 times[group]['duration'] += duration
+@@ -74,7 +74,7 @@ def process(stream, groupField):
+             else:
+                 times[group] = {'draws': 1, 'duration': duration, 'longest': callId, 'longestDuration': duration}
+-    times = sorted(times.items(), key=lambda x: x[1]['duration'], reverse=True)
++    times = sorted(list(times.items()), key=lambda x: x[1]['duration'], reverse=True)
+     if groupField == 'program':
+         groupTitle = 'Shader[id]'
+@@ -84,9 +84,9 @@ def process(stream, groupField):
+     groupTitle = groupField.center(maxGroupLen)
+     groupLine = '-' * maxGroupLen
+-    print '+-%s-+--------------+--------------------+--------------+-------------+' % groupLine
+-    print '| %s |   Draws [#]  |   Duration [ns]  v | Per Call[ns] | Longest[id] |' % groupTitle
+-    print '+-%s-+--------------+--------------------+--------------+-------------+' % groupLine
++    print('+-%s-+--------------+--------------------+--------------+-------------+' % groupLine)
++    print('| %s |   Draws [#]  |   Duration [ns]  v | Per Call[ns] | Longest[id] |' % groupTitle)
++    print('+-%s-+--------------+--------------------+--------------+-------------+' % groupLine)
+     for group in times:
+         id = str(group[0]).rjust(maxGroupLen)
+@@ -94,9 +94,9 @@ def process(stream, groupField):
+         dura = str(group[1]['duration']).rjust(18)
+         perCall = str(group[1]['duration'] / group[1]['draws']).rjust(12)
+         longest = str(group[1]['longest']).rjust(11)
+-        print "| %s | %s | %s | %s | %s |" % (id, draw, dura, perCall, longest)
++        print("| %s | %s | %s | %s | %s |" % (id, draw, dura, perCall, longest))
+-    print '+-%s-+--------------+--------------------+--------------+-------------+' % groupLine
++    print('+-%s-+--------------+--------------------+--------------+-------------+' % groupLine)
+ def main():
+diff --git a/scripts/retracediff.py b/scripts/retracediff.py
+index bb5aa7f5..8105f536 100755
+--- a/scripts/retracediff.py
++++ b/scripts/retracediff.py
+@@ -83,12 +83,12 @@ class Retracer:
+             self.retraceExe,
+         ] + args + self.args
+         if self.env:
+-            for name, value in self.env.iteritems():
++            for name, value in self.env.items():
+                 sys.stderr.write('%s=%s ' % (name, value))
+         sys.stderr.write(' '.join(cmd) + '\n')
+         try:
+             return subprocess.Popen(cmd, env=self.env, stdout=stdout, stderr=NULL)
+-        except OSError, ex:
++        except OSError as ex:
+             sys.stderr.write('error: failed to execute %s: %s\n' % (cmd[0], ex.strerror))
+             sys.exit(1)
+@@ -160,7 +160,7 @@ def read_pnm(stream):
+     while line.startswith('#'):
+         comment += line[1:]
+         line = stream.readline()
+-    width, height = map(int, line.strip().split())
++    width, height = list(map(int, line.strip().split()))
+     maximum = int(stream.readline().strip())
+     if bytesPerChannel == 1:
+         assert maximum == 255
+diff --git a/scripts/snapdiff.py b/scripts/snapdiff.py
+index 59ec870e..b0d5f757 100755
+--- a/scripts/snapdiff.py
++++ b/scripts/snapdiff.py
+@@ -40,6 +40,7 @@ from PIL import Image
+ from PIL import ImageChops
+ from PIL import ImageEnhance
+ from PIL import ImageFilter
++from functools import reduce
+ thumbSize = 320
+@@ -50,12 +51,12 @@ class Comparer:
+     '''Image comparer.'''
+     def __init__(self, ref_image, src_image, alpha = False):
+-        if isinstance(ref_image, basestring):
++        if isinstance(ref_image, str):
+             self.ref_im = Image.open(ref_image)
+         else:
+             self.ref_im = ref_image
+-        if isinstance(src_image, basestring):
++        if isinstance(src_image, str):
+             self.src_im = Image.open(src_image)
+         else:
+             self.src_im = src_image
+@@ -106,7 +107,7 @@ class Comparer:
+         # Compute absolute error
+         if self.size_mismatch():
+-            return sys.maxint
++            return sys.maxsize
+         # TODO: this is approximate due to the grayscale conversion
+         h = self.diff.convert('L').histogram()
+diff --git a/scripts/tracediff.py b/scripts/tracediff.py
+index f111322a..0cd9c8c6 100755
+--- a/scripts/tracediff.py
++++ b/scripts/tracediff.py
+@@ -237,7 +237,7 @@ class BlobReplacer(Rebuilder):
+         return Blob(len(obj), hash(str(obj)))
+     def visitCall(self, call):
+-        call.args = map(self.visit, call.args)
++        call.args = list(map(self.visit, call.args))
+         call.ret = self.visit(call.ret)
+@@ -312,7 +312,7 @@ class PythonDiffer(Differ):
+             elif tag == 'equal':
+                 self.equal(alo, ahi, blo, bhi)
+             else:
+-                raise ValueError, 'unknown tag %s' % (tag,)
++                raise ValueError('unknown tag %s' % (tag,))
+     def isjunk(self, call):
+         return call.functionName == 'glGetError' and call.ret in ('GL_NO_ERROR', 0)
+@@ -338,12 +338,12 @@ class PythonDiffer(Differ):
+             elif tag == 'equal':
+                 self.replace_similar(_alo, _ahi, _blo, _bhi)
+             else:
+-                raise ValueError, 'unknown tag %s' % (tag,)
++                raise ValueError('unknown tag %s' % (tag,))
+     def replace_similar(self, alo, ahi, blo, bhi):
+         assert alo < ahi and blo < bhi
+         assert ahi - alo == bhi - blo
+-        for i in xrange(0, bhi - blo):
++        for i in range(0, bhi - blo):
+             self.highlighter.write('| ')
+             a_call = self.a[alo + i]
+             b_call = self.b[blo + i]
+@@ -355,7 +355,7 @@ class PythonDiffer(Differ):
+             self.highlighter.write('(')
+             sep = ''
+             numArgs = max(len(a_call.args), len(b_call.args))
+-            for j in xrange(numArgs):
++            for j in range(numArgs):
+                 self.highlighter.write(sep)
+                 try:
+                     a_argName, a_argVal = a_call.args[j]
+@@ -402,7 +402,7 @@ class PythonDiffer(Differ):
+     def delete(self, alo, ahi, blo, bhi):
+         assert alo < ahi
+         assert blo == bhi
+-        for i in xrange(alo, ahi):
++        for i in range(alo, ahi):
+             call = self.a[i]
+             self.highlighter.write('- ')
+             self.dumpCallNos(call.no, None)
+@@ -413,7 +413,7 @@ class PythonDiffer(Differ):
+     def insert(self, alo, ahi, blo, bhi):
+         assert alo == ahi
+         assert blo < bhi
+-        for i in xrange(blo, bhi):
++        for i in range(blo, bhi):
+             call = self.b[i]
+             self.highlighter.write('+ ')
+             self.dumpCallNos(None, call.no)
+@@ -425,7 +425,7 @@ class PythonDiffer(Differ):
+             return
+         assert alo < ahi and blo < bhi
+         assert ahi - alo == bhi - blo
+-        for i in xrange(0, bhi - blo):
++        for i in range(0, bhi - blo):
+             self.highlighter.write('  ')
+             a_call = self.a[alo + i]
+             b_call = self.b[blo + i]
+diff --git a/scripts/unpickle.py b/scripts/unpickle.py
+index 334c1a01..86891d29 100755
+--- a/scripts/unpickle.py
++++ b/scripts/unpickle.py
+@@ -38,7 +38,7 @@ import optparse
+ import sys
+ import time
+ import re
+-import cPickle as pickle
++import pickle as pickle
+ # Same as trace_model.hpp's call flags
+@@ -58,7 +58,7 @@ CALL_FLAG_MARKER_POP        = (1 << 10)
+ class Pointer(long):
+     def __str__(self):
+-        if self == 0L:
++        if self == 0:
+             return 'NULL'
+         else:
+             return hex(self).rstrip('L')
+@@ -73,7 +73,7 @@ class Visitor:
+         self.dispatch[type(None)] = self.visitNone
+         self.dispatch[bool] = self.visitBool
+         self.dispatch[int] = self.visitInt
+-        self.dispatch[long] = self.visitInt
++        self.dispatch[int] = self.visitInt
+         self.dispatch[float] = self.visitFloat
+         self.dispatch[str] = self.visitStr
+         self.dispatch[tuple] = self.visitTuple
+@@ -140,18 +140,18 @@ class Dumper(Visitor):
+             return repr(obj)
+     def visitTuple(self, obj):
+-        return '(' + ', '.join(itertools.imap(self.visit, obj)) + ')'
++        return '(' + ', '.join(map(self.visit, obj)) + ')'
+     def visitList(self, obj):
+         if len(obj) == 1:
+             return '&' + self.visit(obj[0])
+-        return '{' + ', '.join(itertools.imap(self.visit, obj)) + '}'
++        return '{' + ', '.join(map(self.visit, obj)) + '}'
+     def visitItems(self, items):
+         return ', '.join(['%s = %s' % (name, self.visit(value)) for name, value in items])
+     def visitDict(self, obj):
+-        return '{' + self.visitItems(obj.iteritems()) + '}'
++        return '{' + self.visitItems(iter(obj.items())) + '}'
+     def visitByteArray(self, obj):
+         return 'blob(%u)' % len(obj)
+@@ -167,7 +167,7 @@ class Hasher(Visitor):
+         return obj
+     def visitIterable(self, obj):
+-        return tuple(itertools.imap(self.visit, obj))
++        return tuple(map(self.visit, obj))
+     def visitByteArray(self, obj):
+         return str(obj)
+@@ -268,7 +268,7 @@ class Counter(Unpickler):
+     def parse(self):
+         Unpickler.parse(self)
+-        functionFrequencies = self.functionFrequencies.items()
++        functionFrequencies = list(self.functionFrequencies.items())
+         functionFrequencies.sort(lambda (name1, freq1), (name2, freq2): cmp(freq1, freq2))
+         for name, frequency in functionFrequencies:
+             sys.stdout.write('%8u %s\n' % (frequency, name))
+diff --git a/specs/cglapi.py b/specs/cglapi.py
+index 69faeeb4..5d61886f 100644
+--- a/specs/cglapi.py
++++ b/specs/cglapi.py
+@@ -29,9 +29,9 @@ http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/
+ """
+-from stdapi import *
+-from glapi import *
+-from glapi import glapi
++from .stdapi import *
++from .glapi import *
++from .glapi import glapi
+ IOSurfaceRef = Opaque("IOSurfaceRef")
+ CGLContextObj = Opaque("CGLContextObj")
+diff --git a/specs/d2d1.py b/specs/d2d1.py
+index dacbea69..9bae43c5 100644
+--- a/specs/d2d1.py
++++ b/specs/d2d1.py
+@@ -25,9 +25,9 @@
+ ##########################################################################/
+-from winapi import *
+-from dxgi import DXGI_FORMAT, IDXGISurface
+-from dwrite import *
++from .winapi import *
++from .dxgi import DXGI_FORMAT, IDXGISurface
++from .dwrite import *
+diff --git a/specs/d3d.py b/specs/d3d.py
+index 0dde09f4..4b7244b2 100644
+--- a/specs/d3d.py
++++ b/specs/d3d.py
+@@ -25,10 +25,10 @@
+ """d3d.h"""
+-from winapi import *
+-from ddraw import *
+-from d3dtypes import *
+-from d3dcaps import *
++from .winapi import *
++from .ddraw import *
++from .d3dtypes import *
++from .d3dcaps import *
+ d3dnextFlags = Flags(DWORD, [
+     "D3DNEXT_NEXT",
+diff --git a/specs/d3d10.py b/specs/d3d10.py
+index 2161a5fd..e22bc230 100644
+--- a/specs/d3d10.py
++++ b/specs/d3d10.py
+@@ -24,8 +24,8 @@
+ ##########################################################################/
+-from dxgi import *
+-from d3d10sdklayers import *
++from .dxgi import *
++from .d3d10sdklayers import *
+ HRESULT = MAKE_HRESULT([
+diff --git a/specs/d3d10sdklayers.py b/specs/d3d10sdklayers.py
+index aad53f04..82beb721 100644
+--- a/specs/d3d10sdklayers.py
++++ b/specs/d3d10sdklayers.py
+@@ -24,7 +24,7 @@
+ ##########################################################################/
+-from dxgi import *
++from .dxgi import *
+ D3D10_DEBUG_FEATURE = Flags(UINT, [
+diff --git a/specs/d3d11.py b/specs/d3d11.py
+index f704b062..0a28caa3 100644
+--- a/specs/d3d11.py
++++ b/specs/d3d11.py
+@@ -24,8 +24,8 @@
+ ##########################################################################/
+-from dxgi import *
+-from d3d11sdklayers import *
++from .dxgi import *
++from .d3d11sdklayers import *
+ HRESULT = MAKE_HRESULT([
+diff --git a/specs/d3d11sdklayers.py b/specs/d3d11sdklayers.py
+index 907c4b09..97d07750 100644
+--- a/specs/d3d11sdklayers.py
++++ b/specs/d3d11sdklayers.py
+@@ -24,7 +24,7 @@
+ ##########################################################################/
+-from dxgi import *
++from .dxgi import *
+ ID3D11DeviceChild = Interface("ID3D11DeviceChild", IUnknown)
+diff --git a/specs/d3d8.py b/specs/d3d8.py
+index 2dbf1140..400af498 100644
+--- a/specs/d3d8.py
++++ b/specs/d3d8.py
+@@ -25,9 +25,9 @@
+ """d3d8.h"""
+-from winapi import *
+-from d3d8types import *
+-from d3d8caps import *
++from .winapi import *
++from .d3d8types import *
++from .d3d8caps import *
+ D3DSHADER8 = Blob(Const(DWORD), "_shaderSize(pFunction)")
+diff --git a/specs/d3d8caps.py b/specs/d3d8caps.py
+index 1af1a19f..b7ee5873 100644
+--- a/specs/d3d8caps.py
++++ b/specs/d3d8caps.py
+@@ -25,8 +25,8 @@
+ """d3d8caps.h"""
+-from winapi import *
+-from d3d8types import *
++from .winapi import *
++from .d3d8types import *
+ D3DCAPS = Flags(DWORD, [
+     "D3DCAPS_READ_SCANLINE",
+diff --git a/specs/d3d8types.py b/specs/d3d8types.py
+index fe58a0cd..a2482328 100644
+--- a/specs/d3d8types.py
++++ b/specs/d3d8types.py
+@@ -25,7 +25,7 @@
+ """d3d8types.h"""
+-from winapi import *
++from .winapi import *
+ D3DCOLOR = Alias("D3DCOLOR", DWORD)
+diff --git a/specs/d3d9.py b/specs/d3d9.py
+index 21015149..68dcaca2 100644
+--- a/specs/d3d9.py
++++ b/specs/d3d9.py
+@@ -25,9 +25,9 @@
+ """d3d9.h"""
+-from winapi import *
+-from d3d9types import *
+-from d3d9caps import *
++from .winapi import *
++from .d3d9types import *
++from .d3d9caps import *
+ D3DSHADER9 = Blob(Const(DWORD), "_shaderSize(pFunction)")
+diff --git a/specs/d3d9caps.py b/specs/d3d9caps.py
+index b3582879..541263b6 100644
+--- a/specs/d3d9caps.py
++++ b/specs/d3d9caps.py
+@@ -25,8 +25,8 @@
+ """d3d9caps.h"""
+-from winapi import *
+-from d3d9types import *
++from .winapi import *
++from .d3d9types import *
+ D3DVS20CAPS = Flags(DWORD, [
+     "D3DVS20CAPS_PREDICATION",
+diff --git a/specs/d3d9types.py b/specs/d3d9types.py
+index 2545a767..c9847030 100644
+--- a/specs/d3d9types.py
++++ b/specs/d3d9types.py
+@@ -26,7 +26,7 @@
+ """d3d9types.h"""
+-from winapi import *
++from .winapi import *
+ D3DCOLOR = Alias("D3DCOLOR", DWORD)
+diff --git a/specs/d3dcaps.py b/specs/d3dcaps.py
+index 0fa9f1cc..88725067 100644
+--- a/specs/d3dcaps.py
++++ b/specs/d3dcaps.py
+@@ -25,8 +25,8 @@
+ """d3dcaps.h"""
+-from winapi import *
+-from d3dtypes import *
++from .winapi import *
++from .d3dtypes import *
+ D3DTRANSFORMCAPS = Flags(DWORD, [
+     "D3DTRANSFORMCAPS_CLIP",
+diff --git a/specs/d3dtypes.py b/specs/d3dtypes.py
+index e1507975..ba460022 100644
+--- a/specs/d3dtypes.py
++++ b/specs/d3dtypes.py
+@@ -25,7 +25,7 @@
+ """d3dtypes.h"""
+-from winapi import *
++from .winapi import *
+ D3DVALUE = Float
+ LPD3DVALUE = Pointer(D3DVALUE)
+diff --git a/specs/dcommon.py b/specs/dcommon.py
+index 21659a5e..6324db3a 100644
+--- a/specs/dcommon.py
++++ b/specs/dcommon.py
+@@ -24,7 +24,7 @@
+ ##########################################################################/
+-from winapi import *
++from .winapi import *
+ DWRITE_MEASURING_MODE = Enum("DWRITE_MEASURING_MODE", [
+diff --git a/specs/dcomp.py b/specs/dcomp.py
+new file mode 100644
+index 00000000..b139a89e
+--- /dev/null
++++ b/specs/dcomp.py
+@@ -0,0 +1,303 @@
++##########################################################################
++#
++# Copyright 2009-2016 VMware, Inc.
++# All Rights Reserved.
++#
++# Permission is hereby granted, free of charge, to any person obtaining a copy
++# of this software and associated documentation files (the "Software"), to deal
++# in the Software without restriction, including without limitation the rights
++# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++# copies of the Software, and to permit persons to whom the Software is
++# furnished to do so, subject to the following conditions:
++#
++# The above copyright notice and this permission notice shall be included in
++# all copies or substantial portions of the Software.
++#
++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
++# THE SOFTWARE.
++#
++##########################################################################/
++
++
++from .dxgi import *
++from .d2d1 import D2D_MATRIX_3X2_F, D2D_RECT_F
++from .d3d9types import D3DMATRIX
++from .d2d1 import D2D1_COMPOSITE_MODE
++
++DCOMPOSITION_BITMAP_INTERPOLATION_MODE = Enum('DCOMPOSITION_BITMAP_INTERPOLATION_MODE', [
++    'DCOMPOSITION_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR',
++    'DCOMPOSITION_BITMAP_INTERPOLATION_MODE_LINEAR',
++    'DCOMPOSITION_BITMAP_INTERPOLATION_MODE_INHERIT',
++])
++
++DCOMPOSITION_BORDER_MODE = Enum('DCOMPOSITION_BORDER_MODE', [
++    'DCOMPOSITION_BORDER_MODE_SOFT',
++    'DCOMPOSITION_BORDER_MODE_HARD',
++    'DCOMPOSITION_BORDER_MODE_INHERIT',
++])
++
++DCOMPOSITION_COMPOSITE_MODE = Enum('DCOMPOSITION_COMPOSITE_MODE', [
++    'DCOMPOSITION_COMPOSITE_MODE_SOURCE_OVER',
++    'DCOMPOSITION_COMPOSITE_MODE_DESTINATION_INVERT',
++    'DCOMPOSITION_COMPOSITE_MODE_INHERIT',
++])
++
++DCOMPOSITION_FRAME_STATISTICS = Struct('DCOMPOSITION_FRAME_STATISTICS', [
++    (LARGE_INTEGER, 'lastFrameTime'),
++    (DXGI_RATIONAL, 'currentCompositionRate'),
++    (LARGE_INTEGER, 'currentTime'),
++    (LARGE_INTEGER, 'timeFrequency'),
++    (LARGE_INTEGER, 'nextEstimatedFrameTime'),
++])
++
++COMPOSITIONOBJECT = Flags(DWORD, [
++    'COMPOSITIONOBJECT_ALL_ACCESS',  # 0x0003
++    'COMPOSITIONOBJECT_READ',        # 0x0001
++    'COMPOSITIONOBJECT_WRITE',       # 0x0002
++])
++
++IDCompositionAnimation = Interface('IDCompositionAnimation', IUnknown)
++IDCompositionDevice = Interface('IDCompositionDevice', IUnknown)
++IDCompositionTarget = Interface('IDCompositionTarget', IUnknown)
++IDCompositionVisual = Interface('IDCompositionVisual', IUnknown)
++IDCompositionEffect = Interface('IDCompositionEffect', IUnknown)
++IDCompositionEffectGroup = Interface('IDCompositionEffectGroup', IDCompositionEffect)
++IDCompositionTransform3D = Interface('IDCompositionTransform3D', IDCompositionEffect)
++IDCompositionTransform = Interface('IDCompositionTransform', IDCompositionTransform3D)
++IDCompositionTranslateTransform = Interface('IDCompositionTranslateTransform', IDCompositionTransform)
++IDCompositionTranslateTransform3D = Interface('IDCompositionTranslateTransform3D', IDCompositionTransform3D)
++IDCompositionScaleTransform = Interface('IDCompositionScaleTransform', IDCompositionTransform)
++IDCompositionScaleTransform3D = Interface('IDCompositionScaleTransform3D', IDCompositionTransform3D)
++IDCompositionRotateTransform = Interface('IDCompositionRotateTransform', IDCompositionTransform)
++IDCompositionRotateTransform3D = Interface('IDCompositionRotateTransform3D', IDCompositionTransform3D)
++IDCompositionSkewTransform = Interface('IDCompositionSkewTransform', IDCompositionTransform)
++IDCompositionMatrixTransform = Interface('IDCompositionMatrixTransform', IDCompositionTransform)
++IDCompositionMatrixTransform3D = Interface('IDCompositionMatrixTransform3D', IDCompositionTransform3D)
++IDCompositionClip = Interface('IDCompositionClip', IUnknown)
++IDCompositionRectangleClip = Interface('IDCompositionRectangleClip', IDCompositionClip)
++IDCompositionSurface = Interface('IDCompositionSurface', IUnknown)
++IDCompositionVirtualSurface = Interface('IDCompositionVirtualSurface', IDCompositionSurface)
++
++IDCompositionAnimation.methods += [
++    StdMethod(HRESULT, 'Reset', []),
++    StdMethod(HRESULT, 'SetAbsoluteBeginTime', [(LARGE_INTEGER, 'beginTime')]),
++    StdMethod(HRESULT, 'AddCubic', [(Double, 'beginOffset'), (Float, 'constantCoefficient'), (Float, 'linearCoefficient'), (Float, 'quadraticCoefficient'), (Float, 'cubicCoefficient')]),
++    StdMethod(HRESULT, 'AddSinusoidal', [(Double, 'beginOffset'), (Float, 'bias'), (Float, 'amplitude'), (Float, 'frequency'), (Float, 'phase')]),
++    StdMethod(HRESULT, 'AddRepeat', [(Double, 'beginOffset'), (Double, 'durationToRepeat')]),
++    StdMethod(HRESULT, 'End', [(Double, 'endOffset'), (Float, 'endValue')]),
++]
++
++IDCompositionDevice.methods += [
++    StdMethod(HRESULT, 'Commit', []),
++    StdMethod(HRESULT, 'WaitForCommitCompletion', []),
++    StdMethod(HRESULT, 'GetFrameStatistics', [Out(Pointer(DCOMPOSITION_FRAME_STATISTICS), 'statistics')]),
++    StdMethod(HRESULT, 'CreateTargetForHwnd', [(HWND, 'hwnd'), (BOOL, 'topmost'), Out(Pointer(ObjPointer(IDCompositionTarget)), 'target')]),
++    StdMethod(HRESULT, 'CreateVisual', [Out(Pointer(ObjPointer(IDCompositionVisual)), 'visual')]),
++    StdMethod(HRESULT, 'CreateSurface', [(UINT, 'width'), (UINT, 'height'), (DXGI_FORMAT, 'pixelFormat'), (DXGI_ALPHA_MODE, 'alphaMode'), Out(Pointer(ObjPointer(IDCompositionSurface)), 'surface')]),
++    StdMethod(HRESULT, 'CreateVirtualSurface', [(UINT, 'initialWidth'), (UINT, 'initialHeight'), (DXGI_FORMAT, 'pixelFormat'), (DXGI_ALPHA_MODE, 'alphaMode'), Out(Pointer(ObjPointer(IDCompositionVirtualSurface)), 'virtualSurface')]),
++    StdMethod(HRESULT, 'CreateSurfaceFromHandle', [(HANDLE, 'handle'), Out(Pointer(ObjPointer(IUnknown)), 'surface')]),
++    StdMethod(HRESULT, 'CreateSurfaceFromHwnd', [(HWND, 'hwnd'), Out(Pointer(ObjPointer(IUnknown)), 'surface')]),
++    StdMethod(HRESULT, 'CreateTranslateTransform', [Out(Pointer(ObjPointer(IDCompositionTranslateTransform)), 'translateTransform')]),
++    StdMethod(HRESULT, 'CreateScaleTransform', [Out(Pointer(ObjPointer(IDCompositionScaleTransform)), 'scaleTransform')]),
++    StdMethod(HRESULT, 'CreateRotateTransform', [Out(Pointer(ObjPointer(IDCompositionRotateTransform)), 'rotateTransform')]),
++    StdMethod(HRESULT, 'CreateSkewTransform', [Out(Pointer(ObjPointer(IDCompositionSkewTransform)), 'skewTransform')]),
++    StdMethod(HRESULT, 'CreateMatrixTransform', [Out(Pointer(ObjPointer(IDCompositionMatrixTransform)), 'matrixTransform')]),
++    StdMethod(HRESULT, 'CreateTransformGroup', [(Array(ObjPointer(IDCompositionTransform), 'elements'), 'transforms'), (UINT, 'elements'), Out(Pointer(ObjPointer(IDCompositionTransform)), 'transformGroup')]),
++    StdMethod(HRESULT, 'CreateTranslateTransform3D', [Out(Pointer(ObjPointer(IDCompositionTranslateTransform3D)), 'translateTransform3D')]),
++    StdMethod(HRESULT, 'CreateScaleTransform3D', [Out(Pointer(ObjPointer(IDCompositionScaleTransform3D)), 'scaleTransform3D')]),
++    StdMethod(HRESULT, 'CreateRotateTransform3D', [Out(Pointer(ObjPointer(IDCompositionRotateTransform3D)), 'rotateTransform3D')]),
++    StdMethod(HRESULT, 'CreateMatrixTransform3D', [Out(Pointer(ObjPointer(IDCompositionMatrixTransform3D)), 'matrixTransform3D')]),
++    StdMethod(HRESULT, 'CreateTransform3DGroup', [(Array(ObjPointer(IDCompositionTransform3D), 'elements'), 'transforms3D'), (UINT, 'elements'), Out(Pointer(ObjPointer(IDCompositionTransform3D)), 'transform3DGroup')]),
++    StdMethod(HRESULT, 'CreateEffectGroup', [Out(Pointer(ObjPointer(IDCompositionEffectGroup)), 'effectGroup')]),
++    StdMethod(HRESULT, 'CreateRectangleClip', [Out(Pointer(ObjPointer(IDCompositionRectangleClip)), 'clip')]),
++    StdMethod(HRESULT, 'CreateAnimation', [Out(Pointer(ObjPointer(IDCompositionAnimation)), 'animation')]),
++    StdMethod(HRESULT, 'CheckDeviceState', [Out(Pointer(BOOL), 'pfValid')]),
++]
++
++IDCompositionTarget.methods += [
++    StdMethod(HRESULT, 'SetRoot', [(ObjPointer(IDCompositionVisual), 'visual')]),
++]
++
++IDCompositionVisual.methods += [
++    StdMethod(HRESULT, 'SetOffsetX', [(Float, 'offsetX')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetY', [(Float, 'offsetY')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetTransform', [(Reference(Const(D2D_MATRIX_3X2_F)), 'matrix')], overloaded=True),
++    StdMethod(HRESULT, 'SetTransform', [(ObjPointer(IDCompositionTransform), 'transform')], overloaded=True),
++    StdMethod(HRESULT, 'SetTransformParent', [(ObjPointer(IDCompositionVisual), 'visual')]),
++    StdMethod(HRESULT, 'SetEffect', [(ObjPointer(IDCompositionEffect), 'effect')]),
++    StdMethod(HRESULT, 'SetBitmapInterpolationMode', [(DCOMPOSITION_BITMAP_INTERPOLATION_MODE, 'interpolationMode')]),
++    StdMethod(HRESULT, 'SetBorderMode', [(DCOMPOSITION_BORDER_MODE, 'borderMode')]),
++    StdMethod(HRESULT, 'SetClip', [(Reference(Const(D2D_RECT_F)), 'rect')], overloaded=True),
++    StdMethod(HRESULT, 'SetClip', [(ObjPointer(IDCompositionClip), 'clip')], overloaded=True),
++    StdMethod(HRESULT, 'SetContent', [(ObjPointer(IUnknown), 'content')]),
++    StdMethod(HRESULT, 'AddVisual', [(ObjPointer(IDCompositionVisual), 'visual'), (BOOL, 'insertAbove'), (ObjPointer(IDCompositionVisual), 'referenceVisual')]),
++    StdMethod(HRESULT, 'RemoveVisual', [(ObjPointer(IDCompositionVisual), 'visual')]),
++    StdMethod(HRESULT, 'RemoveAllVisuals', []),
++    StdMethod(HRESULT, 'SetCompositeMode', [(DCOMPOSITION_COMPOSITE_MODE, 'compositeMode')]),
++]
++
++IDCompositionTransform.methods += [
++]
++
++IDCompositionTransform3D.methods += [
++]
++
++IDCompositionTranslateTransform.methods += [
++    StdMethod(HRESULT, 'SetOffsetX', [(Float, 'offsetX')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetY', [(Float, 'offsetY')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionTranslateTransform3D.methods += [
++    StdMethod(HRESULT, 'SetOffsetX', [(Float, 'offsetX')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetY', [(Float, 'offsetY')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetZ', [(Float, 'offsetZ')], overloaded=True),
++    StdMethod(HRESULT, 'SetOffsetZ', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionScaleTransform.methods += [
++    StdMethod(HRESULT, 'SetScaleX', [(Float, 'scaleX')], overloaded=True),
++    StdMethod(HRESULT, 'SetScaleX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetScaleY', [(Float, 'scaleY')], overloaded=True),
++    StdMethod(HRESULT, 'SetScaleY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(Float, 'centerX')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(Float, 'centerY')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionScaleTransform3D.methods += [
++    StdMethod(HRESULT, 'SetScaleX', [(Float, 'scaleX')], overloaded=True),
++    StdMethod(HRESULT, 'SetScaleX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetScaleY', [(Float, 'scaleY')], overloaded=True),
++    StdMethod(HRESULT, 'SetScaleY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetScaleZ', [(Float, 'scaleZ')], overloaded=True),
++    StdMethod(HRESULT, 'SetScaleZ', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(Float, 'centerX')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(Float, 'centerY')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterZ', [(Float, 'centerZ')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterZ', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionRotateTransform.methods += [
++    StdMethod(HRESULT, 'SetAngle', [(Float, 'angle')], overloaded=True),
++    StdMethod(HRESULT, 'SetAngle', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(Float, 'centerX')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(Float, 'centerY')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionRotateTransform3D.methods += [
++    StdMethod(HRESULT, 'SetAngle', [(Float, 'angle')], overloaded=True),
++    StdMethod(HRESULT, 'SetAngle', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetAxisX', [(Float, 'axisX')], overloaded=True),
++    StdMethod(HRESULT, 'SetAxisX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetAxisY', [(Float, 'axisY')], overloaded=True),
++    StdMethod(HRESULT, 'SetAxisY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetAxisZ', [(Float, 'axisZ')], overloaded=True),
++    StdMethod(HRESULT, 'SetAxisZ', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(Float, 'centerX')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(Float, 'centerY')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterZ', [(Float, 'centerZ')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterZ', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionSkewTransform.methods += [
++    StdMethod(HRESULT, 'SetAngleX', [(Float, 'angleX')], overloaded=True),
++    StdMethod(HRESULT, 'SetAngleX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetAngleY', [(Float, 'angleY')], overloaded=True),
++    StdMethod(HRESULT, 'SetAngleY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(Float, 'centerX')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(Float, 'centerY')], overloaded=True),
++    StdMethod(HRESULT, 'SetCenterY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionMatrixTransform.methods += [
++    StdMethod(HRESULT, 'SetMatrix', [(Reference(Const(D2D_MATRIX_3X2_F)), 'matrix')]),
++    StdMethod(HRESULT, 'SetMatrixElement', [(Int, 'row'), (Int, 'column'), (Float, 'value')], overloaded=True),
++    StdMethod(HRESULT, 'SetMatrixElement', [(Int, 'row'), (Int, 'column'), (ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionMatrixTransform3D.methods += [
++    StdMethod(HRESULT, 'SetMatrix', [(Reference(Const(D3DMATRIX)), 'matrix')]),
++    StdMethod(HRESULT, 'SetMatrixElement', [(Int, 'row'), (Int, 'column'), (Float, 'value')], overloaded=True),
++    StdMethod(HRESULT, 'SetMatrixElement', [(Int, 'row'), (Int, 'column'), (ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionEffect.methods += [
++]
++
++IDCompositionEffectGroup.methods += [
++    StdMethod(HRESULT, 'SetOpacity', [(Float, 'opacity')], overloaded=True),
++    StdMethod(HRESULT, 'SetOpacity', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetTransform3D', [(ObjPointer(IDCompositionTransform3D), 'transform3D')]),
++]
++
++IDCompositionClip.methods += [
++]
++
++IDCompositionRectangleClip.methods += [
++    StdMethod(HRESULT, 'SetLeft', [(Float, 'left')], overloaded=True),
++    StdMethod(HRESULT, 'SetLeft', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetTop', [(Float, 'top')], overloaded=True),
++    StdMethod(HRESULT, 'SetTop', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetRight', [(Float, 'right')], overloaded=True),
++    StdMethod(HRESULT, 'SetRight', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottom', [(Float, 'bottom')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottom', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetTopLeftRadiusX', [(Float, 'radius')], overloaded=True),
++    StdMethod(HRESULT, 'SetTopLeftRadiusX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetTopLeftRadiusY', [(Float, 'radius')], overloaded=True),
++    StdMethod(HRESULT, 'SetTopLeftRadiusY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetTopRightRadiusX', [(Float, 'radius')], overloaded=True),
++    StdMethod(HRESULT, 'SetTopRightRadiusX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetTopRightRadiusY', [(Float, 'radius')], overloaded=True),
++    StdMethod(HRESULT, 'SetTopRightRadiusY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottomLeftRadiusX', [(Float, 'radius')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottomLeftRadiusX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottomLeftRadiusY', [(Float, 'radius')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottomLeftRadiusY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottomRightRadiusX', [(Float, 'radius')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottomRightRadiusX', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottomRightRadiusY', [(Float, 'radius')], overloaded=True),
++    StdMethod(HRESULT, 'SetBottomRightRadiusY', [(ObjPointer(IDCompositionAnimation), 'animation')], overloaded=True),
++]
++
++IDCompositionSurface.methods += [
++    # XXX: riid might be ID2D1DeviceContext
++    StdMethod(HRESULT, 'BeginDraw', [(Pointer(Const(RECT)), 'updateRect'), (REFIID, 'iid'), Out(Pointer(ObjPointer(Void)), 'updateObject'), Out(Pointer(POINT), 'updateOffset')]),
++    StdMethod(HRESULT, 'EndDraw', []),
++    StdMethod(HRESULT, 'SuspendDraw', []),
++    StdMethod(HRESULT, 'ResumeDraw', []),
++    StdMethod(HRESULT, 'Scroll', [(Pointer(Const(RECT)), 'scrollRect'), (Pointer(Const(RECT)), 'clipRect'), (Int, 'offsetX'), (Int, 'offsetY')]),
++]
++
++IDCompositionVirtualSurface.methods += [
++    StdMethod(HRESULT, 'Resize', [(UINT, 'width'), (UINT, 'height')]),
++    StdMethod(HRESULT, 'Trim', [(Array(Const(RECT), 'count'), 'rectangles'), (UINT, 'count')]),
++]
++
++dcomp = Module('dcomp')
++dcomp.addFunctions([
++    StdFunction(HRESULT, 'DCompositionCreateDevice', [(ObjPointer(IDXGIDevice), 'dxgiDevice'), (REFIID, 'iid'), Out(Pointer(ObjPointer(Void)), 'dcompositionDevice')]),
++    StdFunction(HRESULT, 'DCompositionCreateSurfaceHandle', [(COMPOSITIONOBJECT, 'desiredAccess'), (Pointer(SECURITY_ATTRIBUTES), 'securityAttributes'), Out(Pointer(HANDLE), 'surfaceHandle')]),
++])
++dcomp.addInterfaces([
++    IDCompositionDevice,
++])
+diff --git a/specs/ddraw.py b/specs/ddraw.py
+index 99f542fe..5df48be0 100644
+--- a/specs/ddraw.py
++++ b/specs/ddraw.py
+@@ -25,7 +25,7 @@
+ """ddraw.h"""
+-from winapi import *
++from .winapi import *
+ DirectDrawOptSurfaceDescFlags = Flags(DWORD, [
+     "DDOSD_GUID",
+diff --git a/specs/debug.py b/specs/debug.py
+index 0a004741..6ef80f64 100644
+--- a/specs/debug.py
++++ b/specs/debug.py
+@@ -49,7 +49,7 @@ def excepthook(type, value, tb):
+               import traceback, pdb
+               # we are NOT in interactive mode, print the exception...
+               traceback.print_exception(type, value, tb)
+-              print
++              print()
+               # ...then start the debugger in post-mortem mode.
+               pdb.pm()
+diff --git a/specs/dwrite.py b/specs/dwrite.py
+index 60e5034c..be273f81 100644
+--- a/specs/dwrite.py
++++ b/specs/dwrite.py
+@@ -24,8 +24,8 @@
+ ##########################################################################/
+-from winapi import *
+-from dcommon import *
++from .winapi import *
++from .dcommon import *
+ ID2D1SimplifiedGeometrySink = Interface("ID2D1SimplifiedGeometrySink", IUnknown)
+diff --git a/specs/dxgi.py b/specs/dxgi.py
+index 0e880548..040f3bc4 100644
+--- a/specs/dxgi.py
++++ b/specs/dxgi.py
+@@ -25,7 +25,7 @@
+ ##########################################################################/
+-from winapi import *
++from .winapi import *
+ DXGI_FORMAT = Enum("DXGI_FORMAT", [
+diff --git a/specs/dxva2.py b/specs/dxva2.py
+index 3936afac..65f5f0c0 100644
+--- a/specs/dxva2.py
++++ b/specs/dxva2.py
+@@ -24,7 +24,7 @@
+ ##########################################################################/
+-from d3d9 import *
++from .d3d9 import *
+ HRESULT = MAKE_HRESULT(errors = [
+diff --git a/specs/eglapi.py b/specs/eglapi.py
+index 8379e45e..e1edff06 100644
+--- a/specs/eglapi.py
++++ b/specs/eglapi.py
+@@ -26,9 +26,9 @@
+ """EGL API description."""
+-from stdapi import *
+-from gltypes import *
+-from eglenum import *
++from .stdapi import *
++from .gltypes import *
++from .eglenum import *
+ EGLNativeDisplayType = Opaque("EGLNativeDisplayType")
+ EGLNativeWindowType = Opaque("EGLNativeWindowType")
+diff --git a/specs/eglenum.py b/specs/eglenum.py
+index 8b10868d..e6290fb2 100644
+--- a/specs/eglenum.py
++++ b/specs/eglenum.py
+@@ -28,7 +28,7 @@
+ """EGL enum description"""
+-from stdapi import *
++from .stdapi import *
+ # Most of the following content was produced in a semi-automated fashion by
+ # the scripts/eglenum.sed sed script.
+diff --git a/specs/glapi.py b/specs/glapi.py
+index c0e92b3c..8d20052e 100644
+--- a/specs/glapi.py
++++ b/specs/glapi.py
+@@ -34,9 +34,9 @@ corner cases correctly.
+ """
+-from stdapi import *
+-from gltypes import *
+-import glparams
++from .stdapi import *
++from .gltypes import *
++from . import glparams
+ def GlFunction(*args, **kwargs):
+diff --git a/specs/glparams.py b/specs/glparams.py
+index 1bed8a6b..5a036975 100644
+--- a/specs/glparams.py
++++ b/specs/glparams.py
+@@ -27,9 +27,9 @@
+ '''Describe GL parameters.'''
+-from stdapi import *
++from .stdapi import *
+-from gltypes import *
++from .gltypes import *
+ # Shorthands for the types
+diff --git a/specs/gltypes.py b/specs/gltypes.py
+index a9ffc4a1..631eb868 100644
+--- a/specs/gltypes.py
++++ b/specs/gltypes.py
+@@ -29,7 +29,7 @@
+ import platform
+-from stdapi import *
++from .stdapi import *
+ GLboolean = Enum("GLboolean", [
+diff --git a/specs/glxapi.py b/specs/glxapi.py
+index 0d3cd969..f4182799 100644
+--- a/specs/glxapi.py
++++ b/specs/glxapi.py
+@@ -26,8 +26,8 @@
+ """GLX API description."""
+-from stdapi import *
+-from glapi import *
++from .stdapi import *
++from .glapi import *
+ VisualID = Alias("VisualID", UInt32)
+ Display = Opaque("Display *")
+diff --git a/specs/scripts/c2api.py b/specs/scripts/c2api.py
+index 7deb2955..b8aaa81d 100755
+--- a/specs/scripts/c2api.py
++++ b/specs/scripts/c2api.py
+@@ -122,7 +122,7 @@ class DeclParser:
+                     self.consume()
+                     type = 'Pointer(%s)' % type
+                 name = self.consume()
+-                print '%s = Alias("%s", %s)' % (name, name, type)
++                print('%s = Alias("%s", %s)' % (name, name, type))
+                 if self.match(','):
+                     self.consume()
+                 else:
+@@ -136,7 +136,7 @@ class DeclParser:
+         name = self.consume()
+         self.consume('{')
+-        print '%s = Enum("%s", [' % (name, name)
++        print('%s = Enum("%s", [' % (name, name))
+         #value = 0
+         while self.lookahead() != '}':
+@@ -148,12 +148,12 @@ class DeclParser:
+                 self.consume(',')
+             tags = self.parse_tags()
+             #print '    "%s",\t# %s' % (name, value) 
+-            print '    "%s",' % (name,) 
++            print('    "%s",' % (name,)) 
+             #value += 1
+         self.consume('}')
+-        print '])'
+-        print
++        print('])')
++        print()
+     def parse_value(self, ref_token, constructor):
+         self.consume(ref_token)
+@@ -161,14 +161,14 @@ class DeclParser:
+         name = self.consume()
+         self.consume('{')
+-        print '%s = %s(%s, [' % (name, constructor, type)
++        print('%s = %s(%s, [' % (name, constructor, type))
+         while self.lookahead() != '}':
+             name, value = self.parse_define()
+         self.consume('}')
+-        print '])'
+-        print
++        print('])')
++        print()
+     def parse_define(self):
+         self.consume('#')
+@@ -176,18 +176,18 @@ class DeclParser:
+         name = self.consume()
+         value = self.consume()
+         #print '    "%s",\t# %s' % (name, value) 
+-        print '    "%s",' % (name,) 
++        print('    "%s",' % (name,)) 
+         return name, value
+     def parse_struct(self):
+         self.consume('struct')
+         name = self.consume()
+-        print '%s = Struct("%s", [' % (name, name)
++        print('%s = Struct("%s", [' % (name, name))
+         for type, name in self.parse_members():
+-            print '    (%s, "%s"),' % (type, name)
+-        print '])'
+-        print
++            print('    (%s, "%s"),' % (type, name))
++        print('])')
++        print()
+     def parse_union(self):
+         self.consume('union')
+@@ -226,8 +226,8 @@ class DeclParser:
+         base = self.consume()
+         self.consume('{')
+-        print '%s = Interface("%s", %s)' % (name, name, base)
+-        print '%s.methods += [' % (name,)
++        print('%s = Interface("%s", %s)' % (name, name, base))
++        print('%s.methods += [' % (name,))
+         while self.lookahead() != '}':
+             if self.lookahead() in ('public', 'private'):
+@@ -238,8 +238,8 @@ class DeclParser:
+                 self.consume(';')
+         self.consume('}')
+-        print ']'
+-        print
++        print(']')
++        print()
+     def parse_prototype(self, creator = 'Function'):
+         if self.match('extern', 'virtual'):
+@@ -275,7 +275,7 @@ class DeclParser:
+             self.consume()
+             self.consume('0')
+         
+-        print '    %s(%s, "%s", [%s]%s),' % (creator, ret, name, ', '.join(args), extra)
++        print('    %s(%s, "%s", [%s]%s),' % (creator, ret, name, ', '.join(args), extra))
+     def parse_arg(self):
+         tags = self.parse_tags()
+@@ -404,8 +404,8 @@ class DeclParser:
+                     type = 'S' + type
+             elif short:
+                 type = 'Short'
+-            elif long:
+-                type = 'Long' * long
++            elif int:
++                type = 'Long' * int
+             else:
+                 type = 'Int'
+             if unsigned:
+diff --git a/specs/scripts/cxx2api.py b/specs/scripts/cxx2api.py
+new file mode 100755
+index 00000000..9720615d
+--- /dev/null
++++ b/specs/scripts/cxx2api.py
+@@ -0,0 +1,488 @@
++#!/usr/bin/env python
++
++
++
++copyright = '''
++##########################################################################
++#
++# Copyright 2009-2016 VMware, Inc.
++# All Rights Reserved.
++#
++# Permission is hereby granted, free of charge, to any person obtaining a copy
++# of this software and associated documentation files (the "Software"), to deal
++# in the Software without restriction, including without limitation the rights
++# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++# copies of the Software, and to permit persons to whom the Software is
++# furnished to do so, subject to the following conditions:
++#
++# The above copyright notice and this permission notice shall be included in
++# all copies or substantial portions of the Software.
++#
++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
++# THE SOFTWARE.
++#
++##########################################################################/
++'''
++
++
++#
++# Generates API specs from headers using castxml/pygccxml.
++#
++# Usage:
++#
++#   sudo apt-get install castxml mingw-w64-i686-dev
++#   pip install 'pygccxml==1.9.1'
++#   python specs/scripts/cxx2api.py -Idxsdk/Include -DD2D_USE_C_DEFINITIONS dcomp.h dcomptypes.h dcompanimation.h
++#
++# See also:
++# - http://pygccxml.readthedocs.org/en/develop/index.html
++# - https://github.com/CastXML/CastXML/blob/master/doc/manual/castxml.1.rst
++#
++
++import os.path
++import sys
++import io as StringIO
++import subprocess
++
++from pygccxml import utils
++from pygccxml import parser
++from pygccxml import declarations
++
++from pygccxml.declarations import algorithm
++from pygccxml.declarations import decl_visitor
++from pygccxml.declarations import type_traits
++from pygccxml.declarations import type_visitor
++
++
++class decl_dumper_t(decl_visitor.decl_visitor_t):
++
++    def __init__(self, decl = None):
++        decl_visitor.decl_visitor_t.__init__(self)
++        self.decl = decl
++        self.result = None
++
++    def clone(self):
++        return decl_dumper_t(self.decl)
++
++    def visit_class(self):
++        class_ = self.decl
++        assert class_.class_type in ('struct', 'union')
++        self.result = class_.name
++
++    def visit_class_declaration(self):
++        class_ = self.decl
++        self.result = class_.name
++
++    def visit_typedef(self):
++        typedef = self.decl
++        self.result = typedef.name
++
++    def visit_enumeration(self):
++        self.result = self.decl.name
++
++
++def dump_decl(decl):
++    visitor = decl_dumper_t(decl)
++    algorithm.apply_visitor(visitor, decl)
++    return visitor.result
++
++
++class type_dumper_t(type_visitor.type_visitor_t):
++
++    def __init__(self, type):
++        type_visitor.type_visitor_t.__init__(self)
++        self.type = type
++        self.result = None
++
++    def clone(self):
++        return type_dumper_t(self.type)
++
++    def visit_void(self):
++        self.result = 'Void'
++
++    def visit_char(self):
++        self.result = 'Char'
++
++    def visit_unsigned_char(self):
++        self.result = 'UChar'
++
++    def visit_signed_char(self):
++        self.result = 'SChar'
++
++    def visit_wchar(self):
++        raise NotImplementedError
++
++    def visit_short_int(self):
++        self.result = 'Short'
++
++    def visit_short_unsigned_int(self):
++        self.result = 'UShort'
++
++    def visit_bool(self):
++        raise NotImplementedError
++
++    def visit_int(self):
++        self.result = 'Int'
++
++    def visit_unsigned_int(self):
++        self.result = 'UInt'
++
++    def visit_long_int(self):
++        self.result = 'Long'
++
++    def visit_long_unsigned_int(self):
++        self.result = 'ULong'
++
++    def visit_long_long_int(self):
++        self.result = 'LongLong'
++
++    def visit_long_long_unsigned_int(self):
++        self.result = 'ULongLong'
++
++    def visit_float(self):
++        self.result = "Float"
++
++    def visit_double(self):
++        self.result = "Double"
++
++    def visit_array(self):
++        base_type = dump_type(self.type.base)
++        length = self.type.size
++        try:
++            int(length)
++        except ValueError:
++            length = '"%s"' % length
++        self.result = 'Array(%s, %s)' % (base_type, length)
++
++    def visit_pointer(self):
++        base_type = dump_type(self.type.base)
++        # TODO: Use ObjPointer where appropriate
++        #if isinstance(self.type.base, declarations.cpptypes.declarated_t):
++        #    decl = self.type.base.declaration
++        #    if isinstance(decl, declarations.typedef.typedef_t):
++        #        print(decl.type, type(decl.type))
++        #    if isinstance(decl, declarations.class_declaration.class_t):
++        #        if decl.public_members:
++        #            self.result = 'ObjPointer(%s)' % decl.name
++        #            return
++        #    if isinstance(decl, declarations.class_declaration.class_declaration_t):
++        #        if decl.public_members:
++        #            self.result = 'ObjPointer(%s)' % decl.name
++        #            return
++        if base_type.startswith('IDComposition') or \
++           base_type.startswith('IDXGI') or \
++           base_type == 'IUnknown':
++            self.result = 'ObjPointer(%s)' % base_type
++            return
++        self.result = 'Pointer(%s)' % base_type
++
++    def visit_reference(self):
++        base_type = dump_type(self.type.base)
++        if base_type == 'Const(IID)':
++            self.result = 'REFIID'
++        elif base_type == 'Const(GUID)':
++            self.result = 'REFGUID'
++        else:
++            self.result = 'Reference(%s)' % base_type
++
++    def visit_const(self):
++        self.result = 'Const(%s)' % dump_type(self.type.base)
++
++    def visit_declarated(self):
++        decl = self.type.declaration
++        self.result = dump_decl(decl)
++
++    def visit_free_function_type(self):
++        self.result = 'Opaque("%s")' % self.type
++
++
++def dump_type(type):
++    visitor = type_dumper_t(type)
++    algorithm.apply_visitor(visitor, type)
++    # XXX: RECT becomes tagRECT somehow
++    if visitor.result == 'tagRECT':
++        return 'RECT'
++    return visitor.result
++
++
++def is_interface(class_):
++    if not class_.name.startswith('I'):
++        return
++    if len(class_.bases) != 1:
++        return False
++    # TODO: Ensure interface derives from IUnknown
++    return True
++
++
++class decl2_dumper_t(decl_visitor.decl_visitor_t):
++
++    def __init__(self, name):
++        decl_visitor.decl_visitor_t.__init__(self)
++
++        self.name = name
++
++        # The current declaration
++        self.decl = None
++
++        self.interfaces = StringIO.StringIO()
++        self.methods = StringIO.StringIO()
++        self.functions = StringIO.StringIO()
++
++    def start(self):
++        print(copyright.strip())
++        print()
++        print()
++        print(r'from winapi import *')
++        print()
++
++    def finish(self):
++        sys.stdout.write(self.interfaces.getvalue())
++        sys.stdout.write('\n')
++        sys.stdout.write(self.methods.getvalue())
++
++        name = self.name
++        sys.stdout.write('%s = Module(%r)\n' % (name, name))
++        sys.stdout.write('%s.addFunctions([\n' % (name,))
++        sys.stdout.write(self.functions.getvalue())
++        sys.stdout.write('])\n\n')
++
++    def clone(self):
++        return decl_dumper_t(self.decl)
++
++    def visit_class(self):
++        class_ = self.decl
++        assert class_.class_type in ('struct', 'union')
++
++        if is_interface(class_):
++            self.visit_interface()
++        elif class_.name != '':
++            self.visit_struct(class_.name, class_)
++
++    def visit_struct(self, decl_name, decl):
++        struct = decl
++        print(r'%s = Struct(%r, [' % (decl_name, decl_name))
++        for variable in struct.variables(allow_empty=True):
++            var_type = dump_type(variable.decl_type)
++            print(r'    (%s, %r),' % (var_type, variable.name))
++        print(r'])')
++        print()
++
++    def visit_interface(self):
++        class_ = self.decl
++        assert len(class_.bases) == 1
++        base = class_.bases[0]
++
++        s = self.interfaces
++        s.write('%s = Interface(%r, %s)\n' % (class_.name, class_.name, base.related_class.name))
++
++        s = self.methods
++        s.write('%s.methods += [\n' % (class_.name,))
++        for member in class_.public_members:
++            if member.virtuality != 'pure virtual':
++                continue
++            ret_type = dump_type(member.return_type)
++            arg_types = self.convert_args(member.arguments)
++            s.write('    StdMethod(%s, %r, [%s]),\n' % (ret_type, member.name, arg_types))
++        s.write(']\n\n')
++
++    def convert_args(self, args):
++        # TODO: use __attribute__ ((annotate ("out")))
++        # See also:
++        # - https://github.com/CastXML/CastXML/issues/25
++        # XXX: Requires a castxml version newer than the one in Ubuntu 15.10
++        arg_types = []
++        for arg in args:
++            if arg.attributes is not None:
++                sys.stderr.write('warning: found %s attribute %r\n' % (arg.name, arg.attributes))
++            res_arg_type = dump_type(arg.decl_type)
++            res_arg = '(%s, %r)' % (res_arg_type, arg.name)
++
++            # Infer output arguments
++            if res_arg_type.startswith('Pointer(') and \
++               not res_arg_type.startswith('Pointer(Const('):
++                   res_arg = 'Out' + res_arg
++
++            arg_types.append(res_arg)
++
++        arg_types = ', '.join(arg_types)
++        return arg_types
++
++    def visit_class_declaration(self):
++        pass
++
++    def visit_typedef(self):
++        typedef = self.decl
++        base_type = dump_type(typedef.decl_type)
++        if base_type == typedef.name:
++            # Ignore `typedef struct Foo Foo;`
++            return
++        if base_type == '':
++            if isinstance(typedef.decl_type, declarations.cpptypes.declarated_t):
++                base_decl = typedef.decl_type.declaration
++                self.visit_struct(typedef.name, base_decl)
++                return
++        print(r'%s = Alias(%r, %s)' % (typedef.name, typedef.name, base_type))
++        print()
++
++    def visit_enumeration(self):
++        enum = self.decl
++        print(r'%s = Enum(%r, [' % (enum.name, enum.name))
++        for name, value in enum.values:
++            print(r'    %r,' % (name,))
++        print(r'])')
++        print()
++
++    def visit_variable(self):
++        pass
++
++    def visit_free_function(self):
++        function = self.decl
++        if function.has_inline:
++            return
++
++        s = self.functions
++        ret_type = dump_type(function.return_type)
++        arg_types = self.convert_args(function.arguments)
++        s.write('    StdFunction(%s, %r, [%s]),\n' % (ret_type, function.name, arg_types))
++
++    def visit_free_operator(self):
++        pass
++
++
++def main():
++    defines = []
++    includes = []
++    cxxflags = [
++        '-Wno-unknown-attributes',
++        '-Wno-unused-value',
++        '-Wno-macro-redefined',
++    ]
++    compiler = 'g++'
++
++    args = sys.argv[1:]
++    while args and args[0].startswith('-'):
++        arg = args.pop(0)
++        if arg.startswith('-I'):
++            include = arg[2:]
++            includes.append(include)
++        elif arg.startswith('-D'):
++            define = arg[2:]
++            defines.append(define)
++        else:
++            sys.stderr.write('error: unknown option %r\n' % arg)
++            sys.exit(1)
++
++    winsdk = True
++    if winsdk:
++        # Set up Clang compiler flags to use MinGW runtime
++        # http://stackoverflow.com/a/19839946
++        p = subprocess.Popen(
++            ["x86_64-w64-mingw32-g++", "-x", "c++", "-E", "-Wp,-v", '-', '-fsyntax-only'],
++            stdin=open(os.devnull, 'rt'),
++            stdout=open(os.devnull, 'wt'),
++            stderr=subprocess.PIPE)
++        includes.append('/usr/share/castxml/clang/include')
++        for line in p.stderr:
++            if line.startswith(' '):
++                include = line.strip()
++                if os.path.isdir(include):
++                    if os.path.exists(os.path.join(include, 'ia32intrin.h')):
++                        # XXX: We must use Clang's intrinsic headers
++                        continue
++                    includes.append(os.path.normpath(include))
++
++        winver = 0x0602
++
++        defines += [
++            # emulate MinGW
++            '__MINGW32__',
++            '_WIN32',
++            '_WIN64',
++            '__declspec(x)=',
++            # Avoid namespace pollution when including windows.h
++            # http://support.microsoft.com/kb/166474
++            'WIN32_LEAN_AND_MEAN',
++            # Set Windows version to 8.1
++            '_WIN32_WINNT=0x%04X' % winver,
++            'WINVER=0x%04X' % winver,
++            'NTDDI_VERSION=0x%04X0000' % winver,
++            # Prevent headers from requiring a rpcndr.h version beyond MinGW's
++            '__REQUIRED_RPCNDR_H_VERSION__=475',
++            # Avoid C++ helper classes
++            'D3D10_NO_HELPERS',
++            'D3D11_NO_HELPERS',
++            'D3D11_VIDEO_NO_HELPERS',
++        ]
++
++        # XXX: Change compiler?
++        #compiler = 'cl'
++
++        # XXX: This doesn't seem to work well
++        cxxflags += [
++            #'-m32',
++            #'-target', 'x86_64-pc-mingw32',
++        ]
++
++    sys.stderr.write('Include path:\n')
++    for include in includes:
++        sys.stderr.write('  %s\n' % include)
++    sys.stderr.write('Definitions:\n')
++    for define in defines:
++        sys.stderr.write('  %s\n' % define)
++
++    import logging
++    utils.loggers.set_level(logging.DEBUG)
++
++    # Find the location of the xml generator (castxml or gccxml)
++    generator_path, generator_name = utils.find_xml_generator("castxml")
++
++    # Configure the xml generator
++    config = parser.xml_generator_configuration_t(
++        xml_generator_path=generator_path,
++        xml_generator=generator_name,
++        define_symbols = defines,
++        include_paths = includes,
++        cflags = ' '.join(cxxflags),
++        compiler = compiler,
++        #keep_xml = True,
++    )
++
++    script_dir = os.path.dirname(__file__)
++    headers = [
++        os.path.join(script_dir, '..', '..', 'compat', 'winsdk_compat.h'),
++        os.path.join(script_dir, 'cxx2api.h'),
++    ]
++    main_header = args[0]
++    headers.append(main_header)
++
++    decls = parser.parse(headers, config, parser.COMPILATION_MODE.ALL_AT_ONCE)
++    global_ns = declarations.get_global_namespace(decls)
++
++    def decl_filter(decl):
++        location = decl.location
++        if location is None:
++            return False
++        return os.path.basename(location.file_name) in list(map(os.path.basename, args))
++
++    module, _ = os.path.splitext(main_header)
++    visitor = decl2_dumper_t(module)
++    visitor.start()
++    for decl in global_ns.declarations:
++        if not decl_filter(decl):
++            continue
++
++        if sys.stdout.isatty():
++            print('# ' + str(decl))
++
++        visitor.decl = decl
++        algorithm.apply_visitor(visitor, decl)
++    visitor.finish()
++
++
++if __name__ == '__main__':
++    main()
+diff --git a/specs/scripts/spec2api.py b/specs/scripts/spec2api.py
+index f21b08d5..7fb395a4 100755
+--- a/specs/scripts/spec2api.py
++++ b/specs/scripts/spec2api.py
+@@ -181,8 +181,8 @@ class SpecParser(LineParser):
+                 category = self.prefix.upper() + '_' + category
+             if category != self.category:
+                 if self.category is not None:
+-                    print
+-                print '    # %s' % category
++                    print()
++                print('    # %s' % category)
+                 self.category = category
+         if self.prefix == 'wgl':
+@@ -190,7 +190,7 @@ class SpecParser(LineParser):
+         else:
+             constructor = 'GlFunction'
+-        print '    %s(%s, "%s", [%s]%s),' % (constructor, ret_type, function_name, ', '.join(args), extra)
++        print('    %s(%s, "%s", [%s]%s),' % (constructor, ret_type, function_name, ', '.join(args), extra))
+     array_re = re.compile(r'^array\s+\[(.*)\]$')
+diff --git a/specs/scripts/txt2api.py b/specs/scripts/txt2api.py
+index 6cd99dd9..e9469d3c 100755
+--- a/specs/scripts/txt2api.py
++++ b/specs/scripts/txt2api.py
+@@ -31,7 +31,7 @@
+ import sys
+ import re
+ import optparse
+-from urllib2 import urlopen
++from urllib.request import urlopen
+ def stderr(x):
+@@ -116,7 +116,7 @@ class TxtParser(LineParser):
+                 self.consume()
+             line = self.consume()
+             self.parse_section(line)
+-        print
++        print()
+     def parse_section(self, name):
+         if name == 'Name Strings':
+@@ -136,7 +136,7 @@ class TxtParser(LineParser):
+             name = line.strip()
+             if name.startswith('EGL_'):
+                 self.prefix = ''
+-            print '    # %s' % name
++            print('    # %s' % name)
+     def skip_c_comments(self):
+         while not self.eof():
+@@ -192,7 +192,7 @@ class TxtParser(LineParser):
+             args.append(arg)
+             if self.tokens[0] == ',':
+                 self.tokens.pop(0)
+-        print '    GlFunction(%s, "%s", [%s]%s),' % (ret, name, ', '.join(args), extra)
++        print('    GlFunction(%s, "%s", [%s]%s),' % (ret, name, ', '.join(args), extra))
+     def parse_arg(self):
+         type = self.parse_type()
+diff --git a/specs/scripts/xml2api.py b/specs/scripts/xml2api.py
+index e3820e09..f09fe0bf 100755
+--- a/specs/scripts/xml2api.py
++++ b/specs/scripts/xml2api.py
+@@ -126,7 +126,7 @@ def processRequire(node, filterName):
+ def printPrototypes(prototypes, extensionName, functionNames, skip=set()):
+-    print '    # %s' % extensionName
++    print('    # %s' % extensionName)
+     if extensionName == 'GL_EXT_direct_state_access':
+         functionNames.sort()
+@@ -134,9 +134,9 @@ def printPrototypes(prototypes, extensionName, functionNames, skip=set()):
+     for functionName in functionNames:
+         if functionName not in skip:
+             prototype = prototypes[functionName]
+-            print '    %s,' % prototype
++            print('    %s,' % prototype)
+-    print
++    print()
+ def main():
+diff --git a/specs/scripts/xml2enum.py b/specs/scripts/xml2enum.py
+index 6d49e11c..cb2c4ae9 100755
+--- a/specs/scripts/xml2enum.py
++++ b/specs/scripts/xml2enum.py
+@@ -58,8 +58,8 @@ for arg in sys.argv[1:]:
+             params.setdefault(value, name)
+-    values = params.keys()
++    values = list(params.keys())
+     values.sort()
+     for value in values:
+         name = params[value]
+-        print '    "%s",\t\t# 0x%04X' % (name, value)
++        print('    "%s",\t\t# 0x%04X' % (name, value))
+diff --git a/specs/scripts/xml2glparams.py b/specs/scripts/xml2glparams.py
+index 7e2bc351..805aac86 100755
+--- a/specs/scripts/xml2glparams.py
++++ b/specs/scripts/xml2glparams.py
+@@ -58,8 +58,8 @@ for arg in sys.argv[1:]:
+             params.setdefault(value, name)
+-    values = params.keys()
++    values = list(params.keys())
+     values.sort()
+     for value in values:
+         name = params[value]
+-        print '    ("",\tX,\t1,\t"%s"),\t# 0x%04X' % (name, value)
++        print('    ("",\tX,\t1,\t"%s"),\t# 0x%04X' % (name, value))
+diff --git a/specs/stdapi.py b/specs/stdapi.py
+index c72c264b..487b6c1e 100644
+--- a/specs/stdapi.py
++++ b/specs/stdapi.py
+@@ -26,7 +26,9 @@
+ """C basic types"""
+-import debug
++import sys
++
++from . import debug
+ class Type:
+@@ -266,6 +268,10 @@ class Bitmask(Type):
+ Flags = Bitmask
++def EnumFlags(name, values):
++    return Flags(Alias(name, UInt), values)
++
++
+ class Array(Type):
+     def __init__(self, type_, length):
+@@ -273,7 +279,7 @@ class Array(Type):
+         self.type = type_
+         self.length = length
+         if not isinstance(length, int):
+-            assert isinstance(length, basestring)
++            assert isinstance(length, str)
+             # Check if length is actually a valid constant expression
+             try:
+                 eval(length, {}, {})
+@@ -329,6 +335,10 @@ class Struct(Type):
+     def visit(self, visitor, *args, **kwargs):
+         return visitor.visitStruct(self, *args, **kwargs)
++    def getMemberByName(self, name):
++        memberNames = [memberName for memberType, memberName in self.members]
++        return memberNames.index(name)
++
+ def Union(kindExpr, kindTypes, contextLess=True):
+     switchTypes = []
+@@ -372,7 +382,7 @@ def InOut(type, name):
+ class Function:
+-    def __init__(self, type, name, args, call = '', fail = None, sideeffects=True, internal=False):
++    def __init__(self, type, name, args, call = '', fail = None, sideeffects=True, internal=False, overloaded=False):
+         self.type = type
+         self.name = name
+@@ -394,6 +404,7 @@ class Function:
+         self.fail = fail
+         self.sideeffects = sideeffects
+         self.internal = internal
++        self.overloaded = overloaded
+     def prototype(self, name=None):
+         if name is not None:
+@@ -414,6 +425,17 @@ class Function:
+         s += ")"
+         return s
++    def sigName(self):
++        name = self.name
++        if self.overloaded:
++            # suffix used to make overloaded functions/methods unique
++            suffix = ','.join([str(arg.type) for arg in self.args])
++            suffix = suffix.replace(' *', '*')
++            suffix = suffix.replace(' &', '&')
++            suffix = '(' + suffix + ')'
++            name += suffix
++        return name
++
+     def argNames(self):
+         return [arg.name for arg in self.args]
+@@ -463,14 +485,12 @@ class Interface(Type):
+                 yield method
+         for method in self.methods:
+             yield method
+-        raise StopIteration
+     def iterBases(self):
+         iface = self
+         while iface is not None:
+             yield iface
+             iface = iface.base
+-        raise StopIteration
+     def hasBase(self, *bases):
+         for iface in self.iterBases():
+@@ -484,14 +504,13 @@ class Interface(Type):
+                 yield iface, method
+         for method in self.methods:
+             yield self, method
+-        raise StopIteration
+ class Method(Function):
+-    def __init__(self, type, name, args, call = '', const=False, sideeffects=True):
++    def __init__(self, type, name, args, call = '', const=False, sideeffects=True, overloaded=False):
+         assert call == '__stdcall'
+-        Function.__init__(self, type, name, args, call = call, sideeffects=sideeffects)
++        Function.__init__(self, type, name, args, call = call, sideeffects=sideeffects, overloaded=overloaded)
+         for index in range(len(self.args)):
+             self.args[index].index = index + 1
+         self.const = const
+@@ -576,7 +595,7 @@ class Polymorphic(Type):
+             else:
+                 cases[i].append(case)
+-        return zip(cases, types)
++        return list(zip(cases, types))
+ def EnumPolymorphic(enumName, switchExpr, switchTypes, defaultType, contextLess=True):
+@@ -734,7 +753,7 @@ class Rebuilder(Visitor):
+         if pointer_type is pointer.type:
+             return pointer
+         else:
+-            return LinearPointer(pointer_type)
++            return LinearPointer(pointer_type, self.size)
+     def visitReference(self, reference):
+         reference_type = self.visit(reference.type)
+@@ -792,7 +811,7 @@ class MutableRebuilder(Rebuilder):
+     def visitReference(self, reference):
+         # Strip out references
+-        return reference.type
++        return self.visit(reference.type)
+ class Traverser(Visitor):
+@@ -894,7 +913,7 @@ class ExpanderMixin:
+     def expand(self, expr):
+         # Expand a C expression, replacing certain variables
+-        if not isinstance(expr, basestring):
++        if not isinstance(expr, str):
+             return expr
+         variables = {}
+diff --git a/specs/wglapi.py b/specs/wglapi.py
+index f24a8d21..563f0269 100644
+--- a/specs/wglapi.py
++++ b/specs/wglapi.py
+@@ -27,9 +27,9 @@
+ """WGL API description"""
+-from glapi import *
+-from winapi import *
+-from wglenum import *
++from .glapi import *
++from .winapi import *
++from .wglenum import *
+ wglapi = Module("WGL")
+diff --git a/specs/wglenum.py b/specs/wglenum.py
+index ad9bbccf..6bc4e74d 100644
+--- a/specs/wglenum.py
++++ b/specs/wglenum.py
+@@ -27,7 +27,7 @@
+ """WGL enum description"""
+-from stdapi import *
++from .stdapi import *
+ WGLenum = FakeEnum(Int, [
+     "WGL_GPU_VENDOR_AMD",             # 0x1F00
+diff --git a/specs/winapi.py b/specs/winapi.py
+index 445039ff..e66d063a 100644
+--- a/specs/winapi.py
++++ b/specs/winapi.py
+@@ -26,7 +26,7 @@
+ """Win32 API type description."""
+-from stdapi import *
++from .stdapi import *
+ SHORT = Alias("SHORT", Short)
+diff --git a/wrappers/CMakeLists.txt b/wrappers/CMakeLists.txt
+index 2ceac332..7a452ed4 100644
+--- a/wrappers/CMakeLists.txt
++++ b/wrappers/CMakeLists.txt
+@@ -79,7 +79,7 @@ if (WIN32)
+         include_directories (BEFORE SYSTEM ${DirectX_D3D_INCLUDE_DIR})
+         add_custom_command (
+             OUTPUT ddrawtrace.cpp
+-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/ddrawtrace.py > ${CMAKE_CURRENT_BINARY_DIR}/ddrawtrace.cpp
++            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/ddrawtrace.py > ${CMAKE_CURRENT_BINARY_DIR}/ddrawtrace.cpp
+             DEPENDS
+                 ddrawtrace.py
+                 dlltrace.py
+@@ -109,7 +109,7 @@ if (WIN32)
+         include_directories (BEFORE SYSTEM ${DirectX_D3D9_INCLUDE_DIR} ${DirectX_D3D8_INCLUDE_DIR})
+         add_custom_command (
+             OUTPUT d3d8trace.cpp
+-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d8trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d8trace.cpp
++            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d8trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d8trace.cpp
+             DEPENDS
+                 d3d8trace.py
+                 dlltrace.py
+@@ -143,7 +143,7 @@ if (WIN32)
+         include_directories (BEFORE SYSTEM ${DirectX_D3D9_INCLUDE_DIR})
+         add_custom_command (
+             OUTPUT d3d9trace.cpp
+-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d9trace.cpp
++            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d9trace.cpp
+             DEPENDS
+                 d3d9trace.py
+                 dlltrace.py
+@@ -179,7 +179,7 @@ if (WIN32)
+         add_custom_command (
+             OUTPUT dxgitrace.cpp
+-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgitrace.py > ${CMAKE_CURRENT_BINARY_DIR}/dxgitrace.cpp
++            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgitrace.py > ${CMAKE_CURRENT_BINARY_DIR}/dxgitrace.cpp
+             DEPENDS
+                 dxgitrace.py
+                 dlltrace.py
+@@ -216,7 +216,7 @@ if (WIN32)
+         add_custom_command (
+             OUTPUT d2d1trace.cpp
+-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d2d1trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d2d1trace.cpp
++            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d2d1trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d2d1trace.cpp
+             DEPENDS
+                 d2d1trace.py
+                 trace.py
+@@ -241,7 +241,7 @@ if (WIN32)
+     # opengl32.dll
+     add_custom_command (
+         OUTPUT wgltrace.cpp
+-        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wgltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/wgltrace.cpp
++        COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wgltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/wgltrace.cpp
+         DEPENDS
+                 wgltrace.py
+                 gltrace.py
+@@ -278,7 +278,7 @@ elseif (APPLE)
+     # OpenGL framework
+     add_custom_command (
+         OUTPUT cgltrace.cpp
+-        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/cgltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/cgltrace.cpp
++        COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/cgltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/cgltrace.cpp
+         DEPENDS
+             cgltrace.py
+             gltrace.py
+@@ -322,7 +322,7 @@ elseif (X11_FOUND)
+     # libGL.so
+     add_custom_command (
+         OUTPUT glxtrace.cpp
+-        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glxtrace.py > ${CMAKE_CURRENT_BINARY_DIR}/glxtrace.cpp
++        COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glxtrace.py > ${CMAKE_CURRENT_BINARY_DIR}/glxtrace.cpp
+         DEPENDS
+             glxtrace.py
+             gltrace.py
+@@ -372,7 +372,7 @@ if (ENABLE_EGL AND NOT WIN32 AND NOT APPLE)
+     # libEGL.so/libGL.so
+     add_custom_command (
+         OUTPUT egltrace.cpp
+-        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/egltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/egltrace.cpp
++        COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/egltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/egltrace.cpp
+         DEPENDS
+             egltrace.py
+             gltrace.py
+diff --git a/wrappers/cgltrace.py b/wrappers/cgltrace.py
+index 6c72f696..02b3c518 100644
+--- a/wrappers/cgltrace.py
++++ b/wrappers/cgltrace.py
+@@ -43,55 +43,55 @@ class CglTracer(GlTracer):
+         if function.name == 'CGLReleaseContext':
+             # Unlike other GL APIs like EGL or GLX, CGL will make the context
+             # not current if it's the current context.
+-            print '    if (_CGLGetContextRetainCount(ctx) == 1) {'
+-            print '        if (gltrace::releaseContext((uintptr_t)ctx)) {'
+-            print '            if (_CGLGetCurrentContext() == ctx) {'
+-            print '                gltrace::clearContext();'
+-            print '            }'
+-            print '        }'
+-            print '    }'
++            print('    if (_CGLGetContextRetainCount(ctx) == 1) {')
++            print('        if (gltrace::releaseContext((uintptr_t)ctx)) {')
++            print('            if (_CGLGetCurrentContext() == ctx) {')
++            print('                gltrace::clearContext();')
++            print('            }')
++            print('        }')
++            print('    }')
+         if function.name == 'CGLDestroyContext':
+             # The same rule applies here about the  as for CGLReleaseContext.
+-            print '    if (gltrace::releaseContext((uintptr_t)ctx)) {'
+-            print '        if (_CGLGetCurrentContext() == ctx) {'
+-            print '            gltrace::clearContext();'
+-            print '        }'
+-            print '    }'
++            print('    if (gltrace::releaseContext((uintptr_t)ctx)) {')
++            print('        if (_CGLGetCurrentContext() == ctx) {')
++            print('            gltrace::clearContext();')
++            print('        }')
++            print('    }')
+         GlTracer.traceFunctionImplBody(self, function)
+         if function.name == 'CGLCreateContext':
+-            print '    if (_result == kCGLNoError) {'
+-            print '        gltrace::createContext((uintptr_t)*ctx);'
+-            print '    }'
++            print('    if (_result == kCGLNoError) {')
++            print('        gltrace::createContext((uintptr_t)*ctx);')
++            print('    }')
+         if function.name == 'CGLSetCurrentContext':
+-            print '    if (_result == kCGLNoError) {'
+-            print '        if (ctx != NULL) {'
+-            print '            gltrace::setContext((uintptr_t)ctx);'
+-            print '        } else {'
+-            print '            gltrace::clearContext();'
+-            print '        }'
+-            print '    }'
++            print('    if (_result == kCGLNoError) {')
++            print('        if (ctx != NULL) {')
++            print('            gltrace::setContext((uintptr_t)ctx);')
++            print('        } else {')
++            print('            gltrace::clearContext();')
++            print('        }')
++            print('    }')
+         if function.name == 'CGLRetainContext':
+-            print '    gltrace::retainContext((uintptr_t)ctx);'
++            print('    gltrace::retainContext((uintptr_t)ctx);')
+ if __name__ == '__main__':
+-    print
+-    print '#include <stdlib.h>'
+-    print '#include <string.h>'
+-    print
+-    print '#include "trace_writer_local.hpp"'
+-    print
+-    print '// To validate our prototypes'
+-    print '#define GL_GLEXT_PROTOTYPES'
+-    print
+-    print '#include "glproc.hpp"'
+-    print '#include "glsize.hpp"'
+-    print
++    print()
++    print('#include <stdlib.h>')
++    print('#include <string.h>')
++    print()
++    print('#include "trace_writer_local.hpp"')
++    print()
++    print('// To validate our prototypes')
++    print('#define GL_GLEXT_PROTOTYPES')
++    print()
++    print('#include "glproc.hpp"')
++    print('#include "glsize.hpp"')
++    print()
+     module = Module()
+     module.mergeModule(cglapi)
+@@ -101,7 +101,7 @@ if __name__ == '__main__':
+     tracer = CglTracer()
+     tracer.traceApi(api)
+-    print r'''
++    print(r'''
+ PUBLIC
+ void * gll_noop = 0;
+@@ -130,4 +130,4 @@ _init(void) {
+     setenv("SDL_OPENGL_LIBRARY", "/System/Library/Frameworks/OpenGL.framework/OpenGL", 1);
+ }
+-'''
++''')
+diff --git a/wrappers/d2d1trace.py b/wrappers/d2d1trace.py
+index 26223005..2176341f 100644
+--- a/wrappers/d2d1trace.py
++++ b/wrappers/d2d1trace.py
+@@ -31,15 +31,15 @@ from specs.d2d1 import d2d1
+ if __name__ == '__main__':
+-    print '#include "guids_defs.hpp"'
+-    print
+-    print '#include "trace_writer_local.hpp"'
+-    print '#include "os.hpp"'
+-    print
+-    print '#define DWRITE_EXPORT WINAPI'
+-    print
+-    print '#include "d2dimports.hpp"'
+-    print
++    print('#include "guids_defs.hpp"')
++    print()
++    print('#include "trace_writer_local.hpp"')
++    print('#include "os.hpp"')
++    print()
++    print('#define DWRITE_EXPORT WINAPI')
++    print()
++    print('#include "d2dimports.hpp"')
++    print()
+     api = API()
+     api.addModule(d2d1)
+diff --git a/wrappers/d3d8trace.py b/wrappers/d3d8trace.py
+index 2903c48f..11afbca5 100644
+--- a/wrappers/d3d8trace.py
++++ b/wrappers/d3d8trace.py
+@@ -34,7 +34,7 @@ class D3D8Tracer(DllTracer):
+     def serializeArgValue(self, function, arg):
+         # Dump shaders as strings
+         if arg.type is D3DSHADER8:
+-            print '    DumpShader(trace::localWriter, %s);' % (arg.name)
++            print('    DumpShader(trace::localWriter, %s);' % (arg.name))
+             return
+         DllTracer.serializeArgValue(self, function, arg)
+@@ -55,32 +55,32 @@ class D3D8Tracer(DllTracer):
+     def implementWrapperInterfaceMethodBody(self, interface, base, method):
+         if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'):
+-            print '    if (_MappedSize && m_pbData) {'
++            print('    if (_MappedSize && m_pbData) {')
+             self.emit_memcpy('(LPBYTE)m_pbData', '_MappedSize')
+-            print '    }'
++            print('    }')
+         DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method)
+         if method.name in ('Lock', 'LockRect', 'LockBox'):
+             # FIXME: handle recursive locks
+-            print '    if (SUCCEEDED(_result) && !(Flags & D3DLOCK_READONLY)) {'
+-            print '        _getMapInfo(_this, %s, m_pbData, _MappedSize);' % ', '.join(method.argNames()[:-1])
+-            print '    } else {'
+-            print '        m_pbData = NULL;'
+-            print '        _MappedSize = 0;'
+-            print '    }'
++            print('    if (SUCCEEDED(_result) && !(Flags & D3DLOCK_READONLY)) {')
++            print('        _getMapInfo(_this, %s, m_pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]))
++            print('    } else {')
++            print('        m_pbData = NULL;')
++            print('        _MappedSize = 0;')
++            print('    }')
+ if __name__ == '__main__':
+-    print '#define INITGUID'
+-    print
+-    print '#include "trace_writer_local.hpp"'
+-    print '#include "os.hpp"'
+-    print
+-    print '#include "d3d8imports.hpp"'
+-    print '#include "d3d8size.hpp"'
+-    print '#include "d3d9shader.hpp"'
+-    print
++    print('#define INITGUID')
++    print()
++    print('#include "trace_writer_local.hpp"')
++    print('#include "os.hpp"')
++    print()
++    print('#include "d3d8imports.hpp"')
++    print('#include "d3d8size.hpp"')
++    print('#include "d3d9shader.hpp"')
++    print()
+     api = API()
+     api.addModule(d3d8)
+diff --git a/wrappers/d3d9trace.py b/wrappers/d3d9trace.py
+index 0850ba3e..53d5152f 100644
+--- a/wrappers/d3d9trace.py
++++ b/wrappers/d3d9trace.py
+@@ -35,7 +35,7 @@ class D3D9Tracer(DllTracer):
+     def serializeArgValue(self, function, arg):
+         # Dump shaders as strings
+         if arg.type is D3DSHADER9:
+-            print '    DumpShader(trace::localWriter, %s);' % (arg.name)
++            print('    DumpShader(trace::localWriter, %s);' % (arg.name))
+             return
+         DllTracer.serializeArgValue(self, function, arg)
+@@ -72,49 +72,49 @@ class D3D9Tracer(DllTracer):
+     def implementWrapperInterfaceMethodBody(self, interface, base, method):
+         if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'):
+             if interface.name in ['IDirect3DTexture9']:
+-                print '    std::map<UINT, std::pair<size_t, VOID *> >::iterator it = _MappedData.find(Level);'
+-                print '    if (it != _MappedData.end()) {'
++                print('    std::map<UINT, std::pair<size_t, VOID *> >::iterator it = _MappedData.find(Level);')
++                print('    if (it != _MappedData.end()) {')
+                 self.emit_memcpy('(LPBYTE)it->second.second', 'it->second.first')
+-                print '        _MappedData.erase(it);'
+-                print '    }'
++                print('        _MappedData.erase(it);')
++                print('    }')
+             else:
+-                print '    if (_MappedSize && m_pbData) {'
++                print('    if (_MappedSize && m_pbData) {')
+                 self.emit_memcpy('(LPBYTE)m_pbData', '_MappedSize')
+-                print '    }'
++                print('    }')
+         DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method)
+         if method.name in ('Lock', 'LockRect', 'LockBox'):
+             if interface.name in ['IDirect3DTexture9']:
+-                print '    if (SUCCEEDED(_result) && !(Flags & D3DLOCK_READONLY)) {'
+-                print '        size_t mappedSize;'
+-                print '        VOID * pbData;'
+-                print '        _getMapInfo(_this, %s, pbData, mappedSize);' % ', '.join(method.argNames()[:-1])
+-                print '        _MappedData[Level] = std::make_pair(mappedSize, pbData);'
+-                print '    } else {'
+-                print '        _MappedData.erase(Level);'
+-                print '    }'
++                print('    if (SUCCEEDED(_result) && !(Flags & D3DLOCK_READONLY)) {')
++                print('        size_t mappedSize;')
++                print('        VOID * pbData;')
++                print('        _getMapInfo(_this, %s, pbData, mappedSize);' % ', '.join(method.argNames()[:-1]))
++                print('        _MappedData[Level] = std::make_pair(mappedSize, pbData);')
++                print('    } else {')
++                print('        _MappedData.erase(Level);')
++                print('    }')
+             else:
+                 # FIXME: handle recursive locks
+-                print '    if (SUCCEEDED(_result) && !(Flags & D3DLOCK_READONLY)) {'
+-                print '        _getMapInfo(_this, %s, m_pbData, _MappedSize);' % ', '.join(method.argNames()[:-1])
+-                print '    } else {'
+-                print '        m_pbData = NULL;'
+-                print '        _MappedSize = 0;'
+-                print '    }'
++                print('    if (SUCCEEDED(_result) && !(Flags & D3DLOCK_READONLY)) {')
++                print('        _getMapInfo(_this, %s, m_pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]))
++                print('    } else {')
++                print('        m_pbData = NULL;')
++                print('        _MappedSize = 0;')
++                print('    }')
+ if __name__ == '__main__':
+-    print '#define INITGUID'
+-    print
+-    print '#include "trace_writer_local.hpp"'
+-    print '#include "os.hpp"'
+-    print
+-    print '#include "d3d9imports.hpp"'
+-    print '#include "d3d9size.hpp"'
+-    print '#include "d3d9shader.hpp"'
+-    print '#include "dxva2imports.hpp"'
+-    print
++    print('#define INITGUID')
++    print()
++    print('#include "trace_writer_local.hpp"')
++    print('#include "os.hpp"')
++    print()
++    print('#include "d3d9imports.hpp"')
++    print('#include "d3d9size.hpp"')
++    print('#include "d3d9shader.hpp"')
++    print('#include "dxva2imports.hpp"')
++    print()
+     d3d9.mergeModule(d3dperf)
+diff --git a/wrappers/ddrawtrace.py b/wrappers/ddrawtrace.py
+index 96602d21..da7ffbe7 100644
+--- a/wrappers/ddrawtrace.py
++++ b/wrappers/ddrawtrace.py
+@@ -41,12 +41,12 @@ class DDrawTracer(DllTracer):
+ if __name__ == '__main__':
+-    print '#define INITGUID'
+-    print '#include "d3dimports.hpp"'
+-    print '#include "trace_writer_local.hpp"'
+-    print '#include "d3d7size.hpp"'
+-    print '#include "os.hpp"'
+-    print
++    print('#define INITGUID')
++    print('#include "d3dimports.hpp"')
++    print('#include "trace_writer_local.hpp"')
++    print('#include "d3d7size.hpp"')
++    print('#include "os.hpp"')
++    print()
+     api = API()
+     api.addModule(ddraw)
+diff --git a/wrappers/dlltrace.py b/wrappers/dlltrace.py
+index 26962216..8ac18b0c 100644
+--- a/wrappers/dlltrace.py
++++ b/wrappers/dlltrace.py
+@@ -37,24 +37,24 @@ class DllDispatcher(Dispatcher):
+     def dispatchModule(self, module):
+         tag = module.name.upper()
+-        print r'HMODULE g_h%sModule = NULL;' % (tag,)
+-        print r''
+-        print r'static PROC'
+-        print r'_get%sProcAddress(LPCSTR lpProcName) {' % tag
+-        print r'    if (!g_h%sModule) {' % tag
+-        print r'        char szDll[MAX_PATH] = {0};'
+-        print r'        if (!GetSystemDirectoryA(szDll, MAX_PATH)) {'
+-        print r'            return NULL;'
+-        print r'        }'
+-        print r'        strcat(szDll, "\\%s.dll");' % module.name
+-        print r'        g_h%sModule = LoadLibraryA(szDll);' % tag
+-        print r'        if (!g_h%sModule) {' % tag
+-        print r'            return NULL;'
+-        print r'        }'
+-        print r'    }'
+-        print r'    return GetProcAddress(g_h%sModule, lpProcName);' % tag
+-        print r'}'
+-        print r''
++        print(r'HMODULE g_h%sModule = NULL;' % (tag,))
++        print(r'')
++        print(r'static PROC')
++        print(r'_get%sProcAddress(LPCSTR lpProcName) {' % tag)
++        print(r'    if (!g_h%sModule) {' % tag)
++        print(r'        char szDll[MAX_PATH] = {0};')
++        print(r'        if (!GetSystemDirectoryA(szDll, MAX_PATH)) {')
++        print(r'            return NULL;')
++        print(r'        }')
++        print(r'        strcat(szDll, "\\%s.dll");' % module.name)
++        print(r'        g_h%sModule = LoadLibraryA(szDll);' % tag)
++        print(r'        if (!g_h%sModule) {' % tag)
++        print(r'            return NULL;')
++        print(r'        }')
++        print(r'    }')
++        print(r'    return GetProcAddress(g_h%sModule, lpProcName);' % tag)
++        print(r'}')
++        print(r'')
+         Dispatcher.dispatchModule(self, module)
+diff --git a/wrappers/dxgitrace.py b/wrappers/dxgitrace.py
+index 3edda2c2..134f45d7 100644
+--- a/wrappers/dxgitrace.py
++++ b/wrappers/dxgitrace.py
+@@ -40,47 +40,47 @@ class D3DCommonTracer(DllTracer):
+     def serializeArgValue(self, function, arg):
+         # Dump shaders as strings
+         if isinstance(arg.type, stdapi.Blob) and arg.name.startswith('pShaderBytecode'):
+-            print '    DumpShader(trace::localWriter, %s, %s);' % (arg.name, arg.type.size)
++            print('    DumpShader(trace::localWriter, %s, %s);' % (arg.name, arg.type.size))
+             return
+         # Serialize the swapchain dimensions
+         if function.name == 'CreateSwapChain' and arg.name == 'pDesc' \
+            or arg.name == 'pSwapChainDesc':
+-            print r'    DXGI_SWAP_CHAIN_DESC *_pSwapChainDesc = NULL;'
+-            print r'    DXGI_SWAP_CHAIN_DESC _SwapChainDesc;'
+-            print r'    if (%s) {' % arg.name
+-            print r'        _SwapChainDesc = *%s;' % arg.name
++            print(r'    DXGI_SWAP_CHAIN_DESC *_pSwapChainDesc = NULL;')
++            print(r'    DXGI_SWAP_CHAIN_DESC _SwapChainDesc;')
++            print(r'    if (%s) {' % arg.name)
++            print(r'        _SwapChainDesc = *%s;' % arg.name)
+             if function.name != 'CreateSwapChain' or not self.interface.name.endswith('DWM'):
+                 # Obtain size from the window
+-                print r'        RECT _rect;'
+-                print r'        if (GetClientRect(%s->OutputWindow, &_rect)) {' % arg.name
+-                print r'            if (%s->BufferDesc.Width == 0) {' % arg.name
+-                print r'                _SwapChainDesc.BufferDesc.Width = _rect.right  - _rect.left;'
+-                print r'            }'
+-                print r'            if (%s->BufferDesc.Height == 0) {' % arg.name
+-                print r'                _SwapChainDesc.BufferDesc.Height = _rect.bottom - _rect.top;'
+-                print r'            }'
+-                print r'        }'
++                print(r'        RECT _rect;')
++                print(r'        if (GetClientRect(%s->OutputWindow, &_rect)) {' % arg.name)
++                print(r'            if (%s->BufferDesc.Width == 0) {' % arg.name)
++                print(r'                _SwapChainDesc.BufferDesc.Width = _rect.right  - _rect.left;')
++                print(r'            }')
++                print(r'            if (%s->BufferDesc.Height == 0) {' % arg.name)
++                print(r'                _SwapChainDesc.BufferDesc.Height = _rect.bottom - _rect.top;')
++                print(r'            }')
++                print(r'        }')
+             else:
+                 # Obtain size from the output
+-                print r'        DXGI_OUTPUT_DESC _OutputDesc;'
+-                print r'        if (SUCCEEDED(pOutput->GetDesc(&_OutputDesc))) {'
+-                print r'            _SwapChainDesc.BufferDesc.Width  = _OutputDesc.DesktopCoordinates.right  - _OutputDesc.DesktopCoordinates.left;'
+-                print r'            _SwapChainDesc.BufferDesc.Height = _OutputDesc.DesktopCoordinates.bottom - _OutputDesc.DesktopCoordinates.top;'
+-                print r'        }'
+-            print r'        _pSwapChainDesc = &_SwapChainDesc;'
+-            print r'    }'
++                print(r'        DXGI_OUTPUT_DESC _OutputDesc;')
++                print(r'        if (SUCCEEDED(pOutput->GetDesc(&_OutputDesc))) {')
++                print(r'            _SwapChainDesc.BufferDesc.Width  = _OutputDesc.DesktopCoordinates.right  - _OutputDesc.DesktopCoordinates.left;')
++                print(r'            _SwapChainDesc.BufferDesc.Height = _OutputDesc.DesktopCoordinates.bottom - _OutputDesc.DesktopCoordinates.top;')
++                print(r'        }')
++            print(r'        _pSwapChainDesc = &_SwapChainDesc;')
++            print(r'    }')
+             self.serializeValue(arg.type, '_pSwapChainDesc')
+             return
+         # Serialize object names
+         if function.name == 'SetPrivateData' and arg.name == 'pData':
+             iid = function.args[0].name
+-            print r'    if (%s == WKPDID_D3DDebugObjectName) {' % iid
+-            print r'        trace::localWriter.writeString(static_cast<const char *>(pData), DataSize);'
+-            print r'    } else {'
++            print(r'    if (%s == WKPDID_D3DDebugObjectName) {' % iid)
++            print(r'        trace::localWriter.writeString(static_cast<const char *>(pData), DataSize);')
++            print(r'    } else {')
+             DllTracer.serializeArgValue(self, function, arg)
+-            print r'    }'
++            print(r'    }')
+             return
+         DllTracer.serializeArgValue(self, function, arg)
+@@ -110,47 +110,47 @@ class D3DCommonTracer(DllTracer):
+         if method.getArgByName('pInitialData'):
+             pDesc1 = method.getArgByName('pDesc1')
+             if pDesc1 is not None:
+-                print r'    %s pDesc = pDesc1;' % (pDesc1.type,)
++                print(r'    %s pDesc = pDesc1;' % (pDesc1.type,))
+         if method.name in ('Map', 'Unmap'):
+             # On D3D11 Map/Unmap is not a resource method, but a context method instead.
+             resourceArg = method.getArgByName('pResource')
+             if resourceArg is None:
+-                print '    _MAP_DESC & _MapDesc = m_MapDesc;'
++                print('    _MAP_DESC & _MapDesc = m_MapDesc;')
+             else:
+-                print '    _MAP_DESC & _MapDesc = m_MapDescs[std::pair<%s, UINT>(pResource, Subresource)];' % resourceArg.type
++                print('    _MAP_DESC & _MapDesc = m_MapDescs[std::pair<%s, UINT>(pResource, Subresource)];' % resourceArg.type)
+         if method.name == 'Unmap':
+-            print '    if (_MapDesc.Size && _MapDesc.pData) {'
++            print('    if (_MapDesc.Size && _MapDesc.pData) {')
+             self.emit_memcpy('_MapDesc.pData', '_MapDesc.Size')
+-            print '    }'
++            print('    }')
+         DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method)
+         if method.name == 'Map':
+             # NOTE: recursive locks are explicitely forbidden
+-            print '    if (SUCCEEDED(_result)) {'
+-            print '        _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames())
+-            print '    } else {'
+-            print '        _MapDesc.pData = NULL;'
+-            print '        _MapDesc.Size = 0;'
+-            print '    }'
++            print('    if (SUCCEEDED(_result)) {')
++            print('        _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames()))
++            print('    } else {')
++            print('        _MapDesc.pData = NULL;')
++            print('        _MapDesc.Size = 0;')
++            print('    }')
+ if __name__ == '__main__':
+-    print r'#define INITGUID'
+-    print
+-    print r'#include "trace_writer_local.hpp"'
+-    print r'#include "os.hpp"'
+-    print
+-    print r'#include "d3dcommonshader.hpp"'
+-    print
+-    print r'#include "d3d10imports.hpp"'
+-    print r'#include "d3d10size.hpp"'
+-    print r'#include "d3d11imports.hpp"'
+-    print r'#include "d3d11size.hpp"'
+-    print r'#include "d3d9imports.hpp" // D3DPERF_*'
+-    print
++    print(r'#define INITGUID')
++    print()
++    print(r'#include "trace_writer_local.hpp"')
++    print(r'#include "os.hpp"')
++    print()
++    print(r'#include "d3dcommonshader.hpp"')
++    print()
++    print(r'#include "d3d10imports.hpp"')
++    print(r'#include "d3d10size.hpp"')
++    print(r'#include "d3d11imports.hpp"')
++    print(r'#include "d3d11size.hpp"')
++    print(r'#include "d3d9imports.hpp" // D3DPERF_*')
++    print()
+     api = API()
+     api.addModule(dxgi.dxgi)
+diff --git a/wrappers/egltrace.py b/wrappers/egltrace.py
+index 1fcb0fd6..f5b61c0c 100644
+--- a/wrappers/egltrace.py
++++ b/wrappers/egltrace.py
+@@ -50,239 +50,239 @@ class EglTracer(GlTracer):
+     def traceFunctionImplBody(self, function):
+         if function.name == 'glTexDirectMapVIV':
+-            print '    // prevent loop call'
+-            print '    glTexDirectVIVMap(target, width, height, format, Logical, Physical);'
++            print('    // prevent loop call')
++            print('    glTexDirectVIVMap(target, width, height, format, Logical, Physical);')
+             return
+         if function.name == 'glTexDirectInvalidateVIV':
+-            print '    // get current texture'
+-            print '    GLint tex = 0;'
+-            print '    int32_t size = 0;'
+-            print '    int32_t ysize = 0;'
+-            print '    int32_t usize = 0;'
+-            print '    int32_t vsize = 0;'
+-            print '    _glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);'
+-            print '    if(tex == 0)'
+-            print '    {'
+-            print '        return;'
+-            print '    }'
+-            print '    TEXDIRECTVIVDATA &data = _directTextureDataMap[tex];'
+-            print '    switch(data.format){'
+-            print '    case GL_VIV_YV12:'
+-            print '    case GL_VIV_I420:'
+-            print '        ysize=data.width * data.height;'
+-            print '        usize=ysize/4;'
+-            print '        vsize=usize;'
+-            print '        break;'
+-            print '    case GL_VIV_NV12:'
+-            print '    case GL_VIV_NV21:'
+-            print '        ysize=data.width * data.height;'
+-            print '        usize=ysize/2;'
+-            print '        vsize=0;'
+-            print '        break;'
+-            print '    case GL_RGBA:'
+-            print '    case GL_BGRA_EXT:'
+-            print '        ysize=data.width * data.height *4;'
+-            print '        usize=0;'
+-            print '        vsize=0;'
+-            print '        break;'
+-            print '    case GL_RGB:'
+-            print '        ysize=data.width * data.height *3;'
+-            print '        usize=0;'
+-            print '        vsize=0;'
+-            print '        break;'
+-            print '    case GL_VIV_YUY2:'
+-            print '    case GL_VIV_UYVY:'
+-            print '    case GL_RGB565_OES:'
+-            print '    case GL_LUMINANCE8_ALPHA8_EXT:'
+-            print '        ysize=data.width * data.height *2;'
+-            print '        usize=0;'
+-            print '        vsize=0;'
+-            print '        break;'
+-            print '    case GL_ALPHA:'
+-            print '        ysize=data.width * data.height;'
+-            print '        usize=0;'
+-            print '        vsize=0;'
+-            print '        break;'
+-            print '    default:'
+-            print '        return;'
+-            print '    }'
+-            print '    if (NULL==(GLvoid*)data.logical) {'
+-            print '        if (ysize > 0) {'
++            print('    // get current texture')
++            print('    GLint tex = 0;')
++            print('    int32_t size = 0;')
++            print('    int32_t ysize = 0;')
++            print('    int32_t usize = 0;')
++            print('    int32_t vsize = 0;')
++            print('    _glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);')
++            print('    if(tex == 0)')
++            print('    {')
++            print('        return;')
++            print('    }')
++            print('    TEXDIRECTVIVDATA &data = _directTextureDataMap[tex];')
++            print('    switch(data.format){')
++            print('    case GL_VIV_YV12:')
++            print('    case GL_VIV_I420:')
++            print('        ysize=data.width * data.height;')
++            print('        usize=ysize/4;')
++            print('        vsize=usize;')
++            print('        break;')
++            print('    case GL_VIV_NV12:')
++            print('    case GL_VIV_NV21:')
++            print('        ysize=data.width * data.height;')
++            print('        usize=ysize/2;')
++            print('        vsize=0;')
++            print('        break;')
++            print('    case GL_RGBA:')
++            print('    case GL_BGRA_EXT:')
++            print('        ysize=data.width * data.height *4;')
++            print('        usize=0;')
++            print('        vsize=0;')
++            print('        break;')
++            print('    case GL_RGB:')
++            print('        ysize=data.width * data.height *3;')
++            print('        usize=0;')
++            print('        vsize=0;')
++            print('        break;')
++            print('    case GL_VIV_YUY2:')
++            print('    case GL_VIV_UYVY:')
++            print('    case GL_RGB565_OES:')
++            print('    case GL_LUMINANCE8_ALPHA8_EXT:')
++            print('        ysize=data.width * data.height *2;')
++            print('        usize=0;')
++            print('        vsize=0;')
++            print('        break;')
++            print('    case GL_ALPHA:')
++            print('        ysize=data.width * data.height;')
++            print('        usize=0;')
++            print('        vsize=0;')
++            print('        break;')
++            print('    default:')
++            print('        return;')
++            print('    }')
++            print('    if (NULL==(GLvoid*)data.logical) {')
++            print('        if (ysize > 0) {')
+             self.emit_memcpy_opt('(GLvoid*)data.planes[0]', 'ysize')
+-            print '         }'
+-            print '        if (usize > 0) {'
++            print('         }')
++            print('        if (usize > 0) {')
+             self.emit_memcpy_opt('(GLvoid*)data.planes[1]', 'usize')
+-            print '         }'
+-            print '        if (vsize > 0) {'
++            print('         }')
++            print('        if (vsize > 0) {')
+             self.emit_memcpy_opt('(GLvoid*)data.planes[2]', 'vsize')
+-            print '         }'
+-            print '    } else {'
+-            print '        size = ysize + usize + vsize;'
+-            print '        if (size > 0) {'
++            print('         }')
++            print('    } else {')
++            print('        size = ysize + usize + vsize;')
++            print('        if (size > 0) {')
+             self.emit_memcpy_opt('(GLvoid*)data.logical', 'size')
+-            print '         }'
+-            print '    }'
++            print('         }')
++            print('    }')
+         if function.name == 'eglGetProcAddress':
+-            print '    procname = __get_alias_func_name(procname);'
++            print('    procname = __get_alias_func_name(procname);')
+         GlTracer.traceFunctionImplBody(self, function)
+         if function.name == 'glTexDirectVIV':
+-            print '    // get current texture'
+-            print '    GLint tex = 0;'
+-            print '    _glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);'
+-            print '    if(tex != 0)'
+-            print '    {'
+-            print '        TEXDIRECTVIVDATA &data = _directTextureDataMap[tex];'
+-            print '        data.width = width;'
+-            print '        data.height = height;'
+-            print '        data.format = format;'
+-            print '        data.planes[0] = pixels[0];'
+-            print '        data.planes[1] = pixels[1];'
+-            print '        data.planes[2] = pixels[2];'
+-            print '    }'
++            print('    // get current texture')
++            print('    GLint tex = 0;')
++            print('    _glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);')
++            print('    if(tex != 0)')
++            print('    {')
++            print('        TEXDIRECTVIVDATA &data = _directTextureDataMap[tex];')
++            print('        data.width = width;')
++            print('        data.height = height;')
++            print('        data.format = format;')
++            print('        data.planes[0] = pixels[0];')
++            print('        data.planes[1] = pixels[1];')
++            print('        data.planes[2] = pixels[2];')
++            print('    }')
+         if function.name == 'glTexDirectVIVMap' or function.name == 'glTexDirectTiledMapVIV':
+-            print '    // get current texture'
+-            print '    GLint tex = 0;'
+-            print '    _glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);'
+-            print '    if(tex != 0)'
+-            print '    {'
+-            print '        TEXDIRECTVIVDATA &data = _directTextureDataMap[tex];'
+-            print '        data.width = width;'
+-            print '        data.height = height;'
+-            print '        data.format = format;'
+-            print '        data.logical = *Logical; // Logical != NULL'
+-            print '        data.physical = *Physical;'
+-            print '    }'
++            print('    // get current texture')
++            print('    GLint tex = 0;')
++            print('    _glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);')
++            print('    if(tex != 0)')
++            print('    {')
++            print('        TEXDIRECTVIVDATA &data = _directTextureDataMap[tex];')
++            print('        data.width = width;')
++            print('        data.height = height;')
++            print('        data.format = format;')
++            print('        data.logical = *Logical; // Logical != NULL')
++            print('        data.physical = *Physical;')
++            print('    }')
+         if function.name == 'eglCreateContext':
+-            print '    if (_result != EGL_NO_CONTEXT)'
+-            print '        gltrace::createContext((uintptr_t)_result);'
++            print('    if (_result != EGL_NO_CONTEXT)')
++            print('        gltrace::createContext((uintptr_t)_result);')
+         if function.name == 'eglMakeCurrent':
+-            print r'    if (_result) {'
+-            print r'        // update the profile'
+-            print r'        if (ctx != EGL_NO_CONTEXT) {'
+-            print r'            gltrace::setContext((uintptr_t)ctx);'
+-            print r'            gltrace::Context *tr = gltrace::getContext();'
+-            print r'            EGLint api = EGL_OPENGL_ES_API;'
+-            print r'            _eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_TYPE, &api);'
+-            print r'            if (api == EGL_OPENGL_API) {'
+-            print r'                assert(tr->profile.api == glprofile::API_GL);'
+-            print r'            } else if (api == EGL_OPENGL_ES_API) {'
+-            print r'                EGLint client_version = 1;'
+-            print r'                _eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &client_version);'
+-            print r'                if (tr->profile.api != glprofile::API_GLES ||'
+-            print r'                    tr->profile.major < client_version) {'
+-            print r'                    std::string version = tr->profile.str();'
+-            print r'                    os::log("apitrace: warning: eglMakeCurrent: expected OpenGL ES %i.x context, but got %s\n",'
+-            print r'                            client_version, version.c_str());'
+-            print r'                }'
+-            print r'            } else {'
+-            print r'                assert(0);'
+-            print r'            }'
+-            print r'        } else {'
+-            print r'            gltrace::clearContext();'
+-            print r'        }'
+-            print r'    }'
++            print(r'    if (_result) {')
++            print(r'        // update the profile')
++            print(r'        if (ctx != EGL_NO_CONTEXT) {')
++            print(r'            gltrace::setContext((uintptr_t)ctx);')
++            print(r'            gltrace::Context *tr = gltrace::getContext();')
++            print(r'            EGLint api = EGL_OPENGL_ES_API;')
++            print(r'            _eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_TYPE, &api);')
++            print(r'            if (api == EGL_OPENGL_API) {')
++            print(r'                assert(tr->profile.api == glprofile::API_GL);')
++            print(r'            } else if (api == EGL_OPENGL_ES_API) {')
++            print(r'                EGLint client_version = 1;')
++            print(r'                _eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &client_version);')
++            print(r'                if (tr->profile.api != glprofile::API_GLES ||')
++            print(r'                    tr->profile.major < client_version) {')
++            print(r'                    std::string version = tr->profile.str();')
++            print(r'                    os::log("apitrace: warning: eglMakeCurrent: expected OpenGL ES %i.x context, but got %s\n",')
++            print(r'                            client_version, version.c_str());')
++            print(r'                }')
++            print(r'            } else {')
++            print(r'                assert(0);')
++            print(r'            }')
++            print(r'        } else {')
++            print(r'            gltrace::clearContext();')
++            print(r'        }')
++            print(r'    }')
+         if function.name == 'eglDestroyContext':
+-            print '    if (_result) {'
+-            print '        gltrace::releaseContext((uintptr_t)ctx);'
+-            print '    }'
++            print('    if (_result) {')
++            print('        gltrace::releaseContext((uintptr_t)ctx);')
++            print('    }')
+         if function.name == 'glEGLImageTargetTexture2DOES':
+-            print '    image_info *info = _EGLImageKHR_get_image_info(target, image);'
+-            print '    if (info) {'
+-            print '        GLint level = 0;'
+-            print '        GLint internalformat = info->internalformat;'
+-            print '        GLsizei width = info->width;'
+-            print '        GLsizei height = info->height;'
+-            print '        GLint border = 0;'
+-            print '        GLenum format = info->format;'
+-            print '        GLenum type = info->type;'
+-            print '        const GLvoid * pixels = info->pixels;'
++            print('    image_info *info = _EGLImageKHR_get_image_info(target, image);')
++            print('    if (info) {')
++            print('        GLint level = 0;')
++            print('        GLint internalformat = info->internalformat;')
++            print('        GLsizei width = info->width;')
++            print('        GLsizei height = info->height;')
++            print('        GLint border = 0;')
++            print('        GLenum format = info->format;')
++            print('        GLenum type = info->type;')
++            print('        const GLvoid * pixels = info->pixels;')
+             self.emitFakeTexture2D()
+-            print '        _EGLImageKHR_free_image_info(info);'
+-            print '    }'
++            print('        _EGLImageKHR_free_image_info(info);')
++            print('    }')
+ if __name__ == '__main__':
+-    print '#include <stdlib.h>'
+-    print '#include <string.h>'
+-    print
+-    print '#include "trace_writer_local.hpp"'
+-    print
+-    print '// To validate our prototypes'
+-    print '#define GL_GLEXT_PROTOTYPES'
+-    print '#define EGL_EGLEXT_PROTOTYPES'
+-    print
+-    print '#include "dlopen.hpp"'
+-    print '#include "glproc.hpp"'
+-    print '#include "glsize.hpp"'
+-    print '#include "eglsize.hpp"'
+-    print
+-    print 'static const char *__get_alias_func_name(const char *origFunName)'
+-    print '{'
+-    print '    /* Vivante driver uses alias name for following OES/EXT functions, that means dlsym for thoese functions will fail */'
+-    print '    static const char * __glExtProcAlias[][2] ='
+-    print '    {'
+-    print '        /* Extension API alias for GL_OES_texture_3D */'
+-    print '        {"glTexImage3DOES",               "glTexImage3D"},'
+-    print '        {"glTexSubImage3DOES",            "glTexSubImage3D"},'
+-    print '        {"glCopyTexSubImage3DOES",        "glCopyTexSubImage3D"},'
+-    print '        {"glCompressedTexImage3DOES",     "glCompressedTexImage3D"},'
+-    print '        {"glCompressedTexSubImage3DOES",  "glCompressedTexSubImage3D"},'
+-    print
+-    print '        /* Extension API alias for GL_OES_get_program_binary */'
+-    print '        {"glGetProgramBinaryOES",         "glGetProgramBinary"},'
+-    print '        {"glProgramBinaryOES",            "glProgramBinary"},'
+-    print
+-    print '        /* Extension API alias for GL_OES_vertex_array_object */'
+-    print '        {"glBindVertexArrayOES",          "glBindVertexArray"},'
+-    print '        {"glDeleteVertexArraysOES",       "glDeleteVertexArrays"},'
+-    print '        {"glGenVertexArraysOES",          "glGenVertexArrays"},'
+-    print '        {"glIsVertexArrayOES",            "glIsVertexArray"},'
+-    print
+-    print '        /* Extension API alias for GL_OES_blend_minmax */'
+-    print '        {"glBlendEquationEXT",            "glBlendEquation"}'
+-    print '    };'
+-    print
+-    print '    int count = sizeof(__glExtProcAlias) / sizeof(__glExtProcAlias[0]);'
+-    print '    int i;'
+-    print
+-    print '    for(i=0; i<count; i++)'
+-    print '    {'
+-    print '        if(strcmp(__glExtProcAlias[i][0], origFunName) == 0)'
+-    print '            return __glExtProcAlias[i][1];'
+-    print '    }'
+-    print
+-    print '    return origFunName;'
+-    print '}'
+-
+-    print
+-    print 'typedef struct TexDirectVivData'
+-    print '{'
+-    print '    int width;'
+-    print '    int height;'
+-    print '    GLenum format;'
+-    print '    GLvoid*planes[3]; // used for glTexDirectVIV'
+-    print '    GLvoid*logical;   // used for glTexDirectVIVMap/glTexDirectMapVIV/glTexDirectTiledMapVIV'
+-    print '    GLuint physical;'
+-    print '}TEXDIRECTVIVDATA;'
+-    print
+-    print 'static std::map<GLint, TEXDIRECTVIVDATA> _directTextureDataMap;'
+-    print
+-    print '#define GL_VIV_YV12                        0x8FC0'
+-    print '#define GL_VIV_NV12                        0x8FC1'
+-    print '#define GL_VIV_YUY2                        0x8FC2'
+-    print '#define GL_VIV_UYVY                        0x8FC3'
+-    print '#define GL_VIV_NV21                        0x8FC4'
+-    print '#define GL_VIV_I420                        0x8FC5'
+-    print
++    print('#include <stdlib.h>')
++    print('#include <string.h>')
++    print()
++    print('#include "trace_writer_local.hpp"')
++    print()
++    print('// To validate our prototypes')
++    print('#define GL_GLEXT_PROTOTYPES')
++    print('#define EGL_EGLEXT_PROTOTYPES')
++    print()
++    print('#include "dlopen.hpp"')
++    print('#include "glproc.hpp"')
++    print('#include "glsize.hpp"')
++    print('#include "eglsize.hpp"')
++    print()
++    print('static const char *__get_alias_func_name(const char *origFunName)')
++    print('{')
++    print('    /* Vivante driver uses alias name for following OES/EXT functions, that means dlsym for thoese functions will fail */')
++    print('    static const char * __glExtProcAlias[][2] =')
++    print('    {')
++    print('        /* Extension API alias for GL_OES_texture_3D */')
++    print('        {"glTexImage3DOES",               "glTexImage3D"},')
++    print('        {"glTexSubImage3DOES",            "glTexSubImage3D"},')
++    print('        {"glCopyTexSubImage3DOES",        "glCopyTexSubImage3D"},')
++    print('        {"glCompressedTexImage3DOES",     "glCompressedTexImage3D"},')
++    print('        {"glCompressedTexSubImage3DOES",  "glCompressedTexSubImage3D"},')
++    print()
++    print('        /* Extension API alias for GL_OES_get_program_binary */')
++    print('        {"glGetProgramBinaryOES",         "glGetProgramBinary"},')
++    print('        {"glProgramBinaryOES",            "glProgramBinary"},')
++    print()
++    print('        /* Extension API alias for GL_OES_vertex_array_object */')
++    print('        {"glBindVertexArrayOES",          "glBindVertexArray"},')
++    print('        {"glDeleteVertexArraysOES",       "glDeleteVertexArrays"},')
++    print('        {"glGenVertexArraysOES",          "glGenVertexArrays"},')
++    print('        {"glIsVertexArrayOES",            "glIsVertexArray"},')
++    print()
++    print('        /* Extension API alias for GL_OES_blend_minmax */')
++    print('        {"glBlendEquationEXT",            "glBlendEquation"}')
++    print('    };')
++    print()
++    print('    int count = sizeof(__glExtProcAlias) / sizeof(__glExtProcAlias[0]);')
++    print('    int i;')
++    print()
++    print('    for(i=0; i<count; i++)')
++    print('    {')
++    print('        if(strcmp(__glExtProcAlias[i][0], origFunName) == 0)')
++    print('            return __glExtProcAlias[i][1];')
++    print('    }')
++    print()
++    print('    return origFunName;')
++    print('}')
++
++    print()
++    print('typedef struct TexDirectVivData')
++    print('{')
++    print('    int width;')
++    print('    int height;')
++    print('    GLenum format;')
++    print('    GLvoid*planes[3]; // used for glTexDirectVIV')
++    print('    GLvoid*logical;   // used for glTexDirectVIVMap/glTexDirectMapVIV/glTexDirectTiledMapVIV')
++    print('    GLuint physical;')
++    print('}TEXDIRECTVIVDATA;')
++    print()
++    print('static std::map<GLint, TEXDIRECTVIVDATA> _directTextureDataMap;')
++    print()
++    print('#define GL_VIV_YV12                        0x8FC0')
++    print('#define GL_VIV_NV12                        0x8FC1')
++    print('#define GL_VIV_YUY2                        0x8FC2')
++    print('#define GL_VIV_UYVY                        0x8FC3')
++    print('#define GL_VIV_NV21                        0x8FC4')
++    print('#define GL_VIV_I420                        0x8FC5')
++    print()
+     module = Module()
+     module.mergeModule(eglapi)
+@@ -292,7 +292,7 @@ if __name__ == '__main__':
+     tracer = EglTracer()
+     tracer.traceApi(api)
+-    print r'''
++    print(r'''
+@@ -453,8 +453,8 @@ void APIENTRY glWeightPointerOESBounds(GLint size, GLenum type, GLsizei stride,
+ #endif /* ANDROID */
+-'''
+-    print r'''
++''')
++    print(r'''
+ /*
+  * let the GPU driver know that we are in apitrace
+  */
+@@ -464,4 +464,4 @@ int APIENTRY ApiTraceEnabled(void) {
+     return 1;
+ }
+-'''
++''')
+diff --git a/wrappers/gltrace.py b/wrappers/gltrace.py
+index cf13ae18..02504148 100644
+--- a/wrappers/gltrace.py
++++ b/wrappers/gltrace.py
+@@ -79,7 +79,7 @@ class TypeGetter(stdapi.Visitor):
+                 suffix = 'iv'
+                 arg_type = 'GLint'
+         else:
+-            print alias.expr
++            print(alias.expr)
+             assert False
+         function_name = self.prefix + suffix + self.ext_suffix
+         return function_name, arg_type
+@@ -114,48 +114,48 @@ class GlTracer(Tracer):
+     def header(self, api):
+         Tracer.header(self, api)
+-        print '#include <algorithm>'
+-        print
+-        print '#include "gltrace.hpp"'
+-        print
++        print('#include <algorithm>')
++        print()
++        print('#include "gltrace.hpp"')
++        print()
+         
+         # Which glVertexAttrib* variant to use
+-        print 'enum vertex_attrib {'
+-        print '    VERTEX_ATTRIB,'
+-        print '    VERTEX_ATTRIB_NV,'
+-        print '};'
+-        print
+-        print 'static vertex_attrib _get_vertex_attrib(void) {'
+-        print '    gltrace::Context *ctx = gltrace::getContext();'
+-        print '    if (ctx->user_arrays_nv) {'
+-        print '        GLboolean _vertex_program = GL_FALSE;'
+-        print '        _glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &_vertex_program);'
+-        print '        if (_vertex_program) {'
+-        print '            if (ctx->user_arrays_nv) {'
+-        print '                GLint _vertex_program_binding_nv = _glGetInteger(GL_VERTEX_PROGRAM_BINDING_NV);'
+-        print '                if (_vertex_program_binding_nv) {'
+-        print '                    return VERTEX_ATTRIB_NV;'
+-        print '                }'
+-        print '            }'
+-        print '        }'
+-        print '    }'
+-        print '    return VERTEX_ATTRIB;'
+-        print '}'
+-        print
++        print('enum vertex_attrib {')
++        print('    VERTEX_ATTRIB,')
++        print('    VERTEX_ATTRIB_NV,')
++        print('};')
++        print()
++        print('static vertex_attrib _get_vertex_attrib(void) {')
++        print('    gltrace::Context *ctx = gltrace::getContext();')
++        print('    if (ctx->user_arrays_nv) {')
++        print('        GLboolean _vertex_program = GL_FALSE;')
++        print('        _glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &_vertex_program);')
++        print('        if (_vertex_program) {')
++        print('            if (ctx->user_arrays_nv) {')
++        print('                GLint _vertex_program_binding_nv = _glGetInteger(GL_VERTEX_PROGRAM_BINDING_NV);')
++        print('                if (_vertex_program_binding_nv) {')
++        print('                    return VERTEX_ATTRIB_NV;')
++        print('                }')
++        print('            }')
++        print('        }')
++        print('    }')
++        print('    return VERTEX_ATTRIB;')
++        print('}')
++        print()
+         self.defineShadowBufferHelper()
+         # Whether we need user arrays
+-        print 'static inline bool _need_user_arrays(void)'
+-        print '{'
+-        print '    gltrace::Context *ctx = gltrace::getContext();'
+-        print '    if (!ctx->user_arrays) {'
+-        print '        return false;'
+-        print '    }'
+-        print
+-        print '    glprofile::Profile profile = ctx->profile;'
+-        print '    bool es1 = profile.es() && profile.major == 1;'
+-        print
++        print('static inline bool _need_user_arrays(void)')
++        print('{')
++        print('    gltrace::Context *ctx = gltrace::getContext();')
++        print('    if (!ctx->user_arrays) {')
++        print('        return false;')
++        print('    }')
++        print()
++        print('    glprofile::Profile profile = ctx->profile;')
++        print('    bool es1 = profile.es() && profile.major == 1;')
++        print()
+         for camelcase_name, uppercase_name in self.arrays:
+             # in which profile is the array available?
+@@ -166,120 +166,120 @@ class GlTracer(Tracer):
+             function_name = 'gl%sPointer' % camelcase_name
+             enable_name = 'GL_%s_ARRAY' % uppercase_name
+             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
+-            print '    // %s' % function_name
+-            print '  if (%s) {' % profile_check
++            print('    // %s' % function_name)
++            print('  if (%s) {' % profile_check)
+             self.array_prolog(api, uppercase_name)
+-            print '    if (_glIsEnabled(%s) &&' % enable_name
+-            print '        _glGetInteger(%s) == 0) {' % binding_name
++            print('    if (_glIsEnabled(%s) &&' % enable_name)
++            print('        _glGetInteger(%s) == 0) {' % binding_name)
+             self.array_cleanup(api, uppercase_name)
+-            print '        return true;'
+-            print '    }'
++            print('        return true;')
++            print('    }')
+             self.array_epilog(api, uppercase_name)
+-            print '  }'
+-            print
+-
+-        print '    // ES1 does not support generic vertex attributes'
+-        print '    if (es1)'
+-        print '        return false;'
+-        print
+-        print '    vertex_attrib _vertex_attrib = _get_vertex_attrib();'
+-        print
+-        print '    // glVertexAttribPointer'
+-        print '    if (_vertex_attrib == VERTEX_ATTRIB) {'
+-        print '        GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
+-        print '        for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
+-        print '            if (_glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED) &&'
+-        print '                _glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) == 0) {'
+-        print '                return true;'
+-        print '            }'
+-        print '        }'
+-        print '    }'
+-        print
+-        print '    // glVertexAttribPointerNV'
+-        print '    if (_vertex_attrib == VERTEX_ATTRIB_NV) {'
+-        print '        for (GLint index = 0; index < 16; ++index) {'
+-        print '            if (_glIsEnabled(GL_VERTEX_ATTRIB_ARRAY0_NV + index)) {'
+-        print '                return true;'
+-        print '            }'
+-        print '        }'
+-        print '    }'
+-        print
+-
+-        print '    return false;'
+-        print '}'
+-        print
+-
+-        print 'static void _trace_user_arrays(GLuint count);'
+-        print
+-
+-        print '// whether glLockArraysEXT() has ever been called'
+-        print 'static bool _checkLockArraysEXT = false;'
+-        print
++            print('  }')
++            print()
++
++        print('    // ES1 does not support generic vertex attributes')
++        print('    if (es1)')
++        print('        return false;')
++        print()
++        print('    vertex_attrib _vertex_attrib = _get_vertex_attrib();')
++        print()
++        print('    // glVertexAttribPointer')
++        print('    if (_vertex_attrib == VERTEX_ATTRIB) {')
++        print('        GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);')
++        print('        for (GLint index = 0; index < _max_vertex_attribs; ++index) {')
++        print('            if (_glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED) &&')
++        print('                _glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) == 0) {')
++        print('                return true;')
++        print('            }')
++        print('        }')
++        print('    }')
++        print()
++        print('    // glVertexAttribPointerNV')
++        print('    if (_vertex_attrib == VERTEX_ATTRIB_NV) {')
++        print('        for (GLint index = 0; index < 16; ++index) {')
++        print('            if (_glIsEnabled(GL_VERTEX_ATTRIB_ARRAY0_NV + index)) {')
++        print('                return true;')
++        print('            }')
++        print('        }')
++        print('    }')
++        print()
++
++        print('    return false;')
++        print('}')
++        print()
++
++        print('static void _trace_user_arrays(GLuint count);')
++        print()
++
++        print('// whether glLockArraysEXT() has ever been called')
++        print('static bool _checkLockArraysEXT = false;')
++        print()
+         # Buffer mappings
+-        print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
+-        print 'static bool _checkBufferMapRange = false;'
+-        print
+-        print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
+-        print 'static bool _checkBufferFlushingUnmapAPPLE = false;'
+-        print
++        print('// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called')
++        print('static bool _checkBufferMapRange = false;')
++        print()
++        print('// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called')
++        print('static bool _checkBufferFlushingUnmapAPPLE = false;')
++        print()
+         # Generate a helper function to determine whether a parameter name
+         # refers to a symbolic value or not
+-        print 'static bool'
+-        print 'is_symbolic_pname(GLenum pname) {'
+-        print '    switch (pname) {'
++        print('static bool')
++        print('is_symbolic_pname(GLenum pname) {')
++        print('    switch (pname) {')
+         for function, type, count, name in glparams.parameters:
+             if type is glapi.GLenum:
+-                print '    case %s:' % name
+-        print '        return true;'
+-        print '    default:'
+-        print '        return false;'
+-        print '    }'
+-        print '}'
+-        print
++                print('    case %s:' % name)
++        print('        return true;')
++        print('    default:')
++        print('        return false;')
++        print('    }')
++        print('}')
++        print()
+         
+         # Generate a helper function to determine whether a parameter value is
+         # potentially symbolic or not; i.e., if the value can be represented in
+         # an enum or not
+-        print 'template<class T>'
+-        print 'static inline bool'
+-        print 'is_symbolic_param(T param) {'
+-        print '    return static_cast<T>(static_cast<GLenum>(param)) == param;'
+-        print '}'
+-        print
++        print('template<class T>')
++        print('static inline bool')
++        print('is_symbolic_param(T param) {')
++        print('    return static_cast<T>(static_cast<GLenum>(param)) == param;')
++        print('}')
++        print()
+         # Generate a helper function to know how many elements a parameter has
+-        print 'static size_t'
+-        print '_gl_param_size(GLenum pname) {'
+-        print '    switch (pname) {'
++        print('static size_t')
++        print('_gl_param_size(GLenum pname) {')
++        print('    switch (pname) {')
+         for function, type, count, name in glparams.parameters:
+             if name == 'GL_PROGRAM_BINARY_FORMATS':
+                 count = 0
+             if type is not None:
+-                print '    case %s: return %s;' % (name, count)
+-        print '    default:'
+-        print r'        os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
+-        print '        return 1;'
+-        print '    }'
+-        print '}'
+-        print
++                print('    case %s: return %s;' % (name, count))
++        print('    default:')
++        print(r'        os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);')
++        print('        return 1;')
++        print('    }')
++        print('}')
++        print()
+         # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
+-        print 'static inline bool'
+-        print 'can_unpack_subimage(void) {'
+-        print '    gltrace::Context *ctx = gltrace::getContext();'
+-        print '    return ctx->profile.desktop();'
+-        print '}'
+-        print
++        print('static inline bool')
++        print('can_unpack_subimage(void) {')
++        print('    gltrace::Context *ctx = gltrace::getContext();')
++        print('    return ctx->profile.desktop();')
++        print('}')
++        print()
+         # VMWX_map_buffer_debug
+-        print r'extern "C" PUBLIC'
+-        print r'void APIENTRY'
+-        print r'glNotifyMappedBufferRangeVMWX(const void * start, GLsizeiptr length) {'
++        print(r'extern "C" PUBLIC')
++        print(r'void APIENTRY')
++        print(r'glNotifyMappedBufferRangeVMWX(const void * start, GLsizeiptr length) {')
+         self.emit_memcpy('start', 'length')
+-        print r'}'
+-        print
++        print(r'}')
++        print()
+     getProcAddressFunctionNames = []
+@@ -290,70 +290,70 @@ class GlTracer(Tracer):
+             argType = getProcAddressFunction.args[0].type
+             retType = getProcAddressFunction.type
+             
+-            print 'static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType)
+-            print
++            print('static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType))
++            print()
+             
+             Tracer.traceApi(self, api)
+             
+-            print 'static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType)
++            print('static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType))
+             # Provide fallback functions to missing debug functions
+-            print '    if (!procPtr) {'
++            print('    if (!procPtr) {')
+             else_ = ''
+             for function_name in self.debug_functions:
+                 if self.api.getFunctionByName(function_name):
+-                    print '        %sif (strcmp("%s", (const char *)procName) == 0) {' % (else_, function_name)
+-                    print '            return (%s)&%s;' % (retType, function_name)
+-                    print '        }'
++                    print('        %sif (strcmp("%s", (const char *)procName) == 0) {' % (else_, function_name))
++                    print('            return (%s)&%s;' % (retType, function_name))
++                    print('        }')
+                 else_ = 'else '
+-            print '        %s{' % else_
+-            print '            return NULL;'
+-            print '        }'
+-            print '    }'
++            print('        %s{' % else_)
++            print('            return NULL;')
++            print('        }')
++            print('    }')
+             for function in api.getAllFunctions():
+                 ptype = function_pointer_type(function)
+                 pvalue = function_pointer_value(function)
+-                print '    if (strcmp("%s", (const char *)procName) == 0) {' % function.name
+-                print '        assert(procPtr != (%s)&%s);' % (retType, function.name)
+-                print '        %s = (%s)procPtr;' % (pvalue, ptype)
+-                print '        return (%s)&%s;' % (retType, function.name,)
+-                print '    }'
+-            print '    os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);'
+-            print '    return procPtr;'
+-            print '}'
+-            print
++                print('    if (strcmp("%s", (const char *)procName) == 0) {' % function.name)
++                print('        assert(procPtr != (%s)&%s);' % (retType, function.name))
++                print('        %s = (%s)procPtr;' % (pvalue, ptype))
++                print('        return (%s)&%s;' % (retType, function.name,))
++                print('    }')
++            print('    os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);')
++            print('    return procPtr;')
++            print('}')
++            print()
+         else:
+             Tracer.traceApi(self, api)
+     def defineShadowBufferHelper(self):
+-        print 'void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,'
+-        print '                                GLsizeiptr size, GLvoid *data)'
+-        print '{'
+-        print '    gltrace::Context *ctx = gltrace::getContext();'
+-        print '    if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {'
+-        print '        _glGetBufferSubData(target, offset, size, data);'
+-        print '        return;'
+-        print '    }'
+-        print
+-        print '    GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
+-        print '    if (buffer_binding > 0) {'
+-        print '        gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
+-        print '        buf.getSubData(offset, size, data);'
+-        print '    }'
+-        print '}'
++        print('void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,')
++        print('                                GLsizeiptr size, GLvoid *data)')
++        print('{')
++        print('    gltrace::Context *ctx = gltrace::getContext();')
++        print('    if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {')
++        print('        _glGetBufferSubData(target, offset, size, data);')
++        print('        return;')
++        print('    }')
++        print()
++        print('    GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);')
++        print('    if (buffer_binding > 0) {')
++        print('        gltrace::Buffer & buf = ctx->buffers[buffer_binding];')
++        print('        buf.getSubData(offset, size, data);')
++        print('    }')
++        print('}')
+     def shadowBufferMethod(self, method):
+         # Emit code to fetch the shadow buffer, and invoke a method
+-        print '    gltrace::Context *ctx = gltrace::getContext();'
+-        print '    if (ctx->needsShadowBuffers() && target == GL_ELEMENT_ARRAY_BUFFER) {'
+-        print '        GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
+-        print '        if (buffer_binding > 0) {'
+-        print '            gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
+-        print '            buf.' + method + ';'
+-        print '        }'
+-        print '    }'
+-        print
++        print('    gltrace::Context *ctx = gltrace::getContext();')
++        print('    if (ctx->needsShadowBuffers() && target == GL_ELEMENT_ARRAY_BUFFER) {')
++        print('        GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);')
++        print('        if (buffer_binding > 0) {')
++        print('            gltrace::Buffer & buf = ctx->buffers[buffer_binding];')
++        print('            buf.' + method + ';')
++        print('        }')
++        print('    }')
++        print()
+     def shadowBufferProlog(self, function):
+         if function.name == 'glBufferData':
+@@ -363,12 +363,12 @@ class GlTracer(Tracer):
+             self.shadowBufferMethod('bufferSubData(offset, size, data)')
+         if function.name == 'glDeleteBuffers':
+-            print '    gltrace::Context *ctx = gltrace::getContext();'
+-            print '    if (ctx->needsShadowBuffers()) {'
+-            print '        for (GLsizei i = 0; i < n; i++) {'
+-            print '            ctx->buffers.erase(buffer[i]);'
+-            print '        }'
+-            print '    }'
++            print('    gltrace::Context *ctx = gltrace::getContext();')
++            print('    if (ctx->needsShadowBuffers()) {')
++            print('        for (GLsizei i = 0; i < n; i++) {')
++            print('            ctx->buffers.erase(buffer[i]);')
++            print('        }')
++            print('    }')
+     array_pointer_function_names = set((
+         "glVertexPointer",
+@@ -426,42 +426,42 @@ class GlTracer(Tracer):
+     def traceFunctionImplBody(self, function):
+         # Defer tracing of user array pointers...
+         if function.name in self.array_pointer_function_names:
+-            print '    GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
+-            print '    if (!_array_buffer) {'
+-            print '        static bool warned = false;'
+-            print '        if (!warned) {'
+-            print '            warned = true;'
+-            print '            os::log("apitrace: warning: %s: call will be faked due to pointer to user memory (https://github.com/apitrace/apitrace/blob/master/docs/BUGS.markdown#tracing)\\n", __FUNCTION__);'
+-            print '        }'
+-            print '        gltrace::Context *ctx = gltrace::getContext();'
+-            print '        ctx->user_arrays = true;'
++            print('    GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);')
++            print('    if (!_array_buffer) {')
++            print('        static bool warned = false;')
++            print('        if (!warned) {')
++            print('            warned = true;')
++            print('            os::log("apitrace: warning: %s: call will be faked due to pointer to user memory (https://github.com/apitrace/apitrace/blob/master/docs/BUGS.markdown#tracing)\\n", __FUNCTION__);')
++            print('        }')
++            print('        gltrace::Context *ctx = gltrace::getContext();')
++            print('        ctx->user_arrays = true;')
+             if function.name == "glVertexAttribPointerNV":
+-                print '        ctx->user_arrays_nv = true;'
++                print('        ctx->user_arrays_nv = true;')
+             self.invokeFunction(function)
+             # And also break down glInterleavedArrays into the individual calls
+             if function.name == 'glInterleavedArrays':
+-                print
++                print()
+                 # Initialize the enable flags
+                 for camelcase_name, uppercase_name in self.arrays:
+                     flag_name = '_' + uppercase_name.lower()
+-                    print '        GLboolean %s = GL_FALSE;' % flag_name
+-                print
++                    print('        GLboolean %s = GL_FALSE;' % flag_name)
++                print()
+                 # Switch for the interleaved formats
+-                print '        switch (format) {'
++                print('        switch (format) {')
+                 for format in self.interleaved_formats:
+-                    print '            case %s:' % format
++                    print('            case %s:' % format)
+                     for camelcase_name, uppercase_name in self.arrays:
+                         flag_name = '_' + uppercase_name.lower()
+                         if format.find('_' + uppercase_name[0]) >= 0:
+-                            print '                %s = GL_TRUE;' % flag_name
+-                    print '                break;'
+-                print '            default:'
+-                print '               return;'
+-                print '        }'
+-                print
++                            print('                %s = GL_TRUE;' % flag_name)
++                    print('                break;')
++                print('            default:')
++                print('               return;')
++                print('        }')
++                print()
+                 # Emit fake glEnableClientState/glDisableClientState flags
+                 for camelcase_name, uppercase_name in self.arrays:
+@@ -469,16 +469,16 @@ class GlTracer(Tracer):
+                     enable_name = 'GL_%s_ARRAY' % uppercase_name
+                     # Emit a fake function
+-                    print '        {'
+-                    print '            static const trace::FunctionSig &_sig = %s ? _glEnableClientState_sig : _glDisableClientState_sig;' % flag_name
+-                    print '            unsigned _call = trace::localWriter.beginEnter(&_sig, true);'
+-                    print '            trace::localWriter.beginArg(0);'
++                    print('        {')
++                    print('            static const trace::FunctionSig &_sig = %s ? _glEnableClientState_sig : _glDisableClientState_sig;' % flag_name)
++                    print('            unsigned _call = trace::localWriter.beginEnter(&_sig, true);')
++                    print('            trace::localWriter.beginArg(0);')
+                     self.serializeValue(glapi.GLenum, enable_name)
+-                    print '            trace::localWriter.endArg();'
+-                    print '            trace::localWriter.endEnter();'
+-                    print '            trace::localWriter.beginLeave(_call);'
+-                    print '            trace::localWriter.endLeave();'
+-                    print '        }'
++                    print('            trace::localWriter.endArg();')
++                    print('            trace::localWriter.endEnter();')
++                    print('            trace::localWriter.beginLeave(_call);')
++                    print('            trace::localWriter.endLeave();')
++                    print('        }')
+             # Warn about buggy glGet(GL_*ARRAY_SIZE) not returning GL_BGRA
+             buggyFunctions = {
+@@ -489,224 +489,224 @@ class GlTracer(Tracer):
+             }
+             if function.name in buggyFunctions:
+                 getter, extraArg, pname = buggyFunctions[function.name]
+-                print r'        static bool _checked = false;'
+-                print r'        if (!_checked && size == GL_BGRA) {'
+-                print r'            GLint _size = 0;'
+-                print r'            _%s(%s%s, &_size);' % (getter, extraArg, pname)
+-                print r'            if (_size != GL_BGRA) {'
+-                print r'                os::log("apitrace: warning: %s(%s) does not return GL_BGRA; trace will be incorrect (https://github.com/apitrace/apitrace/issues/261)\n");' % (getter, pname)
+-                print r'            }'
+-                print r'            _checked = true;'
+-                print r'        }'
+-
+-            print '        return;'
+-            print '    }'
++                print(r'        static bool _checked = false;')
++                print(r'        if (!_checked && size == GL_BGRA) {')
++                print(r'            GLint _size = 0;')
++                print(r'            _%s(%s%s, &_size);' % (getter, extraArg, pname))
++                print(r'            if (_size != GL_BGRA) {')
++                print(r'                os::log("apitrace: warning: %s(%s) does not return GL_BGRA; trace will be incorrect (https://github.com/apitrace/apitrace/issues/261)\n");' % (getter, pname))
++                print(r'            }')
++                print(r'            _checked = true;')
++                print(r'        }')
++
++            print('        return;')
++            print('    }')
+         # ... to the draw calls
+         if self.draw_function_regex.match(function.name):
+             if not self.multi_draw_function_regex.match(function.name):
+-                print '    if (trace::localWriter.isIgnored()) {'
++                print('    if (trace::localWriter.isIgnored()) {')
+                 self.invokeFunction(function)
+-                print '        return;'
+-                print '    }'
+-            print '    if (_need_user_arrays()) {'
++                print('        return;')
++                print('    }')
++            print('    if (_need_user_arrays()) {')
+             if 'Indirect' in function.name:
+-                print r'        os::log("apitrace: warning: %s: indirect user arrays not supported\n");' % (function.name,)
++                print(r'        os::log("apitrace: warning: %s: indirect user arrays not supported\n");' % (function.name,))
+             else:
+                 arg_names = ', '.join([arg.name for arg in function.args[1:]])
+-                print '        GLuint _count = _%s_count(%s);' % (function.name, arg_names)
++                print('        GLuint _count = _%s_count(%s);' % (function.name, arg_names))
+                 # Some apps, in particular Quake3, can tell the driver to lock more
+                 # vertices than those actually required for the draw call.
+-                print '        if (_checkLockArraysEXT) {'
+-                print '            GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
+-                print '                                 + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
+-                print '            _count = std::max(_count, _locked_count);'
+-                print '        }'
+-                print '        _trace_user_arrays(_count);'
+-            print '    }'
++                print('        if (_checkLockArraysEXT) {')
++                print('            GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)')
++                print('                                 + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);')
++                print('            _count = std::max(_count, _locked_count);')
++                print('        }')
++                print('        _trace_user_arrays(_count);')
++            print('    }')
+         if function.name == 'glLockArraysEXT':
+-            print '        _checkLockArraysEXT = true;'
++            print('        _checkLockArraysEXT = true;')
+         # Warn if user arrays are used with glBegin/glArrayElement/glEnd.
+         if function.name == 'glBegin':
+-            print r'    gltrace::Context *ctx = gltrace::getContext();'
+-            print r'    ctx->userArraysOnBegin = _need_user_arrays();'
++            print(r'    gltrace::Context *ctx = gltrace::getContext();')
++            print(r'    ctx->userArraysOnBegin = _need_user_arrays();')
+         if function.name.startswith('glArrayElement'):
+-            print r'    gltrace::Context *ctx = gltrace::getContext();'
+-            print r'    if (ctx->userArraysOnBegin) {'
+-            print r'        os::log("apitrace: warning: user arrays with glArrayElement not supported (https://github.com/apitrace/apitrace/issues/276)\n");'
+-            print r'        ctx->userArraysOnBegin = false;'
+-            print r'    }'
++            print(r'    gltrace::Context *ctx = gltrace::getContext();')
++            print(r'    if (ctx->userArraysOnBegin) {')
++            print(r'        os::log("apitrace: warning: user arrays with glArrayElement not supported (https://github.com/apitrace/apitrace/issues/276)\n");')
++            print(r'        ctx->userArraysOnBegin = false;')
++            print(r'    }')
+         
+         # Emit a fake memcpy on buffer uploads
+         if function.name == 'glBufferParameteriAPPLE':
+-            print '    if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
+-            print '        _checkBufferFlushingUnmapAPPLE = true;'
+-            print '    }'
++            print('    if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {')
++            print('        _checkBufferFlushingUnmapAPPLE = true;')
++            print('    }')
+         if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
+             if function.name.endswith('ARB'):
+                 suffix = 'ARB'
+             else:
+                 suffix = ''
+-            print '    GLint access_flags = 0;'
+-            print '    GLint access = 0;'
+-            print '    bool flush;'
+-            print '    // GLES3 does not have GL_BUFFER_ACCESS;'
+-            print '    if (_checkBufferMapRange) {'
+-            print '        _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);' % suffix
+-            print '        flush = (access_flags & GL_MAP_WRITE_BIT) && !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT));'
+-            print '    } else {'
+-            print '        _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
+-            print '        flush = access != GL_READ_ONLY;'
+-            print '    }'
+-            print '    if (flush) {'
+-            print '        GLvoid *map = NULL;'
+-            print '        _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);'  % suffix
+-            print '        if (map) {'
+-            print '            GLint length = -1;'
+-            print '            if (_checkBufferMapRange) {'
+-            print '                _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
+-            print '                if (length == -1) {'
+-            print '                    // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
+-            print '                    // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
+-            print '                    static bool warned = false;'
+-            print '                    if (!warned) {'
+-            print '                        os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
+-            print '                        warned = true;'
+-            print '                    }'
+-            print '                }'
+-            print '            } else {'
+-            print '                length = 0;'
+-            print '                _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
+-            print '            }'
+-            print '            if (_checkBufferFlushingUnmapAPPLE) {'
+-            print '                GLint flushing_unmap = GL_TRUE;'
+-            print '                _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
+-            print '                flush = flush && flushing_unmap;'
+-            print '            }'
+-            print '            if (flush && length > 0) {'
++            print('    GLint access_flags = 0;')
++            print('    GLint access = 0;')
++            print('    bool flush;')
++            print('    // GLES3 does not have GL_BUFFER_ACCESS;')
++            print('    if (_checkBufferMapRange) {')
++            print('        _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);' % suffix)
++            print('        flush = (access_flags & GL_MAP_WRITE_BIT) && !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT));')
++            print('    } else {')
++            print('        _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix)
++            print('        flush = access != GL_READ_ONLY;')
++            print('    }')
++            print('    if (flush) {')
++            print('        GLvoid *map = NULL;')
++            print('        _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);'  % suffix)
++            print('        if (map) {')
++            print('            GLint length = -1;')
++            print('            if (_checkBufferMapRange) {')
++            print('                _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix)
++            print('                if (length == -1) {')
++            print('                    // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to')
++            print('                    // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f')
++            print('                    static bool warned = false;')
++            print('                    if (!warned) {')
++            print('                        os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix)
++            print('                        warned = true;')
++            print('                    }')
++            print('                }')
++            print('            } else {')
++            print('                length = 0;')
++            print('                _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix)
++            print('            }')
++            print('            if (_checkBufferFlushingUnmapAPPLE) {')
++            print('                GLint flushing_unmap = GL_TRUE;')
++            print('                _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix)
++            print('                flush = flush && flushing_unmap;')
++            print('            }')
++            print('            if (flush && length > 0) {')
+             self.emit_memcpy('map', 'length')
+-            print '            }'
+-            print '        }'
+-            print '    }'
++            print('            }')
++            print('        }')
++            print('    }')
+         if function.name == 'glUnmapBufferOES':
+-            print '    GLint access_flags = 0;'
+-            print '    GLint access = 0;'
+-            print '    bool flush;'
+-            print '    // GLES3 does not have GL_BUFFER_ACCESS;'
+-            print '    if (_checkBufferMapRange) {'
+-            print '        _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
+-            print '        flush = (access_flags & GL_MAP_WRITE_BIT) && !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT));'
+-            print '    } else {'
+-            print '        _glGetBufferParameteriv(target, GL_BUFFER_ACCESS, &access);'
+-            print '        flush = access != GL_READ_ONLY;'
+-            print '    }'
+-            print '    if (flush) {'
+-            print '        GLvoid *map = NULL;'
+-            print '        _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER, &map);'
+-            print '        if (map) {'
+-            print '            GLint length = 0;'
+-            print '            GLint offset = 0;'
+-            print '            if (_checkBufferMapRange) {'
+-            print '                _glGetBufferParameteriv(target, GL_BUFFER_MAP_LENGTH, &length);'
+-            print '                _glGetBufferParameteriv(target, GL_BUFFER_MAP_OFFSET, &offset);'
+-            print '            } else {'
+-            print '                _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);'
+-            print '            }'
+-            print '            if (flush && length > 0) {'
++            print('    GLint access_flags = 0;')
++            print('    GLint access = 0;')
++            print('    bool flush;')
++            print('    // GLES3 does not have GL_BUFFER_ACCESS;')
++            print('    if (_checkBufferMapRange) {')
++            print('        _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);')
++            print('        flush = (access_flags & GL_MAP_WRITE_BIT) && !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT));')
++            print('    } else {')
++            print('        _glGetBufferParameteriv(target, GL_BUFFER_ACCESS, &access);')
++            print('        flush = access != GL_READ_ONLY;')
++            print('    }')
++            print('    if (flush) {')
++            print('        GLvoid *map = NULL;')
++            print('        _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER, &map);')
++            print('        if (map) {')
++            print('            GLint length = 0;')
++            print('            GLint offset = 0;')
++            print('            if (_checkBufferMapRange) {')
++            print('                _glGetBufferParameteriv(target, GL_BUFFER_MAP_LENGTH, &length);')
++            print('                _glGetBufferParameteriv(target, GL_BUFFER_MAP_OFFSET, &offset);')
++            print('            } else {')
++            print('                _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);')
++            print('            }')
++            print('            if (flush && length > 0) {')
+             self.emit_memcpy('map', 'length')
+             self.shadowBufferMethod('bufferSubData(offset, length, map)')
+-            print '            }'
+-            print '        }'
+-            print '    }'
++            print('            }')
++            print('        }')
++            print('    }')
+         if function.name == 'glUnmapNamedBuffer':
+-            print '    GLint access_flags = 0;'
+-            print '    _glGetNamedBufferParameteriv(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
+-            print '    if ((access_flags & GL_MAP_WRITE_BIT) &&'
+-            print '        !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT))) {'
+-            print '        GLvoid *map = NULL;'
+-            print '        _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
+-            print '        GLint length = 0;'
+-            print '        _glGetNamedBufferParameteriv(buffer, GL_BUFFER_MAP_LENGTH, &length);'
+-            print '        if (map && length > 0) {'
++            print('    GLint access_flags = 0;')
++            print('    _glGetNamedBufferParameteriv(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);')
++            print('    if ((access_flags & GL_MAP_WRITE_BIT) &&')
++            print('        !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT))) {')
++            print('        GLvoid *map = NULL;')
++            print('        _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);')
++            print('        GLint length = 0;')
++            print('        _glGetNamedBufferParameteriv(buffer, GL_BUFFER_MAP_LENGTH, &length);')
++            print('        if (map && length > 0) {')
+             self.emit_memcpy('map', 'length')
+-            print '        }'
+-            print '    }'
++            print('        }')
++            print('    }')
+         if function.name == 'glUnmapNamedBufferEXT':
+-            print '    GLint access_flags = 0;'
+-            print '    _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
+-            print '    if ((access_flags & GL_MAP_WRITE_BIT) &&'
+-            print '        !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT))) {'
+-            print '        GLvoid *map = NULL;'
+-            print '        _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
+-            print '        GLint length = 0;'
+-            print '        _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
+-            print '        if (map && length > 0) {'
++            print('    GLint access_flags = 0;')
++            print('    _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);')
++            print('    if ((access_flags & GL_MAP_WRITE_BIT) &&')
++            print('        !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT))) {')
++            print('        GLvoid *map = NULL;')
++            print('        _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);')
++            print('        GLint length = 0;')
++            print('        _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);')
++            print('        if (map && length > 0) {')
+             self.emit_memcpy('map', 'length')
+-            print '        }'
+-            print '    }'
++            print('        }')
++            print('    }')
+         if function.name == 'glFlushMappedBufferRange':
+-            print '    GLvoid *map = NULL;'
+-            print '    _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
+-            print '    if (map && length > 0) {'
++            print('    GLvoid *map = NULL;')
++            print('    _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);')
++            print('    if (map && length > 0) {')
+             self.emit_memcpy('(const char *)map + offset', 'length')
+-            print '    }'
++            print('    }')
+         if function.name == 'glFlushMappedBufferRangeEXT':
+-            print '    GLvoid *map = NULL;'
+-            print '    _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
+-            print '    if (map && length > 0) {'
++            print('    GLvoid *map = NULL;')
++            print('    _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);')
++            print('    if (map && length > 0) {')
+             self.emit_memcpy('(const char *)map + offset', 'length')
+-            print '    }'
++            print('    }')
+         if function.name == 'glFlushMappedBufferRangeAPPLE':
+-            print '    GLvoid *map = NULL;'
+-            print '    _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
+-            print '    if (map && size > 0) {'
++            print('    GLvoid *map = NULL;')
++            print('    _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);')
++            print('    if (map && size > 0) {')
+             self.emit_memcpy('(const char *)map + offset', 'size')
+-            print '    }'
++            print('    }')
+         if function.name == 'glFlushMappedNamedBufferRange':
+-            print '    GLvoid *map = NULL;'
+-            print '    _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
+-            print '    if (map && length > 0) {'
++            print('    GLvoid *map = NULL;')
++            print('    _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);')
++            print('    if (map && length > 0) {')
+             self.emit_memcpy('(const char *)map + offset', 'length')
+-            print '    }'
++            print('    }')
+         if function.name == 'glFlushMappedNamedBufferRangeEXT':
+-            print '    GLvoid *map = NULL;'
+-            print '    _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
+-            print '    if (map && length > 0) {'
++            print('    GLvoid *map = NULL;')
++            print('    _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);')
++            print('    if (map && length > 0) {')
+             self.emit_memcpy('(const char *)map + offset', 'length')
+-            print '    }'
++            print('    }')
+         # FIXME: We don't support coherent/pinned memory mappings
+         if function.name in ('glBufferStorage', 'glNamedBufferStorage', 'glNamedBufferStorageEXT'):
+-            print r'    if (!(flags & GL_MAP_PERSISTENT_BIT)) {'
+-            print r'        os::log("apitrace: warning: %s: MAP_NOTIFY_EXPLICIT_BIT_VMWX set w/o MAP_PERSISTENT_BIT\n", __FUNCTION__);'
+-            print r'    }'
+-            print r'    flags &= ~GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX;'
++            print(r'    if (!(flags & GL_MAP_PERSISTENT_BIT)) {')
++            print(r'        os::log("apitrace: warning: %s: MAP_NOTIFY_EXPLICIT_BIT_VMWX set w/o MAP_PERSISTENT_BIT\n", __FUNCTION__);')
++            print(r'    }')
++            print(r'    flags &= ~GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX;')
+         if function.name in ('glMapBufferRange', 'glMapBufferRangeEXT', 'glMapNamedBufferRange', 'glMapNamedBufferRangeEXT'):
+-            print r'    if (access & GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX) {'
+-            print r'        if (!(access & GL_MAP_PERSISTENT_BIT)) {'
+-            print r'            os::log("apitrace: warning: %s: MAP_NOTIFY_EXPLICIT_BIT_VMWX set w/o MAP_PERSISTENT_BIT\n", __FUNCTION__);'
+-            print r'        }'
+-            print r'        if (access & GL_MAP_FLUSH_EXPLICIT_BIT) {'
+-            print r'            os::log("apitrace: warning: %s: MAP_NOTIFY_EXPLICIT_BIT_VMWX set w/ MAP_FLUSH_EXPLICIT_BIT\n", __FUNCTION__);'
+-            print r'        }'
+-            print r'        access &= ~GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX;'
+-            print r'    } else if (access & GL_MAP_COHERENT_BIT) {'
+-            print r'        os::log("apitrace: warning: %s: MAP_COHERENT_BIT unsupported (https://github.com/apitrace/apitrace/issues/232)\n", __FUNCTION__);'
+-            print r'    } else if ((access & GL_MAP_PERSISTENT_BIT) &&'
+-            print r'               !(access & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
+-            print r'        os::log("apitrace: warning: %s: MAP_PERSISTENT_BIT w/o FLUSH_EXPLICIT_BIT unsupported (https://github.com/apitrace/apitrace/issues/232)\n", __FUNCTION__);'
+-            print r'    }'
++            print(r'    if (access & GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX) {')
++            print(r'        if (!(access & GL_MAP_PERSISTENT_BIT)) {')
++            print(r'            os::log("apitrace: warning: %s: MAP_NOTIFY_EXPLICIT_BIT_VMWX set w/o MAP_PERSISTENT_BIT\n", __FUNCTION__);')
++            print(r'        }')
++            print(r'        if (access & GL_MAP_FLUSH_EXPLICIT_BIT) {')
++            print(r'            os::log("apitrace: warning: %s: MAP_NOTIFY_EXPLICIT_BIT_VMWX set w/ MAP_FLUSH_EXPLICIT_BIT\n", __FUNCTION__);')
++            print(r'        }')
++            print(r'        access &= ~GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX;')
++            print(r'    } else if (access & GL_MAP_COHERENT_BIT) {')
++            print(r'        os::log("apitrace: warning: %s: MAP_COHERENT_BIT unsupported (https://github.com/apitrace/apitrace/issues/232)\n", __FUNCTION__);')
++            print(r'    } else if ((access & GL_MAP_PERSISTENT_BIT) &&')
++            print(r'               !(access & GL_MAP_FLUSH_EXPLICIT_BIT)) {')
++            print(r'        os::log("apitrace: warning: %s: MAP_PERSISTENT_BIT w/o FLUSH_EXPLICIT_BIT unsupported (https://github.com/apitrace/apitrace/issues/232)\n", __FUNCTION__);')
++            print(r'    }')
+         if function.name in ('glBufferData', 'glBufferDataARB'):
+-            print r'    if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
+-            print r'        os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
+-            print r'    }'
++            print(r'    if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {')
++            print(r'        os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");')
++            print(r'    }')
+         # TODO: We don't track GL_INTEL_map_texture mappings
+         if function.name == 'glMapTexture2DINTEL':
+-            print r'    if (access & GL_MAP_WRITE_BIT) {'
+-            print r'        os::log("apitrace: warning: GL_INTEL_map_texture not fully supported\n");'
+-            print r'    }'
++            print(r'    if (access & GL_MAP_WRITE_BIT) {')
++            print(r'        os::log("apitrace: warning: GL_INTEL_map_texture not fully supported\n");')
++            print(r'    }')
+         # Don't leave vertex attrib locations to chance.  Instead emit fake
+         # glBindAttribLocation calls to ensure that the same locations will be
+@@ -715,40 +715,40 @@ class GlTracer(Tracer):
+         # many entry-points, including non-shader related ones.
+         if function.name == 'glLinkProgram':
+             Tracer.invokeFunction(self, function)
+-            print '    GLint active_attributes = 0;'
+-            print '    _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
+-            print '    for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
+-            print '        GLint size = 0;'
+-            print '        GLenum type = 0;'
+-            print '        GLchar name[256];'
++            print('    GLint active_attributes = 0;')
++            print('    _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);')
++            print('    for (GLint attrib = 0; attrib < active_attributes; ++attrib) {')
++            print('        GLint size = 0;')
++            print('        GLenum type = 0;')
++            print('        GLchar name[256];')
+             # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
+-            print '        _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
+-            print "        if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
+-            print '            GLint location = _glGetAttribLocation(program, name);'
+-            print '            if (location >= 0) {'
++            print('        _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);')
++            print("        if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {")
++            print('            GLint location = _glGetAttribLocation(program, name);')
++            print('            if (location >= 0) {')
+             bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
+             self.fake_call(bind_function, ['program', 'location', 'name'])
+-            print '            }'
+-            print '        }'
+-            print '    }'
++            print('            }')
++            print('        }')
++            print('    }')
+         if function.name == 'glLinkProgramARB':
+             Tracer.invokeFunction(self, function)
+-            print '    GLint active_attributes = 0;'
+-            print '    _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
+-            print '    for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
+-            print '        GLint size = 0;'
+-            print '        GLenum type = 0;'
+-            print '        GLcharARB name[256];'
++            print('    GLint active_attributes = 0;')
++            print('    _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);')
++            print('    for (GLint attrib = 0; attrib < active_attributes; ++attrib) {')
++            print('        GLint size = 0;')
++            print('        GLenum type = 0;')
++            print('        GLcharARB name[256];')
+             # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
+-            print '        _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
+-            print "        if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
+-            print '            GLint location = _glGetAttribLocationARB(programObj, name);'
+-            print '            if (location >= 0) {'
++            print('        _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);')
++            print("        if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {")
++            print('            GLint location = _glGetAttribLocationARB(programObj, name);')
++            print('            if (location >= 0) {')
+             bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
+             self.fake_call(bind_function, ['programObj', 'location', 'name'])
+-            print '            }'
+-            print '        }'
+-            print '    }'
++            print('            }')
++            print('        }')
++            print('    }')
+         self.shadowBufferProlog(function)
+@@ -815,9 +815,9 @@ class GlTracer(Tracer):
+         # Force glProgramBinary to fail.  Per ARB_get_program_binary this
+         # should signal the app that it needs to recompile.
+         if function.name in ('glProgramBinary', 'glProgramBinaryOES'):
+-            print r'   binaryFormat = 0xDEADDEAD;'
+-            print r'   binary = &binaryFormat;'
+-            print r'   length = sizeof binaryFormat;'
++            print(r'   binaryFormat = 0xDEADDEAD;')
++            print(r'   binary = &binaryFormat;')
++            print(r'   length = sizeof binaryFormat;')
+         Tracer.invokeFunction(self, function)
+@@ -838,25 +838,25 @@ class GlTracer(Tracer):
+         # We may be faking KHR_debug, so ensure the pointer queries result is
+         # always zeroed to prevent dereference of unitialized pointers
+         if function.name == 'glGetPointerv':
+-            print '    if (params &&'
+-            print '        (pname == GL_DEBUG_CALLBACK_FUNCTION ||'
+-            print '         pname == GL_DEBUG_CALLBACK_USER_PARAM)) {'
+-            print '        *params = NULL;'
+-            print '    }'
++            print('    if (params &&')
++            print('        (pname == GL_DEBUG_CALLBACK_FUNCTION ||')
++            print('         pname == GL_DEBUG_CALLBACK_USER_PARAM)) {')
++            print('        *params = NULL;')
++            print('    }')
+         if function.name in self.getProcAddressFunctionNames:
+             nameArg = function.args[0].name
+-            print '    if (strcmp("glNotifyMappedBufferRangeVMWX", (const char *)%s) == 0) {' % (nameArg,)
+-            print '        _result = (%s)&glNotifyMappedBufferRangeVMWX;' % (function.type,)
+-            print '    } else if (strcmp("glTexDirectVIV", (const char *)%s) == 0) {' % (nameArg,)
+-            print '        _result = (%s)&glTexDirectVIV;' % (function.type,)
+-            print '    } else if (strcmp("glTexDirectInvalidateVIV", (const char *)%s) == 0) {' % (nameArg,)
+-            print '        _result = (%s)&glTexDirectInvalidateVIV;' % (function.type,)
++            print('    if (strcmp("glNotifyMappedBufferRangeVMWX", (const char *)%s) == 0) {' % (nameArg,))
++            print('        _result = (%s)&glNotifyMappedBufferRangeVMWX;' % (function.type,))
++            print('    } else if (strcmp("glTexDirectVIV", (const char *)%s) == 0) {' % (nameArg,))
++            print('        _result = (%s)&glTexDirectVIV;' % (function.type,))
++            print('    } else if (strcmp("glTexDirectInvalidateVIV", (const char *)%s) == 0) {' % (nameArg,))
++            print('        _result = (%s)&glTexDirectInvalidateVIV;' % (function.type,))
+             for marker_function in self.marker_functions:
+                 if self.api.getFunctionByName(marker_function):
+-                    print '    } else if (strcmp("%s", (const char *)%s) == 0) {' % (marker_function, nameArg)
+-                    print '        _result = (%s)&%s;' % (function.type, marker_function)
+-            print '    } else {'
++                    print('    } else if (strcmp("%s", (const char *)%s) == 0) {' % (marker_function, nameArg))
++                    print('        _result = (%s)&%s;' % (function.type, marker_function))
++            print('    } else {')
+             Tracer.doInvokeFunction(self, function)
+             # Replace function addresses with ours
+@@ -864,24 +864,24 @@ class GlTracer(Tracer):
+             # contain the addresses of the wrapper functions, and not the real
+             # functions, but in practice this should make no difference.
+             if function.name in self.getProcAddressFunctionNames:
+-                print '    _result = _wrapProcAddress(%s, _result);' % (nameArg,)
++                print('    _result = _wrapProcAddress(%s, _result);' % (nameArg,))
+-            print '    }'
++            print('    }')
+             return
+         if function.name in ('glGetProgramBinary', 'glGetProgramBinaryOES'):
+-            print r'    bufSize = 0;'
++            print(r'    bufSize = 0;')
+         Tracer.doInvokeFunction(self, function)
+         if function.name == 'glGetProgramiv':
+-            print r'    if (params && pname == GL_PROGRAM_BINARY_LENGTH) {'
+-            print r'        *params = 0;'
+-            print r'    }'
++            print(r'    if (params && pname == GL_PROGRAM_BINARY_LENGTH) {')
++            print(r'        *params = 0;')
++            print(r'    }')
+         if function.name in ('glGetProgramBinary', 'glGetProgramBinaryOES'):
+-            print r'    if (length) {'
+-            print r'        *length = 0;'
+-            print r'    }'
++            print(r'    if (length) {')
++            print(r'        *length = 0;')
++            print(r'    }')
+     buffer_targets = [
+         'ARRAY_BUFFER',
+@@ -902,9 +902,9 @@ class GlTracer(Tracer):
+         # Keep track of buffer mappings
+         if function.name in ('glMapBufferRange', 'glMapBufferRangeEXT'):
+-            print '    if (access & GL_MAP_WRITE_BIT) {'
+-            print '        _checkBufferMapRange = true;'
+-            print '    }'
++            print('    if (access & GL_MAP_WRITE_BIT) {')
++            print('        _checkBufferMapRange = true;')
++            print('    }')
+     boolean_names = [
+         'GL_FALSE',
+@@ -932,17 +932,17 @@ class GlTracer(Tracer):
+            and (isinstance(arg.type, stdapi.Blob) \
+                 or (isinstance(arg.type, stdapi.Const) \
+                     and isinstance(arg.type.type, stdapi.Blob))):
+-            print '    {'
+-            print '        gltrace::Context *ctx = gltrace::getContext();'
+-            print '        GLint _unpack_buffer = 0;'
+-            print '        if (ctx->profile.desktop())'
+-            print '            _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
+-            print '        if (_unpack_buffer) {'
+-            print '            trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
+-            print '        } else {'
++            print('    {')
++            print('        gltrace::Context *ctx = gltrace::getContext();')
++            print('        GLint _unpack_buffer = 0;')
++            print('        if (ctx->profile.desktop())')
++            print('            _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);')
++            print('        if (_unpack_buffer) {')
++            print('            trace::localWriter.writePointer((uintptr_t)%s);' % arg.name)
++            print('        } else {')
+             Tracer.serializeArgValue(self, function, arg)
+-            print '        }'
+-            print '    }'
++            print('        }')
++            print('    }')
+             return
+         # Several GL state functions take GLenum symbolic names as
+@@ -953,11 +953,11 @@ class GlTracer(Tracer):
+             assert arg.index > 0
+             assert function.args[arg.index - 1].name == 'pname'
+             assert function.args[arg.index - 1].type == glapi.GLenum
+-            print '    if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
++            print('    if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name)
+             self.serializeValue(glapi.GLenum, arg.name)
+-            print '    } else {'
++            print('    } else {')
+             Tracer.serializeArgValue(self, function, arg)
+-            print '    }'
++            print('    }')
+             return
+         Tracer.serializeArgValue(self, function, arg)
+@@ -967,20 +967,20 @@ class GlTracer(Tracer):
+         # A simple state tracker to track the pointer values
+         # update the state
+-        print 'static void _trace_user_arrays(GLuint count)'
+-        print '{'
+-        print '    gltrace::Context *ctx = gltrace::getContext();'
+-        print
+-        print '    glprofile::Profile profile = ctx->profile;'
+-        print '    bool es1 = profile.es() && profile.major == 1;'
+-        print
++        print('static void _trace_user_arrays(GLuint count)')
++        print('{')
++        print('    gltrace::Context *ctx = gltrace::getContext();')
++        print()
++        print('    glprofile::Profile profile = ctx->profile;')
++        print('    bool es1 = profile.es() && profile.major == 1;')
++        print()
+         # Temporarily unbind the array buffer
+-        print '    GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
+-        print '    if (_array_buffer) {'
++        print('    GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);')
++        print('    if (_array_buffer) {')
+         self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
+-        print '    }'
+-        print
++        print('    }')
++        print()
+         for camelcase_name, uppercase_name in self.arrays:
+             # in which profile is the array available?
+@@ -993,45 +993,45 @@ class GlTracer(Tracer):
+             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
+             function = api.getFunctionByName(function_name)
+-            print '    // %s' % function.prototype()
+-            print '  if (%s) {' % profile_check
++            print('    // %s' % function.prototype())
++            print('  if (%s) {' % profile_check)
+             self.array_trace_prolog(api, uppercase_name)
+             self.array_prolog(api, uppercase_name)
+-            print '    if (_glIsEnabled(%s)) {' % enable_name
+-            print '        GLint _binding = _glGetInteger(%s);' % binding_name
+-            print '        if (!_binding) {'
++            print('    if (_glIsEnabled(%s)) {' % enable_name)
++            print('        GLint _binding = _glGetInteger(%s);' % binding_name)
++            print('        if (!_binding) {')
+             # Get the arguments via glGet*
+             for arg in function.args:
+                 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
+                 arg_get_function, arg_type = TypeGetter().visit(arg.type)
+-                print '            %s %s = 0;' % (arg_type, arg.name)
+-                print '            _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
++                print('            %s %s = 0;' % (arg_type, arg.name))
++                print('            _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name))
+             
+             arg_names = ', '.join([arg.name for arg in function.args[:-1]])
+-            print '            size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
++            print('            size_t _size = _%s_size(%s, count);' % (function.name, arg_names))
+             # Emit a fake function
+             self.array_trace_intermezzo(api, uppercase_name)
+-            print '            unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
++            print('            unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,))
+             for arg in function.args:
+                 assert not arg.output
+-                print '            trace::localWriter.beginArg(%u);' % (arg.index,)
++                print('            trace::localWriter.beginArg(%u);' % (arg.index,))
+                 if arg.name != 'pointer':
+                     self.serializeValue(arg.type, arg.name)
+                 else:
+-                    print '            trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
+-                print '            trace::localWriter.endArg();'
++                    print('            trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name))
++                print('            trace::localWriter.endArg();')
+             
+-            print '            trace::localWriter.endEnter();'
+-            print '            trace::localWriter.beginLeave(_call);'
+-            print '            trace::localWriter.endLeave();'
+-            print '        }'
+-            print '    }'
++            print('            trace::localWriter.endEnter();')
++            print('            trace::localWriter.beginLeave(_call);')
++            print('            trace::localWriter.endLeave();')
++            print('        }')
++            print('    }')
+             self.array_epilog(api, uppercase_name)
+             self.array_trace_epilog(api, uppercase_name)
+-            print '  }'
+-            print
++            print('  }')
++            print()
+         # Samething, but for glVertexAttribPointer*
+         #
+@@ -1043,12 +1043,12 @@ class GlTracer(Tracer):
+         # This means that the implementations of these functions do not always
+         # alias, and they need to be considered independently.
+         #
+-        print '    // ES1 does not support generic vertex attributes'
+-        print '    if (es1)'
+-        print '        return;'
+-        print
+-        print '    vertex_attrib _vertex_attrib = _get_vertex_attrib();'
+-        print
++        print('    // ES1 does not support generic vertex attributes')
++        print('    if (es1)')
++        print('        return;')
++        print()
++        print('    vertex_attrib _vertex_attrib = _get_vertex_attrib();')
++        print()
+         for suffix in ['', 'NV']:
+             if suffix:
+                 SUFFIX = '_' + suffix
+@@ -1057,24 +1057,24 @@ class GlTracer(Tracer):
+             function_name = 'glVertexAttribPointer' + suffix
+             function = api.getFunctionByName(function_name)
+-            print '    // %s' % function.prototype()
+-            print '    if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
++            print('    // %s' % function.prototype())
++            print('    if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX)
+             if suffix == 'NV':
+-                print '        GLint _max_vertex_attribs = 16;'
++                print('        GLint _max_vertex_attribs = 16;')
+             else:
+-                print '        GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
+-            print '        for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
+-            print '            GLint _enabled = 0;'
++                print('        GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);')
++            print('        for (GLint index = 0; index < _max_vertex_attribs; ++index) {')
++            print('            GLint _enabled = 0;')
+             if suffix == 'NV':
+-                print '            _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
++                print('            _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);')
+             else:
+-                print '            _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
+-            print '            if (_enabled) {'
+-            print '                GLint _binding = 0;'
++                print('            _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX))
++            print('            if (_enabled) {')
++            print('                GLint _binding = 0;')
+             if suffix != 'NV':
+                 # It doesn't seem possible to use VBOs with NV_vertex_program.
+-                print '                _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
+-            print '                if (!_binding) {'
++                print('                _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX))
++            print('                if (!_binding) {')
+             # Get the arguments via glGet*
+             for arg in function.args[1:]:
+@@ -1083,40 +1083,40 @@ class GlTracer(Tracer):
+                 else:
+                     arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
+                 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
+-                print '                    %s %s = 0;' % (arg_type, arg.name)
+-                print '                    _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
++                print('                    %s %s = 0;' % (arg_type, arg.name))
++                print('                    _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name))
+             
+             arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
+-            print '                    size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
++            print('                    size_t _size = _%s_size(%s, count);' % (function.name, arg_names))
+             # Emit a fake function
+-            print '                    unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
++            print('                    unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,))
+             for arg in function.args:
+                 assert not arg.output
+-                print '                    trace::localWriter.beginArg(%u);' % (arg.index,)
++                print('                    trace::localWriter.beginArg(%u);' % (arg.index,))
+                 if arg.name != 'pointer':
+                     self.serializeValue(arg.type, arg.name)
+                 else:
+-                    print '                    trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
+-                print '                    trace::localWriter.endArg();'
++                    print('                    trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name))
++                print('                    trace::localWriter.endArg();')
+             
+-            print '                    trace::localWriter.endEnter();'
+-            print '                    trace::localWriter.beginLeave(_call);'
+-            print '                    trace::localWriter.endLeave();'
+-            print '                }'
+-            print '            }'
+-            print '        }'
+-            print '    }'
+-            print
++            print('                    trace::localWriter.endEnter();')
++            print('                    trace::localWriter.beginLeave(_call);')
++            print('                    trace::localWriter.endLeave();')
++            print('                }')
++            print('            }')
++            print('        }')
++            print('    }')
++            print()
+         # Restore the original array_buffer
+-        print '    if (_array_buffer) {'
++        print('    if (_array_buffer) {')
+         self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
+-        print '    }'
+-        print
++        print('    }')
++        print()
+-        print '}'
+-        print
++        print('}')
++        print()
+     #
+     # Hooks for glTexCoordPointer, which is identical to the other array
+@@ -1125,49 +1125,49 @@ class GlTracer(Tracer):
+     def array_prolog(self, api, uppercase_name):
+         if uppercase_name == 'TEXTURE_COORD':
+-            print '    GLint max_units = 0;'
+-            print '    if (ctx->profile.desktop())'
+-            print '        _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_units);'
+-            print '    else'
+-            print '        _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_units);'
+-            print '    GLint client_active_texture = GL_TEXTURE0;'
+-            print '    if (max_units > 0) {'
+-            print '        _glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
+-            print '    }'
+-            print '    GLint unit = 0;'
+-            print '    do {'
+-            print '        GLint texture = GL_TEXTURE0 + unit;'
+-            print '        if (max_units > 0) {'
+-            print '            _glClientActiveTexture(texture);'
+-            print '        }'
++            print('    GLint max_units = 0;')
++            print('    if (ctx->profile.desktop())')
++            print('        _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_units);')
++            print('    else')
++            print('        _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_units);')
++            print('    GLint client_active_texture = GL_TEXTURE0;')
++            print('    if (max_units > 0) {')
++            print('        _glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);')
++            print('    }')
++            print('    GLint unit = 0;')
++            print('    do {')
++            print('        GLint texture = GL_TEXTURE0 + unit;')
++            print('        if (max_units > 0) {')
++            print('            _glClientActiveTexture(texture);')
++            print('        }')
+     def array_trace_prolog(self, api, uppercase_name):
+         if uppercase_name == 'TEXTURE_COORD':
+-            print '    bool client_active_texture_dirty = false;'
++            print('    bool client_active_texture_dirty = false;')
+     def array_epilog(self, api, uppercase_name):
+         if uppercase_name == 'TEXTURE_COORD':
+-            print '    } while (++unit < max_units);'
++            print('    } while (++unit < max_units);')
+         self.array_cleanup(api, uppercase_name)
+     def array_cleanup(self, api, uppercase_name):
+         if uppercase_name == 'TEXTURE_COORD':
+-            print '    if (max_units > 0) {'
+-            print '        _glClientActiveTexture(client_active_texture);'
+-            print '    }'
++            print('    if (max_units > 0) {')
++            print('        _glClientActiveTexture(client_active_texture);')
++            print('    }')
+         
+     def array_trace_intermezzo(self, api, uppercase_name):
+         if uppercase_name == 'TEXTURE_COORD':
+-            print '    if (texture != client_active_texture || client_active_texture_dirty) {'
+-            print '        client_active_texture_dirty = true;'
++            print('    if (texture != client_active_texture || client_active_texture_dirty) {')
++            print('        client_active_texture_dirty = true;')
+             self.fake_glClientActiveTexture_call(api, "texture");
+-            print '    }'
++            print('    }')
+     def array_trace_epilog(self, api, uppercase_name):
+         if uppercase_name == 'TEXTURE_COORD':
+-            print '    if (client_active_texture_dirty) {'
++            print('    if (client_active_texture_dirty) {')
+             self.fake_glClientActiveTexture_call(api, "client_active_texture");
+-            print '    }'
++            print('    }')
+     def fake_glBindBuffer(self, api, target, buffer):
+         function = api.getFunctionByName('glBindBuffer')
+@@ -1180,13 +1180,13 @@ class GlTracer(Tracer):
+     def emitFakeTexture2D(self):
+         function = glapi.glapi.getFunctionByName('glTexImage2D')
+         instances = function.argNames()
+-        print '        unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
++        print('        unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,))
+         for arg in function.args:
+             assert not arg.output
+             self.serializeArg(function, arg)
+-        print '        trace::localWriter.endEnter();'
+-        print '        trace::localWriter.beginLeave(_fake_call);'
+-        print '        trace::localWriter.endLeave();'
++        print('        trace::localWriter.endEnter();')
++        print('        trace::localWriter.beginLeave(_fake_call);')
++        print('        trace::localWriter.endLeave();')
+diff --git a/wrappers/glxtrace.py b/wrappers/glxtrace.py
+index f35d1fe9..b05028e2 100644
+--- a/wrappers/glxtrace.py
++++ b/wrappers/glxtrace.py
+@@ -64,7 +64,7 @@ class GlxTracer(GlTracer):
+     def traceFunctionImplBody(self, function):
+         if function.name in self.destroyContextFunctionNames:
+-            print '    gltrace::releaseContext((uintptr_t)ctx);'
++            print('    gltrace::releaseContext((uintptr_t)ctx);')
+         if function.name == 'glXGetCurrentDisplay':
+             print '    if(_glXGetCurrentDisplay == &glXGetCurrentDisplay ){'
+@@ -74,16 +74,16 @@ class GlxTracer(GlTracer):
+         GlTracer.traceFunctionImplBody(self, function)
+         if function.name in self.createContextFunctionNames:
+-            print '    if (_result != NULL)'
+-            print '        gltrace::createContext((uintptr_t)_result);'
++            print('    if (_result != NULL)')
++            print('        gltrace::createContext((uintptr_t)_result);')
+         if function.name in self.makeCurrentFunctionNames:
+-            print '    if (_result) {'
+-            print '        if (ctx != NULL)'
+-            print '            gltrace::setContext((uintptr_t)ctx);'
+-            print '        else'
+-            print '            gltrace::clearContext();'
+-            print '    }'
++            print('    if (_result) {')
++            print('        if (ctx != NULL)')
++            print('            gltrace::setContext((uintptr_t)ctx);')
++            print('        else')
++            print('            gltrace::clearContext();')
++            print('    }')
+         if function.name == 'glXBindTexImageEXT':
+             # FIXME: glXBindTexImageEXT gets called frequently, so we should
+@@ -92,7 +92,7 @@ class GlxTracer(GlTracer):
+             #   emit emitFakeTexture2D when it changes
+             # - keep a global hash of the pixels
+             # FIXME: Handle mipmaps
+-            print r'''
++            print(r'''
+                 unsigned glx_target = 0;
+                 _glXQueryDrawable(display, drawable, GLX_TEXTURE_TARGET_EXT, &glx_target);
+                 GLenum target;
+@@ -152,29 +152,29 @@ class GlxTracer(GlTracer):
+                     GLint row_stride = _align(width * 4, alignment);
+                     GLvoid * pixels = malloc(height * row_stride);
+                     _glGetTexImage(target, level, format, type, pixels);
+-            '''
++            ''')
+             self.emitFakeTexture2D()
+-            print r'''
++            print(r'''
+                     free(pixels);
+                 }
+-            '''
++            ''')
+ if __name__ == '__main__':
+-    print
+-    print '#include <stdlib.h>'
+-    print '#include <string.h>'
+-    print
+-    print '#include "trace_writer_local.hpp"'
+-    print
+-    print '// To validate our prototypes'
+-    print '#define GL_GLEXT_PROTOTYPES'
+-    print '#define GLX_GLXEXT_PROTOTYPES'
+-    print
+-    print '#include "dlopen.hpp"'
+-    print '#include "glproc.hpp"'
+-    print '#include "glsize.hpp"'
+-    print
++    print()
++    print('#include <stdlib.h>')
++    print('#include <string.h>')
++    print()
++    print('#include "trace_writer_local.hpp"')
++    print()
++    print('// To validate our prototypes')
++    print('#define GL_GLEXT_PROTOTYPES')
++    print('#define GLX_GLXEXT_PROTOTYPES')
++    print()
++    print('#include "dlopen.hpp"')
++    print('#include "glproc.hpp"')
++    print('#include "glsize.hpp"')
++    print()
+     module = Module()
+     module.mergeModule(glxapi)
+diff --git a/wrappers/trace.py b/wrappers/trace.py
+index 7d1baa10..318f0990 100644
+--- a/wrappers/trace.py
++++ b/wrappers/trace.py
+@@ -69,21 +69,21 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
+     def visitStruct(self, struct):
+         # Ensure member array has nonzero length to avoid MSVC error C2466
+-        print 'static const char * _struct%s_members[%u] = {' % (struct.tag, max(len(struct.members), 1))
++        print('static const char * _struct%s_members[%u] = {' % (struct.tag, max(len(struct.members), 1)))
+         for type, name,  in struct.members:
+             if name is None:
+-                print '    "",'
++                print('    "",')
+             else:
+-                print '    "%s",' % (name,)
+-        print '};'
+-        print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
++                print('    "%s",' % (name,))
++        print('};')
++        print('static const trace::StructSig _struct%s_sig = {' % (struct.tag,))
+         if struct.name is None:
+             structName = '""'
+         else:
+             structName = '"%s"' % struct.name
+-        print '    %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
+-        print '};'
+-        print
++        print('    %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag))
++        print('};')
++        print()
+     def visitArray(self, array):
+         self.visit(array.type)
+@@ -95,26 +95,26 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
+         pass
+     def visitEnum(self, enum):
+-        print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
++        print('static const trace::EnumValue _enum%s_values[] = {' % (enum.tag))
+         for value in enum.values:
+-            print '    {"%s", %s},' % (value, value)
+-        print '};'
+-        print
+-        print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
+-        print '    %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
+-        print '};'
+-        print
++            print('    {"%s", %s},' % (value, value))
++        print('};')
++        print()
++        print('static const trace::EnumSig _enum%s_sig = {' % (enum.tag))
++        print('    %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag))
++        print('};')
++        print()
+     def visitBitmask(self, bitmask):
+-        print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
++        print('static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag))
+         for value in bitmask.values:
+-            print '    {"%s", %s},' % (value, value)
+-        print '};'
+-        print
+-        print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
+-        print '    %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
+-        print '};'
+-        print
++            print('    {"%s", %s},' % (value, value))
++        print('};')
++        print()
++        print('static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag))
++        print('    %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag))
++        print('};')
++        print()
+     def visitPointer(self, pointer):
+         self.visit(pointer.type)
+@@ -146,16 +146,16 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
+     def visitPolymorphic(self, polymorphic):
+         if not polymorphic.contextLess:
+             return
+-        print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
+-        print '    switch (selector) {'
++        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:
+-                print '    %s:' % case
++                print('    %s:' % case)
+             self.serializer.visit(type, '(%s)(value)' % (type,))
+-            print '        break;'
+-        print '    }'
+-        print '}'
+-        print
++            print('        break;')
++        print('    }')
++        print('}')
++        print()
+ class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
+@@ -167,7 +167,7 @@ class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
+     '''
+     def visitLiteral(self, literal, instance):
+-        print '    trace::localWriter.write%s(%s);' % (literal.kind, instance)
++        print('    trace::localWriter.write%s(%s);' % (literal.kind, instance))
+     def visitString(self, string, instance):
+         if not string.wide:
+@@ -183,33 +183,33 @@ class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
+             length = ', %s' % self.expand(string.length)
+         else:
+             length = ''
+-        print '    trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
++        print('    trace::localWriter.write%s(%s%s);' % (suffix, instance, length))
+     def visitConst(self, const, instance):
+         self.visit(const.type, instance)
+     def visitStruct(self, struct, instance):
+-        print '    trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
++        print('    trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,))
+         for member in struct.members:
+             self.visitMember(member, instance)
+-        print '    trace::localWriter.endStruct();'
++        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 '        trace::localWriter.beginArray(%s);' % length
+-        print '        for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
+-        print '            trace::localWriter.beginElement();'
++        print('    if (%s) {' % instance)
++        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.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
+-        print '            trace::localWriter.endElement();'
+-        print '        }'
+-        print '        trace::localWriter.endArray();'
+-        print '    } else {'
+-        print '        trace::localWriter.writeNull();'
+-        print '    }'
++        print('            trace::localWriter.endElement();')
++        print('        }')
++        print('        trace::localWriter.endArray();')
++        print('    } else {')
++        print('        trace::localWriter.writeNull();')
++        print('    }')
+     def visitAttribArray(self, array, instance):
+         # For each element, decide if it is a key or a value (which depends on the previous key).
+@@ -218,90 +218,90 @@ class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
+         # determine the array length which must be passed to writeArray() up front
+         count = '_c' + array.baseType.tag
+-        print '    {'
+-        print '    int %s;' % count
+-        print '    for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
+-              % {'c': count, 'array': instance, 'terminator': array.terminator}
++        print('    {')
++        print('    int %s;' % count)
++        print('    for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
++              % {'c': count, 'array': instance, 'terminator': array.terminator})
+         if array.hasKeysWithoutValues:
+-            print '        switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count}
++            print('        switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count})
+             for key, valueType in array.valueTypes:
+                 if valueType is None:
+-                    print '        case %s:' % key
+-            print '            %s--;' % count # the next value is a key again and checked if it's the terminator
+-            print '            break;'
+-            print '        }'
+-        print '    }'
+-        print '    %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance}
+-        print '    trace::localWriter.beginArray(%s);' % count
++                    print('        case %s:' % key)
++            print('            %s--;' % count) # the next value is a key again and checked if it's the terminator
++            print('            break;')
++            print('        }')
++        print('    }')
++        print('    %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance})
++        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.baseType.tag
+-        print '    for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
+-        print '        trace::localWriter.beginElement();'
++        print('    for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count})
++        print('        trace::localWriter.beginElement();')
+         self.visit(array.baseType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
+-        print '        trace::localWriter.endElement();'
+-        print '        if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count}
+-        print '            break;'
+-        print '        }'
+-        print '        switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index}
++        print('        trace::localWriter.endElement();')
++        print('        if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count})
++        print('            break;')
++        print('        }')
++        print('        switch (int(%(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 '            trace::localWriter.beginElement();'
++                print('        case %s:' % key)
++                print('            trace::localWriter.beginElement();')
+                 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
+-                print '            trace::localWriter.endElement();'
+-                print '            break;'
++                print('            trace::localWriter.endElement();')
++                print('            break;')
+         # known key with no value, just decrease the index so we treat the next value as a key
+         if array.hasKeysWithoutValues:
+             for key, valueType in array.valueTypes:
+                 if valueType is None:
+-                    print '        case %s:' % key
+-            print '            %s--;' % index
+-            print '            break;'
++                    print('        case %s:' % key)
++            print('            %s--;' % index)
++            print('            break;')
+         # unknown key, write an int value
+-        print '        default:'
+-        print '            trace::localWriter.beginElement();'
+-        print '            os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
+-                           '__FUNCTION__, int(%(array)s[%(i)s - 1]));'  % {'array': instance, 'i': index}
+-        print '            trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
+-        print '            trace::localWriter.endElement();'
+-        print '            break;'
+-        print '        }'
+-        print '    }'
+-        print '    trace::localWriter.endArray();'
+-        print '    }'
++        print('        default:')
++        print('            trace::localWriter.beginElement();')
++        print('            os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
++                           '__FUNCTION__, int(%(array)s[%(i)s - 1]));'  % {'array': instance, 'i': index})
++        print('            trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index})
++        print('            trace::localWriter.endElement();')
++        print('            break;')
++        print('        }')
++        print('    }')
++        print('    trace::localWriter.endArray();')
++        print('    }')
+     def visitBlob(self, blob, instance):
+-        print '    trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
++        print('    trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size)))
+     def visitEnum(self, enum, instance):
+-        print '    trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
++        print('    trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance))
+     def visitBitmask(self, bitmask, instance):
+-        print '    trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
++        print('    trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance))
+     def visitPointer(self, pointer, instance):
+-        print '    if (%s) {' % instance
+-        print '        trace::localWriter.beginArray(1);'
+-        print '        trace::localWriter.beginElement();'
++        print('    if (%s) {' % instance)
++        print('        trace::localWriter.beginArray(1);')
++        print('        trace::localWriter.beginElement();')
+         self.visit(pointer.type, "*" + instance)
+-        print '        trace::localWriter.endElement();'
+-        print '        trace::localWriter.endArray();'
+-        print '    } else {'
+-        print '        trace::localWriter.writeNull();'
+-        print '    }'
++        print('        trace::localWriter.endElement();')
++        print('        trace::localWriter.endArray();')
++        print('    } else {')
++        print('        trace::localWriter.writeNull();')
++        print('    }')
+     def visitIntPointer(self, pointer, instance):
+-        print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
++        print('    trace::localWriter.writePointer((uintptr_t)%s);' % instance)
+     def visitObjPointer(self, pointer, instance):
+-        print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
++        print('    trace::localWriter.writePointer((uintptr_t)%s);' % instance)
+     def visitLinearPointer(self, pointer, instance):
+-        print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
++        print('    trace::localWriter.writePointer((uintptr_t)%s);' % instance)
+     def visitReference(self, reference, instance):
+         self.visit(reference.type, instance)
+@@ -313,31 +313,31 @@ class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
+         self.visit(alias.type, instance)
+     def visitOpaque(self, opaque, instance):
+-        print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
++        print('    trace::localWriter.writePointer((uintptr_t)%s);' % instance)
+     def visitInterface(self, interface, instance):
+         assert False
+     def visitPolymorphic(self, polymorphic, instance):
+         if polymorphic.contextLess:
+-            print '    _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
++            print('    _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance))
+         else:
+             switchExpr = self.expand(polymorphic.switchExpr)
+-            print '    switch (%s) {' % switchExpr
++            print('    switch (%s) {' % switchExpr)
+             for cases, type in polymorphic.iterSwitch():
+                 for case in cases:
+-                    print '    %s:' % case
++                    print('    %s:' % case)
+                 caseInstance = instance
+                 if type.expr is not None:
+                     caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
+                 self.visit(type, caseInstance)
+-                print '        break;'
++                print('        break;')
+             if polymorphic.defaultType is None:
+-                print r'    default:'
+-                print r'        os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
+-                print r'        trace::localWriter.writeNull();'
+-                print r'        break;'
+-            print '    }'
++                print(r'    default:')
++                print(r'        os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,))
++                print(r'        trace::localWriter.writeNull();')
++                print(r'        break;')
++            print('    }')
+ class WrapDecider(stdapi.Traverser):
+@@ -369,16 +369,16 @@ class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
+     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
++        print("    if (%s) {" % instance)
++        print("        for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length)
+         self.visitElement('_i', array.type, instance + "[_i]")
+-        print "        }"
+-        print "    }"
++        print("        }")
++        print("    }")
+     def visitPointer(self, pointer, instance):
+-        print "    if (%s) {" % instance
++        print("    if (%s) {" % instance)
+         self.visit(pointer.type, "*" + instance)
+-        print "    }"
++        print("    }")
+     
+     def visitObjPointer(self, pointer, instance):
+         elem_type = pointer.type.mutable()
+@@ -388,13 +388,13 @@ class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
+             self.visitInterfacePointer(elem_type.type, instance)
+         else:
+             # All interfaces should at least implement IUnknown
+-            print "    WrapIUnknown::_wrap(__FUNCTION__, (IUnknown **) &%s);" % (instance,)
++            print("    WrapIUnknown::_wrap(__FUNCTION__, (IUnknown **) &%s);" % (instance,))
+     
+     def visitInterface(self, interface, instance):
+         raise NotImplementedError
+     def visitInterfacePointer(self, interface, instance):
+-        print "    Wrap%s::_wrap(__FUNCTION__, &%s);" % (interface.name, instance)
++        print("    Wrap%s::_wrap(__FUNCTION__, &%s);" % (interface.name, instance))
+     
+     def visitPolymorphic(self, type, instance):
+         # XXX: There might be polymorphic values that need wrapping in the future
+@@ -409,17 +409,17 @@ class ValueUnwrapper(ValueWrapper):
+     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,)
++            print('    {')
++            print("        %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct))
++            print('        *_t = %s;' % (instance,))
+             assert instance.startswith('*')
+-            print '        %s = _t;' % (instance[1:],)
++            print('        %s = _t;' % (instance[1:],))
+             instance = '*_t'
+             self.allocated = True
+             try:
+                 return ValueWrapper.visitStruct(self, struct, instance)
+             finally:
+-                print '    }'
++                print('    }')
+         else:
+             return ValueWrapper.visitStruct(self, struct, instance)
+@@ -428,18 +428,18 @@ class ValueUnwrapper(ValueWrapper):
+             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 "            _t[_i] = %s[_i];" % instance 
++        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]")
+-        print "        }"
+-        print "        %s = _t;" % instance
+-        print "    }"
++        print("        }")
++        print("        %s = _t;" % instance)
++        print("    }")
+     def visitInterfacePointer(self, interface, instance):
+-        print r'    Wrap%s::_unwrap(__FUNCTION__, &%s);' % (interface.name, instance)
++        print(r'    Wrap%s::_unwrap(__FUNCTION__, &%s);' % (interface.name, instance))
+ def _getInterfaceHierarchy(allIfaces, baseIface, result):
+@@ -479,14 +479,17 @@ class Tracer:
+         # Includes
+         for module in api.modules:
+             for header in module.headers:
+-                print header
+-        print
++                print(header)
++        print()
+         # Generate the serializer functions
+         types = api.getAllTypes()
+         visitor = ComplexValueSerializer(self.serializerFactory())
+-        map(visitor.visit, types)
+-        print
++        
++        for tp in types:
++            visitor.visit(tp)
++        
++        print()
+         # Interfaces wrapers
+         self.traceInterfaces(api)
+@@ -498,22 +501,22 @@ class Tracer:
+             self.traceFunctionDecl(function)
+         for function in api.getAllFunctions():
+             self.traceFunctionImpl(function)
+-        print
++        print()
+         self.footer(api)
+     def header(self, api):
+-        print '#ifdef _WIN32'
+-        print '#  include <malloc.h> // alloca'
+-        print '#  ifndef alloca'
+-        print '#    define alloca _alloca'
+-        print '#  endif'
+-        print '#else'
+-        print '#  include <alloca.h> // alloca'
+-        print '#endif'
+-        print
+-        print
+-        print 'static std::map<void *, void *> g_WrappedObjects;'
++        print('#ifdef _WIN32')
++        print('#  include <malloc.h> // alloca')
++        print('#  ifndef alloca')
++        print('#    define alloca _alloca')
++        print('#  endif')
++        print('#else')
++        print('#  include <alloca.h> // alloca')
++        print('#endif')
++        print()
++        print()
++        print('static std::map<void *, void *> g_WrappedObjects;')
+     def footer(self, api):
+         pass
+@@ -523,11 +526,11 @@ class Tracer:
+         if not function.internal:
+             if function.args:
+-                print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
++                print('static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args])))
+             else:
+-                print 'static const char ** _%s_args = NULL;' % (function.name,)
+-            print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, self.getFunctionSigId(), function.name, len(function.args), function.name)
+-            print
++                print('static const char ** _%s_args = NULL;' % (function.name,))
++            print('static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, self.getFunctionSigId(), function.sigName(), len(function.args), function.name))
++            print()
+     def getFunctionSigId(self):
+         id = Tracer.__id
+@@ -539,12 +542,12 @@ class Tracer:
+     def traceFunctionImpl(self, function):
+         if self.isFunctionPublic(function):
+-            print 'extern "C" PUBLIC'
++            print('extern "C" PUBLIC')
+         else:
+-            print 'extern "C" PRIVATE'
+-        print function.prototype() + ' {'
++            print('extern "C" PRIVATE')
++        print(function.prototype() + ' {')
+         if function.type is not stdapi.Void:
+-            print '    %s _result;' % function.type
++            print('    %s _result;' % function.type)
+         for arg in function.args:
+             if not arg.output:
+@@ -555,43 +558,43 @@ class Tracer:
+         # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
+         if function.type is not stdapi.Void:
+-            print '    return _result;'
++            print('    return _result;')
+-        print '}'
+-        print
++        print('}')
++        print()
+     def traceFunctionImplBody(self, function):
+         multi_draw_function_regex = re.compile(r'^glMultiDraw(Arrays|Elements)([A-Z][a-zA-Z]*)?$' )
+         if not function.internal:
+-            print '    unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
++            print('    unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,))
+             for arg in function.args:
+                 if not arg.output:
+                     self.serializeArg(function, arg)
+-            print '    trace::localWriter.endEnter();'
++            print('    trace::localWriter.endEnter();')
+         if self.multi_draw_function_regex.match(function.name):
+-            print '    trace::localWriter.beginIgnore();'
+-            print '    trace::localWriter.endIgnore();'
++            print('    trace::localWriter.beginIgnore();')
++            print('    trace::localWriter.endEnter();')
+         self.invokeFunction(function)
+         if self.multi_draw_function_regex.match(function.name):
+-            print '    trace::localWriter.beginTrace();'
+-            print '    trace::localWriter.endTrace();'
++            print('    trace::localWriter.beginTrace();')
++            print('    trace::localWriter.endTrace();')
+         if not function.internal:
+-            print '    trace::localWriter.beginLeave(_call);'
+-            print '    if (%s) {' % self.wasFunctionSuccessful(function)
++            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 '    }'
++            print('    }')
+             if function.type is not stdapi.Void:
+                 self.serializeRet(function, "_result")
+             if function.type is not stdapi.Void:
+                 self.wrapRet(function, "_result")
+-            print '    trace::localWriter.endLeave();'
++            print('    trace::localWriter.endLeave();')
+     def invokeFunction(self, function):
+         self.doInvokeFunction(function)
+@@ -603,7 +606,7 @@ class Tracer:
+         else:
+             result = '_result = '
+         dispatch = prefix + function.name + suffix
+-        print '    %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
++        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:
+@@ -613,9 +616,9 @@ class Tracer:
+         return 'true'
+     def serializeArg(self, function, arg):
+-        print '    trace::localWriter.beginArg(%u);' % (arg.index,)
++        print('    trace::localWriter.beginArg(%u);' % (arg.index,))
+         self.serializeArgValue(function, arg)
+-        print '    trace::localWriter.endArg();'
++        print('    trace::localWriter.endArg();')
+     def serializeArgValue(self, function, arg):
+         self.serializeValue(arg.type, arg.name)
+@@ -641,9 +644,9 @@ class Tracer:
+         self.unwrapValue(arg.type, arg.name)
+     def serializeRet(self, function, instance):
+-        print '    trace::localWriter.beginReturn();'
++        print('    trace::localWriter.beginReturn();')
+         self.serializeValue(function.type, instance)
+-        print '    trace::localWriter.endReturn();'
++        print('    trace::localWriter.endReturn();')
+     def serializeValue(self, type, instance):
+         serializer = self.serializerFactory()
+@@ -672,70 +675,72 @@ class Tracer:
+         if not interfaces:
+             return
+-        print r'#include "guids.hpp"'
+-        print
++        print(r'#include "guids.hpp"')
++        print()
+         map(self.declareWrapperInterface, interfaces)
+         # Helper functions to wrap/unwrap interface pointers
+-        print r'static inline bool'
+-        print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
+-        print r'    IUnknown *pObj = NULL;'
+-        print r'    HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
+-        print r'    if (FAILED(hr)) {'
+-        print r'        return false;'
+-        print r'    }'
+-        print r'    assert(pObj);'
+-        print r'    pObj->Release();'
+-        print r'    return pUnknown == pObj;'
+-        print r'}'
+-        print
+-        print r'static inline const void *'
+-        print r'getVtbl(const void *pvObj) {'
+-        print r'    return pvObj ? *(const void **)pvObj : NULL;'
+-        print r'}'
+-        print
++        print(r'static inline bool')
++        print(r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {')
++        print(r'    IUnknown *pObj = NULL;')
++        print(r'    HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);')
++        print(r'    if (FAILED(hr)) {')
++        print(r'        return false;')
++        print(r'    }')
++        print(r'    assert(pObj);')
++        print(r'    pObj->Release();')
++        print(r'    return pUnknown == pObj;')
++        print(r'}')
++        print()
++        print(r'static inline const void *')
++        print(r'getVtbl(const void *pvObj) {')
++        print(r'    return pvObj ? *(const void **)pvObj : NULL;')
++        print(r'}')
++        print()
+         self.implementIidWrapper(api)
+         
+-        map(self.implementWrapperInterface, interfaces)
+-        print
++        for iface in interfaces:
++            self.implementWrapperInterface(iface)
++        
++        print()
+     def declareWrapperInterface(self, interface):
+         wrapperInterfaceName = getWrapperInterfaceName(interface)
+-        print "class %s : public %s " % (wrapperInterfaceName, interface.name)
+-        print "{"
+-        print "private:"
+-        print "    %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
+-        print "    virtual ~%s();" % wrapperInterfaceName
+-        print "public:"
+-        print "    static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
+-        print "    static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
+-        print "    static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
+-        print
++        print("class %s : public %s " % (wrapperInterfaceName, interface.name))
++        print("{")
++        print("private:")
++        print("    %s(%s * pInstance);" % (wrapperInterfaceName, interface.name))
++        print("    virtual ~%s();" % wrapperInterfaceName)
++        print("public:")
++        print("    static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name))
++        print("    static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,))
++        print("    static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,))
++        print()
+         methods = list(interface.iterMethods())
+         for method in methods:
+-            print "    " + method.prototype() + ";"
++            print("    " + method.prototype() + ";")
+         print
+         for type, name, value in self.enumWrapperInterfaceVariables(interface):
+-            print '    %s %s;' % (type, name)
+-        print
+-
+-        print r'private:'
+-        print r'    void _dummy(unsigned i) const {'
+-        print r'        os::log("error: %%s: unexpected virtual method %%i of instance pWrapper=%%p pvObj=%%p pVtbl=%%p\n", "%s", i, this, m_pInstance, m_pVtbl);' % interface.name
+-        print r'        trace::localWriter.flush();'
+-        print r'        os::abort();'
+-        print r'    }'
+-        print
++            print('    %s %s;' % (type, name))
++        print()
++
++        print(r'private:')
++        print(r'    void _dummy(unsigned i) const {')
++        print(r'        os::log("error: %%s: unexpected virtual method %%i of instance pWrapper=%%p pvObj=%%p pVtbl=%%p\n", "%s", i, this, m_pInstance, m_pVtbl);' % interface.name)
++        print(r'        trace::localWriter.flush();')
++        print(r'        os::abort();')
++        print(r'    }')
++        print()
+         for i in range(len(methods), 64):
+-            print r'    virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
+-        print
++            print(r'    virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i))
++        print()
+-        print "};"
+-        print
++        print("};")
++        print()
+     def enumWrapperInterfaceVariables(self, interface):
+         return [
+@@ -751,101 +756,101 @@ class Tracer:
+         wrapperInterfaceName = getWrapperInterfaceName(iface)
+         # Private constructor
+-        print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
++        print('%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name))
+         for type, name, value in self.enumWrapperInterfaceVariables(iface):
+             if value is not None:
+-                print '    %s = %s;' % (name, value)
+-        print '}'
+-        print
++                print('    %s = %s;' % (name, value))
++        print('}')
++        print()
+         # Public constructor
+-        print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
+-        print r'    Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
++        print('%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name))
++        print(r'    Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name))
+         if debug:
+-            print r'    os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", entryName, pInstance, pWrapper, pWrapper->m_pVtbl);' % iface.name
+-        print r'    g_WrappedObjects[pInstance] = pWrapper;'
+-        print r'    return pWrapper;'
+-        print '}'
+-        print
++            print(r'    os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", entryName, pInstance, pWrapper, pWrapper->m_pVtbl);' % iface.name)
++        print(r'    g_WrappedObjects[pInstance] = pWrapper;')
++        print(r'    return pWrapper;')
++        print('}')
++        print()
+         # Destructor
+-        print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
++        print('%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName))
+         if debug:
+-            print r'        os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % iface.name
+-        print r'        g_WrappedObjects.erase(m_pInstance);'
+-        print '}'
+-        print
++            print(r'        os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % iface.name)
++        print(r'        g_WrappedObjects.erase(m_pInstance);')
++        print('}')
++        print()
+         
+         baseMethods = list(iface.iterBaseMethods())
+         for base, method in baseMethods:
+             self.base = base
+             self.implementWrapperInterfaceMethod(iface, base, method)
+-        print
++        print()
+         # Wrap pointer
+         ifaces = self.api.getAllInterfaces()
+-        print r'void'
+-        print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
+-        print r'    if (!ppObj) {'
+-        print r'        return;'
+-        print r'    }'
+-        print r'    %s *pObj = *ppObj;' % (iface.name,)
+-        print r'    if (!pObj) {'
+-        print r'        return;'
+-        print r'    }'
+-        print r'    assert(hasChildInterface(IID_%s, pObj));' % iface.name
+-        print r'    std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
+-        print r'    if (it != g_WrappedObjects.end()) {'
+-        print r'        Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
+-        print r'        assert(pWrapper);'
+-        print r'        assert(pWrapper->m_dwMagic == 0xd8365d6c);'
+-        print r'        assert(pWrapper->m_pInstance == pObj);'
+-        print r'        if (pWrapper->m_pVtbl == getVtbl(pObj) &&'
+-        print r'            pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
++        print(r'void')
++        print(r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name))
++        print(r'    if (!ppObj) {')
++        print(r'        return;')
++        print(r'    }')
++        print(r'    %s *pObj = *ppObj;' % (iface.name,))
++        print(r'    if (!pObj) {')
++        print(r'        return;')
++        print(r'    }')
++        print(r'    assert(hasChildInterface(IID_%s, pObj));' % iface.name)
++        print(r'    std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);')
++        print(r'    if (it != g_WrappedObjects.end()) {')
++        print(r'        Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name))
++        print(r'        assert(pWrapper);')
++        print(r'        assert(pWrapper->m_dwMagic == 0xd8365d6c);')
++        print(r'        assert(pWrapper->m_pInstance == pObj);')
++        print(r'        if (pWrapper->m_pVtbl == getVtbl(pObj) &&')
++        print(r'            pWrapper->m_NumMethods >= %s) {' % len(baseMethods))
+         if debug:
+-            print r'            os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
+-        print r'            *ppObj = pWrapper;'
+-        print r'            return;'
+-        print r'        }'
+-        print r'    }'
++            print(r'            os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);')
++        print(r'            *ppObj = pWrapper;')
++        print(r'            return;')
++        print(r'        }')
++        print(r'    }')
+         for childIface in getInterfaceHierarchy(ifaces, iface):
+-            print r'    if (hasChildInterface(IID_%s, pObj)) {' % (childIface.name,)
+-            print r'        *ppObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
+-            print r'        return;'
+-            print r'    }'
+-        print r'    *ppObj = Wrap%s::_create(entryName, pObj);' % iface.name
+-        print r'}'
+-        print
++            print(r'    if (hasChildInterface(IID_%s, pObj)) {' % (childIface.name,))
++            print(r'        *ppObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name))
++            print(r'        return;')
++            print(r'    }')
++        print(r'    *ppObj = Wrap%s::_create(entryName, pObj);' % iface.name)
++        print(r'}')
++        print()
+         # Unwrap pointer
+-        print r'void'
+-        print r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
+-        print r'    if (!ppObj || !*ppObj) {'
+-        print r'        return;'
+-        print r'    }'
+-        print r'    const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface))
+-        print r'    if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
+-        print r'        *ppObj = pWrapper->m_pInstance;'
+-        print r'    } else {'
+-        print r'        os::log("apitrace: warning: %%s: unexpected %%s pointer %%p\n", entryName, "%s", *ppObj);' % iface.name
+-        print r'        trace::localWriter.flush();'
+-        print r'    }'
+-        print r'}'
+-        print
++        print(r'void')
++        print(r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name))
++        print(r'    if (!ppObj || !*ppObj) {')
++        print(r'        return;')
++        print(r'    }')
++        print(r'    const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface)))
++        print(r'    if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {')
++        print(r'        *ppObj = pWrapper->m_pInstance;')
++        print(r'    } else {')
++        print(r'        os::log("apitrace: warning: %%s: unexpected %%s pointer %%p\n", entryName, "%s", *ppObj);' % iface.name)
++        print(r'        trace::localWriter.flush();')
++        print(r'    }')
++        print(r'}')
++        print()
+     def implementWrapperInterfaceMethod(self, interface, base, method):
+         wrapperInterfaceName = getWrapperInterfaceName(interface)
+-        print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
++        print(method.prototype(wrapperInterfaceName + '::' + method.name) + ' {')
+         if False:
+-            print r'    os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
++            print(r'    os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name))
+         if method.type is not stdapi.Void:
+-            print '    %s _result;' % method.type
++            print('    %s _result;' % method.type)
+     
+-        print '    %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
++        print('    %s *_this = static_cast<%s *>(m_pInstance);' % (base, base))
+         for arg in method.args:
+             if not arg.output:
+                 self.unwrapArg(method, arg)
+@@ -855,36 +860,36 @@ class Tracer:
+         # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
+         if method.type is not stdapi.Void:
+-            print '    return _result;'
++            print('    return _result;')
+-        print '}'
+-        print
++        print('}')
++        print()
+     def implementWrapperInterfaceMethodBody(self, interface, base, method):
+         assert not method.internal
+-        print '    static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
+-        print '    static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1)
++        print('    static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args])))
++        print('    static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1))
+-        print '    unsigned _call = trace::localWriter.beginEnter(&_sig);'
+-        print '    trace::localWriter.beginArg(0);'
+-        print '    trace::localWriter.writePointer((uintptr_t)m_pInstance);'
+-        print '    trace::localWriter.endArg();'
++        print('    unsigned _call = trace::localWriter.beginEnter(&_sig);')
++        print('    trace::localWriter.beginArg(0);')
++        print('    trace::localWriter.writePointer((uintptr_t)m_pInstance);')
++        print('    trace::localWriter.endArg();')
+         for arg in method.args:
+             if not arg.output:
+                 self.serializeArg(method, arg)
+-        print '    trace::localWriter.endEnter();'
++        print('    trace::localWriter.endEnter();')
+         
+         self.invokeMethod(interface, base, method)
+-        print '    trace::localWriter.beginLeave(_call);'
++        print('    trace::localWriter.beginLeave(_call);')
+-        print '    if (%s) {' % self.wasFunctionSuccessful(method)
++        print('    if (%s) {' % self.wasFunctionSuccessful(method))
+         for arg in method.args:
+             if arg.output:
+                 self.serializeArg(method, arg)
+                 self.wrapArg(method, arg)
+-        print '    }'
++        print('    }')
+         if method.type is not stdapi.Void:
+             self.serializeRet(method, '_result')
+@@ -893,51 +898,51 @@ class Tracer:
+         if method.name == 'Release':
+             assert method.type is not stdapi.Void
+-            print r'    if (!_result) {'
+-            print r'        delete this;'
+-            print r'    }'
++            print(r'    if (!_result) {')
++            print(r'        delete this;')
++            print(r'    }')
+         
+-        print '    trace::localWriter.endLeave();'
++        print('    trace::localWriter.endLeave();')
+     def implementIidWrapper(self, api):
+         ifaces = api.getAllInterfaces()
+-        print r'static void'
+-        print r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {'
+-        print r'    os::log("apitrace: warning: %s: %s IID %s\n",'
+-        print r'            entryName, reason,'
+-        print r'            getGuidName(riid));'
+-        print r'    void * pVtbl = *(void **)pvObj;'
+-        print r'    HMODULE hModule = 0;'
+-        print r'    BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |'
+-        print r'                                  GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,'
+-        print r'                                  (LPCTSTR)pVtbl,'
+-        print r'                                  &hModule);'
+-        print r'    assert(bRet);'
+-        print r'    if (bRet) {'
+-        print r'        char szModule[MAX_PATH];'
+-        print r'        DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);'
+-        print r'        assert(dwRet);'
+-        print r'        if (dwRet) {'
+-        print r'            DWORD dwOffset = (UINT_PTR)pVtbl - (UINT_PTR)hModule;'
+-        print r'            os::log("apitrace: warning: pVtbl = %p (%s!+0x%0lx)\n", pVtbl, szModule, dwOffset);'
+-        print r'        }'
+-        print r'    }'
+-        print r'}'
+-        print 
+-        print r'static void'
+-        print r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {'
+-        print r'    if (!ppvObj || !*ppvObj) {'
+-        print r'        return;'
+-        print r'    }'
++        print(r'static void')
++        print(r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {')
++        print(r'    os::log("apitrace: warning: %s: %s IID %s\n",')
++        print(r'            entryName, reason,')
++        print(r'            getGuidName(riid));')
++        print(r'    void * pVtbl = *(void **)pvObj;')
++        print(r'    HMODULE hModule = 0;')
++        print(r'    BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |')
++        print(r'                                  GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,')
++        print(r'                                  (LPCTSTR)pVtbl,')
++        print(r'                                  &hModule);')
++        print(r'    assert(bRet);')
++        print(r'    if (bRet) {')
++        print(r'        char szModule[MAX_PATH];')
++        print(r'        DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);')
++        print(r'        assert(dwRet);')
++        print(r'        if (dwRet) {')
++        print(r'            DWORD dwOffset = (UINT_PTR)pVtbl - (UINT_PTR)hModule;')
++        print(r'            os::log("apitrace: warning: pVtbl = %p (%s!+0x%0lx)\n", pVtbl, szModule, dwOffset);')
++        print(r'        }')
++        print(r'    }')
++        print(r'}')
++        print() 
++        print(r'static void')
++        print(r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {')
++        print(r'    if (!ppvObj || !*ppvObj) {')
++        print(r'        return;')
++        print(r'    }')
+         for iface in ifaces:
+-            print r'    if (riid == IID_%s) {' % (iface.name,)
+-            print r'        Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
+-            print r'        return;'
+-            print r'    }'
+-        print r'    warnIID(entryName, riid, *ppvObj, "unsupported");'
+-        print r'}'
+-        print
++            print(r'    if (riid == IID_%s) {' % (iface.name,))
++            print(r'        Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name))
++            print(r'        return;')
++            print(r'    }')
++        print(r'    warnIID(entryName, riid, *ppvObj, "unsupported");')
++        print(r'}')
++        print()
+     def wrapIid(self, function, riid, out):
+         # Cast output arg to `void **` if necessary
+@@ -947,42 +952,42 @@ class Tracer:
+             assert isinstance(obj_type, stdapi.Interface)
+             out_name = 'reinterpret_cast<void * *>(%s)' % out_name
+-        print r'    if (%s && *%s) {' % (out.name, out.name)
++        print(r'    if (%s && *%s) {' % (out.name, out.name))
+         functionName = function.name
+         else_ = ''
+         if self.interface is not None:
+             functionName = self.interface.name + '::' + functionName
+-            print r'        if (*%s == m_pInstance &&' % (out_name,)
+-            print r'            (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
+-            print r'            *%s = this;' % (out_name,)
+-            print r'        }'
++            print(r'        if (*%s == m_pInstance &&' % (out_name,))
++            print(r'            (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases()))
++            print(r'            *%s = this;' % (out_name,))
++            print(r'        }')
+             else_ = 'else '
+-        print r'        %s{' % else_
+-        print r'             wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
+-        print r'        }'
+-        print r'    }'
++        print(r'        %s{' % else_)
++        print(r'             wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name))
++        print(r'        }')
++        print(r'    }')
+     def invokeMethod(self, interface, base, method):
+         if method.type is stdapi.Void:
+             result = ''
+         else:
+             result = '_result = '
+-        print '    %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
++        print('    %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args])))
+     
+     def emit_memcpy(self, ptr, size):
+-        print '    trace::fakeMemcpy(%s, %s);' % (ptr, size)
++        print('    trace::fakeMemcpy(%s, %s);' % (ptr, size))
+     
+     def emit_memcpy_opt(self, ptr, size):
+-        print '    trace::fakeMemcpyOpt(%s, %s);' % (ptr, size)
++        print('    trace::fakeMemcpyOpt(%s, %s);' % (ptr, size))
+     def fake_call(self, function, args):
+-        print '            unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
++        print('            unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,))
+         for arg, instance in zip(function.args, args):
+             assert not arg.output
+-            print '            trace::localWriter.beginArg(%u);' % (arg.index,)
++            print('            trace::localWriter.beginArg(%u);' % (arg.index,))
+             self.serializeValue(arg.type, instance)
+-            print '            trace::localWriter.endArg();'
+-        print '            trace::localWriter.endEnter();'
+-        print '            trace::localWriter.beginLeave(_fake_call);'
+-        print '            trace::localWriter.endLeave();'
++            print('            trace::localWriter.endArg();')
++        print('            trace::localWriter.endEnter();')
++        print('            trace::localWriter.beginLeave(_fake_call);')
++        print('            trace::localWriter.endLeave();')
+        
+diff --git a/wrappers/wgltrace.py b/wrappers/wgltrace.py
+index bc79d774..be86c36e 100644
+--- a/wrappers/wgltrace.py
++++ b/wrappers/wgltrace.py
+@@ -66,63 +66,65 @@ class WglTracer(GlTracer):
+             # wglCreateContext/wglCreateLayerContext to obtain a HGLRC that's
+             # recognizable by OPENGL32.DLL.  Therefore we need to detect and
+             # dispatch internal calls, without further ado.
+-            print r'    if (_reentrant) {'
++            print(r'    if (_reentrant) {')
+             self.invokeFunction(function)
+             if function.type is not Void:
+-                print '    return _result;'
+-            print r'    }'
+-            print r'    ReentryScope _reentry;'
+-            print r'    (void)_reentry;'
+-            print
++                print('    return _result;')
++            print(r'    }')
++            print(r'    ReentryScope _reentry;')
++            print(r'    (void)_reentry;')
++            print()
+         if function.name in self.destroyContextFunctionNames:
+             # Unlike other GL APIs like EGL or GLX, WGL will make the context
+             # inactive if it's currently the active context.
+-            print '    if (_wglGetCurrentContext() == hglrc) {'
+-            print '        gltrace::clearContext();'
+-            print '    }'
+-            print '    gltrace::releaseContext((uintptr_t)hglrc);'
++            print('    if (_wglGetCurrentContext() == hglrc) {')
++            print('        gltrace::clearContext();')
++            print('    }')
++            print('    gltrace::releaseContext((uintptr_t)hglrc);')
+         GlTracer.traceFunctionImplBody(self, function)
+         if function.name in self.createContextFunctionNames:
+-            print '    if (_result)'
+-            print '        gltrace::createContext((uintptr_t)_result);'
++            print('    if (_result)')
++            print('        gltrace::createContext((uintptr_t)_result);')
+         if function.name in self.makeCurrentFunctionNames:
+-            print '    if (_result) {'
+-            print '        if (hglrc != NULL)'
+-            print '            gltrace::setContext((uintptr_t)hglrc);'
+-            print '        else'
+-            print '            gltrace::clearContext();'
+-            print '    }'
++            print('    if (_result) {')
++            print('        if (hglrc != NULL)')
++            print('            gltrace::setContext((uintptr_t)hglrc);')
++            print('        else')
++            print('            gltrace::clearContext();')
++            print('    }')
+ if __name__ == '__main__':
+-    print
+-    print '#define _GDI32_'
+-    print
+-    print '#include <string.h>'
+-    print '#include <windows.h>'
+-    print
+-    print '#include "trace_writer_local.hpp"'
+-    print '#include "os.hpp"'
+-    print
+-    print '// To validate our prototypes'
+-    print '#define GL_GLEXT_PROTOTYPES'
+-    print '#define WGL_GLXEXT_PROTOTYPES'
+-    print
+-    print '#include "glproc.hpp"'
+-    print '#include "glsize.hpp"'
+-    print
+-    print 'static OS_THREAD_SPECIFIC(uintptr_t) _reentrant;'
+-    print
+-    print '// Helper class to track reentries in function scope.'
+-    print 'struct ReentryScope {'
+-    print 'inline ReentryScope() { _reentrant = 1; }'
+-    print 'inline ~ReentryScope() { _reentrant = 0; }'
+-    print '};'
+-    print
++    print()
++    print('#define _GDI32_')
++    print()
++    print('#include <string.h>')
++    print('#include <windows.h>')
++    print()
++    print('#include <sstream>')
++    print()
++    print('#include "trace_writer_local.hpp"')
++    print('#include "os.hpp"')
++    print()
++    print('// To validate our prototypes')
++    print('#define GL_GLEXT_PROTOTYPES')
++    print('#define WGL_GLXEXT_PROTOTYPES')
++    print()
++    print('#include "glproc.hpp"')
++    print('#include "glsize.hpp"')
++    print()
++    print('static OS_THREAD_LOCAL uintptr_t _reentrant;')
++    print()
++    print('// Helper class to track reentries in function scope.')
++    print('struct ReentryScope {')
++    print('inline ReentryScope() { _reentrant = 1; }')
++    print('inline ~ReentryScope() { _reentrant = 0; }')
++    print('};')
++    print()
+     module = Module()
+     module.mergeModule(glapi)
+     module.mergeModule(wglapi)
+-- 
+2.17.1
+
diff --git a/recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0002-specs-Tie-Python-2-3-conversion-loose-ends.patch b/recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0002-specs-Tie-Python-2-3-conversion-loose-ends.patch
new file mode 100644 (file)
index 0000000..2514160
--- /dev/null
@@ -0,0 +1,169 @@
+From a8791e3dca61500a382be84dc96973639b8bd182 Mon Sep 17 00:00:00 2001
+From: Jose Fonseca <jfonseca@vmware.com>
+Date: Sun, 28 Apr 2019 14:13:01 +0100
+Subject: [PATCH 2/4] specs: Tie Python 2 ->3 conversion loose ends.
+
+Upstream-Status: Backport [https://github.com/apitrace/apitrace/commit/5b3c68cafaddc82c0f34bea8127582eee07ac3be]
+
+(cherry picked from commit 5b3c68cafaddc82c0f34bea8127582eee07ac3be)
+Signed-off-by: Andrey Zhizhikin <andrey.zhizhikin@leica-geosystems.com>
+---
+ specs/scripts/Makefile        | 16 ++++++++--------
+ specs/scripts/c2api.py        |  6 +++---
+ specs/scripts/cxx2api.py      |  2 +-
+ specs/scripts/spec2api.py     |  2 +-
+ specs/scripts/txt2api.py      |  8 +++++---
+ specs/scripts/xml2api.py      |  2 +-
+ specs/scripts/xml2enum.py     |  2 +-
+ specs/scripts/xml2glparams.py |  2 +-
+ 8 files changed, 21 insertions(+), 19 deletions(-)
+
+diff --git a/specs/scripts/Makefile b/specs/scripts/Makefile
+index 714a3deb..f03f36eb 100644
+--- a/specs/scripts/Makefile
++++ b/specs/scripts/Makefile
+@@ -37,28 +37,28 @@ download: \
+       wget -N https://www.opengl.org/registry/oldspecs/$@
+ glapi.py: xml2api.py gl.xml
+-      python $^ > $@
++      python3 $^ > $@
+ glxapi.py: xml2api.py glx.xml
+-      python $^ > $@
++      python3 $^ > $@
+ wglapi.py: xml2api.py wgl.xml
+-      python $^ > $@
++      python3 $^ > $@
+ eglapi.py: xml2api.py egl.xml
+-      python $^ > $@
++      python3 $^ > $@
+ glparams.py: xml2glparams.py gl.xml
+-      python $^ > $@
++      python3 $^ > $@
+ glxenum.py: xml2enum.py glx.xml
+-      python $^ > $@
++      python3 $^ > $@
+ wglenum.py: xml2enum.py wgl.xml
+-      python $^ > $@
++      python3 $^ > $@
+ eglenum.py: xml2enum.py egl.xml
+-      python $^ > $@
++      python3 $^ > $@
+ clean:
+       rm -f \
+diff --git a/specs/scripts/c2api.py b/specs/scripts/c2api.py
+index b8aaa81d..208169d2 100755
+--- a/specs/scripts/c2api.py
++++ b/specs/scripts/c2api.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2011 Jose Fonseca
+@@ -404,8 +404,8 @@ class DeclParser:
+                     type = 'S' + type
+             elif short:
+                 type = 'Short'
+-            elif int:
+-                type = 'Long' * int
++            elif long:
++                type = 'Long' * long
+             else:
+                 type = 'Int'
+             if unsigned:
+diff --git a/specs/scripts/cxx2api.py b/specs/scripts/cxx2api.py
+index 9720615d..8056de47 100755
+--- a/specs/scripts/cxx2api.py
++++ b/specs/scripts/cxx2api.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+diff --git a/specs/scripts/spec2api.py b/specs/scripts/spec2api.py
+index 7fb395a4..33a8d058 100755
+--- a/specs/scripts/spec2api.py
++++ b/specs/scripts/spec2api.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2010 VMware, Inc.
+diff --git a/specs/scripts/txt2api.py b/specs/scripts/txt2api.py
+index e9469d3c..a32ca658 100755
+--- a/specs/scripts/txt2api.py
++++ b/specs/scripts/txt2api.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2010 VMware, Inc.
+@@ -28,6 +28,7 @@
+ """Parser for OpenGL .txt extensions specification."""
++import io
+ import sys
+ import re
+ import optparse
+@@ -233,12 +234,13 @@ def main():
+     for arg in args:
+         if arg.startswith('http://') or arg.startswith('https://'):
+-            stream = urlopen(arg, 'rt')
++            stream = urlopen(arg)
++            stream = io.TextIOWrapper(stream, encoding='ascii')
+         else:
+             stream = open(arg, 'rt')
+         parser = TxtParser(stream, prefix = options.prefix)
+         parser.parse()
+-    
++
+ if __name__ == '__main__':
+     main()
+diff --git a/specs/scripts/xml2api.py b/specs/scripts/xml2api.py
+index f09fe0bf..6b4ec3b7 100755
+--- a/specs/scripts/xml2api.py
++++ b/specs/scripts/xml2api.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2014 VMware, Inc
+diff --git a/specs/scripts/xml2enum.py b/specs/scripts/xml2enum.py
+index cb2c4ae9..f799b7b5 100755
+--- a/specs/scripts/xml2enum.py
++++ b/specs/scripts/xml2enum.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2014 VMware, Inc
+diff --git a/specs/scripts/xml2glparams.py b/specs/scripts/xml2glparams.py
+index 805aac86..a651d896 100755
+--- a/specs/scripts/xml2glparams.py
++++ b/specs/scripts/xml2glparams.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2014 VMware, Inc
+-- 
+2.17.1
+
diff --git a/recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0003-scripts-Tie-Python-2-3-conversion-loose-ends.patch b/recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0003-scripts-Tie-Python-2-3-conversion-loose-ends.patch
new file mode 100644 (file)
index 0000000..e30273d
--- /dev/null
@@ -0,0 +1,276 @@
+From 8ba82a1ef77e60bd614cca1e583e1a0c25b4f281 Mon Sep 17 00:00:00 2001
+From: Jose Fonseca <jfonseca@vmware.com>
+Date: Sun, 28 Apr 2019 14:14:44 +0100
+Subject: [PATCH 3/4] scripts: Tie Python 2 -> 3 conversion loose ends.
+
+Upstream-Status: Backport [https://github.com/apitrace/apitrace/commit/247e1fa87f4e87b8914662e44a8ecef4d444cc90]
+
+(cherry picked from commit 247e1fa87f4e87b8914662e44a8ecef4d444cc90)
+Signed-off-by: Andrey Zhizhikin <andrey.zhizhikin@leica-geosystems.com>
+---
+ retrace/glstate_params.py    |  2 +-
+ scripts/convert.py           |  2 +-
+ scripts/highlight.py         |  3 ++-
+ scripts/jsondiff.py          |  2 +-
+ scripts/jsonextractimages.py |  2 +-
+ scripts/leaks.py             |  4 ++--
+ scripts/profileshader.py     |  2 +-
+ scripts/retracediff.py       |  2 +-
+ scripts/snapdiff.py          |  2 +-
+ scripts/tracecheck.py        |  2 +-
+ scripts/tracediff.py         | 10 +++++-----
+ scripts/unpickle.py          | 19 ++++++++++---------
+ 12 files changed, 27 insertions(+), 25 deletions(-)
+
+diff --git a/retrace/glstate_params.py b/retrace/glstate_params.py
+index bc90f66b..55f2dbc9 100755
+--- a/retrace/glstate_params.py
++++ b/retrace/glstate_params.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2011 Jose Fonseca
+diff --git a/scripts/convert.py b/scripts/convert.py
+index 83df70ce..1f285a8c 100755
+--- a/scripts/convert.py
++++ b/scripts/convert.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2012 VMware Inc.
+diff --git a/scripts/highlight.py b/scripts/highlight.py
+index ed3b54d4..e494abf4 100644
+--- a/scripts/highlight.py
++++ b/scripts/highlight.py
+@@ -221,7 +221,8 @@ def LessHighlighter():
+         try:
+             less = subprocess.Popen(
+                 args = ['less', '-FRXn'],
+-                stdin = subprocess.PIPE
++                stdin = subprocess.PIPE,
++                universal_newlines = True
+             )
+         except OSError:
+             return ColorHighlighter()
+diff --git a/scripts/jsondiff.py b/scripts/jsondiff.py
+index 25c4840e..d7a18e21 100755
+--- a/scripts/jsondiff.py
++++ b/scripts/jsondiff.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2015 VMware, Inc.
+diff --git a/scripts/jsonextractimages.py b/scripts/jsonextractimages.py
+index 917ee7e4..785e32db 100755
+--- a/scripts/jsonextractimages.py
++++ b/scripts/jsonextractimages.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2012 Jose Fonseca
+diff --git a/scripts/leaks.py b/scripts/leaks.py
+index 325af1e2..706e60a9 100755
+--- a/scripts/leaks.py
++++ b/scripts/leaks.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2014-2016 VMware, Inc.
+@@ -39,7 +39,7 @@ class LeakDetector(unpickle.Unpickler):
+     def __init__(self, apitrace, trace):
+         cmd = [apitrace, 'pickle', '--symbolic', trace]
+-        p = subprocess.Popen(args = cmd, stdout = subprocess.PIPE)
++        p = subprocess.Popen(args = cmd, stdout=subprocess.PIPE)
+         unpickle.Unpickler.__init__(self, p.stdout)
+diff --git a/scripts/profileshader.py b/scripts/profileshader.py
+index 5c2a58fb..c6c1c935 100755
+--- a/scripts/profileshader.py
++++ b/scripts/profileshader.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2012-2013 VMware, Inc.
+diff --git a/scripts/retracediff.py b/scripts/retracediff.py
+index 8105f536..967f3a93 100755
+--- a/scripts/retracediff.py
++++ b/scripts/retracediff.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2011 Jose Fonseca
+diff --git a/scripts/snapdiff.py b/scripts/snapdiff.py
+index b0d5f757..58fefe88 100755
+--- a/scripts/snapdiff.py
++++ b/scripts/snapdiff.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2011 Jose Fonseca
+diff --git a/scripts/tracecheck.py b/scripts/tracecheck.py
+index 3a2ec452..38167e89 100755
+--- a/scripts/tracecheck.py
++++ b/scripts/tracecheck.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2011 VMware, Inc.
+diff --git a/scripts/tracediff.py b/scripts/tracediff.py
+index 0cd9c8c6..88e389a3 100755
+--- a/scripts/tracediff.py
++++ b/scripts/tracediff.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2011 Jose Fonseca
+@@ -173,7 +173,7 @@ class ExternalDiffer(Differ):
+             try:
+                 less = subprocess.Popen(
+                     args = ['less', '-FRXn'],
+-                    stdin = subprocess.PIPE
++                    stdin = subprocess.PIPE,
+                 )
+             except OSError:
+                 pass
+@@ -214,7 +214,7 @@ ignoredFunctionNames = set([
+ class Blob:
+-    '''Data-less proxy for bytearrays, to save memory.'''
++    '''Data-less proxy for bytes, to save memory.'''
+     def __init__(self, size, hash):
+         self.size = size
+@@ -233,7 +233,7 @@ class Blob:
+ class BlobReplacer(Rebuilder):
+     '''Replace blobs with proxys.'''
+-    def visitByteArray(self, obj):
++    def visitBytes(self, obj):
+         return Blob(len(obj), hash(str(obj)))
+     def visitCall(self, call):
+@@ -287,7 +287,7 @@ class PythonDiffer(Differ):
+                 '--calls=' + calls,
+                 trace
+             ],
+-            stdout = subprocess.PIPE,
++            stdout=subprocess.PIPE,
+         )
+         parser = Loader(p.stdout)
+diff --git a/scripts/unpickle.py b/scripts/unpickle.py
+index 86891d29..822b8ea8 100755
+--- a/scripts/unpickle.py
++++ b/scripts/unpickle.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+ ##########################################################################
+ #
+ # Copyright 2012 Jose Fonseca
+@@ -34,6 +34,7 @@ Run as:
+ import itertools
++import operator
+ import optparse
+ import sys
+ import time
+@@ -55,7 +56,7 @@ CALL_FLAG_MARKER_PUSH       = (1 << 9)
+ CALL_FLAG_MARKER_POP        = (1 << 10)
+-class Pointer(long):
++class Pointer(int):
+     def __str__(self):
+         if self == 0:
+@@ -79,7 +80,7 @@ class Visitor:
+         self.dispatch[tuple] = self.visitTuple
+         self.dispatch[list] = self.visitList
+         self.dispatch[dict] = self.visitDict
+-        self.dispatch[bytearray] = self.visitByteArray
++        self.dispatch[bytes] = self.visitBytes
+         self.dispatch[Pointer] = self.visitPointer
+     def visit(self, obj):
+@@ -119,7 +120,7 @@ class Visitor:
+     def visitDict(self, obj):
+         return self.visitIterable(obj)
+-    def visitByteArray(self, obj):
++    def visitBytes(self, obj):
+         raise NotImplementedError
+     def visitPointer(self, obj):
+@@ -153,7 +154,7 @@ class Dumper(Visitor):
+     def visitDict(self, obj):
+         return '{' + self.visitItems(iter(obj.items())) + '}'
+-    def visitByteArray(self, obj):
++    def visitBytes(self, obj):
+         return 'blob(%u)' % len(obj)
+@@ -169,7 +170,7 @@ class Hasher(Visitor):
+     def visitIterable(self, obj):
+         return tuple(map(self.visit, obj))
+-    def visitByteArray(self, obj):
++    def visitBytes(self, obj):
+         return str(obj)
+@@ -193,7 +194,7 @@ class Rebuilder(Visitor):
+         else:
+             return obj
+-    def visitByteArray(self, obj):
++    def visitBytes(self, obj):
+         return obj
+@@ -269,7 +270,7 @@ class Counter(Unpickler):
+         Unpickler.parse(self)
+         functionFrequencies = list(self.functionFrequencies.items())
+-        functionFrequencies.sort(lambda (name1, freq1), (name2, freq2): cmp(freq1, freq2))
++        functionFrequencies.sort(key=operator.itemgetter(1))
+         for name, frequency in functionFrequencies:
+             sys.stdout.write('%8u %s\n' % (frequency, name))
+@@ -311,7 +312,7 @@ def main():
+         msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
+     startTime = time.time()
+-    parser = Counter(sys.stdin, options.verbose)
++    parser = Counter(sys.stdin.buffer, options.verbose)
+     parser.parse()
+     stopTime = time.time()
+     duration = stopTime - startTime
+-- 
+2.17.1
+
diff --git a/recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0004-scripts-Tie-a-few-more-Python-2-to-3-conversion-loos.patch b/recipes-graphics/imx-gpu-apitrace/imx-gpu-apitrace/0004-scripts-Tie-a-few-more-Python-2-to-3-conversion-loos.patch
new file mode 100644 (file)
index 0000000..8974e5d
--- /dev/null
@@ -0,0 +1,62 @@
+From aa8e341e73c288b77a5187e3676a2bbb6588b705 Mon Sep 17 00:00:00 2001
+From: Jose Fonseca <jfonseca@vmware.com>
+Date: Mon, 29 Apr 2019 06:41:49 +0100
+Subject: [PATCH 4/4] scripts: Tie a few more Python 2 to 3 conversion loose
+ ends.
+
+Upstream-Status: Backport [https://github.com/apitrace/apitrace/commit/f527924cca45591966139eae8c2fefb4a9a0f947]
+
+(cherry picked from commit f527924cca45591966139eae8c2fefb4a9a0f947)
+Signed-off-by: Andrey Zhizhikin <andrey.zhizhikin@leica-geosystems.com>
+---
+ scripts/jsonextractimages.py | 10 +++++-----
+ scripts/profileshader.py     |  2 +-
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/scripts/jsonextractimages.py b/scripts/jsonextractimages.py
+index 785e32db..ac20c23d 100755
+--- a/scripts/jsonextractimages.py
++++ b/scripts/jsonextractimages.py
+@@ -34,7 +34,7 @@ import base64
+ import sys
+-pngSignature = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"
++pngSignature = b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"
+ def dumpSurfaces(state, memberName):
+@@ -46,13 +46,13 @@ def dumpSurfaces(state, memberName):
+             extName = 'png'
+         else:
+             magic = data[:2]
+-            if magic in ('P1', 'P4'):
++            if magic in (b'P1', b'P4'):
+                 extName = 'pbm'
+-            elif magic in ('P2', 'P5'):
++            elif magic in (b'P2', b'P5'):
+                 extName = 'pgm'
+-            elif magic in ('P3', 'P6'):
++            elif magic in (b'P3', b'P6'):
+                 extName = 'ppm'
+-            elif magic in ('Pf', 'PF'):
++            elif magic in (b'Pf', b'PF'):
+                 extName = 'pfm'
+             else:
+                 sys.stderr.write('warning: unsupport Netpbm format %s\n' % magic)
+diff --git a/scripts/profileshader.py b/scripts/profileshader.py
+index c6c1c935..7e8637eb 100755
+--- a/scripts/profileshader.py
++++ b/scripts/profileshader.py
+@@ -92,7 +92,7 @@ def process(stream, groupField):
+         id = str(group[0]).rjust(maxGroupLen)
+         draw = str(group[1]['draws']).rjust(12)
+         dura = str(group[1]['duration']).rjust(18)
+-        perCall = str(group[1]['duration'] / group[1]['draws']).rjust(12)
++        perCall = str(group[1]['duration'] // group[1]['draws']).rjust(12)
+         longest = str(group[1]['longest']).rjust(11)
+         print("| %s | %s | %s | %s | %s |" % (id, draw, dura, perCall, longest))
+-- 
+2.17.1
+
index 02d7ef9c66f9adde336daac1c4a16b1813378747..0169c26f31dc7ec898b743deb6ad24546915babd 100644 (file)
@@ -4,12 +4,18 @@ LICENSE = "MIT"
 LIC_FILES_CHKSUM = "file://LICENSE;md5=aeb969185a143c3c25130bc2c3ef9a50"
 DEPENDS = "imx-gpu-viv zlib libpng procps"
 
-SRC_URI = "git://source.codeaurora.org/external/imx/apitrace-imx.git;protocol=https;branch=imx_7.1"
+SRC_URI = "\
+       git://source.codeaurora.org/external/imx/apitrace-imx.git;protocol=https;branch=imx_7.1 \
+       file://0001-switch-from-python2-to-python3.patch \
+       file://0002-specs-Tie-Python-2-3-conversion-loose-ends.patch \
+       file://0003-scripts-Tie-Python-2-3-conversion-loose-ends.patch \
+       file://0004-scripts-Tie-a-few-more-Python-2-to-3-conversion-loos.patch \
+"
 SRCREV = "09579e67262af9c993dd082055a924c2c61cf34d"
 
 S = "${WORKDIR}/git"
 
-inherit cmake lib_package pkgconfig perlnative pythonnative
+inherit cmake lib_package pkgconfig perlnative python3native
 
 PACKAGECONFIG ??= ""
 PACKAGECONFIG_append = \