OSDN Git Service

2010-04-08 Bud Davis <bdavis9659@sbcglobal.net>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / io.c
index 85b712f..1ce26df 100644 (file)
@@ -1,5 +1,5 @@
 /* Deal with I/O statements & related stuff.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Andy Vaught
 
@@ -38,8 +38,8 @@ typedef struct
 io_tag;
 
 static const io_tag
-       tag_file        = { "FILE", " file =", " %e", BT_CHARACTER },
-       tag_status      = { "STATUS", " status =", " %e", BT_CHARACTER},
+       tag_file        = {"FILE", " file =", " %e", BT_CHARACTER },
+       tag_status      = {"STATUS", " status =", " %e", BT_CHARACTER},
        tag_e_access    = {"ACCESS", " access =", " %e", BT_CHARACTER},
        tag_e_form      = {"FORM", " form =", " %e", BT_CHARACTER},
        tag_e_recl      = {"RECL", " recl =", " %e", BT_INTEGER},
@@ -94,7 +94,8 @@ static const io_tag
        tag_end         = {"END", " end =", " %l", BT_UNKNOWN},
        tag_eor         = {"EOR", " eor =", " %l", BT_UNKNOWN},
        tag_id          = {"ID", " id =", " %v", BT_INTEGER},
-       tag_pending     = {"PENDING", " pending =", " %v", BT_LOGICAL};
+       tag_pending     = {"PENDING", " pending =", " %v", BT_LOGICAL},
+       tag_newunit     = {"NEWUNIT", " newunit =", " %v", BT_INTEGER};
 
 static gfc_dt *current_dt;
 
@@ -109,8 +110,9 @@ typedef enum
   FMT_NONE, FMT_UNKNOWN, FMT_SIGNED_INT, FMT_ZERO, FMT_POSINT, FMT_PERIOD,
   FMT_COMMA, FMT_COLON, FMT_SLASH, FMT_DOLLAR, FMT_LPAREN,
   FMT_RPAREN, FMT_X, FMT_SIGN, FMT_BLANK, FMT_CHAR, FMT_P, FMT_IBOZ, FMT_F,
-  FMT_E, FMT_EXT, FMT_G, FMT_L, FMT_A, FMT_D, FMT_H, FMT_END, FMT_ERROR, FMT_DC,
-  FMT_DP, FMT_T, FMT_TR, FMT_TL
+  FMT_E, FMT_EN, FMT_ES, FMT_G, FMT_L, FMT_A, FMT_D, FMT_H, FMT_END,
+  FMT_ERROR, FMT_DC, FMT_DP, FMT_T, FMT_TR, FMT_TL, FMT_STAR, FMT_RC,
+  FMT_RD, FMT_RN, FMT_RP, FMT_RU, FMT_RZ
 }
 format_token;
 
@@ -118,6 +120,7 @@ format_token;
    used to back up by a single format token during the parsing
    process.  */
 static gfc_char_t *format_string;
+static int format_string_pos;
 static int format_length, use_last_char;
 static char error_element;
 static locus format_locus;
@@ -170,6 +173,8 @@ next_char (int in_string)
   if (mode != MODE_STRING)
     format_locus = gfc_current_locus;
 
+  format_string_pos++;
+
   c = gfc_wide_toupper (c);
   return c;
 }
@@ -412,8 +417,10 @@ format_lex (void)
 
     case 'E':
       c = next_char_not_space (&error);
-      if (c == 'N' || c == 'S')
-       token = FMT_EXT;
+      if (c == 'N' )
+       token = FMT_EN;
+      else if (c == 'S')
+        token = FMT_ES;
       else
        {
          token = FMT_E;
@@ -461,10 +468,43 @@ format_lex (void)
        }
       break;
 
+    case 'R':
+      c = next_char_not_space (&error);
+      switch (c)
+       {
+       case 'C':
+         token = FMT_RC;
+         break;
+       case 'D':
+         token = FMT_RD;
+         break;
+       case 'N':
+         token = FMT_RN;
+         break;
+       case 'P':
+         token = FMT_RP;
+         break;
+       case 'U':
+         token = FMT_RU;
+         break;
+       case 'Z':
+         token = FMT_RZ;
+         break;
+       default:
+         token = FMT_UNKNOWN;
+         unget_char ();
+         break;
+       }
+      break;
+
     case '\0':
       token = FMT_END;
       break;
 
