* 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.
 
 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.
 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.
 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.
 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.
 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.
 
+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.
 
 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 *);
 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.
   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;
 
                               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
 
+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
 
   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;
 
+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.
 
        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 \
        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 \
 
--- /dev/null
+#!/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
 
--- /dev/null
+#!/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