Implemented the INSERT command.
authorJohn Darrington <john@darrington.wattle.id.au>
Wed, 5 Sep 2007 06:23:01 +0000 (06:23 +0000)
committerJohn Darrington <john@darrington.wattle.id.au>
Wed, 5 Sep 2007 06:23:01 +0000 (06:23 +0000)
24 files changed:
doc/language.texi
doc/utilities.texi
po/de.po
po/pspp.pot
src/language/ChangeLog
src/language/command.c
src/language/command.def
src/language/control/repeat.c
src/language/data-io/data-reader.c
src/language/lexer/lexer.c
src/language/lexer/lexer.h
src/language/syntax-file.c
src/language/syntax-file.h
src/language/syntax-string-source.c
src/language/utilities/include.c
src/libpspp/ChangeLog
src/libpspp/getl.c
src/libpspp/getl.h
src/ui/gui/helper.c
src/ui/gui/syntax-editor-source.c
src/ui/terminal/command-line.c
src/ui/terminal/read-line.c
tests/automake.mk
tests/command/insert.sh [new file with mode: 0755]

index 398f7642318ede8f973bac881479c718775ba5a2..1345433613d3f24e7c7b26cdac457f7132761834 100644 (file)
@@ -15,6 +15,7 @@ Later chapters will describe individual commands in detail.
 @menu
 * Tokens::                      Characters combine to form tokens.
 * Commands::                    Tokens combine to form commands.
 @menu
 * Tokens::                      Characters combine to form tokens.
 * Commands::                    Tokens combine to form commands.
+* Syntax Variants::             Batch vs. Interactive mode
 * Types of Commands::           Commands come in several flavors.
 * Order of Commands::           Commands combine to form syntax files.
 * Missing Observations::        Handling missing observations.
 * Types of Commands::           Commands come in several flavors.
 * Order of Commands::           Commands combine to form syntax files.
 * Missing Observations::        Handling missing observations.
@@ -24,6 +25,7 @@ Later chapters will describe individual commands in detail.
 * BNF::                         How command syntax is described.
 @end menu
 
 * BNF::                         How command syntax is described.
 @end menu
 
+
 @node Tokens
 @section Tokens
 @cindex language, lexical analysis
 @node Tokens
 @section Tokens
 @cindex language, lexical analysis
@@ -188,15 +190,34 @@ one that consists only of white space or comments, also ends a command
 by default, although you can use the NULLINE subcommand of @cmd{SET}
 to disable this feature (@pxref{SET}).
 
 by default, although you can use the NULLINE subcommand of @cmd{SET}
 to disable this feature (@pxref{SET}).
 
