diff options
Diffstat (limited to 'tests/t0039-command-line-macros.sh')
| -rwxr-xr-x | tests/t0039-command-line-macros.sh | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/tests/t0039-command-line-macros.sh b/tests/t0039-command-line-macros.sh new file mode 100755 index 0000000..94a5ec3 --- /dev/null +++ b/tests/t0039-command-line-macros.sh @@ -0,0 +1,174 @@ +#!/bin/sh +set -eu +base="${TMPDIR-/tmp}/mcpu-cpp-command-line-macros-$$" +mkdir -p "$base" +trap 'rm -rf "$base"' EXIT HUP INT TERM + +cat > "$base/main.c" <<'EOT' +OBJECT +DEFAULT +EMPTY marker +СУММА(10, 7) +АНДРЕЙ +résumé +ПОРЯДОК +СТРОКА(АНДРЕЙ) +СКЛЕИТЬ(АНД,РЕЙ) +#ifdef __MCPU_CPP_VERSION__ +BUILTIN_PRESENT +#else +BUILTIN_REMOVED +#endif +#if defined(КОМАНДА) && КОМАНДА == 31 +CONDITIONAL_OK +#else +CONDITIONAL_BAD +#endif +EOT + +"$MCPU_CPP" --no-config \ + -D OBJECT=17 \ + -DDEFAULT \ + -DEMPTY= \ + '-DСУММА(лево,право)=лево + право' \ + -DАНДРЕЙ=23 \ + -Drésumé=29 \ + -DПОРЯДОК=1 -U ПОРЯДОК -DПОРЯДОК=2 \ + '-DСТРОКА(x)=#x' \ + '-DСКЛЕИТЬ(a,b)=a ## b' \ + -DАНДРЕЙ=23 \ + -U__MCPU_CPP_VERSION__ \ + -DКОМАНДА=31 \ + "$base/main.c" -o "$base/out" + +grep '^17$' "$base/out" >/dev/null +grep '^1$' "$base/out" >/dev/null +grep '^ marker$' "$base/out" >/dev/null +grep '^10 + 7$' "$base/out" >/dev/null +test "`grep -c '^23$' "$base/out"`" -eq 2 +grep '^29$' "$base/out" >/dev/null +grep '^2$' "$base/out" >/dev/null +grep '^"АНДРЕЙ"$' "$base/out" >/dev/null +grep '^BUILTIN_REMOVED$' "$base/out" >/dev/null +if grep '^BUILTIN_PRESENT$' "$base/out" >/dev/null; then exit 1; fi +grep '^CONDITIONAL_OK$' "$base/out" >/dev/null +if grep '^CONDITIONAL_BAD$' "$base/out" >/dev/null; then exit 1; fi + +# A function-like -D without '=' has the GNU meaning "replacement is 1". +printf '%s\n' 'F(99)' > "$base/default-func.c" +"$MCPU_CPP" --no-config '-DF(x)' "$base/default-func.c" -o "$base/default-func.out" +grep '^1$' "$base/default-func.out" >/dev/null + +# Unicode XID continuation works on the command line as it does in source. +combining=$(printf 'e\314\201') +printf '%s\n' "$combining" > "$base/combining.c" +"$MCPU_CPP" --no-config "-D$combining=37" "$base/combining.c" -o "$base/combining.out" +grep '^37$' "$base/combining.out" >/dev/null + +arabic_three=$(printf '\331\243') +name="ИМЯ$arabic_three" +printf '%s\n' "$name" > "$base/digit.c" +"$MCPU_CPP" --no-config "-D$name=43" "$base/digit.c" -o "$base/digit.out" +grep '^43$' "$base/digit.out" >/dev/null + +# Command-line definitions pass through the same phase-3 comment cleanup as +# source #define directives. +printf '%s\n' 'COMMENTED' > "$base/comment.c" +"$MCPU_CPP" --no-config '-DCOMMENTED=left/* comment */right' \ + "$base/comment.c" -o "$base/comment.out" +grep '^left right$' "$base/comment.out" >/dev/null + +# -dM observes the final command-line macro state. +printf '%s\n' '' > "$base/empty.c" +"$MCPU_CPP" --no-config -dM -DПОРЯДОК=1 -UПОРЯДОК -DПОРЯДОК=2 \ + "$base/empty.c" -o "$base/macros" +grep '^#define ПОРЯДОК 2$' "$base/macros" >/dev/null + +# '$' is accepted after the first identifier character. Single quotes protect +# it from shell parameter expansion; without quotes a backslash can do the same. +"$MCPU_CPP" --no-config -dD '-DАНДРЕЙ$_Y=62' -DОЛЬГА\$OLD=37 \ + "$base/empty.c" -o "$base/dollar-command-line" +grep '^#define АНДРЕЙ$_Y 62$' "$base/dollar-command-line" >/dev/null +grep '^#define ОЛЬГА$OLD 37$' "$base/dollar-command-line" >/dev/null + +# '$' is not an identifier-start character. +if "$MCPU_CPP" --no-config '-D$BAD=1' "$base/empty.c" -o "$base/bad" \ + >"$base/dollar-start.stdout" 2>"$base/dollar-start.stderr"; then + exit 1 +fi +grep 'macro name expected after #define' "$base/dollar-start.stderr" >/dev/null + +# For -D/-U an invalid tail after a valid identifier is discarded rather than +# becoming part of the replacement list. The value after '=' is preserved. +"$MCPU_CPP" --no-config -dD '-DАНДРЕЙ@XYZ=62' '-DABC+TAIL=17' \ + '-UREMOVE@TAIL' -DREMOVE=99 "$base/empty.c" -o "$base/invalid-tail" +grep '^#define АНДРЕЙ 62$' "$base/invalid-tail" >/dev/null +grep '^#define ABC 17$' "$base/invalid-tail" >/dev/null +grep '^#define REMOVE 99$' "$base/invalid-tail" >/dev/null +if grep '^#define АНДРЕЙ @XYZ 62$' "$base/invalid-tail" >/dev/null; then + exit 1 +fi + +# Explicit '=' in an -U tail is just another invalid suffix and is discarded. +"$MCPU_CPP" --no-config -DNAME=1 '-UNAME=bad' -dM "$base/empty.c" -o "$base/undef-tail" +if grep '^#define NAME ' "$base/undef-tail" >/dev/null; then + exit 1 +fi + +# In -dD output command-line definitions have their own GNU-style origin +# marker and must not be reported as predefined/builtin macros. +"$MCPU_CPP" --no-config -dD -DАНДРЕЙ_К=62 -DОЛЬГА=37 \ + "$base/empty.c" -o "$base/dD-command-line" +awk ' + /^#define АНДРЕЙ_К 62$/ { + if( previous != "# 0 \"<command-line>\"") exit 1 + andrey = 1 + } + /^#define ОЛЬГА 37$/ { + if( previous != "# 0 \"<command-line>\"") exit 1 + olga = 1 + } + /^#define __MCPU_CPP_VERSION__ / { + if( previous != "# 0 \"<built-in>\"") exit 1 + builtin = 1 + } + { previous = $0 } + END { if( !andrey || !olga || !builtin ) exit 1 } +' "$base/dD-command-line" + +# An unterminated block comment in a command-line definition is diagnosed. +if "$MCPU_CPP" --no-config '-DBROKEN=left/*' "$base/empty.c" -o "$base/bad" \ + >"$base/comment-bad.stdout" 2>"$base/comment-bad.stderr"; then + exit 1 +fi +grep -- '-D: unterminated comment' "$base/comment-bad.stderr" >/dev/null + +# Malformed macro names are rejected by the ordinary #define/#undef parsers. +if "$MCPU_CPP" --no-config -D1ABC=2 "$base/empty.c" -o "$base/bad" \ + >"$base/bad.stdout" 2>"$base/bad.stderr"; then + exit 1 +fi +grep 'macro name expected after #define' "$base/bad.stderr" >/dev/null + + +# Only -D/-U payloads are decoded. Invalid UTF-8 and valid supplementary-plane +# UTF-8 are rejected because the internal text model is strict UCS-2. +bad_utf8=$(printf '\377') +if "$MCPU_CPP" --no-config "-D${bad_utf8}=1" "$base/empty.c" -o "$base/bad" \ + >"$base/utf8.stdout" 2>"$base/utf8.stderr"; then + exit 1 +fi +grep -- '-D: invalid UTF-8 or non-UCS-2 character' "$base/utf8.stderr" >/dev/null + +non_ucs2=$(printf '\360\237\230\200') +if "$MCPU_CPP" --no-config "-D${non_ucs2}=1" "$base/empty.c" -o "$base/bad" \ + >"$base/nonucs2.stdout" 2>"$base/nonucs2.stderr"; then + exit 1 +fi +grep -- '-D: invalid UTF-8 or non-UCS-2 character' "$base/nonucs2.stderr" >/dev/null + +if "$MCPU_CPP" --no-config "-U${bad_utf8}" "$base/empty.c" -o "$base/bad" \ + >"$base/utf8u.stdout" 2>"$base/utf8u.stderr"; then + exit 1 +fi +grep -- '-U: invalid UTF-8 or non-UCS-2 character' "$base/utf8u.stderr" >/dev/null |
