1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
31 /*#define DEBUGGING 1*/
32 #include "debug-print.h"
35 static void debug_print ();
38 /* Variables on MIS VAL. */
39 static struct variable **v;
42 /* Type of the variables on MIS VAL. */
45 /* Width of string variables on MIS VAL. */
48 /* Items to fill-in var structs with. */
50 static union value missing[3];
52 static int parse_varnames (void);
53 static int parse_numeric (void);
54 static int parse_alpha (void);
57 cmd_missing_values (void)
61 lex_match_id ("MISSING");
62 lex_match_id ("VALUES");
66 memset (missing, 0, sizeof missing);
69 if (!parse_varnames ())
74 if ((type == NUMERIC && !parse_numeric ())
75 || (type == ALPHA && !parse_alpha ()))
79 miss_type = MISSING_NONE;
83 msg (SE, _("`)' expected after value specification."));
87 for (i = 0; i < nv; i++)
89 v[i]->miss_type = miss_type;
90 memcpy (v[i]->missing, missing, sizeof v[i]->missing);
101 return lex_end_of_command ();
105 return CMD_PART_SUCCESS_MAYBE;
109 parse_varnames (void)
113 if (!parse_variables (NULL, &v, &nv, PV_SAME_TYPE))
115 if (!lex_match ('('))
117 msg (SE, _("`(' expected after variable name%s."), nv > 1 ? "s" : "");
126 for (i = 1; i < nv; i++)
127 if (v[i]->type == ALPHA && v[i]->nv != 1)
129 msg (SE, _("Long string value specified."));
132 else if (v[i]->type == ALPHA && (int) width != v[i]->width)
134 msg (SE, _("Short strings must be of equal width."));
141 /* Number or range? */
144 MV_NOR_NOTHING, /* Empty. */
145 MV_NOR_NUMBER, /* Single number. */
146 MV_NOR_RANGE /* Range. */
149 /* A single value or a range. */
152 int type; /* One of NOR_*. */
153 double d[2]; /* d[0]=lower bound or value, d[1]=upper bound. */
156 /* Parses something of the form <num>, or LO[WEST] THRU <num>, or
157 <num> THRU HI[GHEST], or <num> THRU <num>, and sets the appropriate
158 members of NOR. Returns success. */
160 parse_num_or_range (struct num_or_range * nor)
162 if (lex_match_id ("LO") || lex_match_id ("LOWEST"))
164 nor->type = MV_NOR_RANGE;
165 if (!lex_force_match_id ("THRU"))
167 if (!lex_force_num ())
172 else if (token == T_NUM)
177 if (lex_match_id ("THRU"))
179 nor->type = MV_NOR_RANGE;
180 if (lex_match_id ("HI") || lex_match_id ("HIGHEST"))
184 if (!lex_force_num ())
189 if (nor->d[0] > nor->d[1])
191 msg (SE, _("Range %g THRU %g is not valid because %g is "
193 nor->d[0], nor->d[1], nor->d[0], nor->d[1]);
199 nor->type = MV_NOR_NUMBER;
207 /* Parses a set of numeric missing values and stores them into
208 `missing[]' and `miss_type' global variables. */
212 struct num_or_range set[3];
215 set[1].type = set[2].type = MV_NOR_NOTHING;
217 /* Get first number or range. */
218 r = parse_num_or_range (&set[0]);
222 msg (SE, _("Number or range expected."));
226 /* Get second and third optional number or range. */
228 r = parse_num_or_range (&set[1]);
232 r = parse_num_or_range (&set[2]);
237 /* Force range, if present, into set[0]. */
238 if (set[1].type == MV_NOR_RANGE)
240 struct num_or_range t = set[1];
244 if (set[2].type == MV_NOR_RANGE)
246 struct num_or_range t = set[2];
251 /* Ensure there's not more than one range, or one range
253 if (set[1].type == MV_NOR_RANGE || set[2].type == MV_NOR_RANGE)
255 msg (SE, _("At most one range can exist in the missing values "
256 "for any one variable."));
259 if (set[0].type == MV_NOR_RANGE && set[2].type != MV_NOR_NOTHING)
261 msg (SE, _("At most one individual value can be missing along "
266 /* Set missing[] from set[]. */
267 if (set[0].type == MV_NOR_RANGE)
271 if (set[0].d[0] == LOWEST)
273 miss_type = MISSING_LOW;
274 missing[x++].f = set[0].d[1];
276 else if (set[0].d[1] == HIGHEST)
278 miss_type = MISSING_HIGH;
279 missing[x++].f = set[0].d[0];
283 miss_type = MISSING_RANGE;
284 missing[x++].f = set[0].d[0];
285 missing[x++].f = set[0].d[1];
288 if (set[1].type == MV_NOR_NUMBER)
291 missing[x].f = set[1].d[0];
296 if (set[0].type == MV_NOR_NUMBER)
298 miss_type = MISSING_1;
299 missing[0].f = set[0].d[0];
301 if (set[1].type == MV_NOR_NUMBER)
303 miss_type = MISSING_2;
304 missing[1].f = set[1].d[0];
306 if (set[2].type == MV_NOR_NUMBER)
308 miss_type = MISSING_3;
309 missing[2].f = set[2].d[0];
319 for (miss_type = 0; token == T_STRING && miss_type < 3; miss_type++)
321 if (ds_length (&tokstr) != width)
323 msg (SE, _("String is not of proper length."));
326 strncpy (missing[miss_type].s, ds_value (&tokstr), MAX_SHORT_STRING);
332 msg (SE, _("String expected."));
339 /* Copy the missing values from variable SRC to variable DEST. */
341 copy_missing_values (struct variable *dest, const struct variable *src)
343 static const int n_values[MISSING_COUNT] =
345 0, 1, 2, 3, 2, 1, 1, 3, 2, 2,
348 assert (dest->width == src->width);
349 assert (src->miss_type >= 0 && src->miss_type < MISSING_COUNT);
354 dest->miss_type = src->miss_type;
355 for (i = 0; i < n_values[src->miss_type]; i++)
356 if (src->type == NUMERIC)
357 dest->missing[i].f = src->missing[i].f;
359 memcpy (dest->missing[i].s, src->missing[i].s, src->width);
372 puts (_("Missing value:"));
373 for (i = 0; i < nvar; i++)
375 printf (" %8s: ", var[i]->name);
376 if (var[i]->type == ALPHA && var[i]->nv > 1)
377 puts (_("(long string variable)"));
379 switch (var[i]->miss_type)
382 printf (_("(no missing values)\n"));
387 printf ("(MISSING_%d)", var[i]->miss_type);
388 for (j = 0; j < var[i]->miss_type; j++)
389 if (var[i]->type == ALPHA)
390 printf (" \"%.*s\"", var[i]->width, var[i]->missing[j].s);
392 printf (" %.2g", var[i]->missing[j].f);
396 printf ("(MISSING_RANGE) %.2g THRU %.2g\n",
397 var[i]->missing[0].f, var[i]->missing[1].f);
399 case MISSING_RANGE_1:
400 printf ("(MISSING_RANGE_1) %.2g THRU %.2g, %.2g\n",
401 var[i]->missing[0].f, var[i]->missing[1].f,
402 var[i]->missing[2].f);
405 printf (_("(!!!INTERNAL ERROR--%d!!!)\n"), var[i]->miss_type);
409 #endif /* DEBUGGING */