diff --git a/Makefile b/Makefile index 8b938b78..93c4b36e 100644 --- a/Makefile +++ b/Makefile @@ -411,6 +411,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \ $(BIN)/test_star_fn_deref \ $(BIN)/test_star_fn_deref_call \ $(BIN)/test_match_variant_dispatch \ + $(BIN)/test_strict_package \ $(BIN)/test_io_types_run \ $(BIN)/test_dot_aliased_ptr \ $(BIN)/test_return_tagged_forward \ @@ -649,6 +650,13 @@ $(BIN)/test_unknowndecl_reject: test/wcc/989_unknowndecl_reject.c \ $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< +# 782_strict_package (#24a): every primary section must open with a `package` +# clause; a missing clause on the first decl is a hard error, symmetric on +# cstage w6c + wwstage w6c_ww. Each reject row reddens under a gate revert. +$(BIN)/test_strict_package: test/wcc/782_strict_package.c \ + $(BIN)/w6c $(BIN)/w6c_ww | $(BIN) + $(CC) $(CFLAGS) -o $@ $< + # 989_nullableglobal_reject (#45 silent->loud bridge, task #15 prereq): a # module-level nullable `(*T | void)` GLOBAL has no storage path, so a # match/is/as on it silently miscompiled (0(BP) read / undefined ref) on diff --git a/cmd/wcc/parse.c b/cmd/wcc/parse.c index 9afa7fc0..8c17b3ee 100644 --- a/cmd/wcc/parse.c +++ b/cmd/wcc/parse.c @@ -1407,18 +1407,16 @@ parsefile(Parser *p) Pos pp = { p->l->file, 1, 1 }; Node *file = newnode(p->a, N_FILE, pp); Node *head = NULL, *tail = NULL; + int sawpackage = 0; while (p->cur.kind != TK_EOF) { - /* `package foo;` — directory-as-module declaration. Each - * .ww file's section in a concatenated stream begins with - * one; a single-file or fragment input may omit it (curmod - * stays NULL and decls are treated as primary). - * - * Retained divergence from brief: the strict missing-`package` - * error was softened to silent-default to keep 63 inline-source - * test wrappers (200_parse, 100_lex, 300_check, ...) parsing. - * See task #23 for the wrapper migration that unblocks the - * strict check. Rule 7 + rule 8 documentation. */ + /* `package foo;` — directory-as-module declaration. Every + * primary section opens with one (`package main;` for an + * executable); a missing clause on the first real decl is a + * hard error (strict-package, #24a). Imported (pathmod) and + * sep primary-reset (resetmod) regions carry identity + * out-of-band and are exempt. */ if (p->cur.kind == TK_MODULE) { + sawpackage = 1; advance(p); const char *name = expectident(p); expect(p, TK_SEMI); @@ -1457,6 +1455,7 @@ parsefile(Parser *p) * leaf `package` clause, and are flagged imported (gates the * root-only bare-`main` rule, #32). */ if (p->cur.kind == TK_MODPATH) { + sawpackage = 0; p->pathmod = p->cur.text; p->curmod = p->cur.text; p->resetmod = NULL; @@ -1472,6 +1471,7 @@ parsefile(Parser *p) * directive after a mid-file `package` would strip subsequent * decls to bare — that usage is deliberate-only. */ if (p->cur.kind == TK_MODRESET) { + sawpackage = 0; /* #57: a path-carrying reset (sep primary body) mangles * decls on the dotted path so definer == importer, but * leaves imported==0 (curmod set, pathmod NULL) so -c @@ -1498,6 +1498,16 @@ parsefile(Parser *p) } continue; } + /* strict-package: a primary section's first real decl must be + * preceded by a `package` clause. Imported (pathmod) and sep + * primary-reset (resetmod) regions carry identity out-of-band, + * so they are exempt. Wording mirrors Go's missing-`package` + * diagnostic (rule 5; Hare has no clause to port). */ + if (p->pathmod == NULL && p->resetmod == NULL && !sawpackage) { + errorf(p->cur.pos, "missing package clause"); + p->errs++; + sawpackage = 1; + } Node *attrs = parseattrs(p); int exp = accept(p, TK_EXPORT); Node *d = NULL; diff --git a/lib/ww/syntax/parse.ww b/lib/ww/syntax/parse.ww index b8b8ad48..5e6a3025 100644 --- a/lib/ww/syntax/parse.ww +++ b/lib/ww/syntax/parse.ww @@ -416,17 +416,16 @@ export fn parsefile(p: *parser) *node = { let f = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol); let head: *node = nil; let tail: *node = nil; + let sawpackage: i32 = 0; for (p.curkind != tkind.TK_EOF) { - // `package foo;` — each contributing source's section in a - // concatenated stream begins with one. Single-file inputs - // may omit it (curmod stays empty; decls treated as primary). - // - // Retained divergence from brief: strict missing-`package` - // error softened to silent-default — 63 inline-source test - // wrappers depend on the soft behavior. See task #23 for - // the wrapper migration that unblocks the strict check. - // Rule 7 + rule 8 documentation. + // `package foo;` — directory-as-module declaration. Every + // primary section opens with one (`package main;` for an + // executable); a missing clause on the first real decl is a + // hard error (strict-package, #24a). Imported (pathmod) and + // sep primary-reset (resetmod) regions carry identity + // out-of-band and are exempt. if (p.curkind == tkind.TK_MODULE) { + sawpackage = 1; advance(p); let name: str; expectident(p, &name); @@ -462,6 +461,7 @@ export fn parsefile(p: *parser) *node = { // leaf `package` clause, and are flagged imported (gates the // root-only bare-`main` rule, #32). if (p.curkind == tkind.TK_MODPATH) { + sawpackage = 0; p.pathmod = p.curtext; p.curmod = p.curtext; p.resetmod = ""; @@ -477,6 +477,7 @@ export fn parsefile(p: *parser) *node = { // directive after a mid-file `package` would strip subsequent // decls to bare — that usage is deliberate-only. if (p.curkind == tkind.TK_MODRESET) { + sawpackage = 0; // #57: a path-carrying reset (sep primary body) mangles decls // on the dotted path so definer == importer, but leaves // imported==0 (curmod set, pathmod "") so -c primary-ness and @@ -503,6 +504,15 @@ export fn parsefile(p: *parser) *node = { }; continue; }; + // strict-package: a primary section's first real decl must be + // preceded by a `package` clause. Imported (pathmod) and sep + // primary-reset (resetmod) regions carry identity out-of-band, + // so they are exempt. Wording mirrors Go's missing-`package` + // diagnostic (rule 5; Hare has no clause to port). + if (p.pathmod.len == 0 && p.resetmod.len == 0 && sawpackage == 0) { + errmsg(p, "missing package clause"); + sawpackage = 1; + }; let attrs = parseattrs(p); let exported: i32 = 0; if (p.curkind == tkind.TK_EXPORT) { exported = 1; advance(p); }; diff --git a/rt/ensure.ww b/rt/ensure.ww index f8fa8def..0a5fba30 100644 --- a/rt/ensure.ww +++ b/rt/ensure.ww @@ -14,10 +14,13 @@ // no per-type wrapper functions (appendu8 / appendi64) needed. // // User code never `use`s this — the symbol is resolved at link time -// from libwwrt.a, like rt_malloc and rt_streq. No `module` declaration: -// rt/ensure.ww is compiled standalone via `w6c rt/ensure.ww` (not -// through the driver), and its `export fn rt_ensure` must keep its -// bare symbol name so the linker resolves it. +// from libwwrt.a, like rt_malloc and rt_streq. rt/ensure.ww is compiled +// standalone via `w6c rt/ensure.ww` (not through the driver). Under +// strict-package (#24a) it declares `package rt;` (matching its +// directory) like every primary section; the link-resolved name is +// pinned bare via @symbol on the export (the clause would otherwise +// mangle it to rt.rt_ensure). +package rt; @symbol("rt_malloc") fn malloc(n: u64) *void; @@ -31,7 +34,7 @@ type slice = struct { cap: i64, }; -export fn rt_ensure(s: *slice, membsz: u64) void = { +@symbol("rt_ensure") export fn rt_ensure(s: *slice, membsz: u64) void = { if (s.cap >= s.len) { return; }; let nc: i64 = s.cap * 2i64; if (nc < 8i64) { nc = 8i64; }; diff --git a/rt/malloc.ww b/rt/malloc.ww index 770b525a..d7bb8b2a 100644 --- a/rt/malloc.ww +++ b/rt/malloc.ww @@ -1,6 +1,8 @@ // rt/malloc.ww — bump allocator over 2MiB chunks. Archived into -// libwwrt.a, compiled standalone (no `module`) with bare symbols, like -// rt/ensure.ww. +// libwwrt.a, compiled standalone with bare symbols, like rt/ensure.ww. +// Under strict-package (#24a) it declares `package rt;` (matching its +// directory); the export's link name stays bare via its own +// @symbol("rt_malloc"). // // WHY bump, replacing the page-per-call mmap (rt_segmalloc, ex-rt_malloc): // the old rt_malloc page-rounded every request, so a 32-72B node cost a @@ -15,6 +17,7 @@ // Zero-init is preserved: every byte handed out is fresh from // MAP_ANONYMOUS (kernel-zeroed) and never reused, so alloc(T{})'s // zero-fill still holds. Lazy first chunk falls out of cur=rem=0. +package rt; def CHUNKSZ: u64 = 2097152u64; // 1<<21, ref/hare/rt/malloc.ha:24 def ALIGN: u64 = 16u64; // ref/hare/rt/malloc.ha:14 diff --git a/test/wcc/200_parse.c b/test/wcc/200_parse.c index 9ca9e591..67132990 100644 --- a/test/wcc/200_parse.c +++ b/test/wcc/200_parse.c @@ -11,6 +11,7 @@ #include #include #include +#include "wwtestpkg.h" static int must_parse(const char *src) @@ -18,10 +19,12 @@ must_parse(const char *src) Arena *a = newarena(); Lex l; Parser p; - lexinit(&l, a, "", src, strlen(src)); + char *ws = wwtest_wrap(src); + lexinit(&l, a, "", ws, strlen(ws)); parserinit(&p, a, &l); Node *n = parsefile(&p); int ok = (n != NULL && p.errs == 0 && l.errs == 0); + free(ws); freearena(a); return ok; } @@ -32,7 +35,8 @@ parse_to_str(const char *src, int *errs) Arena *a = newarena(); Lex l; Parser p; - lexinit(&l, a, "", src, strlen(src)); + char *ws = wwtest_wrap(src); + lexinit(&l, a, "", ws, strlen(ws)); parserinit(&p, a, &l); Node *n = parsefile(&p); *errs = p.errs + l.errs; @@ -41,6 +45,7 @@ parse_to_str(const char *src, int *errs) size_t len = 0; FILE *f = open_memstream(&buf, &len); if (f == NULL) { + free(ws); freearena(a); return NULL; } @@ -51,6 +56,7 @@ parse_to_str(const char *src, int *errs) memcpy(out, buf, len); out[len] = '\0'; free(buf); + free(ws); freearena(a); return out; } diff --git a/test/wcc/300_check.c b/test/wcc/300_check.c index 2f4fe981..88e2a1d3 100644 --- a/test/wcc/300_check.c +++ b/test/wcc/300_check.c @@ -8,6 +8,7 @@ #include #include #include +#include "wwtestpkg.h" static int runrow(const char *src, const char *expect) @@ -16,7 +17,8 @@ runrow(const char *src, const char *expect) Lex l; Parser p; Checker c; - lexinit(&l, a, "", src, strlen(src)); + char *ws = wwtest_wrap(src); + lexinit(&l, a, "", ws, strlen(ws)); parserinit(&p, a, &l); Node *file = parsefile(&p); @@ -44,6 +46,7 @@ runrow(const char *src, const char *expect) " src: %s\n", expect, errbuf, src); } free(errbuf); + free(ws); freearena(a); return ok; } diff --git a/test/wcc/400_w6c.c b/test/wcc/400_w6c.c index bbe50cf7..b4921a04 100644 --- a/test/wcc/400_w6c.c +++ b/test/wcc/400_w6c.c @@ -8,6 +8,7 @@ #include #include #include +#include "wwtestpkg.h" static int run6c(const char *src, char **out) @@ -16,7 +17,7 @@ run6c(const char *src, char **out) snprintf(path, sizeof path, "/tmp/wwt_%d.ww", getpid()); FILE *f = fopen(path, "wb"); if (f == NULL) return -1; - fputs(src, f); + wwtest_fputs(src, f); fclose(f); char cmd[256]; @@ -60,7 +61,7 @@ static const struct row rows[] = { { "fn cond(x: i32) i32 = { if (x > 0) { return 1; }; return 0; };", "CMPQ\t$0, AX" }, { "fn lo() void = { for (let i: i32 = 0; i < 10; i += 1) { }; };", "JMP" }, - { "fn callit() i32 = { return 1; };", "TEXT callit,$0" }, + { "fn callit() i32 = { return 1; };", "TEXT main.callit,$0" }, }; int diff --git a/test/wcc/500_w6a.c b/test/wcc/500_w6a.c index 72958819..abb28b55 100644 --- a/test/wcc/500_w6a.c +++ b/test/wcc/500_w6a.c @@ -7,6 +7,7 @@ #include #include #include +#include "wwtestpkg.h" static int run(const char *cmd) @@ -35,7 +36,7 @@ main(void) int n = 0, fail = 0; for (int i = 0; programs[i]; i++, n++) { FILE *f = fopen(src, "wb"); - fputs(programs[i], f); + wwtest_fputs(programs[i], f); fclose(f); char cmd[512]; diff --git a/test/wcc/600_w6l.c b/test/wcc/600_w6l.c index edd8a278..743b2487 100644 --- a/test/wcc/600_w6l.c +++ b/test/wcc/600_w6l.c @@ -6,6 +6,7 @@ #include #include #include +#include "wwtestpkg.h" int main(void) @@ -20,7 +21,7 @@ main(void) snprintf(exe, sizeof exe, "/tmp/wwt_%d.x", getpid()); FILE *f = fopen(src, "wb"); - fputs("fn main() i32 = { return 42; };", f); + wwtest_fputs("fn main() i32 = { return 42; };", f); fclose(f); char cmd[1024]; diff --git a/test/wcc/610_arch.c b/test/wcc/610_arch.c index 3336fe99..336f5d33 100644 --- a/test/wcc/610_arch.c +++ b/test/wcc/610_arch.c @@ -13,6 +13,7 @@ #include #include #include +#include "wwtestpkg.h" static int run(const char *cmd) { return system(cmd); } @@ -33,24 +34,26 @@ main(void) snprintf(dir, sizeof dir, "/tmp/wwarch_%d", getpid()); mkdir(dir, 0755); - /* lib_good.ww — defines f1() */ + /* lib_good.ww — defines f1() (→ main.f1 under strict-package #24a) */ char path[256]; snprintf(path, sizeof path, "%s/lib_good.ww", dir); FILE *f = fopen(path, "wb"); - fputs("export fn f1() i32 = { return 7; };", f); + wwtest_fputs("export fn f1() i32 = { return 7; };", f); fclose(f); /* lib_bad.ww — defines f2() but also references an undefined extern */ snprintf(path, sizeof path, "%s/lib_bad.ww", dir); f = fopen(path, "wb"); - fputs("@symbol(\"this_symbol_does_not_exist\") fn bogus() i32;\n" + wwtest_fputs("@symbol(\"this_symbol_does_not_exist\") fn bogus() i32;\n" "export fn f2() i32 = { return bogus(); };", f); fclose(f); - /* main.ww — calls f1, NOT f2 */ + /* main.ww — calls f1, NOT f2. The plain prototype declares f1 in the + * same (main) module, so the call resolves to main.f1 — matching + * lib_good's moduled definition (no @symbol bare-pin needed). */ snprintf(path, sizeof path, "%s/m.ww", dir); f = fopen(path, "wb"); - fputs("@symbol(\"f1\") fn f1() i32;\n" + wwtest_fputs("fn f1() i32;\n" "fn main() i32 = { return f1(); };", f); fclose(f); diff --git a/test/wcc/630_let_global.c b/test/wcc/630_let_global.c index 7ef8abf6..407ce091 100644 --- a/test/wcc/630_let_global.c +++ b/test/wcc/630_let_global.c @@ -12,6 +12,7 @@ #include #include #include +#include "wwtestpkg.h" static int run_exit(const char *cmd) @@ -33,7 +34,7 @@ build_and_run(const char *bin, const char *prog) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(prog, f); + wwtest_fputs(prog, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/ww run %s", bin, src); diff --git a/test/wcc/631_def_neg_global.c b/test/wcc/631_def_neg_global.c index 59f2e36c..c2268b73 100644 --- a/test/wcc/631_def_neg_global.c +++ b/test/wcc/631_def_neg_global.c @@ -42,6 +42,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -142,7 +143,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s 2>/dev/null", @@ -174,7 +175,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/632_w6l_manyflags.c b/test/wcc/632_w6l_manyflags.c index 94c18515..fb4438f6 100644 --- a/test/wcc/632_w6l_manyflags.c +++ b/test/wcc/632_w6l_manyflags.c @@ -18,6 +18,7 @@ #include #include #include +#include "wwtestpkg.h" static const char * absbin(void) @@ -98,10 +99,10 @@ main(void) /* a standalone main.o (no undefs) + an unrelated archived foo.o. */ FILE *f = fopen(src, "wb"); - fputs("fn main() i32 = { return 42; };", f); + wwtest_fputs("fn main() i32 = { return 42; };", f); fclose(f); f = fopen(fsrc, "wb"); - fputs("export fn foo() i32 = { return 7; };", f); + wwtest_fputs("export fn foo() i32 = { return 7; };", f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s", bin, asmf, src); diff --git a/test/wcc/640_int_cast_signed.c b/test/wcc/640_int_cast_signed.c index ed94bfbb..b2e7bb37 100644 --- a/test/wcc/640_int_cast_signed.c +++ b/test/wcc/640_int_cast_signed.c @@ -16,6 +16,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -149,7 +150,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/650_dot_chain.c b/test/wcc/650_dot_chain.c index 528f4f05..faf7b556 100644 --- a/test/wcc/650_dot_chain.c +++ b/test/wcc/650_dot_chain.c @@ -19,6 +19,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -355,7 +356,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", diff --git a/test/wcc/660_field_signed.c b/test/wcc/660_field_signed.c index c041d3d8..659127d6 100644 --- a/test/wcc/660_field_signed.c +++ b/test/wcc/660_field_signed.c @@ -14,6 +14,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -297,7 +298,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", diff --git a/test/wcc/670_frame_argcount.c b/test/wcc/670_frame_argcount.c index 6b1ec2f5..5e0ac6cd 100644 --- a/test/wcc/670_frame_argcount.c +++ b/test/wcc/670_frame_argcount.c @@ -18,6 +18,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -294,7 +295,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/680_arr_elem_field.c b/test/wcc/680_arr_elem_field.c index b433b629..8744db66 100644 --- a/test/wcc/680_arr_elem_field.c +++ b/test/wcc/680_arr_elem_field.c @@ -24,6 +24,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -153,7 +154,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", diff --git a/test/wcc/681_arr_elem_field_write.c b/test/wcc/681_arr_elem_field_write.c index 37a92883..2f029088 100644 --- a/test/wcc/681_arr_elem_field_write.c +++ b/test/wcc/681_arr_elem_field_write.c @@ -22,6 +22,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -504,7 +505,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/682_arr_enum_elem.c b/test/wcc/682_arr_enum_elem.c index d4a08b84..f3966559 100644 --- a/test/wcc/682_arr_enum_elem.c +++ b/test/wcc/682_arr_enum_elem.c @@ -71,6 +71,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -162,7 +163,7 @@ run_driver(const char *driver, const struct row *r, int i) mkdir(tmpdir, 0755); FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s 2>/dev/null", @@ -194,7 +195,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/688_global_arr_elem_field.c b/test/wcc/688_global_arr_elem_field.c index 4637229e..5855e49e 100644 --- a/test/wcc/688_global_arr_elem_field.c +++ b/test/wcc/688_global_arr_elem_field.c @@ -48,6 +48,7 @@ #include #include #include +#include "wwtestpkg.h" /* want == BYTEID_ONLY: the row cannot LINK/run (a slice-of-struct * module global does not data-emit yet — separate gap), so only the @@ -138,7 +139,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s 2>/dev/null", @@ -169,7 +170,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/690_amp_dot.c b/test/wcc/690_amp_dot.c index e3ec9a47..048881e8 100644 --- a/test/wcc/690_amp_dot.c +++ b/test/wcc/690_amp_dot.c @@ -25,6 +25,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -250,7 +251,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/691_dot_slice_arg.c b/test/wcc/691_dot_slice_arg.c index 8de9c1ad..e9c4ff66 100644 --- a/test/wcc/691_dot_slice_arg.c +++ b/test/wcc/691_dot_slice_arg.c @@ -34,6 +34,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -228,7 +229,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/692_dot_str_chained_arg.c b/test/wcc/692_dot_str_chained_arg.c index 4eaf218b..35383919 100644 --- a/test/wcc/692_dot_str_chained_arg.c +++ b/test/wcc/692_dot_str_chained_arg.c @@ -30,6 +30,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -101,7 +102,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", diff --git a/test/wcc/693_dot_tagged_source.c b/test/wcc/693_dot_tagged_source.c index 02171f91..19ea8f13 100644 --- a/test/wcc/693_dot_tagged_source.c +++ b/test/wcc/693_dot_tagged_source.c @@ -43,6 +43,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -316,7 +317,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/694_tagged_store_intlit.c b/test/wcc/694_tagged_store_intlit.c index bd88c5bd..8fdad646 100644 --- a/test/wcc/694_tagged_store_intlit.c +++ b/test/wcc/694_tagged_store_intlit.c @@ -50,6 +50,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -277,7 +278,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/695_match_bind_struct.c b/test/wcc/695_match_bind_struct.c index 4ea846e7..e115251b 100644 --- a/test/wcc/695_match_bind_struct.c +++ b/test/wcc/695_match_bind_struct.c @@ -45,6 +45,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -223,7 +224,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", diff --git a/test/wcc/698_cgreturn_struct.c b/test/wcc/698_cgreturn_struct.c index a2dde9cf..3166dc22 100644 --- a/test/wcc/698_cgreturn_struct.c +++ b/test/wcc/698_cgreturn_struct.c @@ -40,6 +40,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -301,7 +302,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -332,7 +333,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/700_e2e.c b/test/wcc/700_e2e.c index 1341d8ff..4386ea21 100644 --- a/test/wcc/700_e2e.c +++ b/test/wcc/700_e2e.c @@ -8,6 +8,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -1812,7 +1813,7 @@ main(void) snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir); FILE *f = fopen(src, "wb"); - fputs(rows[i].src, f); + wwtest_fputs(rows[i].src, f); fclose(f); char cmd[1024]; diff --git a/test/wcc/701_cgassign_struct.c b/test/wcc/701_cgassign_struct.c index 24009eb4..22e29227 100644 --- a/test/wcc/701_cgassign_struct.c +++ b/test/wcc/701_cgassign_struct.c @@ -50,6 +50,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -291,7 +292,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -322,7 +323,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/702_dot_explicit_deref.c b/test/wcc/702_dot_explicit_deref.c index c3ef26ec..c1a012c4 100644 --- a/test/wcc/702_dot_explicit_deref.c +++ b/test/wcc/702_dot_explicit_deref.c @@ -33,6 +33,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -156,7 +157,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -185,7 +186,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/703_nested_structlit.c b/test/wcc/703_nested_structlit.c index c594e7cc..33c2310b 100644 --- a/test/wcc/703_nested_structlit.c +++ b/test/wcc/703_nested_structlit.c @@ -36,6 +36,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -149,7 +150,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -178,7 +179,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/704_dot_structlit.c b/test/wcc/704_dot_structlit.c index 232f96b5..569a0ddc 100644 --- a/test/wcc/704_dot_structlit.c +++ b/test/wcc/704_dot_structlit.c @@ -41,6 +41,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -201,7 +202,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -230,7 +231,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/705_nested_call_rhs.c b/test/wcc/705_nested_call_rhs.c index 23c589bc..fc00a504 100644 --- a/test/wcc/705_nested_call_rhs.c +++ b/test/wcc/705_nested_call_rhs.c @@ -53,6 +53,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -221,7 +222,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -250,7 +251,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/707_cgreturn_variant_zero.c b/test/wcc/707_cgreturn_variant_zero.c index 20a0f5a0..a7970e25 100644 --- a/test/wcc/707_cgreturn_variant_zero.c +++ b/test/wcc/707_cgreturn_variant_zero.c @@ -65,6 +65,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -310,7 +311,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -341,7 +342,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/709_localoff_scope.c b/test/wcc/709_localoff_scope.c index 0e7a760d..ddf68c2e 100644 --- a/test/wcc/709_localoff_scope.c +++ b/test/wcc/709_localoff_scope.c @@ -80,6 +80,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -273,7 +274,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", diff --git a/test/wcc/710_cast_enum_movl.c b/test/wcc/710_cast_enum_movl.c index 06eef541..80b97540 100644 --- a/test/wcc/710_cast_enum_movl.c +++ b/test/wcc/710_cast_enum_movl.c @@ -110,6 +110,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -347,7 +348,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s 2>/dev/null", @@ -379,7 +380,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/711_arrlit_str_full.c b/test/wcc/711_arrlit_str_full.c index c64eaab9..5b7252d3 100644 --- a/test/wcc/711_arrlit_str_full.c +++ b/test/wcc/711_arrlit_str_full.c @@ -47,6 +47,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -216,7 +217,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/712_redecl.c b/test/wcc/712_redecl.c index ef24e463..f2989de0 100644 --- a/test/wcc/712_redecl.c +++ b/test/wcc/712_redecl.c @@ -53,6 +53,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -193,7 +194,7 @@ run_row(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s >/dev/null 2>&1", diff --git a/test/wcc/713_struct_field_index.c b/test/wcc/713_struct_field_index.c index 73261cf6..514ac38e 100644 --- a/test/wcc/713_struct_field_index.c +++ b/test/wcc/713_struct_field_index.c @@ -52,6 +52,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -148,7 +149,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", diff --git a/test/wcc/714_tagged_return_scratch.c b/test/wcc/714_tagged_return_scratch.c index a874bb32..f76f0079 100644 --- a/test/wcc/714_tagged_return_scratch.c +++ b/test/wcc/714_tagged_return_scratch.c @@ -73,6 +73,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -222,7 +223,7 @@ run_driver(const char *driver, const struct row *r, int i) mkdir(tmpdir, 0755); FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", diff --git a/test/wcc/715_tagged_widen_f64.c b/test/wcc/715_tagged_widen_f64.c index b39c342a..2e1f4db3 100644 --- a/test/wcc/715_tagged_widen_f64.c +++ b/test/wcc/715_tagged_widen_f64.c @@ -53,6 +53,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -190,7 +191,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/716_match_spill_pointer_payload.c b/test/wcc/716_match_spill_pointer_payload.c index 20961c4e..f72da3f1 100644 --- a/test/wcc/716_match_spill_pointer_payload.c +++ b/test/wcc/716_match_spill_pointer_payload.c @@ -42,6 +42,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -144,7 +145,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -175,7 +176,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/717_struct_byval_param.c b/test/wcc/717_struct_byval_param.c index 70fc39f0..07762d62 100644 --- a/test/wcc/717_struct_byval_param.c +++ b/test/wcc/717_struct_byval_param.c @@ -53,6 +53,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -146,7 +147,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -177,7 +178,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/718_struct_multi_return_scratch.c b/test/wcc/718_struct_multi_return_scratch.c index c5819f1c..2d58cce8 100644 --- a/test/wcc/718_struct_multi_return_scratch.c +++ b/test/wcc/718_struct_multi_return_scratch.c @@ -65,6 +65,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -232,7 +233,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", @@ -308,7 +309,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); int rc = 0; diff --git a/test/wcc/719_signed_data_emit.c b/test/wcc/719_signed_data_emit.c index 4709ee10..2607ec35 100644 --- a/test/wcc/719_signed_data_emit.c +++ b/test/wcc/719_signed_data_emit.c @@ -27,6 +27,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -52,44 +53,44 @@ static const struct row rows[] = { /* Scalar i8 = -1 → low byte 0xff, then 7 bytes of sign-extension. */ { "i8_neg", "let x: i8 = -1i8;\n" "fn main() i32 = { return 0; };\n", - "x", + "main.x", "\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff" }, /* Scalar i16 = -2 → 0xfe 0xff then 6 byte sign extension. */ { "i16_neg", "let x: i16 = -2i16;\n" "fn main() i32 = { return 0; };\n", - "x", + "main.x", "\\xfe\\xff\\xff\\xff\\xff\\xff\\xff\\xff" }, /* Scalar i32 = -100 → 0x9C 0xFF 0xFF 0xFF then 4 byte sign extension. */ { "i32_neg", "let x: i32 = -100i32;\n" "fn main() i32 = { return 0; };\n", - "x", + "main.x", "\\x9c\\xff\\xff\\xff\\xff\\xff\\xff\\xff" }, /* Scalar i64 = -1000 → 0xfffffffffffffc18 little-endian. */ { "i64_neg", "let x: i64 = -1000i64;\n" "fn main() i32 = { return 0; };\n", - "x", + "main.x", "\\x18\\xfc\\xff\\xff\\xff\\xff\\xff\\xff" }, /* Array [4]i8 = [1, -2, 3, -4] → 0x01 0xfe 0x03 0xfc. */ { "i8_arr", "let a: [4]i8 = [1i8, -2i8, 3i8, -4i8];\n" "fn main() i32 = { return 0; };\n", - "a", + "main.a", "\\x01\\xfe\\x03\\xfc" }, /* Array [4]i16 = [1, -2, 3, -4] → LE16 each. */ { "i16_arr", "let a: [4]i16 = [1i16, -2i16, 3i16, -4i16];\n" "fn main() i32 = { return 0; };\n", - "a", + "main.a", "\\x01\\x00\\xfe\\xff\\x03\\x00\\xfc\\xff" }, /* Array [3]i32 = [10, -20, 30] → LE32 each. */ { "i32_arr", "let a: [3]i32 = [10i32, -20i32, 30i32];\n" "fn main() i32 = { return 0; };\n", - "a", + "main.a", "\\x0a\\x00\\x00\\x00\\xec\\xff\\xff\\xff\\x1e\\x00\\x00\\x00" }, /* Array [2]i64 = [100, -200] → LE64 each. Note 100 == 'd' and * 56 == '8' are printable ASCII so emit_data_byte writes them * raw rather than as `\xNN`. */ { "i64_arr", "let a: [2]i64 = [100i64, -200i64];\n" "fn main() i32 = { return 0; };\n", - "a", + "main.a", "d\\x00\\x00\\x00\\x00\\x00\\x00\\x00" "8\\xff\\xff\\xff\\xff\\xff\\xff\\xff" }, }; @@ -128,7 +129,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); diff --git a/test/wcc/720_tagged_call_arg.c b/test/wcc/720_tagged_call_arg.c index 30f73b1d..d483e696 100644 --- a/test/wcc/720_tagged_call_arg.c +++ b/test/wcc/720_tagged_call_arg.c @@ -26,6 +26,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -125,7 +126,7 @@ check_pushdx_before_pushax(const char *spath, const struct row *r) long off = 0; int saw_site = 0; for (;;) { - long call = find_after(buf, off, "CALL\tyield_"); + long call = find_after(buf, off, "CALL\tmain.yield_"); if (call < 0) break; saw_site = 1; long pdx = find_after(buf, call, "PUSHQ\tDX"); @@ -162,7 +163,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); diff --git a/test/wcc/721_sret_struct_return.c b/test/wcc/721_sret_struct_return.c index d9f8e133..79e2d0d0 100644 --- a/test/wcc/721_sret_struct_return.c +++ b/test/wcc/721_sret_struct_return.c @@ -41,6 +41,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -144,7 +145,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); @@ -164,8 +165,8 @@ check_leaq_di_before_call(const char *path, const struct row *r) char line[1024]; int ok = -1; while (fgets(line, sizeof line, f)) { - if (strstr(line, "CALL\tmk(SB)") - || strstr(line, "CALL mk(SB)")) { + if (strstr(line, "CALL\tmain.mk(SB)") + || strstr(line, "CALL main.mk(SB)")) { if (strstr(prev, "LEAQ\t") && strstr(prev, "(BP), DI")) { ok = 0; @@ -199,7 +200,7 @@ check_movq_bp_ax_before_ret(const char *path, const struct row *r) int ok = -1; while (fgets(line, sizeof line, f)) { if (!in_mk) { - if (strstr(line, "TEXT mk,") || strstr(line, "TEXT\tmk,")) + if (strstr(line, "TEXT main.mk,") || strstr(line, "TEXT\tmain.mk,")) in_mk = 1; continue; } @@ -241,15 +242,15 @@ check_movq_bp_di_before_inner_call(const char *path, const struct row *r) int ok = -1; while (fgets(line, sizeof line, f)) { if (!in_mk) { - if (strstr(line, "TEXT mk,") - || strstr(line, "TEXT\tmk,")) + if (strstr(line, "TEXT main.mk,") + || strstr(line, "TEXT\tmain.mk,")) in_mk = 1; strncpy(prev, line, sizeof prev - 1); prev[sizeof prev - 1] = '\0'; continue; } - if (strstr(line, "CALL\tinner(SB)") - || strstr(line, "CALL inner(SB)")) { + if (strstr(line, "CALL\tmain.inner(SB)") + || strstr(line, "CALL main.inner(SB)")) { if (strstr(prev, "MOVQ\t") && strstr(prev, "(BP), DI") && !strstr(prev, "LEAQ")) @@ -283,8 +284,8 @@ check_no_movq_ax_bp_after_call(const char *path, const struct row *r) int ok = 0; while (fgets(line, sizeof line, f)) { if (!seen_call) { - if (strstr(line, "CALL\tmk(SB)") - || strstr(line, "CALL mk(SB)")) { + if (strstr(line, "CALL\tmain.mk(SB)") + || strstr(line, "CALL main.mk(SB)")) { seen_call = 1; } continue; diff --git a/test/wcc/722_match_slice_variant.c b/test/wcc/722_match_slice_variant.c index 2db91d16..dadc4452 100644 --- a/test/wcc/722_match_slice_variant.c +++ b/test/wcc/722_match_slice_variant.c @@ -25,6 +25,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -107,7 +108,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); diff --git a/test/wcc/723_composite_call_arg.c b/test/wcc/723_composite_call_arg.c index 5b3388d2..680f85f7 100644 --- a/test/wcc/723_composite_call_arg.c +++ b/test/wcc/723_composite_call_arg.c @@ -24,6 +24,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -84,7 +85,7 @@ check_three_push_after_call(const char *spath, const struct row *r) char buf[1 << 16]; if (slurp(spath, buf, sizeof buf) < 0) return -1; - long call = find_after(buf, 0, "CALL\tview"); + long call = find_after(buf, 0, "CALL\tmain.view"); if (call < 0) { fprintf(stderr, "row[%s]: no CALL view site\n", r->label); return -1; @@ -135,7 +136,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); diff --git a/test/wcc/724_letdecl_zeroinit.c b/test/wcc/724_letdecl_zeroinit.c index 514a1f61..0410f346 100644 --- a/test/wcc/724_letdecl_zeroinit.c +++ b/test/wcc/724_letdecl_zeroinit.c @@ -29,6 +29,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -79,7 +80,7 @@ check_movq_zero_present(const char *spath, const struct row *r) char buf[1 << 16]; if (slurp(spath, buf, sizeof buf) < 0) return -1; - const char *body = strstr(buf, "TEXT produce"); + const char *body = strstr(buf, "TEXT main.produce"); if (!body) { fprintf(stderr, "row[%s]: no TEXT produce label\n", r->label); return -1; @@ -112,7 +113,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); diff --git a/test/wcc/725_nested_if_labels.c b/test/wcc/725_nested_if_labels.c index b3bedb7d..915bbc96 100644 --- a/test/wcc/725_nested_if_labels.c +++ b/test/wcc/725_nested_if_labels.c @@ -30,6 +30,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -76,7 +77,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); diff --git a/test/wcc/726_alias_leaf_collision.c b/test/wcc/726_alias_leaf_collision.c index 74298f44..e3186bde 100644 --- a/test/wcc/726_alias_leaf_collision.c +++ b/test/wcc/726_alias_leaf_collision.c @@ -30,6 +30,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -97,7 +98,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); @@ -172,7 +173,7 @@ check_movsxd_kept(const char *spath, const struct row *r, const char *stage) r->label, stage, spath); return -1; } - const char *fn = strstr(buf, "TEXT promote"); + const char *fn = strstr(buf, "TEXT main.promote"); if (!fn) { fprintf(stderr, "row[%s][%s]: no TEXT promote in %s\n", r->label, stage, spath); diff --git a/test/wcc/729_empty_alloc_infer.c b/test/wcc/729_empty_alloc_infer.c index 9d53984b..6047b8ab 100644 --- a/test/wcc/729_empty_alloc_infer.c +++ b/test/wcc/729_empty_alloc_infer.c @@ -36,6 +36,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -131,7 +132,7 @@ run_row(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, @@ -155,7 +156,7 @@ run_row(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s run %s >/dev/null 2>&1", driver, src); diff --git a/test/wcc/730_sret_narrow_field.c b/test/wcc/730_sret_narrow_field.c index ce816eaa..0ced1b29 100644 --- a/test/wcc/730_sret_narrow_field.c +++ b/test/wcc/730_sret_narrow_field.c @@ -28,6 +28,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -112,7 +113,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); @@ -144,8 +145,8 @@ check_narrow_mov(const char *path, const struct row *r) (void)load_needle; while (fgets(line, sizeof line, f)) { if (!in_mk) { - if (strstr(line, "TEXT mk,") - || strstr(line, "TEXT\tmk,")) + if (strstr(line, "TEXT main.mk,") + || strstr(line, "TEXT\tmain.mk,")) in_mk = 1; continue; } @@ -188,8 +189,8 @@ check_no_movq_at_off(const char *path, const struct row *r) int bad = 0; while (fgets(line, sizeof line, f)) { if (!in_mk) { - if (strstr(line, "TEXT mk,") - || strstr(line, "TEXT\tmk,")) + if (strstr(line, "TEXT main.mk,") + || strstr(line, "TEXT\tmain.mk,")) in_mk = 1; continue; } diff --git a/test/wcc/732_def_const_fold.c b/test/wcc/732_def_const_fold.c index 971f2d46..d2459ccd 100644 --- a/test/wcc/732_def_const_fold.c +++ b/test/wcc/732_def_const_fold.c @@ -44,6 +44,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -133,7 +134,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); /* timeout 180 per repo convention (990-997); test/run does not bound @@ -187,7 +188,7 @@ asm_byte_identical(const char *bin, const char *src, const char *label, int i) FILE *f = fopen(wwsrc, "wb"); if (!f) return -1; - fputs(src, f); + wwtest_fputs(src, f); fclose(f); char w6c[640], w6c_ww[640]; @@ -255,7 +256,7 @@ xmod_fold_present(const char *w6c, const char *stage) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(xmod_src, f); + wwtest_fputs(xmod_src, f); fclose(f); if (emit_s(w6c, src, s, sizeof s) != 0) { @@ -316,7 +317,7 @@ compile_fails(const char *w6c, const struct failrow *r, const char *stage, int i FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); /* A regressed depth guard would HANG the cycle rows rather than fail diff --git a/test/wcc/736_cstage_label_ssot.c b/test/wcc/736_cstage_label_ssot.c index 475aeef8..fd71fa08 100644 --- a/test/wcc/736_cstage_label_ssot.c +++ b/test/wcc/736_cstage_label_ssot.c @@ -35,6 +35,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -94,7 +95,7 @@ emit_s(const char *w6c, const char *src_text, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(src_text, f); + wwtest_fputs(src_text, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); diff --git a/test/wcc/739_chained_index.c b/test/wcc/739_chained_index.c index 69ee8b2d..c21bd26b 100644 --- a/test/wcc/739_chained_index.c +++ b/test/wcc/739_chained_index.c @@ -32,6 +32,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -96,7 +97,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); @@ -117,7 +118,7 @@ check_loadmov(const char *spath, const struct row *r, const char *stage) r->label, stage, spath); return -1; } - const char *fn = strstr(buf, "TEXT probe"); + const char *fn = strstr(buf, "TEXT main.probe"); if (!fn) { fprintf(stderr, "row[%s][%s]: no TEXT probe in %s\n", @@ -149,7 +150,7 @@ check_inner_scale_only(const char *spath, const struct row *r, { char buf[1 << 14]; if (slurp(spath, buf, sizeof buf) < 0) return -1; - const char *fn = strstr(buf, "TEXT probe"); + const char *fn = strstr(buf, "TEXT main.probe"); if (!fn) return -1; const char *ret = strstr(fn, "\tRET\n"); if (!ret) ret = fn + strlen(fn); diff --git a/test/wcc/740_chained_write.c b/test/wcc/740_chained_write.c index e7177454..20cd3ba5 100644 --- a/test/wcc/740_chained_write.c +++ b/test/wcc/740_chained_write.c @@ -34,6 +34,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -98,7 +99,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); @@ -119,7 +120,7 @@ check_storemov(const char *spath, const struct row *r, const char *stage) r->label, stage, spath); return -1; } - const char *fn = strstr(buf, "TEXT probe"); + const char *fn = strstr(buf, "TEXT main.probe"); if (!fn) { fprintf(stderr, "row[%s][%s]: no TEXT probe in %s\n", @@ -164,7 +165,7 @@ check_inner_scale_only(const char *spath, const struct row *r, { char buf[1 << 14]; if (slurp(spath, buf, sizeof buf) < 0) return -1; - const char *fn = strstr(buf, "TEXT probe"); + const char *fn = strstr(buf, "TEXT main.probe"); if (!fn) return -1; const char *ret = strstr(fn, "\tRET\n"); if (!ret) ret = fn + strlen(fn); diff --git a/test/wcc/741_dotbase_chained.c b/test/wcc/741_dotbase_chained.c index 337a1a1e..b002d2b5 100644 --- a/test/wcc/741_dotbase_chained.c +++ b/test/wcc/741_dotbase_chained.c @@ -46,6 +46,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -126,7 +127,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); @@ -146,7 +147,7 @@ check_probe(const char *spath, const struct row *r, const char *stage) r->label, stage, spath); return -1; } - const char *fn = strstr(buf, "TEXT probe"); + const char *fn = strstr(buf, "TEXT main.probe"); if (!fn) { fprintf(stderr, "row[%s][%s]: no TEXT probe in %s\n", diff --git a/test/wcc/743_variadic_pack.c b/test/wcc/743_variadic_pack.c index b9e4c4fa..d02f1f35 100644 --- a/test/wcc/743_variadic_pack.c +++ b/test/wcc/743_variadic_pack.c @@ -25,6 +25,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -67,7 +68,7 @@ check_caller_stores(const char *spath) char buf[1 << 16]; if (slurp(spath, buf, sizeof buf) < 0) return -1; - const char *body = strstr(buf, "TEXT main"); + const char *body = strstr(buf, "TEXT main,"); if (!body) { fprintf(stderr, "variadic_pack: no TEXT main label\n"); return -1; @@ -118,7 +119,7 @@ emit_s(const char *w6c, char *out_s, size_t cap, int tag) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(src_text, f); + wwtest_fputs(src_text, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); diff --git a/test/wcc/744_letcopy_struct.c b/test/wcc/744_letcopy_struct.c index ed8cbe6a..1f35990c 100644 --- a/test/wcc/744_letcopy_struct.c +++ b/test/wcc/744_letcopy_struct.c @@ -31,6 +31,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -200,7 +201,7 @@ check_copy_loads(const char *spath, const struct row *r) static char buf[1 << 16]; if (slurp(spath, buf, sizeof buf) < 0) return -1; - const char *body = strstr(buf, "TEXT produce"); + const char *body = strstr(buf, "TEXT main.produce"); if (!body) { fprintf(stderr, "row[%s]: no TEXT produce label in %s\n", r->label, spath); @@ -233,7 +234,7 @@ emit_s(const char *w6c, const struct row *r, int i, int stage, FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->asm_src, f); + wwtest_fputs(r->asm_src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); @@ -257,7 +258,7 @@ run_driver(const char *driver, const struct row *r, int i, int stage) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->run_src, f); + wwtest_fputs(r->run_src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s 2>/dev/null", diff --git a/test/wcc/754_slice_of_slice_index.c b/test/wcc/754_slice_of_slice_index.c index d65938d9..1253f0fa 100644 --- a/test/wcc/754_slice_of_slice_index.c +++ b/test/wcc/754_slice_of_slice_index.c @@ -51,6 +51,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -111,7 +112,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); @@ -129,7 +130,7 @@ check_stride(const char *spath, const struct row *r, const char *stage) r->label, stage, spath); return -1; } - const char *fn = strstr(buf, "TEXT probe"); + const char *fn = strstr(buf, "TEXT main.probe"); if (!fn) { fprintf(stderr, "row[%s][%s]: no TEXT probe in %s\n", diff --git a/test/wcc/755_amp_dot_idx.c b/test/wcc/755_amp_dot_idx.c index 60608103..f6563ded 100644 --- a/test/wcc/755_amp_dot_idx.c +++ b/test/wcc/755_amp_dot_idx.c @@ -61,6 +61,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -143,7 +144,7 @@ emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src); @@ -161,7 +162,7 @@ check_stride(const char *spath, const struct row *r, const char *stage) r->label, stage, spath); return -1; } - const char *fn = strstr(buf, "TEXT probe"); + const char *fn = strstr(buf, "TEXT main.probe"); if (!fn) { fprintf(stderr, "row[%s][%s]: no TEXT probe in %s\n", diff --git a/test/wcc/757_letbind_void_bang_void.c b/test/wcc/757_letbind_void_bang_void.c index f57f245a..ce970a0d 100644 --- a/test/wcc/757_letbind_void_bang_void.c +++ b/test/wcc/757_letbind_void_bang_void.c @@ -38,6 +38,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -121,7 +122,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); @@ -152,7 +153,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/759_check_enum_fold.c b/test/wcc/759_check_enum_fold.c index 815e1073..5ed3a4d4 100644 --- a/test/wcc/759_check_enum_fold.c +++ b/test/wcc/759_check_enum_fold.c @@ -27,6 +27,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -158,7 +159,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s 2>/dev/null", @@ -191,7 +192,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); diff --git a/test/wcc/760_def_widen_const.c b/test/wcc/760_def_widen_const.c index d30fc06c..28cf1f21 100644 --- a/test/wcc/760_def_widen_const.c +++ b/test/wcc/760_def_widen_const.c @@ -42,6 +42,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -107,7 +108,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); /* timeout 180 per repo convention; test/run does not bound @@ -151,7 +152,7 @@ asm_byte_identical(const char *bin, const char *src, const char *label, int i) FILE *f = fopen(wwsrc, "wb"); if (!f) return -1; - fputs(src, f); + wwtest_fputs(src, f); fclose(f); char w6c[640], w6c_ww[640]; @@ -212,7 +213,7 @@ cstage_narrow_fails(const char *w6c) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(narrow_src, f); + wwtest_fputs(narrow_src, f); fclose(f); snprintf(cmd, sizeof cmd, "timeout 180 %s -o %s %s 2>/dev/null", diff --git a/test/wcc/761_inferred_struct_arg_push.c b/test/wcc/761_inferred_struct_arg_push.c index 4abb43c0..1bfd427a 100644 --- a/test/wcc/761_inferred_struct_arg_push.c +++ b/test/wcc/761_inferred_struct_arg_push.c @@ -62,6 +62,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -208,7 +209,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); /* timeout 180 per repo convention (cf. 760); test/run does not @@ -243,7 +244,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "timeout 180 %s/w6c -o %s %s 2>/dev/null", diff --git a/test/wcc/762_struct_abi_size.c b/test/wcc/762_struct_abi_size.c index 5d4a9e52..ed415e33 100644 --- a/test/wcc/762_struct_abi_size.c +++ b/test/wcc/762_struct_abi_size.c @@ -46,6 +46,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -141,7 +142,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); /* timeout 180 per repo convention (cf. 760, 761); test/run does @@ -176,7 +177,7 @@ asm_byte_identical(const char *bin, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "timeout 180 %s/w6c -o %s %s 2>/dev/null", diff --git a/test/wcc/763_typeeq_fn_ast.c b/test/wcc/763_typeeq_fn_ast.c index a871d3d5..6041b07e 100644 --- a/test/wcc/763_typeeq_fn_ast.c +++ b/test/wcc/763_typeeq_fn_ast.c @@ -57,6 +57,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -181,7 +182,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); /* timeout 180 per repo convention (cf. 761, 762); test/run does diff --git a/test/wcc/764_amp_fn_ident.c b/test/wcc/764_amp_fn_ident.c index c4b39677..d752d783 100644 --- a/test/wcc/764_amp_fn_ident.c +++ b/test/wcc/764_amp_fn_ident.c @@ -60,6 +60,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -99,7 +100,7 @@ static const struct row rows[] = { " return 0;\n" "};\n", NULL, NULL, - "LEAQ\tadd1(SB)", + "LEAQ\tmain.add1(SB)", STAGE_CS | STAGE_WW }, { "branched_callee", "fn aa(x: i32) i32 = { return x; };\n" @@ -111,7 +112,7 @@ static const struct row rows[] = { " return 0;\n" "};\n", NULL, NULL, - "LEAQ\tbb(SB)", + "LEAQ\tmain.bb(SB)", STAGE_CS | STAGE_WW }, { "alias_chain", "fn add1(x: i32) i32 = { return x + 1; };\n" @@ -121,7 +122,7 @@ static const struct row rows[] = { " return 0;\n" "};\n", NULL, NULL, - "LEAQ\tadd1(SB)", + "LEAQ\tmain.add1(SB)", STAGE_CS | STAGE_WW }, { "fn_with_args", "fn many(a: i32, b: i64, p: *i32) i64 = { return b; };\n" @@ -130,7 +131,7 @@ static const struct row rows[] = { " return 0;\n" "};\n", NULL, NULL, - "LEAQ\tmany(SB)", + "LEAQ\tmain.many(SB)", STAGE_CS | STAGE_WW }, { "fn_tuple_return", "fn pair() (i64, str) = { return (7: i64, \"x\"); };\n" @@ -139,7 +140,7 @@ static const struct row rows[] = { " return 0;\n" "};\n", NULL, NULL, - "LEAQ\tpair(SB)", + "LEAQ\tmain.pair(SB)", STAGE_CS | STAGE_WW }, /* Cross-mod: cstage emits the LEAQ via N_DOT TK_AMP (already * working pre-#180). Wwstage bails asserttyped on the same @@ -156,6 +157,7 @@ static const struct row rows[] = { " return 0;\n" "};\n", "wcamffn764mod", + "package wcamffn764mod;\n" "export fn somefn(x: i32) i32 = { return x + 1; };\n", "LEAQ\twcamffn764mod.somefn(SB)", STAGE_CS }, @@ -181,13 +183,13 @@ write_sources(const struct row *r, char *src, size_t srcsz, mkdir(moddir, 0755); FILE *mf = fopen(modfile, "wb"); if (!mf) return -1; - fputs(r->modsrc, mf); + wwtest_fputs(r->modsrc, mf); fclose(mf); } FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); return 0; } diff --git a/test/wcc/765_star_fn_deref.c b/test/wcc/765_star_fn_deref.c index 35bacfbb..e5bdf75d 100644 --- a/test/wcc/765_star_fn_deref.c +++ b/test/wcc/765_star_fn_deref.c @@ -60,6 +60,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -144,7 +145,7 @@ write_source(const char *src_path, const char *src) { FILE *f = fopen(src_path, "wb"); if (!f) return -1; - fputs(src, f); + wwtest_fputs(src, f); fclose(f); return 0; } diff --git a/test/wcc/766_star_fn_deref_call.c b/test/wcc/766_star_fn_deref_call.c index f641d4d9..0ecdfba4 100644 --- a/test/wcc/766_star_fn_deref_call.c +++ b/test/wcc/766_star_fn_deref_call.c @@ -52,6 +52,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -132,7 +133,7 @@ write_source(const char *src_path, const char *src) { FILE *f = fopen(src_path, "wb"); if (!f) return -1; - fputs(src, f); + wwtest_fputs(src, f); fclose(f); return 0; } diff --git a/test/wcc/767_match_variant_dispatch.c b/test/wcc/767_match_variant_dispatch.c index 9b069f5e..85ace00c 100644 --- a/test/wcc/767_match_variant_dispatch.c +++ b/test/wcc/767_match_variant_dispatch.c @@ -78,6 +78,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -182,7 +183,7 @@ write_source(const char *src_path, const char *src) { FILE *f = fopen(src_path, "wb"); if (!f) return -1; - fputs(src, f); + wwtest_fputs(src, f); fclose(f); return 0; } diff --git a/test/wcc/782_strict_package.c b/test/wcc/782_strict_package.c new file mode 100644 index 00000000..21d52855 --- /dev/null +++ b/test/wcc/782_strict_package.c @@ -0,0 +1,163 @@ +/* + * 782_strict_package — #24a strict-package gate, BOTH stages (w6c + w6c_ww). + * + * Every primary section must open with a `package` clause; a missing clause + * on the first real decl is a hard error ("missing package clause"). An + * imported (`//ww:module `) or sep primary-reset region carries its + * identity out-of-band and is exempt; an in-section `package` clause then + * ASSERTS — its leaf must equal the path's last component ("package + * does not match import path

