#!/bin/bash # Build and run the direct compiler harness (tests/CompileTest.mod). # # Same two-phase ISO link recipe as tpshell: a single monolithic invocation # trips gm2's pass-3 rollup on a compiler-size program, so generate the module # list first (-fgen-module-list -> /dev/null, rc=1 is expected) and then link # with -fuse-list. set -u D=/home/eric/Projets/Projets-Modula2/MyWork/TP3-comp/shell GM2=/home/eric/bin/Modula2/Gm2/bin/gm2 cd "$D" || exit 9 FLAGS="-fiso" # Is `compiletest` itself current? It links against the .o files, and `make` # only ever builds `tpshell` - so after an ordinary `make`, compiletest is # routinely OLDER than Compiler.o and still contains the previous compiler. # The check below used to look only at sources-versus-objects, which is blind # to exactly this: it saw "Compiler.mod is not newer than Compiler.o" and # skipped the rebuild, and the matrix then reported the previous compiler's # verdicts with total confidence. That is the worst kind of wrong, because a # real fix stays invisible and a test that should have gone red stays green. # It happened while bisecting the IF-handler bug, and it is the second time # this project has lost time to a stale harness. # # So compiletest is rebuilt whenever it is older than ANY input: the object # files it links, the sources those came from, and its own source. STALE=no for f in compiletest TextBuf.o Posix.o Compiler.o Runtime.o \ tests/CompileTest.mod TextBuf.mod Posix.c Posix.def \ Compiler.mod Runtime.mod Linker.mod; do if [ -e "$f" ] && [ compiletest -ot "$f" ]; then STALE=yes; break; fi done if [ "$STALE" = yes ]; then echo "compiletest is older than its inputs - it would report the OLD compiler" rm -f compiletest fi if [ ! -f TextBuf.o ] || [ ! -f Compiler.o ] || [ ! -f Posix.o ] \ || [ ! -f Runtime.o ] \ || [ TextBuf.mod -nt TextBuf.o ] || [ Compiler.mod -nt Compiler.o ] \ || [ Runtime.mod -nt Runtime.o ] || [ Runtime.def -nt Runtime.o ] \ || [ Compiler.def -nt Compiler.o ] \ || [ Posix.c -nt Posix.o ] || [ Posix.def -nt Posix.o ]; then echo "building support modules (source newer than object)..." # Runtime is listed because Compiler now links against it: the blob is # copied into the code buffer and the TU_* offsets come from it. A # `make clean` (or a fresh checkout) removes every .o, so the C module has # to be built here too - it used to be assumed present, which made the # script fail with "cannot find Posix.o" after any clean. if [ ! -f Posix.o ] || [ Posix.c -nt Posix.o ] || [ Posix.def -nt Posix.o ]; then cc -c Posix.c >/tmp/ct_c_Posix 2>&1 \ || { echo "COMPILE_FAIL Posix"; grep -m5 "error:" /tmp/ct_c_Posix; exit 1; } fi for m in TextBuf Compiler Runtime; do $GM2 $FLAGS -c $m.mod >/tmp/ct_c_$m 2>&1 if [ $? -ne 0 ]; then echo "COMPILE_FAIL $m" grep -m5 -E "error:|Please submit" /tmp/ct_c_$m exit 1 fi done echo " support modules rebuilt" fi rm -f tests/ct.lst compiletest $GM2 $FLAGS -fgen-module-list=tests/ct.lst -o /dev/null \ tests/CompileTest.mod TextBuf.o Posix.o Compiler.o Runtime.o >/tmp/ct_p1 2>&1 p1=$? $GM2 $FLAGS -fuse-list=tests/ct.lst -o compiletest \ tests/CompileTest.mod TextBuf.o Posix.o Compiler.o Runtime.o >/tmp/ct_p2 2>&1 p2=$? if [ $p2 -ne 0 ]; then echo "LINK_FAIL p1_rc=$p1 p2_rc=$p2" grep -E "error:|undefined" /tmp/ct_p2 | head -10 exit 1 fi echo "compiletest built (p1_rc=$p1, phase 1 rc=1 is the expected rollup)" FX=${1:-tests/fixtures} # ---- assert against tests/fixtures/expected.tsv --------------------------- # Previously this script only printed a verdict, so "17 of 23" was a number a # human counted by hand and a wrong error POSITION was invisible. Both the # verdict and the numbers are compared now, and the exit status is meaningful. EXP="$FX/expected.tsv" if [ ! -f "$EXP" ]; then echo "no expectations file $EXP - printing only" ls "$FX"/*.pas 2>/dev/null | ./compiletest exit 0 fi RAW=$(mktemp) || exit 9 ls "$FX"/*.pas 2>/dev/null | ./compiletest > "$RAW" # expected row for a fixture basename, normalised to single spaces # (only rows that actually carry a verdict count, so the wrapped comment # lines in expected.tsv can never be mistaken for data) expect_for() { awk -F'\t' -v n="$1" ' ($2 == "OK" || $2 == "ERR") && $1 == n { out = "" for (i = 2; i <= NF; i++) out = (out == "") ? $i : out " " $i print out exit } ' "$EXP" } pass=0; fail=0 while IFS= read -r base; do actual=$(grep -F "$base" "$RAW" \ | head -1 \ | tr -d '\r' \ | sed -E 's/^[^ ]+[[:space:]]+//' \ | tr -s ' ' \ | sed -E 's/^OK code=([0-9]+) data=([0-9]+)$/OK \1 \2/; s/^ERROR ([0-9]+) at pos ([0-9]+)$/ERR \1 \2/') want=$(expect_for "$base" | tr -s ' ') if [ -z "$want" ]; then printf ' %-24s NO_EXPECTATION got: %s\n' "$base" "$actual" fail=$((fail + 1)) elif [ "$actual" = "$want" ]; then printf ' %-24s PASS %s\n' "$base" "$actual" pass=$((pass + 1)) else printf ' %-24s FAIL\n expected: %s\n actual: %s\n' \ "$base" "$want" "$actual" fail=$((fail + 1)) fi done </dev/null | xargs -n1 basename | sed 's/\.pas$//') EOF echo "----------------------------------------------------------------" echo "compile matrix: $pass passed, $fail failed (of $((pass + fail)))" rm -f "$RAW" [ "$fail" -eq 0 ] || exit 1