Every surviving carrier now owns its artifacts: checked mkdir/mkdtemp/ fopen acquisition, one all-exit cleanup funnel per carrier, ENOENT- tolerant checked unlinks, exact-path deletion (rm -rf only for an owned pid-keyed dir or a .sepwork beneath one), and cleanup failure fails a passing carrier without overwriting its diagnostic. In the same pass the carriers adapt to the driver contract this branch lands: --sep and WW_PKGCACHE are gone, -S and the /tmp/ww_run_<pid> scratch contract are asserted, and rows whose runtime or reject coverage moved to test/wcc/data fixtures or test/lang @test owners are trimmed to the byte/artifact/diagnostic observations only they can make. Repair and adaptation ride together because most files interleave both in the same hunks; splitting would manufacture intermediate carrier states that never existed and cannot run against either driver.
100 lines
3.9 KiB
C
100 lines
3.9 KiB
C
/*
|
|
* 815: residual separated-package cstage/wwstage assembly identity.
|
|
* Runtime is owned by r815_*; -S stops both driver legs before assembly,
|
|
* archive creation, and linking. The sorted package-assembly concatenation
|
|
* remains the byte oracle.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/wait.h>
|
|
|
|
struct row { const char *label, *path; };
|
|
static const struct row rows[] = {
|
|
{ "bare_int", "test/wcc/data/r815_bare_int/case.ww" },
|
|
{ "bare_int_neg", "test/wcc/data/r815_bare_int_neg/case.ww" },
|
|
{ "bare_uint", "test/wcc/data/r815_bare_uint/case.ww" },
|
|
{ "uint_highbit", "test/wcc/data/r815_uint_highbit/case.ww" },
|
|
{ "int_printf", "test/wcc/data/r815_int_printf/case.ww" },
|
|
{ "unaffected_i64", "test/wcc/data/r815_unaffected_i64/case.ww" },
|
|
{ "unaffected_str", "test/wcc/data/r815_unaffected_str/case.ww" },
|
|
{ "mixed", "test/wcc/data/r815_mixed/case.ww" },
|
|
};
|
|
|
|
static int runwait(const char *cmd) {
|
|
int rc = system(cmd);
|
|
return rc != -1 && WIFEXITED(rc) ? WEXITSTATUS(rc) : -1;
|
|
}
|
|
|
|
static int copyfile(const char *src, const char *dst) {
|
|
char buf[8192]; size_t n; int rc = 0;
|
|
FILE *in = fopen(src, "rb"), *out;
|
|
if (!in) return -1;
|
|
out = fopen(dst, "wb");
|
|
if (!out) { fclose(in); return -1; }
|
|
while ((n = fread(buf, 1, sizeof buf, in)) != 0)
|
|
if (fwrite(buf, 1, n, out) != n) { rc = -1; break; }
|
|
if (ferror(in)) rc = -1;
|
|
if (fclose(out) != 0) rc = -1;
|
|
fclose(in); return rc;
|
|
}
|
|
|
|
static int samefile(const char *a, const char *b) {
|
|
FILE *fa = fopen(a, "rb"), *fb = fopen(b, "rb"); int rc = 0;
|
|
if (!fa || !fb) rc = -1;
|
|
else for (;;) { int ca = fgetc(fa), cb = fgetc(fb); if (ca != cb) { rc = -1; break; } if (ca == EOF) break; }
|
|
if (fa) fclose(fa); if (fb) fclose(fb); return rc;
|
|
}
|
|
|
|
static int byteid(const char *cdrv, const char *wdrv, const char *cwd,
|
|
const struct row *r, int seq) {
|
|
char tmp[256], src[512], cs[512], ws[512], cmd[2048]; int rc = -1;
|
|
snprintf(tmp, sizeof tmp, "/tmp/fic_%d_b_%d", getpid(), seq);
|
|
snprintf(src, sizeof src, "%s/main815b.ww", tmp);
|
|
snprintf(cs, sizeof cs, "%s/all_cs.s", tmp);
|
|
snprintf(ws, sizeof ws, "%s/all_ww.s", tmp);
|
|
/* an unowned path (stale dir, full /tmp) must not be built in — or
|
|
* rm -rf'd — below. */
|
|
if (mkdir(tmp, 0755) != 0) { perror(tmp); return -1; }
|
|
if (copyfile(r->path, src) != 0) goto out;
|
|
snprintf(cmd, sizeof cmd,
|
|
"cd %s && timeout 180 %s build -S -I %s/lib "
|
|
"-o %s/main815b_c %s 2>/dev/null", tmp, cdrv, cwd, tmp, src);
|
|
if (runwait(cmd) != 0) goto out;
|
|
snprintf(cmd, sizeof cmd,
|
|
"cd %s && timeout 180 %s build -S -I %s/lib "
|
|
"-o %s/main815b_w %s 2>/dev/null", tmp, wdrv, cwd, tmp, src);
|
|
if (runwait(cmd) != 0) goto out;
|
|
snprintf(cmd, sizeof cmd,
|
|
"cat %s/main815b_c.sepwork/*.s > %s 2>/dev/null", tmp, cs);
|
|
if (runwait(cmd) != 0) goto out;
|
|
snprintf(cmd, sizeof cmd,
|
|
"cat %s/main815b_w.sepwork/*.s > %s 2>/dev/null", tmp, ws);
|
|
if (runwait(cmd) != 0) goto out;
|
|
rc = samefile(cs, ws);
|
|
out:
|
|
if (rc != 0) fprintf(stderr, "fmt_int_run[%s]: byte mismatch/error\n", r->label);
|
|
snprintf(cmd, sizeof cmd, "rm -rf %s", tmp);
|
|
if (runwait(cmd) != 0) {
|
|
fprintf(stderr, "fmt_int_run[%s]: cleanup %s failed\n", r->label, tmp);
|
|
if (rc == 0) rc = -1;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int main(void) {
|
|
const char *bin = getenv("BIN"); char cwd[1024], absbin[1024];
|
|
char cdrv[1024], wdrv[1024];
|
|
if (!getcwd(cwd, sizeof cwd)) return 1;
|
|
if (!bin) bin = "out/bin";
|
|
if (bin[0] != '/') { snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); bin = absbin; }
|
|
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
|
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
|
if (access(wdrv, X_OK) != 0) { fprintf(stderr, "fmt_int_run: skip wwstage\n"); return 0; }
|
|
int n = (int)(sizeof rows / sizeof rows[0]), fail = 0;
|
|
for (int i = 0; i < n; i++) if (byteid(cdrv, wdrv, cwd, &rows[i], i) != 0) fail++;
|
|
if (fail) { fprintf(stderr, "fmt_int_run: %d/%d byte rows failed\n", fail, n); return 1; }
|
|
printf("fmt_int_run: %d/%d byte rows ok\n", n, n); return 0;
|
|
}
|