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];
68 struct fmt_spec default_format;
75 struct fmt_settings *styles;
77 enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
80 static struct settings the_settings = {
81 INTEGER_NATIVE, /* input_integer_format */
82 FLOAT_NATIVE_DOUBLE, /* input_float_format */
83 INTEGER_NATIVE, /* output_integer_format */
84 FLOAT_NATIVE_DOUBLE, /* output_float_format */
87 false, /* safer_mode */
90 true, /* route_errors_to_terminal */
91 true, /* route_errors_to_listing */
98 100, /* MSG_S_ERROR */
99 100, /* MSG_S_WARNING */
103 true, /* printback */
106 64L * 1024 * 1024, /* workspace */
107 {FMT_F, 8, 2}, /* default_format */
108 false, /* testing_mode */
109 ENHANCED, /* cmd_algorithm */
110 ENHANCED, /* global_algorithm */
111 ENHANCED, /* syntax */
115 {SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
116 SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
118 SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL}
121 /* Initializes the settings module. */
125 settings_set_epoch (-1);
126 the_settings.styles = fmt_settings_create ();
128 settings_set_decimal_char (get_system_decimal ());
131 /* Cleans up the settings module. */
135 settings_destroy (&the_settings);
139 settings_copy (struct settings *dst, const struct settings *src)
142 dst->styles = fmt_settings_clone (src->styles);
145 /* Returns a copy of the current settings. */
149 struct settings *s = xmalloc (sizeof *s);
150 settings_copy (s, &the_settings);
154 /* Replaces the current settings by those in S. The caller retains ownership
157 settings_set (const struct settings *s)
159 settings_destroy (&the_settings);
160 settings_copy (&the_settings, s);
165 settings_destroy (struct settings *s)
169 fmt_settings_destroy (s->styles);
170 if (s != &the_settings)
175 /* Returns the floating-point format used for RB and RBHEX
178 settings_get_input_float_format (void)
180 return the_settings.input_float_format;
183 /* Sets the floating-point format used for RB and RBHEX input to
186 settings_set_input_float_format ( enum float_format format)
188 the_settings.input_float_format = format;
191 /* Returns the integer format used for IB and PIB input. */
193 settings_get_input_integer_format (void)
195 return the_settings.input_integer_format;
198 /* Sets the integer format used for IB and PIB input to
201 settings_set_input_integer_format ( enum integer_format format)
203 the_settings.input_integer_format = format;
206 /* Returns the current output integer format. */
208 settings_get_output_integer_format (void)
210 return the_settings.output_integer_format;
213 /* Sets the output integer format to INTEGER_FORMAT. */
215 settings_set_output_integer_format (
216 enum integer_format integer_format)
218 the_settings.output_integer_format = integer_format;
221 /* Returns the current output float format. */
223 settings_get_output_float_format (void)
225 return the_settings.output_float_format;
228 /* Sets the output float format to FLOAT_FORMAT. */
230 settings_set_output_float_format ( enum float_format float_format)
232 the_settings.output_float_format = float_format;
235 /* Screen length in lines. */
237 settings_get_viewlength (void)
239 return the_settings.viewlength;
242 /* Sets the view length. */
244 settings_set_viewlength ( int viewlength_)
246 the_settings.viewlength = viewlength_;
251 settings_get_viewwidth(void)
253 return the_settings.viewwidth;
256 /* Sets the screen width. */
258 settings_set_viewwidth ( int viewwidth_)
260 the_settings.viewwidth = viewwidth_;
263 /* Whether PSPP can erase and overwrite files. */
265 settings_get_safer_mode (void)
267 return the_settings.safer_mode;
270 /* Set safer mode. */
272 settings_set_safer_mode (void)
274 the_settings.safer_mode = true;
277 /* If echo is on, whether commands from include files are echoed. */
279 settings_get_include (void)
281 return the_settings.include;
284 /* Set include file echo. */
286 settings_set_include ( bool include)
288 the_settings.include = include;
291 /* What year to use as the start of the epoch. */
293 settings_get_epoch (void)
295 assert (the_settings.epoch >= 0);
297 return the_settings.epoch;
300 /* Sets the year that starts the epoch. */
302 settings_set_epoch ( int epoch)
307 struct tm *tm = localtime (&t);
308 epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
311 the_settings.epoch = epoch;
312 assert (the_settings.epoch >= 0);
315 /* Compress system files by default? */
317 settings_get_scompression (void)
319 return the_settings.scompress;
322 /* Set system file default compression. */
324 settings_set_scompression ( bool scompress)
326 the_settings.scompress = scompress;
329 /* Whether to warn on undefined values in numeric data. */
331 settings_get_undefined (void)
333 return the_settings.undefined;
336 /* Set whether to warn on undefined values. */
338 settings_set_undefined ( bool undefined)
340 the_settings.undefined = undefined;
343 /* The value that blank numeric fields are set to when read in. */
345 settings_get_blanks (void)
347 return the_settings.blanks;
350 /* Set the value that blank numeric fields are set to when read
353 settings_set_blanks ( double blanks)
355 the_settings.blanks = blanks;
358 /* Returns the maximum number of messages to show of the given SEVERITY before
359 aborting. (The value for MSG_S_WARNING is interpreted as maximum number of
360 warnings and errors combined.) */
362 settings_get_max_messages (enum msg_severity severity)
364 assert (severity < MSG_N_SEVERITIES);
365 return the_settings.max_messages[severity];
368 /* Sets the maximum number of messages to show of the given SEVERITY before
369 aborting to MAX. (The value for MSG_S_WARNING is interpreted as maximum
370 number of warnings and errors combined.) In addition, in the case of
371 warnings the special value of zero indicates that no warnings are to be
375 settings_set_max_messages (enum msg_severity severity, int max)
377 assert (severity < MSG_N_SEVERITIES);
379 if (severity == MSG_S_WARNING)
384 _("MXWARNS set to zero. No further warnings will be given even when potentially problematic situations are encountered."));
385 msg_ui_disable_warnings (true);
387 else if ( the_settings.max_messages [MSG_S_WARNING] == 0)
389 msg_ui_disable_warnings (false);
390 the_settings.max_messages[MSG_S_WARNING] = max;
391 msg (MW, _("Warnings re-enabled. %d warnings will be issued before aborting syntax processing."), max);
395 the_settings.max_messages[severity] = max;
398 /* Independent of get_printback, controls whether the commands
399 generated by macro invocations are displayed. */
401 settings_get_mprint (void)
403 return the_settings.mprint;
406 /* Sets whether the commands generated by macro invocations are
409 settings_set_mprint ( bool mprint)
411 the_settings.mprint = mprint;
414 /* Implied limit of unbounded loop. */
416 settings_get_mxloops (void)
418 return the_settings.mxloops;
421 /* Set implied limit of unbounded loop. */
423 settings_set_mxloops ( int mxloops)
425 the_settings.mxloops = mxloops;
428 /* Approximate maximum amount of memory to use for cases, in
431 settings_get_workspace (void)
433 return the_settings.workspace;
436 /* Approximate maximum number of cases to allocate in-core, given
437 that each case has the format given in PROTO. */
439 settings_get_workspace_cases (const struct caseproto *proto)
441 size_t n_cases = settings_get_workspace () / case_get_cost (proto);
442 return MAX (n_cases, 4);
445 /* Set approximate maximum amount of memory to use for cases, in
449 settings_set_workspace ( size_t workspace)
451 the_settings.workspace = workspace;
454 /* Default format for variables created by transformations and by
455 DATA LIST {FREE,LIST}. */
456 const struct fmt_spec *
457 settings_get_format (void)
459 return &the_settings.default_format;
462 /* Set default format for variables created by transformations
463 and by DATA LIST {FREE,LIST}. */
465 settings_set_format ( const struct fmt_spec *default_format)
467 the_settings.default_format = *default_format;
470 /* Are we in testing mode? (e.g. --testing-mode command line
473 settings_get_testing_mode (void)
475 return the_settings.testing_mode;
478 /* Set testing mode. */
480 settings_set_testing_mode ( bool testing_mode)
482 the_settings.testing_mode = testing_mode;
485 /* Return the current algorithm setting */
487 settings_get_algorithm (void)
489 return the_settings.cmd_algorithm;
492 /* Set the algorithm option globally. */
494 settings_set_algorithm (enum behavior_mode mode)
496 the_settings.global_algorithm = the_settings.cmd_algorithm = mode;
499 /* Set the algorithm option for this command only */
501 settings_set_cmd_algorithm ( enum behavior_mode mode)
503 the_settings.cmd_algorithm = mode;
506 /* Unset the algorithm option for this command */
508 unset_cmd_algorithm (void)
510 the_settings.cmd_algorithm = the_settings.global_algorithm;
513 /* Get the current syntax setting */
515 settings_get_syntax (void)
517 return the_settings.syntax;
520 /* Set the syntax option */
522 settings_set_syntax ( enum behavior_mode mode)
524 the_settings.syntax = mode;
529 /* Find the grouping characters in CC_STRING and set CC's
530 grouping and decimal members appropriately. Returns true if
531 successful, false otherwise. */
533 find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
536 int comma_cnt, dot_cnt;
538 /* Count commas and periods. There must be exactly three of
539 one or the other, except that an apostrophe escapes a
540 following comma or period. */
541 comma_cnt = dot_cnt = 0;
542 for (sp = cc_string; *sp; sp++)
547 else if (*sp == '\'' && (sp[1] == '.' || sp[1] == ',' || sp[1] == '\''))
550 if ((comma_cnt == 3) == (dot_cnt == 3))
566 /* Extracts a token from IN into AFFIX, using BUFFER for storage. BUFFER must
567 have at least FMT_STYLE_AFFIX_MAX + 1 bytes of space. Tokens are delimited
568 by GROUPING. The token is truncated to at most FMT_STYLE_AFFIX_MAX bytes,
569 followed by a null terminator. Returns the first character following the
572 extract_cc_token (const char *in, int grouping, struct substring *affix,
573 char buffer[FMT_STYLE_AFFIX_MAX + 1])
577 for (; *in != '\0' && *in != grouping; in++)
579 if (*in == '\'' && in[1] == grouping)
581 if (ofs < FMT_STYLE_AFFIX_MAX)
584 *affix = ss_buffer (buffer, ofs);
591 /* Sets custom currency specifier CC having name CC_NAME ('A' through
592 'E') to correspond to the settings in CC_STRING. */
594 settings_set_cc (const char *cc_string, enum fmt_type type)
596 char a[FMT_STYLE_AFFIX_MAX + 1];
597 char b[FMT_STYLE_AFFIX_MAX + 1];
598 char c[FMT_STYLE_AFFIX_MAX + 1];
599 char d[FMT_STYLE_AFFIX_MAX + 1];
600 struct fmt_number_style cc;
602 assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
604 /* Determine separators. */
605 if (!find_cc_separators (cc_string, &cc))
607 msg (SE, _("%s: Custom currency string `%s' does not contain "
608 "exactly three periods or commas (or it contains both)."),
609 fmt_name (type), cc_string);
613 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_prefix, a);
614 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.prefix, b);
615 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.suffix, c);
616 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_suffix, d);
618 fmt_settings_set_style (the_settings.styles, type, &cc);
623 /* Returns the decimal point character for TYPE. */
625 settings_get_decimal_char (enum fmt_type type)
627 return fmt_settings_get_style (the_settings.styles, type)->decimal;
631 settings_set_decimal_char (char decimal)
633 fmt_settings_set_decimal (the_settings.styles, decimal);
636 /* Returns the number formatting style associated with the given
638 const struct fmt_number_style *
639 settings_get_style (enum fmt_type type)
641 assert (is_fmt_type (type));
642 return fmt_settings_get_style (the_settings.styles, type);
645 /* Returns a string of the form "$#,###.##" according to FMT,
646 which must be of type FMT_DOLLAR. The caller must free the
649 settings_dollar_template (const struct fmt_spec *fmt)
651 struct string str = DS_EMPTY_INITIALIZER;
653 const struct fmt_number_style *fns ;
655 assert (fmt->type == FMT_DOLLAR);
657 fns = fmt_settings_get_style (the_settings.styles, fmt->type);
659 ds_put_byte (&str, '$');
660 for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
662 ds_put_byte (&str, '#');
663 if (--c % 4 == 0 && c > 0)
665 ds_put_byte (&str, fns->grouping);
671 ds_put_byte (&str, fns->decimal);
672 ds_put_byte_multiple (&str, '#', fmt->d);
675 return ds_cstr (&str);
679 settings_set_output_routing (enum settings_output_type type,
680 enum settings_output_devices devices)
682 assert (type < SETTINGS_N_OUTPUT_TYPES);
683 the_settings.output_routing[type] = devices;
686 enum settings_output_devices
687 settings_get_output_routing (enum settings_output_type type)
689 assert (type < SETTINGS_N_OUTPUT_TYPES);
690 return the_settings.output_routing[type] | SETTINGS_DEVICE_UNFILTERED;