code wiki / (root) / nx_accept_ref_lib.nx

nx_accept_ref_lib.nx source

↩ module page · 407 lines · 20329 B

1// nx_accept_ref_lib.nx -- THE VERB-SIDE HALF OF THE THREE-PARTY ACCEPTANCE LEDGER (2026-08-31). 2// 3// nx_accept_lib.nx is the DECISION CORE: three planes in, ACCEPTED or INCOMPLETE out, reason codes in why[]. 4// This lib is everything the verbs (nx_accept) and their referee (nx_accept_gate) need ON TOP of that core, 5// kept out of the organ's main() so the gate drives the identical code over /tmp fixtures: 6// * acr_party -- INCOMPLETE is never enough. The FIRST missing signature is NAMED, in the order the 7// operator's standing order lists them (operator, referee, seat), so a NOT-AGREED can 8// always say WHICH negative it is: OPERATOR-MISSING is not OPERATOR-REJECT, 9// REFEREE-BELOW-BAND is not REFEREE-MISSING, and none of them is SEAT-MISSING. 10// * acr_status_line -- one line per subject carrying every input the verdict was derived from (operator 11// verdict and row count, referee code, percept, floor, tier, seat rows, board and organ 12// file), so a reader can refute the verdict from the line instead of trusting it. 13// * acr_unmapped -- an operator row whose targets carry no ga_accept_<subject> token governs NOTHING and 14// the core only COUNTS it. This prints each one with id, verdict, actor, targets and the 15// remedy, because a counted-but-unnamed row is not actionable. 16// * acr_boards -- every ACCEPTANCE watch row on the /compare boards becomes a subject too, so a board 17// subject nobody has judged reads NOT-AGREED missing=OPERATOR-MISSING instead of 18// vanishing from the list, and a watch row naming the WRONG organ file is flagged -- 19// it could never flip, however many signatures arrived. 20// * acr_ref_admit -- may a referee row be written for this tier at all? The panel receipt decides 21// (admitted, tiers_admitted, a floor for the tier); an abstaining panel is not a grade. 22// * acr_kvint -- the mid-line key=<int> reader for the panel lens line (cjp_percept=<n>), because 23// nx_lineconf_lib is deliberately LINE-anchored and that field is not at a line start. 24// * acr_sha256_file -- the artifact identity a seat attests to and the frame identity a referee row carries: 25// sha256 of the bytes, hex, never a hand-typed stamp. -1 when unreadable, never the 26// digest of nothing. 27// * acr_decl_shape -- the emitted declaration file's ONE permitted code form, as a ruler: every non-comment 28// line must be exactly `func ga_accept_<ident>() -> i64 { return 1 }`, the form the 29// compiler is proven to accept, so a buffer that passes this ruler is the form that builds. 30// COMPOSES, NEVER RE-IMPLEMENTS: nx_accept_lib for every rule, nx_seg_store's cursor through al_next for the 31// plane walk, nx_comparewatch_lib's cw_field for tab fields, nx_sha256 for the digest. 32// license_tier: ORIGINAL No hw writes (Rule 26). 33import "nx_syscalls.nx" 34import "nx_sha256.nx" 35import "nx_accept_lib.nx" 36 37// the named missing party, first missing wins in operator -> referee -> seat order 38const ACR_P_AGREED: i64 = 0 39const ACR_P_OP_MISSING: i64 = 1 40const ACR_P_OP_REJECT: i64 = 2 41const ACR_P_OP_UNJUDGED: i64 = 3 42const ACR_P_OP_INVALID: i64 = 4 43const ACR_P_REF_MISSING: i64 = 5 44const ACR_P_REF_BAD: i64 = 6 45const ACR_P_REF_INVALID: i64 = 7 46const ACR_P_REF_PANEL: i64 = 8 47const ACR_P_REF_TIER: i64 = 9 48const ACR_P_REF_NOFLOOR: i64 = 10 49const ACR_P_REF_BELOW: i64 = 11 50const ACR_P_SEAT_MISSING: i64 = 12 51const ACR_P_UNKNOWN: i64 = 13 52// referee-row admission under the panel conf + receipt 53const ACR_REF_OK: i64 = 0 54const ACR_REF_NO_CONF: i64 = 1 55const ACR_REF_NO_RECEIPT: i64 = 2 56const ACR_REF_PANEL_UNADMITTED: i64 = 3 57const ACR_REF_TIER_UNADMITTED: i64 = 4 58const ACR_REF_NO_FLOOR: i64 = 5 59// exit codes of the nx_accept verbs, HERE so the gate reads them instead of mirroring them 60const ACR_EXIT_AGREED: i64 = 0 61const ACR_EXIT_NOT_AGREED: i64 = 1 62const ACR_EXIT_USAGE: i64 = 2 63const ACR_EXIT_UNKNOWN: i64 = 3 64const ACR_EXIT_REFUSED: i64 = 4 65const ACR_EXIT_IO: i64 = 5 66const ACR_EXIT_UNOBS: i64 = 6 67 68const ACR_DIGEST_BYTES: i64 = 32 69const ACR_HEXCAP: i64 = 72 70const ACR_NIB: i64 = 16 71const ACR_HEX_ALPHA: i64 = 87 // 'a' minus 10: nibbles 10..15 print as a..f 72const ACR_UNOBS: i64 = 0 - 9999 // nx_charjudge_census CJP_UNOBS: a lens that could not see 73const ACR_LINECAP: i64 = 1024 74const ACR_LP: i64 = 16 75const ACR_WHY_WORDS: i64 = 8 76const ACR_DECL_TAIL: *u8 = "() -> i64 { return 1 }" 77const ACR_FUNC_KW: *u8 = "func " 78 79func acr_catf(d: *u8, o: i64, key: *u8, v: *u8) -> i64 { var p: i64 = al_cat(d, o, key); p = al_cat(d, p, v); return p } 80func acr_catfn(d: *u8, o: i64, key: *u8, v: i64) -> i64 { var p: i64 = al_cat(d, o, key); p = al_catn(d, p, v); return p } 81 82// ---- the named party -------------------------------------------------------------------------------------- 83func acr_party(bk: *i64, cf: *i64, si: i64, why: *i64) -> i64 { 84 let st: i64 = al_state(bk, cf, si, why) 85 if st == AL_ST_ACCEPTED { return ACR_P_AGREED } 86 let it: *i64 = al_bk_ints(bk, si) 87 if it[AL_I_OPSEEN] == 0 { return ACR_P_OP_MISSING } 88 if why[AL_WHY_OP] == AL_V_REJECT { return ACR_P_OP_REJECT } 89 if why[AL_WHY_OP] == AL_V_UNJUDGED { return ACR_P_OP_UNJUDGED } 90 if why[AL_WHY_OP] != AL_V_ACCEPT { return ACR_P_OP_INVALID } 91 let rc: i64 = why[AL_WHY_REF] 92 if rc == AL_RC_MISSING { return ACR_P_REF_MISSING } 93 if rc == AL_RC_BAD { return ACR_P_REF_BAD } 94 if rc == AL_RC_INVALID { return ACR_P_REF_INVALID } 95 if rc == AL_RC_PANEL_UNADMITTED { return ACR_P_REF_PANEL } 96 if rc == AL_RC_TIER_UNADMITTED { return ACR_P_REF_TIER } 97 if rc == AL_RC_NO_FLOOR { return ACR_P_REF_NOFLOOR } 98 if rc == AL_RC_BELOW_FLOOR { return ACR_P_REF_BELOW } 99 if why[AL_WHY_ATT] != 1 { return ACR_P_SEAT_MISSING } 100 return ACR_P_UNKNOWN 101} 102func acr_party_name(c: i64) -> *u8 { 103 if c == ACR_P_AGREED { return "AGREED" as *u8 } 104 if c == ACR_P_OP_MISSING { return "OPERATOR-MISSING" as *u8 } 105 if c == ACR_P_OP_REJECT { return "OPERATOR-REJECT" as *u8 } 106 if c == ACR_P_OP_UNJUDGED { return "OPERATOR-UNJUDGED" as *u8 } 107 if c == ACR_P_OP_INVALID { return "OPERATOR-INVALID-VERDICT" as *u8 } 108 if c == ACR_P_REF_MISSING { return "REFEREE-MISSING" as *u8 } 109 if c == ACR_P_REF_BAD { return "REFEREE-BAD" as *u8 } 110 if c == ACR_P_REF_INVALID { return "REFEREE-INVALID-ROW" as *u8 } 111 if c == ACR_P_REF_PANEL { return "REFEREE-PANEL-UNADMITTED" as *u8 } 112 if c == ACR_P_REF_TIER { return "REFEREE-TIER-UNADMITTED" as *u8 } 113 if c == ACR_P_REF_NOFLOOR { return "REFEREE-NO-FLOOR-FOR-TIER" as *u8 } 114 if c == ACR_P_REF_BELOW { return "REFEREE-BELOW-BAND" as *u8 } 115 if c == ACR_P_SEAT_MISSING { return "SEAT-MISSING" as *u8 } 116 return "UNKNOWN" as *u8 117} 118 119// ---- referee-row admission ----------------------------------------------------------------------------------- 120func acr_ref_admit(cf: *i64, tier: *u8, floor_out: *i64) -> i64 { 121 floor_out[0] = LCF_MISS 122 if cf[AL_C_CONF_OK] == 0 { return ACR_REF_NO_CONF } 123 if cf[AL_C_RCPT_OK] == 0 { return ACR_REF_NO_RECEIPT } 124 if cf[AL_C_ADMITTED] != 1 { return ACR_REF_PANEL_UNADMITTED } 125 if al_list_has(cf[AL_C_TADM] as *u8, tier) == 0 { return ACR_REF_TIER_UNADMITTED } 126 let fl: i64 = al_floor_for_tier(cf, tier) 127 if fl == LCF_MISS { return ACR_REF_NO_FLOOR } 128 floor_out[0] = fl 129 return ACR_REF_OK 130} 131func acr_ref_admit_name(c: i64) -> *u8 { 132 if c == ACR_REF_OK { return "OK" as *u8 } 133 if c == ACR_REF_NO_CONF { return "NO-PANEL-CONF" as *u8 } 134 if c == ACR_REF_NO_RECEIPT { return "NO-ADMISSION-RECEIPT" as *u8 } 135 if c == ACR_REF_PANEL_UNADMITTED { return "PANEL-UNADMITTED" as *u8 } 136 if c == ACR_REF_TIER_UNADMITTED { return "TIER-UNADMITTED" as *u8 } 137 return "NO-FLOOR-FOR-TIER" as *u8 138} 139// GOOD iff the measured percept clears the tier floor. The row's WORD is necessary, never sufficient: the core 140// re-derives it from the same floor, so a row cannot lie its way past the bar. 141func acr_composite(percept: i64, floor: i64) -> i64 { if floor == LCF_MISS { return 0 } if percept >= floor { return 1 } return 0 } 142 143// ---- mid-line key=<int> (optional leading minus). `absent` when the key or its digits are not there. ---------- 144func acr_kvint(buf: *u8, n: i64, key: *u8, absent: i64) -> i64 { 145 let kl: i64 = al_slen(key) 146 if kl == 0 { return absent } 147 var i: i64 = 0 148 while i + kl <= n { 149 var m: i64 = 1 150 var j: i64 = 0 151 while j < kl { if buf[i + j] != key[j] { m = 0; j = kl } else { j = j + 1 } } 152 if m == 1 { 153 var p: i64 = i + kl 154 var neg: i64 = 0 155 if p < n { if (buf[p] as i64) == AL_MINUS { neg = 1; p = p + 1 } } 156 var v: i64 = 0 157 var digits: i64 = 0 158 var run: i64 = 1 159 while run == 1 { 160 if p < n { 161 let c: i64 = buf[p] as i64 162 var isd: i64 = 0 163 if c >= AL_D0 { if c <= AL_D9 { isd = 1 } } 164 if isd == 1 { v = v * AL_BASE10 + (c - AL_D0); digits = digits + 1; p = p + 1 } else { run = 0 } 165 } else { run = 0 } 166 } 167 if digits == 0 { return absent } 168 if neg == 1 { return 0 - v } 169 return v 170 } 171 i = i + 1 172 } 173 return absent 174} 175 176// ---- sha256 as 64 hex, of a buffer or a file ------------------------------------------------------------------- 177func acr_hex(d: *u8, out: *u8) -> i64 { 178 var i: i64 = 0 179 while i < ACR_DIGEST_BYTES { 180 let v: i64 = d[i] as i64 181 let hi: i64 = v / ACR_NIB 182 let lo: i64 = v % ACR_NIB 183 if hi < AL_BASE10 { out[i * 2] = (AL_D0 + hi) as u8 } else { out[i * 2] = (ACR_HEX_ALPHA + hi) as u8 } 184 if lo < AL_BASE10 { out[i * 2 + 1] = (AL_D0 + lo) as u8 } else { out[i * 2 + 1] = (ACR_HEX_ALPHA + lo) as u8 } 185 i = i + 1 186 } 187 out[ACR_DIGEST_BYTES * 2] = 0 as u8 188 return ACR_DIGEST_BYTES * 2 189} 190func acr_sha256_buf(b: *u8, n: i64, outhex: *u8) -> i64 { 191 let d: *u8 = sys_mmap(ACR_DIGEST_BYTES) 192 sha256_digest(b, n, d) 193 return acr_hex(d, outhex) 194} 195// -1 when the file cannot be read (outhex emptied); never the digest of nothing 196func acr_sha256_file(path: *u8, outhex: *u8) -> i64 { 197 outhex[0] = 0 as u8 198 let ln: *i64 = sys_mmap(ACR_LP) as *i64 199 let b: *u8 = sys_read_file(path, ln) 200 if (b as i64) == 0 { return 0 - 1 } 201 acr_sha256_buf(b, ln[0], outhex) 202 return ln[0] 203} 204 205// ---- the status line ---------------------------------------------------------------------------------------- 206// dom/org may be 0 (no board column). Returns the new offset, -1 when the buffer cannot take another line. 207func acr_status_line(bk: *i64, cf: *i64, si: i64, dom: *u8, org: *u8, out: *u8, o0: i64, cap: i64) -> i64 { 208 if o0 + ACR_LINECAP >= cap { return 0 - 1 } 209 let why: *i64 = sys_mmap(8 * ACR_WHY_WORDS) as *i64 210 let party: i64 = acr_party(bk, cf, si, why) 211 let it: *i64 = al_bk_ints(bk, si) 212 let rec: *u8 = al_bk_rec(bk, si) 213 var o: i64 = acr_catf(out, o0, "subject=" as *u8, al_bk_name(bk, si)) 214 if party == ACR_P_AGREED { o = al_cat(out, o, " verdict=AGREED" as *u8) } else { o = al_cat(out, o, " verdict=NOT-AGREED" as *u8) } 215 o = acr_catf(out, o, " missing=" as *u8, acr_party_name(party)) 216 o = acr_catf(out, o, " operator=" as *u8, al_vname(why[AL_WHY_OP])) 217 o = acr_catfn(out, o, " op_rows=" as *u8, it[AL_I_OPSEEN]) 218 o = acr_catf(out, o, " referee=" as *u8, al_rcname(why[AL_WHY_REF])) 219 o = acr_catfn(out, o, " ref_rows=" as *u8, it[AL_I_RSEEN]) 220 if it[AL_I_RSEEN] == 0 { o = al_cat(out, o, " percept=none" as *u8) } else { o = acr_catfn(out, o, " percept=" as *u8, it[AL_I_RPERCEPT]) } 221 if why[AL_WHY_FLOOR] == LCF_MISS { o = al_cat(out, o, " floor=none" as *u8) } else { o = acr_catfn(out, o, " floor=" as *u8, why[AL_WHY_FLOOR]) } 222 let tier: *u8 = ((rec as i64) + AL_F_RTIER) as *u8 223 if tier[0] == (0 as u8) { o = al_cat(out, o, " tier=-" as *u8) } else { o = acr_catf(out, o, " tier=" as *u8, tier) } 224 o = acr_catfn(out, o, " seat=" as *u8, it[AL_I_ATT]) 225 o = acr_catfn(out, o, " att_rows=" as *u8, it[AL_I_ASEEN]) 226 var hasboard: i64 = 0 227 if (dom as i64) != 0 { if dom[0] != (0 as u8) { hasboard = 1 } } 228 if hasboard == 0 { o = al_cat(out, o, " board=-" as *u8) } else { 229 o = acr_catf(out, o, " board=" as *u8, dom) 230 o = acr_catf(out, o, " organ=" as *u8, org) 231 if al_streq(org, AL_DECL_ROW) == 1 { o = al_cat(out, o, " organ_row=OK" as *u8) } else { o = al_cat(out, o, " organ_row=WRONG-FILE-cannot-flip" as *u8) } 232 } 233 out[o] = AL_NL as u8 234 o = o + 1 235 out[o] = 0 as u8 236 return o 237} 238 239// ---- the summary line: every counter the book kept, so the partition is on the record ------------------------ 240func acr_summary(bk: *i64, cf: *i64, planes: i64, unmapped_named: i64, out: *u8, o0: i64, cap: i64) -> i64 { 241 if o0 + ACR_LINECAP >= cap { return 0 - 1 } 242 let n: i64 = bk[AL_B_N] 243 let a: i64 = al_count_accepted(bk, cf) 244 var o: i64 = acr_catfn(out, o0, "ACCEPT-LEDGER subjects=" as *u8, n) 245 o = acr_catfn(out, o, " agreed=" as *u8, a) 246 o = acr_catfn(out, o, " not_agreed=" as *u8, n - a) 247 o = acr_catfn(out, o, " planes=" as *u8, planes) 248 o = al_cat(out, o, "/3" as *u8) 249 o = acr_catfn(out, o, " acc_rows=" as *u8, bk[AL_B_ACC_ROWS]) 250 o = acr_catfn(out, o, " unmapped=" as *u8, bk[AL_B_UNMAPPED]) 251 o = acr_catfn(out, o, " unmapped_named=" as *u8, unmapped_named) 252 o = acr_catfn(out, o, " ref_rows=" as *u8, bk[AL_B_REF_ROWS]) 253 o = acr_catfn(out, o, " att_rows=" as *u8, bk[AL_B_ATT_ROWS]) 254 o = acr_catfn(out, o, " malformed=" as *u8, bk[AL_B_MALFORMED]) 255 o = acr_catfn(out, o, " badname=" as *u8, bk[AL_B_BADNAME]) 256 o = acr_catfn(out, o, " tombstones=" as *u8, bk[AL_B_TOMB]) 257 o = acr_catfn(out, o, " foreign_keys=" as *u8, bk[AL_B_FOREIGN]) 258 o = acr_catfn(out, o, " overflow=" as *u8, bk[AL_B_OVERFLOW]) 259 if bk[AL_B_OVERFLOW] > 0 { o = al_cat(out, o, " THIS-LIST-IS-A-PREFIX-book-full" as *u8) } 260 out[o] = AL_NL as u8 261 o = o + 1 262 out[o] = 0 as u8 263 return o 264} 265 266// ---- name order over the whole book (selection sort, same rule the emitter uses) -------------------------------- 267func acr_order(bk: *i64, ord: *i64) -> i64 { 268 let n: i64 = bk[AL_B_N] 269 var i: i64 = 0 270 while i < n { ord[i] = i; i = i + 1 } 271 var a: i64 = 0 272 while a < n { 273 var best: i64 = a 274 var b2: i64 = a + 1 275 while b2 < n { if al_strcmp(al_bk_name(bk, ord[b2]), al_bk_name(bk, ord[best])) < 0 { best = b2 } b2 = b2 + 1 } 276 if best != a { let t: i64 = ord[a]; ord[a] = ord[best]; ord[best] = t } 277 a = a + 1 278 } 279 return n 280} 281 282// ---- UNMAPPED rows, NAMED. pfx is the RESOLVED accept plane path. oo[0] is the in/out offset. Returns the count. 283func acr_unmapped(pfx: *u8, out: *u8, oo: *i64, cap: i64) -> i64 { 284 let scratch: *i64 = al_bk_new() 285 let cur: *i64 = al_rows_open(pfx) 286 if cur[AL_RS_LEN] <= 0 { return 0 } 287 let sc: *i64 = sys_mmap(8 * AL_SC_WORDS) as *i64 288 let f: *i64 = sys_mmap(ACR_LP) as *i64 289 let idx: *i64 = sys_mmap(8 * AL_MAX_TOK) as *i64 290 var o: i64 = oo[0] 291 var cnt: i64 = 0 292 while al_rows_next(cur, sc) == 1 { 293 let v: *u8 = sc[2] as *u8 294 let vl: i64 = sc[3] 295 if cw_field(v, vl, AL_AF_TARGETS, f) == 1 { 296 let nt: i64 = al_targets_subjects(scratch, v, f[0], f[1], idx, AL_MAX_TOK) 297 if nt == 0 { 298 cnt = cnt + 1 299 if o + vl + ACR_LINECAP < cap { 300 o = al_cat(out, o, "UNMAPPED id=" as *u8) 301 if cw_field(v, vl, AL_AF_ID, f) == 1 { o = al_catsl(out, o, v, f[0], f[1]) } 302 o = al_cat(out, o, " verdict=" as *u8) 303 if cw_field(v, vl, AL_AF_VERDICT, f) == 1 { o = al_catsl(out, o, v, f[0], f[1]) } 304 o = al_cat(out, o, " actor=" as *u8) 305 if cw_field(v, vl, AL_AF_ACTOR, f) == 1 { o = al_catsl(out, o, v, f[0], f[1]) } 306 o = al_cat(out, o, " targets=" as *u8) 307 if cw_field(v, vl, AL_AF_TARGETS, f) == 1 { o = al_catsl(out, o, v, f[0], f[1]) } 308 o = al_cat(out, o, " governs=NOTHING remedy=re-file the verdict with targets carrying ga_accept_<subject>" as *u8) 309 out[o] = AL_NL as u8 310 o = o + 1 311 } 312 } 313 } 314 } 315 out[o] = 0 as u8 316 oo[0] = o 317 return cnt 318} 319 320// ---- board subjects into the book; doms/orgs are per-BOOK-INDEX tables (AL_NAMEW / AL_ORGW wide, zeroed by the 321// caller). Returns the number of board rows, -1 when dir is unreadable, and over[0] counts rows past the cap. 322func acr_boards(bk: *i64, dir: *u8, doms: *u8, orgs: *u8, over: *i64) -> i64 { 323 let sj: *u8 = sys_mmap(AL_NAMEW * AL_MAX_WATCH) 324 let sd: *u8 = sys_mmap(AL_NAMEW * AL_MAX_WATCH) 325 let so: *u8 = sys_mmap(AL_ORGW * AL_MAX_WATCH) 326 let n: i64 = al_scan_boards(dir, sj, sd, so, AL_MAX_WATCH, over) 327 if n < 0 { return n } 328 var i: i64 = 0 329 while i < n { 330 let nm: *u8 = ((sj as i64) + i * AL_NAMEW) as *u8 331 let dm: *u8 = ((sd as i64) + i * AL_NAMEW) as *u8 332 let og: *u8 = ((so as i64) + i * AL_ORGW) as *u8 333 let si: i64 = al_bk_get(bk, nm, 0, al_slen(nm)) 334 if si >= 0 { 335 al_setf(doms, si * AL_NAMEW, AL_NAMEW, dm, 0, al_slen(dm)) 336 al_setf(orgs, si * AL_ORGW, AL_ORGW, og, 0, al_slen(og)) 337 } 338 i = i + 1 339 } 340 return n 341} 342 343// ---- the emitted file's shape ruler ---------------------------------------------------------------------------- 344// count of lines beginning with needle (column 0) 345func acr_lines_starting(b: *u8, n: i64, needle: *u8) -> i64 { 346 let nl: i64 = al_slen(needle) 347 var cnt: i64 = 0 348 var i: i64 = 0 349 while i + nl <= n { 350 var bol: i64 = 0 351 if i == 0 { bol = 1 } else { if (b[i - 1] as i64) == AL_NL { bol = 1 } } 352 if bol == 1 { 353 var m: i64 = 1 354 var j: i64 = 0 355 while j < nl { if b[i + j] != needle[j] { m = 0; j = nl } else { j = j + 1 } } 356 if m == 1 { cnt = cnt + 1 } 357 } 358 i = i + 1 359 } 360 return cnt 361} 362// does the buffer declare ga_accept_<subject> (column-0 func, exact identifier)? 363func acr_declares(b: *u8, n: i64, subject: *u8) -> i64 { 364 let needle: *u8 = sys_mmap(AL_KEYCAP) 365 var o: i64 = al_cat(needle, 0, ACR_FUNC_KW) 366 o = al_cat(needle, o, AL_SYM_PFX) 367 o = al_cat(needle, o, subject) 368 o = al_cat(needle, o, "(" as *u8) 369 needle[o] = 0 as u8 370 if acr_lines_starting(b, n, needle) > 0 { return 1 } 371 return 0 372} 373// -1 on the first line that is neither a comment, blank, nor the ONE permitted declaration form; else the count 374func acr_decl_shape(b: *u8, n: i64) -> i64 { 375 let kw: *u8 = ACR_FUNC_KW 376 let kl: i64 = al_slen(kw) 377 let pl: i64 = al_slen(AL_SYM_PFX) 378 let tl: i64 = al_slen(ACR_DECL_TAIL) 379 var cnt: i64 = 0 380 var p: i64 = 0 381 while p < n { 382 var e: i64 = p 383 while e < n { if (b[e] as i64) == AL_NL { break } e = e + 1 } 384 let len: i64 = e - p 385 if len > 0 { 386 var comment: i64 = 0 387 if len >= 2 { if (b[p] as i64) == AL_SLASH { if (b[p + 1] as i64) == AL_SLASH { comment = 1 } } } 388 if comment == 0 { 389 if len < kl + pl + 1 + tl { return 0 - 1 } 390 var j: i64 = 0 391 while j < kl { if b[p + j] != kw[j] { return 0 - 1 } j = j + 1 } 392 j = 0 393 while j < pl { if b[p + kl + j] != AL_SYM_PFX[j] { return 0 - 1 } j = j + 1 } 394 var k: i64 = p + kl + pl 395 let ks: i64 = k 396 while k < e { if al_ident_char(b[k] as i64) == 1 { k = k + 1 } else { break } } 397 if al_ident_ok(b, ks, k - ks) == 0 { return 0 - 1 } 398 if e - k != tl { return 0 - 1 } 399 j = 0 400 while j < tl { if b[k + j] != ACR_DECL_TAIL[j] { return 0 - 1 } j = j + 1 } 401 cnt = cnt + 1 402 } 403 } 404 p = e + 1 405 } 406 return cnt 407}