+    case '*':
+      token = FMT_STAR;
+      break;
+
     default:
       token = FMT_UNKNOWN;
       break;
@@ -477,6 +517,26 @@ format_lex (void)
 }
 
 
+static const char *
+token_to_string (format_token t)
+{
+  switch (t)
+    {
+      case FMT_D:
+       return "D";
+      case FMT_G:
+       return "G";
+      case FMT_E:
+       return "E";
+      case FMT_EN:
+       return "EN";
+      case FMT_ES:
+       return "ES";
+      default:
+        return "";
+    }
+}
+
 /* Check a format statement.  The format string, either from a FORMAT
    statement or a constant in an I/O statement has already been parsed
    by itself, and we are checking it for validity.  The dual origin
@@ -503,6 +563,7 @@ check_format (bool is_input)
   level = 0;
   repeat = 0;
   rv = SUCCESS;
+  format_string_pos = 0;
 
   t = format_lex ();
   if (t == FMT_ERROR)
@@ -528,6 +589,19 @@ format_item:
 format_item_1:
   switch (t)
     {
+    case FMT_STAR:
+      repeat = -1;
+      t = format_lex ();
+      if (t == FMT_ERROR)
+       goto fail;
+      if (t == FMT_LPAREN)
+       {
+         level++;
+         goto format_item;
+       }
+      error = _("Left parenthesis required after '*'");
+      goto syntax;
+
     case FMT_POSINT:
       repeat = value;
       t = format_lex ();
@@ -569,8 +643,10 @@ format_item_1:
 
     case FMT_X:
       /* X requires a prior number if we're being pedantic.  */
+      if (mode != MODE_FORMAT)
+       format_locus.nextc += format_string_pos;
       if (gfc_notify_std (GFC_STD_GNU, "Extension: X descriptor "
-                         "requires leading space count at %C")
+                         "requires leading space count at %L", &format_locus)
          == FAILURE)
        return FAILURE;
       goto between_desc;
@@ -579,6 +655,12 @@ format_item_1:
     case FMT_BLANK:
     case FMT_DP:
     case FMT_DC:
+    case FMT_RC:
+    case FMT_RD:
+    case FMT_RN:
+    case FMT_RP:
+    case FMT_RU:
+    case FMT_RZ:
       goto between_desc;
 
     case FMT_CHAR:
@@ -593,12 +675,13 @@ format_item_1:
       if (t == FMT_ERROR)
        goto fail;
 
-      if (gfc_notify_std (GFC_STD_GNU, "Extension: $ descriptor at %C")
-         == FAILURE)
+      if (gfc_notify_std (GFC_STD_GNU, "Extension: $ descriptor at %L",
+         &format_locus) == FAILURE)
        return FAILURE;
       if (t != FMT_RPAREN || level > 0)
        {
-         gfc_warning ("$ should be the last specifier in format at %C");
+         gfc_warning ("$ should be the last specifier in format at %L",
+                      &format_locus);
          goto optional_comma_1;
        }
 
@@ -610,7 +693,8 @@ format_item_1:
     case FMT_IBOZ:
     case FMT_F:
     case FMT_E:
-    case FMT_EXT:
+    case FMT_EN:
+    case FMT_ES:
     case FMT_G:
     case FMT_L:
     case FMT_A:
@@ -640,20 +724,35 @@ data_desc:
       break;
 
     case FMT_P:
