#!/bin/sh set -eu base="${TMPDIR-/tmp}/mcpu-cpp-conditionals-$$" mkdir -p "$base/inc" trap 'rm -rf "$base"' EXIT HUP INT TERM cat > "$base/inc/guard.h" <<'EOT' #ifndef MCPP_TEST_GUARD_H #define MCPP_TEST_GUARD_H 1 #define HEADER_VALUE 17 header_line #endif EOT cat > "$base/main.c" <<'EOT' #define A 1 #define B 2 #define F(x) ((x) + 1) #include #include #if A + B * 3 == 7 && defined(A) && !defined(NO_SUCH_MACRO) if_line #else bad_if #endif #if 0 #define BAD_SKIPPED 1 bad_elif_0 #elif F(B) == 3 elif_line #else bad_elif_else #endif #ifdef A ifdef_line #else bad_ifdef #endif #ifndef NO_SUCH_MACRO ifndef_line #endif #if 0 # if 1 / 0 bad_nested # endif #else nested_skip_line #endif #if 0 && (1 / 0) bad_short_and #endif #if 1 || (1 / 0) short_or_line #endif #if 1 ? 2 : 1 / 0 ternary_true_line #endif #if 0 ? 1 / 0 : 3 ternary_false_line #endif #if UNKNOWN_IDENTIFIER bad_unknown #else unknown_zero_line #endif EOT "$MCPU_CPP" --no-config -I"$base/inc" -dD "$base/main.c" -o "$base/out" for word in \ header_line if_line elif_line ifdef_line ifndef_line nested_skip_line \ short_or_line ternary_true_line ternary_false_line unknown_zero_line; do test "`grep -c "^${word}$" "$base/out"`" -eq 1 done for word in \ bad_if bad_elif_0 bad_elif_else bad_ifdef bad_nested bad_short_and bad_unknown; do if grep "^${word}$" "$base/out" >/dev/null; then exit 1; fi done # Conditional-control directives are consumed by the preprocessor and never # survive in the normal output, including -dD output. if grep '^[[:blank:]]*#[[:blank:]]*\(if\|ifdef\|ifndef\|elif\|else\|endif\)\>' "$base/out" >/dev/null; then exit 1 fi # Active definitions are retained by -dD, skipped ones are not. grep '^#define A 1$' "$base/out" >/dev/null grep '^#define HEADER_VALUE 17$' "$base/out" >/dev/null if grep '^#define BAD_' "$base/out" >/dev/null; then exit 1; fi cat > "$base/bad-endif.c" <<'EOT' #endif EOT if "$MCPU_CPP" --no-config "$base/bad-endif.c" -o "$base/bad-out" 2>/dev/null; then exit 1 fi cat > "$base/bad-else.c" <<'EOT' #if 1 #else #else #endif EOT if "$MCPU_CPP" --no-config "$base/bad-else.c" -o "$base/bad-out" 2>/dev/null; then exit 1 fi cat > "$base/bad-elif.c" <<'EOT' #if 0 #else #elif 1 #endif EOT if "$MCPU_CPP" --no-config "$base/bad-elif.c" -o "$base/bad-out" 2>/dev/null; then exit 1 fi cat > "$base/unterminated.c" <<'EOT' #if 1 unterminated EOT if "$MCPU_CPP" --no-config "$base/unterminated.c" -o "$base/bad-out" 2>/dev/null; then exit 1 fi