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