-      if (pedantic)
+      /* No comma after P allowed only for F, E, EN, ES, D, or G.
+        10.1.1 (1).  */
+      t = format_lex ();
+      if (t == FMT_ERROR)
+       goto fail;
+      if (gfc_option.allow_std < GFC_STD_F2003 && t != FMT_COMMA
+         && t != FMT_F && t != FMT_E && t != FMT_EN && t != FMT_ES
+         && t != FMT_D && t != FMT_G && t != FMT_RPAREN && t != FMT_SLASH)
+       {
+         error = _("Comma required after P descriptor");
+         goto syntax;
+       }
+      if (t != FMT_COMMA)
        {
-         t = format_lex ();
-         if (t == FMT_ERROR)
-           goto fail;
          if (t == FMT_POSINT)
            {
-             error = _("Repeat count cannot follow P descriptor");
+             t = format_lex ();
+             if (t == FMT_ERROR)
+               goto fail;
+           }
+          if (t != FMT_F && t != FMT_E && t != FMT_EN && t != FMT_ES && t != FMT_D
+             && t != FMT_G && t != FMT_RPAREN && t != FMT_SLASH)
+           {
+             error = _("Comma required after P descriptor");
              goto syntax;
            }
-
-         saved_token = t;
        }
 
+      saved_token = t;
       goto optional_comma;
 
     case FMT_T:
@@ -677,8 +776,10 @@ data_desc:
       switch (gfc_notification_std (GFC_STD_GNU))
        {
          case WARNING:
+           if (mode != MODE_FORMAT)
+             format_locus.nextc += format_string_pos;
            gfc_warning ("Extension: Missing positive width after L "
-                        "descriptor at %C");
+                        "descriptor at %L", &format_locus);
            saved_token = t;
            break;
 
@@ -711,7 +812,8 @@ data_desc:
     case FMT_D:
     case FMT_E:
     case FMT_G:
-    case FMT_EXT:
+    case FMT_EN:
+    case FMT_ES:
       u = format_lex ();
       if (t == FMT_G && u == FMT_ZERO)
        {
@@ -721,7 +823,7 @@ data_desc:
              goto syntax;
            }
          if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: 'G0' in "
-                             "format at %C") == FAILURE)
+                             "format at %L", &format_locus) == FAILURE)
            return FAILURE;
          u = format_lex ();
          if (u != FMT_PERIOD)
@@ -729,28 +831,54 @@ data_desc:
              saved_token = u;
              break;
            }
-
          u = format_lex ();
-         if (u == FMT_ERROR)
-           goto fail;
          if (u != FMT_POSINT)
            {
              error = posint_required;
              goto syntax;
            }
+         u = format_lex ();
+         if (u == FMT_E)
+           {
+             error = _("E specifier not allowed with g0 descriptor");
+             goto syntax;
+           }
+         saved_token = u;
          break;
        }
 
+      if (u != FMT_POSINT)
+       {
+         format_locus.nextc += format_string_pos;
+         gfc_error ("Positive width required in format "
+                        "specifier %s at %L", token_to_string (t),
+                        &format_locus);
+         saved_token = u;
+         goto fail;
+       }
+
       u = format_lex ();
       if (u == FMT_ERROR)
        goto fail;
       if (u != FMT_PERIOD)
        {
          /* Warn if -std=legacy, otherwise error.  */
+         format_locus.nextc += format_string_pos;
          if (gfc_option.warn_std != 0)
-           gfc_error_now ("Period required in format specifier at %C");
+           {
+             gfc_error ("Period required in format "
+                            "specifier %s at %L", token_to_string (t),
+                            &format_locus);
+             saved_token = u;
+              goto fail;
+           }
          else
-           gfc_warning ("Period required in format specifier at %C");
+           gfc_warning ("Period required in format "
+                        "specifier %s at %L", token_to_string (t),
+                         &format_locus);
+         /* If we go to finished, we need to unwind this
+            before the next round.  */
+         format_locus.nextc -= format_string_pos;
          saved_token = u;
          break;
        }
@@ -811,9 +939,14 @@ data_desc:
        {
          /* Warn if -std=legacy, otherwise error.  */
          if (gfc_option.warn_std != 0)
-           gfc_error_now ("Period required in format specifier at %C");
-         else
-           gfc_warning ("Period required in format specifier at %C");
+           {
+             error = _("Period required in format specifier");
+             goto syntax;
+           }
+         if (mode != MODE_FORMAT)
+           format_locus.nextc += format_string_pos;
+         gfc_warning ("Period required in format specifier at %L",
+                      &format_locus);
          saved_token = t;
          break;
        }
@@ -831,13 +964,17 @@ data_desc:
 
     case FMT_H:
       if (!(gfc_option.allow_std & GFC_STD_GNU) && !inhibit_warnings)
