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 "gl/ftoastr.h"
27 #include "gl/vasnprintf.h"
29 #include "data/casereader.h"
30 #include "data/data-in.h"
31 #include "data/data-out.h"
32 #include "data/dataset.h"
33 #include "data/dictionary.h"
34 #include "data/format.h"
35 #include "data/settings.h"
36 #include "data/value.h"
37 #include "data/variable.h"
38 #include "language/command.h"
39 #include "language/lexer/format-parser.h"
40 #include "language/lexer/lexer.h"
41 #include "libpspp/assertion.h"
42 #include "libpspp/compiler.h"
43 #include "libpspp/copyleft.h"
44 #include "libpspp/temp-file.h"
45 #include "libpspp/version.h"
46 #include "libpspp/float-format.h"
47 #include "libpspp/i18n.h"
48 #include "libpspp/integer-format.h"
49 #include "libpspp/message.h"
50 #include "math/random.h"
51 #include "output/driver.h"
52 #include "output/journal.h"
53 #include "output/pivot-table.h"
55 #include "gl/minmax.h"
56 #include "gl/xalloc.h"
59 #define _(msgid) gettext (msgid)
64 bool (*set) (struct lexer *);
65 char *(*show) (const struct dataset *);
69 match_subcommand (struct lexer *lexer, const char *name)
71 if (lex_match_id (lexer, name))
73 lex_match (lexer, T_EQUALS);
81 parse_enum_valist (struct lexer *lexer, va_list args)
85 const char *name = va_arg (args, char *);
88 int value = va_arg (args, int);
90 if (lex_match_id (lexer, name))
95 #define parse_enum(...) parse_enum (__VA_ARGS__, NULL_SENTINEL)
96 static int SENTINEL(0)
97 (parse_enum) (struct lexer *lexer, ...)
101 va_start (args, lexer);
102 int retval = parse_enum_valist (lexer, args);
108 #define force_parse_enum(...) force_parse_enum (__VA_ARGS__, NULL_SENTINEL)
109 static int SENTINEL(0)
110 (force_parse_enum) (struct lexer *lexer, ...)
114 va_start (args, lexer);
115 int retval = parse_enum_valist (lexer, args);
120 enum { MAX_OPTIONS = 9 };
121 const char *options[MAX_OPTIONS];
124 va_start (args, lexer);
125 while (n < MAX_OPTIONS)
127 const char *name = va_arg (args, char *);
136 lex_error_expecting_array (lexer, options, n);
143 parse_bool (struct lexer *lexer)
145 return parse_enum (lexer,
146 "ON", true, "YES", true,
147 "OFF", false, "NO", false);
151 force_parse_bool (struct lexer *lexer)
153 return force_parse_enum (lexer,
154 "ON", true, "YES", true,
155 "OFF", false, "NO", false);
159 force_parse_int (struct lexer *lexer, int *integerp)
161 if (!lex_force_int (lexer))
163 *integerp = lex_integer (lexer);
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 (lexer, NULL);
186 settings_set_output_routing (type, devices);
192 show_output_routing (enum settings_output_type type)
194 enum settings_output_devices devices;
197 devices = settings_get_output_routing (type);
198 if (devices & SETTINGS_DEVICE_LISTING)
199 s = devices & SETTINGS_DEVICE_TERMINAL ? "BOTH" : "LISTING";
200 else if (devices & SETTINGS_DEVICE_TERMINAL)
209 parse_integer_format (struct lexer *lexer,
210 void (*set_format) (enum integer_format))
212 int value = force_parse_enum (lexer,
213 "MSBFIRST", INTEGER_MSB_FIRST,
214 "LSBFIRST", INTEGER_LSB_FIRST,
216 "NATIVE", INTEGER_NATIVE);
222 /* Returns a name for the given INTEGER_FORMAT value. */
224 show_integer_format (enum integer_format integer_format)
226 return xasprintf ("%s (%s)",
227 (integer_format == INTEGER_MSB_FIRST ? "MSBFIRST"
228 : integer_format == INTEGER_LSB_FIRST ? "LSBFIRST"
230 integer_format == INTEGER_NATIVE ? "NATIVE" : "nonnative");
234 parse_real_format (struct lexer *lexer,
235 void (*set_format) (enum float_format))
237 int value = force_parse_enum (lexer,
238 "NATIVE", FLOAT_NATIVE_DOUBLE,
239 "ISL", FLOAT_IEEE_SINGLE_LE,
240 "ISB", FLOAT_IEEE_SINGLE_BE,
241 "IDL", FLOAT_IEEE_DOUBLE_LE,
242 "IDB", FLOAT_IEEE_DOUBLE_BE,
253 /* Returns a name for the given FLOAT_FORMAT value. */
255 show_real_format (enum float_format float_format)
257 const char *format_name = "";
259 switch (float_format)
261 case FLOAT_IEEE_SINGLE_LE:
262 format_name = _("ISL (32-bit IEEE 754 single, little-endian)");
264 case FLOAT_IEEE_SINGLE_BE:
265 format_name = _("ISB (32-bit IEEE 754 single, big-endian)");
267 case FLOAT_IEEE_DOUBLE_LE:
268 format_name = _("IDL (64-bit IEEE 754 double, little-endian)");
270 case FLOAT_IEEE_DOUBLE_BE:
271 format_name = _("IDB (64-bit IEEE 754 double, big-endian)");
275 format_name = _("VF (32-bit VAX F, VAX-endian)");
278 format_name = _("VD (64-bit VAX D, VAX-endian)");
281 format_name = _("VG (64-bit VAX G, VAX-endian)");
285 format_name = _("ZS (32-bit IBM Z hexadecimal short, big-endian)");
288 format_name = _("ZL (64-bit IBM Z hexadecimal long, big-endian)");
296 return xasprintf ("%s (%s)", format_name,
297 (float_format == FLOAT_NATIVE_DOUBLE
298 ? "NATIVE" : "nonnative"));
302 parse_unimplemented (struct lexer *lexer, const char *name)
304 msg (SW, _("%s is not yet implemented."), name);
305 if (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
311 parse_ccx (struct lexer *lexer, enum fmt_type ccx)
313 if (!lex_force_string (lexer))
316 settings_set_cc (lex_tokcstr (lexer), ccx);
322 parse_BASETEXTDIRECTION (struct lexer *lexer)
324 return parse_unimplemented (lexer, "BASETEXTDIRECTION");
328 parse_BLANKS (struct lexer *lexer)
330 if (lex_match_id (lexer, "SYSMIS"))
331 settings_set_blanks (SYSMIS);
334 if (!lex_force_num (lexer))
336 settings_set_blanks (lex_number (lexer));
343 show_BLANKS (const struct dataset *ds UNUSED)
345 return (settings_get_blanks () == SYSMIS
347 : xasprintf ("%.*g", DBL_DIG + 1, settings_get_blanks ()));
351 parse_BLOCK (struct lexer *lexer)
353 return parse_unimplemented (lexer, "BLOCK");
357 parse_BOX (struct lexer *lexer)
359 return parse_unimplemented (lexer, "BOX");
363 parse_CACHE (struct lexer *lexer)
365 return parse_unimplemented (lexer, "CACHE");
369 parse_CCA (struct lexer *lexer)
371 return parse_ccx (lexer, FMT_CCA);
375 parse_CCB (struct lexer *lexer)
377 return parse_ccx (lexer, FMT_CCB);
381 parse_CCC (struct lexer *lexer)
383 return parse_ccx (lexer, FMT_CCC);
387 parse_CCD (struct lexer *lexer)
389 return parse_ccx (lexer, FMT_CCD);
393 parse_CCE (struct lexer *lexer)
395 return parse_ccx (lexer, FMT_CCE);
399 show_cc (enum fmt_type type)
401 return fmt_number_style_to_string (fmt_settings_get_style (
402 settings_get_fmt_settings (), type));
406 show_CCA (const struct dataset *ds UNUSED)
408 return show_cc (FMT_CCA);
412 show_CCB (const struct dataset *ds UNUSED)
414 return show_cc (FMT_CCB);
418 show_CCC (const struct dataset *ds UNUSED)
420 return show_cc (FMT_CCC);
424 show_CCD (const struct dataset *ds UNUSED)
426 return show_cc (FMT_CCD);
430 show_CCE (const struct dataset *ds UNUSED)
432 return show_cc (FMT_CCE);
436 parse_CELLSBREAK (struct lexer *lexer)
438 return parse_unimplemented (lexer, "CELLSBREAK");
442 parse_CMPTRANS (struct lexer *lexer)
444 return parse_unimplemented (lexer, "CMPTRANS");
448 parse_COMPRESSION (struct lexer *lexer)
450 return parse_unimplemented (lexer, "COMPRESSION");
454 parse_CTEMPLATE (struct lexer *lexer)
456 return parse_unimplemented (lexer, "CTEMPLATE");
460 parse_DECIMAL (struct lexer *lexer)
462 int decimal_char = force_parse_enum (lexer,
465 if (decimal_char != -1)
466 settings_set_decimal_char (decimal_char);
467 return decimal_char != -1;
471 show_DECIMAL (const struct dataset *ds UNUSED)
473 return xasprintf ("`%c'", settings_get_fmt_settings ()->decimal);
477 parse_EPOCH (struct lexer *lexer)
479 if (lex_match_id (lexer, "AUTOMATIC"))
480 settings_set_epoch (-1);
481 else if (lex_is_integer (lexer))
483 if (!lex_force_int_range (lexer, "EPOCH", 1500, INT_MAX))
485 settings_set_epoch (lex_integer (lexer));
490 lex_error (lexer, _("expecting %s or year"), "AUTOMATIC");
498 show_EPOCH (const struct dataset *ds UNUSED)
500 return xasprintf ("%d", settings_get_epoch ());
504 parse_ERRORS (struct lexer *lexer)
506 return parse_output_routing (lexer, SETTINGS_OUTPUT_ERROR);
510 show_ERRORS (const struct dataset *ds UNUSED)
512 return show_output_routing (SETTINGS_OUTPUT_ERROR);
516 parse_FORMAT (struct lexer *lexer)
520 lex_match (lexer, T_EQUALS);
521 if (!parse_format_specifier (lexer, &fmt))
524 if (!fmt_check_output (&fmt))
527 if (fmt_is_string (fmt.type))
529 char str[FMT_STRING_LEN_MAX + 1];
530 msg (SE, _("%s requires numeric output format as an argument. "
531 "Specified format %s is of type string."),
533 fmt_to_string (&fmt, str));
537 settings_set_format (&fmt);
542 show_FORMAT (const struct dataset *ds UNUSED)
544 char str[FMT_STRING_LEN_MAX + 1];
545 return xstrdup (fmt_to_string (settings_get_format (), str));
549 parse_FUZZBITS (struct lexer *lexer)
551 if (!lex_force_int_range (lexer, "FUZZITS", 0, 20))
553 settings_set_fuzzbits (lex_integer (lexer));
559 show_FUZZBITS (const struct dataset *ds UNUSED)
561 return xasprintf ("%d", settings_get_fuzzbits ());
565 parse_HEADER (struct lexer *lexer)
567 return parse_unimplemented (lexer, "HEADER");
571 parse_INCLUDE (struct lexer *lexer)
573 int include = force_parse_bool (lexer);
575 settings_set_include (include);
576 return include != -1;
580 show_INCLUDE (const struct dataset *ds UNUSED)
582 return xstrdup (settings_get_include () ? "ON" : "OFF");
586 parse_JOURNAL (struct lexer *lexer)
588 int b = parse_bool (lexer);
593 else if (lex_is_string (lexer) || lex_token (lexer) == T_ID)
595 char *filename = utf8_to_filename (lex_tokcstr (lexer));
596 journal_set_file_name (filename);
603 lex_error (lexer, NULL);
610 show_JOURNAL (const struct dataset *ds UNUSED)
612 const char *enabled = journal_is_enabled () ? "ON" : "OFF";
613 const char *file_name = journal_get_file_name ();
615 ? xasprintf ("%s (%s)", enabled, file_name)
616 : xstrdup (enabled));
620 parse_LENGTH (struct lexer *lexer)
624 if (lex_match_id (lexer, "NONE"))
628 if (!lex_force_int_range (lexer, "LENGTH", 1, INT_MAX))
630 page_length = lex_integer (lexer);
634 if (page_length != -1)
635 settings_set_viewlength (page_length);
641 show_LENGTH (const struct dataset *ds UNUSED)
643 return xasprintf ("%d", settings_get_viewlength ());
647 parse_LOCALE (struct lexer *lexer)
649 if (!lex_force_string (lexer))
652 /* Try the argument as an encoding name, then as a locale name or alias. */
653 const char *s = lex_tokcstr (lexer);
654 if (valid_encoding (s))
655 set_default_encoding (s);
656 else if (!set_encoding_from_locale (s))
658 msg (ME, _("%s is not a recognized encoding or locale name"), s);
667 show_LOCALE (const struct dataset *ds UNUSED)
669 return xstrdup (get_default_encoding ());
673 parse_MESSAGES (struct lexer *lexer)
675 return parse_output_routing (lexer, SETTINGS_OUTPUT_NOTE);
679 show_MESSAGES (const struct dataset *ds UNUSED)
681 return show_output_routing (SETTINGS_OUTPUT_NOTE);
685 parse_MEXPAND (struct lexer *lexer)
687 int mexpand = force_parse_bool (lexer);
689 settings_set_mexpand (mexpand);
690 return mexpand != -1;
694 show_MEXPAND (const struct dataset *ds UNUSED)
696 return xstrdup (settings_get_mexpand () ? "ON" : "OFF");
700 parse_MITERATE (struct lexer *lexer)
702 if (!lex_force_int_range (lexer, "MITERATE", 1, INT_MAX))
704 settings_set_miterate (lex_integer (lexer));
710 show_MITERATE (const struct dataset *ds UNUSED)
712 return xasprintf ("%d", settings_get_miterate ());
716 parse_MNEST (struct lexer *lexer)
718 if (!lex_force_int_range (lexer, "MNEST", 1, INT_MAX))
720 settings_set_mnest (lex_integer (lexer));
726 show_MNEST (const struct dataset *ds UNUSED)
728 return xasprintf ("%d", settings_get_mnest ());
732 parse_MPRINT (struct lexer *lexer)
734 int mprint = force_parse_bool (lexer);
736 settings_set_mprint (mprint);
741 show_MPRINT (const struct dataset *ds UNUSED)
743 return xstrdup (settings_get_mprint () ? "ON" : "OFF");
747 parse_MXERRS (struct lexer *lexer)
750 if (!force_parse_int (lexer, &n))
754 settings_set_max_messages (MSG_S_ERROR, n);
756 msg (SE, _("%s must be at least 1."), "MXERRS");
761 show_MXERRS (const struct dataset *ds UNUSED)
763 return xasprintf ("%d", settings_get_max_messages (MSG_S_ERROR));
767 parse_MXLOOPS (struct lexer *lexer)
770 if (!force_parse_int (lexer, &n))
774 settings_set_mxloops (n);
776 msg (SE, _("%s must be at least 1."), "MXLOOPS");
781 show_MXLOOPS (const struct dataset *ds UNUSED)
783 return xasprintf ("%d", settings_get_mxloops ());
787 parse_MXWARNS (struct lexer *lexer)
790 if (!force_parse_int (lexer, &n))
794 settings_set_max_messages (MSG_S_WARNING, n);
796 msg (SE, _("%s must not be negative."), "MXWARNS");
801 show_MXWARNS (const struct dataset *ds UNUSED)
803 return xasprintf ("%d", settings_get_max_messages (MSG_S_WARNING));
807 parse_PRINTBACK (struct lexer *lexer)
809 return parse_output_routing (lexer, SETTINGS_OUTPUT_SYNTAX);
813 show_PRINTBACK (const struct dataset *ds UNUSED)
815 return show_output_routing (SETTINGS_OUTPUT_SYNTAX);
819 parse_RESULTS (struct lexer *lexer)
821 return parse_output_routing (lexer, SETTINGS_OUTPUT_RESULT);
825 show_RESULTS (const struct dataset *ds UNUSED)
827 return show_output_routing (SETTINGS_OUTPUT_RESULT);
831 parse_RIB (struct lexer *lexer)
833 return parse_integer_format (lexer, settings_set_input_integer_format);
837 show_RIB (const struct dataset *ds UNUSED)
839 return show_integer_format (settings_get_input_integer_format ());
843 parse_RRB (struct lexer *lexer)
845 return parse_real_format (lexer, settings_set_input_float_format);
849 show_RRB (const struct dataset *ds UNUSED)
851 return show_real_format (settings_get_input_float_format ());
855 parse_SAFER (struct lexer *lexer)
857 bool ok = force_parse_enum (lexer, "ON", true, "YES", true) != -1;
859 settings_set_safer_mode ();
864 show_SAFER (const struct dataset *ds UNUSED)
866 return xstrdup (settings_get_safer_mode () ? "ON" : "OFF");
870 parse_SCOMPRESSION (struct lexer *lexer)
872 int value = force_parse_bool (lexer);
874 settings_set_scompression (value);
879 show_SCOMPRESSION (const struct dataset *ds UNUSED)
881 return xstrdup (settings_get_scompression () ? "ON" : "OFF");
885 parse_SEED (struct lexer *lexer)
887 if (lex_match_id (lexer, "RANDOM"))
891 if (!lex_force_num (lexer))
893 set_rng (lex_number (lexer));
901 parse_SMALL (struct lexer *lexer)
903 if (!lex_force_num (lexer))
905 settings_set_small (lex_number (lexer));
911 show_SMALL (const struct dataset *ds UNUSED)
913 char buf[DBL_BUFSIZE_BOUND];
914 if (dtoastr (buf, sizeof buf, 0, 0, settings_get_small ()) < 0)
916 return xstrdup (buf);
920 show_SUBTITLE (const struct dataset *ds UNUSED)
922 return xstrdup (output_get_subtitle ());
926 show_SYSTEM (const struct dataset *ds UNUSED)
928 return xstrdup (host_system);
932 show_TEMPDIR (const struct dataset *ds UNUSED)
934 return xstrdup (temp_dir_name ());
938 show_TITLE (const struct dataset *ds UNUSED)
940 return xstrdup (output_get_title ());
944 parse_TNUMBERS (struct lexer *lexer)
946 int value = force_parse_enum (lexer,
947 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
948 "VALUES", SETTINGS_VALUE_SHOW_VALUE,
949 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
951 settings_set_show_values (value);
956 show_TNUMBERS (const struct dataset *ds UNUSED)
958 enum settings_value_show tnumbers = settings_get_show_values ();
959 return xstrdup (tnumbers == SETTINGS_VALUE_SHOW_LABEL ? "LABELS"
960 : tnumbers == SETTINGS_VALUE_SHOW_VALUE ? "VALUES"
965 parse_TVARS (struct lexer *lexer)
967 int value = force_parse_enum (lexer,
968 "LABELS", SETTINGS_VALUE_SHOW_LABEL,
969 "NAMES", SETTINGS_VALUE_SHOW_VALUE,
970 "BOTH", SETTINGS_VALUE_SHOW_BOTH);
972 settings_set_show_variables (value);
977 show_TVARS (const struct dataset *ds UNUSED)
979 enum settings_value_show tvars = settings_get_show_variables ();
980 return xstrdup (tvars == SETTINGS_VALUE_SHOW_LABEL ? "LABELS"
981 : tvars == SETTINGS_VALUE_SHOW_VALUE ? "NAMES"
986 parse_TLOOK (struct lexer *lexer)
988 if (lex_match_id (lexer, "NONE"))
989 pivot_table_look_set_default (pivot_table_look_builtin_default ());
990 else if (lex_is_string (lexer))
992 struct pivot_table_look *look;
993 char *error = pivot_table_look_read (lex_tokcstr (lexer), &look);
998 msg (SE, "%s", error);
1003 pivot_table_look_set_default (look);
1004 pivot_table_look_unref (look);
1011 parse_UNDEFINED (struct lexer *lexer)
1013 int value = force_parse_enum (lexer,
1017 settings_set_undefined (value);
1022 show_UNDEFINED (const struct dataset *ds UNUSED)
1024 return xstrdup (settings_get_undefined () ? "WARN" : "NOWARN");
1028 show_VERSION (const struct dataset *ds UNUSED)
1030 return strdup (announced_version);
1034 show_WEIGHT (const struct dataset *ds)
1036 const struct variable *var = dict_get_weight (dataset_dict (ds));
1037 return xstrdup (var != NULL ? var_get_name (var) : "OFF");
1041 parse_WIB (struct lexer *lexer)
1043 return parse_integer_format (lexer, settings_set_output_integer_format);
1047 show_WIB (const struct dataset *ds UNUSED)
1049 return show_integer_format (settings_get_output_integer_format ());
1053 parse_WRB (struct lexer *lexer)
1055 return parse_real_format (lexer, settings_set_output_float_format);
1059 show_WRB (const struct dataset *ds UNUSED)
1061 return show_real_format (settings_get_output_float_format ());
1065 parse_WIDTH (struct lexer *lexer)
1067 if (lex_match_id (lexer, "NARROW"))
1068 settings_set_viewwidth (79);
1069 else if (lex_match_id (lexer, "WIDE"))
1070 settings_set_viewwidth (131);
1073 if (!lex_force_int_range (lexer, "WIDTH", 40, INT_MAX))
1075 settings_set_viewwidth (lex_integer (lexer));
1083 show_WIDTH (const struct dataset *ds UNUSED)
1085 return xasprintf ("%d", settings_get_viewwidth ());
1089 parse_WORKSPACE (struct lexer *lexer)
1091 if (!lex_force_int_range (lexer, "WORKSPACE",
1092 settings_get_testing_mode () ? 1 : 1024,
1095 int workspace = lex_integer (lexer);
1097 settings_set_workspace (MIN (workspace, INT_MAX / 1024) * 1024);
1102 show_WORKSPACE (const struct dataset *ds UNUSED)
1104 size_t ws = settings_get_workspace () / 1024L;
1105 return xasprintf ("%zu", ws);
1109 show_DIRECTORY (const struct dataset *ds UNUSED)
1118 buf = xrealloc (buf, len);
1120 while (NULL == (wd = getcwd (buf, len)));
1126 show_N (const struct dataset *ds)
1128 const struct casereader *reader = dataset_source (ds);
1130 ? xasprintf ("%lld", (long long int) casereader_count_cases (reader))
1131 : xstrdup (_("Unknown")));
1135 do_show (const struct dataset *ds, const struct setting *s)
1137 char *value = s->show (ds);
1138 msg (SN, _("%s is %s."), s->name, value ? value : _("empty"));
1143 show_warranty (const struct dataset *ds UNUSED)
1145 fputs (lack_of_warranty, stdout);
1149 show_copying (const struct dataset *ds UNUSED)
1151 fputs (copyleft, stdout);
1154 static const struct setting settings[] = {
1155 { "BASETEXTDIRECTION", parse_BASETEXTDIRECTION, NULL },
1156 { "BLANKS", parse_BLANKS, show_BLANKS },
1157 { "BLOCK", parse_BLOCK, NULL },
1158 { "BOX", parse_BOX, NULL },
1159 { "CACHE", parse_CACHE, NULL },
1160 { "CCA", parse_CCA, show_CCA },
1161 { "CCB", parse_CCB, show_CCB },
1162 { "CCC", parse_CCC, show_CCC },
1163 { "CCD", parse_CCD, show_CCD },
1164 { "CCE", parse_CCE, show_CCE },
1165 { "CELLSBREAK", parse_CELLSBREAK, NULL },
1166 { "CMPTRANS", parse_CMPTRANS, NULL },
1167 { "COMPRESSION", parse_COMPRESSION, NULL },
1168 { "CTEMPLATE", parse_CTEMPLATE, NULL },
1169 { "DECIMAL", parse_DECIMAL, show_DECIMAL },
1170 { "DIRECTORY", NULL, show_DIRECTORY },
1171 { "EPOCH", parse_EPOCH, show_EPOCH },
1172 { "ERRORS", parse_ERRORS, show_ERRORS },
1173 { "FORMAT", parse_FORMAT, show_FORMAT },
1174 { "FUZZBITS", parse_FUZZBITS, show_FUZZBITS },
1175 { "HEADER", parse_HEADER, NULL },
1176 { "INCLUDE", parse_INCLUDE, show_INCLUDE },
1177 { "JOURNAL", parse_JOURNAL, show_JOURNAL },
1178 { "LENGTH", parse_LENGTH, show_LENGTH },
1179 { "LOCALE", parse_LOCALE, show_LOCALE },
1180 { "MESSAGES", parse_MESSAGES, show_MESSAGES },
1181 { "MEXPAND", parse_MEXPAND, show_MEXPAND },
1182 { "MITERATE", parse_MITERATE, show_MITERATE },
1183 { "MNEST", parse_MNEST, show_MNEST },
1184 { "MPRINT", parse_MPRINT, show_MPRINT },
1185 { "MXERRS", parse_MXERRS, show_MXERRS },
1186 { "MXLOOPS", parse_MXLOOPS, show_MXLOOPS },
1187 { "MXWARNS", parse_MXWARNS, show_MXWARNS },
1188 { "N", NULL, show_N },
1189 { "PRINTBACK", parse_PRINTBACK, show_PRINTBACK },
1190 { "RESULTS", parse_RESULTS, show_RESULTS },
1191 { "RIB", parse_RIB, show_RIB },
1192 { "RRB", parse_RRB, show_RRB },
1193 { "SAFER", parse_SAFER, show_SAFER },
1194 { "SCOMPRESSION", parse_SCOMPRESSION, show_SCOMPRESSION },
1195 { "SEED", parse_SEED, NULL },
1196 { "SMALL", parse_SMALL, show_SMALL },
1197 { "SYSTEM", NULL, show_SYSTEM },
1198 { "TEMPDIR", NULL, show_TEMPDIR },
1199 { "TNUMBERS", parse_TNUMBERS, show_TNUMBERS },
1200 { "TVARS", parse_TVARS, show_TVARS },
1201 { "TLOOK", parse_TLOOK, NULL },
1202 { "UNDEFINED", parse_UNDEFINED, show_UNDEFINED },
1203 { "VERSION", NULL, show_VERSION },
1204 { "WEIGHT", NULL, show_WEIGHT },
1205 { "WIB", parse_WIB, show_WIB },
1206 { "WRB", parse_WRB, show_WRB },
1207 { "WIDTH", parse_WIDTH, show_WIDTH },
1208 { "WORKSPACE", parse_WORKSPACE, show_WORKSPACE },
1210 enum { N_SETTINGS = sizeof settings / sizeof *settings };
1213 parse_setting (struct lexer *lexer)
1215 for (size_t i = 0; i < N_SETTINGS; i++)
1216 if (settings[i].set && match_subcommand (lexer, settings[i].name))
1217 return settings[i].set (lexer);
1219 lex_error (lexer, NULL);
1224 cmd_set (struct lexer *lexer, struct dataset *ds UNUSED)
1228 lex_match (lexer, T_SLASH);
1229 if (lex_token (lexer) == T_ENDCMD)
1232 if (!parse_setting (lexer))
1240 show_all (const struct dataset *ds)
1242 for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1243 if (settings[i].show)
1244 do_show (ds, &settings[i]);
1248 show_all_cc (const struct dataset *ds)
1250 for (size_t i = 0; i < sizeof settings / sizeof *settings; i++)
1252 const struct setting *s = &settings[i];
1253 if (s->show && !strncmp (s->name, "CC", 2))
1259 cmd_show (struct lexer *lexer, struct dataset *ds)
1261 if (lex_token (lexer) == T_ENDCMD)
1269 if (lex_match (lexer, T_ALL))
1271 else if (lex_match_id (lexer, "CC"))
1273 else if (lex_match_id (lexer, "WARRANTY"))
1275 else if (lex_match_id (lexer, "COPYING") || lex_match_id (lexer, "LICENSE"))
1277 else if (lex_match_id (lexer, "TITLE"))
1279 struct setting s = { .name = "TITLE", .show = show_TITLE };
1282 else if (lex_match_id (lexer, "SUBTITLE"))
1284 struct setting s = { .name = "SUBTITLE", .show = show_SUBTITLE };
1287 else if (lex_token (lexer) == T_ID)
1291 for (i = 0; i < sizeof settings / sizeof *settings; i++)
1293 const struct setting *s = &settings[i];
1294 if (s->show && lex_match_id (lexer, s->name))
1300 lex_error (lexer, NULL);
1307 lex_error (lexer, NULL);
1311 lex_match (lexer, T_SLASH);
1313 while (lex_token (lexer) != T_ENDCMD);
1318 #define MAX_SAVED_SETTINGS 5
1320 static struct settings *saved_settings[MAX_SAVED_SETTINGS];
1321 static int n_saved_settings;
1324 cmd_preserve (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
1326 if (n_saved_settings < MAX_SAVED_SETTINGS)
1328 saved_settings[n_saved_settings++] = settings_get ();
1333 msg (SE, _("Too many %s commands without a %s: at most "
1334 "%d levels of saved settings are allowed."),
1335 "PRESERVE", "RESTORE",
1336 MAX_SAVED_SETTINGS);
1337 return CMD_CASCADING_FAILURE;
1342 cmd_restore (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
1344 if (n_saved_settings > 0)
1346 struct settings *s = saved_settings[--n_saved_settings];
1348 settings_destroy (s);
1353 msg (SE, _("%s without matching %s."), "RESTORE", "PRESERVE");