Automatically infer variables' measurement level from format and data.
[pspp] / src / data / settings.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2015 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include "data/settings.h"
20
21 #include <assert.h>
22 #include <stdlib.h>
23
24 #include "data/case.h"
25 #include "data/format.h"
26 #include "data/value.h"
27 #include "libpspp/i18n.h"
28 #include "libpspp/integer-format.h"
29 #include "libpspp/message.h"
30
31 #include "gl/minmax.h"
32 #include "gl/xalloc.h"
33
34 #include "gettext.h"
35 #define _(msgid) gettext (msgid)
36
37 struct settings
38 {
39   /* Integer format used for IB and PIB input. */
40   enum integer_format input_integer_format;
41
42   /* Floating-point format used for RB and RBHEX input. */
43   enum float_format input_float_format;
44
45   /* Format of integers in output (SET WIB). */
46   enum integer_format output_integer_format;
47
48   /* Format of reals in output (SET WRB). */
49   enum float_format output_float_format;
50
51   /* MATRIX...END MATRIX settings. */
52   enum settings_mdisplay mdisplay;
53
54   int viewlength;
55   int viewwidth;
56   bool safer_mode;
57   bool include;
58   bool route_errors_to_terminal;
59   bool route_errors_to_listing;
60   bool scompress;
61   bool undefined;
62   double blanks;
63   int max_messages[MSG_N_SEVERITIES];
64   bool printback;
65
66   /* Macro settings. */
67   bool mexpand;                 /* Expand macros? */
68   bool mprint;                  /* Print macro expansions? */
69   int miterate;                 /* Maximum iterations of !FOR. */
70   int mnest;                    /* Maximum nested macro expansion levels. */
71
72   int mxloops;
73   size_t workspace;
74   struct fmt_spec default_format;
75   bool testing_mode;
76   int fuzzbits;
77   int scalemin;
78
79   int cmd_algorithm;
80   int global_algorithm;
81   int syntax;
82
83   struct fmt_settings styles;
84   double small;
85
86   enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
87
88   enum settings_value_show show_values;
89   enum settings_value_show show_variables;
90 };
91
92 static struct settings the_settings = {
93   .input_integer_format = INTEGER_NATIVE,
94   .input_float_format = FLOAT_NATIVE_DOUBLE,
95   .output_integer_format = INTEGER_NATIVE,
96   .output_float_format = FLOAT_NATIVE_DOUBLE,
97   .mdisplay = SETTINGS_MDISPLAY_TEXT,
98   .viewlength = 24,
99   .viewwidth = 79,
100   .safer_mode = false,
101   .include = true,
102   .route_errors_to_terminal = true,
103   .route_errors_to_listing = true,
104   .scompress = true,
105   .undefined = true,
106   .blanks = SYSMIS,
107
108   .max_messages = {
109     [MSG_S_ERROR] = 100,
110     [MSG_S_WARNING] = 100,
111     [MSG_S_NOTE] = 100
112   },
113
114   .printback = true,
115
116   .mexpand = true,
117   .mprint = false,
118   .miterate = 1000,
119   .mnest = 50,
120
121   .mxloops = 40,
122   .workspace = 64L * 1024 * 1024,
123   .default_format = { .type = FMT_F, .w = 8, .d = 2 },
124   .testing_mode = false,
125   .fuzzbits = 6,
126   .scalemin = 24,
127   .cmd_algorithm = ENHANCED,
128   .global_algorithm = ENHANCED,
129   .syntax = ENHANCED,
130   .styles = FMT_SETTINGS_INIT,
131   .small = .0001,
132
133   /* output_routing */
134   .output_routing = {
135 #define LT (SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL)
136     [SETTINGS_OUTPUT_ERROR] = LT,
137     [SETTINGS_OUTPUT_NOTE] = LT,
138     [SETTINGS_OUTPUT_SYNTAX] = 0,
139     [SETTINGS_OUTPUT_RESULT] = LT
140 #undef LT
141   },
142
143   .show_values = SETTINGS_VALUE_SHOW_LABEL,
144   .show_variables = SETTINGS_VALUE_SHOW_LABEL,
145 };
146
147 /* Initializes the settings module. */
148 void
149 settings_init (void)
150 {
151   settings_set_decimal_char (get_system_decimal ());
152 }
153
154 /* Cleans up the settings module. */
155 void
156 settings_done (void)
157 {
158   settings_destroy (&the_settings);
159 }
160
161 static void
162 settings_copy (struct settings *dst, const struct settings *src)
163 {
164   *dst = *src;
165   dst->styles = fmt_settings_copy (&src->styles);
166 }
167
168 /* Returns a copy of the current settings. */
169 struct settings *
170 settings_get (void)
171 {
172   struct settings *s = xmalloc (sizeof *s);
173   settings_copy (s, &the_settings);
174   return s;
175 }
176
177 /* Replaces the current settings by those in S.  The caller retains ownership
178    of S. */
179 void
180 settings_set (const struct settings *s)
181 {
182   settings_destroy (&the_settings);
183   settings_copy (&the_settings, s);
184 }
185
186 /* Destroys S. */
187 void
188 settings_destroy (struct settings *s)
189 {
190   if (s != NULL)
191     {
192       fmt_settings_uninit (&s->styles);
193       if (s != &the_settings)
194         free (s);
195     }
196 }
197
198 /* Returns the floating-point format used for RB and RBHEX
199    input. */
200 enum float_format
201 settings_get_input_float_format (void)
202 {
203   return the_settings.input_float_format;
204 }
205
206 /* Sets the floating-point format used for RB and RBHEX input to
207    FORMAT. */
208 void
209 settings_set_input_float_format (enum float_format format)
210 {
211   the_settings.input_float_format = format;
212 }
213
214 /* Returns the integer format used for IB and PIB input. */
215 enum integer_format
216 settings_get_input_integer_format (void)
217 {
218   return the_settings.input_integer_format;
219 }
220
221 /* Sets the integer format used for IB and PIB input to
222    FORMAT. */
223 void
224 settings_set_input_integer_format (enum integer_format format)
225 {
226   the_settings.input_integer_format = format;
227 }
228
229 /* Returns the current output integer format. */
230 enum integer_format
231 settings_get_output_integer_format (void)
232 {
233   return the_settings.output_integer_format;
234 }
235
236 /* Sets the output integer format to INTEGER_FORMAT. */
237 void
238 settings_set_output_integer_format (
239                            enum integer_format integer_format)
240 {
241   the_settings.output_integer_format = integer_format;
242 }
243
244 /* Returns the current output float format. */
245 enum float_format
246 settings_get_output_float_format (void)
247 {
248   return the_settings.output_float_format;
249 }
250
251 /* Sets the output float format to FLOAT_FORMAT. */
252 void
253 settings_set_output_float_format (enum float_format float_format)
254 {
255   the_settings.output_float_format = float_format;
256 }
257
258 /* Screen length in lines. */
259 int
260 settings_get_viewlength (void)
261 {
262   return the_settings.viewlength;
263 }
264
265 /* Sets the view length. */
266 void
267 settings_set_viewlength (int viewlength_)
268 {
269   the_settings.viewlength = viewlength_;
270 }
271
272 /* Screen width. */
273 int
274 settings_get_viewwidth(void)
275 {
276   return the_settings.viewwidth;
277 }
278
279 /* Sets the screen width. */
280 void
281 settings_set_viewwidth (int viewwidth_)
282 {
283   the_settings.viewwidth = viewwidth_;
284 }
285
286 /* Whether PSPP can erase and overwrite files. */
287 bool
288 settings_get_safer_mode (void)
289 {
290   return the_settings.safer_mode;
291 }
292
293 /* Set safer mode. */
294 void
295 settings_set_safer_mode (void)
296 {
297   the_settings.safer_mode = true;
298 }
299
300 /* If echo is on, whether commands from include files are echoed. */
301 bool
302 settings_get_include (void)
303 {
304   return the_settings.include;
305 }
306
307 /* Set include file echo. */
308 void
309 settings_set_include (bool include)
310 {
311   the_settings.include = include;
312 }
313
314 /* Returns the year that starts the epoch. */
315 int
316 settings_get_epoch (void)
317 {
318   return the_settings.styles.epoch;
319 }
320
321 /* Sets the year that starts the epoch. */
322 void
323 settings_set_epoch (int epoch)
324 {
325   the_settings.styles.epoch = epoch;
326 }
327
328 /* Compress system files by default? */
329 bool
330 settings_get_scompression (void)
331 {
332   return the_settings.scompress;
333 }
334
335 /* Set system file default compression. */
336 void
337 settings_set_scompression (bool scompress)
338 {
339   the_settings.scompress = scompress;
340 }
341
342 /* Whether to warn on undefined values in numeric data. */
343 bool
344 settings_get_undefined (void)
345 {
346   return the_settings.undefined;
347 }
348
349 /* Set whether to warn on undefined values. */
350 void
351 settings_set_undefined (bool undefined)
352 {
353   the_settings.undefined = undefined;
354 }
355
356 /* The value that blank numeric fields are set to when read in. */
357 double
358 settings_get_blanks (void)
359 {
360   return the_settings.blanks;
361 }
362
363 /* Set the value that blank numeric fields are set to when read
364    in. */
365 void
366 settings_set_blanks (double blanks)
367 {
368   the_settings.blanks = blanks;
369 }
370
371 /* Returns the maximum number of messages to show of the given SEVERITY before
372    aborting.  (The value for MSG_S_WARNING is interpreted as maximum number of
373    warnings and errors combined.) */
374 int
375 settings_get_max_messages (enum msg_severity severity)
376 {
377   assert (severity < MSG_N_SEVERITIES);
378   return the_settings.max_messages[severity];
379 }
380
381 /* Sets the maximum number of messages to show of the given SEVERITY before
382    aborting to MAX.  (The value for MSG_S_WARNING is interpreted as maximum
383    number of warnings and errors combined.)  In addition, in the case of
384    warnings the special value of zero indicates that no warnings are to be
385    issued.
386 */
387 void
388 settings_set_max_messages (enum msg_severity severity, int max)
389 {
390   assert (severity < MSG_N_SEVERITIES);
391
392   if (severity == MSG_S_WARNING)
393     {
394       if (max == 0)
395         {
396           msg (MW,
397                _("MXWARNS set to zero.  No further warnings will be given even when potentially problematic situations are encountered."));
398           msg_ui_disable_warnings (true);
399         }
400       else if (the_settings.max_messages [MSG_S_WARNING] == 0)
401         {
402           msg_ui_disable_warnings (false);
403           the_settings.max_messages[MSG_S_WARNING] = max;
404           msg (MW, _("Warnings re-enabled. %d warnings will be issued before aborting syntax processing."), max);
405         }
406     }
407
408   the_settings.max_messages[severity] = max;
409 }
410
411 /* Returns whether to expand macro invocations. */
412 bool
413 settings_get_mexpand (void)
414 {
415   return the_settings.mexpand;
416 }
417
418 /* Sets whether to expand macro invocations. */
419 void
420 settings_set_mexpand (bool mexpand)
421 {
422   the_settings.mexpand = mexpand;
423 }
424
425 /* Independent of get_printback, controls whether the commands
426    generated by macro invocations are displayed. */
427 bool
428 settings_get_mprint (void)
429 {
430   return the_settings.mprint;
431 }
432
433 /* Sets whether the commands generated by macro invocations are
434    displayed. */
435 void
436 settings_set_mprint (bool mprint)
437 {
438   the_settings.mprint = mprint;
439 }
440
441 /* Returns the limit for loop iterations within a macro. */
442 int
443 settings_get_miterate (void)
444 {
445   return the_settings.miterate;
446 }
447
448 /* Sets the limit for loop iterations within a macro. */
449 void
450 settings_set_miterate (int miterate)
451 {
452   the_settings.miterate = miterate;
453 }
454
455 /* Returns the limit for recursion macro expansions. */
456 int settings_get_mnest (void)
457 {
458   return the_settings.mnest;
459 }
460
461 /* Sets the limit for recursion macro expansions. */
462 void
463 settings_set_mnest (int mnest)
464 {
465   the_settings.mnest = mnest;
466 }
467
468 int settings_get_mxloops (void);
469 void settings_set_mxloops (int);
470 /* Implied limit of unbounded loop. */
471 int
472 settings_get_mxloops (void)
473 {
474   return the_settings.mxloops;
475 }
476
477 /* Set implied limit of unbounded loop. */
478 void
479 settings_set_mxloops (int mxloops)
480 {
481   the_settings.mxloops = mxloops;
482 }
483
484 /* Approximate maximum amount of memory to use for cases, in
485    bytes. */
486 size_t
487 settings_get_workspace (void)
488 {
489   return the_settings.workspace;
490 }
491
492 /* Approximate maximum number of cases to allocate in-core, given
493    that each case has the format given in PROTO. */
494 size_t
495 settings_get_workspace_cases (const struct caseproto *proto)
496 {
497   size_t n_cases = settings_get_workspace () / case_get_cost (proto);
498   return MAX (n_cases, 4);
499 }
500
501 /* Set approximate maximum amount of memory to use for cases, in
502    bytes. */
503
504 void
505 settings_set_workspace (size_t workspace)
506 {
507   the_settings.workspace = workspace;
508 }
509
510 /* Default format for variables created by transformations and by
511    DATA LIST {FREE,LIST}. */
512 const struct fmt_spec *
513 settings_get_format (void)
514 {
515   return &the_settings.default_format;
516 }
517
518 /* Set default format for variables created by transformations
519    and by DATA LIST {FREE,LIST}. */
520 void
521 settings_set_format (const struct fmt_spec *default_format)
522 {
523   the_settings.default_format = *default_format;
524 }
525
526 /* Are we in testing mode?  (e.g. --testing-mode command line
527    option) */
528 bool
529 settings_get_testing_mode (void)
530 {
531   return the_settings.testing_mode;
532 }
533
534 /* Set testing mode. */
535 void
536 settings_set_testing_mode (bool testing_mode)
537 {
538   the_settings.testing_mode = testing_mode;
539 }
540
541 int
542 settings_get_fuzzbits (void)
543 {
544   return the_settings.fuzzbits;
545 }
546
547 void
548 settings_set_fuzzbits (int fuzzbits)
549 {
550   the_settings.fuzzbits = fuzzbits;
551 }
552
553 int
554 settings_get_scalemin (void)
555 {
556   return the_settings.scalemin;
557 }
558
559 void
560 settings_set_scalemin (int scalemin)
561 {
562   the_settings.scalemin = scalemin;
563 }
564
565 /* Return the current algorithm setting */
566 enum behavior_mode
567 settings_get_algorithm (void)
568 {
569   return the_settings.cmd_algorithm;
570 }
571
572 /* Set the algorithm option globally. */
573 void
574 settings_set_algorithm (enum behavior_mode mode)
575 {
576   the_settings.global_algorithm = the_settings.cmd_algorithm = mode;
577 }
578
579 /* Set the algorithm option for this command only */
580 void
581 settings_set_cmd_algorithm (enum behavior_mode mode)
582 {
583   the_settings.cmd_algorithm = mode;
584 }
585
586 /* Unset the algorithm option for this command */
587 void
588 unset_cmd_algorithm (void)
589 {
590   the_settings.cmd_algorithm = the_settings.global_algorithm;
591 }
592
593 /* Get the current syntax setting */
594 enum behavior_mode
595 settings_get_syntax (void)
596 {
597   return the_settings.syntax;
598 }
599
600 /* Set the syntax option */
601 void
602 settings_set_syntax (enum behavior_mode mode)
603 {
604   the_settings.syntax = mode;
605 }
606
607 \f
608 /* Sets custom currency specifier CC having name CC_NAME ('A' through
609    'E') to correspond to the settings in CC_STRING. */
610 bool
611 settings_set_cc (const char *cc_string, enum fmt_type type)
612 {
613   struct fmt_number_style *style = fmt_number_style_from_string (cc_string);
614   if (!style)
615     {
616       msg (SE, _("%s: Custom currency string `%s' does not contain "
617                  "exactly three periods or commas (or it contains both)."),
618            fmt_name (type), cc_string);
619       return false;
620     }
621
622   fmt_settings_set_cc (&the_settings.styles, type, style);
623   return true;
624 }
625
626 void
627 settings_set_decimal_char (char decimal)
628 {
629   the_settings.styles.decimal = decimal;
630 }
631
632 void
633 settings_set_include_leading_zero (bool include_leading_zero)
634 {
635   the_settings.styles.include_leading_zero = include_leading_zero;
636 }
637
638 const struct fmt_settings *
639 settings_get_fmt_settings (void)
640 {
641   return &the_settings.styles;
642 }
643
644 double
645 settings_get_small (void)
646 {
647   return the_settings.small;
648 }
649
650 void
651 settings_set_small (double small)
652 {
653   the_settings.small = small;
654 }
655
656 /* Returns a string of the form "$#,###.##" according to FMT,
657    which must be of type FMT_DOLLAR.  The caller must free the
658    string. */
659 char *
660 settings_dollar_template (const struct fmt_spec *fmt)
661 {
662   struct string str = DS_EMPTY_INITIALIZER;
663   int c;
664   const struct fmt_number_style *fns ;
665
666   assert (fmt->type == FMT_DOLLAR);
667
668   fns = fmt_settings_get_style (&the_settings.styles, fmt->type);
669
670   ds_put_byte (&str, '$');
671   for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0;)
672     {
673       ds_put_byte (&str, '#');
674       if (--c % 4 == 0 && c > 0)
675         {
676           ds_put_byte (&str, fns->grouping);
677           --c;
678         }
679     }
680   if (fmt->d > 0)
681     {
682       ds_put_byte (&str, fns->decimal);
683       ds_put_byte_multiple (&str, '#', fmt->d);
684     }
685
686   return ds_cstr (&str);
687 }
688
689 void
690 settings_set_output_routing (enum settings_output_type type,
691                              enum settings_output_devices devices)
692 {
693   assert (type < SETTINGS_N_OUTPUT_TYPES);
694   the_settings.output_routing[type] = devices;
695 }
696
697 enum settings_output_devices
698 settings_get_output_routing (enum settings_output_type type)
699 {
700   assert (type < SETTINGS_N_OUTPUT_TYPES);
701   return the_settings.output_routing[type] | SETTINGS_DEVICE_UNFILTERED;
702 }
703
704 enum settings_value_show
705 settings_get_show_values (void)
706 {
707   return the_settings.show_values;
708 }
709
710 void
711 settings_set_show_values (enum settings_value_show s)
712 {
713   the_settings.show_values = s;
714 }
715
716
717 enum settings_value_show
718 settings_get_show_variables (void)
719 {
720   return the_settings.show_variables;
721 }
722
723 void
724 settings_set_show_variables (enum settings_value_show s)
725 {
726   the_settings.show_variables = s;
727 }
728
729 enum settings_mdisplay
730 settings_get_mdisplay (void)
731 {
732   return the_settings.mdisplay;
733 }
734
735 void
736 settings_set_mdisplay (enum settings_mdisplay mdisplay)
737 {
738   the_settings.mdisplay = mdisplay;
739 }