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