ww: select sources by Go platform suffixes
This commit is contained in:
121
cmd/ww/main.c
121
cmd/ww/main.c
@@ -372,6 +372,79 @@ strs_cmp(const void *a, const void *b)
|
||||
return strcmp(sa, sb);
|
||||
}
|
||||
|
||||
static int
|
||||
sep_name_is(const char *s, size_t n, const char *word)
|
||||
{
|
||||
return strlen(word) == n && memcmp(s, word, n) == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sep_known_os(const char *s, size_t n)
|
||||
{
|
||||
static const char *known[] = {
|
||||
"aix", "android", "darwin", "dragonfly", "freebsd", "hurd",
|
||||
"illumos", "ios", "js", "linux", "nacl", "netbsd", "openbsd",
|
||||
"plan9", "solaris", "wasip1", "windows", "zos",
|
||||
};
|
||||
for (size_t i = 0; i < sizeof known / sizeof known[0]; i++)
|
||||
if (sep_name_is(s, n, known[i])) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sep_known_arch(const char *s, size_t n)
|
||||
{
|
||||
static const char *known[] = {
|
||||
"386", "amd64", "amd64p32", "arm", "armbe", "arm64", "arm64be",
|
||||
"loong64", "mips", "mipsle", "mips64", "mips64le", "mips64p32",
|
||||
"mips64p32le", "ppc", "ppc64", "ppc64le", "riscv", "riscv64",
|
||||
"s390", "s390x", "sparc", "sparc64", "wasm",
|
||||
};
|
||||
for (size_t i = 0; i < sizeof known / sizeof known[0]; i++)
|
||||
if (sep_name_is(s, n, known[i])) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sep_target_tag(const char *s, size_t n)
|
||||
{
|
||||
return sep_name_is(s, n, "linux") || sep_name_is(s, n, "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. */
|
||||
static int
|
||||
sep_source_matches_target(const char *name)
|
||||
{
|
||||
size_t stem = strcspn(name, ".");
|
||||
if (memchr(name, '_', stem) == NULL) return 1;
|
||||
|
||||
size_t end = stem;
|
||||
size_t last = end;
|
||||
while (last > 0 && name[last - 1] != '_') last--;
|
||||
if (sep_name_is(name + last, end - last, "test")) {
|
||||
if (last == 0) return 1;
|
||||
end = last - 1;
|
||||
last = end;
|
||||
while (last > 0 && name[last - 1] != '_') last--;
|
||||
}
|
||||
if (last == 0) return 1;
|
||||
|
||||
const char *final = name + last;
|
||||
size_t nfinal = end - last;
|
||||
size_t prevend = last - 1;
|
||||
size_t prev = prevend;
|
||||
while (prev > 0 && name[prev - 1] != '_') prev--;
|
||||
if (prev < prevend
|
||||
&& sep_known_os(name + prev, prevend - prev)
|
||||
&& sep_known_arch(final, nfinal))
|
||||
return sep_target_tag(final, nfinal)
|
||||
&& sep_target_tag(name + prev, prevend - prev);
|
||||
if (sep_known_os(final, nfinal) || sep_known_arch(final, nfinal))
|
||||
return sep_target_tag(final, nfinal);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sep_slurp(const char*, char**, u64*);
|
||||
|
||||
/* Go's contract: only *_test.ww is a test source. Ask the compiler parser,
|
||||
@@ -564,15 +637,39 @@ enumerate_dir_ww(const char *dirpath, int variant, const char *test_package,
|
||||
{
|
||||
DIR *d = opendir(dirpath);
|
||||
if (d == NULL) { *out_files = NULL; return -1; }
|
||||
char **names = NULL;
|
||||
int nnames = 0, capnames = 0;
|
||||
char **prod = NULL, **tests = NULL;
|
||||
int nprod = 0, capprod = 0, ntests = 0, captests = 0;
|
||||
struct dirent *ent;
|
||||
while ((ent = readdir(d)) != NULL) {
|
||||
struct dirent *ent = NULL;
|
||||
for (;;) {
|
||||
errno = 0;
|
||||
ent = readdir(d);
|
||||
if (ent == NULL) break;
|
||||
const char *nm = ent->d_name;
|
||||
size_t nl = strlen(nm);
|
||||
if (nl <= 3) continue;
|
||||
if (nm[0] == '.' || nm[0] == '_') continue;
|
||||
if (strcmp(nm + nl - 3, ".ww") != 0) continue;
|
||||
if (source_list_add(&names, &nnames, &capnames, nm) < 0) {
|
||||
source_list_free(names, nnames);
|
||||
closedir(d);
|
||||
*out_files = NULL;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
int direrr = errno;
|
||||
closedir(d);
|
||||
if (direrr != 0) {
|
||||
source_list_free(names, nnames);
|
||||
*out_files = NULL;
|
||||
return -1;
|
||||
}
|
||||
if (nnames > 1) qsort(names, (size_t)nnames, sizeof *names, strs_cmp);
|
||||
for (int ni = 0; ni < nnames; ni++) {
|
||||
const char *nm = names[ni];
|
||||
size_t nl = strlen(nm);
|
||||
if (!sep_source_matches_target(nm)) continue;
|
||||
int is_test = nl >= 8 && strcmp(nm + nl - 8, "_test.ww") == 0;
|
||||
if (variant == SEP_VARIANT_PRODUCTION && is_test) continue;
|
||||
if (variant == SEP_VARIANT_EXTERNAL && !is_test) continue;
|
||||
@@ -580,9 +677,9 @@ enumerate_dir_ww(const char *dirpath, int variant, const char *test_package,
|
||||
int pn = snprintf(path, sizeof path, "%s/%s", dirpath, nm);
|
||||
if (pn < 0 || (size_t)pn >= sizeof path) {
|
||||
fprintf(stderr, "ww: package source path is too long\n");
|
||||
source_list_free(names, nnames);
|
||||
source_list_free(prod, nprod);
|
||||
source_list_free(tests, ntests);
|
||||
closedir(d);
|
||||
*out_files = NULL;
|
||||
return -2;
|
||||
}
|
||||
@@ -590,9 +687,9 @@ enumerate_dir_ww(const char *dirpath, int variant, const char *test_package,
|
||||
if (lstat(path, &st) != 0) {
|
||||
fprintf(stderr,
|
||||
"ww: %s: package source is not a regular file\n", path);
|
||||
source_list_free(names, nnames);
|
||||
source_list_free(prod, nprod);
|
||||
source_list_free(tests, ntests);
|
||||
closedir(d);
|
||||
*out_files = NULL;
|
||||
return -2;
|
||||
}
|
||||
@@ -601,9 +698,9 @@ enumerate_dir_ww(const char *dirpath, int variant, const char *test_package,
|
||||
fprintf(stderr,
|
||||
"ww: %s: package source is not a regular file\n",
|
||||
path);
|
||||
source_list_free(names, nnames);
|
||||
source_list_free(prod, nprod);
|
||||
source_list_free(tests, ntests);
|
||||
closedir(d);
|
||||
*out_files = NULL;
|
||||
return -2;
|
||||
}
|
||||
@@ -613,17 +710,17 @@ enumerate_dir_ww(const char *dirpath, int variant, const char *test_package,
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
fprintf(stderr,
|
||||
"ww: %s: package source is not a regular file\n", path);
|
||||
source_list_free(names, nnames);
|
||||
source_list_free(prod, nprod);
|
||||
source_list_free(tests, ntests);
|
||||
closedir(d);
|
||||
*out_files = NULL;
|
||||
return -2;
|
||||
}
|
||||
int has_test = !is_test ? source_has_test_decl(path) : 0;
|
||||
if (has_test < 0) {
|
||||
source_list_free(names, nnames);
|
||||
source_list_free(prod, nprod);
|
||||
source_list_free(tests, ntests);
|
||||
closedir(d);
|
||||
*out_files = NULL;
|
||||
return -2;
|
||||
}
|
||||
@@ -631,18 +728,18 @@ enumerate_dir_ww(const char *dirpath, int variant, const char *test_package,
|
||||
fprintf(stderr,
|
||||
"ww: %s: @test declaration outside *_test.ww\n",
|
||||
path);
|
||||
source_list_free(names, nnames);
|
||||
source_list_free(prod, nprod);
|
||||
source_list_free(tests, ntests);
|
||||
closedir(d);
|
||||
*out_files = NULL;
|
||||
return -2;
|
||||
}
|
||||
if (is_test) {
|
||||
char *package = NULL;
|
||||
if (source_package_name(path, &package) < 0) {
|
||||
source_list_free(names, nnames);
|
||||
source_list_free(prod, nprod);
|
||||
source_list_free(tests, ntests);
|
||||
closedir(d);
|
||||
*out_files = NULL;
|
||||
return -2;
|
||||
}
|
||||
@@ -656,14 +753,14 @@ enumerate_dir_ww(const char *dirpath, int variant, const char *test_package,
|
||||
int *n = is_test ? &ntests : &nprod;
|
||||
int *cap = is_test ? &captests : &capprod;
|
||||
if (source_list_add(list, n, cap, path) < 0) {
|
||||
source_list_free(names, nnames);
|
||||
source_list_free(prod, nprod);
|
||||
source_list_free(tests, ntests);
|
||||
closedir(d);
|
||||
*out_files = NULL;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
source_list_free(names, nnames);
|
||||
if (nprod > 1) qsort(prod, (size_t)nprod, sizeof *prod, strs_cmp);
|
||||
if (ntests > 1) qsort(tests, (size_t)ntests, sizeof *tests, strs_cmp);
|
||||
if (nprod > INT_MAX - ntests) {
|
||||
@@ -4161,7 +4258,7 @@ static void
|
||||
workdir_stamp_text(char *buf, size_t bufsz, int is_test, int emit_asm)
|
||||
{
|
||||
snprintf(buf, bufsz, "ww workdir fmt %d mode %s asm %d\n",
|
||||
is_test ? 16 : 17, is_test ? "test" : "build", emit_asm);
|
||||
is_test ? 17 : 18, is_test ? "test" : "build", emit_asm);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -582,9 +582,108 @@ fn pkgisreg(path: str) bool = {
|
||||
};
|
||||
};
|
||||
|
||||
fn pkgnamerangeis(name: str, start: i32, end: i32, word: str) bool = {
|
||||
if (end < start || end - start != word.len) { return false; };
|
||||
let i: i32 = 0;
|
||||
for (i < end - start) {
|
||||
if (name[start + i] != word[i]) { return false; };
|
||||
i += 1;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
fn pkgknownos(name: str, start: i32, end: i32) bool = {
|
||||
return pkgnamerangeis(name, start, end, "aix")
|
||||
|| pkgnamerangeis(name, start, end, "android")
|
||||
|| pkgnamerangeis(name, start, end, "darwin")
|
||||
|| pkgnamerangeis(name, start, end, "dragonfly")
|
||||
|| pkgnamerangeis(name, start, end, "freebsd")
|
||||
|| pkgnamerangeis(name, start, end, "hurd")
|
||||
|| pkgnamerangeis(name, start, end, "illumos")
|
||||
|| pkgnamerangeis(name, start, end, "ios")
|
||||
|| pkgnamerangeis(name, start, end, "js")
|
||||
|| pkgnamerangeis(name, start, end, "linux")
|
||||
|| pkgnamerangeis(name, start, end, "nacl")
|
||||
|| pkgnamerangeis(name, start, end, "netbsd")
|
||||
|| pkgnamerangeis(name, start, end, "openbsd")
|
||||
|| pkgnamerangeis(name, start, end, "plan9")
|
||||
|| pkgnamerangeis(name, start, end, "solaris")
|
||||
|| pkgnamerangeis(name, start, end, "wasip1")
|
||||
|| pkgnamerangeis(name, start, end, "windows")
|
||||
|| pkgnamerangeis(name, start, end, "zos");
|
||||
};
|
||||
|
||||
fn pkgknownarch(name: str, start: i32, end: i32) bool = {
|
||||
return pkgnamerangeis(name, start, end, "386")
|
||||
|| pkgnamerangeis(name, start, end, "amd64")
|
||||
|| pkgnamerangeis(name, start, end, "amd64p32")
|
||||
|| pkgnamerangeis(name, start, end, "arm")
|
||||
|| pkgnamerangeis(name, start, end, "armbe")
|
||||
|| pkgnamerangeis(name, start, end, "arm64")
|
||||
|| pkgnamerangeis(name, start, end, "arm64be")
|
||||
|| pkgnamerangeis(name, start, end, "loong64")
|
||||
|| pkgnamerangeis(name, start, end, "mips")
|
||||
|| pkgnamerangeis(name, start, end, "mipsle")
|
||||
|| pkgnamerangeis(name, start, end, "mips64")
|
||||
|| pkgnamerangeis(name, start, end, "mips64le")
|
||||
|| pkgnamerangeis(name, start, end, "mips64p32")
|
||||
|| pkgnamerangeis(name, start, end, "mips64p32le")
|
||||
|| pkgnamerangeis(name, start, end, "ppc")
|
||||
|| pkgnamerangeis(name, start, end, "ppc64")
|
||||
|| pkgnamerangeis(name, start, end, "ppc64le")
|
||||
|| pkgnamerangeis(name, start, end, "riscv")
|
||||
|| pkgnamerangeis(name, start, end, "riscv64")
|
||||
|| pkgnamerangeis(name, start, end, "s390")
|
||||
|| pkgnamerangeis(name, start, end, "s390x")
|
||||
|| pkgnamerangeis(name, start, end, "sparc")
|
||||
|| pkgnamerangeis(name, start, end, "sparc64")
|
||||
|| pkgnamerangeis(name, start, end, "wasm");
|
||||
};
|
||||
|
||||
fn pkgtargettag(name: str, start: i32, end: i32) bool = {
|
||||
return pkgnamerangeis(name, start, end, "linux")
|
||||
|| pkgnamerangeis(name, start, end, "amd64");
|
||||
};
|
||||
|
||||
// Recursive discovery must decide platform eligibility before a source can
|
||||
// enter any production or test package graph.
|
||||
fn pkgsourceplatform(name: str) bool = {
|
||||
let stem: i32 = 0;
|
||||
let hasunderscore: bool = false;
|
||||
for (stem < name.len && name[stem] != '.') {
|
||||
if (name[stem] == '_') { hasunderscore = true; };
|
||||
stem += 1;
|
||||
};
|
||||
if (!hasunderscore) { return true; };
|
||||
|
||||
let end: i32 = stem;
|
||||
let last: i32 = end;
|
||||
for (last > 0 && name[last - 1] != '_') { last -= 1; };
|
||||
if (pkgnamerangeis(name, last, end, "test")) {
|
||||
if (last == 0) { return true; };
|
||||
end = last - 1;
|
||||
last = end;
|
||||
for (last > 0 && name[last - 1] != '_') { last -= 1; };
|
||||
};
|
||||
if (last == 0) { return true; };
|
||||
|
||||
let prevend: i32 = last - 1;
|
||||
let prev: i32 = prevend;
|
||||
for (prev > 0 && name[prev - 1] != '_') { prev -= 1; };
|
||||
if (prev < prevend && pkgknownos(name, prev, prevend)
|
||||
&& pkgknownarch(name, last, end)) {
|
||||
return pkgtargettag(name, last, end)
|
||||
&& pkgtargettag(name, prev, prevend);
|
||||
};
|
||||
if (pkgknownos(name, last, end) || pkgknownarch(name, last, end)) {
|
||||
return pkgtargettag(name, last, end);
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
fn pkgkeepfile(name: str) bool = {
|
||||
if (name.len <= 3 || name[0] == '.' || name[0] == '_') { return false; };
|
||||
return strings.hassuffix(name, ".ww");
|
||||
return strings.hassuffix(name, ".ww") && pkgsourceplatform(name);
|
||||
};
|
||||
|
||||
type pkgmatcher = struct {
|
||||
|
||||
@@ -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