ww: select sources by Go platform suffixes
This commit is contained in:
@@ -563,6 +563,105 @@ def SEP_LOAD_VENDOR: i32 = -4;
|
||||
def SEP_INITIAL_CAP: i32 = 8;
|
||||
def SEP_COUNT_MAX: i32 = 2147483647;
|
||||
|
||||
fn sepnamerangeis(name: *u8, start: u64, end: u64, word: str) bool = {
|
||||
if (end < start || end - start != word.len: u64) { return false; };
|
||||
let i: u64 = 0u64;
|
||||
for (i < end - start) {
|
||||
if (name[start + i] != word.ptr[i]) { return false; };
|
||||
i += 1u64;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
fn sepknownos(name: *u8, start: u64, end: u64) bool = {
|
||||
return sepnamerangeis(name, start, end, "aix")
|
||||
|| sepnamerangeis(name, start, end, "android")
|
||||
|| sepnamerangeis(name, start, end, "darwin")
|
||||
|| sepnamerangeis(name, start, end, "dragonfly")
|
||||
|| sepnamerangeis(name, start, end, "freebsd")
|
||||
|| sepnamerangeis(name, start, end, "hurd")
|
||||
|| sepnamerangeis(name, start, end, "illumos")
|
||||
|| sepnamerangeis(name, start, end, "ios")
|
||||
|| sepnamerangeis(name, start, end, "js")
|
||||
|| sepnamerangeis(name, start, end, "linux")
|
||||
|| sepnamerangeis(name, start, end, "nacl")
|
||||
|| sepnamerangeis(name, start, end, "netbsd")
|
||||
|| sepnamerangeis(name, start, end, "openbsd")
|
||||
|| sepnamerangeis(name, start, end, "plan9")
|
||||
|| sepnamerangeis(name, start, end, "solaris")
|
||||
|| sepnamerangeis(name, start, end, "wasip1")
|
||||
|| sepnamerangeis(name, start, end, "windows")
|
||||
|| sepnamerangeis(name, start, end, "zos");
|
||||
};
|
||||
|
||||
fn sepknownarch(name: *u8, start: u64, end: u64) bool = {
|
||||
return sepnamerangeis(name, start, end, "386")
|
||||
|| sepnamerangeis(name, start, end, "amd64")
|
||||
|| sepnamerangeis(name, start, end, "amd64p32")
|
||||
|| sepnamerangeis(name, start, end, "arm")
|
||||
|| sepnamerangeis(name, start, end, "armbe")
|
||||
|| sepnamerangeis(name, start, end, "arm64")
|
||||
|| sepnamerangeis(name, start, end, "arm64be")
|
||||
|| sepnamerangeis(name, start, end, "loong64")
|
||||
|| sepnamerangeis(name, start, end, "mips")
|
||||
|| sepnamerangeis(name, start, end, "mipsle")
|
||||
|| sepnamerangeis(name, start, end, "mips64")
|
||||
|| sepnamerangeis(name, start, end, "mips64le")
|
||||
|| sepnamerangeis(name, start, end, "mips64p32")
|
||||
|| sepnamerangeis(name, start, end, "mips64p32le")
|
||||
|| sepnamerangeis(name, start, end, "ppc")
|
||||
|| sepnamerangeis(name, start, end, "ppc64")
|
||||
|| sepnamerangeis(name, start, end, "ppc64le")
|
||||
|| sepnamerangeis(name, start, end, "riscv")
|
||||
|| sepnamerangeis(name, start, end, "riscv64")
|
||||
|| sepnamerangeis(name, start, end, "s390")
|
||||
|| sepnamerangeis(name, start, end, "s390x")
|
||||
|| sepnamerangeis(name, start, end, "sparc")
|
||||
|| sepnamerangeis(name, start, end, "sparc64")
|
||||
|| sepnamerangeis(name, start, end, "wasm");
|
||||
};
|
||||
|
||||
fn septargettag(name: *u8, start: u64, end: u64) bool = {
|
||||
return sepnamerangeis(name, start, end, "linux")
|
||||
|| sepnamerangeis(name, start, end, "amd64");
|
||||
};
|
||||
|
||||
// Go 1.26.5 build.go:1980-2027 filters known platform suffixes before
|
||||
// opening a source. WW currently has one honest target, linux/amd64.
|
||||
fn sepsourcematchestarget(name: *u8, nlen: u64) bool = {
|
||||
let stem: u64 = 0u64;
|
||||
let hasunderscore: bool = false;
|
||||
for (stem < nlen && name[stem] != '.') {
|
||||
if (name[stem] == '_') { hasunderscore = true; };
|
||||
stem += 1u64;
|
||||
};
|
||||
if (!hasunderscore) { return true; };
|
||||
|
||||
let end: u64 = stem;
|
||||
let last: u64 = end;
|
||||
for (last > 0u64 && name[last - 1u64] != '_') { last -= 1u64; };
|
||||
if (sepnamerangeis(name, last, end, "test")) {
|
||||
if (last == 0u64) { return true; };
|
||||
end = last - 1u64;
|
||||
last = end;
|
||||
for (last > 0u64 && name[last - 1u64] != '_') { last -= 1u64; };
|
||||
};
|
||||
if (last == 0u64) { return true; };
|
||||
|
||||
let prevend: u64 = last - 1u64;
|
||||
let prev: u64 = prevend;
|
||||
for (prev > 0u64 && name[prev - 1u64] != '_') { prev -= 1u64; };
|
||||
if (prev < prevend && sepknownos(name, prev, prevend)
|
||||
&& sepknownarch(name, last, end)) {
|
||||
return septargettag(name, last, end)
|
||||
&& septargettag(name, prev, prevend);
|
||||
};
|
||||
if (sepknownos(name, last, end) || sepknownarch(name, last, end)) {
|
||||
return septargettag(name, last, end);
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
// Classify a selected directory entry: 1 production, 2 test, 0 skipped,
|
||||
// -1 @test outside *_test.ww, -2 non-regular source.
|
||||
fn dirfileclass(dirpath: *u8, name: *u8, nlen: u64,
|
||||
@@ -575,10 +674,12 @@ fn dirfileclass(dirpath: *u8, name: *u8, nlen: u64,
|
||||
s.ptr = name;
|
||||
s.len = nlen: i32;
|
||||
if (!strings.hassuffix(s, ".ww")) { return 0; };
|
||||
if (!sepsourcematchestarget(name, nlen)) { return 0; };
|
||||
let istest: bool = strings.hassuffix(s, "_test.ww");
|
||||
if (istest && variant == SEP_VARIANT_PRODUCTION) { return 0; };
|
||||
if (!istest && variant == SEP_VARIANT_EXTERNAL) { return 0; };
|
||||
let source: *u8 = joinpath(dirpath, name);
|
||||
let source: *u8 = sepjoinpath(dirpath, name);
|
||||
if (source == nil) { return -2; };
|
||||
let fi: os.filestat;
|
||||
let sr: (void | os.oserror) = os.lstat(&fi, pathstr(source));
|
||||
let regular: bool = false;
|
||||
@@ -695,31 +796,11 @@ fn enumeratedir(dirpath: *u8, variant: i32,
|
||||
let reclen: u64 = blo + (bhi * 256u64);
|
||||
let nm: *u8 = buf.ptr + off + 19u64;
|
||||
let nl: u64 = cstrlen(nm);
|
||||
let cls: i32 = dirfileclass(dirpath, nm, nl, variant);
|
||||
if (cls == -1) {
|
||||
cerr("ww: ");
|
||||
cerr(pathstr(joinpath(dirpath, nm)));
|
||||
cerr(": @test declaration outside *_test.ww\n");
|
||||
os.close(fd);
|
||||
return nil: **u8, -2;
|
||||
};
|
||||
if (cls == -2) {
|
||||
os.close(fd);
|
||||
return nil: **u8, -2;
|
||||
};
|
||||
if (cls > 0) {
|
||||
let full: *u8 = joinpath(dirpath, nm);
|
||||
if (cls == 2) {
|
||||
let pn: *u8 = dirpackagename(full);
|
||||
if (pn == nil) {
|
||||
os.close(fd);
|
||||
return nil: **u8, -2;
|
||||
};
|
||||
if (testpackage == nil || !cstreq(pn, testpackage)) {
|
||||
off += reclen;
|
||||
continue;
|
||||
};
|
||||
};
|
||||
if (nl > 3u64 && nm[0] != '.' && nm[0] != '_') {
|
||||
let view: str;
|
||||
view.ptr = nm;
|
||||
view.len = nl: i32;
|
||||
if (strings.hassuffix(view, ".ww")) {
|
||||
if (n == SEP_COUNT_MAX) {
|
||||
sepfailsize();
|
||||
os.close(fd);
|
||||
@@ -730,10 +811,16 @@ fn enumeratedir(dirpath: *u8, variant: i32,
|
||||
os.close(fd);
|
||||
return nil: **u8, -2;
|
||||
};
|
||||
names[n] = full;
|
||||
nlens[n] = cstrlen(full);
|
||||
kinds[n] = cls;
|
||||
let owned: *u8 = sepdupcstr(nm, nl);
|
||||
if (owned == nil) {
|
||||
os.close(fd);
|
||||
return nil: **u8, -2;
|
||||
};
|
||||
names[n] = owned;
|
||||
nlens[n] = nl;
|
||||
kinds[n] = 0;
|
||||
n += 1;
|
||||
};
|
||||
};
|
||||
off += reclen;
|
||||
};
|
||||
@@ -749,8 +836,69 @@ fn enumeratedir(dirpath: *u8, variant: i32,
|
||||
return nil: **u8, -1;
|
||||
};
|
||||
|
||||
// Insertion sort, byte-wise. n is small (≤16 in practice).
|
||||
// Go's directory reader presents a byte-sorted name list to the loader.
|
||||
let i: i32 = 1;
|
||||
for (i < n) {
|
||||
let j: i32 = i;
|
||||
for (j > 0) {
|
||||
let c: i32 = bytecmp(names[j - 1], nlens[j - 1],
|
||||
names[j], nlens[j]);
|
||||
if (c <= 0) { j = 0; }
|
||||
else {
|
||||
let t: *u8 = names[j];
|
||||
names[j] = names[j - 1];
|
||||
names[j - 1] = t;
|
||||
let tl: u64 = nlens[j];
|
||||
nlens[j] = nlens[j - 1];
|
||||
nlens[j - 1] = tl;
|
||||
let tk: i32 = kinds[j];
|
||||
kinds[j] = kinds[j - 1];
|
||||
kinds[j - 1] = tk;
|
||||
j -= 1;
|
||||
};
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
let raw: i32 = n;
|
||||
let selected: i32 = 0;
|
||||
let ri: i32 = 0;
|
||||
for (ri < raw) {
|
||||
let nm: *u8 = names[ri];
|
||||
let nl: u64 = nlens[ri];
|
||||
let cls: i32 = dirfileclass(dirpath, nm, nl, variant);
|
||||
if (cls == -1) {
|
||||
let badpath: *u8 = sepjoinpath(dirpath, nm);
|
||||
if (badpath == nil) { return nil: **u8, -2; };
|
||||
cerr("ww: ");
|
||||
cerr(pathstr(badpath));
|
||||
cerr(": @test declaration outside *_test.ww\n");
|
||||
return nil: **u8, -2;
|
||||
};
|
||||
if (cls == -2) { return nil: **u8, -2; };
|
||||
if (cls > 0) {
|
||||
let full: *u8 = sepjoinpath(dirpath, nm);
|
||||
if (full == nil) { return nil: **u8, -2; };
|
||||
let keep: bool = true;
|
||||
if (cls == 2) {
|
||||
let pn: *u8 = dirpackagename(full);
|
||||
if (pn == nil) { return nil: **u8, -2; };
|
||||
if (testpackage == nil || !cstreq(pn, testpackage)) {
|
||||
keep = false;
|
||||
};
|
||||
};
|
||||
if (keep) {
|
||||
names[selected] = full;
|
||||
nlens[selected] = cstrlen(full);
|
||||
kinds[selected] = cls;
|
||||
selected += 1;
|
||||
};
|
||||
};
|
||||
ri += 1;
|
||||
};
|
||||
n = selected;
|
||||
|
||||
// Production files precede test files; each partition remains byte-sorted.
|
||||
i = 1;
|
||||
for (i < n) {
|
||||
let j: i32 = i;
|
||||
for (j > 0) {
|
||||
@@ -4981,14 +5129,14 @@ fn validatecommandoutputpath(out: *u8) i32 = {
|
||||
fn workdirstamptext(istest: i32, emitasm: i32) str = {
|
||||
if (istest != 0) {
|
||||
if (emitasm != 0) {
|
||||
return "ww workdir fmt 16 mode test asm 1\n";
|
||||
return "ww workdir fmt 17 mode test asm 1\n";
|
||||
};
|
||||
return "ww workdir fmt 16 mode test asm 0\n";
|
||||
return "ww workdir fmt 17 mode test asm 0\n";
|
||||
};
|
||||
if (emitasm != 0) {
|
||||
return "ww workdir fmt 17 mode build asm 1\n";
|
||||
return "ww workdir fmt 18 mode build asm 1\n";
|
||||
};
|
||||
return "ww workdir fmt 17 mode build asm 0\n";
|
||||
return "ww workdir fmt 18 mode build asm 0\n";
|
||||
};
|
||||
|
||||
fn stampmatches(path: *u8, want: str) bool = {
|
||||
|
||||
Reference in New Issue
Block a user