summaryrefslogtreecommitdiff
path: root/tests/t0039-command-line-macros.sh
diff options
context:
space:
mode:
Diffstat (limited to 'tests/t0039-command-line-macros.sh')
-rwxr-xr-xtests/t0039-command-line-macros.sh174
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