1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2005, 2006, 2009, 2010, 2011, 2014 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/>. */
19 #include "value-parser.h"
24 #include "data/data-in.h"
25 #include "data/format.h"
26 #include "data/value.h"
27 #include "language/lexer/lexer.h"
28 #include "libpspp/cast.h"
29 #include "libpspp/i18n.h"
30 #include "libpspp/message.h"
31 #include "libpspp/str.h"
34 #define _(msgid) gettext (msgid)
35 #define N_(msgid) msgid
37 static bool parse_number (struct lexer *, double *, const enum fmt_type *);
39 /* Parses and stores a numeric value, or a range of the form "x
40 THRU y". Open-ended ranges may be specified as "LO(WEST) THRU
41 y" or "x THRU HI(GHEST)". Sets *X and *Y to the range or the
42 value and returns success.
44 Numeric values are always accepted. If FORMAT is nonnull,
45 then string values are also accepted, and converted to numeric
46 values using *FORMAT. */
48 parse_num_range (struct lexer *lexer,
49 double *x, double *y, const enum fmt_type *format)
51 if (lex_match_id (lexer, "LO") || lex_match_id (lexer, "LOWEST"))
53 else if (!parse_number (lexer, x, format))
56 if (lex_match_id (lexer, "THRU"))
58 if (lex_match_id (lexer, "HI") || lex_match_id (lexer, "HIGHEST"))
60 else if (!parse_number (lexer, y, format))
66 msg (SW, _("The high end of the range (%.*g) is below the low end "
67 "(%.*g). The range will be treated as if reversed."),
68 DBL_DIG + 1, *y, DBL_DIG + 1, *x);
74 msg (SW, _("Ends of range are equal (%.*g)."), DBL_DIG + 1, *x);
82 msg (SE, _("%s or %s must be part of a range."), "LO", "LOWEST");
91 /* Parses a number and stores it in *X. Returns success.
93 Numeric values are always accepted. If FORMAT is nonnull,
94 then string values are also accepted, and converted to numeric
95 values using *FORMAT. */
97 parse_number (struct lexer *lexer, double *x, const enum fmt_type *format)
99 if (lex_is_number (lexer))
101 *x = lex_number (lexer);
105 else if (lex_is_string (lexer) && format != NULL)
109 assert (fmt_get_category (*format) != FMT_CAT_STRING);
111 if (!data_in_msg (lex_tokss (lexer), "UTF-8", *format, &v, 0, NULL))
118 msg (SE, _("System-missing value is not valid here."));
126 lex_error (lexer, _("expecting number or data string"));
128 lex_force_num (lexer);
133 /* Parses the current token from LEXER into value V, which must already have
134 been initialized with the specified VAR's WIDTH. Returns true if
135 successful, false otherwise. */
137 parse_value (struct lexer *lexer, union value *v, const struct variable *var)
139 int width = var_get_width (var);
141 return parse_number (lexer, &v->f, &var_get_print_format (var)->type);
142 else if (lex_force_string (lexer))
144 const char *s = lex_tokcstr (lexer);
145 value_copy_str_rpad (v, width, CHAR_CAST_BUG (const uint8_t *, s), ' ');