xref: /aosp_15_r20/external/mesa3d/src/gallium/tools/trace/parse.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*61046927SAndroid Build Coastguard Worker##########################################################################
3*61046927SAndroid Build Coastguard Worker#
4*61046927SAndroid Build Coastguard Worker# Copyright 2008 VMware, Inc.
5*61046927SAndroid Build Coastguard Worker# All Rights Reserved.
6*61046927SAndroid Build Coastguard Worker#
7*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the
9*61046927SAndroid Build Coastguard Worker# "Software"), to deal in the Software without restriction, including
10*61046927SAndroid Build Coastguard Worker# without limitation the rights to use, copy, modify, merge, publish,
11*61046927SAndroid Build Coastguard Worker# distribute, sub license, and/or sell copies of the Software, and to
12*61046927SAndroid Build Coastguard Worker# permit persons to whom the Software is furnished to do so, subject to
13*61046927SAndroid Build Coastguard Worker# the following conditions:
14*61046927SAndroid Build Coastguard Worker#
15*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the
16*61046927SAndroid Build Coastguard Worker# next paragraph) shall be included in all copies or substantial portions
17*61046927SAndroid Build Coastguard Worker# of the Software.
18*61046927SAndroid Build Coastguard Worker#
19*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20*61046927SAndroid Build Coastguard Worker# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21*61046927SAndroid Build Coastguard Worker# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22*61046927SAndroid Build Coastguard Worker# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23*61046927SAndroid Build Coastguard Worker# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24*61046927SAndroid Build Coastguard Worker# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25*61046927SAndroid Build Coastguard Worker# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26*61046927SAndroid Build Coastguard Worker#
27*61046927SAndroid Build Coastguard Worker##########################################################################
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Workerimport io
31*61046927SAndroid Build Coastguard Workerimport sys
32*61046927SAndroid Build Coastguard Workerimport xml.parsers.expat as xpat
33*61046927SAndroid Build Coastguard Workerimport argparse
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Workerimport format
36*61046927SAndroid Build Coastguard Workerfrom model import *
37*61046927SAndroid Build Coastguard Worker
38*61046927SAndroid Build Coastguard Worker
39*61046927SAndroid Build Coastguard Workertrace_ignore_calls = set((
40*61046927SAndroid Build Coastguard Worker    ("pipe_screen", "is_format_supported"),
41*61046927SAndroid Build Coastguard Worker    ("pipe_screen", "get_name"),
42*61046927SAndroid Build Coastguard Worker    ("pipe_screen", "get_vendor"),
43*61046927SAndroid Build Coastguard Worker    ("pipe_screen", "get_param"),
44*61046927SAndroid Build Coastguard Worker    ("pipe_screen", "get_paramf"),
45*61046927SAndroid Build Coastguard Worker    ("pipe_screen", "get_shader_param"),
46*61046927SAndroid Build Coastguard Worker    ("pipe_screen", "get_compute_param"),
47*61046927SAndroid Build Coastguard Worker    ("pipe_screen", "get_disk_shader_cache"),
48*61046927SAndroid Build Coastguard Worker))
49*61046927SAndroid Build Coastguard Worker
50*61046927SAndroid Build Coastguard Worker
51*61046927SAndroid Build Coastguard Workerdef trace_call_ignore(call):
52*61046927SAndroid Build Coastguard Worker    return (call.klass, call.method) in trace_ignore_calls
53*61046927SAndroid Build Coastguard Worker
54*61046927SAndroid Build Coastguard Worker
55*61046927SAndroid Build Coastguard WorkerELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4)
56*61046927SAndroid Build Coastguard Worker
57*61046927SAndroid Build Coastguard Worker
58*61046927SAndroid Build Coastguard Workerclass XmlToken:
59*61046927SAndroid Build Coastguard Worker
60*61046927SAndroid Build Coastguard Worker    def __init__(self, type, name_or_data, attrs = None, line = None, column = None):
61*61046927SAndroid Build Coastguard Worker        assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF)
62*61046927SAndroid Build Coastguard Worker        self.type = type
63*61046927SAndroid Build Coastguard Worker        self.name_or_data = name_or_data
64*61046927SAndroid Build Coastguard Worker        self.attrs = attrs
65*61046927SAndroid Build Coastguard Worker        self.line = line
66*61046927SAndroid Build Coastguard Worker        self.column = column
67*61046927SAndroid Build Coastguard Worker
68*61046927SAndroid Build Coastguard Worker    def __str__(self):
69*61046927SAndroid Build Coastguard Worker        if self.type == ELEMENT_START:
70*61046927SAndroid Build Coastguard Worker            return '<' + self.name_or_data + ' ...>'
71*61046927SAndroid Build Coastguard Worker        if self.type == ELEMENT_END:
72*61046927SAndroid Build Coastguard Worker            return '</' + self.name_or_data + '>'
73*61046927SAndroid Build Coastguard Worker        if self.type == CHARACTER_DATA:
74*61046927SAndroid Build Coastguard Worker            return self.name_or_data
75*61046927SAndroid Build Coastguard Worker        if self.type == EOF:
76*61046927SAndroid Build Coastguard Worker            return 'end of file'
77*61046927SAndroid Build Coastguard Worker        assert 0
78*61046927SAndroid Build Coastguard Worker
79*61046927SAndroid Build Coastguard Worker
80*61046927SAndroid Build Coastguard Workerclass XmlTokenizer:
81*61046927SAndroid Build Coastguard Worker    """Expat based XML tokenizer."""
82*61046927SAndroid Build Coastguard Worker
83*61046927SAndroid Build Coastguard Worker    def __init__(self, fp, skip_ws = True):
84*61046927SAndroid Build Coastguard Worker        self.fp = fp
85*61046927SAndroid Build Coastguard Worker        self.tokens = []
86*61046927SAndroid Build Coastguard Worker        self.index = 0
87*61046927SAndroid Build Coastguard Worker        self.final = False
88*61046927SAndroid Build Coastguard Worker        self.skip_ws = skip_ws
89*61046927SAndroid Build Coastguard Worker
90*61046927SAndroid Build Coastguard Worker        self.character_pos = 0, 0
91*61046927SAndroid Build Coastguard Worker        self.character_data = []
92*61046927SAndroid Build Coastguard Worker
93*61046927SAndroid Build Coastguard Worker        self.parser = xpat.ParserCreate()
94*61046927SAndroid Build Coastguard Worker        self.parser.StartElementHandler  = self.handle_element_start
95*61046927SAndroid Build Coastguard Worker        self.parser.EndElementHandler    = self.handle_element_end
96*61046927SAndroid Build Coastguard Worker        self.parser.CharacterDataHandler = self.handle_character_data
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker    def handle_element_start(self, name, attributes):
99*61046927SAndroid Build Coastguard Worker        self.finish_character_data()
100*61046927SAndroid Build Coastguard Worker        line, column = self.pos()
101*61046927SAndroid Build Coastguard Worker        token = XmlToken(ELEMENT_START, name, attributes, line, column)
102*61046927SAndroid Build Coastguard Worker        self.tokens.append(token)
103*61046927SAndroid Build Coastguard Worker
104*61046927SAndroid Build Coastguard Worker    def handle_element_end(self, name):
105*61046927SAndroid Build Coastguard Worker        self.finish_character_data()
106*61046927SAndroid Build Coastguard Worker        line, column = self.pos()
107*61046927SAndroid Build Coastguard Worker        token = XmlToken(ELEMENT_END, name, None, line, column)
108*61046927SAndroid Build Coastguard Worker        self.tokens.append(token)
109*61046927SAndroid Build Coastguard Worker
110*61046927SAndroid Build Coastguard Worker    def handle_character_data(self, data):
111*61046927SAndroid Build Coastguard Worker        if not self.character_data:
112*61046927SAndroid Build Coastguard Worker            self.character_pos = self.pos()
113*61046927SAndroid Build Coastguard Worker        self.character_data.append(data)
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker    def finish_character_data(self):
116*61046927SAndroid Build Coastguard Worker        if self.character_data:
117*61046927SAndroid Build Coastguard Worker            character_data = ''.join(self.character_data)
118*61046927SAndroid Build Coastguard Worker            if not self.skip_ws or not character_data.isspace():
119*61046927SAndroid Build Coastguard Worker                line, column = self.character_pos
120*61046927SAndroid Build Coastguard Worker                token = XmlToken(CHARACTER_DATA, character_data, None, line, column)
121*61046927SAndroid Build Coastguard Worker                self.tokens.append(token)
122*61046927SAndroid Build Coastguard Worker            self.character_data = []
123*61046927SAndroid Build Coastguard Worker
124*61046927SAndroid Build Coastguard Worker    def next(self):
125*61046927SAndroid Build Coastguard Worker        size = 16*1024
126*61046927SAndroid Build Coastguard Worker        while self.index >= len(self.tokens) and not self.final:
127*61046927SAndroid Build Coastguard Worker            self.tokens = []
128*61046927SAndroid Build Coastguard Worker            self.index = 0
129*61046927SAndroid Build Coastguard Worker            data = self.fp.read(size)
130*61046927SAndroid Build Coastguard Worker            self.final = len(data) < size
131*61046927SAndroid Build Coastguard Worker            data = data.rstrip('\0')
132*61046927SAndroid Build Coastguard Worker            try:
133*61046927SAndroid Build Coastguard Worker                self.parser.Parse(data, self.final)
134*61046927SAndroid Build Coastguard Worker            except xpat.ExpatError as e:
135*61046927SAndroid Build Coastguard Worker                #if e.code == xpat.errors.XML_ERROR_NO_ELEMENTS:
136*61046927SAndroid Build Coastguard Worker                if e.code == 3:
137*61046927SAndroid Build Coastguard Worker                    pass
138*61046927SAndroid Build Coastguard Worker                else:
139*61046927SAndroid Build Coastguard Worker                    raise e
140*61046927SAndroid Build Coastguard Worker        if self.index >= len(self.tokens):
141*61046927SAndroid Build Coastguard Worker            line, column = self.pos()
142*61046927SAndroid Build Coastguard Worker            token = XmlToken(EOF, None, None, line, column)
143*61046927SAndroid Build Coastguard Worker        else:
144*61046927SAndroid Build Coastguard Worker            token = self.tokens[self.index]
145*61046927SAndroid Build Coastguard Worker            self.index += 1
146*61046927SAndroid Build Coastguard Worker        return token
147*61046927SAndroid Build Coastguard Worker
148*61046927SAndroid Build Coastguard Worker    def pos(self):
149*61046927SAndroid Build Coastguard Worker        return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber
150*61046927SAndroid Build Coastguard Worker
151*61046927SAndroid Build Coastguard Worker
152*61046927SAndroid Build Coastguard Workerclass TokenMismatch(Exception):
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker    def __init__(self, expected, found):
155*61046927SAndroid Build Coastguard Worker        self.expected = expected
156*61046927SAndroid Build Coastguard Worker        self.found = found
157*61046927SAndroid Build Coastguard Worker
158*61046927SAndroid Build Coastguard Worker    def __str__(self):
159*61046927SAndroid Build Coastguard Worker        return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found))
160*61046927SAndroid Build Coastguard Worker
161*61046927SAndroid Build Coastguard Worker
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Workerclass XmlParser:
164*61046927SAndroid Build Coastguard Worker    """Base XML document parser."""
165*61046927SAndroid Build Coastguard Worker
166*61046927SAndroid Build Coastguard Worker    def __init__(self, fp):
167*61046927SAndroid Build Coastguard Worker        self.tokenizer = XmlTokenizer(fp)
168*61046927SAndroid Build Coastguard Worker        self.consume()
169*61046927SAndroid Build Coastguard Worker
170*61046927SAndroid Build Coastguard Worker    def consume(self):
171*61046927SAndroid Build Coastguard Worker        self.token = self.tokenizer.next()
172*61046927SAndroid Build Coastguard Worker
173*61046927SAndroid Build Coastguard Worker    def match_element_start(self, name):
174*61046927SAndroid Build Coastguard Worker        return self.token.type == ELEMENT_START and self.token.name_or_data == name
175*61046927SAndroid Build Coastguard Worker
176*61046927SAndroid Build Coastguard Worker    def match_element_end(self, name):
177*61046927SAndroid Build Coastguard Worker        return self.token.type == ELEMENT_END and self.token.name_or_data == name
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker    def element_start(self, name):
180*61046927SAndroid Build Coastguard Worker        while self.token.type == CHARACTER_DATA:
181*61046927SAndroid Build Coastguard Worker            self.consume()
182*61046927SAndroid Build Coastguard Worker        if self.token.type != ELEMENT_START:
183*61046927SAndroid Build Coastguard Worker            raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token)
184*61046927SAndroid Build Coastguard Worker        if self.token.name_or_data != name:
185*61046927SAndroid Build Coastguard Worker            raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token)
186*61046927SAndroid Build Coastguard Worker        attrs = self.token.attrs
187*61046927SAndroid Build Coastguard Worker        self.consume()
188*61046927SAndroid Build Coastguard Worker        return attrs
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Worker    def element_end(self, name):
191*61046927SAndroid Build Coastguard Worker        while self.token.type == CHARACTER_DATA:
192*61046927SAndroid Build Coastguard Worker            self.consume()
193*61046927SAndroid Build Coastguard Worker        if self.token.type != ELEMENT_END:
194*61046927SAndroid Build Coastguard Worker            raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token)
195*61046927SAndroid Build Coastguard Worker        if self.token.name_or_data != name:
196*61046927SAndroid Build Coastguard Worker            raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token)
197*61046927SAndroid Build Coastguard Worker        self.consume()
198*61046927SAndroid Build Coastguard Worker
199*61046927SAndroid Build Coastguard Worker    def character_data(self, strip = True):
200*61046927SAndroid Build Coastguard Worker        data = ''
201*61046927SAndroid Build Coastguard Worker        while self.token.type == CHARACTER_DATA:
202*61046927SAndroid Build Coastguard Worker            data += self.token.name_or_data
203*61046927SAndroid Build Coastguard Worker            self.consume()
204*61046927SAndroid Build Coastguard Worker        if strip:
205*61046927SAndroid Build Coastguard Worker            data = data.strip()
206*61046927SAndroid Build Coastguard Worker        return data
207*61046927SAndroid Build Coastguard Worker
208*61046927SAndroid Build Coastguard Worker
209*61046927SAndroid Build Coastguard Workerclass TraceParser(XmlParser):
210*61046927SAndroid Build Coastguard Worker
211*61046927SAndroid Build Coastguard Worker    def __init__(self, fp, options, state):
212*61046927SAndroid Build Coastguard Worker        XmlParser.__init__(self, fp)
213*61046927SAndroid Build Coastguard Worker        self.last_call_no = 0
214*61046927SAndroid Build Coastguard Worker        self.state = state
215*61046927SAndroid Build Coastguard Worker        self.options = options
216*61046927SAndroid Build Coastguard Worker
217*61046927SAndroid Build Coastguard Worker    def parse(self):
218*61046927SAndroid Build Coastguard Worker        self.element_start('trace')
219*61046927SAndroid Build Coastguard Worker        while self.token.type not in (ELEMENT_END, EOF):
220*61046927SAndroid Build Coastguard Worker            call = self.parse_call()
221*61046927SAndroid Build Coastguard Worker            call.is_junk = trace_call_ignore(call)
222*61046927SAndroid Build Coastguard Worker            self.handle_call(call)
223*61046927SAndroid Build Coastguard Worker        if self.token.type != EOF:
224*61046927SAndroid Build Coastguard Worker            self.element_end('trace')
225*61046927SAndroid Build Coastguard Worker
226*61046927SAndroid Build Coastguard Worker    def parse_call(self):
227*61046927SAndroid Build Coastguard Worker        attrs = self.element_start('call')
228*61046927SAndroid Build Coastguard Worker        try:
229*61046927SAndroid Build Coastguard Worker            no = int(attrs['no'])
230*61046927SAndroid Build Coastguard Worker        except KeyError as e:
231*61046927SAndroid Build Coastguard Worker            self.last_call_no += 1
232*61046927SAndroid Build Coastguard Worker            no = self.last_call_no
233*61046927SAndroid Build Coastguard Worker        else:
234*61046927SAndroid Build Coastguard Worker            self.last_call_no = no
235*61046927SAndroid Build Coastguard Worker        klass = attrs['class']
236*61046927SAndroid Build Coastguard Worker        method = attrs['method']
237*61046927SAndroid Build Coastguard Worker        args = []
238*61046927SAndroid Build Coastguard Worker        ret = None
239*61046927SAndroid Build Coastguard Worker        time = None
240*61046927SAndroid Build Coastguard Worker        while self.token.type == ELEMENT_START:
241*61046927SAndroid Build Coastguard Worker            if self.token.name_or_data == 'arg':
242*61046927SAndroid Build Coastguard Worker                arg = self.parse_arg()
243*61046927SAndroid Build Coastguard Worker                args.append(arg)
244*61046927SAndroid Build Coastguard Worker            elif self.token.name_or_data == 'ret':
245*61046927SAndroid Build Coastguard Worker                ret = self.parse_ret()
246*61046927SAndroid Build Coastguard Worker            elif self.token.name_or_data == 'call':
247*61046927SAndroid Build Coastguard Worker                # ignore nested function calls
248*61046927SAndroid Build Coastguard Worker                self.parse_call()
249*61046927SAndroid Build Coastguard Worker            elif self.token.name_or_data == 'time':
250*61046927SAndroid Build Coastguard Worker                time = self.parse_time()
251*61046927SAndroid Build Coastguard Worker            else:
252*61046927SAndroid Build Coastguard Worker                raise TokenMismatch("<arg ...> or <ret ...>", self.token)
253*61046927SAndroid Build Coastguard Worker        self.element_end('call')
254*61046927SAndroid Build Coastguard Worker
255*61046927SAndroid Build Coastguard Worker        return Call(no, klass, method, args, ret, time)
256*61046927SAndroid Build Coastguard Worker
257*61046927SAndroid Build Coastguard Worker    def parse_arg(self):
258*61046927SAndroid Build Coastguard Worker        attrs = self.element_start('arg')
259*61046927SAndroid Build Coastguard Worker        name = attrs['name']
260*61046927SAndroid Build Coastguard Worker        value = self.parse_value(name)
261*61046927SAndroid Build Coastguard Worker        self.element_end('arg')
262*61046927SAndroid Build Coastguard Worker
263*61046927SAndroid Build Coastguard Worker        return name, value
264*61046927SAndroid Build Coastguard Worker
265*61046927SAndroid Build Coastguard Worker    def parse_ret(self):
266*61046927SAndroid Build Coastguard Worker        attrs = self.element_start('ret')
267*61046927SAndroid Build Coastguard Worker        value = self.parse_value('ret')
268*61046927SAndroid Build Coastguard Worker        self.element_end('ret')
269*61046927SAndroid Build Coastguard Worker
270*61046927SAndroid Build Coastguard Worker        return value
271*61046927SAndroid Build Coastguard Worker
272*61046927SAndroid Build Coastguard Worker    def parse_time(self):
273*61046927SAndroid Build Coastguard Worker        attrs = self.element_start('time')
274*61046927SAndroid Build Coastguard Worker        time = self.parse_value('time');
275*61046927SAndroid Build Coastguard Worker        self.element_end('time')
276*61046927SAndroid Build Coastguard Worker        return time
277*61046927SAndroid Build Coastguard Worker
278*61046927SAndroid Build Coastguard Worker    def parse_value(self, name):
279*61046927SAndroid Build Coastguard Worker        expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes')
280*61046927SAndroid Build Coastguard Worker        if self.token.type == ELEMENT_START:
281*61046927SAndroid Build Coastguard Worker            if self.token.name_or_data in expected_tokens:
282*61046927SAndroid Build Coastguard Worker                method = getattr(self, 'parse_' +  self.token.name_or_data)
283*61046927SAndroid Build Coastguard Worker                return method(name)
284*61046927SAndroid Build Coastguard Worker        raise TokenMismatch(" or " .join(expected_tokens), self.token)
285*61046927SAndroid Build Coastguard Worker
286*61046927SAndroid Build Coastguard Worker    def parse_null(self, pname):
287*61046927SAndroid Build Coastguard Worker        self.element_start('null')
288*61046927SAndroid Build Coastguard Worker        self.element_end('null')
289*61046927SAndroid Build Coastguard Worker        return Literal(None)
290*61046927SAndroid Build Coastguard Worker
291*61046927SAndroid Build Coastguard Worker    def parse_bool(self, pname):
292*61046927SAndroid Build Coastguard Worker        self.element_start('bool')
293*61046927SAndroid Build Coastguard Worker        value = int(self.character_data())
294*61046927SAndroid Build Coastguard Worker        self.element_end('bool')
295*61046927SAndroid Build Coastguard Worker        return Literal(value)
296*61046927SAndroid Build Coastguard Worker
297*61046927SAndroid Build Coastguard Worker    def parse_int(self, pname):
298*61046927SAndroid Build Coastguard Worker        self.element_start('int')
299*61046927SAndroid Build Coastguard Worker        value = int(self.character_data())
300*61046927SAndroid Build Coastguard Worker        self.element_end('int')
301*61046927SAndroid Build Coastguard Worker        return Literal(value)
302*61046927SAndroid Build Coastguard Worker
303*61046927SAndroid Build Coastguard Worker    def parse_uint(self, pname):
304*61046927SAndroid Build Coastguard Worker        self.element_start('uint')
305*61046927SAndroid Build Coastguard Worker        value = int(self.character_data())
306*61046927SAndroid Build Coastguard Worker        self.element_end('uint')
307*61046927SAndroid Build Coastguard Worker        return Literal(value)
308*61046927SAndroid Build Coastguard Worker
309*61046927SAndroid Build Coastguard Worker    def parse_float(self, pname):
310*61046927SAndroid Build Coastguard Worker        self.element_start('float')
311*61046927SAndroid Build Coastguard Worker        value = float(self.character_data())
312*61046927SAndroid Build Coastguard Worker        self.element_end('float')
313*61046927SAndroid Build Coastguard Worker        return Literal(value)
314*61046927SAndroid Build Coastguard Worker
315*61046927SAndroid Build Coastguard Worker    def parse_enum(self, pname):
316*61046927SAndroid Build Coastguard Worker        self.element_start('enum')
317*61046927SAndroid Build Coastguard Worker        name = self.character_data()
318*61046927SAndroid Build Coastguard Worker        self.element_end('enum')
319*61046927SAndroid Build Coastguard Worker        return NamedConstant(name)
320*61046927SAndroid Build Coastguard Worker
321*61046927SAndroid Build Coastguard Worker    def parse_string(self, pname):
322*61046927SAndroid Build Coastguard Worker        self.element_start('string')
323*61046927SAndroid Build Coastguard Worker        value = self.character_data()
324*61046927SAndroid Build Coastguard Worker        self.element_end('string')
325*61046927SAndroid Build Coastguard Worker        return Literal(value)
326*61046927SAndroid Build Coastguard Worker
327*61046927SAndroid Build Coastguard Worker    def parse_bytes(self, pname):
328*61046927SAndroid Build Coastguard Worker        self.element_start('bytes')
329*61046927SAndroid Build Coastguard Worker        value = self.character_data()
330*61046927SAndroid Build Coastguard Worker        self.element_end('bytes')
331*61046927SAndroid Build Coastguard Worker        return Blob(value)
332*61046927SAndroid Build Coastguard Worker
333*61046927SAndroid Build Coastguard Worker    def parse_array(self, pname):
334*61046927SAndroid Build Coastguard Worker        self.element_start('array')
335*61046927SAndroid Build Coastguard Worker        elems = []
336*61046927SAndroid Build Coastguard Worker        while self.token.type != ELEMENT_END:
337*61046927SAndroid Build Coastguard Worker            elems.append(self.parse_elem('array'))
338*61046927SAndroid Build Coastguard Worker        self.element_end('array')
339*61046927SAndroid Build Coastguard Worker        return Array(elems)
340*61046927SAndroid Build Coastguard Worker
341*61046927SAndroid Build Coastguard Worker    def parse_elem(self, pname):
342*61046927SAndroid Build Coastguard Worker        self.element_start('elem')
343*61046927SAndroid Build Coastguard Worker        value = self.parse_value('elem')
344*61046927SAndroid Build Coastguard Worker        self.element_end('elem')
345*61046927SAndroid Build Coastguard Worker        return value
346*61046927SAndroid Build Coastguard Worker
347*61046927SAndroid Build Coastguard Worker    def parse_struct(self, pname):
348*61046927SAndroid Build Coastguard Worker        attrs = self.element_start('struct')
349*61046927SAndroid Build Coastguard Worker        name = attrs['name']
350*61046927SAndroid Build Coastguard Worker        members = []
351*61046927SAndroid Build Coastguard Worker        while self.token.type != ELEMENT_END:
352*61046927SAndroid Build Coastguard Worker            members.append(self.parse_member(name))
353*61046927SAndroid Build Coastguard Worker        self.element_end('struct')
354*61046927SAndroid Build Coastguard Worker        return Struct(name, members)
355*61046927SAndroid Build Coastguard Worker
356*61046927SAndroid Build Coastguard Worker    def parse_member(self, pname):
357*61046927SAndroid Build Coastguard Worker        attrs = self.element_start('member')
358*61046927SAndroid Build Coastguard Worker        name = attrs['name']
359*61046927SAndroid Build Coastguard Worker        value = self.parse_value(name)
360*61046927SAndroid Build Coastguard Worker        self.element_end('member')
361*61046927SAndroid Build Coastguard Worker
362*61046927SAndroid Build Coastguard Worker        return name, value
363*61046927SAndroid Build Coastguard Worker
364*61046927SAndroid Build Coastguard Worker    def parse_ptr(self, pname):
365*61046927SAndroid Build Coastguard Worker        self.element_start('ptr')
366*61046927SAndroid Build Coastguard Worker        address = self.character_data()
367*61046927SAndroid Build Coastguard Worker        self.element_end('ptr')
368*61046927SAndroid Build Coastguard Worker
369*61046927SAndroid Build Coastguard Worker        return Pointer(self.state, address, pname)
370*61046927SAndroid Build Coastguard Worker
371*61046927SAndroid Build Coastguard Worker    def handle_call(self, call):
372*61046927SAndroid Build Coastguard Worker        pass
373*61046927SAndroid Build Coastguard Worker
374*61046927SAndroid Build Coastguard Worker
375*61046927SAndroid Build Coastguard Workerclass SimpleTraceDumper(TraceParser):
376*61046927SAndroid Build Coastguard Worker
377*61046927SAndroid Build Coastguard Worker    def __init__(self, fp, options, formatter, state):
378*61046927SAndroid Build Coastguard Worker        TraceParser.__init__(self, fp, options, state)
379*61046927SAndroid Build Coastguard Worker        self.options = options
380*61046927SAndroid Build Coastguard Worker        self.formatter = formatter
381*61046927SAndroid Build Coastguard Worker        self.pretty_printer = PrettyPrinter(self.formatter, options)
382*61046927SAndroid Build Coastguard Worker
383*61046927SAndroid Build Coastguard Worker    def handle_call(self, call):
384*61046927SAndroid Build Coastguard Worker        if self.options.ignore_junk and call.is_junk:
385*61046927SAndroid Build Coastguard Worker            return
386*61046927SAndroid Build Coastguard Worker
387*61046927SAndroid Build Coastguard Worker        call.visit(self.pretty_printer)
388*61046927SAndroid Build Coastguard Worker
389*61046927SAndroid Build Coastguard Worker
390*61046927SAndroid Build Coastguard Workerclass TraceDumper(SimpleTraceDumper):
391*61046927SAndroid Build Coastguard Worker
392*61046927SAndroid Build Coastguard Worker    def __init__(self, fp, options, formatter, state):
393*61046927SAndroid Build Coastguard Worker        SimpleTraceDumper.__init__(self, fp, options, formatter, state)
394*61046927SAndroid Build Coastguard Worker        self.call_stack = []
395*61046927SAndroid Build Coastguard Worker
396*61046927SAndroid Build Coastguard Worker    def handle_call(self, call):
397*61046927SAndroid Build Coastguard Worker        if self.options.ignore_junk and call.is_junk:
398*61046927SAndroid Build Coastguard Worker            return
399*61046927SAndroid Build Coastguard Worker
400*61046927SAndroid Build Coastguard Worker        if self.options.named_ptrs:
401*61046927SAndroid Build Coastguard Worker            self.call_stack.append(call)
402*61046927SAndroid Build Coastguard Worker        else:
403*61046927SAndroid Build Coastguard Worker            call.visit(self.pretty_printer)
404*61046927SAndroid Build Coastguard Worker
405*61046927SAndroid Build Coastguard Worker
406*61046927SAndroid Build Coastguard Workerclass ParseOptions(ModelOptions):
407*61046927SAndroid Build Coastguard Worker
408*61046927SAndroid Build Coastguard Worker    def __init__(self, args=None):
409*61046927SAndroid Build Coastguard Worker        # Initialize options local to this module
410*61046927SAndroid Build Coastguard Worker        self.plain = False
411*61046927SAndroid Build Coastguard Worker        self.ignore_junk = False
412*61046927SAndroid Build Coastguard Worker
413*61046927SAndroid Build Coastguard Worker        ModelOptions.__init__(self, args)
414*61046927SAndroid Build Coastguard Worker
415*61046927SAndroid Build Coastguard Worker
416*61046927SAndroid Build Coastguard Workerclass Main:
417*61046927SAndroid Build Coastguard Worker    '''Common main class for all retrace command line utilities.'''
418*61046927SAndroid Build Coastguard Worker
419*61046927SAndroid Build Coastguard Worker    def __init__(self):
420*61046927SAndroid Build Coastguard Worker        pass
421*61046927SAndroid Build Coastguard Worker
422*61046927SAndroid Build Coastguard Worker    def main(self):
423*61046927SAndroid Build Coastguard Worker        optparser = self.get_optparser()
424*61046927SAndroid Build Coastguard Worker        args = optparser.parse_args()
425*61046927SAndroid Build Coastguard Worker        options = self.make_options(args)
426*61046927SAndroid Build Coastguard Worker
427*61046927SAndroid Build Coastguard Worker        for fname in args.filename:
428*61046927SAndroid Build Coastguard Worker            try:
429*61046927SAndroid Build Coastguard Worker                if fname.endswith('.gz'):
430*61046927SAndroid Build Coastguard Worker                    from gzip import GzipFile
431*61046927SAndroid Build Coastguard Worker                    stream = io.TextIOWrapper(GzipFile(fname, 'rb'))
432*61046927SAndroid Build Coastguard Worker                elif fname.endswith('.bz2'):
433*61046927SAndroid Build Coastguard Worker                    from bz2 import BZ2File
434*61046927SAndroid Build Coastguard Worker                    stream = io.TextIOWrapper(BZ2File(fname, 'rb'))
435*61046927SAndroid Build Coastguard Worker                else:
436*61046927SAndroid Build Coastguard Worker                    stream = open(fname, 'rt')
437*61046927SAndroid Build Coastguard Worker            except Exception as e:
438*61046927SAndroid Build Coastguard Worker                print("ERROR: {}".format(str(e)))
439*61046927SAndroid Build Coastguard Worker                sys.exit(1)
440*61046927SAndroid Build Coastguard Worker
441*61046927SAndroid Build Coastguard Worker            self.process_arg(stream, options)
442*61046927SAndroid Build Coastguard Worker
443*61046927SAndroid Build Coastguard Worker    def make_options(self, args):
444*61046927SAndroid Build Coastguard Worker        return ParseOptions(args)
445*61046927SAndroid Build Coastguard Worker
446*61046927SAndroid Build Coastguard Worker    def get_optparser(self):
447*61046927SAndroid Build Coastguard Worker        estr = "\nList of junk calls:\n"
448*61046927SAndroid Build Coastguard Worker        for klass, call in sorted(trace_ignore_calls):
449*61046927SAndroid Build Coastguard Worker            estr += f"  {klass}::{call}\n"
450*61046927SAndroid Build Coastguard Worker
451*61046927SAndroid Build Coastguard Worker        optparser = argparse.ArgumentParser(
452*61046927SAndroid Build Coastguard Worker            description="Parse and dump Gallium trace(s)",
453*61046927SAndroid Build Coastguard Worker            formatter_class=argparse.RawDescriptionHelpFormatter,
454*61046927SAndroid Build Coastguard Worker            epilog=estr)
455*61046927SAndroid Build Coastguard Worker
456*61046927SAndroid Build Coastguard Worker        optparser.add_argument("filename", action="extend", nargs="+",
457*61046927SAndroid Build Coastguard Worker            type=str, metavar="filename", help="Gallium trace filename (plain or .gz, .bz2)")
458*61046927SAndroid Build Coastguard Worker
459*61046927SAndroid Build Coastguard Worker        optparser.add_argument("-p", "--plain",
460*61046927SAndroid Build Coastguard Worker            action="store_const", const=True, default=False,
461*61046927SAndroid Build Coastguard Worker            dest="plain", help="disable ANSI color etc. formatting")
462*61046927SAndroid Build Coastguard Worker
463*61046927SAndroid Build Coastguard Worker        optparser.add_argument("-S", "--suppress",
464*61046927SAndroid Build Coastguard Worker            action="store_const", const=True, default=False,
465*61046927SAndroid Build Coastguard Worker            dest="suppress_variants", help="suppress some variants in output for better diffability")
466*61046927SAndroid Build Coastguard Worker
467*61046927SAndroid Build Coastguard Worker        optparser.add_argument("-N", "--named",
468*61046927SAndroid Build Coastguard Worker            action="store_const", const=True, default=False,
469*61046927SAndroid Build Coastguard Worker            dest="named_ptrs", help="generate symbolic names for raw pointer values")
470*61046927SAndroid Build Coastguard Worker
471*61046927SAndroid Build Coastguard Worker        optparser.add_argument("-M", "--method-only",
472*61046927SAndroid Build Coastguard Worker            action="store_const", const=True, default=False,
473*61046927SAndroid Build Coastguard Worker            dest="method_only", help="output only call names without arguments")
474*61046927SAndroid Build Coastguard Worker
475*61046927SAndroid Build Coastguard Worker        optparser.add_argument("-I", "--ignore-junk",
476*61046927SAndroid Build Coastguard Worker            action="store_const", const=True, default=False,
477*61046927SAndroid Build Coastguard Worker            dest="ignore_junk", help="filter out/ignore junk calls (see below)")
478*61046927SAndroid Build Coastguard Worker
479*61046927SAndroid Build Coastguard Worker        return optparser
480*61046927SAndroid Build Coastguard Worker
481*61046927SAndroid Build Coastguard Worker    def process_arg(self, stream, options):
482*61046927SAndroid Build Coastguard Worker        if options.plain:
483*61046927SAndroid Build Coastguard Worker            formatter = format.Formatter(sys.stdout)
484*61046927SAndroid Build Coastguard Worker        else:
485*61046927SAndroid Build Coastguard Worker            formatter = format.DefaultFormatter(sys.stdout)
486*61046927SAndroid Build Coastguard Worker
487*61046927SAndroid Build Coastguard Worker        dump = TraceDumper(stream, options, formatter, TraceStateData())
488*61046927SAndroid Build Coastguard Worker        dump.parse()
489*61046927SAndroid Build Coastguard Worker
490*61046927SAndroid Build Coastguard Worker        if options.named_ptrs:
491*61046927SAndroid Build Coastguard Worker            for call in dump.call_stack:
492*61046927SAndroid Build Coastguard Worker                call.visit(dump.pretty_printer)
493*61046927SAndroid Build Coastguard Worker
494*61046927SAndroid Build Coastguard Worker
495*61046927SAndroid Build Coastguard Workerif __name__ == '__main__':
496*61046927SAndroid Build Coastguard Worker    Main().main()
497