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/>. */
25 #include <data/case.h>
26 #include <libpspp/i18n.h>
27 #include <libpspp/integer-format.h>
28 #include <libpspp/message.h>
34 #define _(msgid) gettext (msgid)
36 static int global_algorithm = ENHANCED;
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];
69 struct fmt_spec default_format;
76 struct fmt_settings *styles;
78 enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
81 static struct settings the_settings = {
82 INTEGER_NATIVE, /* input_integer_format */
83 FLOAT_NATIVE_DOUBLE, /* input_float_format */
84 INTEGER_NATIVE, /* output_integer_format */
85 FLOAT_NATIVE_DOUBLE, /* output_float_format */
88 false, /* safer_mode */
91 true, /* route_errors_to_terminal */
92 true, /* route_errors_to_listing */
99 100, /* MSG_S_ERROR */
100 100, /* MSG_S_WARNING */
104 true, /* printback */
109 64L * 1024 * 1024, /* workspace */
110 {FMT_F, 8, 2}, /* default_format */
111 false, /* testing_mode */
112 ENHANCED, /* cmd_algorithm */
113 &global_algorithm, /* algorithm */
114 ENHANCED, /* syntax */
118 {SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
119 SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
121 SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL}
127 settings_set_epoch (-1);
128 the_settings.styles = fmt_settings_create ();
130 settings_set_decimal_char (get_system_decimal ());
136 fmt_settings_destroy (the_settings.styles);
139 /* Returns the floating-point format used for RB and RBHEX
142 settings_get_input_float_format (void)
144 return the_settings.input_float_format;
147 /* Sets the floating-point format used for RB and RBHEX input to
150 settings_set_input_float_format ( enum float_format format)
152 the_settings.input_float_format = format;
155 /* Returns the integer format used for IB and PIB input. */
157 settings_get_input_integer_format (void)
159 return the_settings.input_integer_format;
162 /* Sets the integer format used for IB and PIB input to
165 settings_set_input_integer_format ( enum integer_format format)
167 the_settings.input_integer_format = format;
170 /* Returns the current output integer format. */
172 settings_get_output_integer_format (void)
174 return the_settings.output_integer_format;
177 /* Sets the output integer format to INTEGER_FORMAT. */
179 settings_set_output_integer_format (
180 enum integer_format integer_format)
182 the_settings.output_integer_format = integer_format;
185 /* Returns the current output float format. */
187 settings_get_output_float_format (void)
189 return the_settings.output_float_format;
192 /* Sets the output float format to FLOAT_FORMAT. */
194 settings_set_output_float_format ( enum float_format float_format)
196 the_settings.output_float_format = float_format;
199 /* Screen length in lines. */
201 settings_get_viewlength (void)
203 return the_settings.viewlength;
206 /* Sets the view length. */
208 settings_set_viewlength ( int viewlength_)
210 the_settings.viewlength = viewlength_;
215 settings_get_viewwidth(void)
217 return the_settings.viewwidth;
220 /* Sets the screen width. */
222 settings_set_viewwidth ( int viewwidth_)
224 the_settings.viewwidth = viewwidth_;
227 /* Whether PSPP can erase and overwrite files. */
229 settings_get_safer_mode (void)
231 return the_settings.safer_mode;
234 /* Set safer mode. */
236 settings_set_safer_mode (void)
238 the_settings.safer_mode = true;
241 /* If echo is on, whether commands from include files are echoed. */
243 settings_get_include (void)
245 return the_settings.include;
248 /* Set include file echo. */
250 settings_set_include ( bool include)
252 the_settings.include = include;
255 /* What year to use as the start of the epoch. */
257 settings_get_epoch (void)
259 assert (the_settings.epoch >= 0);
261 return the_settings.epoch;
264 /* Sets the year that starts the epoch. */
266 settings_set_epoch ( int epoch)
271 struct tm *tm = localtime (&t);
272 epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
275 the_settings.epoch = epoch;
276 assert (the_settings.epoch >= 0);
279 /* Compress system files by default? */
281 settings_get_scompression (void)
283 return the_settings.scompress;
286 /* Set system file default compression. */
288 settings_set_scompression ( bool scompress)
290 the_settings.scompress = scompress;
293 /* Whether to warn on undefined values in numeric data. */
295 settings_get_undefined (void)
297 return the_settings.undefined;
300 /* Set whether to warn on undefined values. */
302 settings_set_undefined ( bool undefined)
304 the_settings.undefined = undefined;
307 /* The value that blank numeric fields are set to when read in. */
309 settings_get_blanks (void)
311 return the_settings.blanks;
314 /* Set the value that blank numeric fields are set to when read
317 settings_set_blanks ( double blanks)
319 the_settings.blanks = blanks;
322 /* Returns the maximum number of messages to show of the given SEVERITY before
323 aborting. (The value for MSG_S_WARNING is interpreted as maximum number of
324 warnings and errors combined.) */
326 settings_get_max_messages (enum msg_severity severity)
328 assert (severity < MSG_N_SEVERITIES);
329 return the_settings.max_messages[severity];
332 /* Sets the maximum number of messages to show of the given SEVERITY before
333 aborting to MAX. (The value for MSG_S_WARNING is interpreted as maximum
334 number of warnings and errors combined.) In addition, in the case of
335 warnings the special value of zero indicates that no warnings are to be
339 settings_set_max_messages (enum msg_severity severity, int max)
341 assert (severity < MSG_N_SEVERITIES);
343 if (severity == MSG_S_WARNING)
348 _("MXWARNS set to zero. No further warnings will be given even when potentially problematic situations are encountered."));
349 msg_ui_disable_warnings (true);
351 else if ( the_settings.max_messages [MSG_S_WARNING] == 0)
353 msg_ui_disable_warnings (false);
354 the_settings.max_messages[MSG_S_WARNING] = max;
355 msg (MW, _("Warnings re-enabled. %d warnings will be issued before aborting syntax processing."), max);
359 the_settings.max_messages[severity] = max;
362 /* Independent of get_printback, controls whether the commands
363 generated by macro invocations are displayed. */
365 settings_get_mprint (void)
367 return the_settings.mprint;
370 /* Sets whether the commands generated by macro invocations are
373 settings_set_mprint ( bool mprint)
375 the_settings.mprint = mprint;
378 /* Implied limit of unbounded loop. */
380 settings_get_mxloops (void)
382 return the_settings.mxloops;
385 /* Set implied limit of unbounded loop. */
387 settings_set_mxloops ( int mxloops)
389 the_settings.mxloops = mxloops;
392 /* Whether a blank line is a command terminator. */
394 settings_get_nulline (void)
396 return the_settings.nulline;
399 /* Set whether a blank line is a command terminator. */
401 settings_set_nulline ( bool nulline)
403 the_settings.nulline = nulline;
406 /* The character used to terminate commands. */
408 settings_get_endcmd (void)
410 return the_settings.endcmd;
413 /* Set the character used to terminate commands. */
415 settings_set_endcmd ( char endcmd)
417 the_settings.endcmd = endcmd;
420 /* Approximate maximum amount of memory to use for cases, in
423 settings_get_workspace (void)
425 return the_settings.workspace;
428 /* Approximate maximum number of cases to allocate in-core, given
429 that each case has the format given in PROTO. */
431 settings_get_workspace_cases (const struct caseproto *proto)
433 size_t n_cases = settings_get_workspace () / case_get_cost (proto);
434 return MAX (n_cases, 4);
437 /* Set approximate maximum amount of memory to use for cases, in
441 settings_set_workspace ( size_t workspace)
443 the_settings.workspace = workspace;
446 /* Default format for variables created by transformations and by
447 DATA LIST {FREE,LIST}. */
448 const struct fmt_spec *
449 settings_get_format (void)
451 return &the_settings.default_format;
454 /* Set default format for variables created by transformations
455 and by DATA LIST {FREE,LIST}. */
457 settings_set_format ( const struct fmt_spec *default_format)
459 the_settings.default_format = *default_format;
462 /* Are we in testing mode? (e.g. --testing-mode command line
465 settings_get_testing_mode (void)
467 return the_settings.testing_mode;
470 /* Set testing mode. */
472 settings_set_testing_mode ( bool testing_mode)
474 the_settings.testing_mode = testing_mode;
477 /* Return the current algorithm setting */
479 settings_get_algorithm (void)
481 return *the_settings.algorithm;
484 /* Set the algorithm option globally. */
486 settings_set_algorithm (enum behavior_mode mode)
488 global_algorithm = mode;
491 /* Set the algorithm option for this command only */
493 settings_set_cmd_algorithm ( enum behavior_mode mode)
495 the_settings.cmd_algorithm = mode;
496 the_settings.algorithm = &the_settings.cmd_algorithm;
499 /* Unset the algorithm option for this command */
501 unset_cmd_algorithm (void)
503 the_settings.algorithm = &global_algorithm;
506 /* Get the current syntax setting */
508 settings_get_syntax (void)
510 return the_settings.syntax;
513 /* Set the syntax option */
515 settings_set_syntax ( enum behavior_mode mode)
517 the_settings.syntax = mode;
522 /* Find the grouping characters in CC_STRING and set CC's
523 grouping and decimal members appropriately. Returns true if
524 successful, false otherwise. */
526 find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
529 int comma_cnt, dot_cnt;
531 /* Count commas and periods. There must be exactly three of
532 one or the other, except that an apostrophe escapes a
533 following comma or period. */
534 comma_cnt = dot_cnt = 0;
535 for (sp = cc_string; *sp; sp++)
540 else if (*sp == '\'' && (sp[1] == '.' || sp[1] == ',' || sp[1] == '\''))
543 if ((comma_cnt == 3) == (dot_cnt == 3))
559 /* Extracts a token from IN into AFFIX, using BUFFER for storage. BUFFER must
560 have at least FMT_STYLE_AFFIX_MAX + 1 bytes of space. Tokens are delimited
561 by GROUPING. The token is truncated to at most FMT_STYLE_AFFIX_MAX bytes,
562 followed by a null terminator. Returns the first character following the
565 extract_cc_token (const char *in, int grouping, struct substring *affix,
566 char buffer[FMT_STYLE_AFFIX_MAX + 1])
570 for (; *in != '\0' && *in != grouping; in++)
572 if (*in == '\'' && in[1] == grouping)
574 if (ofs < FMT_STYLE_AFFIX_MAX)
577 *affix = ss_buffer (buffer, ofs);
584 /* Sets custom currency specifier CC having name CC_NAME ('A' through
585 'E') to correspond to the settings in CC_STRING. */
587 settings_set_cc (const char *cc_string, enum fmt_type type)
589 char a[FMT_STYLE_AFFIX_MAX + 1];
590 char b[FMT_STYLE_AFFIX_MAX + 1];
591 char c[FMT_STYLE_AFFIX_MAX + 1];
592 char d[FMT_STYLE_AFFIX_MAX + 1];
593 struct fmt_number_style cc;
595 assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
597 /* Determine separators. */
598 if (!find_cc_separators (cc_string, &cc))
600 msg (SE, _("%s: Custom currency string `%s' does not contain "
601 "exactly three periods or commas (or it contains both)."),
602 fmt_name (type), cc_string);
606 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_prefix, a);
607 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.prefix, b);
608 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.suffix, c);
609 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_suffix, d);
611 fmt_settings_set_style (the_settings.styles, type, &cc);
616 /* Returns the decimal point character for TYPE. */
618 settings_get_decimal_char (enum fmt_type type)
620 return fmt_settings_get_style (the_settings.styles, type)->decimal;
624 settings_set_decimal_char (char decimal)
626 fmt_settings_set_decimal (the_settings.styles, decimal);
629 /* Returns the number formatting style associated with the given
631 const struct fmt_number_style *
632 settings_get_style (enum fmt_type type)
634 assert (is_fmt_type (type));
635 return fmt_settings_get_style (the_settings.styles, type);
638 /* Returns a string of the form "$#,###.##" according to FMT,
639 which must be of type FMT_DOLLAR. The caller must free the
642 settings_dollar_template (const struct fmt_spec *fmt)
644 struct string str = DS_EMPTY_INITIALIZER;
646 const struct fmt_number_style *fns ;
648 assert (fmt->type == FMT_DOLLAR);
650 fns = fmt_settings_get_style (the_settings.styles, fmt->type);
652 ds_put_char (&str, '$');
653 for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
655 ds_put_char (&str, '#');
656 if (--c % 4 == 0 && c > 0)
658 ds_put_char (&str, fns->grouping);
664 ds_put_char (&str, fns->decimal);
665 ds_put_char_multiple (&str, '#', fmt->d);
668 return ds_cstr (&str);
672 settings_set_output_routing (enum settings_output_type type,
673 enum settings_output_devices devices)
675 assert (type < SETTINGS_N_OUTPUT_TYPES);
676 the_settings.output_routing[type] = devices;
679 enum settings_output_devices
680 settings_get_output_routing (enum settings_output_type type)
682 assert (type < SETTINGS_N_OUTPUT_TYPES);
683 return the_settings.output_routing[type] | SETTINGS_DEVICE_UNFILTERED;