13a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca#!/usr/bin/env python 23a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca########################################################################## 33a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# 43a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 53a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# All Rights Reserved. 63a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# 73a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# Permission is hereby granted, free of charge, to any person obtaining a 83a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# copy of this software and associated documentation files (the 93a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# "Software"), to deal in the Software without restriction, including 103a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# without limitation the rights to use, copy, modify, merge, publish, 113a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# distribute, sub license, and/or sell copies of the Software, and to 123a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# permit persons to whom the Software is furnished to do so, subject to 133a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# the following conditions: 143a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# 153a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# The above copyright notice and this permission notice (including the 163a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# next paragraph) shall be included in all copies or substantial portions 173a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# of the Software. 183a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# 193a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 203a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 213a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 223a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 233a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 243a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 253a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 263a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca# 273a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca########################################################################## 283a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 293a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 303a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaimport sys 313a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaimport xml.parsers.expat 323a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaimport binascii 333a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaimport optparse 343a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 353a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecafrom model import * 363a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 373a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 383a618da6e15a6dc4351eb933583569a1ecefc768José FonsecaELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4) 393a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 403a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 413a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaclass XmlToken: 423a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 433a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def __init__(self, type, name_or_data, attrs = None, line = None, column = None): 443a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF) 453a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.type = type 463a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.name_or_data = name_or_data 473a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.attrs = attrs 483a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.line = line 493a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.column = column 503a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 513a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def __str__(self): 523a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.type == ELEMENT_START: 533a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return '<' + self.name_or_data + ' ...>' 543a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.type == ELEMENT_END: 553a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return '</' + self.name_or_data + '>' 563a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.type == CHARACTER_DATA: 573a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return self.name_or_data 583a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.type == EOF: 593a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return 'end of file' 603a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca assert 0 613a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 623a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 633a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaclass XmlTokenizer: 643a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca """Expat based XML tokenizer.""" 653a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 663a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def __init__(self, fp, skip_ws = True): 673a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.fp = fp 683a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.tokens = [] 693a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.index = 0 703a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.final = False 713a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.skip_ws = skip_ws 723a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 733a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.character_pos = 0, 0 743a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.character_data = '' 753a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 763a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.parser = xml.parsers.expat.ParserCreate() 773a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.parser.StartElementHandler = self.handle_element_start 783a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.parser.EndElementHandler = self.handle_element_end 793a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.parser.CharacterDataHandler = self.handle_character_data 803a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 813a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def handle_element_start(self, name, attributes): 823a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.finish_character_data() 833a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca line, column = self.pos() 843a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca token = XmlToken(ELEMENT_START, name, attributes, line, column) 853a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.tokens.append(token) 863a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 873a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def handle_element_end(self, name): 883a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.finish_character_data() 893a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca line, column = self.pos() 903a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca token = XmlToken(ELEMENT_END, name, None, line, column) 913a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.tokens.append(token) 923a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 933a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def handle_character_data(self, data): 943a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if not self.character_data: 953a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.character_pos = self.pos() 963a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.character_data += data 973a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 983a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def finish_character_data(self): 993a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.character_data: 1003a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if not self.skip_ws or not self.character_data.isspace(): 1013a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca line, column = self.character_pos 1023a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca token = XmlToken(CHARACTER_DATA, self.character_data, None, line, column) 1033a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.tokens.append(token) 1043a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.character_data = '' 1053a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1063a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def next(self): 1073a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca size = 16*1024 1083a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca while self.index >= len(self.tokens) and not self.final: 1093a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.tokens = [] 1103a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.index = 0 1113a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca data = self.fp.read(size) 1123a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.final = len(data) < size 1133a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca data = data.rstrip('\0') 1143a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca try: 1153a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.parser.Parse(data, self.final) 1163a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca except xml.parsers.expat.ExpatError, e: 1173a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS: 1183a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if e.code == 3: 1193a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca pass 1203a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca else: 1213a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca raise e 1223a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.index >= len(self.tokens): 1233a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca line, column = self.pos() 1243a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca token = XmlToken(EOF, None, None, line, column) 1253a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca else: 1263a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca token = self.tokens[self.index] 1273a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.index += 1 1283a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return token 1293a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1303a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def pos(self): 1313a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber 1323a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1333a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1343a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaclass TokenMismatch(Exception): 1353a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1363a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def __init__(self, expected, found): 1373a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.expected = expected 1383a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.found = found 1393a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1403a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def __str__(self): 1413a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found)) 1423a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1433a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1443a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1453a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaclass XmlParser: 1463a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca """Base XML document parser.""" 1473a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1483a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def __init__(self, fp): 1493a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.tokenizer = XmlTokenizer(fp) 1503a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.consume() 1513a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1523a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def consume(self): 1533a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.token = self.tokenizer.next() 1543a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1553a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def match_element_start(self, name): 1563a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return self.token.type == ELEMENT_START and self.token.name_or_data == name 1573a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1583a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def match_element_end(self, name): 1593a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return self.token.type == ELEMENT_END and self.token.name_or_data == name 1603a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1613a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def element_start(self, name): 1623a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca while self.token.type == CHARACTER_DATA: 1633a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.consume() 1643a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.token.type != ELEMENT_START: 1653a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) 1663a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.token.name_or_data != name: 1673a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) 1683a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca attrs = self.token.attrs 1693a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.consume() 1703a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return attrs 1713a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1723a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def element_end(self, name): 1733a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca while self.token.type == CHARACTER_DATA: 1743a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.consume() 1753a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.token.type != ELEMENT_END: 1763a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) 1773a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.token.name_or_data != name: 1783a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) 1793a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.consume() 1803a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1813a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def character_data(self, strip = True): 1823a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca data = '' 1833a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca while self.token.type == CHARACTER_DATA: 1843a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca data += self.token.name_or_data 1853a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.consume() 1863a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if strip: 1873a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca data = data.strip() 1883a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return data 1893a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1903a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1913a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaclass TraceParser(XmlParser): 1923a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1933a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def __init__(self, fp): 1943a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca XmlParser.__init__(self, fp) 1953a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.last_call_no = 0 1963a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 1973a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse(self): 1983a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('trace') 1993a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca while self.token.type not in (ELEMENT_END, EOF): 2003a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca call = self.parse_call() 2013a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.handle_call(call) 2023a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.token.type != EOF: 2033a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('trace') 2043a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2053a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_call(self): 2063a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca attrs = self.element_start('call') 2073a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca try: 2083a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca no = int(attrs['no']) 2093a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca except KeyError: 2103a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.last_call_no += 1 2113a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca no = self.last_call_no 2123a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca else: 2133a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.last_call_no = no 2143a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca klass = attrs['class'] 2153a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca method = attrs['method'] 2163a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca args = [] 2173a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca ret = None 2183a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca while self.token.type == ELEMENT_START: 2193a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.token.name_or_data == 'arg': 2203a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca arg = self.parse_arg() 2213a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca args.append(arg) 2223a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca elif self.token.name_or_data == 'ret': 2233a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca ret = self.parse_ret() 2243a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca elif self.token.name_or_data == 'call': 2253a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca # ignore nested function calls 2263a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.parse_call() 2273a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca else: 2283a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca raise TokenMismatch("<arg ...> or <ret ...>", self.token) 2293a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('call') 2303a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2313a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Call(no, klass, method, args, ret) 2323a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2333a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_arg(self): 2343a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca attrs = self.element_start('arg') 2353a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca name = attrs['name'] 2363a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = self.parse_value() 2373a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('arg') 2383a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2393a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return name, value 2403a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2413a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_ret(self): 2423a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca attrs = self.element_start('ret') 2433a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = self.parse_value() 2443a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('ret') 2453a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2463a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return value 2473a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2483a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_value(self): 2493a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes') 2503a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.token.type == ELEMENT_START: 2513a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if self.token.name_or_data in expected_tokens: 2523a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca method = getattr(self, 'parse_' + self.token.name_or_data) 2533a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return method() 2543a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca raise TokenMismatch(" or " .join(expected_tokens), self.token) 2553a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2563a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_null(self): 2573a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('null') 2583a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('null') 2593a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Literal(None) 2603a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2613a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_bool(self): 2623a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('bool') 2633a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = int(self.character_data()) 2643a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('bool') 2653a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Literal(value) 2663a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2673a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_int(self): 2683a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('int') 2693a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = int(self.character_data()) 2703a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('int') 2713a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Literal(value) 2723a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2733a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_uint(self): 2743a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('uint') 2753a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = int(self.character_data()) 2763a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('uint') 2773a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Literal(value) 2783a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2793a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_float(self): 2803a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('float') 2813a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = float(self.character_data()) 2823a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('float') 2833a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Literal(value) 2843a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2853a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_enum(self): 2863a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('enum') 2873a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca name = self.character_data() 2883a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('enum') 2893a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return NamedConstant(name) 2903a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2913a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_string(self): 2923a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('string') 2933a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = self.character_data() 2943a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('string') 2953a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Literal(value) 2963a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 2973a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_bytes(self): 2983a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('bytes') 2993a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = binascii.a2b_hex(self.character_data()) 3003a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('bytes') 3013a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Literal(value) 3023a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3033a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_array(self): 3043a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('array') 3053a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca elems = [] 3063a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca while self.token.type != ELEMENT_END: 3073a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca elems.append(self.parse_elem()) 3083a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('array') 3093a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Array(elems) 3103a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3113a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_elem(self): 3123a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('elem') 3133a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = self.parse_value() 3143a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('elem') 3153a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return value 3163a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3173a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_struct(self): 3183a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca attrs = self.element_start('struct') 3193a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca name = attrs['name'] 3203a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca members = [] 3213a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca while self.token.type != ELEMENT_END: 3223a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca members.append(self.parse_member()) 3233a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('struct') 3243a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Struct(name, members) 3253a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3263a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_member(self): 3273a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca attrs = self.element_start('member') 3283a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca name = attrs['name'] 3293a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca value = self.parse_value() 3303a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('member') 3313a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3323a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return name, value 3333a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3343a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def parse_ptr(self): 3353a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_start('ptr') 3363a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca address = self.character_data() 3373a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.element_end('ptr') 3383a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3393a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return Pointer(address) 3403a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3413a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def handle_call(self, call): 3423a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca pass 3433a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3443a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3453a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaclass TraceDumper(TraceParser): 3463a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3473a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def __init__(self, fp): 3483a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca TraceParser.__init__(self, fp) 3493a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.formatter = format.DefaultFormatter(sys.stdout) 3503a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.pretty_printer = PrettyPrinter(self.formatter) 3513a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3523a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def handle_call(self, call): 3533a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca call.visit(self.pretty_printer) 3543a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.formatter.newline() 3553a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3563a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3573a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaclass Main: 3583a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca '''Common main class for all retrace command line utilities.''' 3593a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3603a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def __init__(self): 3613a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca pass 3623a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3633a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def main(self): 3643a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca optparser = self.get_optparser() 3653a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca (options, args) = optparser.parse_args(sys.argv[1:]) 3663a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3673a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if args: 3683a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca for arg in args: 3693a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca if arg.endswith('.gz'): 3703a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca from gzip import GzipFile 3713a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca stream = GzipFile(arg, 'rt') 3723a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca elif arg.endswith('.bz2'): 3733a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca from bz2 import BZ2File 374cdf56eb68d2718b5702f3d09928da404d745b8e1José Fonseca stream = BZ2File(arg, 'rU') 3753a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca else: 3763a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca stream = open(arg, 'rt') 3773a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.process_arg(stream, options) 3783a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca else: 3793a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca self.process_arg(stream, options) 3803a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3813a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def get_optparser(self): 3823a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca optparser = optparse.OptionParser( 3833a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca usage="\n\t%prog [options] [traces] ...") 3843a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca return optparser 3853a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3863a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca def process_arg(self, stream, options): 3873a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca parser = TraceDumper(stream) 3883a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca parser.parse() 3893a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3903a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca 3913a618da6e15a6dc4351eb933583569a1ecefc768José Fonsecaif __name__ == '__main__': 3923a618da6e15a6dc4351eb933583569a1ecefc768José Fonseca Main().main() 393