diff --git a/test/wcc/989_sepdotpath_run.c b/test/wcc/989_sepdotpath_run.c deleted file mode 100644 index 5a9fb2b9..00000000 --- a/test/wcc/989_sepdotpath_run.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * 989_sepdotpath_run — sep-build of a DOTTED-path (multi-component) package - * (#57). Commit-6 broad-soak prereq: the real toolchain sep-builds packages - * like `encoding.utf8`, whose body must mangle on the full dotted import path - * (`encoding.utf8.X`), not the leaf `package` clause (`utf8.X`). - * - * Root cause it guards: the sep producer splices a package's own body under - * `//ww:module-reset` (so `-c` keeps imported==0). Pre-#57 that reset carried - * NO path, so the body's `package ;` clause set curmod to the LEAF — - * the DEFINER mangled `b.val` while every importer (spliced under - * `//ww:module a.b`) referenced `a.b.val` → unresolved at link. #57 threads - * the dotted path through the reset (`//ww:module-reset a.b`), demoting the - * leaf clause to an assertion. Single-COMPONENT packages were always clean - * (leaf == dotted path) — that invariant is the regression guard below. - * - * Graph (smallest that mixes both kinds): root -> { a.b (dotted), c (single) }. - * - * Asserts (fresh output stems under an invocation-owned root; retained - * `.sepwork` is inspected, then removed by final carrier cleanup): - * 1. Build + run, BOTH stages → exit EXPECT_EXIT (the dotted-package symbol - * resolves + links; the program runs). Pre-#57 the link failed. - * 2. cs==ww (rule 10): per-package `.s`/`.wwi`/`.unit.ww` AND the final - * binary are byte-identical between `ww` and `ww_ww`. - * 3. NON-VACUITY (a) — definer==importer on the DOTTED form: the producer's - * `a.b.s` DEFINES `a.b.val` and the root's `__root.s` REFERENCES - * `a.b.val`. Pre-#57 the definer emitted the leaf `b.val` → the strings - * mismatched; this row would fail (and assert 1's link would fail). - * The reset directive in `a.b.unit.ww` carries the dotted path. - * 4. NON-VACUITY (b) — single-component regression guard: package `c` - * sep-builds in the SAME graph, defines `c.cval` (leaf == dotted), and - * cs==ww (covered by assert 2). Cross-commit byte-id of single-component - * output is additionally pinned by 989_sepbuild_run + the 990-997 gates. - * - * All intermediates are `-o`-redirected to /tmp for isolation. Models - * 989_sepbuild_run.c conventions; 989 prefix per the sep-gate precedent. - */ -#include -#include -#include -#include -#include -#include -#include - -#define EXPECT_EXIT 37 - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return 1; -} - -static const char * -absbin(void) -{ - const char *b = getenv("BIN"); - if (!b) b = "out/bin"; - if (b[0] == '/') return b; - static char buf[2048]; - char cwd[1024]; - if (getcwd(cwd, sizeof cwd) == NULL) return NULL; - snprintf(buf, sizeof buf, "%s/%s", cwd, b); - return buf; -} - -static int -slurp(const char *path, char **outbuf, size_t *outlen) -{ - FILE *f = fopen(path, "rb"); - if (!f) return -1; - fseek(f, 0, SEEK_END); - long n = ftell(f); - fseek(f, 0, SEEK_SET); - if (n < 0) { fclose(f); return -1; } - char *b = malloc((size_t)n + 1); - if (!b) { fclose(f); return -1; } - if (fread(b, 1, (size_t)n, f) != (size_t)n) { free(b); fclose(f); return -1; } - b[n] = '\0'; - fclose(f); - *outbuf = b; - *outlen = (size_t)n; - return 0; -} - -static int -files_eq(const char *a, const char *b) -{ - char *ba = NULL, *bb = NULL; - size_t na = 0, nb = 0; - if (slurp(a, &ba, &na) < 0 || slurp(b, &bb, &nb) < 0) { - free(ba); free(bb); - return -1; - } - int eq = (na == nb && memcmp(ba, bb, na) == 0); - free(ba); free(bb); - return eq ? 0 : 1; -} - -/* 0 if `needle` occurs in the file at `path`, 1 if absent, -1 on read err. */ -static int -file_contains(const char *path, const char *needle) -{ - char *b = NULL; - size_t n = 0; - if (slurp(path, &b, &n) < 0) return -1; - int found = (strstr(b, needle) != NULL); - free(b); - return found ? 0 : 1; -} - -static int -write_file(const char *path, const char *body) -{ - FILE *f = fopen(path, "wb"); - if (!f) return -1; - fputs(body, f); - fclose(f); - return 0; -} - -int -main(void) -{ - const char *bin = absbin(); - if (!bin) return 1; - char td[64], cmd[8192], p[1024]; - int fail = 0, have_lib = 0, have_a = 0, have_ab = 0, have_c = 0; - - snprintf(td, sizeof td, "/tmp/wwsepdot_%d", getpid()); - if (mkdir(td, 0755) != 0) { - fprintf(stderr, "sepdotpath FAIL: cannot acquire %s\n", td); - return 1; - } - - /* lib/a/b — a 2-level dotted package (clause `package b;`, dir a/b). */ - snprintf(p, sizeof p, "%s/lib", td); - if (mkdir(p, 0755) != 0) { - fprintf(stderr, "sepdotpath FAIL: cannot create %s\n", p); - fail++; goto out; - } - have_lib = 1; - snprintf(p, sizeof p, "%s/lib/a", td); - if (mkdir(p, 0755) != 0) { - fprintf(stderr, "sepdotpath FAIL: cannot create %s\n", p); - fail++; goto out; - } - have_a = 1; - snprintf(p, sizeof p, "%s/lib/a/b", td); - if (mkdir(p, 0755) != 0) { - fprintf(stderr, "sepdotpath FAIL: cannot create %s\n", p); - fail++; goto out; - } - have_ab = 1; - snprintf(p, sizeof p, "%s/lib/c", td); - if (mkdir(p, 0755) != 0) { - fprintf(stderr, "sepdotpath FAIL: cannot create %s\n", p); - fail++; goto out; - } - have_c = 1; - - snprintf(p, sizeof p, "%s/lib/a/b/mod.ww", td); - if (write_file(p, "package b;\nexport fn val() i32 = { return 42; };\n")) - { fail++; goto out; } - snprintf(p, sizeof p, "%s/lib/c/mod.ww", td); - if (write_file(p, "package c;\nexport fn cval() i32 = { return 5; };\n")) - { fail++; goto out; } - - char rootww[1024]; - snprintf(rootww, sizeof rootww, "%s/root.ww", td); - if (write_file(rootww, - "package main;\n" - "import a.b;\n" - "import c;\n" - "fn main() i32 = { return b.val() - c.cval(); };\n")) - { fail++; goto out; } - - /* Two driver stages and their scratch dirs (paths rebuilt from the - * small fixed `td` + stage tag → provably non-truncating snprintfs). */ - struct { const char *drv, *tag; char prog[1024]; } - stg[] = { { "ww", "cs", {0} }, { "ww_ww", "ww", {0} } }; - - for (int s = 0; s < 2; s++) { - snprintf(stg[s].prog, sizeof stg[s].prog, "%s/prog.%s", td, stg[s].tag); - /* Each direct build produces the `.s`/`.unit.ww` artifacts this - * gate inspects. */ - snprintf(cmd, sizeof cmd, - "timeout 240 %s/%s build " - "-I %s/lib -o %s %s >/dev/null 2>&1", - bin, stg[s].drv, td, stg[s].prog, rootww); - if (runwait(cmd) != 0) { - fprintf(stderr, "sepdotpath FAIL: %s build\n", stg[s].drv); - fail++; - continue; - } - int rc = runwait(stg[s].prog); - if (rc != EXPECT_EXIT) { - fprintf(stderr, "sepdotpath FAIL: %s prog exit=%d expected %d\n", - stg[s].drv, rc, EXPECT_EXIT); - fail++; - } - } - - /* The discovered package set materialized (dotted + single + root). */ - const char *pkgs[] = { "a.b", "c", "__root" }; - for (int i = 0; i < 3; i++) { - /* #69: the root is compiled WITHOUT `-I`, so it produces no `.wwi`; - * assert its `.s` materialized instead. Deps still emit a `.wwi`. */ - int is_root = (strcmp(pkgs[i], "__root") == 0); - snprintf(p, sizeof p, "%s/prog.cs.sepwork/%s%s", td, pkgs[i], - is_root ? ".s" : ".wwi"); - if (access(p, 0) != 0) { - fprintf(stderr, "sepdotpath FAIL: missing %s%s (discovery)\n", - pkgs[i], is_root ? ".s" : ".wwi"); - fail++; - } - } - - /* cs==ww (rule 10): per-package .s/.wwi/.unit.ww + final binary. The - * root has no `.wwi` post-#69, so it is excluded from the .wwi compare. */ - for (int i = 0; i < 3; i++) { - const char *suf[] = { ".s", ".wwi", ".unit.ww" }; - for (int k = 0; k < 3; k++) { - if (strcmp(pkgs[i], "__root") == 0 && strcmp(suf[k], ".wwi") == 0) - continue; - char a[1024], b[1024]; - snprintf(a, sizeof a, "%s/prog.%s.sepwork/%s%s", - td, stg[0].tag, pkgs[i], suf[k]); - snprintf(b, sizeof b, "%s/prog.%s.sepwork/%s%s", - td, stg[1].tag, pkgs[i], suf[k]); - if (files_eq(a, b) != 0) { - fprintf(stderr, "sepdotpath FAIL: cs!=ww for %s%s (rule 10)\n", - pkgs[i], suf[k]); - fail++; - } - } - } - if (files_eq(stg[0].prog, stg[1].prog) != 0) { - fprintf(stderr, "sepdotpath FAIL: cs exe != ww exe (rule 10)\n"); - fail++; - } - - /* NON-VACUITY (a): definer == importer on the DOTTED qualification. - * Pre-#57 the definer emitted the leaf `b.val` while the importer - * referenced `a.b.val` → mismatch + unresolved link. */ - { - char def_s[1024], ref_s[1024], unit[1024]; - snprintf(def_s, sizeof def_s, "%s/prog.cs.sepwork/a.b.s", td); - snprintf(ref_s, sizeof ref_s, "%s/prog.cs.sepwork/__root.s", td); - snprintf(unit, sizeof unit, "%s/prog.cs.sepwork/a.b.unit.ww", td); - if (file_contains(def_s, "TEXT a.b.val") != 0) { - fprintf(stderr, "sepdotpath FAIL: definer a.b.s lacks dotted " - "`TEXT a.b.val` (leaf-clause regression)\n"); - fail++; - } - if (file_contains(ref_s, "a.b.val") != 0) { - fprintf(stderr, "sepdotpath FAIL: importer __root.s lacks " - "reference to a.b.val\n"); - fail++; - } - if (file_contains(unit, "//ww:module-reset a.b") != 0) { - fprintf(stderr, "sepdotpath FAIL: a.b.unit.ww reset directive " - "does not carry the dotted path\n"); - fail++; - } - } - - /* NON-VACUITY (b): single-component `c` sep-builds in the SAME graph and - * defines its leaf==dotted symbol `c.cval` (curmod resolves to the same - * string with or without #57 → byte-id preserved). cs==ww already - * asserted above; cross-commit byte-id pinned by 989_sepbuild + 990-997. */ - { - char c_s[1024]; - snprintf(c_s, sizeof c_s, "%s/prog.cs.sepwork/c.s", td); - if (file_contains(c_s, "TEXT c.cval") != 0) { - fprintf(stderr, "sepdotpath FAIL: single-component c.s lacks " - "`TEXT c.cval` (regression)\n"); - fail++; - } - } - -out: - snprintf(cmd, sizeof cmd, - "rm -rf -- '%s/prog.cs.sepwork' '%s/prog.ww.sepwork'", td, td); - if (runwait(cmd) != 0) { - fprintf(stderr, "sepdotpath FAIL: cannot clean .sepwork trees\n"); - fail++; - } - { - char path[1200]; - snprintf(path, sizeof path, "%s/root.ww", td); - if (unlink(path) != 0 && errno != ENOENT) { fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", path); fail++; } - snprintf(path, sizeof path, "%s/prog.cs", td); - if (unlink(path) != 0 && errno != ENOENT) { fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", path); fail++; } - snprintf(path, sizeof path, "%s/prog.ww", td); - if (unlink(path) != 0 && errno != ENOENT) { fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", path); fail++; } - } - if (have_ab) { - snprintf(p, sizeof p, "%s/lib/a/b", td); - { - char path[1200]; - snprintf(path, sizeof path, "%s/mod.ww", p); - if (unlink(path) != 0 && errno != ENOENT) { fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", path); fail++; } - } - if (rmdir(p) != 0 && errno != ENOENT) { fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", p); fail++; } - } - if (have_a) { - snprintf(p, sizeof p, "%s/lib/a", td); - if (rmdir(p) != 0 && errno != ENOENT) { fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", p); fail++; } - } - if (have_c) { - snprintf(p, sizeof p, "%s/lib/c", td); - { - char path[1200]; - snprintf(path, sizeof path, "%s/mod.ww", p); - if (unlink(path) != 0 && errno != ENOENT) { fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", path); fail++; } - } - if (rmdir(p) != 0 && errno != ENOENT) { fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", p); fail++; } - } - if (have_lib) { - snprintf(p, sizeof p, "%s/lib", td); - if (rmdir(p) != 0 && errno != ENOENT) { fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", p); fail++; } - } - if (rmdir(td) != 0 && errno != ENOENT) { - fprintf(stderr, "sepdotpath FAIL: cannot remove %s\n", td); - fail++; - } - if (fail) { - fprintf(stderr, "sepdotpath: %d check(s) failed\n", fail); - return 1; - } - printf("sepdotpath: dotted `a.b` + single `c` via build_one_sep — " - "build+run (exit %d) + cs==ww per-pkg .s/.wwi/.unit + final binary " - "+ definer==importer on a.b.val + single-component c.cval intact\n", - EXPECT_EXIT); - return 0; -} diff --git a/test/wcc/989_syntaxexport_run.c b/test/wcc/989_syntaxexport_run.c deleted file mode 100644 index de322a9a..00000000 --- a/test/wcc/989_syntaxexport_run.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * 989_syntaxexport_run — BUG-A residual at the surviving syntax->wcc - * package boundary (#72), post the #74 frontend consolidation. - * - * Root cause it guards: `lib/ww/syntax/` exports the fns wcc calls, and - * those fns' signatures name frontend types (tok, tinfo, tctx, ...). When - * the separate-compilation producer emits syntax's `.wwi`, - * check_exported_type recurses every exported decl — and, for an exported - * struct, its FIELDS too (the - * harec STORAGE_STRUCT precedent, wwi.c wwi_check_type N_TSTRUCT). Any - * referenced type that is itself unexported aborts the producer with - * "exported declaration references unexported type". Pre-fix, syntax's - * surface left 16 such types unexported, so syntax's `.wwi` never produced - * -> every wcc sep-build was blocked. Fix: `export` those 16 type decls - * (10 fn-signature-direct + 6 surfaced by the struct-field recursion: - * tykind/tfield/tparam/ttupleelem via tinfo, tctx via typesinit, and - * tinfocacheent via tctx). Exporting a TYPE emits no code -> the bug is - * byte-id-neutral; this gate proves the PRODUCER residual is closed. - * - * The consumer here uses QUALIFIED refs (`syntax.tokname`, `syntax.tkind`) - * to isolate the producer fix from the separate unqualified-ref question - * (#75). It happens to link + run end-to-end, which also shows the - * qualified-ref path resolves across the sep boundary. - * - * Asserts (direct builds compile every package): - * 1. Build + run, BOTH stages -> exit EXPECT_EXIT (`syntax.tokname( - * TK_INT)` == "int", len 3). Pre-fix the syntax producer exited 1, so - * the build never produced a binary. - * 2. syntax's `.wwi` is produced and carries the 16 `export type` decls. - * 3. cs==ww (rule 10): syntax's `.wwi`/`.s`/`.unit.ww` AND the final - * binary are byte-identical between `ww` and `ww_ww`. - * 4. NON-VACUITY (the bug, isolated, BOTH compilers): replay the producer - * `w6c -c -I` on the produced `syntax.unit.ww` -> exits 0 (exports - * present). On a copy with `export ` stripped from the type decls -> - * MUST exit non-zero (the export-check fires). Proven for w6c + w6c_ww. - * - * All intermediates are `-o`-redirected to /tmp; it only reads - * the in-tree `lib/ww/syntax`. Models 989_seproot_export_run.c. - */ -#include -#include -#include -#include -#include -#include -#include - -#define EXPECT_EXIT 3 - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return 1; -} - -static const char * -absbin(void) -{ - const char *b = getenv("BIN"); - if (!b) b = "out/bin"; - if (b[0] == '/') return b; - static char buf[2048]; - char cwd[1024]; - if (getcwd(cwd, sizeof cwd) == NULL) return NULL; - snprintf(buf, sizeof buf, "%s/%s", cwd, b); - return buf; -} - -static int -slurp(const char *path, char **outbuf, size_t *outlen) -{ - FILE *f = fopen(path, "rb"); - if (!f) return -1; - fseek(f, 0, SEEK_END); - long n = ftell(f); - fseek(f, 0, SEEK_SET); - if (n < 0) { fclose(f); return -1; } - char *b = malloc((size_t)n + 1); - if (!b) { fclose(f); return -1; } - if (fread(b, 1, (size_t)n, f) != (size_t)n) { free(b); fclose(f); return -1; } - b[n] = '\0'; - fclose(f); - *outbuf = b; - *outlen = (size_t)n; - return 0; -} - -static int -files_eq(const char *a, const char *b) -{ - char *ba = NULL, *bb = NULL; - size_t na = 0, nb = 0; - if (slurp(a, &ba, &na) < 0 || slurp(b, &bb, &nb) < 0) { - free(ba); free(bb); - return -1; - } - int eq = (na == nb && memcmp(ba, bb, na) == 0); - free(ba); free(bb); - return eq ? 0 : 1; -} - -/* 0 if `needle` occurs in the file at `path`, 1 if absent, -1 on read err. */ -static int -file_contains(const char *path, const char *needle) -{ - char *b = NULL; - size_t n = 0; - if (slurp(path, &b, &n) < 0) return -1; - int found = (strstr(b, needle) != NULL); - free(b); - return found ? 0 : 1; -} - -static int -write_file(const char *path, const char *body) -{ - FILE *f = fopen(path, "wb"); - if (!f) return -1; - if (fputs(body, f) == EOF) { fclose(f); return -1; } - return fclose(f); -} - -int -main(void) -{ - const char *bin = absbin(); - if (!bin) return 1; - char root[1024]; - if (getcwd(root, sizeof root) == NULL) return 1; - - char td[] = "/tmp/wwsynexp_XXXXXX"; - char cmd[8192]; - int fail = 0, cleanup_fail = 0; - - if (mkdtemp(td) == NULL) return 1; - - /* Root: QUALIFIED refs into the real syntax package — `syntax.tokname` - * over `syntax.tkind`. The producer must serialize syntax's `.wwi` - * (exported fns over frontend types) WITHOUT the unexported-type abort. */ - char rootww[1024]; - snprintf(rootww, sizeof rootww, "%s/root.ww", td); - if (write_file(rootww, - "package main;\n" - "import syntax;\n" - "fn main() i32 = {\n" - "\tlet s: str = syntax.tokname(syntax.tkind.TK_INT);\n" - "\treturn s.len: i32;\n" - "};\n")) - { fail++; goto out; } - - struct { const char *drv, *tag; char prog[1024]; } - stg[] = { { "ww", "cs", {0} }, { "ww_ww", "ww", {0} } }; - - for (int s = 0; s < 2; s++) { - snprintf(stg[s].prog, sizeof stg[s].prog, "%s/prog.%s", td, stg[s].tag); - /* Direct builds produce the `.wwi`/`.s`/`.unit.ww` artifacts this - * gate inspects. */ - snprintf(cmd, sizeof cmd, - "timeout 240 %s/%s build " - "-I %s/lib/ww -o %s %s >%s/build.%s.log 2>&1", - bin, stg[s].drv, root, stg[s].prog, rootww, - td, stg[s].tag); - if (runwait(cmd) != 0) { - fprintf(stderr, "syntaxexport FAIL: %s build (pre-fix: syntax " - "producer rejects export-fn-over-unexported-type)\n", stg[s].drv); - fail++; - continue; - } - /* the producer abort must not appear in the build log. */ - char log[1024], wwi[1024]; - snprintf(log, sizeof log, "%s/build.%s.log", td, stg[s].tag); - if (file_contains(log, "unexported type") == 0) { - fprintf(stderr, "syntaxexport FAIL: %s build log shows " - "'unexported type' (producer residual not closed)\n", stg[s].drv); - fail++; - } - snprintf(wwi, sizeof wwi, "%s/prog.%s.sepwork/syntax.wwi", td, stg[s].tag); - if (access(wwi, 0) != 0) { - fprintf(stderr, "syntaxexport FAIL: %s produced no syntax.wwi\n", - stg[s].drv); - fail++; - } - int rc = runwait(stg[s].prog); - if (rc != EXPECT_EXIT) { - fprintf(stderr, "syntaxexport FAIL: %s prog exit=%d expected %d\n", - stg[s].drv, rc, EXPECT_EXIT); - fail++; - } - } - - /* syntax's `.wwi` carries the now-exported frontend types — spot-check - * a representative set spanning each surfacing path (fn-direct + the - * struct-field and tctx-field cascades). */ - { - char wwi[1024]; - snprintf(wwi, sizeof wwi, "%s/prog.cs.sepwork/syntax.wwi", td); - const char *want[] = { - "export type tok ", "export type tkind ", "export type node ", - "export type nkind ", "export type tinfo ", "export type tfield ", - "export type tctx ", "export type tinfocacheent ", - }; - for (int i = 0; i < (int)(sizeof want / sizeof want[0]); i++) - if (file_contains(wwi, want[i]) != 0) { - fprintf(stderr, "syntaxexport FAIL: syntax.wwi lacks '%s'\n", - want[i]); - fail++; - } - } - - /* cs==ww (rule 10): syntax's per-package artefacts + the final binary. */ - { - const char *suf[] = { ".wwi", ".s", ".unit.ww" }; - for (int k = 0; k < 3; k++) { - char a[1024], b[1024]; - snprintf(a, sizeof a, "%s/prog.cs.sepwork/syntax%s", td, suf[k]); - snprintf(b, sizeof b, "%s/prog.ww.sepwork/syntax%s", td, suf[k]); - if (files_eq(a, b) != 0) { - fprintf(stderr, "syntaxexport FAIL: cs!=ww for syntax%s " - "(rule 10)\n", suf[k]); - fail++; - } - } - if (files_eq(stg[0].prog, stg[1].prog) != 0) { - fprintf(stderr, "syntaxexport FAIL: cs exe != ww exe (rule 10)\n"); - fail++; - } - } - - /* NON-VACUITY (the bug, isolated): replay the producer on the produced - * `syntax.unit.ww`. With the exports present `w6c -c -I` exits 0; with - * `export ` stripped from the type decls it MUST exit non-zero (the - * export-check fires). Proven for BOTH compilers. */ - { - char unit[1024], ne[1024]; - snprintf(unit, sizeof unit, "%s/prog.cs.sepwork/syntax.unit.ww", td); - snprintf(ne, sizeof ne, "%s/syntax.noexport.ww", td); - snprintf(cmd, sizeof cmd, - "sed 's/export type /type /g' %s > %s", unit, ne); - if (runwait(cmd) != 0) { fail++; goto out; } - - struct { const char *comp; } cc[] = { { "w6c" }, { "w6c_ww" } }; - for (int j = 0; j < 2; j++) { - char wwi[1024], asmf[1024]; - snprintf(wwi, sizeof wwi, "%s/nv.%s.wwi", td, cc[j].comp); - snprintf(asmf, sizeof asmf, "%s/nv.%s.s", td, cc[j].comp); - snprintf(cmd, sizeof cmd, "%s/%s -c -I %s -o %s %s >/dev/null 2>&1", - bin, cc[j].comp, wwi, asmf, unit); - if (runwait(cmd) != 0) { - fprintf(stderr, "syntaxexport FAIL: %s -c -I rejected the " - "EXPORTED unit (post-fix producer must succeed)\n", - cc[j].comp); - fail++; - } - snprintf(cmd, sizeof cmd, "%s/%s -c -I %s -o %s %s >/dev/null 2>&1", - bin, cc[j].comp, wwi, asmf, ne); - if (runwait(cmd) == 0) { - fprintf(stderr, "syntaxexport FAIL: %s -c -I accepted the " - "UNEXPORTED-type unit (bug not reproduced -> vacuous " - "gate)\n", cc[j].comp); - fail++; - } - } - } - -out: - for (int s = 0; s < 2; s++) { - const char *tag = s == 0 ? "cs" : "ww"; - char path[1200]; - snprintf(path, sizeof path, "%s/prog.%s.sepwork", td, tag); - snprintf(cmd, sizeof cmd, "rm -rf -- '%s'", path); - if (runwait(cmd) != 0) cleanup_fail = 1; - snprintf(path, sizeof path, "%s/prog.%s", td, tag); - if (unlink(path) != 0 && errno != ENOENT) cleanup_fail = 1; - snprintf(path, sizeof path, "%s/build.%s.log", td, tag); - if (unlink(path) != 0 && errno != ENOENT) cleanup_fail = 1; - } - { - const char *files[] = { - "root.ww", "syntax.noexport.ww", - "nv.w6c.wwi", "nv.w6c.s", - "nv.w6c_ww.wwi", "nv.w6c_ww.s", - }; - for (size_t i = 0; i < sizeof files / sizeof files[0]; i++) { - char path[1200]; - snprintf(path, sizeof path, "%s/%s", td, files[i]); - if (unlink(path) != 0 && errno != ENOENT) cleanup_fail = 1; - } - } - if (rmdir(td) != 0) cleanup_fail = 1; - if (cleanup_fail) { - fprintf(stderr, "syntaxexport FAIL: cleanup incomplete under %s\n", td); - fail++; - } - if (fail) { - fprintf(stderr, "syntaxexport: %d check(s) failed\n", fail); - return 1; - } - printf("syntaxexport: syntax->wcc boundary sep-PRODUCES clean (16 export " - "type decls) + qualified-ref consumer build+run (exit %d) + cs==ww " - "syntax.wwi/.s/.unit.ww/binary + non-vacuity (export strip rejects, " - "both compilers)\n", EXPECT_EXIT); - return 0; -}