From: Ben Pfaff Date: Sat, 10 Sep 2022 18:04:21 +0000 (-0700) Subject: Cite tokens when reporting invalid identifiers. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5d1ac814687386b4cd6af9fa9e6f2f98913aa7d;p=pspp Cite tokens when reporting invalid identifiers. These functions weren't able to cite a specific token in cases where that was appropriate. This fixes the problem. --- diff --git a/perl-module/PSPP.xs b/perl-module/PSPP.xs index 077bf581f0..1f05be2a65 100644 --- a/perl-module/PSPP.xs +++ b/perl-module/PSPP.xs @@ -368,7 +368,7 @@ pxs_dict_create_var (dict, name, ip_fmt) INIT: SV *errstr = get_sv("PSPP::errstr", TRUE); sv_setpv (errstr, ""); - if ( ! id_is_plausible (name, false)) + if ( ! id_is_plausible (name)) { sv_setpv (errstr, "The variable name is not valid."); XSRETURN_UNDEF; diff --git a/src/data/dictionary.c b/src/data/dictionary.c index a2e3fb8fc1..60349bce61 100644 --- a/src/data/dictionary.c +++ b/src/data/dictionary.c @@ -179,15 +179,35 @@ dict_get_encoding (const struct dictionary *d) return d->encoding ; } +/* Checks whether UTF-8 string ID is an acceptable identifier in DICT's + encoding. Returns true if it is, otherwise an error message that the caller + must free(). */ +char * WARN_UNUSED_RESULT +dict_id_is_valid__ (const struct dictionary *dict, const char *id) +{ + if (!dict->names_must_be_ids) + return NULL; + return id_is_valid__ (id, dict->encoding); +} + +static bool +error_to_bool (char *error) +{ + if (error) + { + free (error); + return false; + } + else + return true; +} + /* Returns true if UTF-8 string ID is an acceptable identifier in DICT's - encoding, false otherwise. If ISSUE_ERROR is true, issues an explanatory - error message on failure. */ + encoding, false otherwise. */ bool -dict_id_is_valid (const struct dictionary *dict, const char *id, - bool issue_error) +dict_id_is_valid (const struct dictionary *dict, const char *id) { - return (!dict->names_must_be_ids - || id_is_valid (id, dict->encoding, issue_error)); + return error_to_bool (dict_id_is_valid__ (dict, id)); } void diff --git a/src/data/dictionary.h b/src/data/dictionary.h index 3e874d8707..f709f11dd9 100644 --- a/src/data/dictionary.h +++ b/src/data/dictionary.h @@ -189,8 +189,9 @@ bool dict_has_attributes (const struct dictionary *); /* Data encoding. */ const char *dict_get_encoding (const struct dictionary *d); -bool dict_id_is_valid (const struct dictionary *, const char *id, - bool issue_error); +char *dict_id_is_valid__ (const struct dictionary *, const char *id) + WARN_UNUSED_RESULT; +bool dict_id_is_valid (const struct dictionary *, const char *id); /* Internal variables. */ struct variable *dict_create_internal_var (int case_idx, int width); diff --git a/src/data/identifier.h b/src/data/identifier.h index dcbce970cd..4a23dd7dd5 100644 --- a/src/data/identifier.h +++ b/src/data/identifier.h @@ -89,8 +89,11 @@ bool lex_is_keyword (enum token_type); /* Validating identifiers. */ #define ID_MAX_LEN 64 /* Maximum length of identifier, in bytes. */ -bool id_is_valid (const char *id, const char *dict_encoding, bool issue_error); -bool id_is_plausible (const char *id, bool issue_error); +bool id_is_valid (const char *id, const char *dict_encoding); +bool id_is_plausible (const char *id); +char *id_is_valid__ (const char *id, const char *dict_encoding) + WARN_UNUSED_RESULT; +char *id_is_plausible__ (const char *id) WARN_UNUSED_RESULT; /* Recognizing identifiers. */ bool lex_is_id1 (char); diff --git a/src/data/identifier2.c b/src/data/identifier2.c index 3b6458f02d..d21c6bba5b 100644 --- a/src/data/identifier2.c +++ b/src/data/identifier2.c @@ -34,17 +34,29 @@ #include "gettext.h" #define _(msgid) gettext (msgid) -/* Returns true if UTF-8 string ID is an acceptable identifier in encoding - DICT_ENCODING (UTF-8 if null), false otherwise. If ISSUE_ERROR is true, - issues an explanatory error message on failure. */ -bool -id_is_valid (const char *id, const char *dict_encoding, bool issue_error) +static bool +error_to_bool (char *error) { - size_t dict_len; + if (error) + { + free (error); + return false; + } + else + return true; +} - if (!id_is_plausible (id, issue_error)) - return false; +/* Checks whether if UTF-8 string ID is an acceptable identifier in encoding + DICT_ENCODING (UTF-8 if null). Returns NULL if it is acceptable, otherwise + an error message that the caller must free(). */ +char * WARN_UNUSED_RESULT +id_is_valid__ (const char *id, const char *dict_encoding) +{ + char *error = id_is_plausible__ (id); + if (error) + return error; + size_t dict_len; if (dict_encoding != NULL) { /* XXX need to reject recoded strings that contain the fallback @@ -55,79 +67,74 @@ id_is_valid (const char *id, const char *dict_encoding, bool issue_error) dict_len = strlen (id); if (dict_len > ID_MAX_LEN) - { - if (issue_error) - msg (SE, _("Identifier `%s' exceeds %d-byte limit."), - id, ID_MAX_LEN); - return false; - } + return xasprintf (_("Identifier `%s' exceeds %d-byte limit."), + id, ID_MAX_LEN); - return true; + return NULL; } -/* Returns true if UTF-8 string ID is an plausible identifier, false - otherwise. If ISSUE_ERROR is true, issues an explanatory error message on - failure. */ +/* Returns true if UTF-8 string ID is an acceptable identifier in encoding + DICT_ENCODING (UTF-8 if null), false otherwise. */ bool -id_is_plausible (const char *id, bool issue_error) +id_is_valid (const char *id, const char *dict_encoding) { - const uint8_t *bad_unit; - const uint8_t *s; - char ucname[16]; - int mblen; - ucs4_t uc; + return error_to_bool (id_is_valid__ (id, dict_encoding)); +} +/* Checks whether UTF-8 string ID is an plausible identifier. Returns NULL if + it is, otherwise an error message that the caller must free(). */ +char * WARN_UNUSED_RESULT +id_is_plausible__ (const char *id) +{ /* ID cannot be the empty string. */ if (id[0] == '\0') - { - if (issue_error) - msg (SE, _("Identifier cannot be empty string.")); - return false; - } + return xstrdup (_("Identifier cannot be empty string.")); /* ID cannot be a reserved word. */ if (lex_id_to_token (ss_cstr (id)) != T_ID) - { - if (issue_error) - msg (SE, _("`%s' may not be used as an identifier because it " - "is a reserved word."), id); - return false; - } + return xasprintf (_("`%s' may not be used as an identifier because it " + "is a reserved word."), id); - bad_unit = u8_check (CHAR_CAST (const uint8_t *, id), strlen (id)); + const uint8_t *bad_unit = u8_check (CHAR_CAST (const uint8_t *, id), + strlen (id)); if (bad_unit != NULL) { /* If this message ever appears, it probably indicates a PSPP bug since it shouldn't be possible to get invalid UTF-8 this far. */ - if (issue_error) - msg (SE, _("`%s' may not be used as an identifier because it " - "contains ill-formed UTF-8 at byte offset %tu."), - id, CHAR_CAST (const char *, bad_unit) - id); - return false; + return xasprintf (_("`%s' may not be used as an identifier because it " + "contains ill-formed UTF-8 at byte offset %tu."), + id, CHAR_CAST (const char *, bad_unit) - id); } /* Check that it is a valid identifier. */ - mblen = u8_strmbtouc (&uc, CHAR_CAST (uint8_t *, id)); + ucs4_t uc; + int mblen = u8_strmbtouc (&uc, CHAR_CAST (uint8_t *, id)); if (!lex_uc_is_id1 (uc)) { - if (issue_error) - msg (SE, _("Character %s (in `%s') may not appear " - "as the first character in a identifier."), - uc_name (uc, ucname), id); - return false; + char ucname[16]; + return xasprintf (_("Character %s (in `%s') may not appear " + "as the first character in a identifier."), + uc_name (uc, ucname), id); } - for (s = CHAR_CAST (uint8_t *, id + mblen); + for (const uint8_t *s = CHAR_CAST (uint8_t *, id + mblen); (mblen = u8_strmbtouc (&uc, s)) != 0; s += mblen) if (!lex_uc_is_idn (uc)) { - if (issue_error) - msg (SE, _("Character %s (in `%s') may not appear in an " - "identifier."), - uc_name (uc, ucname), id); - return false; + char ucname[16]; + return xasprintf (_("Character %s (in `%s') may not appear in an " + "identifier."), + uc_name (uc, ucname), id); } - return true; + return NULL; +} + +/* Returns true if UTF-8 string ID is an plausible identifier, false + otherwise. */ +bool +id_is_plausible (const char *id) +{ + return error_to_bool (id_is_plausible__ (id)); } diff --git a/src/data/mrset.c b/src/data/mrset.c index 63f4b3fe33..c5e6cd2ec2 100644 --- a/src/data/mrset.c +++ b/src/data/mrset.c @@ -67,26 +67,42 @@ mrset_destroy (struct mrset *mrset) } } -/* Returns true if the UTF-8 encoded NAME is a valid name for a multiple - response set in a dictionary encoded in DICT_ENCODING, false otherwise. If - ISSUE_ERROR is true, issues an explanatory error message on failure. */ -bool -mrset_is_valid_name (const char *name, const char *dict_encoding, - bool issue_error) +/* Checks whether the UTF-8 encoded NAME is a valid name for a multiple + response set in a dictionary encoded in DICT_ENCODING. Return NULL if it + is, otherwise an error message that the caller must free(). */ +char * WARN_UNUSED_RESULT +mrset_is_valid_name__ (const char *name, const char *dict_encoding) { - if (!id_is_valid (name, dict_encoding, issue_error)) - return false; + char *error = id_is_valid__ (name, dict_encoding); + if (error) + return error; if (name[0] != '$') + return xasprintf (_("%s is not a valid name for a multiple response " + "set. Multiple response set names must begin with " + "`$'."), name); + + return NULL; +} + +static bool +error_to_bool (char *error) +{ + if (error) { - if (issue_error) - msg (SE, _("%s is not a valid name for a multiple response " - "set. Multiple response set names must begin with " - "`$'."), name); + free (error); return false; } + else + return true; +} - return true; +/* Returns true if the UTF-8 encoded NAME is a valid name for a multiple + response set in a dictionary encoded in DICT_ENCODING, false otherwise. */ +bool +mrset_is_valid_name (const char *name, const char *dict_encoding) +{ + return error_to_bool (mrset_is_valid_name__ (name, dict_encoding)); } /* Checks various constraints on MRSET: @@ -112,7 +128,7 @@ mrset_ok (const struct mrset *mrset, const struct dictionary *dict) size_t i; if (mrset->name == NULL - || !mrset_is_valid_name (mrset->name, dict_get_encoding (dict), false) + || !mrset_is_valid_name (mrset->name, dict_get_encoding (dict)) || (mrset->type != MRSET_MD && mrset->type != MRSET_MC) || mrset->vars == NULL || mrset->n_vars < 2) diff --git a/src/data/mrset.h b/src/data/mrset.h index 9971924e0d..30d855ec3d 100644 --- a/src/data/mrset.h +++ b/src/data/mrset.h @@ -77,8 +77,9 @@ struct mrset struct mrset *mrset_clone (const struct mrset *); void mrset_destroy (struct mrset *); -bool mrset_is_valid_name (const char *name, const char *dict_encoding, - bool issue_error); +char *mrset_is_valid_name__ (const char *name, const char *dict_encoding) + WARN_UNUSED_RESULT; +bool mrset_is_valid_name (const char *name, const char *dict_encoding); bool mrset_ok (const struct mrset *, const struct dictionary *); diff --git a/src/data/pc+-file-reader.c b/src/data/pc+-file-reader.c index 8e9cb94df7..5832df8d7f 100644 --- a/src/data/pc+-file-reader.c +++ b/src/data/pc+-file-reader.c @@ -851,7 +851,7 @@ parse_variable_records (struct pcp_reader *r, struct dictionary *dict, if (name[0] == '$') name = pool_asprintf (r->pool, "%s_", name + 1); - if (!dict_id_is_valid (dict, name, false) || name[0] == '#') + if (!dict_id_is_valid (dict, name) || name[0] == '#') { pcp_error (r, rec->pos, _("Invalid variable name `%s'."), name); return false; diff --git a/src/data/por-file-reader.c b/src/data/por-file-reader.c index 8cea15e749..7f32d2cf8f 100644 --- a/src/data/por-file-reader.c +++ b/src/data/por-file-reader.c @@ -716,8 +716,7 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) for (j = 0; j < 6; j++) fmt[j] = read_int (r); - if (!dict_id_is_valid (dict, name, false) - || *name == '#' || *name == '$') + if (!dict_id_is_valid (dict, name) || *name == '#' || *name == '$') error (r, _("Invalid variable name `%s' in position %d."), name, i); str_uppercase (name); diff --git a/src/data/sys-file-reader.c b/src/data/sys-file-reader.c index fb4fa53acf..88c0994dc3 100644 --- a/src/data/sys-file-reader.c +++ b/src/data/sys-file-reader.c @@ -1433,8 +1433,7 @@ parse_variable_records (struct sfm_reader *r, struct dictionary *dict, } struct variable *var; - if (!dict_id_is_valid (dict, name, false) - || name[0] == '$' || name[0] == '#') + if (!dict_id_is_valid (dict, name) || name[0] == '$' || name[0] == '#') { var = add_var_with_generated_name (dict, rec->width); sys_warn (r, rec->pos, _("Renaming variable with invalid name " @@ -1817,7 +1816,7 @@ decode_mrsets (struct sfm_reader *r, struct dictionary *dict) size_t i; name = recode_string ("UTF-8", r->encoding, s->name, -1); - if (!mrset_is_valid_name (name, dict_get_encoding (dict), false)) + if (!mrset_is_valid_name (name, dict_get_encoding (dict))) { sys_warn (r, -1, _("Invalid multiple response set name `%s'."), name); @@ -2051,7 +2050,7 @@ parse_long_var_name_map (struct sfm_reader *r, while (read_variable_to_value_pair (r, dict, text, &var, &long_name)) { /* Validate long name. */ - if (!dict_id_is_valid (dict, long_name, false) + if (!dict_id_is_valid (dict, long_name) || long_name[0] == '$' || long_name[0] == '#') { sys_warn (r, record->pos, diff --git a/src/data/vector.c b/src/data/vector.c index c88d236df6..53378b4b04 100644 --- a/src/data/vector.c +++ b/src/data/vector.c @@ -57,7 +57,7 @@ vector_create (const char *name, struct variable **vars, size_t n_vars) struct vector *vector = xmalloc (sizeof *vector); assert (n_vars > 0); - assert (id_is_plausible (name, false)); + assert (id_is_plausible (name)); vector->name = xstrdup (name); vector->vars = xmemdup (vars, n_vars * sizeof *vector->vars); diff --git a/src/language/control/define.c b/src/language/control/define.c index 27f5093504..14eafacb42 100644 --- a/src/language/control/define.c +++ b/src/language/control/define.c @@ -103,7 +103,7 @@ cmd_define (struct lexer *lexer, struct dataset *ds UNUSED) return CMD_FAILURE; } const char *name = lex_tokcstr (lexer); - if (!id_is_plausible (name + (name[0] == '!'), false)) + if (!id_is_plausible (name + (name[0] == '!'))) { lex_error (lexer, _("Syntax error expecting identifier.")); return CMD_FAILURE; diff --git a/src/language/data-io/get-data.c b/src/language/data-io/get-data.c index e746e9a05c..cf96e415ad 100644 --- a/src/language/data-io/get-data.c +++ b/src/language/data-io/get-data.c @@ -566,16 +566,14 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds) } int name_ofs = lex_ofs (lexer); - const char * tstr = lex_tokcstr (lexer); - if (tstr == NULL) - { - lex_error (lexer, NULL); - goto error; - } - name = xstrdup (tstr); - if (!lex_force_id (lexer) - || !dict_id_is_valid (dict, name, true)) - { + if (!lex_force_id (lexer)) + goto error; + name = xstrdup (lex_tokcstr (lexer)); + char *error = dict_id_is_valid__ (dict, name); + if (error) + { + lex_error (lexer, "%s", error); + free (error); goto error; } lex_get (lexer); diff --git a/src/language/data-io/trim.c b/src/language/data-io/trim.c index ad25f400aa..cf493391e4 100644 --- a/src/language/data-io/trim.c +++ b/src/language/data-io/trim.c @@ -95,12 +95,22 @@ try_to_sequence (struct lexer *lexer, const struct dictionary *dict, /* Check that the first and last tokens are suitable as variable names. */ const char *s0 = lex_tokcstr (lexer); - if (!id_is_valid (s0, dict_get_encoding (dict), true)) - return NULL; + char *error = id_is_valid__ (s0, dict_get_encoding (dict)); + if (error) + { + lex_error (lexer, "%s", error); + free (error); + return NULL; + } const char *s1 = lex_next_tokcstr (lexer, 2); - if (!id_is_valid (s1, dict_get_encoding (dict), true)) - return NULL; + error = id_is_valid__ (s1, dict_get_encoding (dict)); + if (error) + { + lex_next_error (lexer, 2, 2, "%s", error); + free (error); + return NULL; + } int x0 = strcspn (s0, "0123456789"); int x1 = strcspn (s1, "0123456789"); @@ -211,8 +221,16 @@ parse_dict_rename (struct lexer *lexer, struct dictionary *dict, if (n_newvars >= n_oldvars) break; const char *new_name = lex_tokcstr (lexer); - if (!relax && ! id_is_plausible (new_name, true)) - goto fail; + if (!relax) + { + char *error = id_is_plausible__ (new_name); + if (error) + { + lex_error (lexer, "%s", error); + free (error); + goto fail; + } + } if (!check_rename (dict, var_get_name (oldvars[n_newvars]), new_name)) goto fail; diff --git a/src/language/dictionary/attributes.c b/src/language/dictionary/attributes.c index 88832fd501..954314ef4f 100644 --- a/src/language/dictionary/attributes.c +++ b/src/language/dictionary/attributes.c @@ -87,12 +87,16 @@ static char * parse_attribute_name (struct lexer *lexer, const char *dict_encoding, size_t *index) { - char *name; - - if (!lex_force_id (lexer) - || !id_is_valid (lex_tokcstr (lexer), dict_encoding, true)) + if (!lex_force_id (lexer)) return NULL; - name = xstrdup (lex_tokcstr (lexer)); + char *error = id_is_valid__ (lex_tokcstr (lexer), dict_encoding); + if (error) + { + lex_error (lexer, "%s", error); + free (error); + return NULL; + } + char *name = xstrdup (lex_tokcstr (lexer)); lex_get (lexer); if (lex_match (lexer, T_LBRACK)) diff --git a/src/language/dictionary/mrsets.c b/src/language/dictionary/mrsets.c index 0ea5cb8c82..1f281221a2 100644 --- a/src/language/dictionary/mrsets.c +++ b/src/language/dictionary/mrsets.c @@ -92,10 +92,16 @@ parse_group (struct lexer *lexer, struct dictionary *dict, { if (lex_match_id (lexer, "NAME")) { - if (!lex_force_match (lexer, T_EQUALS) || !lex_force_id (lexer) - || !mrset_is_valid_name (lex_tokcstr (lexer), - dict_get_encoding (dict), true)) + if (!lex_force_match (lexer, T_EQUALS) || !lex_force_id (lexer)) goto error; + char *error = mrset_is_valid_name__ (lex_tokcstr (lexer), + dict_get_encoding (dict)); + if (error) + { + lex_error (lexer, "%s", error); + free (error); + goto error; + } free (mrset->name); mrset->name = xstrdup (lex_tokcstr (lexer)); diff --git a/src/language/dictionary/sys-file-info.c b/src/language/dictionary/sys-file-info.c index 45c352579c..4ba4ddd4e0 100644 --- a/src/language/dictionary/sys-file-info.c +++ b/src/language/dictionary/sys-file-info.c @@ -836,7 +836,7 @@ recode_strings (struct pool *pool, ss_rtrim (&utf8, ss_cstr (" ")); utf8.string[utf8.length] = '\0'; - if (ids[i] && !id_is_plausible (utf8.string, false)) + if (ids[i] && !id_is_plausible (utf8.string)) error = EINVAL; } diff --git a/src/language/dictionary/vector.c b/src/language/dictionary/vector.c index 02687e51a9..fe1ab99e14 100644 --- a/src/language/dictionary/vector.c +++ b/src/language/dictionary/vector.c @@ -51,9 +51,15 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) size_t n_vectors, allocated_vectors; /* Get the name(s) of the new vector(s). */ - if (!lex_force_id (lexer) - || !dict_id_is_valid (dict, lex_tokcstr (lexer), true)) + if (!lex_force_id (lexer)) return CMD_CASCADING_FAILURE; + char *error = dict_id_is_valid__ (dict, lex_tokcstr (lexer)); + if (error) + { + lex_error (lexer, "%s", error); + free (error); + return CMD_CASCADING_FAILURE; + } vectors = NULL; n_vectors = allocated_vectors = 0; @@ -111,17 +117,10 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) else if (lex_match (lexer, T_LPAREN)) { /* Short form. */ - struct fmt_spec format; + struct fmt_spec format = fmt_for_output (FMT_F, 8, 2); bool seen_format = false; - - struct variable **vars; - int n_vars; - - size_t i; - - n_vars = 0; - format = fmt_for_output (FMT_F, 8, 2); - seen_format = false; + size_t n_vars = 0; + int start_ofs = lex_ofs (lexer) - 2; while (!lex_match (lexer, T_RPAREN)) { if (lex_is_integer (lexer) && n_vars == 0) @@ -145,6 +144,7 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) } lex_match (lexer, T_COMMA); } + int end_ofs = lex_ofs (lexer) - 1; if (n_vars == 0) { lex_error (lexer, _("Syntax error expecting vector length.")); @@ -153,20 +153,25 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) /* Check that none of the variables exist and that their names are not excessively long. */ - for (i = 0; i < n_vectors; i++) + for (size_t i = 0; i < n_vectors; i++) { int j; for (j = 0; j < n_vars; j++) { char *name = xasprintf ("%s%d", vectors[i], j + 1); - if (!dict_id_is_valid (dict, name, true)) + char *error = dict_id_is_valid__ (dict, name); + if (error) { + lex_ofs_error (lexer, start_ofs, end_ofs, "%s", error); + free (error); free (name); goto fail; } if (dict_lookup_var (dict, name)) { - msg (SE, _("%s is an existing variable name."), name); + lex_ofs_error (lexer, start_ofs, end_ofs, + _("%s is an existing variable name."), + name); free (name); goto fail; } @@ -175,13 +180,12 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) } /* Finally create the variables and vectors. */ - vars = pool_nmalloc (pool, n_vars, sizeof *vars); - for (i = 0; i < n_vectors; i++) + struct variable **vars = pool_nmalloc (pool, n_vars, sizeof *vars); + for (size_t i = 0; i < n_vectors; i++) { - int j; - for (j = 0; j < n_vars; j++) + for (size_t j = 0; j < n_vars; j++) { - char *name = xasprintf ("%s%d", vectors[i], j + 1); + char *name = xasprintf ("%s%zu", vectors[i], j + 1); vars[j] = dict_create_var_assert (dict, name, fmt_var_width (&format)); var_set_both_formats (vars[j], &format); diff --git a/src/language/lexer/variable-parser.c b/src/language/lexer/variable-parser.c index 7d30a2ad92..f444f15e2b 100644 --- a/src/language/lexer/variable-parser.c +++ b/src/language/lexer/variable-parser.c @@ -437,8 +437,13 @@ parse_DATA_LIST_var (struct lexer *lexer, const struct dictionary *d) lex_error (lexer, ("Syntax error expecting variable name.")); return NULL; } - if (!dict_id_is_valid (d, lex_tokcstr (lexer), true)) - return NULL; + char *error = dict_id_is_valid__ (d, lex_tokcstr (lexer)); + if (error) + { + lex_error (lexer, "%s", error); + free (error); + return NULL; + } char *name = xstrdup (lex_tokcstr (lexer)); lex_get (lexer); diff --git a/src/language/stats/flip.c b/src/language/stats/flip.c index 113d565367..cf11e2312c 100644 --- a/src/language/stats/flip.c +++ b/src/language/stats/flip.c @@ -281,7 +281,7 @@ make_new_var (struct dictionary *dict, const char *name_) /* Use the mangled name, if it is available, or add numeric extensions until we find one that is. */ - if (!id_is_plausible (name, false) || !dict_create_var (dict, name, 0)) + if (!id_is_plausible (name) || !dict_create_var (dict, name, 0)) { int len = strlen (name); int i; @@ -292,7 +292,7 @@ make_new_var (struct dictionary *dict, const char *name_) strncpy (n, name, ofs); sprintf (&n[ofs], "%d", i); - if (id_is_plausible (n, false) && dict_create_var (dict, n, 0)) + if (id_is_plausible (n) && dict_create_var (dict, n, 0)) break; } } diff --git a/src/language/stats/matrix.c b/src/language/stats/matrix.c index ba6a140207..7c8d6519d1 100644 --- a/src/language/stats/matrix.c +++ b/src/language/stats/matrix.c @@ -6135,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); diff --git a/src/ui/gui/psppire-dict.c b/src/ui/gui/psppire-dict.c index 215a1d3e58..70d3b49345 100644 --- a/src/ui/gui/psppire-dict.c +++ b/src/ui/gui/psppire-dict.c @@ -454,7 +454,7 @@ psppire_dict_set_name (PsppireDict* d, gint idx, const gchar *name) g_assert (d); g_assert (PSPPIRE_IS_DICT (d)); - if (! dict_id_is_valid (d->dict, name, false)) + if (! dict_id_is_valid (d->dict, name)) return FALSE; if (idx < dict_get_n_vars (d->dict)) @@ -550,26 +550,15 @@ psppire_dict_clear (PsppireDict *d) /* Return true if NAME would be a valid name of a variable to add to the dictionary. False otherwise. - If REPORT is true, then invalid names will be reported as such as errors */ gboolean psppire_dict_check_name (const PsppireDict *dict, - const gchar *name, gboolean report) + const gchar *name) { - if (! dict_id_is_valid (dict->dict, name, report)) - return FALSE; - - if (psppire_dict_lookup_var (dict, name)) - { - if (report) - msg (ME, _("Duplicate variable name.")); - return FALSE; - } - - return TRUE; + return (dict_id_is_valid (dict->dict, name) + && !psppire_dict_lookup_var (dict, name)); } - gint psppire_dict_get_next_value_idx (const PsppireDict *dict) { @@ -891,7 +880,7 @@ gboolean psppire_dict_rename_var (PsppireDict *dict, struct variable *v, const gchar *name) { - if (! dict_id_is_valid (dict->dict, name, false)) + if (! dict_id_is_valid (dict->dict, name)) return FALSE; /* Make sure no other variable has this name */ diff --git a/src/ui/gui/psppire-dict.h b/src/ui/gui/psppire-dict.h index 76c3aa42e8..e5f8032965 100644 --- a/src/ui/gui/psppire-dict.h +++ b/src/ui/gui/psppire-dict.h @@ -107,8 +107,7 @@ void psppire_dict_delete_variables (PsppireDict *d, gint first, gint n); struct variable *psppire_dict_insert_variable (PsppireDict *d, gint idx, const gchar *name); -gboolean psppire_dict_check_name (const PsppireDict *dict, - const gchar *name, gboolean report); +gboolean psppire_dict_check_name (const PsppireDict *, const gchar *name); bool psppire_dict_generate_name (const PsppireDict *, char *name, size_t size); diff --git a/src/ui/gui/psppire-variable-sheet.c b/src/ui/gui/psppire-variable-sheet.c index 486d85c4ca..573e66e4cc 100644 --- a/src/ui/gui/psppire-variable-sheet.c +++ b/src/ui/gui/psppire-variable-sheet.c @@ -342,7 +342,7 @@ change_var_property (PsppireVariableSheet *var_sheet, gint col, gint row, const case DICT_TVM_COL_NAME: { const char *name = g_value_get_string (value); - if (psppire_dict_check_name (dict, name, FALSE)) + if (psppire_dict_check_name (dict, name)) dict_rename_var (dict->dict, var, g_value_get_string (value)); } break; diff --git a/tests/language/dictionary/mrsets.at b/tests/language/dictionary/mrsets.at index bddbbd1919..b72803c19e 100644 --- a/tests/language/dictionary/mrsets.at +++ b/tests/language/dictionary/mrsets.at @@ -198,8 +198,10 @@ AT_DATA([mrsets.sps], [DEFINE_MRSETS_DATA MRSETS /MCGROUP NAME=x. ]) -AT_CHECK([pspp -O format=csv mrsets.sps], [1], - [mrsets.sps:6: error: MRSETS: x is not a valid name for a multiple response set. Multiple response set names must begin with `$'. +AT_CHECK([pspp -O format=csv mrsets.sps], [1], [dnl +"mrsets.sps:6.22: error: MRSETS: x is not a valid name for a multiple response set. Multiple response set names must begin with `$'. + 6 | MRSETS /MCGROUP NAME=x. + | ^" ]) AT_CLEANUP