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