1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include <data/format.h>
22 #include <data/procedure.h>
23 #include <data/dictionary.h>
24 #include <data/variable.h>
25 #include <language/command.h>
26 #include <language/lexer/format-parser.h>
27 #include <language/lexer/lexer.h>
28 #include <language/lexer/variable-parser.h>
29 #include <libpspp/assertion.h>
30 #include <libpspp/message.h>
31 #include <libpspp/misc.h>
32 #include <libpspp/pool.h>
33 #include <libpspp/str.h>
39 #define _(msgid) gettext (msgid)
42 cmd_vector (struct lexer *lexer, struct dataset *ds)
44 struct dictionary *dict = dataset_dict (ds);
45 struct pool *pool = pool_create ();
50 size_t vector_cnt, vector_cap;
52 /* Get the name(s) of the new vector(s). */
53 if (!lex_force_id (lexer))
54 return CMD_CASCADING_FAILURE;
57 vector_cnt = vector_cap = 0;
58 while (lex_token (lexer) == T_ID)
62 if (dict_lookup_vector (dict, lex_tokid (lexer)))
64 msg (SE, _("A vector named %s already exists."),
69 for (i = 0; i < vector_cnt; i++)
70 if (!strcasecmp (vectors[i], lex_tokid (lexer)))
72 msg (SE, _("Vector name %s is given twice."),
77 if (vector_cnt == vector_cap)
78 vectors = pool_2nrealloc (pool,
79 vectors, &vector_cap, sizeof *vectors);
80 vectors[vector_cnt++] = pool_strdup (pool, lex_tokid (lexer));
83 lex_match (lexer, ',');
86 /* Now that we have the names it's time to check for the short
88 if (lex_match (lexer, '='))
96 msg (SE, _("A slash must separate each vector "
97 "specification in VECTOR's long form."));
101 if (!parse_variables_pool (lexer, pool, dict, &v, &nv,
102 PV_SAME_WIDTH | PV_DUPLICATE))
105 dict_create_vector (dict, vectors[0], v, nv);
107 else if (lex_match (lexer, '('))
110 struct fmt_spec format;
111 bool seen_format = false;
113 struct variable **vars;
119 format = fmt_for_output (FMT_F, 8, 2);
121 while (!lex_match (lexer, ')'))
123 if (lex_is_integer (lexer) && var_cnt == 0)
125 var_cnt = lex_integer (lexer);
129 msg (SE, _("Vectors must have at least one element."));
133 else if (lex_token (lexer) == T_ID && !seen_format)
136 if (!parse_format_specifier (lexer, &format)
137 || !fmt_check_output (&format)
138 || !fmt_check_type_compat (&format, VAL_NUMERIC))
143 lex_error (lexer, NULL);
146 lex_match (lexer, ',');
150 lex_error (lexer, _("expecting vector length"));
154 /* Check that none of the variables exist and that
155 their names are no more than VAR_NAME_LEN bytes
157 for (i = 0; i < vector_cnt; i++)
160 for (j = 0; j < var_cnt; j++)
162 char name[VAR_NAME_LEN + INT_STRLEN_BOUND (int) + 1];
163 sprintf (name, "%s%d", vectors[i], j + 1);
164 if (strlen (name) > VAR_NAME_LEN)
166 msg (SE, _("%s is too long for a variable name."), name);
169 if (dict_lookup_var (dict, name))
171 msg (SE, _("%s is an existing variable name."), name);
177 /* Finally create the variables and vectors. */
178 vars = pool_nmalloc (pool, var_cnt, sizeof *vars);
179 for (i = 0; i < vector_cnt; i++)
182 for (j = 0; j < var_cnt; j++)
184 char name[VAR_NAME_LEN + 1];
185 sprintf (name, "%s%d", vectors[i], j + 1);
186 vars[j] = dict_create_var_assert (dict, name, 0);
187 var_set_both_formats (vars[j], &format);
189 dict_create_vector_assert (dict, vectors[i], vars, var_cnt);
194 lex_error (lexer, NULL);
198 while (lex_match (lexer, '/'));
201 return lex_end_of_command (lexer);