X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Fmatrix.c;h=69c6323ef48152076b9c953bf2b4aaea13f2dc27;hb=d84c9fab98875caf8fea1d870bf2a6bceeb36bdc;hp=c1e4adff8e793a05664add867495b80574ec9184;hpb=15d30a4c251fe810f3697bd287afdc8b1699487d;p=pspp diff --git a/src/language/stats/matrix.c b/src/language/stats/matrix.c index c1e4adff8e..69c6323ef4 100644 --- a/src/language/stats/matrix.c +++ b/src/language/stats/matrix.c @@ -89,9 +89,13 @@ struct msave_common /* 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 @@ -3383,7 +3387,7 @@ matrix_expr_evaluate_exp_mat (const struct matrix_expr *e, if (bf != floor (bf) || bf <= LONG_MIN || bf > LONG_MAX) { msg_at (SE, matrix_expr_location (e->subs[1]), - _("Exponent %.1f in matrix multiplication is non-integer " + _("Exponent %.1f in matrix exponentiation is non-integer " "or outside the valid range."), bf); return NULL; } @@ -4742,7 +4746,8 @@ matrix_lvalue_parse (struct matrix_state *s) { 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; } @@ -5173,6 +5178,7 @@ struct matrix_command struct matrix_get { + struct lexer *lexer; struct matrix_lvalue *dst; struct dataset *dataset; struct file_handle *file; @@ -5367,25 +5373,12 @@ matrix_print_parse (struct matrix_state *s) if (lex_token (s->lexer) != T_SLASH && lex_token (s->lexer) != T_ENDCMD) { - size_t depth = 0; - for (size_t i = 0; ; i++) - { - enum token_type t = lex_next_token (s->lexer, i); - if (t == T_LPAREN || t == T_LBRACK || t == T_LCURLY) - depth++; - else if ((t == T_RPAREN || t == T_RBRACK || t == T_RCURLY) && depth) - depth--; - else if ((t == T_SLASH && !depth) || t == T_ENDCMD || t == T_STOP) - { - if (i > 0) - cmd->print.title = lex_next_representation (s->lexer, 0, i - 1); - break; - } - } - + int start_ofs = lex_ofs (s->lexer); cmd->print.expression = matrix_parse_exp (s); if (!cmd->print.expression) goto error; + cmd->print.title = lex_ofs_representation (s->lexer, start_ofs, + lex_ofs (s->lexer) - 1); } while (lex_match (s->lexer, T_SLASH)) @@ -5937,7 +5930,7 @@ matrix_break_parse (struct matrix_state *s) { if (!s->in_loop) { - msg (SE, _("BREAK not inside LOOP.")); + lex_next_error (s->lexer, -1, -1, _("BREAK not inside LOOP.")); return NULL; } @@ -6035,7 +6028,7 @@ matrix_release_parse (struct matrix_state *s) 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)) @@ -6142,10 +6135,15 @@ save_file_open (struct save_file *sf, gsl_matrix *m, for (size_t i = 0; i < nv.size; i++) { char *name = trimmed_string (gsl_vector_get (&nv, i)); - if (dict_id_is_valid (dict, name, true)) + char *error = dict_id_is_valid__ (dict, name); + if (!error) string_array_append_nocopy (&names, name); else - ok = false; + { + msg_at (SE, save_location, "%s", error); + free (error); + ok = false; + } } } gsl_matrix_free (nm); @@ -6267,6 +6265,8 @@ matrix_save_parse (struct matrix_state *s) if (!save->expression) goto error; + int names_start = 0; + int names_end = 0; while (lex_match (s->lexer, T_SLASH)) { if (lex_match_id (s->lexer, "OUTFILE")) @@ -6304,7 +6304,9 @@ matrix_save_parse (struct matrix_state *s) { lex_match (s->lexer, T_EQUALS); matrix_expr_destroy (names); + names_start = lex_ofs (s->lexer); names = matrix_parse_exp (s); + names_end = lex_ofs (s->lexer) - 1; if (!names) goto error; } @@ -6333,7 +6335,7 @@ matrix_save_parse (struct matrix_state *s) fh = fh_ref (s->prev_save_file); else { - lex_sbc_missing ("OUTFILE"); + lex_sbc_missing (s->lexer, "OUTFILE"); goto error; } } @@ -6342,7 +6344,8 @@ matrix_save_parse (struct matrix_state *s) if (variables.n && names) { - msg (SW, _("VARIABLES and NAMES both specified; ignoring NAMES.")); + lex_ofs_msg (s->lexer, SW, names_start, names_end, + _("Ignoring NAMES because VARIABLES was also specified.")); matrix_expr_destroy (names); names = NULL; } @@ -6454,6 +6457,10 @@ matrix_read_parse (struct matrix_state *s) 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; @@ -6484,6 +6491,7 @@ matrix_read_parse (struct matrix_state *s) { 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); @@ -6492,6 +6500,7 @@ matrix_read_parse (struct matrix_state *s) || !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; @@ -6501,12 +6510,20 @@ matrix_read_parse (struct matrix_state *s) 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; } } @@ -6540,7 +6557,7 @@ matrix_read_parse (struct matrix_state *s) { if (seen_format) { - lex_sbc_only_once ("FORMAT"); + lex_sbc_only_once (s->lexer, "FORMAT"); goto error; } seen_format = true; @@ -6550,6 +6567,7 @@ matrix_read_parse (struct matrix_state *s) 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])) { @@ -6583,7 +6601,7 @@ matrix_read_parse (struct matrix_state *s) if (!read->c1) { - lex_sbc_missing ("FIELD"); + lex_sbc_missing (s->lexer, "FIELD"); goto error; } @@ -6591,6 +6609,8 @@ matrix_read_parse (struct matrix_state *s) { 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; } @@ -6600,7 +6620,7 @@ matrix_read_parse (struct matrix_state *s) fh = fh_ref (s->prev_read_file); else { - lex_sbc_missing ("FILE"); + lex_sbc_missing (s->lexer, "FILE"); goto error; } } @@ -6631,6 +6651,10 @@ matrix_read_parse (struct matrix_state *s) { 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 @@ -6638,14 +6662,26 @@ matrix_read_parse (struct matrix_state *s) : 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; @@ -7001,6 +7037,10 @@ matrix_write_parse (struct matrix_state *s) 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; @@ -7032,6 +7072,8 @@ matrix_write_parse (struct matrix_state *s) { 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); @@ -7040,6 +7082,7 @@ matrix_write_parse (struct matrix_state *s) || !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; @@ -7048,13 +7091,21 @@ matrix_write_parse (struct matrix_state *s) 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; } } @@ -7080,7 +7131,7 @@ matrix_write_parse (struct matrix_state *s) { if (has_format || write->format) { - lex_sbc_only_once ("FORMAT"); + lex_sbc_only_once (s->lexer, "FORMAT"); goto error; } @@ -7089,6 +7140,7 @@ matrix_write_parse (struct matrix_state *s) 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])) { @@ -7125,7 +7177,7 @@ matrix_write_parse (struct matrix_state *s) if (!write->c1) { - lex_sbc_missing ("FIELD"); + lex_sbc_missing (s->lexer, "FIELD"); goto error; } @@ -7135,7 +7187,7 @@ matrix_write_parse (struct matrix_state *s) fh = fh_ref (s->prev_write_file); else { - lex_sbc_missing ("OUTFILE"); + lex_sbc_missing (s->lexer, "OUTFILE"); goto error; } } @@ -7164,8 +7216,10 @@ matrix_write_parse (struct matrix_state *s) */ 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 @@ -7173,14 +7227,26 @@ matrix_write_parse (struct matrix_state *s) : 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) @@ -7188,16 +7254,46 @@ matrix_write_parse (struct matrix_state *s) write->format = xmalloc (sizeof *write->format); *write->format = (struct fmt_spec) { .type = format, .w = w }; - if (!fmt_check_output (write->format)) - goto error; - }; + char *error = fmt_check_output__ (write->format); + if (error) + { + msg (SE, "%s", error); + free (error); + + if (has_format) + lex_ofs_msg (s->lexer, SN, format_ofs, format_ofs, + _("This syntax specifies format %s."), + fmt_name (format)); + + if (repetitions) + { + 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); + } + + if (by) + lex_ofs_msg (s->lexer, SN, by_ofs, by_ofs, + _("This syntax specifies field width %d."), by); + + goto error; + } + } 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; } @@ -7304,6 +7400,7 @@ matrix_get_parse (struct matrix_state *s) *cmd = (struct matrix_command) { .type = MCMD_GET, .get = { + .lexer = s->lexer, .dataset = s->dataset, .user = { .treatment = MGET_ERROR }, .system = { .treatment = MGET_ERROR }, @@ -7348,7 +7445,7 @@ matrix_get_parse (struct matrix_state *s) if (get->n_vars) { - lex_sbc_only_once ("VARIABLES"); + lex_sbc_only_once (s->lexer, "VARIABLES"); goto error; } @@ -7431,7 +7528,7 @@ matrix_get_execute__ (struct matrix_command *cmd, struct casereader *reader, 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; } @@ -7553,7 +7650,7 @@ matrix_open_casereader (const struct matrix_command *cmd, { 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; @@ -7592,21 +7689,39 @@ matrix_get_execute (struct matrix_command *cmd) 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; } } @@ -7618,14 +7733,25 @@ msave_common_changed (const struct msave_common *old, 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; @@ -7638,9 +7764,13 @@ msave_common_destroy (struct msave_common *common) { 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]); @@ -7674,17 +7804,22 @@ match_rowtype (struct lexer *lexer) } 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) @@ -7693,16 +7828,17 @@ parse_var_names (struct lexer *lexer, struct string_array *sa) 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; } @@ -7741,23 +7877,30 @@ matrix_msave_parse (struct matrix_state *s) 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")) @@ -7787,7 +7930,7 @@ matrix_msave_parse (struct matrix_state *s) } if (!msave->rowtype) { - lex_sbc_missing ("TYPE"); + lex_sbc_missing (s->lexer, "TYPE"); goto error; } @@ -7795,17 +7938,17 @@ matrix_msave_parse (struct matrix_state *s) { 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) { - lex_sbc_missing ("OUTFILE"); + lex_sbc_missing (s->lexer, "OUTFILE"); goto error; } common->location = lex_ofs_location (s->lexer, start_ofs, @@ -7882,8 +8025,7 @@ msave_add_vars (struct dictionary *d, const struct string_array *vars) } 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 ()); @@ -7900,7 +8042,8 @@ msave_create_dict (const struct msave_common *common, 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; } @@ -7910,7 +8053,8 @@ msave_create_dict (const struct msave_common *common, 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; } @@ -7989,7 +8133,7 @@ matrix_msave_execute (struct matrix_command *cmd) if (!common->writer) { - struct dictionary *dict = msave_create_dict (common, cmd->location); + struct dictionary *dict = msave_create_dict (common); if (!dict) goto error; @@ -8864,7 +9008,8 @@ matrix_commands_parse (struct matrix_state *s, struct matrix_commands *c, 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; }