OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / fortran / io.c
index 5ea051c..ea56292 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},
@@ -50,6 +50,7 @@ static const io_tag
        tag_e_pad       = {"PAD", " pad =", " %e", BT_CHARACTER},
        tag_e_decimal   = {"DECIMAL", " decimal =", " %e", BT_CHARACTER},
        tag_e_encoding  = {"ENCODING", " encoding =", " %e", BT_CHARACTER},
+       tag_e_async     = {"ASYNCHRONOUS", " asynchronous =", " %e", BT_CHARACTER},
        tag_e_round     = {"ROUND", " round =", " %e", BT_CHARACTER},
        tag_e_sign      = {"SIGN", " sign =", " %e", BT_CHARACTER},
        tag_unit        = {"UNIT", " unit =", " %e", BT_INTEGER},
@@ -81,14 +82,20 @@ static const io_tag
        tag_readwrite   = {"READWRITE", " readwrite =", " %v", BT_CHARACTER},
        tag_s_delim     = {"DELIM", " delim =", " %v", BT_CHARACTER},
        tag_s_pad       = {"PAD", " pad =", " %v", BT_CHARACTER},
+       tag_s_decimal   = {"DECIMAL", " decimal =", " %v", BT_CHARACTER},
+       tag_s_encoding  = {"ENCODING", " encoding =", " %v", BT_CHARACTER},
+       tag_s_async     = {"ASYNCHRONOUS", " asynchronous =", " %v", BT_CHARACTER},
+       tag_s_round     = {"ROUND", " round =", " %v", BT_CHARACTER},
+       tag_s_sign      = {"SIGN", " sign =", " %v", BT_CHARACTER},
        tag_iolength    = {"IOLENGTH", " iolength =", " %v", BT_INTEGER},
        tag_convert     = {"CONVERT", " convert =", " %e", BT_CHARACTER},
        tag_strm_out    = {"POS", " pos =", " %v", BT_INTEGER},
        tag_err         = {"ERR", " err =", " %l", BT_UNKNOWN},
        tag_end         = {"END", " end =", " %l", BT_UNKNOWN},
        tag_eor         = {"EOR", " eor =", " %l", BT_UNKNOWN},
-       tag_async       = {"ASYNCHRONOUS", " asynchronous =", " %e", BT_CHARACTER},
-       tag_id          = {"ID", " id =", " %v", BT_INTEGER};
+       tag_id          = {"ID", " id =", " %v", BT_INTEGER},
+       tag_pending     = {"PENDING", " pending =", " %v", BT_LOGICAL},
+       tag_newunit     = {"NEWUNIT", " newunit =", " %v", BT_INTEGER};
 
 static gfc_dt *current_dt;
 
@@ -101,18 +108,21 @@ static gfc_dt *current_dt;
 typedef enum
 {
   FMT_NONE, FMT_UNKNOWN, FMT_SIGNED_INT, FMT_ZERO, FMT_POSINT, FMT_PERIOD,
-  FMT_COMMA, FMT_COLON, FMT_SLASH, FMT_DOLLAR, FMT_POS, FMT_LPAREN,
+  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_DP, FMT_T, FMT_TR, FMT_TL
 }
 format_token;
 
 /* Local variables for checking format strings.  The saved_token is
    used to back up by a single format token during the parsing
    process.  */
-static char *format_string;
+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;
 
 static format_token saved_token;
 
@@ -126,7 +136,7 @@ mode;
 static char
 next_char (int in_string)
 {
-  static char c;
+  static gfc_char_t c;
 
   if (use_last_char)
     {
@@ -147,18 +157,11 @@ next_char (int in_string)
 
   if (gfc_option.flag_backslash && c == '\\')
     {
-      int tmp;
       locus old_locus = gfc_current_locus;
 
-      /* Use a temp variable to avoid side effects from gfc_match_special_char
-        since it uses an int * for its argument.  */
-      tmp = (int)c;
-
-      if (gfc_match_special_char (&tmp) == MATCH_NO)
+      if (gfc_match_special_char (&c) == MATCH_NO)
        gfc_current_locus = old_locus;
 
-      c = (char)tmp;
-
       if (!(gfc_option.allow_std & GFC_STD_GNU) && !inhibit_warnings)
        gfc_warning ("Extension: backslash character at %C");
     }
@@ -166,7 +169,12 @@ next_char (int in_string)
   if (mode == MODE_COPY)
     *format_string++ = c;
 
-  c = TOUPPER (c);
+  if (mode != MODE_STRING)
+    format_locus = gfc_current_locus;
+
+  format_string_pos++;
+
+  c = gfc_wide_toupper (c);
   return c;
 }
 
@@ -187,7 +195,7 @@ next_char_not_space (bool *error)
   char c;
   do
     {
-      c = next_char (0);
+      error_element = c = next_char (0);
       if (c == '\t')
        {
          if (gfc_option.allow_std & GFC_STD_GNU)
@@ -310,10 +318,18 @@ format_lex (void)
 
     case 'T':
       c = next_char_not_space (&error);
-      if (c != 'L' && c != 'R')
-       unget_char ();
-
-      token = FMT_POS;
+      switch (c)
+       {
+       case 'L':
+         token = FMT_TL;
+         break;
+       case 'R':
+         token = FMT_TR;
+         break;
+       default:
+         token = FMT_T;
+         unget_char ();
+       }
       break;
 
     case '(':
@@ -432,14 +448,14 @@ format_lex (void)
        {
          if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: DP format "
              "specifier not allowed at %C") == FAILURE)
-         return FMT_ERROR;
+           return FMT_ERROR;
          token = FMT_DP;
        }
       else if (c == 'C')
        {
          if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: DC format "
              "specifier not allowed at %C") == FAILURE)
