code wiki / _hdl_build / nx_gated_edit_multi.nx
nx_gated_edit_multi.nx source
↩ module page · 106 lines · 5471 B
1// nx_gated_edit_multi.nx -- MULTI-EDIT gated applier: apply N exact old->new edits ATOMICALLY, keep iff a
2// verify command's output is byte-identical before/after (else restore ALL + refuse). The multi-edit
3// generalisation of nx_gated_edit -- needed for delegation that adds an IMPORT line AND replaces a body
4// as ONE unit, so the g_check-bulk organs (which don't import the base) consolidate onto a shared lib.
5// argv: <srcfile> <manifestfile> <verifyelf> <verifyarg>
6// manifest: one edit per line, oldfile<TAB>newfile (paths -> no argv escaping). Edits applied in order;
7// each old must occur EXACTLY once in the evolving working copy, else REFUSE-ALL (no partial writes).
8// exit: 0 CONSOLIDATED | 1 REFUSED (restored) | 2 usage/edit-contract (untouched) | 3 verify-before-empty
9// license_tier: ORIGINAL No hw writes (Rule 26).
10import "nx_seat_drive_lib.nx"
11import "nx_deploy_lib.nx"
12import "nx_ge_str_lib.nx"
13import "nx_syscalls.nx"
14
15const GM_CAP: i64 = 1048576
16const GM_ECAP: i64 = 2097152
17const GM_MANIFEST: i64 = 65536
18const GM_PATH: i64 = 1024
19
20func main(argc: i64, argv: *i64) -> i64 {
21 if argc < 5 { sd_w("usage: nx_gated_edit_multi <srcfile> <manifestfile> <verifyelf> <verifyarg>\n" as *u8); sys_exit(2); return 2 }
22 let srcp: *u8 = argv[1] as *u8
23 let manp: *u8 = argv[2] as *u8
24 let velf: *u8 = argv[3] as *u8
25 let varg: *u8 = argv[4] as *u8
26 let src: *u8 = sys_mmap(GM_CAP)
27 let sn: i64 = dp_read(srcp, src, GM_CAP)
28 if sn <= 0 { sd_w("NX-GEM verdict=SRC-ABSENT " as *u8); sd_w(srcp); sd_w(" . FIX: confirm with `nx_fs ls <dir>`.\n" as *u8); sys_exit(2); return 2 }
29 let man: *u8 = sys_mmap(GM_MANIFEST)
30 let mn: i64 = dp_read(manp, man, GM_MANIFEST)
31 if mn <= 0 { sd_w("NX-GEM verdict=MANIFEST-ABSENT " as *u8); sd_w(manp); sd_w(" . FIX: one oldfile<TAB>newfile per line.\n" as *u8); sys_exit(2); return 2 }
32 let work: *u8 = sys_mmap(GM_ECAP)
33 var wn: i64 = 0
34 var ci: i64 = 0
35 while ci < sn { work[wn] = src[ci]; wn = wn + 1; ci = ci + 1 }
36 let tmp: *u8 = sys_mmap(GM_ECAP)
37 let oldb: *u8 = sys_mmap(GM_CAP)
38 let newb: *u8 = sys_mmap(GM_CAP)
39 let of: *u8 = sys_mmap(GM_PATH)
40 let nf: *u8 = sys_mmap(GM_PATH)
41 var applied: i64 = 0
42 var i: i64 = 0
43 while i < mn {
44 var le: i64 = i
45 var f: i64 = 1
46 while f == 1 { if le >= mn { f = 0 } else { if man[le] == (10 as u8) { f = 0 } else { le = le + 1 } } }
47 var tab: i64 = 0 - 1
48 var j: i64 = i
49 while j < le { if man[j] == (9 as u8) { tab = j; j = le } else { j = j + 1 } }
50 if tab > i {
51 var a: i64 = 0
52 var p: i64 = i
53 while p < tab { of[a] = man[p]; a = a + 1; p = p + 1 }
54 of[a] = 0 as u8
55 var b: i64 = 0
56 var q: i64 = tab + 1
57 while q < le { nf[b] = man[q]; b = b + 1; q = q + 1 }
58 nf[b] = 0 as u8
59 let on: i64 = dp_read(of, oldb, GM_CAP)
60 let nn: i64 = dp_read(nf, newb, GM_CAP)
61 if on <= 0 { sd_w("NX-GEM verdict=OLDFILE-EMPTY " as *u8); sd_w(of); sd_w(" (all untouched)\n" as *u8); sys_exit(2); return 2 }
62 let cnt: i64 = ge_count(work, wn, oldb, on)
63 if cnt == 0 { sd_w("NX-GEM verdict=NOMATCH old=" as *u8); sd_w(of); sd_w(" not in working copy (all untouched). FIX: check old-string or edit order.\n" as *u8); sys_exit(2); return 2 }
64 if cnt > 1 { sd_w("NX-GEM verdict=AMBIGUOUS old=" as *u8); sd_w(of); sd_w(" occurs >1 (all untouched). FIX: longer unique context.\n" as *u8); sys_exit(2); return 2 }
65 let pos: i64 = ge_find(work, wn, oldb, on, 0)
66 var to: i64 = 0
67 var x: i64 = 0
68 while x < pos { tmp[to] = work[x]; to = to + 1; x = x + 1 }
69 var y: i64 = 0
70 while y < nn { tmp[to] = newb[y]; to = to + 1; y = y + 1 }
71 var z: i64 = pos + on
72 while z < wn { tmp[to] = work[z]; to = to + 1; z = z + 1 }
73 wn = to
74 var w2: i64 = 0
75 while w2 < wn { work[w2] = tmp[w2]; w2 = w2 + 1 }
76 applied = applied + 1
77 }
78 i = le
79 if i < mn { i = i + 1 }
80 }
81 if applied == 0 { sd_w("NX-GEM verdict=NO-EDITS (manifest had no oldfile<TAB>newfile rows) (untouched)\n" as *u8); sys_exit(2); return 2 }
82 let av: *i64 = sys_mmap(32) as *i64
83 av[0] = varg as i64
84 dep_run_capture(velf, av, 1, "/tmp/gem_before.out" as *u8)
85 let before: *u8 = sys_mmap(GM_CAP)
86 let bn: i64 = dp_read("/tmp/gem_before.out" as *u8, before, GM_CAP)
87 if bn <= 0 { sd_w("NX-GEM verdict=VERIFY-BEFORE-EMPTY (untouched). FIX: verifyelf must emit deterministic output.\n" as *u8); sys_exit(3); return 3 }
88 dp_writefile(srcp, work, wn)
89 dep_run_capture(velf, av, 1, "/tmp/gem_after.out" as *u8)
90 let after: *u8 = sys_mmap(GM_CAP)
91 let an: i64 = dp_read("/tmp/gem_after.out" as *u8, after, GM_CAP)
92 if an > 0 { if ge_eq(before, bn, after, an) == 1 {
93 sd_w("NX-GEM verdict=CONSOLIDATED edits=" as *u8)
94 let eb: *u8 = sys_mmap(24)
95 sd_num(eb, 0, applied)
96 sd_w(eb)
97 sd_w(" (verify byte-identical) src=" as *u8); sd_w(srcp); sd_w("\n" as *u8)
98 sys_exit(0)
99 return 0
100 } }
101 dp_writefile(srcp, src, sn)
102 dep_run_capture(velf, av, 1, "/tmp/gem_restore.out" as *u8)
103 sd_w("NX-GEM verdict=REFUSED (verify changed -> edits are live) restored src=" as *u8); sd_w(srcp); sd_w("\n" as *u8)
104 sys_exit(1)
105 return 1
106}