ww+wcc: emit and lex // MODULE: <name> directive in combined.ww
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// MODULE: os
|
||||
// os — process and filesystem facade. The body of each call lands
|
||||
// either in libwwrt.a (rt_syscall trampoline) or libc bindings,
|
||||
// depending on how the program was linked.
|
||||
@@ -207,6 +208,7 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = {
|
||||
return syscall3(SYS_GETDENTS64, fd: i64, buf: i64, n: i64);
|
||||
};
|
||||
|
||||
// MODULE: wcc
|
||||
// selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c.
|
||||
//
|
||||
// Bump arena allocator. Backed by the runtime page allocator
|
||||
@@ -314,6 +316,7 @@ export fn freearena(a: *arena) void = {
|
||||
};
|
||||
};
|
||||
|
||||
// MODULE: ww
|
||||
// selfhost/cmd/ww/main.ww — port of cmd/ww/main.c.
|
||||
//
|
||||
// The user-facing driver. Plan 9 cc(1) / Hare hare(1) analogue:
|
||||
@@ -652,6 +655,50 @@ fn scanuse(src: *u8, len: u64) (*u8, u64) = {
|
||||
|
||||
// Recursively expand `path` into c.out. Imported files are emitted
|
||||
// before their importer; cycles are broken via the visited set.
|
||||
// modulename — pick the source's containing-directory basename. So
|
||||
// `lib/os/os.ww` → "os"; `selfhost/cmd/wcc/sym.ww` → "wcc". Falls back
|
||||
// to the file's own basename (sans .ww) when there is no parent dir.
|
||||
// Returns ("",0) if `path` ends in a '/' (degenerate).
|
||||
fn modulename(path: *u8, plen: u64) (*u8, u64) = {
|
||||
if (plen == 0u64) { return nil, 0u64; };
|
||||
// Find the last '/'.
|
||||
let last: u64 = plen;
|
||||
let i: u64 = plen;
|
||||
for (i > 0u64) {
|
||||
i -= 1u64;
|
||||
if (path[i] == 47u8) { last = i; i = 0u64; }
|
||||
else { if (i == 0u64) { last = plen; }; };
|
||||
};
|
||||
if (last == plen) {
|
||||
// No '/' — path is a bare filename. Use its stem.
|
||||
let n: u64 = plen;
|
||||
if (n >= 3u64) {
|
||||
if (path[n - 3u64] == 46u8) {
|
||||
if (path[n - 2u64] == 119u8) {
|
||||
if (path[n - 1u64] == 119u8) {
|
||||
n = n - 3u64;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
return path, n;
|
||||
};
|
||||
// Find the '/' before `last` — segment between is the dir basename.
|
||||
let prev: u64 = 0u64;
|
||||
let found: bool = false;
|
||||
let j: u64 = last;
|
||||
for (j > 0u64) {
|
||||
j -= 1u64;
|
||||
if (path[j] == 47u8) {
|
||||
prev = j + 1u64;
|
||||
found = true;
|
||||
j = 0u64;
|
||||
};
|
||||
};
|
||||
if (!found) { prev = 0u64; };
|
||||
return path + prev, last - prev;
|
||||
};
|
||||
|
||||
fn expand(c: *expctx, path_cs: *u8) void = {
|
||||
let plen: u64 = cstrlen(path_cs);
|
||||
let pathstr: str = astrndup(c.a, path_cs, plen);
|
||||
@@ -687,7 +734,19 @@ fn expand(c: *expctx, path_cs: *u8) void = {
|
||||
i = j + 1u64;
|
||||
};
|
||||
|
||||
// Pass 2: emit our own bytes, then a trailing newline.
|
||||
// Pass 2: prefix a `// MODULE: <name>` directive, then emit our
|
||||
// bytes. The marker is a comment to the C-side wcc and any other
|
||||
// reader; the ww-side wcc lexer recognises it and stamps each
|
||||
// top-level decl with the originating module so cgen can mangle
|
||||
// non-exported names by module.
|
||||
let mp: *u8;
|
||||
let mn: u64;
|
||||
mp, mn = modulename(path_cs, plen);
|
||||
if (mn > 0u64) {
|
||||
os.writefull(c.out, "// MODULE: ".ptr, 11u64);
|
||||
os.writefull(c.out, mp, mn);
|
||||
os.writefull(c.out, "\n".ptr, 1u64);
|
||||
};
|
||||
os.writefull(c.out, bufp, blen);
|
||||
os.writefull(c.out, "\n".ptr, 1u64);
|
||||
};
|
||||
|
||||
@@ -336,6 +336,50 @@ fn scanuse(src: *u8, len: u64) (*u8, u64) = {
|
||||
|
||||
// Recursively expand `path` into c.out. Imported files are emitted
|
||||
// before their importer; cycles are broken via the visited set.
|
||||
// modulename — pick the source's containing-directory basename. So
|
||||
// `lib/os/os.ww` → "os"; `selfhost/cmd/wcc/sym.ww` → "wcc". Falls back
|
||||
// to the file's own basename (sans .ww) when there is no parent dir.
|
||||
// Returns ("",0) if `path` ends in a '/' (degenerate).
|
||||
fn modulename(path: *u8, plen: u64) (*u8, u64) = {
|
||||
if (plen == 0u64) { return nil, 0u64; };
|
||||
// Find the last '/'.
|
||||
let last: u64 = plen;
|
||||
let i: u64 = plen;
|
||||
for (i > 0u64) {
|
||||
i -= 1u64;
|
||||
if (path[i] == 47u8) { last = i; i = 0u64; }
|
||||
else { if (i == 0u64) { last = plen; }; };
|
||||
};
|
||||
if (last == plen) {
|
||||
// No '/' — path is a bare filename. Use its stem.
|
||||
let n: u64 = plen;
|
||||
if (n >= 3u64) {
|
||||
if (path[n - 3u64] == 46u8) {
|
||||
if (path[n - 2u64] == 119u8) {
|
||||
if (path[n - 1u64] == 119u8) {
|
||||
n = n - 3u64;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
return path, n;
|
||||
};
|
||||
// Find the '/' before `last` — segment between is the dir basename.
|
||||
let prev: u64 = 0u64;
|
||||
let found: bool = false;
|
||||
let j: u64 = last;
|
||||
for (j > 0u64) {
|
||||
j -= 1u64;
|
||||
if (path[j] == 47u8) {
|
||||
prev = j + 1u64;
|
||||
found = true;
|
||||
j = 0u64;
|
||||
};
|
||||
};
|
||||
if (!found) { prev = 0u64; };
|
||||
return path + prev, last - prev;
|
||||
};
|
||||
|
||||
fn expand(c: *expctx, path_cs: *u8) void = {
|
||||
let plen: u64 = cstrlen(path_cs);
|
||||
let pathstr: str = astrndup(c.a, path_cs, plen);
|
||||
@@ -371,7 +415,19 @@ fn expand(c: *expctx, path_cs: *u8) void = {
|
||||
i = j + 1u64;
|
||||
};
|
||||
|
||||
// Pass 2: emit our own bytes, then a trailing newline.
|
||||
// Pass 2: prefix a `// MODULE: <name>` directive, then emit our
|
||||
// bytes. The marker is a comment to the C-side wcc and any other
|
||||
// reader; the ww-side wcc lexer recognises it and stamps each
|
||||
// top-level decl with the originating module so cgen can mangle
|
||||
// non-exported names by module.
|
||||
let mp: *u8;
|
||||
let mn: u64;
|
||||
mp, mn = modulename(path_cs, plen);
|
||||
if (mn > 0u64) {
|
||||
os.writefull(c.out, "// MODULE: ".ptr, 11u64);
|
||||
os.writefull(c.out, mp, mn);
|
||||
os.writefull(c.out, "\n".ptr, 1u64);
|
||||
};
|
||||
os.writefull(c.out, bufp, blen);
|
||||
os.writefull(c.out, "\n".ptr, 1u64);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user