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 */
86 NULL, /* viewlength */
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}
124 static void init_viewport ( int *, int *);
127 settings_init (int *width, int *length)
129 init_viewport (width, length);
130 settings_set_epoch (-1);
131 the_settings.styles = fmt_settings_create ();
133 settings_set_decimal_char (get_system_decimal ());
139 fmt_settings_destroy (the_settings.styles);
142 /* Returns the floating-point format used for RB and RBHEX
145 settings_get_input_float_format (void)
147 return the_settings.input_float_format;
150 /* Sets the floating-point format used for RB and RBHEX input to
153 settings_set_input_float_format ( enum float_format format)
155 the_settings.input_float_format = format;
158 /* Returns the integer format used for IB and PIB input. */
160 settings_get_input_integer_format (void)
162 return the_settings.input_integer_format;
165 /* Sets the integer format used for IB and PIB input to
168 settings_set_input_integer_format ( enum integer_format format)
170 the_settings.input_integer_format = format;
173 /* Returns the current output integer format. */
175 settings_get_output_integer_format (void)
177 return the_settings.output_integer_format;
180 /* Sets the output integer format to INTEGER_FORMAT. */
182 settings_set_output_integer_format (
183 enum integer_format integer_format)
185 the_settings.output_integer_format = integer_format;
188 /* Returns the current output float format. */
190 settings_get_output_float_format (void)
192 return the_settings.output_float_format;
195 /* Sets the output float format to FLOAT_FORMAT. */
197 settings_set_output_float_format ( enum float_format float_format)
199 the_settings.output_float_format = float_format;
202 /* Screen length in lines. */
204 settings_get_viewlength (void)
206 return *the_settings.viewlength;
209 /* Sets the view length. */
211 settings_set_viewlength ( int viewlength_)
213 *the_settings.viewlength = viewlength_;
218 settings_get_viewwidth(void)
220 return *the_settings.viewwidth;
223 /* Sets the screen width. */
225 settings_set_viewwidth ( int viewwidth_)
227 *the_settings.viewwidth = viewwidth_;
231 init_viewport ( int *width, int *length)
233 the_settings.viewwidth = width;
234 the_settings.viewlength = length;
237 /* Whether PSPP can erase and overwrite files. */
239 settings_get_safer_mode (void)
241 return the_settings.safer_mode;
244 /* Set safer mode. */
246 settings_set_safer_mode (void)
248 the_settings.safer_mode = true;
251 /* If echo is on, whether commands from include files are echoed. */
253 settings_get_include (void)
255 return the_settings.include;
258 /* Set include file echo. */
260 settings_set_include ( bool include)
262 the_settings.include = include;
265 /* What year to use as the start of the epoch. */
267 settings_get_epoch (void)
269 assert (the_settings.epoch >= 0);
271 return the_settings.epoch;
274 /* Sets the year that starts the epoch. */
276 settings_set_epoch ( int epoch)
281 struct tm *tm = localtime (&t);
282 epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
285 the_settings.epoch = epoch;
286 assert (the_settings.epoch >= 0);
289 /* Compress system files by default? */
291 settings_get_scompression (void)
293 return the_settings.scompress;
296 /* Set system file default compression. */
298 settings_set_scompression ( bool scompress)
300 the_settings.scompress = scompress;
303 /* Whether to warn on undefined values in numeric data. */
305 settings_get_undefined (void)
307 return the_settings.undefined;
310 /* Set whether to warn on undefined values. */
312 settings_set_undefined ( bool undefined)
314 the_settings.undefined = undefined;
317 /* The value that blank numeric fields are set to when read in. */
319 settings_get_blanks (void)
321 return the_settings.blanks;
324 /* Set the value that blank numeric fields are set to when read
327 settings_set_blanks ( double blanks)
329 the_settings.blanks = blanks;
332 /* Returns the maximum number of messages to show of the given SEVERITY before
333 aborting. (The value for MSG_S_WARNING is interpreted as maximum number of
334 warnings and errors combined.) */
336 settings_get_max_messages (enum msg_severity severity)
338 assert (severity < MSG_N_SEVERITIES);
339 return the_settings.max_messages[severity];
342 /* Sets the maximum number of messages to show of the given SEVERITY before
343 aborting to MAX. (The value for MSG_S_WARNING is interpreted as maximum
344 number of warnings and errors combined.) In addition, in the case of
345 warnings the special value of zero indicates that no warnings are to be
349 settings_set_max_messages (enum msg_severity severity, int max)
351 assert (severity < MSG_N_SEVERITIES);
353 if (severity == MSG_S_WARNING)
358 _("MXWARNS set to zero. No further warnings will be given even when potentially problematic situations are encountered."));
359 msg_ui_disable_warnings (true);
361 else if ( the_settings.max_messages [MSG_S_WARNING] == 0)
363 msg_ui_disable_warnings (false);
364 the_settings.max_messages[MSG_S_WARNING] = max;
365 msg (MW, _("Warnings re-enabled. %d warnings will be issued before aborting syntax processing."), max);
369 the_settings.max_messages[severity] = max;
372 /* Independent of get_printback, controls whether the commands
373 generated by macro invocations are displayed. */
375 settings_get_mprint (void)
377 return the_settings.mprint;
380 /* Sets whether the commands generated by macro invocations are
383 settings_set_mprint ( bool mprint)
385 the_settings.mprint = mprint;
388 /* Implied limit of unbounded loop. */
390 settings_get_mxloops (void)
392 return the_settings.mxloops;
395 /* Set implied limit of unbounded loop. */
397 settings_set_mxloops ( int mxloops)
399 the_settings.mxloops = mxloops;
402 /* Whether a blank line is a command terminator. */
404 settings_get_nulline (void)
406 return the_settings.nulline;
409 /* Set whether a blank line is a command terminator. */
411 settings_set_nulline ( bool nulline)
413 the_settings.nulline = nulline;
416 /* The character used to terminate commands. */
418 settings_get_endcmd (void)
420 return the_settings.endcmd;
423 /* Set the character used to terminate commands. */
425 settings_set_endcmd ( char endcmd)
427 the_settings.endcmd = endcmd;
430 /* Approximate maximum amount of memory to use for cases, in
433 settings_get_workspace (void)
435 return the_settings.workspace;
438 /* Approximate maximum number of cases to allocate in-core, given
439 that each case has the format given in PROTO. */
441 settings_get_workspace_cases (const struct caseproto *proto)
443 size_t n_cases = settings_get_workspace () / case_get_cost (proto);
444 return MAX (n_cases, 4);
447 /* Set approximate maximum amount of memory to use for cases, in
451 settings_set_workspace ( size_t workspace)
453 the_settings.workspace = workspace;
456 /* Default format for variables created by transformations and by
457 DATA LIST {FREE,LIST}. */
458 const struct fmt_spec *
459 settings_get_format (void)
461 return &the_settings.default_format;
464 /* Set default format for variables created by transformations
465 and by DATA LIST {FREE,LIST}. */
467 settings_set_format ( const struct fmt_spec *default_format)
469 the_settings.default_format = *default_format;
472 /* Are we in testing mode? (e.g. --testing-mode command line
475 settings_get_testing_mode (void)
477 return the_settings.testing_mode;
480 /* Set testing mode. */
482 settings_set_testing_mode ( bool testing_mode)
484 the_settings.testing_mode = testing_mode;
487 /* Return the current algorithm setting */
489 settings_get_algorithm (void)
491 return *the_settings.algorithm;
494 /* Set the algorithm option globally. */
496 settings_set_algorithm (enum behavior_mode mode)
498 global_algorithm = mode;
501 /* Set the algorithm option for this command only */
503 settings_set_cmd_algorithm ( enum behavior_mode mode)
505 the_settings.cmd_algorithm = mode;
506 the_settings.algorithm = &the_settings.cmd_algorithm;
509 /* Unset the algorithm option for this command */
511 unset_cmd_algorithm (void)
513 the_settings.algorithm = &global_algorithm;
516 /* Get the current syntax setting */
518 settings_get_syntax (void)
520 return the_settings.syntax;
523 /* Set the syntax option */
525 settings_set_syntax ( enum behavior_mode mode)
527 the_settings.syntax = mode;
532 /* Find the grouping characters in CC_STRING and set CC's
533 grouping and decimal members appropriately. Returns true if
534 successful, false otherwise. */
536 find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
539 int comma_cnt, dot_cnt;
541 /* Count commas and periods. There must be exactly three of
542 one or the other, except that an apostrophe escapes a
543 following comma or period. */
544 comma_cnt = dot_cnt = 0;
545 for (sp = cc_string; *sp; sp++)
550 else if (*sp == '\'' && (sp[1] == '.' || sp[1] == ',' || sp[1] == '\''))
553 if ((comma_cnt == 3) == (dot_cnt == 3))
569 /* Extracts a token from IN into AFFIX, using BUFFER for storage. BUFFER must
570 have at least FMT_STYLE_AFFIX_MAX + 1 bytes of space. Tokens are delimited
571 by GROUPING. The token is truncated to at most FMT_STYLE_AFFIX_MAX bytes,
572 followed by a null terminator. Returns the first character following the
575 extract_cc_token (const char *in, int grouping, struct substring *affix,
576 char buffer[FMT_STYLE_AFFIX_MAX + 1])
580 for (; *in != '\0' && *in != grouping; in++)
582 if (*in == '\'' && in[1] == grouping)
584 if (ofs < FMT_STYLE_AFFIX_MAX)
587 *affix = ss_buffer (buffer, ofs);
594 /* Sets custom currency specifier CC having name CC_NAME ('A' through
595 'E') to correspond to the settings in CC_STRING. */
597 settings_set_cc (const char *cc_string, enum fmt_type type)
599 char a[FMT_STYLE_AFFIX_MAX + 1];
600 char b[FMT_STYLE_AFFIX_MAX + 1];
601 char c[FMT_STYLE_AFFIX_MAX + 1];
602 char d[FMT_STYLE_AFFIX_MAX + 1];
603 struct fmt_number_style cc;
605 assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
607 /* Determine separators. */
608 if (!find_cc_separators (cc_string, &cc))
610 msg (SE, _("%s: Custom currency string `%s' does not contain "
611 "exactly three periods or commas (or it contains both)."),
612 fmt_name (type), cc_string);
616 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_prefix, a);
617 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.prefix, b);
618 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.suffix, c);
619 cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_suffix, d);
621 fmt_settings_set_style (the_settings.styles, type, &cc);
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_char (&str, '$');
663 for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
665 ds_put_char (&str, '#');
666 if (--c % 4 == 0 && c > 0)
668 ds_put_char (&str, fns->grouping);
674 ds_put_char (&str, fns->decimal);
675 ds_put_char_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;