blob: d1ae5db90d06695084ad0a3128c152303dff4b87 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
#!/bin/sh
set -eu
base="${TMPDIR-/tmp}/mcpu-cpp-ucs2-identifiers-$$"
mkdir -p "$base"
trap 'rm -rf "$base"' EXIT HUP INT TERM
# The source file is UTF-8 externally. mcpu-cpp decodes it to strict UCS-2,
# and identifier classification is then performed with the locale-independent
# Unicode XID_Start/XID_Continue predicates provided by LibMPUIO.
cat > "$base/main.c" <<'EOT'
#define АНДРЕЙ 11
#define résumé 12
#define Élève 13
#define ΩΜΕΓΑ 14
#define переменная2 15
#define a١ 16
#define é 17
#define СУММА(лево, право) лево + право
#define СТРОКА(имя) #имя
#define СКЛЕИТЬ(лево, право) лево ## право
#define АНДРЕЙ2 18
#define ВРЕМЕННЫЙ 19
#undef ВРЕМЕННЫЙ
#define VALUE$OLD 20
#define ДОЛЛАР$ИМЯ 21
#define DOLLAR_PARAM(x$old) x$old
#define CAT_DOLLAR(a,b) a ## b
#define LEFT$RIGHT 22
АНДРЕЙ
résumé
Élève
ΩΜΕΓΑ
переменная2
a١
é
СУММА(АНДРЕЙ, résumé)
СТРОКА(АНДРЕЙ)
СКЛЕИТЬ(АНДР, ЕЙ)
СКЛЕИТЬ(АНДРЕЙ, 2)
андрей
ВРЕМЕННЫЙ
VALUE$OLD
ДОЛЛАР$ИМЯ
DOLLAR_PARAM(23)
CAT_DOLLAR(LEFT$, RIGHT)
#ifdef АНДРЕЙ
ifdef_ok
#endif
#ifndef ВРЕМЕННЫЙ
ifndef_ok
#endif
#if defined(résumé) && defined(ΩΜΕΓΑ)
defined_ok
#endif
#ifdef VALUE$OLD
dollar_ifdef_ok
#endif
#if defined(ДОЛЛАР$ИМЯ)
dollar_defined_ok
#endif
EOT
"$MCPU_CPP" --no-config "$base/main.c" -o "$base/out"
grep -Fx '11' "$base/out" >/dev/null
grep -Fx '12' "$base/out" >/dev/null
grep -Fx '13' "$base/out" >/dev/null
grep -Fx '14' "$base/out" >/dev/null
grep -Fx '15' "$base/out" >/dev/null
grep -Fx '16' "$base/out" >/dev/null
grep -Fx '17' "$base/out" >/dev/null
grep -Fx '11 + 12' "$base/out" >/dev/null
grep -Fx '"АНДРЕЙ"' "$base/out" >/dev/null
# Raw operands of ## are concatenated, then the result is rescanned.
grep -Fx '11' "$base/out" >/dev/null
grep -Fx '18' "$base/out" >/dev/null
grep -Fx 'андрей' "$base/out" >/dev/null
grep -Fx 'ВРЕМЕННЫЙ' "$base/out" >/dev/null
grep -Fx 'ifdef_ok' "$base/out" >/dev/null
grep -Fx 'ifndef_ok' "$base/out" >/dev/null
grep -Fx 'defined_ok' "$base/out" >/dev/null
grep -Fx '20' "$base/out" >/dev/null
grep -Fx '21' "$base/out" >/dev/null
grep -Fx '23' "$base/out" >/dev/null
grep -Fx '22' "$base/out" >/dev/null
grep -Fx 'dollar_ifdef_ok' "$base/out" >/dev/null
grep -Fx 'dollar_defined_ok' "$base/out" >/dev/null
# XID_Continue admits combining marks after an identifier start. The same
# combining mark is not XID_Start and therefore cannot begin a macro name.
printf '#define \314\201bad 1\n' > "$base/bad-start.c"
if "$MCPU_CPP" --no-config "$base/bad-start.c" -o "$base/bad-start.out" 2>"$base/bad-start.err"; then
echo "combining mark accepted as identifier start" >&2
exit 1
fi
grep 'macro name expected after #define' "$base/bad-start.err" >/dev/null
# A decimal digit is XID_Continue but not XID_Start. Non-ASCII digits are
# therefore legal after the first character but cannot start an identifier.
printf '#define \331\241bad 1\n' > "$base/bad-digit-start.c"
if "$MCPU_CPP" --no-config "$base/bad-digit-start.c" -o "$base/bad-digit-start.out" 2>"$base/bad-digit-start.err"; then
echo "non-ASCII digit accepted as identifier start" >&2
exit 1
fi
grep 'macro name expected after #define' "$base/bad-digit-start.err" >/dev/null
# Dollar is an identifier-continuation extension, never an identifier start.
printf '#define $BAD 1\n' > "$base/bad-dollar-start.c"
if "$MCPU_CPP" --no-config "$base/bad-dollar-start.c" -o "$base/bad-dollar-start.out" 2>"$base/bad-dollar-start.err"; then
echo "dollar accepted as identifier start" >&2
exit 1
fi
grep 'macro name expected after #define' "$base/bad-dollar-start.err" >/dev/null
|