score.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. """MCD proc-compare scorer. Usage: score.py ORIG_TXT OURS_TXT MOD PAIRS...
  2. PAIRS = OrigName:OursName. Masks absolute targets, proc refs, dep slots;
  3. leave-truncates bodies; reports SAME/PREFIX/DIFF per pair."""
  4. import re, sys
  5. def procs(path, mod):
  6. txt = open(path, errors='replace').read()
  7. heads = [(m.group(1), int(m.group(2), 16))
  8. for m in re.finditer(r'(?m)^;? ?' + mod + r'\.(\w+): ([0-9a-f]{4})$', txt)]
  9. ops = []
  10. for line in txt.splitlines():
  11. m = re.match(r'^\s*([0-9a-f]{4})\s+((?:[0-9a-f]{2}\s*)+?)(?:\s{2,}|\t+|$)(.*)$', line)
  12. if m:
  13. ops.append((int(m.group(1), 16), m.group(2).split(), m.group(3).strip()))
  14. out = {}
  15. addrs = sorted(set(a for _, a in heads))
  16. for name, a in heads:
  17. if name in out:
  18. continue
  19. nxt = min([x for x in addrs if x > a] or [0x10000])
  20. out[name] = [(o, b, m) for (o, b, m) in ops if a <= o < nxt and b != ['00'] and m]
  21. return out
  22. def norm(m):
  23. m = re.sub(r'\b0[0-9a-f]{3}\b', '@@@@', m)
  24. m = re.sub(r'call_with_frame proc\d+', 'call_with_frame proc##', m)
  25. m = re.sub(r'nested_call proc\d+', 'nested_call proc##', m)
  26. m = re.sub(r'(?<!_)proc\d+', 'proc##', m)
  27. return m
  28. def trunc(ms):
  29. li = [i for i, m in enumerate(ms)
  30. if m.split()[0] in ('leave', 'leave0', 'leave2', 'leave4', 'leave6',
  31. 'fct_leave', 'longfct_leave', 'end_program', 'Raise')]
  32. return ms[:li[-1] + 1] if li else ms
  33. def main():
  34. orig_txt, ours_txt, mod = sys.argv[1], sys.argv[2], sys.argv[3]
  35. A, B = procs(orig_txt, mod), procs(ours_txt, mod)
  36. same = tot = 0
  37. for pair in sys.argv[4:]:
  38. o, u = pair.split(':')
  39. tot += 1
  40. if o not in A:
  41. print(f'{u}/{o} ORIG-MISSING'); continue
  42. if u not in B:
  43. print(f'{u}/{o} OURS-MISSING'); continue
  44. xa, xb = trunc([norm(m) for (_, _, m) in A[o]]), trunc([norm(m) for (_, _, m) in B[u]])
  45. n = min(len(xa), len(xb))
  46. if xa == xb:
  47. same += 1
  48. print(f'{u}/{o} {len(xa)} vs {len(xb)} SAME')
  49. elif xa[:n] == xb[:n]:
  50. print(f'{u}/{o} {len(xa)} vs {len(xb)} PREFIX(+{abs(len(xa)-len(xb))})')
  51. else:
  52. print(f'{u}/{o} {len(xa)} vs {len(xb)} DIFF')
  53. print(f'{same}/{tot} exact')
  54. main()