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