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