1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2015 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 "data/settings.h"
25 #include "data/case.h"
26 #include "data/format.h"
27 #include "data/value.h"
28 #include "libpspp/i18n.h"
29 #include "libpspp/integer-format.h"
30 #include "libpspp/message.h"
32 #include "gl/minmax.h"
33 #include "gl/xalloc.h"
36 #define _(msgid) gettext (msgid)
40 /* Integer format used for IB and PIB input. */
41 enum integer_format input_integer_format;
43 /* Floating-point format used for RB and RBHEX input. */
44 enum float_format input_float_format;
46 /* Format of integers in output (SET WIB). */
47 enum integer_format output_integer_format;
49 /* Format of reals in output (SET WRB). */
50 enum float_format output_float_format;
57 bool route_errors_to_terminal;
58 bool route_errors_to_listing;
62 int max_messages[MSG_N_SEVERITIES];
67 struct fmt_spec default_format;
75 struct fmt_settings *styles;
77 enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
79 enum settings_var_style var_output_style;
80 enum settings_value_style value_output_style;
83 static struct settings the_settings = {
84 INTEGER_NATIVE, /* input_integer_format */
85 FLOAT_NATIVE_DOUBLE, /* input_float_format */
86 INTEGER_NATIVE, /* output_integer_format */
87 FLOAT_NATIVE_DOUBLE, /* output_float_format */
90 false, /* safer_mode */
93 true, /* route_errors_to_terminal */
94 true, /* route_errors_to_listing */
101 100, /* MSG_S_ERROR */
102 100, /* MSG_S_WARNING */
106 true, /* printback */
109 64L * 1024 * 1024, /* workspace */
110 {FMT_F, 8, 2}, /* default_format */
111 false, /* testing_mode */
113 ENHANCED, /* cmd_algorithm */
114 ENHANCED, /* global_algorithm */
115 ENHANCED, /* syntax */
119 {SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
120 SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
122 SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL},
124 SETTINGS_VAR_STYLE_LABELS,
125 SETTINGS_VAL_STYLE_LABELS
128 /* Initializes the settings module. */
132 settings_set_epoch (-1);
133 the_settings.styles = fmt_settings_create ();
135 settings_set_decimal_char (get_system_decimal ());
138 /* Cleans up the settings module. */
142 settings_destroy (&the_settings);
146 settings_copy (struct settings *dst, const struct settings *src)
149 dst->styles = fmt_settings_clone (src->styles);
152 /* Returns a copy of the current settings. */
156 struct settings *s = xmalloc (sizeof *s);
157 settings_copy (s, &the_settings);
161 /* Replaces the current settings by those in S. The caller retains ownership
164 settings_set (const struct settings *s)
166 settings_destroy (&the_settings);
167 settings_copy (&the_settings, s);
172 settings_destroy (struct settings *s)
176 fmt_settings_destroy (s->styles);
177 if (s != &the_settings)
182 /* Returns the floating-point format used for RB and RBHEX
185 settings_get_input_float_format (void)
187 return the_settings.input_float_format;
190 /* Sets the floating-point format used for RB and RBHEX input to
193 settings_set_input_float_format ( enum float_format format)
195 the_settings.input_float_format = format;
198 /* Returns the integer format used for IB and PIB input. */
200 settings_get_input_integer_format (void)
202 return the_settings.input_integer_format;
205 /* Sets the integer format used for IB and PIB input to
208 settings_set_input_integer_format ( enum integer_format format)
210 the_settings.input_integer_format = format;
213 /* Returns the current output integer format. */
215 settings_get_output_integer_format (void)
217 return the_settings.output_integer_format;
220 /* Sets the output integer format to INTEGER_FORMAT. */
222 settings_set_output_integer_format (
223 enum integer_format integer_format)
225 the_settings.output_integer_format = integer_format;
228 /* Returns the current output float format. */
230 settings_get_output_float_format (void)
232 return the_settings.output_float_format;
235 /* Sets the output float format to FLOAT_FORMAT. */
237 settings_set_output_float_format ( enum float_format float_format)
239 the_settings.output_float_format = float_format;
242 /* Screen length in lines. */
244 settings_get_viewlength (void)
246 return the_settings.viewlength;
249 /* Sets the view length. */
251 settings_set_viewlength ( int viewlength_)
253 the_settings.viewlength = viewlength_;
258 settings_get_viewwidth(void)
260 return the_settings.viewwidth;
263 /* Sets the screen width. */
265 settings_set_viewwidth ( int viewwidth_)
267 the_settings.viewwidth = viewwidth_;
270 /* Whether PSPP can erase and overwrite files. */
272 settings_get_safer_mode (void)
274 return the_settings.safer_mode;
277 /* Set safer mode. */
279 settings_set_safer_mode (void)
281 the_settings.safer_mode = true;
284 /* If echo is on, whether commands from include files are echoed. */
286 settings_get_include (void)
288 return the_settings.include;
291 /* Set include file echo. */
293 settings_set_include ( bool include)
295 the_settings.include = include;
298 /* What year to use as the start of the epoch. */
300 settings_get_epoch (void)
302 assert (the_settings.epoch >= 0);
304 return the_settings.epoch;
307 /* Sets the year that starts the epoch. */
309 settings_set_epoch ( int epoch)
314 struct tm *tm = localtime (&t);
315 epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
318 the_settings.epoch = epoch;
319 assert (the_settings.epoch >= 0);
322 /* Compress system files by default? */
324 settings_get_scompression (void)
326 return the_settings.scompress;
329 /* Set system file default compression. */
331 settings_set_scompression ( bool scompress)
333 the_settings.scompress = scompress;
336 /* Whether to warn on undefined values in numeric data. */
338 settings_get_undefined (void)
340 return the_settings.undefined;
343 /* Set whether to warn on undefined values. */
345 settings_set_undefined ( bool undefined)
347 the_settings.undefined = undefined;
350 /* The value that blank numeric fields are set to when read in. */
352 settings_get_blanks (void)
354 return the_settings.blanks;
357 /* Set the value that blank numeric fields are set to when read
360 settings_set_blanks ( double blanks)
362 the_settings.blanks = blanks;
365 /* Returns the maximum number of messages to show of the given SEVERITY before
366 aborting. (The value for MSG_S_WARNING is interpreted as maximum number of
367 warnings and errors combined.) */
369 settings_get_max_messages (enum msg_severity severity)
371 assert (severity < MSG_N_SEVERITIES);
372 return the_settings.max_messages[severity];
375 /* Sets the maximum number of messages to show of the given SEVERITY before
376 aborting to MAX. (The value for MSG_S_WARNING is interpreted as maximum
377 number of warnings and errors combined.) In addition, in the case of
378 warnings the special value of zero indicates that no warnings are to be
382 settings_set_max_messages (enum msg_severity severity, int max)
384 assert (severity < MSG_N_SEVERITIES);
386 if (severity == MSG_S_WARNING)
391 _("MXWARNS set to zero. No further warnings will be given even when potentially problematic situations are encountered."));
392 msg_ui_disable_warnings (true);
394 else if ( the_settings.max_messages [MSG_S_WARNING] == 0)
396 msg_ui_disable_warnings (false);
397 the_settings.max_messages[MSG_S_WARNING] = max;
398 msg (MW, _("Warnings re-enabled. %d warnings will be issued before aborting syntax processing."), max);
402 the_settings.max_messages[severity] = max;
405 /* Independent of get_printback, controls whether the commands
406 generated by macro invocations are displayed. */
408 settings_get_mprint (void)
410 return the_settings.mprint;
413 /* Sets whether the commands generated by macro invocations are
416 settings_set_mprint ( bool mprint)
418 the_settings.mprint = mprint;
421 /* Implied limit of unbounded loop. */
423 settings_get_mxloops (void)
425 return the_settings.mxloops;
428 /* Set implied limit of unbounded loop. */
430 settings_set_mxloops ( int mxloops)
432 the_settings.mxloops = mxloops;
435 /* Approximate maximum amount of memory to use for cases, in
438 settings_get_workspace (void)
440 return the_settings.workspace;
443 /* Approximate maximum number of cases to allocate in-core, given
444 that each case has the format given in PROTO. */
446 settings_get_workspace_cases (const struct caseproto *proto)
448 size_t n_cases = settings_get_workspace () / case_get_cost (proto);
449 return MAX (n_cases, 4);
452 /* Set approximate maximum amount of memory to use for cases, in
456 settings_set_workspace (size_t workspace)
458 the_settings.workspace = workspace;
461 /* Default format for variables created by transformations and by
462 DATA LIST {FREE,LIST}. */
463 const struct fmt_spec *
464 settings_get_format (void)
466 return &the_settings.default_format;
469 /* Set default format for variables created by transformations
470 and by DATA LIST {FREE,LIST}. */
472 settings_set_format ( const struct fmt_spec *default_format)
474 the_settings.default_format = *default_format;
477 /* Are we in testing mode? (e.g. --testing-mode command line
480 settings_get_testing_mode (void)
482 return the_settings.testing_mode;
485 /* Set testing mode. */
487 settings_set_testing_mode ( bool testing_mode)
489 the_settings.testing_mode = testing_mode;
493 settings_get_fuzzbits (void)
495 return the_settings.fuzzbits;
499 settings_set_fuzzbits (int fuzzbits)
501 the_settings.fuzzbits = fuzzbits;
504 /* Return the current algorithm setting */
506 settings_get_algorithm (void)
508 return the_settings.cmd_algorithm;
511 /* Set the algorithm option globally. */
513 settings_set_algorithm (enum behavior_mode mode)
515 the_settings.global_algorithm = the_settings.cmd_algorithm = mode;
518 /* Set the algorithm option for this command only */
520 settings_set_cmd_algorithm ( enum behavior_mode mode)
522 the_settings.cmd_algorithm = mode;
525 /* Unset the algorithm option for this command */
527 unset_cmd_algorithm (void)
529 the_settings.cmd_algorithm = the_settings.global_algorithm;
532 /* Get the current syntax setting */
534 settings_get_syntax (void)
536 return the_settings.syntax;
539 /* Set the syntax option */
541 settings_set_syntax ( enum behavior_mode mode)
543 the_settings.syntax = mode;
548 /* Find the grouping characters in CC_STRING and sets *GROUPING and *DECIMAL
549 appropriately. Returns true if successful, false otherwise. */
551 find_cc_separators (const char *cc_string, char *decimal, char *grouping)
554 int comma_cnt, dot_cnt;
556 /* Count commas and periods. There must be exactly three of
557 one or the other, except that an apostrophe escapes a
558 following comma or period. */
559 comma_cnt = dot_cnt = 0;
560 for (sp = cc_string; *sp; sp++)
565 else if (*sp == '\'' && (sp[1] == '.' || sp[1] == ',' || sp[1] == '\''))
568 if ((comma_cnt == 3) == (dot_cnt == 3))
584 /* Extracts a token from IN into a newly allocated string AFFIXP. Tokens are
585 delimited by GROUPING. Returns the first character following the token. */
587 extract_cc_token (const char *in, int grouping, char **affixp)
591 out = *affixp = xmalloc (strlen (in) + 1);
592 for (; *in != '\0' && *in != grouping; in++)
594 if (*in == '\'' && in[1] == grouping)
605 /* Sets custom currency specifier CC having name CC_NAME ('A' through
606 'E') to correspond to the settings in CC_STRING. */
608 settings_set_cc (const char *cc_string, enum fmt_type type)
610 char *neg_prefix, *prefix, *suffix, *neg_suffix;
611 char decimal, grouping;
613 assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
615 /* Determine separators. */
616 if (!find_cc_separators (cc_string, &decimal, &grouping))
618 msg (SE, _("%s: Custom currency string `%s' does not contain "
619 "exactly three periods or commas (or it contains both)."),
620 fmt_name (type), cc_string);
624 cc_string = extract_cc_token (cc_string, grouping, &neg_prefix);
625 cc_string = extract_cc_token (cc_string, grouping, &prefix);
626 cc_string = extract_cc_token (cc_string, grouping, &suffix);
627 cc_string = extract_cc_token (cc_string, grouping, &neg_suffix);
629 fmt_settings_set_style (the_settings.styles, type, decimal, grouping,
630 neg_prefix, prefix, suffix, neg_suffix);
640 /* Returns the decimal point character for TYPE. */
642 settings_get_decimal_char (enum fmt_type type)
644 return fmt_settings_get_style (the_settings.styles, type)->decimal;
648 settings_set_decimal_char (char decimal)
650 fmt_settings_set_decimal (the_settings.styles, decimal);
653 /* Returns the number formatting style associated with the given
655 const struct fmt_number_style *
656 settings_get_style (enum fmt_type type)
658 assert (is_fmt_type (type));
659 return fmt_settings_get_style (the_settings.styles, type);
662 /* Returns a string of the form "$#,###.##" according to FMT,
663 which must be of type FMT_DOLLAR. The caller must free the
666 settings_dollar_template (const struct fmt_spec *fmt)
668 struct string str = DS_EMPTY_INITIALIZER;
670 const struct fmt_number_style *fns ;
672 assert (fmt->type == FMT_DOLLAR);
674 fns = fmt_settings_get_style (the_settings.styles, fmt->type);
676 ds_put_byte (&str, '$');
677 for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
679 ds_put_byte (&str, '#');
680 if (--c % 4 == 0 && c > 0)
682 ds_put_byte (&str, fns->grouping);
688 ds_put_byte (&str, fns->decimal);
689 ds_put_byte_multiple (&str, '#', fmt->d);
692 return ds_cstr (&str);
696 settings_set_output_routing (enum settings_output_type type,
697 enum settings_output_devices devices)
699 assert (type < SETTINGS_N_OUTPUT_TYPES);
700 the_settings.output_routing[type] = devices;
703 enum settings_output_devices
704 settings_get_output_routing (enum settings_output_type type)
706 assert (type < SETTINGS_N_OUTPUT_TYPES);
707 return the_settings.output_routing[type] | SETTINGS_DEVICE_UNFILTERED;
710 enum settings_value_style
711 settings_get_value_style (void)
713 return the_settings.value_output_style;
717 settings_set_value_style (enum settings_value_style s)
719 the_settings.value_output_style = s;
724 enum settings_var_style
725 settings_get_var_style (void)
727 return the_settings.var_output_style;
732 settings_set_var_style (enum settings_var_style s)
734 the_settings.var_output_style = s;