1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 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, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include <data/format.h>
24 #include <data/procedure.h>
25 #include <data/dictionary.h>
26 #include <data/variable.h>
27 #include <language/command.h>
28 #include <language/lexer/format-parser.h>
29 #include <language/lexer/lexer.h>
30 #include <language/lexer/variable-parser.h>
31 #include <libpspp/alloc.h>
32 #include <libpspp/assertion.h>
33 #include <libpspp/message.h>
34 #include <libpspp/misc.h>
35 #include <libpspp/pool.h>
36 #include <libpspp/str.h>
41 #define _(msgid) gettext (msgid)
44 cmd_vector (struct lexer *lexer, struct dataset *ds)
46 struct dictionary *dict = dataset_dict (ds);
47 struct pool *pool = pool_create ();
52 size_t vector_cnt, vector_cap;
54 /* Get the name(s) of the new vector(s). */
55 if (!lex_force_id (lexer))
56 return CMD_CASCADING_FAILURE;
59 vector_cnt = vector_cap = 0;
60 while (lex_token (lexer) == T_ID)
64 if (dict_lookup_vector (dict, lex_tokid (lexer)))
66 msg (SE, _("A vector named %s already exists."),
71 for (i = 0; i < vector_cnt; i++)
72 if (!strcasecmp (vectors[i], lex_tokid (lexer)))
74 msg (SE, _("Vector name %s is given twice."),
79 if (vector_cnt == vector_cap)
80 vectors = pool_2nrealloc (pool,
81 vectors, &vector_cap, sizeof *vectors);
82 vectors[vector_cnt++] = xstrdup (lex_tokid (lexer));
85 lex_match (lexer, ',');
88 /* Now that we have the names it's time to check for the short
90 if (lex_match (lexer, '='))
98 msg (SE, _("A slash must separate each vector "
99 "specification in VECTOR's long form."));
103 if (!parse_variables_pool (lexer, pool, dict, &v, &nv,
104 PV_SAME_WIDTH | PV_DUPLICATE))
107 dict_create_vector (dict, vectors[0], v, nv);
109 else if (lex_match (lexer, '('))
112 struct fmt_spec format;
113 bool seen_format = false;
115 struct variable **vars;
121 format = fmt_for_output (FMT_F, 8, 2);
123 while (!lex_match (lexer, ')'))
125 if (lex_is_integer (lexer) && var_cnt == 0)
127 var_cnt = lex_integer (lexer);
131 msg (SE, _("Vectors must have at least one element."));
135 else if (lex_token (lexer) == T_ID && !seen_format)
138 if (!parse_format_specifier (lexer, &format)
139 || !fmt_check_output (&format)
140 || !fmt_check_type_compat (&format, VAR_NUMERIC))
145 lex_error (lexer, NULL);
148 lex_match (lexer, ',');
152 lex_error (lexer, _("expecting vector length"));
156 /* Check that none of the variables exist and that
157 their names are no more than LONG_NAME_LEN bytes
159 for (i = 0; i < vector_cnt; i++)
162 for (j = 0; j < var_cnt; j++)
164 char name[LONG_NAME_LEN + INT_STRLEN_BOUND (int) + 1];
165 sprintf (name, "%s%d", vectors[i], j + 1);
166 if (strlen (name) > LONG_NAME_LEN)
168 msg (SE, _("%s is too long for a variable name."), name);
171 if (dict_lookup_var (dict, name))
173 msg (SE, _("%s is an existing variable name."), name);
179 /* Finally create the variables and vectors. */
180 vars = pool_nmalloc (pool, var_cnt, sizeof *vars);
181 for (i = 0; i < vector_cnt; i++)
184 for (j = 0; j < var_cnt; j++)
186 char name[LONG_NAME_LEN + 1];
187 sprintf (name, "%s%d", vectors[i], j + 1);
188 vars[j] = dict_create_var_assert (dict, name, 0);
189 var_set_both_formats (vars[j], &format);
191 dict_create_vector_assert (dict, vectors[i], vars, var_cnt);
196 lex_error (lexer, NULL);
200 while (lex_match (lexer, '/'));
203 return lex_end_of_command (lexer);