#!/bin/sh set -eu base="${TMPDIR-/tmp}/mcpu-cpp-fmacro-errors-$$" trap 'rm -f "$base".*' EXIT HUP INT TERM cat > "$base.dup.c" <<'EOT' #define F(X, X) X EOT if "$MCPU_CPP" --no-config "$base.dup.c" -o "$base.out" 2>"$base.err"; then echo "duplicate parameter name accepted" >&2 exit 1 fi grep "duplicate argument name 'X'" "$base.err" >/dev/null cat > "$base.few.c" <<'EOT' #define F(X, Y) X + Y F(1) EOT if "$MCPU_CPP" --no-config "$base.few.c" -o "$base.out" 2>"$base.err"; then echo "too few macro arguments accepted" >&2 exit 1 fi grep "used with too few arguments" "$base.err" >/dev/null cat > "$base.many.c" <<'EOT' #define F(X) X F(1, 2) EOT if "$MCPU_CPP" --no-config "$base.many.c" -o "$base.out" 2>"$base.err"; then echo "too many macro arguments accepted" >&2 exit 1 fi grep "used with too many arguments" "$base.err" >/dev/null cat > "$base.unterm.c" <<'EOT' #define F(X) X F(1 EOT if "$MCPU_CPP" --no-config "$base.unterm.c" -o "$base.out" 2>"$base.err"; then echo "unterminated macro call accepted" >&2 exit 1 fi grep "unterminated argument list" "$base.err" >/dev/null cat > "$base.concat-first.c" <<'EOT' #define CAT(X, Y) ## X EOT if "$MCPU_CPP" --no-config "$base.concat-first.c" -o "$base.out" 2>"$base.err"; then echo "leading ## in replacement list accepted" >&2 exit 1 fi grep "'##' cannot appear at the beginning of a macro replacement list" "$base.err" >/dev/null cat > "$base.concat-last.c" <<'EOT' #define CAT(X, Y) Y ## EOT if "$MCPU_CPP" --no-config "$base.concat-last.c" -o "$base.out" 2>"$base.err"; then echo "trailing ## in replacement list accepted" >&2 exit 1 fi grep "'##' cannot appear at the end of a macro replacement list" "$base.err" >/dev/null cat > "$base.sharp-name.c" <<'EOT' #define S(X) #Y EOT if "$MCPU_CPP" --no-config "$base.sharp-name.c" -o "$base.out" 2>"$base.err"; then echo "stringification of a non-parameter accepted" >&2 exit 1 fi grep "'#' operator should be followed by a macro argument name" "$base.err" >/dev/null cat > "$base.sharp-end.c" <<'EOT' #define S(X) # EOT if "$MCPU_CPP" --no-config "$base.sharp-end.c" -o "$base.out" 2>"$base.err"; then echo "unterminated stringification operator accepted" >&2 exit 1 fi grep "'#' operator is not followed by a macro argument name" "$base.err" >/dev/null cat > "$base.bracket.c" <<'EOT' #define F(X) X F(array[x = y, x + 1]) EOT if "$MCPU_CPP" --no-config "$base.bracket.c" -o "$base.out" 2>"$base.err"; then echo "comma in brackets incorrectly protected macro argument" >&2 exit 1 fi grep "used with too many arguments" "$base.err" >/dev/null