"). A bare `//ww:module-reset` opens a fresh + * primary section that must itself re-declare a clause. + * + * Rule-10: every row runs on cstage `w6c` AND wwstage `w6c_ww`; both must + * agree (accept/reject identically; diagnostic text differs by stage — + * cstage `errorf` carries a position, wwstage `errmsg` is terser — so the + * check is on a shared substring, not the whole line). Reject rows feed RAW + * source: the `package` clause IS the unit under test, so there is no + * auto-prepend here (unlike the migrated codegen fixtures). + */ +#include +#include +#include +#include +#include +#include + +static int +runwait(const char *cmd) +{ + int rc = system(cmd); + if (rc == -1) return -1; + if (WIFEXITED(rc)) return WEXITSTATUS(rc); + return 1; +} + +static int +file_contains(const char *path, const char *needle) +{ + FILE *f = fopen(path, "r"); + if (!f) return 0; + char line[4096]; + int found = 0; + while (fgets(line, sizeof line, f)) + if (strstr(line, needle)) { found = 1; break; } + fclose(f); + return found; +} + +struct row { + const char *label; + const char *src; + int accept; /* 1 = must compile clean; 0 = must reject */ + const char *diag; /* reject: required stderr substring (NULL on accept) */ +}; + +static const struct row rows[] = { + /* 1: a `package main;` executable section. */ + { "pkg_main_accept", + "package main;\nexport fn main() i32 = { return 0; };\n", + 1, NULL }, + /* 2: no clause → hard error on the first decl. */ + { "no_clause_reject", + "export fn main() i32 = { return 0; };\n", + 0, "missing package clause" }, + /* 3: imported region — the clause leaf matches the path leaf. */ + { "module_leaf_match_accept", + "//ww:module foo\npackage foo;\nexport fn x() i32 = { return 0; };\n", + 1, NULL }, + /* 4: imported region — the clause leaf mismatches the path. */ + { "module_leaf_mismatch_reject", + "//ww:module foo\npackage bar;\nexport fn x() i32 = { return 0; };\n", + 0, "does not match import path" }, + /* 5: a comment-only file declares nothing, so no clause is required. */ + { "comment_only_accept", + "// just a comment, no decls\n", + 1, NULL }, + /* 6: a bare `//ww:module-reset` opens a fresh primary section; the + * clause-less second section is rejected (the #84/#24a boundary). */ + { "reset_second_section_reject", + "package main;\nexport fn a() i32 = { return 0; };\n" + "//ww:module-reset\nexport fn b() i32 = { return 0; };\n", + 0, "missing package clause" }, + { NULL, NULL, 0, NULL }, +}; + +/* Compile r->src with `stage` (a w6c-family binary); verify accept/reject + * and, on reject, the diagnostic substring. Returns 0 on success. */ +static int +check_stage(const char *stage, const char *tag, const struct row *r, + const char *tmpdir) +{ + char src[256], sout[256], errf[256], cmd[2048]; + snprintf(src, sizeof src, "%s/sp_%s.ww", tmpdir, r->label); + snprintf(sout, sizeof sout, "%s/sp_%s.s", tmpdir, r->label); + snprintf(errf, sizeof errf, "%s/sp_%s.err", tmpdir, r->label); + + FILE *f = fopen(src, "wb"); + if (!f) { fprintf(stderr, "782 FAIL: write %s\n", src); return 1; } + fputs(r->src, f); + fclose(f); + + snprintf(cmd, sizeof cmd, "%s -o %s %s 2>%s", stage, sout, src, errf); + int rc = runwait(cmd); + + if (r->accept) { + if (rc != 0) { + fprintf(stderr, "782 FAIL: [%s][%s] expected ACCEPT, " + "rejected (rc=%d)\n", r->label, tag, rc); + return 1; + } + return 0; + } + if (rc == 0) { + fprintf(stderr, "782 FAIL: [%s][%s] expected REJECT, " + "accepted\n", r->label, tag); + return 1; + } + if (!file_contains(errf, r->diag)) { + fprintf(stderr, "782 FAIL: [%s][%s] rejected but no `%s` " + "on stderr\n", r->label, tag, r->diag); + return 1; + } + return 0; +} + +int +main(void) +{ + const char *bin = getenv("BIN"); + if (!bin) bin = "out/bin"; + char absbin[1024]; + if (bin[0] != '/') { + char cwd[1024]; + if (getcwd(cwd, sizeof cwd) == NULL) return 1; + snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); + bin = absbin; + } + + char cs[1100], ww[1100], tmpdir[64], rmcmd[160]; + snprintf(cs, sizeof cs, "%s/w6c", bin); + snprintf(ww, sizeof ww, "%s/w6c_ww", bin); + snprintf(tmpdir, sizeof tmpdir, "/tmp/sp782_%d", getpid()); + mkdir(tmpdir, 0755); + snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir); + + /* wwstage twin is gated on its presence (rule 14 / 993 pattern). */ + int have_ww = (access(ww, X_OK) == 0); + + int fail = 0; + for (int i = 0; rows[i].label; i++) { + fail += check_stage(cs, "cs", &rows[i], tmpdir); + if (have_ww) + fail += check_stage(ww, "ww", &rows[i], tmpdir); + } + + runwait(rmcmd); + if (fail) { + fprintf(stderr, "782: %d check(s) failed\n", fail); + return 1; + } + printf("strict_package: 6 rows (accept/reject + leaf-assert + bare-reset) " + "agree on cstage w6c%s (#24a)\n", have_ww ? " and wwstage w6c_ww" : ""); + return 0; +} diff --git a/test/wcc/800_ffi.c b/test/wcc/800_ffi.c index f56b09d8..c0eb0861 100644 --- a/test/wcc/800_ffi.c +++ b/test/wcc/800_ffi.c @@ -11,6 +11,7 @@ #include #include #include +#include "wwtestpkg.h" static char * run6c(const char *bin, const char *src) @@ -18,7 +19,7 @@ run6c(const char *bin, const char *src) char path[64]; snprintf(path, sizeof path, "/tmp/wwffi_%d.ww", getpid()); FILE *f = fopen(path, "wb"); - fputs(src, f); + wwtest_fputs(src, f); fclose(f); char cmd[512]; diff --git a/test/wcc/810_dyn.c b/test/wcc/810_dyn.c index 624285f2..0e752d8f 100644 --- a/test/wcc/810_dyn.c +++ b/test/wcc/810_dyn.c @@ -20,6 +20,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -136,7 +137,7 @@ main(void) snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir); FILE *f = fopen(src, "wb"); - fputs(rows[i].src, f); + wwtest_fputs(rows[i].src, f); fclose(f); char cmd[1024]; diff --git a/test/wcc/940_global_sret_run.c b/test/wcc/940_global_sret_run.c index 4fa8b0e2..970443fe 100644 --- a/test/wcc/940_global_sret_run.c +++ b/test/wcc/940_global_sret_run.c @@ -28,6 +28,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -171,7 +172,7 @@ run_driver(const char *driver, const struct row *r, const char *dir, FILE *f = fopen(src, "wb"); if (!f) return -1; - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, diff --git a/test/wcc/940_str_forrange_loopvar_run.c b/test/wcc/940_str_forrange_loopvar_run.c index 223db149..292de5ff 100644 --- a/test/wcc/940_str_forrange_loopvar_run.c +++ b/test/wcc/940_str_forrange_loopvar_run.c @@ -31,6 +31,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -88,7 +89,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src); diff --git a/test/wcc/949_missingpkg.c b/test/wcc/949_missingpkg.c index 856ad436..a3edd782 100644 --- a/test/wcc/949_missingpkg.c +++ b/test/wcc/949_missingpkg.c @@ -53,7 +53,8 @@ run_miss(const char *bin) snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir); FILE *f = fopen(src, "w"); if (!f) { fprintf(stderr, "949 FAIL: stage miss\n"); runwait(rmcmd); return 1; } - fputs("import nosuchpkg;\n" + fputs("package main;\n" + "import nosuchpkg;\n" "export fn main() i32 = { return 0; };\n", f); fclose(f); diff --git a/test/wcc/950_selfcheck.c b/test/wcc/950_selfcheck.c index fef3cb52..300166fb 100644 --- a/test/wcc/950_selfcheck.c +++ b/test/wcc/950_selfcheck.c @@ -11,6 +11,7 @@ #include #include #include +#include "wwtestpkg.h" static int runcap(const char *cmd, char **outerr, size_t *outlen) @@ -42,7 +43,7 @@ writefile(const char *path, const char *src) { FILE *f = fopen(path, "wb"); if (!f) return -1; - fputs(src, f); + wwtest_fputs(src, f); fclose(f); return 0; } diff --git a/test/wcc/978_intdiv_signed.c b/test/wcc/978_intdiv_signed.c index 932748c8..75c52ae6 100644 --- a/test/wcc/978_intdiv_signed.c +++ b/test/wcc/978_intdiv_signed.c @@ -26,6 +26,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -383,7 +384,7 @@ run_driver(const char *driver, const struct row *r, int i) FILE *f = fopen(src, "wb"); if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); + wwtest_fputs(r->src, f); fclose(f); snprintf(cmd, sizeof cmd, "%s build -o %s %s", diff --git a/test/wcc/989_barefn_collide_run.c b/test/wcc/989_barefn_collide_run.c index 154fcfc4..d2b35fe6 100644 --- a/test/wcc/989_barefn_collide_run.c +++ b/test/wcc/989_barefn_collide_run.c @@ -12,27 +12,23 @@ * class silent miscompile, gate-blind and symmetric cs==ww. Surfaced by * #80's `ww test` coexist (lib/test exports `run`). * - * Fixture (the minimal real repro): a dir-package `aa` exporting `run`, - * imported by a PACKAGE-LESS root that defines its OWN bare `fn run` and - * calls it from `main`. Package-less is REQUIRED: a `package main` root's - * decls mangle `main.` (the package clause sets the module), so its - * `run` would be `main.run` — no collision with `aa.run`, vacuous. Only a - * package-less primary yields a truly BARE `run`, the #84 trigger. + * Strict-package (#24a) form: a dir-package `aa` exporting `run`, imported + * by a `package main;` root that defines its OWN `fn run` and calls it from + * `main`. The root's `run` mangles `main.run` — DISTINCT from the imported + * `aa.run` and from the bare entry `main`. The original #84 trigger (a + * truly BARE `run` from a PACKAGE-LESS root) is unreachable now that + * strict-package forbids package-less primaries; the #84 cgen machinery + * (mod_collect / mod_lookup_for_fn) stays dormant-but-load-bearing for + * genuinely package-less `//ww:module-reset` deps until #24b/#26. * - * Asserts (combined `ww build`, BOTH driver stages; the fix lives in - * mod_collect/mod_lookup_for_fn which run in every mode, so combined is - * the minimal repro — `--sep` reproduces identically): - * 1. Build + run, BOTH stages → exit 9 (the USER's bare `run`, return 9), + * Asserts (combined `ww build`, BOTH driver stages; `--sep` reproduces + * identically): + * 1. Build + run, BOTH stages → exit 9 (the user's `main.run`, return 9), * never aa.run (return 5). * 2. cs==ww (rule 10): the combined `.s` is byte-identical between the * two driver stages. - * 3. NON-VACUITY + SOUNDNESS (the #84-specific signal): the `.s` has - * EXACTLY ONE `TEXT run` (the user's, bare) AND EXACTLY ONE `TEXT - * aa.run` (the import) — i.e. DISTINCT symbols, no dup. Pre-fix this - * row fails: two `TEXT aa.run` (the user's `run` mis-mangled onto the - * import) and zero bare `TEXT run`. (Exit alone is not a reliable - * signal: pre-fix the dup happened to bind the user's copy under this - * link order and still exited 9 — the label count is the proof.) + * 3. DISTINCTNESS: the `.s` has EXACTLY ONE `TEXT main.run` (the user's) + * AND EXACTLY ONE `TEXT aa.run` (the import) — distinct symbols, no dup. * * Light wwstage-driver test (CLAUDE.md rule 14): all intermediates are * `-o`-redirected to /tmp, phase-parallel-safe. Models 989_sepbuild_run.c. @@ -136,9 +132,13 @@ static const char *aa_src = "package aa;\n" "export fn run() i32 = { return 5; };\n"; -/* PACKAGE-LESS root (no `package` clause) → its `fn run` is bare (the #84 - * trigger); a `package main` root would mangle it `main.run` (vacuous). */ +/* Strict-package (#24a) root: declares `package main;`, so its `fn run` + * mangles `main.run` — DISTINCT from the imported `aa.run`, and from the + * bare entry `main`. The bare call `run()` resolves to the local `main.run` + * via the standard exact-hint path (the #84 special-case is bypassed for a + * moduled root). */ static const char *root_src = + "package main;\n" "import aa;\n" "fn run() i32 = { return 9; };\n" "export fn main() i32 = { return run(); };\n"; @@ -191,21 +191,20 @@ main(void) fail++; continue; } - /* (1) the user's bare `run` (9) must win over imported aa.run (5). */ + /* (1) the user's `main.run` (9) must win over imported aa.run (5). */ int rc = runwait(stg[s].prog); if (rc != 9) { fprintf(stderr, "84 FAIL: %s prog exit=%d expected 9 " - "(bare user run, not aa.run=5)\n", stg[s].drv, rc); + "(user main.run, not aa.run=5)\n", stg[s].drv, rc); fail++; } - /* (3) distinct symbols, no dup: exactly one bare `run` + one - * `aa.run`. Pre-fix: two `aa.run` (user run mis-mangled) + zero - * bare `run`. */ - int nrun = count_text_label(stg[s].sfile, "run"); + /* (3) distinct symbols, no dup: exactly one `main.run` + one + * `aa.run`. */ + int nrun = count_text_label(stg[s].sfile, "main.run"); int naa = count_text_label(stg[s].sfile, "aa.run"); if (nrun != 1 || naa != 1) { - fprintf(stderr, "84 FAIL: %s labels TEXT run=%d aa.run=%d " - "(want 1/1 — bare user run distinct from import, no dup)\n", + fprintf(stderr, "84 FAIL: %s labels TEXT main.run=%d aa.run=%d " + "(want 1/1 — user main.run distinct from import, no dup)\n", stg[s].drv, nrun, naa); fail++; } @@ -224,8 +223,8 @@ out: fprintf(stderr, "84: %d check(s) failed\n", fail); return 1; } - printf("barefn_collide: package-less root `fn run` (bare) coexists with " - "imported aa.run — distinct labels, no dup, user run wins (exit 9), " - "cs==ww, both driver stages (#84)\n"); + printf("barefn_collide: `package main;` root `fn run` (main.run) coexists " + "with imported aa.run — distinct labels, no dup, user run wins " + "(exit 9), cs==ww, both driver stages (#84/#24a)\n"); return 0; } diff --git a/test/wcc/989_septest_run.c b/test/wcc/989_septest_run.c index 12eb1dcc..781fb768 100644 --- a/test/wcc/989_septest_run.c +++ b/test/wcc/989_septest_run.c @@ -41,6 +41,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -114,7 +115,7 @@ write_file(const char *path, const char *body) { FILE *f = fopen(path, "wb"); if (!f) return -1; - fputs(body, f); + wwtest_fputs(body, f); fclose(f); return 0; } @@ -196,12 +197,13 @@ static struct tcase cases[] = { /* a non-`fn() void` @test signature must loud-reject, not be coerced. */ { "badsig", NULL, "test/wcc/data/attest_badsig.ww", 0, 0, 1 }, /* a user `fn run` COEXISTS with lib/test's bound runner (post-#80 synth - * `use test;` keys the runner under "test", #84 mangles the user `run` - * bare) → accept and run to exit 0. Under sep the two land in distinct - * units (`run` in __root.s, `test.run` in test.s), so a regressed #84 - * collision re-mangles the user `run` to `test.run` and the force-loaded - * root `.o` + test's `.a` both define `test.run` → w6l duplicate-symbol - * → non-zero; exit 0 is the teeth (empirically confirmed). byteid=1 also + * `use test;` keys the runner under "test"; under strict-package #24a the + * user file's `package main;` mangles its `run` to `main.run`) → accept + * and run to exit 0. Under sep the two land in distinct units (`main.run` + * in __root.s, `test.run` in test.s), so a regressed collision re-mangles + * the user `run` to `test.run` and the force-loaded root `.o` + test's + * `.a` both define `test.run` → w6l duplicate-symbol → non-zero; exit 0 + * is the teeth (empirically confirmed). byteid=1 also * pins this coexist path's cs==ww per-pkg asm + synth presence — the * rule-10 leg the ported 997 `coexist_run` carried over the #84 mangle. */ { "collide_run", NULL, "test/wcc/data/attest_userrun.ww", 0, 1, 0 }, diff --git a/test/wcc/990_selfhost.c b/test/wcc/990_selfhost.c index 230f5767..24fcfb34 100644 --- a/test/wcc/990_selfhost.c +++ b/test/wcc/990_selfhost.c @@ -23,6 +23,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -472,7 +473,7 @@ probe_ww_compile(const char *bin) FILE *f = fopen(src, "wb"); if (!f) { fail++; continue; } - fputs(progs[i].src, f); + wwtest_fputs(progs[i].src, f); fclose(f); snprintf(cmd, sizeof cmd, "timeout 180 %s/wwdump_ww -c %s > %s 2>/dev/null", diff --git a/test/wcc/993_ww_ww.c b/test/wcc/993_ww_ww.c index e8130bdb..99c45bd9 100644 --- a/test/wcc/993_ww_ww.c +++ b/test/wcc/993_ww_ww.c @@ -17,6 +17,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -129,7 +130,8 @@ run_exit_code(const char *bin, const char *driver, int code) snprintf(src, sizeof src, "/tmp/ww_rc_%d_%d.ww", getpid(), code); FILE *f = fopen(src, "w"); if (!f) return -1; - fprintf(f, "export fn main() i32 = {\n\treturn %d;\n};\n", code); + fprintf(f, "package main;\nexport fn main() i32 = {\n\treturn %d;\n};\n", + code); fclose(f); char cmd[256]; @@ -151,7 +153,7 @@ run_build_fail(const char *bin, const char *driver) snprintf(src, sizeof src, "/tmp/ww_badbuild_%d.ww", getpid()); FILE *f = fopen(src, "w"); if (!f) return -1; - fputs("export fn main() i32 = {\n\treturn 1\n", f); /* no ; no } */ + wwtest_fputs("export fn main() i32 = {\n\treturn 1\n", f); /* no ; no } */ fclose(f); char cmd[256]; @@ -178,7 +180,7 @@ run_missing_pkg(const char *bin, const char *driver) snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir); FILE *f = fopen(src, "w"); if (!f) { runwait(rmcmd); return 1; } - fputs("import nosuchpkg;\nexport fn main() i32 = { return 0; };\n", f); + wwtest_fputs("import nosuchpkg;\nexport fn main() i32 = { return 0; };\n", f); fclose(f); /* #8: the sep scratch is mkdir'd before the import-resolution failure, @@ -225,7 +227,7 @@ main(void) { FILE *f = fopen(hello_src, "w"); if (!f) return 1; - fputs("import os;\n\n" + wwtest_fputs("import os;\n\n" "export fn main() i32 = {\n" "\tos.write(1, \"hi\\n\".ptr, 3u64);\n" "\treturn 0;\n" diff --git a/test/wcc/994_w6c_ww.c b/test/wcc/994_w6c_ww.c index 732bd5e5..268e8ddb 100644 --- a/test/wcc/994_w6c_ww.c +++ b/test/wcc/994_w6c_ww.c @@ -18,6 +18,7 @@ #include #include #include +#include "wwtestpkg.h" static int runwait(const char *cmd) @@ -101,7 +102,7 @@ write_file(const char *path, const char *content) { FILE *f = fopen(path, "wb"); if (!f) return -1; - fputs(content, f); + wwtest_fputs(content, f); fclose(f); return 0; } diff --git a/test/wcc/data/attest_userrun.ww b/test/wcc/data/attest_userrun.ww index 16f96157..01845aa3 100644 --- a/test/wcc/data/attest_userrun.ww +++ b/test/wcc/data/attest_userrun.ww @@ -1,15 +1,16 @@ // #80/#84 -T coexist — a user `fn run` COEXISTS with lib/test's bound // runner `run` (the synth main's callee). Once `ww test -c` bundles // lib/test, the synth `use test;` keys lib/test's `run` under module -// "test" (#80: prepended before binding) and the user's package-less -// `run` mangles to a DISTINCT bare `run` (#84) — no duplicate. Both +// "test" (#80: prepended before binding) and the user's `package main;` +// `run` mangles to a DISTINCT `main.run` (#84/#24a) — no duplicate. Both // stages accept under -T and the synth runner runs the @test to exit 0; // the user `run` must NOT hijack the entry. Pre-#80 this loud-rejected // "duplicate fn run". The gate (910/997 coexist_run) static-label-counts -// the -T asm — exactly 1 `TEXT run` (user, bare) + 1 `TEXT test.run` (lib +// the -T asm — exactly 1 `TEXT main.run` (user) + 1 `TEXT test.run` (lib // runner) — pinning #84 distinctness here in the REAL @test/-T path (a -// dead-dup regression yields 0x run / 2x test.run). General callability of -// the bare run is gated separately by 989_barefn_collide. +// dead-dup regression yields 0x main.run / 2x test.run). General +// callability of the user run is gated separately by 989_barefn_collide. +package main; fn run() i32 = { return 9; }; @test fn t_one() void = { diff --git a/test/wcc/data/builtin_redecl_ok.ww b/test/wcc/data/builtin_redecl_ok.ww index 38826204..c6b8a152 100644 --- a/test/wcc/data/builtin_redecl_ok.ww +++ b/test/wcc/data/builtin_redecl_ok.ww @@ -4,6 +4,7 @@ // builtins into c.top, so installtop must DROP this redecl rather than // erroring. Both stages accept; the builtin `nomem` (= !void) wins, so // g()'s i32 arm returns 7. Pins the 771/774/926 shape. +package main; type nomem = !void; fn g() (i32 | nomem) = { return 7; }; export fn main() i32 = { diff --git a/test/wcc/data/dup_def.ww b/test/wcc/data/dup_def.ww index c7ab771b..ddf9d55d 100644 --- a/test/wcc/data/dup_def.ww +++ b/test/wcc/data/dup_def.ww @@ -1,5 +1,6 @@ // #23 — two top-level defs of the same name in one (flat) module. // cstage's install pass rejects "duplicate def D"; wwstage now mirrors. +package main; def D: i32 = 1; def D: i32 = 2; export fn main() i32 = { return 0; }; diff --git a/test/wcc/data/dup_fn.ww b/test/wcc/data/dup_fn.ww index 2977f191..87422861 100644 --- a/test/wcc/data/dup_fn.ww +++ b/test/wcc/data/dup_fn.ww @@ -1,5 +1,6 @@ // #23 — two top-level fns of the same name in the same (flat) module. // cstage's install pass rejects "duplicate fn foo"; wwstage now mirrors. +package main; fn foo() i32 = { return 1; }; fn foo() i32 = { return 2; }; export fn main() i32 = { return foo(); }; diff --git a/test/wcc/data/dup_let.ww b/test/wcc/data/dup_let.ww index a42a0530..298107bb 100644 --- a/test/wcc/data/dup_let.ww +++ b/test/wcc/data/dup_let.ww @@ -1,5 +1,6 @@ // #23 — two top-level lets of the same name in one (flat) module. // cstage's install pass rejects "duplicate let g"; wwstage now mirrors. +package main; let g: i32 = 1; let g: i32 = 2; export fn main() i32 = { return 0; }; diff --git a/test/wcc/data/dup_type.ww b/test/wcc/data/dup_type.ww index 6bae68c0..dfe29df0 100644 --- a/test/wcc/data/dup_type.ww +++ b/test/wcc/data/dup_type.ww @@ -1,5 +1,6 @@ // #23 — two top-level types of the same name in one (flat) module. // cstage's install pass rejects "duplicate type t"; wwstage now mirrors. +package main; type t = i32; type t = u32; export fn main() i32 = { return 0; }; diff --git a/test/wcc/wwtestpkg.h b/test/wcc/wwtestpkg.h new file mode 100644 index 00000000..edcaa4b0 --- /dev/null +++ b/test/wcc/wwtestpkg.h @@ -0,0 +1,61 @@ +/* + * wwtestpkg.h — strict-package (#24a) test support. + * + * Inline ww test fixtures historically omitted the `package main;` clause + * that the parser now requires (a missing clause is a hard error). These + * helpers inject it transparently so the fixtures stay terse, WITHOUT + * disturbing fixtures that already declare their own module identity. + * + * wwtest_fputs is a drop-in for fputs(src, f): it prepends `package main;` + * only when writing at the START of a fresh file (ftell == 0) AND the + * fixture does not already open with its own `package`/`//ww:module` + * directive. The ftell guard keeps multi-part writes and writes to + * non-seekable streams (stderr) behaving exactly like plain fputs. + */ +#ifndef WWTESTPKG_H +#define WWTESTPKG_H + +#include +#include +#include + +static inline int +wwtest_has_module(const char *s) +{ + const char *p = s; + while (p != NULL) { + while (*p == ' ' || *p == '\t') + p++; + if (strncmp(p, "package ", 8) == 0 + || strncmp(p, "package\t", 8) == 0 + || strncmp(p, "//ww:module", 11) == 0) + return 1; + p = strchr(p, '\n'); + if (p != NULL) + p++; + } + return 0; +} + +static inline void +wwtest_fputs(const char *src, FILE *f) +{ + if (ftell(f) == 0 && !wwtest_has_module(src)) + fputs("package main;\n", f); + fputs(src, f); +} + +/* In-process variant: a malloc'd copy of src with the clause prefixed + * (unless src declares its own module). Caller frees. */ +static inline char * +wwtest_wrap(const char *src) +{ + const char *pfx = wwtest_has_module(src) ? "" : "package main;\n"; + size_t np = strlen(pfx), ns = strlen(src); + char *b = malloc(np + ns + 1); + memcpy(b, pfx, np); + memcpy(b + np, src, ns + 1); + return b; +} + +#endif