print ' Dump%s(%s);' % (self.id, instance)
-class Intrinsic(Concrete):
+class Literal(Concrete):
- def __init__(self, expr, format):
+ def __init__(self, expr, format, base=10):
Concrete.__init__(self, expr)
self.format = format
def _dump(self, instance):
- print ' Log::TextF("%s", %s);' % (self.format, instance)
+ print ' Log::Literal%s(%s);' % (self.format, instance)
class Const(Type):
print ' Log::EndReference();'
print ' }'
print ' else'
- print ' Log::Text("NULL");'
+ print ' Log::LiteralNull();'
def wrap_instance(self, instance):
self.type.wrap_instance("*" + instance)
print ' switch(%s) {' % instance
for value in self.values:
print ' case %s:' % value
- print ' Log::Text("%s");' % value
+ print ' Log::LiteralNamedConstant("%s");' % value
print ' break;'
print ' default:'
- print ' Log::TextF("%%i", %s);' % instance
+ print ' Log::LiteralSInt(%s);' % instance
print ' break;'
print ' }'
self.values = values
def _dump(self, instance):
- print ' bool l_First = true;'
print ' %s l_Value = %s;' % (self.type, instance)
+ print ' Log::BeginBitmask("%s");' % (self.type,)
for value in self.values:
print ' if((l_Value & %s) == %s) {' % (value, value)
- print ' if(!l_First)'
- print ' Log::Text(" | ");'
- print ' Log::Text("%s");' % value
+ print ' Log::LiteralNamedConstant("%s");' % value
print ' l_Value &= ~%s;' % value
- print ' l_First = false;'
print ' }'
- print ' if(l_Value || l_First) {'
- print ' if(!l_First)'
- print ' Log::Text(" | ");'
+ print ' if(l_Value) {'
self.type.dump("l_Value");
print ' }'
+ print ' Log::EndBitmask();'
class Array(Type):
def dump(self, instance):
index = '__i' + self.type.id
+ print ' Log::BeginArray("%s", %s);' % (self.type, self.length)
print ' for (int %s = 0; %s < %s; ++%s) {' % (index, index, self.length, index)
print ' Log::BeginElement("%s");' % (self.type,)
self.type.dump('(%s)[%s]' % (instance, index))
print ' Log::EndElement();'
print ' }'
+ print ' Log::EndArray();'
def wrap_instance(self, instance):
self.type.wrap_instance("*" + instance)
def __init__(self, name, members):
Concrete.__init__(self, name)
+ self.name = name
self.members = members
def _dump(self, instance):
+ print ' Log::BeginStruct("%s");' % (self.name,)
for type, name in self.members:
- print ' Log::BeginElement("%s", "%s");' % (type, name)
+ print ' Log::BeginMember("%s", "%s");' % (type, name)
type.dump('(%s).%s' % (instance, name))
- print ' Log::EndElement();'
+ print ' Log::EndMember();'
+ print ' Log::EndStruct();'
class Alias(Type):
class Method(Function):
def __init__(self, type, name, args):
- Function.__init__(self, type, name, args)
+ Function.__init__(self, type, name, args, call = '__stdcall')
towrap = []
Type.__init__(self, "char *")
def dump(self, instance):
- print ' Log::DumpString((const char *)%s);' % instance
+ print ' Log::LiteralString((const char *)%s);' % instance
String = _String()
-class _WString(Type):
+
+class _Opaque(Type):
def __init__(self):
- Type.__init__(self, "wchar_t *")
+ Type.__init__(self, "void *")
def dump(self, instance):
- print ' Log::DumpWString(%s);' % instance
-
-WString = _WString()
-
-
-SChar = Intrinsic("signed char", "%i")
-UChar = Intrinsic("unsigned char", "%u")
-Short = Intrinsic("short", "%i")
-Int = Intrinsic("int", "%i")
-Long = Intrinsic("long", "%li")
-UShort = Intrinsic("unsigned short", "%u")
-UInt = Intrinsic("unsigned int", "%u")
-ULong = Intrinsic("unsigned long", "%lu")
-Float = Intrinsic("float", "%f")
-Double = Intrinsic("double", "%f")
-SizeT = Intrinsic("size_t", "%lu")
+ print ' Log::LiteralOpaque((const void *)%s);' % instance
+
+Opaque = _Opaque()
+
+
+Bool = Literal("bool", "Bool")
+SChar = Literal("signed char", "SInt")
+UChar = Literal("unsigned char", "UInt")
+Short = Literal("short", "SInt")
+Int = Literal("int", "SInt")
+Long = Literal("long", "SInt")
+LongLong = Literal("long long", "SInt")
+UShort = Literal("unsigned short", "UInt")
+UInt = Literal("unsigned int", "UInt")
+ULong = Literal("unsigned long", "UInt")
+Float = Literal("float", "Float")
+Double = Literal("double", "Float")
+SizeT = Literal("size_t", "UInt")
+WString = Literal("wchar_t *", "WString")
def wrap():
--- /dev/null
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008-2009 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 sys
+
+
+class Formatter:
+ '''Plain formatter'''
+
+ def __init__(self, stream):
+ self.stream = stream
+
+ def text(self, text):
+ self.stream.write(text)
+
+ def newline(self):
+ self.text('\n')
+
+ def function(self, name):
+ self.text(name)
+
+ def variable(self, name):
+ self.text(name)
+
+ def literal(self, value):
+ self.text(str(value))
+
+ def address(self, addr):
+ self.text(str(addr))
+
+
+class AnsiFormatter(Formatter):
+ '''Formatter for plain-text files which outputs ANSI escape codes. See
+ http://en.wikipedia.org/wiki/ANSI_escape_code for more information
+ concerning ANSI escape codes.
+ '''
+
+ _csi = '\33['
+
+ _normal = '0m'
+ _bold = '1m'
+ _italic = '3m'
+ _red = '31m'
+ _green = '32m'
+ _blue = '34m'
+
+ def _escape(self, code):
+ self.text(self._csi + code)
+
+ def function(self, name):
+ self._escape(self._bold)
+ Formatter.function(self, name)
+ self._escape(self._normal)
+
+ def variable(self, name):
+ self._escape(self._italic)
+ Formatter.variable(self, name)
+ self._escape(self._normal)
+
+ def literal(self, value):
+ self._escape(self._blue)
+ Formatter.literal(self, value)
+ self._escape(self._normal)
+
+ def address(self, value):
+ self._escape(self._green)
+ Formatter.address(self, value)
+ self._escape(self._normal)
+
+
+class WindowsConsoleFormatter(Formatter):
+ '''Formatter for the Windows Console. See
+ http://code.activestate.com/recipes/496901/ for more information.
+ '''
+
+ STD_INPUT_HANDLE = -10
+ STD_OUTPUT_HANDLE = -11
+ STD_ERROR_HANDLE = -12
+
+ FOREGROUND_BLUE = 0x01
+ FOREGROUND_GREEN = 0x02
+ FOREGROUND_RED = 0x04
+ FOREGROUND_INTENSITY = 0x08
+ BACKGROUND_BLUE = 0x10
+ BACKGROUND_GREEN = 0x20
+ BACKGROUND_RED = 0x40
+ BACKGROUND_INTENSITY = 0x80
+
+ _normal = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
+ _bold = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
+ _italic = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
+ _red = FOREGROUND_RED | FOREGROUND_INTENSITY
+ _green = FOREGROUND_GREEN | FOREGROUND_INTENSITY
+ _blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY
+
+ def __init__(self, stream):
+ Formatter.__init__(self, stream)
+
+ if stream is sys.stdin:
+ nStdHandle = self.STD_INPUT_HANDLE
+ elif stream is sys.stdout:
+ nStdHandle = self.STD_OUTPUT_HANDLE
+ elif stream is sys.stderr:
+ nStdHandle = self.STD_ERROR_HANDLE
+ else:
+ nStdHandle = None
+
+ if nStdHandle:
+ import ctypes
+ self.handle = ctypes.windll.kernel32.GetStdHandle(nStdHandle)
+ else:
+ self.handle = None
+
+ def _attribute(self, attr):
+ if self.handle:
+ import ctypes
+ ctypes.windll.kernel32.SetConsoleTextAttribute(self.handle, attr)
+
+ def function(self, name):
+ self._attribute(self._bold)
+ Formatter.function(self, name)
+ self._attribute(self._normal)
+
+ def variable(self, name):
+ self._attribute(self._italic)
+ Formatter.variable(self, name)
+ self._attribute(self._normal)
+
+ def literal(self, value):
+ self._attribute(self._blue)
+ Formatter.literal(self, value)
+ self._attribute(self._normal)
+
+ def address(self, value):
+ self._attribute(self._green)
+ Formatter.address(self, value)
+ self._attribute(self._normal)
+
+
+def DefaultFormatter(stream):
+ if sys.platform in ('linux2', 'cygwin'):
+ return AnsiFormatter(stream)
+ elif sys.platform in ('win32',):
+ return WindowsConsoleFormatter(stream)
+ else:
+ return Formatter(stream)
+
print ' }'
-PROC = Intrinsic("__GLXextFuncPtr", "%p")
+PROC = Alias("__GLXextFuncPtr", Opaque)
glXgetprocaddress = GlxGetProcAddressFunction(PROC, "glXGetProcAddress", [(Pointer(Const(GLubyte)), "procName")])
libgl.functions.append(glXgetprocaddress)
}
static inline void
-Escape(char c)
+Escape(wchar_t c)
{
switch(c) {
case '&':
case '\'':
Write("'");
break;
+ case '\t':
+ Write("	");
+ break;
+ case '\r':
+ Write(" ");
+ break;
+ case '\n':
+ Write(" ");
+ break;
default:
- Write(c);
+ if (c >= 0x20 && c <= 0x7e) {
+ Write((char)c);
+ } else {
+ Write('.');
+ }
}
}
}
}
+static inline void
+Escape(const wchar_t *s)
+{
+ unsigned char c;
+ while((c = *s++) != 0) {
+ Escape(c);
+ }
+}
+
static inline void
EscapeF(const char *format, ...)
{
_Close();
}
-void Text(const char *text) {
- Escape(text);
-}
-
-void TextF(const char *format, ...) {
- char szBuffer[4096];
- va_list ap;
- va_start(ap, format);
- vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
- va_end(ap);
- Escape(szBuffer);
-}
-
void BeginCall(const char *function) {
OS::AcquireMutex();
Indent(1);
NewLine();
}
-void BeginElement(const char *type, const char *name) {
- BeginTag("elem", "type", type, "name", name);
+void BeginArray(const char *type, size_t length)
+{
+ BeginTag("array", "type", type);
+}
+
+void EndArray(void)
+{
+ EndTag("array");
}
-void BeginElement(const char *type) {
+void BeginElement(const char *type)
+{
BeginTag("elem", "type", type);
}
-void EndElement(void) {
+void EndElement(void)
+{
EndTag("elem");
}
-void BeginReference(const char *type, const void *addr) {
+void BeginStruct(const char *type)
+{
+ BeginTag("struct", "type", type);
+}
+
+void EndStruct(void)
+{
+ EndTag("struct");
+}
+
+void BeginMember(const char *type, const char *name)
+{
+ BeginTag("member", "type", type, "name", name);
+}
+
+void EndMember(void)
+{
+ EndTag("member");
+}
+
+void BeginBitmask(const char *type)
+{
+ BeginTag("bitmask");
+}
+
+void EndBitmask(void)
+{
+ EndTag("bitmask");
+}
+
+void BeginReference(const char *type, const void *addr)
+{
char saddr[256];
snprintf(saddr, sizeof(saddr), "%p", addr);
BeginTag("ref", "type", type, "addr", saddr);
}
-void EndReference(void) {
+void EndReference(void)
+{
EndTag("ref");
}
-void DumpString(const char *str) {
- const unsigned char *p = (const unsigned char *)str;
+void LiteralBool(bool value)
+{
+ BeginTag("bool");
+ WriteF("%u", value ? 0 : 1);
+ EndTag("bool");
+}
+
+void LiteralSInt(signed long long value)
+{
+ BeginTag("int");
+ WriteF("%lli", value);
+ EndTag("int");
+}
+
+void LiteralUInt(unsigned long long value)
+{
+ BeginTag("uint");
+ WriteF("%llu", value);
+ EndTag("uint");
+}
+
+void LiteralFloat(double value)
+{
+ BeginTag("float");
+ WriteF("%f", value);
+ EndTag("float");
+}
+
+void LiteralString(const char *str)
+{
if (!str) {
- Write("NULL");
+ LiteralNull();
return;
}
- Write("\"");
- unsigned char c;
- while((c = *p++) != 0) {
- if(c == '\"')
- Write("\\\"");
- else if(c == '\\')
- Write("\\\\");
- else if(c >= 0x20 && c <= 0x7e)
- Write(c);
- else if(c == '\t')
- Write("	");
- else if(c == '\r')
- Write(" ");
- else if(c == '\n')
- Write(" ");
- else {
- unsigned char octal0 = c & 0x7;
- unsigned char octal1 = (c >> 3) & 0x7;
- unsigned char octal2 = (c >> 3) & 0x7;
- if(octal2)
- WriteF("\\%u%u%u", octal2, octal1, octal0);
- else if(octal1)
- WriteF("\\%u%u", octal1, octal0);
- else
- WriteF("\\%u", octal0);
- }
- }
- Write("\"");
+ BeginTag("string");
+ Escape(str);
+ EndTag("string");
}
-void DumpWString(const wchar_t *str) {
- const wchar_t *p = str;
+void LiteralWString(const wchar_t *str)
+{
if (!str) {
- Write("NULL");
+ LiteralNull();
return;
}
- Write("L\"");
- wchar_t c;
- while((c = *p++) != 0) {
- if(c == '\"')
- Write("\\\"");
- else if(c == '\\')
- Write("\\\\");
- else if(c >= 0x20 && c <= 0x7e)
- Write((char)c);
- else if(c == '\t')
- Write("	");
- else if(c == '\r')
- Write(" ");
- else if(c == '\n')
- Write(" ");
- else {
- unsigned octal0 = c & 0x7;
- unsigned octal1 = (c >> 3) & 0x7;
- unsigned octal2 = (c >> 3) & 0x7;
- if(octal2)
- WriteF("\\%u%u%u", octal2, octal1, octal0);
- else if(octal1)
- WriteF("\\%u%u", octal1, octal0);
- else
- WriteF("\\%u", octal0);
- }
+ BeginTag("wstring");
+ Escape(str);
+ EndTag("wstring");
+}
+
+void LiteralNamedConstant(const char *str)
+{
+ BeginTag("const");
+ Escape(str);
+ EndTag("const");
+}
+
+void LiteralOpaque(const void *addr)
+{
+ char saddr[256];
+ if (!addr) {
+ LiteralNull();
+ return;
}
- Write("\"");
+ snprintf(saddr, sizeof(saddr), "%p", addr);
+ BeginTag("opaque", "addr", saddr);
+ EndTag("opaque");
+}
+
+void LiteralNull(void)
+{
+ Tag("null");
}
} /* namespace Log */
void ReOpen(void);
void Close(void);
- void Text(const char *text);
- void TextF(const char *format, ...);
-
void BeginCall(const char *function);
void EndCall(void);
void BeginReturn(const char *type);
void EndReturn(void);
+ void BeginArray(const char *type, size_t length);
+ void EndArray(void);
+
void BeginElement(const char *type);
- void BeginElement(const char *type, const char *name);
void EndElement(void);
+ void BeginStruct(const char *type);
+ void EndStruct(void);
+
+ void BeginMember(const char *type, const char *name);
+ void EndMember(void);
+
+ void BeginBitmask(const char *type);
+ void EndBitmask(void);
+
void BeginReference(const char *type, const void *addr);
void EndReference(void);
- void DumpString(const char *str);
- void DumpWString(const wchar_t *str);
-
+ void LiteralBool(bool value);
+ void LiteralSInt(signed long long value);
+ void LiteralUInt(unsigned long long value);
+ void LiteralFloat(double value);
+ void LiteralString(const char *str);
+ void LiteralWString(const wchar_t *str);
+ void LiteralNamedConstant(const char *str);
+ void LiteralOpaque(const void *addr);
+ void LiteralNull(void);
}
#endif /* _LOG_HPP_ */
--- /dev/null
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008-2009 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.
+#
+##########################################################################/
+
+
+'''Trace data model.'''
+
+
+import sys
+import string
+import format
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+
+class Node:
+
+ def visit(self, visitor):
+ raise NotImplementedError
+
+ def __str__(self):
+ stream = StringIO()
+ formatter = format.DefaultFormatter(stream)
+ pretty_printer = PrettyPrinter(formatter)
+ self.visit(pretty_printer)
+ return stream.getvalue()
+
+
+class Literal(Node):
+
+ def __init__(self, value):
+ self.value = value
+
+ def visit(self, visitor):
+ visitor.visit_literal(self)
+
+
+class NamedConstant(Node):
+
+ def __init__(self, name):
+ self.name = name
+
+ def visit(self, visitor):
+ visitor.visit_named_constant(self)
+
+
+class Bitmask(Node):
+
+ def __init__(self, elements):
+ self.elements = elements
+
+ def visit(self, visitor):
+ visitor.visit_bitmask(self)
+
+
+class Array(Node):
+
+ def __init__(self, elements):
+ self.elements = elements
+
+ def visit(self, visitor):
+ visitor.visit_array(self)
+
+
+class Struct(Node):
+
+ def __init__(self, name, members):
+ self.name = name
+ self.members = members
+
+ def visit(self, visitor):
+ visitor.visit_struct(self)
+
+
+class Pointer(Node):
+
+ def __init__(self, address, value):
+ self.address = address
+ self.address = value
+
+ def visit(self, visitor):
+ visitor.visit_pointer(self)
+
+
+class Call(Node):
+
+ def __init__(self, no, name, args, ret, attrs = None):
+ self.no = no
+ self.name = name
+ self.args = args
+ self.ret = ret
+ if attrs is None:
+ self.attrs = {}
+ else:
+ self.attrs = attrs
+
+ def visit(self, visitor):
+ visitor.visit_call(self)
+
+
+class Trace:
+
+ def __init__(self, calls):
+ self.calls = calls
+
+ def visit(self, visitor):
+ visitor.visit_trace(self)
+
+
+class Visitor:
+
+ def visit_literal(self, node):
+ raise NotImplementedError
+
+ def visit_named_constant(self, node):
+ raise NotImplementedError
+
+ def visit_bitmask(self, node):
+ raise NotImplementedError
+
+ def visit_array(self, node):
+ raise NotImplementedError
+
+ def visit_struct(self, node):
+ raise NotImplementedError
+
+ def visit_pointer(self, node):
+ raise NotImplementedError
+
+ def visit_call(self, node):
+ raise NotImplementedError
+
+ def visit_trace(self, node):
+ raise NotImplementedError
+
+
+class PrettyPrinter:
+
+ def __init__(self, formatter):
+ self.formatter = formatter
+
+ def visit_literal(self, node):
+ if isinstance(node.value, basestring):
+ if len(node.value) >= 4096 or node.value.strip(string.printable):
+ self.formatter.text('...')
+ return
+
+ self.formatter.literal('"' + node.value + '"')
+ return
+
+ self.formatter.literal(str(node.value))
+
+ def visit_named_constant(self, node):
+ self.formatter.literal(node.name)
+
+ def visit_bitmask(self, node):
+ if len(node.elements) == 0:
+ self.formatter.literal('0')
+ return
+ if len(node.elements) > 1:
+ self.formatter.text('(')
+ sep = ''
+ for value in node.elements:
+ self.formatter.text(sep)
+ value.visit(self)
+ sep = ' | '
+ if len(node.elements) > 1:
+ self.formatter.text(')')
+
+ def visit_array(self, node):
+ self.formatter.text('{')
+ sep = ''
+ for value in node.elements:
+ self.formatter.text(sep)
+ value.visit(self)
+ sep = ', '
+ self.formatter.text('}')
+
+ def visit_struct(self, node):
+ self.formatter.text('{')
+ sep = ''
+ for name, value in node.members:
+ self.formatter.text(sep)
+ self.formatter.variable(name)
+ self.formatter.text(' = ')
+ value.visit(self)
+ sep = ', '
+ self.formatter.text('}')
+
+ def visit_pointer(self, node):
+ self.formatter.address(node.address)
+
+ def visit_call(self, node):
+ self.formatter.text('%s ' % node.no)
+ self.formatter.function(node.name)
+ self.formatter.text('(')
+ sep = ''
+ for name, value in node.args:
+ self.formatter.text(sep)
+ self.formatter.variable(name)
+ self.formatter.text(' = ')
+ value.visit(self)
+ sep = ', '
+ self.formatter.text(')')
+ if node.ret is not None:
+ self.formatter.text(' = ')
+ node.ret.visit(self)
+
+ def visit_trace(self, node):
+ for call in node.calls:
+ call.visit(self)
+ self.formatter.newline()
+
]
HGLRC = Alias("HGLRC", HANDLE)
-PROC = Intrinsic("PROC", "%p")
+PROC = Alias("PROC", Opaque)
PFD = Flags(DWORD, [
"PFD_DOUBLEBUFFER",
from base import *
-SHORT = Intrinsic("SHORT", "%i")
-USHORT = Intrinsic("USHORT", "%u")
-INT = Intrinsic("INT", "%i")
-UINT = Intrinsic("UINT", "%u")
-LONG = Intrinsic("LONG", "%li")
-ULONG = Intrinsic("ULONG", "%lu")
-FLOAT = Intrinsic("FLOAT", "%f")
+SHORT = Alias("SHORT", Short)
+USHORT = Alias("USHORT", UShort)
+INT = Alias("INT", Int)
+UINT = Alias("UINT", UInt)
+LONG = Alias("LONG", Long)
+ULONG = Alias("ULONG", ULong)
+LONGLONG = Alias("LONGLONG", LongLong)
+FLOAT = Alias("FLOAT", Float)
-INT32 = Intrinsic("INT32", "%i")
-UINT32 = Intrinsic("UINT32", "%i")
+INT32 = Literal("INT32", "UInt")
+UINT32 = Literal("UINT32", "UInt")
-BYTE = Intrinsic("BYTE", "0x%02lx")
-WORD = Intrinsic("WORD", "0x%04lx")
-DWORD = Intrinsic("DWORD", "0x%08lx")
+BYTE = Literal("BYTE", "UInt", base=16)
+WORD = Literal("WORD", "UInt", base=16)
+DWORD = Literal("DWORD", "UInt", base=16)
-BOOL = Intrinsic("BOOL", "%i")
+BOOL = Alias("BOOL", Bool)
LPLONG = Pointer(LONG)
LPWORD = Pointer(WORD)
LPWSTR = WString
LPCWSTR = Const(WString)
-LARGE_INTEGER = Intrinsic("LARGE_INTEGER", "0x%llx")
+LARGE_INTEGER = Struct("LARGE_INTEGER", [
+ (LONGLONG, 'QuadPart'),
+])
+
SIZE_T = Alias("SIZE_T", SizeT)
HRESULT = Alias("HRESULT", Int)
-PVOID = Intrinsic("PVOID", "%p")
+PVOID = Alias("PVOID", Opaque)
LPVOID = PVOID
-HANDLE = Intrinsic("HANDLE", "%p")
-HWND = Intrinsic("HWND", "%p")
-HDC = Intrinsic("HDC", "%p")
-HMONITOR = Intrinsic("HMONITOR", "%p")
+HANDLE = Alias("HANDLE", Opaque)
+HWND = Alias("HWND", Opaque)
+HDC = Alias("HDC", Opaque)
+HMONITOR = Alias("HMONITOR", Opaque)
GUID = Struct("GUID", [
(DWORD, "Data1"),
import xml.parsers.expat
import gzip
+from model import *
+
ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4)
pass
-class Formatter:
-
- def function(self, name):
- return name
-
- def variable(self, name):
- return name
-
- def literal(self, value):
- return str(value)
-
- def address(self, addr):
- return addr
-
-
-class AnsiFormatter(Formatter):
- '''Formatter for plain-text files which outputs ANSI escape codes. See
- http://en.wikipedia.org/wiki/ANSI_escape_code for more information
- concerning ANSI escape codes.
- '''
-
- _csi = '\33['
-
- _normal = '0m'
- _bold = '1m'
- _italic = '3m'
- _red = '31m'
- _green = '32m'
- _blue = '34m'
-
- def _escape(self, code, text):
- return self._csi + code + text + self._csi + self._normal
-
- def function(self, name):
- text = Formatter.function(self, name)
- return self._escape(self._bold, text)
-
- def variable(self, name):
- text = Formatter.variable(self, name)
- return self._escape(self._italic, text)
-
- def literal(self, value):
- text = Formatter.literal(self, value)
- return self._escape(self._blue, text)
-
- def address(self, value):
- text = Formatter.address(self, value)
- return self._escape(self._green, text)
-
-
-def DefaultFormatter():
- if sys.platform in ('linux2', 'cygwin'):
- return AnsiFormatter()
- else:
- return Formatter()
-
-
class TraceParser(XmlParser):
- def __init__(self, stream, formatter):
+ def __init__(self, stream):
XmlParser.__init__(self, stream)
- self.formatter = formatter
+ self.call_no = 0
def parse(self):
self.element_start('trace')
name = attrs['name']
args = []
ret = None
- duration = None
+ properties = {}
while self.token.type == ELEMENT_START:
if self.token.name_or_data == 'arg':
arg = self.parse_arg()
args.append(arg)
elif self.token.name_or_data == 'ret':
ret = self.parse_ret()
- elif self.token.name_or_data == 'duration':
- duration = self.parse_duration()
+ elif self.token.name_or_data in ('duration', 'starttsc', 'endtsc'):
+ property = self.token.name_or_data
+ properties[property] = self.parse_hex(self.token.name_or_data)
elif self.token.name_or_data == 'call':
# ignore nested function calls
self.parse_call()
raise TokenMismatch("<arg ...> or <ret ...>", self.token)
self.element_end('call')
- self.handle_call(name, args, ret, duration)
+ self.call_no += 1
+
+ call = Call(self.call_no, name, args, ret, properties)
+
+ self.handle_call(call)
def parse_arg(self):
attrs = self.element_start('arg')
return value
- def parse_duration(self):
- attrs = self.element_start('duration')
- value = int(self.character_data())
- self.element_end('duration')
+ def parse_hex(self, token_name):
+ attrs = self.element_start(token_name)
+ value = int(self.character_data(), 16)
+ self.element_end(token_name)
return value
def parse_value(self):
- if self.token.type == CHARACTER_DATA:
- return self.formatter.literal(self.character_data())
if self.token.type == ELEMENT_START:
- if self.token.name_or_data == 'elem':
- return self.parse_elems()
+ if self.token.name_or_data == 'int':
+ return self.parse_int()
+ if self.token.name_or_data == 'uint':
+ return self.parse_uint()
+ if self.token.name_or_data == 'float':
+ return self.parse_float()
+ if self.token.name_or_data == 'string':
+ return self.parse_string()
+ if self.token.name_or_data == 'wstring':
+ return self.parse_wstring()
+ if self.token.name_or_data == 'const':
+ return self.parse_const()
+ if self.token.name_or_data == 'bitmask':
+ return self.parse_bitmask()
if self.token.name_or_data == 'ref':
return self.parse_ref()
raise TokenMismatch("<elem ...>, <ref ...>, or text", self.token)
elems = [self.parse_elem()]
while self.token.type != ELEMENT_END:
elems.append(self.parse_elem())
- return '{' + ', '.join(elems) + '}'
+ return Struct("", elems)
def parse_elem(self):
attrs = self.element_start('elem')
try:
name = attrs['name']
except KeyError:
- pass
- else:
- value = name + ' = ' + value
+ name = ""
- return value
+ return name, value
def parse_ref(self):
attrs = self.element_start('ref')
if self.token.type != ELEMENT_END:
- value = '&' + self.parse_value()
+ value = self.parse_value()
else:
- value = self.formatter.address(attrs['addr'])
+ value = None
self.element_end('ref')
- return value
+ return Pointer(attrs['addr'], value)
- def handle_call(self, name, args, ret, duration):
- s = ''
+ def parse_bitmask(self):
+ self.element_start('bitmask')
+ elems = []
+ while self.token.type != ELEMENT_END:
+ elems.append(self.parse_value())
+ self.element_end('bitmask')
+ return Bitmask(elems)
+
+ def parse_int(self):
+ self.element_start('int')
+ value = self.character_data()
+ self.element_end('int')
+ return Literal(int(value))
+
+ def parse_uint(self):
+ self.element_start('uint')
+ value = self.character_data()
+ self.element_end('uint')
+ return Literal(int(value))
+
+ def parse_float(self):
+ self.element_start('float')
+ value = self.character_data()
+ self.element_end('float')
+ return Literal(float(value))
+
+ def parse_string(self):
+ self.element_start('string')
+ value = self.character_data()
+ self.element_end('string')
+ return Literal(value)
+
+ def parse_wstring(self):
+ self.element_start('wstring')
+ value = self.character_data()
+ self.element_end('wstring')
+ return Literal(value)
+
+ def parse_const(self):
+ self.element_start('const')
+ value = self.character_data()
+ self.element_end('const')
+ return NamedConstant(value)
+
+ def handle_call(self, call):
+ pass
+
+
+class DumpTraceParser(TraceParser):
- #if duration is not None:
- # s += '%8u ' % (duration)
+ def __init__(self, stream, formatter):
+ XmlParser.__init__(self, stream)
+ self.formatter = formatter
+ self.pretty_printer = PrettyPrinter(self.formatter)
+ self.call_no = 0
- s += self.formatter.function(name)
- s += '(' + ', '.join([self.formatter.variable(name) + ' = ' + value for name, value in args]) + ')'
- if ret is not None:
- s += ' = ' + ret
- s += '\n'
-
- try:
- sys.stdout.write(s)
- except IOError:
- # catch broken pipe
- sys.exit(0)
+ def handle_call(self, call):
+ call.visit(self.pretty_printer)
+ self.formatter.newline()
class StatsTraceParser(TraceParser):
self.stats[name] = nr_calls, total_duration
-def main():
- parser = optparse.OptionParser(
- usage="\n\t%prog [options] [file] ...")
- parser.add_option(
- '-s', '--stats',
- action="store_true",
- dest="stats", default=False,
- help="generate statistics instead")
- parser.add_option(
- '--color', '--colour',
- type="choice", choices=('never', 'always', 'auto'), metavar='WHEN',
- dest="color", default="always",
- help="coloring: never, always, or auto [default: %default]")
- (options, args) = parser.parse_args(sys.argv[1:])
-
- if options.color == 'always' or options.color == 'auto' and sys.stdout.isatty():
- formatter = DefaultFormatter()
- else:
- formatter = Formatter()
+class Main:
+
+ def __init__(self):
+ pass
+
+ def main(self):
+ optparser = self.get_optparser()
+ (options, args) = optparser.parse_args(sys.argv[1:])
- if options.stats:
- factory = StatsTraceParser
- else:
- factory = TraceParser
-
- if args:
- for arg in args:
- if arg.endswith('.gz'):
- stream = GzipFile(arg, 'rb')
- elif arg.endswith('.bz2'):
- from bz2 import BZ2File
- stream = BZ2File(arg, 'rt')
- else:
- stream = open(arg, 'rt')
- parser = factory(stream, formatter)
- parser.parse()
- else:
- parser = factory(sys.stdin, formatter)
- parser.parse()
+ if args:
+ for arg in args:
+ if arg.endswith('.gz'):
+ from gzip import GzipFile
+ stream = GzipFile(arg, 'rb')
+ elif arg.endswith('.bz2'):
+ from bz2 import BZ2File
+ stream = BZ2File(arg, 'rU')
+ else:
+ stream = open(arg, 'rt')
+ self.process_arg(stream, options)
+ else:
+ self.process_arg(stream, options)
+
+ def get_optparser(self):
+ optparser = optparse.OptionParser(
+ usage="\n\t%prog [options] [traces] ...")
+ optparser.add_option(
+ '-s', '--stats',
+ action="store_true",
+ dest="stats", default=False,
+ help="generate statistics instead")
+ optparser.add_option(
+ '--color', '--colour',
+ type="choice", choices=('never', 'always', 'auto'), metavar='WHEN',
+ dest="color", default="always",
+ help="coloring: never, always, or auto [default: %default]")
+ return optparser
+
+ def process_arg(self, stream, options):
+ if options.color == 'always' or options.color == 'auto' and sys.stdout.isatty():
+ formatter = format.DefaultFormatter(sys.stdout)
+ else:
+ formatter = format.Formatter(sys.stdout)
+
+ if options.stats:
+ factory = StatsTraceParser
+ else:
+ factory = DumpTraceParser
+
+ parser = DumpTraceParser(stream, formatter)
+ parser.parse()
if __name__ == '__main__':
- main()
+ Main().main()
+