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}