-       gfc_warning ("The H format specifier at %C is"
-                    " a Fortran 95 deleted feature");
-
+       {
+         if (mode != MODE_FORMAT)
+           format_locus.nextc += format_string_pos;
+         gfc_warning ("The H format specifier at %L is"
+                      " a Fortran 95 deleted feature", &format_locus);
+       }
       if (mode == MODE_STRING)
        {
          format_string += value;
          format_length -= value;
+          format_string_pos += repeat;
        }
       else
        {
@@ -916,9 +1053,15 @@ between_desc:
       goto syntax;
 
     default:
-      if (gfc_notify_std (GFC_STD_GNU, "Extension: Missing comma at %C")
-         == FAILURE)
+      if (mode != MODE_FORMAT)
+       format_locus.nextc += format_string_pos - 1;
+      if (gfc_notify_std (GFC_STD_GNU, "Extension: Missing comma at %L",
+         &format_locus) == FAILURE)
        return FAILURE;
+      /* If we do not actually return a failure, we need to unwind this
+         before the next round.  */
+      if (mode != MODE_FORMAT)
+       format_locus.nextc -= format_string_pos;
       goto format_item_1;
     }
 
@@ -973,16 +1116,24 @@ extension_optional_comma:
       goto syntax;
 
     default:
-      if (gfc_notify_std (GFC_STD_GNU, "Extension: Missing comma at %C")
-         == FAILURE)
+      if (mode != MODE_FORMAT)
+       format_locus.nextc += format_string_pos;
+      if (gfc_notify_std (GFC_STD_GNU, "Extension: Missing comma at %L",
+         &format_locus) == FAILURE)
        return FAILURE;
+      /* If we do not actually return a failure, we need to unwind this
+         before the next round.  */
+      if (mode != MODE_FORMAT)
+       format_locus.nextc -= format_string_pos;
       saved_token = t;
       break;
     }
 
   goto format_item;
-
+  
 syntax:
+  if (mode != MODE_FORMAT)
+    format_locus.nextc += format_string_pos;
   if (error == unexpected_element)
     gfc_error (error, error_element, &format_locus);
   else
