Thanks to John Darrington for reporting this bug.
Bug #22012.
@vindex FORMATS
@display
-FORMATS var_list (fmt_spec).
+FORMATS var_list (fmt_spec) [var_list (fmt_spec)]@dots{}.
@end display
@cmd{FORMATS} set both print and write formats for the specified
-numeric variables to the specified format specification.
+variables to the specified format specification.
@xref{Input and Output Formats}.
Specify a list of variables followed by a format specification in
parentheses. The print and write formats of the specified variables
-will be changed.
+will be changed. All of the variables listed together must have
+the same type and, for string variables, the same width.
-Additional lists of variables and formats may be included if they are
-delimited by a slash (@samp{/}).
+Additional lists of variables and formats may be included following
+the first one.
@cmd{FORMATS} takes effect immediately. It is not affected by
conditional and looping structures such as @cmd{DO IF} or @cmd{LOOP}.
@vindex PRINT FORMATS
@display
-PRINT FORMATS var_list (fmt_spec).
+PRINT FORMATS var_list (fmt_spec) [var_list (fmt_spec)]@dots{}.
@end display
@cmd{PRINT FORMATS} sets the print formats for the specified
-numeric variables to the specified format specification.
+variables to the specified format specification.
Its syntax is identical to that of @cmd{FORMATS} (@pxref{FORMATS}),
but @cmd{PRINT FORMATS} sets only print formats, not write formats.
@vindex WRITE FORMATS
@display
-WRITE FORMATS var_list (fmt_spec).
+WRITE FORMATS var_list (fmt_spec) [var_list (fmt_spec)]@dots{}.
@end display
-@cmd{WRITE FORMATS} sets the write formats for the specified numeric
-variables
+@cmd{WRITE FORMATS} sets the write formats for the specified variables
to the specified format specification. Its syntax is identical to
that of FORMATS (@pxref{FORMATS}), but @cmd{WRITE FORMATS} sets only
write formats, not print formats.
struct variable **v;
size_t cv;
- /* Format to set the variables to. */
- struct fmt_spec f;
-
- /* Numeric or string. */
- int type;
-
- /* Counter. */
- size_t i;
-
for (;;)
{
+ struct fmt_spec f;
+ int width;
+ size_t i;
+
if (lex_token (lexer) == T_ENDCMD)
break;
- if (!parse_variables (lexer, dataset_dict (ds), &v, &cv, PV_NUMERIC))
+ if (!parse_variables (lexer, dataset_dict (ds), &v, &cv, PV_SAME_WIDTH))
return CMD_FAILURE;
- type = var_get_type (v[0]);
+ width = var_get_width (v[0]);
if (!lex_match (lexer, T_LPAREN))
{
}
if (!parse_format_specifier (lexer, &f)
|| !fmt_check_output (&f)
- || !fmt_check_type_compat (&f, VAL_NUMERIC))
+ || !fmt_check_width_compat (&f, width))
goto fail;
if (!lex_match (lexer, T_RPAREN))
tests/language/data-io/save-translate.at \
tests/language/data-io/update.at \
tests/language/dictionary/attributes.at \
+ tests/language/dictionary/formats.at \
tests/language/dictionary/missing-values.at \
tests/language/dictionary/mrsets.at \
tests/language/dictionary/rename-variables.at \
--- /dev/null
+AT_BANNER([FORMATS])
+
+AT_SETUP([FORMATS positive tests])
+AT_DATA([formats.sps], [dnl
+DATA LIST LIST /a b c * x (A1) y (A2) z (A3).
+DISPLAY VARIABLES.
+FORMATS a (COMMA10) b (N4).
+DISPLAY VARIABLES.
+FORMATS c (E8.1) x (A1) y (AHEX4) z (A3).
+DISPLAY VARIABLES.
+])
+AT_CHECK([pspp -o pspp.csv formats.sps])
+AT_CHECK([grep -E -v 'Measure|Display' pspp.csv], [0], [dnl
+Table: Reading free-form data from INLINE.
+Variable,Format
+a,F8.0
+b,F8.0
+c,F8.0
+x,A1
+y,A2
+z,A3
+
+Variable,Description,,Position
+a,Format: F8.2,,1
+b,Format: F8.2,,2
+c,Format: F8.2,,3
+x,Format: A1,,4
+y,Format: A2,,5
+z,Format: A3,,6
+
+Variable,Description,,Position
+a,Format: COMMA10.0,,1
+b,Format: N4.0,,2
+c,Format: F8.2,,3
+x,Format: A1,,4
+y,Format: A2,,5
+z,Format: A3,,6
+
+Variable,Description,,Position
+a,Format: COMMA10.0,,1
+b,Format: N4.0,,2
+c,Format: E8.1,,3
+x,Format: A1,,4
+y,Format: AHEX4,,5
+z,Format: A3,,6
+])
+AT_CLEANUP
+
+AT_SETUP([FORMATS negative tests])
+AT_DATA([formats.sps], [dnl
+DATA LIST LIST /a b c * x (A1) y (A2) z (A3).
+FORMATS a (E6.1).
+FORMATS a y (F4).
+FORMATS x (A2).
+FORMATS y (AHEX2).
+FORMATS x y (A2).
+])
+AT_CHECK([pspp -O format=csv formats.sps], [1], [dnl
+Table: Reading free-form data from INLINE.
+Variable,Format
+a,F8.0
+b,F8.0
+c,F8.0
+x,A1
+y,A2
+z,A3
+
+"formats.sps:2: error: FORMATS: Output format E6.1 specifies 1 decimal place, but the given width does not allow for any decimals."
+
+formats.sps:3: error: FORMATS: a and y are not the same type. All variables in this variable list must be of the same type. y will be omitted from the list.
+
+formats.sps:4: error: FORMATS: String variable with width 1 is not compatible with format A2.
+
+formats.sps:5: error: FORMATS: String variable with width 2 is not compatible with format AHEX2.
+
+formats.sps:6: error: FORMATS: x and y are string variables with different widths. All variables in this variable list must have the same width. y will be omitted from the list.
+
+formats.sps:6: error: FORMATS: String variable with width 1 is not compatible with format A2.
+])
+AT_CLEANUP