OSDN Git Service

2013-04-28 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / libgfortran / io / list_read.c
index 6e1cb69..e44cc14 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+/* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Andy Vaught
    Namelist input contributed by Paul Thomas
@@ -63,10 +63,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #define MAX_REPEAT 200000000
 
-#ifndef HAVE_SNPRINTF
-# undef snprintf
-# define snprintf(str, size, ...) sprintf (str, __VA_ARGS__)
-#endif
+
+#define MSGLEN 100
 
 /* Save a character to a string buffer, enlarging it as necessary.  */
 
@@ -353,16 +351,7 @@ eat_separator (st_parameter_dt *dtp)
                  err = eat_line (dtp);
                  if (err)
                    return err;
-                 if ((c = next_char (dtp)) == EOF)
-                   return LIBERROR_END;
-                 if (c == '!')
-                   {
-                     err = eat_line (dtp);
-                     if (err)
-                       return err;
-                     if ((c = next_char (dtp)) == EOF)
-                       return LIBERROR_END;
-                   }
+                 c = '\n';
                }
            }
          while (c == '\n' || c == '\r' || c == ' ' || c == '\t');
@@ -471,7 +460,7 @@ nml_bad_return (st_parameter_dt *dtp, char c)
 static int
 convert_integer (st_parameter_dt *dtp, int length, int negative)
 {
-  char c, *buffer, message[100];
+  char c, *buffer, message[MSGLEN];
   int m;
   GFC_INTEGER_LARGEST v, max, max10;
 
@@ -511,7 +500,7 @@ convert_integer (st_parameter_dt *dtp, int length, int negative)
 
       if (dtp->u.p.repeat_count == 0)
        {
-         sprintf (message, "Zero repeat count in item %d of list input",
+         snprintf (message, MSGLEN, "Zero repeat count in item %d of list input",
                   dtp->u.p.item_count);
 
          generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
@@ -524,10 +513,10 @@ convert_integer (st_parameter_dt *dtp, int length, int negative)
 
  overflow:
   if (length == -1)
-    sprintf (message, "Repeat count overflow in item %d of list input",
+    snprintf (message, MSGLEN, "Repeat count overflow in item %d of list input",
             dtp->u.p.item_count);
   else
-    sprintf (message, "Integer overflow while reading item %d",
+    snprintf (message, MSGLEN, "Integer overflow while reading item %d",
             dtp->u.p.item_count);
 
   free_saved (dtp);
@@ -544,7 +533,7 @@ convert_integer (st_parameter_dt *dtp, int length, int negative)
 static int
 parse_repeat (st_parameter_dt *dtp)
 {
-  char message[100];
+  char message[MSGLEN];
   int c, repeat;
 
   if ((c = next_char (dtp)) == EOF)
@@ -575,7 +564,7 @@ parse_repeat (st_parameter_dt *dtp)
 
          if (repeat > MAX_REPEAT)
            {
-             sprintf (message,
+             snprintf (message, MSGLEN,
                       "Repeat count overflow in item %d of list input",
                       dtp->u.p.item_count);
 
@@ -588,7 +577,7 @@ parse_repeat (st_parameter_dt *dtp)
        case '*':
          if (repeat == 0)
            {
-             sprintf (message,
+             snprintf (message, MSGLEN,
                       "Zero repeat count in item %d of list input",
                       dtp->u.p.item_count);
 
@@ -617,7 +606,7 @@ parse_repeat (st_parameter_dt *dtp)
     }
   else
     eat_line (dtp);
-  sprintf (message, "Bad repeat count in item %d of list input",
+  snprintf (message, MSGLEN, "Bad repeat count in item %d of list input",
           dtp->u.p.item_count);
   generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
   return 1;
@@ -647,7 +636,7 @@ l_push_char (st_parameter_dt *dtp, char c)
 static void
 read_logical (st_parameter_dt *dtp, int length)
 {
-  char message[100];
+  char message[MSGLEN];
   int c, i, v;
 
   if (parse_repeat (dtp))
@@ -659,22 +648,20 @@ read_logical (st_parameter_dt *dtp, int length)
     {
     case 't':
       v = 1;
-      if ((c = next_char (dtp)) == EOF)
-       goto bad_logical;
+      c = next_char (dtp);
       l_push_char (dtp, c);
 
-      if (!is_separator(c))
+      if (!is_separator(c) && c != EOF)
        goto possible_name;
 
       unget_char (dtp, c);
       break;
     case 'f':
       v = 0;
-      if ((c = next_char (dtp)) == EOF)
-       goto bad_logical;
+      c = next_char (dtp);
       l_push_char (dtp, c);
 
-      if (!is_separator(c))
+      if (!is_separator(c) && c != EOF)
        goto possible_name;
 
       unget_char (dtp, c);
@@ -770,7 +757,7 @@ read_logical (st_parameter_dt *dtp, int length)
     }
   else if (c != '\n')
     eat_line (dtp);
-  sprintf (message, "Bad logical value while reading item %d",
+  snprintf (message, MSGLEN, "Bad logical value while reading item %d",
              dtp->u.p.item_count);
   generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
   return;
@@ -793,7 +780,7 @@ read_logical (st_parameter_dt *dtp, int length)
 static void
 read_integer (st_parameter_dt *dtp, int length)
 {
-  char message[100];
+  char message[MSGLEN];
   int c, negative;
 
   negative = 0;
@@ -839,6 +826,7 @@ read_integer (st_parameter_dt *dtp, int length)
          goto repeat;
 
        CASE_SEPARATORS:        /* Not a repeat count.  */
+       case EOF:
          goto done;
 
        default:
@@ -888,6 +876,7 @@ read_integer (st_parameter_dt *dtp, int length)
          break;
 
        CASE_SEPARATORS:
+       case EOF:
          goto done;
 
        default:
@@ -908,7 +897,7 @@ read_integer (st_parameter_dt *dtp, int length)
     }
   else if (c != '\n')
     eat_line (dtp);
-  sprintf (message, "Bad integer for item %d in list input",
+  snprintf (message, MSGLEN, "Bad integer for item %d in list input",
              dtp->u.p.item_count);
   generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
 
@@ -935,7 +924,7 @@ read_integer (st_parameter_dt *dtp, int length)
 static void
 read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
 {
-  char quote, message[100];
+  char quote, message[MSGLEN];
   int c;
 
   quote = ' ';                 /* Space means no quote character.  */
@@ -1024,7 +1013,7 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
   for (;;)
     {
       if ((c = next_char (dtp)) == EOF)
-       goto eof;
+       goto done_eof;
       switch (c)
        {
        case '"':
@@ -1070,26 +1059,26 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
      invalid.  */
  done:
   c = next_char (dtp);
- eof:
-  if (is_separator (c) || c == '!')
done_eof:
+  if (is_separator (c) || c == '!' || c == EOF)
     {
       unget_char (dtp, c);
       eat_separator (dtp);
       dtp->u.p.saved_type = BT_CHARACTER;
       free_line (dtp);
     }
-  else
+  else 
     {
       free_saved (dtp);
-      if (c == EOF)
-       {
-         hit_eof (dtp);
-         return;
-       }
-      sprintf (message, "Invalid string input in item %d",
+      snprintf (message, MSGLEN, "Invalid string input in item %d",
                  dtp->u.p.item_count);
       generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
     }
+  return;
+
+ eof:
+  free_saved (dtp);
+  hit_eof (dtp);
 }
 
 
@@ -1099,7 +1088,7 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
 static int
 parse_real (st_parameter_dt *dtp, void *buffer, int length)
 {
-  char message[100];
+  char message[MSGLEN];
   int c, m, seen_dp;
 
   if ((c = next_char (dtp)) == EOF)
@@ -1284,7 +1273,7 @@ parse_real (st_parameter_dt *dtp, void *buffer, int length)
     }
   else if (c != '\n')
     eat_line (dtp);
-  sprintf (message, "Bad floating point number for item %d",
+  snprintf (message, MSGLEN, "Bad floating point number for item %d",
              dtp->u.p.item_count);
   generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
 
@@ -1298,7 +1287,7 @@ parse_real (st_parameter_dt *dtp, void *buffer, int length)
 static void
 read_complex (st_parameter_dt *dtp, void * dest, int kind, size_t size)
 {
-  char message[100];
+  char message[MSGLEN];
   int c;
 
   if (parse_repeat (dtp))
@@ -1388,7 +1377,7 @@ eol_4:
     }
   else if (c != '\n')   
     eat_line (dtp);
-  sprintf (message, "Bad complex value in item %d of list input",
+  snprintf (message, MSGLEN, "Bad complex value in item %d of list input",
              dtp->u.p.item_count);
   generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
 }
@@ -1399,7 +1388,7 @@ eol_4:
 static void
 read_real (st_parameter_dt *dtp, void * dest, int length)
 {
-  char message[100];
+  char message[MSGLEN];
   int c;
   int seen_dp;
   int is_inf;
@@ -1760,7 +1749,7 @@ read_real (st_parameter_dt *dtp, void * dest, int length)
   else if (c != '\n')
     eat_line (dtp);
 
-  sprintf (message, "Bad real number in item %d of list input",
+  snprintf (message, MSGLEN, "Bad real number in item %d of list input",
              dtp->u.p.item_count);
   generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
 }
@@ -1772,11 +1761,11 @@ read_real (st_parameter_dt *dtp, void * dest, int length)
 static int
 check_type (st_parameter_dt *dtp, bt type, int len)
 {
-  char message[100];
+  char message[MSGLEN];
 
   if (dtp->u.p.saved_type != BT_UNKNOWN && dtp->u.p.saved_type != type)
     {
-      sprintf (message, "Read type %s where %s was expected for item %d",
+      snprintf (message, MSGLEN, "Read type %s where %s was expected for item %d",
                  type_name (dtp->u.p.saved_type), type_name (type),
                  dtp->u.p.item_count);
 
@@ -1789,7 +1778,7 @@ check_type (st_parameter_dt *dtp, bt type, int len)
 
   if (dtp->u.p.saved_length != len)
     {
-      sprintf (message,
+      snprintf (message, MSGLEN,
                  "Read kind %d %s where kind %d is required for item %d",
                  dtp->u.p.saved_length, type_name (dtp->u.p.saved_type), len,
                  dtp->u.p.item_count);
@@ -2039,7 +2028,8 @@ calls:
 
 static try
 nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
-                    array_loop_spec *ls, int rank, char *parse_err_msg,
+                    array_loop_spec *ls, int rank, bt nml_elem_type,
+                    char *parse_err_msg, size_t parse_err_msg_size,
                     int *parsed_rank)
 {
   int dim;
@@ -2063,7 +2053,7 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
   /* The next character in the stream should be the '('.  */
 
   if ((c = next_char (dtp)) == EOF)
-    return FAILURE;
+    goto err_ret;
 
   /* Process the qualifier, by dimension and triplet.  */
 
@@ -2077,7 +2067,7 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
 
          /* Process a potential sign.  */
          if ((c = next_char (dtp)) == EOF)
-           return FAILURE;
+           goto err_ret;
          switch (c)
            {
            case '-':
@@ -2095,11 +2085,12 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
          /* Process characters up to the next ':' , ',' or ')'.  */
          for (;;)
            {
-             if ((c = next_char (dtp)) == EOF)
-               return FAILURE;
-
+             c = next_char (dtp);
              switch (c)
                {
+               case EOF:
+                 goto err_ret;
+
                case ':':
                   is_array_section = 1;
                  break;
@@ -2109,9 +2100,11 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
                      || (c==')' && dim < rank -1))
                    {
                      if (is_char)
-                       sprintf (parse_err_msg, "Bad substring qualifier");
+                       snprintf (parse_err_msg, parse_err_msg_size, 
+                                 "Bad substring qualifier");
                      else
-                       sprintf (parse_err_msg, "Bad number of index fields");
+                       snprintf (parse_err_msg, parse_err_msg_size, 
+                                "Bad number of index fields");
                      goto err_ret;
                    }
                  break;
@@ -2120,18 +2113,17 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
                  push_char (dtp, c);
                  continue;
 
-               case ' ': case '\t':
+               case ' ': case '\t': case '\r': case '\n':
                  eat_spaces (dtp);
-                 if ((c = next_char (dtp) == EOF))
-                   return FAILURE;
                  break;
 
                default:
                  if (is_char)
-                   sprintf (parse_err_msg,
+                   snprintf (parse_err_msg, parse_err_msg_size,
                             "Bad character in substring qualifier");
                  else
-                   sprintf (parse_err_msg, "Bad character in index");
+                   snprintf (parse_err_msg, parse_err_msg_size, 
+                             "Bad character in index");
                  goto err_ret;
                }
 
@@ -2139,9 +2131,11 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
                  && dtp->u.p.saved_string == 0)
                {
                  if (is_char)
-                   sprintf (parse_err_msg, "Null substring qualifier");
+                   snprintf (parse_err_msg, parse_err_msg_size, 
+                             "Null substring qualifier");
                  else
-                   sprintf (parse_err_msg, "Null index field");
+                   snprintf (parse_err_msg, parse_err_msg_size, 
+                             "Null index field");
                  goto err_ret;
                }
 
@@ -2149,15 +2143,17 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
                  || (indx == 2 && dtp->u.p.saved_string == 0))
                {
                  if (is_char)
-                   sprintf (parse_err_msg, "Bad substring qualifier");
+                   snprintf (parse_err_msg, parse_err_msg_size, 
+                             "Bad substring qualifier");
                  else
-                   sprintf (parse_err_msg, "Bad index triplet");
+                   snprintf (parse_err_msg, parse_err_msg_size,
+                             "Bad index triplet");
                  goto err_ret;
                }
 
              if (is_char && !is_array_section)
                {
-                 sprintf (parse_err_msg,
+                 snprintf (parse_err_msg, parse_err_msg_size,
                           "Missing colon in substring qualifier");
                  goto err_ret;
                }
@@ -2172,12 +2168,14 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
                }
 
              /* Now read the index.  */
-             if (convert_integer (dtp, sizeof(ssize_t), neg))
+             if (convert_integer (dtp, sizeof(index_type), neg))
                {
                  if (is_char)
-                   sprintf (parse_err_msg, "Bad integer substring qualifier");
+                   snprintf (parse_err_msg, parse_err_msg_size,
+                             "Bad integer substring qualifier");
                  else
-                   sprintf (parse_err_msg, "Bad integer in index");
+                   snprintf (parse_err_msg, parse_err_msg_size,
+                             "Bad integer in index");
                  goto err_ret;
                }
              break;
@@ -2187,11 +2185,11 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
          if (!null_flag)
            {
              if (indx == 0)
-               memcpy (&ls[dim].start, dtp->u.p.value, sizeof(ssize_t));
+               memcpy (&ls[dim].start, dtp->u.p.value, sizeof(index_type));
              if (indx == 1)
-               memcpy (&ls[dim].end, dtp->u.p.value, sizeof(ssize_t));
+               memcpy (&ls[dim].end, dtp->u.p.value, sizeof(index_type));
              if (indx == 2)
-               memcpy (&ls[dim].step, dtp->u.p.value, sizeof(ssize_t));
+               memcpy (&ls[dim].step, dtp->u.p.value, sizeof(index_type));
            }
 
          /* Singlet or doublet indices.  */
@@ -2199,14 +2197,13 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
            {
              if (indx == 0)
                {
-                 memcpy (&ls[dim].start, dtp->u.p.value, sizeof(ssize_t));
+                 memcpy (&ls[dim].start, dtp->u.p.value, sizeof(index_type));
 
                  /*  If -std=f95/2003 or an array section is specified,
                      do not allow excess data to be processed.  */
                  if (is_array_section == 1
                      || !(compile_options.allow_std & GFC_STD_GNU)
-                     || !dtp->u.p.ionml->touched
-                     || dtp->u.p.ionml->type == BT_DERIVED)
+                     || nml_elem_type == BT_DERIVED)
                    ls[dim].end = ls[dim].start;
                  else
                    dtp->u.p.expanded_read = 1;
@@ -2229,22 +2226,25 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
        }
 
       /* Check the values of the triplet indices.  */
-      if ((ls[dim].start > (ssize_t) GFC_DIMENSION_UBOUND(ad[dim]))
-          || (ls[dim].start < (ssize_t) GFC_DIMENSION_LBOUND(ad[dim]))
-          || (ls[dim].end > (ssize_t) GFC_DIMENSION_UBOUND(ad[dim]))
-          || (ls[dim].end < (ssize_t) GFC_DIMENSION_LBOUND(ad[dim])))
+      if ((ls[dim].start > GFC_DIMENSION_UBOUND(ad[dim]))
+          || (ls[dim].start < GFC_DIMENSION_LBOUND(ad[dim]))
+          || (ls[dim].end > GFC_DIMENSION_UBOUND(ad[dim]))
+          || (ls[dim].end < GFC_DIMENSION_LBOUND(ad[dim])))
        {
          if (is_char)
-           sprintf (parse_err_msg, "Substring out of range");
+           snprintf (parse_err_msg, parse_err_msg_size, 
+                     "Substring out of range");
          else
-           sprintf (parse_err_msg, "Index %d out of range", dim + 1);
+           snprintf (parse_err_msg, parse_err_msg_size, 
+                     "Index %d out of range", dim + 1);
          goto err_ret;
        }
 
       if (((ls[dim].end - ls[dim].start ) * ls[dim].step < 0)
          || (ls[dim].step == 0))
        {
-         sprintf (parse_err_msg, "Bad range in index %d", dim + 1);
+         snprintf (parse_err_msg, parse_err_msg_size, 
+                  "Bad range in index %d", dim + 1);
          goto err_ret;
        }
 
@@ -2256,6 +2256,15 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
 
 err_ret:
 
+  /* The EOF error message is issued by hit_eof. Return true so that the
+     caller does not use parse_err_msg and parse_err_msg_size to generate
+     an unrelated error message.  */
+  if (c == EOF)
+    {
+      hit_eof (dtp);
+      dtp->u.p.input_complete = 1;
+      return SUCCESS;
+    }
   return FAILURE;
 }
 
@@ -2354,11 +2363,11 @@ nml_query (st_parameter_dt *dtp, char c)
   index_type len;
   char * p;
 #ifdef HAVE_CRLF
-  static const index_type endlen = 3;
+  static const index_type endlen = 2;
   static const char endl[] = "\r\n";
   static const char nmlend[] = "&end\r\n";
 #else
-  static const index_type endlen = 2;
+  static const index_type endlen = 1;
   static const char endl[] = "\n";
   static const char nmlend[] = "&end\n";
 #endif
@@ -2388,12 +2397,12 @@ nml_query (st_parameter_dt *dtp, char c)
          /* "&namelist_name\n"  */
 
          len = dtp->namelist_name_len;
-         p = write_block (dtp, len + endlen);
+         p = write_block (dtp, len - 1 + endlen);
           if (!p)
             goto query_return;
          memcpy (p, "&", 1);
          memcpy ((char*)(p + 1), dtp->namelist_name, len);
-         memcpy ((char*)(p + len + 1), &endl, endlen - 1);
+         memcpy ((char*)(p + len + 1), &endl, endlen);
          for (nl = dtp->u.p.ionml; nl; nl = nl->next)
            {
              /* " var_name\n"  */
@@ -2404,14 +2413,15 @@ nml_query (st_parameter_dt *dtp, char c)
                goto query_return;
              memcpy (p, " ", 1);
              memcpy ((char*)(p + 1), nl->var_name, len);
-             memcpy ((char*)(p + len + 1), &endl, endlen - 1);
+             memcpy ((char*)(p + len + 1), &endl, endlen);
            }
 
          /* "&end\n"  */
 
-          p = write_block (dtp, endlen + 3);
+          p = write_block (dtp, endlen + 4);
+         if (!p)
            goto query_return;
-          memcpy (p, &nmlend, endlen + 3);
+          memcpy (p, &nmlend, endlen + 4);
        }
 
       /* Flush the stream to force immediate output.  */
@@ -2551,17 +2561,17 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset,
               since a single object can have multiple reads.  */
            dtp->u.p.expanded_read = 0;
 
-           /* Now loop over the components. Update the component pointer
-              with the return value from nml_write_obj.  This loop jumps
-              past nested derived types by testing if the potential
-              component name contains '%'.  */
+           /* Now loop over the components.  */
 
            for (cmp = nl->next;
                 cmp &&
-                  !strncmp (cmp->var_name, obj_name, obj_name_len) &&
-                  !strchr (cmp->var_name + obj_name_len, '%');
+                  !strncmp (cmp->var_name, obj_name, obj_name_len);
                 cmp = cmp->next)
              {
+               /* Jump over nested derived type by testing if the potential
+                  component name contains '%'.  */
+               if (strchr (cmp->var_name + obj_name_len, '%'))
+                   continue;
 
                if (nml_read_obj (dtp, cmp, (index_type)(pdata - nl->mem_pos),
                                  pprev_nl, nml_err_msg, nml_err_msg_size,
@@ -2724,15 +2734,16 @@ nml_get_obj_data (st_parameter_dt *dtp, namelist_info **pprev_nl,
     return SUCCESS;
 
   if ((c = next_char (dtp)) == EOF)
-    return FAILURE;
+    goto nml_err_ret;
   switch (c)
     {
     case '=':
       if ((c = next_char (dtp)) == EOF)
-       return FAILURE;
+       goto nml_err_ret;
       if (c != '?')
        {
-         sprintf (nml_err_msg, "namelist read: misplaced = sign");
+         snprintf (nml_err_msg, nml_err_msg_size, 
+                   "namelist read: misplaced = sign");
          goto nml_err_ret;
        }
       nml_query (dtp, '=');
@@ -2747,7 +2758,8 @@ nml_get_obj_data (st_parameter_dt *dtp, namelist_info **pprev_nl,
       nml_match_name (dtp, "end", 3);
       if (dtp->u.p.nml_read_error)
        {
-         sprintf (nml_err_msg, "namelist not terminated with / or &end");
+         snprintf (nml_err_msg, nml_err_msg_size, 
+                   "namelist not terminated with / or &end");
          goto nml_err_ret;
        }
     case '/':
@@ -2777,8 +2789,9 @@ get_name:
       if (!is_separator (c))
        push_char (dtp, tolower(c));
       if ((c = next_char (dtp)) == EOF)
-       return FAILURE;
-    } while (!( c=='=' || c==' ' || c=='\t' || c =='(' || c =='%' ));
+       goto nml_err_ret;
+    }
+  while (!( c=='=' || c==' ' || c=='\t' || c =='(' || c =='%' ));
 
   unget_char (dtp, c);
 
@@ -2838,7 +2851,8 @@ get_name:
     {
       parsed_rank = 0;
       if (nml_parse_qualifier (dtp, nl->dim, nl->ls, nl->var_rank,
-                              nml_err_msg, &parsed_rank) == FAILURE)
+                              nl->type, nml_err_msg, nml_err_msg_size,
+                              &parsed_rank) == FAILURE)
        {
          char *nml_err_msg_end = strchr (nml_err_msg, '\0');
          snprintf (nml_err_msg_end,
@@ -2852,7 +2866,7 @@ get_name:
       qualifier_flag = 1;
 
       if ((c = next_char (dtp)) == EOF)
-       return FAILURE;
+       goto nml_err_ret;
       unget_char (dtp, c);
     }
   else if (nl->var_rank > 0)
@@ -2871,14 +2885,15 @@ get_name:
          goto nml_err_ret;
        }
 
-      if (*pprev_nl == NULL || !component_flag)
+      /* Don't move first_nl further in the list if a qualifier was found.  */
+      if ((*pprev_nl == NULL && !qualifier_flag) || !component_flag)
        first_nl = nl;
 
       root_nl = nl;
 
       component_flag = 1;
       if ((c = next_char (dtp)) == EOF)
-       return FAILURE;
+       goto nml_err_ret;
       goto get_name;
     }
 
@@ -2893,7 +2908,8 @@ get_name:
       descriptor_dimension chd[1] = { {1, clow, nl->string_length} };
       array_loop_spec ind[1] = { {1, clow, nl->string_length, 1} };
 
-      if (nml_parse_qualifier (dtp, chd, ind, -1, nml_err_msg, &parsed_rank)
+      if (nml_parse_qualifier (dtp, chd, ind, -1, nl->type,
+                              nml_err_msg, nml_err_msg_size, &parsed_rank)
          == FAILURE)
        {
          char *nml_err_msg_end = strchr (nml_err_msg, '\0');
@@ -2915,7 +2931,7 @@ get_name:
        }
 
       if ((c = next_char (dtp)) == EOF)
-       return FAILURE;
+       goto nml_err_ret;
       unget_char (dtp, c);
     }
 
@@ -2955,7 +2971,7 @@ get_name:
     return SUCCESS;
 
   if ((c = next_char (dtp)) == EOF)
-    return FAILURE;
+    goto nml_err_ret;
 
   if (c != '=')
     {
@@ -2990,6 +3006,17 @@ get_name:
 
 nml_err_ret:
 
+  /* The EOF error message is issued by hit_eof. Return true so that the
+     caller does not use nml_err_msg and nml_err_msg_size to generate
+     an unrelated error message.  */
+  if (c == EOF)
+    {
+      dtp->u.p.input_complete = 1;
+      unget_char (dtp, c);
+      hit_eof (dtp);
+      return SUCCESS;
+    }
+
   return FAILURE;
 }
 
@@ -3042,6 +3069,7 @@ find_nml_name:
 
     case '?':
       nml_query (dtp, '?');
+      goto find_nml_name;
 
     case EOF:
       return;