code wiki / _hdl_build / nx_translate_daemon.nx

nx_translate_daemon.nx source

↩ module page · 159 lines · 6558 B

1// nx_translate_daemon.nx -- the SOVEREIGN live /translate service for nishifamily.com/video, now on the 2// DATA-DRIVEN RU<->EN engine (nx_xlate_mt) -- replaces the old toy EN->ES (sea/tea/go) demo. Loopback :8447, 3// plain HTTP behind the edge; supervised by the existing hostctl guard (nx_hostctl.nx HC_XLATE :8447) so it 4// CANNOT affect the video/signaling path. GET /translate?text=<urlenc>[&dir=ru2en|en2ru] -> text/plain 5// (CORS-open). Direction auto-detected from Cyrillic when dir= absent. Lexicon + morphology load from 6// knowledge/xlate/ at startup. Any non-text GET (e.g. a health probe) -> 200 "?" so the guard sees it alive. 7// genealogy_id: sovereign_data_driven_ruen_mt_v1 license_tier: ORIGINAL 8import "nx_http_server.nx" 9import "nx_xlate_mt.nx" 10import "nx_syscalls.nx" 11const TD_MAGIC_8192: i64 = 8192 12const TD_MAGIC_4096: i64 = 4096 13const TD_MAGIC_16384: i64 = 16384 14 15const TD_PORT: i64 = 8447 16const TD_HDR1: *u8 = "HTTP/1.1 200 OK\r\nContent-Type: text/plain; charset=utf-8\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: " as *u8 17const TD_HDR2: *u8 = "\r\nConnection: close\r\n\r\n" as *u8 18 19func td_puts(buf: *u8, off: i64, s: *u8) -> i64 { 20 var o: i64 = off 21 var i: i64 = 0 22 while s[i] != (0 as u8) { buf[o] = s[i]; o = o + 1; i = i + 1 } 23 return o 24} 25func td_wdec(buf: *u8, off: i64, v: i64) -> i64 { 26 var o: i64 = off 27 var m: i64 = v 28 if m == 0 { buf[o] = 48; return o + 1 } 29 let t: *u8 = sys_mmap(28) 30 var k: i64 = 0 31 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 32 while k > 0 { buf[o] = t[k - 1]; o = o + 1; k = k - 1 } 33 sys_munmap(t, 28) 34 return o 35} 36func td_hex(c: i64) -> i64 { 37 if c >= 48 { if c <= 57 { return c - 48 } } 38 if c >= 97 { if c <= 102 { return c - 87 } } 39 if c >= 65 { if c <= 70 { return c - 55 } } 40 return 0 - 1 41} 42// find "text=" in req[0..len), URL-decode value (until '&'/space/CR/LF/end) into out; return length 43func td_param(req: *u8, len: i64, out: *u8) -> i64 { 44 var i: i64 = 0 45 var start: i64 = 0 - 1 46 while i + 5 <= len { 47 var m: i64 = 1 48 if (req[i] as i64) != 116 { m = 0 } 49 if (req[i+1] as i64) != 101 { m = 0 } 50 if (req[i+2] as i64) != 120 { m = 0 } 51 if (req[i+3] as i64) != 116 { m = 0 } 52 if (req[i+4] as i64) != 61 { m = 0 } 53 if m == 1 { start = i + 5; break } 54 i = i + 1 55 } 56 if start < 0 { return 0 } 57 var o: i64 = 0 58 var j: i64 = start 59 while j < len { 60 let c: i64 = req[j] as i64 61 if c == 38 { break } 62 if c == 32 { break } 63 if c == 13 { break } 64 if c == 10 { break } 65 if c == 37 { 66 if j + 2 < len { 67 let h: i64 = td_hex(req[j+1] as i64) 68 let l: i64 = td_hex(req[j+2] as i64) 69 if h >= 0 { if l >= 0 { out[o] = ((h * 16) + l) as u8; o = o + 1; j = j + 3 } } 70 if h < 0 { out[o] = c as u8; o = o + 1; j = j + 1 } 71 if h >= 0 { if l < 0 { out[o] = c as u8; o = o + 1; j = j + 1 } } 72 } else { out[o] = c as u8; o = o + 1; j = j + 1 } 73 } else { 74 if c == 43 { out[o] = 32 as u8; o = o + 1; j = j + 1 } else { out[o] = c as u8; o = o + 1; j = j + 1 } 75 } 76 } 77 return o 78} 79func td_dirparam(req: *u8, len: i64) -> i64 { 80 var i: i64 = 0 81 while i + 3 <= len { 82 if (req[i] as i64) == 50 { 83 if (req[i+1] as i64) == 114 { if (req[i+2] as i64) == 117 { return 1 } } 84 if (req[i+1] as i64) == 101 { if (req[i+2] as i64) == 110 { return 2 } } 85 } 86 i = i + 1 87 } 88 return 0 89} 90func td_autodir(txt: *u8, n: i64) -> i64 { 91 var i: i64 = 0 92 while i < n { if (txt[i] as i64) >= 208 { return 1 } i = i + 1 } 93 return 0 94} 95func main() -> i64 { 96 let lnp: *i64 = sys_mmap(8) as *i64 97 let mnp: *i64 = sys_mmap(8) as *i64 98 let lex: *u8 = sys_read_file("buildroot/runtime/_hdl_build/xlate_lex.tsv" as *u8, lnp) 99 let morph: *u8 = sys_read_file("buildroot/runtime/_hdl_build/xlate_morph_ru.tsv" as *u8, mnp) 100 if (lex as i64) == 0 { return 2 } 101 var morphn: i64 = 0 102 if (morph as i64) != 0 { morphn = mnp[0] } 103 let eng: *i64 = sys_mmap(256) as *i64 104 xl_build(eng, lex, lnp[0], morph, morphn) 105 let addr: *u8 = sys_mmap(16) 106 nx_http_server_addr_loopback(addr, TD_PORT) 107 let lv: *i64 = sys_mmap(8) as *i64 108 let listen_fd: i64 = nx_http_server_listen(addr, 16, lv) 109 if listen_fd < 0 { return 1 } 110 let banner: *u8 = "nx_translate_daemon: sovereign data-driven RU<->EN /translate on 127.0.0.1:8447\n" as *u8 111 var bn: i64 = 0 112 while banner[bn] != (0 as u8) { bn = bn + 1 } 113 sys_write(1, banner, bn) 114 let req: *u8 = sys_mmap(TD_MAGIC_8192) 115 let mo: *i64 = sys_mmap(8) as *i64 116 let po: *i64 = sys_mmap(8) as *i64 117 let pl: *i64 = sys_mmap(8) as *i64 118 let cl: *i64 = sys_mmap(8) as *i64 119 let bo: *i64 = sys_mmap(8) as *i64 120 let rn: *i64 = sys_mmap(8) as *i64 121 let cv: *i64 = sys_mmap(8) as *i64 122 let txt: *u8 = sys_mmap(TD_MAGIC_4096) 123 let out: *u8 = sys_mmap(TD_MAGIC_8192) 124 let resp: *u8 = sys_mmap(TD_MAGIC_16384) 125 var run: i64 = 1 126 while run == 1 { 127 let cfd: i64 = nx_http_server_accept_one(listen_fd, cv) 128 if cfd >= 0 { 129 let rc: i64 = nx_http_server_read_request(cfd, req, TD_MAGIC_8192, mo, po, pl, cl, bo, rn) 130 if rc == NXS_OK { 131 let tlen: i64 = td_param(req, rn[0], txt) 132 if tlen > 0 { 133 var dir: i64 = td_autodir(txt, tlen) 134 let dp: i64 = td_dirparam(req, rn[0]) 135 if dp == 1 { dir = 0 } 136 if dp == 2 { dir = 1 } 137 let olen: i64 = xl_translate(eng, txt, tlen, dir, out, TD_MAGIC_8192) 138 var o: i64 = 0 139 o = td_puts(resp, o, TD_HDR1) 140 o = td_wdec(resp, o, olen) 141 o = td_puts(resp, o, TD_HDR2) 142 var i: i64 = 0 143 while i < olen { resp[o + i] = out[i]; i = i + 1 } 144 o = o + olen 145 nx_http_server_send_response(cfd, resp, o) 146 } else { 147 var o2: i64 = 0 148 o2 = td_puts(resp, o2, TD_HDR1) 149 o2 = td_wdec(resp, o2, 1) 150 o2 = td_puts(resp, o2, TD_HDR2) 151 resp[o2] = 63 as u8 152 o2 = o2 + 1 153 nx_http_server_send_response(cfd, resp, o2) 154 } 155 } else { sys_close(cfd) } 156 } 157 } 158 return 0 159}