FILE HANDLE: Improve error messages and coding style.
[pspp] / src / language / data-io / file-handle.c
index 8d65418db75b0a30078c2600730404b3adfeb5ff..66411794fa5f934b4ab9f60bc42ca6c25622a05e 100644 (file)
@@ -56,11 +56,13 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
     goto exit;
 
   handle_name = xstrdup (lex_tokcstr (lexer));
-  if (fh_from_id (handle_name))
+  struct file_handle *fh = fh_from_id (handle_name);
+  if (fh)
     {
-      msg (SE, _("File handle %s is already defined.  "
-                 "Use %s before redefining a file handle."),
-          handle_name, "CLOSE FILE HANDLE");
+      fh_unref (fh);
+      lex_error (lexer, _("File handle %s is already defined.  "
+                          "Use %s before redefining a file handle."),
+                 handle_name, "CLOSE FILE HANDLE");
       goto exit;
     }
 
@@ -68,13 +70,15 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
   if (!lex_force_match (lexer, T_SLASH))
     goto exit;
 
+  int mode_start = 0;
+  int mode_end = 0;
   while (lex_token (lexer) != T_ENDCMD)
     {
       if (lex_match_id (lexer, "NAME"))
         {
           if (file_name)
             {
-              lex_sbc_only_once ("NAME");
+              lex_sbc_only_once (lexer, "NAME");
               goto exit;
             }
 
@@ -89,12 +93,12 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
         {
           if (lrecl)
             {
-              lex_sbc_only_once ("LRECL");
+              lex_sbc_only_once (lexer, "LRECL");
               goto exit;
             }
 
           lex_match (lexer, T_EQUALS);
-          if (!lex_force_int (lexer))
+          if (!lex_force_int_range (lexer, "LRECL", 1, (1UL << 31) - 1))
             goto exit;
           lrecl = lex_integer (lexer);
           lex_get (lexer);
@@ -103,12 +107,12 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
         {
           if (tabwidth >= 0)
             {
-              lex_sbc_only_once ("TABWIDTH");
+              lex_sbc_only_once (lexer, "TABWIDTH");
               goto exit;
             }
           lex_match (lexer, T_EQUALS);
 
-          if (!lex_force_int (lexer))
+          if (!lex_force_int_range (lexer, "TABWIDTH", 1, INT_MAX))
             goto exit;
           tabwidth = lex_integer (lexer);
           lex_get (lexer);
@@ -117,9 +121,10 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
         {
           if (mode != MODE_DEFAULT)
             {
-              lex_sbc_only_once ("MODE");
+              lex_sbc_only_once (lexer, "MODE");
               goto exit;
             }
+          mode_start = lex_ofs (lexer) - 1;
           lex_match (lexer, T_EQUALS);
 
           if (lex_match_id (lexer, "CHARACTER"))
@@ -132,15 +137,17 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
             mode = MODE_360;
           else
             {
-              lex_error (lexer, NULL);
+              lex_error_expecting (lexer, "CHARACTER", "BINARY",
+                                   "IMAGE", "360");
               goto exit;
             }
+          mode_end = lex_ofs (lexer) - 1;
         }
       else if (lex_match_id (lexer, "ENDS"))
         {
           if (ends >= 0)
             {
-              lex_sbc_only_once ("ENDS");
+              lex_sbc_only_once (lexer, "ENDS");
               goto exit;
             }
           lex_match (lexer, T_EQUALS);
@@ -151,7 +158,7 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
             ends = FH_END_CRLF;
           else
             {
-              lex_error (lexer, NULL);
+              lex_error_expecting (lexer, "LF", "CRLF");
               goto exit;
             }
         }
@@ -159,7 +166,7 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
         {
           if (recform)
             {
-              lex_sbc_only_once ("RECFORM");
+              lex_sbc_only_once (lexer, "RECFORM");
               goto exit;
             }
           lex_match (lexer, T_EQUALS);
@@ -173,7 +180,7 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
             recform = RECFORM_SPANNED;
           else
             {
-              lex_error (lexer, NULL);
+              lex_error_expecting (lexer, "FIXED", "VARIABLE", "SPANNED");
               goto exit;
             }
         }
@@ -181,7 +188,7 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
         {
           if (encoding)
             {
-              lex_sbc_only_once ("ENCODING");
+              lex_sbc_only_once (lexer, "ENCODING");
               goto exit;
             }
 
@@ -202,7 +209,7 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
   struct fh_properties properties = *fh_default_properties ();
   if (file_name == NULL)
     {
-      lex_sbc_missing ("NAME");
+      lex_sbc_missing (lexer, "NAME");
       goto exit;
     }
 
@@ -238,7 +245,9 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
         }
       else
         {
-          msg (SE, _("%s must be specified with %s."), "RECFORM", "MODE=360");
+          lex_ofs_error (lexer, mode_start, mode_end,
+                         _("%s must be specified with %s."),
+                         "RECFORM", "MODE=360");
           goto exit;
         }
       break;
@@ -252,10 +261,6 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED)
         msg (SE, _("The specified file mode requires LRECL.  "
                    "Assuming %zu-character records."),
              properties.record_width);
-      else if (lrecl < 1 || lrecl >= (1UL << 31))
-        msg (SE, _("Record length (%d) must be between 1 and %lu bytes.  "
-                   "Assuming %zu-character records."),
-             lrecl, (1UL << 31) - 1, properties.record_width);
       else
         properties.record_width = lrecl;
     }
@@ -327,8 +332,6 @@ struct file_handle *
 fh_parse (struct lexer *lexer, enum fh_referent referent_mask,
           struct session *session)
 {
-  struct file_handle *handle;
-
   if (session != NULL && lex_token (lexer) == T_ID)
     {
       struct dataset *ds;
@@ -341,13 +344,16 @@ fh_parse (struct lexer *lexer, enum fh_referent referent_mask,
         }
     }
 
+  int start_ofs = lex_ofs (lexer);
+  struct file_handle *handle;
   if (lex_match_id (lexer, "INLINE"))
     handle = fh_inline_file ();
   else
     {
       if (lex_token (lexer) != T_ID && !lex_is_string (lexer))
         {
-          lex_error (lexer, _("expecting a file name or handle name"));
+          lex_error (lexer,
+                     _("Syntax error expecting a file name or handle name."));
           return NULL;
         }
 
@@ -362,17 +368,12 @@ fh_parse (struct lexer *lexer, enum fh_referent referent_mask,
 
   if (!(fh_get_referent (handle) & referent_mask))
     {
-      msg (SE, _("Handle for %s not allowed here."),
-           referent_name (fh_get_referent (handle)));
+      lex_ofs_error (lexer, start_ofs, lex_ofs (lexer) - 1,
+                     _("Handle for %s not allowed here."),
+                     referent_name (fh_get_referent (handle)));
       fh_unref (handle);
       return NULL;
     }
 
   return handle;
 }
-
-/*
-   Local variables:
-   mode: c
-   End:
-*/