1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2007 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 <libpspp/i18n.h>
26 #include <libpspp/integer-format.h>
27 #include <libpspp/message.h>
32 #define _(msgid) gettext (msgid)
34 static int global_algorithm = ENHANCED;
38 /* Integer format used for IB and PIB input. */
39 enum integer_format input_integer_format;
41 /* Floating-point format used for RB and RBHEX input. */
42 enum float_format input_float_format;
44 /* Format of integers in output (SET WIB). */
45 enum integer_format output_integer_format;
47 /* Format of reals in output (SET WRB). */
48 enum float_format output_float_format;
57 bool route_errors_to_terminal;
58 bool route_errors_to_listing;
70 struct fmt_spec default_format;
77 struct fmt_number_style *styles;
80 static struct settings the_settings = {
81 /* input_integer_format */
83 /* input_float_format */
85 /* output_integer_format */
87 /* output_float_format */
103 /* route_errors_to_terminal */
105 /* route_errors_to_listing */
143 static void init_viewport ( int *, int *);
146 settings_init (int *width, int *length)
148 init_viewport (width, length);
149 settings_set_epoch (-1);
151 the_settings.styles = fmt_create ();
157 fmt_done (the_settings.styles);
161 /* Returns the floating-point format used for RB and RBHEX
164 settings_get_input_float_format (void)
166 return the_settings.input_float_format;
169 /* Sets the floating-point format used for RB and RBHEX input to
172 settings_set_input_float_format ( enum float_format format)
174 the_settings.input_float_format = format;
177 /* Returns the integer format used for IB and PIB input. */
179 settings_get_input_integer_format (void)
181 return the_settings.input_integer_format;
184 /* Sets the integer format used for IB and PIB input to
187 settings_set_input_integer_format ( enum integer_format format)
189 the_settings.input_integer_format = format;
192 /* Returns the current output integer format. */
194 settings_get_output_integer_format (void)
196 return the_settings.output_integer_format;
199 /* Sets the output integer format to INTEGER_FORMAT. */
201 settings_set_output_integer_format (
202 enum integer_format integer_format)
204 the_settings.output_integer_format = integer_format;
207 /* Returns the current output float format. */
209 settings_get_output_float_format (void)
211 return the_settings.output_float_format;
214 /* Sets the output float format to FLOAT_FORMAT. */
216 settings_set_output_float_format ( enum float_format float_format)
218 the_settings.output_float_format = float_format;
221 /* Screen length in lines. */
223 settings_get_viewlength (void)
225 return *the_settings.viewlength;
228 /* Sets the view length. */
230 settings_set_viewlength ( int viewlength_)
232 *the_settings.viewlength = viewlength_;
237 settings_get_viewwidth(void)
239 return *the_settings.viewwidth;
242 /* Sets the screen width. */
244 settings_set_viewwidth ( int viewwidth_)
246 *the_settings.viewwidth = viewwidth_;
250 init_viewport ( int *width, int *length)
252 the_settings.viewwidth = width;
253 the_settings.viewlength = length;
256 /* Whether PSPP can erase and overwrite files. */
258 settings_get_safer_mode (void)
260 return the_settings.safer_mode;
263 /* Set safer mode. */
265 settings_set_safer_mode (void)
267 the_settings.safer_mode = true;
270 /* Echo commands to the listing file/printer? */
272 settings_get_echo (void)
274 return the_settings.do_echo;
279 settings_set_echo ( bool echo)
281 the_settings.do_echo = echo;
284 /* If echo is on, whether commands from include files are echoed. */
286 settings_get_include (void)
288 return the_settings.include;
291 /* Set include file echo. */
293 settings_set_include ( bool include)
295 the_settings.include = include;
298 /* What year to use as the start of the epoch. */
300 settings_get_epoch (void)
302 assert (the_settings.epoch >= 0);
304 return the_settings.epoch;
307 /* Sets the year that starts the epoch. */
309 settings_set_epoch ( int epoch)
314 struct tm *tm = localtime (&t);
315 epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
318 the_settings.epoch = epoch;
319 assert (the_settings.epoch >= 0);
322 /* Does an error stop execution? */
324 settings_get_errorbreak (void)
326 return the_settings.errorbreak;
329 /* Sets whether an error stops execution. */
331 settings_set_errorbreak ( bool errorbreak)
333 the_settings.errorbreak = errorbreak;
336 /* Route error messages to terminal? */
338 settings_get_error_routing_to_terminal (void)
340 return the_settings.route_errors_to_terminal;
343 /* Sets whether error messages should be routed to the
346 settings_set_error_routing_to_terminal ( bool route_to_terminal)
348 the_settings.route_errors_to_terminal = route_to_terminal;
351 /* Route error messages to listing file? */
353 settings_get_error_routing_to_listing (void)
355 return the_settings.route_errors_to_listing;
358 /* Sets whether error messages should be routed to the
361 settings_set_error_routing_to_listing ( bool route_to_listing)
363 the_settings.route_errors_to_listing = route_to_listing;
366 /* Compress system files by default? */
368 settings_get_scompression (void)
370 return the_settings.scompress;
373 /* Set system file default compression. */
375 settings_set_scompression ( bool scompress)
377 the_settings.scompress = scompress;
380 /* Whether to warn on undefined values in numeric data. */
382 settings_get_undefined (void)
384 return the_settings.undefined;
387 /* Set whether to warn on undefined values. */
389 settings_set_undefined ( bool undefined)
391 the_settings.undefined = undefined;
394 /* The value that blank numeric fields are set to when read in. */
396 settings_get_blanks (void)
398 return the_settings.blanks;
401 /* Set the value that blank numeric fields are set to when read
404 settings_set_blanks ( double blanks)
406 the_settings.blanks = blanks;
409 /* Maximum number of warnings + errors. */
411 settings_get_mxwarns (void)
413 return the_settings.mxwarns;
416 /* Sets maximum number of warnings + errors. */
418 settings_set_mxwarns ( int mxwarns)
420 the_settings.mxwarns = mxwarns;
423 /* Maximum number of errors. */
425 settings_get_mxerrs (void)
427 return the_settings.mxerrs;
430 /* Sets maximum number of errors. */
432 settings_set_mxerrs ( int mxerrs)
434 the_settings.mxerrs = mxerrs;
437 /* Whether commands are written to the display. */
439 settings_get_printback (void)
441 return the_settings.printback;
444 /* Sets whether commands are written to the display. */
446 settings_set_printback ( bool printback)
448 the_settings.printback = printback;
451 /* Independent of get_printback, controls whether the commands
452 generated by macro invocations are displayed. */
454 settings_get_mprint (void)
456 return the_settings.mprint;
459 /* Sets whether the commands generated by macro invocations are
462 settings_set_mprint ( bool mprint)
464 the_settings.mprint = mprint;
467 /* Implied limit of unbounded loop. */
469 settings_get_mxloops (void)
471 return the_settings.mxloops;
474 /* Set implied limit of unbounded loop. */
476 settings_set_mxloops ( int mxloops)
478 the_settings.mxloops = mxloops;
481 /* Whether a blank line is a command terminator. */
483 settings_get_nulline (void)
485 return the_settings.nulline;
488 /* Set whether a blank line is a command terminator. */
490 settings_set_nulline ( bool nulline)
492 the_settings.nulline = nulline;
495 /* The character used to terminate commands. */
497 settings_get_endcmd (void)
499 return the_settings.endcmd;
502 /* Set the character used to terminate commands. */
504 settings_set_endcmd ( char endcmd)
506 the_settings.endcmd = endcmd;
509 /* Approximate maximum amount of memory to use for cases, in
512 settings_get_workspace (void)
514 return the_settings.workspace;
517 /* Approximate maximum number of cases to allocate in-core, given
518 that each case contains VALUE_CNT values. */
520 settings_get_workspace_cases (size_t value_cnt)
522 size_t case_size = sizeof (union value) * value_cnt + 4 * sizeof (void *);
523 size_t case_cnt = MAX (settings_get_workspace () / case_size, 4);
527 /* Set approximate maximum amount of memory to use for cases, in
531 settings_set_workspace ( size_t workspace)
533 the_settings.workspace = workspace;
536 /* Default format for variables created by transformations and by
537 DATA LIST {FREE,LIST}. */
538 const struct fmt_spec *
539 settings_get_format (void)
541 return &the_settings.default_format;
544 /* Set default format for variables created by transformations
545 and by DATA LIST {FREE,LIST}. */
547 settings_set_format ( const struct fmt_spec *default_format)
549 the_settings.default_format = *default_format;
552 /* Are we in testing mode? (e.g. --testing-mode command line
555 settings_get_testing_mode (void)
557 return the_settings.testing_mode;
560 /* Set testing mode. */
562 settings_set_testing_mode ( bool testing_mode)
564 the_settings.testing_mode = testing_mode;
567 /* Return the current algorithm setting */
569 settings_get_algorithm (void)
571 return *the_settings.algorithm;
574 /* Set the algorithm option globally. */
576 settings_set_algorithm (enum behavior_mode mode)
578 global_algorithm = mode;
581 /* Set the algorithm option for this command only */
583 settings_set_cmd_algorithm ( enum behavior_mode mode)
585 the_settings.cmd_algorithm = mode;
586 the_settings.algorithm = &the_settings.cmd_algorithm;
589 /* Unset the algorithm option for this command */
591 unset_cmd_algorithm (void)
593 the_settings.algorithm = &global_algorithm;
596 /* Get the current syntax setting */
598 settings_get_syntax (void)
600 return the_settings.syntax;
603 /* Set the syntax option */
605 settings_set_syntax ( enum behavior_mode mode)
607 the_settings.syntax = mode;
612 /* Find the grouping characters in CC_STRING and set CC's
613 grouping and decimal members appropriately. Returns true if
614 successful, false otherwise. */
616 find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
619 int comma_cnt, dot_cnt;
621 /* Count commas and periods. There must be exactly three of
622 one or the other, except that an apostrophe escapes a
623 following comma or period. */
624 comma_cnt = dot_cnt = 0;
625 for (sp = cc_string; *sp; sp++)
630 else if (*sp == '\'' && (sp[1] == '.' || sp[1] == ',' || sp[1] == '\''))
633 if ((comma_cnt == 3) == (dot_cnt == 3))
649 /* Extracts a token from IN into a newly allocated AFFIX. Tokens
650 are delimited by GROUPING. The token is truncated to at most
651 FMT_STYLE_AFFIX_MAX characters. Returns the first character
652 following the token. */
654 extract_cc_token (const char *in, int grouping, struct substring *affix)
657 ss_alloc_uninit (affix, FMT_STYLE_AFFIX_MAX);
658 for (; *in != '\0' && *in != grouping; in++)
660 if (*in == '\'' && in[1] == grouping)
662 if (ofs < FMT_STYLE_AFFIX_MAX)
663 ss_data (*affix)[ofs++] = *in;
673 /* Sets custom currency specifier CC having name CC_NAME ('A' through
674 'E') to correspond to the settings in CC_STRING. */
676 settings_set_cc (const char *cc_string, enum fmt_type type)
678 struct fmt_number_style *cc = &the_settings.styles[type];
680 assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
682 /* Determine separators. */
683 if (!find_cc_separators (cc_string, cc))
685 msg (SE, _("%s: Custom currency string `%s' does not contain "
686 "exactly three periods or commas (or it contains both)."),
687 fmt_name (type), cc_string);
691 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_prefix);
692 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->prefix);
693 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->suffix);
694 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_suffix);
696 fmt_check_style (cc);
701 /* Returns the decimal point character for TYPE. */
703 settings_get_decimal_char (enum fmt_type type)
705 return fmt_get_style (the_settings.styles, type)->decimal;
709 settings_set_decimal_char (char decimal)
711 fmt_set_decimal (the_settings.styles, decimal);
716 /* Returns the number formatting style associated with the given
718 const struct fmt_number_style *
719 settings_get_style (enum fmt_type type)
721 assert (is_fmt_type (type));
722 return &the_settings.styles[type];
726 /* Returns a string of the form "$#,###.##" according to FMT,
727 which must be of type FMT_DOLLAR. The caller must free the
730 settings_dollar_template (const struct fmt_spec *fmt)
732 const struct fmt_number_style *styles = the_settings.styles;
733 struct string str = DS_EMPTY_INITIALIZER;
735 const struct fmt_number_style *fns ;
737 assert (fmt->type == FMT_DOLLAR);
739 fns = fmt_get_style (styles, fmt->type);
741 ds_put_char (&str, '$');
742 for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
744 ds_put_char (&str, '#');
745 if (--c % 4 == 0 && c > 0)
747 ds_put_char (&str, fns->grouping);
753 ds_put_char (&str, fns->decimal);
754 ds_put_char_multiple (&str, '#', fmt->d);
757 return ds_cstr (&str);