nx_mccabe_lib.nx
buildroot/runtime/nx_mccabe_lib.nx
about
nx_mccabe_lib.nx -- CYCLOMATIC COMPLEXITY FOR NISHILANG. Closes seq251.
WHY THIS EXISTS. nx_cwe_scan grades this estate against ISO/IEC 5055, and its own output has carried the
hole since the day it shipped: "iso5055_factors":{"covered_of_4":3,"gap":["Maintainability -- needs
cyclomatic/Halstead complexity, filed seq251"]}. The estate identified its own conformance gap, FILED it,
and then nobody built it. This is that build.
THE MAPPING, STATED SO NOBODY HAS TO GUESS IT. McCabe 1976 defines v(G) = e - n + 2p over the control-flow
graph of a single procedure with one entry and one exit; for one connected procedure (p=1) that reduces to
DECISION POINTS + 1, which is the form computed here. This TRANSFERS CLEANLY -- it needs a procedure with
branching, not classes, not inheritance, not packages. It is not a re-target and not an analogue.
Decision points counted, and this list IS the mapping: if, while, for, and each short-circuit operator
(&& and ||), each of which adds an independent path. `else` is NOT counted -- it is the other side of a
predicate already counted. `else if` IS counted, via its own `if`.
COMMENTS AND STRING LITERALS ARE SKIPPED, AND THAT IS THE WHOLE BALLGAME. Measured on this very corpus
before the organ existed: the first three `&&` occurrences found by a naive text search were all inside
COMMENTS, and one more was a lexer emitting the token as data. A SCANNER THAT DOES NOT SKIP COMMENTS
MEASURES THE DOCUMENTATION, NOT THE CODE -- the estate already paid for that law once (readOnly 15.5->32.5%).
NO CAP. The body is read with sys_read_file, which sizes its buffer from the file itself and cannot
short-read, so there is no truncation to declare and no guessed ceiling to tune.
NO THRESHOLD IS INVENTED HERE. The organ publishes the DISTRIBUTION and derives its own percentiles from
the CDF. The one bar it names -- 10 -- is CITED from McCabe 1976 and formalised in NIST SP 500-235, and is
reported as "above the cited limit", never as a pass or a fail. AN UNCALIBRATED CLASSIFIER MUST REPORT
NUMBERS, NEVER VERDICTS.
license_tier: ORIGINAL LIBRARY -- no main. nx_mccabe.nx and nx_mccabe_gate.nx both consume it, so the
census and its gate share ONE ruler by construction and cannot drift apart.
dependencies 2 imports · 7 importers
imports: nx_syscalls.nxnx_headmark_lib.nx
imported by: nx_claude_harvest.nxnx_claude_harvest_before_evidence_t45.nxnx_claude_harvest_evidence_t45.nxnx_claude_harvest_requests_t144.nxnx_claude_harvest_usage_t76.nxnx_mccabe.nxnx_mccabe_gate.nx
structs
| none |
consts
| 33 | const MC_DEF_DIR: *u8 = "buildroot/runtime\x00" |
| 34 | const MC_LIMIT: i64 = 10 // CITED: McCabe 1976 and NIST SP 500-235. NOT chosen here. |
| 35 | const MC_HIST_MAX: i64 = 512 // exact histogram buckets; anything above is counted in the overflow |
| 36 | const MC_WORKCAP: i64 = 1048576 |
| 37 | const MC_WORKFLUSH: i64 = 1046000 |
| 38 | const MC_PATHCAP: i64 = 4096 |
| 39 | const MC_DIRBUF: i64 = 131072 |
| 40 | const MC_MAXDEPTH: i64 = 8 |
| 41 | const MC_NAMECAP: i64 = 128 |
| 42 | const MC_DT_DIR: i64 = 4 |
| 43 | const MC_PERMILLE: i64 = 1000 |
| 46 | const MC_C_FUNCS: i64 = 0 |
| 47 | const MC_C_FILES: i64 = 1 |
| 48 | const MC_C_OVER: i64 = 2 // v(G) above MC_HIST_MAX (histogram overflow) |
| 49 | const MC_C_MAX: i64 = 3 |
| 50 | const MC_C_ABOVE: i64 = 4 // v(G) > MC_LIMIT |
| 51 | const MC_C_SUMVG: i64 = 5 |
| 52 | const MC_C_UNREAD: i64 = 6 // files that could not be read -- UNKNOWN, never counted as clean |
| 102 | const MC_CLS_MAX: i64 = 8 // table rows incl. row 0 (UNMARKED); conf rows land in 1..MC_CLS_MAX-1 |
| 103 | const MC_CLS_FIELDS: i64 = 4 |
| 104 | const MC_CF_FILES: i64 = 0 |
| 105 | const MC_CF_FUNCS: i64 = 1 |
| 106 | const MC_CF_SUMVG: i64 = 2 |
| 107 | const MC_CF_ABOVE: i64 = 3 |
| 108 | const MC_C_CLSN: i64 = 8 // conf rows loaded (0 = classification off) |
| 109 | const MC_C_CLSTAB: i64 = 9 // the table, a *u8 carried as i64: MC_CLS_MAX rows of MC_CLS_ROW bytes |
| 110 | const MC_C_CLSBASE: i64 = 16 // per-class blocks: c[MC_C_CLSBASE + cls*MC_CLS_FIELDS + field] |
| 111 | const MC_C_SLOTS: i64 = 64 |
| 112 | const MC_CLS_ROW: i64 = 160 // one row: name NUL marker NUL |
| 113 | const MC_CLS_NAMECAP: i64 = 31 |
| 114 | const MC_CLS_NULS: i64 = 2 // the two terminators a row carries |
| 115 | const MC_CLS_CONF: *u8 = "knowledge/headmark_classes.conf\x00" |
| 116 | const MC_CH_NL: i64 = 10 |
| 117 | const MC_CH_CR: i64 = 13 |
| 118 | const MC_CH_HASH: i64 = 35 |
| 119 | const MC_CH_BAR: i64 = 124 |
functions
| 54 | func mc_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } |
| 55 | func mc_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } |
| 56 | func mc_cat(o: *u8, at: i64, s: *u8) -> i64 { var i: i64=0; var a: i64=at; while s[i]!=(0 as u8){o[a]=s[i]; a=a+1; i=i+1} return a } |
| 57 | func mc_catn(o: *u8, at: i64, v: i64) -> i64 |
| 67 | func mc_is_ident(c: i64) -> i64 |
| 75 | func mc_kw(buf: *u8, i: i64, n: i64, kw: *u8) -> i64 |
| 84 | func mc_isdotdot(nm: *u8) -> i64 { if nm[0]==(46 as u8){ if nm[1]==(0 as u8){return 1} if nm[1]==(46 as u8){ if nm[2]==(0 as u8){return 1} } } return 0 } called by 1: mc_walk |
| 85 | func mc_join(buf: *u8, base_n: i64, name: *u8) -> i64 { buf[base_n]=47 as u8; var o: i64=base_n+1; var i: i64=0; while name[i]!=(0 as u8){buf[o]=name[i];o=o+1;i=i+1} return o } called by 1: mc_walk |
| 86 | func mc_ends_nx(p: *u8, n: i64) -> i64 |
| 121 | func mc_cls_name(c: *i64, k: i64) -> *u8 { return (c[MC_C_CLSTAB] + k*MC_CLS_ROW) as *u8 } |
| 122 | func mc_cls_marker(c: *i64, k: i64) -> *u8 { let nm: *u8 = mc_cls_name(c, k); return ((nm as i64) + mc_slen(nm) + 1) as *u8 } |
| 125 | func mc_cls_load_from(c: *i64, path: *u8) -> i64 |
| 170 | func mc_cls_load(c: *i64) -> i64 { return mc_cls_load_from(c, MC_CLS_CONF as *u8) } |
| 172 | func mc_headclass(buf: *u8, n: i64, c: *i64) -> i64 |
| 187 | func mc_scan_file(path: *u8, hist: *i64, c: *i64, work: *u8, wo: *i64) -> i64 |
| 312 | func mc_walk(p: *u8, pn: i64, depth: i64, hist: *i64, c: *i64, work: *u8, wo: *i64) -> i64 called by 2: mainmc_walk calls 12: sys_openat_rdsys_mmapsys_getdents64dirent_typedirent_namemc_isdotdot+6 |
| 343 | func mc_pct(hist: *i64, total: i64, over: i64, maxv: i64, permille: i64) -> i64 called by 1: main |