@code{F@i{width}.0} format.
@item
-@code{FORMAT=@i{count}F} divides the input area into @i{count}
+@code{FORMAT="@i{count}F"} divides the input area into integer @i{count}
equal-width fields per line. The input area must be a multiple of
@i{count} columns wide. Another format type may be substituted for
@code{F}.
masks. */
enum dict_class
{
- DC_ORDINARY = 0x0001, /* Ordinary identifier. */
- DC_SYSTEM = 0x0002, /* System variable. */
- DC_SCRATCH = 0x0004, /* Scratch variable. */
- DC_ALL = 0x0007 /* All of the above. */
+ DC_ORDINARY = 1 << 0, /* Ordinary identifier. */
+ DC_SYSTEM = 1 << 1, /* System variable. */
+ DC_SCRATCH = 1 << 2, /* Scratch variable. */
+#define DC_ALL (DC_ORDINARY | DC_SYSTEM | DC_SCRATCH)
};
enum dict_class dict_class_from_id (const char *name);
r->line_length = 0;
}
if (c == EOF)
- error (r, _("unexpected end of file"));
+ error (r, _("Unexpected end of file"));
if (r->trans != NULL)
c = r->trans[c];
static const size_t n_commands = sizeof commands / sizeof *commands;
static bool in_correct_state (const struct command *, enum cmd_state);
-static void report_state_mismatch (const struct command *, enum cmd_state);
+static char *report_state_mismatch (const struct command *, enum cmd_state);
static void set_completion_state (enum cmd_state);
\f
/* Command parser. */
utf8_to_title (command->name),
utf8_to_title (command->name)));
+ int end = n_tokens - 1;
if (command->function == NULL)
{
- msg (SE, _("%s is not yet implemented."), command->name);
+ lex_ofs_error (lexer, 0, end, _("%s is not yet implemented."),
+ command->name);
result = CMD_NOT_IMPLEMENTED;
}
else if ((command->flags & F_TESTING) && !settings_get_testing_mode ())
{
- msg (SE, _("%s may be used only in testing mode."), command->name);
+ lex_ofs_error (lexer, 0, end, _("%s may be used only in testing mode."),
+ command->name);
result = CMD_FAILURE;
}
else if ((command->flags & F_ENHANCED) && settings_get_syntax () != ENHANCED)
{
- msg (SE, _("%s may be used only in enhanced syntax mode."),
- command->name);
+ lex_ofs_error (lexer, 0, end,
+ _("%s may be used only in enhanced syntax mode."),
+ command->name);
result = CMD_FAILURE;
}
else if (!in_correct_state (command, state))
{
- report_state_mismatch (command, state);
+ char *message = report_state_mismatch (command, state);
+ lex_ofs_error (lexer, 0, end, "%s", message);
+ free (message);
+
result = CMD_FAILURE;
}
else
ds_truncate (&s, ds_length (&s) - 2);
}
+ *n_tokens = (word + 1) + missing_words;
if (command == NULL)
{
if (ds_is_empty (&s))
- lex_error (lexer, _("expecting command name"));
+ lex_error (lexer, _("Syntax error expecting command name."));
else
- msg (SE, _("Unknown command `%s'."), ds_cstr (&s));
+ lex_ofs_error (lexer, 0, *n_tokens - 1,
+ _("Unknown command `%s'."), ds_cstr (&s));
}
ds_destroy (&s);
- *n_tokens = (word + 1) + missing_words;
return command;
}
return command->states & (1 << state);
}
-/* Emits an appropriate error message for trying to invoke
+/* Returns an appropriate error message for trying to invoke
COMMAND in STATE. */
-static void
+static char *
report_state_mismatch (const struct command *command, enum cmd_state state)
{
assert (!in_correct_state (command, state));
{
/* One allowed state. */
case S_INITIAL:
- msg (SE, _("%s is allowed only before the active dataset has "
- "been defined."), command->name);
- break;
+ return xasprintf (_("%s is allowed only before the active dataset has "
+ "been defined."), command->name);
case S_DATA:
- msg (SE, _("%s is allowed only after the active dataset has "
- "been defined."), command->name);
- break;
+ return xasprintf (_("%s is allowed only after the active dataset has "
+ "been defined."), command->name);
case S_INPUT_PROGRAM:
- msg (SE, _("%s is allowed only inside %s."),
- command->name, "INPUT PROGRAM");
- break;
+ return xasprintf (_("%s is allowed only inside %s."),
+ command->name, "INPUT PROGRAM");
case S_FILE_TYPE:
- msg (SE, _("%s is allowed only inside %s."), command->name, "FILE TYPE");
- break;
+ return xasprintf (_("%s is allowed only inside %s."), command->name, "FILE TYPE");
/* Two allowed states. */
case S_INITIAL | S_DATA:
NOT_REACHED ();
case S_INITIAL | S_INPUT_PROGRAM:
- msg (SE, _("%s is allowed only before the active dataset has been defined or inside %s."),
- command->name, "INPUT PROGRAM");
- break;
+ return xasprintf (_("%s is allowed only before the active dataset "
+ "has been defined or inside %s."),
+ command->name, "INPUT PROGRAM");
case S_INITIAL | S_FILE_TYPE:
- msg (SE, _("%s is allowed only before the active dataset has been defined or inside %s."),
- command->name, "FILE TYPE");
- break;
+ return xasprintf (_("%s is allowed only before the active dataset "
+ "has been defined or inside %s."),
+ command->name, "FILE TYPE");
case S_DATA | S_INPUT_PROGRAM:
- msg (SE, _("%s is allowed only after the active dataset has been defined or inside %s."),
- command->name, "INPUT PROGRAM");
- break;
+ return xasprintf (_("%s is allowed only after the active dataset "
+ "has been defined or inside %s."),
+ command->name, "INPUT PROGRAM");
case S_DATA | S_FILE_TYPE:
- msg (SE, _("%s is allowed only after the active dataset has been defined or inside %s."),
- command->name, "FILE TYPE");
- break;
+ return xasprintf (_("%s is allowed only after the active dataset "
+ "has been defined or inside %s."),
+ command->name, "FILE TYPE");
case S_INPUT_PROGRAM | S_FILE_TYPE:
- msg (SE, _("%s is allowed only inside %s or inside %s."), command->name,
- "INPUT PROGRAM", "FILE TYPE");
- break;
+ return xasprintf (_("%s is allowed only inside %s or inside %s."),
+ command->name, "INPUT PROGRAM", "FILE TYPE");
/* Three allowed states. */
case S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE:
- msg (SE, _("%s is allowed only after the active dataset has "
- "been defined, inside INPUT PROGRAM, or inside "
- "FILE TYPE."), command->name);
- break;
+ return xasprintf (_("%s is allowed only after the active dataset has "
+ "been defined, inside INPUT PROGRAM, or inside "
+ "FILE TYPE."), command->name);
case S_INITIAL | S_INPUT_PROGRAM | S_FILE_TYPE:
- msg (SE, _("%s is allowed only before the active dataset has "
- "been defined, inside INPUT PROGRAM, or inside "
- "FILE TYPE."), command->name);
- break;
+ return xasprintf (_("%s is allowed only before the active dataset "
+ "has been defined, inside INPUT PROGRAM, or "
+ "inside FILE TYPE."), command->name);
case S_INITIAL | S_DATA | S_FILE_TYPE:
NOT_REACHED ();
case S_INITIAL | S_DATA | S_INPUT_PROGRAM:
break;
case CMD_STATE_INPUT_PROGRAM:
- msg (SE, _("%s is not allowed inside %s."),
- command->name, "INPUT PROGRAM");
- break;
+ return xasprintf (_("%s is not allowed inside %s."),
+ command->name, "INPUT PROGRAM");
case CMD_STATE_FILE_TYPE:
- msg (SE, _("%s is not allowed inside %s."), command->name, "FILE TYPE");
- break;
+ return xasprintf (_("%s is not allowed inside %s."),
+ command->name, "FILE TYPE");
case CMD_STATE_NESTED_DATA:
case CMD_STATE_NESTED_INPUT_PROGRAM:
switch ((int) command->states & S_NESTED_ANY)
{
case 0:
- msg (SE, _("%s is not allowed inside DO IF or LOOP."), command->name);
- break;
+ return xasprintf (_("%s is not allowed inside DO IF or LOOP."),
+ command->name);
case S_NESTED_DATA:
- msg (SE, _("In INPUT PROGRAM, "
- "%s is not allowed inside DO IF or LOOP."), command->name);
- break;
+ return xasprintf (_("In INPUT PROGRAM, "
+ "%s is not allowed inside DO IF or LOOP."),
+ command->name);
default:
NOT_REACHED ();
}
- break;
}
+
+ NOT_REACHED ();
}
\f
/* Command name completion. */
{
if (*saw_arg_type)
{
- lex_error (lexer, _("Only one of !TOKENS, !CHAREND, !ENCLOSE, or "
- "!CMDEND is allowed."));
+ lex_next_error (lexer, -1, -1,
+ _("Only one of !TOKENS, !CHAREND, !ENCLOSE, or "
+ "!CMDEND is allowed."));
return false;
}
else
macro-expanded. */
if (lex_token (lexer) != T_STRING)
{
- lex_error (lexer, _("expecting identifier"));
+ lex_error (lexer, _("Syntax error expecting identifier."));
return CMD_FAILURE;
}
const char *name = lex_tokcstr (lexer);
if (!id_is_plausible (name + (name[0] == '!'), false))
{
- lex_error (lexer, _("expecting identifier"));
+ lex_error (lexer, _("Syntax error expecting identifier."));
return CMD_FAILURE;
}
goto error;
size_t allocated_params = 0;
+ int keyword_ofs = 0;
while (!lex_match (lexer, T_RPAREN))
{
if (m->n_params >= allocated_params)
{
if (param_index > 0 && !m->params[param_index - 1].positional)
{
- lex_error (lexer, _("Positional parameters must precede "
- "keyword parameters."));
+ lex_next_error (lexer, -1, -1,
+ _("Positional parameters must precede "
+ "keyword parameters."));
+ lex_ofs_msg (lexer, SN, keyword_ofs, keyword_ofs,
+ _("Here is a previous keyword parameter."));
goto error;
}
}
else
{
+ if (keyword_ofs == 0)
+ keyword_ofs = lex_ofs (lexer);
if (lex_token (lexer) == T_MACRO_ID)
{
lex_error (lexer, _("Keyword macro parameter must be named in "
{
if (saw_default)
{
- lex_error (lexer,
- _("!DEFAULT is allowed only once per argument."));
+ lex_next_error (
+ lexer, -1, -1,
+ _("!DEFAULT is allowed only once per argument."));
goto error;
}
saw_default = true;
{
if (lex_token (lexer) != T_STRING)
{
- lex_error (lexer, _("Expecting macro body or !ENDDEFINE"));
+ lex_error (lexer,
+ _("Syntax error expecting macro body or !ENDDEFINE."));
ds_destroy (&body);
goto error;
}
&& !do_if->clauses[do_if->n_clauses - 1].condition)
{
if (condition)
- msg (SE, _("ELSE IF is not allowed following ELSE "
- "within DO IF...END IF."));
+ lex_ofs_error (lexer, 0, 1,
+ _("ELSE IF is not allowed following ELSE "
+ "within DO IF...END IF."));
else
- msg (SE, _("Only one ELSE is allowed within DO IF...END IF."));
+ lex_ofs_error (lexer, 0, 0,
+ _("Only one ELSE is allowed within DO IF...END IF."));
msg_at (SN, do_if->clauses[do_if->n_clauses - 1].location,
_("This is the location of the previous ELSE clause."));
{
if (*condition != NULL)
{
- lex_sbc_only_once ("IF");
+ lex_sbc_only_once (lexer, "IF");
return false;
}
if (*e != NULL)
{
- lex_sbc_only_once (e == &loop->last_expr ? "TO" : "BY");
+ lex_sbc_only_once (lexer, e == &loop->last_expr ? "TO" : "BY");
return false;
}
*e = expr_parse (lexer, ds, VAL_NUMERIC);
size_t name_len = strlen (name);
if (find_dummy_var (dummies, name, name_len))
{
- msg (SE, _("Dummy variable name `%s' is given twice."), name);
+ lex_error (lexer, _("Dummy variable name `%s' is given twice."),
+ name);
goto error;
}
{
if (!lex_is_integer (lexer))
{
- msg (SE, _("Ranges may only have integer bounds."));
+ lex_error (lexer, _("Ranges may only have integer bounds."));
return false;
}
long b = lex_integer (lexer);
if (b < a)
{
- msg (SE, _("%ld TO %ld is an invalid range."), a, b);
+ lex_next_error (lexer, -2, 0,
+ _("%ld TO %ld is an invalid range."), a, b);
return false;
}
lex_get (lexer);
/* Parses the TEMPORARY command. */
int
-cmd_temporary (struct lexer *lexer UNUSED, struct dataset *ds)
+cmd_temporary (struct lexer *lexer, struct dataset *ds)
{
if (!proc_in_temporary_transformations (ds))
proc_start_temporary_transformations (ds);
else
- msg (SE, _("This command may only appear once between "
- "procedures and procedure-like commands."));
+ lex_ofs_error (lexer, 0, 0,
+ _("This command may only appear once between "
+ "procedures and procedure-like commands."));
return CMD_SUCCESS;
}
{
if (!dataset_has_source (ds))
{
- msg (SE, _("Cannot specify the active dataset since none "
- "has been defined."));
+ lex_next_error (lexer, -1, -1,
+ _("Cannot specify the active dataset since none "
+ "has been defined."));
goto error;
}
if (proc_make_temporary_transformations_permanent (ds))
- msg (SE, _("This command may not be used after TEMPORARY when "
- "the active dataset is an input source. "
- "Temporary transformations will be made permanent."));
+ lex_next_error (lexer, -1, -1,
+ _("This command may not be used after TEMPORARY "
+ "when the active dataset is an input source. "
+ "Temporary transformations will be made "
+ "permanent."));
file->dict = dict_clone (dataset_dict (ds));
}
else if (lex_match_id (lexer, "IN"))
{
lex_match (lexer, T_EQUALS);
- if (lex_token (lexer) != T_ID)
- {
- lex_error (lexer, NULL);
- goto error;
- }
+ if (!lex_force_id (lexer))
+ goto error;
if (file->in_name)
{
- msg (SE, _("Multiple IN subcommands for a single FILE or "
- "TABLE."));
+ lex_error (lexer, _("Multiple IN subcommands for a single FILE "
+ "or TABLE."));
goto error;
}
file->in_name = xstrdup (lex_tokcstr (lexer));
if (saw_by)
{
- lex_sbc_only_once ("BY");
+ lex_sbc_only_once (lexer, "BY");
goto error;
}
saw_by = true;
{
if (first_name != NULL)
{
- lex_sbc_only_once ("FIRST");
+ lex_sbc_only_once (lexer, "FIRST");
goto error;
}
{
if (last_name != NULL)
{
- lex_sbc_only_once ("LAST");
+ lex_sbc_only_once (lexer, "LAST");
goto error;
}
{
if (data_parser_get_records (parser) > 0)
{
- lex_sbc_only_once ("RECORDS");
+ lex_sbc_only_once (lexer, "RECORDS");
goto error;
}
lex_match (lexer, T_EQUALS);
{
if (!in_input_program ())
{
- msg (SE, _("The %s subcommand may only be used within %s."), "END", "INPUT PROGRAM");
+ lex_next_error (lexer, -1, -1,
+ _("The %s subcommand may only be used within %s."),
+ "END", "INPUT PROGRAM");
goto error;
}
if (end)
{
- lex_sbc_only_once ("END");
+ lex_sbc_only_once (lexer, "END");
goto error;
}
if (has_type)
{
- msg (SE, _("Only one of FIXED, FREE, or LIST may "
- "be specified."));
+ lex_next_error (lexer, -1, -1,
+ _("Only one of FIXED, FREE, or LIST may "
+ "be specified."));
goto error;
}
has_type = true;
return NULL;
if (!fmt_from_name (type, &input.type))
{
- msg (SE, _("Unknown format type `%s'."), type);
+ lex_next_error (lexer, -1, -1,
+ _("Unknown format type `%s'."), type);
return NULL;
}
if (!fh_is_locked (fh_inline_file (), FH_ACC_READ))
{
- msg (SE, _("This command is not valid here since the current "
- "input program does not access the inline file."));
+ lex_ofs_error (lexer, 0, lex_ofs (lexer) - 1,
+ _("This command is not valid here since the current "
+ "input program does not access the inline file."));
return CMD_CASCADING_FAILURE;
}
lex_match (lexer, T_ENDCMD);
if (ds != NULL)
lex_get (lexer);
else
- msg (SE, _("There is no dataset named %s."), lex_tokcstr (lexer));
+ lex_error (lexer, _("There is no dataset named %s."), lex_tokcstr (lexer));
return ds;
}
handle_name = xstrdup (lex_tokcstr (lexer));
if (fh_from_id (handle_name))
{
- msg (SE, _("File handle %s is already defined. "
- "Use %s before redefining a file handle."),
- handle_name, "CLOSE FILE HANDLE");
+ lex_error (lexer, _("File handle %s is already defined. "
+ "Use %s before redefining a file handle."),
+ handle_name, "CLOSE FILE HANDLE");
goto exit;
}
{
if (file_name)
{
- lex_sbc_only_once ("NAME");
+ lex_sbc_only_once (lexer, "NAME");
goto exit;
}
{
if (lrecl)
{
- lex_sbc_only_once ("LRECL");
+ lex_sbc_only_once (lexer, "LRECL");
goto exit;
}
{
if (tabwidth >= 0)
{
- lex_sbc_only_once ("TABWIDTH");
+ lex_sbc_only_once (lexer, "TABWIDTH");
goto exit;
}
lex_match (lexer, T_EQUALS);
{
if (mode != MODE_DEFAULT)
{
- lex_sbc_only_once ("MODE");
+ lex_sbc_only_once (lexer, "MODE");
goto exit;
}
lex_match (lexer, T_EQUALS);
{
if (ends >= 0)
{
- lex_sbc_only_once ("ENDS");
+ lex_sbc_only_once (lexer, "ENDS");
goto exit;
}
lex_match (lexer, T_EQUALS);
{
if (recform)
{
- lex_sbc_only_once ("RECFORM");
+ lex_sbc_only_once (lexer, "RECFORM");
goto exit;
}
lex_match (lexer, T_EQUALS);
{
if (encoding)
{
- lex_sbc_only_once ("ENCODING");
+ lex_sbc_only_once (lexer, "ENCODING");
goto exit;
}
fh_parse (struct lexer *lexer, enum fh_referent referent_mask,
struct session *session)
{
- struct file_handle *handle;
-
if (session != NULL && lex_token (lexer) == T_ID)
{
struct dataset *ds;
}
}
+ int start_ofs = lex_ofs (lexer);
+ struct file_handle *handle;
if (lex_match_id (lexer, "INLINE"))
handle = fh_inline_file ();
else
{
if (lex_token (lexer) != T_ID && !lex_is_string (lexer))
{
- lex_error (lexer, _("expecting a file name or handle name"));
+ lex_error (lexer,
+ _("Syntax error expecting a file name or handle name."));
return NULL;
}
if (!(fh_get_referent (handle) & referent_mask))
{
- msg (SE, _("Handle for %s not allowed here."),
- referent_name (fh_get_referent (handle)));
+ lex_ofs_error (lexer, start_ofs, lex_ofs (lexer) - 1,
+ _("Handle for %s not allowed here."),
+ referent_name (fh_get_referent (handle)));
fh_unref (handle);
return NULL;
}
spreadsheet_unref (spreadsheet);
}
else
- msg (SE, _("Unsupported TYPE %s."), tok);
-
+ lex_error_expecting (lexer, "TXT", "PSQL", "GNM", "ODS");
error:
destroy_spreadsheet_read_info (&opts);
}
else
{
- msg (SE, _("%s must be followed by either \"%s\" or \"%s\"."),
- "/SHEET", "NAME", "INDEX");
+ lex_error_expecting (lexer, "NAME", "INDEX");
goto error;
}
}
}
else
{
- msg (SE, _("%s must be followed by either \"%s\" or \"%s\"."),
- "/CELLRANGE", "FULL", "RANGE");
+ lex_error_expecting (lexer, "FULL", "RANGE");
goto error;
}
}
}
else
{
- msg (SE, _("%s must be followed by either \"%s\" or \"%s\"."),
- "/READNAMES", "ON", "OFF");
+ lex_error_expecting (lexer, "ON", "OFF");
goto error;
}
}
}
else if (lex_match_id (lexer, "IMPORTCASES"))
{
+ int start_ofs = lex_ofs (lexer) - 1;
lex_match (lexer, T_EQUALS);
if (lex_match (lexer, T_ALL))
{
goto error;
lex_get (lexer);
}
- msg (SW, _("Ignoring obsolete IMPORTCASES subcommand. (N OF CASES "
- "or SAMPLE may be used to substitute.)"));
+ lex_ofs_msg (lexer, SW, start_ofs, lex_ofs (lexer) - 1,
+ _("Ignoring obsolete IMPORTCASES subcommand. (N OF "
+ "CASES or SAMPLE may be used to substitute.)"));
}
else if (lex_match_id_n (lexer, "DELIMITERS", 4))
{
if (settings_get_syntax () == COMPATIBLE
&& ss_length (lex_tokss (lexer)) != 1)
{
- msg (SE, _("In compatible syntax mode, the QUALIFIER string "
- "must contain exactly one character."));
+ lex_error (lexer, _("In compatible syntax mode, the QUALIFIER "
+ "string must contain exactly one character."));
goto error;
}
lex_get (lexer);
}
+ int name_ofs = lex_ofs (lexer);
const char * tstr = lex_tokcstr (lexer);
if (tstr == NULL)
{
goto error;
if (!fmt_from_name (fmt_type_name, &fmt_type))
{
- msg (SE, _("Unknown format type `%s'."), fmt_type_name);
+ lex_next_error (lexer, -1, -1,
+ _("Unknown format type `%s'."), fmt_type_name);
goto error;
}
/* Compose input format. */
v = dict_create_var (dict, name, fmt_var_width (&input));
if (v == NULL)
{
- msg (SE, _("%s is a duplicate variable name."), name);
+ lex_ofs_error (lexer, name_ofs, name_ofs,
+ _("%s is a duplicate variable name."), name);
goto error;
}
var_set_both_formats (v, &output);
if (e)
{
- lex_sbc_only_once ("COLUMN");
+ lex_sbc_only_once (lexer, "COLUMN");
goto error;
}
free (cmd.v_variables);
return CMD_FAILURE;
}
-
else if (lex_match_id (lexer, "CELLS"))
{
if (mf.input_rowtype)
- msg (SW, _("CELLS is ignored when VARIABLES includes ROWTYPE_"));
+ lex_next_msg (lexer, SW,
+ -1, -1, _("CELLS is ignored when VARIABLES "
+ "includes ROWTYPE_"));
lex_match (lexer, T_EQUALS);
if (open || in_parens || (lex_token (lexer) != T_ENDCMD
&& lex_token (lexer) != T_SLASH))
{
- lex_error (lexer, _("Row type keyword expected."));
+ const char *rowtypes[] = {
+#define RT(NAME, DIMS) #NAME,
+ ROWTYPES
+#undef RT
+ "N_VECTOR", "SD",
+ };
+ lex_error_expecting_array (
+ lexer, rowtypes, sizeof rowtypes / sizeof *rowtypes);
goto error;
}
break;
}
else
{
- msg (SE, _("SPSS-like or Fortran-like format "
- "specification expected after variable names."));
+ lex_error (lexer, _("SPSS-like or Fortran-like format "
+ "specification expected after variable names."));
return false;
}
}
{
if (!fmt_from_name (type, &f.type))
{
- msg (SE, _("Unknown format type `%s'."), type);
+ lex_next_error (lexer, -1, -1,
+ _("Unknown format type `%s'."), type);
return false;
}
if (!fmt_check (&f, use))
}
static bool
-parse_column__ (int value, int base, int *column)
+parse_column__ (struct lexer *lexer, bool negative, int base, int *column)
{
assert (base == 0 || base == 1);
+
+ if (!lex_force_int (lexer))
+ return false;
+ long int value = lex_integer (lexer);
+ if (negative)
+ value = -value;
+ lex_get (lexer);
+
*column = value - base + 1;
if (*column < 1)
{
if (base == 1)
- msg (SE, _("Column positions for fields must be positive."));
+ lex_next_error (lexer, -1, -1,
+ _("Column positions for fields must be positive."));
else
- msg (SE, _("Column positions for fields must not be negative."));
+ lex_next_error (lexer, -1, -1,
+ _("Column positions for fields must not be negative."));
return false;
}
return true;
bool
parse_column (struct lexer *lexer, int base, int *column)
{
- assert (base == 0 || base == 1);
-
- if (!lex_force_int (lexer)
- || !parse_column__ (lex_integer (lexer), base, column))
- return false;
-
- lex_get (lexer);
- return true;
+ return parse_column__ (lexer, false, base, column);
}
/* Parse a column or a range of columns, specified as a single
int *first_column, int *last_column,
bool *range_specified)
{
+ int start_ofs = lex_ofs (lexer);
+
/* First column. */
- if (!lex_force_int (lexer)
- || !parse_column__ (lex_integer (lexer), base, first_column))
+ if (!parse_column__ (lexer, false, base, first_column))
return false;
- lex_get (lexer);
/* Last column. */
if (lex_is_integer (lexer) && lex_integer (lexer) < 0)
{
- if (!parse_column__ (-lex_integer (lexer), base, last_column))
+ if (!parse_column__ (lexer, true, base, last_column))
return false;
- lex_get (lexer);
if (*last_column < *first_column)
{
- msg (SE, _("The ending column for a field must be "
- "greater than the starting column."));
+ lex_ofs_error (lexer, start_ofs, lex_ofs (lexer) - 1,
+ _("The ending column for a field must be "
+ "greater than the starting column."));
return false;
}
expr = expr_parse (lexer, ds, VAL_NUMERIC);
if (lex_token (lexer) != T_ENDCMD)
{
- lex_error (lexer, _("expecting end of command"));
+ lex_error (lexer, _("Syntax error expecting end of command."));
goto error;
}
}
print_table = false;
else
{
- lex_error (lexer, _("expecting a valid subcommand"));
+ lex_error_expecting (lexer, "OUTFILE", "ENCODING", "RECORDS",
+ "TABLE", "NOTABLE");
goto error;
}
}
{
if (handle != NULL)
{
- lex_sbc_only_once ("OUTFILE");
+ lex_sbc_only_once (lexer, "OUTFILE");
goto error;
}
{
if (type != 0)
{
- lex_sbc_only_once ("TYPE");
+ lex_sbc_only_once (lexer, "TYPE");
goto error;
}
/* XXX should support multibyte UTF-8 delimiters */
if (ss_length (lex_tokss (lexer)) != 1)
{
- msg (SE, _("The %s string must contain exactly one "
- "character."), "DELIMITER");
+ lex_error (lexer, _("The %s string must contain exactly "
+ "one character."), "DELIMITER");
goto error;
}
delimiter = ss_first (lex_tokss (lexer));
/* XXX should support multibyte UTF-8 qualifiers */
if (ss_length (lex_tokss (lexer)) != 1)
{
- msg (SE, _("The %s string must contain exactly one "
- "character."), "QUALIFIER");
+ lex_error (lexer, _("The %s string must contain exactly "
+ "one character."), "QUALIFIER");
goto error;
}
qualifier = ss_first (lex_tokss (lexer));
{
if (handle != NULL)
{
- lex_sbc_only_once ("OUTFILE");
+ lex_sbc_only_once (lexer, "OUTFILE");
goto error;
}
{
if (metadata != NULL)
{
- lex_sbc_only_once ("METADATA");
+ lex_sbc_only_once (lexer, "METADATA");
goto error;
}
return parse_dict_rename (lexer, dict, relax);
else
{
- lex_error (lexer, _("expecting a valid subcommand"));
+ lex_error_expecting (lexer, "MAP", "DROP", "KEEP", "RENAME");
return false;
}
}
#include "data/dataset.h"
#include "data/dictionary.h"
#include "language/command.h"
+#include "language/lexer/lexer.h"
#include "language/lexer/variable-parser.h"
#include "libpspp/message.h"
bool ok;
if (proc_make_temporary_transformations_permanent (ds))
- msg (SE, _("%s may not be used after %s. "
- "Temporary transformations will be made permanent."),
- "DELETE VARIABLES", "TEMPORARY");
+ lex_ofs_error (lexer, 0, lex_ofs (lexer) - 1,
+ _("%s may not be used after %s. "
+ "Temporary transformations will be made permanent."),
+ "DELETE VARIABLES", "TEMPORARY");
if (!parse_variables (lexer, dataset_dict (ds), &vars, &n_vars, PV_NONE))
goto error;
utf8_trunc_len = utf8_encoding_trunc_len (utf8_s, encoding,
MV_MAX_STRING);
if (utf8_trunc_len < utf8_len)
- msg (SE, _("Truncating missing value to maximum "
- "acceptable length (%d bytes)."),
- MV_MAX_STRING);
+ lex_error (lexer, _("Truncating missing value to maximum "
+ "acceptable length (%d bytes)."),
+ MV_MAX_STRING);
/* Recode to dictionary encoding and add. */
raw_s = recode_string (encoding, "UTF-8",
cmd_modify_vars (struct lexer *lexer, struct dataset *ds)
{
if (proc_make_temporary_transformations_permanent (ds))
- msg (SE, _("%s may not be used after %s. "
- "Temporary transformations will be made permanent."),
- "MODIFY VARS", "TEMPORARY");
+ lex_ofs_error (lexer, 0, lex_ofs (lexer) - 1,
+ _("%s may not be used after %s. "
+ "Temporary transformations will be made permanent."),
+ "MODIFY VARS", "TEMPORARY");
/* Bits indicated whether we've already encountered a subcommand of this
type. */
{
if (already_encountered & 1)
{
- lex_sbc_only_once ("REORDER");
+ lex_sbc_only_once (lexer, "REORDER");
goto done;
}
already_encountered |= 1;
{
if (already_encountered & 2)
{
- lex_sbc_only_once ("RENAME");
+ lex_sbc_only_once (lexer, "RENAME");
goto done;
}
already_encountered |= 2;
{
if (already_encountered & 4)
{
- msg (SE,
- _("%s subcommand may be given at most once. It may "
- "not be given in conjunction with the %s subcommand."),
- "KEEP", "DROP");
+ lex_next_error (lexer, -1, -1,
+ _("%s subcommand may be given at most once. "
+ "It may not be given in conjunction with the "
+ "%s subcommand."),
+ "KEEP", "DROP");
goto done;
}
already_encountered |= 4;
if (already_encountered & 4)
{
- msg (SE, _("%s subcommand may be given at most once. It may "
- "not be given in conjunction with the %s "
- "subcommand."),
+ lex_next_error (lexer, -1, -1,
+ _("%s subcommand may be given at most once. "
+ "It may not be given in conjunction with the "
+ "%s subcommand."),
"DROP", "KEEP"
);
goto done;
}
else
{
- if (lex_token (lexer) == T_ID)
- msg (SE, _("Unrecognized subcommand name `%s'."),
- lex_tokcstr (lexer));
- else
- msg (SE, _("Subcommand name expected."));
+ lex_error_expecting (lexer, "REORDER", "RENAME", "KEEP",
+ "DROP", "MAP");
goto done;
}
{
if (!lex_is_integer (lexer))
{
- msg (SE, _("Numeric VALUE must be an integer."));
+ lex_error (lexer, _("Numeric VALUE must be an integer."));
goto error;
}
value_destroy (&mrset->counted, mrset->width);
return false;
if (dict_lookup_mrset (dict, lex_tokcstr (lexer)) == NULL)
{
- msg (SE, _("No multiple response set named %s."),
- lex_tokcstr (lexer));
+ lex_error (lexer, _("No multiple response set named %s."),
+ lex_tokcstr (lexer));
stringi_set_destroy (mrset_names);
return false;
}
if (fmt_is_string (f.type))
{
char str[FMT_STRING_LEN_MAX + 1];
- msg (SE, _("Format type %s may not be used with a numeric "
- "variable."), fmt_to_string (&f, str));
+ lex_next_error (lexer, -1, -1,
+ _("Format type %s may not be used with a numeric "
+ "variable."), fmt_to_string (&f, str));
goto fail;
}
if (!fmt_is_string (f.type))
{
char str[FMT_STRING_LEN_MAX + 1];
- msg (SE, _("Format type %s may not be used with a string "
- "variable."), fmt_to_string (&f, str));
+ lex_next_error (lexer, -2, -2,
+ _("Format type %s may not be used with a string "
+ "variable."), fmt_to_string (&f, str));
goto fail;
}
if (!fmt_check_output (&f))
int status = CMD_CASCADING_FAILURE;
if (proc_make_temporary_transformations_permanent (ds))
- msg (SE, _("%s may not be used after %s. "
- "Temporary transformations will be made permanent."), "RENAME VARS", "TEMPORARY");
+ lex_ofs_error (lexer, 0, lex_ofs (lexer) - 1,
+ _("%s may not be used after %s. "
+ "Temporary transformations will be made permanent."),
+ "RENAME VARS", "TEMPORARY");
do
{
size_t n_vectors = dict_get_n_vectors (dict);
if (n_vectors == 0)
{
- msg (SW, _("No vectors defined."));
+ msg (SN, _("No vectors defined."));
return;
}
MAX_LABEL_LEN);
if (ds_length (&label) > trunc_len)
{
- msg (SW, _("Truncating value label to %d bytes."), MAX_LABEL_LEN);
+ lex_next_msg (lexer, SW, 0, 0,
+ _("Truncating value label to %d bytes."),
+ MAX_LABEL_LEN);
ds_truncate (&label, trunc_len);
}
if (dict_lookup_vector (dict, lex_tokcstr (lexer)))
{
- msg (SE, _("A vector named %s already exists."),
- lex_tokcstr (lexer));
+ lex_next_error (lexer, 0, 0,
+ _("A vector named %s already exists."),
+ lex_tokcstr (lexer));
goto fail;
}
for (i = 0; i < n_vectors; i++)
if (!utf8_strcasecmp (vectors[i], lex_tokcstr (lexer)))
{
- msg (SE, _("Vector name %s is given twice."),
- lex_tokcstr (lexer));
+ lex_next_error (lexer, 0, 0,
+ _("Vector name %s is given twice."),
+ lex_tokcstr (lexer));
goto fail;
}
if (n_vectors > 1)
{
- msg (SE, _("A slash must separate each vector "
- "specification in VECTOR's long form."));
+ lex_error (lexer, _("A slash must separate each vector "
+ "specification in VECTOR's long form."));
goto fail;
}
}
if (n_vars == 0)
{
- lex_error (lexer, _("expecting vector length"));
+ lex_error (lexer, _("Syntax error expecting vector length."));
goto fail;
}
return CMD_CASCADING_FAILURE;
if (var_is_alpha (v))
{
- msg (SE, _("The weighting variable must be numeric."));
+ lex_next_error (lexer, -1, -1,
+ _("The weighting variable must be numeric."));
return CMD_CASCADING_FAILURE;
}
if (dict_class_from_id (var_get_name (v)) == DC_SCRATCH)
{
- msg (SE, _("The weighting variable may not be scratch."));
+ lex_next_error (lexer, -1, -1,
+ _("The weighting variable may not be scratch."));
return CMD_CASCADING_FAILURE;
}
if (!lex_force_id (lexer))
goto done;
+ int name_ofs = lex_ofs (lexer);
name = xstrdup (lex_tokcstr (lexer));
lex_get (lexer);
}
else
{
- lex_error (lexer, _("expecting number or string"));
+ lex_error (lexer, _("Syntax error expecting number or string."));
goto done;
}
v = dict_create_var (d, name, width);
if (v == NULL)
{
- msg (SE, _("Duplicate variable name %s."), name);
+ lex_ofs_error (lexer, name_ofs, name_ofs,
+ _("Duplicate variable name %s."), name);
value_destroy (&value, width);
goto done;
}
return expr_allocate_number (e, settings_get_viewwidth ());
else
{
- msg (SE, _("Unknown system variable %s."), lex_tokcstr (lexer));
+ lex_error (lexer, _("Unknown system variable %s."), lex_tokcstr (lexer));
return NULL;
}
}
return expr_allocate_format (e, &fmt);
/* All attempts failed. */
- msg (SE, _("Unknown identifier %s."), lex_tokcstr (lexer));
+ lex_error (lexer, _("Unknown identifier %s."), lex_tokcstr (lexer));
return NULL;
}
break;
const struct operation *first, *last;
if (!lookup_function (lex_tokcstr (lexer), &first, &last))
{
- msg (SE, _("No function or vector named %s."), lex_tokcstr (lexer));
+ lex_error (lexer, _("No function or vector named %s."),
+ lex_tokcstr (lexer));
ds_destroy (&func_name);
return NULL;
}
return true;
error:
- lex_error (lexer, _("expecting valid format specifier"));
+ lex_error (lexer, _("Syntax error expecting valid format specifier."));
return false;
}
if (!fmt_from_name (type, &format->type))
{
- msg (SE, _("Unknown format type `%s'."), type);
+ lex_error (lexer, _("Unknown format type `%s'."), type);
return false;
}
if (format->w == 0 && !strchr (lex_tokcstr (lexer), '0'))
{
- msg (SE, _("Format specifier `%s' lacks required width."),
- lex_tokcstr (lexer));
+ lex_error (lexer, _("Format specifier `%s' lacks required width."),
+ lex_tokcstr (lexer));
return false;
}
{
if (lex_token (lexer) != T_ID)
{
- lex_error (lexer, _("expecting format type"));
+ lex_error (lexer, _("Syntax error expecting format type."));
return false;
}
if (!fmt_from_name (lex_tokcstr (lexer), type))
{
- msg (SE, _("Unknown format type `%s'."), lex_tokcstr (lexer));
+ lex_error (lexer, _("Unknown format type `%s'."), lex_tokcstr (lexer));
return false;
}
lex_get (lexer);
static struct msg_point lex_token_end_point (const struct lex_source *,
const struct lex_token *);
+static size_t lex_ofs_at_phrase__ (struct lexer *, int ofs, const char *s);
+
/* Source offset of the last byte in TOKEN. */
static size_t
lex_token_end (const struct lex_token *token)
static void lex_source_clear_parse (struct lex_source *);
static bool lex_source_get_parse (struct lex_source *);
-static void lex_source_error_valist (struct lex_source *, int ofs0, int ofs1,
- const char *format, va_list)
- PRINTF_FORMAT (4, 0);
+static void lex_source_msg_valist (struct lex_source *, enum msg_class,
+ int ofs0, int ofs1,
+ const char *format, va_list)
+ PRINTF_FORMAT (5, 0);
static const struct lex_token *lex_source_next__ (const struct lex_source *,
int n);
\f
va_list args;
va_start (args, format);
- lex_ofs_error_valist (lexer, lex_ofs (lexer), lex_ofs (lexer), format, args);
+ lex_ofs_msg_valist (lexer, SE, lex_ofs (lexer), lex_ofs (lexer),
+ format, args);
va_end (args);
}
-/* Prints a syntax error message containing the current token and
- given message MESSAGE (if non-null). */
+/* Prints a syntax error message for the span of tokens N0 through N1,
+ inclusive, from the current token in LEXER, adding message MESSAGE (if
+ non-null). */
void
-lex_error_valist (struct lexer *lexer, const char *format, va_list args)
+lex_next_error (struct lexer *lexer, int n0, int n1, const char *format, ...)
{
- lex_ofs_error_valist (lexer, lex_ofs (lexer), lex_ofs (lexer), format, args);
+ va_list args;
+
+ va_start (args, format);
+ int ofs = lex_ofs (lexer);
+ lex_ofs_msg_valist (lexer, SE, n0 + ofs, n1 + ofs, format, args);
+ va_end (args);
+}
+
+/* Prints a syntax error message for the span of tokens with offsets OFS0
+ through OFS1, inclusive, within the current command in LEXER, adding message
+ MESSAGE (if non-null). */
+void
+lex_ofs_error (struct lexer *lexer, int ofs0, int ofs1, const char *format, ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ lex_ofs_msg_valist (lexer, SE, ofs0, ofs1, format, args);
+ va_end (args);
+}
+
+/* Prints a message of the given CLASS containing the current token and given
+ message MESSAGE (if non-null). */
+void
+lex_msg (struct lexer *lexer, enum msg_class class, const char *format, ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ lex_ofs_msg_valist (lexer, class, lex_ofs (lexer), lex_ofs (lexer),
+ format, args);
+ va_end (args);
}
/* Prints a syntax error message for the span of tokens N0 through N1,
inclusive, from the current token in LEXER, adding message MESSAGE (if
non-null). */
void
-lex_next_error (struct lexer *lexer, int n0, int n1, const char *format, ...)
+lex_next_msg (struct lexer *lexer, enum msg_class class, int n0, int n1,
+ const char *format, ...)
{
va_list args;
va_start (args, format);
int ofs = lex_ofs (lexer);
- lex_ofs_error_valist (lexer, n0 + ofs, n1 + ofs, format, args);
+ lex_ofs_msg_valist (lexer, class, n0 + ofs, n1 + ofs, format, args);
va_end (args);
}
-/* Prints a syntax error message for the span of tokens with offsets OFS0
+/* Prints a message of the given CLASS for the span of tokens with offsets OFS0
through OFS1, inclusive, within the current command in LEXER, adding message
MESSAGE (if non-null). */
void
-lex_ofs_error (struct lexer *lexer, int ofs0, int ofs1, const char *format, ...)
+lex_ofs_msg (struct lexer *lexer, enum msg_class class, int ofs0, int ofs1,
+ const char *format, ...)
{
va_list args;
va_start (args, format);
- lex_ofs_error_valist (lexer, ofs0, ofs1, format, args);
+ lex_ofs_msg_valist (lexer, class, ofs0, ofs1, format, args);
va_end (args);
}
break;
case 1:
- lex_error (lexer, _("expecting %s"), options[0]);
+ lex_error (lexer, _("Syntax error expecting %s."), options[0]);
break;
case 2:
- lex_error (lexer, _("expecting %s or %s"), options[0], options[1]);
+ lex_error (lexer, _("Syntax error expecting %s or %s."),
+ options[0], options[1]);
break;
case 3:
- lex_error (lexer, _("expecting %s, %s, or %s"), options[0], options[1],
- options[2]);
+ lex_error (lexer, _("Syntax error expecting %s, %s, or %s."),
+ options[0], options[1], options[2]);
break;
case 4:
- lex_error (lexer, _("expecting %s, %s, %s, or %s"),
+ lex_error (lexer, _("Syntax error expecting %s, %s, %s, or %s."),
options[0], options[1], options[2], options[3]);
break;
case 5:
- lex_error (lexer, _("expecting %s, %s, %s, %s, or %s"),
+ lex_error (lexer, _("Syntax error expecting %s, %s, %s, %s, or %s."),
options[0], options[1], options[2], options[3], options[4]);
break;
case 6:
- lex_error (lexer, _("expecting %s, %s, %s, %s, %s, or %s"),
+ lex_error (lexer, _("Syntax error expecting %s, %s, %s, %s, %s, or %s."),
options[0], options[1], options[2], options[3], options[4],
options[5]);
break;
case 7:
- lex_error (lexer, _("expecting %s, %s, %s, %s, %s, %s, or %s"),
+ lex_error (lexer, _("Syntax error expecting %s, %s, %s, %s, %s, %s, "
+ "or %s."),
options[0], options[1], options[2], options[3], options[4],
options[5], options[6]);
break;
case 8:
- lex_error (lexer, _("expecting %s, %s, %s, %s, %s, %s, %s, or %s"),
+ lex_error (lexer, _("Syntax error expecting %s, %s, %s, %s, %s, %s, %s, "
+ "or %s."),
options[0], options[1], options[2], options[3], options[4],
options[5], options[6], options[7]);
break;
ds_put_cstr (&s, ", ");
ds_put_cstr (&s, options[i]);
}
- lex_error (lexer, _("expecting one of the following: %s"),
+ lex_error (lexer, _("Syntax error expecting one of the following: %s."),
ds_cstr (&s));
ds_destroy (&s);
}
}
/* Reports an error to the effect that subcommand SBC may only be specified
- once.
-
- This function does not take a lexer as an argument or use lex_error(),
- because the result would ordinarily just be redundant: "Syntax error at
- SUBCOMMAND: Subcommand SUBCOMMAND may only be specified once.", which does
- not help the user find the error. */
+ once. */
void
-lex_sbc_only_once (const char *sbc)
+lex_sbc_only_once (struct lexer *lexer, const char *sbc)
{
- msg (SE, _("Subcommand %s may only be specified once."), sbc);
+ int ofs = lex_ofs (lexer) - 1;
+ if (lex_ofs_token (lexer, ofs)->type == T_EQUALS)
+ ofs--;
+
+ /* lex_ofs_at_phrase__() handles subcommand names that are keywords, such as
+ BY. */
+ if (lex_ofs_at_phrase__ (lexer, ofs, sbc))
+ lex_ofs_error (lexer, ofs, ofs,
+ _("Subcommand %s may only be specified once."), sbc);
+ else
+ msg (SE, _("Subcommand %s may only be specified once."), sbc);
}
/* Reports an error to the effect that subcommand SBC is missing.
void
lex_spec_only_once (struct lexer *lexer, const char *sbc, const char *spec)
{
- lex_error (lexer, _("%s may only be specified once within subcommand %s"),
+ lex_error (lexer, _("%s may only be specified once within subcommand %s."),
spec, sbc);
}
void
lex_spec_missing (struct lexer *lexer, const char *sbc, const char *spec)
{
- lex_error (lexer, _("Required %s specification missing from %s subcommand"),
- sbc, spec);
+ lex_error (lexer, _("Required %s specification missing from %s subcommand."),
+ spec, sbc);
}
/* Prints a syntax error message for the span of tokens with offsets OFS0
through OFS1, inclusive, within the current command in LEXER, adding message
MESSAGE (if non-null) with the given ARGS. */
void
-lex_ofs_error_valist (struct lexer *lexer, int ofs0, int ofs1,
- const char *format, va_list args)
+lex_ofs_msg_valist (struct lexer *lexer, enum msg_class class,
+ int ofs0, int ofs1, const char *format, va_list args)
{
- struct lex_source *src = lex_source__ (lexer);
-
- if (src != NULL)
- lex_source_error_valist (src, ofs0, ofs1, format, args);
- else
- {
- struct string s;
-
- ds_init_empty (&s);
- ds_put_format (&s, _("Syntax error at end of input"));
- if (format != NULL)
- {
- ds_put_cstr (&s, ": ");
- ds_put_vformat (&s, format, args);
- }
- if (ds_last (&s) != '.')
- ds_put_byte (&s, '.');
- msg (SE, "%s", ds_cstr (&s));
- ds_destroy (&s);
- }
+ lex_source_msg_valist (lex_source__ (lexer), class, ofs0, ofs1, format, args);
}
/* Checks that we're at end of command.
{
if (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_STOP)
{
- lex_error (lexer, _("expecting end of command"));
+ lex_error (lexer, _("Syntax error expecting end of command."));
return CMD_FAILURE;
}
else
return true;
else
{
- lex_error (lexer, _("expecting string"));
+ lex_error (lexer, _("Syntax error expecting string."));
return false;
}
}
return true;
else
{
- lex_error (lexer, _("expecting integer"));
+ lex_error (lexer, _("Syntax error expecting integer."));
return false;
}
}
/* Weird, maybe a bug in the caller. Just report that we needed an
integer. */
if (name)
- lex_error (lexer, _("Integer expected for %s."), name);
+ lex_error (lexer, _("Syntax error expecting integer for %s."), name);
else
- lex_error (lexer, _("Integer expected."));
+ lex_error (lexer, _("Syntax error expecting integer."));
}
else if (min == max)
{
if (name)
- lex_error (lexer, _("Expected %ld for %s."), min, name);
+ lex_error (lexer, _("Syntax error expecting %ld for %s."), min, name);
else
- lex_error (lexer, _("Expected %ld."), min);
+ lex_error (lexer, _("Syntax error expecting %ld."), min);
}
else if (min + 1 == max)
{
if (name)
- lex_error (lexer, _("Expected %ld or %ld for %s."), min, min + 1, name);
+ lex_error (lexer, _("Syntax error expecting %ld or %ld for %s."),
+ min, min + 1, name);
else
- lex_error (lexer, _("Expected %ld or %ld."), min, min + 1);
+ lex_error (lexer, _("Syntax error expecting %ld or %ld."),
+ min, min + 1);
}
else
{
{
if (name)
lex_error (lexer,
- _("Expected integer between %ld and %ld for %s."),
+ _("Syntax error expecting integer "
+ "between %ld and %ld for %s."),
min, max, name);
else
- lex_error (lexer, _("Expected integer between %ld and %ld."),
+ lex_error (lexer, _("Syntax error expecting integer "
+ "between %ld and %ld."),
min, max);
}
else if (report_lower_bound)
if (min == 0)
{
if (name)
- lex_error (lexer, _("Expected non-negative integer for %s."),
+ lex_error (lexer, _("Syntax error expecting "
+ "non-negative integer for %s."),
name);
else
- lex_error (lexer, _("Expected non-negative integer."));
+ lex_error (lexer, _("Syntax error expecting "
+ "non-negative integer."));
}
else if (min == 1)
{
if (name)
- lex_error (lexer, _("Expected positive integer for %s."),
+ lex_error (lexer, _("Syntax error expecting "
+ "positive integer for %s."),
name);
else
- lex_error (lexer, _("Expected positive integer."));
+ lex_error (lexer, _("Syntax error expecting "
+ "positive integer."));
}
else
{
if (name)
- lex_error (lexer, _("Expected integer %ld or greater for %s."),
+ lex_error (lexer, _("Syntax error expecting "
+ "integer %ld or greater for %s."),
min, name);
else
- lex_error (lexer, _("Expected integer %ld or greater."), min);
+ lex_error (lexer, _("Syntax error expecting "
+ "integer %ld or greater."), min);
}
}
else if (report_upper_bound)
{
if (name)
lex_error (lexer,
- _("Expected integer less than or equal to %ld for %s."),
+ _("Syntax error expecting integer less than or equal "
+ "to %ld for %s."),
max, name);
else
- lex_error (lexer, _("Expected integer less than or equal to %ld."),
+ lex_error (lexer, _("Syntax error expecting integer less than or "
+ "equal to %ld."),
max);
}
else
{
if (name)
- lex_error (lexer, _("Integer expected for %s."), name);
+ lex_error (lexer, _("Syntax error expecting integer for %s."),
+ name);
else
- lex_error (lexer, _("Integer expected."));
+ lex_error (lexer, _("Syntax error expecting integer."));
}
}
return false;
if (lex_is_number (lexer))
return true;
- lex_error (lexer, _("expecting number"));
+ lex_error (lexer, _("Syntax error expecting number."));
return false;
}
/* Weird, maybe a bug in the caller. Just report that we needed an
number. */
if (name)
- lex_error (lexer, _("Number expected for %s."), name);
+ lex_error (lexer, _("Syntax error expecting number for %s."), name);
else
- lex_error (lexer, _("Number expected."));
+ lex_error (lexer, _("Syntax error expecting number."));
}
else if (min == max)
{
if (name)
- lex_error (lexer, _("Expected %g for %s."), min, name);
+ lex_error (lexer, _("Syntax error expecting number %g for %s."),
+ min, name);
else
- lex_error (lexer, _("Expected %g."), min);
+ lex_error (lexer, _("Syntax error expecting number %g."), min);
}
else
{
{
if (name)
lex_error (lexer,
- _("Expected number between %g and %g for %s."),
+ _("Syntax error expecting number "
+ "between %g and %g for %s."),
min, max, name);
else
- lex_error (lexer, _("Expected number between %g and %g."),
+ lex_error (lexer, _("Syntax error expecting number "
+ "between %g and %g."),
min, max);
}
else if (report_lower_bound)
if (min == 0)
{
if (name)
- lex_error (lexer, _("Expected non-negative number for %s."),
+ lex_error (lexer, _("Syntax error expecting "
+ "non-negative number for %s."),
name);
else
- lex_error (lexer, _("Expected non-negative number."));
+ lex_error (lexer, _("Syntax error expecting "
+ "non-negative number."));
}
else
{
if (name)
- lex_error (lexer, _("Expected number %g or greater for %s."),
+ lex_error (lexer, _("Syntax error expecting number "
+ "%g or greater for %s."),
min, name);
else
- lex_error (lexer, _("Expected number %g or greater."), min);
+ lex_error (lexer, _("Syntax error expecting number "
+ "%g or greater."), min);
}
}
else if (report_upper_bound)
{
if (name)
lex_error (lexer,
- _("Expected number less than or equal to %g for %s."),
+ _("Syntax error expecting number "
+ "less than or equal to %g for %s."),
max, name);
else
- lex_error (lexer, _("Expected number less than or equal to %g."),
+ lex_error (lexer, _("Syntax error expecting number "
+ "less than or equal to %g."),
max);
}
else
{
if (name)
- lex_error (lexer, _("Number expected for %s."), name);
+ lex_error (lexer, _("Syntax error expecting number for %s."), name);
else
- lex_error (lexer, _("Number expected."));
+ lex_error (lexer, _("Syntax error expecting number."));
}
}
return false;
/* Weird, maybe a bug in the caller. Just report that we needed an
number. */
if (name)
- lex_error (lexer, _("Number expected for %s."), name);
+ lex_error (lexer, _("Syntax error expecting number for %s."), name);
else
- lex_error (lexer, _("Number expected."));
+ lex_error (lexer, _("Syntax error expecting number."));
}
else
{
if (report_lower_bound && report_upper_bound)
{
if (name)
- lex_error (lexer, _("Expected number in [%g,%g) for %s."),
+ lex_error (lexer, _("Syntax error expecting number "
+ "in [%g,%g) for %s."),
min, max, name);
else
- lex_error (lexer, _("Expected number in [%g,%g)."),
+ lex_error (lexer, _("Syntax error expecting number in [%g,%g)."),
min, max);
}
else if (report_lower_bound)
if (min == 0)
{
if (name)
- lex_error (lexer, _("Expected non-negative number for %s."),
+ lex_error (lexer, _("Syntax error expecting "
+ "non-negative number for %s."),
name);
else
- lex_error (lexer, _("Expected non-negative number."));
+ lex_error (lexer, _("Syntax error expecting "
+ "non-negative number."));
}
else
{
if (name)
- lex_error (lexer, _("Expected number %g or greater for %s."),
+ lex_error (lexer, _("Syntax error expecting "
+ "number %g or greater for %s."),
min, name);
else
- lex_error (lexer, _("Expected number %g or greater."), min);
+ lex_error (lexer, _("Syntax error expecting "
+ "number %g or greater."), min);
}
}
else if (report_upper_bound)
{
if (name)
lex_error (lexer,
- _("Expected number less than %g for %s."), max, name);
+ _("Syntax error expecting "
+ "number less than %g for %s."), max, name);
else
- lex_error (lexer, _("Expected number less than %g."), max);
+ lex_error (lexer, _("Syntax error expecting "
+ "number less than %g."), max);
}
else
{
if (name)
- lex_error (lexer, _("Number expected for %s."), name);
+ lex_error (lexer, _("Syntax error expecting number for %s."), name);
else
- lex_error (lexer, _("Number expected."));
+ lex_error (lexer, _("Syntax error expecting number."));
}
}
return false;
}
-/* If the current token is an number in the open range (MIN,MAX], does
+/* If the current token is an number in the open range (MIN,MAX), does
nothing and returns true. Otherwise, reports an error and returns false.
If NAME is nonnull, then it is used in the error message. */
bool
/* Weird, maybe a bug in the caller. Just report that we needed an
number. */
if (name)
- lex_error (lexer, _("Number expected for %s."), name);
+ lex_error (lexer, _("Syntax error expecting number for %s."), name);
else
- lex_error (lexer, _("Number expected."));
+ lex_error (lexer, _("Syntax error expecting number."));
}
else
{
if (report_lower_bound && report_upper_bound)
{
if (name)
- lex_error (lexer, _("Expected number in (%g,%g) for %s."),
+ lex_error (lexer, _("Syntax error expecting number "
+ "in (%g,%g) for %s."),
min, max, name);
else
- lex_error (lexer, _("Expected number in (%g,%g)."), min, max);
+ lex_error (lexer, _("Syntax error expecting number "
+ "in (%g,%g)."), min, max);
}
else if (report_lower_bound)
{
if (min == 0)
{
if (name)
- lex_error (lexer, _("Expected positive number for %s."), name);
+ lex_error (lexer, _("Syntax error expecting "
+ "positive number for %s."), name);
else
- lex_error (lexer, _("Expected positive number."));
+ lex_error (lexer, _("Syntax error expecting "
+ "positive number."));
}
else
{
if (name)
- lex_error (lexer, _("Expected number greater than %g for %s."),
+ lex_error (lexer, _("Syntax error expecting number "
+ "greater than %g for %s."),
min, name);
else
- lex_error (lexer, _("Expected number greater than %g."), min);
+ lex_error (lexer, _("Syntax error expecting number "
+ "greater than %g."), min);
}
}
else if (report_upper_bound)
{
if (name)
- lex_error (lexer, _("Expected number less than %g for %s."),
+ lex_error (lexer, _("Syntax error expecting number "
+ "less than %g for %s."),
max, name);
else
- lex_error (lexer, _("Expected number less than %g."), max);
+ lex_error (lexer, _("Syntax error expecting number "
+ "less than %g."), max);
}
else
{
if (name)
- lex_error (lexer, _("Number expected for %s."), name);
+ lex_error (lexer, _("Syntax error expecting number "
+ "for %s."), name);
else
- lex_error (lexer, _("Number expected."));
+ lex_error (lexer, _("Syntax error expecting number."));
}
}
return false;
if (lex_token (lexer) == T_ID)
return true;
- lex_error (lexer, _("expecting identifier"));
+ lex_error (lexer, _("Syntax error expecting identifier."));
return false;
}
\f
}
static size_t
-lex_at_phrase__ (struct lexer *lexer, const char *s)
+lex_ofs_at_phrase__ (struct lexer *lexer, int ofs, const char *s)
{
struct string_lexer slex;
struct token token;
string_lexer_init (&slex, s, strlen (s), SEG_MODE_INTERACTIVE, true);
while (string_lexer_next (&slex, &token))
{
- bool match = lex_tokens_match (lex_next (lexer, i++), &token);
+ bool match = lex_tokens_match (lex_ofs_token (lexer, ofs + i++), &token);
token_uninit (&token);
if (!match)
return 0;
bool
lex_at_phrase (struct lexer *lexer, const char *s)
{
- return lex_at_phrase__ (lexer, s) > 0;
+ return lex_ofs_at_phrase__ (lexer, lex_ofs (lexer), s) > 0;
}
/* If LEXER is positioned at the sequence of tokens that may be parsed from S,
bool
lex_match_phrase (struct lexer *lexer, const char *s)
{
- size_t n = lex_at_phrase__ (lexer, s);
+ size_t n = lex_ofs_at_phrase__ (lexer, lex_ofs (lexer), s);
if (n > 0)
lex_get_n (lexer, n);
return n > 0;
.file_name = intern_new_if_nonnull (src->reader->file_name),
.start = lex_token_start_point (src, t0),
.end = lex_token_end_point (src, t1),
+ .src = CONST_CAST (struct lex_source *, src),
};
}
}
static void
-lex_source_error_valist (struct lex_source *src, int ofs0, int ofs1,
- const char *format, va_list args)
+lex_source_msg_valist (struct lex_source *src, enum msg_class class,
+ int ofs0, int ofs1, const char *format, va_list args)
{
- const struct lex_token *token;
- struct string s;
-
- ds_init_empty (&s);
+ struct string s = DS_EMPTY_INITIALIZER;
- token = lex_source_ofs__ (src, ofs0);
- if (token->token.type == T_ENDCMD)
- ds_put_cstr (&s, _("Syntax error at end of command"));
- else
+ if (src)
{
- /* Get the syntax that caused the error. */
- char *raw_syntax = lex_source_syntax__ (src, ofs0, ofs1);
- char syntax[64];
- str_ellipsize (ss_cstr (raw_syntax), syntax, sizeof syntax);
- free (raw_syntax);
-
/* Get the macro call(s) that expanded to the syntax that caused the
error. */
char call[64];
str_ellipsize (lex_source_get_macro_call (src, ofs0, ofs1),
call, sizeof call);
-
- if (syntax[0])
- {
- if (call[0])
- ds_put_format (&s,
- _("Syntax error at `%s' (in expansion of `%s')"),
- syntax, call);
- else
- ds_put_format (&s, _("Syntax error at `%s'"), syntax);
- }
- else
- {
- if (call[0])
- ds_put_format (&s, _("Syntax error in syntax expanded from `%s'"),
- call);
- else
- ds_put_cstr (&s, _("Syntax error"));
- }
+ if (call[0])
+ ds_put_format (&s, _("In syntax expanded from `%s'"), call);
}
+ else
+ ds_put_cstr (&s, _("At end of input"));
+ if (!ds_is_empty (&s))
+ ds_put_cstr (&s, ": ");
if (format)
- {
- ds_put_cstr (&s, ": ");
- ds_put_vformat (&s, format, args);
- }
+ ds_put_vformat (&s, format, args);
+ else
+ ds_put_cstr (&s, _("Syntax error."));
+
if (ds_last (&s) != '.')
ds_put_byte (&s, '.');
struct msg *m = xmalloc (sizeof *m);
*m = (struct msg) {
- .category = MSG_C_SYNTAX,
- .severity = MSG_S_ERROR,
- .location = lex_source_get_location (src, ofs0, ofs1),
+ .category = msg_class_to_category (class),
+ .severity = msg_class_to_severity (class),
+ .location = src ? lex_source_get_location (src, ofs0, ofs1) : NULL,
.text = ds_steal_cstr (&s),
};
msg_emit (m);
syntax, sizeof syntax);
struct string s = DS_EMPTY_INITIALIZER;
- ds_put_format (&s, _("Syntax error at `%s'"), syntax);
- ds_put_format (&s, ": %s", token->token.string.string);
+ ds_put_cstr (&s, token->token.string.string);
struct msg *m = xmalloc (sizeof *m);
*m = (struct msg) {
msg_set_handler (&msg_handler);
}
-void
+struct lex_source *
lex_source_ref (const struct lex_source *src_)
{
struct lex_source *src = CONST_CAST (struct lex_source *, src_);
assert (src->n_refs > 0);
src->n_refs++;
}
+ return src;
}
void
return ss_empty ();
size_t ofs = src->lines[line - 1];
- size_t end = line >= src->n_lines ? src->length : src->lines[line];
+ size_t end;
+ if (line < src->n_lines)
+ end = src->lines[line];
+ else
+ {
+ const char *newline = memchr (src->buffer + ofs, '\n', src->length - ofs);
+ end = newline ? newline - src->buffer : src->length;
+ }
return ss_buffer (&src->buffer[ofs], end - ofs);
}
struct msg_location *lex_get_location (const struct lexer *, int n0, int n1);
const char *lex_get_encoding (const struct lexer *);
-/* Issuing errors. */
+/* Issuing errors and warnings. */
void lex_error (struct lexer *, const char *, ...) PRINTF_FORMAT (2, 3);
void lex_next_error (struct lexer *, int n0, int n1, const char *, ...)
PRINTF_FORMAT (4, 5);
void lex_ofs_error (struct lexer *, int ofs0, int ofs1, const char *, ...)
PRINTF_FORMAT (4, 5);
+
+void lex_msg (struct lexer *, enum msg_class, const char *, ...)
+ PRINTF_FORMAT (3, 4);
+void lex_next_msg (struct lexer *, enum msg_class, int n0, int n1,
+ const char *, ...)
+ PRINTF_FORMAT (5, 6);
+void lex_ofs_msg (struct lexer *, enum msg_class, int ofs0, int ofs1,
+ const char *, ...)
+ PRINTF_FORMAT (5, 6);
+void lex_ofs_msg_valist (struct lexer *lexer, enum msg_class,
+ int ofs0, int ofs1, const char *format, va_list)
+ PRINTF_FORMAT (5, 0);
+
int lex_end_of_command (struct lexer *);
void lex_error_expecting (struct lexer *, ...) SENTINEL(0);
void lex_error_expecting_valist (struct lexer *, va_list);
void lex_error_expecting_array (struct lexer *, const char **, size_t n);
-void lex_sbc_only_once (const char *);
+void lex_sbc_only_once (struct lexer *, const char *);
void lex_sbc_missing (const char *);
void lex_spec_only_once (struct lexer *, const char *subcommand,
void lex_spec_missing (struct lexer *, const char *subcommand,
const char *specification);
-void lex_error_valist (struct lexer *, const char *, va_list)
- PRINTF_FORMAT (2, 0);
-void lex_ofs_error_valist (struct lexer *lexer, int ofs0, int ofs1,
- const char *format, va_list)
- PRINTF_FORMAT (4, 0);
-
/* Error handling. */
enum segmenter_mode lex_get_syntax_mode (const struct lexer *);
enum lex_error_mode lex_get_error_mode (const struct lexer *);
void lex_set_message_handler (struct lexer *,
void (*output_msg) (const struct msg *,
struct lexer *));
-void lex_source_ref (const struct lex_source *);
+struct lex_source *lex_source_ref (const struct lex_source *);
void lex_source_unref (struct lex_source *);
struct substring lex_source_get_line (const struct lex_source *, int line);
/* If TOKEN is the first token of a call to a macro in MACROS, create a new
macro expander, initializes *MCP to it. Returns 0 if more tokens are needed
and should be added via macro_call_add() or 1 if the caller should next call
- macro_call_get_expansion().
+ macro_call_expand().
If TOKEN is not the first token of a macro call, returns -1 and sets *MCP to
NULL. */
Returns a positive number to indicate that the returned number of tokens
invoke a macro. The number returned might be less than the number of tokens
added because it can take a few tokens of lookahead to determine whether the
- macro invocation is finished. The caller should call
- macro_call_get_expansion() to obtain the expansion. */
+ macro invocation is finished. The caller should call macro_call_expand() to
+ obtain the expansion. */
int
macro_call_add (struct macro_call *mc, const struct macro_token *mt,
const struct msg_location *loc)
parse_num_range (struct lexer *lexer,
double *x, double *y, const enum fmt_type *format)
{
+ int start_ofs = lex_ofs (lexer);
+
if (lex_match_id (lexer, "LO") || lex_match_id (lexer, "LOWEST"))
*x = LOWEST;
else if (!parse_number (lexer, x, format))
if (*y < *x)
{
double t;
- msg (SW, _("The high end of the range (%.*g) is below the low end "
- "(%.*g). The range will be treated as if reversed."),
- DBL_DIG + 1, *y, DBL_DIG + 1, *x);
+ lex_ofs_msg (lexer, SW, start_ofs, lex_ofs (lexer) - 1,
+ ("The high end of the range (%.*g) is below the low end "
+ "(%.*g). The range will be treated as if reversed."),
+ DBL_DIG + 1, *y, DBL_DIG + 1, *x);
t = *x;
*x = *y;
*y = t;
}
else if (*x == *y)
- msg (SW, _("Ends of range are equal (%.*g)."), DBL_DIG + 1, *x);
+ lex_ofs_msg (lexer, SW, start_ofs, lex_ofs (lexer) - 1,
+ _("Ends of range are equal (%.*g)."), DBL_DIG + 1, *x);
return true;
}
{
if (*x == LOWEST)
{
- msg (SE, _("%s or %s must be part of a range."), "LO", "LOWEST");
+ lex_next_msg (lexer, SW, -1, -1,
+ _("%s or %s must be part of a range."),
+ "LO", "LOWEST");
return false;
}
*y = *x;
*x = v.f;
if (*x == SYSMIS)
{
- msg (SE, _("System-missing value is not valid here."));
+ lex_next_error (lexer, -1, -1,
+ _("System-missing value is not valid here."));
return false;
}
return true;
if (!is_vs_name_token (lexer, vs))
{
- lex_error (lexer, _("expecting variable name"));
+ lex_error (lexer, _("Syntax error expecting variable name."));
return false;
}
else if (var_set_lookup_var_idx (vs, lex_tokcstr (lexer), idx))
}
else
{
- msg (SE, _("%s is not a variable name."), lex_tokcstr (lexer));
+ lex_error (lexer, _("%s is not a variable name."), lex_tokcstr (lexer));
return false;
}
}
PV_OPTS, which also affects what variables are allowed in
appropriate ways. */
static void
-add_variable (struct variable ***v, size_t *nv, size_t *mv,
+add_variable (struct lexer *lexer,
+ struct variable ***v, size_t *nv, size_t *mv,
char *included, int pv_opts,
- const struct var_set *vs, size_t idx)
+ const struct var_set *vs, size_t idx,
+ int start_ofs, int end_ofs)
{
struct variable *add = var_set_get_var (vs, idx);
const char *add_name = var_get_name (add);
if ((pv_opts & PV_NUMERIC) && !var_is_numeric (add))
- msg (SW, _("%s is not a numeric variable. It will not be "
- "included in the variable list."), add_name);
+ lex_ofs_msg (lexer, SW, start_ofs, end_ofs,
+ _("%s is not a numeric variable. It will not be "
+ "included in the variable list."), add_name);
else if ((pv_opts & PV_STRING) && !var_is_alpha (add))
- msg (SE, _("%s is not a string variable. It will not be "
- "included in the variable list."), add_name);
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("%s is not a string variable. It will not be "
+ "included in the variable list."), add_name);
else if ((pv_opts & PV_NO_SCRATCH)
&& dict_class_from_id (add_name) == DC_SCRATCH)
- msg (SE, _("Scratch variables (such as %s) are not allowed "
- "here."), add_name);
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("Scratch variables (such as %s) are not allowed "
+ "here."), add_name);
else if ((pv_opts & (PV_SAME_TYPE | PV_SAME_WIDTH)) && *nv
&& var_get_type (add) != var_get_type ((*v)[0]))
- msg (SE, _("%s and %s are not the same type. All variables in "
- "this variable list must be of the same type. %s "
- "will be omitted from the list."),
- var_get_name ((*v)[0]), add_name, add_name);
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("%s and %s are not the same type. All variables in "
+ "this variable list must be of the same type. %s "
+ "will be omitted from the list."),
+ var_get_name ((*v)[0]), add_name, add_name);
else if ((pv_opts & PV_SAME_WIDTH) && *nv
&& var_get_width (add) != var_get_width ((*v)[0]))
- msg (SE, _("%s and %s are string variables with different widths. "
- "All variables in this variable list must have the "
- "same width. %s will be omitted from the list."),
- var_get_name ((*v)[0]), add_name, add_name);
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("%s and %s are string variables with different widths. "
+ "All variables in this variable list must have the "
+ "same width. %s will be omitted from the list."),
+ var_get_name ((*v)[0]), add_name, add_name);
else if ((pv_opts & PV_NO_DUPLICATE) && included && included[idx])
- msg (SE, _("Variable %s appears twice in variable list."), add_name);
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("Variable %s appears twice in variable list."), add_name);
else if ((pv_opts & PV_DUPLICATE) || !included || !included[idx])
{
if (*nv >= *mv)
duplicates if indicated by PV_OPTS, which also affects what
variables are allowed in appropriate ways. */
static void
-add_variables (struct variable ***v, size_t *nv, size_t *mv, char *included,
+add_variables (struct lexer *lexer,
+ struct variable ***v, size_t *nv, size_t *mv, char *included,
int pv_opts,
const struct var_set *vs, int first_idx, int last_idx,
- enum dict_class class)
+ enum dict_class class,
+ int start_ofs, int end_ofs)
{
size_t i;
for (i = first_idx; i <= last_idx; i++)
if (dict_class_from_id (var_get_name (var_set_get_var (vs, i))) == class)
- add_variable (v, nv, mv, included, pv_opts, vs, i);
+ add_variable (lexer, v, nv, mv, included, pv_opts, vs, i,
+ start_ofs, end_ofs);
}
/* Note that if parse_variables() returns false, *v is free()'d.
do
{
+ int start_ofs = lex_ofs (lexer);
if (lex_match (lexer, T_ALL))
- add_variables (v, nv, &mv, included, pv_opts,
- vs, 0, var_set_get_n (vs) - 1, DC_ORDINARY);
+ add_variables (lexer, v, nv, &mv, included, pv_opts,
+ vs, 0, var_set_get_n (vs) - 1, DC_ORDINARY,
+ start_ofs, start_ofs);
else
{
enum dict_class class;
goto fail;
if (!lex_match (lexer, T_TO))
- add_variable (v, nv, &mv, included, pv_opts, vs, first_idx);
+ add_variable (lexer, v, nv, &mv, included, pv_opts, vs, first_idx,
+ start_ofs, start_ofs);
else
{
size_t last_idx;
if (!parse_var_idx_class (lexer, vs, &last_idx, &last_class))
goto fail;
+ int end_ofs = lex_ofs (lexer) - 1;
+
first_var = var_set_get_var (vs, first_idx);
last_var = var_set_get_var (vs, last_idx);
{
const char *first_name = var_get_name (first_var);
const char *last_name = var_get_name (last_var);
- msg (SE, _("%s TO %s is not valid syntax since %s "
- "precedes %s in the dictionary."),
- first_name, last_name, first_name, last_name);
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("%s TO %s is not valid syntax since %s "
+ "precedes %s in the dictionary."),
+ first_name, last_name, first_name, last_name);
goto fail;
}
if (class != last_class)
{
- msg (SE, _("When using the TO keyword to specify several "
- "variables, both variables must be from "
- "the same variable dictionaries, of either "
- "ordinary, scratch, or system variables. "
- "%s is a %s variable, whereas %s is %s."),
- var_get_name (first_var), dict_class_to_name (class),
- var_get_name (last_var),
- dict_class_to_name (last_class));
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("With the syntax <a> TO <b>, variables <a> "
+ "and <b> must be both regular variables "
+ "or both scratch variables."));
+ struct pair
+ {
+ const char *name;
+ enum dict_class class;
+ int ofs;
+ }
+ pairs[2] = {
+ { var_get_name (first_var), class, start_ofs },
+ { var_get_name (last_var), last_class, end_ofs },
+ };
+ for (size_t i = 0; i < 2; i++)
+ switch (pairs[i].class)
+ {
+ case DC_ORDINARY:
+ lex_ofs_msg (lexer, SN, pairs[i].ofs, pairs[i].ofs,
+ _("%s is a regular variable."),
+ pairs[i].name);
+ break;
+
+ case DC_SCRATCH:
+ lex_ofs_msg (lexer, SN, pairs[i].ofs, pairs[i].ofs,
+ _("%s is a scratch variable."),
+ pairs[i].name);
+ break;
+
+ case DC_SYSTEM:
+ lex_ofs_msg (lexer, SN, pairs[i].ofs, pairs[i].ofs,
+ _("%s is a system variable."),
+ pairs[i].name);
+ break;
+ }
goto fail;
}
- add_variables (v, nv, &mv, included, pv_opts,
- vs, first_idx, last_idx, class);
+ add_variables (lexer, v, nv, &mv, included, pv_opts,
+ vs, first_idx, last_idx, class,
+ start_ofs, lex_ofs (lexer) - 1);
}
}
{
if (!is_dict_name_token (lexer, d))
{
- lex_error (lexer, "expecting variable name");
+ lex_error (lexer, ("Syntax error expecting variable name."));
return NULL;
}
if (!dict_id_is_valid (d, lex_tokcstr (lexer), true))
the number of digits in the suffix into *N_DIGITSP, and returns the number
of bytes in the root. On failure, returns 0. */
static int
-extract_numeric_suffix (const char *name,
+extract_numeric_suffix (struct lexer *lexer, int ofs, const char *name,
unsigned long int *numberp, int *n_digitsp)
{
size_t root_len, n_digits;
if (n_digits == 0)
{
- msg (SE, _("`%s' cannot be used with TO because it does not end in "
- "a digit."), name);
+ lex_ofs_error (lexer, ofs, ofs,
+ _("`%s' cannot be used with TO because it does not end in "
+ "a digit."), name);
return 0;
}
*numberp = strtoull (name + root_len, NULL, 10);
if (*numberp == ULONG_MAX)
{
- msg (SE, _("Numeric suffix on `%s' is larger than supported with TO."),
- name);
+ lex_ofs_error (lexer, ofs, ofs,
+ _("Numeric suffix on `%s' is larger than supported with TO."),
+ name);
return 0;
}
*n_digitsp = n_digits;
}
static bool
-add_var_name (char *name,
+add_var_name (struct lexer *lexer, int start_ofs, int end_ofs, char *name,
char ***names, size_t *n_vars, size_t *allocated_vars,
struct stringi_set *set, int pv_opts)
{
if (pv_opts & PV_NO_DUPLICATE && !stringi_set_insert (set, name))
{
- msg (SE, _("Variable %s appears twice in variable list."),
- name);
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("Variable %s appears twice in variable list."),
+ name);
return false;
}
do
{
+ int start_ofs = lex_ofs (lexer);
name1 = parse_DATA_LIST_var (lexer, dict);
if (!name1)
goto exit;
if (dict_class_from_id (name1) == DC_SCRATCH && pv_opts & PV_NO_SCRATCH)
{
- msg (SE, _("Scratch variables not allowed here."));
+ lex_ofs_error (lexer, start_ofs, start_ofs,
+ _("Scratch variables not allowed here."));
goto exit;
}
if (lex_match (lexer, T_TO))
name2 = parse_DATA_LIST_var (lexer, dict);
if (!name2)
goto exit;
+ int end_ofs = lex_ofs (lexer) - 1;
- root_len1 = extract_numeric_suffix (name1, &num1, &n_digits1);
+ root_len1 = extract_numeric_suffix (lexer, start_ofs,
+ name1, &num1, &n_digits1);
if (root_len1 == 0)
goto exit;
- root_len2 = extract_numeric_suffix (name2, &num2, &n_digits2);
+ root_len2 = extract_numeric_suffix (lexer, end_ofs,
+ name2, &num2, &n_digits2);
if (root_len2 == 0)
goto exit;
if (root_len1 != root_len2 || memcasecmp (name1, name2, root_len1))
{
- msg (SE, _("Prefixes don't match in use of TO convention."));
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("Prefixes don't match in use of TO convention."));
goto exit;
}
if (num1 > num2)
{
- msg (SE, _("Bad bounds in use of TO convention."));
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("Bad bounds in use of TO convention."));
goto exit;
}
char *name = xasprintf ("%.*s%0*lu",
root_len1, name1,
n_digits1, number);
- if (!add_var_name (name, &names, &n_vars, &allocated_vars,
+ if (!add_var_name (lexer, start_ofs, end_ofs,
+ name, &names, &n_vars, &allocated_vars,
&set, pv_opts))
{
free (name);
}
else
{
- if (!add_var_name (name1, &names, &n_vars, &allocated_vars,
+ if (!add_var_name (lexer, start_ofs, start_ofs,
+ name1, &names, &n_vars, &allocated_vars,
&set, pv_opts))
goto exit;
name1 = NULL;
if (lex_token (lexer) != T_ID)
{
- lex_error (lexer, _("expecting variable name"));
+ lex_error (lexer, _("Syntax error expecting variable name."));
goto error;
}
if (allocated_vs >= *n_vs)
*vs = x2nrealloc (*vs, &allocated_vs, sizeof **vs);
struct var_syntax *new = &(*vs)[(*n_vs)++];
- *new = (struct var_syntax) { .first = ss_xstrdup (lex_tokss (lexer)) };
+ *new = (struct var_syntax) {
+ .first = ss_xstrdup (lex_tokss (lexer)),
+ .first_ofs = lex_ofs (lexer)
+ };
lex_get (lexer);
if (lex_match (lexer, T_TO))
{
if (lex_token (lexer) != T_ID)
{
- lex_error (lexer, _("expecting variable name"));
+ lex_error (lexer, _("Syntax error expecting variable name."));
goto error;
}
new->last = ss_xstrdup (lex_tokss (lexer));
lex_get (lexer);
}
+ new->last_ofs = lex_ofs (lexer) - 1;
}
while (lex_token (lexer) == T_ID);
return true;
array of pointers to variables and *N_VARS to the length of the array and
returns true. On error, sets *VARS to NULL and *N_VARS to 0.
+ The LEXER is just used for error messages.
+
For the moment, only honors PV_NUMERIC in OPTS. */
bool
-var_syntax_evaluate (const struct var_syntax *vs, size_t n_vs,
+var_syntax_evaluate (struct lexer *lexer,
+ const struct var_syntax *vs, size_t n_vs,
const struct dictionary *dict,
struct variable ***vars, size_t *n_vars, int opts)
{
size_t allocated_vars = 0;
for (size_t i = 0; i < n_vs; i++)
{
+ int first_ofs = vs[i].first_ofs;
struct variable *first = dict_lookup_var (dict, vs[i].first);
if (!first)
{
- msg (SE, _("%s is not a variable name."), vs[i].first);
+ lex_ofs_error (lexer, first_ofs, first_ofs,
+ _("%s is not a variable name."), vs[i].first);
goto error;
}
+ int last_ofs = vs[i].last_ofs;
struct variable *last = (vs[i].last
? dict_lookup_var (dict, vs[i].last)
: first);
if (!last)
{
- msg (SE, _("%s is not a variable name."), vs[i].last);
+ lex_ofs_error (lexer, last_ofs, last_ofs,
+ _("%s is not a variable name."), vs[i].last);
goto error;
}
size_t last_idx = var_get_dict_index (last);
if (last_idx < first_idx)
{
- msg (SE, _("%s TO %s is not valid syntax since %s "
- "precedes %s in the dictionary."),
- vs[i].first, vs[i].last,
- vs[i].first, vs[i].last);
+ lex_ofs_error (lexer, first_ofs, last_ofs,
+ _("%s TO %s is not valid syntax since %s "
+ "precedes %s in the dictionary."),
+ vs[i].first, vs[i].last,
+ vs[i].first, vs[i].last);
goto error;
}
struct variable *v = dict_get_var (dict, j);
if (opts & PV_NUMERIC && !var_is_numeric (v))
{
- msg (SW, _("%s is not a numeric variable."), var_get_name (v));
+ lex_ofs_error (lexer, first_ofs, last_ofs,
+ _("%s is not a numeric variable."),
+ var_get_name (v));
goto error;
}
{
char *first; /* Always nonnull. */
char *last; /* Nonnull for var ranges (e.g. "a TO b"). */
+
+ /* For error reporting.
+
+ This only works if var_syntax_parse() and var_syntax_evaluate() are
+ called while we're parsing the same source file. That matches the
+ current use case in MATRIX; if that changes, then this will need to
+ switch to use struct msg_location instead. */
+ int first_ofs;
+ int last_ofs;
};
void var_syntax_destroy (struct var_syntax *, size_t n);
bool var_syntax_parse (struct lexer *, struct var_syntax **, size_t *);
-bool var_syntax_evaluate (const struct var_syntax *, size_t,
+bool var_syntax_evaluate (struct lexer *, const struct var_syntax *, size_t,
const struct dictionary *,
struct variable ***, size_t *, int opts);
/* Get the name of the aggregation function. */
if (lex_token (lexer) != T_ID)
{
- lex_error (lexer, _("expecting aggregation function"));
+ lex_error (lexer, _("Syntax error expecting aggregation function."));
goto error;
}
break;
if (NULL == function->name)
{
- msg (SE, _("Unknown aggregation function %s."),
- ds_cstr (&function_name));
+ lex_error (lexer, _("Unknown aggregation function %s."),
+ ds_cstr (&function_name));
goto error;
}
ds_destroy (&function_name);
else
{
/* Parse list of source variables. */
- {
- int pv_opts = PV_NO_SCRATCH;
-
- if (func_index == SUM || func_index == MEAN || func_index == SD)
- pv_opts |= PV_NUMERIC;
- else if (function->n_args)
- pv_opts |= PV_SAME_TYPE;
-
- if (!parse_variables_const (lexer, dict, &src, &n_src, pv_opts))
- goto error;
- }
+ int pv_opts = PV_NO_SCRATCH;
+ if (func_index == SUM || func_index == MEAN || func_index == SD)
+ pv_opts |= PV_NUMERIC;
+ else if (function->n_args)
+ pv_opts |= PV_SAME_TYPE;
+
+ int vars_start_ofs = lex_ofs (lexer);
+ if (!parse_variables_const (lexer, dict, &src, &n_src, pv_opts))
+ goto error;
+ int vars_end_ofs = lex_ofs (lexer) - 1;
/* Parse function arguments, for those functions that
require arguments. */
+ int args_start_ofs = 0;
if (function->n_args != 0)
for (i = 0; i < function->n_args; i++)
{
int type;
lex_match (lexer, T_COMMA);
+ if (i == 0)
+ args_start_ofs = lex_ofs (lexer);
if (lex_is_string (lexer))
{
arg[i].c = recode_string (dict_get_encoding (agr->dict),
}
else
{
- msg (SE, _("Missing argument %zu to %s."),
- i + 1, function->name);
+ lex_error (lexer, _("Missing argument %zu to %s."),
+ i + 1, function->name);
goto error;
}
-
- lex_get (lexer);
-
if (type != var_get_type (src[0]))
{
msg (SE, _("Arguments to %s must be of same type as "
"source variables."),
function->name);
+ if (type == VAL_NUMERIC)
+ {
+ lex_next_msg (lexer, SN, 0, 0,
+ _("The argument is numeric."));
+ lex_ofs_msg (lexer, SN, vars_start_ofs, vars_end_ofs,
+ _("The variables have string type."));
+ }
+ else
+ {
+ lex_next_msg (lexer, SN, 0, 0,
+ _("The argument is a string."));
+ lex_ofs_msg (lexer, SN, vars_start_ofs, vars_end_ofs,
+ _("The variables are numeric."));
+ }
goto error;
}
+
+ lex_get (lexer);
}
+ int args_end_ofs = lex_ofs (lexer) - 1;
/* Trailing rparen. */
if (!lex_force_match (lexer, T_RPAREN))
arg[0] = arg[1];
arg[1] = t;
- msg (SW, _("The value arguments passed to the %s function "
- "are out-of-order. They will be treated as if "
- "they had been specified in the correct order."),
- function->name);
+ lex_ofs_msg (lexer, SW, args_start_ofs, args_end_ofs,
+ _("The value arguments passed to the %s function "
+ "are out of order. They will be treated as if "
+ "they had been specified in the correct order."),
+ function->name);
}
}
if (lex_token (lexer) == T_ENDCMD)
return true;
- lex_error (lexer, "expecting end of command");
+ lex_error (lexer, "Syntax error expecting end of command.");
return false;
}
continue;
if (lex_token (lexer) != T_ENDCMD)
{
- lex_error (lexer, _("expecting end of command"));
+ lex_error (lexer, _("Syntax error expecting end of command."));
goto error;
}
.descending = false,
};
bool show_tables = true;
+ int exclude_ofs = 0;
lex_match (lexer, T_SLASH);
for (;;)
{
else if (lex_match_id (lexer, "MISSING"))
{
lex_match (lexer, T_EQUALS);
+ exclude_ofs = lex_ofs (lexer);
if (lex_match_id (lexer, "TABLE"))
proc.exclude = MV_ANY;
else if (lex_match_id (lexer, "INCLUDE"))
/* Missing values. */
if (proc.mode == GENERAL && !proc.exclude)
{
- msg (SE, _("Missing mode %s not allowed in general mode. "
- "Assuming %s."), "REPORT", "MISSING=TABLE");
+ lex_ofs_error (lexer, exclude_ofs, exclude_ofs,
+ _("Missing mode %s not allowed in general mode. "
+ "Assuming %s."), "REPORT", "MISSING=TABLE");
proc.exclude = MV_ANY;
}
{
if (proc->n_pivots)
{
- msg (SE, _("%s must be specified before %s."), "VARIABLES", "TABLES");
+ lex_next_error (lexer, -1, -1, _("%s must be specified before %s."),
+ "VARIABLES", "TABLES");
return false;
}
}
}
- lex_error (lexer, _("Expecting summary function name."));
+ lex_error (lexer, _("Syntax error expecting summary function name."));
return false;
}
};
};
- /* Source location. This is null for CCT_TOTAL, CCT_VALUE, CCT_LABEL,
- CCT_FUNCTION, CCT_EXCLUDED_MISSING. */
+ /* Source location (sometimes NULL). */
struct msg_location *location;
};
enum pivot_axis_type label_axis[PIVOT_N_AXES];
enum pivot_axis_type clabels_from_axis;
enum pivot_axis_type clabels_to_axis;
+ int clabels_start_ofs, clabels_end_ofs;
const struct variable *clabels_example;
struct hmap clabels_values_map;
struct ctables_value **clabels_values;
bool show_totals = false;
char *total_label = NULL;
bool totals_before = false;
+ int key_start_ofs = 0;
+ int key_end_ofs = 0;
while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
{
if (!c->n_cats && lex_match_id (lexer, "ORDER"))
}
else if (!c->n_cats && lex_match_id (lexer, "KEY"))
{
- int start_ofs = lex_ofs (lexer) - 1;
+ key_start_ofs = lex_ofs (lexer) - 1;
lex_match (lexer, T_EQUALS);
if (lex_match_id (lexer, "VALUE"))
cat.type = CCT_VALUE;
bool UNUSED b = lex_force_match (lexer, T_LPAREN);
goto error;
}
+ }
+ key_end_ofs = lex_ofs (lexer) - 1;
- lex_ofs_error (lexer, start_ofs, lex_ofs (lexer) - 1,
- _("Data-dependent sorting is not implemented."));
+ if (cat.type == CCT_FUNCTION)
+ {
+ lex_ofs_error (lexer, key_start_ofs, key_end_ofs,
+ _("Data-dependent sorting is not implemented."));
goto error;
}
}
if (!c->n_cats)
{
+ if (key_start_ofs)
+ cat.location = lex_ofs_location (lexer, key_start_ofs, key_end_ofs);
+
if (c->n_cats >= allocated_cats)
c->cats = x2nrealloc (c->cats, &allocated_cats, sizeof *c->cats);
c->cats[c->n_cats++] = cat;
}
static bool
-ctables_check_label_position (struct ctables_table *t, enum pivot_axis_type a)
+ctables_check_label_position (struct ctables_table *t, struct lexer *lexer,
+ enum pivot_axis_type a)
{
enum pivot_axis_type label_pos = t->label_axis[a];
if (label_pos == a)
return true;
- const char *subcommand_name = a == PIVOT_AXIS_ROW ? "ROWLABELS" : "COLLABELS";
- const char *pos_name = label_pos == PIVOT_AXIS_LAYER ? "LAYER" : "OPPOSITE";
-
const struct ctables_stack *stack = &t->stacks[a];
if (!stack->n)
return true;
for (size_t i = 0; i < c0->n_cats; i++)
if (c0->cats[i].type == CCT_FUNCTION)
{
- msg (SE, _("%s=%s is not allowed with sorting based "
- "on a summary function."),
- subcommand_name, pos_name);
+ msg (SE, _("Category labels may not be moved to another axis when "
+ "sorting by a summary function."));
+ lex_ofs_msg (lexer, SN, t->clabels_start_ofs, t->clabels_end_ofs,
+ _("This syntax moves category labels to another axis."));
+ msg_at (SN, c0->cats[i].location,
+ _("This syntax requests sorting by a summary function."));
return false;
}
- if (n0->n - 1 == n0->scale_idx)
+
+ for (size_t i = 0; i < stack->n; i++)
{
- msg (SE, _("%s=%s requires the variables to be moved to be categorical, "
- "but %s is a scale variable."),
- subcommand_name, pos_name, var_get_name (v0));
- return false;
+ const struct ctables_nest *ni = &stack->nests[i];
+ assert (ni->n > 0);
+ const struct variable *vi = ni->vars[ni->n - 1];
+ if (n0->n - 1 == ni->scale_idx)
+ {
+ msg (SE, _("To move category labels from one axis to another, "
+ "the variables whose labels are to be moved must be "
+ "categorical, but %s is scale."), var_get_name (vi));
+ lex_ofs_msg (lexer, SN, t->clabels_start_ofs, t->clabels_end_ofs,
+ _("This syntax moves category labels to another axis."));
+ return false;
+ }
}
for (size_t i = 1; i < stack->n; i++)
const struct variable *vi = ni->vars[ni->n - 1];
struct ctables_categories *ci = t->categories[var_get_dict_index (vi)];
- if (ni->n - 1 == ni->scale_idx)
- {
- msg (SE, _("%s=%s requires the variables to be moved to be "
- "categorical, but %s is a scale variable."),
- subcommand_name, pos_name, var_get_name (vi));
- return false;
- }
if (var_get_width (v0) != var_get_width (vi))
{
- msg (SE, _("%s=%s requires the variables to be "
- "moved to have the same width, but %s has "
- "width %d and %s has width %d."),
- subcommand_name, pos_name,
+ msg (SE, _("To move category labels from one axis to another, "
+ "the variables whose labels are to be moved must all "
+ "have the same width, but %s has width %d and %s has "
+ "width %d."),
var_get_name (v0), var_get_width (v0),
var_get_name (vi), var_get_width (vi));
+ lex_ofs_msg (lexer, SN, t->clabels_start_ofs, t->clabels_end_ofs,
+ _("This syntax moves category labels to another axis."));
return false;
}
if (!val_labs_equal (var_get_value_labels (v0),
var_get_value_labels (vi)))
{
- msg (SE, _("%s=%s requires the variables to be "
- "moved to have the same value labels, but %s "
- "and %s have different value labels."),
- subcommand_name, pos_name,
+ msg (SE, _("To move category labels from one axis to another, "
+ "the variables whose labels are to be moved must all "
+ "have the same value labels, but %s and %s have "
+ "different value labels."),
var_get_name (v0), var_get_name (vi));
+ lex_ofs_msg (lexer, SN, t->clabels_start_ofs, t->clabels_end_ofs,
+ _("This syntax moves category labels to another axis."));
return false;
}
if (!ctables_categories_equal (c0, ci))
{
- msg (SE, _("%s=%s requires the variables to be "
- "moved to have the same category "
- "specifications, but %s and %s have different "
- "category specifications."),
- subcommand_name, pos_name,
+ msg (SE, _("To move category labels from one axis to another, "
+ "the variables whose labels are to be moved must all "
+ "have the same category specifications, but %s and %s "
+ "have different category specifications."),
var_get_name (v0), var_get_name (vi));
+ lex_ofs_msg (lexer, SN, t->clabels_start_ofs, t->clabels_end_ofs,
+ _("This syntax moves category labels to another axis."));
return false;
}
}
}
static bool
-ctables_prepare_table (struct ctables_table *t)
+ctables_prepare_table (struct ctables_table *t, struct lexer *lexer)
{
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
if (t->axes[a])
enumerate_sum_vars (t->axes[t->summary_axis],
&t->sum_vars, &t->n_sum_vars, &allocated_sum_vars);
- return (ctables_check_label_position (t, PIVOT_AXIS_ROW)
- && ctables_check_label_position (t, PIVOT_AXIS_COLUMN));
+ return (ctables_check_label_position (t, lexer, PIVOT_AXIS_ROW)
+ && ctables_check_label_position (t, lexer, PIVOT_AXIS_COLUMN));
}
static void
= ctables_find_postcompute (ct, lex_tokcstr (lexer));
if (!pc)
{
- msg (SE, _("Unknown computed category &%s."), lex_tokcstr (lexer));
+ lex_error (lexer, _("Unknown computed category &%s."),
+ lex_tokcstr (lexer));
goto error;
}
lex_get (lexer);
double widths[2] = { SYSMIS, SYSMIS };
double units_per_inch = 72.0;
+ int start_ofs = lex_ofs (lexer);
while (lex_token (lexer) != T_SLASH)
{
if (lex_match_id (lexer, "MINCOLWIDTH"))
if (widths[0] != SYSMIS && widths[1] != SYSMIS
&& widths[0] > widths[1])
{
- msg (SE, _("MINCOLWIDTH must not be greater than MAXCOLWIDTH."));
+ lex_ofs_error (lexer, start_ofs, lex_ofs (lexer) - 1,
+ _("MINCOLWIDTH must not be greater than "
+ "MAXCOLWIDTH."));
goto error;
}
lex_error_expecting (lexer, "FORMAT", "VLABELS", "MRSETS",
"SMISSING", "PCOMPUTE", "PPROPERTIES",
"WEIGHT", "HIDESMALLCOUNTS", "TABLE");
+ if (lex_match_id (lexer, "SLABELS")
+ || lex_match_id (lexer, "CLABELS")
+ || lex_match_id (lexer, "CRITERIA")
+ || lex_match_id (lexer, "CATEGORIES")
+ || lex_match_id (lexer, "TITLES")
+ || lex_match_id (lexer, "SIGTEST")
+ || lex_match_id (lexer, "COMPARETEST"))
+ lex_next_msg (lexer, SN, -1, -1,
+ _("TABLE must appear before this subcommand."));
goto error;
}
if (lex_token (lexer) == T_ENDCMD)
{
- if (!ctables_prepare_table (t))
+ if (!ctables_prepare_table (t, lexer))
goto error;
break;
}
}
else if (lex_match_id (lexer, "CLABELS"))
{
+ int start_ofs = lex_ofs (lexer) - 1;
if (lex_match_id (lexer, "AUTO"))
{
t->label_axis[PIVOT_AXIS_ROW] = PIVOT_AXIS_ROW;
"COLLABELS");
goto error;
}
+ int end_ofs = lex_ofs (lexer) - 1;
+
+ if (t->label_axis[PIVOT_AXIS_ROW] != PIVOT_AXIS_ROW
+ && t->label_axis[PIVOT_AXIS_COLUMN] != PIVOT_AXIS_COLUMN)
+ {
+ msg (SE, _("ROWLABELS and COLLABELS may not both be "
+ "specified."));
+
+ lex_ofs_msg (lexer, SN, t->clabels_start_ofs,
+ t->clabels_end_ofs,
+ _("This is the first specification."));
+ lex_ofs_msg (lexer, SN, start_ofs, end_ofs,
+ _("This is the second specification."));
+ goto error;
+ }
+
+ t->clabels_start_ofs = start_ofs;
+ t->clabels_end_ofs = end_ofs;
}
else if (lex_match_id (lexer, "CRITERIA"))
{
}
else if (lex_match_id (lexer, "COMPARETEST"))
{
- int start_ofs = lex_ofs (lexer);
+ int start_ofs = lex_ofs (lexer) - 1;
if (!t->pairwise)
{
t->pairwise = xmalloc (sizeof *t->pairwise);
lex_error_expecting (lexer, "TABLE", "SLABELS", "CLABELS",
"CRITERIA", "CATEGORIES", "TITLES",
"SIGTEST", "COMPARETEST");
+ if (lex_match_id (lexer, "FORMAT")
+ || lex_match_id (lexer, "VLABELS")
+ || lex_match_id (lexer, "MRSETS")
+ || lex_match_id (lexer, "SMISSING")
+ || lex_match_id (lexer, "PCOMPUTE")
+ || lex_match_id (lexer, "PPROPERTIES")
+ || lex_match_id (lexer, "WEIGHT")
+ || lex_match_id (lexer, "HIDESMALLCOUNTS"))
+ lex_next_msg (lexer, SN, -1, -1,
+ _("This subcommand must appear before TABLE."));
goto error;
}
}
if (t->label_axis[PIVOT_AXIS_ROW] != PIVOT_AXIS_ROW)
- {
- t->clabels_from_axis = PIVOT_AXIS_ROW;
- if (t->label_axis[PIVOT_AXIS_COLUMN] != PIVOT_AXIS_COLUMN)
- {
- msg (SE, _("ROWLABELS and COLLABELS may not both be specified."));
- goto error;
- }
- }
+ t->clabels_from_axis = PIVOT_AXIS_ROW;
else if (t->label_axis[PIVOT_AXIS_COLUMN] != PIVOT_AXIS_COLUMN)
t->clabels_from_axis = PIVOT_AXIS_COLUMN;
t->clabels_to_axis = t->label_axis[t->clabels_from_axis];
- if (!ctables_prepare_table (t))
+ if (!ctables_prepare_table (t, lexer))
goto error;
}
while (lex_token (lexer) != T_ENDCMD);
if (lex_match (lexer, T_LPAREN))
{
- if (lex_token (lexer) != T_ID)
- {
- lex_error (lexer, NULL);
- goto error;
- }
+ if (!lex_force_id (lexer))
+ goto error;
if (try_name (dict, dsc, lex_tokcstr (lexer)))
{
struct dsc_var *dsc_var = &dsc->vars[dsc->n_vars - 1];
n_zs++;
}
else
- msg (SE, _("Z-score variable name %s would be"
- " a duplicate variable name."), lex_tokcstr (lexer));
+ lex_error (lexer, _("Z-score variable name %s would be "
+ "a duplicate variable name."),
+ lex_tokcstr (lexer));
lex_get (lexer);
if (!lex_force_match (lexer, T_RPAREN))
goto error;
{
if (lex_token (lexer) == T_ID)
{
- enum dsc_statistic stat;
-
- for (stat = 0; stat < DSC_N_STATS; stat++)
+ for (enum dsc_statistic stat = 0; stat < DSC_N_STATS; stat++)
if (lex_match_id (lexer, dsc_info[stat].identifier))
return stat;
- lex_error (lexer, _("expecting statistic name: reverting to default"));
+ const char *stat_names[DSC_N_STATS];
+ for (enum dsc_statistic stat = 0; stat < DSC_N_STATS; stat++)
+ stat_names[stat] = dsc_info[stat].identifier;
+ lex_error_expecting_array (lexer, stat_names,
+ sizeof stat_names / sizeof *stat_names);
lex_get (lexer);
}
if (totals_seen && nototals_seen)
{
- msg (SE, _("%s and %s are mutually exclusive"), "TOTAL", "NOTOTAL");
+ msg (SE, _("%s and %s are mutually exclusive."), "TOTAL", "NOTOTAL");
goto error;
}
bool ok;
if (proc_make_temporary_transformations_permanent (ds))
- msg (SW, _("%s ignores %s. "
- "Temporary transformations will be made permanent."), "FLIP", "TEMPORARY");
+ lex_ofs_msg (lexer, SW, 0, lex_ofs (lexer) - 1,
+ _("%s ignores %s. "
+ "Temporary transformations will be made permanent."),
+ "FLIP", "TEMPORARY");
flip = pool_create_container (struct flip_pgm, pool);
flip->n_vars = 0;
const struct variable *v = NULL;
if (!lex_match_variable (lexer,graph.dict,&v))
{
- lex_error (lexer, _("Variable expected"));
+ lex_error (lexer, _("Syntax error expecting variable name."));
goto error;
}
graph.by_var[0] = v;
else if (lex_match_id (lexer, "FOOTNOTE"))
{
lex_error (lexer, _("%s is not yet implemented."),"FOOTNOTE");
- lex_error (lexer, _("FOOTNOTE is not implemented yet for GRAPH"));
goto error;
}
else if (lex_match_id (lexer, "MISSING"))
/* Common configuration for all MSAVEs. */
struct msg_location *location; /* Range of lines for first MSAVE. */
struct file_handle *outfile; /* Output file for all the MSAVEs. */
+ struct msg_location *outfile_location;
struct string_array variables; /* VARIABLES subcommand. */
+ struct msg_location *variables_location;
struct string_array fnames; /* FNAMES subcommand. */
+ struct msg_location *fnames_location;
struct string_array snames; /* SNAMES subcommand. */
+ struct msg_location *snames_location;
/* Collects and owns factors and splits. The individual msave_command
structs point to these but do not own them. (This is because factors
{
if (!lvalue->var)
{
- msg (SE, _("Undefined variable %s."), lex_tokcstr (s->lexer));
+ lex_error (s->lexer, _("Undefined variable %s."),
+ lex_tokcstr (s->lexer));
goto error;
}
struct matrix_get
{
+ struct lexer *lexer;
struct matrix_lvalue *dst;
struct dataset *dataset;
struct file_handle *file;
{
if (!s->in_loop)
{
- msg (SE, _("BREAK not inside LOOP."));
+ lex_next_error (s->lexer, -1, -1, _("BREAK not inside LOOP."));
return NULL;
}
cmd->release.vars[cmd->release.n_vars++] = var;
}
else
- lex_error (s->lexer, _("Variable name expected."));
+ lex_error (s->lexer, _("Syntax error expecting variable name."));
lex_get (s->lexer);
if (!lex_match (s->lexer, T_COMMA))
if (!read->dst)
goto error;
+ int by_ofs = 0;
+ int format_ofs = 0;
+ int record_width_start = 0, record_width_end = 0;
+
int by = 0;
int repetitions = 0;
int record_width = 0;
{
lex_match (s->lexer, T_EQUALS);
+ record_width_start = lex_ofs (s->lexer);
if (!lex_force_int_range (s->lexer, "FIELD", 1, INT_MAX))
goto error;
read->c1 = lex_integer (s->lexer);
|| !lex_force_int_range (s->lexer, "TO", read->c1, INT_MAX))
goto error;
read->c2 = lex_integer (s->lexer) + 1;
+ record_width_end = lex_ofs (s->lexer);
lex_get (s->lexer);
record_width = read->c2 - read->c1;
read->c2 - read->c1))
goto error;
by = lex_integer (s->lexer);
+ by_ofs = lex_ofs (s->lexer);
+ int field_end = lex_ofs (s->lexer);
lex_get (s->lexer);
if (record_width % by)
{
- msg (SE, _("BY %d does not evenly divide record width %d."),
- by, record_width);
+ lex_ofs_error (
+ s->lexer, record_width_start, field_end,
+ _("Field width %d does not evenly divide record width %d."),
+ by, record_width);
+ lex_ofs_msg (s->lexer, SN, record_width_start, record_width_end,
+ _("This syntax designates the record width."));
+ lex_ofs_msg (s->lexer, SN, by_ofs, by_ofs,
+ _("This syntax specifies the field width."));
goto error;
}
}
{
if (seen_format)
{
- lex_sbc_only_once ("FORMAT");
+ lex_sbc_only_once (s->lexer, "FORMAT");
goto error;
}
seen_format = true;
if (lex_token (s->lexer) != T_STRING && !lex_force_id (s->lexer))
goto error;
+ format_ofs = lex_ofs (s->lexer);
const char *p = lex_tokcstr (s->lexer);
if (c_isdigit (p[0]))
{
{
msg (SE, _("SIZE is required for reading data into a full matrix "
"(as opposed to a submatrix)."));
+ msg_at (SN, read->dst->var_location,
+ _("This expression designates a full matrix."));
goto error;
}
{
msg (SE, _("%d repetitions cannot fit in record width %d."),
repetitions, record_width);
+ lex_ofs_msg (s->lexer, SN, format_ofs, format_ofs,
+ _("This syntax designates the number of repetitions."));
+ lex_ofs_msg (s->lexer, SN, record_width_start, record_width_end,
+ _("This syntax designates the record width."));
goto error;
}
int w = (repetitions ? record_width / repetitions
: by);
if (by && w != by)
{
+ msg (SE, _("This command specifies two different field widths."));
if (repetitions)
- msg (SE, _("FORMAT specifies %d repetitions with record width %d, "
- "which implies field width %d, "
- "but BY specifies field width %d."),
- repetitions, record_width, w, by);
+ {
+ lex_ofs_msg (s->lexer, SN, format_ofs, format_ofs,
+ ngettext ("This syntax specifies %d repetition.",
+ "This syntax specifies %d repetitions.",
+ repetitions),
+ repetitions);
+ lex_ofs_msg (s->lexer, SN, record_width_start, record_width_end,
+ _("This syntax designates record width %d, "
+ "which divided by %d repetitions implies "
+ "field width %d."),
+ record_width, repetitions, w);
+ }
else
- msg (SE, _("FORMAT specifies field width %d but BY specifies %d."),
- w, by);
+ lex_ofs_msg (s->lexer, SN, format_ofs, format_ofs,
+ _("This syntax specifies field width %d."), w);
+
+ lex_ofs_msg (s->lexer, SN, by_ofs, by_ofs,
+ _("This syntax specifies field width %d."), by);
goto error;
}
read->w = w;
if (!write->expression)
goto error;
+ int by_ofs = 0;
+ int format_ofs = 0;
+ int record_width_start = 0, record_width_end = 0;
+
int by = 0;
int repetitions = 0;
int record_width = 0;
{
lex_match (s->lexer, T_EQUALS);
+ record_width_start = lex_ofs (s->lexer);
+
if (!lex_force_int_range (s->lexer, "FIELD", 1, INT_MAX))
goto error;
write->c1 = lex_integer (s->lexer);
|| !lex_force_int_range (s->lexer, "TO", write->c1, INT_MAX))
goto error;
write->c2 = lex_integer (s->lexer) + 1;
+ record_width_end = lex_ofs (s->lexer);
lex_get (s->lexer);
record_width = write->c2 - write->c1;
if (!lex_force_int_range (s->lexer, "BY", 1,
write->c2 - write->c1))
goto error;
+ by_ofs = lex_ofs (s->lexer);
+ int field_end = lex_ofs (s->lexer);
by = lex_integer (s->lexer);
lex_get (s->lexer);
if (record_width % by)
{
- msg (SE, _("BY %d does not evenly divide record width %d."),
- by, record_width);
+ lex_ofs_error (
+ s->lexer, record_width_start, field_end,
+ _("Field width %d does not evenly divide record width %d."),
+ by, record_width);
+ lex_ofs_msg (s->lexer, SN, record_width_start, record_width_end,
+ _("This syntax designates the record width."));
+ lex_ofs_msg (s->lexer, SN, by_ofs, by_ofs,
+ _("This syntax specifies the field width."));
goto error;
}
}
{
if (has_format || write->format)
{
- lex_sbc_only_once ("FORMAT");
+ lex_sbc_only_once (s->lexer, "FORMAT");
goto error;
}
if (lex_token (s->lexer) != T_STRING && !lex_force_id (s->lexer))
goto error;
+ format_ofs = lex_ofs (s->lexer);
const char *p = lex_tokcstr (s->lexer);
if (c_isdigit (p[0]))
{
*/
if (repetitions > record_width)
{
- msg (SE, _("%d repetitions cannot fit in record width %d."),
- repetitions, record_width);
+ lex_ofs_msg (s->lexer, SN, format_ofs, format_ofs,
+ _("This syntax designates the number of repetitions."));
+ lex_ofs_msg (s->lexer, SN, record_width_start, record_width_end,
+ _("This syntax designates the record width."));
goto error;
}
int w = (repetitions ? record_width / repetitions
: by);
if (by && w != by)
{
+ msg (SE, _("This command specifies two different field widths."));
if (repetitions)
- msg (SE, _("FORMAT specifies %d repetitions with record width %d, "
- "which implies field width %d, "
- "but BY specifies field width %d."),
- repetitions, record_width, w, by);
+ {
+ lex_ofs_msg (s->lexer, SN, format_ofs, format_ofs,
+ ngettext ("This syntax specifies %d repetition.",
+ "This syntax specifies %d repetitions.",
+ repetitions),
+ repetitions);
+ lex_ofs_msg (s->lexer, SN, record_width_start, record_width_end,
+ _("This syntax designates record width %d, "
+ "which divided by %d repetitions implies "
+ "field width %d."),
+ record_width, repetitions, w);
+ }
else
- msg (SE, _("FORMAT specifies field width %d but BY specifies %d."),
- w, by);
+ lex_ofs_msg (s->lexer, SN, format_ofs, format_ofs,
+ _("This syntax specifies field width %d."), w);
+
+ lex_ofs_msg (s->lexer, SN, by_ofs, by_ofs,
+ _("This syntax specifies field width %d."), by);
goto error;
}
if (w && !write->format)
if (write->format && fmt_var_width (write->format) > sizeof (double))
{
- char s[FMT_STRING_LEN_MAX + 1];
- fmt_to_string (write->format, s);
- msg (SE, _("Format %s is too wide for %zu-byte matrix elements."),
- s, sizeof (double));
+ char fs[FMT_STRING_LEN_MAX + 1];
+ fmt_to_string (write->format, fs);
+ lex_ofs_error (s->lexer, format_ofs, format_ofs,
+ _("Format %s is too wide for %zu-byte matrix elements."),
+ fs, sizeof (double));
goto error;
}
*cmd = (struct matrix_command) {
.type = MCMD_GET,
.get = {
+ .lexer = s->lexer,
.dataset = s->dataset,
.user = { .treatment = MGET_ERROR },
.system = { .treatment = MGET_ERROR },
if (get->n_vars)
{
- lex_sbc_only_once ("VARIABLES");
+ lex_sbc_only_once (s->lexer, "VARIABLES");
goto error;
}
if (get->n_vars)
{
- if (!var_syntax_evaluate (get->vars, get->n_vars, dict,
+ if (!var_syntax_evaluate (get->lexer, get->vars, get->n_vars, dict,
&vars, &n_vars, PV_NUMERIC))
return;
}
{
if (dict_get_n_vars (dataset_dict (dataset)) == 0)
{
- msg_at (ME, cmd->location,
+ msg_at (SE, cmd->location,
_("The %s command cannot read an empty active file."),
command_name);
return false;
static bool
variables_changed (const char *keyword,
- const struct string_array *new,
- const struct string_array *old)
-{
- if (new->n)
- {
- if (!old->n)
- {
- msg (SE, _("%s may only be specified on MSAVE if it was specified "
- "on the first MSAVE within MATRIX."), keyword);
+ const struct string_array *new_vars,
+ const struct msg_location *new_vars_location,
+ const struct msg_location *new_location,
+ const struct string_array *old_vars,
+ const struct msg_location *old_vars_location,
+ const struct msg_location *old_location)
+{
+ if (new_vars->n)
+ {
+ if (!old_vars->n)
+ {
+ msg_at (SE, new_location,
+ _("%s may only be specified on MSAVE if it was specified "
+ "on the first MSAVE within MATRIX."), keyword);
+ msg_at (SN, old_location,
+ _("The first MSAVE in MATRIX did not specify %s."),
+ keyword);
+ msg_at (SN, new_vars_location,
+ _("This is the specification of %s on a later MSAVE."),
+ keyword);
return true;
}
- else if (!string_array_equal_case (old, new))
- {
- msg (SE, _("%s must specify the same variables each time within "
- "a given MATRIX."), keyword);
+ if (!string_array_equal_case (old_vars, new_vars))
+ {
+ msg_at (SE, new_location,
+ _("%s must specify the same variables on each MSAVE "
+ "within a given MATRIX."), keyword);
+ msg_at (SE, old_vars_location,
+ _("This is the specification of %s on the first MSAVE."),
+ keyword);
+ msg_at (SE, new_vars_location,
+ _("This is a different specification of %s on a later MSAVE."),
+ keyword);
return true;
}
}
const struct msave_common *new)
{
if (new->outfile && !fh_equal (old->outfile, new->outfile))
- msg (SE, _("OUTFILE must name the same file on each MSAVE "
- "within a single MATRIX command."));
- else if (variables_changed ("VARIABLES", &new->variables, &old->variables)
- || variables_changed ("FNAMES", &new->fnames, &old->fnames)
- || variables_changed ("SNAMES", &new->snames, &old->snames))
- msg_at (SN, old->location,
- _("This is the location of the first MSAVE command."));
- else
+ {
+ msg (SE, _("OUTFILE must name the same file on each MSAVE "
+ "within a single MATRIX command."));
+ msg_at (SN, old->outfile_location,
+ _("This is the OUTFILE on the first MSAVE command."));
+ msg_at (SN, new->outfile_location,
+ _("This is the OUTFILE on a later MSAVE command."));
+ return false;
+ }
+
+ if (!variables_changed ("VARIABLES",
+ &new->variables, new->variables_location, new->location,
+ &old->variables, old->variables_location, old->location)
+ && !variables_changed ("FNAMES",
+ &new->fnames, new->fnames_location, new->location,
+ &old->fnames, old->fnames_location, old->location)
+ && !variables_changed ("SNAMES",
+ &new->snames, new->snames_location, new->location,
+ &old->snames, old->snames_location, old->location))
return false;
return true;
{
msg_location_destroy (common->location);
fh_unref (common->outfile);
+ msg_location_destroy (common->outfile_location);
string_array_destroy (&common->variables);
+ msg_location_destroy (common->variables_location);
string_array_destroy (&common->fnames);
+ msg_location_destroy (common->fnames_location);
string_array_destroy (&common->snames);
+ msg_location_destroy (common->snames_location);
for (size_t i = 0; i < common->n_factors; i++)
matrix_expr_destroy (common->factors[i]);
}
static bool
-parse_var_names (struct lexer *lexer, struct string_array *sa)
+parse_var_names (struct lexer *lexer, struct string_array *sa,
+ struct msg_location **locationp)
{
lex_match (lexer, T_EQUALS);
string_array_clear (sa);
+ msg_location_destroy (*locationp);
+ *locationp = NULL;
struct dictionary *dict = dict_create (get_default_encoding ());
char **names;
size_t n_names;
+ int start_ofs = lex_ofs (lexer);
bool ok = parse_DATA_LIST_vars (lexer, dict, &names, &n_names,
PV_NO_DUPLICATE | PV_NO_SCRATCH);
+ int end_ofs = lex_ofs (lexer) - 1;
dict_unref (dict);
if (ok)
if (ss_equals_case (ss_cstr (names[i]), ss_cstr ("ROWTYPE_"))
|| ss_equals_case (ss_cstr (names[i]), ss_cstr ("VARNAME_")))
{
- msg (SE, _("Variable name %s is reserved."), names[i]);
+ lex_ofs_error (lexer, start_ofs, end_ofs,
+ _("Variable name %s is reserved."), names[i]);
for (size_t j = 0; j < n_names; j++)
free (names[i]);
free (names);
return false;
}
- string_array_clear (sa);
sa->strings = names;
sa->n = sa->allocated = n_names;
+ *locationp = lex_ofs_location (lexer, start_ofs, end_ofs);
}
return ok;
}
lex_match (s->lexer, T_EQUALS);
fh_unref (common->outfile);
+ int start_ofs = lex_ofs (s->lexer);
common->outfile = fh_parse (s->lexer, FH_REF_FILE, NULL);
if (!common->outfile)
goto error;
+ msg_location_destroy (common->outfile_location);
+ common->outfile_location = lex_ofs_location (s->lexer, start_ofs,
+ lex_ofs (s->lexer) - 1);
}
else if (lex_match_id (s->lexer, "VARIABLES"))
{
- if (!parse_var_names (s->lexer, &common->variables))
+ if (!parse_var_names (s->lexer, &common->variables,
+ &common->variables_location))
goto error;
}
else if (lex_match_id (s->lexer, "FNAMES"))
{
- if (!parse_var_names (s->lexer, &common->fnames))
+ if (!parse_var_names (s->lexer, &common->fnames,
+ &common->fnames_location))
goto error;
}
else if (lex_match_id (s->lexer, "SNAMES"))
{
- if (!parse_var_names (s->lexer, &common->snames))
+ if (!parse_var_names (s->lexer, &common->snames,
+ &common->snames_location))
goto error;
}
else if (lex_match_id (s->lexer, "SPLIT"))
{
if (common->fnames.n && !factors)
{
- msg (SE, _("FNAMES requires FACTOR."));
+ msg_at (SE, common->fnames_location, _("FNAMES requires FACTOR."));
goto error;
}
if (common->snames.n && !splits)
{
- msg (SE, _("SNAMES requires SPLIT."));
+ msg_at (SE, common->snames_location, _("SNAMES requires SPLIT."));
goto error;
}
if (!common->outfile)
}
static struct dictionary *
-msave_create_dict (const struct msave_common *common,
- const struct msg_location *location)
+msave_create_dict (const struct msave_common *common)
{
struct dictionary *dict = dict_create (get_default_encoding ());
const char *dup_factor = msave_add_vars (dict, &common->fnames);
if (dup_factor)
{
- msg_at (SE, location, _("Duplicate or invalid FACTOR variable name %s."),
+ msg_at (SE, common->fnames_location,
+ _("Duplicate or invalid FACTOR variable name %s."),
dup_factor);
goto error;
}
const char *dup_var = msave_add_vars (dict, &common->variables);
if (dup_var)
{
- msg_at (SE, location, _("Duplicate or invalid variable name %s."),
+ msg_at (SE, common->variables_location,
+ _("Duplicate or invalid variable name %s."),
dup_var);
goto error;
}
if (!common->writer)
{
- struct dictionary *dict = msave_create_dict (common, cmd->location);
+ struct dictionary *dict = msave_create_dict (common);
if (!dict)
goto error;
if (lex_at_phrase (s->lexer, "END MATRIX"))
{
- msg (SE, _("Premature END MATRIX within %s."), command_name);
+ lex_next_error (s->lexer, 0, 1,
+ _("Premature END MATRIX within %s."), command_name);
return false;
}
npt->missing++;
if (npt->missing > 1)
{
- lex_sbc_only_once ("MISSING");
+ lex_sbc_only_once (lexer, "MISSING");
goto lossage;
}
while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
npt->method++;
if (npt->method > 1)
{
- lex_sbc_only_once ("METHOD");
+ lex_sbc_only_once (lexer, "METHOD");
goto lossage;
}
switch (npar_method (lexer, nps))
}
if (lex_token (lexer) != T_ENDCMD)
{
- lex_error (lexer, _("expecting end of command"));
+ lex_error (lexer, _("Syntax error expecting end of command."));
goto lossage;
}
}
else
{
- lex_error (lexer, _("Expecting %s, %s, %s or a number."), "MEAN", "MEDIAN", "MODE");
+ lex_error (lexer, _("Syntax error expecting %s, %s, %s or a number."),
+ "MEAN", "MEDIAN", "MODE");
return 0;
}
}
else
{
- msg (SE, _("The post hoc analysis method %s is not supported."), lex_tokcstr (lexer));
- lex_error (lexer, NULL);
+ lex_error (lexer,
+ _("The post hoc analysis method %s is not supported."),
+ lex_tokcstr (lexer));
goto error;
}
}
}
else
{
- lex_error (lexer, _("Expecting %s or %s."),
- "CLUSTER", "DISTANCE");
+ lex_error_expecting (lexer, "CLUSTER", "DISTANCE");
return false;
}
}
const char *name = lex_tokcstr (lexer);
if (var_count >= subcase_get_n_fields (&cmd->sc))
- msg (SE, _("Too many variables in %s clause."), "INTO");
+ lex_error (lexer, _("Too many variables in %s clause."), "INTO");
else if (dict_lookup_var (cmd->dict, name) != NULL)
- msg (SE, _("Variable %s already exists."), name);
+ lex_error (lexer, _("Variable %s already exists."), name);
else if (string_set_contains (new_names, name))
- msg (SE, _("Duplicate variable name %s."), name);
+ lex_error (lexer, _("Duplicate variable name %s."), name);
else
{
string_set_insert (new_names, name);
bool variables_seen = false;
bool method_seen = false;
bool dependent_seen = false;
+ int save_start = 0;
+ int save_end = 0;
while (lex_token (lexer) != T_ENDCMD)
{
lex_match (lexer, T_SLASH);
{
if (method_seen)
{
- msg (SE, _("VARIABLES may not appear after %s"), "METHOD");
+ lex_next_error (lexer, -1, -1,
+ _("VARIABLES may not appear after %s"), "METHOD");
goto error;
}
if (dependent_seen)
{
- msg (SE, _("VARIABLES may not appear after %s"), "DEPENDENT");
+ lex_next_error (lexer, -1, -1,
+ _("VARIABLES may not appear after %s"), "DEPENDENT");
goto error;
}
variables_seen = true;
}
else if (lex_match_id (lexer, "SAVE"))
{
+ save_start = lex_ofs (lexer) - 1;
lex_match (lexer, T_EQUALS);
while (lex_token (lexer) != T_ENDCMD
goto error;
}
}
+ save_end = lex_ofs (lexer) - 1;
}
else
{
}
if (proc_make_temporary_transformations_permanent (ds))
- msg (SW, _("REGRESSION with SAVE ignores TEMPORARY. "
- "Temporary transformations will be made permanent."));
+ lex_ofs_msg (lexer, SW, save_start, save_end,
+ _("REGRESSION with SAVE ignores TEMPORARY. "
+ "Temporary transformations will be made permanent."));
if (dict_get_filter (dict))
- msg (SW, _("REGRESSION with SAVE ignores FILTER. "
- "All cases will be processed."));
+ lex_ofs_msg (lexer, SW, save_start, save_end,
+ _("REGRESSION with SAVE ignores FILTER. "
+ "All cases will be processed."));
workspace.writer = autopaging_writer_create (proto);
caseproto_unref (proto);
}
else if (lex_match_id (lexer, "STATISTICS"))
{
+ int statistics_start = lex_ofs (lexer) - 1;
lex_match (lexer, T_EQUALS);
- msg (SW, _("The STATISTICS subcommand is not yet implemented. "
- "No statistics will be produced."));
while (lex_match (lexer, T_ID))
continue;
+ int statistics_end = lex_ofs (lexer) - 1;
+
+ lex_ofs_msg (lexer, SW, statistics_start, statistics_end,
+ _("The STATISTICS subcommand is not yet implemented. "
+ "No statistics will be produced."));
}
else
{
tt.mode = MODE_INDEP;
lex_match (lexer, T_EQUALS);
+ int groups_start = lex_ofs (lexer);
if (NULL == (gvar = parse_variable (lexer, dict)))
goto exit;
cut = false;
n = 0;
}
+ int groups_end = lex_ofs (lexer) - 1;
if (n != 2 && var_is_alpha (gvar))
{
- msg (SE, _("When applying %s to a string variable, two "
- "values must be specified."), "GROUPS");
+ lex_ofs_error (lexer, groups_start, groups_end,
+ _("When applying %s to a string variable, two "
+ "values must be specified."), "GROUPS");
goto exit;
}
}
if (tt.n_vars > 0)
{
- msg (SE, _("%s subcommand may not be used with %s."), "VARIABLES", "PAIRS");
+ lex_next_error (lexer, -1, -1,
+ _("%s subcommand may not be used with %s."),
+ "VARIABLES", "PAIRS");
goto exit;
}
{
if (tt.mode == MODE_PAIRED)
{
- msg (SE, _("%s subcommand may not be used with %s."), "VARIABLES", "PAIRS");
+ lex_next_error (lexer, -1, -1,
+ _("%s subcommand may not be used with %s."),
+ "VARIABLES", "PAIRS");
goto exit;
}
*format = fp_formats[i].format;
return true;
}
- lex_error (lexer, "expecting floating-point format identifier");
+ lex_error (lexer, "Syntax error expecting floating-point format identifier.");
return false;
}
{
if (!lex_is_number (lexer))
{
- lex_error (lexer, _("expecting weight value"));
+ lex_error (lexer, _("Syntax error expecting weight value."));
return false;
}
weight = lex_tokval (lexer);
if (-1 == chdir (path))
{
int err = errno;
- msg (SE, _("Cannot change directory to %s: %s"), path,
- strerror (err));
+ lex_error (lexer, _("Cannot change directory to %s: %s"), path,
+ strerror (err));
goto error;
}
if (lex_match (lexer, T_ALL))
return CMD_SUCCESS;
- msg (SW, _("Only %s is currently implemented."), "USE ALL");
+ lex_msg (lexer, SW, _("Only %s is currently implemented."), "USE ALL");
return CMD_FAILURE;
}
#define N_(msgid) msgid
\f
#if !HAVE_FORK
+#define TIME_LIMIT_SUPPORTED 0
static bool
run_commands (const struct string_array *commands, double time_limit)
{
- if (time_limit != DBL_MAX)
- {
- msg (SE, _("Time limit not supported on this platform."));
- return false;
- }
+ assert (time_limit == DBL_MAX);
for (size_t i = 0; i < commands->n; i++)
{
return true;
}
#else
+#define TIME_LIMIT_SUPPORTED 1
static bool
run_command (const char *command, struct timespec timeout)
{
{
if (settings_get_safer_mode ())
{
- msg (SE, _("This command not allowed when the %s option is set."), "SAFER");
+ lex_next_error (lexer, -1, -1,
+ _("This command not allowed when the %s option is set."),
+ "SAFER");
return CMD_FAILURE;
}
double time_limit = DBL_MAX;
if (lex_match_id (lexer, "TIMELIMIT"))
{
+ int time_limit_start = lex_ofs (lexer) - 1;
if (!lex_force_match (lexer, T_EQUALS)
|| !lex_force_num (lexer))
{
double num = lex_number (lexer);
lex_get (lexer);
time_limit = num < 0.0 ? 0.0 : num;
+
+ int time_limit_end = lex_ofs (lexer) - 1;
+ if (!TIME_LIMIT_SUPPORTED)
+ {
+ lex_ofs_error (lexer, time_limit_start, time_limit_end,
+ _("Time limit not supported on this platform."));
+ string_array_destroy (&commands);
+ return false;
+ }
}
enum cmd_result result = lex_end_of_command (lexer);
int
cmd_permissions (struct lexer *lexer, struct dataset *ds UNUSED)
{
+ if (settings_get_safer_mode ())
+ {
+ lex_next_error (lexer, -1, -1,
+ _("This command not allowed when the %s option is set."),
+ "SAFER");
+ return 0;
+ }
+
char *fn = NULL;
const char *str = NULL;
lex_match (lexer, T_SLASH);
struct stat buf;
mode_t mode;
- if (settings_get_safer_mode ())
- {
- msg (SE, _("This command not allowed when the %s option is set."), "SAFER");
- return 0;
- }
-
locale_file_name = utf8_to_filename (file_name);
if (-1 == stat(locale_file_name, &buf))
{
#include "language/command.h"
#include "language/lexer/format-parser.h"
#include "language/lexer/lexer.h"
+#include "language/lexer/token.h"
#include "libpspp/assertion.h"
#include "libpspp/compiler.h"
#include "libpspp/copyleft.h"
return false;
}
+static int
+subcommand_start_ofs (struct lexer *lexer)
+{
+ int ofs = lex_ofs (lexer) - 1;
+ return lex_ofs_token (lexer, ofs)->type == T_EQUALS ? ofs - 1 : ofs;
+}
+
static int
parse_enum_valist (struct lexer *lexer, va_list args)
{
"OFF", false, "NO", false);
}
-static bool
-force_parse_int (struct lexer *lexer, int *integerp)
-{
- if (!lex_force_int (lexer))
- return false;
- *integerp = lex_integer (lexer);
- lex_get (lexer);
- return true;
-}
-
static bool
parse_output_routing (struct lexer *lexer, enum settings_output_type type)
{
static bool
parse_unimplemented (struct lexer *lexer, const char *name)
{
- msg (SW, _("%s is not yet implemented."), name);
+ int start = subcommand_start_ofs (lexer);
if (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
lex_get (lexer);
+ int end = lex_ofs (lexer) - 1;
+
+ lex_ofs_msg (lexer, SW, start, end, _("%s is not yet implemented."), name);
return true;
}
}
else
{
- lex_error (lexer, _("expecting %s or year"), "AUTOMATIC");
+ lex_error (lexer, _("Syntax error expecting %s or year."), "AUTOMATIC");
return false;
}
static bool
parse_FORMAT (struct lexer *lexer)
{
+ int start = subcommand_start_ofs (lexer);
struct fmt_spec fmt;
- lex_match (lexer, T_EQUALS);
if (!parse_format_specifier (lexer, &fmt))
return false;
if (!fmt_check_output (&fmt))
return false;
+ int end = lex_ofs (lexer) - 1;
if (fmt_is_string (fmt.type))
{
char str[FMT_STRING_LEN_MAX + 1];
- msg (SE, _("%s requires numeric output format as an argument. "
- "Specified format %s is of type string."),
- "FORMAT",
- fmt_to_string (&fmt, str));
+ lex_ofs_error (lexer, start, end,
+ _("%s requires numeric output format as an argument. "
+ "Specified format %s is of type string."),
+ "FORMAT", fmt_to_string (&fmt, str));
return false;
}
set_default_encoding (s);
else if (!set_encoding_from_locale (s))
{
- msg (ME, _("%s is not a recognized encoding or locale name"), s);
+ lex_error (lexer, _("%s is not a recognized encoding or locale name"), s);
return false;
}
static bool
parse_MXERRS (struct lexer *lexer)
{
- int n;
- if (!force_parse_int (lexer, &n))
+ if (!lex_force_int_range (lexer, "MXERRS", 1, INT_MAX))
return false;
-
- if (n >= 1)
- settings_set_max_messages (MSG_S_ERROR, n);
- else
- msg (SE, _("%s must be at least 1."), "MXERRS");
+ settings_set_max_messages (MSG_S_ERROR, lex_integer (lexer));
+ lex_get (lexer);
return true;
}
static bool
parse_MXLOOPS (struct lexer *lexer)
{
- int n;
- if (!force_parse_int (lexer, &n))
+ if (!lex_force_int_range (lexer, "MXLOOPS", 1, INT_MAX))
return false;
-
- if (n >= 1)
- settings_set_mxloops (n);
- else
- msg (SE, _("%s must be at least 1."), "MXLOOPS");
+ settings_set_mxloops (lex_integer (lexer));
+ lex_get (lexer);
return true;
}
static bool
parse_MXWARNS (struct lexer *lexer)
{
- int n;
- if (!force_parse_int (lexer, &n))
+ if (!lex_force_int_range (lexer, "MXWARNS", 0, INT_MAX))
return false;
-
- if (n >= 0)
- settings_set_max_messages (MSG_S_WARNING, n);
- else
- msg (SE, _("%s must not be negative."), "MXWARNS");
+ settings_set_max_messages (MSG_S_WARNING, lex_integer (lexer));
+ lex_get (lexer);
return true;
}
static int n_saved_settings;
int
-cmd_preserve (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
+cmd_preserve (struct lexer *lexer, struct dataset *ds UNUSED)
{
if (n_saved_settings < MAX_SAVED_SETTINGS)
{
}
else
{
- msg (SE, _("Too many %s commands without a %s: at most "
- "%d levels of saved settings are allowed."),
- "PRESERVE", "RESTORE",
- MAX_SAVED_SETTINGS);
+ lex_next_error (lexer, -1, -1,
+ _("Too many %s commands without a %s: at most "
+ "%d levels of saved settings are allowed."),
+ "PRESERVE", "RESTORE",
+ MAX_SAVED_SETTINGS);
return CMD_CASCADING_FAILURE;
}
}
int
-cmd_restore (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
+cmd_restore (struct lexer *lexer, struct dataset *ds UNUSED)
{
if (n_saved_settings > 0)
{
}
else
{
- msg (SE, _("%s without matching %s."), "RESTORE", "PRESERVE");
+ lex_next_error (lexer, -1, -1,
+ _("%s without matching %s."), "RESTORE", "PRESERVE");
return CMD_FAILURE;
}
}
lvalue->vector = dict_lookup_vector (dict, lex_tokcstr (lexer));
if (lvalue->vector == NULL)
{
- msg (SE, _("There is no vector named %s."), lex_tokcstr (lexer));
+ lex_error (lexer, _("There is no vector named %s."),
+ lex_tokcstr (lexer));
goto lossage;
}
{
if (var_is_alpha (dv->var))
{
- msg (SE, _("Destination cannot be a string variable."));
+ lex_error (lexer, _("Destination cannot be a string variable."));
goto fail;
}
}
if (trns->src_type != VAL_STRING
|| (have_dst_type && trns->dst_type != VAL_NUMERIC))
{
- msg (SE, _("CONVERT requires string input values and "
- "numeric output values."));
+ lex_next_error (lexer, -1, -1,
+ _("CONVERT requires string input values and "
+ "numeric output values."));
return false;
}
}
if (lex_token (lexer) == T_ID
&& lex_id_match (ss_cstr ("THRU"), lex_tokss (lexer)))
{
- msg (SE, _("%s is not allowed with string variables."), "THRU");
+ lex_error (lexer, _("%s is not allowed with string variables."),
+ "THRU");
return false;
}
}
}
else
{
- lex_error (lexer, _("expecting output value"));
+ lex_error (lexer, _("Syntax error expecting output value."));
return false;
}
return true;
const struct variable *v = trns->dst_vars[i];
if (v != NULL && var_get_type (v) != trns->dst_type)
{
- msg (SE, _("Type mismatch. Cannot store %s data in "
- "%s variable %s."),
- trns->dst_type == VAL_STRING ? _("string") : _("numeric"),
- var_is_alpha (v) ? _("string") : _("numeric"),
- var_get_name (v));
+ if (trns->dst_type == VAL_STRING)
+ msg (SE, _("Type mismatch. Cannot store string data in "
+ "numeric variable %s."), var_get_name (v));
+ else
+ msg (SE, _("Type mismatch. Cannot store numeric data in "
+ "string variable %s."), var_get_name (v));
return false;
}
}
unsigned long max = gsl_rng_max (get_rng ());
type = TYPE_FRACTION;
- if (lex_tokval (lexer) <= 0 || lex_tokval (lexer) >= 1)
- {
- msg (SE, _("The sampling factor must be between 0 and 1 "
- "exclusive."));
- return CMD_FAILURE;
- }
+ if (!lex_force_num_range_open (lexer, "SAMPLE", 0, 1))
+ return CMD_FAILURE;
frac = lex_tokval (lexer) * (max - min) + min;
a = b = 0;
if (lex_token (lexer) != T_ENDCMD)
{
expr_free (e);
- lex_error (lexer, _("expecting end of command"));
+ lex_error (lexer, _("Syntax error expecting end of command."));
return CMD_CASCADING_FAILURE;
}
struct dictionary *dict = dataset_dict (ds);
if (lex_match_id (lexer, "OFF"))
dict_set_filter (dict, NULL);
- else if (lex_token (lexer) == T_ENDCMD)
+ else if (lex_match (lexer, T_BY))
{
- msg (SW, _("Syntax error expecting OFF or BY. "
- "Turning off case filtering."));
- dict_set_filter (dict, NULL);
- }
- else
- {
- struct variable *v;
-
- lex_match (lexer, T_BY);
- v = parse_variable (lexer, dict);
+ struct variable *v = parse_variable (lexer, dict);
if (!v)
return CMD_FAILURE;
if (var_is_alpha (v))
{
- msg (SE, _("The filter variable must be numeric."));
+ lex_next_error (lexer, -1, -1,
+ _("The filter variable must be numeric."));
return CMD_FAILURE;
}
if (dict_class_from_id (var_get_name (v)) == DC_SCRATCH)
{
- msg (SE, _("The filter variable may not be scratch."));
+ lex_next_error (lexer, -1, -1,
+ _("The filter variable may not be scratch."));
return CMD_FAILURE;
}
dict_set_filter (dict, v);
}
+ else
+ {
+ lex_error_expecting (lexer, "OFF", "BY");
+ return CMD_FAILURE;
+ }
return CMD_SUCCESS;
}
void (*output_msg) (const struct msg *, void *aux);
void *aux;
- void (*lex_source_ref) (const struct lex_source *);
+ struct lex_source *(*lex_source_ref) (const struct lex_source *);
void (*lex_source_unref) (struct lex_source *);
struct substring (*lex_source_get_line) (const struct lex_source *,
int line);
dnl
AT_BANNER([command parser])
+AT_SETUP([command parser negative tests])
+AT_DATA([command.sps], [dnl
+DATA X.
+XYZZY.
+CLOSE FILE XYZZY.
+foo.
+])
+AT_CHECK([pspp command.sps], [1], [dnl
+command.sps:1.1-1.6: error: Unknown command `DATA X'.
+ 1 | DATA X.
+ | ^~~~~~
+
+command.sps:2.1-2.5: error: Unknown command `XYZZY'.
+ 2 | XYZZY.
+ | ^~~~~
+
+command.sps:3.1-3.16: error: Unknown command `CLOSE FILE XYZZY'.
+ 3 | CLOSE FILE XYZZY.
+ | ^~~~~~~~~~~~~~~~
+
+command.sps:4.1-4.3: error: Unknown command `foo'.
+ 4 | foo.
+ | ^~~
+])
+AT_CLEANUP
+
dnl Tests for a bug which crashed pspp when given certain invalid input.
AT_SETUP([command parser crash bug])
AT_DATA([command.sps], [dnl
EXECUTE.
])
AT_CHECK([pspp -O format=csv command.sps], [1], [dnl
-command.sps:1: error: Unknown command `DATA rubbish'.
+"command.sps:1.1-1.12: error: Unknown command `DATA rubbish'.
+ 1 | DATA rubbish.
+ | ^~~~~~~~~~~~"
-command.sps:2: error: EXECUTE: EXECUTE is allowed only after the active dataset has been defined.
+"command.sps:2.1-2.7: error: EXECUTE: EXECUTE is allowed only after the active dataset has been defined.
+ 2 | EXECUTE.
+ | ^~~~~~~"
])
AT_CLEANUP
dnl Tests for a bug where FINISH or EXIT wasn't executed until the lexer
dnl read the first token of the next command.
dnl
-dnl (If this reecurs, the test will run forever.)
+dnl (If this recurs, the test will run forever.)
AT_SETUP([FINISH executes immediately])
AT_CHECK([(echo "FINISH."; while echo ; do true; done) | pspp], [0], [ignore], [ignore])
AT_CLEANUP
define.sps:8.18: error: DEBUG EXPAND: Reached end of command expecting 1 more
token in argument !3 to macro !p.
+ 8 | !p a1 a2 b1 b2 c1.
+ | ^
(a1 a2, b1 b2, c1)
define.sps:10.12: error: DEBUG EXPAND: Reached end of command expecting 1 more
token in argument !2 to macro !p.
+ 10 | !p a1 a2 b1.
+ | ^
(a1 a2, b1, z)
define.sps:12.6: error: DEBUG EXPAND: Reached end of command expecting 1 more
token in argument !1 to macro !p.
+ 12 | !p a1.
+ | ^
(a1, y, z)
define.sps:8.9: error: DEBUG EXPAND: Reached end of command expecting ":" in
argument !3 to macro !p.
+ 8 | !p a,b;c.
+ | ^
(a, b, c)
define.sps:10.7: error: DEBUG EXPAND: Reached end of command expecting ";" in
argument !2 to macro !p.
+ 10 | !p a,b.
+ | ^
(a, b, z)
define.sps:12.5: error: DEBUG EXPAND: Reached end of command expecting "," in
argument !1 to macro !p.
+ 12 | !p a.
+ | ^
(a, y, z)
define.sps:8.12: error: DEBUG EXPAND: Reached end of command expecting "}" in
argument !3 to macro !p.
+ 8 | !p (a)<b>{c.
+ | ^
(a, b, c)
define.sps:9.11: error: DEBUG EXPAND: Reached end of command expecting "}" in
argument !3 to macro !p.
+ 9 | !p (a)<b>{.
+ | ^
(a, b, )
define.sps:11.9: error: DEBUG EXPAND: Reached end of command expecting ">" in
argument !2 to macro !p.
+ 11 | !p (a)<b.
+ | ^
(a, b, z)
define.sps:12.8: error: DEBUG EXPAND: Reached end of command expecting ">" in
argument !2 to macro !p.
+ 12 | !p (a)<.
+ | ^
(a, , z)
define.sps:14.6: error: DEBUG EXPAND: Reached end of command expecting ")" in
argument !1 to macro !p.
+ 14 | !p (a.
+ | ^
(a, y, z)
define.sps:15.5: error: DEBUG EXPAND: Reached end of command expecting ")" in
argument !1 to macro !p.
+ 15 | !p (.
+ | ^
(, y, z)
DEFINE !macro(!x !TOKENS(1).
])
AT_CHECK([pspp -O format=csv define.sps], [1], [dnl
-"define.sps:1.15-1.16: error: DEFINE: Syntax error at `!x': Keyword macro parameter must be named in definition without ""!"" prefix."
+"define.sps:1.15-1.16: error: DEFINE: Keyword macro parameter must be named in definition without ""!"" prefix.
+ 1 | DEFINE !macro@{:@!x !TOKENS(1).
+ | ^~"
])
AT_CLEANUP
DEFINE !macro(if=!TOKENS(1).
])
AT_CHECK([pspp -O format=csv define.sps], [1], [dnl
-"define.sps:1.15-1.16: error: DEFINE: Syntax error at `if': Cannot use macro keyword ""if"" as an argument name."
+"define.sps:1.15-1.16: error: DEFINE: Cannot use macro keyword ""if"" as an argument name.
+ 1 | DEFINE !macro@{:@if=!TOKENS(1).
+ | ^~"
])
AT_CLEANUP
AT_CHECK([pspp --testing-mode define.sps], [1], [dnl
define.sps:3.8: error: DEBUG EXPAND: Found `.' while expecting `=' reading
argument !arg1 to macro !k.
+ 3 | !k arg1.
+ | ^
k( )
define.sps:4.9: error: DEBUG EXPAND: Reached end of command expecting 1 more
token in argument !arg1 to macro !k.
+ 4 | !k arg1=.
+ | ^
k( )
])
AT_CHECK([pspp --testing-mode define.sps], [1], [dnl
define.sps:6.8: error: DEBUG EXPAND: Found `.' while expecting `=' reading
argument !arg1 to macro !k.
+ 6 | !k arg1.
+ | ^
k(, )
define.sps:7.9: error: DEBUG EXPAND: Reached end of command expecting "/" in
argument !arg1 to macro !k.
+ 7 | !k arg1=.
+ | ^
k(, )
define.sps:8.10: error: DEBUG EXPAND: Reached end of command expecting "/" in
argument !arg1 to macro !k.
+ 8 | !k arg1=x.
+ | ^
k(x, )
define.sps:9.18: error: DEBUG EXPAND: Reached end of command expecting "/" in
argument !arg2 to macro !k.
+ 9 | !k arg1=x/ arg2=y.
+ | ^
k(x, y)
])
AT_CHECK([pspp --testing-mode define.sps], [1], [dnl
define.sps:6.8: error: DEBUG EXPAND: Found `.' while expecting `=' reading
argument !arg1 to macro !k.
+ 6 | !k arg1.
+ | ^
k(, )
define.sps:7.9: error: DEBUG EXPAND: Found `.' while expecting `@{:@' reading
argument !arg1 to macro !k.
+ 7 | !k arg1=.
+ | ^
k(, )
define.sps:8.9: error: DEBUG EXPAND: Found `x' while expecting `@{:@' reading
argument !arg1 to macro !k.
+ 8 | !k arg1=x.
+ | ^
k(, )
define.sps:9.11: error: DEBUG EXPAND: Reached end of command expecting "@:}@" in
argument !arg1 to macro !k.
+ 9 | !k arg1=@{:@x.
+ | ^
k(x, )
define.sps:10.17: error: DEBUG EXPAND: Found `.' while expecting `=' reading
argument !arg2 to macro !k.
+ 10 | !k arg1=(x) arg2.
+ | ^
k(x, )
define.sps:11.18: error: DEBUG EXPAND: Found `.' while expecting `{' reading
argument !arg2 to macro !k.
+ 11 | !k arg1=(x) arg2=.
+ | ^
k(x, )
define.sps:12.18: error: DEBUG EXPAND: Found `y' while expecting `{' reading
argument !arg2 to macro !k.
+ 12 | !k arg1=(x) arg2=y.
+ | ^
k(x, )
define.sps:13.18: error: DEBUG EXPAND: Found `@{:@' while expecting `{' reading
argument !arg2 to macro !k.
+ 13 | !k arg1=(x) arg2=@{:@y.
+ | ^
k(x, )
define.sps:1-10: At `"ba' in the expansion of `!s',dnl "
define.sps:12.1-12.2: error: DEBUG EXPAND: Unterminated string constant.
+ 12 | !s.
+ | ^~
nana.
nan.
define.sps:1-3: inside the expansion of `!macro',
define.sps:1-3: inside the expansion of `!macro',
define.sps:1-3: inside the expansion of `!macro',
-define.sps:4.1-4.6: error: DEFINE: Maximum nesting level 50 exceeded. (Use SET MNEST to change the limit.)"
+define.sps:4.1-4.6: error: DEFINE: Maximum nesting level 50 exceeded. (Use SET MNEST to change the limit.)
+ 4 | !macro.
+ | ^~~~~~"
-define.sps:4.1-4.6: error: Syntax error at `!macro' (in expansion of `!macro'): expecting command name.
+"define.sps:4.1-4.6: error: In syntax expanded from `!macro': Syntax error expecting command name.
+ 4 | !macro.
+ | ^~~~~~"
])
AT_CLEANUP
define.sps:1-3: At `!x' in the expansion of `!for',
define.sps:10.1-10.12: error: DEBUG EXPAND: Cannot use argument name or macro
keyword as !DO variable.
+ 10 | !for x=1 y=5.
+ | ^~~~~~~~~~~~
!DO 1 = 1 !TO 5 !var !DOEND.
define.sps:5-7: At `!noexpand' in the expansion of `!for2',
define.sps:11.1-11.13: error: DEBUG EXPAND: Cannot use argument name or macro
keyword as !DO variable.
+ 11 | !for2 x=1 y=5.
+ | ^~~~~~~~~~~~~
!DO !noexpand = 1 !TO 5 !var !DOEND.
])
define.sps:3-5: inside the expansion of `!for',
define.sps:14.1-14.8: error: DEBUG EXPAND: Numerical !DO loop exceeded maximum
number of iterations 3. (Use SET MITERATE to change the limit.)
+ 14 | !for 1 5.
+ | ^~~~~~~~
1 2 3 4.
define.sps:7-9: inside the expansion of `!forby',
define.sps:15.1-15.12: error: DEBUG EXPAND: Numerical !DO loop exceeded maximum
number of iterations 3. (Use SET MITERATE to change the limit.)
+ 15 | !forby 1 5 1.
+ | ^~~~~~~~~~~~
1 2 3 4.
define.sps:7-9: inside the expansion of `!forby',
define.sps:23.1-23.13: error: DEBUG EXPAND: Numerical !DO loop exceeded maximum
number of iterations 3. (Use SET MITERATE to change the limit.)
+ 23 | !forby 5 1 -1.
+ | ^~~~~~~~~~~~~
5 4 3 2.
define.sps:1-3: inside the expansion of `!for',
define.sps:7.1-7.10: error: DEBUG EXPAND: !DO loop over list exceeded maximum
number of iterations 2. (Use SET MITERATE to change the limit.)
+ 7 | !for a b c.
+ | ^~~~~~~~~~
( (a) (b) ).
define.sps:1-3: inside the expansion of `!for',
define.sps:8.1-8.23: error: DEBUG EXPAND: !DO loop over list exceeded maximum
number of iterations 2. (Use SET MITERATE to change the limit.)
+ 8 | !for 'foo bar baz quux'.
+ | ^~~~~~~~~~~~~~~~~~~~~~~
( (foo) (bar) ).
])
AT_CHECK([pspp --testing-mode define.sps -O format=csv], [1], [dnl
"define.sps:1-3: At `!x' in the expansion of `!macro',
-define.sps:10.1-10.10: error: DEBUG EXPAND: Cannot use argument name or macro keyword ""!x"" as !LET variable."
+define.sps:10.1-10.10: error: DEBUG EXPAND: Cannot use argument name or macro keyword ""!x"" as !LET variable.
+ 10 | !macro x=1.
+ | ^~~~~~~~~~"
!LET 1 = 1
"define.sps:5-7: At `!do' in the expansion of `!macro2',
-define.sps:11.1-11.7: error: DEBUG EXPAND: Cannot use argument name or macro keyword ""!do"" as !LET variable."
+define.sps:11.1-11.7: error: DEBUG EXPAND: Cannot use argument name or macro keyword ""!do"" as !LET variable.
+ 11 | !macro2.
+ | ^~~~~~~"
"define.sps:5-7: At `=' in the expansion of `!macro2',
-define.sps:11.1-11.7: error: DEBUG EXPAND: Expected macro variable name following !DO."
+define.sps:11.1-11.7: error: DEBUG EXPAND: Expected macro variable name following !DO.
+ 11 | !macro2.
+ | ^~~~~~~"
!LET !do = x
])
COMPUTE x = !vars x.
])
AT_CHECK([pspp -O format=csv define.sps], [1], [dnl
-define.sps:3.13-3.19: error: COMPUTE: Syntax error at `b' (in expansion of `!vars x'): expecting end of command.
+"define.sps:3.13-3.19: error: COMPUTE: In syntax expanded from `!vars x': Syntax error expecting end of command.
+ 3 | COMPUTE x = !vars x.
+ | ^~~~~~~"
])
AT_CLEANUP
define.sps:3: At `x' in the expansion of `!c',
define.sps:20.1-20.2: error: DEBUG EXPAND: `,' or `@:}@' expected in call to macro
function !SUBSTR.
+ 20 | !c.
+ | ^~
!SUBSTR(1 x)
define.sps:4: In the expansion of `!d',
define.sps:21.1-21.2: error: DEBUG EXPAND: Missing `@:}@' in call to macro
function !SUBSTR.
+ 21 | !d.
+ | ^~
!SUBSTR@{:@1
define.sps:5: In the expansion of `!narg_blanks',
define.sps:22.1-22.12: error: DEBUG EXPAND: Macro function !BLANKS takes one
argument (not 0).
+ 22 | !narg_blanks.
+ | ^~~~~~~~~~~~
!BLANKS( )
define.sps:6: In the expansion of `!narg_concat',
define.sps:23.1-23.12: error: DEBUG EXPAND: Macro function !CONCAT needs at
least one argument.
+ 23 | !narg_concat.
+ | ^~~~~~~~~~~~
!CONCAT( )
define.sps:7: In the expansion of `!narg_eval',
define.sps:24.1-24.10: error: DEBUG EXPAND: Macro function !EVAL takes one
argument (not 0).
+ 24 | !narg_eval.
+ | ^~~~~~~~~~
!EVAL( )
define.sps:8: In the expansion of `!narg_head',
define.sps:25.1-25.10: error: DEBUG EXPAND: Macro function !HEAD takes one
argument (not 0).
+ 25 | !narg_head.
+ | ^~~~~~~~~~
!HEAD( )
define.sps:9: In the expansion of `!narg_index',
define.sps:26.1-26.11: error: DEBUG EXPAND: Macro function !INDEX takes two
arguments (not 0).
+ 26 | !narg_index.
+ | ^~~~~~~~~~~
!INDEX( )
define.sps:10: In the expansion of `!narg_length',
define.sps:27.1-27.12: error: DEBUG EXPAND: Macro function !LENGTH takes one
argument (not 0).
+ 27 | !narg_length.
+ | ^~~~~~~~~~~~
!LENGTH( )
define.sps:12: In the expansion of `!narg_quote',
define.sps:29.1-29.11: error: DEBUG EXPAND: Macro function !QUOTE takes one
argument (not 0).
+ 29 | !narg_quote.
+ | ^~~~~~~~~~~
!QUOTE( )
define.sps:13: In the expansion of `!narg_substr',
define.sps:30.1-30.12: error: DEBUG EXPAND: Macro function !SUBSTR takes two or
three arguments (not 0).
-
+ 30 | !narg_substr.
+ | ^~~~~~~~~~~~
+
!SUBSTR( )
define.sps:14: In the expansion of `!narg_tail',
define.sps:31.1-31.10: error: DEBUG EXPAND: Macro function !TAIL takes one
argument (not 0).
+ 31 | !narg_tail.
+ | ^~~~~~~~~~
!TAIL( )
define.sps:15: In the expansion of `!narg_unquote',
define.sps:32.1-32.13: error: DEBUG EXPAND: Macro function !UNQUOTE takes one
argument (not 0).
+ 32 | !narg_unquote.
+ | ^~~~~~~~~~~~~
!UNQUOTE( )
define.sps:16: In the expansion of `!narg_upcase',
define.sps:33.1-33.12: error: DEBUG EXPAND: Macro function !UPCASE takes one
argument (not 0).
+ 33 | !narg_upcase.
+ | ^~~~~~~~~~~~
!UPCASE( )
])
define.sps:1: In the expansion of `!a',
define.sps:5.1-5.2: error: DEBUG EXPAND: Argument to !BLANKS must be non-
negative integer (not "x").
+ 5 | !a.
+ | ^~
!BLANKS(x).
define.sps:2: In the expansion of `!b',
define.sps:6.1-6.2: error: DEBUG EXPAND: Second argument of !SUBSTR must be
positive integer (not "y").
+ 6 | !b.
+ | ^~
!SUBSTR(x, y).
define.sps:3: In the expansion of `!c',
define.sps:7.1-7.2: error: DEBUG EXPAND: Third argument of !SUBSTR must be non-
negative integer (not "z").
+ 7 | !c.
+ | ^~
!SUBSTR(x, 1, z).
])
AT_CHECK([pspp --testing-mode define.sps], [1], [dnl
define.sps:1-2: At `.' in the expansion of `!a',
define.sps:5.1-5.2: error: DEBUG EXPAND: Expecting ')' in macro expression.
+ 5 | !a.
+ | ^~
!LET !x = (1.
define.sps:2: inside the expansion of `!b',
define.sps:6.1-6.2: error: DEBUG EXPAND: Macro expression must evaluate to a
number (not "x").
+ 6 | !b.
+ | ^~
!DO !x = x.
define.sps:3: At `)' in the expansion of `!c',
define.sps:7.1-7.2: error: DEBUG EXPAND: Expecting literal or function
invocation in macro expression.
+ 7 | !c.
+ | ^~
!LET !x = ( ).
])
AT_CHECK([pspp --testing-mode define.sps], [1], [dnl
define.sps:1: In the expansion of `!a',
define.sps:5.1-5.2: error: DEBUG EXPAND: !THEN expected in macro !IF construct.
+ 5 | !a.
+ | ^~
!IF 1
define.sps:2: In the expansion of `!b',
define.sps:6.1-6.2: error: DEBUG EXPAND: !ELSE or !IFEND expected in macro !IF
construct.
+ 6 | !b.
+ | ^~
!IF 1 !THEN
define.sps:3: In the expansion of `!c',
define.sps:7.1-7.2: error: DEBUG EXPAND: !IFEND expected in macro !IF
construct.
+ 7 | !c.
+ | ^~
!IF 1 !THEN !ELSE
])
define.sps:1: In the expansion of `!a',
define.sps:6.1-6.2: error: DEBUG EXPAND: Expected macro variable name following
!LET.
+ 6 | !a.
+ | ^~
!LET
define.sps:2: At `0' in the expansion of `!b',
define.sps:7.1-7.2: error: DEBUG EXPAND: Expected macro variable name following
!LET.
+ 7 | !b.
+ | ^~
!LET 0
define.sps:3: In the expansion of `!c',
define.sps:8.1-8.2: error: DEBUG EXPAND: Expected `=' following !LET.
+ 8 | !c.
+ | ^~
!LET !x
define.sps:4: At `y' in the expansion of `!d',
define.sps:9.1-9.2: error: DEBUG EXPAND: Expected `=' following !LET.
+ 9 | !d.
+ | ^~
!LET !x y
])
define.sps:1: In the expansion of `!a',
define.sps:12.1-12.2: error: DEBUG EXPAND: Expected macro variable name
following !DO.
+ 12 | !a.
+ | ^~
!DO
define.sps:2: At `0' in the expansion of `!b',
define.sps:13.1-13.2: error: DEBUG EXPAND: Expected macro variable name
following !DO.
+ 13 | !b.
+ | ^~
!DO 0
define.sps:3: In the expansion of `!c',
define.sps:14.1-14.2: error: DEBUG EXPAND: Expected `=' or !IN in !DO loop.
+ 14 | !c.
+ | ^~
!DO !x
In the expansion of `!DO',
define.sps:4: inside the expansion of `!d',
define.sps:15.1-15.2: error: DEBUG EXPAND: Missing !DOEND.
+ 15 | !d.
+ | ^~
!DO !x !in(x)
define.sps:5: inside the expansion of `!e',
define.sps:16.1-16.2: error: DEBUG EXPAND: Macro expression must evaluate to a
number (not "x").
+ 16 | !e.
+ | ^~
!DO !x = x.
At `x' in the expansion of `!DO',
define.sps:6: inside the expansion of `!f',
define.sps:17.1-17.2: error: DEBUG EXPAND: Expected !TO in numerical !DO loop.
+ 17 | !f.
+ | ^~
!DO !x = 5 x
In the expansion of `!DO',
define.sps:7: inside the expansion of `!g',
define.sps:18.1-18.2: error: DEBUG EXPAND: !BY value cannot be zero.
+ 18 | !g.
+ | ^~
!DO !x = 5 !TO 6 !BY 0
define.sps:8: In the expansion of `!h',
define.sps:19.1-19.2: error: DEBUG EXPAND: Expected `=' or !IN in !DO loop.
+ 19 | !h.
+ | ^~
!DO !x
define.sps:9: At `0' in the expansion of `!i',
define.sps:20.1-20.2: error: DEBUG EXPAND: Expected `=' or !IN in !DO loop.
+ 20 | !i.
+ | ^~
!DO !x 0
define.sps:10: At `!BREAK' in the expansion of `!j',
define.sps:21.1-21.2: error: DEBUG EXPAND: !BREAK outside !DO.
+ 21 | !j.
+ | ^~
])
AT_CLEANUP
DEFINE !macro()
])
AT_CHECK([pspp define.sps], [1], [dnl
-define.sps:1.36-1.40: error: DEFINE: Syntax error at `'x y'': String must
-contain exactly one token.
-
-define.sps:2.40-2.46: error: DEFINE: Syntax error at `!TOKENS': Positional
-parameters must precede keyword parameters.
-
-define.sps:3.15-3.16: error: DEFINE: Syntax error at `!a': Keyword macro
-parameter must be named in definition without "!" prefix.
-
-define.sps:4.15-4.16: error: DEFINE: Syntax error at `do': Cannot use macro
-keyword "do" as an argument name.
-
-define.sps:5.8: error: DEFINE: Syntax error at `0': expecting identifier.
-
-define.sps:6.10: error: DEFINE: Syntax error at `y': expecting `@{:@'.
-
-define.sps:7.15: error: DEFINE: Syntax error at `1': expecting identifier.
-
-define.sps:8.17: error: DEFINE: Syntax error at `2': expecting !TOKENS, !
+define.sps:1.36-1.40: error: DEFINE: String must contain exactly one token.
+ 1 | DEFINE !macro(!POSITIONAL !CHAREND('x y')) !ENDDEFINE.
+ | ^~~~~
+
+define.sps:2.28-2.38: error: DEFINE: Positional parameters must precede keyword
+parameters.
+ 2 | DEFINE !macro(a=!TOKENS(1)/!POSITIONAL !TOKENS(1)) !ENDDEFINE.
+ | ^~~~~~~~~~~
+
+define.sps:2.15: note: DEFINE: Here is a previous keyword parameter.
+ 2 | DEFINE !macro(a=!TOKENS(1)/!POSITIONAL !TOKENS(1)) !ENDDEFINE.
+ | ^
+
+define.sps:3.15-3.16: error: DEFINE: Keyword macro parameter must be named in
+definition without "!" prefix.
+ 3 | DEFINE !macro(!a=!TOKENS(1)) !ENDDEFINE.
+ | ^~
+
+define.sps:4.15-4.16: error: DEFINE: Cannot use macro keyword "do" as an
+argument name.
+ 4 | DEFINE !macro(do=!TOKENS(1)) !ENDDEFINE.
+ | ^~
+
+define.sps:5.8: error: DEFINE: Syntax error expecting identifier.
+ 5 | DEFINE 0() !ENDDEFINE.
+ | ^
+
+define.sps:6.10: error: DEFINE: Syntax error expecting `@{:@'.
+ 6 | DEFINE x y () !ENDDEFINE.
+ | ^
+
+define.sps:7.15: error: DEFINE: Syntax error expecting identifier.
+ 7 | DEFINE !macro(1) !ENDDEFINE.
+ | ^
+
+define.sps:8.17: error: DEFINE: Syntax error expecting !TOKENS, !CHAREND, !
+ENCLOSE, or !CMDEND.
+ 8 | DEFINE !macro(x 2) !ENDDEFINE.
+ | ^
+
+define.sps:9.26: error: DEFINE: Syntax error expecting `@{:@'.
+ 9 | DEFINE !macro(x=!DEFAULT 3) !ENDDEFINE.
+ | ^
+
+define.sps:10.25: error: DEFINE: Syntax error expecting `@{:@'.
+ 10 | DEFINE !macro(x=!TOKENS 4) !ENDDEFINE.
+ | ^
+
+define.sps:11.25: error: DEFINE: Syntax error expecting positive integer for !
+TOKENS.
+ 11 | DEFINE !macro(x=!TOKENS(x)) !ENDDEFINE.
+ | ^
+
+define.sps:12.27: error: DEFINE: Syntax error expecting `@:}@'.
+ 12 | DEFINE !macro(x=!TOKENS(1 5)) !ENDDEFINE.
+ | ^
+
+define.sps:13.26: error: DEFINE: Syntax error expecting `@{:@'.
+ 13 | DEFINE !macro(x=!ENCLOSE 6) !ENDDEFINE.
+ | ^
+
+define.sps:14.30: error: DEFINE: Syntax error expecting `,'.
+ 14 | DEFINE !macro(x=!ENCLOSE('x' y)) !ENDDEFINE.
+ | ^
+
+define.sps:15.30: error: DEFINE: Syntax error expecting string.
+ 15 | DEFINE !macro(x=!ENCLOSE('x',y)) !ENDDEFINE.
+ | ^
+
+define.sps:16.34: error: DEFINE: Syntax error expecting `@:}@'.
+ 16 | DEFINE !macro(x=!ENCLOSE('x','y' z)) !ENDDEFINE.
+ | ^
+
+define.sps:17.26: error: DEFINE: Syntax error expecting `@{:@'.
+ 17 | DEFINE !macro(x=!CHAREND 7) !ENDDEFINE.
+ | ^
+
+define.sps:18.26: error: DEFINE: Syntax error expecting string.
+ 18 | DEFINE !macro(x=!CHAREND(8)) !ENDDEFINE.
+ | ^
+
+define.sps:19.30: error: DEFINE: Syntax error expecting `@:}@'.
+ 19 | DEFINE !macro(x=!CHAREND('x' 9)) !ENDDEFINE.
+ | ^
+
+define.sps:20.17-20.20: error: DEFINE: Syntax error expecting !TOKENS, !
CHAREND, !ENCLOSE, or !CMDEND.
+ 20 | DEFINE !macro(x=!WTF) !ENDDEFINE.
+ | ^~~~
-define.sps:9.26: error: DEFINE: Syntax error at `3': expecting `@{:@'.
-
-define.sps:10.25: error: DEFINE: Syntax error at `4': expecting `('.
-
-define.sps:11.25: error: DEFINE: Syntax error at `x': Expected positive integer
-for !TOKENS.
-
-define.sps:12.27: error: DEFINE: Syntax error at `5': expecting `)'.
-
-define.sps:13.26: error: DEFINE: Syntax error at `6': expecting `('.
+define.sps:21.28: error: DEFINE: Syntax error expecting `/'.
+ 21 | DEFINE !macro(x=!TOKENS(1) x) !ENDDEFINE.
+ | ^
-define.sps:14.30: error: DEFINE: Syntax error at `y': expecting `,'.
+define.sps:22.28-22.35: error: DEFINE: !DEFAULT is allowed only once per
+argument.
+ 22 | DEFINE !macro(x=!DEFAULT() !DEFAULT()) !ENDDEFINE.
+ | ^~~~~~~~
-define.sps:15.30: error: DEFINE: Syntax error at `y': expecting string.
+define.sps:23.28-23.34: error: DEFINE: Only one of !TOKENS, !CHAREND, !ENCLOSE,
+or !CMDEND is allowed.
+ 23 | DEFINE !macro(x=!TOKENS(1) !CMDEND) !ENDDEFINE.
+ | ^~~~~~~
-define.sps:16.34: error: DEFINE: Syntax error at `z': expecting `)'.
-
-define.sps:17.26: error: DEFINE: Syntax error at `7': expecting `('.
-
-define.sps:18.26: error: DEFINE: Syntax error at `8': expecting string.
-
-define.sps:19.30: error: DEFINE: Syntax error at `9': expecting `)'.
-
-define.sps:20.17-20.20: error: DEFINE: Syntax error at `!WTF': expecting !
-TOKENS, !CHAREND, !ENCLOSE, or !CMDEND.
-
-define.sps:21.28: error: DEFINE: Syntax error at `x': expecting `/'.
-
-define.sps:22.36: error: DEFINE: Syntax error at `(': !DEFAULT is allowed only
-once per argument.
-
-define.sps:23.35: error: DEFINE: Syntax error at `)': Only one of !TOKENS, !
-CHAREND, !ENCLOSE, or !CMDEND is allowed.
-
-define.sps:25.1: error: DEFINE: Syntax error at end of command: Expecting macro
-body or !ENDDEFINE.
+define.sps:25.1: error: DEFINE: Syntax error expecting macro body or !
+ENDDEFINE.
+ 25 |
+ | ^
])
AT_CLEANUP
two
-define.sps:13.12-13.20: error: ECHO: Syntax error at `"strings"': expecting end
-of command.
-
-define.sps:14.12-14.17: error: N OF CASES: Syntax error at `-/**/1': Expected
-positive integer for N OF CASES.
-
-define.sps:15.12-15.19: error: N OF CASES: Syntax error at `!minus 1': Expected
-positive integer for N OF CASES.
-
-define.sps:16.12-16.17: error: N OF CASES: Syntax error at `- !one': Expected
-positive integer for N OF CASES.
-
-define.sps:17.12-17.22: error: N OF CASES: Syntax error at `!minus !one':
-Expected positive integer for N OF CASES.
+define.sps:13.12-13.20: error: ECHO: Syntax error expecting end of command.
+ 13 | ECHO "two" "strings".
+ | ^~~~~~~~~
+
+define.sps:14.12-14.17: error: N OF CASES: Syntax error expecting positive
+integer for N OF CASES.
+ 14 | N OF CASES -/**/1.
+ | ^~~~~~
+
+define.sps:15.12-15.19: error: N OF CASES: Syntax error expecting positive
+integer for N OF CASES.
+ 15 | N OF CASES !minus 1.
+ | ^~~~~~~~
+
+define.sps:16.12-16.17: error: N OF CASES: Syntax error expecting positive
+integer for N OF CASES.
+ 16 | N OF CASES - !one.
+ | ^~~~~~
+
+define.sps:17.12-17.22: error: N OF CASES: Syntax error expecting positive
+integer for N OF CASES.
+ 17 | N OF CASES !minus !one.
+ | ^~~~~~~~~~~
])
AT_CLEANUP
do-if.sps:8: error: ELSE IF: This command cannot appear outside DO IF...END IF.
-do-if.sps:12: error: DO IF: Only one ELSE is allowed within DO IF...END IF.
+"do-if.sps:12.1-12.4: error: DO IF: Only one ELSE is allowed within DO IF...END IF.
+ 12 | ELSE.
+ | ^~~~"
"do-if.sps:11.1-11.5: note: DO IF: This is the location of the previous ELSE clause.
11 | ELSE.
10 | DO IF 0.
| ^~~~~~~~"
-do-if.sps:17: error: DO IF: ELSE IF is not allowed following ELSE within DO IF...END IF.
+"do-if.sps:17.1-17.7: error: DO IF: ELSE IF is not allowed following ELSE within DO IF...END IF.
+ 17 | ELSE IF 0.
+ | ^~~~~~~"
"do-if.sps:16.1-16.5: note: DO IF: This is the location of the previous ELSE clause.
16 | ELSE.
15 | DO IF 0.
| ^~~~~~~~"
-do-if.sps:20.7: error: DO IF: Syntax error at `!'.
+"do-if.sps:20.7: error: DO IF: Syntax error.
+ 20 | DO IF !.
+ | ^"
-error: DO IF: Syntax error at end of input.
+error: DO IF: At end of input: Syntax error.
])
AT_CLEANUP
DO REPEAT y = 1 TO 10.
])
AT_CHECK([pspp -O format=csv do-repeat.sps], [1], [dnl
-error: DO REPEAT: Syntax error at end of input: expecting END.
+error: DO REPEAT: At end of input: Syntax error expecting END.
])
AT_CLEANUP
loop.sps:5: error: LOOP: Only one index clause may be specified.
-loop.sps:7.6: error: LOOP: Syntax error at `5'.
+loop.sps:7.6: error: LOOP: Syntax error.
+ 7 | LOOP 5.
+ | ^
-loop.sps:9.8: error: LOOP: Syntax error at `!': expecting `='.
+loop.sps:9.8: error: LOOP: Syntax error expecting `='.
+ 9 | LOOP B !.
+ | ^
-loop.sps:11.8: error: LOOP: Syntax error at `!'.
+loop.sps:11.8: error: LOOP: Syntax error.
+ 11 | LOOP B=!.
+ | ^
-loop.sps:13.13: error: LOOP: Syntax error at `!'.
+loop.sps:13.13: error: LOOP: Syntax error.
+ 13 | LOOP A=1 TO !.
+ | ^
-loop.sps:15.13: error: LOOP: Syntax error at `!'.
+loop.sps:15.13: error: LOOP: Syntax error.
+ 15 | LOOP A=1 BY !.
+ | ^
-loop.sps:17: error: LOOP: Subcommand TO may only be specified once.
+loop.sps:17.20-17.21: error: LOOP: Subcommand TO may only be specified once.
+ 17 | LOOP A=1 TO 5 BY 5 TO !.
+ | ^~
-loop.sps:19: error: LOOP: Subcommand BY may only be specified once.
+loop.sps:19.21-19.22: error: LOOP: Subcommand BY may only be specified once.
+ 19 | LOOP A=1 BY 5 TO 10 BY !.
+ | ^~
loop.sps:21: error: LOOP: Required subcommand TO was not specified.
-loop.sps:23.6: error: LOOP: Syntax error at `!'.
+loop.sps:23.6: error: LOOP: Syntax error.
+ 23 | LOOP !.
+ | ^
-loop.sps:26: error: LOOP: Subcommand IF may only be specified once.
+loop.sps:26.11-26.12: error: LOOP: Subcommand IF may only be specified once.
+ 26 | LOOP IF 1 IF 0.
+ | ^~
-loop.sps:29.9: error: LOOP: Syntax error at `!'.
+loop.sps:29.9: error: LOOP: Syntax error.
+ 29 | LOOP IF !.
+ | ^
-loop.sps:33.13: error: LOOP: Syntax error at `!'.
+loop.sps:33.13: error: LOOP: Syntax error.
+ 33 | END LOOP IF !.
+ | ^
-loop.sps:36.10: error: LOOP: Syntax error at `!': expecting end of command.
+loop.sps:36.10: error: LOOP: Syntax error expecting end of command.
+ 36 | END LOOP !.
+ | ^
-error: LOOP: Syntax error at end of input.
+error: LOOP: At end of input: Syntax error.
])
AT_CLEANUP
\ No newline at end of file
])
AT_CHECK([pspp -O format=csv data-list.sps], [1], [dnl
-data-list.sps:1.41-1.42: error: DATA LIST: Syntax error at `-1': Expected non-negative integer for SKIP.
+"data-list.sps:1.41-1.42: error: DATA LIST: Syntax error expecting non-negative integer for SKIP.
+ 1 | DATA LIST LIST FILE='f.in' NOTABLE SKIP=-1 /a b c d.
+ | ^~"
data-list.sps:3: error: Stopping syntax file processing here to avoid a cascade of dependent command failures.
])
])
AT_CHECK([pspp -O format=csv data-list.sps], [1], [dnl
-data-list.sps:1.44-1.45: error: DATA LIST: Syntax error at `-1': Expected non-negative integer for RECORDS.
+"data-list.sps:1.44-1.45: error: DATA LIST: Syntax error expecting non-negative integer for RECORDS.
+ 1 | DATA LIST LIST FILE='f.in' NOTABLE RECORDS=-1 /a b c d.
+ | ^~"
data-list.sps:3: error: Stopping syntax file processing here to avoid a cascade of dependent command failures.
])
Table: Datasets
second (active dataset)
-dataset.pspp:10: error: LIST: LIST is allowed only after the active dataset has been defined.
+"dataset.pspp:10.1-10.4: error: LIST: LIST is allowed only after the active dataset has been defined.
+ 10 | LIST.
+ | ^~~~"
])
AT_CLEANUP
5 @&t@
-dataset.pspp:16: error: LIST: LIST is allowed only after the active dataset has been defined.
+"dataset.pspp:16.1-16.4: error: LIST: LIST is allowed only after the active dataset has been defined.
+ 16 | LIST.
+ | ^~~~"
Table: Data List
x
get data /type=txt /file='test.data' /importcase=percent 100 /variables x f8.0.
])
AT_CHECK([pspp -O format=csv get-data.sps], [0], [dnl
-get-data.sps:1: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.)
+"get-data.sps:1.39-1.57: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.).
+ 1 | get data /type=txt /file='test.data' /importcase=first 10 /variables x f8.0.
+ | ^~~~~~~~~~~~~~~~~~~"
-get-data.sps:2: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.)
+"get-data.sps:2.39-2.58: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.).
+ 2 | get data /type=txt /file='test.data' /importcase=percent 1 /variables x f8.0.
+ | ^~~~~~~~~~~~~~~~~~~~"
-get-data.sps:3: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.)
+"get-data.sps:3.39-3.59: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.).
+ 3 | get data /type=txt /file='test.data' /importcase=percent 35 /variables x f8.0.
+ | ^~~~~~~~~~~~~~~~~~~~~"
-get-data.sps:4: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.)
+"get-data.sps:4.39-4.59: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.).
+ 4 | get data /type=txt /file='test.data' /importcase=percent 95 /variables x f8.0.
+ | ^~~~~~~~~~~~~~~~~~~~~"
-get-data.sps:5: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.)
+"get-data.sps:5.39-5.60: warning: GET DATA: Ignoring obsolete IMPORTCASES subcommand. (N OF CASES or SAMPLE may be used to substitute.).
+ 5 | get data /type=txt /file='test.data' /importcase=percent 100 /variables x f8.0.
+ | ^~~~~~~~~~~~~~~~~~~~~~"
])
AT_CLEANUP
END INPUT PROGRAM.
])
AT_CHECK([pspp -O format=csv input-program.sps], [1], [dnl
-input-program.sps:3: error: BEGIN DATA: BEGIN DATA is not allowed inside INPUT PROGRAM.
+"input-program.sps:3.1-3.10: error: BEGIN DATA: BEGIN DATA is not allowed inside INPUT PROGRAM.
+ 3 | BEGIN DATA
+ | ^~~~~~~~~~"
])
AT_CLEANUP
DESCRIPTIVES x.
])
AT_CHECK([pspp -O format=csv input-program.sps], [1], [dnl
-error: DESCRIPTIVES: Syntax error at end of input: expecting BEGIN.
+error: DESCRIPTIVES: At end of input: Syntax error expecting BEGIN.
])
AT_CLEANUP
AT_CHECK([pspp -O format=csv input-program.sps], [1], [dnl
input-program.sps:3: error: INPUT PROGRAM: Input program must contain DATA LIST or END FILE.
-input-program.sps:4: error: EXECUTE: EXECUTE is allowed only after the active dataset has been defined.
+"input-program.sps:4.1-4.7: error: EXECUTE: EXECUTE is allowed only after the active dataset has been defined.
+ 4 | EXECUTE.
+ | ^~~~~~~"
])
AT_CLEANUP
])
AT_CHECK([pspp -O format=csv matrix-data.sps], [0], [dnl
-matrix-data.sps:4: warning: MATRIX DATA: CELLS is ignored when VARIABLES includes ROWTYPE_
+"matrix-data.sps:4.6-4.10: warning: MATRIX DATA: CELLS is ignored when VARIABLES includes ROWTYPE_.
+ 4 | /cells = 2.
+ | ^~~~~"
Table: Data List
ROWTYPE_,VARNAME_,var01,var02,var03,var04
AT_CHECK([pspp matrix-data.sps -O format=csv], [1], [dnl
matrix-data.sps:1: error: MATRIX DATA: VARIABLES may not include VARNAME_.
-matrix-data.sps:2: error: MATRIX DATA: Variable v appears twice in variable list.
+"matrix-data.sps:2.25: error: MATRIX DATA: Variable v appears twice in variable list.
+ 2 | MATRIX DATA VARIABLES=v v v.
+ | ^"
matrix-data.sps:3: error: MATRIX DATA: ROWTYPE_ is not allowed on SPLIT or FACTORS.
matrix-data.sps:14: error: MATRIX DATA: Cannot specify N on CONTENTS along with the N subcommand.
-matrix-data.sps:15.35-15.39: error: MATRIX DATA: Syntax error at `XYZZY': Row type keyword expected.
+"matrix-data.sps:15.35-15.39: error: MATRIX DATA: Syntax error expecting one of the following: CORR, COV, MAT, N_MATRIX, PROX, COUNT, DFE, MEAN, MSE, STDDEV, N, N_SCALAR, N_VECTOR, SD.
+ 15 | MATRIX DATA VARIABLES=v1/CONTENTS=XYZZY.
+ | ^~~~~"
-matrix-data.sps:16.36: error: MATRIX DATA: Syntax error at end of command: Row type keyword expected.
+"matrix-data.sps:16.36: error: MATRIX DATA: Syntax error expecting one of the following: CORR, COV, MAT, N_MATRIX, PROX, COUNT, DFE, MEAN, MSE, STDDEV, N, N_SCALAR, N_VECTOR, SD.
+ 16 | MATRIX DATA VARIABLES=v1/CONTENTS=@{:@.
+ | ^"
-matrix-data.sps:17.40: error: MATRIX DATA: Syntax error at end of command: Row type keyword expected.
+"matrix-data.sps:17.40: error: MATRIX DATA: Syntax error expecting one of the following: CORR, COV, MAT, N_MATRIX, PROX, COUNT, DFE, MEAN, MSE, STDDEV, N, N_SCALAR, N_VECTOR, SD.
+ 17 | MATRIX DATA VARIABLES=v1/CONTENTS=@{:@CORR.
+ | ^"
-matrix-data.sps:18.35: error: MATRIX DATA: Syntax error at `)': Row type keyword expected.
+"matrix-data.sps:18.35: error: MATRIX DATA: Syntax error expecting one of the following: CORR, COV, MAT, N_MATRIX, PROX, COUNT, DFE, MEAN, MSE, STDDEV, N, N_SCALAR, N_VECTOR, SD.
+ 18 | MATRIX DATA VARIABLES=v1/CONTENTS=@:}@.
+ | ^"
-matrix-data.sps:19.12: error: MATRIX DATA: Syntax error at end of command: expecting VARIABLES.
+"matrix-data.sps:19.12: error: MATRIX DATA: Syntax error expecting VARIABLES.
+ 19 | MATRIX DATA.
+ | ^"
-matrix-data.sps:20.24: error: MATRIX DATA: Syntax error at `*': expecting `/'.
+"matrix-data.sps:20.24: error: MATRIX DATA: Syntax error expecting `/'.
+ 20 | MATRIX DATA VARIABLES=v*.
+ | ^"
-matrix-data.sps:21.27-21.28: error: MATRIX DATA: Syntax error at `-1': Expected non-negative integer for N.
+"matrix-data.sps:21.27-21.28: error: MATRIX DATA: Syntax error expecting non-negative integer for N.
+ 21 | MATRIX DATA VARIABLES=v/N=-1.
+ | ^~"
-matrix-data.sps:22.32-22.36: error: MATRIX DATA: Syntax error at `XYZZY'.
+"matrix-data.sps:22.32-22.36: error: MATRIX DATA: Syntax error.
+ 22 | MATRIX DATA VARIABLES=v/FORMAT=XYZZY.
+ | ^~~~~"
-matrix-data.sps:23.30-23.32: error: MATRIX DATA: Syntax error at `123': expecting a file name or handle name.
+"matrix-data.sps:23.30-23.32: error: MATRIX DATA: Syntax error expecting a file name or handle name.
+ 23 | MATRIX DATA VARIABLES=v/FILE=123.
+ | ^~~"
-matrix-data.sps:24.31-24.33: error: MATRIX DATA: Syntax error at `123': expecting variable name.
+"matrix-data.sps:24.31-24.33: error: MATRIX DATA: Syntax error expecting variable name.
+ 24 | MATRIX DATA VARIABLES=v/SPLIT=123.
+ | ^~~"
-matrix-data.sps:25.31-25.32: error: MATRIX DATA: Syntax error at `-1': Expected non-negative integer for CELLS.
+"matrix-data.sps:25.31-25.32: error: MATRIX DATA: Syntax error expecting non-negative integer for CELLS.
+ 25 | MATRIX DATA VARIABLES=v/CELLS=-1.
+ | ^~"
-matrix-data.sps:26.25-26.29: error: MATRIX DATA: Syntax error at `XYZZY'.
+"matrix-data.sps:26.25-26.29: error: MATRIX DATA: Syntax error.
+ 26 | MATRIX DATA VARIABLES=v/XYZZY.
+ | ^~~~~"
])
AT_CLEANUP
AT_CHECK([pspp -O format=csv input.sps])
AT_CHECK([pspp -O format=csv mconvert.sps], [1], [dnl
-mconvert.sps:2: error: LIST: LIST is allowed only after the active dataset has been defined.
+"mconvert.sps:2.1-2.4: error: LIST: LIST is allowed only after the active dataset has been defined.
+ 2 | LIST.
+ | ^~~~"
])
AT_CHECK([pspp -O format=csv output.sps], [0], [dnl
Table: Data List
LIST.
])
AT_CHECK([pspp -O format=csv print.sps], [1], [dnl
-print.sps:7.7-7.10: error: PRINT: Syntax error at `F8.2': expecting a valid subcommand.
+"print.sps:7.7-7.10: error: PRINT: Syntax error expecting OUTFILE, ENCODING, RECORDS, TABLE, or NOTABLE.
+ 7 | PRINT F8.2
+ | ^~~~"
Table: Data List
a,b
"formats.sps:2: error: FORMATS: Output format E6.1 specifies 1 decimal place, but the given width does not allow for any decimals."
-formats.sps:3: error: FORMATS: a and y are not the same type. All variables in this variable list must be of the same type. y will be omitted from the list.
+"formats.sps:3.11: error: FORMATS: a and y are not the same type. All variables in this variable list must be of the same type. y will be omitted from the list.
+ 3 | FORMATS a y (F4).
+ | ^"
formats.sps:4: error: FORMATS: String variable with width 1 is not compatible with format A2.
formats.sps:5: error: FORMATS: String variable with width 2 is not compatible with format AHEX2.
-formats.sps:6: error: FORMATS: x and y are string variables with different widths. All variables in this variable list must have the same width. y will be omitted from the list.
+"formats.sps:6.11: error: FORMATS: x and y are string variables with different widths. All variables in this variable list must have the same width. y will be omitted from the list.
+ 6 | FORMATS x y (A2).
+ | ^"
formats.sps:6: error: FORMATS: String variable with width 1 is not compatible with format A2.
])
AT_CHECK([pspp -O format=csv missing-values.sps], [1], [dnl
missing-values.sps:5: error: MISSING VALUES: Missing values provided are too long to assign to variable of width 3.
-missing-values.sps:8: error: MISSING VALUES: Truncating missing value to maximum acceptable length (8 bytes).
+"missing-values.sps:8.25-8.37: error: MISSING VALUES: Truncating missing value to maximum acceptable length (8 bytes).
+ 8 | MISSING VALUES longstr ('abcdefghijk').
+ | ^~~~~~~~~~~~~"
-missing-values.sps:11.26-11.29: error: MISSING VALUES: Syntax error at `THRU': expecting string.
+"missing-values.sps:11.26-11.29: error: MISSING VALUES: Syntax error expecting string.
+ 11 | MISSING VALUES str1 ('a' THRU 'z').
+ | ^~~~"
-missing-values.sps:11: error: MISSING VALUES: THRU is not a variable name.
+"missing-values.sps:11.26-11.29: error: MISSING VALUES: THRU is not a variable name.
+ 11 | MISSING VALUES str1 ('a' THRU 'z').
+ | ^~~~"
missing-values.sps:14: error: MISSING VALUES: Cannot mix numeric variables (e.g. num1) and string variables (e.g. str1) within a single list.
missing-values.sps:20: error: MISSING VALUES: Too many string missing values. At most three individual values are allowed.
-missing-values.sps:23: warning: MISSING VALUES: The high end of the range (1) is below the low end (2). The range will be treated as if reversed.
+"missing-values.sps:23.22-23.29: warning: MISSING VALUES: The high end of the range (1) is below the low end (2). The range will be treated as if reversed.
+ 23 | MISSING VALUES num1 (2 THRU 1).
+ | ^~~~~~~~"
])
AT_CLEANUP
[DEFINE_MRSETS_DATA
MRSETS /MDGROUP VALUE=1.5.
])
-AT_CHECK([pspp -O format=csv mrsets.sps], [1],
- [mrsets.sps:6: error: MRSETS: Numeric VALUE must be an integer.
+AT_CHECK([pspp -O format=csv mrsets.sps], [1], [dnl
+"mrsets.sps:6.23-6.25: error: MRSETS: Numeric VALUE must be an integer.
+ 6 | MRSETS /MDGROUP VALUE=1.5.
+ | ^~~"
])
AT_CLEANUP
[DEFINE_MRSETS_DATA
MRSETS /MCGROUP VARIABLES=a b c.
])
-AT_CHECK([pspp -O format=csv mrsets.sps], [1],
- [mrsets.sps:6.32: error: MRSETS: Syntax error at end of command: Required MCGROUP specification missing from NAME subcommand.
+AT_CHECK([pspp -O format=csv mrsets.sps], [1], [dnl
+"mrsets.sps:6.32: error: MRSETS: Required NAME specification missing from MCGROUP subcommand.
+ 6 | MRSETS /MCGROUP VARIABLES=a b c.
+ | ^"
])
AT_CLEANUP
[DEFINE_MRSETS_DATA
MRSETS /MCGROUP NAME=$Mcgroup.
])
-AT_CHECK([pspp -O format=csv mrsets.sps], [1],
- [mrsets.sps:6.30: error: MRSETS: Syntax error at end of command: Required MCGROUP specification missing from VARIABLES subcommand.
+AT_CHECK([pspp -O format=csv mrsets.sps], [1], [dnl
+"mrsets.sps:6.30: error: MRSETS: Required VARIABLES specification missing from MCGROUP subcommand.
+ 6 | MRSETS /MCGROUP NAME=$Mcgroup.
+ | ^"
])
AT_CLEANUP
[DEFINE_MRSETS_DATA
MRSETS /MCGROUP NAME=$mygroup VARIABLES=a b x y.
])
-AT_CHECK([pspp -O format=csv mrsets.sps], [1],
- [mrsets.sps:6: error: MRSETS: a and x are not the same type. All variables in this variable list must be of the same type. x will be omitted from the list.
+AT_CHECK([pspp -O format=csv mrsets.sps], [1], [dnl
+"mrsets.sps:6.45: error: MRSETS: a and x are not the same type. All variables in this variable list must be of the same type. x will be omitted from the list.
+ 6 | MRSETS /MCGROUP NAME=$mygroup VARIABLES=a b x y.
+ | ^"
-mrsets.sps:6: error: MRSETS: a and y are not the same type. All variables in this variable list must be of the same type. y will be omitted from the list.
+"mrsets.sps:6.47: error: MRSETS: a and y are not the same type. All variables in this variable list must be of the same type. y will be omitted from the list.
+ 6 | MRSETS /MCGROUP NAME=$mygroup VARIABLES=a b x y.
+ | ^"
])
AT_CLEANUP
[MRSETS /DISPLAY NAME=[$x].
MRSETS /DELETE NAME=[$y].
]])
-AT_CHECK([pspp -O format=csv mrsets.sps], [1],
- [mrsets.sps:6: error: MRSETS: No multiple response set named $x.
+AT_CHECK([pspp -O format=csv mrsets.sps], [1], [dnl
+"mrsets.sps:6.23-6.24: error: MRSETS: No multiple response set named $x.
+ 6 | MRSETS /DISPLAY NAME=[[$x]].
+ | ^~"
-mrsets.sps:7: error: MRSETS: No multiple response set named $y.
+"mrsets.sps:7.22-7.23: error: MRSETS: No multiple response set named $y.
+ 7 | MRSETS /DELETE NAME=[[$y]].
+ | ^~"
])
AT_CLEANUP
])
AT_CHECK([pspp -o pspp.csv rename-variables.sps], [1], [dnl
-rename-variables.sps:2.23-2.31: error: RENAME VARIABLES: Syntax error at `auxiliary': expecting `='.
+rename-variables.sps:2.23-2.31: error: RENAME VARIABLES: Syntax error expecting `='.
+ 2 | RENAME VARIABLES warp auxiliary=foobar xyzzy.
+ | ^~~~~~~~~
])
AT_CLEANUP
VALUE LABELS /var=a 'label for a'.
])
AT_CHECK([pspp -O format=csv value-labels.sps], [1], [dnl
-value-labels.sps:9: error: VALUE LABELS: var is not a variable name.
+"value-labels.sps:9.15-9.17: error: VALUE LABELS: var is not a variable name.
+ 9 | VALUE LABELS /var=a 'label for a'.
+ | ^~~"
])
AT_CLEANUP
1 >= 2 = 2 ge 3 => false
-evaluate.sps:17.24: error: DEBUG EVALUATE: Syntax error at `!': expecting end
-of command.
+evaluate.sps:17.24: error: DEBUG EVALUATE: Syntax error expecting end of
+command.
+ 17 | DEBUG EVALUATE /3 ne 2 != 1.
+ | ^
3 ne 2 != 1 => error
2 le 2 => true
-evaluate.sps:25.21: error: DEBUG EVALUATE: Syntax error at `='.
+evaluate.sps:25.21: error: DEBUG EVALUATE: Syntax error.
+ 25 | DEBUG EVALUATE /2 < = 2.
+ | ^
2 < = 2 => error
2 ge 2 => true
-evaluate.sps:8.21: error: DEBUG EVALUATE: Syntax error at `='.
+evaluate.sps:8.21: error: DEBUG EVALUATE: Syntax error.
+ 8 | DEBUG EVALUATE /2 > = 2.
+ | ^
2 > = 2 => error
'asdf ' ~= "asdf " => false
-evaluate.sps:41.21: error: DEBUG EVALUATE: Syntax error at `>'.
+evaluate.sps:41.21: error: DEBUG EVALUATE: Syntax error.
+ 41 | DEBUG EVALUATE /1 < > 1.
+ | ^
1 < > 1 => error
-evaluate.sps:42.19: error: DEBUG EVALUATE: Syntax error at `~': expecting end
-of command.
+evaluate.sps:42.19: error: DEBUG EVALUATE: Syntax error expecting end of
+command.
+ 42 | DEBUG EVALUATE /1 ~ = 1.
+ | ^
1 ~ = 1 => error
])
any(a10, 'b', 'c', 'd') => error
-evaluate.sps:37: error: DEBUG EVALUATE: Unknown identifier b.
+evaluate.sps:37.26: error: DEBUG EVALUATE: Unknown identifier b.
+ 37 | DEBUG EVALUATE /any('a', b, 'c', 'd').
+ | ^
any('a', b, 'c', 'd') => error
-evaluate.sps:38: error: DEBUG EVALUATE: Unknown identifier c.
+evaluate.sps:38.31: error: DEBUG EVALUATE: Unknown identifier c.
+ 38 | DEBUG EVALUATE /any('a', 'b', c, 'd').
+ | ^
any('a', 'b', c, 'd') => error
-evaluate.sps:39: error: DEBUG EVALUATE: Unknown identifier d.
+evaluate.sps:39.36: error: DEBUG EVALUATE: Unknown identifier d.
+ 39 | DEBUG EVALUATE /any('a', 'b', 'c', d).
+ | ^
any('a', 'b', 'c', d) => error
]])
END IF.
])
AT_CHECK([pspp -O format=csv parse.sps], [1], [dnl
-parse.sps:10: error: IF: Unknown identifier y.
+"parse.sps:10.6: error: IF: Unknown identifier y.
+ 10 | IF ( y > 0 ) .
+ | ^"
parse.sps:11: error: Stopping syntax file processing here to avoid a cascade of dependent command failures.
])
COMPUTE x=$nonexistent.
])
AT_CHECK([pspp parse.sps], [1], [dnl
-parse.sps:2: error: COMPUTE: Unknown system variable $nonexistent.
+parse.sps:2.11-2.22: error: COMPUTE: Unknown system variable $nonexistent.
+ 2 | COMPUTE x=$nonexistent.
+ | ^~~~~~~~~~~~
])
AT_CLEANUP
COMPUTE x=y.
])
AT_CHECK([pspp parse.sps], [1], [dnl
-parse.sps:2: error: COMPUTE: Unknown identifier y.
+parse.sps:2.11: error: COMPUTE: Unknown identifier y.
+ 2 | COMPUTE x=y.
+ | ^
])
AT_CLEANUP
for opt in OPT NOOPT; do
AS_BOX([$opt])
sed "s/opt/$opt/" < evaluate-base.sps > evaluate.sps
- AT_CHECK([pspp --testing-mode evaluate.sps], [1],
-[[evaluate.sps:3: error: DEBUG EVALUATE: Unknown system variable $nonexistent.
+ AT_CHECK([pspp --testing-mode evaluate.sps], [1], [dnl
+evaluate.sps:3.17-3.28: error: DEBUG EVALUATE: Unknown system variable
+$nonexistent.
+ 3 | DEBUG EVALUATE /$nonexistent.
+ | ^~~~~~~~~~~~
$nonexistent => error
-evaluate.sps:4.17-4.27: error: DEBUG EVALUATE: RANGE(number, number, number[,
-number, number]...) must have an odd number of arguments.
+evaluate.sps:4.17-4.27: error: DEBUG EVALUATE: RANGE(number, number, number[[,
+number, number]]...) must have an odd number of arguments.
4 | DEBUG EVALUATE /RANGE(1, 2).
| ^~~~~~~~~~~
RANGE(1, 2) => error
-evaluate.sps:5.17-5.34: error: DEBUG EVALUATE: CONCAT(string[, string]...)
+evaluate.sps:5.17-5.34: error: DEBUG EVALUATE: CONCAT(string[[, string]]...)
function cannot accept suffix .1 to specify the minimum number of valid
arguments.
5 | DEBUG EVALUATE /CONCAT.1('a', 'b').
CONCAT.1('a', 'b') => error
-evaluate.sps:6: error: DEBUG EVALUATE: No function or vector named foobar.
+evaluate.sps:6.17-6.22: error: DEBUG EVALUATE: No function or vector named
+foobar.
+ 6 | DEBUG EVALUATE /foobar(x).
+ | ^~~~~~
foobar(x) => error
-evaluate.sps:7.30: error: DEBUG EVALUATE: Syntax error at `b': expecting `,' or
-`)'.
+evaluate.sps:7.30: error: DEBUG EVALUATE: Syntax error expecting `,' or `@:}@'.
+ 7 | DEBUG EVALUATE /CONCAT.1('a' b).
+ | ^
CONCAT.1('a' b) => error
| ^~~~~
v('abc') => error
-]])
+])
done
AT_CLEANUP
�
])
AT_CHECK([pspp -O format=csv lexer.sps], [1], [dnl
-"lexer.sps:1.1-1.6: error: Syntax error at `x'123'': String of hex digits has 3 characters, which is not a multiple of 2."
+"lexer.sps:1.1-1.6: error: String of hex digits has 3 characters, which is not a multiple of 2.
+ 1 | x'123'
+ | ^~~~~~"
-lexer.sps:2.1-2.5: error: Syntax error at `x'1x'': `x' is not a valid hex digit.
+"lexer.sps:2.1-2.5: error: `x' is not a valid hex digit.
+ 2 | x'1x'
+ | ^~~~~"
-"lexer.sps:3.1-3.3: error: Syntax error at `u''': Unicode string contains 0 bytes, which is not in the valid range of 1 to 8 bytes."
+"lexer.sps:3.1-3.3: error: Unicode string contains 0 bytes, which is not in the valid range of 1 to 8 bytes.
+ 3 | u''
+ | ^~~"
-"lexer.sps:4.1-4.12: error: Syntax error at `u'012345678'': Unicode string contains 9 bytes, which is not in the valid range of 1 to 8 bytes."
+"lexer.sps:4.1-4.12: error: Unicode string contains 9 bytes, which is not in the valid range of 1 to 8 bytes.
+ 4 | u'012345678'
+ | ^~~~~~~~~~~~"
-lexer.sps:5.1-5.7: error: Syntax error at `u'd800'': U+D800 is not a valid Unicode code point.
+"lexer.sps:5.1-5.7: error: U+D800 is not a valid Unicode code point.
+ 5 | u'd800'
+ | ^~~~~~~"
-lexer.sps:6.1-6.9: error: Syntax error at `u'110000'': U+110000 is not a valid Unicode code point.
+"lexer.sps:6.1-6.9: error: U+110000 is not a valid Unicode code point.
+ 6 | u'110000'
+ | ^~~~~~~~~"
-lexer.sps:7.1-7.4: error: Syntax error at `'foo': Unterminated string constant.
+"lexer.sps:7.1-7.4: error: Unterminated string constant.
+ 7 | 'foo
+ | ^~~~"
-lexer.sps:8.1-8.70: error: Syntax error at `'very long unterminated string that be ellipsized in its err...': Unterminated string constant.
+"lexer.sps:8.1-8.70: error: Unterminated string constant.
+ 8 | 'very long unterminated string that be ellipsized in its error message
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
-lexer.sps:9.1-9.2: error: Syntax error at `1e': Missing exponent following `1e'.
+"lexer.sps:9.1-9.2: error: Missing exponent following `1e'.
+ 9 | 1e .x
+ | ^~"
-lexer.sps:9.4: error: Syntax error at `.': expecting command name.
+"lexer.sps:9.4: error: Syntax error expecting command name.
+ 9 | 1e .x
+ | ^"
-lexer.sps:10.1: error: Syntax error at `^': Bad character `^' in input.
+"lexer.sps:10.1: error: Bad character `^' in input.
+ 10 | ^
+ | ^"
-lexer.sps:11.1-11.2: error: Syntax error at `�': Bad character U+FFFD in input.
+"lexer.sps:11.1-11.2: error: Bad character U+FFFD in input.
+ 11 | �
+ | ^~"
])
AT_CLEANUP
lis|.\0" > lexer.sps
AT_CHECK([pspp -O format=csv lexer.sps], [1], [dnl
-lexer.sps:1: error: Unknown command `datA dist'.
+"lexer.sps:1.1-1.9: error: Unknown command `datA dist'.
+ 1 | datA dist list notable file='input.txt'/a b c.
+ | ^~~~~~~~~"
-lexer.sps:2: error: LIST: LIST is allowed only after the active dataset has been defined.
+"lexer.sps:2.1-2.3: error: LIST: LIST is allowed only after the active dataset has been defined.
+ 2 | lis|."
-lexer.sps:2.6: error: LIST: Syntax error at `...': Bad character U+0000 in input.
+"lexer.sps:2.6: error: LIST: Bad character U+0000 in input.
+ 2 | lis|."
])
AT_CLEANUP
printf "DATA LIST/5555555555555555." > lexer.sps
AT_CHECK([pspp -O format=csv lexer.sps], [1], [dnl
-lexer.sps:1.11-1.26: error: DATA LIST: Syntax error at `5555555555555555': Expected integer between 1 and 2147483647.
+"lexer.sps:1.11-1.26: error: DATA LIST: Syntax error expecting integer between 1 and 2147483647.
+ 1 | DATA LIST/5555555555555555.
+ | ^~~~~~~~~~~~~~~~"
])
AT_CLEANUP
[outfile=aggregate]) dnl
m4_if([$2], [presorted], [/PRESORTED]) dnl
m4_if([$3], [columnwise], [/MISSING=COLUMNWISE])
- /DOCUMENT
- /BREAK=g
- /N = n
- /NI = n./
- NU = nu
- /NUI = nu./
- NFGT2 = fgt(n, 2)
- /NFGT2I = fgt.(n, 2)
- /SFGT2 = fgt(s, '2')
- /SFGT2I = fgt.(s, '2')
- /NFIN23 = fin(n, 2, 3)
- /NFIN23I = fin.(n, 2, 3)
- /SFIN23 = fin(s, '2', '3')
- /SFIN23I = fin.(s, '2', '3')
- /NFLT2 = flt(n, 2)
- /NFLT2I = flt.(n, 2)
- /SFLT2 = flt(s, '2')
- /SFLT2I = flt.(s, '2')
- /NFIRST = first(n)
- /NFIRSTI = first.(n)
- /SFIRST = first(s)
- /SFIRSTI = first.(s)
- /NFOUT23 = fout(n, 3, 2)
- /NFOUT23I = fout.(n, 3, 2)
- /SFOUT23 = fout(s, '3', '2')
- /SFOUT23I = fout.(s, '3', '2')
- /NLAST = last(n)
- /NLASTI = last.(n)
- /SLAST = last(s)
- /SLASTI = last.(s)
- /NMAX = max(n)
- /NMAXI = max.(n)
- /SMAX = max(s)
- /SMAXI = max.(s)
- /NMEAN = mean(n)
- /NMEANI = mean.(n)
- /NMIN = min(n)
- /NMINI = min.(n)
- /SMIN = min(s)
- /SMINI = min.(s)
- /NN = n(n)
- /NNI = n.(n)
- /SN = n(s)
- /SNI = n.(s)
- /NNMISS = nmiss(n)
- /NNMISSI = nmiss.(n)
- /SNMISS = nmiss(s)
- /SNMISSI = nmiss.(s)
- /NNU = nu(n)
- /NNUI = nu.(n)
- /SNU = nu(s)
- /SNUI = nu.(s)
- /NNUMISS = numiss(n)
- /NNUMISSI = numiss.(n)
- /SNUMISS = numiss(s)
- /SNUMISSI = numiss.(s)
- /NPGT2 = pgt(n, 2)
- /NPGT2I = pgt.(n, 2)
- /SPGT2 = pgt(s, '2')
- /SPGT2I = pgt.(s, '2')
- /NPIN23 = pin(n, 2, 3)
- /NPIN23I = pin.(n, 2, 3)
- /SPIN23 = pin(s, '2', '3')
- /SPIN23I = pin.(s, '2', '3')
- /NPLT2 = plt(n, 2)
- /NPLT2I = plt.(n, 2)
- /SPLT2 = plt(s, '2')
- /SPLT2I = plt.(s, '2')
- /NPOUT23 = pout(n, 2, 3)
- /NPOUT23I = pout.(n, 2, 3)
- /SPOUT23 = pout(s, '2', '3')
- /SPOUT23I = pout.(s, '2', '3')
- /NMEDIAN = median(n)
- /NMEDIANI = median.(n)
- /NSD = sd(n)
- /NSDI = sd.(n)
- /NSUM = sum(n)
- /NSUMI = sum.(n).
+ /DOCUMENT
+ /BREAK=g
+ /N = n
+ /NI = n./
+ NU = nu
+ /NUI = nu./
+ NFGT2 = fgt(n, 2)
+ /NFGT2I = fgt.(n, 2)
+ /SFGT2 = fgt(s, '2')
+ /SFGT2I = fgt.(s, '2')
+ /NFIN23 = fin(n, 2, 3)
+ /NFIN23I = fin.(n, 2, 3)
+ /SFIN23 = fin(s, '2', '3')
+ /SFIN23I = fin.(s, '2', '3')
+ /NFLT2 = flt(n, 2)
+ /NFLT2I = flt.(n, 2)
+ /SFLT2 = flt(s, '2')
+ /SFLT2I = flt.(s, '2')
+ /NFIRST = first(n)
+ /NFIRSTI = first.(n)
+ /SFIRST = first(s)
+ /SFIRSTI = first.(s)
+ /NFOUT23 = fout(n, 3, 2)
+ /NFOUT23I = fout.(n, 3, 2)
+ /SFOUT23 = fout(s, '3', '2')
+ /SFOUT23I = fout.(s, '3', '2')
+ /NLAST = last(n)
+ /NLASTI = last.(n)
+ /SLAST = last(s)
+ /SLASTI = last.(s)
+ /NMAX = max(n)
+ /NMAXI = max.(n)
+ /SMAX = max(s)
+ /SMAXI = max.(s)
+ /NMEAN = mean(n)
+ /NMEANI = mean.(n)
+ /NMIN = min(n)
+ /NMINI = min.(n)
+ /SMIN = min(s)
+ /SMINI = min.(s)
+ /NN = n(n)
+ /NNI = n.(n)
+ /SN = n(s)
+ /SNI = n.(s)
+ /NNMISS = nmiss(n)
+ /NNMISSI = nmiss.(n)
+ /SNMISS = nmiss(s)
+ /SNMISSI = nmiss.(s)
+ /NNU = nu(n)
+ /NNUI = nu.(n)
+ /SNU = nu(s)
+ /SNUI = nu.(s)
+ /NNUMISS = numiss(n)
+ /NNUMISSI = numiss.(n)
+ /SNUMISS = numiss(s)
+ /SNUMISSI = numiss.(s)
+ /NPGT2 = pgt(n, 2)
+ /NPGT2I = pgt.(n, 2)
+ /SPGT2 = pgt(s, '2')
+ /SPGT2I = pgt.(s, '2')
+ /NPIN23 = pin(n, 2, 3)
+ /NPIN23I = pin.(n, 2, 3)
+ /SPIN23 = pin(s, '2', '3')
+ /SPIN23I = pin.(s, '2', '3')
+ /NPLT2 = plt(n, 2)
+ /NPLT2I = plt.(n, 2)
+ /SPLT2 = plt(s, '2')
+ /SPLT2I = plt.(s, '2')
+ /NPOUT23 = pout(n, 2, 3)
+ /NPOUT23I = pout.(n, 2, 3)
+ /SPOUT23 = pout(s, '2', '3')
+ /SPOUT23I = pout.(s, '2', '3')
+ /NMEDIAN = median(n)
+ /NMEDIANI = median.(n)
+ /NSD = sd(n)
+ /NSDI = sd.(n)
+ /NSUM = sum(n)
+ /NSUMI = sum.(n).
m4_if([$1], [external], [GET FILE='aggregate.sys'.],
[$1], [dataset], [DATASET ACTIVATE aggregate.])
LIST.
])
- AT_CHECK([pspp -O format=csv aggregate.sps], [0], [stdout])
- AT_CHECK([[sed 's/^[^:]*:[0-9]*: //' < stdout]], [0],
- [m4_if([$3], [itemwise],
- [warning: AGGREGATE: The value arguments passed to the FOUT function are out-of-order. They will be treated as if they had been specified in the correct order.
-
-warning: AGGREGATE: The value arguments passed to the FOUT function are out-of-order. They will be treated as if they had been specified in the correct order.
-
-warning: AGGREGATE: The value arguments passed to the FOUT function are out-of-order. They will be treated as if they had been specified in the correct order.
-
-warning: AGGREGATE: The value arguments passed to the FOUT function are out-of-order. They will be treated as if they had been specified in the correct order.
+ AT_CHECK([pspp -O format=csv aggregate.sps], [0],
+ [m4_if([$3], [itemwise], [dnl
+"aggregate.sps:29.28-29.31: warning: AGGREGATE: The value arguments passed to the FOUT function are out of order. They will be treated as if they had been specified in the correct order.
+ 29 | /NFOUT23 = fout(n, 3, 2)
+ | ^~~~"
+
+"aggregate.sps:30.30-30.33: warning: AGGREGATE: The value arguments passed to the FOUT function are out of order. They will be treated as if they had been specified in the correct order.
+ 30 | /NFOUT23I = fout.(n, 3, 2)
+ | ^~~~"
+
+"aggregate.sps:31.28-31.35: warning: AGGREGATE: The value arguments passed to the FOUT function are out of order. They will be treated as if they had been specified in the correct order.
+ 31 | /SFOUT23 = fout(s, '3', '2')
+ | ^~~~~~~~"
+
+"aggregate.sps:32.30-32.37: warning: AGGREGATE: The value arguments passed to the FOUT function are out of order. They will be treated as if they had been specified in the correct order.
+ 32 | /SFOUT23I = fout.(s, '3', '2')
+ | ^~~~~~~~"
Table: Data List
G,N,NI,NU,NUI,NFGT2,NFGT2I,SFGT2,SFGT2I,NFIN23,NFIN23I,SFIN23,SFIN23I,NFLT2,NFLT2I,SFLT2,SFLT2I,NFIRST,NFIRSTI,SFIRST,SFIRSTI,NFOUT23,NFOUT23I,SFOUT23,SFOUT23I,NLAST,NLASTI,SLAST,SLASTI,NMAX,NMAXI,SMAX,SMAXI,NMEAN,NMEANI,NMIN,NMINI,SMIN,SMINI,NN,NNI,SN,SNI,NNMISS,NNMISSI,SNMISS,SNMISSI,NNU,NNUI,SNU,SNUI,NNUMISS,NNUMISSI,SNUMISS,SNUMISSI,NPGT2,NPGT2I,SPGT2,SPGT2I,NPIN23,NPIN23I,SPIN23,SPIN23I,NPLT2,NPLT2I,SPLT2,SPLT2I,NPOUT23,NPOUT23I,SPOUT23,SPOUT23I,NMEDIAN,NMEDIANI,NSD,NSDI,NSUM,NSUMI
3,2.00,2.00,1,1,.000,.000,.000,.000,.000,.000,.000,.000,1.000,1.000,1.000,1.000,1,1,1,1,1.000,1.000,1.000,1.000,1,1,1,1,1,1,1,1,1.00,1.00,1,1,1,1,2.00,2.00,2.00,2.00,.00,.00,.00,.00,1,1,1,1,0,0,0,0,.0,.0,.0,.0,.0,.0,.0,.0,100.0,100.0,100.0,100.0,100.0,100.0,100.0,100.0,1.00,1.00,.00,.00,2.00,2.00
4,1.00,1.00,1,1,. ,. ,. ,1.000,. ,. ,. ,.000,. ,. ,. ,.000,.,.,,4,. ,. ,. ,1.000,.,.,,4,.,.,,4,. ,. ,.,.,,4,.00,.00,.00,1.00,1.00,1.00,1.00,.00,0,0,0,1,1,1,1,0,. ,. ,. ,100.0,. ,. ,. ,.0,. ,. ,. ,.0,. ,. ,. ,100.0,NaN,NaN,. ,. ,. ,. @&t@
],
- [warning: AGGREGATE: The value arguments passed to the FOUT function are out-of-order. They will be treated as if they had been specified in the correct order.
-
-warning: AGGREGATE: The value arguments passed to the FOUT function are out-of-order. They will be treated as if they had been specified in the correct order.
-
-warning: AGGREGATE: The value arguments passed to the FOUT function are out-of-order. They will be treated as if they had been specified in the correct order.
-
-warning: AGGREGATE: The value arguments passed to the FOUT function are out-of-order. They will be treated as if they had been specified in the correct order.
+ [dnl
+"aggregate.sps:29.28-29.31: warning: AGGREGATE: The value arguments passed to the FOUT function are out of order. They will be treated as if they had been specified in the correct order.
+ 29 | /NFOUT23 = fout(n, 3, 2)
+ | ^~~~"
+
+"aggregate.sps:30.30-30.33: warning: AGGREGATE: The value arguments passed to the FOUT function are out of order. They will be treated as if they had been specified in the correct order.
+ 30 | /NFOUT23I = fout.(n, 3, 2)
+ | ^~~~"
+
+"aggregate.sps:31.28-31.35: warning: AGGREGATE: The value arguments passed to the FOUT function are out of order. They will be treated as if they had been specified in the correct order.
+ 31 | /SFOUT23 = fout(s, '3', '2')
+ | ^~~~~~~~"
+
+"aggregate.sps:32.30-32.37: warning: AGGREGATE: The value arguments passed to the FOUT function are out of order. They will be treated as if they had been specified in the correct order.
+ 32 | /SFOUT23I = fout.(s, '3', '2')
+ | ^~~~~~~~"
Table: Data List
G,N,NI,NU,NUI,NFGT2,NFGT2I,SFGT2,SFGT2I,NFIN23,NFIN23I,SFIN23,SFIN23I,NFLT2,NFLT2I,SFLT2,SFLT2I,NFIRST,NFIRSTI,SFIRST,SFIRSTI,NFOUT23,NFOUT23I,SFOUT23,SFOUT23I,NLAST,NLASTI,SLAST,SLASTI,NMAX,NMAXI,SMAX,SMAXI,NMEAN,NMEANI,NMIN,NMINI,SMIN,SMINI,NN,NNI,SN,SNI,NNMISS,NNMISSI,SNMISS,SNMISSI,NNU,NNUI,SNU,SNUI,NNUMISS,NNUMISSI,SNUMISS,SNUMISSI,NPGT2,NPGT2I,SPGT2,SPGT2I,NPIN23,NPIN23I,SPIN23,SPIN23I,NPLT2,NPLT2I,SPLT2,SPLT2I,NPOUT23,NPOUT23I,SPOUT23,SPOUT23I,NMEDIAN,NMEDIANI,NSD,NSDI,NSUM,NSUMI
CTABLES /TABLE qn1 /COMPARETEST STYLE=**.
CTABLES /TABLE qn1 /COMPARETEST SHOWSIG=**.
CTABLES /TABLE qn1 /COMPARETEST **.
-CTABLES /TABLE qn1 / **.
+CTABLES /TABLE qn1 /FORMAT.
CTABLES /TABLE qn1 /CLABELS ROWLABELS=OPPOSITE /CLABELS COLLABELS=OPPOSITE.
CTABLES /TABLE qn20 > qnd1.
CTABLES /TABLE qn1 [ROWPCT] > qnsa1.
CTABLES /TABLE qn1 /CATEGORIES VARIABLES=datetime ['123'].
]])
AT_CHECK([pspp ctables.sps -O box=unicode -O width=80], [1],
-[[ctables.sps:2.8: error: CTABLES: Syntax error at end of command: expecting `/'.
+[[ctables.sps:2.8: error: CTABLES: Syntax error expecting `/'.
+ 2 | CTABLES.
+ | ^
-ctables.sps:3.29-3.33: error: CTABLES: Syntax error at `'foo'': Expected non-
-negative number for MINCOLWIDTH.
+ctables.sps:3.29-3.33: error: CTABLES: Syntax error expecting non-negative
+number for MINCOLWIDTH.
+ 3 | CTABLES /FORMAT MINCOLWIDTH='foo'.
+ | ^~~~~
-ctables.sps:4.21-4.22: error: CTABLES: Syntax error at `**': expecting
-identifier.
+ctables.sps:4.21-4.22: error: CTABLES: Syntax error expecting identifier.
+ 4 | CTABLES /TABLE qn1 [**].
+ | ^~
-ctables.sps:5.21-5.32: error: CTABLES: Syntax error at `NOTAFUNCTION': Expecting
-summary function name.
+ctables.sps:5.21-5.32: error: CTABLES: Syntax error expecting summary function
+name.
+ 5 | CTABLES /TABLE qn1 [NOTAFUNCTION].
+ | ^~~~~~~~~~~~
-ctables.sps:6.20: error: CTABLES: Syntax error at end of command: expecting `@:}@'.
+ctables.sps:6.20: error: CTABLES: Syntax error expecting `@:}@'.
+ 6 | CTABLES /TABLE @{:@qn1.
+ | ^
-ctables.sps:7.16-7.17: error: CTABLES: Syntax error at `**': expecting
-identifier.
+ctables.sps:7.16-7.17: error: CTABLES: Syntax error expecting identifier.
+ 7 | CTABLES /TABLE **.
+ | ^~
-ctables.sps:8: error: CTABLES: NOTAVAR is not a variable name.
+ctables.sps:8.16-8.22: error: CTABLES: NOTAVAR is not a variable name.
+ 8 | CTABLES /TABLE NOTAVAR.
+ | ^~~~~~~
ctables.sps:10.16-10.24: error: CTABLES: Cannot use string variable string as a
scale variable.
10 | CTABLES /TABLE string[S].
| ^~~~~~~~~
-ctables.sps:11.27-11.29: error: CTABLES: Syntax error at `101': Expected number
-between 0 and 100 for PTILE.
+ctables.sps:11.27-11.29: error: CTABLES: Syntax error expecting number between 0
+and 100 for PTILE.
+ 11 | CTABLES /TABLE qn1 [PTILE 101].
+ | ^~~
ctables.sps:12: error: CTABLES: Output format F0.1 specifies width 0, but F
requires a width between 1 and 40.
-ctables.sps:13.26-13.36: error: CTABLES: Syntax error at `NEGPAREN1.2': Output
-format NEGPAREN requires width 2 or greater.
+ctables.sps:13.26-13.36: error: CTABLES: Output format NEGPAREN requires width 2
+or greater.
+ 13 | CTABLES /TABLE qn1 [MEAN NEGPAREN1.2].
+ | ^~~~~~~~~~~
-ctables.sps:14.26-14.36: error: CTABLES: Syntax error at `NEGPAREN3.4': Output
-format NEGPAREN requires width greater than decimals.
+ctables.sps:14.26-14.36: error: CTABLES: Output format NEGPAREN requires width
+greater than decimals.
+ 14 | CTABLES /TABLE qn1 [MEAN NEGPAREN3.4].
+ | ^~~~~~~~~~~
ctables.sps:15.21-15.24: error: CTABLES: Summary function MEAN applies only to
scale variables.
15 | CTABLES /TABLE qn1 [MEAN TOTALS].
| ^~~
-ctables.sps:15.32: error: CTABLES: Syntax error at `@:>@': expecting `@<:@'.
+ctables.sps:15.32: error: CTABLES: Syntax error expecting `@<:@'.
+ 15 | CTABLES /TABLE qn1 [MEAN TOTALS].
+ | ^
ctables.sps:16.21-16.24: error: CTABLES: Summary function MEAN applies only to
scale variables.
16 | CTABLES /TABLE qn1 [MEAN TOTALS[STDDEV]%].
| ^~~
-ctables.sps:16.40: error: CTABLES: Syntax error at `%': expecting `@:>@'.
+ctables.sps:16.40: error: CTABLES: Syntax error expecting `@:>@'.
+ 16 | CTABLES /TABLE qn1 [MEAN TOTALS[STDDEV]%].
+ | ^
-ctables.sps:17.56: error: CTABLES: Syntax error at `x': expecting string.
+ctables.sps:17.56: error: CTABLES: Syntax error expecting string.
+ 17 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [SUBTOTAL=x].
+ | ^
-ctables.sps:18.50-18.51: error: CTABLES: Syntax error at `**': expecting THRU.
+ctables.sps:18.50-18.51: error: CTABLES: Syntax error expecting THRU.
+ 18 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [LO **].
+ | ^~
-ctables.sps:19.55: error: CTABLES: Syntax error at `x': expecting number.
+ctables.sps:19.55: error: CTABLES: Syntax error expecting number.
+ 19 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [LO THRU x].
+ | ^
-ctables.sps:20.54-20.55: error: CTABLES: Syntax error at `**': expecting number.
+ctables.sps:20.54-20.55: error: CTABLES: Syntax error expecting number.
+ 20 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [1 THRU **].
+ | ^~
-ctables.sps:21.56-21.57: error: CTABLES: Syntax error at `**': expecting string.
+ctables.sps:21.56-21.57: error: CTABLES: Syntax error expecting string.
+ 21 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 ['x' THRU **].
+ | ^~
-ctables.sps:22.48-22.49: error: CTABLES: Syntax error at `**': expecting
-identifier.
+ctables.sps:22.48-22.49: error: CTABLES: Syntax error expecting identifier.
+ 22 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&**].
+ | ^~
ctables.sps:23.47-23.48: error: CTABLES: Unknown postcompute &x.
23 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&x].
| ^~
-ctables.sps:24.61-24.63: error: CTABLES: Syntax error at `101': Expected number
-between 0 and 100 for PTILE.
+ctables.sps:24.61-24.63: error: CTABLES: Syntax error expecting number between 0
+and 100 for PTILE.
+ 24 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 KEY=PTILE(qn1, 101).
+ | ^~~
-ctables.sps:25.58: error: CTABLES: Syntax error at end of command: expecting
-`@:}@'.
+ctables.sps:25.58: error: CTABLES: Syntax error expecting `@:}@'.
+ 25 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 KEY=MEAN(qn1.
+ | ^
-ctables.sps:26.54: error: CTABLES: Syntax error at end of command: expecting
-`@{:@'.
+ctables.sps:26.54: error: CTABLES: Syntax error expecting `@{:@'.
+ 26 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 KEY=MEAN.
+ | ^
-ctables.sps:27.54-27.55: error: CTABLES: Syntax error at `**': expecting INCLUDE
-or EXCLUDE.
+ctables.sps:27.54-27.55: error: CTABLES: Syntax error expecting INCLUDE or
+EXCLUDE.
+ 27 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 MISSING=**.
+ | ^~
-ctables.sps:28.52-28.53: error: CTABLES: Syntax error at `**': expecting YES or
-NO.
+ctables.sps:28.52-28.53: error: CTABLES: Syntax error expecting YES or NO.
+ 28 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 TOTAL=**.
+ | ^~
-ctables.sps:29.52-29.53: error: CTABLES: Syntax error at `**': expecting string.
+ctables.sps:29.52-29.53: error: CTABLES: Syntax error expecting string.
+ 29 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 LABEL=**.
+ | ^~
-ctables.sps:30.55-30.56: error: CTABLES: Syntax error at `**': expecting BEFORE
-or AFTER.
+ctables.sps:30.55-30.56: error: CTABLES: Syntax error expecting BEFORE or AFTER.
+ 30 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 POSITION=**.
+ | ^~
-ctables.sps:31.52-31.53: error: CTABLES: Syntax error at `**': expecting INCLUDE
-or EXCLUDE.
+ctables.sps:31.52-31.53: error: CTABLES: Syntax error expecting INCLUDE or
+EXCLUDE.
+ 31 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 EMPTY=**.
+ | ^~
-ctables.sps:32.46-32.47: error: CTABLES: Syntax error at `**': expecting ORDER,
-KEY, MISSING, TOTAL, LABEL, POSITION, or EMPTY.
+ctables.sps:32.46-32.47: error: CTABLES: Syntax error expecting ORDER, KEY,
+MISSING, TOTAL, LABEL, POSITION, or EMPTY.
+ 32 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 **.
+ | ^~
-ctables.sps:33.54-33.55: error: CTABLES: Syntax error at `**': expecting TOTAL,
-LABEL, POSITION, or EMPTY.
+ctables.sps:33.54-33.55: error: CTABLES: Syntax error expecting TOTAL, LABEL,
+POSITION, or EMPTY.
+ 33 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [1,2,3] **.
+ | ^~
-ctables.sps:34.36: error: CTABLES: Syntax error at `0': Expected positive
-integer for SUBTOTAL.
+ctables.sps:34.36: error: CTABLES: Syntax error expecting positive integer for
+SUBTOTAL.
+ 34 | CTABLES /PCOMPUTE &k=EXPR(SUBTOTAL[0]).
+ | ^
-ctables.sps:35.37-35.38: error: CTABLES: Syntax error at `**': expecting `@:>@'.
+ctables.sps:35.37-35.38: error: CTABLES: Syntax error expecting `@:>@'.
+ 35 | CTABLES /PCOMPUTE &k=EXPR(SUBTOTAL[1**]).
+ | ^~
-ctables.sps:36.31-36.32: error: CTABLES: Syntax error at `**': expecting THRU.
+ctables.sps:36.31-36.32: error: CTABLES: Syntax error expecting THRU.
+ 36 | CTABLES /PCOMPUTE &k=EXPR([LO **]).
+ | ^~
-ctables.sps:37.36-37.37: error: CTABLES: Syntax error at `**': expecting number.
+ctables.sps:37.36-37.37: error: CTABLES: Syntax error expecting number.
+ 37 | CTABLES /PCOMPUTE &k=EXPR([LO THRU **]).
+ | ^~
-ctables.sps:38.35-38.36: error: CTABLES: Syntax error at `**': expecting number.
+ctables.sps:38.35-38.36: error: CTABLES: Syntax error expecting number.
+ 38 | CTABLES /PCOMPUTE &k=EXPR([1 THRU **]).
+ | ^~
-ctables.sps:39.29-39.30: error: CTABLES: Syntax error at `**': expecting `@:>@'.
+ctables.sps:39.29-39.30: error: CTABLES: Syntax error expecting `@:>@'.
+ 39 | CTABLES /PCOMPUTE &k=EXPR([1**]).
+ | ^~
-ctables.sps:40.29: error: CTABLES: Syntax error at `x': expecting `@:}@'.
+ctables.sps:40.29: error: CTABLES: Syntax error expecting `@:}@'.
+ 40 | CTABLES /PCOMPUTE &k=EXPR((1x)).
+ | ^
-ctables.sps:41.19-41.20: error: CTABLES: Syntax error at `**': expecting &.
+ctables.sps:41.19-41.20: error: CTABLES: Syntax error expecting &.
+ 41 | CTABLES /PCOMPUTE **k.
+ | ^~
-ctables.sps:42.20: error: CTABLES: Syntax error at `1': expecting identifier.
+ctables.sps:42.20: error: CTABLES: Syntax error expecting identifier.
+ 42 | CTABLES /PCOMPUTE &1.
+ | ^
-ctables.sps:43.21-43.22: error: CTABLES: Syntax error at `**': expecting `='.
+ctables.sps:43.21-43.22: error: CTABLES: Syntax error expecting `='.
+ 43 | CTABLES /PCOMPUTE &k**.
+ | ^~
-ctables.sps:44.22-44.23: error: CTABLES: Syntax error at `**': expecting EXPR.
+ctables.sps:44.22-44.23: error: CTABLES: Syntax error expecting EXPR.
+ 44 | CTABLES /PCOMPUTE &k=**.
+ | ^~
-ctables.sps:45.26-45.27: error: CTABLES: Syntax error at `**': expecting `('.
+ctables.sps:45.26-45.27: error: CTABLES: Syntax error expecting `@{:@'.
+ 45 | CTABLES /PCOMPUTE &k=EXPR**.
+ | ^~
-ctables.sps:46.28: error: CTABLES: Syntax error at `x': expecting `)'.
+ctables.sps:46.28: error: CTABLES: Syntax error expecting `@:}@'.
+ 46 | CTABLES /PCOMPUTE &k=EXPR(1x).
+ | ^
ctables.sps:47.31-47.49: warning: CTABLES: New definition of &k will override
the previous definition.
47 | CTABLES /PCOMPUTE &k=EXPR(1) /PCOMPUTE &k=EXPR(2).
| ^~~~~~~~~~~~~~~~~~~
-ctables.sps:47.50: error: CTABLES: Syntax error at end of command: expecting
-`/'.
+ctables.sps:47.50: error: CTABLES: Syntax error expecting `/'.
+ 47 | CTABLES /PCOMPUTE &k=EXPR(1) /PCOMPUTE &k=EXPR(2).
+ | ^
-ctables.sps:48.53-48.64: error: CTABLES: Syntax error at `NOTAFUNCTION':
-Expecting summary function name.
+ctables.sps:48.53-48.64: error: CTABLES: Syntax error expecting summary function
+name.
+ 48 | CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k FORMAT=NOTAFUNCTION.
+ | ^~~~~~~~~~~~
-ctables.sps:49.59-49.60: error: CTABLES: Syntax error at `**': Expected number
-between 0 and 100 for PTILE.
+ctables.sps:49.59-49.60: error: CTABLES: Syntax error expecting number between 0
+and 100 for PTILE.
+ 49 | CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k FORMAT=PTILE **.
+ | ^~
-ctables.sps:50.52-50.53: error: CTABLES: Syntax error at `**': expecting string.
+ctables.sps:50.52-50.53: error: CTABLES: Syntax error expecting string.
+ 50 | CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k LABEL=**.
+ | ^~
-ctables.sps:51.61-51.62: error: CTABLES: Syntax error at `**': expecting YES or
-NO.
+ctables.sps:51.61-51.62: error: CTABLES: Syntax error expecting YES or NO.
+ 51 | CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k HIDESOURCECATS=**.
+ | ^~
-ctables.sps:52.46-52.47: error: CTABLES: Syntax error at `**': expecting LABEL,
-FORMAT, or HIDESOURCECATS.
+ctables.sps:52.46-52.47: error: CTABLES: Syntax error expecting LABEL, FORMAT,
+or HIDESOURCECATS.
+ 52 | CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k **.
+ | ^~
-ctables.sps:53.23-53.24: error: CTABLES: Syntax error at `**': expecting string.
+ctables.sps:53.23-53.24: error: CTABLES: Syntax error expecting string.
+ 53 | CTABLES /FORMAT EMPTY=**.
+ | ^~
-ctables.sps:54.25-54.26: error: CTABLES: Syntax error at `**': expecting string.
+ctables.sps:54.25-54.26: error: CTABLES: Syntax error expecting string.
+ 54 | CTABLES /FORMAT MISSING=**.
+ | ^~
-ctables.sps:55.17-55.18: error: CTABLES: Syntax error at `**': expecting
-MINCOLWIDTH, MAXCOLWIDTH, UNITS, EMPTY, or MISSING.
+ctables.sps:55.17-55.18: error: CTABLES: Syntax error expecting MINCOLWIDTH,
+MAXCOLWIDTH, UNITS, EMPTY, or MISSING.
+ 55 | CTABLES /FORMAT **.
+ | ^~
-ctables.sps:56: error: CTABLES: MINCOLWIDTH must not be greater than
+ctables.sps:56.17-56.45: error: CTABLES: MINCOLWIDTH must not be greater than
MAXCOLWIDTH.
+ 56 | CTABLES /FORMAT MINCOLWIDTH=20 MAXCOLWIDTH=10/.
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ctables.sps:57.18-57.19: error: CTABLES: Syntax error expecting VARIABLES.
+ 57 | CTABLES /VLABELS **.
+ | ^~
+
+ctables.sps:58.28-58.34: error: CTABLES: NOTAVAR is not a variable name.
+ 58 | CTABLES /VLABELS VARIABLES=NOTAVAR.
+ | ^~~~~~~
+
+ctables.sps:59.32-59.33: error: CTABLES: Syntax error expecting DISPLAY.
+ 59 | CTABLES /VLABELS VARIABLES=qn1 **.
+ | ^~
+
+ctables.sps:60.40-60.41: error: CTABLES: Syntax error expecting DEFAULT, NAME,
+LABEL, BOTH, or NONE.
+ 60 | CTABLES /VLABELS VARIABLES=qn1 DISPLAY=**.
+ | ^~
+
+ctables.sps:61.17-61.18: error: CTABLES: Syntax error expecting COUNTDUPLICATES.
+ 61 | CTABLES /MRSETS **.
+ | ^~
+
+ctables.sps:62.33-62.34: error: CTABLES: Syntax error expecting YES or NO.
+ 62 | CTABLES /MRSETS COUNTDUPLICATES=**.
+ | ^~
+
+ctables.sps:63.19-63.20: error: CTABLES: Syntax error expecting VARIABLE or
+LISTWISE.
+ 63 | CTABLES /SMISSING **.
+ | ^~
+
+ctables.sps:64.17-64.18: error: CTABLES: Syntax error expecting VARIABLE.
+ 64 | CTABLES /WEIGHT **.
+ | ^~
+
+ctables.sps:65.26-65.32: error: CTABLES: NOTAVAR is not a variable name.
+ 65 | CTABLES /WEIGHT VARIABLE=NOTAVAR.
+ | ^~~~~~~
+
+ctables.sps:66.32: error: CTABLES: Syntax error expecting integer 2 or greater
+for HIDESMALLCOUNTS COUNT.
+ 66 | CTABLES /HIDESMALLCOUNTS COUNT=1.
+ | ^
+
+ctables.sps:67.10-67.13: error: CTABLES: Syntax error expecting one of the
+following: FORMAT, VLABELS, MRSETS, SMISSING, PCOMPUTE, PPROPERTIES, WEIGHT,
+HIDESMALLCOUNTS, TABLE.
+ 67 | CTABLES /QUUX.
+ | ^~~~
+
+ctables.sps:68.33: error: CTABLES: Syntax error expecting `/'.
+ 68 | CTABLES /HIDESMALLCOUNTS COUNT=2.
+ | ^
+
+ctables.sps:69.19-69.20: error: CTABLES: Syntax error expecting `/'.
+ 69 | CTABLES /TABLE qn1**.
+ | ^~
+
+ctables.sps:70.38-70.39: error: CTABLES: Syntax error expecting COLUMN, ROW, or
+LAYER.
+ 70 | CTABLES /TABLE qn1 /SLABELS POSITION=**.
+ | ^~
+
+ctables.sps:71.37-71.38: error: CTABLES: Syntax error expecting YES or NO.
+ 71 | CTABLES /TABLE qn1 /SLABELS VISIBLE=**.
+ | ^~
+
+ctables.sps:72.29-72.30: error: CTABLES: Syntax error expecting POSITION or
+VISIBLE.
+ 72 | CTABLES /TABLE qn1 /SLABELS **.
+ | ^~
+
+ctables.sps:73.39-73.40: error: CTABLES: Syntax error expecting OPPOSITE or
+LAYER.
+ 73 | CTABLES /TABLE qn1 /CLABELS ROWLABELS=**.
+ | ^~
+
+ctables.sps:74.39-74.40: error: CTABLES: Syntax error expecting OPPOSITE or
+LAYER.
+ 74 | CTABLES /TABLE qn1 /CLABELS COLLABELS=**.
+ | ^~
+
+ctables.sps:75.29-75.30: error: CTABLES: Syntax error expecting AUTO, ROWLABELS,
+or COLLABELS.
+ 75 | CTABLES /TABLE qn1 /CLABELS **.
+ | ^~
+
+ctables.sps:76.30-76.31: error: CTABLES: Syntax error expecting CILEVEL.
+ 76 | CTABLES /TABLE qn1 /CRITERIA **.
+ | ^~
+
+ctables.sps:77.38-77.40: error: CTABLES: Syntax error expecting number in
+@<:@0,100@:}@ for CILEVEL.
+ 77 | CTABLES /TABLE qn1 /CRITERIA CILEVEL=101.
+ | ^~~
+
+ctables.sps:78.28-78.29: error: CTABLES: Syntax error expecting CAPTION, CORNER,
+or TITLE.
+ 78 | CTABLES /TABLE qn1 /TITLES **.
+ | ^~
+
+ctables.sps:79.34-79.35: error: CTABLES: Syntax error expecting CHISQUARE.
+ 79 | CTABLES /TABLE qn1 /SIGTEST TYPE=**.
+ | ^~
+
+ctables.sps:80.35-80.36: error: CTABLES: Syntax error expecting number in @<:@0,1@:}@
+for ALPHA.
+ 80 | CTABLES /TABLE qn1 /SIGTEST ALPHA=**.
+ | ^~
-ctables.sps:57.18-57.19: error: CTABLES: Syntax error at `**': expecting
-VARIABLES.
-
-ctables.sps:58: error: CTABLES: NOTAVAR is not a variable name.
-
-ctables.sps:59.32-59.33: error: CTABLES: Syntax error at `**': expecting
-DISPLAY.
-
-ctables.sps:60.40-60.41: error: CTABLES: Syntax error at `**': expecting
-DEFAULT, NAME, LABEL, BOTH, or NONE.
-
-ctables.sps:61.17-61.18: error: CTABLES: Syntax error at `**': expecting
-COUNTDUPLICATES.
-
-ctables.sps:62.33-62.34: error: CTABLES: Syntax error at `**': expecting YES or
-NO.
-
-ctables.sps:63.19-63.20: error: CTABLES: Syntax error at `**': expecting
-VARIABLE or LISTWISE.
-
-ctables.sps:64.17-64.18: error: CTABLES: Syntax error at `**': expecting
-VARIABLE.
-
-ctables.sps:65: error: CTABLES: NOTAVAR is not a variable name.
-
-ctables.sps:66.32: error: CTABLES: Syntax error at `1': Expected integer 2 or
-greater for HIDESMALLCOUNTS COUNT.
-
-ctables.sps:67.10-67.13: error: CTABLES: Syntax error at `QUUX': expecting one
-of the following: FORMAT, VLABELS, MRSETS, SMISSING, PCOMPUTE, PPROPERTIES,
-WEIGHT, HIDESMALLCOUNTS, TABLE.
-
-ctables.sps:68.33: error: CTABLES: Syntax error at end of command: expecting
-`/'.
-
-ctables.sps:69.19-69.20: error: CTABLES: Syntax error at `**': expecting `/'.
-
-ctables.sps:70.38-70.39: error: CTABLES: Syntax error at `**': expecting COLUMN,
-ROW, or LAYER.
-
-ctables.sps:71.37-71.38: error: CTABLES: Syntax error at `**': expecting YES or
-NO.
-
-ctables.sps:72.29-72.30: error: CTABLES: Syntax error at `**': expecting
-POSITION or VISIBLE.
-
-ctables.sps:73.39-73.40: error: CTABLES: Syntax error at `**': expecting
-OPPOSITE or LAYER.
-
-ctables.sps:74.39-74.40: error: CTABLES: Syntax error at `**': expecting
-OPPOSITE or LAYER.
-
-ctables.sps:75.29-75.30: error: CTABLES: Syntax error at `**': expecting AUTO,
-ROWLABELS, or COLLABELS.
-
-ctables.sps:76.30-76.31: error: CTABLES: Syntax error at `**': expecting
-CILEVEL.
-
-ctables.sps:77.38-77.40: error: CTABLES: Syntax error at `101': Expected number
-in @<:@0,100@:}@ for CILEVEL.
-
-ctables.sps:78.28-78.29: error: CTABLES: Syntax error at `**': expecting
-CAPTION, CORNER, or TITLE.
-
-ctables.sps:79.34-79.35: error: CTABLES: Syntax error at `**': expecting
-CHISQUARE.
-
-ctables.sps:80.35-80.36: error: CTABLES: Syntax error at `**': Expected number
-in @<:@0,1@:}@ for ALPHA.
+ctables.sps:81.43-81.44: error: CTABLES: Syntax error expecting YES or NO.
+ 81 | CTABLES /TABLE qn1 /SIGTEST INCLUDEMRSETS=**.
+ | ^~
-ctables.sps:81.43-81.44: error: CTABLES: Syntax error at `**': expecting YES or
-NO.
+ctables.sps:82.40-82.41: error: CTABLES: Syntax error expecting ALLVISIBLE or
+SUBTOTALS.
+ 82 | CTABLES /TABLE qn1 /SIGTEST CATEGORIES=**.
+ | ^~
-ctables.sps:82.40-82.41: error: CTABLES: Syntax error at `**': expecting
-ALLVISIBLE or SUBTOTALS.
+ctables.sps:83.29-83.30: error: CTABLES: Syntax error expecting TYPE, ALPHA,
+INCLUDEMRSETS, or CATEGORIES.
+ 83 | CTABLES /TABLE qn1 /SIGTEST **.
+ | ^~
-ctables.sps:83.29-83.30: error: CTABLES: Syntax error at `**': expecting TYPE,
-ALPHA, INCLUDEMRSETS, or CATEGORIES.
+ctables.sps:84.38-84.39: error: CTABLES: Syntax error expecting PROP or MEAN.
+ 84 | CTABLES /TABLE qn1 /COMPARETEST TYPE=**.
+ | ^~
-ctables.sps:84.38-84.39: error: CTABLES: Syntax error at `**': expecting PROP or
-MEAN.
+ctables.sps:85.39-85.40: error: CTABLES: Syntax error expecting number in (0,1)
+for ALPHA.
+ 85 | CTABLES /TABLE qn1 /COMPARETEST ALPHA=**.
+ | ^~
-ctables.sps:85.39-85.40: error: CTABLES: Syntax error at `**': Expected number
-in (0,1) for ALPHA.
+ctables.sps:86.39: error: CTABLES: Syntax error expecting number in (0,1) for
+ALPHA.
+ 86 | CTABLES /TABLE qn1 /COMPARETEST ALPHA=0,5.
+ | ^
-ctables.sps:86.39: error: CTABLES: Syntax error at `0': Expected number in (0,1)
-for ALPHA.
+ctables.sps:87.40-87.41: error: CTABLES: Syntax error expecting BONFERRONI, BH,
+or NONE.
+ 87 | CTABLES /TABLE qn1 /COMPARETEST ADJUST=**.
+ | ^~
-ctables.sps:87.40-87.41: error: CTABLES: Syntax error at `**': expecting
-BONFERRONI, BH, or NONE.
+ctables.sps:88.47-88.48: error: CTABLES: Syntax error expecting YES or NO.
+ 88 | CTABLES /TABLE qn1 /COMPARETEST INCLUDEMRSETS=**.
+ | ^~
-ctables.sps:88.47-88.48: error: CTABLES: Syntax error at `**': expecting YES or
-NO.
+ctables.sps:89.47-89.48: error: CTABLES: Syntax error expecting ALLCATS or
+TESTEDCATS.
+ 89 | CTABLES /TABLE qn1 /COMPARETEST MEANSVARIANCE=**.
+ | ^~
-ctables.sps:89.47-89.48: error: CTABLES: Syntax error at `**': expecting ALLCATS
-or TESTEDCATS.
+ctables.sps:90.44-90.45: error: CTABLES: Syntax error expecting ALLVISIBLE or
+SUBTOTALS.
+ 90 | CTABLES /TABLE qn1 /COMPARETEST CATEGORIES=**.
+ | ^~
-ctables.sps:90.44-90.45: error: CTABLES: Syntax error at `**': expecting
-ALLVISIBLE or SUBTOTALS.
+ctables.sps:91.39-91.40: error: CTABLES: Syntax error expecting YES or NO.
+ 91 | CTABLES /TABLE qn1 /COMPARETEST MERGE=**.
+ | ^~
-ctables.sps:91.39-91.40: error: CTABLES: Syntax error at `**': expecting YES or
-NO.
+ctables.sps:92.39-92.40: error: CTABLES: Syntax error expecting APA or SIMPLE.
+ 92 | CTABLES /TABLE qn1 /COMPARETEST STYLE=**.
+ | ^~
-ctables.sps:92.39-92.40: error: CTABLES: Syntax error at `**': expecting APA or
-SIMPLE.
+ctables.sps:93.41-93.42: error: CTABLES: Syntax error expecting YES or NO.
+ 93 | CTABLES /TABLE qn1 /COMPARETEST SHOWSIG=**.
+ | ^~
-ctables.sps:93.41-93.42: error: CTABLES: Syntax error at `**': expecting YES or
-NO.
+ctables.sps:94.33-94.34: error: CTABLES: Syntax error expecting one of the
+following: TYPE, ALPHA, ADJUST, INCLUDEMRSETS, MEANSVARIANCE, CATEGORIES, MERGE,
+STYLE, SHOWSIG.
+ 94 | CTABLES /TABLE qn1 /COMPARETEST **.
+ | ^~
-ctables.sps:94.33-94.34: error: CTABLES: Syntax error at `**': expecting one of
-the following: TYPE, ALPHA, ADJUST, INCLUDEMRSETS, MEANSVARIANCE, CATEGORIES,
-MERGE, STYLE, SHOWSIG.
+ctables.sps:95.21-95.26: error: CTABLES: Syntax error expecting TABLE, SLABELS,
+CLABELS, CRITERIA, CATEGORIES, TITLES, SIGTEST, or COMPARETEST.
+ 95 | CTABLES /TABLE qn1 /FORMAT.
+ | ^~~~~~
-ctables.sps:95.22-95.23: error: CTABLES: Syntax error at `**': expecting TABLE,
-SLABELS, CLABELS, CRITERIA, CATEGORIES, TITLES, SIGTEST, or COMPARETEST.
+ctables.sps:95.21-95.26: note: CTABLES: This subcommand must appear before
+TABLE.
+ 95 | CTABLES /TABLE qn1 /FORMAT.
+ | ^~~~~~
ctables.sps:96: error: CTABLES: ROWLABELS and COLLABELS may not both be
specified.
+ctables.sps:96.21-96.46: note: CTABLES: This is the first specification.
+ 96 | CTABLES /TABLE qn1 /CLABELS ROWLABELS=OPPOSITE /CLABELS
+COLLABELS=OPPOSITE.
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ctables.sps:96.49-96.74: note: CTABLES: This is the second specification.
+ 96 | CTABLES /TABLE qn1 /CLABELS ROWLABELS=OPPOSITE /CLABELS
+COLLABELS=OPPOSITE.
+ |
+^~~~~~~~~~~~~~~~~~~~~~~~~~
+
ctables.sps:97.16-97.26: error: CTABLES: Cannot nest scale variables.
97 | CTABLES /TABLE qn20 > qnd1.
| ^~~~~~~~~~~
CTABLES /TABLE qn113 [COUNT.UCL].
CTABLES /TABLE qn1 /CATEGORIES **.
+
+CTABLES /TITLES.
]])
-AT_CHECK([pspp ctables.sps -O box=unicode -O width=80], [1],
-[[ctables.sps:2.76-2.78: error: CTABLES: Computed category &pc references a
-category not included in the category list.
- 2 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
-VARIABLES=qn1 [&pc].
- |
-^~~
+AT_CHECK([pspp ctables.sps -O box=unicode -O width=120], [1],
+[[ctables.sps:2.76-2.78: error: CTABLES: Computed category &pc references a category not included in the category list.
+ 2 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc].
+ | ^~~
ctables.sps:2.28-2.35: note: CTABLES: This is the missing category.
- 2 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
-VARIABLES=qn1 [&pc].
+ 2 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc].
| ^~~~~~~~
-ctables.sps:2.76-2.79: note: CTABLES: To fix the problem, add subtotals to the
-list of categories here.
- 2 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
-VARIABLES=qn1 [&pc].
- |
-^~~~
+ctables.sps:2.76-2.79: note: CTABLES: To fix the problem, add subtotals to the list of categories here.
+ 2 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc].
+ | ^~~~
-ctables.sps:3.73-3.75: error: CTABLES: Computed category &pc references a
-category not included in the category list.
- 3 | CTABLES /PCOMPUTE &pc=EXPR(TOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1
-[&pc].
- |
-^~~
+ctables.sps:3.73-3.75: error: CTABLES: Computed category &pc references a category not included in the category list.
+ 3 | CTABLES /PCOMPUTE &pc=EXPR(TOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc].
+ | ^~~
ctables.sps:3.28-3.32: note: CTABLES: This is the missing category.
- 3 | CTABLES /PCOMPUTE &pc=EXPR(TOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1
-[&pc].
+ 3 | CTABLES /PCOMPUTE &pc=EXPR(TOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc].
| ^~~~~
-ctables.sps:3: note: CTABLES: To fix the problem, add TOTAL=YES to the
-variable's CATEGORIES specification.
+ctables.sps:3: note: CTABLES: To fix the problem, add TOTAL=YES to the variable's CATEGORIES specification.
-ctables.sps:4.76-4.99: error: CTABLES: These categories include 2 instances of
-SUBTOTAL or HSUBTOTAL, so references from computed categories must refer to
-subtotals by position, e.g. SUBTOTAL[1].
- 4 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
-VARIABLES=qn1 [&pc, SUBTOTAL, SUBTOTAL].
- |
-^~~~~~~~~~~~~~~~~~~~~~~~
+ctables.sps:4.76-4.99: error: CTABLES: These categories include 2 instances of SUBTOTAL or HSUBTOTAL, so references from
+computed categories must refer to subtotals by position, e.g. SUBTOTAL[1].
+ 4 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc, SUBTOTAL, SUBTOTAL].
+ | ^~~~~~~~~~~~~~~~~~~~~~~~
-ctables.sps:4.28-4.35: note: CTABLES: This is the reference that lacks a
-position.
- 4 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
-VARIABLES=qn1 [&pc, SUBTOTAL, SUBTOTAL].
+ctables.sps:4.28-4.35: note: CTABLES: This is the reference that lacks a position.
+ 4 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc, SUBTOTAL, SUBTOTAL].
| ^~~~~~~~
-ctables.sps:7.47-7.54: error: CTABLES: This category specification may be
-applied only to string variables, but this subcommand tries to apply it to
-numeric variable QN1.
+ctables.sps:7.47-7.54: error: CTABLES: This category specification may be applied only to string variables, but this
+subcommand tries to apply it to numeric variable QN1.
7 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 ['string'].
| ^~~~~~~~
-ctables.sps:8.53: error: CTABLES: This category specification may be applied
-only to numeric variables, but this subcommand tries to apply it to string
-variable string.
+ctables.sps:8.53: error: CTABLES: This category specification may be applied only to numeric variables, but this
+subcommand tries to apply it to string variable string.
8 | CTABLES /TABLE string /CATEGORIES VARIABLES=string [1].
| ^
-ctables.sps:10.74-10.86: error: CTABLES: Syntax error at `KEY=MEAN(qn1)': Data-
-dependent sorting is not implemented.
+ctables.sps:10.74-10.86: error: CTABLES: Data-dependent sorting is not implemented.
+ 10 | CTABLES /TABLE qn1 /CLABELS ROWLABELS=OPPOSITE /CATEGORIES VARIABLES=qn1 KEY=MEAN(qn1).
+ | ^~~~~~~~~~~~~
+
+ctables.sps:12: error: CTABLES: To move category labels from one axis to another, the variables whose labels are to be
+moved must be categorical, but qnd1 is scale.
+
+ctables.sps:12.22-12.47: note: CTABLES: This syntax moves category labels to another axis.
+ 12 | CTABLES /TABLE qnd1 /CLABELS ROWLABELS=OPPOSITE.
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ctables.sps:13: error: CTABLES: To move category labels from one axis to another, the variables whose labels are to be
+moved must all have the same width, but QN1 has width 0 and string has width 8.
+
+ctables.sps:13.30-13.55: note: CTABLES: This syntax moves category labels to another axis.
+ 13 | CTABLES /TABLE qn1 + string /CLABELS ROWLABELS=OPPOSITE.
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~
-ctables.sps:12: error: CTABLES: ROWLABELS=OPPOSITE requires the variables to be
-moved to be categorical, but qnd1 is a scale variable.
+ctables.sps:14: error: CTABLES: To move category labels from one axis to another, the variables whose labels are to be
+moved must all have the same value labels, but QN1 and QNSA1 have different value labels.
-ctables.sps:13: error: CTABLES: ROWLABELS=OPPOSITE requires the variables to be
-moved to have the same width, but QN1 has width 0 and string has width 8.
+ctables.sps:14.29-14.54: note: CTABLES: This syntax moves category labels to another axis.
+ 14 | CTABLES /TABLE qn1 + qnsa1 /CLABELS ROWLABELS=OPPOSITE.
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~
-ctables.sps:14: error: CTABLES: ROWLABELS=OPPOSITE requires the variables to be
-moved to have the same value labels, but QN1 and QNSA1 have different value
-labels.
+ctables.sps:15: error: CTABLES: To move category labels from one axis to another, the variables whose labels are to be
+moved must all have the same category specifications, but QN105BA and QN105BB have different category specifications.
-ctables.sps:15: error: CTABLES: ROWLABELS=OPPOSITE requires the variables to be
-moved to have the same category specifications, but QN105BA and QN105BB have
-different category specifications.
+ctables.sps:15.35-15.60: note: CTABLES: This syntax moves category labels to another axis.
+ 15 | CTABLES /TABLE qn105ba + qn105bb /CLABELS ROWLABELS=OPPOSITE /CATEGORIES VARIABLES=qn105ba [1,2,3].
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~
-ctables.sps:17.27-17.33: warning: CTABLES: The exponentiation operator (`**') is
-left-associative: `a**b**c' equals `(a**b)**c', not `a**(b**c)'. To disable
-this warning, insert parentheses.
+ctables.sps:17.27-17.33: warning: CTABLES: The exponentiation operator (`**') is left-associative: `a**b**c' equals
+`(a**b)**c', not `a**(b**c)'. To disable this warning, insert parentheses.
17 | CTABLES /PCOMPUTE &x=EXPR(1**2**3).
| ^~~~~~~
-ctables.sps:17.35: error: CTABLES: Syntax error at end of command: expecting
-`/'.
+ctables.sps:17.35: error: CTABLES: Syntax error expecting `/'.
+ 17 | CTABLES /PCOMPUTE &x=EXPR(1**2**3).
+ | ^
-ctables.sps:18.28-18.29: error: CTABLES: Syntax error at `**'.
+ctables.sps:18.28-18.29: error: CTABLES: Syntax error.
+ 18 | CTABLES /PCOMPUTE &x=EXPR([**]).
+ | ^~
-ctables.sps:19.27-19.28: error: CTABLES: Syntax error at `**'.
+ctables.sps:19.27-19.28: error: CTABLES: Syntax error.
+ 19 | CTABLES /PCOMPUTE &x=EXPR(**).
+ | ^~
-ctables.sps:21.15: error: CTABLES: Syntax error at end of command: At least one
-variable must be specified.
+ctables.sps:21.15: error: CTABLES: At least one variable must be specified.
+ 21 | CTABLES /TABLE.
+ | ^
ctables.sps:23: error: CTABLES: Summaries may appear only on one axis.
-ctables.sps:23.50-23.54: note: CTABLES: This variable on the layers axis has a
-summary.
+ctables.sps:23.50-23.54: note: CTABLES: This variable on the layers axis has a summary.
23 | CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT].
| ^~~~~
-ctables.sps:23.16-23.20: note: CTABLES: This variable on the rows axis has a
-summary.
+ctables.sps:23.16-23.20: note: CTABLES: This variable on the rows axis has a summary.
23 | CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT].
| ^~~~~
-ctables.sps:23.33-23.37: note: CTABLES: This variable on the columns axis has a
-summary.
+ctables.sps:23.33-23.37: note: CTABLES: This variable on the columns axis has a summary.
23 | CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT].
| ^~~~~
-ctables.sps:23.33-23.37: note: CTABLES: This is a scale variable, so it always
-has a summary even if the syntax does not explicitly specify one.
+ctables.sps:23.33-23.37: note: CTABLES: This is a scale variable, so it always has a summary even if the syntax does not
+explicitly specify one.
23 | CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT].
| ^~~~~
-ctables.sps:25.46-25.63: error: CTABLES: Syntax error at `KEY=PTILE(qn1, 50)':
-Data-dependent sorting is not implemented.
+ctables.sps:25.46-25.63: error: CTABLES: Data-dependent sorting is not implemented.
+ 25 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 KEY=PTILE(qn1, 50).
+ | ^~~~~~~~~~~~~~~~~~
+
+ctables.sps:27.16-27.21: error: CTABLES: Multiple response set support not implemented.
+ 27 | CTABLES /TABLE $mrset.
+ | ^~~~~~
+
+ctables.sps:29.23-29.44: error: CTABLES: Support for SIGTEST not yet implemented.
+ 29 | CTABLES /TABLE qn113 /SIGTEST TYPE=CHISQUARE.
+ | ^~~~~~~~~~~~~~~~~~~~~~
-ctables.sps:27.16-27.21: error: CTABLES: Syntax error at `$mrset': Multiple
-response set support not implemented.
+ctables.sps:30.23-30.43: error: CTABLES: Support for COMPARETEST not yet implemented.
+ 30 | CTABLES /TABLE qn113 /COMPARETEST TYPE=PROP.
+ | ^~~~~~~~~~~~~~~~~~~~~
-ctables.sps:29.23-29.44: error: CTABLES: Syntax error at `SIGTEST
-TYPE=CHISQUARE': Support for SIGTEST not yet implemented.
+ctables.sps:32.23-32.31: error: CTABLES: Support for LCL, UCL, and SE summary functions is not yet implemented.
+ 32 | CTABLES /TABLE qn113 [COUNT.UCL].
+ | ^~~~~~~~~
-ctables.sps:30.35-30.43: error: CTABLES: Syntax error at `TYPE=PROP': Support
-for COMPARETEST not yet implemented.
+ctables.sps:34.32-34.33: error: CTABLES: Syntax error expecting VARIABLES.
+ 34 | CTABLES /TABLE qn1 /CATEGORIES **.
+ | ^~
-ctables.sps:32.23-32.31: error: CTABLES: Syntax error at `COUNT.UCL': Support
-for LCL, UCL, and SE summary functions is not yet implemented.
+ctables.sps:36.10-36.15: error: CTABLES: Syntax error expecting one of the following: FORMAT, VLABELS, MRSETS, SMISSING,
+PCOMPUTE, PPROPERTIES, WEIGHT, HIDESMALLCOUNTS, TABLE.
+ 36 | CTABLES /TITLES.
+ | ^~~~~~
-ctables.sps:34.32-34.33: error: CTABLES: Syntax error at `**': expecting
-VARIABLES.
+ctables.sps:36.10-36.15: note: CTABLES: TABLE must appear before this subcommand.
+ 36 | CTABLES /TITLES.
+ | ^~~~~~
]])
AT_CLEANUP
DESCRIPTIVES ALL/STATISTICS=COUNT MEAN.
])
AT_CHECK([pspp descriptives.sps], [1], [dnl
-descriptives.sps:5.29-5.33: error: DESCRIPTIVES: Syntax error at `COUNT':
-expecting statistic name: reverting to default.
-
-descriptives.sps:5.35-5.38: error: DESCRIPTIVES: Syntax error at `MEAN'.
+descriptives.sps:5.29-5.33: error: DESCRIPTIVES: Syntax error expecting one of
+the following: MEAN, SEMEAN, STDDEV, VARIANCE, KURTOSIS, SEKURTOSIS, SKEWNESS,
+SESKEWNESS, RANGE, MINIMUM, MAXIMUM, SUM.
+ 5 | DESCRIPTIVES ALL/STATISTICS=COUNT MEAN.
+ | ^~~~~
+
+descriptives.sps:5.35-5.38: error: DESCRIPTIVES: Syntax error.
+ 5 | DESCRIPTIVES ALL/STATISTICS=COUNT MEAN.
+ | ^~~~
])
AT_CLEANUP
y,16,17,18,19
z,21,22,23,24
-flip.sps:12: warning: FLIP: FLIP ignores TEMPORARY. Temporary transformations will be made permanent.
+"flip.sps:12.1-12.4: warning: FLIP: FLIP ignores TEMPORARY. Temporary transformations will be made permanent.
+ 12 | flip newnames=n.
+ | ^~~~"
Table: Data List
CASE_LBL,v,w,x,y,z
END MATRIX.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:2.10: error: COMPUTE: Syntax error at end of command: expecting `='.
+matrix.sps:2.10: error: COMPUTE: Syntax error expecting `='.
+ 2 | COMPUTE x.
+ | ^
-matrix.sps:3.11: error: COMPUTE: Syntax error at end of command.
+matrix.sps:3.11: error: COMPUTE: Syntax error.
+ 3 | COMPUTE x=.
+ | ^
matrix.sps:4.9: error: MATRIX: Undefined variable x.
4 | COMPUTE x(5)=1.
| ^
-matrix.sps:5: error: COMPUTE: Undefined variable y.
+matrix.sps:5.9: error: COMPUTE: Undefined variable y.
+ 5 | COMPUTE y(5)=1.
+ | ^
])
AT_CLEANUP
END MATRIX.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:2: error: BREAK: BREAK not inside LOOP.
+matrix.sps:2.1-2.5: error: BREAK: BREAK not inside LOOP.
+ 2 | BREAK.
+ | ^~~~~
])
AT_CLEANUP
.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:2.6: error: READ: Syntax error at `!': expecting identifier.
+matrix.sps:2.6: error: READ: Syntax error expecting identifier.
+ 2 | READ !.
+ | ^
-matrix.sps:3.13: error: READ: Syntax error at `!': expecting a file name or
-handle name.
+matrix.sps:3.13: error: READ: Syntax error expecting a file name or handle
+name.
+ 3 | READ x/FILE=!.
+ | ^
-matrix.sps:4.17: error: READ: Syntax error at `!': expecting string.
+matrix.sps:4.17: error: READ: Syntax error expecting string.
+ 4 | READ x/ENCODING=!.
+ | ^
-matrix.sps:5.14: error: READ: Syntax error at `!': Expected positive integer
-for FIELD.
+matrix.sps:5.14: error: READ: Syntax error expecting positive integer for
+FIELD.
+ 5 | READ x/FIELD=!.
+ | ^
-matrix.sps:6.16: error: READ: Syntax error at `!': expecting `TO'.
+matrix.sps:6.16: error: READ: Syntax error expecting `TO'.
+ 6 | READ x/FIELD=1 !.
+ | ^
-matrix.sps:7.19: error: READ: Syntax error at `!': Expected positive integer
-for TO.
+matrix.sps:7.19: error: READ: Syntax error expecting positive integer for TO.
+ 7 | READ x/FIELD=1 TO !.
+ | ^
-matrix.sps:8.19: error: READ: Syntax error at `0': Expected positive integer
-for TO.
+matrix.sps:8.19: error: READ: Syntax error expecting positive integer for TO.
+ 8 | READ x/FIELD=1 TO 0.
+ | ^
-matrix.sps:9.25: error: READ: Syntax error at `!': Expected integer between 1
-and 10 for BY.
+matrix.sps:9.25: error: READ: Syntax error expecting integer between 1 and 10
+for BY.
+ 9 | READ x/FIELD=1 TO 10 BY !.
+ | ^
-matrix.sps:10: error: READ: BY 6 does not evenly divide record width 10.
+matrix.sps:10.14-10.25: error: READ: Field width 6 does not evenly divide
+record width 10.
+ 10 | READ x/FIELD=1 TO 10 BY 6.
+ | ^~~~~~~~~~~~
+
+matrix.sps:10.14-10.20: note: READ: This syntax designates the record width.
+ 10 | READ x/FIELD=1 TO 10 BY 6.
+ | ^~~~~~~
-matrix.sps:11.13: error: READ: Syntax error at `!'.
+matrix.sps:10.25: note: READ: This syntax specifies the field width.
+ 10 | READ x/FIELD=1 TO 10 BY 6.
+ | ^
-matrix.sps:12.13: error: READ: Syntax error at `!': expecting RECTANGULAR or
-SYMMETRIC.
+matrix.sps:11.13: error: READ: Syntax error.
+ 11 | READ x/SIZE=!.
+ | ^
-matrix.sps:13.15: error: READ: Syntax error at `!': expecting identifier.
+matrix.sps:12.13: error: READ: Syntax error expecting RECTANGULAR or SYMMETRIC.
+ 12 | READ x/MODE=!.
+ | ^
-matrix.sps:14: error: READ: Subcommand FORMAT may only be specified once.
+matrix.sps:13.15: error: READ: Syntax error expecting identifier.
+ 13 | READ x/FORMAT=!.
+ | ^
+
+matrix.sps:14.20-14.25: error: READ: Subcommand FORMAT may only be specified
+once.
+ 14 | READ x/FORMAT=F8.2/FORMAT=F8.2.
+ | ^~~~~~
-matrix.sps:15.15-15.22: error: READ: Syntax error at `'5XYZZY'': Unknown format
-XYZZY.
+matrix.sps:15.15-15.22: error: READ: Unknown format XYZZY.
+ 15 | READ x/FORMAT='5XYZZY'.
+ | ^~~~~~~~
-matrix.sps:16: error: READ: Unknown format type `XYZZY'.
+matrix.sps:16.15-16.19: error: READ: Unknown format type `XYZZY'.
+ 16 | READ x/FORMAT=XYZZY.
+ | ^~~~~
-matrix.sps:17.8: error: READ: Syntax error at `!': expecting FILE, FIELD, MODE,
-REREAD, or FORMAT.
+matrix.sps:17.8: error: READ: Syntax error expecting FILE, FIELD, MODE, REREAD,
+or FORMAT.
+ 17 | READ x/!.
+ | ^
matrix.sps:18: error: READ: Required subcommand FIELD was not specified.
matrix.sps:19: error: READ: SIZE is required for reading data into a full
matrix (as opposed to a submatrix).
+matrix.sps:19.6: note: READ: This expression designates a full matrix.
+ 19 | READ x/FIELD=1 TO 10.
+ | ^
+
matrix.sps:20: error: READ: Required subcommand FILE was not specified.
matrix.sps:21: error: READ: 15 repetitions cannot fit in record width 10.
-matrix.sps:22: error: READ: FORMAT specifies field width 5 but BY specifies 2.
+matrix.sps:21.57-21.61: note: READ: This syntax designates the number of
+repetitions.
+ 21 | READ x/FIELD=1 TO 10/SIZE={1,2}/FILE='xyzzy.txt'/FORMAT='15F'.
+ | ^~~~~
+
+matrix.sps:21.14-21.20: note: READ: This syntax designates the record width.
+ 21 | READ x/FIELD=1 TO 10/SIZE={1,2}/FILE='xyzzy.txt'/FORMAT='15F'.
+ | ^~~~~~~
+
+matrix.sps:22: error: READ: This command specifies two different field widths.
-matrix.sps:23: error: READ: FORMAT specifies 2 repetitions with record width
-10, which implies field width 5, but BY specifies field width 2.
+matrix.sps:22.62-22.63: note: READ: This syntax specifies field width 5.
+ 22 | READ x/FIELD=1 TO 10 BY 2/SIZE={1,2}/FILE='xyzzy.txt'/FORMAT=F5.
+ | ^~
+
+matrix.sps:22.25: note: READ: This syntax specifies field width 2.
+ 22 | READ x/FIELD=1 TO 10 BY 2/SIZE={1,2}/FILE='xyzzy.txt'/FORMAT=F5.
+ | ^
+
+matrix.sps:23: error: READ: This command specifies two different field widths.
+
+matrix.sps:23.62-23.65: note: READ: This syntax specifies 2 repetitions.
+ 23 | READ x/FIELD=1 TO 10 BY 2/SIZE={1,2}/FILE='xyzzy.txt'/FORMAT='2F'.
+ | ^~~~
+
+matrix.sps:23.14-23.20: note: READ: This syntax designates record width 10,
+which divided by 2 repetitions implies field width 5.
+ 23 | READ x/FIELD=1 TO 10 BY 2/SIZE={1,2}/FILE='xyzzy.txt'/FORMAT='2F'.
+ | ^~~~~~~
+
+matrix.sps:23.25: note: READ: This syntax specifies field width 2.
+ 23 | READ x/FIELD=1 TO 10 BY 2/SIZE={1,2}/FILE='xyzzy.txt'/FORMAT='2F'.
+ | ^
matrix.sps:24.27-24.35: error: MATRIX: SIZE must evaluate to a scalar or a 2-
element vector, not a 2×2 matrix.
END MATRIX.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:2.7: error: WRITE: Syntax error at `!'.
+matrix.sps:2.7: error: WRITE: Syntax error.
+ 2 | WRITE !.
+ | ^
-matrix.sps:3.17: error: WRITE: Syntax error at `!': expecting a file name or
-handle name.
+matrix.sps:3.17: error: WRITE: Syntax error expecting a file name or handle
+name.
+ 3 | WRITE 1/OUTFILE=!.
+ | ^
-matrix.sps:4.18: error: WRITE: Syntax error at `!': expecting string.
+matrix.sps:4.18: error: WRITE: Syntax error expecting string.
+ 4 | WRITE 1/ENCODING=!.
+ | ^
-matrix.sps:5.15: error: WRITE: Syntax error at `!': Expected positive integer
-for FIELD.
+matrix.sps:5.15: error: WRITE: Syntax error expecting positive integer for
+FIELD.
+ 5 | WRITE 1/FIELD=!.
+ | ^
-matrix.sps:6.17: error: WRITE: Syntax error at `!': expecting `TO'.
+matrix.sps:6.17: error: WRITE: Syntax error expecting `TO'.
+ 6 | WRITE 1/FIELD=1 !.
+ | ^
-matrix.sps:7.20: error: WRITE: Syntax error at `0': Expected positive integer
-for TO.
+matrix.sps:7.20: error: WRITE: Syntax error expecting positive integer for TO.
+ 7 | WRITE 1/FIELD=1 TO 0.
+ | ^
-matrix.sps:8.26-8.27: error: WRITE: Syntax error at `20': Expected integer
-between 1 and 10 for BY.
+matrix.sps:8.26-8.27: error: WRITE: Syntax error expecting integer between 1
+and 10 for BY.
+ 8 | WRITE 1/FIELD=1 TO 10 BY 20.
+ | ^~
+
+matrix.sps:9.15-9.26: error: WRITE: Field width 6 does not evenly divide record
+width 10.
+ 9 | WRITE 1/FIELD=1 TO 10 BY 6.
+ | ^~~~~~~~~~~~
+
+matrix.sps:9.15-9.21: note: WRITE: This syntax designates the record width.
+ 9 | WRITE 1/FIELD=1 TO 10 BY 6.
+ | ^~~~~~~
+
+matrix.sps:9.26: note: WRITE: This syntax specifies the field width.
+ 9 | WRITE 1/FIELD=1 TO 10 BY 6.
+ | ^
+
+matrix.sps:10.14-10.24: error: WRITE: Syntax error expecting RECTANGULAR or
+TRIANGULAR.
+ 10 | WRITE 1/MODE=TRAPEZOIDAL.
+ | ^~~~~~~~~~~
+
+matrix.sps:11.19-11.24: error: WRITE: Subcommand FORMAT may only be specified
+once.
+ 11 | WRITE 1/FORMAT=F5/FORMAT=F5.
+ | ^~~~~~
-matrix.sps:9: error: WRITE: BY 6 does not evenly divide record width 10.
+matrix.sps:12.16-12.22: error: WRITE: Unknown format ASDF.
+ 12 | WRITE 1/FORMAT='5ASDF'.
+ | ^~~~~~~
-matrix.sps:10.14-10.24: error: WRITE: Syntax error at `TRAPEZOIDAL': expecting
-RECTANGULAR or TRIANGULAR.
+matrix.sps:13.16-13.20: error: WRITE: Unknown format type `ASDF'.
+ 13 | WRITE 1/FORMAT=ASDF5.
+ | ^~~~~
-matrix.sps:11: error: WRITE: Subcommand FORMAT may only be specified once.
+matrix.sps:14.9: error: WRITE: Syntax error expecting OUTFILE, FIELD, MODE,
+HOLD, or FORMAT.
+ 14 | WRITE 1/!.
+ | ^
-matrix.sps:12.16-12.22: error: WRITE: Syntax error at `'5ASDF'': Unknown format
-ASDF.
+matrix.sps:15: error: WRITE: Required subcommand FIELD was not specified.
-matrix.sps:13: error: WRITE: Unknown format type `ASDF'.
+matrix.sps:16: error: WRITE: Required subcommand OUTFILE was not specified.
-matrix.sps:14.9: error: WRITE: Syntax error at `!': expecting OUTFILE, FIELD,
-MODE, HOLD, or FORMAT.
+matrix.sps:17.51-17.55: note: WRITE: This syntax designates the number of
+repetitions.
+ 17 | WRITE 1/FIELD=1 TO 10/OUTFILE='matrix.txt'/FORMAT='15F'.
+ | ^~~~~
-matrix.sps:15: error: WRITE: Required subcommand FIELD was not specified.
+matrix.sps:17.15-17.21: note: WRITE: This syntax designates the record width.
+ 17 | WRITE 1/FIELD=1 TO 10/OUTFILE='matrix.txt'/FORMAT='15F'.
+ | ^~~~~~~
-matrix.sps:16: error: WRITE: Required subcommand OUTFILE was not specified.
+matrix.sps:18: error: WRITE: This command specifies two different field widths.
+
+matrix.sps:18.56-18.59: note: WRITE: This syntax specifies 5 repetitions.
+ 18 | WRITE 1/FIELD=1 TO 10 BY 5/OUTFILE='matrix.txt'/FORMAT='5F'.
+ | ^~~~
-matrix.sps:17: error: WRITE: 15 repetitions cannot fit in record width 10.
+matrix.sps:18.15-18.21: note: WRITE: This syntax designates record width 10,
+which divided by 5 repetitions implies field width 2.
+ 18 | WRITE 1/FIELD=1 TO 10 BY 5/OUTFILE='matrix.txt'/FORMAT='5F'.
+ | ^~~~~~~
-matrix.sps:18: error: WRITE: FORMAT specifies 5 repetitions with record width
-10, which implies field width 2, but BY specifies field width 5.
+matrix.sps:18.26: note: WRITE: This syntax specifies field width 5.
+ 18 | WRITE 1/FIELD=1 TO 10 BY 5/OUTFILE='matrix.txt'/FORMAT='5F'.
+ | ^
matrix.sps:19: error: WRITE: Output format E5.0 specifies width 5, but E
requires a width between 6 and 40.
-matrix.sps:20: error: WRITE: Format A9 is too wide for 8-byte matrix elements.
+matrix.sps:20.51-20.52: error: WRITE: Format A9 is too wide for 8-byte matrix
+elements.
+ 20 | WRITE 1/FIELD=1 TO 10/OUTFILE='matrix.txt'/FORMAT=A9.
+ | ^~
matrix.sps:21.7-21.11: error: MATRIX: WRITE with MODE=TRIANGULAR requires a
square matrix but the matrix to be written has dimensions 1×2.
END MATRIX.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:12.5: error: GET: Syntax error at `!': expecting identifier.
+matrix.sps:12.5: error: GET: Syntax error expecting identifier.
+ 12 | GET !.
+ | ^
-matrix.sps:13.17: error: GET: Syntax error at `!': expecting variable name.
+matrix.sps:13.17: error: GET: Syntax error expecting variable name.
+ 13 | GET x/VARIABLES=!.
+ | ^
-matrix.sps:14.12: error: GET: Syntax error at `!': expecting a file name or
-handle name.
+matrix.sps:14.12: error: GET: Syntax error expecting a file name or handle
+name.
+ 14 | GET x/FILE=!.
+ | ^
-matrix.sps:15.16: error: GET: Syntax error at `!': expecting string.
+matrix.sps:15.16: error: GET: Syntax error expecting string.
+ 15 | GET x/ENCODING=!.
+ | ^
-matrix.sps:16.13: error: GET: Syntax error at `!': expecting identifier.
+matrix.sps:16.13: error: GET: Syntax error expecting identifier.
+ 16 | GET x/NAMES=!.
+ | ^
-matrix.sps:17.15: error: GET: Syntax error at `!'.
+matrix.sps:17.15: error: GET: Syntax error.
+ 17 | GET x/MISSING=!.
+ | ^
-matrix.sps:18.14: error: GET: Syntax error at `!'.
+matrix.sps:18.14: error: GET: Syntax error.
+ 18 | GET x/SYSMIS=!.
+ | ^
-matrix.sps:19.7: error: GET: Syntax error at `!': expecting FILE, VARIABLES,
-NAMES, MISSING, or SYSMIS.
+matrix.sps:19.7: error: GET: Syntax error expecting FILE, VARIABLES, NAMES,
+MISSING, or SYSMIS.
+ 19 | GET x/!.
+ | ^
-matrix.sps:20.17: error: GET: Syntax error at `!': expecting variable name.
+matrix.sps:20.17: error: GET: Syntax error expecting variable name.
+ 20 | GET x/VARIABLES=!.
+ | ^
-matrix.sps:21.22: error: GET: Syntax error at `!': expecting variable name.
+matrix.sps:21.22: error: GET: Syntax error expecting variable name.
+ 21 | GET x/VARIABLES=x TO !.
+ | ^
-matrix.sps:22: error: MATRIX: x is not a variable name.
+matrix.sps:22.17: error: MATRIX: x is not a variable name.
+ 22 | GET x/VARIABLES=x.
+ | ^
-matrix.sps:23: error: MATRIX: c TO a is not valid syntax since c precedes a in
-the dictionary.
+matrix.sps:23.17-23.22: error: MATRIX: c TO a is not valid syntax since c
+precedes a in the dictionary.
+ 23 | GET x/VARIABLES=c TO a.
+ | ^~~~~~
-matrix.sps:24: warning: MATRIX: d is not a numeric variable.
+matrix.sps:24.17: error: MATRIX: d is not a numeric variable.
+ 24 | GET x/VARIABLES=d.
+ | ^
matrix.sps:25: error: MATRIX: Variable d is not numeric.
-error: The GET command cannot read an empty active file.
+matrix.sps:30: error: MATRIX: The GET command cannot read an empty active file.
])
AT_CLEANUP
END MATRIX.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:2.6: error: SAVE: Syntax error at `!'.
+matrix.sps:2.6: error: SAVE: Syntax error.
+ 2 | SAVE !.
+ | ^
-matrix.sps:3.16: error: SAVE: Syntax error at `!': expecting a file name or
-handle name.
+matrix.sps:3.16: error: SAVE: Syntax error expecting a file name or handle
+name.
+ 3 | SAVE 1/OUTFILE=!.
+ | ^
-matrix.sps:4.18: error: SAVE: Syntax error at `!': expecting variable name.
+matrix.sps:4.18: error: SAVE: Syntax error expecting variable name.
+ 4 | SAVE 1/VARIABLES=!.
+ | ^
-matrix.sps:5.14: error: SAVE: Syntax error at `!'.
+matrix.sps:5.14: error: SAVE: Syntax error.
+ 5 | SAVE 1/NAMES=!.
+ | ^
-matrix.sps:6.8: error: SAVE: Syntax error at `!': expecting OUTFILE, VARIABLES,
-NAMES, or STRINGS.
+matrix.sps:6.8: error: SAVE: Syntax error expecting OUTFILE, VARIABLES, NAMES,
+or STRINGS.
+ 6 | SAVE 1/!.
+ | ^
matrix.sps:7: error: SAVE: Required subcommand OUTFILE was not specified.
END MATRIX.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:2.6: error: MGET: Syntax error at `!': expecting FILE or TYPE.
+matrix.sps:2.6: error: MGET: Syntax error expecting FILE or TYPE.
+ 2 | MGET !.
+ | ^
-matrix.sps:3.11: error: MGET: Syntax error at `!': expecting a file name or
-handle name.
+matrix.sps:3.11: error: MGET: Syntax error expecting a file name or handle
+name.
+ 3 | MGET FILE=!.
+ | ^
-matrix.sps:4.15: error: MGET: Syntax error at `!': expecting string.
+matrix.sps:4.15: error: MGET: Syntax error expecting string.
+ 4 | MGET ENCODING=!.
+ | ^
-matrix.sps:5.11: error: MGET: Syntax error at `!': expecting COV, CORR, MEAN,
-STDDEV, N, or COUNT.
+matrix.sps:5.11: error: MGET: Syntax error expecting COV, CORR, MEAN, STDDEV,
+N, or COUNT.
+ 5 | MGET TYPE=!.
+ | ^
-matrix.sps:6.16: error: MGET: Syntax error at `!': expecting COV, CORR, MEAN,
-STDDEV, N, or COUNT.
+matrix.sps:6.16: error: MGET: Syntax error expecting COV, CORR, MEAN, STDDEV,
+N, or COUNT.
+ 6 | MGET TYPE=CORR !.
+ | ^
])
AT_CLEANUP
END MATRIX.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:2.7: error: MSAVE: Syntax error at `!'.
+matrix.sps:2.7: error: MSAVE: Syntax error.
+ 2 | MSAVE !.
+ | ^
-matrix.sps:3.14: error: MSAVE: Syntax error at `!': expecting COV, CORR, MEAN,
-STDDEV, N, or COUNT.
+matrix.sps:3.14: error: MSAVE: Syntax error expecting COV, CORR, MEAN, STDDEV,
+N, or COUNT.
+ 3 | MSAVE 1/TYPE=!.
+ | ^
-matrix.sps:4.17: error: MSAVE: Syntax error at `!': expecting a file name or
-handle name.
+matrix.sps:4.17: error: MSAVE: Syntax error expecting a file name or handle
+name.
+ 4 | MSAVE 1/OUTFILE=!.
+ | ^
-matrix.sps:5.19: error: MSAVE: Syntax error at `!': expecting variable name.
+matrix.sps:5.19: error: MSAVE: Syntax error expecting variable name.
+ 5 | MSAVE 1/VARIABLES=!.
+ | ^
-matrix.sps:6.16: error: MSAVE: Syntax error at `!': expecting variable name.
+matrix.sps:6.16: error: MSAVE: Syntax error expecting variable name.
+ 6 | MSAVE 1/FNAMES=!.
+ | ^
-matrix.sps:7.16: error: MSAVE: Syntax error at `!': expecting variable name.
+matrix.sps:7.16: error: MSAVE: Syntax error expecting variable name.
+ 7 | MSAVE 1/SNAMES=!.
+ | ^
-matrix.sps:8.15: error: MSAVE: Syntax error at `!'.
+matrix.sps:8.15: error: MSAVE: Syntax error.
+ 8 | MSAVE 1/SPLIT=!.
+ | ^
-matrix.sps:9.16: error: MSAVE: Syntax error at `!'.
+matrix.sps:9.16: error: MSAVE: Syntax error.
+ 9 | MSAVE 1/FACTOR=!.
+ | ^
-matrix.sps:10.9: error: MSAVE: Syntax error at `!': expecting TYPE, OUTFILE,
-VARIABLES, FNAMES, SNAMES, SPLIT, or FACTOR.
+matrix.sps:10.9: error: MSAVE: Syntax error expecting TYPE, OUTFILE, VARIABLES,
+FNAMES, SNAMES, SPLIT, or FACTOR.
+ 10 | MSAVE 1/!.
+ | ^
matrix.sps:11: error: MSAVE: Required subcommand TYPE was not specified.
-matrix.sps:12: error: MSAVE: FNAMES requires FACTOR.
+matrix.sps:12.25: error: MSAVE: FNAMES requires FACTOR.
+ 12 | MSAVE 1/TYPE=COV/FNAMES=x.
+ | ^
-matrix.sps:13: error: MSAVE: SNAMES requires SPLIT.
+matrix.sps:13.25: error: MSAVE: SNAMES requires SPLIT.
+ 13 | MSAVE 1/TYPE=COV/SNAMES=x.
+ | ^
matrix.sps:14: error: MSAVE: Required subcommand OUTFILE was not specified.
matrix.sps:20: error: MSAVE: OUTFILE must name the same file on each MSAVE
within a single MATRIX command.
-matrix.sps:21: error: MSAVE: VARIABLES must specify the same variables each
-time within a given MATRIX.
+matrix.sps:16.26-16.37: note: MSAVE: This is the OUTFILE on the first MSAVE
+command.
+ 16 | MSAVE 1/TYPE=COV/OUTFILE='matrix.sav'
+ | ^~~~~~~~~~~~
+
+matrix.sps:20.26-20.38: note: MSAVE: This is the OUTFILE on a later MSAVE
+command.
+ 20 | MSAVE 1/TYPE=COV/OUTFILE='matrix2.sav'.
+ | ^~~~~~~~~~~~~
-matrix.sps:16-19: note: MSAVE: This is the location of the first MSAVE command.
+matrix.sps:21: error: MSAVE: VARIABLES must specify the same variables on each
+MSAVE within a given MATRIX.
-matrix.sps:22: error: MSAVE: FNAMES must specify the same variables each time
-within a given MATRIX.
+matrix.sps:19.16: error: MSAVE: This is the specification of VARIABLES on the
+first MSAVE.
+ 19 | /VARIABLES=w.
+ | ^
-matrix.sps:16-19: note: MSAVE: This is the location of the first MSAVE command.
+matrix.sps:21.28: error: MSAVE: This is a different specification of VARIABLES
+on a later MSAVE.
+ 21 | MSAVE 1/TYPE=COV/VARIABLES=x.
+ | ^
-matrix.sps:23: error: MSAVE: SNAMES must specify the same variables each time
-within a given MATRIX.
+matrix.sps:22: error: MSAVE: FNAMES must specify the same variables on each
+MSAVE within a given MATRIX.
-matrix.sps:16-19: note: MSAVE: This is the location of the first MSAVE command.
+matrix.sps:17.23: error: MSAVE: This is the specification of FNAMES on the
+first MSAVE.
+ 17 | /FACTOR=1 /FNAMES=y
+ | ^
+
+matrix.sps:22.25: error: MSAVE: This is a different specification of FNAMES on
+a later MSAVE.
+ 22 | MSAVE 1/TYPE=COV/FNAMES=x.
+ | ^
+
+matrix.sps:23: error: MSAVE: SNAMES must specify the same variables on each
+MSAVE within a given MATRIX.
+
+matrix.sps:18.22: error: MSAVE: This is the specification of SNAMES on the
+first MSAVE.
+ 18 | /SPLIT=2 /SNAMES=z
+ | ^
+
+matrix.sps:23.25: error: MSAVE: This is a different specification of SNAMES on
+a later MSAVE.
+ 23 | MSAVE 1/TYPE=COV/SNAMES=x.
+ | ^
matrix.sps:28.7-28.11: error: MATRIX: Matrix on MSAVE has 2 columns but there
are 1 variables.
31 | MSAVE 0/TYPE=COV/FACTOR=1/SPLIT={1;2}.
| ^~~~~
-matrix.sps:35: error: MSAVE: Variable x appears twice in variable list.
+matrix.sps:35.49: error: MSAVE: Variable x appears twice in variable list.
+ 35 | MSAVE 1/TYPE=COV/OUTFILE='matrix4.sav'/SNAMES=x,x/SPLIT=1.
+ | ^
-matrix.sps:39: error: MATRIX: Duplicate or invalid FACTOR variable name x.
+matrix.sps:39.56: error: MATRIX: Duplicate or invalid FACTOR variable name x.
+ 39 | MSAVE 1/TYPE=COV/OUTFILE='matrix5.sav'/SNAMES=x/FNAMES=x/SPLIT=1/
+FACTOR=1.
+ | ^
-matrix.sps:43: error: MATRIX: Duplicate or invalid variable name x.
+matrix.sps:43.50: error: MATRIX: Duplicate or invalid variable name x.
+ 43 | MSAVE 1/TYPE=COV/OUTFILE='matrix6.sav'/VARIABLES=x/FNAMES=x/FACTOR=1.
+ | ^
-matrix.sps:47: error: MATRIX: Duplicate or invalid variable name x.
+matrix.sps:47.50: error: MATRIX: Duplicate or invalid variable name x.
+ 47 | MSAVE 1/TYPE=COV/OUTFILE='matrix6.sav'/VARIABLES=x/SNAMES=x/SPLIT=1.
+ | ^
-matrix.sps:51: error: MSAVE: Variable name VARNAME_ is reserved.
+matrix.sps:51.47-51.54: error: MSAVE: Variable name VARNAME_ is reserved.
+ 51 | MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/SNAMES=VARNAME_.
+ | ^~~~~~~~
-matrix.sps:52: error: MSAVE: Variable name ROWTYPE_ is reserved.
+matrix.sps:52.47-52.54: error: MSAVE: Variable name ROWTYPE_ is reserved.
+ 52 | MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/SNAMES=ROWTYPE_.
+ | ^~~~~~~~
-matrix.sps:53: error: MSAVE: Variable name VARNAME_ is reserved.
+matrix.sps:53.47-53.54: error: MSAVE: Variable name VARNAME_ is reserved.
+ 53 | MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/FNAMES=VARNAME_.
+ | ^~~~~~~~
-matrix.sps:54: error: MSAVE: Variable name ROWTYPE_ is reserved.
+matrix.sps:54.47-54.54: error: MSAVE: Variable name ROWTYPE_ is reserved.
+ 54 | MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/FNAMES=ROWTYPE_.
+ | ^~~~~~~~
-matrix.sps:55: error: MSAVE: Variable name VARNAME_ is reserved.
+matrix.sps:55.50-55.57: error: MSAVE: Variable name VARNAME_ is reserved.
+ 55 | MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/VARIABLES=VARNAME_.
+ | ^~~~~~~~
-matrix.sps:56: error: MSAVE: Variable name ROWTYPE_ is reserved.
+matrix.sps:56.50-56.57: error: MSAVE: Variable name ROWTYPE_ is reserved.
+ 56 | MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/VARIABLES=ROWTYPE_.
+ | ^~~~~~~~
])
AT_CLEANUP
END MATRIX.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:2.9: error: DISPLAY: Syntax error at `!': expecting DICTIONARY or
-STATUS.
+matrix.sps:2.9: error: DISPLAY: Syntax error expecting DICTIONARY or STATUS.
+ 2 | DISPLAY !.
+ | ^
])
AT_CLEANUP
END MATRIX.
])
AT_CHECK([pspp matrix.sps], [1], [dnl
-matrix.sps:2.9: error: RELEASE: Syntax error at `!': expecting end of command.
+matrix.sps:2.9: error: RELEASE: Syntax error expecting end of command.
+ 2 | RELEASE !.
+ | ^
-matrix.sps:3.9: error: RELEASE: Syntax error at `x': Variable name expected.
+matrix.sps:3.9: error: RELEASE: Syntax error expecting variable name.
+ 3 | RELEASE x.
+ | ^
-matrix.sps:5.12: error: RELEASE: Syntax error at `!': expecting end of command.
+matrix.sps:5.12: error: RELEASE: Syntax error expecting end of command.
+ 5 | RELEASE x, !.
+ | ^
-matrix.sps:7.11: error: RELEASE: Syntax error at `y': expecting end of command.
+matrix.sps:7.11: error: RELEASE: Syntax error expecting end of command.
+ 7 | RELEASE x y.
+ | ^
])
AT_CLEANUP
\ No newline at end of file
QUICK CLUSTER x y /UNSUPPORTED.
])
AT_CHECK([pspp -O format=csv quick-cluster.sps], [1], [dnl
-quick-cluster.sps:7.20-7.30: error: QUICK CLUSTER: Syntax error at `UNSUPPORTED'.
+"quick-cluster.sps:7.20-7.30: error: QUICK CLUSTER: Syntax error.
+ 7 | QUICK CLUSTER x y /UNSUPPORTED.
+ | ^~~~~~~~~~~"
])
AT_CLEANUP
/RANK INTO foo bar wiz.
])
AT_CHECK([pspp -O format=csv rank.sps], [1], [dnl
-rank.sps:15.1: error: RANK: Syntax error at end of command: expecting `@{:@'.
+"rank.sps:15.1: error: RANK: Syntax error expecting `@{:@'.
+ 15 | .
+ | ^"
-rank.sps:19.11: error: RANK: Syntax error at `d': Expected positive integer for NTILES.
+"rank.sps:19.11: error: RANK: Syntax error expecting positive integer for NTILES.
+ 19 | /NTILES(d)
+ | ^"
-rank.sps:25: error: RANK: Variable x already exists.
+"rank.sps:25.13: error: RANK: Variable x already exists.
+ 25 | /RANK INTO x.
+ | ^"
-rank.sps:30: error: RANK: Too many variables in INTO clause.
+"rank.sps:30.18-30.20: error: RANK: Too many variables in INTO clause.
+ 30 | /RANK INTO foo bar wiz.
+ | ^~~"
])
AT_CLEANUP
])
AT_CHECK([pspp -O format=csv regression.sps], [0], [dnl
-regression.sps:16: warning: REGRESSION: REGRESSION with SAVE ignores FILTER. All cases will be processed.
+"regression.sps:16.82-16.96: warning: REGRESSION: REGRESSION with SAVE ignores FILTER. All cases will be processed.
+ 16 | regression /variables=v0 v1 v2 /statistics defaults /dependent=v2 /method=enter /save=pred resid.
+ | ^~~~~~~~~~~~~~~"
Table: Model Summary (v2)
R,R Square,Adjusted R Square,Std. Error of the Estimate
/VARIABLES=var6 var8 var15 var17
.
])
-AT_CHECK([pspp -o pspp.csv -o pspp.txt reliability.sps], [0],
- [reliability.sps:174: warning: RELIABILITY: The STATISTICS subcommand is not yet implemented. No statistics will be produced.
+AT_CHECK([pspp -o pspp.csv -o pspp.txt reliability.sps], [0], [dnl
+reliability.sps:174.4-174.40: warning: RELIABILITY: The STATISTICS subcommand is not yet implemented. No statistics will be produced.
+ 174 | /STATISTICS = DESCRIPTIVES COVARIANCES
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
])
AT_CHECK([cat pspp.csv], [0], [dnl
Scale: Everything
,Unequal Length,,.75
Guttman Split-Half Coefficient,,,.75
-reliability.sps:174: warning: RELIABILITY: The STATISTICS subcommand is not yet implemented. No statistics will be produced.
+"reliability.sps:174.4-174.40: warning: RELIABILITY: The STATISTICS subcommand is not yet implemented. No statistics will be produced.
+ 174 | /STATISTICS = DESCRIPTIVES COVARIANCES
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
Scale: Totals
t-test /GROUPS=indep('a') /var=dep1 dep2.
])
AT_CHECK([pspp -O format=csv t-test.sps], [1], [dnl
-"t-test.sps:17: error: T-TEST: When applying GROUPS to a string variable, two values must be specified."
+"t-test.sps:17.16-17.25: error: T-TEST: When applying GROUPS to a string variable, two values must be specified.
+ 17 | t-test /GROUPS=indep('a') /var=dep1 dep2.
+ | ^~~~~~~~~~"
])
AT_CLEANUP
HOST COMMAND=[['sleep 10']] TIMELIMIT=0.1.
])
AT_CHECK([pspp -O format=csv host.sps], [1], [dnl
-host.sps:2: error: HOST: This command not allowed when the SAFER option is set.
+"host.sps:2.1-2.4: error: HOST: This command not allowed when the SAFER option is set.
+ 2 | HOST COMMAND=[['sleep 10']] TIMELIMIT=0.1.
+ | ^~~~"
])
AT_CLEANUP
LIST.
])
AT_CHECK([pspp -o pspp.csv insert.sps], [1], [dnl
-batch.sps:2.1-2.4: error: INPUT PROGRAM: Syntax error at `loop': expecting end of command.
-batch.sps:3: error: COMPUTE: COMPUTE is allowed only after the active dataset has been defined or inside INPUT PROGRAM.
-batch.sps:4: error: END CASE: END CASE is allowed only inside INPUT PROGRAM.
-insert.sps:4: error: LIST: LIST is allowed only after the active dataset has been defined.
+batch.sps:2.1-2.4: error: INPUT PROGRAM: Syntax error expecting end of command.
+ 2 | loop #i = 1 to 5
+ | ^~~~
+batch.sps:3.4-3.10: error: COMPUTE: COMPUTE is allowed only after the active dataset has been defined or inside INPUT PROGRAM.
+ 3 | + compute z = #i
+ | ^~~~~~~
+batch.sps:4.4-4.11: error: END CASE: END CASE is allowed only inside INPUT PROGRAM.
+ 4 | + end case
+ | ^~~~~~~~
+insert.sps:4.1-4.4: error: LIST: LIST is allowed only after the active dataset has been defined.
+ 4 | LIST.
+ | ^~~~
])
AT_CLEANUP
])
AT_CHECK([pspp -o pspp.csv insert.sps], [1], [dnl
Dir1/foo.sps:1: error: INSERT: Can't find `bar.sps' in include file search path.
-insert.sps:2: error: LIST: LIST is allowed only after the active dataset has been defined.
+insert.sps:2.1-2.4: error: LIST: LIST is allowed only after the active dataset has been defined.
+ 2 | LIST.
+ | ^~~~
])
AT_CLEANUP
AT_DATA([insert.sps], [INSERT FILE='error.sps' ERROR=STOP.
])
AT_CHECK([pspp -o pspp.csv insert.sps], [1], [dnl
-error.sps:10: error: DISPLAY: AKSDJ is not a variable name.
+error.sps:10.9-10.13: error: DISPLAY: AKSDJ is not a variable name.
+ 10 | DISPLAY AKSDJ.
+ | ^~~~~
warning: Error encountered while ERROR=STOP is effective.
])
AT_CLEANUP
AT_DATA([insert.sps], [INSERT FILE='error.sps' ERROR=CONTINUE.
])
AT_CHECK([pspp -o pspp.csv insert.sps], [1], [dnl
-error.sps:10: error: DISPLAY: AKSDJ is not a variable name.
+error.sps:10.9-10.13: error: DISPLAY: AKSDJ is not a variable name.
+ 10 | DISPLAY AKSDJ.
+ | ^~~~~
])
AT_CHECK([cat pspp.csv], [0], [dnl
-error.sps:10: error: DISPLAY: AKSDJ is not a variable name.
+"error.sps:10.9-10.13: error: DISPLAY: AKSDJ is not a variable name.
+ 10 | DISPLAY AKSDJ.
+ | ^~~~~"
Table: Data List
x
AT_CHECK([pspp -O format=csv insert.sps], [1], [dnl
insert.sps:2: error: INSERT: Can't find `nonexistent' in include file search path.
-insert.sps:6: error: LIST: LIST is allowed only after the active dataset has been defined.
+"insert.sps:6.1-6.4: error: LIST: LIST is allowed only after the active dataset has been defined.
+ 6 | LIST.
+ | ^~~~"
])
AT_CLEANUP
]])
AT_CHECK([pspp -O format=csv pe.sps], [1], [dnl
-pe.sps:1.6: error: PERMISSIONS: Syntax error at `|': expecting STRING.
+"pe.sps:1.6: error: PERMISSIONS: Syntax error expecting STRING.
+ 1 | PERMI|SIONS /FILE='foobar' PERMISSIONS=WRITEABLE.
+ | ^"
])
AT_CLEANUP
REGRESSION
/VARIABLES= a
-ascii.sps:11: warning: REGRESSION: a is not a numeric variable. It will not be
-included in the variable list.
+ascii.sps:10.13: warning: REGRESSION: a is not a numeric variable. It will not
+be included in the variable list.
+ 10 | /VARIABLES= a
+ | ^
/DEPENDENT= x y
/STATISTICS=COEFF R ANOVA.
return;
}
- lex_error (lexer, "Expecting valid value option");
+ lex_error (lexer, "Syntax error expecting valid value option.");
exit (1);
}
if (lex_match_id (lexer, table_stroke_to_string (stroke)))
return stroke;
- lex_error (lexer, "expecting stroke");
+ lex_error (lexer, "Syntax error expecting stroke.");
exit (1);
}
bool ok = parse_variables (lexer, dict, vars, n_vars, 0);
if (ok && (lex_token (lexer) != T_STOP && lex_token (lexer) != T_ENDCMD))
{
- lex_error (lexer, _("expecting variable name"));
+ lex_error (lexer, _("Syntax error expecting variable name."));
ok = false;
}