/* * 110_uniesc_run — .wwi round-trip carrier for \u / \U Unicode escapes. * * The value-row half (rune/string \u \U \x decode asserts) migrated to the * in-language row-table test/lang/uniesc_test.ww (fold-6, task #4); this * file retains ONLY the .wwi round-trip case, which is a two-package * sep-build observer with no in-language @test home (it asserts the * PRODUCER re-serializes a wide-rune `def` byte-exact, observed across a * package boundary — not expressible as a single-compile @test). * * An exported wide-rune `def` re-serialized by the producer must re-parse * into the same codepoint (the write-twin of the lexer read-fix — * cmd/w6c/wwi.c wwi_rune / selfhost/cmd/wcc/wwi.ww wwirune emit \u/\U above * 0xFF). Runs through both the cstage `ww` and wwstage `ww_ww` drivers * (task #50); the wwstage arm is skipped when ww_ww is absent (a * cstage-only build), mirroring 640_int_cast_signed. */ #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; } /* run_roundtrip — sep-build a two-package program where the imported * package exports wide-rune defs; the producer must serialize them as * \u/\U so the importer re-parses the same codepoint. Returns the built * program's exit code (42 on a correct round-trip). */ static int run_roundtrip(const char *driver, int id) { char dir[80], wrdir[112], wrp[176], mainp[160], cmd[1024]; char outbin[160], scratch[176]; snprintf(dir, sizeof dir, "/tmp/wwue_rt_%d_%d", getpid(), id); snprintf(wrdir, sizeof wrdir, "%s/wr", dir); snprintf(wrp, sizeof wrp, "%s/wr.ww", wrdir); snprintf(mainp, sizeof mainp, "%s/main.ww", dir); snprintf(outbin, sizeof outbin, "%s/main", dir); snprintf(scratch, sizeof scratch, "%s/main.sepwork", dir); if (mkdir(dir, 0755) != 0) { perror(dir); return -1; } int got = -1; int wr_owned = 0; if (mkdir(wrdir, 0755) != 0) { perror(wrdir); goto cleanup; } wr_owned = 1; FILE *f = fopen(wrp, "wb"); if (!f) { perror(wrp); goto cleanup; } /* one def per serializer branch: \x (<=0xFF), \u (<=0xFFFF), \U. */ fputs("package wr;\n" "export def EACUTE: rune = '\\u00e9';\n" "export def EURO: rune = '\\u20ac';\n" "export def SMILEY: rune = '\\U0001F600';\n", f); if (fclose(f) != 0) { perror(wrp); goto cleanup; } f = fopen(mainp, "wb"); if (!f) { perror(mainp); goto cleanup; } fputs("package main;\n" "import wr;\n" "fn main() i32 = {\n" " let a: rune = wr.EACUTE;\n" " let b: rune = wr.EURO;\n" " let c: rune = wr.SMILEY;\n" " if ((a: u32) != 233u32) { return 1; };\n" " if ((b: u32) != 8364u32) { return 2; };\n" " if ((c: u32) != 128512u32) { return 3; };\n" " return 42;\n" "};\n", f); if (fclose(f) != 0) { perror(mainp); goto cleanup; } snprintf(cmd, sizeof cmd, "cd %s && %s build main.ww", dir, driver); if (runwait(cmd) != 0) { fprintf(stderr, "roundtrip: build via %s failed\n", driver); goto cleanup; } got = runwait(outbin); cleanup: /* `ww build` retains this exact caller-owned scratch tree. */ snprintf(cmd, sizeof cmd, "rm -rf %s", scratch); int cleanfail = runwait(cmd) != 0; if (unlink(outbin) != 0 && errno != ENOENT) { perror(outbin); cleanfail = 1; } if (unlink(mainp) != 0 && errno != ENOENT) { perror(mainp); cleanfail = 1; } if (wr_owned) { if (unlink(wrp) != 0 && errno != ENOENT) { perror(wrp); cleanfail = 1; } if (rmdir(wrdir) != 0) { perror(wrdir); cleanfail = 1; } } if (rmdir(dir) != 0) { perror(dir); cleanfail = 1; } if (cleanfail && got == 42) got = -1; return got; } 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 cdrv[1024]; snprintf(cdrv, sizeof cdrv, "%s/ww", bin); char wdrv[1024]; snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin); struct { const char *name; const char *path; int gated_on_existence; } drivers[] = { { "cstage", cdrv, 0 }, { "wwstage", wdrv, 1 }, { NULL, NULL, 0 }, }; int total = 0, fail = 0; for (int d = 0; drivers[d].name; d++) { if (drivers[d].gated_on_existence && access(drivers[d].path, X_OK) != 0) { fprintf(stderr, "uniesc_run: skip %s (no %s)\n", drivers[d].name, drivers[d].path); continue; } int rt = run_roundtrip(drivers[d].path, d); total++; if (rt != 42) { fprintf(stderr, "uniesc_run[%s][wwi_roundtrip]: exit=%d want=42\n", drivers[d].name, rt); fail++; } } if (fail) { fprintf(stderr, "uniesc_run: %d/%d fixtures failed\n", fail, total); return 1; } printf("uniesc_run: %d/%d ok\n", total, total); return 0; }