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}