pivot-table: Incorporate format settings.
[pspp] / src / language / utilities / set.q
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/compiler.h"
41 #include "libpspp/copyleft.h"
42 #include "libpspp/temp-file.h"
43 #include "libpspp/version.h"
44 #include "libpspp/float-format.h"
45 #include "libpspp/i18n.h"
46 #include "libpspp/integer-format.h"
47 #include "libpspp/message.h"
48 #include "math/random.h"
49 #include "output/driver.h"
50 #include "output/journal.h"
51 #include "output/pivot-table.h"
52
53 #if HAVE_LIBTERMCAP
54 #if HAVE_TERMCAP_H
55 #include <termcap.h>
56 #else /* !HAVE_TERMCAP_H */
57 int tgetent (char *, const char *);
58 int tgetnum (const char *);
59 #endif /* !HAVE_TERMCAP_H */
60 #endif /* !HAVE_LIBTERMCAP */
61
62 #include "xalloc.h"
63
64 #include "gettext.h"
65 #define _(msgid) gettext (msgid)
66
67 /* (specification)
68    "SET" (stc_):
69      blanks=custom;
70      block=string;
71      boxstring=string;
72      case=size:upper/uplow;
73      cca=string;
74      ccb=string;
75      ccc=string;
76      ccd=string;
77      cce=string;
78      compression=compress:on/off;
79      cpi=integer;
80      decimal=dec:dot/comma;
81      epoch=custom;
82      errors=custom;
83      format=custom;
84      fuzzbits=integer;
85      headers=headers:no/yes/blank;
86      highres=hires:on/off;
87      histogram=string;
88      include=inc:on/off;
89      journal=custom;
90      log=custom;
91      length=custom;
92      locale=custom;
93      lowres=lores:auto/on/off;
94      lpi=integer;
95      menus=menus:standard/extended;
96      messages=custom;
97      mexpand=mexp:on/off;
98      miterate=integer;
99      mnest=integer;
100      mprint=mprint:on/off;
101      mxerrs=integer;
102      mxloops=integer;
103      mxmemory=integer;
104      mxwarns=integer;
105      printback=custom;
106      results=custom;
107      rib=rib:msbfirst/lsbfirst/vax/native;
108      rrb=rrb:native/isl/isb/idl/idb/vf/vd/vg/zs/zl;
109      safer=safe:on;
110      scompression=scompress:on/off;
111      scripttab=string;
112      seed=custom;
113      tnumbers=custom;
114      tvars=custom;
115      tb1=string;
116      tbfonts=string;
117      tlook=custom;
118      undefined=undef:warn/nowarn;
119      wib=wib:msbfirst/lsbfirst/vax/native;
120      wrb=wrb:native/isl/isb/idl/idb/vf/vd/vg/zs/zl;
121      width=custom;
122      workspace=integer;
123      xsort=xsort:yes/no.
124 */
125
126 /* (headers) */
127
128 /* (declarations) */
129
130 /* (functions) */
131
132 static enum integer_format stc_to_integer_format (int stc);
133 static enum float_format stc_to_float_format (int stc);
134
135 int
136 cmd_set (struct lexer *lexer, struct dataset *ds)
137 {
138   struct cmd_set cmd;
139
140   if (!parse_set (lexer, ds, &cmd, NULL))
141     {
142       return CMD_FAILURE;
143     }
144
145   if (cmd.sbc_cca)
146     settings_set_cc ( cmd.s_cca, FMT_CCA);
147   if (cmd.sbc_ccb)
148     settings_set_cc ( cmd.s_ccb, FMT_CCB);
149   if (cmd.sbc_ccc)
150     settings_set_cc ( cmd.s_ccc, FMT_CCC);
151   if (cmd.sbc_ccd)
152     settings_set_cc ( cmd.s_ccd, FMT_CCD);
153   if (cmd.sbc_cce)
154     settings_set_cc ( cmd.s_cce, FMT_CCE);
155
156   if (cmd.sbc_decimal)
157     settings_set_decimal_char (cmd.dec == STC_DOT ? '.' : ',');
158   if (cmd.sbc_fuzzbits)
159     {
160       int fuzzbits = cmd.n_fuzzbits[0];
161       if (fuzzbits >= 0 && fuzzbits <= 20)
162         settings_set_fuzzbits (fuzzbits);
163       else
164         msg (SE, _("%s must be between 0 and 20."), "FUZZBITS");
165     }
166
167   if (cmd.sbc_include)
168     settings_set_include (cmd.inc == STC_ON);
169   if (cmd.sbc_mxerrs)
170     {
171       if (cmd.n_mxerrs[0] >= 1)
172         settings_set_max_messages (MSG_S_ERROR, cmd.n_mxerrs[0]);
173       else
174         msg (SE, _("%s must be at least 1."), "MXERRS");
175     }
176   if (cmd.sbc_mxloops)
177     {
178       if (cmd.n_mxloops[0] >= 1)
179         settings_set_mxloops (cmd.n_mxloops[0]);
180       else
181         msg (SE, _("%s must be at least 1."), "MXLOOPS");
182     }
183   if (cmd.sbc_mxwarns)
184     {
185       if (cmd.n_mxwarns[0] >= 0)
186         settings_set_max_messages (MSG_S_WARNING, cmd.n_mxwarns[0]);
187       else
188         msg (SE, _("%s must not be negative."), "MXWARNS");
189     }
190   if (cmd.sbc_rib)
191     settings_set_input_integer_format (stc_to_integer_format (cmd.rib));
192   if (cmd.sbc_rrb)
193     settings_set_input_float_format (stc_to_float_format (cmd.rrb));
194   if (cmd.sbc_safer)
195     settings_set_safer_mode ();
196   if (cmd.sbc_scompression)
197     settings_set_scompression (cmd.scompress == STC_ON);
198   if (cmd.sbc_undefined)
199     settings_set_undefined (cmd.undef == STC_WARN);
200   if (cmd.sbc_wib)
201     settings_set_output_integer_format (stc_to_integer_format (cmd.wib));
202   if (cmd.sbc_wrb)
203     settings_set_output_float_format (stc_to_float_format (cmd.wrb));
204   if (cmd.sbc_workspace)
205     {
206       if ( cmd.n_workspace[0] < 1024 && ! settings_get_testing_mode ())
207         msg (SE, _("%s must be at least 1MB"), "WORKSPACE");
208       else if (cmd.n_workspace[0] <= 0)
209         msg (SE, _("%s must be positive"), "WORKSPACE");
210       else
211         settings_set_workspace (cmd.n_workspace[0] * 1024L);
212     }
213
214   if (cmd.sbc_block)
215     msg (SW, _("%s is obsolete."), "BLOCK");
216   if (cmd.sbc_boxstring)
217     msg (SW, _("%s is obsolete."), "BOXSTRING");
218   if (cmd.sbc_cpi)
219     msg (SW, _("%s is obsolete."), "CPI");
220   if (cmd.sbc_histogram)
221     msg (SW, _("%s is obsolete."), "HISTOGRAM");
222   if (cmd.sbc_lpi)
223     msg (SW, _("%s is obsolete."), "LPI");
224   if (cmd.sbc_menus)
225     msg (SW, _("%s is obsolete."), "MENUS");
226   if (cmd.sbc_xsort)
227     msg (SW, _("%s is obsolete."), "XSORT");
228   if (cmd.sbc_mxmemory)
229     msg (SE, _("%s is obsolete."), "MXMEMORY");
230   if (cmd.sbc_scripttab)
231     msg (SE, _("%s is obsolete."), "SCRIPTTAB");
232   if (cmd.sbc_tbfonts)
233     msg (SW, _("%s is obsolete."), "TBFONTS");
234   if (cmd.sbc_tb1 && cmd.s_tb1)
235     msg (SW, _("%s is obsolete."), "TB1");
236
237   if (cmd.sbc_case)
238     msg (SW, _("%s is not yet implemented."), "CASE");
239
240   if (cmd.sbc_compression)
241     msg (SW, _("Active file compression is not implemented."));
242
243   free_set (&cmd);
244
245   return CMD_SUCCESS;
246 }
247
248 /* Returns the integer_format value corresponding to STC,
249    which should be the value of cmd.rib or cmd.wib. */
250 static enum integer_format
251 stc_to_integer_format (int stc)
252 {
253   return (stc == STC_MSBFIRST ? INTEGER_MSB_FIRST
254           : stc == STC_LSBFIRST ? INTEGER_LSB_FIRST
255           : stc == STC_VAX ? INTEGER_VAX
256           : INTEGER_NATIVE);
257 }
258
259 /* Returns the float_format value corresponding to STC,
260    which should be the value of cmd.rrb or cmd.wrb. */
261 static enum float_format
262 stc_to_float_format (int stc)
263 {
264   switch (stc)
265     {
266     case STC_NATIVE:
267       return FLOAT_NATIVE_DOUBLE;
268
269     case STC_ISL:
270       return FLOAT_IEEE_SINGLE_LE;
271     case STC_ISB:
272       return FLOAT_IEEE_SINGLE_BE;
273     case STC_IDL:
274       return FLOAT_IEEE_DOUBLE_LE;
275     case STC_IDB:
276       return FLOAT_IEEE_DOUBLE_BE;
277
278     case STC_VF:
279       return FLOAT_VAX_F;
280     case STC_VD:
281       return FLOAT_VAX_D;
282     case STC_VG:
283       return FLOAT_VAX_G;
284
285     case STC_ZS:
286       return FLOAT_Z_SHORT;
287     case STC_ZL:
288       return FLOAT_Z_LONG;
289     }
290
291   NOT_REACHED ();
292 }
293
294 static int
295 set_output_routing (struct lexer *lexer, enum settings_output_type type)
296 {
297   enum settings_output_devices devices;
298
299   lex_match (lexer, T_EQUALS);
300   if (lex_match_id (lexer, "ON") || lex_match_id (lexer, "BOTH"))
301     devices = SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL;
302   else if (lex_match_id (lexer, "TERMINAL"))
303     devices = SETTINGS_DEVICE_TERMINAL;
304   else if (lex_match_id (lexer, "LISTING"))
305     devices = SETTINGS_DEVICE_LISTING;
306   else if (lex_match_id (lexer, "OFF") || lex_match_id (lexer, "NONE"))
307     devices = 0;
308   else
309     {
310       lex_error (lexer, NULL);
311       return 0;
312     }
313
314   settings_set_output_routing (type, devices);
315
316   return 1;
317 }
318
319 /* Parses the BLANKS subcommand, which controls the value that
320    completely blank fields in numeric data imply.  X, Wnd: Syntax is
321    SYSMIS or a numeric value. */
322 static int
323 stc_custom_blanks (struct lexer *lexer,
324                    struct dataset *ds UNUSED,
325                    struct cmd_set *cmd UNUSED, void *aux UNUSED)
326 {
327   lex_match (lexer, T_EQUALS);
328   if (lex_match_id (lexer, "SYSMIS"))
329     {
330       lex_get (lexer);
331       settings_set_blanks (SYSMIS);
332     }
333   else
334     {
335       if (!lex_force_num (lexer))
336         return 0;
337       settings_set_blanks (lex_number (lexer));
338       lex_get (lexer);
339     }
340   return 1;
341 }
342
343 static int
344 stc_custom_tnumbers (struct lexer *lexer,
345                    struct dataset *ds UNUSED,
346                    struct cmd_set *cmd UNUSED, void *aux UNUSED)
347 {
348   lex_match (lexer, T_EQUALS);
349
350   if (lex_match_id (lexer, "VALUES"))
351     settings_set_show_values (SETTINGS_VALUE_SHOW_VALUE);
352   else if (lex_match_id (lexer, "LABELS"))
353     settings_set_show_values (SETTINGS_VALUE_SHOW_LABEL);
354   else if (lex_match_id (lexer, "BOTH"))
355     settings_set_show_values (SETTINGS_VALUE_SHOW_BOTH);
356   else
357     {
358       lex_error_expecting (lexer, "VALUES", "LABELS", "BOTH");
359       return 0;
360     }
361
362   return 1;
363 }
364
365
366 static int
367 stc_custom_tvars (struct lexer *lexer,
368                   struct dataset *ds UNUSED,
369                   struct cmd_set *cmd UNUSED, void *aux UNUSED)
370 {
371   lex_match (lexer, T_EQUALS);
372
373   if (lex_match_id (lexer, "NAMES"))
374     settings_set_show_variables (SETTINGS_VALUE_SHOW_VALUE);
375   else if (lex_match_id (lexer, "LABELS"))
376     settings_set_show_variables (SETTINGS_VALUE_SHOW_LABEL);
377   else if (lex_match_id (lexer, "BOTH"))
378     settings_set_show_variables (SETTINGS_VALUE_SHOW_BOTH);
379   else
380     {
381       lex_error_expecting (lexer, "NAMES", "LABELS", "BOTH");
382       return 0;
383     }
384
385   return 1;
386 }
387
388 static int
389 stc_custom_tlook (struct lexer *lexer,
390                   struct dataset *ds UNUSED,
391                   struct cmd_set *cmd UNUSED, void *aux UNUSED)
392 {
393   lex_match (lexer, T_EQUALS);
394
395   if (lex_match_id (lexer, "NONE"))
396     pivot_table_look_set_default (pivot_table_look_builtin_default ());
397   else if (lex_is_string (lexer))
398     {
399       struct pivot_table_look *look;
400       char *error = pivot_table_look_read (lex_tokcstr (lexer), &look);
401       lex_get (lexer);
402
403       if (error)
404         {
405           msg (SE, "%s", error);
406           free (error);
407           return 0;
408         }
409
410       pivot_table_look_set_default (look);
411       pivot_table_look_unref (look);
412     }
413
414   return 1;
415 }
416
417 /* Parses the EPOCH subcommand, which controls the epoch used for
418    parsing 2-digit years. */
419 static int
420 stc_custom_epoch (struct lexer *lexer,
421                   struct dataset *ds UNUSED,
422                   struct cmd_set *cmd UNUSED, void *aux UNUSED)
423 {
424   lex_match (lexer, T_EQUALS);
425   if (lex_match_id (lexer, "AUTOMATIC"))
426     settings_set_epoch (-1);
427   else if (lex_is_integer (lexer))
428     {
429       int new_epoch = lex_integer (lexer);
430       lex_get (lexer);
431       if (new_epoch < 1500)
432         {
433           msg (SE, _("%s must be 1500 or later."), "EPOCH");
434           return 0;
435         }
436       settings_set_epoch (new_epoch);
437     }
438   else
439     {
440       lex_error (lexer, _("expecting %s or year"), "AUTOMATIC");
441       return 0;
442     }
443
444   return 1;
445 }
446
447 static int
448 stc_custom_errors (struct lexer *lexer, struct dataset *ds UNUSED,
449                    struct cmd_set *cmd UNUSED, void *aux UNUSED)
450 {
451   return set_output_routing (lexer, SETTINGS_OUTPUT_ERROR);
452 }
453
454 static int
455 stc_custom_length (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
456 {
457   int page_length;
458
459   lex_match (lexer, T_EQUALS);
460   if (lex_match_id (lexer, "NONE"))
461     page_length = -1;
462   else
463     {
464       if (!lex_force_int (lexer))
465         return 0;
466       if (lex_integer (lexer) < 1)
467         {
468           msg (SE, _("%s must be at least %d."), "LENGTH", 1);
469           return 0;
470         }
471       page_length = lex_integer (lexer);
472       lex_get (lexer);
473     }
474
475   if (page_length != -1)
476     settings_set_viewlength (page_length);
477
478   return 1;
479 }
480
481 static int
482 stc_custom_locale (struct lexer *lexer, struct dataset *ds UNUSED,
483                    struct cmd_set *cmd UNUSED, void *aux UNUSED)
484 {
485   const char *s;
486
487   lex_match (lexer, T_EQUALS);
488
489   if ( !lex_force_string (lexer))
490     return 0;
491
492   s = lex_tokcstr (lexer);
493
494   /* First try this string as an encoding name */
495   if ( valid_encoding (s))
496     set_default_encoding (s);
497
498   /* Now try as a locale name (or alias) */
499   else if (set_encoding_from_locale (s))
500     {
501     }
502   else
503     {
504       msg (ME, _("%s is not a recognized encoding or locale name"), s);
505       return 0;
506     }
507
508   lex_get (lexer);
509
510   return 1;
511 }
512
513 static int
514 stc_custom_messages (struct lexer *lexer, struct dataset *ds UNUSED,
515                    struct cmd_set *cmd UNUSED, void *aux UNUSED)
516 {
517   return set_output_routing (lexer, SETTINGS_OUTPUT_NOTE);
518 }
519
520 static int
521 stc_custom_printback (struct lexer *lexer, struct dataset *ds UNUSED,
522                       struct cmd_set *cmd UNUSED, void *aux UNUSED)
523 {
524   return set_output_routing (lexer, SETTINGS_OUTPUT_SYNTAX);
525 }
526
527 static int
528 stc_custom_results (struct lexer *lexer, struct dataset *ds UNUSED,
529                     struct cmd_set *cmd UNUSED, void *aux UNUSED)
530 {
531   return set_output_routing (lexer, SETTINGS_OUTPUT_RESULT);
532 }
533
534 static int
535 stc_custom_seed (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
536 {
537   lex_match (lexer, T_EQUALS);
538   if (lex_match_id (lexer, "RANDOM"))
539     set_rng (time (0));
540   else
541     {
542       if (!lex_force_num (lexer))
543         return 0;
544       set_rng (lex_number (lexer));
545       lex_get (lexer);
546     }
547
548   return 1;
549 }
550
551 static int
552 stc_custom_width (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
553 {
554   lex_match (lexer, T_EQUALS);
555   if (lex_match_id (lexer, "NARROW"))
556     settings_set_viewwidth (79);
557   else if (lex_match_id (lexer, "WIDE"))
558     settings_set_viewwidth (131);
559   else
560     {
561       if (!lex_force_int (lexer))
562         return 0;
563       if (lex_integer (lexer) < 40)
564         {
565           msg (SE, _("%s must be at least %d."), "WIDTH", 40);
566           return 0;
567         }
568       settings_set_viewwidth (lex_integer (lexer));
569       lex_get (lexer);
570     }
571
572   return 1;
573 }
574
575 /* Parses FORMAT subcommand, which consists of a numeric format
576    specifier. */
577 static int
578 stc_custom_format (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
579 {
580   struct fmt_spec fmt;
581
582   lex_match (lexer, T_EQUALS);
583   if (!parse_format_specifier (lexer, &fmt))
584     return 0;
585
586   if (!fmt_check_output (&fmt))
587     return 0;
588
589   if (fmt_is_string (fmt.type))
590     {
591       char str[FMT_STRING_LEN_MAX + 1];
592       msg (SE, _("%s requires numeric output format as an argument.  "
593                  "Specified format %s is of type string."),
594            "FORMAT",
595            fmt_to_string (&fmt, str));
596       return 0;
597     }
598
599   settings_set_format (&fmt);
600   return 1;
601 }
602
603 static int
604 stc_custom_journal (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
605 {
606   lex_match (lexer, T_EQUALS);
607   if (lex_match_id (lexer, "ON") || lex_match_id (lexer, "YES"))
608     journal_enable ();
609   else if (lex_match_id (lexer, "OFF") || lex_match_id (lexer, "NO"))
610     journal_disable ();
611   else if (lex_is_string (lexer) || lex_token (lexer) == T_ID)
612     {
613       char *filename = utf8_to_filename (lex_tokcstr (lexer));
614       journal_set_file_name (filename);
615       free (filename);
616
617       lex_get (lexer);
618     }
619   else
620     {
621       lex_error (lexer, NULL);
622       return 0;
623     }
624   return 1;
625 }
626
627 static int
628 stc_custom_log (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
629 {
630   return stc_custom_journal (lexer, ds, cmd, aux);
631 }
632 \f
633 static char *
634 show_output_routing (enum settings_output_type type)
635 {
636   enum settings_output_devices devices;
637   const char *s;
638
639   devices = settings_get_output_routing (type);
640   if (devices & SETTINGS_DEVICE_LISTING)
641     s = devices & SETTINGS_DEVICE_TERMINAL ? "BOTH" : "LISTING";
642   else if (devices & SETTINGS_DEVICE_TERMINAL)
643     s = "TERMINAL";
644   else
645     s = "NONE";
646
647   return xstrdup (s);
648 }
649
650 static char *
651 show_blanks (const struct dataset *ds UNUSED)
652 {
653   return (settings_get_blanks () == SYSMIS
654           ? xstrdup ("SYSMIS")
655           : xasprintf ("%.*g", DBL_DIG + 1, settings_get_blanks ()));
656 }
657
658 static char *
659 show_cc (enum fmt_type type)
660 {
661   return fmt_number_style_to_string (fmt_settings_get_style (
662                                        settings_get_fmt_settings (), type));
663 }
664
665 static char *
666 show_cca (const struct dataset *ds UNUSED)
667 {
668   return show_cc (FMT_CCA);
669 }
670
671 static char *
672 show_ccb (const struct dataset *ds UNUSED)
673 {
674   return show_cc (FMT_CCB);
675 }
676
677 static char *
678 show_ccc (const struct dataset *ds UNUSED)
679 {
680   return show_cc (FMT_CCC);
681 }
682
683 static char *
684 show_ccd (const struct dataset *ds UNUSED)
685 {
686   return show_cc (FMT_CCD);
687 }
688
689 static char *
690 show_cce (const struct dataset *ds UNUSED)
691 {
692   return show_cc (FMT_CCE);
693 }
694
695 static char *
696 show_decimals (const struct dataset *ds UNUSED)
697 {
698   return xasprintf ("`%c'", settings_get_fmt_settings ()->decimal);
699 }
700
701 static char *
702 show_errors (const struct dataset *ds UNUSED)
703 {
704   return show_output_routing (SETTINGS_OUTPUT_ERROR);
705 }
706
707 static char *
708 show_format (const struct dataset *ds UNUSED)
709 {
710   char str[FMT_STRING_LEN_MAX + 1];
711   return xstrdup (fmt_to_string (settings_get_format (), str));
712 }
713
714 static char *
715 show_fuzzbits (const struct dataset *ds UNUSED)
716 {
717   return xasprintf ("%d", settings_get_fuzzbits ());
718 }
719
720 static char *
721 show_journal (const struct dataset *ds UNUSED)
722 {
723   return (journal_is_enabled ()
724           ? xasprintf ("\"%s\"", journal_get_file_name ())
725           : xstrdup ("disabled"));
726 }
727
728 static char *
729 show_length (const struct dataset *ds UNUSED)
730 {
731   return xasprintf ("%d", settings_get_viewlength ());
732 }
733
734 static char *
735 show_locale (const struct dataset *ds UNUSED)
736 {
737   return xstrdup (get_default_encoding ());
738 }
739
740 static char *
741 show_messages (const struct dataset *ds UNUSED)
742 {
743   return show_output_routing (SETTINGS_OUTPUT_NOTE);
744 }
745
746 static char *
747 show_printback (const struct dataset *ds UNUSED)
748 {
749   return show_output_routing (SETTINGS_OUTPUT_SYNTAX);
750 }
751
752 static char *
753 show_results (const struct dataset *ds UNUSED)
754 {
755   return show_output_routing (SETTINGS_OUTPUT_RESULT);
756 }
757
758 static char *
759 show_mxerrs (const struct dataset *ds UNUSED)
760 {
761   return xasprintf ("%d", settings_get_max_messages (MSG_S_ERROR));
762 }
763
764 static char *
765 show_mxloops (const struct dataset *ds UNUSED)
766 {
767   return xasprintf ("%d", settings_get_mxloops ());
768 }
769
770 static char *
771 show_mxwarns (const struct dataset *ds UNUSED)
772 {
773   return xasprintf ("%d", settings_get_max_messages (MSG_S_WARNING));
774 }
775
776 /* Returns a name for the given INTEGER_FORMAT value. */
777 static char *
778 show_integer_format (enum integer_format integer_format)
779 {
780   return xasprintf ("%s (%s)",
781                     (integer_format == INTEGER_MSB_FIRST ? "MSBFIRST"
782                      : integer_format == INTEGER_LSB_FIRST ? "LSBFIRST"
783                      : "VAX"),
784                     integer_format == INTEGER_NATIVE ? "NATIVE" : "nonnative");
785 }
786
787 /* Returns a name for the given FLOAT_FORMAT value. */
788 static char *
789 show_float_format (enum float_format float_format)
790 {
791   const char *format_name = "";
792
793   switch (float_format)
794     {
795     case FLOAT_IEEE_SINGLE_LE:
796       format_name = _("ISL (32-bit IEEE 754 single, little-endian)");
797       break;
798     case FLOAT_IEEE_SINGLE_BE:
799       format_name = _("ISB (32-bit IEEE 754 single, big-endian)");
800       break;
801     case FLOAT_IEEE_DOUBLE_LE:
802       format_name = _("IDL (64-bit IEEE 754 double, little-endian)");
803       break;
804     case FLOAT_IEEE_DOUBLE_BE:
805       format_name = _("IDB (64-bit IEEE 754 double, big-endian)");
806       break;
807
808     case FLOAT_VAX_F:
809       format_name = _("VF (32-bit VAX F, VAX-endian)");
810       break;
811     case FLOAT_VAX_D:
812       format_name = _("VD (64-bit VAX D, VAX-endian)");
813       break;
814     case FLOAT_VAX_G:
815       format_name = _("VG (64-bit VAX G, VAX-endian)");
816       break;
817
818     case FLOAT_Z_SHORT:
819       format_name = _("ZS (32-bit IBM Z hexadecimal short, big-endian)");
820       break;
821     case FLOAT_Z_LONG:
822       format_name = _("ZL (64-bit IBM Z hexadecimal long, big-endian)");
823       break;
824
825     case FLOAT_FP:
826     case FLOAT_HEX:
827       NOT_REACHED ();
828     }
829
830   return xasprintf ("%s (%s)", format_name,
831                     (float_format == FLOAT_NATIVE_DOUBLE
832                      ? "NATIVE" : "nonnative"));
833 }
834
835 static char *
836 show_rib (const struct dataset *ds UNUSED)
837 {
838   return show_integer_format (settings_get_input_integer_format ());
839 }
840
841 static char *
842 show_rrb (const struct dataset *ds UNUSED)
843 {
844   return show_float_format (settings_get_input_float_format ());
845 }
846
847 static char *
848 show_scompression (const struct dataset *ds UNUSED)
849 {
850   return xstrdup (settings_get_scompression () ? "ON" : "OFF");
851 }
852
853 static char *
854 show_undefined (const struct dataset *ds UNUSED)
855 {
856   return xstrdup (settings_get_undefined () ? "WARN" : "NOWARN");
857 }
858
859 static char *
860 show_weight (const struct dataset *ds)
861 {
862   const struct variable *var = dict_get_weight (dataset_dict (ds));
863   return xstrdup (var != NULL ? var_get_name (var) : "OFF");
864 }
865
866 static char *
867 show_wib (const struct dataset *ds UNUSED)
868 {
869   return show_integer_format (settings_get_output_integer_format ());
870 }
871
872 static char *
873 show_wrb (const struct dataset *ds UNUSED)
874 {
875   return show_float_format (settings_get_output_float_format ());
876 }
877
878 static char *
879 show_width (const struct dataset *ds UNUSED)
880 {
881   return xasprintf ("%d", settings_get_viewwidth ());
882 }
883
884 static char *
885 show_workspace (const struct dataset *ds UNUSED)
886 {
887   size_t ws = settings_get_workspace () / 1024L;
888   return xasprintf ("%zu", ws);
889 }
890
891 static char *
892 show_current_directory (const struct dataset *ds UNUSED)
893 {
894   char *buf = NULL;
895   char *wd = NULL;
896   size_t len = 256;
897
898   do
899     {
900       len <<= 1;
901       buf = xrealloc (buf, len);
902     }
903   while (NULL == (wd = getcwd (buf, len)));
904
905   return wd;
906 }
907
908 static char *
909 show_tempdir (const struct dataset *ds UNUSED)
910 {
911   return strdup (temp_dir_name ());
912 }
913
914 static char *
915 show_version (const struct dataset *ds UNUSED)
916 {
917   return strdup (announced_version);
918 }
919
920 static char *
921 show_system (const struct dataset *ds UNUSED)
922 {
923   return strdup (host_system);
924 }
925
926 static char *
927 show_n (const struct dataset *ds)
928 {
929   casenumber n;
930   size_t l;
931
932   const struct casereader *reader = dataset_source (ds);
933
934   if (reader == NULL)
935     return strdup (_("Unknown"));
936
937   n =  casereader_count_cases (reader);
938
939   return  asnprintf (NULL, &l, "%ld", n);
940 }
941
942
943 struct show_sbc
944   {
945     const char *name;
946     char *(*function) (const struct dataset *);
947   };
948
949 const struct show_sbc show_table[] =
950   {
951     {"BLANKS", show_blanks},
952     {"CCA", show_cca},
953     {"CCB", show_ccb},
954     {"CCC", show_ccc},
955     {"CCD", show_ccd},
956     {"CCE", show_cce},
957     {"DECIMALS", show_decimals},
958     {"DIRECTORY", show_current_directory},
959     {"ENVIRONMENT", show_system},
960     {"ERRORS", show_errors},
961     {"FORMAT", show_format},
962     {"FUZZBITS", show_fuzzbits},
963     {"JOURNAL", show_journal},
964     {"LENGTH", show_length},
965     {"LOCALE", show_locale},
966     {"MESSAGES", show_messages},
967     {"MXERRS", show_mxerrs},
968     {"MXLOOPS", show_mxloops},
969     {"MXWARNS", show_mxwarns},
970     {"N", show_n},
971     {"PRINTBACk", show_printback},
972     {"RESULTS", show_results},
973     {"RIB", show_rib},
974     {"RRB", show_rrb},
975     {"SCOMPRESSION", show_scompression},
976     {"TEMPDIR", show_tempdir},
977     {"UNDEFINED", show_undefined},
978     {"VERSION", show_version},
979     {"WEIGHT", show_weight},
980     {"WIB", show_wib},
981     {"WRB", show_wrb},
982     {"WIDTH", show_width},
983     {"WORKSPACE", show_workspace},
984   };
985
986 static void
987 do_show (const struct dataset *ds, const struct show_sbc *sbc)
988 {
989   char *value = sbc->function (ds);
990   msg (SN, _("%s is %s."), sbc->name, value);
991   free (value);
992 }
993
994 static void
995 show_all (const struct dataset *ds)
996 {
997   size_t i;
998
999   for (i = 0; i < sizeof show_table / sizeof *show_table; i++)
1000     do_show (ds, &show_table[i]);
1001 }
1002
1003 static void
1004 show_all_cc (const struct dataset *ds)
1005 {
1006   int i;
1007
1008   for (i = 0; i < sizeof show_table / sizeof *show_table; i++)
1009     {
1010       const struct show_sbc *sbc = &show_table[i];
1011       if (!strncmp (sbc->name, "CC", 2))
1012         do_show (ds, sbc);
1013     }
1014 }
1015
1016 static void
1017 show_warranty (const struct dataset *ds UNUSED)
1018 {
1019   fputs (lack_of_warranty, stdout);
1020 }
1021
1022 static void
1023 show_copying (const struct dataset *ds UNUSED)
1024 {
1025   fputs (copyleft, stdout);
1026 }
1027
1028
1029 int
1030 cmd_show (struct lexer *lexer, struct dataset *ds)
1031 {
1032   if (lex_token (lexer) == T_ENDCMD)
1033     {
1034       show_all (ds);
1035       return CMD_SUCCESS;
1036     }
1037
1038   do
1039     {
1040       if (lex_match (lexer, T_ALL))
1041         show_all (ds);
1042       else if (lex_match_id (lexer, "CC"))
1043         show_all_cc (ds);
1044       else if (lex_match_id (lexer, "WARRANTY"))
1045         show_warranty (ds);
1046       else if (lex_match_id (lexer, "COPYING") || lex_match_id (lexer, "LICENSE"))
1047         show_copying (ds);
1048       else if (lex_token (lexer) == T_ID)
1049         {
1050           int i;
1051
1052           for (i = 0; i < sizeof show_table / sizeof *show_table; i++)
1053             {
1054               const struct show_sbc *sbc = &show_table[i];
1055               if (lex_match_id (lexer, sbc->name))
1056                 {
1057                   do_show (ds, sbc);
1058                   goto found;
1059                 }
1060               }
1061           lex_error (lexer, NULL);
1062           return CMD_FAILURE;
1063
1064         found: ;
1065         }
1066       else
1067         {
1068           lex_error (lexer, NULL);
1069           return CMD_FAILURE;
1070         }
1071
1072       lex_match (lexer, T_SLASH);
1073     }
1074   while (lex_token (lexer) != T_ENDCMD);
1075
1076   return CMD_SUCCESS;
1077 }
1078 \f
1079 #define MAX_SAVED_SETTINGS 5
1080
1081 static struct settings *saved_settings[MAX_SAVED_SETTINGS];
1082 static int n_saved_settings;
1083
1084 int
1085 cmd_preserve (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
1086 {
1087   if (n_saved_settings < MAX_SAVED_SETTINGS)
1088     {
1089       saved_settings[n_saved_settings++] = settings_get ();
1090       return CMD_SUCCESS;
1091     }
1092   else
1093     {
1094       msg (SE, _("Too many %s commands without a %s: at most "
1095                  "%d levels of saved settings are allowed."),
1096            "PRESERVE", "RESTORE",
1097            MAX_SAVED_SETTINGS);
1098       return CMD_CASCADING_FAILURE;
1099     }
1100 }
1101
1102 int
1103 cmd_restore (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
1104 {
1105   if (n_saved_settings > 0)
1106     {
1107       struct settings *s = saved_settings[--n_saved_settings];
1108       settings_set (s);
1109       settings_destroy (s);
1110       return CMD_SUCCESS;
1111     }
1112   else
1113     {
1114       msg (SE, _("%s without matching %s."), "RESTORE", "PRESERVE");
1115       return CMD_FAILURE;
1116     }
1117 }
1118
1119 /*
1120    Local Variables:
1121    mode: c
1122    End:
1123 */