-         return FMT_ERROR;
+           return FMT_ERROR;
          token = FMT_DC;
        }
       else
@@ -470,25 +486,28 @@ format_lex (void)
    by itself, and we are checking it for validity.  The dual origin
    means that the warning message is a little less than great.  */
 
-static try
+static gfc_try
 check_format (bool is_input)
 {
   const char *posint_required    = _("Positive width required");
   const char *nonneg_required    = _("Nonnegative width required");
-  const char *unexpected_element  = _("Unexpected element");
+  const char *unexpected_element  = _("Unexpected element '%c' in format string"
+                                     " at %L");
   const char *unexpected_end     = _("Unexpected end of format string");
+  const char *zero_width         = _("Zero width in format descriptor");
 
   const char *error;
   format_token t, u;
   int level;
   int repeat;
-  try rv;
+  gfc_try rv;
 
   use_last_char = 0;
   saved_token = FMT_NONE;
   level = 0;
   repeat = 0;
   rv = SUCCESS;
+  format_string_pos = 0;
 
   t = format_lex ();
   if (t == FMT_ERROR)
@@ -590,7 +609,9 @@ format_item_1:
 
       goto finished;
 
-    case FMT_POS:
+    case FMT_T:
+    case FMT_TL:
+    case FMT_TR:
     case FMT_IBOZ:
     case FMT_F:
     case FMT_E:
@@ -640,7 +661,17 @@ data_desc:
 
       goto optional_comma;
 
-    case FMT_POS:
+    case FMT_T:
+    case FMT_TL:
+    case FMT_TR:
+      t = format_lex ();
+      if (t != FMT_POSINT)
+       {
+         error = _("Positive width required with T descriptor");
+         goto syntax;
+       }
+      break;
+
     case FMT_L:
       t = format_lex ();
       if (t == FMT_ERROR)
@@ -673,6 +704,11 @@ data_desc:
       t = format_lex ();
       if (t == FMT_ERROR)
        goto fail;
+      if (t == FMT_ZERO)
+       {
+         error = zero_width;
+         goto syntax;
+       }
       if (t != FMT_POSINT)
        saved_token = t;
       break;
@@ -682,12 +718,36 @@ data_desc:
     case FMT_G:
     case FMT_EXT:
       u = format_lex ();
-      if (u == FMT_ERROR)
-       goto fail;
-      if (u != FMT_POSINT)
+      if (t == FMT_G && u == FMT_ZERO)
        {
-         error = posint_required;
-         goto syntax;
+         if (is_input)
+           {
+             error = zero_width;
+             goto syntax;
+           }
+         if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: 'G0' in "
+                             "format at %C") == FAILURE)
+           return FAILURE;
+         u = format_lex ();
+         if (u != FMT_PERIOD)
+           {
+             saved_token = u;
+             break;
+           }
+         u = format_lex ();
+         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;
        }
 
       u = format_lex ();
@@ -783,7 +843,7 @@ data_desc:
        gfc_warning ("The H format specifier at %C is"
                     " a Fortran 95 deleted feature");
 
