selfhost/cmd/ww: strip *arena cascade (γ-5)
amalloc has 0 callers post-γ-2; the *arena threaded through ww driver's importpathform / locatein / locateimport / enumeratedir / peekpackage / arenadupcstr / builddirmodulepath / buildsearchpath / resolvemodule and the expctx.a field are vestigial. Drop `import mem;`, remove expctx.a, strip *arena from 9 signatures, update 9 call sites. Drop 4 dead `let a: *arena = newarena();` in buildone/dobuild/dorun/dotest. Comments retidied. main.combined.ww auto-regenerated. builddirmodulepath body intact — still 0 callers; γ-5b drops it. arenadupcstr name is now a misnomer (task #10). Verified 132/132 incl. 993_ww_ww + 995_self_rebuild byte-identity.
This commit is contained in:
@@ -750,98 +750,6 @@ package rt;
|
||||
// a future task (task #39). ref/hare/rt/malloc.ha:27.
|
||||
@symbol("rt_malloc") export fn malloc(n: u64) *void;
|
||||
|
||||
// selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c.
|
||||
//
|
||||
// Bump arena allocator. Backed by the runtime page allocator
|
||||
// (rt_malloc / rt_free), no libc. Each chunk is mmap'd; when the
|
||||
// current chunk runs out we link a fresh one. Freeing the arena
|
||||
// unmaps the chain.
|
||||
//
|
||||
// Memory handed out is 16-byte aligned. The C version under
|
||||
// cmd/wcc/ is retained until the three-stage bootstrap diffs clean.
|
||||
|
||||
package wcc;
|
||||
|
||||
import os;
|
||||
import rt;
|
||||
|
||||
def ALIGN: u64 = 16u64;
|
||||
def INIT_CHUNK: u64 = 65536u64;
|
||||
def MAX_CHUNK: u64 = 4194304u64;
|
||||
def ARENA_SZ: u64 = 48u64; // sizeof(arena), kept in sync below
|
||||
|
||||
type arena = struct {
|
||||
buf: *u8,
|
||||
off: u64,
|
||||
cap: u64,
|
||||
next: *arena,
|
||||
total: u64,
|
||||
};
|
||||
|
||||
fn roundup(n: u64, a: u64) u64 = {
|
||||
return (n + a - 1u64) & ~(a - 1u64);
|
||||
};
|
||||
|
||||
export fn newarena() *arena = {
|
||||
let a: *arena = rt.malloc(ARENA_SZ): *arena;
|
||||
a.buf = rt.malloc(INIT_CHUNK): *u8;
|
||||
a.off = 0u64;
|
||||
a.cap = INIT_CHUNK;
|
||||
a.next = nil;
|
||||
a.total = 0u64;
|
||||
return a;
|
||||
};
|
||||
|
||||
// Grow: link a fresh chunk in front of the head. We push the old
|
||||
// chunk into `next` so the head always describes the current bump
|
||||
// region. Chunk size doubles up to MAX_CHUNK.
|
||||
fn grow(a: *arena, need: u64) bool = {
|
||||
let want: u64 = a.cap * 2u64;
|
||||
if (want < need) { want = need; };
|
||||
if (want > MAX_CHUNK) { want = MAX_CHUNK; };
|
||||
if (want < need) { return false; }; // single allocation too big
|
||||
|
||||
let old: *arena = rt.malloc(ARENA_SZ): *arena;
|
||||
old.buf = a.buf;
|
||||
old.off = a.off;
|
||||
old.cap = a.cap;
|
||||
old.next = a.next;
|
||||
old.total = 0u64;
|
||||
|
||||
a.buf = rt.malloc(want): *u8;
|
||||
a.off = 0u64;
|
||||
a.cap = want;
|
||||
a.next = old;
|
||||
return true;
|
||||
};
|
||||
|
||||
export fn amalloc(a: *arena, n: u64) *void = {
|
||||
let need: u64 = roundup(n, ALIGN);
|
||||
if (need > a.cap - a.off) {
|
||||
if (!grow(a, need)) { return nil; };
|
||||
};
|
||||
let p: *u8 = a.buf + a.off;
|
||||
a.off += need;
|
||||
a.total += need;
|
||||
// Zero the region. Plan 9 amalloc zeroes; we mirror that here so
|
||||
// the checker can assume freshly allocated nodes start at 0.
|
||||
let i: u64 = 0u64;
|
||||
for (i < need) {
|
||||
p[i] = 0u8;
|
||||
i += 1u64;
|
||||
};
|
||||
return p: *void;
|
||||
};
|
||||
|
||||
export fn freearena(a: *arena) void = {
|
||||
for (a != nil) {
|
||||
let next: *arena = a.next;
|
||||
os.free(a.buf: *void, a.cap);
|
||||
os.free(a: *void, ARENA_SZ);
|
||||
a = next;
|
||||
};
|
||||
};
|
||||
|
||||
// types — integer limits. Mirrors Hare's types::limits (I8_MAX, …)
|
||||
// platform-fixed for amd64. Numeric helpers live in lib/math, matching
|
||||
// Hare's split between types::limits and math::.
|
||||
@@ -2790,7 +2698,6 @@ package main;
|
||||
|
||||
import os;
|
||||
import rt;
|
||||
import mem;
|
||||
import strings;
|
||||
|
||||
// All path/string scratch buffers go on the runtime page allocator.
|
||||
@@ -2807,7 +2714,7 @@ fn cstrlen(p: *u8) u64 = {
|
||||
};
|
||||
|
||||
// pathstr — view a NUL-terminated *u8 as a str. Bridges the
|
||||
// driver's argv/arena *u8 paths to lib/os entrypoints (str
|
||||
// driver's argv-style *u8 paths to lib/os entrypoints (str
|
||||
// post-task-#23).
|
||||
fn pathstr(p: *u8) str = {
|
||||
let r: str;
|
||||
@@ -2978,7 +2885,6 @@ type strnode = struct {
|
||||
};
|
||||
|
||||
type expctx = struct {
|
||||
a: *arena, // arena for path strings + the visited list
|
||||
out: i32, // fd we're writing the combined source to
|
||||
dirs: *u8, // ":"-separated search path (NUL-terminated)
|
||||
visit: *strnode,
|
||||
@@ -3011,7 +2917,7 @@ fn visitadd(c: *expctx, path: str) void = {
|
||||
// use-path → fs-path mapping
|
||||
// (ref/hare/hare/module/srcs.ha:78 builds the same shape via
|
||||
// path::push per ident part).
|
||||
fn importpathform(a: *arena, name: *u8, namelen: u64) *u8 = {
|
||||
fn importpathform(name: *u8, namelen: u64) *u8 = {
|
||||
let buf: []u8 = alloc([], namelen + 1u64)!;
|
||||
let i: u64 = 0u64;
|
||||
for (i < namelen) {
|
||||
@@ -3029,7 +2935,7 @@ fn importpathform(a: *arena, name: *u8, namelen: u64) *u8 = {
|
||||
// form was dropped in task #22 — directory-as-module enumeration
|
||||
// replaces it, mirroring ref/hare/hare/module/srcs.ha (Hare has no
|
||||
// `foo/foo.ha` fallback; a module IS the directory).
|
||||
fn locatein(a: *arena, dir: *u8, dirlen: u64,
|
||||
fn locatein(dir: *u8, dirlen: u64,
|
||||
pathform: *u8, pflen: u64, isdir: *i32) *u8 = {
|
||||
let buf: []u8 = alloc([], PATH_MAX)!;
|
||||
let off: u64 = 0u64;
|
||||
@@ -3078,9 +2984,9 @@ fn locatein(a: *arena, dir: *u8, dirlen: u64,
|
||||
|
||||
// Walk a colon-separated dirlist, return first hit or nil. Sets
|
||||
// *isdir on hit.
|
||||
fn locateimport(a: *arena, dirs: *u8, name: *u8, namelen: u64,
|
||||
fn locateimport(dirs: *u8, name: *u8, namelen: u64,
|
||||
isdir: *i32) *u8 = {
|
||||
let pathform: *u8 = importpathform(a, name, namelen);
|
||||
let pathform: *u8 = importpathform(name, namelen);
|
||||
let pflen: u64 = cstrlen(pathform);
|
||||
let total: u64 = cstrlen(dirs);
|
||||
let p: u64 = 0u64;
|
||||
@@ -3092,7 +2998,7 @@ fn locateimport(a: *arena, dirs: *u8, name: *u8, namelen: u64,
|
||||
};
|
||||
let seglen: u64 = q - p;
|
||||
if (seglen > 0u64) {
|
||||
let hit: *u8 = locatein(a, dirs + p, seglen,
|
||||
let hit: *u8 = locatein(dirs + p, seglen,
|
||||
pathform, pflen, isdir);
|
||||
if (hit != nil) { return hit; };
|
||||
};
|
||||
@@ -3170,8 +3076,8 @@ fn bytecmp(a: *u8, alen: u64, b: *u8, blen: u64) i32 = {
|
||||
|
||||
// enumeratedir — list *.ww entries of `dirpath` (less *test.ww and
|
||||
// *.combined.ww), byte-sort. Returns (names[], nnames) with each
|
||||
// name a NUL-terminated arena copy.
|
||||
fn enumeratedir(a: *arena, dirpath: *u8) (**u8, i32) = {
|
||||
// name a NUL-terminated heap copy.
|
||||
fn enumeratedir(dirpath: *u8) (**u8, i32) = {
|
||||
let fd: i32 = os.open(pathstr(dirpath), os.flag.RDONLY, 0i32);
|
||||
if (fd < 0) { return nil: **u8, 0; };
|
||||
let maxnames: i32 = 256;
|
||||
@@ -3332,7 +3238,7 @@ fn expand(c: *expctx, pathcs: *u8) void = {
|
||||
idp, idn = scanuse(bufp + i, j - i);
|
||||
if (idp != nil) {
|
||||
let isdir: i32 = 0;
|
||||
let ipath: *u8 = locateimport(c.a, c.dirs, idp, idn,
|
||||
let ipath: *u8 = locateimport(c.dirs, idp, idn,
|
||||
&isdir);
|
||||
if (ipath != nil) {
|
||||
if (isdir != 0) { expanddir(c, ipath); }
|
||||
@@ -3347,9 +3253,10 @@ fn expand(c: *expctx, pathcs: *u8) void = {
|
||||
};
|
||||
|
||||
// Scan `pathcs` for its first non-comment-non-blank line; if it
|
||||
// starts with `package <name>;` return the package name as a
|
||||
// borrowed-arena str, else nil. Same shape as cstage peek_package.
|
||||
fn peekpackage(a: *arena, pathcs: *u8) *u8 = {
|
||||
// starts with `package <name>;` return the package name as a fresh
|
||||
// heap-allocated NUL-terminated *u8, else nil. Same shape as cstage
|
||||
// peek_package.
|
||||
fn peekpackage(pathcs: *u8) *u8 = {
|
||||
let fd: i32 = os.open(pathstr(pathcs), os.flag.RDONLY, 0i32);
|
||||
if (fd < 0) { return nil; };
|
||||
let buf: []u8 = alloc([], 2048u64)!;
|
||||
@@ -3451,7 +3358,7 @@ fn strictpkgmismatch(file: *u8, pkg: *u8, dirpkg: *u8, dirpath: *u8) void = {
|
||||
fn expanddir(c: *expctx, dirpath: *u8) void = {
|
||||
let names: **u8;
|
||||
let n: i32;
|
||||
names, n = enumeratedir(c.a, dirpath);
|
||||
names, n = enumeratedir(dirpath);
|
||||
let dlen: u64 = cstrlen(dirpath);
|
||||
let dirpkg: *u8 = nil;
|
||||
let i: i32 = 0;
|
||||
@@ -3464,7 +3371,7 @@ fn expanddir(c: *expctx, dirpath: *u8) void = {
|
||||
k = 0u64;
|
||||
for (k < nlen) { fp[dlen + 1u64 + k] = names[i][k]; k += 1u64; };
|
||||
fp[dlen + 1u64 + nlen] = 0u8;
|
||||
let pkg: *u8 = peekpackage(c.a, fp.ptr);
|
||||
let pkg: *u8 = peekpackage(fp.ptr);
|
||||
if (pkg != nil) {
|
||||
if (dirpkg == nil) { dirpkg = pkg; }
|
||||
else { if (!cstreq(dirpkg, pkg)) {
|
||||
@@ -3532,8 +3439,6 @@ type lflags = struct {
|
||||
// still drives the C-built w6c/w6a/w6l. Test 993 pins the two
|
||||
// pipelines to byte-identical output on a corpus.
|
||||
fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *lflags) i32 = {
|
||||
let a: *arena = newarena();
|
||||
|
||||
let c6: *u8 = joinpathlit(selfdir, "w6c_ww");
|
||||
let a6: *u8 = joinpathlit(selfdir, "w6a_ww");
|
||||
let l6: *u8 = joinpathlit(selfdir, "w6l_ww");
|
||||
@@ -3638,7 +3543,6 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l
|
||||
};
|
||||
{
|
||||
let c: expctx;
|
||||
c.a = a;
|
||||
c.out = cf;
|
||||
c.dirs = searchpath.ptr;
|
||||
c.visit = nil;
|
||||
@@ -3762,8 +3666,8 @@ fn basenameoff(p: *u8, plen: u64) u64 = {
|
||||
};
|
||||
|
||||
// arenadupcstr — copy `plen` bytes from `src` into a fresh NUL-sealed
|
||||
// arena buffer.
|
||||
fn arenadupcstr(a: *arena, src: *u8, plen: u64) *u8 = {
|
||||
// heap buffer.
|
||||
fn arenadupcstr(src: *u8, plen: u64) *u8 = {
|
||||
let buf: []u8 = alloc([], plen + 1u64)!;
|
||||
let i: u64 = 0u64;
|
||||
for (i < plen) { buf[i] = src[i]; i += 1u64; };
|
||||
@@ -3771,8 +3675,8 @@ fn arenadupcstr(a: *arena, src: *u8, plen: u64) *u8 = {
|
||||
return buf.ptr;
|
||||
};
|
||||
|
||||
// builddirmodulepath — alloc <dir>/<base>.ww, NUL-terminated, in `a`.
|
||||
fn builddirmodulepath(a: *arena, dir: *u8, dlen: u64,
|
||||
// builddirmodulepath — alloc <dir>/<base>.ww, NUL-terminated.
|
||||
fn builddirmodulepath(dir: *u8, dlen: u64,
|
||||
base: *u8, blen: u64) *u8 = {
|
||||
let need: u64 = dlen + 1u64 + blen + 3u64 + 1u64;
|
||||
let buf: []u8 = alloc([], need)!;
|
||||
@@ -3791,7 +3695,7 @@ fn builddirmodulepath(a: *arena, dir: *u8, dlen: u64,
|
||||
|
||||
// buildsearchpath — compose the colon-separated lookup path used by
|
||||
// resolvemodule's case (4). Order: "." : <incs> : <selfdir>/../../lib
|
||||
fn buildsearchpath(a: *arena, selfdir: *u8, incs: *u8) *u8 = {
|
||||
fn buildsearchpath(selfdir: *u8, incs: *u8) *u8 = {
|
||||
let buf: []u8 = alloc([], PATH_MAX * 2u64)!;
|
||||
let off: u64 = 0u64;
|
||||
buf[off] = 46u8; off += 1u64; // '.'
|
||||
@@ -3811,14 +3715,14 @@ fn buildsearchpath(a: *arena, selfdir: *u8, incs: *u8) *u8 = {
|
||||
// resolvemodule — map a name like "foo", "lib/foo", "foo.ww", or
|
||||
// "." to a concrete entry path. Sets *isdir when the entry is a
|
||||
// module directory (caller will dir-enumerate).
|
||||
fn resolvemodule(a: *arena, selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
||||
fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
||||
let nlen: u64 = cstrlen(name);
|
||||
|
||||
// (1) Literal file that exists → use as-is.
|
||||
if (cstrendswithlit(name, ".ww")) {
|
||||
if (os.access(pathstr(name), 0i32) == 0) {
|
||||
*isdir = 0;
|
||||
return arenadupcstr(a, name, nlen);
|
||||
return arenadupcstr(name, nlen);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3837,12 +3741,12 @@ fn resolvemodule(a: *arena, selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8
|
||||
};
|
||||
if (found) {
|
||||
*isdir = foundisdir;
|
||||
return arenadupcstr(a, name, nlen);
|
||||
return arenadupcstr(name, nlen);
|
||||
};
|
||||
|
||||
// (3) Search-path lookup with dot-to-slash path translation.
|
||||
let search: *u8 = buildsearchpath(a, selfdir, incs);
|
||||
return locateimport(a, search, name, nlen, isdir);
|
||||
let search: *u8 = buildsearchpath(selfdir, incs);
|
||||
return locateimport(search, name, nlen, isdir);
|
||||
};
|
||||
|
||||
// ---- Subcommand handlers ----------------------------------------------
|
||||
@@ -3891,7 +3795,6 @@ fn defaultoutpath(src: *u8) *u8 = {
|
||||
};
|
||||
|
||||
fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let a: *arena = newarena();
|
||||
let src: *u8 = nil;
|
||||
let incs: []u8 = alloc([], PATH_MAX * 2u64)!;
|
||||
incs.len = (PATH_MAX * 2u64): i32;
|
||||
@@ -3980,7 +3883,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
src = &dot[0];
|
||||
};
|
||||
let isdir: i32 = 0;
|
||||
let resolved: *u8 = resolvemodule(a, selfdir, src, incs.ptr, &isdir);
|
||||
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
|
||||
if (resolved == nil) {
|
||||
os.write(2, "ww build: cannot find module\n".ptr, 29u64);
|
||||
return 1;
|
||||
@@ -4042,7 +3945,6 @@ fn makeruntmp(buf: *u8) void = {
|
||||
};
|
||||
|
||||
fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let a: *arena = newarena();
|
||||
let src: *u8 = nil;
|
||||
let passstart: i32 = -1; // first argv idx to pass through to program
|
||||
let incs: []u8 = alloc([], PATH_MAX * 2u64)!;
|
||||
@@ -4139,7 +4041,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
src = &dot[0];
|
||||
};
|
||||
let isdir: i32 = 0;
|
||||
let resolved: *u8 = resolvemodule(a, selfdir, src, incs.ptr, &isdir);
|
||||
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
|
||||
if (resolved == nil) {
|
||||
os.write(2, "ww run: cannot find module\n".ptr, 27u64);
|
||||
return 1;
|
||||
@@ -4278,7 +4180,6 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = {
|
||||
};
|
||||
|
||||
fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let a: *arena = newarena();
|
||||
let target: *u8;
|
||||
if (start >= argc) {
|
||||
let dot: [2]u8 = ['.': u8, 0u8];
|
||||
|
||||
@@ -15,7 +15,6 @@ package main;
|
||||
|
||||
import os;
|
||||
import rt;
|
||||
import mem;
|
||||
import strings;
|
||||
|
||||
// All path/string scratch buffers go on the runtime page allocator.
|
||||
@@ -32,7 +31,7 @@ fn cstrlen(p: *u8) u64 = {
|
||||
};
|
||||
|
||||
// pathstr — view a NUL-terminated *u8 as a str. Bridges the
|
||||
// driver's argv/arena *u8 paths to lib/os entrypoints (str
|
||||
// driver's argv-style *u8 paths to lib/os entrypoints (str
|
||||
// post-task-#23).
|
||||
fn pathstr(p: *u8) str = {
|
||||
let r: str;
|
||||
@@ -203,7 +202,6 @@ type strnode = struct {
|
||||
};
|
||||
|
||||
type expctx = struct {
|
||||
a: *arena, // arena for path strings + the visited list
|
||||
out: i32, // fd we're writing the combined source to
|
||||
dirs: *u8, // ":"-separated search path (NUL-terminated)
|
||||
visit: *strnode,
|
||||
@@ -236,7 +234,7 @@ fn visitadd(c: *expctx, path: str) void = {
|
||||
// use-path → fs-path mapping
|
||||
// (ref/hare/hare/module/srcs.ha:78 builds the same shape via
|
||||
// path::push per ident part).
|
||||
fn importpathform(a: *arena, name: *u8, namelen: u64) *u8 = {
|
||||
fn importpathform(name: *u8, namelen: u64) *u8 = {
|
||||
let buf: []u8 = alloc([], namelen + 1u64)!;
|
||||
let i: u64 = 0u64;
|
||||
for (i < namelen) {
|
||||
@@ -254,7 +252,7 @@ fn importpathform(a: *arena, name: *u8, namelen: u64) *u8 = {
|
||||
// form was dropped in task #22 — directory-as-module enumeration
|
||||
// replaces it, mirroring ref/hare/hare/module/srcs.ha (Hare has no
|
||||
// `foo/foo.ha` fallback; a module IS the directory).
|
||||
fn locatein(a: *arena, dir: *u8, dirlen: u64,
|
||||
fn locatein(dir: *u8, dirlen: u64,
|
||||
pathform: *u8, pflen: u64, isdir: *i32) *u8 = {
|
||||
let buf: []u8 = alloc([], PATH_MAX)!;
|
||||
let off: u64 = 0u64;
|
||||
@@ -303,9 +301,9 @@ fn locatein(a: *arena, dir: *u8, dirlen: u64,
|
||||
|
||||
// Walk a colon-separated dirlist, return first hit or nil. Sets
|
||||
// *isdir on hit.
|
||||
fn locateimport(a: *arena, dirs: *u8, name: *u8, namelen: u64,
|
||||
fn locateimport(dirs: *u8, name: *u8, namelen: u64,
|
||||
isdir: *i32) *u8 = {
|
||||
let pathform: *u8 = importpathform(a, name, namelen);
|
||||
let pathform: *u8 = importpathform(name, namelen);
|
||||
let pflen: u64 = cstrlen(pathform);
|
||||
let total: u64 = cstrlen(dirs);
|
||||
let p: u64 = 0u64;
|
||||
@@ -317,7 +315,7 @@ fn locateimport(a: *arena, dirs: *u8, name: *u8, namelen: u64,
|
||||
};
|
||||
let seglen: u64 = q - p;
|
||||
if (seglen > 0u64) {
|
||||
let hit: *u8 = locatein(a, dirs + p, seglen,
|
||||
let hit: *u8 = locatein(dirs + p, seglen,
|
||||
pathform, pflen, isdir);
|
||||
if (hit != nil) { return hit; };
|
||||
};
|
||||
@@ -395,8 +393,8 @@ fn bytecmp(a: *u8, alen: u64, b: *u8, blen: u64) i32 = {
|
||||
|
||||
// enumeratedir — list *.ww entries of `dirpath` (less *test.ww and
|
||||
// *.combined.ww), byte-sort. Returns (names[], nnames) with each
|
||||
// name a NUL-terminated arena copy.
|
||||
fn enumeratedir(a: *arena, dirpath: *u8) (**u8, i32) = {
|
||||
// name a NUL-terminated heap copy.
|
||||
fn enumeratedir(dirpath: *u8) (**u8, i32) = {
|
||||
let fd: i32 = os.open(pathstr(dirpath), os.flag.RDONLY, 0i32);
|
||||
if (fd < 0) { return nil: **u8, 0; };
|
||||
let maxnames: i32 = 256;
|
||||
@@ -557,7 +555,7 @@ fn expand(c: *expctx, pathcs: *u8) void = {
|
||||
idp, idn = scanuse(bufp + i, j - i);
|
||||
if (idp != nil) {
|
||||
let isdir: i32 = 0;
|
||||
let ipath: *u8 = locateimport(c.a, c.dirs, idp, idn,
|
||||
let ipath: *u8 = locateimport(c.dirs, idp, idn,
|
||||
&isdir);
|
||||
if (ipath != nil) {
|
||||
if (isdir != 0) { expanddir(c, ipath); }
|
||||
@@ -572,9 +570,10 @@ fn expand(c: *expctx, pathcs: *u8) void = {
|
||||
};
|
||||
|
||||
// Scan `pathcs` for its first non-comment-non-blank line; if it
|
||||
// starts with `package <name>;` return the package name as a
|
||||
// borrowed-arena str, else nil. Same shape as cstage peek_package.
|
||||
fn peekpackage(a: *arena, pathcs: *u8) *u8 = {
|
||||
// starts with `package <name>;` return the package name as a fresh
|
||||
// heap-allocated NUL-terminated *u8, else nil. Same shape as cstage
|
||||
// peek_package.
|
||||
fn peekpackage(pathcs: *u8) *u8 = {
|
||||
let fd: i32 = os.open(pathstr(pathcs), os.flag.RDONLY, 0i32);
|
||||
if (fd < 0) { return nil; };
|
||||
let buf: []u8 = alloc([], 2048u64)!;
|
||||
@@ -676,7 +675,7 @@ fn strictpkgmismatch(file: *u8, pkg: *u8, dirpkg: *u8, dirpath: *u8) void = {
|
||||
fn expanddir(c: *expctx, dirpath: *u8) void = {
|
||||
let names: **u8;
|
||||
let n: i32;
|
||||
names, n = enumeratedir(c.a, dirpath);
|
||||
names, n = enumeratedir(dirpath);
|
||||
let dlen: u64 = cstrlen(dirpath);
|
||||
let dirpkg: *u8 = nil;
|
||||
let i: i32 = 0;
|
||||
@@ -689,7 +688,7 @@ fn expanddir(c: *expctx, dirpath: *u8) void = {
|
||||
k = 0u64;
|
||||
for (k < nlen) { fp[dlen + 1u64 + k] = names[i][k]; k += 1u64; };
|
||||
fp[dlen + 1u64 + nlen] = 0u8;
|
||||
let pkg: *u8 = peekpackage(c.a, fp.ptr);
|
||||
let pkg: *u8 = peekpackage(fp.ptr);
|
||||
if (pkg != nil) {
|
||||
if (dirpkg == nil) { dirpkg = pkg; }
|
||||
else { if (!cstreq(dirpkg, pkg)) {
|
||||
@@ -757,8 +756,6 @@ type lflags = struct {
|
||||
// still drives the C-built w6c/w6a/w6l. Test 993 pins the two
|
||||
// pipelines to byte-identical output on a corpus.
|
||||
fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *lflags) i32 = {
|
||||
let a: *arena = newarena();
|
||||
|
||||
let c6: *u8 = joinpathlit(selfdir, "w6c_ww");
|
||||
let a6: *u8 = joinpathlit(selfdir, "w6a_ww");
|
||||
let l6: *u8 = joinpathlit(selfdir, "w6l_ww");
|
||||
@@ -863,7 +860,6 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l
|
||||
};
|
||||
{
|
||||
let c: expctx;
|
||||
c.a = a;
|
||||
c.out = cf;
|
||||
c.dirs = searchpath.ptr;
|
||||
c.visit = nil;
|
||||
@@ -987,8 +983,8 @@ fn basenameoff(p: *u8, plen: u64) u64 = {
|
||||
};
|
||||
|
||||
// arenadupcstr — copy `plen` bytes from `src` into a fresh NUL-sealed
|
||||
// arena buffer.
|
||||
fn arenadupcstr(a: *arena, src: *u8, plen: u64) *u8 = {
|
||||
// heap buffer.
|
||||
fn arenadupcstr(src: *u8, plen: u64) *u8 = {
|
||||
let buf: []u8 = alloc([], plen + 1u64)!;
|
||||
let i: u64 = 0u64;
|
||||
for (i < plen) { buf[i] = src[i]; i += 1u64; };
|
||||
@@ -996,8 +992,8 @@ fn arenadupcstr(a: *arena, src: *u8, plen: u64) *u8 = {
|
||||
return buf.ptr;
|
||||
};
|
||||
|
||||
// builddirmodulepath — alloc <dir>/<base>.ww, NUL-terminated, in `a`.
|
||||
fn builddirmodulepath(a: *arena, dir: *u8, dlen: u64,
|
||||
// builddirmodulepath — alloc <dir>/<base>.ww, NUL-terminated.
|
||||
fn builddirmodulepath(dir: *u8, dlen: u64,
|
||||
base: *u8, blen: u64) *u8 = {
|
||||
let need: u64 = dlen + 1u64 + blen + 3u64 + 1u64;
|
||||
let buf: []u8 = alloc([], need)!;
|
||||
@@ -1016,7 +1012,7 @@ fn builddirmodulepath(a: *arena, dir: *u8, dlen: u64,
|
||||
|
||||
// buildsearchpath — compose the colon-separated lookup path used by
|
||||
// resolvemodule's case (4). Order: "." : <incs> : <selfdir>/../../lib
|
||||
fn buildsearchpath(a: *arena, selfdir: *u8, incs: *u8) *u8 = {
|
||||
fn buildsearchpath(selfdir: *u8, incs: *u8) *u8 = {
|
||||
let buf: []u8 = alloc([], PATH_MAX * 2u64)!;
|
||||
let off: u64 = 0u64;
|
||||
buf[off] = 46u8; off += 1u64; // '.'
|
||||
@@ -1036,14 +1032,14 @@ fn buildsearchpath(a: *arena, selfdir: *u8, incs: *u8) *u8 = {
|
||||
// resolvemodule — map a name like "foo", "lib/foo", "foo.ww", or
|
||||
// "." to a concrete entry path. Sets *isdir when the entry is a
|
||||
// module directory (caller will dir-enumerate).
|
||||
fn resolvemodule(a: *arena, selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
||||
fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
||||
let nlen: u64 = cstrlen(name);
|
||||
|
||||
// (1) Literal file that exists → use as-is.
|
||||
if (cstrendswithlit(name, ".ww")) {
|
||||
if (os.access(pathstr(name), 0i32) == 0) {
|
||||
*isdir = 0;
|
||||
return arenadupcstr(a, name, nlen);
|
||||
return arenadupcstr(name, nlen);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1062,12 +1058,12 @@ fn resolvemodule(a: *arena, selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8
|
||||
};
|
||||
if (found) {
|
||||
*isdir = foundisdir;
|
||||
return arenadupcstr(a, name, nlen);
|
||||
return arenadupcstr(name, nlen);
|
||||
};
|
||||
|
||||
// (3) Search-path lookup with dot-to-slash path translation.
|
||||
let search: *u8 = buildsearchpath(a, selfdir, incs);
|
||||
return locateimport(a, search, name, nlen, isdir);
|
||||
let search: *u8 = buildsearchpath(selfdir, incs);
|
||||
return locateimport(search, name, nlen, isdir);
|
||||
};
|
||||
|
||||
// ---- Subcommand handlers ----------------------------------------------
|
||||
@@ -1116,7 +1112,6 @@ fn defaultoutpath(src: *u8) *u8 = {
|
||||
};
|
||||
|
||||
fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let a: *arena = newarena();
|
||||
let src: *u8 = nil;
|
||||
let incs: []u8 = alloc([], PATH_MAX * 2u64)!;
|
||||
incs.len = (PATH_MAX * 2u64): i32;
|
||||
@@ -1205,7 +1200,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
src = &dot[0];
|
||||
};
|
||||
let isdir: i32 = 0;
|
||||
let resolved: *u8 = resolvemodule(a, selfdir, src, incs.ptr, &isdir);
|
||||
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
|
||||
if (resolved == nil) {
|
||||
os.write(2, "ww build: cannot find module\n".ptr, 29u64);
|
||||
return 1;
|
||||
@@ -1267,7 +1262,6 @@ fn makeruntmp(buf: *u8) void = {
|
||||
};
|
||||
|
||||
fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let a: *arena = newarena();
|
||||
let src: *u8 = nil;
|
||||
let passstart: i32 = -1; // first argv idx to pass through to program
|
||||
let incs: []u8 = alloc([], PATH_MAX * 2u64)!;
|
||||
@@ -1364,7 +1358,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
src = &dot[0];
|
||||
};
|
||||
let isdir: i32 = 0;
|
||||
let resolved: *u8 = resolvemodule(a, selfdir, src, incs.ptr, &isdir);
|
||||
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
|
||||
if (resolved == nil) {
|
||||
os.write(2, "ww run: cannot find module\n".ptr, 27u64);
|
||||
return 1;
|
||||
@@ -1503,7 +1497,6 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = {
|
||||
};
|
||||
|
||||
fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let a: *arena = newarena();
|
||||
let target: *u8;
|
||||
if (start >= argc) {
|
||||
let dot: [2]u8 = ['.': u8, 0u8];
|
||||
|
||||
Reference in New Issue
Block a user