"""MCD proc-compare scorer. Usage: score.py ORIG_TXT OURS_TXT MOD PAIRS... PAIRS = OrigName:OursName. Masks absolute targets, proc refs, dep slots; leave-truncates bodies; reports SAME/PREFIX/DIFF per pair.""" import re, sys def procs(path, mod): txt = open(path, errors='replace').read() heads = [(m.group(1), int(m.group(2), 16)) for m in re.finditer(r'(?m)^;? ?' + mod + r'\.(\w+)\s*: ([0-9a-f]{4})$', txt)] ops = [] cur = None for line in txt.splitlines(): m = re.match(r'^\s*([0-9a-f]{4})\s+((?:[0-9a-f]{2}\s*)+?)(?:\s{2,}|\t+|$)(.*)$', line) if m: cur = int(m.group(1), 16) ops.append((cur, m.group(2).split(), m.group(3).strip())) continue # case-table lines carry no address: attach to preceding cd op so # CASE bounds/labels participate in comparison (else invisible). # NOTE: unassemble prints labels +90 (subtracts 32678 not 32768); # the shift applies equally to both sides, so comparison stays valid. c = re.match(r'^\s*case (\d+) => ([0-9a-f]{4})$', line) if c and cur is not None: ops.append((cur, ['cd'], 'case %d => %s' % (int(c.group(1)), c.group(2)))) out = {} addrs = sorted(set(a for _, a in heads)) for name, a in heads: if name in out: continue nxt = min([x for x in addrs if x > a] or [0x10000]) out[name] = [(o, b, m) for (o, b, m) in ops if a <= o < nxt and b != ['00'] and m] return out def norm(m): m = re.sub(r'\b[0-9a-f]{4}\b', '@@@@', m) m = re.sub(r'call_with_frame proc\d+', 'call_with_frame proc##', m) m = re.sub(r'nested_call proc\d+', 'nested_call proc##', m) m = re.sub(r'(?