lexer: New function lex_force_int_range().
[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   return parse_unimplemented (lexer, "MEXPAND");
494 }
495
496 static bool
497 parse_MITERATE (struct lexer *lexer)
498 {
499   return parse_unimplemented (lexer, "MITERATE");
500 }
501
502 static bool
503 parse_MNEST (struct lexer *lexer)
504 {
505   return parse_unimplemented (lexer, "MNEST");
506 }
507
508 static bool
509 parse_MPRINT (struct lexer *lexer)
510 {
511   return parse_unimplemented (lexer, "MPRINT");
512 }
513
514 static bool
515 parse_MXERRS (struct lexer *lexer)
516 {
517   int n;
518   if (!force_parse_int (lexer, &n))
519     return false;
520
521   if (n >= 1)
522     settings_set_max_messages (MSG_S_ERROR, n);
523   else
524     msg (SE, _("%s must be at least 1."), "MXERRS");
525   return true;
526 }
527
528 static bool
529 parse_MXLOOPS (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_mxloops (n);
537   else
538     msg (SE, _("%s must be at least 1."), "MXLOOPS");
539   return true;
540 }
541
542 static bool
543 parse_MXWARNS (struct lexer *lexer)
544 {
545   int n;
546   if (!force_parse_int (lexer, &n))
547     return false;
548
549   if (n >= 0)
550     settings_set_max_messages (MSG_S_WARNING, n);
551   else
552     msg (SE, _("%s must not be negative."), "MXWARNS");
553   return true;
554 }
555
556 static bool
557 parse_PRINTBACK (struct lexer *lexer)
558 {
559   return parse_output_routing (lexer, SETTINGS_OUTPUT_SYNTAX);
560 }
561
562 static bool
563 parse_RESULTS (struct lexer *lexer)
564 {
565   return parse_output_routing (lexer, SETTINGS_OUTPUT_RESULT);
566 }
567
568 static bool
569 parse_RIB (struct lexer *lexer)
570 {
571   return parse_integer_format (lexer, settings_set_input_integer_format);
572 }
573
574 static bool
575 parse_RRB (struct lexer *lexer)
576 {
577   return parse_real_format (lexer, settings_set_input_float_format);
578 }
579
580 static bool
581 parse_SAFER (struct lexer *lexer)
582 {
583   bool ok = force_parse_enum (lexer, "ON", true, "YES", true) != -1;
584   if (ok)
585     settings_set_safer_mode ();
586   return ok;
587 }
588
589 static bool
590 parse_SCOMPRESSION (struct lexer *lexer)
591 {
592   int value = force_parse_bool (lexer);
593   if (value >= 0)
594     settings_set_scompression (value);
595   return value >= 0;
596 }
597
598 static bool
599 parse_SEED (struct lexer *lexer)
600 {
601   if (lex_match_id (lexer, "RANDOM"))
602     set_rng (time (0));
603   else
604     {
605       if (!lex_force_num (lexer))
606         return false;
607       set_rng (lex_number (lexer));
608       lex_get (lexer);
609     }
610
611   return true;
612 }
613
614 static bool
615 parse_SMALL (struct lexer *lexer)
616 {
617   if (!lex_force_num (lexer))
618     return false;
619   settings_set_small (lex_number (lexer));
620   lex_get (lexer);
621   return true;
622 }
623
624 static bool
625 parse_TNUMBERS (struct lexer *lexer)
626 {
627   int value = force_parse_enum (lexer,
628                                 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
629                                 "VALUES", SETTINGS_VALUE_SHOW_VALUE,
630                                 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
631   if (value >= 0)
632     settings_set_show_values (value);
633   return value >= 0;
634 }
635
636 static bool
637 parse_TVARS (struct lexer *lexer)
638 {
639   int value = force_parse_enum (lexer,
640                                 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
641                                 "NAMES", SETTINGS_VALUE_SHOW_VALUE,
642                                 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
643   if (value >= 0)
644     settings_set_show_variables (value);
645   return value >= 0;
646 }
647
648 static bool
649 parse_TLOOK (struct lexer *lexer)
650 {
651   if (lex_match_id (lexer, "NONE"))
652     pivot_table_look_set_default (pivot_table_look_builtin_default ());
653   else if (lex_is_string (lexer))
654     {
655       struct pivot_table_look *look;
656       char *error = pivot_table_look_read (lex_tokcstr (lexer), &look);
657       lex_get (lexer);
658
659       if (error)
660         {
661           msg (SE, "%s", error);
662           free (error);
663           return false;
664         }
665
666       pivot_table_look_set_default (look);
667       pivot_table_look_unref (look);
668     }
669
670   return true;
671 }
672
673 static bool
674 parse_UNDEFINED (struct lexer *lexer)
675 {
676   int value = force_parse_enum (lexer,
677                                 "WARN", true,
678                                 "NOWARN", false);
679   if (value >= 0)
680     settings_set_undefined (value);
681   return value >= 0;
682 }
683
684 static bool
685 parse_WIB (struct lexer *lexer)
686 {
687   return parse_integer_format (lexer, settings_set_output_integer_format);
688 }
689
690 static bool
691 parse_WRB (struct lexer *lexer)
692 {
693   return parse_real_format (lexer, settings_set_output_float_format);
694 }
695
696 static bool
697 parse_WIDTH (struct lexer *lexer)
698 {
699   if (lex_match_id (lexer, "NARROW"))
700     settings_set_viewwidth (79);
701   else if (lex_match_id (lexer, "WIDE"))
702     settings_set_viewwidth (131);
703   else
704     {
705       if (!lex_force_int_range (lexer, "WIDTH", 40, INT_MAX))
706         return false;
707       settings_set_viewwidth (lex_integer (lexer));
708       lex_get (lexer);
709     }
710
711   return true;
712 }
713
714 static bool
715 parse_WORKSPACE (struct lexer *lexer)
716 {
717   if (!lex_force_int_range (lexer, "WORKSPACE",
718                             settings_get_testing_mode () ? 1 : 1024,
719                             INT_MAX))
720     return false;
721   int workspace = lex_integer (lexer);
722   lex_get (lexer);
723   settings_set_workspace (MIN (workspace, INT_MAX / 1024) * 1024);
724   return true;
725 }
726 \f
727 static bool
728 parse_setting (struct lexer *lexer)
729 {
730   struct setting
731     {
732       const char *name;
733       bool (*function) (struct lexer *);
734     };
735   const struct setting settings[] = {
736     { "BASETEXTDIRECTION", parse_BASETEXTDIRECTION },
737     { "BLANKS", parse_BLANKS },
738     { "BLOCK", parse_BLOCK },
739     { "BOX", parse_BOX },
740     { "CACHE", parse_CACHE },
741     { "CCA", parse_CCA },
742     { "CCB", parse_CCB },
743     { "CCC", parse_CCC },
744     { "CCD", parse_CCD },
745     { "CCE", parse_CCE },
746     { "CELLSBREAK", parse_CELLSBREAK },
747     { "CMPTRANS", parse_CMPTRANS },
748     { "COMPRESSION", parse_COMPRESSION },
749     { "CTEMPLATE", parse_CTEMPLATE },
750     { "DECIMAL", parse_DECIMAL },
751     { "EPOCH", parse_EPOCH },
752     { "ERRORS", parse_ERRORS },
753     { "FORMAT", parse_FORMAT },
754     { "FUZZBITS", parse_FUZZBITS },
755     { "HEADER", parse_HEADER },
756     { "INCLUDE", parse_INCLUDE },
757     { "JOURNAL", parse_JOURNAL },
758     { "LENGTH", parse_LENGTH },
759     { "LOCALE", parse_LOCALE },
760     { "MESSAGES", parse_MESSAGES },
761     { "MEXPAND", parse_MEXPAND },
762     { "MITERATE", parse_MITERATE },
763     { "MNEST", parse_MNEST },
764     { "MPRINT", parse_MPRINT },
765     { "MXERRS", parse_MXERRS },
766     { "MXLOOPS", parse_MXLOOPS },
767     { "MXWARNS", parse_MXWARNS },
768     { "PRINTBACK", parse_PRINTBACK },
769     { "RESULTS", parse_RESULTS },
770     { "RIB", parse_RIB },
771     { "RRB", parse_RRB },
772     { "SAFER", parse_SAFER },
773     { "SCOMPRESSION", parse_SCOMPRESSION },
774     { "SEED", parse_SEED },
775     { "SMALL", parse_SMALL },
776     { "TNUMBERS", parse_TNUMBERS },
777     { "TVARS", parse_TVARS },
778     { "TLOOK", parse_TLOOK },
779     { "UNDEFINED", parse_UNDEFINED },
780     { "WIB", parse_WIB },
781     { "WRB", parse_WRB },
782     { "WIDTH", parse_WIDTH },
783     { "WORKSPACE", parse_WORKSPACE },
784   };
785   enum { N_SETTINGS = sizeof settings / sizeof *settings };
786
787   for (size_t i = 0; i < N_SETTINGS; i++)
788     if (match_subcommand (lexer, settings[i].name))
789         return settings[i].function (lexer);
790
791   lex_error (lexer, NULL);
792   return false;
793 }
794
795 int
796 cmd_set (struct lexer *lexer, struct dataset *ds UNUSED)
797 {
798   for (;;)
799     {
800       lex_match (lexer, T_SLASH);
801       if (lex_token (lexer) == T_ENDCMD)
802         break;
803
804       if (!parse_setting (lexer))
805         return CMD_FAILURE;
806     }
807
808   return CMD_SUCCESS;
809 }
810 \f
811 static char *
812 show_output_routing (enum settings_output_type type)
813 {
814   enum settings_output_devices devices;
815   const char *s;
816
817   devices = settings_get_output_routing (type);
818   if (devices & SETTINGS_DEVICE_LISTING)
819     s = devices & SETTINGS_DEVICE_TERMINAL ? "BOTH" : "LISTING";
820   else if (devices & SETTINGS_DEVICE_TERMINAL)
821     s = "TERMINAL";
822   else
823     s = "NONE";
824
825   return xstrdup (s);
826 }
827
828 static char *
829 show_blanks (const struct dataset *ds UNUSED)
830 {
831   return (settings_get_blanks () == SYSMIS
832           ? xstrdup ("SYSMIS")
833           : xasprintf ("%.*g", DBL_DIG + 1, settings_get_blanks ()));
834 }
835
836 static char *
837 show_cc (enum fmt_type type)
838 {
839   return fmt_number_style_to_string (fmt_settings_get_style (
840                                        settings_get_fmt_settings (), type));
841 }
842
843 static char *
844 show_cca (const struct dataset *ds UNUSED)
845 {
846   return show_cc (FMT_CCA);
847 }
848
849 static char *
850 show_ccb (const struct dataset *ds UNUSED)
851 {
852   return show_cc (FMT_CCB);
853 }
854
855 static char *
856 show_ccc (const struct dataset *ds UNUSED)
857 {
858   return show_cc (FMT_CCC);
859 }
860
861 static char *
862 show_ccd (const struct dataset *ds UNUSED)
863 {
864   return show_cc (FMT_CCD);
865 }
866
867 static char *
868 show_cce (const struct dataset *ds UNUSED)
869 {
870   return show_cc (FMT_CCE);
871 }
872
873 static char *
874 show_decimals (const struct dataset *ds UNUSED)
875 {
876   return xasprintf ("`%c'", settings_get_fmt_settings ()->decimal);
877 }
878
879 static char *
880 show_errors (const struct dataset *ds UNUSED)
881 {
882   return show_output_routing (SETTINGS_OUTPUT_ERROR);
883 }
884
885 static char *
886 show_format (const struct dataset *ds UNUSED)
887 {
888   char str[FMT_STRING_LEN_MAX + 1];
889   return xstrdup (fmt_to_string (settings_get_format (), str));
890 }
891
892 static char *
893 show_fuzzbits (const struct dataset *ds UNUSED)
894 {
895   return xasprintf ("%d", settings_get_fuzzbits ());
896 }
897
898 static char *
899 show_journal (const struct dataset *ds UNUSED)
900 {
901   return (journal_is_enabled ()
902           ? xasprintf ("\"%s\"", journal_get_file_name ())
903           : xstrdup ("disabled"));
904 }
905
906 static char *
907 show_length (const struct dataset *ds UNUSED)
908 {
909   return xasprintf ("%d", settings_get_viewlength ());
910 }
911
912 static char *
913 show_locale (const struct dataset *ds UNUSED)
914 {
915   return xstrdup (get_default_encoding ());
916 }
917
918 static char *
919 show_messages (const struct dataset *ds UNUSED)
920 {
921   return show_output_routing (SETTINGS_OUTPUT_NOTE);
922 }
923
924 static char *
925 show_printback (const struct dataset *ds UNUSED)
926 {
927   return show_output_routing (SETTINGS_OUTPUT_SYNTAX);
928 }
929
930 static char *
931 show_results (const struct dataset *ds UNUSED)
932 {
933   return show_output_routing (SETTINGS_OUTPUT_RESULT);
934 }
935
936 static char *
937 show_mxerrs (const struct dataset *ds UNUSED)
938 {
939   return xasprintf ("%d", settings_get_max_messages (MSG_S_ERROR));
940 }
941
942 static char *
943 show_mxloops (const struct dataset *ds UNUSED)
944 {
945   return xasprintf ("%d", settings_get_mxloops ());
946 }
947
948 static char *
949 show_mxwarns (const struct dataset *ds UNUSED)
950 {
951   return xasprintf ("%d", settings_get_max_messages (MSG_S_WARNING));
952 }
953
954 /* Returns a name for the given INTEGER_FORMAT value. */
955 static char *
956 show_integer_format (enum integer_format integer_format)
957 {
958   return xasprintf ("%s (%s)",
959                     (integer_format == INTEGER_MSB_FIRST ? "MSBFIRST"
960                      : integer_format == INTEGER_LSB_FIRST ? "LSBFIRST"
961                      : "VAX"),
962                     integer_format == INTEGER_NATIVE ? "NATIVE" : "nonnative");
963 }
964
965 /* Returns a name for the given FLOAT_FORMAT value. */
966 static char *
967 show_float_format (enum float_format float_format)
968 {
969   const char *format_name = "";
970
971   switch (float_format)
972     {
973     case FLOAT_IEEE_SINGLE_LE:
974       format_name = _("ISL (32-bit IEEE 754 single, little-endian)");
975       break;
976     case FLOAT_IEEE_SINGLE_BE:
977       format_name = _("ISB (32-bit IEEE 754 single, big-endian)");
978       break;
979     case FLOAT_IEEE_DOUBLE_LE:
980       format_name = _("IDL (64-bit IEEE 754 double, little-endian)");
981       break;
982     case FLOAT_IEEE_DOUBLE_BE:
983       format_name = _("IDB (64-bit IEEE 754 double, big-endian)");
984       break;
985
986     case FLOAT_VAX_F:
987       format_name = _("VF (32-bit VAX F, VAX-endian)");
988       break;
989     case FLOAT_VAX_D:
990       format_name = _("VD (64-bit VAX D, VAX-endian)");
991       break;
992     case FLOAT_VAX_G:
993       format_name = _("VG (64-bit VAX G, VAX-endian)");
994       break;
995
996     case FLOAT_Z_SHORT:
997       format_name = _("ZS (32-bit IBM Z hexadecimal short, big-endian)");
998       break;
999     case FLOAT_Z_LONG:
1000       format_name = _("ZL (64-bit IBM Z hexadecimal long, big-endian)");
1001       break;
1002
1003     case FLOAT_FP:
1004     case FLOAT_HEX:
1005       NOT_REACHED ();
1006     }
1007
1008   return xasprintf ("%s (%s)", format_name,
1009                     (float_format == FLOAT_NATIVE_DOUBLE
1010                      ? "NATIVE" : "nonnative"));
1011 }
1012
1013 static char *
1014 show_rib (const struct dataset *ds UNUSED)
1015 {
1016   return show_integer_format (settings_get_input_integer_format ());
1017 }
1018
1019 static char *
1020 show_rrb (const struct dataset *ds UNUSED)
1021 {
1022   return show_float_format (settings_get_input_float_format ());
1023 }
1024
1025 static char *
1026 show_scompression (const struct dataset *ds UNUSED)
1027 {
1028   return xstrdup (settings_get_scompression () ? "ON" : "OFF");
1029 }
1030
1031 static char *
1032 show_undefined (const struct dataset *ds UNUSED)
1033 {
1034   return xstrdup (settings_get_undefined () ? "WARN" : "NOWARN");
1035 }
1036
1037 static char *
1038 show_weight (const struct dataset *ds)
1039 {
1040   const struct variable *var = dict_get_weight (dataset_dict (ds));
1041   return xstrdup (var != NULL ? var_get_name (var) : "OFF");
1042 }
1043
1044 static char *
1045 show_wib (const struct dataset *ds UNUSED)
1046 {
1047   return show_integer_format (settings_get_output_integer_format ());
1048 }
1049
1050 static char *
1051 show_wrb (const struct dataset *ds UNUSED)
1052 {
1053   return show_float_format (settings_get_output_float_format ());
1054 }
1055
1056 static char *
1057 show_width (const struct dataset *ds UNUSED)
1058 {
1059   return xasprintf ("%d", settings_get_viewwidth ());
1060 }
1061
1062 static char *
1063 show_workspace (const struct dataset *ds UNUSED)
1064 {
1065   size_t ws = settings_get_workspace () / 1024L;
1066   return xasprintf ("%zu", ws);
1067 }
1068
1069 static char *
1070 show_current_directory (const struct dataset *ds UNUSED)
1071 {
1072   char *buf = NULL;
1073   char *wd = NULL;
1074   size_t len = 256;
1075
1076   do
1077     {
1078       len <<= 1;
1079       buf = xrealloc (buf, len);
1080     }
1081   while (NULL == (wd = getcwd (buf, len)));
1082
1083   return wd;
1084 }
1085
1086 static char *
1087 show_tempdir (const struct dataset *ds UNUSED)
1088 {
1089   return strdup (temp_dir_name ());
1090 }
1091
1092 static char *
1093 show_version (const struct dataset *ds UNUSED)
1094 {
1095   return strdup (announced_version);
1096 }
1097
1098 static char *
1099 show_system (const struct dataset *ds UNUSED)
1100 {
1101   return strdup (host_system);
1102 }
1103
1104 static char *
1105 show_n (const struct dataset *ds)
1106 {
1107   casenumber n;
1108   size_t l;
1109
1110   const struct casereader *reader = dataset_source (ds);
1111
1112   if (reader == NULL)
1113     return strdup (_("Unknown"));
1114
1115   n =  casereader_count_cases (reader);
1116
1117   return  asnprintf (NULL, &l, "%ld", n);
1118 }
1119
1120
1121 struct show_sbc
1122   {
1123     const char *name;
1124     char *(*function) (const struct dataset *);
1125   };
1126
1127 const struct show_sbc show_table[] =
1128   {
1129     {"BLANKS", show_blanks},
1130     {"CCA", show_cca},
1131     {"CCB", show_ccb},
1132     {"CCC", show_ccc},
1133     {"CCD", show_ccd},
1134     {"CCE", show_cce},
1135     {"DECIMALS", show_decimals},
1136     {"DIRECTORY", show_current_directory},
1137     {"ENVIRONMENT", show_system},
1138     {"ERRORS", show_errors},
1139     {"FORMAT", show_format},
1140     {"FUZZBITS", show_fuzzbits},
1141     {"JOURNAL", show_journal},
1142     {"LENGTH", show_length},
1143     {"LOCALE", show_locale},
1144     {"MESSAGES", show_messages},
1145     {"MXERRS", show_mxerrs},
1146     {"MXLOOPS", show_mxloops},
1147     {"MXWARNS", show_mxwarns},
1148     {"N", show_n},
1149     {"PRINTBACk", show_printback},
1150     {"RESULTS", show_results},
1151     {"RIB", show_rib},
1152     {"RRB", show_rrb},
1153     {"SCOMPRESSION", show_scompression},
1154     {"TEMPDIR", show_tempdir},
1155     {"UNDEFINED", show_undefined},
1156     {"VERSION", show_version},
1157     {"WEIGHT", show_weight},
1158     {"WIB", show_wib},
1159     {"WRB", show_wrb},
1160     {"WIDTH", show_width},
1161     {"WORKSPACE", show_workspace},
1162   };
1163
1164 static void
1165 do_show (const struct dataset *ds, const struct show_sbc *sbc)
1166 {
1167   char *value = sbc->function (ds);
1168   msg (SN, _("%s is %s."), sbc->name, value);
1169   free (value);
1170 }
1171
1172 static void
1173 show_all (const struct dataset *ds)
1174 {
1175   size_t i;
1176
1177   for (i = 0; i < sizeof show_table / sizeof *show_table; i++)
1178     do_show (ds, &show_table[i]);
1179 }
1180
1181 static void
1182 show_all_cc (const struct dataset *ds)
1183 {
1184   int i;
1185
1186   for (i = 0; i < sizeof show_table / sizeof *show_table; i++)
1187     {
1188       const struct show_sbc *sbc = &show_table[i];
1189       if (!strncmp (sbc->name, "CC", 2))
1190         do_show (ds, sbc);
1191     }
1192 }
1193
1194 static void
1195 show_warranty (const struct dataset *ds UNUSED)
1196 {
1197   fputs (lack_of_warranty, stdout);
1198 }
1199
1200 static void
1201 show_copying (const struct dataset *ds UNUSED)
1202 {
1203   fputs (copyleft, stdout);
1204 }
1205
1206
1207 int
1208 cmd_show (struct lexer *lexer, struct dataset *ds)
1209 {
1210   if (lex_token (lexer) == T_ENDCMD)
1211     {
1212       show_all (ds);
1213       return CMD_SUCCESS;
1214     }
1215
1216   do
1217     {
1218       if (lex_match (lexer, T_ALL))
1219         show_all (ds);
1220       else if (lex_match_id (lexer, "CC"))
1221         show_all_cc (ds);
1222       else if (lex_match_id (lexer, "WARRANTY"))
1223         show_warranty (ds);
1224       else if (lex_match_id (lexer, "COPYING") || lex_match_id (lexer, "LICENSE"))
1225         show_copying (ds);
1226       else if (lex_token (lexer) == T_ID)
1227         {
1228           int i;
1229
1230           for (i = 0; i < sizeof show_table / sizeof *show_table; i++)
1231             {
1232               const struct show_sbc *sbc = &show_table[i];
1233               if (lex_match_id (lexer, sbc->name))
1234                 {
1235                   do_show (ds, sbc);
1236                   goto found;
1237                 }
1238               }
1239           lex_error (lexer, NULL);
1240           return CMD_FAILURE;
1241
1242         found: ;
1243         }
1244       else
1245         {
1246           lex_error (lexer, NULL);
1247           return CMD_FAILURE;
1248         }
1249
1250       lex_match (lexer, T_SLASH);
1251     }
1252   while (lex_token (lexer) != T_ENDCMD);
1253
1254   return CMD_SUCCESS;
1255 }
1256 \f
1257 #define MAX_SAVED_SETTINGS 5
1258
1259 static struct settings *saved_settings[MAX_SAVED_SETTINGS];
1260 static int n_saved_settings;
1261
1262 int
1263 cmd_preserve (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
1264 {
1265   if (n_saved_settings < MAX_SAVED_SETTINGS)
1266     {
1267       saved_settings[n_saved_settings++] = settings_get ();
1268       return CMD_SUCCESS;
1269     }
1270   else
1271     {
1272       msg (SE, _("Too many %s commands without a %s: at most "
1273                  "%d levels of saved settings are allowed."),
1274            "PRESERVE", "RESTORE",
1275            MAX_SAVED_SETTINGS);
1276       return CMD_CASCADING_FAILURE;
1277     }
1278 }
1279
1280 int
1281 cmd_restore (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
1282 {
1283   if (n_saved_settings > 0)
1284     {
1285       struct settings *s = saved_settings[--n_saved_settings];
1286       settings_set (s);
1287       settings_destroy (s);
1288       return CMD_SUCCESS;
1289     }
1290   else
1291     {
1292       msg (SE, _("%s without matching %s."), "RESTORE", "PRESERVE");
1293       return CMD_FAILURE;
1294     }
1295 }
1296
1297 /*
1298    Local Variables:
1299    mode: c
1300    End:
1301 */