1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011 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;
74 struct fmt_settings *styles;
76 enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
78 enum settings_var_style var_output_style;
79 enum settings_value_style value_output_style;
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 */
108 64L * 1024 * 1024, /* workspace */
109 {FMT_F, 8, 2}, /* default_format */
110 false, /* testing_mode */
111 ENHANCED, /* cmd_algorithm */
112 ENHANCED, /* global_algorithm */
113 ENHANCED, /* syntax */
117 {SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
118 SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
120 SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL},
122 SETTINGS_VAR_STYLE_LABELS,
123 SETTINGS_VAL_STYLE_LABELS
126 /* Initializes the settings module. */
130 settings_set_epoch (-1);
131 the_settings.styles = fmt_settings_create ();
133 settings_set_decimal_char (get_system_decimal ());
136 /* Cleans up the settings module. */
140 settings_destroy (&the_settings);
144 settings_copy (struct settings *dst, const struct settings *src)
147 dst->styles = fmt_settings_clone (src->styles);
150 /* Returns a copy of the current settings. */
154 struct settings *s = xmalloc (sizeof *s);
155 settings_copy (s, &the_settings);
159 /* Replaces the current settings by those in S. The caller retains ownership
162 settings_set (const struct settings *s)
164 settings_destroy (&the_settings);
165 settings_copy (&the_settings, s);
170 settings_destroy (struct settings *s)
174 fmt_settings_destroy (s->styles);
175 if (s != &the_settings)
180 /* Returns the floating-point format used for RB and RBHEX
183 settings_get_input_float_format (void)
185 return the_settings.input_float_format;
188 /* Sets the floating-point format used for RB and RBHEX input to
191 settings_set_input_float_format ( enum float_format format)
193 the_settings.input_float_format = format;
196 /* Returns the integer format used for IB and PIB input. */
198 settings_get_input_integer_format (void)
200 return the_settings.input_integer_format;
203 /* Sets the integer format used for IB and PIB input to
206 settings_set_input_integer_format ( enum integer_format format)
208 the_settings.input_integer_format = format;
211 /* Returns the current output integer format. */
213 settings_get_output_integer_format (void)
215 return the_settings.output_integer_format;
218 /* Sets the output integer format to INTEGER_FORMAT. */
220 settings_set_output_integer_format (
221 enum integer_format integer_format)
223 the_settings.output_integer_format = integer_format;
226 /* Returns the current output float format. */
228 settings_get_output_float_format (void)
230 return the_settings.output_float_format;
233 /* Sets the output float format to FLOAT_FORMAT. */
235 settings_set_output_float_format ( enum float_format float_format)
237 the_settings.output_float_format = float_format;
240 /* Screen length in lines. */
242 settings_get_viewlength (void)
244 return the_settings.viewlength;
247 /* Sets the view length. */
249 settings_set_viewlength ( int viewlength_)
251 the_settings.viewlength = viewlength_;
256 settings_get_viewwidth(void)
258 return the_settings.viewwidth;
261 /* Sets the screen width. */
263 settings_set_viewwidth ( int viewwidth_)
265 the_settings.viewwidth = viewwidth_;
268 /* Whether PSPP can erase and overwrite files. */
270 settings_get_safer_mode (void)
272 return the_settings.safer_mode;
275 /* Set safer mode. */
277 settings_set_safer_mode (void)
279 the_settings.safer_mode = true;
282 /* If echo is on, whether commands from include files are echoed. */
284 settings_get_include (void)
286 return the_settings.include;
289 /* Set include file echo. */
291 settings_set_include ( bool include)
293 the_settings.include = include;
296 /* What year to use as the start of the epoch. */
298 settings_get_epoch (void)
300 assert (the_settings.epoch >= 0);
302 return the_settings.epoch;
305 /* Sets the year that starts the epoch. */
307 settings_set_epoch ( int epoch)
312 struct tm *tm = localtime (&t);
313 epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
316 the_settings.epoch = epoch;
317 assert (the_settings.epoch >= 0);
320 /* Compress system files by default? */
322 settings_get_scompression (void)
324 return the_settings.scompress;
327 /* Set system file default compression. */
329 settings_set_scompression ( bool scompress)
331 the_settings.scompress = scompress;
334 /* Whether to warn on undefined values in numeric data. */
336 settings_get_undefined (void)
338 return the_settings.undefined;
341 /* Set whether to warn on undefined values. */
343 settings_set_undefined ( bool undefined)
345 the_settings.undefined = undefined;
348 /* The value that blank numeric fields are set to when read in. */
350 settings_get_blanks (void)
352 return the_settings.blanks;
355 /* Set the value that blank numeric fields are set to when read
358 settings_set_blanks ( double blanks)
360 the_settings.blanks = blanks;
363 /* Returns the maximum number of messages to show of the given SEVERITY before
364 aborting. (The value for MSG_S_WARNING is interpreted as maximum number of
365 warnings and errors combined.) */
367 settings_get_max_messages (enum msg_severity severity)
369 assert (severity < MSG_N_SEVERITIES);
370 return the_settings.max_messages[severity];
373 /* Sets the maximum number of messages to show of the given SEVERITY before
374 aborting to MAX. (The value for MSG_S_WARNING is interpreted as maximum
375 number of warnings and errors combined.) In addition, in the case of
376 warnings the special value of zero indicates that no warnings are to be
380 settings_set_max_messages (enum msg_severity severity, int max)
382 assert (severity < MSG_N_SEVERITIES);
384 if (severity == MSG_S_WARNING)
389 _("MXWARNS set to zero. No further warnings will be given even when potentially problematic situations are encountered."));
390 msg_ui_disable_warnings (true);
392 else if ( the_settings.max_messages [MSG_S_WARNING] == 0)
394 msg_ui_disable_warnings (false);
395 the_settings.max_messages[MSG_S_WARNING] = max;
396 msg (MW, _("Warnings re-enabled. %d warnings will be issued before aborting syntax processing."), max);
400 the_settings.max_messages[severity] = max;
403 /* Independent of get_printback, controls whether the commands
404 generated by macro invocations are displayed. */
406 settings_get_mprint (void)
408 return the_settings.mprint;
411 /* Sets whether the commands generated by macro invocations are
414 settings_set_mprint ( bool mprint)
416 the_settings.mprint = mprint;
419 /* Implied limit of unbounded loop. */
421 settings_get_mxloops (void)
423 return the_settings.mxloops;
426 /* Set implied limit of unbounded loop. */
428 settings_set_mxloops ( int mxloops)
430 the_settings.mxloops = mxloops;
433 /* Approximate maximum amount of memory to use for cases, in
436 settings_get_workspace (void)
438 return the_settings.workspace;
441 /* Approximate maximum number of cases to allocate in-core, given
442 that each case has the format given in PROTO. */
444 settings_get_workspace_cases (const struct caseproto *proto)
446 size_t n_cases = settings_get_workspace () / case_get_cost (proto);
447 return MAX (n_cases, 4);
450 /* Set approximate maximum amount of memory to use for cases, in
454 settings_set_workspace (size_t workspace)
456 the_settings.workspace = workspace;
459 /* Default format for variables created by transformations and by
460 DATA LIST {FREE,LIST}. */
461 const struct fmt_spec *
462 settings_get_format (void)
464 return &the_settings.default_format;
467 /* Set default format for variables created by transformations
468 and by DATA LIST {FREE,LIST}. */
470 settings_set_format ( const struct fmt_spec *default_format)
472 the_settings.default_format = *default_format;
475 /* Are we in testing mode? (e.g. --testing-mode command line
478 settings_get_testing_mode (void)
480 return the_settings.testing_mode;
483 /* Set testing mode. */
485 settings_set_testing_mode ( bool testing_mode)
487 the_settings.testing_mode = testing_mode;
490 /* Return the current algorithm setting */
492 settings_get_algorithm (void)
494 return the_settings.cmd_algorithm;
497 /* Set the algorithm option globally. */
499 settings_set_algorithm (enum behavior_mode mode)
501 the_settings.global_algorithm = the_settings.cmd_algorithm = mode;
504 /* Set the algorithm option for this command only */
506 settings_set_cmd_algorithm ( enum behavior_mode mode)
508 the_settings.cmd_algorithm = mode;
511 /* Unset the algorithm option for this command */
513 unset_cmd_algorithm (void)
515 the_settings.cmd_algorithm = the_settings.global_algorithm;
518 /* Get the current syntax setting */
520 settings_get_syntax (void)
522 return the_settings.syntax;
525 /* Set the syntax option */
527 settings_set_syntax ( enum behavior_mode mode)
529 the_settings.syntax = mode;
534 /* Find the grouping characters in CC_STRING and sets *GROUPING and *DECIMAL
535 appropriately. Returns true if successful, false otherwise. */
537 find_cc_separators (const char *cc_string, char *decimal, char *grouping)
540 int comma_cnt, dot_cnt;
542 /* Count commas and periods. There must be exactly three of
543 one or the other, except that an apostrophe escapes a
544 following comma or period. */
545 comma_cnt = dot_cnt = 0;
546 for (sp = cc_string; *sp; sp++)
551 else if (*sp == '\'' && (sp[1] == '.' || sp[1] == ',' || sp[1] == '\''))
554 if ((comma_cnt == 3) == (dot_cnt == 3))
570 /* Extracts a token from IN into a newly allocated string AFFIXP. Tokens are
571 delimited by GROUPING. Returns the first character following the token. */
573 extract_cc_token (const char *in, int grouping, char **affixp)
577 out = *affixp = xmalloc (strlen (in) + 1);
578 for (; *in != '\0' && *in != grouping; in++)
580 if (*in == '\'' && in[1] == grouping)
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 *neg_prefix, *prefix, *suffix, *neg_suffix;
597 char decimal, grouping;
599 assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
601 /* Determine separators. */
602 if (!find_cc_separators (cc_string, &decimal, &grouping))
604 msg (SE, _("%s: Custom currency string `%s' does not contain "
605 "exactly three periods or commas (or it contains both)."),
606 fmt_name (type), cc_string);
610 cc_string = extract_cc_token (cc_string, grouping, &neg_prefix);
611 cc_string = extract_cc_token (cc_string, grouping, &prefix);
612 cc_string = extract_cc_token (cc_string, grouping, &suffix);
613 cc_string = extract_cc_token (cc_string, grouping, &neg_suffix);
615 fmt_settings_set_style (the_settings.styles, type, decimal, grouping,
616 neg_prefix, prefix, suffix, neg_suffix);
626 /* Returns the decimal point character for TYPE. */
628 settings_get_decimal_char (enum fmt_type type)
630 return fmt_settings_get_style (the_settings.styles, type)->decimal;
634 settings_set_decimal_char (char decimal)
636 fmt_settings_set_decimal (the_settings.styles, decimal);
639 /* Returns the number formatting style associated with the given
641 const struct fmt_number_style *
642 settings_get_style (enum fmt_type type)
644 assert (is_fmt_type (type));
645 return fmt_settings_get_style (the_settings.styles, type);
648 /* Returns a string of the form "$#,###.##" according to FMT,
649 which must be of type FMT_DOLLAR. The caller must free the
652 settings_dollar_template (const struct fmt_spec *fmt)
654 struct string str = DS_EMPTY_INITIALIZER;
656 const struct fmt_number_style *fns ;
658 assert (fmt->type == FMT_DOLLAR);
660 fns = fmt_settings_get_style (the_settings.styles, fmt->type);
662 ds_put_byte (&str, '$');
663 for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
665 ds_put_byte (&str, '#');
666 if (--c % 4 == 0 && c > 0)
668 ds_put_byte (&str, fns->grouping);
674 ds_put_byte (&str, fns->decimal);
675 ds_put_byte_multiple (&str, '#', fmt->d);
678 return ds_cstr (&str);
682 settings_set_output_routing (enum settings_output_type type,
683 enum settings_output_devices devices)
685 assert (type < SETTINGS_N_OUTPUT_TYPES);
686 the_settings.output_routing[type] = devices;
689 enum settings_output_devices
690 settings_get_output_routing (enum settings_output_type type)
692 assert (type < SETTINGS_N_OUTPUT_TYPES);
693 return the_settings.output_routing[type] | SETTINGS_DEVICE_UNFILTERED;
696 enum settings_value_style
697 settings_get_value_style (void)
699 return the_settings.value_output_style;
703 settings_set_value_style (enum settings_value_style s)
705 the_settings.value_output_style = s;
710 enum settings_var_style
711 settings_get_var_style (void)
713 return the_settings.var_output_style;
718 settings_set_var_style (enum settings_var_style s)
720 the_settings.var_output_style = s;