PRINT: Improve error messages.
[pspp] / src / language / dictionary / formats.c
index de58615619f1548a772b3cdba64cb4e3143a25f9..907a47f9ae6efb68d5c6e4e6b1a64ab7752eb57f 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2010 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2010, 2011 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <data/procedure.h>
-#include <data/variable.h>
-#include <data/format.h>
-#include <language/command.h>
-#include <language/lexer/format-parser.h>
-#include <language/lexer/lexer.h>
-#include <language/lexer/variable-parser.h>
-#include <libpspp/message.h>
-#include <libpspp/misc.h>
-#include <libpspp/str.h>
+#include "data/dataset.h"
+#include "data/format.h"
+#include "data/variable.h"
+#include "language/command.h"
+#include "language/lexer/format-parser.h"
+#include "language/lexer/lexer.h"
+#include "language/lexer/variable-parser.h"
+#include "libpspp/message.h"
+#include "libpspp/misc.h"
+#include "libpspp/str.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
-enum
-  {
-    FORMATS_PRINT = 001,
-    FORMATS_WRITE = 002
-  };
-
-static int internal_cmd_formats (struct lexer *, struct dataset *ds, int);
+static int cmd_formats__ (struct lexer *, struct dataset *ds,
+                          bool print_format, bool write_format);
 
 int
 cmd_print_formats (struct lexer *lexer, struct dataset *ds)
 {
-  return internal_cmd_formats (lexer, ds, FORMATS_PRINT);
+  return cmd_formats__ (lexer, ds, true, false);
 }
 
 int
 cmd_write_formats (struct lexer *lexer, struct dataset *ds)
 {
-  return internal_cmd_formats (lexer, ds, FORMATS_WRITE);
+  return cmd_formats__ (lexer, ds, false, true);
 }
 
 int
 cmd_formats (struct lexer *lexer, struct dataset *ds)
 {
-  return internal_cmd_formats (lexer, ds, FORMATS_PRINT | FORMATS_WRITE);
+  return cmd_formats__ (lexer, ds, true, true);
 }
 
 static int
-internal_cmd_formats (struct lexer *lexer, struct dataset *ds, int which)
+cmd_formats__ (struct lexer *lexer, struct dataset *ds,
+               bool print_format, bool write_format)
 {
   /* Variables. */
   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;
+
+      lex_match (lexer, T_SLASH);
+
       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))
        {
-         msg (SE, _("`(' expected after variable list."));
+          lex_error_expecting (lexer, "`('");
          goto fail;
        }
-      if (!parse_format_specifier (lexer, &f)
-          || !fmt_check_output (&f)
-          || !fmt_check_type_compat (&f, VAL_NUMERIC))
-       goto fail;
+      if (!parse_format_specifier (lexer, &f))
+        goto fail;
+      char *error = fmt_check_output__ (&f);
+      if (!error)
+        error = fmt_check_width_compat__ (&f, var_get_name (v[0]), width);
+      if (error)
+        {
+          lex_next_error (lexer, -1, -1, "%s", error);
+          free (error);
+          goto fail;
+        }
 
       if (!lex_match (lexer, T_RPAREN))
        {
-         msg (SE, _("`)' expected after output format."));
+          lex_error_expecting (lexer, "`)'");
          goto fail;
        }
 
       for (i = 0; i < cv; i++)
        {
-         if (which & FORMATS_PRINT)
+         if (print_format)
             var_set_print_format (v[i], &f);
-         if (which & FORMATS_WRITE)
+         if (write_format)
             var_set_write_format (v[i], &f);
        }
       free (v);