#!/bin/sh
# usage: sf3_cc <file.c>  ->  prints cc1 assembly (maspsx applied) for one file
#
# WHY THIS EXISTS (worker F, Phase 11): a full `sf3_match range` run compiles, links, extracts
# and compares.  When you are sweeping SPELLINGS you only need the assembly, and the sweep cost
# dominates everything else.  This makes one spelling cost ~0.1 s, which is what turns "try a
# few variants" into "grid the whole space".
#
# Pair it with `sf3_diff`, which tells you WHICH DIMENSION a residual lives in -- worker F's
# judgement was that these two together are the highest-value tooling it built, because the
# first removes the cost of a spelling and the second removes the guesswork about what is wrong.
#
# Pipeline: cpp -> cc1 (the pinned 2.7.2-psx build) -> maspsx (the project's vendored patched
# version), which is exactly what sf3_match does internally.
#
# PHASE 12 ADDITION -- argument handling, and why it is here rather than in a charter.
# Three of the four Phase 12 workers probed this tool with `--help` and every one got a raw
# coreutils `basename` error, because ANY leading-`-` argument was taken as a source path.
# That is cookbook 179 from the other side: the rule lives in a tracked tool, but the tool
# was not usable the way every worker reaches for it first. A tool that fails confusingly on
# its own help flag costs a worker time on the one path it will always try. So: `--help`
# works, an unknown option is rejected BY NAME, and a missing source file says so instead of
# surfacing a cpp error. The compile path is unchanged.
#
# LIMIT -- READ BEFORE TRUSTING THE OUTPUT. The maspsx stage always runs with DEFAULT options,
# and no region option is passed. This tool shows you a SPELLING's shape, NOT a region's final
# bytes: a region needing a maspsx token (`epilogue`, `nopmarker`, `moves`, `regread`, `off`)
# or `gp=`/`cc1=`/`as=` will look DIFFERENT here than under `sf3_match range`. Sweep SPELLINGS
# with this; decide MATCHES with `sf3_match range`. An `epilogue` row in particular shows the
# UNFILLED tail here, and that token must be decided from the CANDIDATE's tail, never the
# original's (cookbook 165/180).
#
# PHASE 12 FIX -- THE MASPSX STAGE NEVER RAN, AND THEN IT DOUBLED THE OUTPUT.
# Worker B measured it and was right. The call was
#     maspsx.py --aspsx-version=2.56 "$OUT/$BASE.s" "$OUT/$BASE.ms.s"
# but maspsx takes ONE positional (an INPUT) and writes to STDOUT -- it has no output-file
# argument. Compare `sf3_match`, which runs it as a stdin->stdout filter (`run_filter`).
# So maspsx tried to open the OUTPUT path as input, failed, and the failure was hidden TWICE:
# by `2>/dev/null` and by the `|| cp` fallback, which quietly copied the raw cc1 output to
# `.ms.s`. Consequences, both measured on `src/func_8006B5F0.c`:
#
#   run 1, fresh scratch : .ms.s IDENTICAL to .s (71 lines) -- maspsx NEVER APPLIED.
#   run 2, scratch exists: 133 lines = TWO body copies with 6 `addu`, because maspsx now read
#                          the STALE .ms.s as its input, succeeded, printed its real output
#                          STRAIGHT TO STDOUT (unredirected), and then `cat` printed the stale
#                          raw copy after it.
#
# So the output was WRONG on the first run and WRONG AND DOUBLED on every later one, from
# `b29963e` (Phase 11 promotion) until now. Cookbook 185's description of this tool was wrong
# for as long as the bug existed, and the coordinator edited this very file earlier in Phase 12
# to fix `--help` WITHOUT noticing -- while documenting a maspsx-related LIMIT about a stage
# that was not running at all.
#
# The fix is the correct filter form, and the removal of both things that hid the failure.
# A fallback that turns a hard error into plausible output is worse than no fallback: it is
# how a broken tool survives a whole phase of use by four workers.
set -e
REPO=$(cd "$(dirname "$0")/.." && pwd)
cd "$REPO"

if [ $# -lt 1 ]; then
    echo "usage: sf3_cc <file.c>" >&2
    exit 2
fi

case "$1" in
    -h|--help)
        echo "usage: sf3_cc <file.c>   ->  prints cc1 assembly (maspsx applied) for ONE file"
        echo
        echo 'The spelling-sweep tool: one spelling costs ~0.1 s, which is what turns'
        echo '"try a few variants" into "grid the whole space". Pair it with tools/sf3_diff,'
        echo "which names WHICH DIMENSION a residual lives in -- compile+diff together remove"
        echo "both the cost of a spelling and the guesswork about what is wrong."
        echo
        echo "Env: SF3_CC_OUT (default .run/sf3_cc) selects the scratch directory."
        exit 0
        ;;
    -*)
        echo "sf3_cc: unknown option: $1" >&2
        echo "usage: sf3_cc <file.c>" >&2
        exit 2
        ;;
esac

SRC=$1
if [ ! -f "$SRC" ]; then
    echo "sf3_cc: no such source file: $SRC" >&2
    exit 2
fi
BASE=$(basename "$SRC" .c)
OUT=${SF3_CC_OUT:-.run/sf3_cc}
mkdir -p "$OUT"

tools/old-gcc/gcc-2.7.2-psx/cpp -E -P -undef "$SRC" > "$OUT/$BASE.i"
tools/old-gcc/gcc-2.7.2-psx/cc1 -quiet -O2 -G0 "$OUT/$BASE.i" -o "$OUT/$BASE.s"

# maspsx is a stdin->stdout FILTER (same stage `sf3_match` runs). No output-file argument,
# and NO fallback: a maspsx failure must be loud, not silently replaced by raw cc1 output.
python3 tools/maspsx/maspsx.py --aspsx-version=2.56 < "$OUT/$BASE.s" > "$OUT/$BASE.ms.s"

cat "$OUT/$BASE.ms.s"
