code wiki / (root) / nx_underbuilt_lib.nx

nx_underbuilt_lib.nx source

↩ module page · 249 lines · 8365 B

1// nx_underbuilt_lib.nx -- R6 parse/tally core for the NHTSA underbuilt-part signal (LIB, no main; imported 2// by nx_underbuilt_board + nx_underbuilt_gate). Context-byte JSON key matching (quote-key-quote-colon) so no 3// quote characters appear in nx string literals; component values split on commas and tallied in a ctx-table 4// arena. ctx t: *i64 slots: 0=name-arena ptr, 1=arena-used, 2=off[] ptr, 3=len[] ptr, 4=count[] ptr, 5// 5=ndistinct, 6=records (key occurrences), 7=tokens (sum of counts), 8=arena cap. 6// Board persistence to seg_store = a later rung; v0 board is printed + gated. license_tier: ORIGINAL 7import "nx_syscalls.nx" 8 9func ubl_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 10func ubl_putn(v: i64) -> i64 { 11 let bb: *u8 = sys_mmap(28) 12 var m: i64 = v 13 if m < 0 { ubl_puts("-" as *u8); m = 0 - m } 14 let t: *u8 = sys_mmap(28) 15 var k: i64 = 0 16 if m == 0 { t[0] = 48 as u8; k = 1 } 17 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 18 var i: i64 = 0 19 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 20 sys_write(1, bb, k) 21 return 0 22} 23 24// read whole file into buf (cap-bounded); returns bytes or -1 25func ubl_read(path: *u8, buf: *u8, cap: i64) -> i64 { 26 let fd: i64 = sys_openat_rd(path) 27 if fd < 0 { return 0 - 1 } 28 var off: i64 = 0 29 var going: i64 = 1 30 while going == 1 { 31 if off >= cap { going = 0 } else { 32 let want: i64 = cap - off 33 let p: *u8 = ((buf as i64) + off) as *u8 34 let r: i64 = sys_read(fd, p, want) 35 if r <= 0 { going = 0 } else { off = off + r } 36 } 37 } 38 sys_close(fd) 39 return off 40} 41 42// 1 if key bytes match at 'at' with JSON context: quote before, quote+colon after 43func ubl_match(buf: *u8, n: i64, key: *u8, klen: i64, at: i64) -> i64 { 44 if at < 1 { return 0 } 45 if at + klen + 2 > n { return 0 } 46 var j: i64 = 0 47 while j < klen { 48 if buf[at + j] != key[j] { return 0 } 49 j = j + 1 50 } 51 if buf[at - 1] != (34 as u8) { return 0 } 52 if buf[at + klen] != (34 as u8) { return 0 } 53 if buf[at + klen + 1] != (58 as u8) { return 0 } 54 return 1 55} 56 57// next context-verified key occurrence at/after 'from'; -1 if none 58func ubl_next(buf: *u8, n: i64, key: *u8, klen: i64, from: i64) -> i64 { 59 var i: i64 = from 60 if i < 1 { i = 1 } 61 let k0: u8 = key[0] 62 while i + klen + 2 <= n { 63 if buf[i] == k0 { 64 let m: i64 = ubl_match(buf, n, key, klen, i) 65 if m == 1 { return i } 66 } 67 i = i + 1 68 } 69 return 0 - 1 70} 71 72// first integer value of key (skips spaces; digits only); -1 if absent 73func ubl_key_int(buf: *u8, n: i64, key: *u8, klen: i64) -> i64 { 74 let i: i64 = ubl_next(buf, n, key, klen, 0) 75 if i < 0 { return 0 - 1 } 76 var v: i64 = i + klen + 2 77 var sk: i64 = 1 78 while sk == 1 { 79 if v < n { if buf[v] == (32 as u8) { v = v + 1 } else { sk = 0 } } else { sk = 0 } 80 } 81 var val: i64 = 0 82 var got: i64 = 0 83 var going: i64 = 1 84 while going == 1 { 85 if v >= n { going = 0 } else { 86 let c: i64 = buf[v] as i64 87 if c >= 48 { 88 if c <= 57 { val = val * 10 + (c - 48); got = 1; v = v + 1 } else { going = 0 } 89 } else { going = 0 } 90 } 91 } 92 if got == 0 { return 0 - 1 } 93 return val 94} 95 96// count key occurrences whose value starts with 't' (true) 97func ubl_count_true(buf: *u8, n: i64, key: *u8, klen: i64) -> i64 { 98 var total: i64 = 0 99 var i: i64 = ubl_next(buf, n, key, klen, 0) 100 while i >= 0 { 101 var v: i64 = i + klen + 2 102 var sk: i64 = 1 103 while sk == 1 { 104 if v < n { if buf[v] == (32 as u8) { v = v + 1 } else { sk = 0 } } else { sk = 0 } 105 } 106 if v < n { if buf[v] == (116 as u8) { total = total + 1 } } 107 i = ubl_next(buf, n, key, klen, v) 108 } 109 return total 110} 111 112func ubl_reset(t: *i64) -> i64 { t[1] = 0; t[5] = 0; t[6] = 0; t[7] = 0; return 0 } 113 114// find-or-add token [at,at+len) from buf into the tally; count++ 115func ubl_tok_add(t: *i64, buf: *u8, at: i64, len: i64) -> i64 { 116 let arena: *u8 = t[0] as *u8 117 let offs: *i64 = t[2] as *i64 118 let lens: *i64 = t[3] as *i64 119 let cnts: *i64 = t[4] as *i64 120 var found: i64 = 0 - 1 121 var k: i64 = 0 122 while k < t[5] { 123 if found < 0 { 124 if lens[k] == len { 125 let ao: i64 = offs[k] 126 var same: i64 = 1 127 var j: i64 = 0 128 while j < len { 129 if arena[ao + j] != buf[at + j] { same = 0; j = len } else { j = j + 1 } 130 } 131 if same == 1 { found = k } 132 } 133 } 134 k = k + 1 135 } 136 if found >= 0 { 137 cnts[found] = cnts[found] + 1 138 t[7] = t[7] + 1 139 return found 140 } 141 if t[5] >= 512 { return 0 - 1 } 142 if t[1] + len > t[8] { return 0 - 1 } 143 let nd: i64 = t[5] 144 offs[nd] = t[1] 145 lens[nd] = len 146 cnts[nd] = 1 147 var j2: i64 = 0 148 while j2 < len { arena[t[1] + j2] = buf[at + j2]; j2 = j2 + 1 } 149 t[1] = t[1] + len 150 t[5] = nd + 1 151 t[7] = t[7] + 1 152 return nd 153} 154 155// tally every string value of key: records++ per occurrence, split value on commas, trim spaces, add tokens 156func ubl_tally(t: *i64, buf: *u8, n: i64, key: *u8, klen: i64) -> i64 { 157 var i: i64 = ubl_next(buf, n, key, klen, 0) 158 while i >= 0 { 159 var v: i64 = i + klen + 2 160 var sk: i64 = 1 161 while sk == 1 { 162 if v < n { if buf[v] == (32 as u8) { v = v + 1 } else { sk = 0 } } else { sk = 0 } 163 } 164 var resume: i64 = v 165 if v < n { 166 if buf[v] == (34 as u8) { 167 var e: i64 = v + 1 168 var sc: i64 = 1 169 while sc == 1 { 170 if e < n { if buf[e] == (34 as u8) { sc = 0 } else { e = e + 1 } } else { sc = 0 } 171 } 172 t[6] = t[6] + 1 173 var ts: i64 = v + 1 174 var p: i64 = v + 1 175 while p <= e { 176 var isend: i64 = 0 177 if p == e { isend = 1 } else { if buf[p] == (44 as u8) { isend = 1 } } 178 if isend == 1 { 179 var a: i64 = ts 180 var b: i64 = p 181 var tr: i64 = 1 182 while tr == 1 { 183 if a < b { if buf[a] == (32 as u8) { a = a + 1 } else { tr = 0 } } else { tr = 0 } 184 } 185 tr = 1 186 while tr == 1 { 187 if b > a { if buf[b - 1] == (32 as u8) { b = b - 1 } else { tr = 0 } } else { tr = 0 } 188 } 189 if b > a { let dummy: i64 = ubl_tok_add(t, buf, a, b - a) } 190 ts = p + 1 191 } 192 p = p + 1 193 } 194 resume = e + 1 195 } 196 } 197 i = ubl_next(buf, n, key, klen, resume) 198 } 199 return t[6] 200} 201 202// fill rank[0..m) with distinct-token indices sorted by count desc; returns m 203func ubl_top(t: *i64, rank: *i64, kmax: i64) -> i64 { 204 let cnts: *i64 = t[4] as *i64 205 var m: i64 = kmax 206 if t[5] < m { m = t[5] } 207 var r: i64 = 0 208 while r < m { 209 var best: i64 = 0 - 1 210 var bestc: i64 = 0 - 1 211 var k: i64 = 0 212 while k < t[5] { 213 var used: i64 = 0 214 var q: i64 = 0 215 while q < r { if rank[q] == k { used = 1 } q = q + 1 } 216 if used == 0 { if cnts[k] > bestc { bestc = cnts[k]; best = k } } 217 k = k + 1 218 } 219 rank[r] = best 220 r = r + 1 221 } 222 return m 223} 224 225// print token name idx 226func ubl_name_out(t: *i64, idx: i64) -> i64 { 227 let offs: *i64 = t[2] as *i64 228 let lens: *i64 = t[3] as *i64 229 let p: *u8 = (t[0] + offs[idx]) as *u8 230 sys_write(1, p, lens[idx]) 231 return 0 232} 233 234// 1 if token idx equals zero-terminated s 235func ubl_name_is(t: *i64, idx: i64, s: *u8) -> i64 { 236 let offs: *i64 = t[2] as *i64 237 let lens: *i64 = t[3] as *i64 238 var sl: i64 = 0 239 while s[sl] != (0 as u8) { sl = sl + 1 } 240 if lens[idx] != sl { return 0 } 241 let arena: *u8 = t[0] as *u8 242 let ao: i64 = offs[idx] 243 var j: i64 = 0 244 while j < sl { 245 if arena[ao + j] != s[j] { return 0 } 246 j = j + 1 247 } 248 return 1 249}