-In batch mode only, that is, when reading commands from a file instead
-of an interactive user, any line that contains a non-space character
-in the leftmost column begins a new command.  Thus, each command
-consists of a flush-left line followed by any number of lines indented
-from the left margin.  In this mode, a plus or minus sign
-(@samp{+}, @samp{@minus{}}) as the first character
-in a line is ignored and causes that line to begin a new command,
-which allows for visual indentation of a command without that command
-being considered part of the previous command.
+@node Syntax Variants
+@section Variants of syntax.
+
+@cindex Batch syntax
+@cindex Interactive syntax
+
+There are two variants of command syntax, @i{viz}: @dfn{batch} mode and
+@dfn{interactive} mode.
+Batch mode is the default when reading commands from a file.
+Interactive mode is the default when commands are typed at a prompt
+by a user.
+Certain commands, such as @cmd{INSERT} (@pxref{INSERT}), may explicitly
+change the syntax mode. 
+
+In batch mode, any line that contains a non-space character
+in the leftmost column begins a new command. 
+Thus, each command consists of a flush-left line followed by any
+number of lines indented from the left margin. 
+In this mode, a plus or minus sign (@samp{+}, @samp{@minus{}}) as the
+first character in a line is ignored and causes that line to begin a
+new command, which allows for visual indentation of a command without
+that command being considered part of the previous command. 
+The period terminating the end of a command is optional but recommended.
+
+In interactive mode, each command must  either be terminated with a period,
+or an empty line must follow the command.
+The use of (@samp{+} and @samp{@minus{}} as continuation characters is not
+permitted.
 
 @node Types of Commands
 @section Types of Commands
 
 @node Types of Commands
 @section Types of Commands
index ba5a5e8b0912a18c317a1e80195b724f188434fc..94fa50744d6a4c70d48befce93b2b57438c1d658 100644 (file)
@@ -23,6 +23,7 @@ encountered in the input.
 * FINISH::                      Terminate the PSPP session.
 * HOST::                        Temporarily return to the operating system.
 * INCLUDE::                     Include a file within the current one.
 * FINISH::                      Terminate the PSPP session.
 * HOST::                        Temporarily return to the operating system.
 * INCLUDE::                     Include a file within the current one.
+* INSERT::                      Insert a file within the current one.
 * PERMISSIONS::                 Change permissions on a file.
 * SET::                         Adjust PSPP runtime parameters.
 * SHOW::                        Display runtime parameters.
 * PERMISSIONS::                 Change permissions on a file.
 * SET::                         Adjust PSPP runtime parameters.
 * SHOW::                        Display runtime parameters.
@@ -220,23 +221,70 @@ This command cannot be used if the SAFER setting is active.
 @node INCLUDE
 @section INCLUDE
 @vindex INCLUDE
 @node INCLUDE
 @section INCLUDE
 @vindex INCLUDE
-@vindex @@
 
 @display
 
 @display
-Two possible syntaxes:
-        INCLUDE 'file-name'.
-        @@file-name.
+        INCLUDE [FILE=]'file-name'.
 @end display
 
 @cmd{INCLUDE} causes the PSPP command processor to read an
 additional command file as if it were included bodily in the current
 command file.
 @end display
 
 @cmd{INCLUDE} causes the PSPP command processor to read an
 additional command file as if it were included bodily in the current
 command file.
-
+If errors are encountered in the included file, then command processing will 
+stop and no more commands will be processed.
 Include files may be nested to any depth, up to the limit of available
 memory.
 
 Include files may be nested to any depth, up to the limit of available
 memory.
 
+
+The @cmd{INSERT} command (@pxref{INSERT}) may be used instead of
+@cmd{INCLUDE} if you require more flexible options.
+The syntax 
+@example
+INCLUDE FILE=@var{file-name}.
+@end example
+@noindent 
+functions identically to 
+@example
+INSERT FILE=@var{file-name} ERROR=STOP CD=NO SYNTAX=BATCH.
+@end example
+
+
+@node INSERT
+@section INSERT
+@vindex INSERT
+
+@display
+     INSERT [FILE=]'file-name'
+        [CD=@{NO,YES@}]
+        [ERROR=@{CONTINUE,STOP@}]
+        [SYNTAX=@{BATCH,INTERACTIVE@}].
+@end display
+
+@cmd{INSERT} is similar to @cmd{INCLUDE} (@pxref{INCLUDE}) 
+but somewhat more flexible.
+It causes the command processor to read a file as if it were embedded in the 
+current command file.
+
+If @samp{CD=YES} is specified, then before including the file, the
+current directory  will be changed to the directory of the included
+file.  
+The default setting is @samp{CD=NO}.
+Note that this directory will remain current until it is
+changed explicitly (with the @cmd{CD} command, or a subsequent
+@cmd{INSERT} command with the @samp{CD=YES} option).
+It will not revert to its original setting even after the included
+file is finished processing.
+
+If @samp{ERROR=STOP} is specified, errors encountered in the
+inserted file will cause processing to immediately cease.
+Otherwise processing will continue at the next command.
+The default setting is @samp{ERROR=CONTINUE}.
+
+If @samp{SYNTAX=INTERACTIVE} is specified then the syntax contained in
+the included file must conform to interactive syntax
+conventions. @xref{Syntax Variants}.
+The default setting is @samp{SYNTAX=BATCH}.
+
 @node PERMISSIONS
 @node PERMISSIONS
-@comment  node-name,  next,  previous,  up
 @section PERMISSIONS
 @vindex PERMISSIONS
 @cindex mode
 @section PERMISSIONS
 @vindex PERMISSIONS
 @cindex mode
index c92f367f24a7972e3135428242bff3ac5bb7e4c5..cad53f8a70edab5a96febe6f667d5e188ea1ac01 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -10,7 +10,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PSPP 0.4.3\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
 msgstr ""
 "Project-Id-Version: PSPP 0.4.3\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2007-08-31 07:06+0800\n"
+"POT-Creation-Date: 2007-09-01 08:59+0800\n"
 "PO-Revision-Date: 2006-07-28 19:32+0800\n"
 "Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
 "Language-Team: German <pspp-dev@gnu.org>\n"
 "PO-Revision-Date: 2006-07-28 19:32+0800\n"
 "Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
 "Language-Team: German <pspp-dev@gnu.org>\n"
@@ -988,41 +988,41 @@ msgstr ""
 msgid "Only one index clause may be specified."
 msgstr ""
 
 msgid "Only one index clause may be specified."
 msgstr ""
 
-#: src/language/control/repeat.c:168
+#: src/language/control/repeat.c:173
 #, c-format
 msgid "Dummy variable name \"%s\" hides dictionary variable \"%s\"."
 msgstr ""
 
 #, c-format
 msgid "Dummy variable name \"%s\" hides dictionary variable \"%s\"."
 msgstr ""
 
-#: src/language/control/repeat.c:173
+#: src/language/control/repeat.c:178
 #, c-format
 msgid "Dummy variable name \"%s\" is given twice."
 msgstr ""
 
 #, c-format
 msgid "Dummy variable name \"%s\" is given twice."
 msgstr ""
 
-#: src/language/control/repeat.c:219
+#: src/language/control/repeat.c:224
 #, c-format
 msgid ""
 "Dummy variable \"%.*s\" had %d substitutions, so \"%.*s\" must also, but %d "
 "were specified."
 msgstr ""
 
 #, c-format
 msgid ""
 "Dummy variable \"%.*s\" had %d substitutions, so \"%.*s\" must also, but %d "
 "were specified."
 msgstr ""
 
-#: src/language/control/repeat.c:331
+#: src/language/control/repeat.c:336
 msgid "DO REPEAT may not nest in compatibility mode."
 msgstr ""
 
 msgid "DO REPEAT may not nest in compatibility mode."
 msgstr ""
 
-#: src/language/control/repeat.c:433
+#: src/language/control/repeat.c:438
 msgid "Ranges may only have integer bounds"
 msgstr ""
 
 msgid "Ranges may only have integer bounds"
 msgstr ""
 
-#: src/language/control/repeat.c:442
+#: src/language/control/repeat.c:447
 #, c-format
 msgid "%g TO %g is an invalid range."
 msgstr ""
 
 #, c-format
 msgid "%g TO %g is an invalid range."
 msgstr ""
 
-#: src/language/control/repeat.c:477
+#: src/language/control/repeat.c:482
 msgid "String expected."
 msgstr ""
 
 msgid "String expected."
 msgstr ""
 
-#: src/language/control/repeat.c:496
+#: src/language/control/repeat.c:501
 msgid "No matching DO REPEAT."
 msgstr ""
 
 msgid "No matching DO REPEAT."
 msgstr ""
 
@@ -1411,7 +1411,7 @@ msgid_plural "Writing %d records."
 msgstr[0] ""
 msgstr[1] ""
 
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/language/data-io/print-space.c:73 src/language/lexer/lexer.c:464
+#: src/language/data-io/print-space.c:73 src/language/lexer/lexer.c:471
 #: src/language/stats/autorecode.c:154 src/language/xforms/select-if.c:59
 msgid "expecting end of command"
 msgstr ""
 #: src/language/stats/autorecode.c:154 src/language/xforms/select-if.c:59
 msgid "expecting end of command"
 msgstr ""
@@ -1828,11 +1828,11 @@ msgid ""
 "s."
 msgstr ""
 
 "s."
 msgstr ""
 
-#: src/language/dictionary/value-labels.c:156 src/language/lexer/lexer.c:608
+#: src/language/dictionary/value-labels.c:156 src/language/lexer/lexer.c:615
 msgid "expecting string"
 msgstr ""
 
 msgid "expecting string"
 msgstr ""
 
-#: src/language/dictionary/value-labels.c:165 src/language/lexer/lexer.c:622
+#: src/language/dictionary/value-labels.c:165 src/language/lexer/lexer.c:629
 msgid "expecting integer"
 msgstr ""
 
 msgid "expecting integer"
 msgstr ""
 
@@ -2079,89 +2079,89 @@ msgstr ""
 msgid "expecting format type"
 msgstr ""
 
 msgid "expecting format type"
 msgstr ""
 
-#: src/language/lexer/lexer.c:270
+#: src/language/lexer/lexer.c:277
 #, c-format
 msgid "%s does not form a valid number."
 msgstr ""
 
 #, c-format
 msgid "%s does not form a valid number."
 msgstr ""
 
-#: src/language/lexer/lexer.c:374
+#: src/language/lexer/lexer.c:381
 #, c-format
 msgid "Bad character in input: `%c'."
 msgstr ""
 
 #, c-format
 msgid "Bad character in input: `%c'."
 msgstr ""
 
-#: src/language/lexer/lexer.c:376
+#: src/language/lexer/lexer.c:383
 #, c-format
 msgid "Bad character in input: `\\%o'."
 msgstr ""
 
 #, c-format
 msgid "Bad character in input: `\\%o'."
 msgstr ""
 
-#: src/language/lexer/lexer.c:412
+#: src/language/lexer/lexer.c:419
 #, c-format
 msgid "Subcommand %s may only be specified once."
 msgstr ""
 
 #, c-format
 msgid "Subcommand %s may only be specified once."
 msgstr ""
 
-#: src/language/lexer/lexer.c:420
+#: src/language/lexer/lexer.c:427
 #, c-format
 msgid "missing required subcommand %s"
 msgstr ""
 
 #, c-format
 msgid "missing required subcommand %s"
 msgstr ""
 
-#: src/language/lexer/lexer.c:449
+#: src/language/lexer/lexer.c:456
 #, c-format
 msgid "Syntax error %s at %s."
 msgstr ""
 
 #, c-format
 msgid "Syntax error %s at %s."
 msgstr ""
 
-#: src/language/lexer/lexer.c:452
+#: src/language/lexer/lexer.c:459
 #, c-format
 msgid "Syntax error at %s."
 msgstr ""
 
 #, c-format
 msgid "Syntax error at %s."
 msgstr ""
 
-#: src/language/lexer/lexer.c:577 src/language/lexer/lexer.c:594
+#: src/language/lexer/lexer.c:584 src/language/lexer/lexer.c:601
 #, c-format
 msgid "expecting `%s'"
 msgstr ""
 
 #, c-format
 msgid "expecting `%s'"
 msgstr ""
 
-#: src/language/lexer/lexer.c:635
+#: src/language/lexer/lexer.c:642
 msgid "expecting number"
 msgstr ""
 
 msgid "expecting number"
 msgstr ""
 
-#: src/language/lexer/lexer.c:647
+#: src/language/lexer/lexer.c:654
 msgid "expecting identifier"
 msgstr ""
 
 msgid "expecting identifier"
 msgstr ""
 
-#: src/language/lexer/lexer.c:1045
+#: src/language/lexer/lexer.c:1048
 msgid "binary"
 msgstr ""
 
 msgid "binary"
 msgstr ""
 
-#: src/language/lexer/lexer.c:1050
+#: src/language/lexer/lexer.c:1053
 msgid "octal"
 msgstr ""
 
 msgid "octal"
 msgstr ""
 
-#: src/language/lexer/lexer.c:1055
+#: src/language/lexer/lexer.c:1058
 msgid "hex"
 msgstr ""
 
 msgid "hex"
 msgstr ""
 
-#: src/language/lexer/lexer.c:1065
+#: src/language/lexer/lexer.c:1068
 #, c-format
 msgid "String of %s digits has %d characters, which is not a multiple of %d."
 msgstr ""
 
 #, c-format
 msgid "String of %s digits has %d characters, which is not a multiple of %d."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1094
+#: src/language/lexer/lexer.c:1097
 #, c-format
 msgid "`%c' is not a valid %s digit."
 msgstr ""
 
 #, c-format
 msgid "`%c' is not a valid %s digit."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1128
+#: src/language/lexer/lexer.c:1131
 msgid "Unterminated string constant."
 msgstr ""
 
 msgid "Unterminated string constant."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1182
+#: src/language/lexer/lexer.c:1185
 msgid "Unexpected end of file in string concatenation."
 msgstr ""
 
 msgid "Unexpected end of file in string concatenation."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1190
+#: src/language/lexer/lexer.c:1193
 msgid "String expected following `+'."
 msgstr ""
 
 msgid "String expected following `+'."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1203
+#: src/language/lexer/lexer.c:1206
 #, c-format
 msgid "String exceeds 255 characters in length (%d characters)."
 msgstr ""
 #, c-format
 msgid "String exceeds 255 characters in length (%d characters)."
 msgstr ""
@@ -3494,7 +3494,7 @@ msgstr ""
 msgid "Reading `%s': %s."
 msgstr ""
 
 msgid "Reading `%s': %s."
 msgstr ""
 
-#: src/language/syntax-file.c:125
+#: src/language/syntax-file.c:124
 #, c-format
 msgid "Closing `%s': %s."
 msgstr ""
 #, c-format
 msgid "Closing `%s': %s."
 msgstr ""
@@ -3550,15 +3550,32 @@ msgstr ""
 msgid "Only USE ALL is currently implemented."
 msgstr ""
 
 msgid "Only USE ALL is currently implemented."
 msgstr ""
 
-#: src/language/utilities/include.c:47
+#: src/language/utilities/include.c:47 src/language/utilities/insert.c:138
 msgid "expecting file name"
 msgstr ""
 
 msgid "expecting file name"
 msgstr ""
 
-#: src/language/utilities/include.c:62
+#: src/language/utilities/include.c:63 src/language/utilities/insert.c:149
 #, c-format
 msgid "Can't find `%s' in include file search path."
 msgstr ""
 
 #, c-format
 msgid "Can't find `%s' in include file search path."
 msgstr ""
 
+#: src/language/utilities/insert.c:60
+msgid "Expecting BATCH or INTERACTIVE after SYNTAX."
+msgstr ""
+
+#: src/language/utilities/insert.c:77
+msgid "Expecting YES or NO after CD."
+msgstr ""
+
+#: src/language/utilities/insert.c:94
+msgid "Expecting CONTINUE or STOP after ERROR."
+msgstr ""
+
+#: src/language/utilities/insert.c:101
+#, fuzzy, c-format
+msgid "Unexpected token: `%s'."
+msgstr "plotzlich ist der Datei beendet"
+
 #: src/language/utilities/permissions.c:73
 #, c-format
 msgid "Expecting %s or %s."
 #: src/language/utilities/permissions.c:73
 #, c-format
 msgid "Expecting %s or %s."
@@ -5280,7 +5297,7 @@ msgstr ""
 msgid "%s --- PSPP Output"
 msgstr "PSPP Dateiaufbereiter"
 
 msgid "%s --- PSPP Output"
 msgstr "PSPP Dateiaufbereiter"
 
-#: src/ui/terminal/command-line.c:219
+#: src/ui/terminal/command-line.c:223
 #, c-format
 msgid ""
 "PSPP, a program for statistical analysis of sample data.\n"
 #, c-format
 msgid ""
 "PSPP, a program for statistical analysis of sample data.\n"
@@ -5326,7 +5343,7 @@ msgid ""
 "\n"
 msgstr ""
 
 "\n"
 msgstr ""
 
-#: src/ui/terminal/command-line.c:254
+#: src/ui/terminal/command-line.c:258
 #, c-format
 msgid ""
 "\n"
 #, c-format
 msgid ""
 "\n"
index 5123ff96efe3761a0675840a47d0f112e95e1390..148a959c781e4ecfd7db34e9fc5357f716fa2154 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2007-08-31 07:06+0800\n"
+"POT-Creation-Date: 2007-09-01 08:59+0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -982,41 +982,41 @@ msgstr ""
 msgid "Only one index clause may be specified."
 msgstr ""
 
 msgid "Only one index clause may be specified."
 msgstr ""
 
-#: src/language/control/repeat.c:168
+#: src/language/control/repeat.c:173
 #, c-format
 msgid "Dummy variable name \"%s\" hides dictionary variable \"%s\"."
 msgstr ""
 
 #, c-format
 msgid "Dummy variable name \"%s\" hides dictionary variable \"%s\"."
 msgstr ""
 
-#: src/language/control/repeat.c:173
+#: src/language/control/repeat.c:178
 #, c-format
 msgid "Dummy variable name \"%s\" is given twice."
 msgstr ""
 
 #, c-format
 msgid "Dummy variable name \"%s\" is given twice."
 msgstr ""
 
-#: src/language/control/repeat.c:219
+#: src/language/control/repeat.c:224
 #, c-format
 msgid ""
 "Dummy variable \"%.*s\" had %d substitutions, so \"%.*s\" must also, but %d "
 "were specified."
 msgstr ""
 
 #, c-format
 msgid ""
 "Dummy variable \"%.*s\" had %d substitutions, so \"%.*s\" must also, but %d "
 "were specified."
 msgstr ""
 
-#: src/language/control/repeat.c:331
+#: src/language/control/repeat.c:336
 msgid "DO REPEAT may not nest in compatibility mode."
 msgstr ""
 
 msgid "DO REPEAT may not nest in compatibility mode."
 msgstr ""
 
-#: src/language/control/repeat.c:433
+#: src/language/control/repeat.c:438
 msgid "Ranges may only have integer bounds"
 msgstr ""
 
 msgid "Ranges may only have integer bounds"
 msgstr ""
 
-#: src/language/control/repeat.c:442
+#: src/language/control/repeat.c:447
 #, c-format
 msgid "%g TO %g is an invalid range."
 msgstr ""
 
 #, c-format
 msgid "%g TO %g is an invalid range."
 msgstr ""
 
-#: src/language/control/repeat.c:477
+#: src/language/control/repeat.c:482
 msgid "String expected."
 msgstr ""
 
 msgid "String expected."
 msgstr ""
 
-#: src/language/control/repeat.c:496
+#: src/language/control/repeat.c:501
 msgid "No matching DO REPEAT."
 msgstr ""
 
 msgid "No matching DO REPEAT."
 msgstr ""
 
@@ -1405,7 +1405,7 @@ msgid_plural "Writing %d records."
 msgstr[0] ""
 msgstr[1] ""
 
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/language/data-io/print-space.c:73 src/language/lexer/lexer.c:464
+#: src/language/data-io/print-space.c:73 src/language/lexer/lexer.c:471
 #: src/language/stats/autorecode.c:154 src/language/xforms/select-if.c:59
 msgid "expecting end of command"
 msgstr ""
 #: src/language/stats/autorecode.c:154 src/language/xforms/select-if.c:59
 msgid "expecting end of command"
 msgstr ""
@@ -1822,11 +1822,11 @@ msgid ""
 "s."
 msgstr ""
 
 "s."
 msgstr ""
 
-#: src/language/dictionary/value-labels.c:156 src/language/lexer/lexer.c:608
+#: src/language/dictionary/value-labels.c:156 src/language/lexer/lexer.c:615
 msgid "expecting string"
 msgstr ""
 
 msgid "expecting string"
 msgstr ""
 
-#: src/language/dictionary/value-labels.c:165 src/language/lexer/lexer.c:622
+#: src/language/dictionary/value-labels.c:165 src/language/lexer/lexer.c:629
 msgid "expecting integer"
 msgstr ""
 
 msgid "expecting integer"
 msgstr ""
 
@@ -2073,89 +2073,89 @@ msgstr ""
 msgid "expecting format type"
 msgstr ""
 
 msgid "expecting format type"
 msgstr ""
 
-#: src/language/lexer/lexer.c:270
+#: src/language/lexer/lexer.c:277
 #, c-format
 msgid "%s does not form a valid number."
 msgstr ""
 
 #, c-format
 msgid "%s does not form a valid number."
 msgstr ""
 
-#: src/language/lexer/lexer.c:374
+#: src/language/lexer/lexer.c:381
 #, c-format
 msgid "Bad character in input: `%c'."
 msgstr ""
 
 #, c-format
 msgid "Bad character in input: `%c'."
 msgstr ""
 
-#: src/language/lexer/lexer.c:376
+#: src/language/lexer/lexer.c:383
 #, c-format
 msgid "Bad character in input: `\\%o'."
 msgstr ""
 
 #, c-format
 msgid "Bad character in input: `\\%o'."
 msgstr ""
 
-#: src/language/lexer/lexer.c:412
+#: src/language/lexer/lexer.c:419
 #, c-format
 msgid "Subcommand %s may only be specified once."
 msgstr ""
 
 #, c-format
 msgid "Subcommand %s may only be specified once."
 msgstr ""
 
-#: src/language/lexer/lexer.c:420
+#: src/language/lexer/lexer.c:427
 #, c-format
 msgid "missing required subcommand %s"
 msgstr ""
 
 #, c-format
 msgid "missing required subcommand %s"
 msgstr ""
 
-#: src/language/lexer/lexer.c:449
+#: src/language/lexer/lexer.c:456
 #, c-format
 msgid "Syntax error %s at %s."
 msgstr ""
 
 #, c-format
 msgid "Syntax error %s at %s."
 msgstr ""
 
-#: src/language/lexer/lexer.c:452
+#: src/language/lexer/lexer.c:459
 #, c-format
 msgid "Syntax error at %s."
 msgstr ""
 
 #, c-format
 msgid "Syntax error at %s."
 msgstr ""
 
-#: src/language/lexer/lexer.c:577 src/language/lexer/lexer.c:594
+#: src/language/lexer/lexer.c:584 src/language/lexer/lexer.c:601
 #, c-format
 msgid "expecting `%s'"
 msgstr ""
 
 #, c-format
 msgid "expecting `%s'"
 msgstr ""
 
-#: src/language/lexer/lexer.c:635
+#: src/language/lexer/lexer.c:642
 msgid "expecting number"
 msgstr ""
 
 msgid "expecting number"
 msgstr ""
 
-#: src/language/lexer/lexer.c:647
+#: src/language/lexer/lexer.c:654
 msgid "expecting identifier"
 msgstr ""
 
 msgid "expecting identifier"
 msgstr ""
 
-#: src/language/lexer/lexer.c:1045
+#: src/language/lexer/lexer.c:1048
 msgid "binary"
 msgstr ""
 
 msgid "binary"
 msgstr ""
 
-#: src/language/lexer/lexer.c:1050
+#: src/language/lexer/lexer.c:1053
 msgid "octal"
 msgstr ""
 
 msgid "octal"
 msgstr ""
 
-#: src/language/lexer/lexer.c:1055
+#: src/language/lexer/lexer.c:1058
 msgid "hex"
 msgstr ""
 
 msgid "hex"
 msgstr ""
 
-#: src/language/lexer/lexer.c:1065
+#: src/language/lexer/lexer.c:1068
 #, c-format
 msgid "String of %s digits has %d characters, which is not a multiple of %d."
 msgstr ""
 
 #, c-format
 msgid "String of %s digits has %d characters, which is not a multiple of %d."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1094
+#: src/language/lexer/lexer.c:1097
 #, c-format
 msgid "`%c' is not a valid %s digit."
 msgstr ""
 
 #, c-format
 msgid "`%c' is not a valid %s digit."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1128
+#: src/language/lexer/lexer.c:1131
 msgid "Unterminated string constant."
 msgstr ""
 
 msgid "Unterminated string constant."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1182
+#: src/language/lexer/lexer.c:1185
 msgid "Unexpected end of file in string concatenation."
 msgstr ""
 
 msgid "Unexpected end of file in string concatenation."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1190
+#: src/language/lexer/lexer.c:1193
 msgid "String expected following `+'."
 msgstr ""
 
 msgid "String expected following `+'."
 msgstr ""
 
-#: src/language/lexer/lexer.c:1203
+#: src/language/lexer/lexer.c:1206
 #, c-format
 msgid "String exceeds 255 characters in length (%d characters)."
 msgstr ""
 #, c-format
 msgid "String exceeds 255 characters in length (%d characters)."
 msgstr ""
@@ -3487,7 +3487,7 @@ msgstr ""
 msgid "Reading `%s': %s."
 msgstr ""
 
 msgid "Reading `%s': %s."
 msgstr ""
 
-#: src/language/syntax-file.c:125
+#: src/language/syntax-file.c:124
 #, c-format
 msgid "Closing `%s': %s."
 msgstr ""
 #, c-format
 msgid "Closing `%s': %s."
 msgstr ""
@@ -3543,15 +3543,32 @@ msgstr ""
 msgid "Only USE ALL is currently implemented."
 msgstr ""
 
 msgid "Only USE ALL is currently implemented."
 msgstr ""
 
-#: src/language/utilities/include.c:47
+#: src/language/utilities/include.c:47 src/language/utilities/insert.c:138
 msgid "expecting file name"
 msgstr ""
 
 msgid "expecting file name"
 msgstr ""
 
-#: src/language/utilities/include.c:62
+#: src/language/utilities/include.c:63 src/language/utilities/insert.c:149
 #, c-format
 msgid "Can't find `%s' in include file search path."
 msgstr ""
 
 #, c-format
 msgid "Can't find `%s' in include file search path."
 msgstr ""
 
+#: src/language/utilities/insert.c:60
+msgid "Expecting BATCH or INTERACTIVE after SYNTAX."
+msgstr ""
+
+#: src/language/utilities/insert.c:77
+msgid "Expecting YES or NO after CD."
+msgstr ""
+
+#: src/language/utilities/insert.c:94
+msgid "Expecting CONTINUE or STOP after ERROR."
+msgstr ""
+
+#: src/language/utilities/insert.c:101
+#, c-format
+msgid "Unexpected token: `%s'."
+msgstr ""
+
 #: src/language/utilities/permissions.c:73
 #, c-format
 msgid "Expecting %s or %s."
 #: src/language/utilities/permissions.c:73
 #, c-format
 msgid "Expecting %s or %s."
@@ -5225,7 +5242,7 @@ msgstr ""
 msgid "%s --- PSPP Output"
 msgstr ""
 
 msgid "%s --- PSPP Output"
 msgstr ""
 
-#: src/ui/terminal/command-line.c:219
+#: src/ui/terminal/command-line.c:223
 #, c-format
 msgid ""
 "PSPP, a program for statistical analysis of sample data.\n"
 #, c-format
 msgid ""
 "PSPP, a program for statistical analysis of sample data.\n"
@@ -5271,7 +5288,7 @@ msgid ""
 "\n"
 msgstr ""
 
 "\n"
 msgstr ""
 
-#: src/ui/terminal/command-line.c:254
+#: src/ui/terminal/command-line.c:258
 #, c-format
 msgid ""
 "\n"
 #, c-format
 msgid ""
 "\n"
index 8949ff75c1b989290dd343e45de6772fa925804b..d25c2d0379b7210e1d71fcff6453ff465894161f 100644 (file)
@@ -1,3 +1,10 @@
+2007-09-05  John Darrington <john@darrington.wattle.id.au>
+
+       * command.c (do_parse_command): Translate CMD_FAILURE into
+       CMD_CASCADING_FAILURE, if the ERRMODE_STOP is set on the syntax
+       source. 
+       
+       
 2007-06-06  Ben Pfaff  <blp@gnu.org>
 
        * command.def: Add DEBUG DATASHEET command.  Remove DEBUG CASEFILE
 2007-06-06  Ben Pfaff  <blp@gnu.org>
 
        * command.def: Add DEBUG DATASHEET command.  Remove DEBUG CASEFILE
index 40b8505eba7753d0d247c982ec22f7d3648f99bb..1688a10eb6e3472dc5fa7e3ae0a21134827fc006 100644 (file)
@@ -39,6 +39,7 @@
 #include <libpspp/str.h>
 #include <output/manager.h>
 #include <output/table.h>
 #include <libpspp/str.h>
 #include <output/manager.h>
 #include <output/table.h>
+#include <libpspp/getl.h>
 
 #if HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 
 #if HAVE_SYS_WAIT_H
 #include <sys/wait.h>
@@ -169,7 +170,8 @@ cmd_parse (struct lexer *lexer, struct dataset *ds)
 /* Parses an entire command, from command name to terminating
    dot. */
 static enum cmd_result
 /* Parses an entire command, from command name to terminating
    dot. */
 static enum cmd_result
-do_parse_command (struct lexer *lexer, struct dataset *ds, enum cmd_state state)
+do_parse_command (struct lexer *lexer,
+                 struct dataset *ds, enum cmd_state state)
 {
   const struct command *command;
   enum cmd_result result;
 {
   const struct command *command;
   enum cmd_result result;
@@ -179,38 +181,50 @@ do_parse_command (struct lexer *lexer, struct dataset *ds, enum cmd_state state)
   set_completion_state (state);
   lex_get (lexer);
   if (lex_token (lexer) == T_STOP)
   set_completion_state (state);
   lex_get (lexer);
   if (lex_token (lexer) == T_STOP)
-    return CMD_EOF;
+    {
+      result = CMD_EOF;
+      goto finish;
+    }
   else if (lex_token (lexer) == '.')
     {
       /* Null commands can result from extra empty lines. */
   else if (lex_token (lexer) == '.')
     {
       /* Null commands can result from extra empty lines. */
-      return CMD_SUCCESS;
+      result = CMD_SUCCESS;
+      goto finish;
     }
     }
+
   prompt_set_style (PROMPT_LATER);
 
   /* Parse the command name. */
   command = parse_command_name (lexer);
   if (command == NULL)
   prompt_set_style (PROMPT_LATER);
 
   /* Parse the command name. */
   command = parse_command_name (lexer);
   if (command == NULL)
-    return CMD_FAILURE;
+    {
+      result = CMD_FAILURE;
+      goto finish;
+    }
   else if (command->function == NULL)
     {
       msg (SE, _("%s is unimplemented."), command->name);
   else if (command->function == NULL)
     {
       msg (SE, _("%s is unimplemented."), command->name);
-      return CMD_NOT_IMPLEMENTED;
+      result = CMD_NOT_IMPLEMENTED;
+      goto finish;
     }
   else if ((command->flags & F_TESTING) && !get_testing_mode ())
     {
       msg (SE, _("%s may be used only in testing mode."), command->name);
     }
   else if ((command->flags & F_TESTING) && !get_testing_mode ())
     {
       msg (SE, _("%s may be used only in testing mode."), command->name);
-      return CMD_FAILURE;
+      result = CMD_FAILURE;
+      goto finish;
     }
   else if ((command->flags & F_ENHANCED) && get_syntax () != ENHANCED)
     {
       msg (SE, _("%s may be used only in enhanced syntax mode."),
            command->name);
     }
   else if ((command->flags & F_ENHANCED) && get_syntax () != ENHANCED)
     {
       msg (SE, _("%s may be used only in enhanced syntax mode."),
            command->name);
-      return CMD_FAILURE;
+      result = CMD_FAILURE;
+      goto finish;
     }
   else if (!in_correct_state (command, state))
     {
       report_state_mismatch (command, state);
     }
   else if (!in_correct_state (command, state))
     {
       report_state_mismatch (command, state);
-      return CMD_FAILURE;
+      result = CMD_FAILURE;
+      goto finish;
     }
 
   /* Execute command. */
     }
 
   /* Execute command. */
@@ -221,6 +235,19 @@ do_parse_command (struct lexer *lexer, struct dataset *ds, enum cmd_state state)
   msg_set_command_name (NULL);
 
   assert (cmd_result_is_valid (result));
   msg_set_command_name (NULL);
 
   assert (cmd_result_is_valid (result));
+
+ finish:
+  if ( cmd_result_is_failure (result))
+    {
+      const struct source_stream *cs = lex_get_source_stream (lexer);
+
+      if ( source_stream_current_error_mode (cs) == ERRMODE_STOP )
+       {
+         msg (MW, _("Error encountered while ERROR=STOP is effective."));
+         result = CMD_CASCADING_FAILURE;
+       }
+    }
+
   return result;
 }
 
   return result;
 }
 
index 5967e5d28958bdbc49b97cb5787f898f70b3f2e0..7a89ae0a1631cab8384a82c7911b772ea6b74143 100644 (file)
@@ -26,6 +26,7 @@ DEF_CMD (S_ANY, F_KEEP_FINAL_TOKEN, "FILE LABEL", cmd_file_label)
 DEF_CMD (S_ANY, 0, "FINISH", cmd_finish)
 DEF_CMD (S_ANY, F_KEEP_FINAL_TOKEN, "HOST", cmd_host)
 DEF_CMD (S_ANY, 0, "INCLUDE", cmd_include)
 DEF_CMD (S_ANY, 0, "FINISH", cmd_finish)
 DEF_CMD (S_ANY, F_KEEP_FINAL_TOKEN, "HOST", cmd_host)
 DEF_CMD (S_ANY, 0, "INCLUDE", cmd_include)
+DEF_CMD (S_ANY, 0, "INSERT", cmd_insert)
 DEF_CMD (S_ANY, 0, "N OF CASES", cmd_n_of_cases)
 DEF_CMD (S_ANY, F_ABBREV, "N", cmd_n_of_cases)
 DEF_CMD (S_ANY, 0, "NEW FILE", cmd_new_file)
 DEF_CMD (S_ANY, 0, "N OF CASES", cmd_n_of_cases)
 DEF_CMD (S_ANY, F_ABBREV, "N", cmd_n_of_cases)
 DEF_CMD (S_ANY, 0, "NEW FILE", cmd_new_file)
index ede37016ee816a05820c6e97a97ff0bbe873ec43..cd56d7c81164c44103693c5e3da2a7083be584b1 100644 (file)
@@ -49,7 +49,6 @@ struct repeat_line
     const char *file_name;      /* File name. */
     int line_number;            /* Line number. */
     struct substring text;     /* Contents. */
     const char *file_name;      /* File name. */
     int line_number;            /* Line number. */
     struct substring text;     /* Contents. */
-    enum getl_syntax syntax;    /* Syntax mode. */
   };
 
 /* The type of substitution made for a DO REPEAT macro. */
   };
 
 /* The type of substitution made for a DO REPEAT macro. */
