1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2009, 2010 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 "output/options.h"
27 #include "libpspp/str.h"
28 #include "libpspp/string-map.h"
29 #include "output/driver-provider.h"
30 #include "output/measure.h"
33 #include "gl/xalloc.h"
36 #define _(msgid) gettext (msgid)
38 /* Creates and returns a new struct driver_option that contains copies of
39 all of the supplied arguments. All of the arguments must be nonnull,
40 except that VALUE may be NULL (if the user did not supply a value for this
43 Refer to struct driver_option for the meaning of each argument. */
44 struct driver_option *
45 driver_option_create (const char *driver_name, const char *name,
46 const char *value, const char *default_value)
48 struct driver_option *o = xmalloc (sizeof *o);
49 o->driver_name = xstrdup (driver_name);
50 o->name = xstrdup (name);
51 o->value = value != NULL ? xstrdup (value) : NULL;
52 o->default_value = xstrdup (default_value);
56 /* Creates and returns a new struct driver_option for output driver DRIVER
57 (which is needed only to the extent that its name will be used in error
58 messages). The option named NAME is extracted from OPTIONS. DEFAULT_VALUE
59 is the default value of the option, used if the given option was not
60 supplied or was invalid. */
61 struct driver_option *
62 driver_option_get (struct output_driver *driver, struct string_map *options,
63 const char *name, const char *default_value)
65 struct driver_option *option;
68 value = string_map_find_and_delete (options, name);
69 option = driver_option_create (output_driver_get_name (driver), name, value,
75 /* Frees driver option O. */
77 driver_option_destroy (struct driver_option *o)
81 free (o->driver_name);
84 free (o->default_value);
89 /* Stores the paper size of the value of option O into *H and *V, in 1/72000"
90 units. Any syntax accepted by measure_paper() may be used.
94 parse_paper_size (struct driver_option *o, int *h, int *v)
96 if (o->value == NULL || !measure_paper (o->value, h, v))
97 measure_paper (o->default_value, h, v);
98 driver_option_destroy (o);
102 do_parse_boolean (const char *driver_name, const char *key,
105 if (!strcmp (value, "on") || !strcmp (value, "true")
106 || !strcmp (value, "yes") || !strcmp (value, "1"))
108 else if (!strcmp (value, "off") || !strcmp (value, "false")
109 || !strcmp (value, "no") || !strcmp (value, "0"))
113 error (0, 0, _("%s: `%s' is `%s' but a Boolean value is required"),
114 driver_name, value, key);
119 /* Parses and return O's value as a Boolean value. "true" and "false", "yes"
120 and "no", "on" and "off", and "1" and "0" are acceptable boolean strings.
124 parse_boolean (struct driver_option *o)
128 retval = do_parse_boolean (o->driver_name, o->name, o->default_value) > 0;
129 if (o->value != NULL)
131 int value = do_parse_boolean (o->driver_name, o->name, o->value);
136 driver_option_destroy (o);
141 /* Parses O's value as an enumeration constant. The arguments to this function
142 consist of a series of string/int pairs, terminated by a null pointer value.
143 O's value is compared to each string in turn, and parse_enum() returns the
144 int associated with the first matching string. If there is no match, or if
145 O has no user-specified value, then O's default value is treated the same
146 way. If the default value still does not match, parse_enum() returns 0.
148 Example: parse_enum (o, "a", 1, "b", 2, NULL_SENTINEL) returns 1 if O's
149 value if "a", 2 if O's value is "b".
153 parse_enum (struct driver_option *o, ...)
165 s = va_arg (args, const char *);
168 if (o->value != NULL)
170 struct string choices;
173 ds_init_empty (&choices);
178 s = va_arg (args, const char *);
181 value = va_arg (args, int);
184 ds_put_cstr (&choices, ", ");
185 ds_put_format (&choices, "`%s'", s);
188 error (0, 0, _("%s: `%s' is `%s' but one of the following "
190 o->driver_name, o->name, o->value, ds_cstr (&choices));
191 ds_destroy (&choices);
195 value = va_arg (args, int);
197 if (o->value != NULL && !strcmp (s, o->value))
202 else if (!strcmp (s, o->default_value))
206 driver_option_destroy (o);
210 /* Parses O's value as an integer in the range MIN_VALUE to MAX_VALUE
211 (inclusive) and returns the integer.
215 parse_int (struct driver_option *o, int min_value, int max_value)
217 int retval = strtol (o->default_value, NULL, 0);
219 if (o->value != NULL)
225 value = strtol (o->value, &tail, 0);
226 if (tail != o->value && *tail == '\0' && errno != ERANGE
227 && value >= min_value && value <= max_value)
229 else if (max_value == INT_MAX)
232 error (0, 0, _("%s: `%s' is `%s' but a nonnegative integer "
234 o->driver_name, o->name, o->value);
235 else if (min_value == 1)
236 error (0, 0, _("%s: `%s' is `%s' but a positive integer is "
237 "required"), o->driver_name, o->name, o->value);
238 else if (min_value == INT_MIN)
239 error (0, 0, _("%s: `%s' is `%s' but an integer is required"),
240 o->driver_name, o->name, o->value);
242 error (0, 0, _("%s: `%s' is `%s' but an integer greater "
243 "than %d is required"),
244 o->driver_name, o->name, o->value, min_value - 1);
247 error (0, 0, _("%s: `%s' is `%s' but an integer between %d and "
249 o->driver_name, o->name, o->value, min_value, max_value);
252 driver_option_destroy (o);
256 /* Parses O's value as a dimension, as understood by measure_dimension(), and
257 returns its length in units of 1/72000".
261 parse_dimension (struct driver_option *o)
265 retval = o->value != NULL ? measure_dimension (o->value) : -1;
267 retval = measure_dimension (o->default_value);
269 driver_option_destroy (o);
273 /* Parses O's value as a string and returns it as a malloc'd string that the
274 caller is responsible for freeing.
278 parse_string (struct driver_option *o)
280 char *retval = xstrdup (o->value != NULL ? o->value : o->default_value);
281 driver_option_destroy (o);
286 default_chart_file_name (const char *file_name)
288 if (strcmp (file_name, "-"))
290 const char *extension = strrchr (file_name, '.');
291 int stem_length = extension ? extension - file_name : strlen (file_name);
292 return xasprintf ("%.*s-#.png", stem_length, file_name);
298 /* Parses and returns a chart file name, or NULL if no charts should be output.
299 If a nonnull string is returned, it will contain at least one '#' character,
300 which the client will presumably replace by a number as part of writing
301 charts to separate files.
303 If O->value is "none", then this function returns NULL.
305 If O->value is non-NULL but not "none", returns a copy of that string (if it
308 If O->value is NULL, then O's default_value should be the name of the main
309 output file. Returns NULL if default_value is "-", and otherwise returns a
310 copy of string string with its extension stripped off and "-#.png" appended.
314 parse_chart_file_name (struct driver_option *o)
316 char *chart_file_name;
318 if (o->value != NULL)
320 if (!strcmp (o->value, "none"))
321 chart_file_name = NULL;
322 else if (strchr (o->value, '#') != NULL)
323 chart_file_name = xstrdup (o->value);
326 error (0, 0, _("%s: `%s' is `%s' but a file name that contains "
328 o->name, o->value, o->driver_name);
329 chart_file_name = default_chart_file_name (o->default_value);
333 chart_file_name = default_chart_file_name (o->default_value);
335 driver_option_destroy (o);
337 return chart_file_name;