1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#!/usr/bin/env python
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org##########################################################################
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# All Rights Reserved.
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Permission is hereby granted, free of charge, to any person obtaining a
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# copy of this software and associated documentation files (the
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# "Software"), to deal in the Software without restriction, including
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# without limitation the rights to use, copy, modify, merge, publish,
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# distribute, sub license, and/or sell copies of the Software, and to
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# permit persons to whom the Software is furnished to do so, subject to
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# the following conditions:
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# The above copyright notice and this permission notice (including the
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# next paragraph) shall be included in all copies or substantial portions
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# of the Software.
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org##########################################################################
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org'''Trace data model.'''
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport sys
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport string
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport format
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtry:
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    from cStringIO import StringIO
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgexcept ImportError:
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    from StringIO import StringIO
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass Node:
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit(self, visitor):
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise NotImplementedError
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def __str__(self):
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        stream = StringIO()
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        formatter = format.DefaultFormatter(stream)
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        pretty_printer = PrettyPrinter(formatter)
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.visit(pretty_printer)
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return stream.getvalue()
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass Literal(Node):
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def __init__(self, value):
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.value = value
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit(self, visitor):
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        visitor.visit_literal(self)
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass NamedConstant(Node):
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def __init__(self, name):
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.name = name
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit(self, visitor):
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        visitor.visit_named_constant(self)
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass Array(Node):
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def __init__(self, elements):
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.elements = elements
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit(self, visitor):
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        visitor.visit_array(self)
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass Struct(Node):
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def __init__(self, name, members):
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.name = name
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.members = members
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit(self, visitor):
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        visitor.visit_struct(self)
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass Pointer(Node):
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def __init__(self, address):
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.address = address
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit(self, visitor):
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        visitor.visit_pointer(self)
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass Call:
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def __init__(self, no, klass, method, args, ret):
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.no = no
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.klass = klass
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.method = method
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.args = args
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.ret = ret
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit(self, visitor):
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        visitor.visit_call(self)
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass Trace:
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def __init__(self, calls):
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.calls = calls
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit(self, visitor):
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        visitor.visit_trace(self)
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass Visitor:
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_literal(self, node):
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise NotImplementedError
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_named_constant(self, node):
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise NotImplementedError
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_array(self, node):
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise NotImplementedError
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_struct(self, node):
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise NotImplementedError
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_pointer(self, node):
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise NotImplementedError
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_call(self, node):
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise NotImplementedError
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_trace(self, node):
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise NotImplementedError
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass PrettyPrinter:
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def __init__(self, formatter):
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter = formatter
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_literal(self, node):
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if node.value is None:
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.literal('NULL')
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if isinstance(node.value, basestring):
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if len(node.value) >= 4096 or node.value.strip(string.printable):
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                self.formatter.address('blob(%u)' % len(node.value))
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                #self.formatter.text('...')
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                return
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.literal('"' + node.value + '"')
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.literal(repr(node.value))
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_named_constant(self, node):
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.literal(node.name)
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_array(self, node):
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.text('{')
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        sep = ''
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for value in node.elements:
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.text(sep)
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            value.visit(self)
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            sep = ', '
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.text('}')
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_struct(self, node):
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.text('{')
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        sep = ''
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for name, value in node.members:
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.text(sep)
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.variable(name)
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.text(' = ')
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            value.visit(self)
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            sep = ', '
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.text('}')
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_pointer(self, node):
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.address(node.address)
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_call(self, node):
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.text('%s ' % node.no)
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if node.klass is not None:
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.function(node.klass + '::' + node.method)
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        else:
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.function(node.method)
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.text('(')
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        sep = ''
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for name, value in node.args:
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.text(sep)
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.variable(name)
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.text(' = ')
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            value.visit(self)
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            sep = ', '
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        self.formatter.text(')')
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if node.ret is not None:
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.text(' = ')
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            node.ret.visit(self)
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def visit_trace(self, node):
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for call in node.calls:
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            call.visit(self)
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            self.formatter.newline()
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
219