From: John Darrington Date: Wed, 5 Sep 2007 06:23:01 +0000 (+0000) Subject: Implemented the INSERT command. X-Git-Tag: v0.6.0~283 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp-builds.git;a=commitdiff_plain;h=68f08c4bb53fcde16035b622bdb6e9529f9cf3ae Implemented the INSERT command. --- diff --git a/doc/language.texi b/doc/language.texi index 398f7642..13454336 100644 --- a/doc/language.texi +++ b/doc/language.texi @@ -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. +* 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. @@ -24,6 +25,7 @@ Later chapters will describe individual commands in detail. * BNF:: How command syntax is described. @end menu + @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}). -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 diff --git a/doc/utilities.texi b/doc/utilities.texi index ba5a5e8b..94fa5074 100644 --- a/doc/utilities.texi +++ b/doc/utilities.texi @@ -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. +* INSERT:: Insert a file within the current one. * 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 -@vindex @@ @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. - +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. + +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 -@comment node-name, next, previous, up @section PERMISSIONS @vindex PERMISSIONS @cindex mode diff --git a/po/de.po b/po/de.po index c92f367f..cad53f8a 100644 --- 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" -"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 \n" "Language-Team: German \n" @@ -988,41 +988,41 @@ 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 "" -#: src/language/control/repeat.c:173 +#: src/language/control/repeat.c:178 #, 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 "" -#: src/language/control/repeat.c:331 +#: src/language/control/repeat.c:336 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 "" -#: src/language/control/repeat.c:442 +#: src/language/control/repeat.c:447 #, 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 "" -#: src/language/control/repeat.c:496 +#: src/language/control/repeat.c:501 msgid "No matching DO REPEAT." msgstr "" @@ -1411,7 +1411,7 @@ msgid_plural "Writing %d records." 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 "" @@ -1828,11 +1828,11 @@ msgid "" "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 "" -#: 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 "" @@ -2079,89 +2079,89 @@ 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 "" -#: src/language/lexer/lexer.c:374 +#: src/language/lexer/lexer.c:381 #, 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 "" -#: src/language/lexer/lexer.c:412 +#: src/language/lexer/lexer.c:419 #, 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 "" -#: src/language/lexer/lexer.c:449 +#: src/language/lexer/lexer.c:456 #, 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 "" -#: 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 "" -#: src/language/lexer/lexer.c:635 +#: src/language/lexer/lexer.c:642 msgid "expecting number" msgstr "" -#: src/language/lexer/lexer.c:647 +#: src/language/lexer/lexer.c:654 msgid "expecting identifier" msgstr "" -#: src/language/lexer/lexer.c:1045 +#: src/language/lexer/lexer.c:1048 msgid "binary" msgstr "" -#: src/language/lexer/lexer.c:1050 +#: src/language/lexer/lexer.c:1053 msgid "octal" msgstr "" -#: src/language/lexer/lexer.c:1055 +#: src/language/lexer/lexer.c:1058 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 "" -#: src/language/lexer/lexer.c:1094 +#: src/language/lexer/lexer.c:1097 #, 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 "" -#: src/language/lexer/lexer.c:1182 +#: src/language/lexer/lexer.c:1185 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 "" -#: src/language/lexer/lexer.c:1203 +#: src/language/lexer/lexer.c:1206 #, c-format msgid "String exceeds 255 characters in length (%d characters)." msgstr "" @@ -3494,7 +3494,7 @@ 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 "" @@ -3550,15 +3550,32 @@ 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 "" -#: 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 "" +#: 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." @@ -5280,7 +5297,7 @@ msgstr "" 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" @@ -5326,7 +5343,7 @@ msgid "" "\n" msgstr "" -#: src/ui/terminal/command-line.c:254 +#: src/ui/terminal/command-line.c:258 #, c-format msgid "" "\n" diff --git a/po/pspp.pot b/po/pspp.pot index 5123ff96..148a959c 100644 --- a/po/pspp.pot +++ b/po/pspp.pot @@ -8,7 +8,7 @@ msgid "" 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 \n" "Language-Team: LANGUAGE \n" @@ -982,41 +982,41 @@ 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 "" -#: src/language/control/repeat.c:173 +#: src/language/control/repeat.c:178 #, 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 "" -#: src/language/control/repeat.c:331 +#: src/language/control/repeat.c:336 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 "" -#: src/language/control/repeat.c:442 +#: src/language/control/repeat.c:447 #, 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 "" -#: src/language/control/repeat.c:496 +#: src/language/control/repeat.c:501 msgid "No matching DO REPEAT." msgstr "" @@ -1405,7 +1405,7 @@ msgid_plural "Writing %d records." 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 "" @@ -1822,11 +1822,11 @@ msgid "" "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 "" -#: 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 "" @@ -2073,89 +2073,89 @@ 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 "" -#: src/language/lexer/lexer.c:374 +#: src/language/lexer/lexer.c:381 #, 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 "" -#: src/language/lexer/lexer.c:412 +#: src/language/lexer/lexer.c:419 #, 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 "" -#: src/language/lexer/lexer.c:449 +#: src/language/lexer/lexer.c:456 #, 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 "" -#: 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 "" -#: src/language/lexer/lexer.c:635 +#: src/language/lexer/lexer.c:642 msgid "expecting number" msgstr "" -#: src/language/lexer/lexer.c:647 +#: src/language/lexer/lexer.c:654 msgid "expecting identifier" msgstr "" -#: src/language/lexer/lexer.c:1045 +#: src/language/lexer/lexer.c:1048 msgid "binary" msgstr "" -#: src/language/lexer/lexer.c:1050 +#: src/language/lexer/lexer.c:1053 msgid "octal" msgstr "" -#: src/language/lexer/lexer.c:1055 +#: src/language/lexer/lexer.c:1058 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 "" -#: src/language/lexer/lexer.c:1094 +#: src/language/lexer/lexer.c:1097 #, 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 "" -#: src/language/lexer/lexer.c:1182 +#: src/language/lexer/lexer.c:1185 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 "" -#: src/language/lexer/lexer.c:1203 +#: src/language/lexer/lexer.c:1206 #, c-format msgid "String exceeds 255 characters in length (%d characters)." msgstr "" @@ -3487,7 +3487,7 @@ 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 "" @@ -3543,15 +3543,32 @@ 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 "" -#: 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 "" +#: 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." @@ -5225,7 +5242,7 @@ 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" @@ -5271,7 +5288,7 @@ msgid "" "\n" msgstr "" -#: src/ui/terminal/command-line.c:254 +#: src/ui/terminal/command-line.c:258 #, c-format msgid "" "\n" diff --git a/src/language/ChangeLog b/src/language/ChangeLog index 8949ff75..d25c2d03 100644 --- a/src/language/ChangeLog +++ b/src/language/ChangeLog @@ -1,3 +1,10 @@ +2007-09-05 John Darrington + + * 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 * command.def: Add DEBUG DATASHEET command. Remove DEBUG CASEFILE diff --git a/src/language/command.c b/src/language/command.c index 40b8505e..1688a10e 100644 --- a/src/language/command.c +++ b/src/language/command.c @@ -39,6 +39,7 @@ #include #include #include +#include #if HAVE_SYS_WAIT_H #include @@ -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 -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; @@ -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) - return CMD_EOF; + { + result = CMD_EOF; + goto finish; + } 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) - return CMD_FAILURE; + { + result = CMD_FAILURE; + goto finish; + } 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); - 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); - return CMD_FAILURE; + result = CMD_FAILURE; + goto finish; } else if (!in_correct_state (command, state)) { report_state_mismatch (command, state); - return CMD_FAILURE; + result = CMD_FAILURE; + goto finish; } /* 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)); + + 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; } diff --git a/src/language/command.def b/src/language/command.def index 5967e5d2..7a89ae0a 100644 --- a/src/language/command.def +++ b/src/language/command.def @@ -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, "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) diff --git a/src/language/control/repeat.c b/src/language/control/repeat.c index ede37016..cd56d7c8 100644 --- a/src/language/control/repeat.c +++ b/src/language/control/repeat.c @@ -49,7 +49,6 @@ struct repeat_line 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. */ @@ -103,9 +102,9 @@ static int parse_strings (struct lexer *, struct repeat_macro *, 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 *, - 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 *); @@ -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)) - 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); @@ -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; - enum getl_syntax syntax; 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)); @@ -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->syntax = syntax; + /* 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))) @@ -510,7 +513,7 @@ find_substitution (struct repeat_block *block, struct substring name) 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; @@ -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, - struct string *output, enum getl_syntax *syntax) + struct string *output) { 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); - *syntax = line->syntax; return true; } diff --git a/src/language/data-io/data-reader.c b/src/language/data-io/data-reader.c index c752587b..7176aed4 100644 --- a/src/language/data-io/data-reader.c +++ b/src/language/data-io/data-reader.c @@ -170,7 +170,7 @@ read_inline_record (struct dfm_reader *r) 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 " diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index 4e10ec22..71597302 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -43,6 +43,7 @@ #define DUMP_TOKENS 0 + struct lexer { struct string line_buffer; @@ -108,6 +109,18 @@ lex_get_source_stream (const struct lexer *lex) 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) @@ -832,7 +845,7 @@ strip_comments (struct string *string) *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) { @@ -854,15 +867,11 @@ lex_preprocess_line (struct string *line, 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; } @@ -874,15 +883,15 @@ bool 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; } - 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) diff --git a/src/language/lexer/lexer.h b/src/language/lexer/lexer.h index 44be0e93..ada09ade 100644 --- a/src/language/lexer/lexer.h +++ b/src/language/lexer/lexer.h @@ -30,8 +30,10 @@ 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 *); - +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 *); @@ -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 *); -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 *); @@ -79,7 +81,7 @@ void lex_discard_rest_of_command (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); diff --git a/src/language/syntax-file.c b/src/language/syntax-file.c index b3ae6f4a..dde807c3 100644 --- a/src/language/syntax-file.c +++ b/src/language/syntax-file.c @@ -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. */ -bool +static bool 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; @@ -112,7 +112,6 @@ read_syntax_file (struct getl_interface *s, if (get_echo ()) tab_output_text (TAB_LEFT | TAB_FIX, ds_cstr (line)); - *syntax = GETL_BATCH; return true; } diff --git a/src/language/syntax-file.h b/src/language/syntax-file.h index c038a432..8044f3c0 100644 --- a/src/language/syntax-file.h +++ b/src/language/syntax-file.h @@ -17,15 +17,9 @@ #if !SYNTAX_FILE #define SYNTAX_FILE 1 -#include -#include - -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. */ -struct getl_interface * create_syntax_file_source (const char *fn) ; +struct getl_interface * create_syntax_file_source (const char *) ; #endif diff --git a/src/language/syntax-string-source.c b/src/language/syntax-string-source.c index bcdcbd37..f80bca2e 100644 --- a/src/language/syntax-string-source.c +++ b/src/language/syntax-string-source.c @@ -70,8 +70,7 @@ do_close (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; diff --git a/src/language/utilities/include.c b/src/language/utilities/include.c index 0ef9d463..26c718a4 100644 --- a/src/language/utilities/include.c +++ b/src/language/utilities/include.c @@ -1,5 +1,5 @@ /* 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 @@ -25,17 +25,147 @@ #include #include #include +#include +#include #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) { - 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 *relative_filename; /* 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")); - return CMD_CASCADING_FAILURE; + return CMD_FAILURE; } 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); + return CMD_FAILURE; + } - lex_get (lexer); - return lex_end_of_command (lexer); + *filename = canonicalize_file_name (relative_filename); + free (relative_filename); + + return CMD_SUCCESS; } diff --git a/src/libpspp/ChangeLog b/src/libpspp/ChangeLog index 6f3ddf51..9c1b654d 100644 --- a/src/libpspp/ChangeLog +++ b/src/libpspp/ChangeLog @@ -1,3 +1,8 @@ +2007-09-05 John Darrington + + * getl.c: Add extra members to struct getl_source, to maintain the + error mode and the syntax_mode. + 2007-07-25 Ben Pfaff * getl.c (getl_append_source): Add source to *end* of list. diff --git a/src/libpspp/getl.c b/src/libpspp/getl.c index b4617122..4d6338ce 100644 --- a/src/libpspp/getl.c +++ b/src/libpspp/getl.c @@ -32,6 +32,8 @@ struct getl_source 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 @@ -54,6 +56,26 @@ current_source (const struct source_stream *ss) 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) @@ -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 -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 ; + 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 -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 )); @@ -108,6 +138,8 @@ getl_include_source (struct source_stream *ss, struct getl_interface *i) 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); @@ -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. - On success, sets *SYNTAX to the style of the syntax read. */ +*/ 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)) @@ -216,12 +247,12 @@ getl_read_line (struct source_stream *ss, struct string *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) - s->interface->filter (s->interface, line, *syntax); + s->interface->filter (s->interface, line); s = s->included_from; } diff --git a/src/libpspp/getl.h b/src/libpspp/getl.h index 26c0649c..c0399377 100644 --- a/src/libpspp/getl.h +++ b/src/libpspp/getl.h @@ -25,7 +25,7 @@ struct string; 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 @@ -38,6 +38,16 @@ enum getl_syntax 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 @@ -51,7 +61,7 @@ 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 *); @@ -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 *, - struct string *line, enum getl_syntax); + struct string *line); /* 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 *); + +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 *); @@ -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 *); -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 *); diff --git a/src/ui/gui/helper.c b/src/ui/gui/helper.c index 6259965a..1ca0df3e 100644 --- a/src/ui/gui/helper.c +++ b/src/ui/gui/helper.c @@ -178,7 +178,7 @@ execute_syntax (struct getl_interface *sss) 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 (;;) { diff --git a/src/ui/gui/syntax-editor-source.c b/src/ui/gui/syntax-editor-source.c index 1cee2888..289bd37a 100644 --- a/src/ui/gui/syntax-editor-source.c +++ b/src/ui/gui/syntax-editor-source.c @@ -67,8 +67,7 @@ location (const 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; diff --git a/src/ui/terminal/command-line.c b/src/ui/terminal/command-line.c index e152f700..1205d4d5 100644 --- a/src/ui/terminal/command-line.c +++ b/src/ui/terminal/command-line.c @@ -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) { - 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); } @@ -200,13 +204,20 @@ parse_command_line (int argc, char **argv, struct source_stream *ss) 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) { - 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"); } diff --git a/src/ui/terminal/read-line.c b/src/ui/terminal/read-line.c index 2529dee4..626b0635 100644 --- a/src/ui/terminal/read-line.c +++ b/src/ui/terminal/read-line.c @@ -101,12 +101,11 @@ readln_uninitialize (void) 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 ; - *syntax = GETL_INTERACTIVE; return is->interactive_func (line, prompt_get_style ()); } diff --git a/tests/automake.mk b/tests/automake.mk index a67be09c..d2648e53 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -20,6 +20,7 @@ dist_TESTS = \ 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 \ diff --git a/tests/command/insert.sh b/tests/command/insert.sh new file mode 100755 index 00000000..ba4f543a --- /dev/null +++ b/tests/command/insert.sh @@ -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 < $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 < $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 < $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 < $TESTFILE +INSERT + FILE='$TEMPDIR/Dir1/foo.sps' + CD=NO + . + + +LIST. + +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="create wrapper 4" +cat < $TEMPDIR/Dir1/foo.sps +INSERT + FILE='bar.sps' + CD=NO + . + +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="create wrapper 5" +cat < $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 < $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 < $TESTFILE +INSERT + FILE='$TEMPDIR/foo.sps' + ERROR=STOP. + . + +LIST. + +EOF +if [ $? -ne 0 ] ; then no_result ; fi + + +activity="create included file" +cat < $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 - < $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 - <