SET: Improve error messages for SET CCx.
[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   char *error = settings_set_cc (lex_tokcstr (lexer), ccx);
319   if (error)
320     {
321       lex_error (lexer, "%s", error);
322       free (error);
323       return false;
324     }
325
326   lex_get (lexer);
327   return true;
328 }
329 \f
330 static bool
331 parse_BASETEXTDIRECTION (struct lexer *lexer)
332 {
333   return parse_unimplemented (lexer, "BASETEXTDIRECTION");
334 }
335
336 static bool
337 parse_BLANKS (struct lexer *lexer)
338 {
339   if (lex_match_id (lexer, "SYSMIS"))
340     settings_set_blanks (SYSMIS);
341   else
342     {
343       if (!lex_force_num (lexer))
344         return false;
345       settings_set_blanks (lex_number (lexer));
346       lex_get (lexer);
347     }
348   return true;
349 }
350
351 static char *
352 show_BLANKS (const struct dataset *ds UNUSED)
353 {
354   return (settings_get_blanks () == SYSMIS
355           ? xstrdup ("SYSMIS")
356           : xasprintf ("%.*g", DBL_DIG + 1, settings_get_blanks ()));
357 }
358
359 static bool
360 parse_BLOCK (struct lexer *lexer)
361 {
362   return parse_unimplemented (lexer, "BLOCK");
363 }
364
365 static bool
366 parse_BOX (struct lexer *lexer)
367 {
368   return parse_unimplemented (lexer, "BOX");
369 }
370
371 static bool
372 parse_CACHE (struct lexer *lexer)
373 {
374   return parse_unimplemented (lexer, "CACHE");
375 }
376
377 static bool
378 parse_CCA (struct lexer *lexer)
379 {
380   return parse_ccx (lexer, FMT_CCA);
381 }
382
383 static bool
384 parse_CCB (struct lexer *lexer)
385 {
386   return parse_ccx (lexer, FMT_CCB);
387 }
388
389 static bool
390 parse_CCC (struct lexer *lexer)
391 {
392   return parse_ccx (lexer, FMT_CCC);
393 }
394
395 static bool
396 parse_CCD (struct lexer *lexer)
397 {
398   return parse_ccx (lexer, FMT_CCD);
399 }
400
401 static bool
402 parse_CCE (struct lexer *lexer)
403 {
404   return parse_ccx (lexer, FMT_CCE);
405 }
406
407 static char *
408 show_cc (enum fmt_type type)
409 {
410   return fmt_number_style_to_string (fmt_settings_get_style (
411                                        settings_get_fmt_settings (), type));
412 }
413
414 static char *
415 show_CCA (const struct dataset *ds UNUSED)
416 {
417   return show_cc (FMT_CCA);
418 }
419
420 static char *
421 show_CCB (const struct dataset *ds UNUSED)
422 {
423   return show_cc (FMT_CCB);
424 }
425
426 static char *
427 show_CCC (const struct dataset *ds UNUSED)
428 {
429   return show_cc (FMT_CCC);
430 }
431
432 static char *
433 show_CCD (const struct dataset *ds UNUSED)
434 {
435   return show_cc (FMT_CCD);
436 }
437
438 static char *
439 show_CCE (const struct dataset *ds UNUSED)
440 {
441   return show_cc (FMT_CCE);
442 }
443
444 static bool
445 parse_CELLSBREAK (struct lexer *lexer)
446 {
447   return parse_unimplemented (lexer, "CELLSBREAK");
448 }
449
450 static bool
451 parse_CMPTRANS (struct lexer *lexer)
452 {
453   return parse_unimplemented (lexer, "CMPTRANS");
454 }
455
456 static bool
457 parse_COMPRESSION (struct lexer *lexer)
458 {
459   return parse_unimplemented (lexer, "COMPRESSION");
460 }
461
462 static bool
463 parse_CTEMPLATE (struct lexer *lexer)
464 {
465   return parse_unimplemented (lexer, "CTEMPLATE");
466 }
467
468 static bool
469 parse_DECIMAL (struct lexer *lexer)
470 {
471   int decimal_char = force_parse_enum (lexer,
472                                        "DOT", '.',
473                                        "COMMA", ',');
474   if (decimal_char != -1)
475     settings_set_decimal_char (decimal_char);
476   return decimal_char != -1;
477 }
478
479 static char *
480 show_DECIMAL (const struct dataset *ds UNUSED)
481 {
482   return xasprintf ("`%c'", settings_get_fmt_settings ()->decimal);
483 }
484
485 static bool
486 parse_EPOCH (struct lexer *lexer)
487 {
488   if (lex_match_id (lexer, "AUTOMATIC"))
489     settings_set_epoch (-1);
490   else if (lex_is_integer (lexer))
491     {
492       if (!lex_force_int_range (lexer, "EPOCH", 1500, INT_MAX))
493         return false;
494       settings_set_epoch (lex_integer (lexer));
495       lex_get (lexer);
496     }
497   else
498     {
499       lex_error (lexer, _("Syntax error expecting %s or year."), "AUTOMATIC");
500       return false;
501     }
502
503   return true;
504 }
505
506 static char *
507 show_EPOCH (const struct dataset *ds UNUSED)
508 {
509   return xasprintf ("%d", settings_get_epoch ());
510 }
511
512 static bool
513 parse_ERRORS (struct lexer *lexer)
514 {
515   return parse_output_routing (lexer, SETTINGS_OUTPUT_ERROR);
516 }
517
518 static char *
519 show_ERRORS (const struct dataset *ds UNUSED)
520 {
521   return show_output_routing (SETTINGS_OUTPUT_ERROR);
522 }
523
524 static bool
525 parse_FORMAT (struct lexer *lexer)
526 {
527   int start = subcommand_start_ofs (lexer);
528   struct fmt_spec fmt;
529
530   if (!parse_format_specifier (lexer, &fmt))
531     return false;
532
533   char *error = fmt_check_output__ (&fmt);
534   if (error)
535     {
536       lex_next_error (lexer, -1, -1, "%s", error);
537       free (error);
538       return false;
539     }
540
541   int end = lex_ofs (lexer) - 1;
542   if (fmt_is_string (fmt.type))
543     {
544       char str[FMT_STRING_LEN_MAX + 1];
545       lex_ofs_error (lexer, start, end,
546                      _("%s requires numeric output format as an argument.  "
547                        "Specified format %s is of type string."),
548                      "FORMAT", fmt_to_string (&fmt, str));
549       return false;
550     }
551
552   settings_set_format (&fmt);
553   return true;
554 }
555
556 static char *
557 show_FORMAT (const struct dataset *ds UNUSED)
558 {
559   char str[FMT_STRING_LEN_MAX + 1];
560   return xstrdup (fmt_to_string (settings_get_format (), str));
561 }
562
563 static bool
564 parse_FUZZBITS (struct lexer *lexer)
565 {
566   if (!lex_force_int_range (lexer, "FUZZITS", 0, 20))
567     return false;
568   settings_set_fuzzbits (lex_integer (lexer));
569   lex_get (lexer);
570   return true;
571 }
572
573 static char *
574 show_FUZZBITS (const struct dataset *ds UNUSED)
575 {
576   return xasprintf ("%d", settings_get_fuzzbits ());
577 }
578
579 static bool
580 parse_HEADER (struct lexer *lexer)
581 {
582   return parse_unimplemented (lexer, "HEADER");
583 }
584
585 static bool
586 parse_INCLUDE (struct lexer *lexer)
587 {
588   int include = force_parse_bool (lexer);
589   if (include != -1)
590     settings_set_include (include);
591   return include != -1;
592 }
593
594 static char *
595 show_INCLUDE (const struct dataset *ds UNUSED)
596 {
597   return xstrdup (settings_get_include () ? "ON" : "OFF");
598 }
599
600 static bool
601 parse_JOURNAL (struct lexer *lexer)
602 {
603   int b = parse_bool (lexer);
604   if (b == true)
605     journal_enable ();
606   else if (b == false)
607     journal_disable ();
608   else if (lex_is_string (lexer) || lex_token (lexer) == T_ID)
609     {
610       char *filename = utf8_to_filename (lex_tokcstr (lexer));
611       journal_set_file_name (filename);
612       free (filename);
613
614       lex_get (lexer);
615     }
616   else
617     {
618       lex_error (lexer, NULL);
619       return false;
620     }
621   return true;
622 }
623
624 static char *
625 show_JOURNAL (const struct dataset *ds UNUSED)
626 {
627   const char *enabled = journal_is_enabled () ? "ON" : "OFF";
628   const char *file_name = journal_get_file_name ();
629   return (file_name
630           ? xasprintf ("%s (%s)", enabled, file_name)
631           : xstrdup (enabled));
632 }
633
634 static bool
635 parse_LEADZERO (struct lexer *lexer)
636 {
637   int leadzero = force_parse_bool (lexer);
638   if (leadzero != -1)
639     settings_set_include_leading_zero (leadzero);
640   return leadzero != -1;
641 }
642
643 static char *
644 show_LEADZERO (const struct dataset *ds UNUSED)
645 {
646   bool leadzero = settings_get_fmt_settings ()->include_leading_zero;
647   return xstrdup (leadzero ? "ON" : "OFF");
648 }
649
650 static bool
651 parse_LENGTH (struct lexer *lexer)
652 {
653   int page_length;
654
655   if (lex_match_id (lexer, "NONE"))
656     page_length = -1;
657   else
658     {
659       if (!lex_force_int_range (lexer, "LENGTH", 1, INT_MAX))
660         return false;
661       page_length = lex_integer (lexer);
662       lex_get (lexer);
663     }
664
665   if (page_length != -1)
666     settings_set_viewlength (page_length);
667
668   return true;
669 }
670
671 static char *
672 show_LENGTH (const struct dataset *ds UNUSED)
673 {
674   return xasprintf ("%d", settings_get_viewlength ());
675 }
676
677 static bool
678 parse_LOCALE (struct lexer *lexer)
679 {
680   if (!lex_force_string (lexer))
681     return false;
682
683   /* Try the argument as an encoding name, then as a locale name or alias. */
684   const char *s = lex_tokcstr (lexer);
685   if (valid_encoding (s))
686     set_default_encoding (s);
687   else if (!set_encoding_from_locale (s))
688     {
689       lex_error (lexer, _("%s is not a recognized encoding or locale name"), s);
690       return false;
691     }
692
693   lex_get (lexer);
694   return true;
695 }
696
697 static char *
698 show_LOCALE (const struct dataset *ds UNUSED)
699 {
700   return xstrdup (get_default_encoding ());
701 }
702
703 static bool
704 parse_MDISPLAY (struct lexer *lexer)
705 {
706   int mdisplay = force_parse_enum (lexer,
707                                    "TEXT", SETTINGS_MDISPLAY_TEXT,
708                                    "TABLES", SETTINGS_MDISPLAY_TABLES);
709   if (mdisplay >= 0)
710     settings_set_mdisplay (mdisplay);
711   return mdisplay >= 0;
712 }
713
714 static char *
715 show_MDISPLAY (const struct dataset *ds UNUSED)
716 {
717   return xstrdup (settings_get_mdisplay () == SETTINGS_MDISPLAY_TEXT
718                   ? "TEXT" : "TABLES");
719 }
720
721 static bool
722 parse_MESSAGES (struct lexer *lexer)
723 {
724   return parse_output_routing (lexer, SETTINGS_OUTPUT_NOTE);
725 }
726
727 static char *
728 show_MESSAGES (const struct dataset *ds UNUSED)
729 {
730   return show_output_routing (SETTINGS_OUTPUT_NOTE);
731 }
732
733 static bool
734 parse_MEXPAND (struct lexer *lexer)
735 {
736   int mexpand = force_parse_bool (lexer);
737   if (mexpand != -1)
738     settings_set_mexpand (mexpand);
739   return mexpand != -1;
740 }
741
742 static char *
743 show_MEXPAND (const struct dataset *ds UNUSED)
744 {
745   return xstrdup (settings_get_mexpand () ? "ON" : "OFF");
746 }
747
748 static bool
749 parse_MITERATE (struct lexer *lexer)
750 {
751   if (!lex_force_int_range (lexer, "MITERATE", 1, INT_MAX))
752     return false;
753   settings_set_miterate (lex_integer (lexer));
754   lex_get (lexer);
755   return true;
756 }
757
758 static char *
759 show_MITERATE (const struct dataset *ds UNUSED)
760 {
761   return xasprintf ("%d", settings_get_miterate ());
762 }
763
764 static bool
765 parse_MNEST (struct lexer *lexer)
766 {
767   if (!lex_force_int_range (lexer, "MNEST", 1, INT_MAX))
768     return false;
769   settings_set_mnest (lex_integer (lexer));
770   lex_get (lexer);
771   return true;
772 }
773
774 static char *
775 show_MNEST (const struct dataset *ds UNUSED)
776 {
777   return xasprintf ("%d", settings_get_mnest ());
778 }
779
780 static bool
781 parse_MPRINT (struct lexer *lexer)
782 {
783   int mprint = force_parse_bool (lexer);
784   if (mprint != -1)
785     settings_set_mprint (mprint);
786   return mprint != -1;
787 }
788
789 static char *
790 show_MPRINT (const struct dataset *ds UNUSED)
791 {
792   return xstrdup (settings_get_mprint () ? "ON" : "OFF");
793 }
794
795 static bool
796 parse_MXERRS (struct lexer *lexer)
797 {
798   if (!lex_force_int_range (lexer, "MXERRS", 1, INT_MAX))
799     return false;
800   settings_set_max_messages (MSG_S_ERROR, lex_integer (lexer));
801   lex_get (lexer);
802   return true;
803 }
804
805 static char *
806 show_MXERRS (const struct dataset *ds UNUSED)
807 {
808   return xasprintf ("%d", settings_get_max_messages (MSG_S_ERROR));
809 }
810
811 static bool
812 parse_MXLOOPS (struct lexer *lexer)
813 {
814   if (!lex_force_int_range (lexer, "MXLOOPS", 1, INT_MAX))
815     return false;
816   settings_set_mxloops (lex_integer (lexer));
817   lex_get (lexer);
818   return true;
819 }
820
821 static char *
822 show_MXLOOPS (const struct dataset *ds UNUSED)
823 {
824   return xasprintf ("%d", settings_get_mxloops ());
825 }
826
827 static bool
828 parse_MXWARNS (struct lexer *lexer)
829 {
830   if (!lex_force_int_range (lexer, "MXWARNS", 0, INT_MAX))
831     return false;
832   settings_set_max_messages (MSG_S_WARNING, lex_integer (lexer));
833   lex_get (lexer);
834   return true;
835 }
836
837 static char *
838 show_MXWARNS (const struct dataset *ds UNUSED)
839 {
840   return xasprintf ("%d", settings_get_max_messages (MSG_S_WARNING));
841 }
842
843 static bool
844 parse_PRINTBACK (struct lexer *lexer)
845 {
846   return parse_output_routing (lexer, SETTINGS_OUTPUT_SYNTAX);
847 }
848
849 static char *
850 show_PRINTBACK (const struct dataset *ds UNUSED)
851 {
852   return show_output_routing (SETTINGS_OUTPUT_SYNTAX);
853 }
854
855 static bool
856 parse_RESULTS (struct lexer *lexer)
857 {
858   return parse_output_routing (lexer, SETTINGS_OUTPUT_RESULT);
859 }
860
861 static char *
862 show_RESULTS (const struct dataset *ds UNUSED)
863 {
864   return show_output_routing (SETTINGS_OUTPUT_RESULT);
865 }
866
867 static bool
868 parse_RIB (struct lexer *lexer)
869 {
870   return parse_integer_format (lexer, settings_set_input_integer_format);
871 }
872
873 static char *
874 show_RIB (const struct dataset *ds UNUSED)
875 {
876   return show_integer_format (settings_get_input_integer_format ());
877 }
878
879 static bool
880 parse_RRB (struct lexer *lexer)
881 {
882   return parse_real_format (lexer, settings_set_input_float_format);
883 }
884
885 static char *
886 show_RRB (const struct dataset *ds UNUSED)
887 {
888   return show_real_format (settings_get_input_float_format ());
889 }
890
891 static bool
892 parse_SAFER (struct lexer *lexer)
893 {
894   bool ok = force_parse_enum (lexer, "ON", true, "YES", true) != -1;
895   if (ok)
896     settings_set_safer_mode ();
897   return ok;
898 }
899
900 static char *
901 show_SAFER (const struct dataset *ds UNUSED)
902 {
903   return xstrdup (settings_get_safer_mode () ? "ON" : "OFF");
904 }
905
906 static bool
907 parse_SCOMPRESSION (struct lexer *lexer)
908 {
909   int value = force_parse_bool (lexer);
910   if (value >= 0)
911     settings_set_scompression (value);
912   return value >= 0;
913 }
914
915 static char *
916 show_SCOMPRESSION (const struct dataset *ds UNUSED)
917 {
918   return xstrdup (settings_get_scompression () ? "ON" : "OFF");
919 }
920
921 static bool
922 parse_SEED (struct lexer *lexer)
923 {
924   if (lex_match_id (lexer, "RANDOM"))
925     set_rng (time (0));
926   else
927     {
928       if (!lex_force_num (lexer))
929         return false;
930       set_rng (lex_number (lexer));
931       lex_get (lexer);
932     }
933
934   return true;
935 }
936
937 static bool
938 parse_SMALL (struct lexer *lexer)
939 {
940   if (!lex_force_num (lexer))
941     return false;
942   settings_set_small (lex_number (lexer));
943   lex_get (lexer);
944   return true;
945 }
946
947 static char *
948 show_SMALL (const struct dataset *ds UNUSED)
949 {
950   char buf[DBL_BUFSIZE_BOUND];
951   if (dtoastr (buf, sizeof buf, 0, 0, settings_get_small ()) < 0)
952     abort ();
953   return xstrdup (buf);
954 }
955
956 static char *
957 show_SUBTITLE (const struct dataset *ds UNUSED)
958 {
959   return xstrdup (output_get_subtitle ());
960 }
961
962 static char *
963 show_TEMPDIR (const struct dataset *ds UNUSED)
964 {
965   return xstrdup (temp_dir_name ());
966 }
967
968 static char *
969 show_TITLE (const struct dataset *ds UNUSED)
970 {
971   return xstrdup (output_get_title ());
972 }
973
974 static bool
975 parse_TNUMBERS (struct lexer *lexer)
976 {
977   int value = force_parse_enum (lexer,
978                                 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
979                                 "VALUES", SETTINGS_VALUE_SHOW_VALUE,
980                                 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
981   if (value >= 0)
982     settings_set_show_values (value);
983   return value >= 0;
984 }
985
986 static char *
987 show_TNUMBERS (const struct dataset *ds UNUSED)
988 {
989   enum settings_value_show tnumbers = settings_get_show_values ();
990   return xstrdup (tnumbers == SETTINGS_VALUE_SHOW_LABEL ? "LABELS"
991                   : tnumbers == SETTINGS_VALUE_SHOW_VALUE ? "VALUES"
992                   : "BOTH");
993 }
994
995 static bool
996 parse_TVARS (struct lexer *lexer)
997 {
998   int value = force_parse_enum (lexer,
999                                 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
1000                                 "NAMES", SETTINGS_VALUE_SHOW_VALUE,
1001                                 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
1002   if (value >= 0)
1003     settings_set_show_variables (value);
1004   return value >= 0;
1005 }
1006
1007 static char *
1008 show_TVARS (const struct dataset *ds UNUSED)
1009 {
1010   enum settings_value_show tvars = settings_get_show_variables ();
1011   return xstrdup (tvars == SETTINGS_VALUE_SHOW_LABEL ? "LABELS"
1012                   : tvars == SETTINGS_VALUE_SHOW_VALUE ? "NAMES"
1013                   : "BOTH");
1014 }
1015
1016 static bool
1017 parse_TLOOK (struct lexer *lexer)
1018 {
1019   if (lex_match_id (lexer, "NONE"))
1020     pivot_table_look_set_default (pivot_table_look_builtin_default ());
1021   else if (lex_is_string (lexer))
1022     {
1023       struct pivot_table_look *look;
1024       char *error = pivot_table_look_read (lex_tokcstr (lexer), &look);
1025       lex_get (lexer);
1026
1027       if (error)
1028         {
1029           msg (SE, "%s", error);
1030           free (error);
1031           return false;
1032         }
1033
1034       pivot_table_look_set_default (look);
1035       pivot_table_look_unref (look);
1036     }
1037
1038   return true;
1039 }
1040
1041 static bool
1042 parse_UNDEFINED (struct lexer *lexer)
1043 {
1044   int value = force_parse_enum (lexer,
1045                                 "WARN", true,
1046                                 "NOWARN", false);
1047   if (value >= 0)
1048     settings_set_undefined (value);
1049   return value >= 0;
1050 }
1051
1052 static char *
1053 show_UNDEFINED (const struct dataset *ds UNUSED)
1054 {
1055   return xstrdup (settings_get_undefined () ? "WARN" : "NOWARN");
1056 }
1057
1058 static char *
1059 show_VERSION (const struct dataset *ds UNUSED)
1060 {
1061   return strdup (announced_version);
1062 }
1063
1064 static char *
1065 show_WEIGHT (const struct dataset *ds)
1066 {
1067   const struct variable *var = dict_get_weight (dataset_dict (ds));
1068   return xstrdup (var != NULL ? var_get_name (var) : "OFF");
1069 }
1070
1071 static bool
1072 parse_WIB (struct lexer *lexer)
1073 {
1074   return parse_integer_format (lexer, settings_set_output_integer_format);
1075 }
1076
1077 static char *
1078 show_WIB (const struct dataset *ds UNUSED)
1079 {
1080   return show_integer_format (settings_get_output_integer_format ());
1081 }
1082
1083 static bool
1084 parse_WRB (struct lexer *lexer)
1085 {
1086   return parse_real_format (lexer, settings_set_output_float_format);
1087 }
1088
1089 static char *
1090 show_WRB (const struct dataset *ds UNUSED)
1091 {
1092   return show_real_format (settings_get_output_float_format ());
1093 }
1094
1095 static bool
1096 parse_WIDTH (struct lexer *lexer)
1097 {
1098   if (lex_match_id (lexer, "NARROW"))
1099     settings_set_viewwidth (79);
1100   else if (lex_match_id (lexer, "WIDE"))
1101     settings_set_viewwidth (131);
1102   else
1103     {
1104       if (!lex_force_int_range (lexer, "WIDTH", 40, INT_MAX))
1105         return false;
1106       settings_set_viewwidth (lex_integer (lexer));
1107       lex_get (lexer);
1108     }
1109
1110   return true;
1111 }
1112
1113 static char *
1114 show_WIDTH (const struct dataset *ds UNUSED)
1115 {
1116   return xasprintf ("%d", settings_get_viewwidth ());
1117 }
1118
1119 static bool
1120 parse_WORKSPACE (struct lexer *lexer)
1121 {
1122   if (!lex_force_int_range (lexer, "WORKSPACE",
1123                             settings_get_testing_mode () ? 1 : 1024,
1124                             INT_MAX))
1125     return false;
1126   int workspace = lex_integer (lexer);
1127   lex_get (lexer);
1128   settings_set_workspace (MIN (workspace, INT_MAX / 1024) * 1024);
1129   return true;
1130 }
1131
1132 static char *
1133 show_WORKSPACE (const struct dataset *ds UNUSED)
1134 {
1135   size_t ws = settings_get_workspace () / 1024L;
1136   return xasprintf ("%zu", ws);
1137 }
1138 \f
1139 static char *
1140 show_DIRECTORY (const struct dataset *ds UNUSED)
1141 {
1142   char *buf = NULL;
1143   char *wd = NULL;
1144   size_t len = 256;
1145
1146   do
1147     {
1148       len <<= 1;
1149       buf = xrealloc (buf, len);
1150     }
1151   while (NULL == (wd = getcwd (buf, len)));
1152
1153   return wd;
1154 }
1155
1156 static char *
1157 show_N (const struct dataset *ds)
1158 {
1159   const struct casereader *reader = dataset_source (ds);
1160   return (reader
1161           ? xasprintf ("%lld", (long long int) casereader_count_cases (reader))
1162           : xstrdup (_("Unknown")));
1163 }
1164
1165 static void
1166 do_show (const struct dataset *ds, const struct setting *s,
1167          struct pivot_table **ptp)
1168 {
1169   struct pivot_table *pt = *ptp;
1170   if (!pt)
1171     {
1172       pt = *ptp = pivot_table_create (N_("Settings"));
1173       pivot_dimension_create (pt, PIVOT_AXIS_ROW, N_("Setting"));
1174     }
1175
1176   struct pivot_value *name = pivot_value_new_user_text (s->name, SIZE_MAX);
1177   char *text = s->show (ds);
1178   if (!text)
1179     text = xstrdup("empty");
1180   struct pivot_value *value = pivot_value_new_user_text_nocopy (text);
1181
1182   int row = pivot_category_create_leaf (pt->dimensions[0]->root, name);
1183   pivot_table_put1 (pt, row, value);
1184 }
1185
1186 static void
1187 show_warranty (const struct dataset *ds UNUSED)
1188 {
1189   fputs (lack_of_warranty, stdout);
1190 }
1191
1192 static void
1193 show_copying (const struct dataset *ds UNUSED)
1194 {
1195   fputs (copyleft, stdout);
1196 }
1197
1198 static void
1199 add_row (struct pivot_table *table, const char *attribute,
1200          const char *value)
1201 {
1202   int row = pivot_category_create_leaf (table->dimensions[0]->root,
1203                                         pivot_value_new_text (attribute));
1204   if (value)
1205     pivot_table_put1 (table, row, pivot_value_new_user_text (value, -1));
1206 }
1207
1208 static void
1209 show_system (const struct dataset *ds UNUSED)
1210 {
1211   struct pivot_table *table = pivot_table_create (N_("System Information"));
1212   pivot_dimension_create (table, PIVOT_AXIS_ROW, N_("Attribute"));
1213
1214   add_row (table, N_("Version"), version);
1215   add_row (table, N_("Host System"), host_system);
1216   add_row (table, N_("Build System"), build_system);
1217   add_row (table, N_("Locale Directory"), relocate (locale_dir));
1218   add_row (table, N_("Compiler Version"),
1219 #ifdef __VERSION__
1220            __VERSION__
1221 #else
1222            "Unknown"
1223 #endif
1224            );
1225   pivot_table_submit (table);
1226 }
1227 \f
1228 static const struct setting settings[] = {
1229   { "BASETEXTDIRECTION", parse_BASETEXTDIRECTION, NULL },
1230   { "BLANKS", parse_BLANKS, show_BLANKS },
1231   { "BLOCK", parse_BLOCK, NULL },
1232   { "BOX", parse_BOX, NULL },
1233   { "CACHE", parse_CACHE, NULL },
1234   { "CCA", parse_CCA, show_CCA },
1235   { "CCB", parse_CCB, show_CCB },
1236   { "CCC", parse_CCC, show_CCC },
1237   { "CCD", parse_CCD, show_CCD },
1238   { "CCE", parse_CCE, show_CCE },
1239   { "CELLSBREAK", parse_CELLSBREAK, NULL },
1240   { "CMPTRANS", parse_CMPTRANS, NULL },
1241   { "COMPRESSION", parse_COMPRESSION, NULL },
1242   { "CTEMPLATE", parse_CTEMPLATE, NULL },
1243   { "DECIMAL", parse_DECIMAL, show_DECIMAL },
1244   { "DIRECTORY", NULL, show_DIRECTORY },
1245   { "EPOCH", parse_EPOCH, show_EPOCH },
1246   { "ERRORS", parse_ERRORS, show_ERRORS },
1247   { "FORMAT", parse_FORMAT, show_FORMAT },
1248   { "FUZZBITS", parse_FUZZBITS, show_FUZZBITS },
1249   { "HEADER", parse_HEADER, NULL },
1250   { "INCLUDE", parse_INCLUDE, show_INCLUDE },
1251   { "JOURNAL", parse_JOURNAL, show_JOURNAL },
1252   { "LEADZERO", parse_LEADZERO, show_LEADZERO },
1253   { "LENGTH", parse_LENGTH, show_LENGTH },
1254   { "LOCALE", parse_LOCALE, show_LOCALE },
1255   { "MDISPLAY", parse_MDISPLAY, show_MDISPLAY },
1256   { "MESSAGES", parse_MESSAGES, show_MESSAGES },
1257   { "MEXPAND", parse_MEXPAND, show_MEXPAND },
1258   { "MITERATE", parse_MITERATE, show_MITERATE },
1259   { "MNEST", parse_MNEST, show_MNEST },
1260   { "MPRINT", parse_MPRINT, show_MPRINT },
1261   { "MXERRS", parse_MXERRS, show_MXERRS },
1262   { "MXLOOPS", parse_MXLOOPS, show_MXLOOPS },
1263   { "MXWARNS", parse_MXWARNS, show_MXWARNS },
1264   { "N", NULL, show_N },
1265   { "PRINTBACK", parse_PRINTBACK, show_PRINTBACK },
1266   { "RESULTS", parse_RESULTS, show_RESULTS },
1267   { "RIB", parse_RIB, show_RIB },
1268   { "RRB", parse_RRB, show_RRB },
1269   { "SAFER", parse_SAFER, show_SAFER },
1270   { "SCOMPRESSION", parse_SCOMPRESSION, show_SCOMPRESSION },
1271   { "SEED", parse_SEED, NULL },
1272   { "SMALL", parse_SMALL, show_SMALL },
1273   { "TEMPDIR", NULL, show_TEMPDIR },
1274   { "TNUMBERS", parse_TNUMBERS, show_TNUMBERS },
1275   { "TVARS", parse_TVARS, show_TVARS },
1276   { "TLOOK", parse_TLOOK, NULL },
1277   { "UNDEFINED", parse_UNDEFINED, show_UNDEFINED },
1278   { "VERSION", NULL, show_VERSION },
1279   { "WEIGHT", NULL, show_WEIGHT },
1280   { "WIB", parse_WIB, show_WIB },
1281   { "WRB", parse_WRB, show_WRB },
1282   { "WIDTH", parse_WIDTH, show_WIDTH },
1283   { "WORKSPACE", parse_WORKSPACE, show_WORKSPACE },
1284 };
1285 enum { N_SETTINGS = sizeof settings / sizeof *settings };
1286
1287 static bool
1288 parse_setting (struct lexer *lexer)
1289 {
1290   for (size_t i = 0; i < N_SETTINGS; i++)
1291     if (settings[i].set && match_subcommand (lexer, settings[i].name))
1292         return settings[i].set (lexer);
1293
1294   lex_error (lexer, NULL);
1295   return false;
1296 }
1297
1298 int
1299 cmd_set (struct lexer *lexer, struct dataset *ds UNUSED)
1300 {
1301   for (;;)
1302     {
1303       lex_match (lexer, T_SLASH);
1304       if (lex_token (lexer) == T_ENDCMD)
1305         break;
1306
1307       if (!parse_setting (lexer))
1308         return CMD_FAILURE;
1309     }
1310
1311   return CMD_SUCCESS;
1312 }
1313
1314 static void
1315 show_all (const struct dataset *ds, struct pivot_table **ptp)
1316 {
1317   for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1318     if (settings[i].show)
1319       do_show (ds, &settings[i], ptp);
1320 }
1321
1322 static void
1323 show_all_cc (const struct dataset *ds, struct pivot_table **ptp)
1324 {
1325   for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1326     {
1327       const struct setting *s = &settings[i];
1328       if (s->show && !strncmp (s->name, "CC", 2))
1329         do_show (ds, s, ptp);
1330     }
1331 }
1332
1333 int
1334 cmd_show (struct lexer *lexer, struct dataset *ds)
1335 {
1336   struct pivot_table *pt = NULL;
1337   if (lex_token (lexer) == T_ENDCMD)
1338     {
1339       show_all (ds, &pt);
1340       pivot_table_submit (pt);
1341       return CMD_SUCCESS;
1342     }
1343
1344   do
1345     {
1346       if (lex_match (lexer, T_ALL))
1347         show_all (ds, &pt);
1348       else if (lex_match_id (lexer, "CC"))
1349         show_all_cc (ds, &pt);
1350       else if (lex_match_id (lexer, "WARRANTY"))
1351         show_warranty (ds);
1352       else if (lex_match_id (lexer, "COPYING") || lex_match_id (lexer, "LICENSE"))
1353         show_copying (ds);
1354       else if (lex_match_id (lexer, "SYSTEM"))
1355         show_system (ds);
1356       else if (lex_match_id (lexer, "TITLE"))
1357         {
1358           struct setting s = { .name = "TITLE", .show = show_TITLE };
1359           do_show (ds, &s, &pt);
1360         }
1361       else if (lex_match_id (lexer, "SUBTITLE"))
1362         {
1363           struct setting s = { .name = "SUBTITLE", .show = show_SUBTITLE };
1364           do_show (ds, &s, &pt);
1365         }
1366       else if (lex_token (lexer) == T_ID)
1367         {
1368           for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1369             {
1370               const struct setting *s = &settings[i];
1371               if (s->show && lex_match_id (lexer, s->name))
1372                 {
1373                   do_show (ds, s, &pt);
1374                   goto found;
1375                 }
1376               }
1377           lex_error (lexer, NULL);
1378           return CMD_FAILURE;
1379
1380         found: ;
1381         }
1382       else
1383         {
1384           lex_error (lexer, NULL);
1385           return CMD_FAILURE;
1386         }
1387
1388       lex_match (lexer, T_SLASH);
1389     }
1390   while (lex_token (lexer) != T_ENDCMD);
1391
1392   if (pt)
1393     pivot_table_submit (pt);
1394
1395   return CMD_SUCCESS;
1396 }
1397 \f
1398 #define MAX_SAVED_SETTINGS 5
1399
1400 static struct settings *saved_settings[MAX_SAVED_SETTINGS];
1401 static int n_saved_settings;
1402
1403 int
1404 cmd_preserve (struct lexer *lexer, struct dataset *ds UNUSED)
1405 {
1406   if (n_saved_settings < MAX_SAVED_SETTINGS)
1407     {
1408       saved_settings[n_saved_settings++] = settings_get ();
1409       return CMD_SUCCESS;
1410     }
1411   else
1412     {
1413       lex_next_error (lexer, -1, -1,
1414                       _("Too many %s commands without a %s: at most "
1415                         "%d levels of saved settings are allowed."),
1416                       "PRESERVE", "RESTORE",
1417                       MAX_SAVED_SETTINGS);
1418       return CMD_CASCADING_FAILURE;
1419     }
1420 }
1421
1422 int
1423 cmd_restore (struct lexer *lexer, struct dataset *ds UNUSED)
1424 {
1425   if (n_saved_settings > 0)
1426     {
1427       struct settings *s = saved_settings[--n_saved_settings];
1428       settings_set (s);
1429       settings_destroy (s);
1430       return CMD_SUCCESS;
1431     }
1432   else
1433     {
1434       lex_next_error (lexer, -1, -1,
1435                       _("%s without matching %s."), "RESTORE", "PRESERVE");
1436       return CMD_FAILURE;
1437     }
1438 }