#!/bin/sh
# migra-zig.sh — ¿cuáles de las recetas compiler=gcc migran a zig-cc? (frente matar-gcc)
#
# harkaq nombró 47 recetas que compilan con el gcc de Alpine. Muchas se marcaron cuando zig era
# peor (0.13/0.16 segfaultaban C clásicos); zig mejoró. Este script MIDE cuáles ya migran, no lo
# adivina. Para cada una: build con zig-cc y —lo crítico— SMOKE-TEST del binario, porque el
# motivo del gcc era segfault en RUNTIME, no fallo de build. Un artefacto que sella pero
# segfaultea es peor que gcc.
#
#   migra-zig.sh              # prueba todas las compiler=gcc
#   migra-zig.sh htop less    # sólo esas
#
# Salidas: work/migra-zig/{migrable,matraca}.txt
set -u
cd "$(dirname "$0")/../.."
HAMMER="${HAMMER:-./target/debug/hammer}"
OUT="work/migra-zig"; mkdir -p "$OUT"
# ACUMULA entre corridas (no trunca): probar las 47 no cabe en un timeout, así que se corre por
# lotes y cada lote SUMA. `reg` evita duplicar una receta ya clasificada en una corrida previa.
touch "$OUT/migrable.txt" "$OUT/matraca.txt"
ya_hecha() { grep -qE "^$1	" "$OUT/migrable.txt" "$OUT/matraca.txt" 2>/dev/null; }

if [ $# -gt 0 ]; then LISTA="$*"; else
    LISTA=$(grep -lE '^\s*compiler\s*=\s*"gcc"' recipes/*.toml | xargs -n1 basename | sed 's/.toml//')
fi

for n in $LISTA; do
    r="recipes/$n.toml"
    [ -f "$r" ] || continue
    ya_hecha "$n" && continue   # idempotente: no re-medir lo ya clasificado
    tmp="recipes/.mz-$n.toml"
    # compiler=zig-cc + nombre nuevo (forzar build real). El sed del name tolera 1+ espacios.
    sed -E -e 's/^(\s*compiler\s*=\s*)"gcc"/\1"zig-cc"/' -e "s/^(name\s*=\s*)\"$n\"/\1\"$n-mz\"/" "$r" > "$tmp"

    hash=$(timeout "${POR:-200}" "$HAMMER" build "$tmp" --store "$PWD/store" 2>/dev/null | grep -oE '^b3:[a-f0-9]{64}' | head -1)
    rm -f "$tmp"
    if [ -z "$hash" ]; then
        echo "$n	build-falla" >> "$OUT/matraca.txt"; echo "  ✗ $n (no construye con zig)"; continue
    fi

    # Smoke-test: si el artefacto trae binarios, correrlos (--version/--help). Static musl ⇒ corren
    # directo del store. Si NINGUNO corre limpio ⇒ el gcc estaba por un segfault de runtime real.
    art="store/${hash#b3:}-$n-mz"
    bins=$(find "$art/usr/bin" "$art/bin" -type f 2>/dev/null)
    if [ -z "$bins" ]; then
        # Es una lib (sin binario): build OK basta como señal. El consumidor validará el link.
        echo "$n	lib-build-ok" >> "$OUT/migrable.txt"; echo "  ✓ $n (lib, construye con zig)"; continue
    fi
    ok=0; seg=0
    for b in $bins; do
        "$b" --version >/dev/null 2>&1 || "$b" --help >/dev/null 2>&1 || "$b" -V >/dev/null 2>&1
        rc=$?
        # 139=segfault (SIGSEGV+128), 132=SIGILL. Un binario útil suele dar 0/1/2 a --version/--help.
        case $rc in 139|132|134|136) seg=1 ;; 0|1|2) ok=1 ;; esac
    done
    if [ "$seg" = 1 ]; then
        echo "$n	SEGFAULT-runtime" >> "$OUT/matraca.txt"; echo "  ✗ $n (zig lo SEGFAULTEA — el gcc era por esto)"
    elif [ "$ok" = 1 ]; then
        echo "$n	bin-corre" >> "$OUT/migrable.txt"; echo "  ✓ $n (construye Y corre con zig)"
    else
        echo "$n	bin-no-verificable" >> "$OUT/matraca.txt"; echo "  ? $n (construye, binario no verificable)"
    fi
done

echo "─────"
echo "MIGRABLE: $(wc -l < "$OUT/migrable.txt")   MATRACA: $(wc -l < "$OUT/matraca.txt")"
