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 ();
153 settings_set_decimal_char (get_system_decimal ());
159 fmt_done (the_settings.styles);
163 /* Returns the floating-point format used for RB and RBHEX
166 settings_get_input_float_format (void)
168 return the_settings.input_float_format;
171 /* Sets the floating-point format used for RB and RBHEX input to
174 settings_set_input_float_format ( enum float_format format)
176 the_settings.input_float_format = format;
179 /* Returns the integer format used for IB and PIB input. */
181 settings_get_input_integer_format (void)
183 return the_settings.input_integer_format;
186 /* Sets the integer format used for IB and PIB input to
189 settings_set_input_integer_format ( enum integer_format format)
191 the_settings.input_integer_format = format;
194 /* Returns the current output integer format. */
196 settings_get_output_integer_format (void)
198 return the_settings.output_integer_format;
201 /* Sets the output integer format to INTEGER_FORMAT. */
203 settings_set_output_integer_format (
204 enum integer_format integer_format)
206 the_settings.output_integer_format = integer_format;
209 /* Returns the current output float format. */
211 settings_get_output_float_format (void)
213 return the_settings.output_float_format;
216 /* Sets the output float format to FLOAT_FORMAT. */
218 settings_set_output_float_format ( enum float_format float_format)
220 the_settings.output_float_format = float_format;
223 /* Screen length in lines. */
225 settings_get_viewlength (void)
227 return *the_settings.viewlength;
230 /* Sets the view length. */
232 settings_set_viewlength ( int viewlength_)
234 *the_settings.viewlength = viewlength_;
239 settings_get_viewwidth(void)
241 return *the_settings.viewwidth;
244 /* Sets the screen width. */
246 settings_set_viewwidth ( int viewwidth_)
248 *the_settings.viewwidth = viewwidth_;
252 init_viewport ( int *width, int *length)
254 the_settings.viewwidth = width;
255 the_settings.viewlength = length;
258 /* Whether PSPP can erase and overwrite files. */
260 settings_get_safer_mode (void)
262 return the_settings.safer_mode;
265 /* Set safer mode. */
267 settings_set_safer_mode (void)
269 the_settings.safer_mode = true;
272 /* Echo commands to the listing file/printer? */
274 settings_get_echo (void)
276 return the_settings.do_echo;
281 settings_set_echo ( bool echo)
283 the_settings.do_echo = echo;
286 /* If echo is on, whether commands from include files are echoed. */
288 settings_get_include (void)
290 return the_settings.include;
293 /* Set include file echo. */
295 settings_set_include ( bool include)
297 the_settings.include = include;
300 /* What year to use as the start of the epoch. */
302 settings_get_epoch (void)
304 assert (the_settings.epoch >= 0);
306 return the_settings.epoch;
309 /* Sets the year that starts the epoch. */
311 settings_set_epoch ( int epoch)
316 struct tm *tm = localtime (&t);
317 epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
320 the_settings.epoch = epoch;
321 assert (the_settings.epoch >= 0);
324 /* Does an error stop execution? */
326 settings_get_errorbreak (void)
328 return the_settings.errorbreak;
331 /* Sets whether an error stops execution. */
333 settings_set_errorbreak ( bool errorbreak)
335 the_settings.errorbreak = errorbreak;
338 /* Route error messages to terminal? */
340 settings_get_error_routing_to_terminal (void)
342 return the_settings.route_errors_to_terminal;
345 /* Sets whether error messages should be routed to the
348 settings_set_error_routing_to_terminal ( bool route_to_terminal)
350 the_settings.route_errors_to_terminal = route_to_terminal;
353 /* Route error messages to listing file? */
355 settings_get_error_routing_to_listing (void)
357 return the_settings.route_errors_to_listing;
360 /* Sets whether error messages should be routed to the
363 settings_set_error_routing_to_listing ( bool route_to_listing)
365 the_settings.route_errors_to_listing = route_to_listing;
368 /* Compress system files by default? */
370 settings_get_scompression (void)
372 return the_settings.scompress;
375 /* Set system file default compression. */
377 settings_set_scompression ( bool scompress)
379 the_settings.scompress = scompress;
382 /* Whether to warn on undefined values in numeric data. */
384 settings_get_undefined (void)
386 return the_settings.undefined;
389 /* Set whether to warn on undefined values. */
391 settings_set_undefined ( bool undefined)
393 the_settings.undefined = undefined;
396 /* The value that blank numeric fields are set to when read in. */
398 settings_get_blanks (void)
400 return the_settings.blanks;
403 /* Set the value that blank numeric fields are set to when read
406 settings_set_blanks ( double blanks)
408 the_settings.blanks = blanks;
411 /* Maximum number of warnings + errors. */
413 settings_get_mxwarns (void)
415 return the_settings.mxwarns;
418 /* Sets maximum number of warnings + errors. */
420 settings_set_mxwarns ( int mxwarns)
422 the_settings.mxwarns = mxwarns;
425 /* Maximum number of errors. */
427 settings_get_mxerrs (void)
429 return the_settings.mxerrs;
432 /* Sets maximum number of errors. */
434 settings_set_mxerrs ( int mxerrs)
436 the_settings.mxerrs = mxerrs;
439 /* Whether commands are written to the display. */
441 settings_get_printback (void)
443 return the_settings.printback;
446 /* Sets whether commands are written to the display. */
448 settings_set_printback ( bool printback)
450 the_settings.printback = printback;
453 /* Independent of get_printback, controls whether the commands
454 generated by macro invocations are displayed. */
456 settings_get_mprint (void)
458 return the_settings.mprint;
461 /* Sets whether the commands generated by macro invocations are
464 settings_set_mprint ( bool mprint)
466 the_settings.mprint = mprint;
469 /* Implied limit of unbounded loop. */
471 settings_get_mxloops (void)
473 return the_settings.mxloops;
476 /* Set implied limit of unbounded loop. */
478 settings_set_mxloops ( int mxloops)
480 the_settings.mxloops = mxloops;
483 /* Whether a blank line is a command terminator. */
485 settings_get_nulline (void)
487 return the_settings.nulline;
490 /* Set whether a blank line is a command terminator. */
492 settings_set_nulline ( bool nulline)
494 the_settings.nulline = nulline;
497 /* The character used to terminate commands. */
499 settings_get_endcmd (void)
501 return the_settings.endcmd;
504 /* Set the character used to terminate commands. */
506 settings_set_endcmd ( char endcmd)
508 the_settings.endcmd = endcmd;
511 /* Approximate maximum amount of memory to use for cases, in
514 settings_get_workspace (void)
516 return the_settings.workspace;
519 /* Approximate maximum number of cases to allocate in-core, given
520 that each case contains VALUE_CNT values. */
522 settings_get_workspace_cases (size_t value_cnt)
524 size_t case_size = sizeof (union value) * value_cnt + 4 * sizeof (void *);
525 size_t case_cnt = MAX (settings_get_workspace () / case_size, 4);
529 /* Set approximate maximum amount of memory to use for cases, in
533 settings_set_workspace ( size_t workspace)
535 the_settings.workspace = workspace;
538 /* Default format for variables created by transformations and by
539 DATA LIST {FREE,LIST}. */
540 const struct fmt_spec *
541 settings_get_format (void)
543 return &the_settings.default_format;
546 /* Set default format for variables created by transformations
547 and by DATA LIST {FREE,LIST}. */
549 settings_set_format ( const struct fmt_spec *default_format)
551 the_settings.default_format = *default_format;
554 /* Are we in testing mode? (e.g. --testing-mode command line
557 settings_get_testing_mode (void)
559 return the_settings.testing_mode;
562 /* Set testing mode. */
564 settings_set_testing_mode ( bool testing_mode)
566 the_settings.testing_mode = testing_mode;
569 /* Return the current algorithm setting */
571 settings_get_algorithm (void)
573 return *the_settings.algorithm;
576 /* Set the algorithm option globally. */
578 settings_set_algorithm (enum behavior_mode mode)
580 global_algorithm = mode;
583 /* Set the algorithm option for this command only */
585 settings_set_cmd_algorithm ( enum behavior_mode mode)
587 the_settings.cmd_algorithm = mode;
588 the_settings.algorithm = &the_settings.cmd_algorithm;
591 /* Unset the algorithm option for this command */
593 unset_cmd_algorithm (void)
595 the_settings.algorithm = &global_algorithm;
598 /* Get the current syntax setting */
600 settings_get_syntax (void)
602 return the_settings.syntax;
605 /* Set the syntax option */
607 settings_set_syntax ( enum behavior_mode mode)
609 the_settings.syntax = mode;
614 /* Find the grouping characters in CC_STRING and set CC's
615 grouping and decimal members appropriately. Returns true if
616 successful, false otherwise. */
618 find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
621 int comma_cnt, dot_cnt;
623 /* Count commas and periods. There must be exactly three of
624 one or the other, except that an apostrophe escapes a
625 following comma or period. */
626 comma_cnt = dot_cnt = 0;
627 for (sp = cc_string; *sp; sp++)
632 else if (*sp == '\'' && (sp[1] == '.' || sp[1] == ',' || sp[1] == '\''))
635 if ((comma_cnt == 3) == (dot_cnt == 3))
651 /* Extracts a token from IN into a newly allocated AFFIX. Tokens
652 are delimited by GROUPING. The token is truncated to at most
653 FMT_STYLE_AFFIX_MAX characters. Returns the first character
654 following the token. */
656 extract_cc_token (const char *in, int grouping, struct substring *affix)
659 ss_alloc_uninit (affix, FMT_STYLE_AFFIX_MAX);
660 for (; *in != '\0' && *in != grouping; in++)
662 if (*in == '\'' && in[1] == grouping)
664 if (ofs < FMT_STYLE_AFFIX_MAX)
665 ss_data (*affix)[ofs++] = *in;
675 /* Sets custom currency specifier CC having name CC_NAME ('A' through
676 'E') to correspond to the settings in CC_STRING. */
678 settings_set_cc (const char *cc_string, enum fmt_type type)
680 struct fmt_number_style *cc = &the_settings.styles[type];
682 assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
684 /* Determine separators. */
685 if (!find_cc_separators (cc_string, cc))
687 msg (SE, _("%s: Custom currency string `%s' does not contain "
688 "exactly three periods or commas (or it contains both)."),
689 fmt_name (type), cc_string);
693 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_prefix);
694 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->prefix);
695 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->suffix);
696 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_suffix);
698 fmt_check_style (cc);
703 /* Returns the decimal point character for TYPE. */
705 settings_get_decimal_char (enum fmt_type type)
707 return fmt_get_style (the_settings.styles, type)->decimal;
711 settings_set_decimal_char (char decimal)
713 fmt_set_decimal (the_settings.styles, decimal);
718 /* Returns the number formatting style associated with the given
720 const struct fmt_number_style *
721 settings_get_style (enum fmt_type type)
723 assert (is_fmt_type (type));
724 return &the_settings.styles[type];
728 /* Returns a string of the form "$#,###.##" according to FMT,
729 which must be of type FMT_DOLLAR. The caller must free the
732 settings_dollar_template (const struct fmt_spec *fmt)
734 const struct fmt_number_style *styles = the_settings.styles;
735 struct string str = DS_EMPTY_INITIALIZER;
737 const struct fmt_number_style *fns ;
739 assert (fmt->type == FMT_DOLLAR);
741 fns = fmt_get_style (styles, fmt->type);
743 ds_put_char (&str, '$');
744 for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
746 ds_put_char (&str, '#');
747 if (--c % 4 == 0 && c > 0)
749 ds_put_char (&str, fns->grouping);
755 ds_put_char (&str, fns->decimal);
756 ds_put_char_multiple (&str, '#', fmt->d);
759 return ds_cstr (&str);