code wiki / (root) / nx_hex_dump.nx

nx_hex_dump.nx source

↩ module page · 133 lines · 3967 B

1// nx_hex_dump.nx -- bits-up hex+ASCII dump of a byte buffer to an fd. 2// 3// Replaces external tools (xxd, hexdump, hd) with a native NishiLang 4// primitive. Substrate diagnostics MUST use bits-up tools per 5// [[feedback-no-third-party-in-build-path-source-of-truth-is-bits-up]]; 6// if reaching for Wireshark/xxd would diagnose the bug, the 7// substrate needs that capability natively. 8// 9// Output format (16 bytes per line): 10// 00000000 68 74 74 70 73 3a 2f 2f 65 78 61 6d 70 6c 65 2e |https://example.| 11// 12// API: 13// nx_hex_dump_to_fd(fd, label, label_len, bytes, len) -- emit 14// labeled dump on fd (stderr is fd 2). label/label_len may be 15// 0/0 for no label. Returns 0. 16// 17// Per Cardinals 9 (single-responsibility -- one diagnostic primitive), 18// 22 (composition over configuration -- callers choose fd). 19// 20// license_tier: ORIGINAL 21// lineage_id: nishi_hex_dump_q10 22 23import "nx_syscalls.nx" 24 25func _hexnib(v: i64) -> i64 { 26 if v < 10 { return 0x30 + v } 27 return 0x61 + (v - 10) 28} 29 30func _emit_offset(fd: i64, off: i64) -> i64 { 31 let buf: *u8 = sys_mmap(16) 32 var i: i64 = 7 33 var v: i64 = off 34 while i >= 0 { 35 buf[i] = _hexnib(v & 0xf) as u8 36 v = v >> 4 37 i = i - 1 38 } 39 buf[8] = 0x20; buf[9] = 0x20 40 sys_write(fd, buf, 10) 41 return 0 42} 43 44// Emit one line: 16 bytes starting at off, padded with spaces if the 45// line is short. Each byte = "XX " (3 chars), with an extra space 46// between groups of 8. 47func _emit_line(fd: i64, bytes: *u8, off: i64, total: i64) -> i64 { 48 _emit_offset(fd, off) 49 50 // Hex section: 16 bytes, "XX " each + extra space after byte 7. 51 let hexbuf: *u8 = sys_mmap(64) 52 var i: i64 = 0 53 var pos: i64 = 0 54 while i < 16 { 55 if off + i < total { 56 let b: i64 = bytes[off + i] & 0xff 57 hexbuf[pos] = _hexnib((b >> 4) & 0xf) as u8 58 hexbuf[pos + 1] = _hexnib(b & 0xf) as u8 59 } else { 60 hexbuf[pos] = 0x20 61 hexbuf[pos + 1] = 0x20 62 } 63 hexbuf[pos + 2] = 0x20 64 pos = pos + 3 65 if i == 7 { hexbuf[pos] = 0x20; pos = pos + 1 } 66 i = i + 1 67 } 68 hexbuf[pos] = 0x7C // '|' 69 pos = pos + 1 70 sys_write(fd, hexbuf, pos) 71 72 // ASCII gutter 73 let asc: *u8 = sys_mmap(32) 74 var ap: i64 = 0 75 i = 0 76 while i < 16 { 77 if off + i < total { 78 let b: i64 = bytes[off + i] & 0xff 79 if b < 0x20 { asc[ap] = 0x2E } 80 else { if b > 0x7e { asc[ap] = 0x2E } else { asc[ap] = b as u8 } } 81 } else { 82 asc[ap] = 0x20 83 } 84 ap = ap + 1 85 i = i + 1 86 } 87 asc[ap] = 0x7C // '|' 88 asc[ap + 1] = 0x0A // newline 89 sys_write(fd, asc, ap + 2) 90 return 0 91} 92 93// Public API. Emits an optional label header line followed by a 94// canonical xxd-style hex+ASCII dump of bytes[0..len). 95func nx_hex_dump_to_fd(fd: i64, label: *u8, label_len: i64, 96 bytes: *u8, len: i64) -> i64 { 97 if label_len > 0 { 98 sys_write(fd, label, label_len) 99 let arrow: *u8 = sys_mmap(8) 100 arrow[0]=0x20; arrow[1]=0x28; arrow[2]=0x6C; arrow[3]=0x65 101 arrow[4]=0x6E; arrow[5]=0x3D 102 sys_write(fd, arrow, 6) 103 // Length as decimal 104 let lbuf: *u8 = sys_mmap(16) 105 var pos: i64 = 0 106 var x: i64 = len 107 if x == 0 { lbuf[0] = 0x30; pos = 1 } 108 while x > 0 { 109 lbuf[pos] = (0x30 + (x % 10)) as u8 110 x = x / 10 111 pos = pos + 1 112 } 113 // Reverse 114 let lout: *u8 = sys_mmap(16) 115 var li: i64 = 0 116 while li < pos { lout[li] = lbuf[pos - 1 - li]; li = li + 1 } 117 sys_write(fd, lout, pos) 118 let tail: *u8 = sys_mmap(8) 119 tail[0] = 0x29; tail[1] = 0x0A 120 sys_write(fd, tail, 2) 121 } 122 123 var off: i64 = 0 124 while off < len { 125 _emit_line(fd, bytes, off, len) 126 off = off + 16 127 } 128 return 0 129} 130 131func main() -> i64 { 132 return 0 133}