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