@@ -1001,6 +1152,8 @@ finished:
 static gfc_try
 check_format_string (gfc_expr *e, bool is_input)
 {
+  gfc_try rv;
+  int i;
   if (!e || e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
     return SUCCESS;
 
@@ -1011,8 +1164,20 @@ check_format_string (gfc_expr *e, bool is_input)
      format string that has been calculated, but that's probably not worth the
      effort.  */
   format_locus = e->where;
-
-  return check_format (is_input);
+  rv = check_format (is_input);
+  /* check for extraneous characters at the end of an otherwise valid format
+     string, like '(A10,I3)F5'
+     start at the end and move back to the last character processed,
+     spaces are OK */
+  if (rv == SUCCESS && e->value.character.length > format_string_pos)
+    for (i=e->value.character.length-1;i>format_string_pos-1;i--)
+      if (e->value.character.string[i] != ' ')
+        {
+          format_locus.nextc += format_length + 1; 
+          gfc_warning ("Extraneous characters in format at %L", &format_locus); 
+          break;
+        }
+  return rv;
 }
 
 
@@ -1224,8 +1389,11 @@ resolve_tag_format (const gfc_expr *e)
   /* If e's rank is zero and e is not an element of an array, it should be
      of integer or character type.  The integer variable should be
      ASSIGNED.  */
-  if (e->symtree == NULL || e->symtree->n.sym->as == NULL
-      || e->symtree->n.sym->as->rank == 0)
+  if (e->rank == 0
+      && (e->expr_type != EXPR_VARIABLE
+         || e->symtree == NULL
+         || e->symtree->n.sym->as == NULL
+         || e->symtree->n.sym->as->rank == 0))
     {
       if (e->ts.type != BT_CHARACTER && e->ts.type != BT_INTEGER)
        {
@@ -1256,20 +1424,34 @@ resolve_tag_format (const gfc_expr *e)
       return SUCCESS;
     }
 
-  /* If rank is nonzero, we allow the type to be character under GFC_STD_GNU
-     and other type under GFC_STD_LEGACY. It may be assigned an Hollerith
-     constant.  */
-  if (e->ts.type == BT_CHARACTER)
-    {
-      if (gfc_notify_std (GFC_STD_GNU, "Extension: Character array "
-                         "in FORMAT tag at %L", &e->where) == FAILURE)
-       return FAILURE;
-    }
-  else
+  /* If rank is nonzero and type is not character, we allow it under GFC_STD_LEGACY.
+     It may be assigned an Hollerith constant.  */
+  if (e->ts.type != BT_CHARACTER)
     {
       if (gfc_notify_std (GFC_STD_LEGACY, "Extension: Non-character "
                          "in FORMAT tag at %L", &e->where) == FAILURE)
        return FAILURE;
+
+      if (e->rank == 0 && e->symtree->n.sym->as->type == AS_ASSUMED_SHAPE)
+       {
+         gfc_error ("Non-character assumed shape array element in FORMAT"
+                    " tag at %L", &e->where);
+         return FAILURE;
+       }
+
+      if (e->rank == 0 && e->symtree->n.sym->as->type == AS_ASSUMED_SIZE)
+       {
+         gfc_error ("Non-character assumed size array element in FORMAT"
+                    " tag at %L", &e->where);
+         return FAILURE;
+       }
+
+      if (e->rank == 0 && e->symtree->n.sym->attr.pointer)
+       {
+         gfc_error ("Non-character pointer array element in FORMAT tag at %L",
+                    &e->where);
+         return FAILURE;
+       }
     }
 
   return SUCCESS;
@@ -1397,6 +1579,9 @@ match_open_element (gfc_open *open)
   m = match_etag (&tag_convert, &open->convert);
   if (m != MATCH_NO)
     return m;
+  m = match_out_tag (&tag_newunit, &open->newunit);
+  if (m != MATCH_NO)
+    return m;
 
   return MATCH_NO;
 }
@@ -1429,6 +1614,7 @@ gfc_free_open (gfc_open *open)
   gfc_free_expr (open->sign);
   gfc_free_expr (open->convert);
   gfc_free_expr (open->asynchronous);
+  gfc_free_expr (open->newunit);
   gfc_free (open);
 }
 
@@ -1458,6 +1644,7 @@ gfc_resolve_open (gfc_open *open)
   RESOLVE_TAG (&tag_e_round, open->round);
   RESOLVE_TAG (&tag_e_sign, open->sign);
   RESOLVE_TAG (&tag_convert, open->convert);
+  RESOLVE_TAG (&tag_newunit, open->newunit);
 
   if (gfc_reference_st_label (open->err, ST_LABEL_TARGET) == FAILURE)
     return FAILURE;
@@ -1618,6 +1805,26 @@ gfc_match_open (void)
     }
 
   warn = (open->err || open->iostat) ? true : false;
+
+  /* Checks on NEWUNIT specifier.  */
+  if (open->newunit)
+    {
+      if (open->unit)
+       {
+         gfc_error ("UNIT specifier not allowed with NEWUNIT at %C");
+         goto cleanup;
+       }
+
+      if (!(open->file || (open->status
+          && gfc_wide_strncasecmp (open->status->value.character.string,
+                                  "scratch", 7) == 0)))
+       {
+         gfc_error ("NEWUNIT specifier must have FILE= "
+                    "or STATUS='scratch' at %C");
+         goto cleanup;
+       }
+    }
+
   /* Checks on the ACCESS specifier.  */
   if (open->access && open->access->expr_type == EXPR_CONSTANT)
     {
@@ -1769,8 +1976,8 @@ gfc_match_open (void)
   /* Checks on the ROUND specifier.  */
   if (open->round)
     {
-      /* When implemented, change the following to use gfc_notify_std F2003.  */
-      gfc_error ("Fortran F2003: ROUND= specifier at %C not implemented");
+      if (gfc_notify_std (GFC_STD_F2003, "Fortran F2003: ROUND= at %C "
+         "not allowed in Fortran 95") == FAILURE)
       goto cleanup;
 
       if (open->round->expr_type == EXPR_CONSTANT)
@@ -2045,6 +2252,14 @@ gfc_resolve_close (gfc_close *close)
   if (gfc_reference_st_label (close->err, ST_LABEL_TARGET) == FAILURE)
     return FAILURE;
 
+  if (close->unit->expr_type == EXPR_CONSTANT
+      && close->unit->ts.type == BT_INTEGER
+      && mpz_sgn (close->unit->value.integer) < 0)
+    {
+      gfc_error ("UNIT number in CLOSE statement at %L must be non-negative",
+                &close->unit->where);
+    }
+
   return SUCCESS;
 }
 
@@ -2167,6 +2382,14 @@ gfc_resolve_filepos (gfc_filepos *fp)
   if (gfc_reference_st_label (fp->err, ST_LABEL_TARGET) == FAILURE)
     return FAILURE;
 
+  if (fp->unit->expr_type == EXPR_CONSTANT
+      && fp->unit->ts.type == BT_INTEGER
+      && mpz_sgn (fp->unit->value.integer) < 0)
+    {
+      gfc_error ("UNIT number in statement at %L must be non-negative",
+                &fp->unit->where);
+    }
+
   return SUCCESS;
 }
 
