~breadbox/cppp

d5024191f6859cb9be71bafeb018bcc2d2c474f1 — Brian Raiter 2 years ago e92668a
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.
9 files changed, 92 insertions(+), 30 deletions(-)

M cppp.1
M cppp.c
M ppproc.c
M ppproc.h
A tests/basic.c
M tests/good.c
M tests/phases.c
A tests/qqs.c
M tests/testall
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