1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2007, 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 "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"
33 #include "gl/minmax.h"
34 #include "gl/xalloc.h"
37 #define _(msgid) gettext (msgid)
41 /* Integer format used for IB and PIB input. */
42 enum integer_format input_integer_format;
44 /* Floating-point format used for RB and RBHEX input. */
45 enum float_format input_float_format;
47 /* Format of integers in output (SET WIB). */
48 enum integer_format output_integer_format;
50 /* Format of reals in output (SET WRB). */
51 enum float_format output_float_format;
58 bool route_errors_to_terminal;
59 bool route_errors_to_listing;
63 int max_messages[MSG_N_SEVERITIES];
70 struct fmt_spec default_format;
77 struct fmt_settings *styles;
79 enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
82 static struct settings the_settings = {
83 INTEGER_NATIVE, /* input_integer_format */
84 FLOAT_NATIVE_DOUBLE, /* input_float_format */
85 INTEGER_NATIVE, /* output_integer_format */
86 FLOAT_NATIVE_DOUBLE, /* output_float_format */
89 false, /* safer_mode */
92 true, /* route_errors_to_terminal */
93 true, /* route_errors_to_listing */
100 100, /* MSG_S_ERROR */
101 100, /* MSG_S_WARNING */
105 true, /* printback */
110 64L * 1024 * 1024, /* workspace */
111 {FMT_F, 8, 2}, /* default_format */
112 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}
125 /* Initializes the settings module. */
129 settings_set_epoch (-1);
130 the_settings.styles = fmt_settings_create ();
132 settings_set_decimal_char (get_system_decimal ());
135 /* Cleans up the settings module. */
139 settings_destroy (&the_settings);
143 settings_copy (struct settings *dst, const struct settings *src)
146 dst->styles = fmt_settings_clone (src->styles);
149 /* Returns a copy of the current settings. */
153 struct settings *s = xmalloc (sizeof *s);
154 settings_copy (s, &the_settings);
158 /* Replaces the current settings by those in S. The caller retains ownership
161 settings_set (const struct settings *s)
163 settings_destroy (&the_settings);
164 settings_copy (&the_settings, s);
169 settings_destroy (struct settings *s)
173 fmt_settings_destroy (s->styles);
174 if (s != &the_settings)
179 /* Returns the floating-point format used for RB and RBHEX
182 settings_get_input_float_format (void)
184 return the_settings.input_float_format;
187 /* Sets the floating-point format used for RB and RBHEX input to
190 settings_set_input_float_format ( enum float_format format)
192 the_settings.input_float_format = format;
195 /* Returns the integer format used for IB and PIB input. */
197 settings_get_input_integer_format (void)
199 return the_settings.input_integer_format;
202 /* Sets the integer format used for IB and PIB input to
205 settings_set_input_integer_format ( enum integer_format format)
207 the_settings.input_integer_format = format;
210 /* Returns the current output integer format. */
212 settings_get_output_integer_format (void)
214 return the_settings.output_integer_format;
217 /* Sets the output integer format to INTEGER_FORMAT. */
219 settings_set_output_integer_format (
220 enum integer_format integer_format)
222 the_settings.output_integer_format = integer_format;
225 /* Returns the current output float format. */
227 settings_get_output_float_format (void)
229 return the_settings.output_float_format;
232 /* Sets the output float format to FLOAT_FORMAT. */
234 settings_set_output_float_format ( enum float_format float_format)
236 the_settings.output_float_format = float_format;
239 /* Screen length in lines. */
241 settings_get_viewlength (void)
243 return the_settings.viewlength;
246 /* Sets the view length. */
248 settings_set_viewlength ( int viewlength_)
250 the_settings.viewlength = viewlength_;
255 settings_get_viewwidth(void)
257 return the_settings.viewwidth;
260 /* Sets the screen width. */
262 settings_set_viewwidth ( int viewwidth_)
264 the_settings.viewwidth = viewwidth_;
267 /* Whether PSPP can erase and overwrite files. */
269 settings_get_safer_mode (void)
271 return the_settings.safer_mode;
274 /* Set safer mode. */
276 settings_set_safer_mode (void)
278 the_settings.safer_mode = true;
281 /* If echo is on, whether commands from include files are echoed. */
283 settings_get_include (void)
285 return the_settings.include;
288 /* Set include file echo. */
290 settings_set_include ( bool include)
292 the_settings.include = include;
295 /* What year to use as the start of the epoch. */
297 settings_get_epoch (void)
299 assert (the_settings.epoch >= 0);
301 return the_settings.epoch;
304 /* Sets the year that starts the epoch. */
306 settings_set_epoch ( int epoch)
311 struct tm *tm = localtime (&t);
312 epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
315 the_settings.epoch = epoch;
316 assert (the_settings.epoch >= 0);
319 /* Compress system files by default? */
321 settings_get_scompression (void)
323 return the_settings.scompress;
326 /* Set system file default compression. */
328 settings_set_scompression ( bool scompress)
330 the_settings.scompress = scompress;
333 /* Whether to warn on undefined values in numeric data. */
335 settings_get_undefined (void)
337 return the_settings.undefined;
340 /* Set whether to warn on undefined values. */
342 settings_set_undefined ( bool undefined)
344 the_settings.undefined = undefined;
347 /* The value that blank numeric fields are set to when read in. */
349 settings_get_blanks (void)
351 return the_settings.blanks;
354 /* Set the value that blank numeric fields are set to when read
357 settings_set_blanks ( double blanks)
359 the_settings.blanks = blanks;
362 /* Returns the maximum number of messages to show of the given SEVERITY before
363 aborting. (The value for MSG_S_WARNING is interpreted as maximum number of
364 warnings and errors combined.) */
366 settings_get_max_messages (enum msg_severity severity)
368 assert (severity < MSG_N_SEVERITIES);
369 return the_settings.max_messages[severity];
372 /* Sets the maximum number of messages to show of the given SEVERITY before
373 aborting to MAX. (The value for MSG_S_WARNING is interpreted as maximum
374 number of warnings and errors combined.) In addition, in the case of
375 warnings the special value of zero indicates that no warnings are to be
379 settings_set_max_messages (enum msg_severity severity, int max)
381 assert (severity < MSG_N_SEVERITIES);
383 if (severity == MSG_S_WARNING)
388 _("MXWARNS set to zero. No further warnings will be given even when potentially problematic situations are encountered."));
389 msg_ui_disable_warnings (true);
391 else if ( the_settings.max_messages [MSG_S_WARNING] == 0)
393 msg_ui_disable_warnings (false);
394 the_settings.max_messages[MSG_S_WARNING] = max;
395 msg (MW, _("Warnings re-enabled. %d warnings will be issued before aborting syntax processing."), max);
399 the_settings.max_messages[severity] = max;
402 /* Independent of get_printback, controls whether the commands
403 generated by macro invocations are displayed. */
405 settings_get_mprint (void)
407 return the_settings.mprint;
410 /* Sets whether the commands generated by macro invocations are
413 settings_set_mprint ( bool mprint)
415 the_settings.mprint = mprint;
418 /* Implied limit of unbounded loop. */
420 settings_get_mxloops (void)
422 return the_settings.mxloops;
425 /* Set implied limit of unbounded loop. */
427 settings_set_mxloops ( int mxloops)
429 the_settings.mxloops = mxloops;
432 /* Whether a blank line is a command terminator. */
434 settings_get_nulline (void)
436 return the_settings.nulline;
439 /* Set whether a blank line is a command terminator. */
441 settings_set_nulline ( bool nulline)
443 the_settings.nulline = nulline;
446 /* The character used to terminate commands. */
448 settings_get_endcmd (void)
450 return the_settings.endcmd;
453 /* Set the character used to terminate commands. */
455 settings_set_endcmd ( char endcmd)
457 the_settings.endcmd = endcmd;
460 /* Approximate maximum amount of memory to use for cases, in
463 settings_get_workspace (void)
465 return the_settings.workspace;
468 /* Approximate maximum number of cases to allocate in-core, given
469 that each case has the format given in PROTO. */
471 settings_get_workspace_cases (const struct caseproto *proto)
473 size_t n_cases = settings_get_workspace () / case_get_cost (proto);
474 return MAX (n_cases, 4);
477 /* Set approximate maximum amount of memory to use for cases, in
481 settings_set_workspace ( size_t workspace)
483 the_settings.workspace = workspace;
486 /* Default format for variables created by transformations and by
487 DATA LIST {FREE,LIST}. */
488 const struct fmt_spec *
489 settings_get_format (void)
491 return &the_settings.default_format;
494 /* Set default format for variables created by transformations
495 and by DATA LIST {FREE,LIST}. */
497 settings_set_format ( const struct fmt_spec *default_format)
499 the_settings.default_format = *default_format;
502 /* Are we in testing mode? (e.g. --testing-mode command line
505 settings_get_testing_mode (void)
507 return the_settings.testing_mode;
510 /* Set testing mode. */
512 settings_set_testing_mode ( bool testing_mode)
514 the_settings.testing_mode = testing_mode;
517 /* Return the current algorithm setting */
519 settings_get_algorithm (void)
521 return the_settings.cmd_algorithm;
524 /* Set the algorithm option globally. */
526 settings_set_algorithm (enum behavior_mode mode)
528 the_settings.global_algorithm = the_settings.cmd_algorithm = mode;
531 /* Set the algorithm option for this command only */
533 settings_set_cmd_algorithm ( enum behavior_mode mode)
535 the_settings.cmd_algorithm = mode;
538 /* Unset the algorithm option for this command */
540 unset_cmd_algorithm (void)
542 the_settings.cmd_algorithm = the_settings.global_algorithm;
545 /* Get the current syntax setting */
547 settings_get_syntax (void)
549 return the_settings.syntax;
552 /* Set the syntax option */
554 settings_set_syntax ( enum behavior_mode mode)
556 the_settings.syntax = mode;
561 /* Find the grouping characters in CC_STRING and set CC's
562 grouping and decimal members appropriately. Returns true if
563 successful, false otherwise. */
565 find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
568 int comma_cnt, dot_cnt;
570 /* Count commas and periods. There must be exactly three of
571 one or the other, except that an apostrophe escapes a
572 following comma or period. */
573 comma_cnt = dot_cnt = 0;
574 for (sp = cc_string; *sp; sp++)
579 else if (*sp == '\'' && (sp[1] == '.' || sp[1] == ',' || sp[1] == '\''))
582 if ((comma_cnt == 3) == (dot_cnt == 3))
598 /* Extracts a token from IN into AFFIX, using BUFFER for storage. BUFFER must
599 have at least FMT_STYLE_AFFIX_MAX + 1 bytes of space. Tokens are delimited
600 by GROUPING. The token is truncated to at most FMT_STYLE_AFFIX_MAX bytes,
601 followed by a null terminator. Returns the first character following the
604 extract_cc_token (const char *in, int grouping, struct substring *affix,
605 char buffer[FMT_STYLE_AFFIX_MAX + 1])
609 for (; *in != '\0' && *in != grouping; in++)
611 if (*in == '\'' && in[1] == grouping)
613 if (ofs < FMT_STYLE_AFFIX_MAX)
616 *affix = ss_buffer (buffer, ofs);
623 /* Sets custom currency specifier CC having name CC_NAME ('A' through
624 'E') to correspond to the settings in CC_STRING. */
626 settings_set_cc (const char *cc_string, enum fmt_type type)
628 char a[FMT_STYLE_AFFIX_MAX + 1];
629 char b[FMT_STYLE_AFFIX_MAX + 1];
630 char c[FMT_STYLE_AFFIX_MAX + 1];
631 char d[FMT_STYLE_AFFIX_MAX + 1];
632 struct fmt_number_style cc;
634 assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
636 /* Determine separators. */
637 if (!find_cc_separators (cc_string, &cc))
639 msg (SE, _("%s: Custom currency string `%s' does not contain "
640 "exactly three periods or commas (or it contains both)."),
641 fmt_name (type), cc_string);
645 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_prefix, a);
646 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.prefix, b);
647 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.suffix, c);
648 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_suffix, d);
650 fmt_settings_set_style (the_settings.styles, type, &cc);
655 /* Returns the decimal point character for TYPE. */
657 settings_get_decimal_char (enum fmt_type type)
659 return fmt_settings_get_style (the_settings.styles, type)->decimal;
663 settings_set_decimal_char (char decimal)
665 fmt_settings_set_decimal (the_settings.styles, decimal);
668 /* Returns the number formatting style associated with the given
670 const struct fmt_number_style *
671 settings_get_style (enum fmt_type type)
673 assert (is_fmt_type (type));
674 return fmt_settings_get_style (the_settings.styles, type);
677 /* Returns a string of the form "$#,###.##" according to FMT,
678 which must be of type FMT_DOLLAR. The caller must free the
681 settings_dollar_template (const struct fmt_spec *fmt)
683 struct string str = DS_EMPTY_INITIALIZER;
685 const struct fmt_number_style *fns ;
687 assert (fmt->type == FMT_DOLLAR);
689 fns = fmt_settings_get_style (the_settings.styles, fmt->type);
691 ds_put_char (&str, '$');
692 for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
694 ds_put_char (&str, '#');
695 if (--c % 4 == 0 && c > 0)
697 ds_put_char (&str, fns->grouping);
703 ds_put_char (&str, fns->decimal);
704 ds_put_char_multiple (&str, '#', fmt->d);
707 return ds_cstr (&str);
711 settings_set_output_routing (enum settings_output_type type,
712 enum settings_output_devices devices)
714 assert (type < SETTINGS_N_OUTPUT_TYPES);
715 the_settings.output_routing[type] = devices;
718 enum settings_output_devices
719 settings_get_output_routing (enum settings_output_type type)
721 assert (type < SETTINGS_N_OUTPUT_TYPES);
722 return the_settings.output_routing[type] | SETTINGS_DEVICE_UNFILTERED;