nx_strfmt.nx
buildroot/runtime/nx_strfmt.nx
about
nx_strfmt.nx -- minimal printf-style formatter.
Replaces the dozens of ad-hoc `out_str` + `out_int64` chains
scattered across the runtime with one canonical "format string +
args" interface.
Format directives supported (printf subset):
%d signed decimal i64
%u unsigned decimal i64
%x lowercase hex i64 (no 0x prefix)
%X uppercase hex i64
%s NUL-terminated *u8
%c single byte (low 8 bits of i64)
%p pointer (= 0x + 16-char zero-padded hex)
%% literal '%'
Width / precision / alignment NOT supported (v0.0.1). Add
when the codegen-disassembler-debugger triangle needs prettier
output.
Three entry points:
nx_fmt_to_buf(out, cap, fmt, argv, argc)
Writes into a caller buffer; returns bytes written.
nx_fmt_to_fd(fd, fmt, argv, argc)
Writes directly to fd via sys_write; returns total bytes.
nx_fmt_int / nx_fmt_hex / nx_fmt_bytes (low-level helpers)
Args are passed as a *i64 array of length argc. Each %d / %u /
%x / %X / %p / %c consumes one slot (i64). %s consumes one slot
(interpreted as *u8).
Why this design (vs varargs):
Varargs in NishiLang would need ABI work; a flat i64 array is
already the calling convention for ir_emit_call internally.
Caller does:
let argv: *i64 = sys_mmap(8 * 4)
dependencies 1 imports · 4 importers
imports: syscalls.nx
imported by: nx_dbg.nxnx_nm.nxnx_readelf.nxnx_size.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 52 | const K_MAGIC_4096: i64 = 4096 |
functions
| 57 | func nx_fmt_int(dst: *u8, off: i64, cap: i64, v: i64) -> i64 called by 1: nx_fmt_to_buf |
| 91 | func nx_fmt_hex(dst: *u8, off: i64, cap: i64, v: i64, called by 1: nx_fmt_to_buf |
| 125 | func nx_fmt_bytes(dst: *u8, off: i64, cap: i64, src: *u8) -> i64 called by 1: nx_fmt_to_buf |
| 142 | func nx_fmt_to_buf(out: *u8, cap: i64, fmt: *u8, argv: *i64, argc: i64) -> i64 |
| 200 | func nx_fmt_to_fd(fd: i64, fmt: *u8, argv: *i64, argc: i64) -> i64 |
| 209 | func main() -> i64 calls 1: nx_fmt_to_buf |