code wiki / _hdl_build / nx_doc_view.nx

nx_doc_view.nx source

↩ module page · 119 lines · 5061 B

1// nx_doc_view.nx -- the Nishi browser's DOCUMENT-VIEWER DISPATCH. Makes the browser an omnitool WITHOUT bloat: 2// a data-driven registry (knowledge/doc_viewers.conf: "<ext>\t<renderer_elf>\t<label>") maps a file extension to 3// a focused sovereign renderer organ, which nx_doc_view fork-execs to turn the document into a 0-JS HTML page the 4// browser shows INLINE. Adding a format = ONE registry row + a renderer organ; this dispatcher never changes. 5// Renderers share one interface: "<elf> html <in> <out.html> [download_url]". license_tier: ORIGINAL 6import "nx_syscalls.nx" 7const REG_MAGIC_65536: i64 = 65536 8const REG_MAGIC_65535: i64 = 65535 9 10const REG_PATH: *u8 = "knowledge/doc_viewers.conf\x00" 11 12func dv_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8) { n=n+1 } return n } 13func dv_puts(s: *u8) -> i64 { sys_write(1, s, dv_slen(s)); return 0 } 14 15func dv_readfile(path: *u8, buf: *u8, cap: i64) -> i64 { 16 let fd: i64=sys_openat_rd(path); if fd<0 { return 0-1 } 17 var tot: i64=0; while tot<cap { let r: i64=sys_read(fd,(buf as i64+tot) as *u8,cap-tot); if r<=0 { break } tot=tot+r } 18 sys_close(fd); return tot 19} 20 21// lowercase a byte 22func dv_low(c: i64) -> i64 { if c>=65 { if c<=90 { return c+32 } } return c } 23 24// extract the lowercased extension of `path` into `ext` (NUL-terminated); return its length (0 if none). 25func dv_ext(path: *u8, ext: *u8) -> i64 { 26 let n: i64=dv_slen(path) 27 var dot: i64=0-1; var i: i64=0 28 while i<n { if path[i]==(46 as u8) { dot=i } if path[i]==(47 as u8) { dot=0-1 } i=i+1 } 29 if dot<0 { ext[0]=0 as u8; return 0 } 30 var k: i64=0; var p: i64=dot+1 31 while p<n { ext[k]=dv_low(path[p] as i64) as u8; k=k+1; p=p+1 } 32 ext[k]=0 as u8 33 return k 34} 35 36func dv_streq(a: *u8, an: i64, b: *u8, bn: i64) -> i64 { 37 if an!=bn { return 0 } 38 var i: i64=0; while i<an { if a[i]!=b[i] { return 0 } i=i+1 } return 1 39} 40 41// look up `ext` in the registry buffer; copy the renderer elf path into `elf` and label into `label`. 42// returns 1 if found, 0 if not. Tolerant of trailing CR. 43func dv_lookup(reg: *u8, rlen: i64, ext: *u8, extn: i64, elf: *u8, label: *u8) -> i64 { 44 var i: i64=0 45 while i<rlen { 46 var e: i64=i 47 while e<rlen { if reg[e]==(10 as u8) { break } e=e+1 } 48 var end: i64=e 49 if end>i { if reg[end-1]==(13 as u8) { end=end-1 } } 50 // field 1: ext (up to TAB) 51 var t1: i64=i 52 while t1<end { if reg[t1]==(9 as u8) { break } t1=t1+1 } 53 var rext: *u8=(reg as i64 + i) as *u8 54 var rextn: i64=t1-i 55 if dv_streq(rext, rextn, ext, extn)==1 { 56 // field 2: elf (TAB..TAB) 57 var t2: i64=t1+1 58 while t2<end { if reg[t2]==(9 as u8) { break } t2=t2+1 } 59 var k: i64=0; var p: i64=t1+1 60 while p<t2 { elf[k]=reg[p]; k=k+1; p=p+1 } elf[k]=0 as u8 61 // field 3: label (rest) 62 k=0; p=t2+1 63 while p<end { label[k]=reg[p]; k=k+1; p=p+1 } label[k]=0 as u8 64 return 1 65 } 66 i=e+1 67 } 68 return 0 69} 70 71// fork+exec "<elf> html <inp> <outp> [dlurl]"; wait; return child exit code (or 128+sig). 72func dv_run(elf: *u8, inp: *u8, outp: *u8, dlurl: *u8) -> i64 { 73 let pid: i64=sys_fork() 74 if pid==0 { 75 let argv: *i64=sys_mmap(64) as *i64 76 argv[0]=elf as i64 77 argv[1]="html\x00" as *u8 as i64 78 argv[2]=inp as i64 79 argv[3]=outp as i64 80 if (dlurl as i64)!=0 { argv[4]=dlurl as i64; argv[5]=0 } else { argv[4]=0 } 81 let envp: *i64=sys_mmap(16) as *i64; envp[0]=0 82 sys_execve(elf, argv, envp) 83 sys_exit(127) 84 } 85 let st: *i64=sys_mmap(16) as *i64; sys_wait4(pid, st, 0) 86 let sig: i64=st[0]&0x7f; if sig!=0 { return 128+sig } 87 return (st[0]>>8)&0xff 88} 89 90func main(argc: i64, argv: *i64) -> i64 { 91 if argc<3 { dv_puts("usage: nx_doc_view <in.doc> <out.html> [download_url]\n" as *u8); sys_exit(2); return 2 } 92 let inp: *u8=argv[1] as *u8 93 let outp: *u8=argv[2] as *u8 94 var dlu: *u8=0 as *u8 95 if argc>3 { dlu=argv[3] as *u8 } 96 97 let ext: *u8=sys_mmap(64) 98 let extn: i64=dv_ext(inp, ext) 99 if extn==0 { dv_puts("DOC-VIEW-UNSUPPORTED no-extension\n" as *u8); sys_exit(3); return 3 } 100 101 let reg: *u8=sys_mmap(REG_MAGIC_65536) 102 let rlen: i64=dv_readfile(REG_PATH, reg, REG_MAGIC_65535) 103 if rlen<0 { dv_puts("DOC-VIEW-FAIL registry-missing\n" as *u8); sys_exit(1); return 1 } 104 105 let elf: *u8=sys_mmap(512) 106 let label: *u8=sys_mmap(256) 107 if dv_lookup(reg, rlen, ext, extn, elf, label)==0 { 108 dv_puts("DOC-VIEW-UNSUPPORTED ext=" as *u8); dv_puts(ext); dv_puts(" (add a row to knowledge/doc_viewers.conf)\n" as *u8) 109 sys_exit(3); return 3 110 } 111 112 let rc: i64=dv_run(elf, inp, outp, dlu) 113 if rc!=0 { 114 dv_puts("DOC-VIEW-FAIL renderer=" as *u8); dv_puts(elf); dv_puts(" rc-nonzero\n" as *u8) 115 sys_exit(1); return 1 116 } 117 dv_puts("DOC-VIEW-OK ext=" as *u8); dv_puts(ext); dv_puts(" viewer=" as *u8); dv_puts(label); dv_puts(" -> " as *u8); dv_puts(outp); dv_puts("\n" as *u8) 118 sys_exit(0); return 0 119}