code wiki / _hdl_build / nx_site_compose.nx

nx_site_compose.nx source

↩ module page · 177 lines · 7188 B

1// nx_site_compose.nx -- UNIFIED file-driven multi-type builder. One organ reads a .site DATA file and, from a 2// `type|<legal|game|video>` selector line, dispatches to the right page-type builder: 3// legal (default) -> the marketing block-walk (sgp_parse + sg_build_page) 4// game -> the last-mile game template (sgg_build) 5// video -> the video-gallery (vid_build) 6// Default type = legal, so every existing legal .site file keeps building untouched (additive). This makes the 7// "autonomously built from data, no AI" core (R4a) cover ALL three page types through ONE entry point, not just 8// legal. Each field is escaped by the underlying builder this routes to (block-walk sg_esc / crd_render slots / 9// vid_esc) -- this organ only parses + dispatches, it never emits HTML itself. license_tier: ORIGINAL 10import "nx_sitegen_parse.nx" 11import "nx_sitegen.nx" 12import "nx_sitegen_game.nx" 13import "nx_sitegen_video.nx" 14import "nx_syscalls.nx" 15const K_MAGIC_1024: i64 = 1024 16const K_MAGIC_131072: i64 = 131072 17const K_MAGIC_2048: i64 = 2048 18const K_MAGIC_2047: i64 = 2047 19 20func cmp_klen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 21 22func cmp_streq(a: *u8, b: *u8) -> i64 { 23 var i: i64 = 0 24 var go: i64 = 1 25 while go == 1 { 26 let ca: i64 = a[i] as i64 27 let cb: i64 = b[i] as i64 28 if ca != cb { return 0 } 29 if ca == 0 { return 1 } 30 i = i + 1 31 } 32 return 1 33} 34 35// does text[ls..le) start with key followed by '|'? return the value-start index, or -1. 36func cmp_line_match(text: *u8, ls: i64, le: i64, key: *u8, klen: i64) -> i64 { 37 if ls + klen + 1 > le { return 0 - 1 } 38 var i: i64 = 0 39 while i < klen { 40 if (text[ls+i] as i64) != (key[i] as i64) { return 0 - 1 } 41 i = i + 1 42 } 43 if (text[ls+klen] as i64) != 124 { return 0 - 1 } // '|' 44 return ls + klen + 1 45} 46 47// copy text[start..end) into arena at ap (trim a trailing CR), null-terminate, return new ap. 48func cmp_copy(arena: *u8, ap: i64, text: *u8, start: i64, end: i64) -> i64 { 49 var o: i64 = ap 50 var j: i64 = start 51 while j < end { arena[o] = text[j]; o = o + 1; j = j + 1 } 52 if o > ap { if (arena[o-1] as i64) == 13 { o = o - 1 } } 53 arena[o] = 0 as u8; o = o + 1 54 return o 55} 56 57// get the value of the first "key|value" line into out (null-terminated, trailing CR trimmed); return len or -1. 58func cmp_get(text: *u8, tn: i64, key: *u8, out: *u8, cap: i64) -> i64 { 59 let klen: i64 = cmp_klen(key) 60 var ls: i64 = 0 61 var i: i64 = 0 62 while i <= tn { 63 var eol: i64 = 0 64 if i == tn { eol = 1 } 65 if i < tn { if (text[i] as i64) == 10 { eol = 1 } } 66 if eol == 1 { 67 let vs: i64 = cmp_line_match(text, ls, i, key, klen) 68 if vs >= 0 { 69 var o: i64 = 0 70 var j: i64 = vs 71 while j < i { 72 if o < cap - 1 { out[o] = text[j]; o = o + 1 } 73 j = j + 1 74 } 75 if o > 0 { if (out[o-1] as i64) == 13 { o = o - 1 } } 76 out[o] = 0 as u8 77 return o 78 } 79 ls = i + 1 80 } 81 i = i + 1 82 } 83 return 0 - 1 84} 85 86// parse every "video|title|thumb|url" line into the parallel arrays (fields copied into arena). return count. 87func cmp_videos(text: *u8, tn: i64, titles: *i64, thumbs: *i64, urls: *i64, arena: *u8, max: i64) -> i64 { 88 var ap: i64 = 0 89 var cnt: i64 = 0 90 var ls: i64 = 0 91 var i: i64 = 0 92 while i <= tn { 93 var eol: i64 = 0 94 if i == tn { eol = 1 } 95 if i < tn { if (text[i] as i64) == 10 { eol = 1 } } 96 if eol == 1 { 97 let vs: i64 = cmp_line_match(text, ls, i, "video" as *u8, 5) 98 if vs >= 0 { 99 if cnt < max { 100 var p1: i64 = vs 101 while p1 < i { if (text[p1] as i64) == 124 { break } p1 = p1 + 1 } 102 var p2: i64 = p1 + 1 103 while p2 < i { if (text[p2] as i64) == 124 { break } p2 = p2 + 1 } 104 titles[cnt] = (arena + ap) as i64 105 ap = cmp_copy(arena, ap, text, vs, p1) 106 thumbs[cnt] = (arena + ap) as i64 107 ap = cmp_copy(arena, ap, text, p1 + 1, p2) 108 urls[cnt] = (arena + ap) as i64 109 ap = cmp_copy(arena, ap, text, p2 + 1, i) 110 cnt = cnt + 1 111 } 112 } 113 ls = i + 1 114 } 115 i = i + 1 116 } 117 return cnt 118} 119 120// build a page from an in-memory .site (text/tn) to fd, dispatching on the `type|` line. game_tpl = the game 121// template path (used only for type|game). returns the underlying builder's result (>=0 built, <0 refused). 122func compose_build(text: *u8, tn: i64, fd: i64, game_tpl: *u8) -> i64 { 123 let typ: *u8 = sys_mmap(64) 124 let tl: i64 = cmp_get(text, tn, "type" as *u8, typ, 63) 125 var is_video: i64 = 0 126 var is_game: i64 = 0 127 if tl > 0 { 128 if cmp_streq(typ, "video" as *u8) == 1 { is_video = 1 } 129 if cmp_streq(typ, "game" as *u8) == 1 { is_game = 1 } 130 } 131 132 if is_video == 1 { 133 let vt: *u8 = sys_mmap(K_MAGIC_1024) 134 cmp_get(text, tn, "vtitle" as *u8, vt, 1023) 135 let vh: *u8 = sys_mmap(K_MAGIC_1024) 136 cmp_get(text, tn, "vheading" as *u8, vh, 1023) 137 let titles: *i64 = sys_mmap(8*64) as *i64 138 let thumbs: *i64 = sys_mmap(8*64) as *i64 139 let urls: *i64 = sys_mmap(8*64) as *i64 140 let varena: *u8 = sys_mmap(K_MAGIC_131072) 141 let n: i64 = cmp_videos(text, tn, titles, thumbs, urls, varena, 64) 142 return vid_build(fd, vt, vh, titles, thumbs, urls, n) 143 } 144 145 if is_game == 1 { 146 let gt: *u8 = sys_mmap(K_MAGIC_1024) 147 cmp_get(text, tn, "gtitle" as *u8, gt, 1023) 148 let wasm: *u8 = sys_mmap(K_MAGIC_1024) 149 cmp_get(text, tn, "wasm" as *u8, wasm, 1023) 150 let fbw: *u8 = sys_mmap(64) 151 cmp_get(text, tn, "fbw" as *u8, fbw, 63) 152 let fbh: *u8 = sys_mmap(64) 153 cmp_get(text, tn, "fbh" as *u8, fbh, 63) 154 let dpw: *u8 = sys_mmap(64) 155 cmp_get(text, tn, "dispw" as *u8, dpw, 63) 156 let dph: *u8 = sys_mmap(64) 157 cmp_get(text, tn, "disph" as *u8, dph, 63) 158 let room: *u8 = sys_mmap(64) 159 cmp_get(text, tn, "room" as *u8, room, 63) 160 let ctl: *u8 = sys_mmap(K_MAGIC_2048) 161 cmp_get(text, tn, "controls" as *u8, ctl, K_MAGIC_2047) 162 return sgg_build(fd, game_tpl, gt, wasm, fbw, fbh, dpw, dph, room, ctl) 163 } 164 165 // legal (default) -- the marketing block-walk 166 let kind: *i64 = sys_mmap(8*64) as *i64 167 let a: *i64 = sys_mmap(8*64) as *i64 168 let b: *i64 = sys_mmap(8*64) as *i64 169 let cc: *i64 = sys_mmap(8*64) as *i64 170 let d: *i64 = sys_mmap(8*64) as *i64 171 let list: *i64 = sys_mmap(8*64) as *i64 172 let lcount: *i64 = sys_mmap(8*64) as *i64 173 let arena2: *u8 = sys_mmap(K_MAGIC_131072) 174 let title2: *u8 = sys_mmap(512) 175 let nblk: i64 = sgp_parse(text, tn, kind, a, b, cc, d, list, lcount, 64, arena2, title2, 511) 176 return sg_build_page(fd, title2, kind, a, b, cc, d, list, lcount, nblk) 177}