"""Verify the pileSizeClientData key enum before changing boot-critical massinfo.

Contradiction to resolve:
 - utas_server.py comment: pileSizeClientData is "the MY CLUB counter", enum
   "not recoverable", so it sprays the club count across keys 0..15.
 - workflow wf_29791945: parser FUN_18013adb0 has EXACTLY two arms, key 2 -> trade
   pile (response+0xd0 -> model+0x1fd1c = TRADE_PILE_SIZE, the red 0/0) and key 4 ->
   watch list (+0xd4 -> +0x1fd20). No club key. Spraying the club count (246) onto
   key 2 would set the TRANSFER-LIST CAPACITY to 246, which is wrong.

Only one can be right. Read the parser. If it has cmp esi,2 / cmp esi,4 and no
default store, the workflow is right and the current code is a latent bug.

CONTROL: the parser must be reached from the massinfo root via arm 0x227
(pileSizeClientData atom). Confirm the atom and the call.
"""
import re, traceback

PARSER = 0x18013ADB0

try:
    src = dec(PARSER)
    f = func(PARSER)
    print("%#x pileSizeClientData parser  body %d / decompile %d chars (IN FULL)"
          % (PARSER, f.getBody().getNumAddresses() if f else -1, len(src)))
    print("=" * 78)
    print(src)

    print("\n=== raw instructions: every cmp against a small immediate + the stores ===")
    a = f.getBody().getMinAddress()
    end = f.getBody().getMaxAddress()
    while a is not None and a.compareTo(end) <= 0:
        i = listing.getInstructionAt(a)
        if i is None:
            a = a.add(1); continue
        m = i.getMnemonicString().lower()
        t = str(i)
        if (m == "cmp" and re.search(r",0x[0-9a-f]$|,0x[0-9a-f]\b", t)) or \
           (m == "mov" and "0xd0" in t) or (m == "mov" and "0xd4" in t) or \
           (m == "mov" and "+ 0x8]" in t) or (m == "mov" and "+ 0xc]" in t):
            print("  %#x  %s" % (int(i.getAddress().getOffset()), t))
        a = i.getAddress().add(i.getLength())

    print("\n=== who calls the parser, and the pileSizeClientData atom (0x227) ===")
    for adr, n in callers(PARSER):
        print("  caller %#x %s" % (adr, n))
    aid = None
    for line in open("/home/alex/Documents/OpenFUT/fifa17-recon/docs/fut_atoms.tsv"):
        p = line.rstrip("\n").split("\t")
        if len(p) >= 3 and p[2] == "pileSizeClientData":
            aid = p[1]
    print("  pileSizeClientData atom id (from tsv):", aid)

except Exception:
    traceback.print_exc()
