import re
+class MatchObject:
+
+ def __init__(self):
+ self.params = {}
+
+
class Matcher:
- def match(self, value):
+ def match(self, value, mo):
raise NotImplementedError
- def _matchSequence(self, refValues, srcValues):
+ def _matchSequence(self, refValues, srcValues, mo):
if not isinstance(srcValues, (list, tuple)):
return False
return False
for refValue, srcValue in zip(refValues, srcValues):
- if not refValue.match(srcValue):
+ if not refValue.match(srcValue, mo):
return False
return True
class WildcardMatcher(Matcher):
- def match(self, value):
+ def __init__(self, name = ''):
+ self.name = name
+
+ def match(self, value, mo):
+ if self.name:
+ try:
+ refValue = mo.params[self.name]
+ except KeyError:
+ mo.params[self.name] = value
+ else:
+ return refValue == value
return True
def __str__(self):
- return '*'
+ return '<' + self.name + '>'
class LiteralMatcher(Matcher):
def __init__(self, refValue):
self.refValue = refValue
- def match(self, value):
+ def match(self, value, mo):
return self.refValue == value
def __str__(self):
self.refValue = refValue
self.tolerance = tolerance
- def match(self, value):
+ def match(self, value, mo):
if not isinstance(value, float):
return
def __init__(self, refElements):
self.refElements = refElements
- def match(self, value):
- return self._matchSequence(self.refElements, value)
+ def match(self, value, mo):
+ return self._matchSequence(self.refElements, value, mo)
def __str__(self):
return ' | '.join(map(str, self.refElements))
def __init__(self, refElements):
self.refElements = refElements
- def match(self, value):
- return self._matchSequence(self.refElements, value)
+ def match(self, value, mo):
+ return self._matchSequence(self.refElements, value, mo)
def __str__(self):
return '{' + ', '.join(map(str, self.refElements)) + '}'
def __init__(self, refMembers):
self.refMembers = refMembers
- def match(self, value):
+ def match(self, value, mo):
if not isinstance(value, dict):
return False
except KeyError:
return False
else:
- if not refMember.match(member):
+ if not refMember.match(member, mo):
return False
return True
def __str__(self):
- print self.refMembers
return '{' + ', '.join(['%s = %s' % refMember for refMember in self.refMembers.iteritems()]) + '}'
class CallMatcher(Matcher):
- def __init__(self, functionName, args, ret = None):
+ def __init__(self, callNo, functionName, args, ret):
+ self.callNo = callNo
self.functionName = functionName
self.args = args
self.ret = ret
- def match(self, call):
- srcFunctionName, srcArgs, srcRet = call
+ def match(self, call, mo):
+ callNo, srcFunctionName, srcArgs, srcRet = call
if self.functionName != srcFunctionName:
return False
refArgs = [value for name, value in self.args]
srcArgs = [value for name, value in srcArgs]
- if not self._matchSequence(refArgs, srcArgs):
+ if not self._matchSequence(refArgs, srcArgs, mo):
return False
if self.ret is None:
if srcRet is not None:
return False
else:
- if not self.ret.match(srcRet):
+ if not self.ret.match(srcRet, mo):
+ return False
+
+ if self.callNo is not None:
+ if not self.callNo.match(callNo, mo):
return False
return True
self.calls = calls
def match(self, trace):
-
+ mo = MatchObject()
srcCalls = iter(trace.calls)
for refCall in self.calls:
skippedSrcCalls = []
raise Exception('missing call `%s` (found `%s`)' % (refCall, skippedSrcCalls[0]))
else:
raise Exception('missing call %s' % refCall)
- if refCall.match(srcCall):
+ if refCall.match(srcCall, mo):
break
else:
skippedSrcCalls.append(srcCall)
- return True
+ return mo
def __str__(self):
return ''.join(['%s\n' % call for call in self.calls])
#######################################################################
-ID, NUMBER, HEXNUM, STRING, PRAGMA, LPAREN, RPAREN, LCURLY, RCURLY, COMMA, AMP, EQUAL, VERT, BLOB = xrange(14)
+ID, NUMBER, HEXNUM, STRING, WILDCARD, PRAGMA, LPAREN, RPAREN, LCURLY, RCURLY, COMMA, AMP, EQUAL, VERT, BLOB = xrange(15)
class CallScanner(Scanner):
# String IDs
(STRING, r'"[^"\\]*(?:\\.[^"\\]*)*"', False),
+ # Wildcard
+ (WILDCARD, r'<[^>]*>', False),
+
# Pragma
(PRAGMA, r'#[^\r\n]*', False),
]
while self.lookahead.type == PRAGMA:
# TODO
token = self.consume()
- print token.text
if self.lookahead.type == NUMBER:
token = self.consume()
- callNo = int(token.text)
+ callNo = self.handleInt(int(token.text))
+ elif self.lookahead.type == WILDCARD:
+ token = self.consume()
+ callNo = self.handleWildcard((token.text[1:-1]))
else:
callNo = None
else:
ret = None
- self.handleCall(functionName, args, ret)
+ self.handleCall(callNo, functionName, args, ret)
def parse_pair(self):
'''Parse a `name = value` pair.'''
elif self.match(BLOB):
token = self.consume()
self.consume(LPAREN)
- length = self.consume()
+ token = self.consume()
+ length = int(token.text)
self.consume(RPAREN)
return self.handleBlob(length)
+ elif self.match(WILDCARD):
+ token = self.consume()
+ return self.handleWildcard(token.text[1:-1])
else:
self.error()
raise NotImplementedError
def handleBlob(self, length):
+ return self.handleID('blob(%u)' % length)
+
+ def handleWildcard(self, name):
raise NotImplementedError
- # TODO
- return WildcardMatcher()
- def handleCall(self, functionName, args, ret):
+ def handleCall(self, callNo, functionName, args, ret):
raise NotImplementedError
def handlePragma(self, line):
def handleStruct(self, value):
return StructMatcher(value)
- def handleBlob(self, length):
- # TODO
- return WildcardMatcher()
+ def handleWildcard(self, name):
+ return WildcardMatcher(name)
- def handleCall(self, functionName, args, ret):
- call = CallMatcher(functionName, args, ret)
+ def handleCall(self, callNo, functionName, args, ret):
+ call = CallMatcher(callNo, functionName, args, ret)
self.calls.append(call)
def handleStruct(self, members):
return dict(members)
- def handleBlob(self, length):
- # TODO
- return None
-
- def handleCall(self, functionName, args, ret):
- call = (functionName, args, ret)
+ def handleCall(self, callNo, functionName, args, ret):
+ call = (callNo, functionName, args, ret)
self.calls.append(call)
sys.stdout.write(str(refTrace))
srcParser = SrcTraceParser(open(args[1], 'rt'))
srcTrace = srcParser.parse()
- refTrace.match(srcTrace)
+ mo = refTrace.match(srcTrace)
+
+ paramNames = mo.params.keys()
+ paramNames.sort()
+ for paramName in paramNames:
+ print '%s = %r' % (paramName, mo.params[paramName])
if __name__ == '__main__':