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