-      if(mode == MODE_STRING)
+      if (mode == MODE_STRING)
        {
          format_string += value;
          format_length -= value;
@@ -932,10 +992,13 @@ extension_optional_comma:
   goto format_item;
 
 syntax:
-  gfc_error ("%s in format string at %C", error);
+  if (mode != MODE_FORMAT)
+    format_locus.nextc += format_string_pos;
+  if (error == unexpected_element)
+    gfc_error (error, error_element, &format_locus);
+  else
+    gfc_error ("%s in format string at %L", error, &format_locus);
 fail:
-  /* TODO: More elaborate measures are needed to show where a problem
-     is within a format string that has been calculated.  */
   rv = FAILURE;
 
 finished:
@@ -946,7 +1009,7 @@ finished:
 /* Given an expression node that is a constant string, see if it looks
    like a format string.  */
 
-static try
+static gfc_try
 check_format_string (gfc_expr *e, bool is_input)
 {
   if (!e || e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
@@ -954,6 +1017,12 @@ check_format_string (gfc_expr *e, bool is_input)
 
   mode = MODE_STRING;
   format_string = e->value.character.string;
+
+  /* More elaborate measures are needed to show where a problem is within a
+     format string that has been calculated, but that's probably not worth the
+     effort.  */
+  format_locus = e->where;
+
   return check_format (is_input);
 }
 
@@ -1011,7 +1080,8 @@ gfc_match_format (void)
   e->ts.type = BT_CHARACTER;
   e->ts.kind = gfc_default_character_kind;
   e->where = start;
-  e->value.character.string = format_string = gfc_getmem (format_length + 1);
+  e->value.character.string = format_string
+                           = gfc_get_wide_string (format_length + 1);
   e->value.character.length = format_length;
   gfc_statement_label->format = e;
 
@@ -1082,14 +1152,15 @@ match_vtag (const io_tag *tag, gfc_expr **v)
 
   if (result->symtree->n.sym->attr.intent == INTENT_IN)
     {
-      gfc_error ("Variable tag cannot be INTENT(IN) at %C");
+      gfc_error ("Variable %s cannot be INTENT(IN) at %C", tag->name);
       gfc_free_expr (result);
       return MATCH_ERROR;
     }
 
   if (gfc_pure (NULL) && gfc_impure_variable (result->symtree->n.sym))
     {
-      gfc_error ("Variable tag cannot be assigned in PURE procedure at %C");
+      gfc_error ("Variable %s cannot be assigned in PURE procedure at %C",
+                tag->name);
       gfc_free_expr (result);
       return MATCH_ERROR;
     }
@@ -1102,13 +1173,13 @@ match_vtag (const io_tag *tag, gfc_expr **v)
 /* Match I/O tags that cause variables to become redefined.  */
 
 static match
-match_out_tag(const io_tag *tag, gfc_expr **result)
+match_out_tag (const io_tag *tag, gfc_expr **result)
 {
   match m;
 
-  m = match_vtag(tag, result);
+  m = match_vtag (tag, result);
   if (m == MATCH_YES)
-    gfc_check_do_variable((*result)->symtree);
+    gfc_check_do_variable ((*result)->symtree);
 
   return m;
 }
@@ -1149,7 +1220,7 @@ match_ltag (const io_tag *tag, gfc_st_label ** label)
 
 /* Resolution of the FORMAT tag, to be called from resolve_tag.  */
 
-static try
+static gfc_try
 resolve_tag_format (const gfc_expr *e)
 {
   if (e->expr_type == EXPR_CONSTANT
@@ -1164,8 +1235,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)
        {
@@ -1196,20 +1270,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;
@@ -1218,7 +1306,7 @@ resolve_tag_format (const gfc_expr *e)
 
 /* Do expression resolution and type-checking on an expression tag.  */
 
-static try
+static gfc_try
 resolve_tag (const io_tag *tag, gfc_expr *e)
 {
   if (e == NULL)
@@ -1277,7 +1365,7 @@ match_open_element (gfc_open *open)
 {
   match m;
 
-  m = match_etag (&tag_async, &open->asynchronous);
+  m = match_etag (&tag_e_async, &open->asynchronous);
   if (m != MATCH_NO)
     return m;
   m = match_etag (&tag_unit, &open->unit);
@@ -1337,6 +1425,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;
 }
@@ -1369,13 +1460,14 @@ 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);
 }
 
 
 /* Resolve everything in a gfc_open structure.  */
 
-try
+gfc_try
 gfc_resolve_open (gfc_open *open)
 {
 
@@ -1394,9 +1486,11 @@ gfc_resolve_open (gfc_open *open)
   RESOLVE_TAG (&tag_e_pad, open->pad);
   RESOLVE_TAG (&tag_e_decimal, open->decimal);
   RESOLVE_TAG (&tag_e_encoding, open->encoding);
+  RESOLVE_TAG (&tag_e_async, open->asynchronous);
   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;
@@ -1412,13 +1506,13 @@ gfc_resolve_open (gfc_open *open)
 static int
 compare_to_allowed_values (const char *specifier, const char *allowed[],
                           const char *allowed_f2003[], 
-                          const char *allowed_gnu[], char *value,
+                          const char *allowed_gnu[], gfc_char_t *value,
                           const char *statement, bool warn)
 {
   int i;
   unsigned int len;
 
-  len = strlen (value);
+  len = gfc_wide_strlen (value);
   if (len > 0)
   {
     for (len--; len > 0; len--)
@@ -1429,13 +1523,13 @@ compare_to_allowed_values (const char *specifier, const char *allowed[],
 
   for (i = 0; allowed[i]; i++)
     if (len == strlen (allowed[i])
-       && strncasecmp (value, allowed[i], strlen (allowed[i])) == 0)
+       && gfc_wide_strncasecmp (value, allowed[i], strlen (allowed[i])) == 0)
       return 1;
 
   for (i = 0; allowed_f2003 && allowed_f2003[i]; i++)
     if (len == strlen (allowed_f2003[i])
-       && strncasecmp (value, allowed_f2003[i], strlen (allowed_f2003[i]))
-          == 0)
+       && gfc_wide_strncasecmp (value, allowed_f2003[i],
+                                strlen (allowed_f2003[i])) == 0)
       {
        notification n = gfc_notification_std (GFC_STD_F2003);
 
@@ -1461,7 +1555,8 @@ compare_to_allowed_values (const char *specifier, const char *allowed[],
 
   for (i = 0; allowed_gnu && allowed_gnu[i]; i++)
     if (len == strlen (allowed_gnu[i])
-       && strncasecmp (value, allowed_gnu[i], strlen (allowed_gnu[i])) == 0)
+       && gfc_wide_strncasecmp (value, allowed_gnu[i],
+                                strlen (allowed_gnu[i])) == 0)
       {
        notification n = gfc_notification_std (GFC_STD_GNU);
 
@@ -1487,14 +1582,18 @@ compare_to_allowed_values (const char *specifier, const char *allowed[],
 
   if (warn)
     {
+      char *s = gfc_widechar_to_char (value, -1);
       gfc_warning ("%s specifier in %s statement at %C has invalid value '%s'",
-                  specifier, statement, value);
+                  specifier, statement, s);
+      gfc_free (s);
       return 1;
     }
   else
     {
+      char *s = gfc_widechar_to_char (value, -1);
       gfc_error ("%s specifier in %s statement at %C has invalid value '%s'",
-                specifier, statement, value);
+                specifier, statement, s);
+      gfc_free (s);
       return 0;
     }
 }
@@ -1513,7 +1612,7 @@ gfc_match_open (void)
   if (m == MATCH_NO)
     return m;
 
-  open = gfc_getmem (sizeof (gfc_open));
+  open = XCNEW (gfc_open);
 
   m = match_open_element (open);
 
@@ -1552,6 +1651,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)
     {
@@ -1652,16 +1771,13 @@ gfc_match_open (void)
   /* Checks on the ENCODING specifier.  */
   if (open->encoding)
     {
-      /* When implemented, change the following to use gfc_notify_std F2003.
       if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ENCODING= at %C "
          "not allowed in Fortran 95") == FAILURE)
-       goto cleanup; */
-      gfc_error ("F2003 Feature: ENCODING=specifier at %C not implemented");
-      goto cleanup;
+       goto cleanup;
     
       if (open->encoding->expr_type == EXPR_CONSTANT)
        {
-         static const char * encoding[] = { "UTF-8", "DEFAULT", NULL };
+         static const char * encoding[] = { "DEFAULT", "UTF-8", NULL };
 
          if (!compare_to_allowed_values ("ENCODING", encoding, NULL, NULL,
                                          open->encoding->value.character.string,
@@ -1707,7 +1823,7 @@ gfc_match_open (void)
   if (open->round)
     {
       /* When implemented, change the following to use gfc_notify_std F2003.  */
-      gfc_error ("F2003 Feature: ROUND=specifier at %C not implemented");
+      gfc_error ("Fortran F2003: ROUND= specifier at %C not implemented");
       goto cleanup;
 
       if (open->round->expr_type == EXPR_CONSTANT)
@@ -1772,23 +1888,25 @@ gfc_match_open (void)
                                      "OPEN", warn))
        goto cleanup;
 
-      /* F2003, 9.4.5: If the STATUS=specifier has the value NEW or REPLACE,
-        the FILE=specifier shall appear.  */
+      /* F2003, 9.4.5: If the STATUS= specifier has the value NEW or REPLACE,
+        the FILE= specifier shall appear.  */
       if (open->file == NULL
-         && (strncasecmp (open->status->value.character.string, "replace", 7)
-             == 0
-            || strncasecmp (open->status->value.character.string, "new", 3)
-               == 0))
+         && (gfc_wide_strncasecmp (open->status->value.character.string,
+                                   "replace", 7) == 0
+             || gfc_wide_strncasecmp (open->status->value.character.string,
+                                      "new", 3) == 0))
        {
+         char *s = gfc_widechar_to_char (open->status->value.character.string,
+                                         -1);
          warn_or_error ("The STATUS specified in OPEN statement at %C is "
-                        "'%s' and no FILE specifier is present",
-                        open->status->value.character.string);
+                        "'%s' and no FILE specifier is present", s);
+         gfc_free (s);
        }
 
-      /* F2003, 9.4.5: If the STATUS=specifier has the value SCRATCH,
-        the FILE=specifier shall not appear.  */
-      if (strncasecmp (open->status->value.character.string, "scratch", 7)
-         == 0 && open->file)
+      /* F2003, 9.4.5: If the STATUS= specifier has the value SCRATCH,
+        the FILE= specifier shall not appear.  */
+      if (gfc_wide_strncasecmp (open->status->value.character.string,
+                               "scratch", 7) == 0 && open->file)
        {
          warn_or_error ("The STATUS specified in OPEN statement at %C "
                         "cannot have the value SCRATCH if a FILE specifier "
@@ -1800,8 +1918,8 @@ gfc_match_open (void)
   if (open->form && open->form->expr_type == EXPR_CONSTANT
       && (open->delim || open->decimal || open->encoding || open->round
          || open->sign || open->pad || open->blank)
-      && strncasecmp (open->form->value.character.string,
-                     "unformatted", 11) == 0)
+      && gfc_wide_strncasecmp (open->form->value.character.string,
+                              "unformatted", 11) == 0)
     {
       const char *spec = (open->delim ? "DELIM "
                                      : (open->pad ? "PAD " : open->blank
@@ -1812,7 +1930,8 @@ gfc_match_open (void)
     }
 
   if (open->recl && open->access && open->access->expr_type == EXPR_CONSTANT
-      && strncasecmp (open->access->value.character.string, "stream", 6) == 0)
+      && gfc_wide_strncasecmp (open->access->value.character.string,
+                              "stream", 6) == 0)
     {
       warn_or_error ("RECL specifier not allowed in OPEN statement at %C for "
                     "stream I/O");
@@ -1820,12 +1939,12 @@ gfc_match_open (void)
 
   if (open->position
       && open->access && open->access->expr_type == EXPR_CONSTANT
-      && !(strncasecmp (open->access->value.character.string,
-                       "sequential", 10) == 0
-          || strncasecmp (open->access->value.character.string,
-                          "stream", 6) == 0
-          || strncasecmp (open->access->value.character.string,
-                          "append", 6) == 0))
+      && !(gfc_wide_strncasecmp (open->access->value.character.string,
+                                "sequential", 10) == 0
+          || gfc_wide_strncasecmp (open->access->value.character.string,
+                                   "stream", 6) == 0
+          || gfc_wide_strncasecmp (open->access->value.character.string,
+                                   "append", 6) == 0))
     {
       warn_or_error ("POSITION specifier in OPEN statement at %C only allowed "
                     "for stream or sequential ACCESS");
@@ -1902,7 +2021,7 @@ gfc_match_close (void)
   if (m == MATCH_NO)
     return m;
 
-  close = gfc_getmem (sizeof (gfc_close));
+  close = XCNEW (gfc_close);
 
   m = match_close_element (close);
 
@@ -1968,7 +2087,7 @@ cleanup:
 
 /* Resolve everything in a gfc_close structure.  */
 
-try
+gfc_try
 gfc_resolve_close (gfc_close *close)
 {
   RESOLVE_TAG (&tag_unit, close->unit);
@@ -1979,6 +2098,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;
 }
 
@@ -2028,7 +2155,7 @@ match_filepos (gfc_statement st, gfc_exec_op op)
   gfc_filepos *fp;
   match m;
 
-  fp = gfc_getmem (sizeof (gfc_filepos));
+  fp = XCNEW (gfc_filepos);
 
   if (gfc_match_char ('(') == MATCH_NO)
     {
@@ -2092,7 +2219,7 @@ cleanup:
 }
 
 
-try
+gfc_try
 gfc_resolve_filepos (gfc_filepos *fp)
 {
   RESOLVE_TAG (&tag_unit, fp->unit);
@@ -2101,6 +2228,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;
 }
 
@@ -2138,11 +2273,6 @@ gfc_match_flush (void)
 
 /******************** Data Transfer Statements *********************/
 
-typedef enum
-{ M_READ, M_WRITE, M_PRINT, M_INQUIRE }
-io_kind;
-
-
 /* Return a default unit number.  */
 
 static gfc_expr *
@@ -2324,7 +2454,7 @@ match_dt_element (io_kind k, gfc_dt *dt)
       return MATCH_YES;
     }
 
-  m = match_etag (&tag_async, &dt->asynchronous);
+  m = match_etag (&tag_e_async, &dt->asynchronous);
   if (m != MATCH_NO)
     return m;
   m = match_etag (&tag_e_blank, &dt->blank);
@@ -2351,7 +2481,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);
@@ -2416,21 +2546,24 @@ gfc_free_dt (gfc_dt *dt)
   gfc_free_expr (dt->round);
   gfc_free_expr (dt->blank);
   gfc_free_expr (dt->decimal);
+  gfc_free_expr (dt->extra_comma);
+  gfc_free_expr (dt->pos);
   gfc_free (dt);
 }
 
 
 /* Resolve everything in a gfc_dt structure.  */
 
-try
+gfc_try
 gfc_resolve_dt (gfc_dt *dt)
 {
   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);
   RESOLVE_TAG (&tag_iostat, dt->iostat);
   RESOLVE_TAG (&tag_size, dt->size);
@@ -2440,15 +2573,47 @@ gfc_resolve_dt (gfc_dt *dt)
   RESOLVE_TAG (&tag_e_round, dt->round);
   RESOLVE_TAG (&tag_e_blank, dt->blank);
   RESOLVE_TAG (&tag_e_decimal, dt->decimal);
+  RESOLVE_TAG (&tag_e_async, dt->asynchronous);
 
   e = dt->io_unit;
   if (gfc_resolve_expr (e) == SUCCESS
       && (e->ts.type != BT_INTEGER
          && (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_VARIABLE)))
     {
-      gfc_error ("UNIT specification at %L must be an INTEGER expression "
-                "or a CHARACTER variable", &e->where);
-      return FAILURE;
+      /* If there is no extra comma signifying the "format" form of the IO
+        statement, then this must be an error.  */
+      if (!dt->extra_comma)
+       {
+         gfc_error ("UNIT specification at %L must be an INTEGER expression "
+                    "or a CHARACTER variable", &e->where);
+         return FAILURE;
+       }
+      else
+       {
+         /* At this point, we have an extra comma.  If io_unit has arrived as
+            type character, we assume its really the "format" form of the I/O
+            statement.  We set the io_unit to the default unit and format to
+            the character expression.  See F95 Standard section 9.4.  */
+         io_kind k;
+         k = dt->extra_comma->value.iokind;
+         if (e->ts.type == BT_CHARACTER && (k == M_READ || k == M_PRINT))
+           {
+             dt->format_expr = dt->io_unit;
+             dt->io_unit = default_unit (k);
+
+             /* Free this pointer now so that a warning/error is not triggered
+                below for the "Extension".  */
+             gfc_free_expr (dt->extra_comma);
+             dt->extra_comma = NULL;
+           }
+
+         if (k == M_WRITE)
+           {
+             gfc_error ("Invalid form of WRITE statement at %L, UNIT required",
+                        &dt->extra_comma->where);
+             return FAILURE;
+           }
+       }
     }
 
   if (e->ts.type == BT_CHARACTER)
@@ -2466,6 +2631,17 @@ 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);
+    }
+
+  if (dt->extra_comma
+      && gfc_notify_std (GFC_STD_GNU, "Extension: Comma before i/o "
+                        "item list at %L", &dt->extra_comma->where) == FAILURE)
+    return FAILURE;
+
   if (dt->err)
     {
       if (gfc_reference_st_label (dt->err, ST_LABEL_TARGET) == FAILURE)
@@ -2555,7 +2731,7 @@ static match match_io_element (io_kind, gfc_code **);
 static match
 match_io_iterator (io_kind k, gfc_code **result)
 {
-  gfc_code *head, *tail, *new;
+  gfc_code *head, *tail, *new_code;
   gfc_iterator *iter;
   locus old_loc;
   match m;
@@ -2591,7 +2767,7 @@ match_io_iterator (io_kind k, gfc_code **result)
          break;
        }
 
-      m = match_io_element (k, &new);
+      m = match_io_element (k, &new_code);
       if (m == MATCH_ERROR)
        goto cleanup;
       if (m == MATCH_NO)
@@ -2601,7 +2777,7 @@ match_io_iterator (io_kind k, gfc_code **result)
          goto cleanup;
        }
 
-      tail = gfc_append_code (tail, new);
+      tail = gfc_append_code (tail, new_code);
 
       if (gfc_match_char (',') != MATCH_YES)
        {
@@ -2615,15 +2791,15 @@ match_io_iterator (io_kind k, gfc_code **result)
   if (gfc_match_char (')') != MATCH_YES)
     goto syntax;
 
-  new = gfc_get_code ();
-  new->op = EXEC_DO;
-  new->ext.iterator = iter;
+  new_code = gfc_get_code ();
+  new_code->op = EXEC_DO;
+  new_code->ext.iterator = iter;
 
-  new->block = gfc_get_code ();
-  new->block->op = EXEC_DO;
-  new->block->next = head;
+  new_code->block = gfc_get_code ();
+  new_code->block->op = EXEC_DO;
+  new_code->block->next = head;
 
-  *result = new;
+  *result = new_code;
   return MATCH_YES;
 
 syntax:
@@ -2719,7 +2895,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;
@@ -2731,7 +2907,7 @@ match_io_element (io_kind k, gfc_code **cpp)
 static match
 match_io_list (io_kind k, gfc_code **head_p)
 {
-  gfc_code *head, *tail, *new;
+  gfc_code *head, *tail, *new_code;
   match m;
 
   *head_p = head = tail = NULL;
@@ -2740,15 +2916,15 @@ match_io_list (io_kind k, gfc_code **head_p)
 
   for (;;)
     {
-      m = match_io_element (k, &new);
+      m = match_io_element (k, &new_code);
       if (m == MATCH_ERROR)
        goto cleanup;
       if (m == MATCH_NO)
        goto syntax;
 
-      tail = gfc_append_code (tail, new);
+      tail = gfc_append_code (tail, new_code);
       if (head == NULL)
-       head = new;
+       head = new_code;
 
       if (gfc_match_eos () == MATCH_YES)
        break;
@@ -2830,6 +3006,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",
@@ -2869,13 +3049,13 @@ if (condition) \
       io_constraint (dt->eor, "EOR tag not allowed with output at %L",
                     &dt->eor_where);
 
-      io_constraint (dt->blank, "BLANK=specifier not allowed with output at %L",
+      io_constraint (dt->blank, "BLANK= specifier not allowed with output at %L",
                     &dt->blank->where);
 
-      io_constraint (dt->pad, "PAD=specifier not allowed with output at %L",
+      io_constraint (dt->pad, "PAD= specifier not allowed with output at %L",
                     &dt->pad->where);
 
-      io_constraint (dt->size, "SIZE=specifier not allowed with output at %L",
+      io_constraint (dt->size, "SIZE= specifier not allowed with output at %L",
                     &dt->size->where);
     }
   else
@@ -2893,7 +3073,7 @@ if (condition) \
     {
       static const char * asynchronous[] = { "YES", "NO", NULL };
 
-      if (dt->asynchronous->expr_type != EXPR_CONSTANT)
+      if (gfc_reduce_init_expr (dt->asynchronous) != SUCCESS)
        {
          gfc_error ("ASYNCHRONOUS= specifier at %L must be an initialization "
                     "expression", &dt->asynchronous->where);
@@ -2909,10 +3089,13 @@ if (condition) \
 
   if (dt->id)
     {
-      io_constraint (!dt->asynchronous
-                    || strcmp (dt->asynchronous->value.character.string,
-                                "yes"),
-                    "ID=specifier at %L must be with ASYNCHRONOUS='yes' "
+      bool not_yes
+       = !dt->asynchronous
+         || gfc_wide_strlen (dt->asynchronous->value.character.string) != 3
+         || gfc_wide_strncasecmp (dt->asynchronous->value.character.string,
+                                  "yes", 3) != 0;
+      io_constraint (not_yes,
+                    "ID= specifier at %L must be with ASYNCHRONOUS='yes' "
                     "specifier", &dt->id->where);
     }
 
@@ -2932,7 +3115,7 @@ if (condition) \
            return MATCH_ERROR;
 
          io_constraint (unformatted,
-                        "the DECIMAL=specifier at %L must be with an "
+                        "the DECIMAL= specifier at %L must be with an "
                         "explicit format expression", &dt->decimal->where);
        }
     }
@@ -2953,7 +3136,7 @@ if (condition) \
            return MATCH_ERROR;
 
          io_constraint (unformatted,
-                        "the BLANK=specifier at %L must be with an "
+                        "the BLANK= specifier at %L must be with an "
                         "explicit format expression", &dt->blank->where);
        }
     }
@@ -2974,7 +3157,7 @@ if (condition) \
            return MATCH_ERROR;
 
          io_constraint (unformatted,
-                        "the PAD=specifier at %L must be with an "
+                        "the PAD= specifier at %L must be with an "
                         "explicit format expression", &dt->pad->where);
        }
     }
@@ -2985,7 +3168,7 @@ if (condition) \
       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");
+      gfc_error ("F2003 Feature: ROUND= specifier at %C not implemented");
       return MATCH_ERROR;
 
       if (dt->round->expr_type == EXPR_CONSTANT)
@@ -3018,11 +3201,11 @@ if (condition) \
            return MATCH_ERROR;
 
          io_constraint (unformatted,
-                        "SIGN=specifier at %L must be with an "
+                        "SIGN= specifier at %L must be with an "
                         "explicit format expression", &dt->sign->where);
 
          io_constraint (k == M_READ,
-                        "SIGN=specifier at %L not allowed in a "
+                        "SIGN= specifier at %L not allowed in a "
                         "READ statement", &dt->sign->where);
        }
     }
@@ -3043,17 +3226,17 @@ if (condition) \
            return MATCH_ERROR;
 
          io_constraint (k == M_READ,
-                        "DELIM=specifier at %L not allowed in a "
+                        "DELIM= specifier at %L not allowed in a "
                         "READ statement", &dt->delim->where);
       
          io_constraint (dt->format_label != &format_asterisk
                         && dt->namelist == NULL,
-                        "DELIM=specifier at %L must have FMT=*",
+                        "DELIM= specifier at %L must have FMT=*",
                         &dt->delim->where);
 
          io_constraint (unformatted && dt->namelist == NULL,
-                        "DELIM=specifier at %L must be with FMT=* or "
-                        "NML=specifier ", &dt->delim->where);
+                        "DELIM= specifier at %L must be with FMT=* or "
+                        "NML= specifier ", &dt->delim->where);
        }
     }
   
@@ -3065,7 +3248,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,
@@ -3073,23 +3256,27 @@ if (condition) \
                     "and format label at %L", spec_end);
 
       io_constraint (dt->rec,
-                    "NAMELIST IO is not allowed with a REC=specifier "
-                    "at %L.", &dt->rec->where);
+                    "NAMELIST IO is not allowed with a REC= specifier "
+                    "at %L", &dt->rec->where);
 
       io_constraint (dt->advance,
-                    "NAMELIST IO is not allowed with a ADVANCE=specifier "
-                    "at %L.", &dt->advance->where);
+                    "NAMELIST IO is not allowed with a ADVANCE= specifier "
+                    "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);
+                    "FMT=* is not allowed with a REC= specifier "
+                    "at %L", spec_end);
+
+      io_constraint (dt->pos,
+                    "POS= is not allowed with REC= specifier "
+                    "at %L", &dt->pos->where);
     }
 
   if (dt->advance)
