+ case FMT_QYR:
+ case FMT_MOYR:
+ case FMT_WKYR:
+ max_d = 0;
+ break;
+
+ case FMT_DATETIME:
+ max_d = width - 21;
+ break;
+
+ case FMT_TIME:
+ max_d = width - 9;
+ break;
+
+ case FMT_DTIME:
+ max_d = width - 12;
+ break;
+
+ case FMT_WKDAY:
+ case FMT_MONTH:
+ case FMT_A:
+ case FMT_AHEX:
+ max_d = 0;
+ break;
+
+ default:
+ NOT_REACHED ();
+ }
+
+ if (max_d < 0)
+ max_d = 0;
+ else if (max_d > 16)
+ max_d = 16;
+ return max_d;
+}
+
+/* Returns the minimum acceptable width for an input field
+ formatted with the given TYPE. */
+int
+fmt_min_input_width (enum fmt_type type)
+{
+ return get_fmt_desc (type)->min_input_width;
+}
+
+/* Returns the maximum acceptable width for an input field
+ formatted with the given TYPE. */
+int
+fmt_max_input_width (enum fmt_type type)
+{
+ return fmt_max_width (type, FMT_FOR_INPUT);
+}
+
+/* Returns the maximum number of decimal places allowed in an
+ input field of the given TYPE and WIDTH. */
+int
+fmt_max_input_decimals (enum fmt_type type, int width)
+{
+ assert (valid_width (type, width, true));
+ return fmt_max_decimals (type, width, FMT_FOR_INPUT);
+}
+
+/* Returns the minimum acceptable width for an output field
+ formatted with the given TYPE. */
+int
+fmt_min_output_width (enum fmt_type type)
+{
+ return get_fmt_desc (type)->min_output_width;
+}
+
+/* Returns the maximum acceptable width for an output field
+ formatted with the given TYPE. */
+int
+fmt_max_output_width (enum fmt_type type)
+{
+ return fmt_max_width (type, FMT_FOR_OUTPUT);
+}
+
+/* Returns the maximum number of decimal places allowed in an
+ output field of the given TYPE and WIDTH. */
+int
+fmt_max_output_decimals (enum fmt_type type, int width)
+{
+ assert (valid_width (type, width, false));
+ return fmt_max_decimals (type, width, FMT_FOR_OUTPUT);
+}
+
+/* Returns the width step for a field formatted with the given
+ TYPE. Field width must be a multiple of the width step. */
+int
+fmt_step_width (enum fmt_type type)
+{
+ return (fmt_get_category (type) == FMT_CAT_HEXADECIMAL || type == FMT_AHEX
+ ? 2 : 1);
+}
+
+/* Returns true if TYPE is used for string fields,
+ false if it is used for numeric fields. */
+bool
+fmt_is_string (enum fmt_type type)
+{
+ return fmt_get_category (type) == FMT_CAT_STRING;
+}
+
+/* Returns true if TYPE is used for numeric fields,
+ false if it is used for string fields. */
+bool
+fmt_is_numeric (enum fmt_type type)
+{
+ return !fmt_is_string (type);
+}
+
+/* Returns the format TYPE's category.
+ Each format type is in exactly one category,
+ and each category's value is bitwise disjoint from every other
+ category. Thus, the return value may be tested for equality
+ or compared bitwise against a mask of FMT_CAT_* values. */
+enum fmt_category
+fmt_get_category (enum fmt_type type)
+{
+ return get_fmt_desc (type)->category;
+}
+
+/* Returns the output format selected by default when TYPE is
+ used as an input format. */
+enum fmt_type
+fmt_input_to_output (enum fmt_type type)
+{
+ switch (fmt_get_category (type))
+ {
+ case FMT_CAT_STRING:
+ return FMT_A;
+
+ case FMT_CAT_LEGACY:
+ case FMT_CAT_BINARY:
+ case FMT_CAT_HEXADECIMAL:
+ return FMT_F;
+
+ default:
+ return type;
+ }
+}
+
+/* Returns the SPSS format type corresponding to the given PSPP
+ format type. */
+int
+fmt_to_io (enum fmt_type type)
+{
+ return get_fmt_desc (type)->io;
+}
+
+/* Determines the PSPP format corresponding to the given SPSS
+ format type. If successful, sets *FMT_TYPE to the PSPP format
+ and returns true. On failure, return false. */
+bool
+fmt_from_io (int io, enum fmt_type *fmt_type)
+{
+ switch (io)
+ {
+#define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
+ case IO: \
+ *fmt_type = FMT_##NAME; \
+ return true;
+#include "format.def"
+ default:
+ return false;
+ }
+}
+
+/* Returns true if TYPE may be used as an input format,
+ false otherwise. */
+bool
+fmt_usable_for_input (enum fmt_type type)
+{
+ assert (is_fmt_type (type));
+ return fmt_get_category (type) != FMT_CAT_CUSTOM;
+}
+
+/* For time and date formats, returns a template used for input and output in a
+ field of the given WIDTH.
+
+ WIDTH only affects whether a 2-digit year or a 4-digit year is used, that
+ is, whether the returned string contains "yy" or "yyyy", and whether seconds
+ are include, that is, whether the returned string contains ":SS". A caller
+ that doesn't care whether the returned string contains "yy" or "yyyy" or
+ ":SS" can just specify 0 to omit them. */
+const char *
+fmt_date_template (enum fmt_type type, int width)
+{
+ const char *s1, *s2;
+
+ switch (type)
+ {
+ case FMT_DATE:
+ s1 = "dd-mmm-yy";
+ s2 = "dd-mmm-yyyy";
+ break;
+