code wiki / _hdl_build / nishi.nx
nishi.nx source
↩ module page · 532 lines · 21789 B
1// nishi.nx -- SOVEREIGN browse CLI + interactive navigator (the Nishi browser).
2// (B)-AUTHORIZED tutor build; flagged backfill debt (re-author from spec later).
3//
4// nishi <https-url> one-shot: fetch + render + link list, then exit
5// nishi interactive REPL (prompt for first URL)
6// nishi -i <https-url> interactive, starting at the given URL
7//
8// Interactive commands: <number> follow that link | <url> open | b back |
9// r reload | q quit (EOF also quits)
10//
11// live DNS -> sovereign TLS 1.3 -> HTTP/1.1 GET -> follow 3xx (abs+relative)
12// -> de-chunk -> gunzip (Content-Encoding) -> charset (header + <meta>) ->
13// UTF-8 -> HTML->text + absolute link list. No curl/zlib/Playwright/gcc.
14//
15// Composes existing sovereign organs only. Artifact = Linux x86-64 ELF (WSL).
16import "nx_syscalls.nx"
17import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
18import "nx_x509_trust_store.nx"
19import "nx_trust_store_load_from_certdata.nx"
20import "nx_https_get.nx"
21import "nx_http_response_parse.nx"
22import "nx_html_to_text.nx"
23import "nx_redirect_resolve.nx"
24import "nx_gzip_wrap.nx"
25import "nx_charset.nx"
26import "nx_html_extract_links.nx"
27import "nx_js_eval.nx" // R-NISH-JS1: run the page's inline <script> against the parsed DOM
28
29func _p(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
30// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
31// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
32// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
33// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
34func _pn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
35
36// Read one line from stdin into out (NUL-terminated, CR/LF stripped).
37// Returns the line length (0 for an empty line), or -1 on EOF with no data.
38func _readline(out: *u8, cap: i64) -> i64 {
39 var n: i64 = 0
40 let ch: *u8 = sys_mmap(8)
41 var go: i64 = 1
42 var eof: i64 = 0
43 while go == 1 {
44 let r: i64 = sys_read(0, ch, 1)
45 if r <= 0 { go = 0; if n == 0 { eof = 1 } }
46 else {
47 let c: i64 = ch[0] & 0xff
48 if c == 0x0a { go = 0 }
49 else {
50 if c != 0x0d {
51 if n < (cap - 1) { out[n] = c as u8; n = n + 1 }
52 }
53 }
54 }
55 }
56 out[n] = 0 as u8
57 if eof == 1 { return 0 - 1 }
58 return n
59}
60
61// Parse an all-digits string -> number, or -1 if not purely numeric.
62func _parse_num(s: *u8, n: i64) -> i64 {
63 if n <= 0 { return 0 - 1 }
64 var v: i64 = 0
65 var i: i64 = 0
66 while i < n {
67 let c: i64 = s[i] & 0xff
68 if c < 0x30 { return 0 - 1 }
69 if c > 0x39 { return 0 - 1 }
70 v = (v * 10) + (c - 0x30)
71 i = i + 1
72 }
73 return v
74}
75
76// 1 iff s starts with "http" (covers http/https).
77func _is_http(s: *u8, n: i64) -> i64 {
78 if n < 7 { return 0 }
79 if _lc(s[0] & 0xff) != 104 { return 0 } // h
80 if _lc(s[1] & 0xff) != 116 { return 0 } // t
81 if _lc(s[2] & 0xff) != 116 { return 0 } // t
82 if _lc(s[3] & 0xff) != 112 { return 0 } // p
83 return 1
84}
85
86// If the parsed response is a followable redirect, copy the resolved https
87// target into `cur` and return 1; else 0. (https-only gate in nx_redirect_resolve.)
88func _try_redirect(buf: *u8, n: i64, r: *i64, cur: *u8, urlcap: i64) -> i64 {
89 let st: i64 = r[1]
90 var isr: i64 = 0
91 if st == 301 { isr = 1 }
92 if st == 302 { isr = 1 }
93 if st == 303 { isr = 1 }
94 if st == 307 { isr = 1 }
95 if st == 308 { isr = 1 }
96 if isr == 0 { return 0 }
97 let vo: *i64 = sys_mmap(8) as *i64
98 let vl: *i64 = sys_mmap(8) as *i64
99 let loc: *u8 = sys_mmap(16)
100 loc[0]=76 as u8; loc[1]=111 as u8; loc[2]=99 as u8; loc[3]=97 as u8
101 loc[4]=116 as u8; loc[5]=105 as u8; loc[6]=111 as u8; loc[7]=110 as u8
102 if nx_http_response_header(buf, n, r, loc, 8, vo, vl) == 0 { return 0 }
103 let lo: i64 = vo[0]
104 let ll: i64 = vl[0]
105 if ll >= urlcap { return 0 }
106 let lp: *u8 = ((buf as i64) + lo) as *u8
107 var blen: i64 = 0
108 while (cur[blen] & 0xff) != 0 { blen = blen + 1 }
109 let tmp: *u8 = sys_mmap(urlcap)
110 let olp: *i64 = sys_mmap(8) as *i64
111 if nx_redirect_resolve(cur, blen, lp, ll, tmp, urlcap, olp) == 0 { return 0 }
112 let tl: i64 = olp[0]
113 var ci: i64 = 0
114 while ci < tl { cur[ci] = tmp[ci]; ci = ci + 1 }
115 cur[tl] = 0 as u8
116 _p(2, "nishi: -> redirect " as *u8); _pn(2, st)
117 _p(2, " -> " as *u8); sys_write(2, tmp, tl); _p(2, "\n" as *u8)
118 return 1
119}
120
121// Fetch `cur` (URL, modified in place by redirects), decode + render the page
122// to stdout, and fill the link buffers (absolute URLs). Returns 0 on success
123// or a negative verdict on failure. Trust store + entropy are loaded once by
124// the caller and passed in. Sets nlinks_box[0] to the number of links.
125func nish_fetch_render(cur: *u8, urlcap: i64, store: *TrustStore, cr: *u8, priv: *u8,
126 lbuf: *u8, lcap: i64, loff: *i64, llen: *i64, lmax: i64,
127 nlinks_box: *i64, emit_links: i64, out_html: i64, out_binary: i64) -> i64 {
128 nlinks_box[0] = 0
129 let t_start: i64 = sys_now_ms()
130 let now: i64 = sys_now_realtime_sec()
131 let cap: i64 = 524288
132 let buf: *u8 = sys_mmap(cap)
133 let r: *i64 = nx_http_resp_alloc()
134
135 let MAXREDIR: i64 = 6
136 var redirs: i64 = 0
137 var n: i64 = 0
138 var pv: i64 = 0
139 var loopdone: i64 = 0
140 while loopdone == 0 {
141 n = nx_https_get(cur, cr, priv, store, now, buf, cap)
142 if n < 0 {
143 _p(2, "nishi: request failed. verdict=" as *u8); _pn(2, 0 - n)
144 _p(2, " (2=bad-url 3=connect-fail 4=handshake-fail 5=fetch-fail)\n" as *u8)
145 return 0 - 4
146 }
147 pv = nx_http_response_parse(buf, n, r)
148 var follow: i64 = 0
149 if pv == NX_HTTP_RESP_OK {
150 if redirs < MAXREDIR {
151 if _try_redirect(buf, n, r, cur, urlcap) == 1 { redirs = redirs + 1; follow = 1 }
152 }
153 }
154 if follow == 0 { loopdone = 1 }
155 }
156 let t_net: i64 = sys_now_ms()
157
158 let base: i64 = buf as i64
159 var body: *u8 = buf
160 var body_len: i64 = n
161 if pv == NX_HTTP_RESP_OK {
162 let bo: i64 = r[6]
163 let kind: i64 = r[8]
164 body = (base + bo) as *u8
165 body_len = n - bo
166 if kind == NX_HTTP_BODY_CONTENT_LENGTH {
167 body_len = r[7]
168 if body_len > n - bo { body_len = n - bo }
169 }
170 if kind == NX_HTTP_BODY_CHUNKED {
171 let dcap: i64 = 1048576
172 let dbuf: *u8 = sys_mmap(dcap)
173 let dl: i64 = nx_http_dechunk(body, n - bo, dbuf, dcap)
174 if dl > 0 {
175 body = dbuf
176 body_len = dl
177 }
178 }
179
180 // gunzip if Content-Encoding: gzip (KAT-proven nx_gzip_inflate).
181 let cevo: *i64 = sys_mmap(8) as *i64
182 let cevl: *i64 = sys_mmap(8) as *i64
183 let cen: *u8 = sys_mmap(20)
184 cen[0]=67 as u8; cen[1]=111 as u8; cen[2]=110 as u8; cen[3]=116 as u8
185 cen[4]=101 as u8; cen[5]=110 as u8; cen[6]=116 as u8; cen[7]=45 as u8
186 cen[8]=69 as u8; cen[9]=110 as u8; cen[10]=99 as u8; cen[11]=111 as u8
187 cen[12]=100 as u8;cen[13]=105 as u8;cen[14]=110 as u8;cen[15]=103 as u8
188 if nx_http_response_header(buf, n, r, cen, 16, cevo, cevl) == 1 {
189 let cvl: i64 = cevl[0]
190 var isgz: i64 = 0
191 if cvl >= 4 {
192 let cvp: *u8 = (base + cevo[0]) as *u8
193 if _lc(cvp[0] as i64)==103 { if _lc(cvp[1] as i64)==122 {
194 if _lc(cvp[2] as i64)==105 { if _lc(cvp[3] as i64)==112 { isgz=1 } } } }
195 }
196 if isgz == 1 {
197 let gr: *NxGzipResult = nx_gzip_inflate(body, body_len, 4194304)
198 if gr != (0 as *NxGzipResult) {
199 if gr.error_code == NX_GZ_OK {
200 body = gr.output_data
201 body_len = gr.output_size
202 }
203 }
204 }
205 }
206 }
207
208 // -B raw binary: emit the dechunked+gunzipped body VERBATIM (NO charset decode -- charset decode
209 // corrupts binary, which is why -H returned a PNG with zeroed magic). For fetching images so the
210 // decoder gets the exact bytes. MUST precede the charset step below.
211 if out_binary == 1 {
212 if pv == NX_HTTP_RESP_OK { if body_len > 0 { sys_write(1, body, body_len) } }
213 nlinks_box[0] = 0
214 return 0
215 }
216
217 // charset -> UTF-8 (Content-Type charset wins, else <meta charset>).
218 if pv == NX_HTTP_RESP_OK {
219 let ctvo: *i64 = sys_mmap(8) as *i64
220 let ctvl: *i64 = sys_mmap(8) as *i64
221 let ctn: *u8 = sys_mmap(20)
222 ctn[0]=67 as u8; ctn[1]=111 as u8; ctn[2]=110 as u8; ctn[3]=116 as u8
223 ctn[4]=101 as u8; ctn[5]=110 as u8; ctn[6]=116 as u8; ctn[7]=45 as u8
224 ctn[8]=84 as u8; ctn[9]=121 as u8; ctn[10]=112 as u8; ctn[11]=101 as u8
225 var cs: i64 = 0 - 1
226 if nx_http_response_header(buf, n, r, ctn, 12, ctvo, ctvl) == 1 {
227 let ctp: *u8 = (base + ctvo[0]) as *u8
228 cs = nx_charset_sniff(ctp, ctvl[0])
229 }
230 if cs < 0 { cs = nx_charset_sniff(body, body_len) }
231 if cs > 0 {
232 let ccap: i64 = 2097152
233 let cbuf: *u8 = sys_mmap(ccap)
234 let cl: i64 = nx_charset_to_utf8(body, body_len, cs, cbuf, ccap)
235 if cl > 0 {
236 body = cbuf
237 body_len = cl
238 }
239 }
240 }
241
242 // Save the fetched+cleaned HTML so the styled GRAPHICAL renderer (nx_render_wiki_styled) can
243 // render THIS page next -- the fetch -> styled-render -> view browse loop, reusing nishi's proven
244 // fetch (TLS/redirect/dechunk/charset) instead of replicating it. Additive; CLI text output below
245 // is unchanged.
246 if pv == NX_HTTP_RESP_OK { if body_len > 0 {
247 let _sfd: i64 = sys_openat_wr("knowledge/fetched/last_fetch.html\x00" as *u8, 420)
248 if _sfd >= 0 { sys_write(_sfd, body, body_len); sys_close(_sfd) }
249 } }
250
251 // R1 (CSS-on-PE arc): raw-HTML output mode -- emit the decoded HTML body verbatim so the GUI's
252 // CSS layout+paint pipeline (nx_browser br_layout/br_draw_fb) renders the REAL page, not flattened
253 // text. Placed AFTER fetch+redirect+dechunk+gunzip+charset so `body` is final UTF-8 HTML.
254 if out_html == 1 {
255 nlinks_box[0] = 0
256 sys_write(1, body, body_len)
257 return 0
258 }
259 // render HTML -> readable text. emit_links=1 (GUI) interleaves inline link
260 // markers (STX url SOH anchor ETX) in the body; emit_links=0 (CLI) is plain.
261 let tcap: i64 = 524288
262 let tbuf: *u8 = sys_mmap(tcap)
263 let tn: i64 = nx_html_to_text_x(body, body_len, tbuf, tcap, emit_links)
264
265 // links (absolute, resolved against the final URL) -> caller's buffers
266 // (needed for nlinks_box + the CLI's follow-link-by-number).
267 var nlinks: i64 = 0
268 if pv == NX_HTTP_RESP_OK {
269 var curlen: i64 = 0
270 while (cur[curlen] & 0xff) != 0 { curlen = curlen + 1 }
271 nlinks = nx_html_extract_links(body, body_len, cur, curlen,
272 lbuf, lcap, loff, llen, lmax)
273 }
274 nlinks_box[0] = nlinks
275
276 // Output: title (first rendered line), then -- only in CLI mode -- the numbered
277 // link list, then the article body. In GUI inline mode the body already carries
278 // clickable link markers, so the separate list is suppressed (cleaner article).
279 if tn > 0 {
280 var t1: i64 = 0
281 var tf: i64 = 0
282 while tf == 0 {
283 if t1 >= tn { tf = 1 } else { if (tbuf[t1] & 0xff) == 0x0a { tf = 1 } else { t1 = t1 + 1 } }
284 }
285 sys_write(1, tbuf, t1)
286 _p(1, "\n" as *u8)
287 if emit_links == 0 {
288 if nlinks > 0 {
289 _p(1, "--- Links (" as *u8); _pn(1, nlinks); _p(1, ") ---\n" as *u8)
290 var li: i64 = 0
291 while li < nlinks {
292 _pn(1, li + 1); _p(1, ". " as *u8)
293 sys_write(1, ((lbuf as i64) + loff[li]) as *u8, llen[li])
294 _p(1, "\n" as *u8)
295 li = li + 1
296 }
297 _p(1, "\n" as *u8)
298 }
299 }
300 if t1 < tn { sys_write(1, ((tbuf as i64) + t1 + 1) as *u8, tn - t1 - 1) }
301 _p(1, "\n" as *u8)
302 }
303 if tn <= 0 {
304 sys_write(1, body, body_len)
305 }
306 // R-NISH-JS1: execute the page's inline <script> blocks against the parsed DOM -- the sovereign
307 // browser RUNS JavaScript. Scripts' console.log output appears on stdout (above); external src=
308 // scripts are skipped; per-script errors + oversized bundles are swallowed (best-effort, never
309 // crashes the browse). The i64-only engine errors out gracefully on bundles needing f64/regex.
310 if pv == NX_HTTP_RESP_OK {
311 if body_len > 0 {
312 let nsc: i64 = js_run_page_scripts(body, body_len)
313 _p(2, "nishi-js inline_scripts_executed=" as *u8); _pn(2, nsc); _p(2, "\n" as *u8)
314 }
315 }
316 // native sovereign perf line (system performance, emitted to stderr via sys_now_ms)
317 let t_end: i64 = sys_now_ms()
318 _p(2, "nishi-perf net=" as *u8); _pn(2, t_net - t_start)
319 _p(2, "ms proc=" as *u8); _pn(2, t_end - t_net)
320 _p(2, "ms total=" as *u8); _pn(2, t_end - t_start)
321 _p(2, "ms bytes=" as *u8); _pn(2, n); _p(2, "\n" as *u8)
322 return 0
323}
324
325func main(argc: i64, argv: *i64) -> i64 {
326 // trust store (Mozilla NSS bundle) -- loaded ONCE.
327 var tr: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt" as *u8, 300, 4194304)
328 if tr <= 0 { tr = nx_trust_store_load_from_certdata("/tmp/mozilla_certdata.txt" as *u8, 300, 4194304) }
329 if tr <= 0 {
330 _p(2, "nishi: CA bundle load failed (need /tmp/mozilla_certdata.txt). verdict=" as *u8)
331 _pn(2, 0 - tr); _p(2, "\n" as *u8)
332 sys_exit(3); return 3
333 }
334 let store: *TrustStore = tr as *TrustStore
335
336 // entropy -- loaded ONCE (32B client_random + 32B x25519 ephemeral priv).
337 let cr: *u8 = sys_mmap(32)
338 let priv: *u8 = sys_mmap(32)
339 let ufd: i64 = sys_openat_rd("/dev/urandom" as *u8)
340 if ufd >= 0 {
341 sys_read(ufd, cr, 32)
342 sys_read(ufd, priv, 32)
343 sys_close(ufd)
344 }
345 if ufd < 0 {
346 var z: i64 = 0
347 while z < 32 { cr[z] = (0xC0 + z) as u8; priv[z] = (0xA0 + z) as u8; z = z + 1 }
348 }
349
350 // working buffers (persist across pages).
351 let URLCAP: i64 = 4096
352 let cur: *u8 = sys_mmap(URLCAP)
353 let cmd: *u8 = sys_mmap(URLCAP)
354 let LMAX: i64 = 150
355 let lcap: i64 = 262144
356 let lbuf: *u8 = sys_mmap(lcap)
357 let loff: *i64 = sys_mmap(8 * LMAX) as *i64
358 let llen: *i64 = sys_mmap(8 * LMAX) as *i64
359 let nbox: *i64 = sys_mmap(8) as *i64
360
361 // history stack (packed URLs).
362 let HMAX: i64 = 64
363 let hcap: i64 = 131072
364 let hbuf: *u8 = sys_mmap(hcap)
365 let hoff: *i64 = sys_mmap(8 * HMAX) as *i64
366 let hlen: *i64 = sys_mmap(8 * HMAX) as *i64
367 var hcount: i64 = 0
368 var hw: i64 = 0
369
370 // arg parse: interactive (-i) vs one-shot; -L = one-shot with inline link
371 // markers (used by the graphical GUI front-end); optional initial URL.
372 var interactive: i64 = 0
373 var initial: *u8 = 0 as *u8
374 var emit_links: i64 = 0
375 var out_html: i64 = 0 // -H: emit the raw decoded HTML (for the GUI CSS renderer)
376 var out_binary: i64 = 0 // -B: emit the raw body bytes verbatim (images/binary)
377 if argc < 2 { interactive = 1 }
378 else {
379 let a1: *u8 = argv[1] as *u8
380 var isi: i64 = 0
381 var isL: i64 = 0
382 var isH: i64 = 0
383 var isB: i64 = 0
384 if (a1[0] & 0xff) == 0x2d {
385 if (a1[1] & 0xff) == 0x69 { isi = 1 } // -i
386 if (a1[1] & 0xff) == 0x4c { isL = 1 } // -L
387 if (a1[1] & 0xff) == 0x48 { isH = 1 } // -H (raw HTML out)
388 if (a1[1] & 0xff) == 0x42 { isB = 1 } // -B (raw binary out)
389 }
390 if isi == 1 {
391 interactive = 1
392 if argc >= 3 { initial = argv[2] as *u8 }
393 } else {
394 if isL == 1 {
395 emit_links = 1
396 initial = ((a1 as i64) + 2) as *u8 // URL is the rest of argv[1] after "-L" (build_argv gives one token)
397 } else {
398 if isH == 1 {
399 out_html = 1
400 initial = ((a1 as i64) + 2) as *u8 // URL is the rest of argv[1] after "-H"
401 } else {
402 if isB == 1 {
403 out_binary = 1
404 initial = ((a1 as i64) + 2) as *u8 // URL is the rest of argv[1] after "-B"
405 } else {
406 initial = a1
407 }
408 }
409 }
410 }
411 }
412
413 var have_page: i64 = 0
414 var cur_nlinks: i64 = 0
415
416 // open the initial URL (if any).
417 if initial != (0 as *u8) {
418 var ul: i64 = 0
419 while initial[ul] != (0 as u8) { cur[ul] = initial[ul]; ul = ul + 1 }
420 cur[ul] = 0 as u8
421 if nish_fetch_render(cur, URLCAP, store, cr, priv, lbuf, lcap, loff, llen, LMAX, nbox, emit_links, out_html, out_binary) == 0 {
422 have_page = 1
423 cur_nlinks = nbox[0]
424 // push final cur onto history.
425 var cl0: i64 = 0
426 while (cur[cl0] & 0xff) != 0 { cl0 = cl0 + 1 }
427 if hcount < HMAX { if (hw + cl0) < hcap {
428 hoff[hcount] = hw
429 var q: i64 = 0
430 while q < cl0 { hbuf[hw + q] = cur[q]; q = q + 1 }
431 hlen[hcount] = cl0
432 hw = hw + cl0
433 hcount = hcount + 1
434 } }
435 }
436 }
437
438 if interactive == 0 { sys_exit(0); return 0 }
439
440 _p(2, "nishi interactive -- <number> follow link | <url> open | b back | r reload | q quit\n" as *u8)
441 var go: i64 = 1
442 while go == 1 {
443 _p(2, "\nnish> " as *u8)
444 let clen: i64 = _readline(cmd, URLCAP)
445 if clen < 0 { go = 0 }
446 else {
447 if clen > 0 {
448 let c0: i64 = cmd[0] & 0xff
449 var handled: i64 = 0
450 var target_ready: i64 = 0
451 var push: i64 = 1
452
453 // q quit
454 if handled == 0 { if clen == 1 { if c0 == 0x71 { go = 0; handled = 1 } } }
455 // b back
456 if handled == 0 { if clen == 1 { if c0 == 0x62 {
457 handled = 1
458 if hcount >= 2 {
459 hcount = hcount - 1
460 let idx: i64 = hcount - 1
461 let o: i64 = hoff[idx]
462 let l: i64 = hlen[idx]
463 var q: i64 = 0
464 while q < l { cur[q] = hbuf[o + q]; q = q + 1 }
465 cur[l] = 0 as u8
466 target_ready = 1
467 push = 0
468 } else { _p(2, "(no history)\n" as *u8) }
469 } } }
470 // r reload
471 if handled == 0 { if clen == 1 { if c0 == 0x72 {
472 handled = 1
473 if have_page == 1 { target_ready = 1; push = 0 }
474 else { _p(2, "(no page yet)\n" as *u8) }
475 } } }
476 // url
477 if handled == 0 { if _is_http(cmd, clen) == 1 {
478 handled = 1
479 var q: i64 = 0
480 while q < clen { cur[q] = cmd[q]; q = q + 1 }
481 cur[clen] = 0 as u8
482 target_ready = 1
483 push = 1
484 } }
485 // number -> follow link
486 if handled == 0 {
487 let num: i64 = _parse_num(cmd, clen)
488 if num >= 1 {
489 handled = 1
490 if have_page == 1 { if num <= cur_nlinks {
491 let li: i64 = num - 1
492 let o: i64 = loff[li]
493 let l: i64 = llen[li]
494 var q: i64 = 0
495 while q < l { cur[q] = lbuf[o + q]; q = q + 1 }
496 cur[l] = 0 as u8
497 target_ready = 1
498 push = 1
499 } }
500 if target_ready == 0 { _p(2, "(no such link)\n" as *u8) }
501 }
502 }
503 // unknown
504 if handled == 0 {
505 _p(2, "commands: <number> | <url> | b back | r reload | q quit\n" as *u8)
506 }
507
508 // navigate
509 if target_ready == 1 {
510 if nish_fetch_render(cur, URLCAP, store, cr, priv, lbuf, lcap, loff, llen, LMAX, nbox, emit_links, out_html, out_binary) == 0 {
511 have_page = 1
512 cur_nlinks = nbox[0]
513 if push == 1 {
514 var cl1: i64 = 0
515 while (cur[cl1] & 0xff) != 0 { cl1 = cl1 + 1 }
516 if hcount < HMAX { if (hw + cl1) < hcap {
517 hoff[hcount] = hw
518 var q2: i64 = 0
519 while q2 < cl1 { hbuf[hw + q2] = cur[q2]; q2 = q2 + 1 }
520 hlen[hcount] = cl1
521 hw = hw + cl1
522 hcount = hcount + 1
523 } }
524 }
525 }
526 }
527 }
528 }
529 }
530 _p(2, "bye\n" as *u8)
531 sys_exit(0); return 0
532}