code wiki / (root) / nx_docgen_lib.nx

nx_docgen_lib.nx source

↩ module page · 105 lines · 4242 B

1// nx_docgen_lib.nx -- Nishi Office: DOCUMENT ASSEMBLY (F505) core lib. Data-driven clause 2// library + templates (ordered clause refs) + {field} merge -> a deterministic, content- 3// addressed legal document. Legal-SOTA: (1) clauses/templates are DATA on the immutable 4// seg_store (add a clause = a data change, rule-11/rule-25, never fewer options); (2) merge 5// is FAIL-CLOSED -- an unknown clause OR an unfilled {field} REFUSES the whole document 6// (never a silent blank in a contract); (3) same template+data -> same CID (nx_canon_cid), 7// so an assembled engagement letter is tamper-evident and composes with nx_box + nx_sign. 8// Composes nx_matter_lib (mt_field/mt_streq/canon) + nx_registry + nx_canon_cid. LIB. license_tier: ORIGINAL 9 10import "nx_matter_lib.nx" 11 12func dg_strlen(s: *u8) -> i64 { 13 var i: i64 = 0 14 while s[i] != (0 as u8) { i = i + 1 } 15 return i 16} 17 18// store a clause (raw text) on the immutable plane, keyed by id 19func dg_clause_put(prefix: *u8, id: *u8, text: *u8) -> i64 { 20 return reg_put(prefix, "clause:" as *u8, "clause:__idx__" as *u8, id, text, dg_strlen(text)) 21} 22 23// store a template = ordered comma-separated clause ids 24func dg_tmpl_put(prefix: *u8, id: *u8, csv: *u8) -> i64 { 25 return reg_put(prefix, "tmpl:" as *u8, "tmpl:__idx__" as *u8, id, csv, dg_strlen(csv)) 26} 27 28// append src to dst[o..], substituting every {field} from the canonical merge record. 29// returns the new offset, or -1 if a {field} is absent (FAIL-CLOSED, no silent blank). 30func dg_merge(src: *u8, srclen: i64, mergerec: *u8, mergelen: i64, dst: *u8, o0: i64) -> i64 { 31 var o: i64 = o0 32 var i: i64 = 0 33 let tok: *u8 = sys_mmap(128) 34 let val: *u8 = sys_mmap(512) 35 while i < srclen { 36 let c: i64 = src[i] as i64 37 if c == 123 { 38 var j: i64 = i + 1 39 var found: i64 = 0 40 while found == 0 { 41 if j >= srclen { found = 2 } 42 if found == 0 { if (src[j] as i64) == 125 { found = 1 } } 43 if found == 0 { j = j + 1 } 44 } 45 if found == 2 { dst[o] = src[i]; o = o + 1; i = i + 1 } 46 if found == 1 { 47 var k: i64 = 0 48 var p: i64 = i + 1 49 while p < j { tok[k] = src[p]; k = k + 1; p = p + 1 } 50 tok[k] = 0 as u8 51 let vl: i64 = mt_field(mergerec, mergelen, tok, k, val) 52 if vl < 0 { return 0 - 1 } 53 var d: i64 = 0 54 while d < vl { dst[o] = val[d]; o = o + 1; d = d + 1 } 55 i = j + 1 56 } 57 } 58 if c != 123 { dst[o] = src[i]; o = o + 1; i = i + 1 } 59 } 60 return o 61} 62 63// assemble template tmpl_id with the merge record into out (NUL-terminated); returns length, 64// or -1 if the template/a clause is unknown OR a merge field is unfilled (FAIL-CLOSED). 65func dg_assemble(prefix: *u8, tmpl_id: *u8, mergerec: *u8, mergelen: i64, out: *u8) -> i64 { 66 let po: *i64 = sys_mmap(16) as *i64 67 let lo: *i64 = sys_mmap(16) as *i64 68 if reg_get(prefix, "tmpl:" as *u8, tmpl_id, po, lo) != 1 { return 0 - 1 } 69 let csv: *u8 = po[0] as *u8 70 let csvlen: i64 = lo[0] 71 var o: i64 = 0 72 var s: i64 = 0 73 while s < csvlen { 74 var e: i64 = s 75 var done: i64 = 0 76 while done == 0 { 77 if e >= csvlen { done = 1 } 78 if done == 0 { if (csv[e] as i64) == 44 { done = 1 } else { e = e + 1 } } 79 } 80 let cid: *u8 = sys_mmap(128) 81 var k: i64 = 0 82 var p: i64 = s 83 while p < e { cid[k] = csv[p]; k = k + 1; p = p + 1 } 84 cid[k] = 0 as u8 85 let cpo: *i64 = sys_mmap(16) as *i64 86 let clo: *i64 = sys_mmap(16) as *i64 87 if reg_get(prefix, "clause:" as *u8, cid, cpo, clo) != 1 { return 0 - 1 } 88 let no: i64 = dg_merge(cpo[0] as *u8, clo[0], mergerec, mergelen, out, o) 89 if no < 0 { return 0 - 1 } 90 o = no 91 out[o] = 10 as u8 92 o = o + 1 93 s = e + 1 94 } 95 out[o] = 0 as u8 96 return o 97} 98 99// count '{' left in a doc (0 == every merge field was substituted) 100func dg_unmerged(doc: *u8, len: i64) -> i64 { 101 var n: i64 = 0 102 var i: i64 = 0 103 while i < len { if (doc[i] as i64) == 123 { n = n + 1 } i = i + 1 } 104 return n 105}