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.
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.
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.
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/>. */
26 #include "data/casereader.h"
27 #include "data/data-in.h"
28 #include "data/data-out.h"
29 #include "data/dataset.h"
30 #include "data/dictionary.h"
31 #include "data/format.h"
32 #include "data/settings.h"
33 #include "data/value.h"
34 #include "data/variable.h"
35 #include "language/command.h"
36 #include "language/lexer/format-parser.h"
37 #include "language/lexer/lexer.h"
38 #include "language/lexer/token.h"
39 #include "libpspp/assertion.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 "libpspp/string-array.h"
49 #include "math/random.h"
50 #include "output/driver.h"
51 #include "output/journal.h"
52 #include "output/pivot-table.h"
54 #include "gl/ftoastr.h"
55 #include "gl/minmax.h"
56 #include "gl/relocatable.h"
57 #include "gl/vasnprintf.h"
58 #include "gl/xalloc.h"
61 #define _(msgid) gettext (msgid)
62 #define N_(msgid) (msgid)
67 bool (*set) (struct lexer *);
68 char *(*show) (const struct dataset *);
72 match_subcommand (struct lexer *lexer, const char *name)
74 if (lex_match_id (lexer, name))
76 lex_match (lexer, T_EQUALS);
84 subcommand_start_ofs (struct lexer *lexer)
86 int ofs = lex_ofs (lexer) - 1;
87 return lex_ofs_token (lexer, ofs)->type == T_EQUALS ? ofs - 1 : ofs;
91 parse_enum_valist (struct lexer *lexer, va_list args)
95 const char *name = va_arg (args, char *);
98 int value = va_arg (args, int);
100 if (lex_match_id (lexer, name))
105 #define parse_enum(...) parse_enum (__VA_ARGS__, NULL_SENTINEL)
106 static int SENTINEL(0)
107 (parse_enum) (struct lexer *lexer, ...)
111 va_start (args, lexer);
112 int retval = parse_enum_valist (lexer, args);
118 #define force_parse_enum(...) force_parse_enum (__VA_ARGS__, NULL_SENTINEL)
119 static int SENTINEL(0)
120 (force_parse_enum) (struct lexer *lexer, ...)
124 va_start (args, lexer);
125 int retval = parse_enum_valist (lexer, args);
130 enum { MAX_OPTIONS = 9 };
131 const char *options[MAX_OPTIONS];
134 va_start (args, lexer);
135 while (n < MAX_OPTIONS)
137 const char *name = va_arg (args, char *);
146 lex_error_expecting_array (lexer, options, n);
153 parse_bool (struct lexer *lexer)
155 return parse_enum (lexer,
156 "ON", true, "YES", true,
157 "OFF", false, "NO", false);
161 force_parse_bool (struct lexer *lexer)
163 return force_parse_enum (lexer,
164 "ON", true, "YES", true,
165 "OFF", false, "NO", false);
169 parse_output_routing (struct lexer *lexer, enum settings_output_type type)
171 enum settings_output_devices devices;
172 if (lex_match_id (lexer, "ON") || lex_match_id (lexer, "BOTH"))
173 devices = SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL;
174 else if (lex_match_id (lexer, "TERMINAL"))
175 devices = SETTINGS_DEVICE_TERMINAL;
176 else if (lex_match_id (lexer, "LISTING"))
177 devices = SETTINGS_DEVICE_LISTING;
178 else if (lex_match_id (lexer, "OFF") || lex_match_id (lexer, "NONE"))
182 lex_error_expecting (lexer, "ON", "BOTH", "TERMINAL", "LISTING",
187 settings_set_output_routing (type, devices);
193 show_output_routing (enum settings_output_type type)
195 enum settings_output_devices devices;
198 devices = settings_get_output_routing (type);
199 if (devices & SETTINGS_DEVICE_LISTING)
200 s = devices & SETTINGS_DEVICE_TERMINAL ? "BOTH" : "LISTING";
201 else if (devices & SETTINGS_DEVICE_TERMINAL)
210 parse_integer_format (struct lexer *lexer,
211 void (*set_format) (enum integer_format))
213 int value = force_parse_enum (lexer,
214 "MSBFIRST", INTEGER_MSB_FIRST,
215 "LSBFIRST", INTEGER_LSB_FIRST,
217 "NATIVE", INTEGER_NATIVE);
223 /* Returns a name for the given INTEGER_FORMAT value. */
225 show_integer_format (enum integer_format integer_format)
227 return xasprintf ("%s (%s)",
228 (integer_format == INTEGER_MSB_FIRST ? "MSBFIRST"
229 : integer_format == INTEGER_LSB_FIRST ? "LSBFIRST"
231 integer_format == INTEGER_NATIVE ? "NATIVE" : "nonnative");
235 parse_real_format (struct lexer *lexer,
236 void (*set_format) (enum float_format))
238 int value = force_parse_enum (lexer,
239 "NATIVE", FLOAT_NATIVE_DOUBLE,
240 "ISL", FLOAT_IEEE_SINGLE_LE,
241 "ISB", FLOAT_IEEE_SINGLE_BE,
242 "IDL", FLOAT_IEEE_DOUBLE_LE,
243 "IDB", FLOAT_IEEE_DOUBLE_BE,
254 /* Returns a name for the given FLOAT_FORMAT value. */
256 show_real_format (enum float_format float_format)
258 const char *format_name = "";
260 switch (float_format)
262 case FLOAT_IEEE_SINGLE_LE:
263 format_name = _("ISL (32-bit IEEE 754 single, little-endian)");
265 case FLOAT_IEEE_SINGLE_BE:
266 format_name = _("ISB (32-bit IEEE 754 single, big-endian)");
268 case FLOAT_IEEE_DOUBLE_LE:
269 format_name = _("IDL (64-bit IEEE 754 double, little-endian)");
271 case FLOAT_IEEE_DOUBLE_BE:
272 format_name = _("IDB (64-bit IEEE 754 double, big-endian)");
276 format_name = _("VF (32-bit VAX F, VAX-endian)");
279 format_name = _("VD (64-bit VAX D, VAX-endian)");
282 format_name = _("VG (64-bit VAX G, VAX-endian)");
286 format_name = _("ZS (32-bit IBM Z hexadecimal short, big-endian)");
289 format_name = _("ZL (64-bit IBM Z hexadecimal long, big-endian)");
297 return xasprintf ("%s (%s)", format_name,
298 (float_format == FLOAT_NATIVE_DOUBLE
299 ? "NATIVE" : "nonnative"));
303 parse_unimplemented (struct lexer *lexer, const char *name)
305 int start = subcommand_start_ofs (lexer);
306 if (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
308 int end = lex_ofs (lexer) - 1;
310 lex_ofs_msg (lexer, SW, start, end, _("%s is not yet implemented."), name);
315 parse_ccx (struct lexer *lexer, enum fmt_type ccx)
317 if (!lex_force_string (lexer))
320 char *error = settings_set_cc (lex_tokcstr (lexer), ccx);
323 lex_error (lexer, "%s", error);
333 parse_BASETEXTDIRECTION (struct lexer *lexer)
335 return parse_unimplemented (lexer, "BASETEXTDIRECTION");
339 parse_BLANKS (struct lexer *lexer)
341 if (lex_match_id (lexer, "SYSMIS"))
342 settings_set_blanks (SYSMIS);
345 if (!lex_force_num (lexer))
347 settings_set_blanks (lex_number (lexer));
354 show_BLANKS (const struct dataset *ds UNUSED)
356 return (settings_get_blanks () == SYSMIS
358 : xasprintf ("%.*g", DBL_DIG + 1, settings_get_blanks ()));
362 parse_BLOCK (struct lexer *lexer)
364 return parse_unimplemented (lexer, "BLOCK");
368 parse_BOX (struct lexer *lexer)
370 return parse_unimplemented (lexer, "BOX");
374 parse_CACHE (struct lexer *lexer)
376 return parse_unimplemented (lexer, "CACHE");
380 parse_CCA (struct lexer *lexer)
382 return parse_ccx (lexer, FMT_CCA);
386 parse_CCB (struct lexer *lexer)
388 return parse_ccx (lexer, FMT_CCB);
392 parse_CCC (struct lexer *lexer)
394 return parse_ccx (lexer, FMT_CCC);
398 parse_CCD (struct lexer *lexer)
400 return parse_ccx (lexer, FMT_CCD);
404 parse_CCE (struct lexer *lexer)
406 return parse_ccx (lexer, FMT_CCE);
410 show_cc (enum fmt_type type)
412 return fmt_number_style_to_string (fmt_settings_get_style (
413 settings_get_fmt_settings (), type));
417 show_CCA (const struct dataset *ds UNUSED)
419 return show_cc (FMT_CCA);
423 show_CCB (const struct dataset *ds UNUSED)
425 return show_cc (FMT_CCB);
429 show_CCC (const struct dataset *ds UNUSED)
431 return show_cc (FMT_CCC);
435 show_CCD (const struct dataset *ds UNUSED)
437 return show_cc (FMT_CCD);
441 show_CCE (const struct dataset *ds UNUSED)
443 return show_cc (FMT_CCE);
447 parse_CELLSBREAK (struct lexer *lexer)
449 return parse_unimplemented (lexer, "CELLSBREAK");
453 parse_CMPTRANS (struct lexer *lexer)
455 return parse_unimplemented (lexer, "CMPTRANS");
459 parse_COMPRESSION (struct lexer *lexer)
461 return parse_unimplemented (lexer, "COMPRESSION");
465 parse_CTEMPLATE (struct lexer *lexer)
467 return parse_unimplemented (lexer, "CTEMPLATE");
471 parse_DECIMAL (struct lexer *lexer)
473 int decimal_char = force_parse_enum (lexer,
476 if (decimal_char != -1)
477 settings_set_decimal_char (decimal_char);
478 return decimal_char != -1;
482 show_DECIMAL (const struct dataset *ds UNUSED)
484 return xasprintf ("`%c'", settings_get_fmt_settings ()->decimal);
488 parse_EPOCH (struct lexer *lexer)
490 if (lex_match_id (lexer, "AUTOMATIC"))
491 settings_set_epoch (-1);
492 else if (lex_is_integer (lexer))
494 if (!lex_force_int_range (lexer, "EPOCH", 1500, INT_MAX))
496 settings_set_epoch (lex_integer (lexer));
501 lex_error (lexer, _("Syntax error expecting %s or year."), "AUTOMATIC");
509 show_EPOCH (const struct dataset *ds UNUSED)
511 return xasprintf ("%d", settings_get_epoch ());
515 parse_ERRORS (struct lexer *lexer)
517 return parse_output_routing (lexer, SETTINGS_OUTPUT_ERROR);
521 show_ERRORS (const struct dataset *ds UNUSED)
523 return show_output_routing (SETTINGS_OUTPUT_ERROR);
527 parse_FORMAT (struct lexer *lexer)
529 int start = subcommand_start_ofs (lexer);
532 if (!parse_format_specifier (lexer, &fmt))
535 char *error = fmt_check_output__ (fmt);
538 lex_next_error (lexer, -1, -1, "%s", error);
543 int end = lex_ofs (lexer) - 1;
544 if (fmt_is_string (fmt.type))
546 char str[FMT_STRING_LEN_MAX + 1];
547 lex_ofs_error (lexer, start, end,
548 _("%s requires numeric output format as an argument. "
549 "Specified format %s is of type string."),
550 "FORMAT", fmt_to_string (fmt, str));
554 settings_set_format (fmt);
559 show_FORMAT (const struct dataset *ds UNUSED)
561 char str[FMT_STRING_LEN_MAX + 1];
562 return xstrdup (fmt_to_string (settings_get_format (), str));
566 parse_FUZZBITS (struct lexer *lexer)
568 if (!lex_force_int_range (lexer, "FUZZBITS", 0, 20))
570 settings_set_fuzzbits (lex_integer (lexer));
576 show_FUZZBITS (const struct dataset *ds UNUSED)
578 return xasprintf ("%d", settings_get_fuzzbits ());
582 parse_HEADER (struct lexer *lexer)
584 return parse_unimplemented (lexer, "HEADER");
588 parse_INCLUDE (struct lexer *lexer)
590 int include = force_parse_bool (lexer);
592 settings_set_include (include);
593 return include != -1;
597 show_INCLUDE (const struct dataset *ds UNUSED)
599 return xstrdup (settings_get_include () ? "ON" : "OFF");
603 parse_JOURNAL (struct lexer *lexer)
605 int b = parse_bool (lexer);
610 else if (lex_is_string (lexer) || lex_token (lexer) == T_ID)
612 char *filename = utf8_to_filename (lex_tokcstr (lexer));
613 journal_set_file_name (filename);
620 lex_error (lexer, _("Syntax error expecting ON or OFF or a file name."));
627 show_JOURNAL (const struct dataset *ds UNUSED)
629 const char *enabled = journal_is_enabled () ? "ON" : "OFF";
630 const char *file_name = journal_get_file_name ();
632 ? xasprintf ("%s (%s)", enabled, file_name)
633 : xstrdup (enabled));
637 parse_LEADZERO (struct lexer *lexer)
639 int leadzero = force_parse_bool (lexer);
641 settings_set_include_leading_zero (leadzero);
642 return leadzero != -1;
646 show_LEADZERO (const struct dataset *ds UNUSED)
648 bool leadzero = settings_get_fmt_settings ()->include_leading_zero;
649 return xstrdup (leadzero ? "ON" : "OFF");
653 parse_LENGTH (struct lexer *lexer)
657 if (lex_match_id (lexer, "NONE"))
661 if (!lex_force_int_range (lexer, "LENGTH", 1, INT_MAX))
663 page_length = lex_integer (lexer);
667 if (page_length != -1)
668 settings_set_viewlength (page_length);
674 show_LENGTH (const struct dataset *ds UNUSED)
676 return xasprintf ("%d", settings_get_viewlength ());
680 parse_LOCALE (struct lexer *lexer)
682 if (!lex_force_string (lexer))
685 /* Try the argument as an encoding name, then as a locale name or alias. */
686 const char *s = lex_tokcstr (lexer);
687 if (valid_encoding (s))
688 set_default_encoding (s);
689 else if (!set_encoding_from_locale (s))
691 lex_error (lexer, _("%s is not a recognized encoding or locale name"), s);
700 show_LOCALE (const struct dataset *ds UNUSED)
702 return xstrdup (get_default_encoding ());
706 parse_MDISPLAY (struct lexer *lexer)
708 int mdisplay = force_parse_enum (lexer,
709 "TEXT", SETTINGS_MDISPLAY_TEXT,
710 "TABLES", SETTINGS_MDISPLAY_TABLES);
712 settings_set_mdisplay (mdisplay);
713 return mdisplay >= 0;
717 show_MDISPLAY (const struct dataset *ds UNUSED)
719 return xstrdup (settings_get_mdisplay () == SETTINGS_MDISPLAY_TEXT
720 ? "TEXT" : "TABLES");
724 parse_MESSAGES (struct lexer *lexer)
726 return parse_output_routing (lexer, SETTINGS_OUTPUT_NOTE);
730 show_MESSAGES (const struct dataset *ds UNUSED)
732 return show_output_routing (SETTINGS_OUTPUT_NOTE);
736 parse_MEXPAND (struct lexer *lexer)
738 int mexpand = force_parse_bool (lexer);
740 settings_set_mexpand (mexpand);
741 return mexpand != -1;
745 show_MEXPAND (const struct dataset *ds UNUSED)
747 return xstrdup (settings_get_mexpand () ? "ON" : "OFF");
751 parse_MITERATE (struct lexer *lexer)
753 if (!lex_force_int_range (lexer, "MITERATE", 1, INT_MAX))
755 settings_set_miterate (lex_integer (lexer));
761 show_MITERATE (const struct dataset *ds UNUSED)
763 return xasprintf ("%d", settings_get_miterate ());
767 parse_MNEST (struct lexer *lexer)
769 if (!lex_force_int_range (lexer, "MNEST", 1, INT_MAX))
771 settings_set_mnest (lex_integer (lexer));
777 show_MNEST (const struct dataset *ds UNUSED)
779 return xasprintf ("%d", settings_get_mnest ());
783 parse_MPRINT (struct lexer *lexer)
785 int mprint = force_parse_bool (lexer);
787 settings_set_mprint (mprint);
792 show_MPRINT (const struct dataset *ds UNUSED)
794 return xstrdup (settings_get_mprint () ? "ON" : "OFF");
798 parse_MXERRS (struct lexer *lexer)
800 if (!lex_force_int_range (lexer, "MXERRS", 1, INT_MAX))
802 settings_set_max_messages (MSG_S_ERROR, lex_integer (lexer));
808 show_MXERRS (const struct dataset *ds UNUSED)
810 return xasprintf ("%d", settings_get_max_messages (MSG_S_ERROR));
814 parse_MXLOOPS (struct lexer *lexer)
816 if (!lex_force_int_range (lexer, "MXLOOPS", 1, INT_MAX))
818 settings_set_mxloops (lex_integer (lexer));
824 show_MXLOOPS (const struct dataset *ds UNUSED)
826 return xasprintf ("%d", settings_get_mxloops ());
830 parse_MXWARNS (struct lexer *lexer)
832 if (!lex_force_int_range (lexer, "MXWARNS", 0, INT_MAX))
834 settings_set_max_messages (MSG_S_WARNING, lex_integer (lexer));
840 show_MXWARNS (const struct dataset *ds UNUSED)
842 return xasprintf ("%d", settings_get_max_messages (MSG_S_WARNING));
846 parse_PRINTBACK (struct lexer *lexer)
848 return parse_output_routing (lexer, SETTINGS_OUTPUT_SYNTAX);
852 show_PRINTBACK (const struct dataset *ds UNUSED)
854 return show_output_routing (SETTINGS_OUTPUT_SYNTAX);
858 parse_RESULTS (struct lexer *lexer)
860 return parse_output_routing (lexer, SETTINGS_OUTPUT_RESULT);
864 show_RESULTS (const struct dataset *ds UNUSED)
866 return show_output_routing (SETTINGS_OUTPUT_RESULT);
870 parse_RIB (struct lexer *lexer)
872 return parse_integer_format (lexer, settings_set_input_integer_format);
876 show_RIB (const struct dataset *ds UNUSED)
878 return show_integer_format (settings_get_input_integer_format ());
882 parse_RRB (struct lexer *lexer)
884 return parse_real_format (lexer, settings_set_input_float_format);
888 show_RRB (const struct dataset *ds UNUSED)
890 return show_real_format (settings_get_input_float_format ());
894 parse_SAFER (struct lexer *lexer)
896 bool ok = force_parse_enum (lexer, "ON", true, "YES", true) != -1;
898 settings_set_safer_mode ();
903 show_SAFER (const struct dataset *ds UNUSED)
905 return xstrdup (settings_get_safer_mode () ? "ON" : "OFF");
909 parse_SCOMPRESSION (struct lexer *lexer)
911 int value = force_parse_bool (lexer);
913 settings_set_scompression (value);
918 show_SCOMPRESSION (const struct dataset *ds UNUSED)
920 return xstrdup (settings_get_scompression () ? "ON" : "OFF");
924 parse_SEED (struct lexer *lexer)
926 if (lex_match_id (lexer, "RANDOM"))
930 if (!lex_force_num (lexer))
932 set_rng (lex_number (lexer));
940 parse_SMALL (struct lexer *lexer)
942 if (!lex_force_num (lexer))
944 settings_set_small (lex_number (lexer));
950 show_SMALL (const struct dataset *ds UNUSED)
952 char buf[DBL_BUFSIZE_BOUND];
953 if (dtoastr (buf, sizeof buf, 0, 0, settings_get_small ()) < 0)
955 return xstrdup (buf);
959 show_SPLIT (const struct dataset *ds)
961 const struct dictionary *dict = dataset_dict (ds);
964 switch (dict_get_split_type (dict))
967 return xstrdup ("none");
981 struct string s = DS_EMPTY_INITIALIZER;
983 size_t n = dict_get_n_splits (dict);
984 const struct variable *const *vars = dict_get_split_vars (dict);
985 for (size_t i = 0; i < n; i++)
988 ds_put_cstr (&s, ", ");
989 ds_put_cstr (&s, var_get_name (vars[i]));
991 ds_put_format (&s, " (%s)", type);
992 return ds_steal_cstr (&s);
996 show_SUBTITLE (const struct dataset *ds UNUSED)
998 return xstrdup (output_get_subtitle ());
1002 show_TEMPDIR (const struct dataset *ds UNUSED)
1004 return xstrdup (temp_dir_name ());
1008 show_TITLE (const struct dataset *ds UNUSED)
1010 return xstrdup (output_get_title ());
1014 parse_TNUMBERS (struct lexer *lexer)
1016 int value = force_parse_enum (lexer,
1017 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
1018 "VALUES", SETTINGS_VALUE_SHOW_VALUE,
1019 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
1021 settings_set_show_values (value);
1026 show_TNUMBERS (const struct dataset *ds UNUSED)
1028 enum settings_value_show tnumbers = settings_get_show_values ();
1029 return xstrdup (tnumbers == SETTINGS_VALUE_SHOW_LABEL ? "LABELS"
1030 : tnumbers == SETTINGS_VALUE_SHOW_VALUE ? "VALUES"
1035 parse_TVARS (struct lexer *lexer)
1037 int value = force_parse_enum (lexer,
1038 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
1039 "NAMES", SETTINGS_VALUE_SHOW_VALUE,
1040 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
1042 settings_set_show_variables (value);
1047 show_TVARS (const struct dataset *ds UNUSED)
1049 enum settings_value_show tvars = settings_get_show_variables ();
1050 return xstrdup (tvars == SETTINGS_VALUE_SHOW_LABEL ? "LABELS"
1051 : tvars == SETTINGS_VALUE_SHOW_VALUE ? "NAMES"
1056 parse_TLOOK (struct lexer *lexer)
1058 if (lex_match_id (lexer, "NONE"))
1059 pivot_table_look_set_default (pivot_table_look_builtin_default ());
1060 else if (lex_is_string (lexer))
1062 struct pivot_table_look *look;
1063 char *error = pivot_table_look_read (lex_tokcstr (lexer), &look);
1068 msg (SE, "%s", error);
1073 pivot_table_look_set_default (look);
1074 pivot_table_look_unref (look);
1081 parse_UNDEFINED (struct lexer *lexer)
1083 int value = force_parse_enum (lexer,
1087 settings_set_undefined (value);
1092 show_UNDEFINED (const struct dataset *ds UNUSED)
1094 return xstrdup (settings_get_undefined () ? "WARN" : "NOWARN");
1098 show_VERSION (const struct dataset *ds UNUSED)
1100 return strdup (announced_version);
1104 show_WEIGHT (const struct dataset *ds)
1106 const struct variable *var = dict_get_weight (dataset_dict (ds));
1107 return xstrdup (var != NULL ? var_get_name (var) : "OFF");
1111 parse_WIB (struct lexer *lexer)
1113 return parse_integer_format (lexer, settings_set_output_integer_format);
1117 show_WIB (const struct dataset *ds UNUSED)
1119 return show_integer_format (settings_get_output_integer_format ());
1123 parse_WRB (struct lexer *lexer)
1125 return parse_real_format (lexer, settings_set_output_float_format);
1129 show_WRB (const struct dataset *ds UNUSED)
1131 return show_real_format (settings_get_output_float_format ());
1135 parse_WIDTH (struct lexer *lexer)
1137 if (lex_match_id (lexer, "NARROW"))
1138 settings_set_viewwidth (79);
1139 else if (lex_match_id (lexer, "WIDE"))
1140 settings_set_viewwidth (131);
1143 if (!lex_force_int_range (lexer, "WIDTH", 40, INT_MAX))
1145 settings_set_viewwidth (lex_integer (lexer));
1153 show_WIDTH (const struct dataset *ds UNUSED)
1155 return xasprintf ("%d", settings_get_viewwidth ());
1159 parse_WORKSPACE (struct lexer *lexer)
1161 if (!lex_force_int_range (lexer, "WORKSPACE",
1162 settings_get_testing_mode () ? 1 : 1024,
1165 int workspace = lex_integer (lexer);
1167 settings_set_workspace (MIN (workspace, INT_MAX / 1024) * 1024);
1172 show_WORKSPACE (const struct dataset *ds UNUSED)
1174 size_t ws = settings_get_workspace () / 1024L;
1175 return xasprintf ("%zu", ws);
1179 show_DIRECTORY (const struct dataset *ds UNUSED)
1188 buf = xrealloc (buf, len);
1190 while (NULL == (wd = getcwd (buf, len)));
1196 show_N (const struct dataset *ds)
1198 const struct casereader *reader = dataset_source (ds);
1200 ? xasprintf ("%lld", (long long int) casereader_count_cases (reader))
1201 : xstrdup (_("Unknown")));
1205 do_show (const struct dataset *ds, const struct setting *s,
1206 struct pivot_table **ptp)
1208 struct pivot_table *pt = *ptp;
1211 pt = *ptp = pivot_table_create (N_("Settings"));
1212 pivot_dimension_create (pt, PIVOT_AXIS_ROW, N_("Setting"));
1215 struct pivot_value *name = pivot_value_new_user_text (s->name, SIZE_MAX);
1216 char *text = s->show (ds);
1218 text = xstrdup("empty");
1219 struct pivot_value *value = pivot_value_new_user_text_nocopy (text);
1221 int row = pivot_category_create_leaf (pt->dimensions[0]->root, name);
1222 pivot_table_put1 (pt, row, value);
1226 show_warranty (const struct dataset *ds UNUSED)
1228 fputs (lack_of_warranty, stdout);
1232 show_copying (const struct dataset *ds UNUSED)
1234 fputs (copyleft, stdout);
1238 add_row (struct pivot_table *table, const char *attribute,
1241 int row = pivot_category_create_leaf (table->dimensions[0]->root,
1242 pivot_value_new_text (attribute));
1244 pivot_table_put1 (table, row, pivot_value_new_user_text (value, -1));
1248 show_system (const struct dataset *ds UNUSED)
1250 struct pivot_table *table = pivot_table_create (N_("System Information"));
1251 pivot_dimension_create (table, PIVOT_AXIS_ROW, N_("Attribute"));
1253 add_row (table, N_("Version"), version);
1254 add_row (table, N_("Host System"), host_system);
1255 add_row (table, N_("Build System"), build_system);
1256 add_row (table, N_("Locale Directory"), relocate (locale_dir));
1257 add_row (table, N_("Compiler Version"),
1264 pivot_table_submit (table);
1267 static const struct setting settings[] = {
1268 { "BASETEXTDIRECTION", parse_BASETEXTDIRECTION, NULL },
1269 { "BLANKS", parse_BLANKS, show_BLANKS },
1270 { "BLOCK", parse_BLOCK, NULL },
1271 { "BOX", parse_BOX, NULL },
1272 { "CACHE", parse_CACHE, NULL },
1273 { "CCA", parse_CCA, show_CCA },
1274 { "CCB", parse_CCB, show_CCB },
1275 { "CCC", parse_CCC, show_CCC },
1276 { "CCD", parse_CCD, show_CCD },
1277 { "CCE", parse_CCE, show_CCE },
1278 { "CELLSBREAK", parse_CELLSBREAK, NULL },
1279 { "CMPTRANS", parse_CMPTRANS, NULL },
1280 { "COMPRESSION", parse_COMPRESSION, NULL },
1281 { "CTEMPLATE", parse_CTEMPLATE, NULL },
1282 { "DECIMAL", parse_DECIMAL, show_DECIMAL },
1283 { "DIRECTORY", NULL, show_DIRECTORY },
1284 { "EPOCH", parse_EPOCH, show_EPOCH },
1285 { "ERRORS", parse_ERRORS, show_ERRORS },
1286 { "FORMAT", parse_FORMAT, show_FORMAT },
1287 { "FUZZBITS", parse_FUZZBITS, show_FUZZBITS },
1288 { "HEADER", parse_HEADER, NULL },
1289 { "INCLUDE", parse_INCLUDE, show_INCLUDE },
1290 { "JOURNAL", parse_JOURNAL, show_JOURNAL },
1291 { "LEADZERO", parse_LEADZERO, show_LEADZERO },
1292 { "LENGTH", parse_LENGTH, show_LENGTH },
1293 { "LOCALE", parse_LOCALE, show_LOCALE },
1294 { "MDISPLAY", parse_MDISPLAY, show_MDISPLAY },
1295 { "MESSAGES", parse_MESSAGES, show_MESSAGES },
1296 { "MEXPAND", parse_MEXPAND, show_MEXPAND },
1297 { "MITERATE", parse_MITERATE, show_MITERATE },
1298 { "MNEST", parse_MNEST, show_MNEST },
1299 { "MPRINT", parse_MPRINT, show_MPRINT },
1300 { "MXERRS", parse_MXERRS, show_MXERRS },
1301 { "MXLOOPS", parse_MXLOOPS, show_MXLOOPS },
1302 { "MXWARNS", parse_MXWARNS, show_MXWARNS },
1303 { "N", NULL, show_N },
1304 { "PRINTBACK", parse_PRINTBACK, show_PRINTBACK },
1305 { "RESULTS", parse_RESULTS, show_RESULTS },
1306 { "RIB", parse_RIB, show_RIB },
1307 { "RRB", parse_RRB, show_RRB },
1308 { "SAFER", parse_SAFER, show_SAFER },
1309 { "SCOMPRESSION", parse_SCOMPRESSION, show_SCOMPRESSION },
1310 { "SEED", parse_SEED, NULL },
1311 { "SMALL", parse_SMALL, show_SMALL },
1312 { "SPLIT", NULL, show_SPLIT },
1313 { "TEMPDIR", NULL, show_TEMPDIR },
1314 { "TNUMBERS", parse_TNUMBERS, show_TNUMBERS },
1315 { "TVARS", parse_TVARS, show_TVARS },
1316 { "TLOOK", parse_TLOOK, NULL },
1317 { "UNDEFINED", parse_UNDEFINED, show_UNDEFINED },
1318 { "VERSION", NULL, show_VERSION },
1319 { "WEIGHT", NULL, show_WEIGHT },
1320 { "WIB", parse_WIB, show_WIB },
1321 { "WRB", parse_WRB, show_WRB },
1322 { "WIDTH", parse_WIDTH, show_WIDTH },
1323 { "WORKSPACE", parse_WORKSPACE, show_WORKSPACE },
1325 enum { N_SETTINGS = sizeof settings / sizeof *settings };
1328 parse_setting (struct lexer *lexer)
1330 for (size_t i = 0; i < N_SETTINGS; i++)
1331 if (settings[i].set && match_subcommand (lexer, settings[i].name))
1332 return settings[i].set (lexer);
1334 lex_error (lexer, _("Syntax error expecting the name of a setting."));
1339 cmd_set (struct lexer *lexer, struct dataset *ds UNUSED)
1343 lex_match (lexer, T_SLASH);
1344 if (lex_token (lexer) == T_ENDCMD)
1347 if (!parse_setting (lexer))
1355 show_all (const struct dataset *ds, struct pivot_table **ptp)
1357 for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1358 if (settings[i].show)
1359 do_show (ds, &settings[i], ptp);
1363 show_all_cc (const struct dataset *ds, struct pivot_table **ptp)
1365 for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1367 const struct setting *s = &settings[i];
1368 if (s->show && !strncmp (s->name, "CC", 2))
1369 do_show (ds, s, ptp);
1374 show_environment (void)
1376 struct pivot_table *pt = pivot_table_create (N_("Environment Variables"));
1377 pivot_dimension_create (pt, PIVOT_AXIS_ROW, N_("Variable"));
1379 struct string_array sa = STRING_ARRAY_INITIALIZER;
1380 for (char **env = environ; *env; env++)
1381 string_array_append (&sa, *env);
1382 string_array_sort (&sa);
1384 for (size_t i = 0; i < sa.n; i++)
1386 struct substring value = ss_cstr (sa.strings[i]);
1387 struct substring variable;
1388 ss_get_until (&value, '=', &variable);
1390 char *variable_s = ss_xstrdup (variable);
1391 char *value_s = ss_xstrdup (value);
1392 add_row (pt, variable_s, value_s);
1396 string_array_destroy (&sa);
1397 pivot_table_submit (pt);
1401 cmd_show (struct lexer *lexer, struct dataset *ds)
1403 struct pivot_table *pt = NULL;
1404 if (lex_token (lexer) == T_ENDCMD)
1407 pivot_table_submit (pt);
1413 if (lex_match (lexer, T_ALL))
1415 else if (lex_match_id (lexer, "CC"))
1416 show_all_cc (ds, &pt);
1417 else if (lex_match_id (lexer, "WARRANTY"))
1419 else if (lex_match_id (lexer, "COPYING") || lex_match_id (lexer, "LICENSE"))
1421 else if (lex_match_id (lexer, "SYSTEM"))
1423 else if (lex_match_id (lexer, "ENVIRONMENT"))
1424 show_environment ();
1425 else if (lex_match_id (lexer, "TITLE"))
1427 struct setting s = { .name = "TITLE", .show = show_TITLE };
1428 do_show (ds, &s, &pt);
1430 else if (lex_match_id (lexer, "SUBTITLE"))
1432 struct setting s = { .name = "SUBTITLE", .show = show_SUBTITLE };
1433 do_show (ds, &s, &pt);
1435 else if (lex_token (lexer) == T_ID)
1437 for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1439 const struct setting *s = &settings[i];
1440 if (s->show && lex_match_id (lexer, s->name))
1442 do_show (ds, s, &pt);
1446 lex_error (lexer, _("Syntax error expecting the name of a setting."));
1453 lex_error (lexer, _("Syntax error expecting the name of a setting."));
1457 lex_match (lexer, T_SLASH);
1459 while (lex_token (lexer) != T_ENDCMD);
1462 pivot_table_submit (pt);
1467 #define MAX_SAVED_SETTINGS 5
1469 static struct settings *saved_settings[MAX_SAVED_SETTINGS];
1470 static int n_saved_settings;
1473 cmd_preserve (struct lexer *lexer, struct dataset *ds UNUSED)
1475 if (n_saved_settings < MAX_SAVED_SETTINGS)
1477 saved_settings[n_saved_settings++] = settings_get ();
1482 lex_next_error (lexer, -1, -1,
1483 _("Too many %s commands without a %s: at most "
1484 "%d levels of saved settings are allowed."),
1485 "PRESERVE", "RESTORE",
1486 MAX_SAVED_SETTINGS);
1487 return CMD_CASCADING_FAILURE;
1492 cmd_restore (struct lexer *lexer, struct dataset *ds UNUSED)
1494 if (n_saved_settings > 0)
1496 struct settings *s = saved_settings[--n_saved_settings];
1498 settings_destroy (s);
1503 lex_next_error (lexer, -1, -1,
1504 _("%s without matching %s."), "RESTORE", "PRESERVE");