nx_mccabe.nx source
↩ module page · 170 lines · 9922 B
1// nx_mccabe.nx -- THIN MAIN over nx_mccabe_lib.nx. Publishes the DISTRIBUTION of cyclomatic complexity
2// across the corpus; the only bar it names is CITED, never chosen here.
3// nx_mccabe [dir] default dir=buildroot/runtime
4// license_tier: ORIGINAL expect_exit: 0
5import "nx_mccabe_lib.nx"
6
7const MCM_EXACT_TO: i64 = 15 // exact buckets up to here, then DOUBLING ranges -- a derivation, not a taste
8const MCM_OUTBUF: i64 = 16384
9// CE1 (codeeffectiveness): one row per run on a time spine -- a level cannot express a trajectory, two rows can
10const MCM_SPINE: *u8 = "knowledge/status/mccabe.spine\x00"
11const MCM_MODE644: i64 = 420
12const MCM_SPINEBUF: i64 = 2048
13
14func mcm_range(ob: *u8, a0: i64, hist: *i64, lo: i64, hi: i64, total: i64) -> i64 {
15 var a: i64=a0
16 var s: i64=0
17 var v: i64=lo
18 while v<=hi { if v<MC_HIST_MAX { s=s+hist[v] } v=v+1 }
19 if s==0 { return a }
20 a=mc_cat(ob, a, " vG " as *u8)
21 a=mc_catn(ob, a, lo)
22 if hi>lo { a=mc_cat(ob, a, "-" as *u8); a=mc_catn(ob, a, hi) }
23 a=mc_cat(ob, a, " n=" as *u8); a=mc_catn(ob, a, s)
24 if total>0 { a=mc_cat(ob, a, " permille=" as *u8); a=mc_catn(ob, a, (s*MC_PERMILLE)/total) }
25 a=mc_cat(ob, a, "\n" as *u8)
26 return a
27}
28
29// ce_mccabe_live -- the LIVE census's own trajectory row (codeeffectiveness CE5: the keystone is not merely present in
30// source, it RUNS on the serving tree and writes its spine). Appends one row to MCM_SPINE for the production subject and
31// announces fd= wrote= of= into the report, so a row that failed to write is visible in the run that failed to write it.
32// Named for the watch that measures it; the name is the writer, not a badge.
33func ce_mccabe_live(c: *i64, funcs: i64, crows: i64, ob: *u8, a0: i64) -> i64 {
34 var a: i64=a0
35 let sfd: i64=sys_openat_append(MCM_SPINE as *u8, MCM_MODE644)
36 let sb: *u8=sys_mmap(MCM_SPINEBUF)
37 var s: i64=0
38 s=mc_catn(sb, s, sys_now_realtime_sec())
39 s=mc_cat(sb, s, "|files=" as *u8); s=mc_catn(sb, s, c[MC_C_FILES])
40 s=mc_cat(sb, s, "|funcs=" as *u8); s=mc_catn(sb, s, funcs)
41 s=mc_cat(sb, s, "|above_10=" as *u8); s=mc_catn(sb, s, c[MC_C_ABOVE])
42 if funcs>0 { s=mc_cat(sb, s, "|permille=" as *u8); s=mc_catn(sb, s, (c[MC_C_ABOVE]*MC_PERMILLE)/funcs) }
43 s=mc_cat(sb, s, "|classes=" as *u8); s=mc_catn(sb, s, crows)
44 var sk: i64=0
45 while sk<=crows {
46 let sbk: i64=MC_C_CLSBASE+sk*MC_CLS_FIELDS
47 s=mc_cat(sb, s, "|" as *u8); s=mc_cat(sb, s, mc_cls_name(c, sk))
48 s=mc_cat(sb, s, ":" as *u8); s=mc_catn(sb, s, c[sbk+MC_CF_FILES])
49 s=mc_cat(sb, s, ":" as *u8); s=mc_catn(sb, s, c[sbk+MC_CF_FUNCS])
50 s=mc_cat(sb, s, ":" as *u8); s=mc_catn(sb, s, c[sbk+MC_CF_ABOVE])
51 sk=sk+1
52 }
53 s=mc_cat(sb, s, "\n" as *u8)
54 var swrote: i64=0-1
55 if sfd>=0 { swrote=sys_write(sfd, sb, s); sys_close(sfd) }
56 a=mc_cat(ob, a, " spine=" as *u8); a=mc_cat(ob, a, MCM_SPINE as *u8); a=mc_cat(ob, a, " fd=" as *u8); a=mc_catn(ob, a, sfd); a=mc_cat(ob, a, " wrote=" as *u8); a=mc_catn(ob, a, swrote); a=mc_cat(ob, a, " of=" as *u8); a=mc_catn(ob, a, s); a=mc_cat(ob, a, "\n" as *u8)
57 return a
58}
59
60func main(argc: i64, argv: *i64) -> i64 {
61 var dir: *u8 = MC_DEF_DIR as *u8
62 if argc>=2 { dir = argv[1] as *u8 }
63 let hist: *i64=sys_mmap(MC_HIST_MAX*8+64) as *i64
64 var z: i64=0
65 while z<MC_HIST_MAX { hist[z]=0; z=z+1 }
66 let c: *i64=sys_mmap(MC_C_SLOTS*8) as *i64
67 var y: i64=0
68 while y<MC_C_SLOTS { c[y]=0; y=y+1 }
69 // CE1: the head-marker class table is DATA; an absent conf reads 0 rows and the census SAYS so below
70 let crows: i64=mc_cls_load(c)
71 let work: *u8=sys_mmap(MC_WORKCAP)
72 let wo: *i64=sys_mmap(16) as *i64
73 wo[0]=0
74 let pbuf: *u8=sys_mmap(MC_PATHCAP)
75 var dn: i64=0
76 while dir[dn]!=(0 as u8) { pbuf[dn]=dir[dn]; dn=dn+1 }
77
78 mc_w("=== NX-MCCABE -- cyclomatic complexity v(G) per function. Closes the ISO-5055 Maintainability gap (seq251). ===\n" as *u8)
79 mc_w(" subject dir: " as *u8); mc_w(dir); mc_w("\n" as *u8)
80 mc_walk(pbuf, dn, 0, hist, c, work, wo)
81
82 let funcs: i64=c[MC_C_FUNCS]
83 mc_w("\n-- WORKLIST: every function above the CITED limit of 10 (McCabe 1976, NIST SP 500-235) --\n" as *u8)
84 if wo[0]==0 { mc_w(" (none)\n" as *u8) } else { work[wo[0]]=0 as u8; mc_w(work) }
85 if wo[0]>=MC_WORKFLUSH { mc_w(" <== THIS LIST IS A PREFIX OF ITS OWN COUNT (worklist buffer filled)\n" as *u8) }
86
87 let ob: *u8=sys_mmap(MCM_OUTBUF)
88 var a: i64=0
89 a=mc_cat(ob, a, "\n-- DISTRIBUTION (published BEFORE any bar, because a bar picked before the shape is a guess) --\n" as *u8)
90 var v: i64=1
91 while v<=MCM_EXACT_TO { a=mcm_range(ob, a, hist, v, v, funcs); v=v+1 }
92 var lo: i64=MCM_EXACT_TO+1
93 while lo<MC_HIST_MAX {
94 var hi: i64=lo*2-1
95 if hi>=MC_HIST_MAX { hi=MC_HIST_MAX-1 }
96 a=mcm_range(ob, a, hist, lo, hi, funcs)
97 lo=hi+1
98 }
99 if c[MC_C_OVER]>0 {
100 a=mc_cat(ob, a, " vG >=" as *u8); a=mc_catn(ob, a, MC_HIST_MAX)
101 a=mc_cat(ob, a, " n=" as *u8); a=mc_catn(ob, a, c[MC_C_OVER])
102 a=mc_cat(ob, a, " (histogram overflow -- counted, never dropped)\n" as *u8)
103 }
104 a=mc_cat(ob, a, "\n-- DERIVED FROM THE CDF, not chosen --\n p50=" as *u8)
105 a=mc_catn(ob, a, mc_pct(hist, funcs, c[MC_C_OVER], c[MC_C_MAX], 500))
106 a=mc_cat(ob, a, " p90=" as *u8); a=mc_catn(ob, a, mc_pct(hist, funcs, c[MC_C_OVER], c[MC_C_MAX], 900))
107 a=mc_cat(ob, a, " p99=" as *u8); a=mc_catn(ob, a, mc_pct(hist, funcs, c[MC_C_OVER], c[MC_C_MAX], 990))
108 a=mc_cat(ob, a, " max=" as *u8); a=mc_catn(ob, a, c[MC_C_MAX])
109 if funcs>0 { a=mc_cat(ob, a, " mean=" as *u8); a=mc_catn(ob, a, c[MC_C_SUMVG]/funcs) }
110 a=mc_cat(ob, a, "\n\n-- AGAINST THE CITED BAR (the number comes from the standard, not from us) --\n above_10=" as *u8)
111 a=mc_catn(ob, a, c[MC_C_ABOVE])
112 if funcs>0 { a=mc_cat(ob, a, " permille=" as *u8); a=mc_catn(ob, a, (c[MC_C_ABOVE]*MC_PERMILLE)/funcs) }
113 a=mc_cat(ob, a, "\n McCabe 1976 calls 10 a reasonable upper limit and explicitly not a magic number, and NIST SP\n" as *u8)
114 a=mc_cat(ob, a, " 500-235 formalises it while permitting a documented exception for multiway decisions. This organ\n" as *u8)
115 a=mc_cat(ob, a, " therefore REPORTS the count above that bar and does NOT pass or fail anything on it.\n" as *u8)
116 a=mc_cat(ob, a, "\n-- BY HEAD-MARKER CLASS (codeeffectiveness CE1: WHOSE code carries the complexity; knowledge/headmark_classes.conf, first row wins) --\n" as *u8)
117 a=mc_cat(ob, a, " classes_src=" as *u8)
118 if crows>0 { a=mc_cat(ob, a, "CONF rows=" as *u8); a=mc_catn(ob, a, crows) } else { a=mc_cat(ob, a, "ABSENT -- every source reads UNMARKED (a table nobody wrote is an absence, not a measurement)" as *u8) }
119 a=mc_cat(ob, a, "\n" as *u8)
120 var ck: i64=0
121 var cpf: i64=0
122 var cpn: i64=0
123 while ck<=crows {
124 let cb: i64=MC_C_CLSBASE+ck*MC_CLS_FIELDS
125 a=mc_cat(ob, a, " " as *u8); a=mc_cat(ob, a, mc_cls_name(c, ck))
126 a=mc_cat(ob, a, " files=" as *u8); a=mc_catn(ob, a, c[cb+MC_CF_FILES])
127 a=mc_cat(ob, a, " funcs=" as *u8); a=mc_catn(ob, a, c[cb+MC_CF_FUNCS])
128 if c[cb+MC_CF_FUNCS]>0 { a=mc_cat(ob, a, " mean_vG=" as *u8); a=mc_catn(ob, a, c[cb+MC_CF_SUMVG]/c[cb+MC_CF_FUNCS]) }
129 a=mc_cat(ob, a, " above_10=" as *u8); a=mc_catn(ob, a, c[cb+MC_CF_ABOVE])
130 if c[cb+MC_CF_FUNCS]>0 { a=mc_cat(ob, a, " permille=" as *u8); a=mc_catn(ob, a, (c[cb+MC_CF_ABOVE]*MC_PERMILLE)/c[cb+MC_CF_FUNCS]) }
131 a=mc_cat(ob, a, "\n" as *u8)
132 cpf=cpf+c[cb+MC_CF_FILES]
133 cpn=cpn+c[cb+MC_CF_FUNCS]
134 ck=ck+1
135 }
136 a=mc_cat(ob, a, " partition: class_files=" as *u8); a=mc_catn(ob, a, cpf); a=mc_cat(ob, a, " of files=" as *u8); a=mc_catn(ob, a, c[MC_C_FILES])
137 a=mc_cat(ob, a, " class_funcs=" as *u8); a=mc_catn(ob, a, cpn); a=mc_cat(ob, a, " of funcs=" as *u8); a=mc_catn(ob, a, funcs)
138 if crows>0 { if cpf==c[MC_C_FILES] { if cpn==funcs { a=mc_cat(ob, a, " SUMS" as *u8) } else { a=mc_cat(ob, a, " LEAK" as *u8) } } else { a=mc_cat(ob, a, " LEAK" as *u8) } } else { a=mc_cat(ob, a, " (unclassified run)" as *u8) }
139 a=mc_cat(ob, a, "\n" as *u8)
140 // CE1: one row on the time spine, ONLY for the production subject -- a trial run over another dir must not write the
141 // production trajectory (the forgeable-heartbeat law), so it announces SKIPPED instead. The writer prints fd= wrote= of=.
142 var spine_ok: i64=0
143 if argc<2 { spine_ok=1 }
144 if spine_ok==1 {
145 a=ce_mccabe_live(c, funcs, crows, ob, a)
146 } else {
147 a=mc_cat(ob, a, " spine=SKIPPED (non-default subject dir: a trial run does not write the production trajectory)\n" as *u8)
148 }
149 a=mc_cat(ob, a, "\n-- SCOPE, so nobody reads this as more than it is --\n" as *u8)
150 a=mc_cat(ob, a, " Decision points counted: if, while, for, and each of && and ||. `else` is NOT counted.\n" as *u8)
151 a=mc_cat(ob, a, " Comments and string literals are SKIPPED -- a scanner that does not is measuring documentation.\n" as *u8)
152 a=mc_cat(ob, a, " Bodies are read with sys_read_file, which sizes its buffer from the file, so there is NO cap.\n" as *u8)
153 a=mc_cat(ob, a, " files_unreadable=" as *u8); a=mc_catn(ob, a, c[MC_C_UNREAD])
154 a=mc_cat(ob, a, " (UNKNOWN -- counted apart, never folded into a clean result)\n" as *u8)
155 ob[a]=0 as u8
156 mc_w(ob)
157
158 let vb: *u8=sys_mmap(512)
159 var q: i64=0
160 q=mc_cat(vb, q, "\nNX-MCCABE files=" as *u8); q=mc_catn(vb, q, c[MC_C_FILES])
161 q=mc_cat(vb, q, " funcs=" as *u8); q=mc_catn(vb, q, funcs)
162 q=mc_cat(vb, q, " max=" as *u8); q=mc_catn(vb, q, c[MC_C_MAX])
163 q=mc_cat(vb, q, " above_cited_10=" as *u8); q=mc_catn(vb, q, c[MC_C_ABOVE])
164 q=mc_cat(vb, q, " unreadable=" as *u8); q=mc_catn(vb, q, c[MC_C_UNREAD])
165 q=mc_cat(vb, q, " verdict=MEASURED\n" as *u8)
166 vb[q]=0 as u8
167 mc_w(vb)
168 sys_exit(0)
169 return 0
170}