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