From 24d4c143974d0cf3258fe2d355695e820c4ff24e Mon Sep 17 00:00:00 2001 From: Ben Pfaff <blp@gnu.org> Date: Sun, 23 Sep 2007 16:47:27 +0000 Subject: [PATCH] Bug #21111. Reviewed by John Darrington. * command/input-program.sh: New test. * command/do-if.sh: New tests. * data-list.c (data_list_trns_proc): Properly set retval when END subcommand is in use. * do-if.c: Fix ELSE and ELSE IF clauses. (add_clause): Drop TARGET_INDEX argument and figure out the target of the jump on our own. The caller couldn't compensate for the inserted BREAK transformation. Updated all callers. --- doc/data-io.texi | 10 + src/language/control/ChangeLog | 9 + src/language/control/do-if.c | 15 +- src/language/data-io/ChangeLog | 7 + src/language/data-io/data-list.c | 4 +- tests/ChangeLog | 8 + tests/automake.mk | 2 + tests/command/do-if.sh | 115 ++++++++++++ tests/command/input-program.sh | 306 +++++++++++++++++++++++++++++++ 9 files changed, 466 insertions(+), 10 deletions(-) create mode 100755 tests/command/do-if.sh create mode 100755 tests/command/input-program.sh diff --git a/doc/data-io.texi b/doc/data-io.texi index 83d1949cd7..cb11c7cfc1 100644 --- a/doc/data-io.texi +++ b/doc/data-io.texi @@ -541,6 +541,8 @@ structure. All this is very confusing. A few examples should help to clarify. +@c If you change this example, change the regression test1 in +@c tests/command/input-program.sh to match. @example INPUT PROGRAM. DATA LIST NOTABLE FILE='a.data'/X 1-10. @@ -553,6 +555,8 @@ The example above reads variable X from file @file{a.data} and variable Y from file @file{b.data}. If one file is shorter than the other then the extra data in the longer file is ignored. +@c If you change this example, change the regression test2 in +@c tests/command/input-program.sh to match. @example INPUT PROGRAM. NUMERIC #A #B. @@ -576,6 +580,8 @@ The above example reads variable X from @file{a.data} and variable Y from field is set to the system-missing value alongside the present value for the remaining length of the longer file. +@c If you change this example, change the regression test3 in +@c tests/command/input-program.sh to match. @example INPUT PROGRAM. NUMERIC #A #B. @@ -600,6 +606,8 @@ LIST. The above example reads data from file @file{a.data}, then from @file{b.data}, and concatenates them into a single active file. +@c If you change this example, change the regression test4 in +@c tests/command/input-program.sh to match. @example INPUT PROGRAM. NUMERIC #EOF. @@ -627,6 +635,8 @@ LIST. The above example does the same thing as the previous example, in a different way. +@c If you change this example, make similar changes to the regression +@c test5 in tests/command/input-program.sh. @example INPUT PROGRAM. LOOP #I=1 TO 50. diff --git a/src/language/control/ChangeLog b/src/language/control/ChangeLog index f26aba150f..ecdcc65877 100644 --- a/src/language/control/ChangeLog +++ b/src/language/control/ChangeLog @@ -1,3 +1,12 @@ +2007-09-23 Ben Pfaff <blp@gnu.org> + + Bug #21111. Reviewed by John Darrington. + + * do-if.c: Fix ELSE and ELSE IF clauses. + (add_clause): Drop TARGET_INDEX argument and figure out the target + of the jump on our own. The caller couldn't compensate for the + inserted BREAK transformation. Updated all callers. + Fri Feb 2 22:41:43 WST 2007 John Darrington <john@darrington.wattle.id.au> * repeat.c (parse_numbers): Fixed bug parseing ranges vs. lists. diff --git a/src/language/control/do-if.c b/src/language/control/do-if.c index cb4207846c..2e1e0abf5f 100644 --- a/src/language/control/do-if.c +++ b/src/language/control/do-if.c @@ -82,8 +82,7 @@ struct do_if_trns static const struct ctl_class do_if_class; static int parse_clause (struct lexer *, struct do_if_trns *, struct dataset *ds); -static void add_clause (struct do_if_trns *, - struct expression *condition, int target_index); +static void add_clause (struct do_if_trns *, struct expression *condition); static void add_else (struct do_if_trns *); static bool has_else (struct do_if_trns *); @@ -165,7 +164,7 @@ static void add_else (struct do_if_trns *do_if) { assert (!has_else (do_if)); - add_clause (do_if, NULL, next_transformation (do_if->ds)); + add_clause (do_if, NULL); } /* Returns true if DO_IF does not yet have an ELSE clause. @@ -203,16 +202,16 @@ parse_clause (struct lexer *lexer, struct do_if_trns *do_if, struct dataset *ds) if (condition == NULL) return CMD_CASCADING_FAILURE; - add_clause (do_if, condition, next_transformation (ds)); + add_clause (do_if, condition); return lex_end_of_command (lexer); } /* Adds a clause to DO_IF that tests for the given CONDITION and, - if true, jumps to TARGET_INDEX. */ + if true, jumps to the set of transformations produced by + following commands. */ static void -add_clause (struct do_if_trns *do_if, - struct expression *condition, int target_index) +add_clause (struct do_if_trns *do_if, struct expression *condition) { struct clause *clause; @@ -223,7 +222,7 @@ add_clause (struct do_if_trns *do_if, do_if->clause_cnt + 1, sizeof *do_if->clauses); clause = &do_if->clauses[do_if->clause_cnt++]; clause->condition = condition; - clause->target_index = target_index; + clause->target_index = next_transformation (do_if->ds); } /* Finalizes DO IF by clearing the control stack, thus ensuring diff --git a/src/language/data-io/ChangeLog b/src/language/data-io/ChangeLog index 572aacd5a7..ec8873acbe 100644 --- a/src/language/data-io/ChangeLog +++ b/src/language/data-io/ChangeLog @@ -1,3 +1,10 @@ +2007-09-23 Ben Pfaff <blp@gnu.org> + + Bug #21111. Reviewed by John Darrington. + + * data-list.c (data_list_trns_proc): Properly set retval when END + subcommand is in use. + 2007-09-12 Ben Pfaff <blp@gnu.org> * get.c (get_translate_case): Change input case parameter from diff --git a/src/language/data-io/data-list.c b/src/language/data-io/data-list.c index 9f77ed8d9a..4e2f083bee 100644 --- a/src/language/data-io/data-list.c +++ b/src/language/data-io/data-list.c @@ -807,10 +807,10 @@ data_list_trns_proc (void *dls_, struct ccase *c, casenumber case_num UNUSED) if (dls->end != NULL) { double *end = &case_data_rw (c, dls->end)->f; - if (retval == TRNS_DROP_CASE) + if (retval == TRNS_END_FILE) { *end = 1.0; - retval = TRNS_END_FILE; + retval = TRNS_CONTINUE; } else *end = 0.0; diff --git a/tests/ChangeLog b/tests/ChangeLog index e91645ce4c..3a912d5615 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,11 @@ +2007-09-23 Ben Pfaff <blp@gnu.org> + + Bug #21111. Reviewed by John Darrington. + + * command/input-program.sh: New test. + + * command/do-if.sh: New tests. + 2007-09-22 Ben Pfaff <blp@gnu.org> Bug #21128. Reviewed by John Darrington. diff --git a/tests/automake.mk b/tests/automake.mk index 3ee837dab6..25eb1ab9ce 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -10,6 +10,7 @@ dist_TESTS = \ tests/command/count.sh \ tests/command/datasheet.sh \ tests/command/data-list.sh \ + tests/command/do-if.sh \ tests/command/do-repeat.sh \ tests/command/erase.sh \ tests/command/examine.sh \ @@ -20,6 +21,7 @@ dist_TESTS = \ tests/command/filter.sh \ tests/command/flip.sh \ tests/command/import-export.sh \ + tests/command/input-program.sh \ tests/command/insert.sh \ tests/command/lag.sh \ tests/command/list.sh \ diff --git a/tests/command/do-if.sh b/tests/command/do-if.sh new file mode 100755 index 0000000000..185dc4e4fc --- /dev/null +++ b/tests/command/do-if.sh @@ -0,0 +1,115 @@ +#!/bin/sh + +# This program tests the DO IF command. + +TEMPDIR=/tmp/pspp-tst-$$ + +# ensure that top_builddir are absolute +if [ -z "$top_builddir" ] ; then top_builddir=. ; fi +if [ -z "$top_srcdir" ] ; then top_srcdir=. ; fi +top_builddir=`cd $top_builddir; pwd` +PSPP=$top_builddir/src/ui/terminal/pspp + +# ensure that top_srcdir is absolute +top_srcdir=`cd $top_srcdir; pwd` + +STAT_CONFIG_PATH=$top_srcdir/config +export STAT_CONFIG_PATH + +LANG=C +export LANG + +cleanup() +{ + cd / + #rm -rf $TEMPDIR +} + + +fail() +{ + echo $activity + echo FAILED + cleanup; + exit 1; +} + + +no_result() +{ + echo $activity + echo NO RESULT; + cleanup; + exit 2; +} + +pass() +{ + cleanup; + exit 0; +} + +mkdir -p $TEMPDIR + +cd $TEMPDIR + +activity="generate input and expected output" +(for a in 0 1 ' '; do + for b in 0 1 ' '; do + for c in 0 1 ' '; do + for d in 0 1 ' '; do + abcd=$a$b$c$d + echo "$abcd" 1>&3 + if test "$a" = "1"; then + echo " $abcd A" + elif test "$a" = " "; then + : + elif test "$b" = "1"; then + echo " $abcd B" + elif test "$b" = " "; then + : + elif test "$c" = "1"; then + echo " $abcd C" + elif test "$c" = " "; then + : + elif test "$d" = "1"; then + echo " $abcd D" + elif test "$d" = " "; then + : + else + echo " $abcd E" + fi + done + done + done +done) >test1.expected 3>test1.data +if [ $? -ne 0 ] ; then no_result ; fi + +activity="create test1.pspp" +cat > test1.pspp <<EOF +DATA LIST FILE="test1.data"/A B C D 1-4 ABCD 1-4 (A). +DO IF A. +PRINT OUTFILE="test1.out"/ABCD 'A'. +ELSE IF B. +PRINT OUTFILE="test1.out"/ABCD 'B'. +ELSE IF C. +PRINT OUTFILE="test1.out"/ABCD 'C'. +ELSE IF D. +PRINT OUTFILE="test1.out"/ABCD 'D'. +ELSE. +PRINT OUTFILE="test1.out"/ABCD 'E'. +END IF. +EXECUTE. +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="run test1" +$SUPERVISOR $PSPP --testing-mode test1.pspp +if [ $? -ne 0 ] ; then no_result ; fi + +activity="compare test1 results" +perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list +diff -u $TEMPDIR/test1.out $TEMPDIR/test1.expected +if [ $? -ne 0 ] ; then fail ; fi + +pass diff --git a/tests/command/input-program.sh b/tests/command/input-program.sh new file mode 100755 index 0000000000..0d7d95ca2b --- /dev/null +++ b/tests/command/input-program.sh @@ -0,0 +1,306 @@ +#!/bin/sh + +# This program tests the INPUT PROGRAM command, specifically all of +# the examples given in the user manual. + +TEMPDIR=/tmp/pspp-tst-$$ + +# ensure that top_builddir are absolute +if [ -z "$top_builddir" ] ; then top_builddir=. ; fi +if [ -z "$top_srcdir" ] ; then top_srcdir=. ; fi +top_builddir=`cd $top_builddir; pwd` +PSPP=$top_builddir/src/ui/terminal/pspp + +# ensure that top_srcdir is absolute +top_srcdir=`cd $top_srcdir; pwd` + +STAT_CONFIG_PATH=$top_srcdir/config +export STAT_CONFIG_PATH + +LANG=C +export LANG + +cleanup() +{ + cd / + rm -rf $TEMPDIR +} + + +fail() +{ + echo $activity + echo FAILED + cleanup; + exit 1; +} + + +no_result() +{ + echo $activity + echo NO RESULT; + cleanup; + exit 2; +} + +pass() +{ + cleanup; + exit 0; +} + +mkdir -p $TEMPDIR + +cd $TEMPDIR + +activity="create a.data" +cat > a.data <<EOF +1 +2 +3 +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="create b.data" +cat > b.data <<EOF +4 +5 +6 +7 +8 +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="create test1.pspp" +cat > test1.pspp <<EOF +INPUT PROGRAM. + DATA LIST NOTABLE FILE='a.data'/X 1-10. + DATA LIST NOTABLE FILE='b.data'/Y 1-10. +END INPUT PROGRAM. +LIST. +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="run test1" +$SUPERVISOR $PSPP --testing-mode test1.pspp +if [ $? -ne 0 ] ; then no_result ; fi + +activity="compare test1 results" +perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list +diff -b $TEMPDIR/pspp.list - << EOF + X Y +---------- ---------- + 1 4 + 2 5 + 3 6 +EOF +if [ $? -ne 0 ] ; then fail ; fi + +activity="create test2.pspp" +cat > test2.pspp <<EOF +INPUT PROGRAM. + NUMERIC #A #B. + + DO IF NOT #A. + DATA LIST NOTABLE END=#A FILE='a.data'/X 1-10. + END IF. + DO IF NOT #B. + DATA LIST NOTABLE END=#B FILE='b.data'/Y 1-10. + END IF. + DO IF #A AND #B. + END FILE. + END IF. + END CASE. +END INPUT PROGRAM. +LIST. +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="run test2" +$SUPERVISOR $PSPP --testing-mode test2.pspp +if [ $? -ne 0 ] ; then no_result ; fi + +activity="compare test2 results" +perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list +diff -b $TEMPDIR/pspp.list - << EOF + X Y +---------- ---------- + 1 4 + 2 5 + 3 6 + . 7 + . 8 +EOF +if [ $? -ne 0 ] ; then fail ; fi + +activity="create test3.pspp" +cat > test3.pspp <<EOF +INPUT PROGRAM. + NUMERIC #A #B. + + DO IF #A. + DATA LIST NOTABLE END=#B FILE='b.data'/X 1-10. + DO IF #B. + END FILE. + ELSE. + END CASE. + END IF. + ELSE. + DATA LIST NOTABLE END=#A FILE='a.data'/X 1-10. + DO IF NOT #A. + END CASE. + END IF. + END IF. +END INPUT PROGRAM. +LIST. +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="run test3" +$SUPERVISOR $PSPP --testing-mode test3.pspp +if [ $? -ne 0 ] ; then no_result ; fi + +activity="compare test3 results" +perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list +diff -b $TEMPDIR/pspp.list - << EOF + X +---------- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 +EOF +if [ $? -ne 0 ] ; then fail ; fi + +activity="create test4.pspp" +cat > test4.pspp <<EOF +INPUT PROGRAM. + NUMERIC #EOF. + + LOOP IF NOT #EOF. + DATA LIST NOTABLE END=#EOF FILE='a.data'/X 1-10. + DO IF NOT #EOF. + END CASE. + END IF. + END LOOP. + + COMPUTE #EOF = 0. + LOOP IF NOT #EOF. + DATA LIST NOTABLE END=#EOF FILE='b.data'/X 1-10. + DO IF NOT #EOF. + END CASE. + END IF. + END LOOP. + + END FILE. +END INPUT PROGRAM. +LIST. +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="run test4" +$SUPERVISOR $PSPP --testing-mode test4.pspp +if [ $? -ne 0 ] ; then no_result ; fi + +activity="compare test4 results" +perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list +diff -b $TEMPDIR/pspp.list - << EOF + X +---------- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 +EOF +if [ $? -ne 0 ] ; then fail ; fi + +# This example differs slightly from the one in the manual in that +# it doesn't generate random variates. There's already a test that +# checks that random variates are predictable, so we don't need +# another. +activity="create test5.pspp" +cat > test5.pspp <<EOF +INPUT PROGRAM. + LOOP #I=1 TO 50. + COMPUTE X=#I * 3. + END CASE. + END LOOP. + END FILE. +END INPUT PROGRAM. +LIST/FORMAT=NUMBERED. +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="run test5" +$SUPERVISOR $PSPP --testing-mode test5.pspp +if [ $? -ne 0 ] ; then no_result ; fi + +activity="compare test5 results" +perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list +diff -b $TEMPDIR/pspp.list - << EOF +Case# X +----- -------- + 1 3.00 + 2 6.00 + 3 9.00 + 4 12.00 + 5 15.00 + 6 18.00 + 7 21.00 + 8 24.00 + 9 27.00 + 10 30.00 + 11 33.00 + 12 36.00 + 13 39.00 + 14 42.00 + 15 45.00 + 16 48.00 + 17 51.00 + 18 54.00 + 19 57.00 + 20 60.00 + 21 63.00 + 22 66.00 + 23 69.00 + 24 72.00 + 25 75.00 + 26 78.00 + 27 81.00 + 28 84.00 + 29 87.00 + 30 90.00 + 31 93.00 + 32 96.00 + 33 99.00 + 34 102.00 + 35 105.00 + 36 108.00 + 37 111.00 + 38 114.00 + 39 117.00 + 40 120.00 + 41 123.00 + 42 126.00 + 43 129.00 + 44 132.00 + 45 135.00 + 46 138.00 + 47 141.00 + 48 144.00 + 49 147.00 + 50 150.00 +EOF +if [ $? -ne 0 ] ; then fail ; fi + + +pass -- 2.30.2