#!/bin/sh set -eu : "${CPU_AS:?CPU_AS is not set}" tmp="${TMPDIR:-/tmp}/libcpu-line-$$" trap 'rm -rf "$tmp"' EXIT HUP INT TERM mkdir -p "$tmp" # --help remains a compact public interface. Preprocessor source-control # details belong to the documentation, not to the command-line synopsis. "$CPU_AS" --help >"$tmp/help.txt" 2>&1 grep -q -- '--help' "$tmp/help.txt" grep -q -- '-o ' "$tmp/help.txt" if grep -q -- '#line' "$tmp/help.txt"; then echo "mcpu-as --help unexpectedly documents obsolete #line" >&2 exit 1 fi # The assembler accepts the usual UNIX-style option ordering. -c is no # longer part of the interface because mcpu-as always produces ET_REL. cat >"$tmp/cli.s" <<'SRC' .text .global helper helper: RET SRC "$CPU_AS" -o "$tmp/cli-before.o" "$tmp/cli.s" >/dev/null "$CPU_AS" "$tmp/cli.s" -o "$tmp/cli-after.o" >/dev/null test -s "$tmp/cli-before.o" test -s "$tmp/cli-after.o" cmp "$tmp/cli-before.o" "$tmp/cli-after.o" if "$CPU_AS" -c "$tmp/cli.s" -o "$tmp/cli-old.o" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted obsolete -c" >&2 exit 1 fi grep -Fq 'mcpu-as: unknown option -c' "$tmp/err.txt" # Native diagnostics count every ordinary physical source line, including a # zero-length line. cat >"$tmp/physical.s" <<'SRC' .text BAD_OPCODE SRC if "$CPU_AS" -o "$tmp/physical.o" "$tmp/physical.s" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted invalid physical-line source" >&2 exit 1 fi grep -Fq "$tmp/physical.s:3: error:" "$tmp/err.txt" # Preprocessor line markers set the logical number and optional filename of the # source line immediately following the marker. Trailing preprocessor flags # are deliberately ignored by mcpu-as. cat >"$tmp/marker.S" <<'SRC' # 7 "included source.s" 1 3 4 anything-after-the-filename-is-ignored .text THIS_IS_NOT_AN_INSTRUCTION SRC if "$CPU_AS" -o "$tmp/marker.o" "$tmp/marker.S" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted invalid marker source" >&2 exit 1 fi grep -Fq 'included source.s:8: error:' "$tmp/err.txt" # The logical counter continues across empty ordinary lines. cat >"$tmp/blank-lines.S" <<'SRC' # 4 "dyn.s" .text helper: BAD_OPCODE SRC if "$CPU_AS" -o "$tmp/blank-lines.o" "$tmp/blank-lines.S" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted invalid blank-line source" >&2 exit 1 fi grep -Fq 'dyn.s:7: error:' "$tmp/err.txt" # Omitting the filename retains the previous logical filename. Leading zeroes # remain decimal: 0200 means line 200, not octal 128. cat >"$tmp/preserve.s" <<'SRC' # 100 "first-name.s" # 0200 .text BAD_OPCODE SRC if "$CPU_AS" -o "$tmp/preserve.o" "$tmp/preserve.s" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted invalid preserve test" >&2 exit 1 fi grep -Fq 'first-name.s:201: error:' "$tmp/err.txt" # Zero is accepted. Here .text is logical line 0 and the bad opcode is line 1. cat >"$tmp/zero.s" <<'SRC' # 0 "zero.s" .text BAD_OPCODE SRC if "$CPU_AS" -o "$tmp/zero.o" "$tmp/zero.s" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted invalid zero-line test" >&2 exit 1 fi grep -Fq 'zero.s:1: error:' "$tmp/err.txt" # The accepted decimal marker range remains 0..2147483647. cat >"$tmp/range.s" <<'SRC' # 2147483648 "too-large.s" .text SRC if "$CPU_AS" -o "$tmp/range.o" "$tmp/range.s" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted an out-of-range line marker" >&2 exit 1 fi grep -Fq 'range.s:1: error: preprocessor line marker value is outside 0..2147483647' "$tmp/err.txt" # #pragma and #lang are passed through by preprocessing stages for other # consumers. mcpu-as ignores them and they do not advance the logical counter. cat >"$tmp/meta.s" <<'SRC' # 100 "meta.s" #pragma once #lang "mcpu" BAD_OPCODE SRC if "$CPU_AS" -o "$tmp/meta.o" "$tmp/meta.s" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted invalid pragma/lang source" >&2 exit 1 fi grep -Fq 'meta.s:100: error:' "$tmp/err.txt" # Other '#' lines are discarded as assembler syntax but still count as normal # logical source lines. cat >"$tmp/hash.s" <<'SRC' # 50 "hash.s" #define SOMETHING 1 #unknown whatever BAD_OPCODE SRC if "$CPU_AS" -o "$tmp/hash.o" "$tmp/hash.s" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted invalid generic-hash source" >&2 exit 1 fi grep -Fq 'hash.s:52: error:' "$tmp/err.txt" # Historical #line is no longer a source-location directive. It is simply an # unrecognized '#' line: ignored as syntax, counted as a normal source line, # and it must not replace the diagnostic filename or line counter. cat >"$tmp/obsolete-line.s" <<'SRC' #line 700 "obsolete.s" .text BAD_OPCODE SRC if "$CPU_AS" -o "$tmp/obsolete-line.o" "$tmp/obsolete-line.s" >"$tmp/out.txt" 2>"$tmp/err.txt"; then echo "mcpu-as unexpectedly accepted invalid obsolete-#line source" >&2 exit 1 fi grep -Fq "$tmp/obsolete-line.s:3: error:" "$tmp/err.txt" if grep -Fq 'obsolete.s:' "$tmp/err.txt"; then echo "obsolete #line unexpectedly changed source coordinates" >&2 exit 1 fi # A normal preprocessor marker is accepted independently of the input suffix. cat >"$tmp/good.s" <<'SRC' # 42 "generated/original source.s" 1 .text .global helper helper: RET SRC "$CPU_AS" -o "$tmp/good.o" "$tmp/good.s" >/dev/null test -s "$tmp/good.o" echo "libmcpu mcpu-as preprocessor source-control regression: PASS"