lib/memio+shlex+getopt: use os.alloc / os.free; drop @symbol bindings
Migrate the three modules that still carried private
@symbol("rt_alloc") / @symbol("rt_free") bindings onto the public
lib/os.alloc / lib/os.free surface that landed in 87c0883.
memio: 1 alloc (grow) + 2 free (grow's old-buffer drop, dynamicclose).
shlex: 1 alloc (dupstr) + 2 free (freepartial: element strs + slice
header). getopt: 1 alloc (tryparse) + 2 free (tryparse + finish).
ABI identity holds — same rt syms, same shapes, just routed through
the public surface.
rt_ensure stays inline in shlex + getopt; the slice-growth helper
isn't part of os and has no stdlib facade. Comments explain why.
Header rationale comments updated: dropped the now-stale
"lib/io ↔ lib/os C-symbol collision" framing on shlex's inlined
dupstr (that was a pre-#9 concern); reworded shlex's OOM trailer to
match lib/os.ww's documented contract (poisonous pointer, not nil,
fault on deref); fixed memio's dynamicfrom doc to reference
[[os.free]] instead of the retired rt_free name.
980_memio_run / 973_shlex_run / 982_getopt_run all green; bootstrap
byte-identical.
This commit is contained in:
@@ -28,9 +28,10 @@
|
||||
//
|
||||
// Divergences from Hare:
|
||||
//
|
||||
// - Drop nomem: ww os.alloc aborts on OOM (same precedent as
|
||||
// strings.dup, getopt.appendoption). Hare's
|
||||
// (...|syntaxerr|nomem) collapses to (...|syntaxerr).
|
||||
// - Drop nomem: ww os.alloc has no recoverable failure path (OOM
|
||||
// yields a poisonous pointer that faults on deref; see lib/os.ww
|
||||
// comment). Same precedent as strings.dup, getopt.appendoption.
|
||||
// Hare's (...|syntaxerr|nomem) collapses to (...|syntaxerr).
|
||||
//
|
||||
// - Byte-wise iteration via i32 cursor instead of Hare's
|
||||
// strings::iterator (no UTF-8 rune iteration in the language
|
||||
@@ -66,13 +67,10 @@
|
||||
// greppable across modules. When the append-builtin is fixed,
|
||||
// all three (getopt, shlex, anywhere else) collapse in one go.
|
||||
//
|
||||
// - Internal [[dupstr]] inlined rather than `use strings;`: lib/io
|
||||
// and lib/os both export read/write/close as C symbols with
|
||||
// different signatures, and `use strings;` would transitively
|
||||
// pull `use os;` (strings:6) which collides with `use io;` here.
|
||||
// Same defensive shape lib/fmt and lib/memio use until task #17
|
||||
// (cgen module-mangles fn labels) lands; at that point dupstr
|
||||
// graduates to strings.dup and the workaround retires.
|
||||
// - Internal [[dupstr]] inlined rather than `use strings;`: keeps
|
||||
// the dep surface small for a 6-line helper. shlex doesn't reach
|
||||
// for any other strings:: routine, and callers free split()'s
|
||||
// result via [[strings.freeall]] directly.
|
||||
//
|
||||
// Caller layout — split:
|
||||
//
|
||||
@@ -96,18 +94,13 @@
|
||||
|
||||
use io;
|
||||
use memio;
|
||||
use os;
|
||||
|
||||
// Direct rt_alloc / rt_free / rt_ensure bindings rather than `use os;`
|
||||
// — os exports read/write/close, which collide with io.read/write/close
|
||||
// under the driver's flat-scope concat. Same workaround as lib/memio,
|
||||
// lib/fmt, lib/log; retires when task #17 (cgen mod-mangling) lands.
|
||||
//
|
||||
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||
// `append(s, v)` builtin. We bind it directly because the builtin's
|
||||
// expansion stores only 8 bytes of the new element (cgen emits a
|
||||
// single MOVQ), losing the `len` half of a `str` (16B).
|
||||
@symbol("rt_alloc") fn rtalloc(n: u64) *void;
|
||||
@symbol("rt_free") fn rtfree(p: *void, n: u64) void;
|
||||
// single MOVQ), losing the `len` half of a `str` (16B). No public
|
||||
// stdlib facade exposes it, hence the direct @symbol.
|
||||
@symbol("rt_ensure") fn rtensure(s: *void, membsz: u64) void;
|
||||
|
||||
// syntaxerr — the input wasn't a valid shell-tokenizable string
|
||||
@@ -122,16 +115,15 @@ export fn strerror(err: syntaxerr) str = {
|
||||
return "Invalid shell syntax";
|
||||
};
|
||||
|
||||
// dupstr — local strings.dup. Inlined to keep `use strings;` out of
|
||||
// this module (would re-trip the lib/io ↔ lib/os C-symbol collision;
|
||||
// see file header). Same algorithm and same {nil, 0} handling for
|
||||
// empty input. Retires when task #17 lands.
|
||||
// dupstr — local strings.dup. Inlined to avoid a `use strings;` dep
|
||||
// on this small site; same algorithm and same {nil, 0} handling for
|
||||
// empty input.
|
||||
fn dupstr(s: str) str = {
|
||||
let r: str;
|
||||
r.ptr = nil;
|
||||
r.len = 0;
|
||||
if (s.len == 0) { return r; };
|
||||
let buf: *u8 = rtalloc(s.len: u64): *u8;
|
||||
let buf: *u8 = os.alloc(s.len: u64): *u8;
|
||||
let i: i32 = 0;
|
||||
for (i < s.len) { buf[i] = s[i]; i += 1; };
|
||||
r.ptr = buf;
|
||||
@@ -160,12 +152,12 @@ fn freepartial(slice: []str) void = {
|
||||
let i: i32 = 0;
|
||||
for (i < slice.len) {
|
||||
if (slice[i].len > 0) {
|
||||
rtfree(slice[i].ptr: *void, slice[i].len: u64);
|
||||
os.free(slice[i].ptr: *void, slice[i].len: u64);
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
if (slice.cap > 0) {
|
||||
rtfree(slice.ptr: *void, (slice.cap: u64) * 16u64);
|
||||
os.free(slice.ptr: *void, (slice.cap: u64) * 16u64);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user