@@ -103,9 +102,9 @@ static int parse_strings (struct lexer *, struct repeat_macro *,
                          struct pool *);
 
 static void do_repeat_filter (struct getl_interface *,
                          struct pool *);
 
 static void do_repeat_filter (struct getl_interface *,
-                              struct string *, enum getl_syntax);
+                              struct string *);
 static bool do_repeat_read (struct getl_interface *,
 static bool do_repeat_read (struct getl_interface *,
-                            struct string *, enum getl_syntax *);
+                            struct string *);
 static void do_repeat_close (struct getl_interface *);
 static bool always_false (const struct getl_interface *);
 static const char *do_repeat_name (const struct getl_interface *);
 static void do_repeat_close (struct getl_interface *);
 static bool always_false (const struct getl_interface *);
 static const char *do_repeat_name (const struct getl_interface *);
@@ -136,7 +135,11 @@ cmd_do_repeat (struct lexer *lexer, struct dataset *ds)
   block->parent.location = do_repeat_location;
 
   if (!ll_is_empty (&block->lines))
   block->parent.location = do_repeat_location;
 
   if (!ll_is_empty (&block->lines))
-    getl_include_source (lex_get_source_stream (lexer), &block->parent);
+    getl_include_source (lex_get_source_stream (lexer),
+                        &block->parent,
+                        lex_current_syntax_mode (lexer),
+                        lex_current_error_mode (lexer)
+                        );
   else
     pool_destroy (block->pool);
 
   else
     pool_destroy (block->pool);
 
