FORMATS: Allow setting formats of string variables.
authorBen Pfaff <blp@cs.stanford.edu>
Tue, 12 Apr 2011 05:48:08 +0000 (22:48 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 12 Apr 2011 05:48:08 +0000 (22:48 -0700)
Thanks to John Darrington for reporting this bug.
Bug #22012.

doc/variables.texi
src/language/dictionary/formats.c
tests/automake.mk
tests/language/dictionary/formats.at [new file with mode: 0644]

index dcb7ba7dfb9ed6c30e9a3f577a29b9961c49916a..dbb3f228b3e770fab4e8909f86b3824b9f2ca2cb 100644 (file)
@@ -127,19 +127,20 @@ FILE LABEL}.
 @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}.
@@ -406,11 +407,11 @@ response sets are currently used only by third party software.
 @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.
@@ -655,11 +656,10 @@ Variables within a vector may be referenced in expressions using
 @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.
index 9f943be214931d14f1c6265de20be0e8349e5885..718344acc63ed1037787c1ab6823507b7e2ae8dd 100644 (file)
@@ -67,23 +67,18 @@ internal_cmd_formats (struct lexer *lexer, struct dataset *ds, int which)
   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))
        {
@@ -92,7 +87,7 @@ internal_cmd_formats (struct lexer *lexer, struct dataset *ds, int which)
        }
       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))
index 0b7fcb249a68ce1a7f66ff77279ab41e5c8a8aa9..b261a8cd6a242d67ebb0cc022ac3bdee707bbc9e 100644 (file)
@@ -307,6 +307,7 @@ TESTSUITE_AT = \
        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 \
diff --git a/tests/language/dictionary/formats.at b/tests/language/dictionary/formats.at
new file mode 100644 (file)
index 0000000..4bdf089
--- /dev/null
@@ -0,0 +1,80 @@
+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