17ec681f3Smrg#!/usr/bin/env python3
23464ebd5Sriastradh##########################################################################
33464ebd5Sriastradh#
4af69d88dSmrg# Copyright 2008 VMware, Inc.
53464ebd5Sriastradh# All Rights Reserved.
63464ebd5Sriastradh#
73464ebd5Sriastradh# Permission is hereby granted, free of charge, to any person obtaining a
83464ebd5Sriastradh# copy of this software and associated documentation files (the
93464ebd5Sriastradh# "Software"), to deal in the Software without restriction, including
103464ebd5Sriastradh# without limitation the rights to use, copy, modify, merge, publish,
113464ebd5Sriastradh# distribute, sub license, and/or sell copies of the Software, and to
123464ebd5Sriastradh# permit persons to whom the Software is furnished to do so, subject to
133464ebd5Sriastradh# the following conditions:
143464ebd5Sriastradh#
153464ebd5Sriastradh# The above copyright notice and this permission notice (including the
163464ebd5Sriastradh# next paragraph) shall be included in all copies or substantial portions
173464ebd5Sriastradh# of the Software.
183464ebd5Sriastradh#
193464ebd5Sriastradh# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
203464ebd5Sriastradh# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
213464ebd5Sriastradh# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22af69d88dSmrg# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
233464ebd5Sriastradh# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
243464ebd5Sriastradh# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
253464ebd5Sriastradh# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
263464ebd5Sriastradh#
273464ebd5Sriastradh##########################################################################
283464ebd5Sriastradh
293464ebd5Sriastradh
307ec681f3Smrgimport io
313464ebd5Sriastradhimport sys
327ec681f3Smrgimport xml.parsers.expat as xpat
337ec681f3Smrgimport argparse
343464ebd5Sriastradh
357ec681f3Smrgimport format
363464ebd5Sriastradhfrom model import *
373464ebd5Sriastradh
383464ebd5Sriastradh
393464ebd5SriastradhELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4)
403464ebd5Sriastradh
413464ebd5Sriastradh
423464ebd5Sriastradhclass XmlToken:
433464ebd5Sriastradh
443464ebd5Sriastradh    def __init__(self, type, name_or_data, attrs = None, line = None, column = None):
453464ebd5Sriastradh        assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF)
463464ebd5Sriastradh        self.type = type
473464ebd5Sriastradh        self.name_or_data = name_or_data
483464ebd5Sriastradh        self.attrs = attrs
493464ebd5Sriastradh        self.line = line
503464ebd5Sriastradh        self.column = column
513464ebd5Sriastradh
523464ebd5Sriastradh    def __str__(self):
533464ebd5Sriastradh        if self.type == ELEMENT_START:
543464ebd5Sriastradh            return '<' + self.name_or_data + ' ...>'
553464ebd5Sriastradh        if self.type == ELEMENT_END:
563464ebd5Sriastradh            return '</' + self.name_or_data + '>'
573464ebd5Sriastradh        if self.type == CHARACTER_DATA:
583464ebd5Sriastradh            return self.name_or_data
593464ebd5Sriastradh        if self.type == EOF:
603464ebd5Sriastradh            return 'end of file'
613464ebd5Sriastradh        assert 0
623464ebd5Sriastradh
633464ebd5Sriastradh
643464ebd5Sriastradhclass XmlTokenizer:
653464ebd5Sriastradh    """Expat based XML tokenizer."""
663464ebd5Sriastradh
673464ebd5Sriastradh    def __init__(self, fp, skip_ws = True):
683464ebd5Sriastradh        self.fp = fp
693464ebd5Sriastradh        self.tokens = []
703464ebd5Sriastradh        self.index = 0
713464ebd5Sriastradh        self.final = False
723464ebd5Sriastradh        self.skip_ws = skip_ws
733464ebd5Sriastradh
743464ebd5Sriastradh        self.character_pos = 0, 0
753464ebd5Sriastradh        self.character_data = ''
763464ebd5Sriastradh
777ec681f3Smrg        self.parser = xpat.ParserCreate()
783464ebd5Sriastradh        self.parser.StartElementHandler  = self.handle_element_start
793464ebd5Sriastradh        self.parser.EndElementHandler    = self.handle_element_end
803464ebd5Sriastradh        self.parser.CharacterDataHandler = self.handle_character_data
813464ebd5Sriastradh
823464ebd5Sriastradh    def handle_element_start(self, name, attributes):
833464ebd5Sriastradh        self.finish_character_data()
843464ebd5Sriastradh        line, column = self.pos()
853464ebd5Sriastradh        token = XmlToken(ELEMENT_START, name, attributes, line, column)
863464ebd5Sriastradh        self.tokens.append(token)
873464ebd5Sriastradh
883464ebd5Sriastradh    def handle_element_end(self, name):
893464ebd5Sriastradh        self.finish_character_data()
903464ebd5Sriastradh        line, column = self.pos()
913464ebd5Sriastradh        token = XmlToken(ELEMENT_END, name, None, line, column)
923464ebd5Sriastradh        self.tokens.append(token)
933464ebd5Sriastradh
943464ebd5Sriastradh    def handle_character_data(self, data):
953464ebd5Sriastradh        if not self.character_data:
963464ebd5Sriastradh            self.character_pos = self.pos()
973464ebd5Sriastradh        self.character_data += data
983464ebd5Sriastradh
993464ebd5Sriastradh    def finish_character_data(self):
1003464ebd5Sriastradh        if self.character_data:
1013464ebd5Sriastradh            if not self.skip_ws or not self.character_data.isspace():
1023464ebd5Sriastradh                line, column = self.character_pos
1033464ebd5Sriastradh                token = XmlToken(CHARACTER_DATA, self.character_data, None, line, column)
1043464ebd5Sriastradh                self.tokens.append(token)
1053464ebd5Sriastradh            self.character_data = ''
1063464ebd5Sriastradh
1073464ebd5Sriastradh    def next(self):
1083464ebd5Sriastradh        size = 16*1024
1093464ebd5Sriastradh        while self.index >= len(self.tokens) and not self.final:
1103464ebd5Sriastradh            self.tokens = []
1113464ebd5Sriastradh            self.index = 0
1123464ebd5Sriastradh            data = self.fp.read(size)
1133464ebd5Sriastradh            self.final = len(data) < size
1143464ebd5Sriastradh            data = data.rstrip('\0')
1153464ebd5Sriastradh            try:
1163464ebd5Sriastradh                self.parser.Parse(data, self.final)
1177ec681f3Smrg            except xpat.ExpatError as e:
1187ec681f3Smrg                #if e.code == xpat.errors.XML_ERROR_NO_ELEMENTS:
1193464ebd5Sriastradh                if e.code == 3:
1203464ebd5Sriastradh                    pass
1213464ebd5Sriastradh                else:
1223464ebd5Sriastradh                    raise e
1233464ebd5Sriastradh        if self.index >= len(self.tokens):
1243464ebd5Sriastradh            line, column = self.pos()
1253464ebd5Sriastradh            token = XmlToken(EOF, None, None, line, column)
1263464ebd5Sriastradh        else:
1273464ebd5Sriastradh            token = self.tokens[self.index]
1283464ebd5Sriastradh            self.index += 1
1293464ebd5Sriastradh        return token
1303464ebd5Sriastradh
1313464ebd5Sriastradh    def pos(self):
1323464ebd5Sriastradh        return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber
1333464ebd5Sriastradh
1343464ebd5Sriastradh
1353464ebd5Sriastradhclass TokenMismatch(Exception):
1363464ebd5Sriastradh
1373464ebd5Sriastradh    def __init__(self, expected, found):
1383464ebd5Sriastradh        self.expected = expected
1393464ebd5Sriastradh        self.found = found
1403464ebd5Sriastradh
1413464ebd5Sriastradh    def __str__(self):
1423464ebd5Sriastradh        return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found))
1433464ebd5Sriastradh
1443464ebd5Sriastradh
1453464ebd5Sriastradh
1463464ebd5Sriastradhclass XmlParser:
1473464ebd5Sriastradh    """Base XML document parser."""
1483464ebd5Sriastradh
1493464ebd5Sriastradh    def __init__(self, fp):
1503464ebd5Sriastradh        self.tokenizer = XmlTokenizer(fp)
1513464ebd5Sriastradh        self.consume()
1523464ebd5Sriastradh
1533464ebd5Sriastradh    def consume(self):
1543464ebd5Sriastradh        self.token = self.tokenizer.next()
1553464ebd5Sriastradh
1563464ebd5Sriastradh    def match_element_start(self, name):
1573464ebd5Sriastradh        return self.token.type == ELEMENT_START and self.token.name_or_data == name
1583464ebd5Sriastradh
1593464ebd5Sriastradh    def match_element_end(self, name):
1603464ebd5Sriastradh        return self.token.type == ELEMENT_END and self.token.name_or_data == name
1613464ebd5Sriastradh
1623464ebd5Sriastradh    def element_start(self, name):
1633464ebd5Sriastradh        while self.token.type == CHARACTER_DATA:
1643464ebd5Sriastradh            self.consume()
1653464ebd5Sriastradh        if self.token.type != ELEMENT_START:
1663464ebd5Sriastradh            raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token)
1673464ebd5Sriastradh        if self.token.name_or_data != name:
1683464ebd5Sriastradh            raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token)
1693464ebd5Sriastradh        attrs = self.token.attrs
1703464ebd5Sriastradh        self.consume()
1713464ebd5Sriastradh        return attrs
1723464ebd5Sriastradh
1733464ebd5Sriastradh    def element_end(self, name):
1743464ebd5Sriastradh        while self.token.type == CHARACTER_DATA:
1753464ebd5Sriastradh            self.consume()
1763464ebd5Sriastradh        if self.token.type != ELEMENT_END:
1773464ebd5Sriastradh            raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token)
1783464ebd5Sriastradh        if self.token.name_or_data != name:
1793464ebd5Sriastradh            raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token)
1803464ebd5Sriastradh        self.consume()
1813464ebd5Sriastradh
1823464ebd5Sriastradh    def character_data(self, strip = True):
1833464ebd5Sriastradh        data = ''
1843464ebd5Sriastradh        while self.token.type == CHARACTER_DATA:
1853464ebd5Sriastradh            data += self.token.name_or_data
1863464ebd5Sriastradh            self.consume()
1873464ebd5Sriastradh        if strip:
1883464ebd5Sriastradh            data = data.strip()
1893464ebd5Sriastradh        return data
1903464ebd5Sriastradh
1913464ebd5Sriastradh
1923464ebd5Sriastradhclass TraceParser(XmlParser):
1933464ebd5Sriastradh
1943464ebd5Sriastradh    def __init__(self, fp):
1953464ebd5Sriastradh        XmlParser.__init__(self, fp)
1963464ebd5Sriastradh        self.last_call_no = 0
1973464ebd5Sriastradh
1983464ebd5Sriastradh    def parse(self):
1993464ebd5Sriastradh        self.element_start('trace')
2003464ebd5Sriastradh        while self.token.type not in (ELEMENT_END, EOF):
2013464ebd5Sriastradh            call = self.parse_call()
2023464ebd5Sriastradh            self.handle_call(call)
2033464ebd5Sriastradh        if self.token.type != EOF:
2043464ebd5Sriastradh            self.element_end('trace')
2053464ebd5Sriastradh
2063464ebd5Sriastradh    def parse_call(self):
2073464ebd5Sriastradh        attrs = self.element_start('call')
2083464ebd5Sriastradh        try:
2093464ebd5Sriastradh            no = int(attrs['no'])
2107ec681f3Smrg        except KeyError as e:
2113464ebd5Sriastradh            self.last_call_no += 1
2123464ebd5Sriastradh            no = self.last_call_no
2133464ebd5Sriastradh        else:
2143464ebd5Sriastradh            self.last_call_no = no
2153464ebd5Sriastradh        klass = attrs['class']
2163464ebd5Sriastradh        method = attrs['method']
2173464ebd5Sriastradh        args = []
2183464ebd5Sriastradh        ret = None
219af69d88dSmrg        time = None
2203464ebd5Sriastradh        while self.token.type == ELEMENT_START:
2213464ebd5Sriastradh            if self.token.name_or_data == 'arg':
2223464ebd5Sriastradh                arg = self.parse_arg()
2233464ebd5Sriastradh                args.append(arg)
2243464ebd5Sriastradh            elif self.token.name_or_data == 'ret':
2253464ebd5Sriastradh                ret = self.parse_ret()
2263464ebd5Sriastradh            elif self.token.name_or_data == 'call':
2273464ebd5Sriastradh                # ignore nested function calls
2283464ebd5Sriastradh                self.parse_call()
229af69d88dSmrg            elif self.token.name_or_data == 'time':
230af69d88dSmrg                time = self.parse_time()
2313464ebd5Sriastradh            else:
2323464ebd5Sriastradh                raise TokenMismatch("<arg ...> or <ret ...>", self.token)
2333464ebd5Sriastradh        self.element_end('call')
2343464ebd5Sriastradh
235af69d88dSmrg        return Call(no, klass, method, args, ret, time)
2363464ebd5Sriastradh
2373464ebd5Sriastradh    def parse_arg(self):
2383464ebd5Sriastradh        attrs = self.element_start('arg')
2393464ebd5Sriastradh        name = attrs['name']
2407ec681f3Smrg        value = self.parse_value(name)
2413464ebd5Sriastradh        self.element_end('arg')
2423464ebd5Sriastradh
2433464ebd5Sriastradh        return name, value
2443464ebd5Sriastradh
2453464ebd5Sriastradh    def parse_ret(self):
2463464ebd5Sriastradh        attrs = self.element_start('ret')
2477ec681f3Smrg        value = self.parse_value('ret')
2483464ebd5Sriastradh        self.element_end('ret')
2493464ebd5Sriastradh
2503464ebd5Sriastradh        return value
2513464ebd5Sriastradh
252af69d88dSmrg    def parse_time(self):
253af69d88dSmrg        attrs = self.element_start('time')
2547ec681f3Smrg        time = self.parse_value('time');
255af69d88dSmrg        self.element_end('time')
256af69d88dSmrg        return time
257af69d88dSmrg
2587ec681f3Smrg    def parse_value(self, name):
2593464ebd5Sriastradh        expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes')
2603464ebd5Sriastradh        if self.token.type == ELEMENT_START:
2613464ebd5Sriastradh            if self.token.name_or_data in expected_tokens:
2623464ebd5Sriastradh                method = getattr(self, 'parse_' +  self.token.name_or_data)
2637ec681f3Smrg                return method(name)
2643464ebd5Sriastradh        raise TokenMismatch(" or " .join(expected_tokens), self.token)
2653464ebd5Sriastradh
2667ec681f3Smrg    def parse_null(self, pname):
2673464ebd5Sriastradh        self.element_start('null')
2683464ebd5Sriastradh        self.element_end('null')
2693464ebd5Sriastradh        return Literal(None)
2703464ebd5Sriastradh
2717ec681f3Smrg    def parse_bool(self, pname):
2723464ebd5Sriastradh        self.element_start('bool')
2733464ebd5Sriastradh        value = int(self.character_data())
2743464ebd5Sriastradh        self.element_end('bool')
2753464ebd5Sriastradh        return Literal(value)
2763464ebd5Sriastradh
2777ec681f3Smrg    def parse_int(self, pname):
2783464ebd5Sriastradh        self.element_start('int')
2793464ebd5Sriastradh        value = int(self.character_data())
2803464ebd5Sriastradh        self.element_end('int')
2813464ebd5Sriastradh        return Literal(value)
2823464ebd5Sriastradh
2837ec681f3Smrg    def parse_uint(self, pname):
2843464ebd5Sriastradh        self.element_start('uint')
2853464ebd5Sriastradh        value = int(self.character_data())
2863464ebd5Sriastradh        self.element_end('uint')
2873464ebd5Sriastradh        return Literal(value)
2883464ebd5Sriastradh
2897ec681f3Smrg    def parse_float(self, pname):
2903464ebd5Sriastradh        self.element_start('float')
2913464ebd5Sriastradh        value = float(self.character_data())
2923464ebd5Sriastradh        self.element_end('float')
2933464ebd5Sriastradh        return Literal(value)
2943464ebd5Sriastradh
2957ec681f3Smrg    def parse_enum(self, pname):
2963464ebd5Sriastradh        self.element_start('enum')
2973464ebd5Sriastradh        name = self.character_data()
2983464ebd5Sriastradh        self.element_end('enum')
2993464ebd5Sriastradh        return NamedConstant(name)
3003464ebd5Sriastradh
3017ec681f3Smrg    def parse_string(self, pname):
3023464ebd5Sriastradh        self.element_start('string')
3033464ebd5Sriastradh        value = self.character_data()
3043464ebd5Sriastradh        self.element_end('string')
3053464ebd5Sriastradh        return Literal(value)
3063464ebd5Sriastradh
3077ec681f3Smrg    def parse_bytes(self, pname):
3083464ebd5Sriastradh        self.element_start('bytes')
309af69d88dSmrg        value = self.character_data()
3103464ebd5Sriastradh        self.element_end('bytes')
311af69d88dSmrg        return Blob(value)
3123464ebd5Sriastradh
3137ec681f3Smrg    def parse_array(self, pname):
3143464ebd5Sriastradh        self.element_start('array')
3153464ebd5Sriastradh        elems = []
3163464ebd5Sriastradh        while self.token.type != ELEMENT_END:
3177ec681f3Smrg            elems.append(self.parse_elem('array'))
3183464ebd5Sriastradh        self.element_end('array')
3193464ebd5Sriastradh        return Array(elems)
3203464ebd5Sriastradh
3217ec681f3Smrg    def parse_elem(self, pname):
3223464ebd5Sriastradh        self.element_start('elem')
3237ec681f3Smrg        value = self.parse_value('elem')
3243464ebd5Sriastradh        self.element_end('elem')
3253464ebd5Sriastradh        return value
3263464ebd5Sriastradh
3277ec681f3Smrg    def parse_struct(self, pname):
3283464ebd5Sriastradh        attrs = self.element_start('struct')
3293464ebd5Sriastradh        name = attrs['name']
3303464ebd5Sriastradh        members = []
3313464ebd5Sriastradh        while self.token.type != ELEMENT_END:
3327ec681f3Smrg            members.append(self.parse_member(name))
3333464ebd5Sriastradh        self.element_end('struct')
3343464ebd5Sriastradh        return Struct(name, members)
3353464ebd5Sriastradh
3367ec681f3Smrg    def parse_member(self, pname):
3373464ebd5Sriastradh        attrs = self.element_start('member')
3383464ebd5Sriastradh        name = attrs['name']
3397ec681f3Smrg        value = self.parse_value(name)
3403464ebd5Sriastradh        self.element_end('member')
3413464ebd5Sriastradh
3423464ebd5Sriastradh        return name, value
3433464ebd5Sriastradh
3447ec681f3Smrg    def parse_ptr(self, pname):
3453464ebd5Sriastradh        self.element_start('ptr')
3463464ebd5Sriastradh        address = self.character_data()
3473464ebd5Sriastradh        self.element_end('ptr')
3483464ebd5Sriastradh
3497ec681f3Smrg        return Pointer(address, pname)
3503464ebd5Sriastradh
3513464ebd5Sriastradh    def handle_call(self, call):
3523464ebd5Sriastradh        pass
3533464ebd5Sriastradh
3543464ebd5Sriastradh
3557ec681f3Smrgclass SimpleTraceDumper(TraceParser):
3563464ebd5Sriastradh
3577ec681f3Smrg    def __init__(self, fp, options, formatter):
3583464ebd5Sriastradh        TraceParser.__init__(self, fp)
3597ec681f3Smrg        self.options = options
3607ec681f3Smrg        self.formatter = formatter
3617ec681f3Smrg        self.pretty_printer = PrettyPrinter(self.formatter, options)
3623464ebd5Sriastradh
3633464ebd5Sriastradh    def handle_call(self, call):
3643464ebd5Sriastradh        call.visit(self.pretty_printer)
3653464ebd5Sriastradh        self.formatter.newline()
3667ec681f3Smrg
3677ec681f3Smrg
3687ec681f3Smrgclass TraceDumper(SimpleTraceDumper):
3697ec681f3Smrg
3707ec681f3Smrg    def __init__(self, fp, options, formatter):
3717ec681f3Smrg        SimpleTraceDumper.__init__(self, fp, options, formatter)
3727ec681f3Smrg        self.call_stack = []
3737ec681f3Smrg
3747ec681f3Smrg    def handle_call(self, call):
3757ec681f3Smrg        if self.options.named_ptrs:
3767ec681f3Smrg            self.call_stack.append(call)
3777ec681f3Smrg        else:
3787ec681f3Smrg            call.visit(self.pretty_printer)
3797ec681f3Smrg            self.formatter.newline()
3807ec681f3Smrg
3817ec681f3Smrg    def dump_calls(self):
3827ec681f3Smrg        for call in self.call_stack:
3837ec681f3Smrg            call.visit(self.pretty_printer)
3847ec681f3Smrg            self.formatter.newline()
3853464ebd5Sriastradh
3863464ebd5Sriastradh
3873464ebd5Sriastradhclass Main:
3883464ebd5Sriastradh    '''Common main class for all retrace command line utilities.'''
3893464ebd5Sriastradh
3903464ebd5Sriastradh    def __init__(self):
3913464ebd5Sriastradh        pass
3923464ebd5Sriastradh
3933464ebd5Sriastradh    def main(self):
3943464ebd5Sriastradh        optparser = self.get_optparser()
3957ec681f3Smrg        args = optparser.parse_args()
3967ec681f3Smrg
3977ec681f3Smrg        for fname in args.filename:
3987ec681f3Smrg            try:
3997ec681f3Smrg                if fname.endswith('.gz'):
4007ec681f3Smrg                    from gzip import GzipFile
4017ec681f3Smrg                    stream = io.TextIOWrapper(GzipFile(fname, 'rb'))
4027ec681f3Smrg                elif fname.endswith('.bz2'):
4037ec681f3Smrg                    from bz2 import BZ2File
4047ec681f3Smrg                    stream = io.TextIOWrapper(BZ2File(fname, 'rb'))
4057ec681f3Smrg                else:
4067ec681f3Smrg                    stream = open(fname, 'rt')
4077ec681f3Smrg            except Exception as e:
4087ec681f3Smrg                print("ERROR: {}".format(str(e)))
4097ec681f3Smrg                sys.exit(1)
4107ec681f3Smrg
4117ec681f3Smrg            self.process_arg(stream, args)
4123464ebd5Sriastradh
4133464ebd5Sriastradh    def get_optparser(self):
4147ec681f3Smrg        optparser = argparse.ArgumentParser(
4157ec681f3Smrg            description="Parse and dump Gallium trace(s)")
4167ec681f3Smrg        optparser.add_argument("filename", action="extend", nargs="+",
4177ec681f3Smrg            type=str, metavar="filename", help="Gallium trace filename (plain or .gz, .bz2)")
4187ec681f3Smrg        optparser.add_argument("-p", "--plain",
4197ec681f3Smrg            action="store_const", const=True, default=False,
4207ec681f3Smrg            dest="plain", help="disable ANSI color etc. formatting")
4217ec681f3Smrg        optparser.add_argument("-S", "--suppress",
4227ec681f3Smrg            action="store_const", const=True, default=False,
4237ec681f3Smrg            dest="suppress_variants", help="suppress some variants in output for better diffability")
4247ec681f3Smrg        optparser.add_argument("-N", "--named",
4257ec681f3Smrg            action="store_const", const=True, default=False,
4267ec681f3Smrg            dest="named_ptrs", help="generate symbolic names for raw pointer values")
4277ec681f3Smrg        optparser.add_argument("-M", "--method-only",
4287ec681f3Smrg            action="store_const", const=True, default=False,
4297ec681f3Smrg            dest="method_only", help="output only call names without arguments")
4307ec681f3Smrg
4313464ebd5Sriastradh        return optparser
4323464ebd5Sriastradh
4333464ebd5Sriastradh    def process_arg(self, stream, options):
4347ec681f3Smrg        if options.plain:
4357ec681f3Smrg            formatter = format.Formatter(sys.stdout)
4367ec681f3Smrg        else:
4377ec681f3Smrg            formatter = format.DefaultFormatter(sys.stdout)
4387ec681f3Smrg
4397ec681f3Smrg        parser = TraceDumper(stream, options, formatter)
4403464ebd5Sriastradh        parser.parse()
4413464ebd5Sriastradh
4427ec681f3Smrg        if options.named_ptrs:
4437ec681f3Smrg            parser.dump_calls()
4447ec681f3Smrg
4453464ebd5Sriastradh
4463464ebd5Sriastradhif __name__ == '__main__':
4473464ebd5Sriastradh    Main().main()
448