M cppp.1 => cppp.1 +5 -0
@@ 52,6 52,11 @@ Treat
.I SYMBOL
as undefined during partial preprocessing.
.TP
+.B \-t, \--trigraphs
+Enable trigraph handling. By default
+.B cppp
+ignores trigraph sequences in the input files.
+.TP
.B \--help
Display help and exit.
.TP
M cppp.c => cppp.c +4 -1
@@ 23,6 23,7 @@ static char const *const yowzitch1 =
static char const *const yowzitch2 =
" -D SYMBOL[=NUMBER] Preprocess SYMBOL as defined [to NUMBER].\n"
" -U SYMBOL Preprocess SYMBOL as undefined.\n"
+ " -t, --trigraphs Enable trigraph handling.\n"
" --help Display this help and exit.\n"
" --version Display version information and exit.\n\n";
static char const *const yowzitch3 =
@@ 33,7 34,7 @@ static char const *const yowzitch3 =
/* Version identifier.
*/
static char const *const vourzhon =
- "cppp: version 2.8\n"
+ "cppp: version 2.9\n"
"Copyright (C) 2011-2022 by Brian Raiter <breadbox@muppetlabs.com>\n"
"License GPLv2+: GNU GPL version 2 or later.\n"
"This is free software; you are free to change and redistribute it.\n"
@@ 131,6 132,8 @@ static int readcmdline(int argc, char *argv[], symset *defs, symset *undefs)
else if (removesymbolfromset(undefs, arg))
warn("undefining already-undefined symbol %s", arg);
addsymboltoset(undefs, arg, 0L);
+ } else if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "--trigraphs")) {
+ enabletrigraphs(TRUE);
} else {
fail("invalid option: %s", argv[i]);
}
M ppproc.c => ppproc.c +12 -1
@@ 48,6 48,10 @@ struct ppproc {
int stack[STACK_SIZE]; /* state flags for each level */
};
+/* This global flag controls trigraph handling.
+ */
+static int trigraphsenabled = FALSE;
+
/* Allocates a partial preprocessor object.
*/
ppproc *initppproc(symset const *defs, symset const *undefs)
@@ 71,6 75,13 @@ void freeppproc(ppproc *ppp)
deallocate(ppp);
}
+/* Enable and disable trigraph handling.
+ */
+void enabletrigraphs(int flag)
+{
+ trigraphsenabled = flag;
+}
+
/* Set the state appropriate for the beginning of a file.
*/
static void beginfile(ppproc *ppp)
@@ 457,7 468,7 @@ static int readline(ppproc *ppp, FILE *infile)
erasemstr(ppp->line);
while (ch != EOF) {
appendmstr(ppp->line, ch);
- if (back2 == '?' && back1 == '?') {
+ if (trigraphsenabled && back2 == '?' && back1 == '?') {
switch (ch) {
case '=': replacement = '#'; break;
case '(': replacement = '['; break;
M ppproc.h => ppproc.h +5 -0
@@ 23,6 23,11 @@ extern ppproc *initppproc(symset const *defs, symset const *undefs);
*/
extern void freeppproc(ppproc *ppp);
+/* Enable and disable trigraph handling in the preprocessor. Trigraph
+ * support is disabled by default.
+ */
+extern void enabletrigraphs(int flag);
+
/* Partially preprocesses infile's contents to outfile.
*/
extern void partialpreprocess(ppproc *ppp, FILE *infile, FILE *outfile);
A tests/basic.c => tests/basic.c +7 -0
@@ 0,0 1,7 @@
+#ifdef foo
+-Dfoo
+#else
+#if !defined(foo)
+-Ufoo
+#endif
+#endif
M tests/good.c => tests/good.c +0 -8
@@ 1,11 1,3 @@
-#ifdef foo
--Dfoo
-#else
-#if !defined(foo)
--Ufoo
-#endif
-#endif
-$
/*1*/#/*2*/ifdef/*3*/foo\
/*4*/
-Dfoo
M tests/phases.c => tests/phases.c +6 -6
@@ 16,9 16,9 @@ l\
s\
e /* backslash-newline pair within digraph */
-Ufoo
-??=??/
-e??/
-n??/
-d??/
-i??/
-f /* trigraphs */
+#\
+e\
+n\
+d\
+i\
+f /* backslash-newline pair with MS-DOS newline sequence */
A tests/qqs.c => tests/qqs.c +13 -0
@@ 0,0 1,13 @@
+??=if defined foo /* trigraph for # */
+-Dfoo
+??=elif ??-foo == ??-0 /* more trigraphs */
+-Ufoo
+??=??/
+else /* backslash-newline pair with trigraph */
+failed -Ufoo test
+??=??/
+e??/
+n??/
+d??/
+i??/
+f /* backslash-newline pair with trigraph and MS-DOS newline */
M tests/testall => tests/testall +40 -14
@@ 7,28 7,26 @@ PROG=${1:-./cppp}
fail()
{
echo "Unit test failure:" "$@" >&2
- exit 1
+# exit 1
}
-# Run through an input file that responds to the preprocessor symbol
-# "foo", and verify that it behaves as expected.
+# Run through a single input file that responds to the preprocessor
+# symbol "foo", and verify that it behaves as expected.
#
goodparsingtest()
{
infile=$1
"$PROG" "$infile" | cmp -s "$infile" || fail "altered $infile with no flags."
- IFS='$' read -a inputs -d@ <$infile
- for input in "${inputs[@]}" ; do
- for flag in -Dfoo -Ufoo ; do
- out=$(echo "$input" | "$PROG" $flag 2>&1)
- test $? == 0 || fail "non-zero exit code for $infile with flag $flag."
- test $out == $flag || fail "expected: $flag, got output: \"$out\""
- test $out == $flag || fail "bad output for $infile with flag $flag."
- done
+ for flag in -Dfoo -Ufoo ; do
+ out=$("$PROG" $flag "$infile" 2>&1)
+ test $? == 0 || fail "non-zero exit code for $infile with flag $flag."
+ test "$out" == $flag || fail "expected: $flag, got output: \"$out\""
+ test "$out" == $flag || fail "for $infile with flag $flag."
done
}
-# Run an invalid input file and verify that it produces an error message.
+# Run through an input file with multiple sections and verify that
+# each section produces an error message.
#
badparsingtest()
{
@@ 41,6 39,25 @@ badparsingtest()
done
}
+# Run an input file containing trigraphs and verify that trigraphs are
+# only detected when enabled.
+#
+trigraphtest()
+{
+ infile=$1
+ "$PROG" "$infile" | cmp -s "$infile" || fail "altered $infile with no flags."
+ "$PROG" -Dfoo "$infile" | cmp -s "$infile" ||
+ fail "altered $infile with trigraphs disabled."
+ for tflag in -t --trigraphs ; do
+ for dflag in -Dfoo -Ufoo ; do
+ out=$("$PROG" $tflag $dflag "$infile" 2>&1)
+ test $? == 0 || fail "error for $infile with flags \"$tflag $dflag\"."
+ test "$out" == $dflag || fail "expected: $dflag, got output: \"$out\""
+ test "$out" == $dflag || fail "for $infile with flags \"$tflag $dflag\"."
+ done
+ done
+}
+
# Run an input file through every combination of three preprocessor
# symbols, with each one be defined, undefined, and unspecified.
#
@@ 61,6 78,7 @@ fulltest()
test $? == 0 || fail "non-zero exit code for $infile with flags $flags."
done | diff - "$checkfile"
test $? == 0 || fail "bad output for $infile."
+
}
# Run an input file containing two preprocessor symbols that can take
@@ 87,12 105,18 @@ misctests()
{
"$PROG" </dev/null >/dev/null
test $? == 0 || fail "unable to run test program: $PROG."
- out=$("$PROG" --help)
+ out=$("$PROG" --help </dev/null)
test $? == 0 || fail "--help option not recognized."
test -z "$out" && fail "no --help text."
- out=$("$PROG" --version)
+ out=$("$PROG" --version </dev/null)
test $? == 0 || fail "--version option not recoginzed."
test -z "$out" && fail "no --version text."
+ out=$("$PROG" -D </dev/null 2>&1 >/dev/null)
+ test $? != 0 || fail "no warning for missing option argument."
+ test -z "$out" && fail "no error message for missing option argument."
+ out=$("$PROG" --nosuchoption </dev/null 2>&1 >/dev/null)
+ test $? != 0 || fail "no warning for invalid option."
+ test -z "$out" && fail "no error message for invalid option."
out=$("$PROG" -Dfoo nosuchfile.c 2>&1 >/dev/null)
test $? != 0 || fail "no warning for invalid filename."
test -z "$out" && fail "no error message for invalid filename."
@@ 103,10 127,12 @@ misctests()
#
misctests
+goodparsingtest tests/basic.c
goodparsingtest tests/good.c
goodparsingtest tests/lines.c
badparsingtest tests/bad.c
goodparsingtest tests/phases.c
+trigraphtest tests/qqs.c
for f in tests/full*.c ; do
fulltest "$f" "${f%.c}.out"
done