@@ -3099,17 +3286,19 @@ if (condition) \
 
       io_constraint (dt->format_label == &format_asterisk,
                     "List directed format(*) is not allowed with a "
-                    "ADVANCE=specifier at %L.", &expr->where);
+                    "ADVANCE= specifier at %L.", &expr->where);
 
       io_constraint (unformatted,
-                    "the ADVANCE=specifier at %L must appear with an "
+                    "the ADVANCE= specifier at %L must appear with an "
                     "explicit format expression", &expr->where);
 
       if (expr->expr_type == EXPR_CONSTANT && expr->ts.type == BT_CHARACTER)
        {
-         const char * advance = expr->value.character.string;
-         not_no = strcasecmp (advance, "no") != 0;
-         not_yes = strcasecmp (advance, "yes") != 0;
+         const gfc_char_t *advance = expr->value.character.string;
+         not_no = gfc_wide_strlen (advance) != 2
+                  || gfc_wide_strncasecmp (advance, "no", 2) != 0;
+         not_yes = gfc_wide_strlen (advance) != 3
+                   || gfc_wide_strncasecmp (advance, "yes", 3) != 0;
        }
       else
        {
@@ -3118,7 +3307,7 @@ if (condition) \
        }
 
       io_constraint (not_no && not_yes,
-                    "ADVANCE=specifier at %L must have value = "
+                    "ADVANCE= specifier at %L must have value = "
                     "YES or NO.", &expr->where);
 
       io_constraint (dt->size && not_no && k == M_READ,
@@ -3148,7 +3337,7 @@ match_io (io_kind k)
   char name[GFC_MAX_SYMBOL_LEN + 1];
   gfc_code *io_code;
   gfc_symbol *sym;
-  int comma_flag, c;
+  int comma_flag;
   locus where;
   locus spec_end;
   gfc_dt *dt;
@@ -3156,7 +3345,7 @@ match_io (io_kind k)
 
   where = gfc_current_locus;
   comma_flag = 0;
-  current_dt = dt = gfc_getmem (sizeof (gfc_dt));
+  current_dt = dt = XCNEW (gfc_dt);
   m = gfc_match_char ('(');
   if (m == MATCH_NO)
     {
@@ -3166,7 +3355,7 @@ match_io (io_kind k)
       else if (k == M_PRINT)
        {
          /* Treat the non-standard case of PRINT namelist.  */
-         if ((gfc_current_form == FORM_FIXED || gfc_peek_char () == ' ')
+         if ((gfc_current_form == FORM_FIXED || gfc_peek_ascii_char () == ' ')
              && gfc_match_name (name) == MATCH_YES)
            {
              gfc_find_symbol (name, NULL, 1, &sym);
@@ -3190,7 +3379,7 @@ match_io (io_kind k)
 
       if (gfc_current_form == FORM_FREE)
        {
-         c = gfc_peek_char();
+         char c = gfc_peek_ascii_char ();
          if (c != ' ' && c != '*' && c != '\'' && c != '"')
            {
              m = MATCH_NO;
@@ -3301,12 +3490,23 @@ get_io_list:
   /* Used in check_io_constraints, where no locus is available.  */
   spec_end = gfc_current_locus;
 
-  /* Optional leading comma (non-standard).  */
-  if (!comma_flag
-      && gfc_match_char (',') == MATCH_YES
-      && gfc_notify_std (GFC_STD_GNU, "Extension: Comma before i/o "
-                        "item list at %C") == FAILURE)
-    return MATCH_ERROR;
+  /* Optional leading comma (non-standard).  We use a gfc_expr structure here
+     to save the locus.  This is used later when resolving transfer statements
+     that might have a format expression without unit number.  */
+  if (!comma_flag && gfc_match_char (',') == MATCH_YES)
+    {
+      dt->extra_comma = gfc_get_expr ();
+
+      /* Set the types to something compatible with iokind. This is needed to
+        get through gfc_free_expr later since iokind really has no Basic Type,
+        BT, of its own.  */
+      dt->extra_comma->expr_type = EXPR_CONSTANT;
+      dt->extra_comma->ts.type = BT_LOGICAL;
+
+      /* Save the iokind and locus for later use in resolution.  */
+      dt->extra_comma->value.iokind = k;
+      dt->extra_comma->where = gfc_current_locus;
+    }
 
   io_code = NULL;
   if (gfc_match_eos () != MATCH_YES)
@@ -3418,10 +3618,18 @@ gfc_free_inquire (gfc_inquire *inquire)
   gfc_free_expr (inquire->write);
   gfc_free_expr (inquire->readwrite);
   gfc_free_expr (inquire->delim);
+  gfc_free_expr (inquire->encoding);
   gfc_free_expr (inquire->pad);
   gfc_free_expr (inquire->iolength);
   gfc_free_expr (inquire->convert);
   gfc_free_expr (inquire->strm_pos);
+  gfc_free_expr (inquire->asynchronous);
+  gfc_free_expr (inquire->decimal);
+  gfc_free_expr (inquire->pending);
+  gfc_free_expr (inquire->id);
+  gfc_free_expr (inquire->sign);
+  gfc_free_expr (inquire->size);
+  gfc_free_expr (inquire->round);
   gfc_free (inquire);
 }
 
@@ -3459,11 +3667,19 @@ match_inquire_element (gfc_inquire *inquire)
   RETM m = match_vtag (&tag_read, &inquire->read);
   RETM m = match_vtag (&tag_write, &inquire->write);
   RETM m = match_vtag (&tag_readwrite, &inquire->readwrite);
+  RETM m = match_vtag (&tag_s_async, &inquire->asynchronous);
   RETM m = match_vtag (&tag_s_delim, &inquire->delim);
+  RETM m = match_vtag (&tag_s_decimal, &inquire->decimal);
+  RETM m = match_vtag (&tag_size, &inquire->size);
+  RETM m = match_vtag (&tag_s_encoding, &inquire->encoding);
+  RETM m = match_vtag (&tag_s_round, &inquire->round);
+  RETM m = match_vtag (&tag_s_sign, &inquire->sign);
   RETM m = match_vtag (&tag_s_pad, &inquire->pad);
   RETM m = match_vtag (&tag_iolength, &inquire->iolength);
   RETM m = match_vtag (&tag_convert, &inquire->convert);
   RETM m = match_out_tag (&tag_strm_out, &inquire->strm_pos);
+  RETM m = match_vtag (&tag_pending, &inquire->pending);
+  RETM m = match_vtag (&tag_id, &inquire->id);
   RETM return MATCH_NO;
 }
 
@@ -3482,7 +3698,7 @@ gfc_match_inquire (void)
   if (m == MATCH_NO)
     return m;
 
-  inquire = gfc_getmem (sizeof (gfc_inquire));
+  inquire = XCNEW (gfc_inquire);
 
   loc = gfc_current_locus;
 
@@ -3511,7 +3727,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))
@@ -3571,6 +3787,13 @@ gfc_match_inquire (void)
       gfc_error ("INQUIRE statement not allowed in PURE procedure at %C");
       goto cleanup;
     }
+  
+  if (inquire->id != NULL && inquire->pending == NULL)
+    {
+      gfc_error ("INQUIRE statement at %L requires a PENDING= specifier with "
+                "the ID= specifier", &loc);
+      goto cleanup;
+    }
 
   new_st.op = EXEC_INQUIRE;
   new_st.ext.inquire = inquire;
@@ -3587,7 +3810,7 @@ cleanup:
 
 /* Resolve everything in a gfc_inquire structure.  */
 
-try
+gfc_try
 gfc_resolve_inquire (gfc_inquire *inquire)
 {
   RESOLVE_TAG (&tag_unit, inquire->unit);
@@ -3615,9 +3838,17 @@ gfc_resolve_inquire (gfc_inquire *inquire)
   RESOLVE_TAG (&tag_readwrite, inquire->readwrite);
   RESOLVE_TAG (&tag_s_delim, inquire->delim);
   RESOLVE_TAG (&tag_s_pad, inquire->pad);
+  RESOLVE_TAG (&tag_s_encoding, inquire->encoding);
+  RESOLVE_TAG (&tag_s_round, inquire->round);
   RESOLVE_TAG (&tag_iolength, inquire->iolength);
   RESOLVE_TAG (&tag_convert, inquire->convert);
   RESOLVE_TAG (&tag_strm_out, inquire->strm_pos);
+  RESOLVE_TAG (&tag_s_async, inquire->asynchronous);
+  RESOLVE_TAG (&tag_s_sign, inquire->sign);
+  RESOLVE_TAG (&tag_s_round, inquire->round);
+  RESOLVE_TAG (&tag_pending, inquire->pending);
+  RESOLVE_TAG (&tag_size, inquire->size);
+  RESOLVE_TAG (&tag_id, inquire->id);
 
   if (gfc_reference_st_label (inquire->err, ST_LABEL_TARGET) == FAILURE)
     return FAILURE;
@@ -3639,7 +3870,7 @@ gfc_free_wait (gfc_wait *wait)
 }
 
 
-try
+gfc_try
 gfc_resolve_wait (gfc_wait *wait)
 {
   RESOLVE_TAG (&tag_unit, wait->unit);
@@ -3689,7 +3920,7 @@ gfc_match_wait (void)
   if (m == MATCH_NO)
     return m;
 
-  wait = gfc_getmem (sizeof (gfc_wait));
+  wait = XCNEW (gfc_wait);
 
   loc = gfc_current_locus;