@@ -298,11 +301,10 @@ parse_lines (struct lexer *lexer, struct repeat_block *block)
       const char *cur_file_name;
       struct repeat_line *line;
       struct string text;
       const char *cur_file_name;
       struct repeat_line *line;
       struct string text;
-      enum getl_syntax syntax;
       bool command_ends_before_line, command_ends_after_line;
 
       /* Retrieve an input line and make a copy of it. */
       bool command_ends_before_line, command_ends_after_line;
 
       /* Retrieve an input line and make a copy of it. */
-      if (!lex_get_line_raw (lexer, &syntax))
+      if (!lex_get_line_raw (lexer))
         return false;
       ds_init_string (&text, lex_entire_line_ds (lexer));
 
         return false;
       ds_init_string (&text, lex_entire_line_ds (lexer));
 
@@ -318,11 +320,12 @@ parse_lines (struct lexer *lexer, struct repeat_block *block)
       line->file_name = previous_file_name;
       line->line_number = getl_source_location (lex_get_source_stream (lexer));
       ss_alloc_substring_pool (&line->text, ds_ss (&text), block->pool);
       line->file_name = previous_file_name;
       line->line_number = getl_source_location (lex_get_source_stream (lexer));
       ss_alloc_substring_pool (&line->text, ds_ss (&text), block->pool);
