code wiki / _hdl_build / nx_magic_lib.nx
nx_magic_lib.nx source
↩ module page · 598 lines · 31098 B
1// nx_magic_lib.nx -- THE RULE-11 LITERAL SCANNER. Extracted out of nx_magic.nx on 2026-08-25 for two
2// reasons, and the second is the one that mattered.
3//
4// (1) IT COULD NEVER BE MUTATION-PROVEN WHERE IT WAS. mg_scan lived inside a program with main(), so the
5// only way to exercise it was to fork the deployed elf -- and every mutant of a fork/exec'd subject comes
6// back NOT-REACHED. The estate's most widely-consumed text scanner (it decides what /api/build calls a
7// rule-11 breach) had therefore never had a single tooth on it. In a lib it sits inside the gate's own
8// build closure and nx_gate_bite can kill mutants in it.
9//
10// (2) IT WAS BLIND TO HEXADECIMAL, AND THE BLINDNESS WAS DECLARED RATHER THAN FIXED. nx_magic's header
11// said "Decimal only -- hex is DECLARED out of envelope (nearly all hex here is < 1024)" and the map
12// envelope printed decimal_only:1, hex_out_of_envelope:1 on every call. A declaration does not make a
13// count mean what its name says. MEASURED 2026-08-25 on buildroot/runtime/_hdl_build/nx_activities_gate.nx
14// at floor 2: 41 sites / 26 distinct, one of which is the decimal literal 420 -- while the FOUR `0x1ed`
15// literals on lines 123/124/127/128 of the same file, which are THE SAME NUMBER, were not sites at all.
16// The mechanism was mechanical and total: at `0x1ed` the scanner read the digit run `0`, saw that the next
17// byte `x` is an identifier character, and discarded the whole token as identifier-digits. So the value it
18// would have carried was not merely mis-scaled, it was 0.
19// A file written entirely in 0x notation read as magic:0.
20// The estate had ALREADY banked the law -- "THE SAME CONSTANT IN TWO BASES IS TWO CONSTANTS TO EVERY
21// SCANNER", earned when a 39-site MODE_0644 sweep matched decimal 420 and missed a raw 0x1a4 -- and then
22// never taught the ruler the second base. A LAW BANKED IN PROSE AND ABSENT FROM THE INSTRUMENT IS A LAW
23// THE NEXT SWEEP WILL BREAK AGAIN.
24//
25// SCOPE OF THE FIX, STATED SO IT IS NOT OVERREAD: this closes the blind spot in nx_magic's scanner, which
26// produces the WORKLIST and the FLOOR VIEW. It does NOT change the number nx_magicratchet gates builds on:
27// that count comes from `nx_law_warden countfile` -> lw_line_lits, which is hex-blind by exactly the same
28// mechanism and is deliberately left alone here, because raising a count that already has 911 stored
29// baselines is the one edit that can refuse real builds estate-wide. Named, measured, not done blind.
30//
31// SKIPPED BY CONSTRUCTION (the false-positive controls, unchanged except where noted): whole-line comments,
32// TRAILING comments after code, const/static DECLARATION lines, bytes inside string literals, digits that
33// continue an identifier (x2048, and now also a hex body that runs into a letter), named-index table writes
34// `a[NAME] = literal`, any value below the threshold, and NEW: a hex literal too wide to represent exactly
35// (see MG_HEX_SAFE_DIGITS -- it is COUNTED and REPORTED, never silently dropped, and never recorded as a
36// site because a site authorises `nx_magic apply` to REWRITE THAT TEXT and a wrong value there is source
37// corruption). A HEURISTIC THAT GATES A DESTRUCTIVE ACTION MUST BE WRONG IN THE DIRECTION OF DOING NOTHING.
38//
39// 100% sovereign. No hardware writes (Rule 26). license_tier: ORIGINAL
40import "nx_syscalls.nx"
41
42const MG_CAP: i64 = 1048576
43const MG_NL: i64 = 10
44const MG_QU: i64 = 34
45const MG_BSL: i64 = 92
46const MG_SLASH: i64 = 47
47const MG_US: i64 = 95
48const MG_SP: i64 = 32
49const MG_TAB: i64 = 9
50const MG_LSQ: i64 = 91
51const MG_RSQ: i64 = 93
52const MG_EQ: i64 = 61
53const MG_MAXSITES: i64 = 4096
54const MG_MAXVALS: i64 = 256
55// The FLOOR view's bar. `threshold` is a GUESSED CEILING and the estate's rule-11 law is explicit
56// that a ceiling which must be guessed is a defect generator in BOTH directions -- raising it only
57// moves the guess. So this organ does not move it; it REPORTS WHAT THE BAR HIDES, at a floor low
58// enough that essentially nothing hides under it. 2, not 1 or 0, because 0/1 are structural (loop
59// bounds, flags, sign) and carry no policy.
60const MG_FLOOR: i64 = 2
61
62// ---- numeric-literal notation ----
63const MG_ZERO: i64 = 48
64const MG_NINE: i64 = 57
65const MG_LC_A: i64 = 97
66const MG_LC_F: i64 = 102
67const MG_LC_X: i64 = 120
68const MG_LC_Z: i64 = 122
69const MG_UC_A: i64 = 65
70const MG_UC_F: i64 = 70
71const MG_UC_X: i64 = 88
72const MG_UC_Z: i64 = 90
73const MG_BASE_DEC: i64 = 10
74const MG_BASE_HEX: i64 = 16
75const MG_HEXDIG_OFF: i64 = 10
76// DERIVED, NOT PICKED: the widest hex body whose value is exactly representable in the i64 this scanner
77// and every consumer of `value` use. 16 hex digits is 64 bits, which overflows a SIGNED i64; 15 hex digits
78// is 60 bits and cannot. A literal wider than this is counted in the oversize stat and REFUSED as a site,
79// because a site is a licence for `nx_magic apply` to replace that text with a const of the parsed value.
80const MG_HEX_SAFE_DIGITS: i64 = 15
81
82// ---- mg_scan's out-of-band stat channel (indices into the caller's sstat array) ----
83// These are COUNTS OF THINGS THAT DID NOT BECOME SITES, or that became sites in a second notation. They
84// are a separate array rather than extra return values because a count that has nowhere to go is a count
85// that gets dropped, and the whole reason this file exists is a number that was dropped at the next hop.
86const MG_STAT_HEX: i64 = 0
87const MG_STAT_HEX_OVERSIZE: i64 = 1
88const MG_STAT_N: i64 = 2
89const MG_I64_BYTES: i64 = 8
90
91func mg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
92func mg_is_ident(c: i64) -> i64 {
93 if c >= MG_ZERO { if c <= MG_NINE { return 1 } }
94 if c >= MG_UC_A { if c <= MG_UC_Z { return 1 } }
95 if c >= MG_LC_A { if c <= MG_LC_Z { return 1 } }
96 if c == MG_US { return 1 }
97 return 0
98}
99func mg_is_digit(c: i64) -> i64 { if c >= MG_ZERO { if c <= MG_NINE { return 1 } } return 0 }
100// A HEX DIGIT IS NOT AN IDENTIFIER CHARACTER MINUS SOME LETTERS -- it is 0-9 a-f A-F and nothing else.
101// Spelling it as its own predicate (rather than reusing mg_is_ident and subtracting) is what makes the
102// run terminate correctly at `g`..`z`, so `0x1edge` stays an identifier and never becomes the value 493.
103func mg_is_hexdigit(c: i64) -> i64 {
104 if c >= MG_ZERO { if c <= MG_NINE { return 1 } }
105 if c >= MG_LC_A { if c <= MG_LC_F { return 1 } }
106 if c >= MG_UC_A { if c <= MG_UC_F { return 1 } }
107 return 0
108}
109// -1 for a non-hex byte. The caller only ever asks after mg_is_hexdigit said yes, but the sentinel is
110// real rather than a silent 0: a 0 would be indistinguishable from the digit '0' and would parse garbage
111// into a value that `apply` then writes into somebody's source.
112func mg_hexval(c: i64) -> i64 {
113 if c >= MG_ZERO { if c <= MG_NINE { return c - MG_ZERO } }
114 if c >= MG_LC_A { if c <= MG_LC_F { return c - MG_LC_A + MG_HEXDIG_OFF } }
115 if c >= MG_UC_A { if c <= MG_UC_F { return c - MG_UC_A + MG_HEXDIG_OFF } }
116 return 0 - 1
117}
118// first non-space index of line [ls,le)
119func mg_first_ns(q: *u8, ls: i64, le: i64) -> i64 {
120 var i: i64 = ls
121 var go: i64 = 1
122 while go == 1 {
123 go = 0
124 if i < le { if q[i] == (MG_SP as u8) { i = i + 1; go = 1 } else { if q[i] == (MG_TAB as u8) { i = i + 1; go = 1 } } }
125 }
126 return i
127}
128// does line [ls,le) start (after indent) with the c-string lit?
129func mg_starts(q: *u8, ls: i64, le: i64, lit: *u8) -> i64 {
130 let s: i64 = mg_first_ns(q, ls, le)
131 let n: i64 = mg_slen(lit)
132 if s + n > le { return 0 }
133 var i: i64 = 0
134 while i < n { if q[s+i] != lit[i] { return 0 } i = i + 1 }
135 return 1
136}
137// a line we must NOT touch: comment, or a const/static DECLARATION (its literal is already named)
138func mg_skip_line(q: *u8, ls: i64, le: i64) -> i64 {
139 if mg_starts(q, ls, le, "//" as *u8) == 1 { return 1 }
140 if mg_starts(q, ls, le, "const " as *u8) == 1 { return 1 }
141 if mg_starts(q, ls, le, "static " as *u8) == 1 { return 1 }
142 return 0
143}
144func mg_read(path: *u8, b: *u8, cap: i64) -> i64 {
145 let fd: i64 = sys_openat_rd(path)
146 if fd < 0 { return 0 - 1 }
147 var n: i64 = 0
148 var go: i64 = 1
149 while go == 1 {
150 let r: i64 = sys_read(fd, (b as i64 + n) as *u8, cap - n)
151 if r > 0 { n = n + r } else { go = 0 }
152 if n >= cap { go = 0 }
153 }
154 sys_close(fd)
155 return n
156}
157
158// ONE DISTINCT-VALUE COUNTER FOR THE WHOLE RULE-11 LANE. It lives here because nx_magic and
159// nx_magicratchet both need it and two copies of a counting loop is how two organs come to disagree
160// about one population. Fills tbl (insertion-ordered) and returns the distinct count. A return equal to
161// cap means the table FILLED -- the caller must publish that as a floor, not as a total.
162func mg_distinct(sval: *i64, sites: i64, tbl: *i64, cap: i64) -> i64 {
163 var nd: i64 = 0
164 var i: i64 = 0
165 while i < sites {
166 var found: i64 = 0
167 var j: i64 = 0
168 while j < nd { if tbl[j] == sval[i] { found = 1; j = nd } else { j = j + 1 } }
169 if found == 0 { if nd < cap { tbl[nd] = sval[i]; nd = nd + 1 } }
170 i = i + 1
171 }
172 return nd
173}
174
175// THE SCANNER. Walks the file once and records every offending literal site into the parallel
176// arrays (line, col, len, value, base). Returns the site count. Honest about its own bound: stops at
177// MG_MAXSITES and the caller DECLARES truncation rather than silently under-reporting.
178// sbase carries 10 or 16 per site -- a consumer that prints a value without its notation reproduces
179// the very ambiguity this scanner was just taught to see through.
180// sstat must have at least MG_STAT_N words and is expected zero-filled (sys_mmap is).
181func mg_scan(q: *u8, n: i64, thr: i64, sline: *i64, scol: *i64, slen: *i64, sval: *i64, sls: *i64, sle: *i64, sbase: *i64, sstat: *i64) -> i64 {
182 var sites: i64 = 0
183 var lineno: i64 = 1
184 var i: i64 = 0
185 while i < n {
186 var le: i64 = i
187 var s: i64 = 1
188 while s == 1 { if le >= n { s = 0 } else { if q[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } }
189 if mg_skip_line(q, i, le) == 0 {
190 var instr: i64 = 0
191 var p: i64 = i
192 while p < le {
193 let c: i64 = q[p] as i64
194 // TRAILING COMMENTS (fixed 2026-08-14). This loop tracked STRINGS but never
195 // COMMENTS, and mg_skip_line only excludes a WHOLE comment line -- so a `//`
196 // comment sitting after CODE was scanned as code. The header above has promised
197 // "comment lines" were skipped since day one, and that word `lines` was the bug.
198 // MEASURED: nx_skullsdf line 20 is
199 // import "nx_memfloor.nx" // ... (2026-07-30 incident)
200 // and map reported the DATE 2026 as a site at col 86, while nx_law_warden
201 // countfile -- which the ratchet's COUNT uses -- correctly returned 0. The two
202 // instruments disagreeing by exactly one is what located this.
203 // Setting p = le is sufficient and needs no restructuring: c is '/', so the
204 // chain below falls through to its final `p = p + 1`, making p = le + 1 and
205 // ending the loop without recording a site.
206 if instr == 0 { if c == MG_SLASH { if p + 1 < le { if q[p+1] == (MG_SLASH as u8) { p = le } } } }
207 if instr == 1 {
208 if c == MG_BSL { p = p + 1 } else { if c == MG_QU { instr = 0 } }
209 p = p + 1
210 } else {
211 if c == MG_QU { instr = 1; p = p + 1 } else {
212 if mg_is_digit(c) == 1 {
213 // a digit run only counts if it does NOT continue an identifier
214 var prev_ident: i64 = 0
215 if p > i { if mg_is_ident(q[p-1] as i64) == 1 { prev_ident = 1 } }
216 // NAMED-INDEX TABLE WRITE (2026-08-14). `P[P_OR]=8` is NOT a magic number:
217 // the INDEX IS THE NAME and the array IS the data, which is what rule 11
218 // asks for. MEASURED: 106 of nx_skullsdf's 942 sites are `ss_defaults`,
219 // whose own header reads "FITTED, NOT TYPED -- the output of `tune`,
220 // coordinate descent that took mean surface error 8.37mm -> 5.06mm against
221 // a 171k-triangle scan". Counting them inflated the population AND aimed a
222 // drain at the most dangerous class in the organ: a conf migration there
223 // would have moved a tuner's output away from its tuner. Some are not even
224 // typed (`P[P_UY]=P[P_MY]-24`, derived from the parent bone).
225 // Skip only the exact shape `<ident>[<non-numeric-index>] = <literal>`;
226 // a numeric index (`buf[0]=4096`) still counts, so a real buffer constant
227 // is not lost.
228 var tbl: i64 = 0
229 var w: i64 = p - 1
230 var ws: i64 = 1
231 while ws == 1 { ws = 0; if w > i { if q[w] == (MG_SP as u8) { w = w - 1; ws = 1 } } }
232 if w > i { if q[w] == (MG_EQ as u8) {
233 var w2: i64 = w - 1
234 var ws2: i64 = 1
235 while ws2 == 1 { ws2 = 0; if w2 > i { if q[w2] == (MG_SP as u8) { w2 = w2 - 1; ws2 = 1 } } }
236 if w2 > i { if q[w2] == (MG_RSQ as u8) {
237 var w3: i64 = w2 - 1
238 var idn: i64 = 0
239 var g3: i64 = 1
240 while g3 == 1 { g3 = 0
241 if w3 > i { if q[w3] != (MG_LSQ as u8) {
242 if mg_is_digit(q[w3] as i64) == 0 { idn = 1 }
243 w3 = w3 - 1
244 g3 = 1
245 } }
246 }
247 if idn == 1 { tbl = 1 }
248 } }
249 } }
250 // ---- BASE DETECTION (2026-08-25). See the header: this is the half that
251 // was declared out of envelope for a year and reported as a count anyway.
252 // `0x` or `0X` followed by AT LEAST ONE hex digit is a hex literal. The
253 // "at least one" matters: a bare `0x` with nothing after it is not a
254 // number in any dialect, and treating it as one would invent a value of 0.
255 var base: i64 = MG_BASE_DEC
256 var e: i64 = p
257 var v: i64 = 0
258 var oversize: i64 = 0
259 if c == MG_ZERO { if p + 2 < le {
260 if q[p+1] == (MG_LC_X as u8) { if mg_is_hexdigit(q[p+2] as i64) == 1 { base = MG_BASE_HEX } }
261 if q[p+1] == (MG_UC_X as u8) { if mg_is_hexdigit(q[p+2] as i64) == 1 { base = MG_BASE_HEX } }
262 } }
263 if base == MG_BASE_HEX {
264 let hs: i64 = p + 2
265 e = hs
266 var gh: i64 = 1
267 while gh == 1 { gh = 0; if e < le { if mg_is_hexdigit(q[e] as i64) == 1 { e = e + 1; gh = 1 } } }
268 if e - hs > MG_HEX_SAFE_DIGITS { oversize = 1 }
269 if oversize == 0 {
270 var kh: i64 = hs
271 while kh < e { v = v * MG_BASE_HEX + mg_hexval(q[kh] as i64); kh = kh + 1 }
272 }
273 } else {
274 var g2: i64 = 1
275 while g2 == 1 { g2 = 0; if e < le { if mg_is_digit(q[e] as i64) == 1 { e = e + 1; g2 = 1 } } }
276 var kd: i64 = p
277 while kd < e { v = v * MG_BASE_DEC + ((q[kd] as i64) - MG_ZERO); kd = kd + 1 }
278 }
279 var trail_ident: i64 = 0
280 if e < le { if mg_is_ident(q[e] as i64) == 1 { trail_ident = 1 } }
281 if prev_ident == 0 { if trail_ident == 0 { if tbl == 0 {
282 if oversize == 1 {
283 // NOT a site, and NOT invisible either. `apply` rewrites site text,
284 // so a value we cannot represent exactly must never authorise an
285 // edit -- but a silent drop would recreate the blind spot this
286 // whole change exists to close, one notation deeper.
287 sstat[MG_STAT_HEX_OVERSIZE] = sstat[MG_STAT_HEX_OVERSIZE] + 1
288 } else {
289 if v >= thr { if sites < MG_MAXSITES {
290 sline[sites] = lineno
291 scol[sites] = p - i
292 slen[sites] = e - p
293 sval[sites] = v
294 sls[sites] = i
295 sle[sites] = le
296 sbase[sites] = base
297 if base == MG_BASE_HEX { sstat[MG_STAT_HEX] = sstat[MG_STAT_HEX] + 1 }
298 sites = sites + 1
299 } }
300 }
301 } } }
302 p = e
303 } else { p = p + 1 }
304 }
305 }
306 }
307 }
308 lineno = lineno + 1
309 i = le + 1
310 }
311 return sites
312}
313
314// ---- PURPOSE NAMES (rule 11, 2026-09-05): the table that turns <PFX>_MAGIC_<v> into a name that says WHY ----
315// knowledge/magic_names.conf rows: value|needle|name|why. A row CLAIMS a site when the literal equals value and the
316// needle (a literal substring, or * for any) occurs in the site's context window -- the same line-centred window
317// `map` prints, so what a reader can SEE is exactly what decided the name. Rows are tried in file order and the first
318// match wins (put the specific needle above the general one). A site no row claims keeps the mechanical name, and
319// every verb says which is which, so a guessed meaning can never wear a domain term. The organ prefix is prepended
320// by the caller (<PFX>_<name>), so two organs naming the same byte never share one symbol. One value with two
321// meanings (8 as bytes-per-i64 beside 8 as bits-per-byte) becomes TWO consts when two rows discriminate by needle --
322// which is why the name is resolved per SITE and the consts are deduped by NAME, never by value.
323const MG_NAMES_CONF: *u8 = "knowledge/magic_names.conf"
324const MG_NAMES_MAX: i64 = 512
325const MG_NAMES_FIELD: i64 = 96 // a needle or a name; the why column is read and not stored
326const MG_NAMES_COL_VALUE: i64 = 0
327const MG_NAMES_COL_NEEDLE: i64 = 1
328const MG_NAMES_COL_NAME: i64 = 2
329const MG_NAME_W: i64 = 256 // one resolved name: prefix, underscore, name -- or the mechanical form
330const MG_NAME_ANY: i64 = 42 // the * needle: any context
331const MG_PIPE: i64 = 124
332const MG_HASH: i64 = 35 // a comment row in the conf
333const MG_CR: i64 = 13 // a CRLF conf reads the same as an LF one
334const MG_CTX: i64 = 60 // the context window `map` prints and the resolver reads
335// How much of the window sits BEFORE the site. The operator that gives a literal its meaning is almost always
336// immediately to its left (`/100` is a unit, ` 100` is a clamp or a coordinate), so the lead only has to carry the
337// enclosing expression, not the whole line.
338const MG_CTX_LEAD: i64 = 24
339static mg_nm_val: *i64
340static mg_nm_needle: *i64
341static mg_nm_name: *i64
342static mg_nm_arena: *u8
343static mg_nm_n: i64
344static mg_nm_src: i64 // 0 = conf absent or empty (mechanical names only), 1 = conf read
345
346// non-negative decimal in a field (the scanner records literals, never signs); stops at the first non-digit
347func mg_nm_int(s: *u8) -> i64 {
348 var i: i64 = 0
349 var v: i64 = 0
350 while mg_is_digit(s[i] as i64) == 1 { v = v * MG_BASE_DEC + ((s[i] as i64) - MG_ZERO); i = i + 1 }
351 return v
352}
353// pipe field idx of the row [s,e) into out (CR stripped); its length
354func mg_nm_field(b: *u8, s: i64, e: i64, idx: i64, out: *u8, cap: i64) -> i64 {
355 var p: i64 = s
356 var f: i64 = 0
357 var k: i64 = 0
358 while p < e {
359 let c: i64 = b[p] as i64
360 if c == MG_PIPE { f = f + 1; if f > idx { p = e } } else {
361 if f == idx { if c != MG_CR { if k < cap - 1 { out[k] = c as u8; k = k + 1 } } }
362 }
363 p = p + 1
364 }
365 out[k] = 0 as u8
366 return k
367}
368func mg_names_load(path: *u8) -> i64 {
369 mg_nm_val = sys_mmap(MG_NAMES_MAX * MG_I64_BYTES) as *i64
370 mg_nm_needle = sys_mmap(MG_NAMES_MAX * MG_I64_BYTES) as *i64
371 mg_nm_name = sys_mmap(MG_NAMES_MAX * MG_I64_BYTES) as *i64
372 mg_nm_arena = sys_mmap(MG_NAMES_MAX * MG_NAMES_FIELD * 2)
373 mg_nm_n = 0
374 mg_nm_src = 0
375 let b: *u8 = sys_mmap(MG_CAP)
376 let n: i64 = mg_read(path, b, MG_CAP - 1)
377 if n <= 0 { return 0 - 1 }
378 mg_nm_src = 1
379 let fld: *u8 = sys_mmap(MG_NAMES_FIELD)
380 var ao: i64 = 0
381 var i: i64 = 0
382 while i < n {
383 var le: i64 = i
384 var s: i64 = 1
385 while s == 1 { if le >= n { s = 0 } else { if b[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } }
386 if le > i { if b[i] != (MG_HASH as u8) { if mg_nm_n < MG_NAMES_MAX {
387 let vl: i64 = mg_nm_field(b, i, le, MG_NAMES_COL_VALUE, fld, MG_NAMES_FIELD)
388 let nl: i64 = mg_nm_field(b, i, le, MG_NAMES_COL_NEEDLE, (mg_nm_arena as i64 + ao) as *u8, MG_NAMES_FIELD)
389 let ml: i64 = mg_nm_field(b, i, le, MG_NAMES_COL_NAME, (mg_nm_arena as i64 + ao + MG_NAMES_FIELD) as *u8, MG_NAMES_FIELD)
390 if vl > 0 { if nl > 0 { if ml > 0 {
391 mg_nm_val[mg_nm_n] = mg_nm_int(fld)
392 mg_nm_needle[mg_nm_n] = ao
393 mg_nm_name[mg_nm_n] = ao + MG_NAMES_FIELD
394 ao = ao + MG_NAMES_FIELD * 2
395 mg_nm_n = mg_nm_n + 1
396 } } }
397 } } }
398 i = le + 1
399 }
400 return mg_nm_n
401}
402func mg_names_src() -> i64 { return mg_nm_src }
403func mg_names_count() -> i64 { return mg_nm_n }
404func mg_nm_name_at(row: i64) -> *u8 { return (mg_nm_arena as i64 + mg_nm_name[row]) as *u8 }
405func mg_nm_needle_at(row: i64) -> *u8 { return (mg_nm_arena as i64 + mg_nm_needle[row]) as *u8 }
406// the window `map` prints for a site: the whole line when it fits, else MG_CTX bytes centred on the site
407func mg_ctx_window(ls: i64, le: i64, col: i64, csp: *i64, cep: *i64) -> i64 {
408 var cs: i64 = ls
409 var ce: i64 = le
410 if ce - cs > MG_CTX {
411 if col > MG_CTX_LEAD { cs = ls + col - MG_CTX_LEAD }
412 ce = cs + MG_CTX
413 if ce > le { ce = le }
414 }
415 csp[0] = cs
416 cep[0] = ce
417 return 0
418}
419// literal substring inside [cs,ce); an empty needle claims nothing
420func mg_ctx_has(q: *u8, cs: i64, ce: i64, needle: *u8) -> i64 {
421 let nl: i64 = mg_slen(needle)
422 if nl == 0 { return 0 }
423 var i: i64 = cs
424 while i + nl <= ce {
425 var k: i64 = 0
426 var ok: i64 = 1
427 while k < nl { if q[i + k] != needle[k] { ok = 0; k = nl } else { k = k + 1 } }
428 if ok == 1 { return 1 }
429 i = i + 1
430 }
431 return 0
432}
433// the first row that claims (value, window); -1 when none does (the caller then uses the mechanical name)
434func mg_name_lookup(v: i64, q: *u8, cs: i64, ce: i64) -> i64 {
435 var r: i64 = 0
436 while r < mg_nm_n {
437 if mg_nm_val[r] == v {
438 let nd: *u8 = mg_nm_needle_at(r)
439 if (nd[0] as i64) == MG_NAME_ANY { if (nd[1] as i64) == 0 { return r } }
440 if mg_ctx_has(q, cs, ce, nd) == 1 { return r }
441 }
442 r = r + 1
443 }
444 return 0 - 1
445}
446
447// ---- KIND AND DERIVATION (operator standing order 2026-09-17) -----------------------------------------------------------
448// "from the first byte up we should have derived numbers that are intelligent based on resource, not literals replaced
449// with constants ... that should be estate wide and how the magic number ratchet works with you and everything else."
450// A literal hoisted into a named const is a RENAME: a person still typed the number. What a number IS decides where it
451// should COME FROM, and that is DATA (knowledge/magic_kinds.conf): unit rows name the values a constant is right for,
452// kind rows class a site by the company the literal keeps on its line, derive rows say where a number of that kind comes
453// from. A gate source is FIXTURE before any needle is tried; a site no row claims is UNKNOWN and says so.
454const MG_KIND_CONF: *u8 = "knowledge/magic_kinds.conf"
455const MG_KROW_UNIT: *u8 = "unit"
456const MG_KROW_KIND: *u8 = "kind"
457const MG_KROW_DERIVE: *u8 = "derive"
458const MG_KIND_UNIT: *u8 = "UNIT"
459const MG_KIND_FIXTURE: *u8 = "FIXTURE"
460const MG_KIND_UNKNOWN: *u8 = "UNKNOWN"
461const MG_GATE_SFX: *u8 = "_gate.nx"
462const MG_PLACEHOLDER: *u8 = "_MAGIC_"
463const MG_CONST_KW: *u8 = "const "
464const MG_KCOL_TAG: i64 = 0
465const MG_KCOL_KEY: i64 = 1
466const MG_KCOL_VAL: i64 = 2
467const MG_KD_COLON: i64 = 58
468static mg_kd_buf: *u8
469static mg_kd_n: i64
470
471// the kinds table, read WHOLE (sys_read_file sizes from the file); returns its bytes, 0 when absent
472func mg_kinds_load(path: *u8) -> i64 {
473 let lenp: *i64 = sys_mmap(MG_I64_BYTES) as *i64
474 lenp[0] = 0
475 mg_kd_buf = sys_read_file(path, lenp)
476 mg_kd_n = lenp[0]
477 if mg_kd_n < 0 { mg_kd_n = 0 }
478 return mg_kd_n
479}
480// no sentence of the table is longer than the table: a caller sizes its derive buffer from this, never from a guess
481func mg_kinds_bytes() -> i64 { return mg_kd_n }
482
483func mg_line_end(b: *u8, n: i64, i: i64) -> i64 {
484 var le: i64 = i
485 var s: i64 = 1
486 while s == 1 { if le >= n { s = 0 } else { if b[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } }
487 return le
488}
489func mg_str_eq(a: *u8, b: *u8) -> i64 {
490 var i: i64 = 0
491 var s: i64 = 1
492 while s == 1 { if a[i] != b[i] { return 0 } if a[i] == (0 as u8) { s = 0 } else { i = i + 1 } }
493 return 1
494}
495func mg_copy(dst: *u8, src: *u8, cap: i64) -> i64 {
496 var k: i64 = 0
497 while src[k] != (0 as u8) { if k < cap - 1 { dst[k] = src[k] } k = k + 1 }
498 if k > cap - 1 { k = cap - 1 }
499 dst[k] = 0 as u8
500 return k
501}
502func mg_ends(s: *u8, sfx: *u8) -> i64 {
503 let sl: i64 = mg_slen(s)
504 let xl: i64 = mg_slen(sfx)
505 if xl > sl { return 0 }
506 var k: i64 = 0
507 while k < xl { if s[sl - xl + k] != sfx[k] { return 0 } k = k + 1 }
508 return 1
509}
510
511// the KIND of a site, the word into out; returns its length. path is the source file, v the literal's value, [cs,ce) the
512// site's context window (the same window nx_magic map prints).
513func mg_kind_of(path: *u8, v: i64, q: *u8, cs: i64, ce: i64, out: *u8, cap: i64) -> i64 {
514 if mg_ends(path, MG_GATE_SFX) == 1 { return mg_copy(out, MG_KIND_FIXTURE, cap) }
515 let tag: *u8 = sys_mmap(MG_NAMES_FIELD)
516 let key: *u8 = sys_mmap(MG_NAMES_FIELD)
517 // a value the table names as a unit is a unit wherever it stands
518 var i: i64 = 0
519 while i < mg_kd_n {
520 let le: i64 = mg_line_end(mg_kd_buf, mg_kd_n, i)
521 if le > i { if mg_kd_buf[i] != (MG_HASH as u8) {
522 mg_nm_field(mg_kd_buf, i, le, MG_KCOL_TAG, tag, MG_NAMES_FIELD)
523 if mg_str_eq(tag, MG_KROW_UNIT) == 1 {
524 let kl: i64 = mg_nm_field(mg_kd_buf, i, le, MG_KCOL_KEY, key, MG_NAMES_FIELD)
525 if kl > 0 { if mg_nm_int(key) == v { return mg_copy(out, MG_KIND_UNIT, cap) } }
526 }
527 } }
528 i = le + 1
529 }
530 // then the company it keeps: the first needle found in the window wins
531 i = 0
532 while i < mg_kd_n {
533 let le2: i64 = mg_line_end(mg_kd_buf, mg_kd_n, i)
534 if le2 > i { if mg_kd_buf[i] != (MG_HASH as u8) {
535 mg_nm_field(mg_kd_buf, i, le2, MG_KCOL_TAG, tag, MG_NAMES_FIELD)
536 if mg_str_eq(tag, MG_KROW_KIND) == 1 {
537 mg_nm_field(mg_kd_buf, i, le2, MG_KCOL_KEY, key, MG_NAMES_FIELD)
538 if mg_ctx_has(q, cs, ce, key) == 1 { return mg_nm_field(mg_kd_buf, i, le2, MG_KCOL_VAL, out, cap) }
539 }
540 } }
541 i = le2 + 1
542 }
543 return mg_copy(out, MG_KIND_UNKNOWN, cap)
544}
545
546// where a number of that kind comes from: the sentence into out (size it from mg_kinds_bytes() + 1); 0 when no row says
547func mg_kind_derive(kind: *u8, out: *u8, cap: i64) -> i64 {
548 let tag: *u8 = sys_mmap(MG_NAMES_FIELD)
549 let key: *u8 = sys_mmap(MG_NAMES_FIELD)
550 var i: i64 = 0
551 while i < mg_kd_n {
552 let le: i64 = mg_line_end(mg_kd_buf, mg_kd_n, i)
553 if le > i { if mg_kd_buf[i] != (MG_HASH as u8) {
554 mg_nm_field(mg_kd_buf, i, le, MG_KCOL_TAG, tag, MG_NAMES_FIELD)
555 if mg_str_eq(tag, MG_KROW_DERIVE) == 1 {
556 mg_nm_field(mg_kd_buf, i, le, MG_KCOL_KEY, key, MG_NAMES_FIELD)
557 if mg_str_eq(key, kind) == 1 { return mg_nm_field(mg_kd_buf, i, le, MG_KCOL_VAL, out, cap) }
558 }
559 } }
560 i = le + 1
561 }
562 out[0] = 0 as u8
563 return 0
564}
565
566// the kinds a report has SEEN, as NUL-separated words in seen[0..so): add w when it is not there yet; returns the new fill.
567// Size seen from mg_kinds_bytes() plus one name width: every kind word comes from the table (or is one of the three built in).
568func mg_seen_add(seen: *u8, so: i64, w: *u8) -> i64 {
569 var p: i64 = 0
570 while p < so {
571 if mg_str_eq((seen as i64 + p) as *u8, w) == 1 { return so }
572 p = p + mg_slen((seen as i64 + p) as *u8) + 1
573 }
574 var k: i64 = 0
575 while w[k] != (0 as u8) { seen[so + k] = w[k]; k = k + 1 }
576 seen[so + k] = 0 as u8
577 return so + k + 1
578}
579
580// a DECLARATION whose NAME carries the mechanical placeholder: const <PFX>_MAGIC_<digits>. It is a literal wearing a name.
581// The name ends at the first colon, so a placeholder mentioned in a trailing comment is prose and is not counted.
582func mg_placeholder_decl(q: *u8, ls: i64, le: i64) -> i64 {
583 if mg_starts(q, ls, le, MG_CONST_KW) == 0 { return 0 }
584 var c: i64 = ls
585 var go: i64 = 1
586 while go == 1 { if c >= le { go = 0 } else { if (q[c] as i64) == MG_KD_COLON { go = 0 } else { c = c + 1 } } }
587 return mg_ctx_has(q, ls, c, MG_PLACEHOLDER)
588}
589func mg_placeholder_count(q: *u8, n: i64) -> i64 {
590 var k: i64 = 0
591 var i: i64 = 0
592 while i < n {
593 let le: i64 = mg_line_end(q, n, i)
594 k = k + mg_placeholder_decl(q, i, le)
595 i = le + 1
596 }
597 return k
598}