1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2009, 2010, 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 "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"
32 #include "gl/xalloc.h"
35 #define _(msgid) gettext (msgid)
37 /* Creates and returns a new struct driver_option that contains copies of
38 all of the supplied arguments. All of the arguments must be nonnull,
39 except that VALUE may be NULL (if the user did not supply a value for this
42 Refer to struct driver_option for the meaning of each argument. */
43 struct driver_option *
44 driver_option_create (const char *driver_name, const char *name,
45 const char *value, const char *default_value)
47 struct driver_option *o = xmalloc (sizeof *o);
48 o->driver_name = xstrdup (driver_name);
49 o->name = xstrdup (name);
50 o->value = value != NULL ? xstrdup (value) : NULL;
51 o->default_value = default_value ? xstrdup (default_value) : NULL;
55 /* Creates and returns a new struct driver_option for output driver DRIVER
56 (which is needed only to the extent that its name will be used in error
57 messages). The option named NAME is extracted from OPTIONS. DEFAULT_VALUE
58 is the default value of the option, used if the given option was not
59 supplied or was invalid. */
60 struct driver_option *
61 driver_option_get (struct output_driver *driver, struct string_map *options,
62 const char *name, const char *default_value)
64 struct driver_option *option;
67 value = string_map_find_and_delete (options, name);
68 option = driver_option_create (output_driver_get_name (driver), name, value,
74 /* Frees driver option O. */
76 driver_option_destroy (struct driver_option *o)
80 free (o->driver_name);
83 free (o->default_value);
88 /* Stores the paper size of the value of option O into *H and *V, in 1/72000"
89 units. Any syntax accepted by measure_paper() may be used.
93 parse_paper_size (struct driver_option *o, int *h, int *v)
95 if (o->value == NULL || !measure_paper (o->value, h, v))
96 measure_paper (o->default_value, h, v);
97 driver_option_destroy (o);
101 do_parse_boolean (const char *driver_name, const char *key,
104 if (!strcmp (value, "on") || !strcmp (value, "true")
105 || !strcmp (value, "yes") || !strcmp (value, "1"))
107 else if (!strcmp (value, "off") || !strcmp (value, "false")
108 || !strcmp (value, "no") || !strcmp (value, "0"))
112 msg (MW, _("%s: `%s' is `%s' but a Boolean value is required"),
113 driver_name, value, key);
118 /* Parses and return O's value as a Boolean value. "true" and "false", "yes"
119 and "no", "on" and "off", and "1" and "0" are acceptable boolean strings.
123 parse_boolean (struct driver_option *o)
127 retval = do_parse_boolean (o->driver_name, o->name, o->default_value) > 0;
128 if (o->value != NULL)
130 int value = do_parse_boolean (o->driver_name, o->name, o->value);
135 driver_option_destroy (o);
140 /* Parses O's value as an enumeration constant. The arguments to this function
141 consist of a series of string/int pairs, terminated by a null pointer value.
142 O's value is compared to each string in turn, and parse_enum() returns the
143 int associated with the first matching string. If there is no match, or if
144 O has no user-specified value, then O's default value is treated the same
145 way. If the default value still does not match, parse_enum() returns 0.
147 Example: parse_enum (o, "a", 1, "b", 2, NULL_SENTINEL) returns 1 if O's
148 value if "a", 2 if O's value is "b".
152 parse_enum (struct driver_option *o, ...)
164 s = va_arg (args, const char *);
167 if (o->value != NULL)
169 struct string choices;
172 ds_init_empty (&choices);
177 s = va_arg (args, const char *);
180 value = va_arg (args, int);
183 ds_put_cstr (&choices, ", ");
184 ds_put_format (&choices, "`%s'", s);
187 msg (MW, _("%s: `%s' is `%s' but one of the following "
189 o->driver_name, o->name, o->value, ds_cstr (&choices));
190 ds_destroy (&choices);
194 value = va_arg (args, int);
196 if (o->value != NULL && !strcmp (s, o->value))
201 else if (!strcmp (s, o->default_value))
205 driver_option_destroy (o);
209 /* Parses O's value as an integer in the range MIN_VALUE to MAX_VALUE
210 (inclusive) and returns the integer.
214 parse_int (struct driver_option *o, int min_value, int max_value)
216 int retval = strtol (o->default_value, NULL, 0);
218 if (o->value != NULL)
224 value = strtol (o->value, &tail, 0);
225 if (tail != o->value && *tail == '\0' && errno != ERANGE
226 && value >= min_value && value <= max_value)
228 else if (max_value == INT_MAX)
231 msg (MW, _("%s: `%s' is `%s' but a nonnegative integer "
233 o->driver_name, o->name, o->value);
234 else if (min_value == 1)
235 msg (MW, _("%s: `%s' is `%s' but a positive integer is "
236 "required"), o->driver_name, o->name, o->value);
237 else if (min_value == INT_MIN)
238 msg (MW, _("%s: `%s' is `%s' but an integer is required"),
239 o->driver_name, o->name, o->value);
241 msg (MW, _("%s: `%s' is `%s' but an integer greater "
242 "than %d is required"),
243 o->driver_name, o->name, o->value, min_value - 1);
246 msg (MW, _("%s: `%s' is `%s' but an integer between %d and "
248 o->driver_name, o->name, o->value, min_value, max_value);
251 driver_option_destroy (o);
255 /* Parses O's value as a dimension, as understood by measure_dimension(), and
256 returns its length in units of 1/72000".
260 parse_dimension (struct driver_option *o)
264 retval = (o->value != NULL ? measure_dimension (o->value)
265 : o->default_value != NULL ? measure_dimension (o->default_value)
268 driver_option_destroy (o);
272 /* Parses O's value as a string and returns it as a malloc'd string that the
273 caller is responsible for freeing.
277 parse_string (struct driver_option *o)
279 char *retval = xstrdup (o->value != NULL ? o->value : o->default_value);
280 driver_option_destroy (o);
285 default_chart_file_name (const char *file_name)
287 if (strcmp (file_name, "-"))
289 const char *extension = strrchr (file_name, '.');
290 int stem_length = extension ? extension - file_name : strlen (file_name);
291 return xasprintf ("%.*s-#.png", stem_length, file_name);
297 /* Parses and returns a chart file name, or NULL if no charts should be output.
298 If a nonnull string is returned, it will contain at least one '#' character,
299 which the client will presumably replace by a number as part of writing
300 charts to separate files.
302 If O->value is "none", then this function returns NULL.
304 If O->value is non-NULL but not "none", returns a copy of that string (if it
307 If O->value is NULL, then O's default_value should be the name of the main
308 output file. Returns NULL if default_value is "-", and otherwise returns a
309 copy of string string with its extension stripped off and "-#.png" appended.
313 parse_chart_file_name (struct driver_option *o)
315 char *chart_file_name;
317 if (o->value != NULL)
319 if (!strcmp (o->value, "none"))
320 chart_file_name = NULL;
321 else if (strchr (o->value, '#') != NULL)
322 chart_file_name = xstrdup (o->value);
325 msg (MW, _("%s: `%s' is `%s' but a file name that contains "
327 o->name, o->value, o->driver_name);
328 chart_file_name = default_chart_file_name (o->default_value);
332 chart_file_name = default_chart_file_name (o->default_value);
334 driver_option_destroy (o);
336 return chart_file_name;