@@ -2412,7 +2635,7 @@ match_dt_element (io_kind k, gfc_dt *dt)
   m = match_etag (&tag_rec, &dt->rec);
   if (m != MATCH_NO)
     return m;
-  m = match_etag (&tag_spos, &dt->rec);
+  m = match_etag (&tag_spos, &dt->pos);
   if (m != MATCH_NO)
     return m;
   m = match_out_tag (&tag_iomsg, &dt->iomsg);
@@ -2478,6 +2701,7 @@ gfc_free_dt (gfc_dt *dt)
   gfc_free_expr (dt->blank);
   gfc_free_expr (dt->decimal);
   gfc_free_expr (dt->extra_comma);
+  gfc_free_expr (dt->pos);
   gfc_free (dt);
 }
 
@@ -2485,13 +2709,13 @@ gfc_free_dt (gfc_dt *dt)
 /* Resolve everything in a gfc_dt structure.  */
 
 gfc_try
-gfc_resolve_dt (gfc_dt *dt)
+gfc_resolve_dt (gfc_dt *dt, locus *loc)
 {
   gfc_expr *e;
 
   RESOLVE_TAG (&tag_format, dt->format_expr);
   RESOLVE_TAG (&tag_rec, dt->rec);
-  RESOLVE_TAG (&tag_spos, dt->rec);
+  RESOLVE_TAG (&tag_spos, dt->pos);
   RESOLVE_TAG (&tag_advance, dt->advance);
   RESOLVE_TAG (&tag_id, dt->id);
   RESOLVE_TAG (&tag_iomsg, dt->iomsg);
@@ -2506,6 +2730,12 @@ gfc_resolve_dt (gfc_dt *dt)
   RESOLVE_TAG (&tag_e_async, dt->asynchronous);
 
   e = dt->io_unit;
+  if (e == NULL)
+    {
+      gfc_error ("UNIT not specified at %L", loc);
+      return FAILURE;
+    }
+
   if (gfc_resolve_expr (e) == SUCCESS
       && (e->ts.type != BT_INTEGER
          && (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_VARIABLE)))
@@ -2561,6 +2791,13 @@ gfc_resolve_dt (gfc_dt *dt)
       return FAILURE;
     }
 
+  if (e->expr_type == EXPR_CONSTANT && e->ts.type == BT_INTEGER
+      && mpz_sgn (e->value.integer) < 0)
+    {
+      gfc_error ("UNIT number in statement at %L must be non-negative", &e->where);
+      return FAILURE;
+    }
+
   if (dt->extra_comma
       && gfc_notify_std (GFC_STD_GNU, "Extension: Comma before i/o "
                         "item list at %L", &dt->extra_comma->where) == FAILURE)
