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