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