From d5024191f6859cb9be71bafeb018bcc2d2c474f1 Mon Sep 17 00:00:00 2001 From: Brian Raiter Date: Mon, 15 Aug 2022 20:48:42 -0700 Subject: [PATCH] Placed trigraph support behind a cmdline option, disabled by default. Updated tests to test trigraph handling with and without the option, and bumped the version number. --- cppp.1 | 5 +++++ cppp.c | 5 ++++- ppproc.c | 13 +++++++++++- ppproc.h | 5 +++++ tests/basic.c | 7 +++++++ tests/good.c | 8 -------- tests/phases.c | 12 +++++------ tests/qqs.c | 13 ++++++++++++ tests/testall | 54 +++++++++++++++++++++++++++++++++++++------------- 9 files changed, 92 insertions(+), 30 deletions(-) create mode 100644 tests/basic.c create mode 100644 tests/qqs.c diff --git a/cppp.1 b/cppp.1 index 24fddee..713e0ea 100644 --- a/cppp.1 +++ b/cppp.1 @@ -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 diff --git a/cppp.c b/cppp.c index 67c917a..b0df1b3 100644 --- a/cppp.c +++ b/cppp.c @@ -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 \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]); } diff --git a/ppproc.c b/ppproc.c index 4f39381..984caf3 100644 --- a/ppproc.c +++ b/ppproc.c @@ -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; diff --git a/ppproc.h b/ppproc.h index 6760f4e..06ec4ee 100644 --- a/ppproc.h +++ b/ppproc.h @@ -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); diff --git a/tests/basic.c b/tests/basic.c new file mode 100644 index 0000000..ee3500c --- /dev/null +++ b/tests/basic.c @@ -0,0 +1,7 @@ +#ifdef foo +-Dfoo +#else +#if !defined(foo) +-Ufoo +#endif +#endif diff --git a/tests/good.c b/tests/good.c index d5d746a..c7586b7 100644 --- a/tests/good.c +++ b/tests/good.c @@ -1,11 +1,3 @@ -#ifdef foo --Dfoo -#else -#if !defined(foo) --Ufoo -#endif -#endif -$ /*1*/#/*2*/ifdef/*3*/foo\ /*4*/ -Dfoo diff --git a/tests/phases.c b/tests/phases.c index b241db4..f876a7e 100644 --- a/tests/phases.c +++ b/tests/phases.c @@ -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 */ diff --git a/tests/qqs.c b/tests/qqs.c new file mode 100644 index 0000000..f5ac95e --- /dev/null +++ b/tests/qqs.c @@ -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 */ diff --git a/tests/testall b/tests/testall index 284b2b1..b2df167 100755 --- a/tests/testall +++ b/tests/testall @@ -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 test $? == 0 || fail "unable to run test program: $PROG." - out=$("$PROG" --help) + out=$("$PROG" --help &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 &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 -- 2.45.2