From cd1e38ee0b279c3b013ab4887610b101565b46be Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Wed, 26 Aug 2026 15:48:34 -0600 Subject: [PATCH] fix(tools): jr_isolate_all recognises lifted "} __attribute__((...)) X;" typedefs as engine types (5 drafts refused on Block4 after the lift) and drops a cut equal to the object start (a jr function that leads its object made an empty region -> out of order); mk_write refuses to merge a block that moved on disk since the caller read it (R43) (P31 S62 T3) --- tools/jr_isolate_all.py | 9 +++++++++ tools/mk_write.py | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/tools/jr_isolate_all.py b/tools/jr_isolate_all.py index 4820eff8c..cf7bd9c22 100644 --- a/tools/jr_isolate_all.py +++ b/tools/jr_isolate_all.py @@ -257,6 +257,12 @@ def build_new_config(ov, p): if nm not in p["per_obj"]: continue cuts = p["per_obj"][nm] # jr vrams in this object + # A jr function that IS the object's first function (the object is already named after it, + # e.g. ov_SC06_029_jr_8017C954) yields a cut at the object start -> an empty region 0 at the + # same offset -> "code subseg … out of order" at config time (P31 S62). Such a cut is a no-op. + cuts = [c for c in cuts if c != s] + if not cuts: + continue srcpath = os.path.join(REPO, f"src/{ov}/{nm}.c") header, regions = _partition(srcpath, cuts, syms) # region 0 (lo=None) keeps the object name; each jr-led region -> _jr_. Regions are @@ -400,6 +406,9 @@ def _engine_types(): continue t = open(p, errors="replace").read() names |= set(re.findall(r'\}\s*([A-Za-z_]\w*)\s*;', t)) # typedef struct {...} X; + # `} __attribute__((packed, aligned(1))) X;` — the lifted Block4/Blk4_E960 shape (P31 S62): the + # attribute sits between the brace and the name, so the pattern above never saw them. + names |= set(re.findall(r'\}\s*__attribute__\s*\(\(.*?\)\)\s*([A-Za-z_]\w*)\s*;', t)) names |= set(re.findall(r'^\s*typedef\s+[^;{}]*?\b([A-Za-z_]\w*)\s*;', t, re.M)) names |= set(re.findall(r'^\s*(?:struct|union|enum)\s+([A-Za-z_]\w*)\s*;', t, re.M)) # ...and the same TAGS defined WITH A BODY (`struct PW8017E6D8 { int w; };`). The diff --git a/tools/mk_write.py b/tools/mk_write.py index cc4520dbb..16f8b8517 100644 --- a/tools/mk_write.py +++ b/tools/mk_write.py @@ -39,6 +39,7 @@ missing line, not a wiped file — and it is caught downstream by the fleet chec Closing it properly means holding the lock across read-modify-write in every caller. """ import re +import sys import fcntl import os @@ -67,6 +68,12 @@ def merge_blocks(cur, base, new): changed = {k for k in nb if nb[k] != bb.get(k)} if not changed: return cur + # R43: a block this caller changed whose text ALSO moved on disk since the caller's read is a + # conflict — applying the caller's version would resurrect its stale view of that block. + conflict = [k for k in changed if k in cb and k in bb and cb[k] != bb[k]] + if conflict: + sys.exit("mk_write: overlays.mk block(s) %s changed on disk since this caller read them — " + "refusing to write a stale view; re-read and retry" % conflict) out = [] for k, v in cb.items(): out.append(nb[k] if k in changed else v)