New command SHOW SYSTEM to easily print information useful in bug reports.
[pspp] / src / language / utilities / set.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014, 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 <float.h>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <time.h>
24 #include <unistd.h>
25
26 #include "data/casereader.h"
27 #include "data/data-in.h"
28 #include "data/data-out.h"
29 #include "data/dataset.h"
30 #include "data/dictionary.h"
31 #include "data/format.h"
32 #include "data/settings.h"
33 #include "data/value.h"
34 #include "data/variable.h"
35 #include "language/command.h"
36 #include "language/lexer/format-parser.h"
37 #include "language/lexer/lexer.h"
38 #include "libpspp/assertion.h"
39 #include "libpspp/compiler.h"
40 #include "libpspp/copyleft.h"
41 #include "libpspp/temp-file.h"
42 #include "libpspp/version.h"
43 #include "libpspp/float-format.h"
44 #include "libpspp/i18n.h"
45 #include "libpspp/integer-format.h"
46 #include "libpspp/message.h"
47 #include "math/random.h"
48 #include "output/driver.h"
49 #include "output/journal.h"
50 #include "output/pivot-table.h"
51
52 #include "gl/ftoastr.h"
53 #include "gl/minmax.h"
54 #include "gl/relocatable.h"
55 #include "gl/vasnprintf.h"
56 #include "gl/xalloc.h"
57
58 #include "gettext.h"
59 #define _(msgid) gettext (msgid)
60 #define N_(msgid) (msgid)
61
62 struct setting
63   {
64     const char *name;
65     bool (*set) (struct lexer *);
66     char *(*show) (const struct dataset *);
67   };
68
69 static bool
70 match_subcommand (struct lexer *lexer, const char *name)
71 {
72   if (lex_match_id (lexer, name))
73     {
74       lex_match (lexer, T_EQUALS);
75       return true;
76     }
77   else
78     return false;
79 }
80
81 static int
82 parse_enum_valist (struct lexer *lexer, va_list args)
83 {
84   for (;;)
85     {
86       const char *name = va_arg (args, char *);
87       if (!name)
88         return -1;
89       int value = va_arg (args, int);
90
91       if (lex_match_id (lexer, name))
92         return value;
93     }
94 }
95
96 #define parse_enum(...) parse_enum (__VA_ARGS__, NULL_SENTINEL)
97 static int SENTINEL(0)
98 (parse_enum) (struct lexer *lexer, ...)
99 {
100   va_list args;
101
102   va_start (args, lexer);
103   int retval = parse_enum_valist (lexer, args);
104   va_end (args);
105
106   return retval;
107 }
108
109 #define force_parse_enum(...) force_parse_enum (__VA_ARGS__, NULL_SENTINEL)
110 static int SENTINEL(0)
111 (force_parse_enum) (struct lexer *lexer, ...)
112 {
113   va_list args;
114
115   va_start (args, lexer);
116   int retval = parse_enum_valist (lexer, args);
117   va_end (args);
118
119   if (retval == -1)
120     {
121       enum { MAX_OPTIONS = 9 };
122       const char *options[MAX_OPTIONS];
123       int n = 0;
124
125       va_start (args, lexer);
126       while (n < MAX_OPTIONS)
127         {
128           const char *name = va_arg (args, char *);
129           if (!name)
130             break;
131           va_arg (args, int);
132
133           options[n++] = name;
134         }
135       va_end (args);
136
137       lex_error_expecting_array (lexer, options, n);
138     }
139
140   return retval;
141 }
142
143 static int
144 parse_bool (struct lexer *lexer)
145 {
146   return parse_enum (lexer,
147                      "ON", true, "YES", true,
148                      "OFF", false, "NO", false);
149 }
150
151 static int
152 force_parse_bool (struct lexer *lexer)
153 {
154   return force_parse_enum (lexer,
155                            "ON", true, "YES", true,
156                            "OFF", false, "NO", false);
157 }
158
159 static bool
160 force_parse_int (struct lexer *lexer, int *integerp)
161 {
162   if (!lex_force_int (lexer))
163     return false;
164   *integerp = lex_integer (lexer);
165   lex_get (lexer);
166   return true;
167 }
168
169 static bool
170 parse_output_routing (struct lexer *lexer, enum settings_output_type type)
171 {
172   enum settings_output_devices devices;
173   if (lex_match_id (lexer, "ON") || lex_match_id (lexer, "BOTH"))
174     devices = SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL;
175   else if (lex_match_id (lexer, "TERMINAL"))
176     devices = SETTINGS_DEVICE_TERMINAL;
177   else if (lex_match_id (lexer, "LISTING"))
178     devices = SETTINGS_DEVICE_LISTING;
179   else if (lex_match_id (lexer, "OFF") || lex_match_id (lexer, "NONE"))
180     devices = 0;
181   else
182     {
183       lex_error (lexer, NULL);
184       return false;
185     }
186
187   settings_set_output_routing (type, devices);
188
189   return true;
190 }
191
192 static char *
193 show_output_routing (enum settings_output_type type)
194 {
195   enum settings_output_devices devices;
196   const char *s;
197
198   devices = settings_get_output_routing (type);
199   if (devices & SETTINGS_DEVICE_LISTING)
200     s = devices & SETTINGS_DEVICE_TERMINAL ? "BOTH" : "LISTING";
201   else if (devices & SETTINGS_DEVICE_TERMINAL)
202     s = "TERMINAL";
203   else
204     s = "NONE";
205
206   return xstrdup (s);
207 }
208
209 static bool
210 parse_integer_format (struct lexer *lexer,
211                       void (*set_format) (enum integer_format))
212 {
213   int value = force_parse_enum (lexer,
214                                 "MSBFIRST", INTEGER_MSB_FIRST,
215                                 "LSBFIRST", INTEGER_LSB_FIRST,
216                                 "VAX", INTEGER_VAX,
217                                 "NATIVE", INTEGER_NATIVE);
218   if (value >= 0)
219     set_format (value);
220   return value >= 0;
221 }
222
223 /* Returns a name for the given INTEGER_FORMAT value. */
224 static char *
225 show_integer_format (enum integer_format integer_format)
226 {
227   return xasprintf ("%s (%s)",
228                     (integer_format == INTEGER_MSB_FIRST ? "MSBFIRST"
229                      : integer_format == INTEGER_LSB_FIRST ? "LSBFIRST"
230                      : "VAX"),
231                     integer_format == INTEGER_NATIVE ? "NATIVE" : "nonnative");
232 }
233
234 static bool
235 parse_real_format (struct lexer *lexer,
236                    void (*set_format) (enum float_format))
237 {
238   int value = force_parse_enum (lexer,
239                                 "NATIVE", FLOAT_NATIVE_DOUBLE,
240                                 "ISL", FLOAT_IEEE_SINGLE_LE,
241                                 "ISB", FLOAT_IEEE_SINGLE_BE,
242                                 "IDL", FLOAT_IEEE_DOUBLE_LE,
243                                 "IDB", FLOAT_IEEE_DOUBLE_BE,
244                                 "VF", FLOAT_VAX_F,
245                                 "VD", FLOAT_VAX_D,
246                                 "VG", FLOAT_VAX_G,
247                                 "ZS", FLOAT_Z_SHORT,
248                                 "ZL", FLOAT_Z_LONG);
249   if (value >= 0)
250     set_format (value);
251   return value >= 0;
252 }
253
254 /* Returns a name for the given FLOAT_FORMAT value. */
255 static char *
256 show_real_format (enum float_format float_format)
257 {
258   const char *format_name = "";
259
260   switch (float_format)
261     {
262     case FLOAT_IEEE_SINGLE_LE:
263       format_name = _("ISL (32-bit IEEE 754 single, little-endian)");
264       break;
265     case FLOAT_IEEE_SINGLE_BE:
266       format_name = _("ISB (32-bit IEEE 754 single, big-endian)");
267       break;
268     case FLOAT_IEEE_DOUBLE_LE:
269       format_name = _("IDL (64-bit IEEE 754 double, little-endian)");
270       break;
271     case FLOAT_IEEE_DOUBLE_BE:
272       format_name = _("IDB (64-bit IEEE 754 double, big-endian)");
273       break;
274
275     case FLOAT_VAX_F:
276       format_name = _("VF (32-bit VAX F, VAX-endian)");
277       break;
278     case FLOAT_VAX_D:
279       format_name = _("VD (64-bit VAX D, VAX-endian)");
280       break;
281     case FLOAT_VAX_G:
282       format_name = _("VG (64-bit VAX G, VAX-endian)");
283       break;
284
285     case FLOAT_Z_SHORT:
286       format_name = _("ZS (32-bit IBM Z hexadecimal short, big-endian)");
287       break;
288     case FLOAT_Z_LONG:
289       format_name = _("ZL (64-bit IBM Z hexadecimal long, big-endian)");
290       break;
291
292     case FLOAT_FP:
293     case FLOAT_HEX:
294       NOT_REACHED ();
295     }
296
297   return xasprintf ("%s (%s)", format_name,
298                     (float_format == FLOAT_NATIVE_DOUBLE
299                      ? "NATIVE" : "nonnative"));
300 }
301
302 static bool
303 parse_unimplemented (struct lexer *lexer, const char *name)
304 {
305   msg (SW, _("%s is not yet implemented."), name);
306   if (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
307     lex_get (lexer);
308   return true;
309 }
310
311 static bool
312 parse_ccx (struct lexer *lexer, enum fmt_type ccx)
313 {
314   if (!lex_force_string (lexer))
315     return false;
316
317   settings_set_cc (lex_tokcstr (lexer), ccx);
318   lex_get (lexer);
319   return true;
320 }
321 \f
322 static bool
323 parse_BASETEXTDIRECTION (struct lexer *lexer)
324 {
325   return parse_unimplemented (lexer, "BASETEXTDIRECTION");
326 }
327
328 static bool
329 parse_BLANKS (struct lexer *lexer)
330 {
331   if (lex_match_id (lexer, "SYSMIS"))
332     settings_set_blanks (SYSMIS);
333   else
334     {
335       if (!lex_force_num (lexer))
336         return false;
337       settings_set_blanks (lex_number (lexer));
338       lex_get (lexer);
339     }
340   return true;
341 }
342
343 static char *
344 show_BLANKS (const struct dataset *ds UNUSED)
345 {
346   return (settings_get_blanks () == SYSMIS
347           ? xstrdup ("SYSMIS")
348           : xasprintf ("%.*g", DBL_DIG + 1, settings_get_blanks ()));
349 }
350
351 static bool
352 parse_BLOCK (struct lexer *lexer)
353 {
354   return parse_unimplemented (lexer, "BLOCK");
355 }
356
357 static bool
358 parse_BOX (struct lexer *lexer)
359 {
360   return parse_unimplemented (lexer, "BOX");
361 }
362
363 static bool
364 parse_CACHE (struct lexer *lexer)
365 {
366   return parse_unimplemented (lexer, "CACHE");
367 }
368
369 static bool
370 parse_CCA (struct lexer *lexer)
371 {
372   return parse_ccx (lexer, FMT_CCA);
373 }
374
375 static bool
376 parse_CCB (struct lexer *lexer)
377 {
378   return parse_ccx (lexer, FMT_CCB);
379 }
380
381 static bool
382 parse_CCC (struct lexer *lexer)
383 {
384   return parse_ccx (lexer, FMT_CCC);
385 }
386
387 static bool
388 parse_CCD (struct lexer *lexer)
389 {
390   return parse_ccx (lexer, FMT_CCD);
391 }
392
393 static bool
394 parse_CCE (struct lexer *lexer)
395 {
396   return parse_ccx (lexer, FMT_CCE);
397 }
398
399 static char *
400 show_cc (enum fmt_type type)
401 {
402   return fmt_number_style_to_string (fmt_settings_get_style (
403                                        settings_get_fmt_settings (), type));
404 }
405
406 static char *
407 show_CCA (const struct dataset *ds UNUSED)
408 {
409   return show_cc (FMT_CCA);
410 }
411
412 static char *
413 show_CCB (const struct dataset *ds UNUSED)
414 {
415   return show_cc (FMT_CCB);
416 }
417
418 static char *
419 show_CCC (const struct dataset *ds UNUSED)
420 {
421   return show_cc (FMT_CCC);
422 }
423
424 static char *
425 show_CCD (const struct dataset *ds UNUSED)
426 {
427   return show_cc (FMT_CCD);
428 }
429
430 static char *
431 show_CCE (const struct dataset *ds UNUSED)
432 {
433   return show_cc (FMT_CCE);
434 }
435
436 static bool
437 parse_CELLSBREAK (struct lexer *lexer)
438 {
439   return parse_unimplemented (lexer, "CELLSBREAK");
440 }
441
442 static bool
443 parse_CMPTRANS (struct lexer *lexer)
444 {
445   return parse_unimplemented (lexer, "CMPTRANS");
446 }
447
448 static bool
449 parse_COMPRESSION (struct lexer *lexer)
450 {
451   return parse_unimplemented (lexer, "COMPRESSION");
452 }
453
454 static bool
455 parse_CTEMPLATE (struct lexer *lexer)
456 {
457   return parse_unimplemented (lexer, "CTEMPLATE");
458 }
459
460 static bool
461 parse_DECIMAL (struct lexer *lexer)
462 {
463   int decimal_char = force_parse_enum (lexer,
464                                        "DOT", '.',
465                                        "COMMA", ',');
466   if (decimal_char != -1)
467     settings_set_decimal_char (decimal_char);
468   return decimal_char != -1;
469 }
470
471 static char *
472 show_DECIMAL (const struct dataset *ds UNUSED)
473 {
474   return xasprintf ("`%c'", settings_get_fmt_settings ()->decimal);
475 }
476
477 static bool
478 parse_EPOCH (struct lexer *lexer)
479 {
480   if (lex_match_id (lexer, "AUTOMATIC"))
481     settings_set_epoch (-1);
482   else if (lex_is_integer (lexer))
483     {
484       if (!lex_force_int_range (lexer, "EPOCH", 1500, INT_MAX))
485         return false;
486       settings_set_epoch (lex_integer (lexer));
487       lex_get (lexer);
488     }
489   else
490     {
491       lex_error (lexer, _("expecting %s or year"), "AUTOMATIC");
492       return false;
493     }
494
495   return true;
496 }
497
498 static char *
499 show_EPOCH (const struct dataset *ds UNUSED)
500 {
501   return xasprintf ("%d", settings_get_epoch ());
502 }
503
504 static bool
505 parse_ERRORS (struct lexer *lexer)
506 {
507   return parse_output_routing (lexer, SETTINGS_OUTPUT_ERROR);
508 }
509
510 static char *
511 show_ERRORS (const struct dataset *ds UNUSED)
512 {
513   return show_output_routing (SETTINGS_OUTPUT_ERROR);
514 }
515
516 static bool
517 parse_FORMAT (struct lexer *lexer)
518 {
519   struct fmt_spec fmt;
520
521   lex_match (lexer, T_EQUALS);
522   if (!parse_format_specifier (lexer, &fmt))
523     return false;
524
525   if (!fmt_check_output (&fmt))
526     return false;
527
528   if (fmt_is_string (fmt.type))
529     {
530       char str[FMT_STRING_LEN_MAX + 1];
531       msg (SE, _("%s requires numeric output format as an argument.  "
532                  "Specified format %s is of type string."),
533            "FORMAT",
534            fmt_to_string (&fmt, str));
535       return false;
536     }
537
538   settings_set_format (&fmt);
539   return true;
540 }
541
542 static char *
543 show_FORMAT (const struct dataset *ds UNUSED)
544 {
545   char str[FMT_STRING_LEN_MAX + 1];
546   return xstrdup (fmt_to_string (settings_get_format (), str));
547 }
548
549 static bool
550 parse_FUZZBITS (struct lexer *lexer)
551 {
552   if (!lex_force_int_range (lexer, "FUZZITS", 0, 20))
553     return false;
554   settings_set_fuzzbits (lex_integer (lexer));
555   lex_get (lexer);
556   return true;
557 }
558
559 static char *
560 show_FUZZBITS (const struct dataset *ds UNUSED)
561 {
562   return xasprintf ("%d", settings_get_fuzzbits ());
563 }
564
565 static bool
566 parse_HEADER (struct lexer *lexer)
567 {
568   return parse_unimplemented (lexer, "HEADER");
569 }
570
571 static bool
572 parse_INCLUDE (struct lexer *lexer)
573 {
574   int include = force_parse_bool (lexer);
575   if (include != -1)
576     settings_set_include (include);
577   return include != -1;
578 }
579
580 static char *
581 show_INCLUDE (const struct dataset *ds UNUSED)
582 {
583   return xstrdup (settings_get_include () ? "ON" : "OFF");
584 }
585
586 static bool
587 parse_JOURNAL (struct lexer *lexer)
588 {
589   int b = parse_bool (lexer);
590   if (b == true)
591     journal_enable ();
592   else if (b == false)
593     journal_disable ();
594   else if (lex_is_string (lexer) || lex_token (lexer) == T_ID)
595     {
596       char *filename = utf8_to_filename (lex_tokcstr (lexer));
597       journal_set_file_name (filename);
598       free (filename);
599
600       lex_get (lexer);
601     }
602   else
603     {
604       lex_error (lexer, NULL);
605       return false;
606     }
607   return true;
608 }
609
610 static char *
611 show_JOURNAL (const struct dataset *ds UNUSED)
612 {
613   const char *enabled = journal_is_enabled () ? "ON" : "OFF";
614   const char *file_name = journal_get_file_name ();
615   return (file_name
616           ? xasprintf ("%s (%s)", enabled, file_name)
617           : xstrdup (enabled));
618 }
619
620 static bool
621 parse_LENGTH (struct lexer *lexer)
622 {
623   int page_length;
624
625   if (lex_match_id (lexer, "NONE"))
626     page_length = -1;
627   else
628     {
629       if (!lex_force_int_range (lexer, "LENGTH", 1, INT_MAX))
630         return false;
631       page_length = lex_integer (lexer);
632       lex_get (lexer);
633     }
634
635   if (page_length != -1)
636     settings_set_viewlength (page_length);
637
638   return true;
639 }
640
641 static char *
642 show_LENGTH (const struct dataset *ds UNUSED)
643 {
644   return xasprintf ("%d", settings_get_viewlength ());
645 }
646
647 static bool
648 parse_LOCALE (struct lexer *lexer)
649 {
650   if (!lex_force_string (lexer))
651     return false;
652
653   /* Try the argument as an encoding name, then as a locale name or alias. */
654   const char *s = lex_tokcstr (lexer);
655   if (valid_encoding (s))
656     set_default_encoding (s);
657   else if (!set_encoding_from_locale (s))
658     {
659       msg (ME, _("%s is not a recognized encoding or locale name"), s);
660       return false;
661     }
662
663   lex_get (lexer);
664   return true;
665 }
666
667 static char *
668 show_LOCALE (const struct dataset *ds UNUSED)
669 {
670   return xstrdup (get_default_encoding ());
671 }
672
673 static bool
674 parse_MDISPLAY (struct lexer *lexer)
675 {
676   int mdisplay = force_parse_enum (lexer,
677                                    "TEXT", SETTINGS_MDISPLAY_TEXT,
678                                    "TABLES", SETTINGS_MDISPLAY_TABLES);
679   if (mdisplay >= 0)
680     settings_set_mdisplay (mdisplay);
681   return mdisplay >= 0;
682 }
683
684 static char *
685 show_MDISPLAY (const struct dataset *ds UNUSED)
686 {
687   return xstrdup (settings_get_mdisplay () == SETTINGS_MDISPLAY_TEXT
688                   ? "TEXT" : "TABLES");
689 }
690
691 static bool
692 parse_MESSAGES (struct lexer *lexer)
693 {
694   return parse_output_routing (lexer, SETTINGS_OUTPUT_NOTE);
695 }
696
697 static char *
698 show_MESSAGES (const struct dataset *ds UNUSED)
699 {
700   return show_output_routing (SETTINGS_OUTPUT_NOTE);
701 }
702
703 static bool
704 parse_MEXPAND (struct lexer *lexer)
705 {
706   int mexpand = force_parse_bool (lexer);
707   if (mexpand != -1)
708     settings_set_mexpand (mexpand);
709   return mexpand != -1;
710 }
711
712 static char *
713 show_MEXPAND (const struct dataset *ds UNUSED)
714 {
715   return xstrdup (settings_get_mexpand () ? "ON" : "OFF");
716 }
717
718 static bool
719 parse_MITERATE (struct lexer *lexer)
720 {
721   if (!lex_force_int_range (lexer, "MITERATE", 1, INT_MAX))
722     return false;
723   settings_set_miterate (lex_integer (lexer));
724   lex_get (lexer);
725   return true;
726 }
727
728 static char *
729 show_MITERATE (const struct dataset *ds UNUSED)
730 {
731   return xasprintf ("%d", settings_get_miterate ());
732 }
733
734 static bool
735 parse_MNEST (struct lexer *lexer)
736 {
737   if (!lex_force_int_range (lexer, "MNEST", 1, INT_MAX))
738     return false;
739   settings_set_mnest (lex_integer (lexer));
740   lex_get (lexer);
741   return true;
742 }
743
744 static char *
745 show_MNEST (const struct dataset *ds UNUSED)
746 {
747   return xasprintf ("%d", settings_get_mnest ());
748 }
749
750 static bool
751 parse_MPRINT (struct lexer *lexer)
752 {
753   int mprint = force_parse_bool (lexer);
754   if (mprint != -1)
755     settings_set_mprint (mprint);
756   return mprint != -1;
757 }
758
759 static char *
760 show_MPRINT (const struct dataset *ds UNUSED)
761 {
762   return xstrdup (settings_get_mprint () ? "ON" : "OFF");
763 }
764
765 static bool
766 parse_MXERRS (struct lexer *lexer)
767 {
768   int n;
769   if (!force_parse_int (lexer, &n))
770     return false;
771
772   if (n >= 1)
773     settings_set_max_messages (MSG_S_ERROR, n);
774   else
775     msg (SE, _("%s must be at least 1."), "MXERRS");
776   return true;
777 }
778
779 static char *
780 show_MXERRS (const struct dataset *ds UNUSED)
781 {
782   return xasprintf ("%d", settings_get_max_messages (MSG_S_ERROR));
783 }
784
785 static bool
786 parse_MXLOOPS (struct lexer *lexer)
787 {
788   int n;
789   if (!force_parse_int (lexer, &n))
790     return false;
791
792   if (n >= 1)
793     settings_set_mxloops (n);
794   else
795     msg (SE, _("%s must be at least 1."), "MXLOOPS");
796   return true;
797 }
798
799 static char *
800 show_MXLOOPS (const struct dataset *ds UNUSED)
801 {
802   return xasprintf ("%d", settings_get_mxloops ());
803 }
804
805 static bool
806 parse_MXWARNS (struct lexer *lexer)
807 {
808   int n;
809   if (!force_parse_int (lexer, &n))
810     return false;
811
812   if (n >= 0)
813     settings_set_max_messages (MSG_S_WARNING, n);
814   else
815     msg (SE, _("%s must not be negative."), "MXWARNS");
816   return true;
817 }
818
819 static char *
820 show_MXWARNS (const struct dataset *ds UNUSED)
821 {
822   return xasprintf ("%d", settings_get_max_messages (MSG_S_WARNING));
823 }
824
825 static bool
826 parse_PRINTBACK (struct lexer *lexer)
827 {
828   return parse_output_routing (lexer, SETTINGS_OUTPUT_SYNTAX);
829 }
830
831 static char *
832 show_PRINTBACK (const struct dataset *ds UNUSED)
833 {
834   return show_output_routing (SETTINGS_OUTPUT_SYNTAX);
835 }
836
837 static bool
838 parse_RESULTS (struct lexer *lexer)
839 {
840   return parse_output_routing (lexer, SETTINGS_OUTPUT_RESULT);
841 }
842
843 static char *
844 show_RESULTS (const struct dataset *ds UNUSED)
845 {
846   return show_output_routing (SETTINGS_OUTPUT_RESULT);
847 }
848
849 static bool
850 parse_RIB (struct lexer *lexer)
851 {
852   return parse_integer_format (lexer, settings_set_input_integer_format);
853 }
854
855 static char *
856 show_RIB (const struct dataset *ds UNUSED)
857 {
858   return show_integer_format (settings_get_input_integer_format ());
859 }
860
861 static bool
862 parse_RRB (struct lexer *lexer)
863 {
864   return parse_real_format (lexer, settings_set_input_float_format);
865 }
866
867 static char *
868 show_RRB (const struct dataset *ds UNUSED)
869 {
870   return show_real_format (settings_get_input_float_format ());
871 }
872
873 static bool
874 parse_SAFER (struct lexer *lexer)
875 {
876   bool ok = force_parse_enum (lexer, "ON", true, "YES", true) != -1;
877   if (ok)
878     settings_set_safer_mode ();
879   return ok;
880 }
881
882 static char *
883 show_SAFER (const struct dataset *ds UNUSED)
884 {
885   return xstrdup (settings_get_safer_mode () ? "ON" : "OFF");
886 }
887
888 static bool
889 parse_SCOMPRESSION (struct lexer *lexer)
890 {
891   int value = force_parse_bool (lexer);
892   if (value >= 0)
893     settings_set_scompression (value);
894   return value >= 0;
895 }
896
897 static char *
898 show_SCOMPRESSION (const struct dataset *ds UNUSED)
899 {
900   return xstrdup (settings_get_scompression () ? "ON" : "OFF");
901 }
902
903 static bool
904 parse_SEED (struct lexer *lexer)
905 {
906   if (lex_match_id (lexer, "RANDOM"))
907     set_rng (time (0));
908   else
909     {
910       if (!lex_force_num (lexer))
911         return false;
912       set_rng (lex_number (lexer));
913       lex_get (lexer);
914     }
915
916   return true;
917 }
918
919 static bool
920 parse_SMALL (struct lexer *lexer)
921 {
922   if (!lex_force_num (lexer))
923     return false;
924   settings_set_small (lex_number (lexer));
925   lex_get (lexer);
926   return true;
927 }
928
929 static char *
930 show_SMALL (const struct dataset *ds UNUSED)
931 {
932   char buf[DBL_BUFSIZE_BOUND];
933   if (dtoastr (buf, sizeof buf, 0, 0, settings_get_small ()) < 0)
934     abort ();
935   return xstrdup (buf);
936 }
937
938 static char *
939 show_SUBTITLE (const struct dataset *ds UNUSED)
940 {
941   return xstrdup (output_get_subtitle ());
942 }
943
944 static char *
945 show_TEMPDIR (const struct dataset *ds UNUSED)
946 {
947   return xstrdup (temp_dir_name ());
948 }
949
950 static char *
951 show_TITLE (const struct dataset *ds UNUSED)
952 {
953   return xstrdup (output_get_title ());
954 }
955
956 static bool
957 parse_TNUMBERS (struct lexer *lexer)
958 {
959   int value = force_parse_enum (lexer,
960                                 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
961                                 "VALUES", SETTINGS_VALUE_SHOW_VALUE,
962                                 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
963   if (value >= 0)
964     settings_set_show_values (value);
965   return value >= 0;
966 }
967
968 static char *
969 show_TNUMBERS (const struct dataset *ds UNUSED)
970 {
971   enum settings_value_show tnumbers = settings_get_show_values ();
972   return xstrdup (tnumbers == SETTINGS_VALUE_SHOW_LABEL ? "LABELS"
973                   : tnumbers == SETTINGS_VALUE_SHOW_VALUE ? "VALUES"
974                   : "BOTH");
975 }
976
977 static bool
978 parse_TVARS (struct lexer *lexer)
979 {
980   int value = force_parse_enum (lexer,
981                                 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
982                                 "NAMES", SETTINGS_VALUE_SHOW_VALUE,
983                                 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
984   if (value >= 0)
985     settings_set_show_variables (value);
986   return value >= 0;
987 }
988
989 static char *
990 show_TVARS (const struct dataset *ds UNUSED)
991 {
992   enum settings_value_show tvars = settings_get_show_variables ();
993   return xstrdup (tvars == SETTINGS_VALUE_SHOW_LABEL ? "LABELS"
994                   : tvars == SETTINGS_VALUE_SHOW_VALUE ? "NAMES"
995                   : "BOTH");
996 }
997
998 static bool
999 parse_TLOOK (struct lexer *lexer)
1000 {
1001   if (lex_match_id (lexer, "NONE"))
1002     pivot_table_look_set_default (pivot_table_look_builtin_default ());
1003   else if (lex_is_string (lexer))
1004     {
1005       struct pivot_table_look *look;
1006       char *error = pivot_table_look_read (lex_tokcstr (lexer), &look);
1007       lex_get (lexer);
1008
1009       if (error)
1010         {
1011           msg (SE, "%s", error);
1012           free (error);
1013           return false;
1014         }
1015
1016       pivot_table_look_set_default (look);
1017       pivot_table_look_unref (look);
1018     }
1019
1020   return true;
1021 }
1022
1023 static bool
1024 parse_UNDEFINED (struct lexer *lexer)
1025 {
1026   int value = force_parse_enum (lexer,
1027                                 "WARN", true,
1028                                 "NOWARN", false);
1029   if (value >= 0)
1030     settings_set_undefined (value);
1031   return value >= 0;
1032 }
1033
1034 static char *
1035 show_UNDEFINED (const struct dataset *ds UNUSED)
1036 {
1037   return xstrdup (settings_get_undefined () ? "WARN" : "NOWARN");
1038 }
1039
1040 static char *
1041 show_VERSION (const struct dataset *ds UNUSED)
1042 {
1043   return strdup (announced_version);
1044 }
1045
1046 static char *
1047 show_WEIGHT (const struct dataset *ds)
1048 {
1049   const struct variable *var = dict_get_weight (dataset_dict (ds));
1050   return xstrdup (var != NULL ? var_get_name (var) : "OFF");
1051 }
1052
1053 static bool
1054 parse_WIB (struct lexer *lexer)
1055 {
1056   return parse_integer_format (lexer, settings_set_output_integer_format);
1057 }
1058
1059 static char *
1060 show_WIB (const struct dataset *ds UNUSED)
1061 {
1062   return show_integer_format (settings_get_output_integer_format ());
1063 }
1064
1065 static bool
1066 parse_WRB (struct lexer *lexer)
1067 {
1068   return parse_real_format (lexer, settings_set_output_float_format);
1069 }
1070
1071 static char *
1072 show_WRB (const struct dataset *ds UNUSED)
1073 {
1074   return show_real_format (settings_get_output_float_format ());
1075 }
1076
1077 static bool
1078 parse_WIDTH (struct lexer *lexer)
1079 {
1080   if (lex_match_id (lexer, "NARROW"))
1081     settings_set_viewwidth (79);
1082   else if (lex_match_id (lexer, "WIDE"))
1083     settings_set_viewwidth (131);
1084   else
1085     {
1086       if (!lex_force_int_range (lexer, "WIDTH", 40, INT_MAX))
1087         return false;
1088       settings_set_viewwidth (lex_integer (lexer));
1089       lex_get (lexer);
1090     }
1091
1092   return true;
1093 }
1094
1095 static char *
1096 show_WIDTH (const struct dataset *ds UNUSED)
1097 {
1098   return xasprintf ("%d", settings_get_viewwidth ());
1099 }
1100
1101 static bool
1102 parse_WORKSPACE (struct lexer *lexer)
1103 {
1104   if (!lex_force_int_range (lexer, "WORKSPACE",
1105                             settings_get_testing_mode () ? 1 : 1024,
1106                             INT_MAX))
1107     return false;
1108   int workspace = lex_integer (lexer);
1109   lex_get (lexer);
1110   settings_set_workspace (MIN (workspace, INT_MAX / 1024) * 1024);
1111   return true;
1112 }
1113
1114 static char *
1115 show_WORKSPACE (const struct dataset *ds UNUSED)
1116 {
1117   size_t ws = settings_get_workspace () / 1024L;
1118   return xasprintf ("%zu", ws);
1119 }
1120 \f
1121 static char *
1122 show_DIRECTORY (const struct dataset *ds UNUSED)
1123 {
1124   char *buf = NULL;
1125   char *wd = NULL;
1126   size_t len = 256;
1127
1128   do
1129     {
1130       len <<= 1;
1131       buf = xrealloc (buf, len);
1132     }
1133   while (NULL == (wd = getcwd (buf, len)));
1134
1135   return wd;
1136 }
1137
1138 static char *
1139 show_N (const struct dataset *ds)
1140 {
1141   const struct casereader *reader = dataset_source (ds);
1142   return (reader
1143           ? xasprintf ("%lld", (long long int) casereader_count_cases (reader))
1144           : xstrdup (_("Unknown")));
1145 }
1146
1147 static void
1148 do_show (const struct dataset *ds, const struct setting *s)
1149 {
1150   char *value = s->show (ds);
1151   msg (SN, _("%s is %s."), s->name, value ? value : _("empty"));
1152   free (value);
1153 }
1154
1155 static void
1156 show_warranty (const struct dataset *ds UNUSED)
1157 {
1158   fputs (lack_of_warranty, stdout);
1159 }
1160
1161 static void
1162 show_copying (const struct dataset *ds UNUSED)
1163 {
1164   fputs (copyleft, stdout);
1165 }
1166
1167 static void
1168 add_row (struct pivot_table *table, const char *attribute,
1169          const char *value)
1170 {
1171   int row = pivot_category_create_leaf (table->dimensions[0]->root,
1172                                         pivot_value_new_text (attribute));
1173   if (value)
1174     pivot_table_put1 (table, row, pivot_value_new_user_text (value, -1));
1175 }
1176
1177 static void
1178 show_system (const struct dataset *ds UNUSED)
1179 {
1180   struct pivot_table *table = pivot_table_create (N_("System Information"));
1181   pivot_dimension_create (table, PIVOT_AXIS_ROW, N_("Attribute"));
1182
1183   add_row (table, N_("Version"), version);
1184   add_row (table, N_("Host System"), host_system);
1185   add_row (table, N_("Build System"), build_system);
1186   add_row (table, N_("Locale Directory"), relocate (locale_dir));
1187   add_row (table, N_("Compiler Version"),
1188 #ifdef __VERSION__
1189            __VERSION__
1190 #else
1191            "Unknown"
1192 #endif
1193            );
1194   pivot_table_submit (table);
1195 }
1196 \f
1197 static const struct setting settings[] = {
1198   { "BASETEXTDIRECTION", parse_BASETEXTDIRECTION, NULL },
1199   { "BLANKS", parse_BLANKS, show_BLANKS },
1200   { "BLOCK", parse_BLOCK, NULL },
1201   { "BOX", parse_BOX, NULL },
1202   { "CACHE", parse_CACHE, NULL },
1203   { "CCA", parse_CCA, show_CCA },
1204   { "CCB", parse_CCB, show_CCB },
1205   { "CCC", parse_CCC, show_CCC },
1206   { "CCD", parse_CCD, show_CCD },
1207   { "CCE", parse_CCE, show_CCE },
1208   { "CELLSBREAK", parse_CELLSBREAK, NULL },
1209   { "CMPTRANS", parse_CMPTRANS, NULL },
1210   { "COMPRESSION", parse_COMPRESSION, NULL },
1211   { "CTEMPLATE", parse_CTEMPLATE, NULL },
1212   { "DECIMAL", parse_DECIMAL, show_DECIMAL },
1213   { "DIRECTORY", NULL, show_DIRECTORY },
1214   { "EPOCH", parse_EPOCH, show_EPOCH },
1215   { "ERRORS", parse_ERRORS, show_ERRORS },
1216   { "FORMAT", parse_FORMAT, show_FORMAT },
1217   { "FUZZBITS", parse_FUZZBITS, show_FUZZBITS },
1218   { "HEADER", parse_HEADER, NULL },
1219   { "INCLUDE", parse_INCLUDE, show_INCLUDE },
1220   { "JOURNAL", parse_JOURNAL, show_JOURNAL },
1221   { "LENGTH", parse_LENGTH, show_LENGTH },
1222   { "LOCALE", parse_LOCALE, show_LOCALE },
1223   { "MDISPLAY", parse_MDISPLAY, show_MDISPLAY },
1224   { "MESSAGES", parse_MESSAGES, show_MESSAGES },
1225   { "MEXPAND", parse_MEXPAND, show_MEXPAND },
1226   { "MITERATE", parse_MITERATE, show_MITERATE },
1227   { "MNEST", parse_MNEST, show_MNEST },
1228   { "MPRINT", parse_MPRINT, show_MPRINT },
1229   { "MXERRS", parse_MXERRS, show_MXERRS },
1230   { "MXLOOPS", parse_MXLOOPS, show_MXLOOPS },
1231   { "MXWARNS", parse_MXWARNS, show_MXWARNS },
1232   { "N", NULL, show_N },
1233   { "PRINTBACK", parse_PRINTBACK, show_PRINTBACK },
1234   { "RESULTS", parse_RESULTS, show_RESULTS },
1235   { "RIB", parse_RIB, show_RIB },
1236   { "RRB", parse_RRB, show_RRB },
1237   { "SAFER", parse_SAFER, show_SAFER },
1238   { "SCOMPRESSION", parse_SCOMPRESSION, show_SCOMPRESSION },
1239   { "SEED", parse_SEED, NULL },
1240   { "SMALL", parse_SMALL, show_SMALL },
1241   { "TEMPDIR", NULL, show_TEMPDIR },
1242   { "TNUMBERS", parse_TNUMBERS, show_TNUMBERS },
1243   { "TVARS", parse_TVARS, show_TVARS },
1244   { "TLOOK", parse_TLOOK, NULL },
1245   { "UNDEFINED", parse_UNDEFINED, show_UNDEFINED },
1246   { "VERSION", NULL, show_VERSION },
1247   { "WEIGHT", NULL, show_WEIGHT },
1248   { "WIB", parse_WIB, show_WIB },
1249   { "WRB", parse_WRB, show_WRB },
1250   { "WIDTH", parse_WIDTH, show_WIDTH },
1251   { "WORKSPACE", parse_WORKSPACE, show_WORKSPACE },
1252 };
1253 enum { N_SETTINGS = sizeof settings / sizeof *settings };
1254
1255 static bool
1256 parse_setting (struct lexer *lexer)
1257 {
1258   for (size_t i = 0; i < N_SETTINGS; i++)
1259     if (settings[i].set && match_subcommand (lexer, settings[i].name))
1260         return settings[i].set (lexer);
1261
1262   lex_error (lexer, NULL);
1263   return false;
1264 }
1265
1266 int
1267 cmd_set (struct lexer *lexer, struct dataset *ds UNUSED)
1268 {
1269   for (;;)
1270     {
1271       lex_match (lexer, T_SLASH);
1272       if (lex_token (lexer) == T_ENDCMD)
1273         break;
1274
1275       if (!parse_setting (lexer))
1276         return CMD_FAILURE;
1277     }
1278
1279   return CMD_SUCCESS;
1280 }
1281
1282 static void
1283 show_all (const struct dataset *ds)
1284 {
1285   for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1286     if (settings[i].show)
1287       do_show (ds, &settings[i]);
1288 }
1289
1290 static void
1291 show_all_cc (const struct dataset *ds)
1292 {
1293   for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1294     {
1295       const struct setting *s = &settings[i];
1296       if (s->show && !strncmp (s->name, "CC", 2))
1297         do_show (ds, s);
1298     }
1299 }
1300
1301 int
1302 cmd_show (struct lexer *lexer, struct dataset *ds)
1303 {
1304   if (lex_token (lexer) == T_ENDCMD)
1305     {
1306       show_all (ds);
1307       return CMD_SUCCESS;
1308     }
1309
1310   do
1311     {
1312       if (lex_match (lexer, T_ALL))
1313         show_all (ds);
1314       else if (lex_match_id (lexer, "CC"))
1315         show_all_cc (ds);
1316       else if (lex_match_id (lexer, "WARRANTY"))
1317         show_warranty (ds);
1318       else if (lex_match_id (lexer, "COPYING") || lex_match_id (lexer, "LICENSE"))
1319         show_copying (ds);
1320       else if (lex_match_id (lexer, "SYSTEM"))
1321         show_system (ds);
1322       else if (lex_match_id (lexer, "TITLE"))
1323         {
1324           struct setting s = { .name = "TITLE", .show = show_TITLE };
1325           do_show (ds, &s);
1326         }
1327       else if (lex_match_id (lexer, "SUBTITLE"))
1328         {
1329           struct setting s = { .name = "SUBTITLE", .show = show_SUBTITLE };
1330           do_show (ds, &s);
1331         }
1332       else if (lex_token (lexer) == T_ID)
1333         {
1334           int i;
1335
1336           for (i = 0; i < sizeof settings / sizeof *settings; i++)
1337             {
1338               const struct setting *s = &settings[i];
1339               if (s->show && lex_match_id (lexer, s->name))
1340                 {
1341                   do_show (ds, s);
1342                   goto found;
1343                 }
1344               }
1345           lex_error (lexer, NULL);
1346           return CMD_FAILURE;
1347
1348         found: ;
1349         }
1350       else
1351         {
1352           lex_error (lexer, NULL);
1353           return CMD_FAILURE;
1354         }
1355
1356       lex_match (lexer, T_SLASH);
1357     }
1358   while (lex_token (lexer) != T_ENDCMD);
1359
1360   return CMD_SUCCESS;
1361 }
1362 \f
1363 #define MAX_SAVED_SETTINGS 5
1364
1365 static struct settings *saved_settings[MAX_SAVED_SETTINGS];
1366 static int n_saved_settings;
1367
1368 int
1369 cmd_preserve (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
1370 {
1371   if (n_saved_settings < MAX_SAVED_SETTINGS)
1372     {
1373       saved_settings[n_saved_settings++] = settings_get ();
1374       return CMD_SUCCESS;
1375     }
1376   else
1377     {
1378       msg (SE, _("Too many %s commands without a %s: at most "
1379                  "%d levels of saved settings are allowed."),
1380            "PRESERVE", "RESTORE",
1381            MAX_SAVED_SETTINGS);
1382       return CMD_CASCADING_FAILURE;
1383     }
1384 }
1385
1386 int
1387 cmd_restore (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
1388 {
1389   if (n_saved_settings > 0)
1390     {
1391       struct settings *s = saved_settings[--n_saved_settings];
1392       settings_set (s);
1393       settings_destroy (s);
1394       return CMD_SUCCESS;
1395     }
1396   else
1397     {
1398       msg (SE, _("%s without matching %s."), "RESTORE", "PRESERVE");
1399       return CMD_FAILURE;
1400     }
1401 }