-      line->syntax = syntax;
+
 
       /* Check whether the line contains a DO REPEAT or END
          REPEAT command. */
 
       /* Check whether the line contains a DO REPEAT or END
          REPEAT command. */
-      lex_preprocess_line (&text, syntax,
+      lex_preprocess_line (&text,
+                          lex_current_syntax_mode (lexer),
                            &command_ends_before_line,
                            &command_ends_after_line);
       if (recognize_do_repeat (ds_ss (&text)))
                            &command_ends_before_line,
                            &command_ends_after_line);
       if (recognize_do_repeat (ds_ss (&text)))
@@ -510,7 +513,7 @@ find_substitution (struct repeat_block *block, struct substring name)
    repeated lines. */
 static void
 do_repeat_filter (struct getl_interface *block_,
    repeated lines. */
 static void
 do_repeat_filter (struct getl_interface *block_,
-                  struct string *line, enum getl_syntax syntax UNUSED)
+                  struct string *line)
 {
   struct repeat_block *block = (struct repeat_block *) block_;
   bool in_apos, in_quote, dot;
 {
   struct repeat_block *block = (struct repeat_block *) block_;
   bool in_apos, in_quote, dot;
@@ -566,7 +569,7 @@ current_line (const struct getl_interface *interface)
    was obtained, false if the source is exhausted. */
 static bool
 do_repeat_read  (struct getl_interface *interface,
    was obtained, false if the source is exhausted. */
 static bool
 do_repeat_read  (struct getl_interface *interface,
-                 struct string *output, enum getl_syntax *syntax)
+                 struct string *output)
 {
   struct repeat_block *block = (struct repeat_block *) interface;
   struct repeat_line *line;
 {
   struct repeat_block *block = (struct repeat_block *) interface;
   struct repeat_line *line;
@@ -583,7 +586,6 @@ do_repeat_read  (struct getl_interface *interface,
 
   line = current_line (interface);
   ds_assign_substring (output, line->text);
 
   line = current_line (interface);
   ds_assign_substring (output, line->text);
-  *syntax = line->syntax;
   return true;
 }
 
   return true;
 }
 
index c752587b5b1354393de8442eb6efb47d579ed2c9..7176aed43a03f7c763a86747cf889cc69c9c10e2 100644 (file)
@@ -170,7 +170,7 @@ read_inline_record (struct dfm_reader *r)
       prompt_set_style (PROMPT_DATA);
     }
 
       prompt_set_style (PROMPT_DATA);
     }
 
-  if (!lex_get_line_raw (r->lexer, NULL))
+  if (!lex_get_line_raw (r->lexer))
     {
       msg (SE, _("Unexpected end-of-file while reading data in BEGIN "
                  "DATA.  This probably indicates "
     {
       msg (SE, _("Unexpected end-of-file while reading data in BEGIN "
                  "DATA.  This probably indicates "
index 4e10ec22478caf8c8e3579d9e8b8094b0b31f688..71597302032a48cbf31f4d12d028f54bbc009780 100644 (file)
@@ -43,6 +43,7 @@
 #define DUMP_TOKENS 0
 
 
 #define DUMP_TOKENS 0
 
 
+
 struct lexer
 {
   struct string line_buffer;
 struct lexer
 {
   struct string line_buffer;
@@ -108,6 +109,18 @@ lex_get_source_stream (const struct lexer *lex)
   return lex->ss;
 }
 
   return lex->ss;
 }
 
+enum syntax_mode
+lex_current_syntax_mode (const struct lexer *lex)
+{
+  return source_stream_current_syntax_mode (lex->ss);
+}
+
+enum error_mode
+lex_current_error_mode (const struct lexer *lex)
+{
+  return source_stream_current_error_mode (lex->ss);
+}
+
 
 void
 lex_destroy (struct lexer *lexer)
 
 void
 lex_destroy (struct lexer *lexer)
@@ -832,7 +845,7 @@ strip_comments (struct string *string)
    *LINE_STARTS_COMMAND and *LINE_ENDS_COMMAND appropriately. */
 void
 lex_preprocess_line (struct string *line,
    *LINE_STARTS_COMMAND and *LINE_ENDS_COMMAND appropriately. */
 void
 lex_preprocess_line (struct string *line,
-                     enum getl_syntax syntax,
+                     enum syntax_mode syntax,
                      bool *line_starts_command,
                      bool *line_ends_command)
 {
                      bool *line_starts_command,
                      bool *line_ends_command)
 {
@@ -854,15 +867,11 @@ lex_preprocess_line (struct string *line,
    Sets *SYNTAX, if SYNTAX is non-null, to the line's syntax
    mode. */
 bool
    Sets *SYNTAX, if SYNTAX is non-null, to the line's syntax
    mode. */
 bool
-lex_get_line_raw (struct lexer *lexer, enum getl_syntax *syntax)
+lex_get_line_raw (struct lexer *lexer)
 {
 {
-  enum getl_syntax dummy;
-  bool ok;
-
-  if (syntax == NULL)
-    syntax = &dummy;
-  ok = getl_read_line (lexer->ss, &lexer->line_buffer, syntax);
-  journal_write (*syntax == GETL_BATCH, ds_cstr (&lexer->line_buffer));
+  bool ok = getl_read_line (lexer->ss, &lexer->line_buffer);
+  enum syntax_mode mode = lex_current_syntax_mode (lexer);
+  journal_write (mode == GETL_BATCH, ds_cstr (&lexer->line_buffer));
 
   return ok;
 }
 
   return ok;
 }
@@ -874,15 +883,15 @@ bool
 lex_get_line (struct lexer *lexer)
 {
   bool line_starts_command;
 lex_get_line (struct lexer *lexer)
 {
   bool line_starts_command;
-  enum getl_syntax syntax = GETL_BATCH;
 
 
-  if (!lex_get_line_raw (lexer, &syntax))
+  if (!lex_get_line_raw (lexer))
     {
       lexer->prog = NULL;
       return false;
     }
 
     {
       lexer->prog = NULL;
       return false;
     }
 
-  lex_preprocess_line (&lexer->line_buffer, syntax,
+  lex_preprocess_line (&lexer->line_buffer,
+                      lex_current_syntax_mode (lexer),
                        &line_starts_command, &lexer->dot);
 
   if (line_starts_command)
                        &line_starts_command, &lexer->dot);
 
   if (line_starts_command)
index 44be0e930d41fa2be6e2c78b8a70202698c8b92e..ada09ade9a89f1eb0d4f682a0d70c94cef9be04d 100644 (file)
@@ -30,8 +30,10 @@ struct lexer;
 struct lexer * lex_create (struct source_stream *);
 void lex_destroy (struct lexer *);
 
 struct lexer * lex_create (struct source_stream *);
 void lex_destroy (struct lexer *);
 
+/* State accessors */
 struct source_stream * lex_get_source_stream (const struct lexer *);
 struct source_stream * lex_get_source_stream (const struct lexer *);
-
+enum syntax_mode lex_current_syntax_mode (const struct lexer *);
+enum error_mode lex_current_error_mode (const struct lexer *);
 
 /* Common functions. */
 void lex_get (struct lexer *);
 
 /* Common functions. */
 void lex_get (struct lexer *);
@@ -71,7 +73,7 @@ const char *lex_entire_line (const struct lexer *);
 const struct string *lex_entire_line_ds (const struct lexer *);
 const char *lex_rest_of_line (const struct lexer *);
 bool lex_end_dot (const struct lexer *);
 const struct string *lex_entire_line_ds (const struct lexer *);
 const char *lex_rest_of_line (const struct lexer *);
 bool lex_end_dot (const struct lexer *);
-void lex_preprocess_line (struct string *, enum getl_syntax,
+void lex_preprocess_line (struct string *, enum syntax_mode,
                           bool *line_starts_command,
                           bool *line_ends_command);
 void lex_discard_line (struct lexer *);
                           bool *line_starts_command,
                           bool *line_ends_command);
 void lex_discard_line (struct lexer *);
@@ -79,7 +81,7 @@ void lex_discard_rest_of_command (struct lexer *);
 
 /* Weird line reading functions. */
 bool lex_get_line (struct lexer *);
 
 /* Weird line reading functions. */
 bool lex_get_line (struct lexer *);
-bool lex_get_line_raw (struct lexer *, enum getl_syntax *);
+bool lex_get_line_raw (struct lexer *);
 
 /* Token names. */
 const char *lex_token_name (int);
 
 /* Token names. */
 const char *lex_token_name (int);
index b3ae6f4aca17ec2154a95cd1f8c2886f1953af6d..dde807c37c9c4409cc54b2d6049bc859679ee137 100644 (file)
@@ -74,9 +74,9 @@ line_number (const struct getl_interface *s)
 
 /* Reads a line from syntax file source S into LINE.
    Returns true if successful, false at end of file. */
 
 /* Reads a line from syntax file source S into LINE.
    Returns true if successful, false at end of file. */
-bool
+static bool
 read_syntax_file (struct getl_interface *s,
 read_syntax_file (struct getl_interface *s,
-                  struct string *line, enum getl_syntax *syntax)
+                  struct string *line)
 {
   struct syntax_file_source *sfs = (struct syntax_file_source *) s;
 
 {
   struct syntax_file_source *sfs = (struct syntax_file_source *) s;
 
@@ -112,7 +112,6 @@ read_syntax_file (struct getl_interface *s,
   if (get_echo ())
     tab_output_text (TAB_LEFT | TAB_FIX, ds_cstr (line));
 
   if (get_echo ())
     tab_output_text (TAB_LEFT | TAB_FIX, ds_cstr (line));
 
-  *syntax = GETL_BATCH;
   return true;
 }
 
   return true;
 }
 
index c038a4327a080774aa15457cac8cf797e637db48..8044f3c04e242b213d023ece8cfec1045c1abc41 100644 (file)
 #if !SYNTAX_FILE
 #define SYNTAX_FILE 1
 
 #if !SYNTAX_FILE
 #define SYNTAX_FILE 1
 
-#include <stdbool.h>
-#include <libpspp/getl.h>
-
-struct string;
-
-bool read_syntax_file (struct getl_interface *s,
-                       struct string *line, enum getl_syntax *syntax);
+struct getl_interface;
 
 /* Creates a syntax file source with file name FN. */
 
 /* Creates a syntax file source with file name FN. */
-struct getl_interface * create_syntax_file_source (const char *fn) ;
+struct getl_interface * create_syntax_file_source (const char *) ;
 
 #endif
 
 #endif
index bcdcbd3767c5b671df04bf1ac2d46477f3d880e2..f80bca2e9edfe68a9b8cd1715d4809a941e6e756 100644 (file)
@@ -70,8 +70,7 @@ do_close (struct getl_interface *i )
 
 static bool
 read_single_line (struct getl_interface *i,
 
 static bool
 read_single_line (struct getl_interface *i,
-                 struct string *line,
-                 enum getl_syntax *syntax_rules UNUSED)
+                 struct string *line)
 {
   struct syntax_string_source *sss = (struct syntax_string_source *) i;
 
 {
   struct syntax_string_source *sss = (struct syntax_string_source *) i;
 
index 0ef9d463d7393b1488dc0d768d012671dcde2b84..26c718a42de419ada022a35cb07b199dc2fd7406 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include <language/lexer/lexer.h>
 #include <libpspp/str.h>
 #include <data/file-name.h>
 #include <language/lexer/lexer.h>
 #include <libpspp/str.h>
 #include <data/file-name.h>
+#include <dirname.h>
+#include <canonicalize.h>
 
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
 
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
+static int parse_insert (struct lexer *lexer, char **filename);
+
+
 int
 cmd_include (struct lexer *lexer, struct dataset *ds UNUSED)
 {
 int
 cmd_include (struct lexer *lexer, struct dataset *ds UNUSED)
 {
-  struct source_stream *ss;
-  char *found_fn;
+  char *filename = NULL;
+  int status = parse_insert (lexer, &filename);
+
+  if ( CMD_SUCCESS != status)
+    return status;
+
+  lex_get (lexer);
+
+  status = lex_end_of_command (lexer);
+
+  if ( status == CMD_SUCCESS)
+    {
+      struct source_stream *ss = lex_get_source_stream (lexer);
+
+      assert (filename);
+      getl_include_source (ss, create_syntax_file_source (filename),
+                          GETL_BATCH, ERRMODE_STOP);
+      free (filename);
+    }
+
+  return status;
+}
+
+
+int
+cmd_insert (struct lexer *lexer, struct dataset *ds UNUSED)
+{
+  enum syntax_mode syntax_mode = GETL_INTERACTIVE;
+  enum error_mode error_mode = ERRMODE_CONTINUE;
+  char *filename = NULL;
+  int status = parse_insert (lexer, &filename);
+  bool cd = false;
+
+  if ( CMD_SUCCESS != status)
+    return status;
+
+  lex_get (lexer);
+
+  while ( '.' != lex_token (lexer))
+    {
+      if (lex_match_id (lexer, "SYNTAX"))
+       {
+         lex_match (lexer, '=');
+         if ( lex_match_id (lexer, "INTERACTIVE") )
+           syntax_mode = GETL_INTERACTIVE;
+         else if ( lex_match_id (lexer, "BATCH"))
+           syntax_mode = GETL_BATCH;
+         else
+           {
+             lex_error(lexer,
+                       _("Expecting BATCH or INTERACTIVE after SYNTAX."));
+             return CMD_FAILURE;
+           }
+       }
+      else if (lex_match_id (lexer, "CD"))
+       {
+         lex_match (lexer, '=');
+         if ( lex_match_id (lexer, "YES") )
+           {
+             cd = true;
+           }
+         else if ( lex_match_id (lexer, "NO"))
+           {
+             cd = false;
+           }
+         else
+           {
+             lex_error (lexer, _("Expecting YES or NO after CD."));
+             return CMD_FAILURE;
+           }
+       }
+      else if (lex_match_id (lexer, "ERROR"))
+       {
+         lex_match (lexer, '=');
+         if ( lex_match_id (lexer, "CONTINUE") )
+           {
+             error_mode = ERRMODE_CONTINUE;
+           }
+         else if ( lex_match_id (lexer, "STOP"))
+           {
+             error_mode = ERRMODE_STOP;
+           }
+         else
+           {
+             lex_error (lexer, _("Expecting CONTINUE or STOP after ERROR."));
+             return CMD_FAILURE;
+           }
+       }
+
+      else
+       {
+         lex_error (lexer, _("Unexpected token: `%s'."),
+                    lex_token_representation (lexer));
+
+         return CMD_FAILURE;
+       }
+    }
+
+  status = lex_end_of_command (lexer);
+
+  if ( status == CMD_SUCCESS)
+    {
+      struct source_stream *ss = lex_get_source_stream (lexer);
+
+      assert (filename);
+      getl_include_source (ss, create_syntax_file_source (filename),
+                          syntax_mode,
+                          error_mode);
+
+      if ( cd )
+       {
+         char *directory = dir_name (filename);
+         chdir (directory);
+         free (directory);
+       }
+
+      free (filename);
+    }
+
+  return status;
+}
+
+
+static int
+parse_insert (struct lexer *lexer, char **filename)
+{
   char *target_fn;
   char *target_fn;
+  char *relative_filename;
 
   /* Skip optional FILE=. */
   if (lex_match_id (lexer, "FILE"))
 
   /* Skip optional FILE=. */
   if (lex_match_id (lexer, "FILE"))
@@ -45,23 +175,24 @@ cmd_include (struct lexer *lexer, struct dataset *ds UNUSED)
   if (lex_token (lexer) != T_ID && lex_token (lexer) != T_STRING)
     {
       lex_error (lexer, _("expecting file name"));
   if (lex_token (lexer) != T_ID && lex_token (lexer) != T_STRING)
     {
       lex_error (lexer, _("expecting file name"));
-      return CMD_CASCADING_FAILURE;
+      return CMD_FAILURE;
     }
 
   target_fn = ds_cstr (lex_tokstr (lexer));
 
     }
 
   target_fn = ds_cstr (lex_tokstr (lexer));
 
-  ss = lex_get_source_stream (lexer);
-  found_fn = fn_search_path (target_fn, getl_include_path ( ss ));
+  relative_filename =
+    fn_search_path (target_fn,
+                   getl_include_path (lex_get_source_stream (lexer)));
 
 
-  if (found_fn != NULL)
+  if ( ! relative_filename)
     {
     {
-      getl_include_source (ss, create_syntax_file_source (found_fn));
-      free (found_fn);
-    }
-  else
-    msg (SE, _("Can't find `%s' in include file search path."),
+      msg (SE, _("Can't find `%s' in include file search path."),
         target_fn);
         target_fn);
+      return CMD_FAILURE;
+    }
 
 
-  lex_get (lexer);
-  return lex_end_of_command (lexer);
+  *filename = canonicalize_file_name (relative_filename);
+  free (relative_filename);
+
+  return CMD_SUCCESS;
 }
 }
index 6f3ddf519d23e9068b6cc970962eff23ac905dc5..9c1b654d9cd6d35bb19b671da60dbd823a8a55c0 100644 (file)
@@ -1,3 +1,8 @@
+2007-09-05 John Darrington <john@darrington.wattle.id.au>
+
+       * getl.c: Add extra members to struct getl_source, to maintain the
+       error mode and the syntax_mode. 
+
 2007-07-25  Ben Pfaff  <blp@gnu.org>
 
        * getl.c (getl_append_source): Add source to *end* of list.
 2007-07-25  Ben Pfaff  <blp@gnu.org>
 
        * getl.c (getl_append_source): Add source to *end* of list.
index b4617122677840ecd65a9670a3d424e3f03964d6..4d6338ce023155b28277b2efc5d94687daea1eb6 100644 (file)
@@ -32,6 +32,8 @@ struct getl_source
     struct ll  ll;   /* Element in the sources list */
 
     struct getl_interface *interface;
     struct ll  ll;   /* Element in the sources list */
 
     struct getl_interface *interface;
+    enum syntax_mode syntax_mode;
+    enum error_mode error_mode;
   };
 
 struct source_stream
   };
 
 struct source_stream
@@ -54,6 +56,26 @@ current_source (const struct source_stream *ss)
   return ll_data (ll, struct getl_source, ll );
 }
 
   return ll_data (ll, struct getl_source, ll );
 }
 
+enum syntax_mode
+source_stream_current_syntax_mode (const struct source_stream *ss)
+{
+  struct getl_source *cs = current_source (ss);
+
+  return cs->syntax_mode;
+}
+
+
+
+enum error_mode
+source_stream_current_error_mode (const struct source_stream *ss)
+{
+  struct getl_source *cs = current_source (ss);
+
+  return cs->error_mode;
+}
+
+
+
 /* Initialize getl. */
 struct source_stream *
 create_source_stream (const char *initial_include_path)
 /* Initialize getl. */
 struct source_stream *
 create_source_stream (const char *initial_include_path)
@@ -88,18 +110,26 @@ getl_add_include_dir (struct source_stream *ss, const char *path)
 
 /* Appends source S to the list of source files. */
 void
 
 /* Appends source S to the list of source files. */
 void
-getl_append_source (struct source_stream *ss, struct getl_interface *i)
+getl_append_source (struct source_stream *ss,
+                   struct getl_interface *i,
+                   enum syntax_mode syntax_mode,
+                   enum error_mode err_mode)
 {
   struct getl_source *s = xzalloc (sizeof ( struct getl_source ));
 
   s->interface = i ;
 {
   struct getl_source *s = xzalloc (sizeof ( struct getl_source ));
 
   s->interface = i ;
+  s->syntax_mode = syntax_mode;
+  s->error_mode = err_mode;
 
   ll_push_tail (&ss->sources, &s->ll);
 }
 
 /* Nests source S within the current source file. */
 void
 
   ll_push_tail (&ss->sources, &s->ll);
 }
 
 /* Nests source S within the current source file. */
 void
-getl_include_source (struct source_stream *ss, struct getl_interface *i)
+getl_include_source (struct source_stream *ss,
+                    struct getl_interface *i,
+                    enum syntax_mode syntax_mode,
+                    enum error_mode err_mode)
 {
   struct getl_source *current = current_source (ss);
   struct getl_source *s = xzalloc (sizeof ( struct getl_source ));
 {
   struct getl_source *current = current_source (ss);
   struct getl_source *s = xzalloc (sizeof ( struct getl_source ));
@@ -108,6 +138,8 @@ getl_include_source (struct source_stream *ss, struct getl_interface *i)
 
   s->included_from = current ;
   s->includes  = NULL;
 
   s->included_from = current ;
   s->includes  = NULL;
+  s->syntax_mode  = syntax_mode;
+  s->error_mode = err_mode;
   current->includes = s;
 
   ll_push_head (&ss->sources, &s->ll);
   current->includes = s;
 
   ll_push_head (&ss->sources, &s->ll);
@@ -205,10 +237,9 @@ destroy_source_stream (struct source_stream *ss)
 
 /* Reads a single line into LINE.
    Returns true when a line has been read, false at end of input.
 
 /* Reads a single line into LINE.
    Returns true when a line has been read, false at end of input.
-   On success, sets *SYNTAX to the style of the syntax read. */
+*/
 bool
 bool
-getl_read_line (struct source_stream *ss, struct string *line,
-               enum getl_syntax *syntax)
+getl_read_line (struct source_stream *ss, struct string *line)
 {
   assert (ss != NULL);
   while (!ll_is_empty (&ss->sources))
 {
   assert (ss != NULL);
   while (!ll_is_empty (&ss->sources))
@@ -216,12 +247,12 @@ getl_read_line (struct source_stream *ss, struct string *line,
       struct getl_source *s = current_source (ss);
 
       ds_clear (line);
       struct getl_source *s = current_source (ss);
 
       ds_clear (line);
-      if (s->interface->read (s->interface, line, syntax))
+      if (s->interface->read (s->interface, line))
         {
           while (s)
            {
              if (s->interface->filter)
         {
           while (s)
            {
              if (s->interface->filter)
-               s->interface->filter (s->interface, line, *syntax);
+               s->interface->filter (s->interface, line);
              s = s->included_from;
            }
 
              s = s->included_from;
            }
 
index 26c0649cfe8da63c5f1a7704892a2356af0fc95e..c0399377982bf556ce588cabfcdf0b4cdd1e571e 100644 (file)
@@ -25,7 +25,7 @@ struct string;
 struct getl_source;
 
 /* Syntax rules that apply to a given source line. */
 struct getl_source;
 
 /* Syntax rules that apply to a given source line. */
-enum getl_syntax
+enum syntax_mode
   {
     /* Each line that begins in column 1 starts a new command.  A
        `+' or `-' in column 1 is ignored to allow visual
   {
     /* Each line that begins in column 1 starts a new command.  A
        `+' or `-' in column 1 is ignored to allow visual
@@ -38,6 +38,16 @@ enum getl_syntax
     GETL_INTERACTIVE
   };
 
     GETL_INTERACTIVE
   };
 
+enum error_mode
+  {
+    /* When errors are encountered, report the error and continue to
+       the next command. */
+    ERRMODE_CONTINUE,
+
+    /* When errors are encountered, abort the current stream. */
+    ERRMODE_STOP
+  };
+
 /* An abstract base class for objects which act as line buffers for the
    PSPP.  Ie anything which might contain content for the lexer */
 struct getl_interface
 /* An abstract base class for objects which act as line buffers for the
    PSPP.  Ie anything which might contain content for the lexer */
 struct getl_interface
@@ -51,7 +61,7 @@ struct getl_interface
        Returns true if succesful, false on failure or at end of
        input. */
     bool  (*read)  (struct getl_interface *,
        Returns true if succesful, false on failure or at end of
        input. */
     bool  (*read)  (struct getl_interface *,
-                    struct string *, enum getl_syntax *);
+                    struct string *);
 
     /* Close and destroy the interface */
     void  (*close) (struct getl_interface *);
 
     /* Close and destroy the interface */
     void  (*close) (struct getl_interface *);
@@ -59,7 +69,7 @@ struct getl_interface
     /* Filter for current and all included sources, which may
        modify the line.  Usually null.  */
     void  (*filter) (struct getl_interface *,
     /* Filter for current and all included sources, which may
        modify the line.  Usually null.  */
     void  (*filter) (struct getl_interface *,
-                     struct string *line, enum getl_syntax);
+                     struct string *line);
 
     /* Returns the name of the source */
     const char * (*name) (const struct getl_interface *);
 
     /* Returns the name of the source */
     const char * (*name) (const struct getl_interface *);
@@ -71,6 +81,15 @@ struct getl_interface
 struct source_stream;
 
 struct source_stream * create_source_stream (const char *);
 struct source_stream;
 
 struct source_stream * create_source_stream (const char *);
+
+enum syntax_mode source_stream_current_syntax_mode
+   (const struct source_stream *);
+
+
+enum error_mode source_stream_current_error_mode
+   (const struct source_stream *);
+
+
 void destroy_source_stream (struct source_stream *);
 
 void getl_clear_include_path (struct source_stream *);
 void destroy_source_stream (struct source_stream *);
 
 void getl_clear_include_path (struct source_stream *);
@@ -80,11 +99,13 @@ const char * getl_include_path (const struct source_stream *);
 void getl_abort_noninteractive (struct source_stream *);
 bool getl_is_interactive (const struct source_stream *);
 
 void getl_abort_noninteractive (struct source_stream *);
 bool getl_is_interactive (const struct source_stream *);
 
-bool getl_read_line (struct source_stream *, struct string *,
-                    enum getl_syntax *);
+bool getl_read_line (struct source_stream *, struct string *);
+
+void getl_append_source (struct source_stream *, struct getl_interface *s,
+                        enum syntax_mode, enum error_mode) ;
 
 
-void getl_append_source (struct source_stream *, struct getl_interface *s) ;
-void getl_include_source (struct source_stream *, struct getl_interface *s) ;
+void getl_include_source (struct source_stream *, struct getl_interface *s,
+                         enum syntax_mode, enum error_mode) ;
 
 const char * getl_source_name (const struct source_stream *);
 int getl_source_location (const struct source_stream *);
 
 const char * getl_source_name (const struct source_stream *);
 int getl_source_location (const struct source_stream *);
index 6259965aaf3abfdd168b30ca569471f5d0f5126a..1ca0df3e48dfd476fd33c1b5132c240774e50319 100644 (file)
@@ -178,7 +178,7 @@ execute_syntax (struct getl_interface *sss)
 
   lexer = lex_create (the_source_stream);
 
 
   lexer = lex_create (the_source_stream);
 
-  getl_append_source (the_source_stream, sss);
+  getl_append_source (the_source_stream, sss, GETL_BATCH, ERRMODE_CONTINUE);
 
   for (;;)
     {
 
   for (;;)
     {
index 1cee28886c2e04bfa6d6ff48040b72d6f58bf305..289bd37a0f5cd7537a0806f1a10ccfb40e935fb8 100644 (file)
@@ -67,8 +67,7 @@ location (const struct getl_interface *i)
 
 static bool
 read_line_from_buffer (struct getl_interface *i,
 
 static bool
 read_line_from_buffer (struct getl_interface *i,
-                      struct string *line,
-                      enum getl_syntax *syntax_rules)
+                      struct string *line)
 {
   gchar *text;
   GtkTextIter next_line;
 {
   gchar *text;
   GtkTextIter next_line;
index e152f7009992eb55ad6194bddb62d4efd323488e..1205d4d5a4954d05cdcbae134af38970caaa987c 100644 (file)
@@ -189,7 +189,11 @@ parse_command_line (int argc, char **argv, struct source_stream *ss)
       char *pspprc_fn = fn_search_path ("rc", config_path);
       if (pspprc_fn != NULL)
         {
       char *pspprc_fn = fn_search_path ("rc", config_path);
       if (pspprc_fn != NULL)
         {
-         getl_append_source (ss, create_syntax_file_source (pspprc_fn));
+         getl_append_source (ss,
+                             create_syntax_file_source (pspprc_fn),
+                             GETL_BATCH,
+                             ERRMODE_CONTINUE
+                             );
 
           free (pspprc_fn);
         }
 
           free (pspprc_fn);
         }
@@ -200,13 +204,20 @@ parse_command_line (int argc, char **argv, struct source_stream *ss)
       outp_configure_macro (argv[i]);
     else
       {
       outp_configure_macro (argv[i]);
     else
       {
-       getl_append_source (ss, create_syntax_file_source (argv[i]));
+       getl_append_source (ss,
+                           create_syntax_file_source (argv[i]),
+                           GETL_BATCH,
+                           ERRMODE_CONTINUE
+                           );
         syntax_files++;
       }
 
   if (!syntax_files || interactive_mode)
     {
         syntax_files++;
       }
 
   if (!syntax_files || interactive_mode)
     {
-      getl_append_source (ss, create_readln_source () );
+      getl_append_source (ss, create_readln_source (),
+                         GETL_INTERACTIVE,
+                         ERRMODE_CONTINUE
+                         );
       if (!cleared_device_defaults)
         outp_configure_add ("interactive");
     }
       if (!cleared_device_defaults)
         outp_configure_add ("interactive");
     }
index 2529dee40b29ac1732a9292c9c54e8c95bc196ec..626b06353392f75c6941c6e1ac1e30f6096a0ef2 100644 (file)
@@ -101,12 +101,11 @@ readln_uninitialize (void)
 
 static bool
 read_interactive (struct getl_interface *s,
 
 static bool
 read_interactive (struct getl_interface *s,
-                  struct string *line, enum getl_syntax *syntax)
+                  struct string *line)
 {
   struct readln_source *is  =
     (struct readln_source *) s ;
 
 {
   struct readln_source *is  =
     (struct readln_source *) s ;
 
-  *syntax = GETL_INTERACTIVE;
   return is->interactive_func (line, prompt_get_style ());
 }
 
   return is->interactive_func (line, prompt_get_style ());
 }
 
index a67be09c553bb0b3b4dafbad4c1002836ab446a5..d2648e5336abe11504fbe28775a2be71ee59ad1b 100644 (file)
@@ -20,6 +20,7 @@ dist_TESTS = \
        tests/command/filter.sh \
        tests/command/flip.sh \
        tests/command/import-export.sh \
        tests/command/filter.sh \
        tests/command/flip.sh \
        tests/command/import-export.sh \
+       tests/command/insert.sh \
        tests/command/lag.sh \
        tests/command/list.sh \
        tests/command/loop.sh \
        tests/command/lag.sh \
        tests/command/list.sh \
        tests/command/loop.sh \
diff --git a/tests/command/insert.sh b/tests/command/insert.sh
new file mode 100755 (executable)
index 0000000..ba4f543
--- /dev/null
@@ -0,0 +1,253 @@
+#!/bin/sh
+
+# This program tests the INSERT command
+
+TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
+
+# ensure that top_srcdir and top_builddir  are absolute
+if [ -z "$top_srcdir" ] ; then top_srcdir=. ; fi
+if [ -z "$top_builddir" ] ; then top_builddir=. ; fi
+top_srcdir=`cd $top_srcdir; pwd`
+top_builddir=`cd $top_builddir; pwd`
+
+PSPP=$top_builddir/src/ui/terminal/pspp
+
+STAT_CONFIG_PATH=$top_srcdir/config
+export STAT_CONFIG_PATH
+
+LANG=C
+export LANG
+
+
+cleanup()
+{
+     if [ x"$PSPP_TEST_NO_CLEANUP" != x ] ; then 
+       echo "NOT cleaning $TEMPDIR"
+       return ; 
+     fi
+     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 wrapper 1"
+cat <<EOF > $TESTFILE
+INSERT 
+  FILE='$TEMPDIR/foo.sps'
+  SYNTAX=INTERACTIVE
+  .
+
+
+LIST.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+#The following syntax intentionally omits periods from some lines
+#It's an example of "batch" syntax
+activity="create insert"
+cat <<EOF > $TEMPDIR/foo.sps
+input program.
++  loop #i = 1 to 100.
++    compute z = #i
++    end case.
++  end loop
+end file.
+end input program.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+#This command should fail
+activity="run program 1"
+$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE > /dev/null
+if [ $? -eq 0 ] ; then fail ; fi
+
+
+activity="create wrapper 2"
+cat <<EOF > $TESTFILE
+INSERT 
+  FILE='$TEMPDIR/foo.sps'
+  SYNTAX=BATCH
+  .
+
+
+LIST.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="run program 2"
+$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+# Now test the CD subcommand
+
+activity="mkdir 1"
+mkdir $TEMPDIR/Dir1
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="create wrapper 3"
+cat <<EOF > $TESTFILE
+INSERT 
+  FILE='$TEMPDIR/Dir1/foo.sps'
+  CD=NO
+  .
+
+
+LIST.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="create wrapper 4"
+cat <<EOF > $TEMPDIR/Dir1/foo.sps
+INSERT 
+  FILE='bar.sps'
+  CD=NO
+  .
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="create wrapper 5"
+cat <<EOF > $TEMPDIR/Dir1/bar.sps
+DATA LIST LIST /x *.
+BEGIN DATA.
+1
+2
+3
+END DATA.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+# This command should fail
+activity="run program 3"
+$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE > /dev/null
+if [ $? -eq 0 ] ; then fail ; fi
+
+activity="create wrapper 6"
+cat <<EOF > $TESTFILE
+INSERT 
+  FILE='$TEMPDIR/Dir1/foo.sps'
+  CD=YES
+  .
+
+LIST.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="run program 4"
+$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+# Now test the ERROR= feature
+
+activity="create wrapper 7"
+cat <<EOF > $TESTFILE
+INSERT 
+  FILE='$TEMPDIR/foo.sps'
+  ERROR=STOP.
+  .
+
+LIST.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="create included file"
+cat <<EOF > $TEMPDIR/foo.sps
+DATA LIST NOTABLE LIST /x *.
+BEGIN DATA.
+1
+2
+3
+END DATA.
+
+* The following line is erroneous
+
+DISPLAY AKSDJ.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="run program 5"
+$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE > /dev/null
+if [ $? -ne 1 ] ; then no_result ; fi
+
+activity="examine output 1"
+diff $TEMPDIR/pspp.list - <<EOF
+$TEMPDIR/foo.sps:10: error: DISPLAY: AKSDJ is not a variable name.
+warning: Error encountered while ERROR=STOP is effective.
+$TEMPDIR/foo.sps:10: error: Stopping syntax file processing here to avoid a cascade of dependent command failures.
+
+EOF
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+activity="create wrapper 8"
+cat <<EOF > $TESTFILE
+INSERT 
+  FILE='$TEMPDIR/foo.sps'
+  ERROR=CONTINUE.
+  .
+
+LIST.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="run program 6"
+$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE > /dev/null
+if [ $? -ne 1 ] ; then no_result ; fi
+
+activity="examine output 2"
+diff $TEMPDIR/pspp.list - <<EOF
+$TEMPDIR/foo.sps:10: error: DISPLAY: AKSDJ is not a variable name.
+
+       x
+--------
+    1.00 
+    2.00 
+    3.00 
+
+EOF
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+
+pass;