@@ -2781,6 +3018,7 @@ match_io_element (io_kind k, gfc_code **cpp)
 
        if (gfc_pure (NULL)
            && gfc_impure_variable (expr->symtree->n.sym)
+           && current_dt->io_unit
            && current_dt->io_unit->ts.type == BT_CHARACTER)
          {
            gfc_error ("Cannot read to variable '%s' in PURE procedure at %C",
@@ -2794,7 +3032,8 @@ match_io_element (io_kind k, gfc_code **cpp)
        break;
 
       case M_WRITE:
-       if (current_dt->io_unit->ts.type == BT_CHARACTER
+       if (current_dt->io_unit
+           && current_dt->io_unit->ts.type == BT_CHARACTER
            && gfc_pure (NULL)
            && current_dt->io_unit->expr_type == EXPR_VARIABLE
            && gfc_impure_variable (current_dt->io_unit->symtree->n.sym))
@@ -2819,7 +3058,7 @@ match_io_element (io_kind k, gfc_code **cpp)
 
   cp = gfc_get_code ();
   cp->op = EXEC_TRANSFER;
-  cp->expr = expr;
+  cp->expr1 = expr;
 
   *cpp = cp;
   return MATCH_YES;
@@ -2930,6 +3169,10 @@ if (condition) \
       io_constraint (dt->rec != NULL,
                     "REC tag at %L is incompatible with internal file",
                     &dt->rec->where);
+    
+      io_constraint (dt->pos != NULL,
+                    "POS tag at %L is incompatible with internal file",
+                    &dt->pos->where);
 
       io_constraint (unformatted,
                     "Unformatted I/O not allowed with internal unit at %L",
@@ -3084,12 +3327,9 @@ if (condition) \
 
   if (dt->round)
     {
-      /* When implemented, change the following to use gfc_notify_std F2003.
       if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ROUND= at %C "
          "not allowed in Fortran 95") == FAILURE)
-       return MATCH_ERROR;  */
-      gfc_error ("F2003 Feature: ROUND= specifier at %C not implemented");
-      return MATCH_ERROR;
+       return MATCH_ERROR;
 
       if (dt->round->expr_type == EXPR_CONSTANT)
        {
@@ -3168,7 +3408,7 @@ if (condition) \
 
       io_constraint (dt->format_expr,
                     "IO spec-list cannot contain both NAMELIST group name "
-                    "and format specification at %L.",
+                    "and format specification at %L",
                     &dt->format_expr->where);
 
       io_constraint (dt->format_label,
@@ -3177,22 +3417,26 @@ if (condition) \
 
       io_constraint (dt->rec,
                     "NAMELIST IO is not allowed with a REC= specifier "
-                    "at %L.", &dt->rec->where);
+                    "at %L", &dt->rec->where);
 
       io_constraint (dt->advance,
                     "NAMELIST IO is not allowed with a ADVANCE= specifier "
-                    "at %L.", &dt->advance->where);
+                    "at %L", &dt->advance->where);
     }
 
   if (dt->rec)
     {
       io_constraint (dt->end,
                     "An END tag is not allowed with a "
-                    "REC= specifier at %L.", &dt->end_where);
+                    "REC= specifier at %L", &dt->end_where);
 
       io_constraint (dt->format_label == &format_asterisk,
                     "FMT=* is not allowed with a REC= specifier "
-                    "at %L.", spec_end);
+                    "at %L", spec_end);
+
+      io_constraint (dt->pos,
+                    "POS= is not allowed with REC= specifier "
+                    "at %L", &dt->pos->where);
     }
 
   if (dt->advance)
@@ -3643,7 +3887,7 @@ gfc_match_inquire (void)
        goto syntax;
 
       new_st.op = EXEC_IOLENGTH;
-      new_st.expr = inquire->iolength;
+      new_st.expr1 = inquire->iolength;
       new_st.ext.inquire = inquire;
 
       if (gfc_pure (NULL))
@@ -3830,7 +4074,6 @@ gfc_match_wait (void)
 {
   gfc_wait *wait;
   match m;
-  locus loc;
 
   m = gfc_match_char ('(');
   if (m == MATCH_NO)
@@ -3838,8 +4081,6 @@ gfc_match_wait (void)
 
   wait = XCNEW (gfc_wait);
 
-  loc = gfc_current_locus;
-
   m = match_wait_element (wait);
   if (m == MATCH_ERROR)
     goto cleanup;