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/integer-format.h>
26 #include <libpspp/message.h>
31 #define _(msgid) gettext (msgid)
33 static int global_algorithm = ENHANCED;
37 /* Integer format used for IB and PIB input. */
38 enum integer_format input_integer_format;
40 /* Floating-point format used for RB and RBHEX input. */
41 enum float_format input_float_format;
43 /* Format of integers in output (SET WIB). */
44 enum integer_format output_integer_format;
46 /* Format of reals in output (SET WRB). */
47 enum float_format output_float_format;
56 bool route_errors_to_terminal;
57 bool route_errors_to_listing;
69 struct fmt_spec default_format;
76 struct fmt_number_style *styles;
79 static struct settings the_settings = {
80 /* input_integer_format */
82 /* input_float_format */
84 /* output_integer_format */
86 /* output_float_format */
102 /* route_errors_to_terminal */
104 /* route_errors_to_listing */
142 static void init_viewport ( int *, int *);
145 settings_init (int *width, int *length)
147 init_viewport (width, length);
148 settings_set_epoch (-1);
149 the_settings.styles = fmt_create ();
151 settings_set_decimal_char (get_system_decimal ());
157 fmt_done (the_settings.styles);
160 /* Returns the floating-point format used for RB and RBHEX
163 settings_get_input_float_format (void)
165 return the_settings.input_float_format;
168 /* Sets the floating-point format used for RB and RBHEX input to
171 settings_set_input_float_format ( enum float_format format)
173 the_settings.input_float_format = format;
176 /* Returns the integer format used for IB and PIB input. */
178 settings_get_input_integer_format (void)
180 return the_settings.input_integer_format;
183 /* Sets the integer format used for IB and PIB input to
186 settings_set_input_integer_format ( enum integer_format format)
188 the_settings.input_integer_format = format;
191 /* Returns the current output integer format. */
193 settings_get_output_integer_format (void)
195 return the_settings.output_integer_format;
198 /* Sets the output integer format to INTEGER_FORMAT. */
200 settings_set_output_integer_format (
201 enum integer_format integer_format)
203 the_settings.output_integer_format = integer_format;
206 /* Returns the current output float format. */
208 settings_get_output_float_format (void)
210 return the_settings.output_float_format;
213 /* Sets the output float format to FLOAT_FORMAT. */
215 settings_set_output_float_format ( enum float_format float_format)
217 the_settings.output_float_format = float_format;
220 /* Screen length in lines. */
222 settings_get_viewlength (void)
224 return *the_settings.viewlength;
227 /* Sets the view length. */
229 settings_set_viewlength ( int viewlength_)
231 *the_settings.viewlength = viewlength_;
236 settings_get_viewwidth(void)
238 return *the_settings.viewwidth;
241 /* Sets the screen width. */
243 settings_set_viewwidth ( int viewwidth_)
245 *the_settings.viewwidth = viewwidth_;
249 init_viewport ( int *width, int *length)
251 the_settings.viewwidth = width;
252 the_settings.viewlength = length;
255 /* Whether PSPP can erase and overwrite files. */
257 settings_get_safer_mode (void)
259 return the_settings.safer_mode;
262 /* Set safer mode. */
264 settings_set_safer_mode (void)
266 the_settings.safer_mode = true;
269 /* Echo commands to the listing file/printer? */
271 settings_get_echo (void)
273 return the_settings.do_echo;
278 settings_set_echo ( bool echo)
280 the_settings.do_echo = echo;
283 /* If echo is on, whether commands from include files are echoed. */
285 settings_get_include (void)
287 return the_settings.include;
290 /* Set include file echo. */
292 settings_set_include ( bool include)
294 the_settings.include = include;
297 /* What year to use as the start of the epoch. */
299 settings_get_epoch (void)
301 assert (the_settings.epoch >= 0);
303 return the_settings.epoch;
306 /* Sets the year that starts the epoch. */
308 settings_set_epoch ( int epoch)
313 struct tm *tm = localtime (&t);
314 epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
317 the_settings.epoch = epoch;
318 assert (the_settings.epoch >= 0);
321 /* Does an error stop execution? */
323 settings_get_errorbreak (void)
325 return the_settings.errorbreak;
328 /* Sets whether an error stops execution. */
330 settings_set_errorbreak ( bool errorbreak)
332 the_settings.errorbreak = errorbreak;
335 /* Route error messages to terminal? */
337 settings_get_error_routing_to_terminal (void)
339 return the_settings.route_errors_to_terminal;
342 /* Sets whether error messages should be routed to the
345 settings_set_error_routing_to_terminal ( bool route_to_terminal)
347 the_settings.route_errors_to_terminal = route_to_terminal;
350 /* Route error messages to listing file? */
352 settings_get_error_routing_to_listing (void)
354 return the_settings.route_errors_to_listing;
357 /* Sets whether error messages should be routed to the
360 settings_set_error_routing_to_listing ( bool route_to_listing)
362 the_settings.route_errors_to_listing = route_to_listing;
365 /* Compress system files by default? */
367 settings_get_scompression (void)
369 return the_settings.scompress;
372 /* Set system file default compression. */
374 settings_set_scompression ( bool scompress)
376 the_settings.scompress = scompress;
379 /* Whether to warn on undefined values in numeric data. */
381 settings_get_undefined (void)
383 return the_settings.undefined;
386 /* Set whether to warn on undefined values. */
388 settings_set_undefined ( bool undefined)
390 the_settings.undefined = undefined;
393 /* The value that blank numeric fields are set to when read in. */
395 settings_get_blanks (void)
397 return the_settings.blanks;
400 /* Set the value that blank numeric fields are set to when read
403 settings_set_blanks ( double blanks)
405 the_settings.blanks = blanks;
408 /* Maximum number of warnings + errors. */
410 settings_get_mxwarns (void)
412 return the_settings.mxwarns;
415 /* Sets maximum number of warnings + errors. */
417 settings_set_mxwarns ( int mxwarns)
419 the_settings.mxwarns = mxwarns;
422 /* Maximum number of errors. */
424 settings_get_mxerrs (void)
426 return the_settings.mxerrs;
429 /* Sets maximum number of errors. */
431 settings_set_mxerrs ( int mxerrs)
433 the_settings.mxerrs = mxerrs;
436 /* Whether commands are written to the display. */
438 settings_get_printback (void)
440 return the_settings.printback;
443 /* Sets whether commands are written to the display. */
445 settings_set_printback ( bool printback)
447 the_settings.printback = printback;
450 /* Independent of get_printback, controls whether the commands
451 generated by macro invocations are displayed. */
453 settings_get_mprint (void)
455 return the_settings.mprint;
458 /* Sets whether the commands generated by macro invocations are
461 settings_set_mprint ( bool mprint)
463 the_settings.mprint = mprint;
466 /* Implied limit of unbounded loop. */
468 settings_get_mxloops (void)
470 return the_settings.mxloops;
473 /* Set implied limit of unbounded loop. */
475 settings_set_mxloops ( int mxloops)
477 the_settings.mxloops = mxloops;
480 /* Whether a blank line is a command terminator. */
482 settings_get_nulline (void)
484 return the_settings.nulline;
487 /* Set whether a blank line is a command terminator. */
489 settings_set_nulline ( bool nulline)
491 the_settings.nulline = nulline;
494 /* The character used to terminate commands. */
496 settings_get_endcmd (void)
498 return the_settings.endcmd;
501 /* Set the character used to terminate commands. */
503 settings_set_endcmd ( char endcmd)
505 the_settings.endcmd = endcmd;
508 /* Approximate maximum amount of memory to use for cases, in
511 settings_get_workspace (void)
513 return the_settings.workspace;
516 /* Approximate maximum number of cases to allocate in-core, given
517 that each case contains VALUE_CNT values. */
519 settings_get_workspace_cases (size_t value_cnt)
521 size_t case_size = sizeof (union value) * value_cnt + 4 * sizeof (void *);
522 size_t case_cnt = MAX (settings_get_workspace () / case_size, 4);
526 /* Set approximate maximum amount of memory to use for cases, in
530 settings_set_workspace ( size_t workspace)
532 the_settings.workspace = workspace;
535 /* Default format for variables created by transformations and by
536 DATA LIST {FREE,LIST}. */
537 const struct fmt_spec *
538 settings_get_format (void)
540 return &the_settings.default_format;
543 /* Set default format for variables created by transformations
544 and by DATA LIST {FREE,LIST}. */
546 settings_set_format ( const struct fmt_spec *default_format)
548 the_settings.default_format = *default_format;
551 /* Are we in testing mode? (e.g. --testing-mode command line
554 settings_get_testing_mode (void)
556 return the_settings.testing_mode;
559 /* Set testing mode. */
561 settings_set_testing_mode ( bool testing_mode)
563 the_settings.testing_mode = testing_mode;
566 /* Return the current algorithm setting */
568 settings_get_algorithm (void)
570 return *the_settings.algorithm;
573 /* Set the algorithm option globally. */
575 settings_set_algorithm (enum behavior_mode mode)
577 global_algorithm = mode;
580 /* Set the algorithm option for this command only */
582 settings_set_cmd_algorithm ( enum behavior_mode mode)
584 the_settings.cmd_algorithm = mode;
585 the_settings.algorithm = &the_settings.cmd_algorithm;
588 /* Unset the algorithm option for this command */
590 unset_cmd_algorithm (void)
592 the_settings.algorithm = &global_algorithm;
595 /* Get the current syntax setting */
597 settings_get_syntax (void)
599 return the_settings.syntax;
602 /* Set the syntax option */
604 settings_set_syntax ( enum behavior_mode mode)
606 the_settings.syntax = mode;
611 /* Find the grouping characters in CC_STRING and set CC's
612 grouping and decimal members appropriately. Returns true if
613 successful, false otherwise. */
615 find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
618 int comma_cnt, dot_cnt;
620 /* Count commas and periods. There must be exactly three of
621 one or the other, except that an apostrophe escapes a
622 following comma or period. */
623 comma_cnt = dot_cnt = 0;
624 for (sp = cc_string; *sp; sp++)
629 else if (*sp == '\'' && (sp[1] == '.' || sp[1] == ',' || sp[1] == '\''))
632 if ((comma_cnt == 3) == (dot_cnt == 3))
648 /* Extracts a token from IN into a newly allocated AFFIX. Tokens
649 are delimited by GROUPING. The token is truncated to at most
650 FMT_STYLE_AFFIX_MAX characters. Returns the first character
651 following the token. */
653 extract_cc_token (const char *in, int grouping, struct substring *affix)
656 ss_alloc_uninit (affix, FMT_STYLE_AFFIX_MAX);
657 for (; *in != '\0' && *in != grouping; in++)
659 if (*in == '\'' && in[1] == grouping)
661 if (ofs < FMT_STYLE_AFFIX_MAX)
662 ss_data (*affix)[ofs++] = *in;
672 /* Sets custom currency specifier CC having name CC_NAME ('A' through
673 'E') to correspond to the settings in CC_STRING. */
675 settings_set_cc (const char *cc_string, enum fmt_type type)
677 struct fmt_number_style *cc = &the_settings.styles[type];
679 assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
681 /* Determine separators. */
682 if (!find_cc_separators (cc_string, cc))
684 msg (SE, _("%s: Custom currency string `%s' does not contain "
685 "exactly three periods or commas (or it contains both)."),
686 fmt_name (type), cc_string);
690 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_prefix);
691 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->prefix);
692 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->suffix);
693 cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_suffix);
695 fmt_check_style (cc);
700 /* Returns the decimal point character for TYPE. */
702 settings_get_decimal_char (enum fmt_type type)
704 return fmt_get_style (the_settings.styles, type)->decimal;
708 settings_set_decimal_char (char decimal)
710 fmt_set_decimal (the_settings.styles, decimal);
715 /* Returns the number formatting style associated with the given
717 const struct fmt_number_style *
718 settings_get_style (enum fmt_type type)
720 assert (is_fmt_type (type));
721 return &the_settings.styles[type];
725 /* Returns a string of the form "$#,###.##" according to FMT,
726 which must be of type FMT_DOLLAR. The caller must free the
729 settings_dollar_template (const struct fmt_spec *fmt)
731 const struct fmt_number_style *styles = the_settings.styles;
732 struct string str = DS_EMPTY_INITIALIZER;
734 const struct fmt_number_style *fns ;
736 assert (fmt->type == FMT_DOLLAR);
738 fns = fmt_get_style (styles, fmt->type);
740 ds_put_char (&str, '$');
741 for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
743 ds_put_char (&str, '#');
744 if (--c % 4 == 0 && c > 0)
746 ds_put_char (&str, fns->grouping);
752 ds_put_char (&str, fns->decimal);
753 ds_put_char_multiple (&str, '#', fmt->d);
756 return ds_cstr (&str);