OSDN Git Service

2011-08-18 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / libgfortran / io / list_read.c
index 9f8555a..11a35c9 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);
@@ -768,9 +755,9 @@ read_logical (st_parameter_dt *dtp, int length)
       hit_eof (dtp);
       return;
     }
-  else
+  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:
@@ -906,9 +895,9 @@ read_integer (st_parameter_dt *dtp, int length)
       hit_eof (dtp);
       return;
     }
-  else
+  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,11 +1088,12 @@ 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)
     goto bad;
+    
   if (c == '-' || c == '+')
     {
       push_char (dtp, c);
@@ -1162,7 +1152,6 @@ parse_real (st_parameter_dt *dtp, void *buffer, int length)
          goto exp2;
 
        CASE_SEPARATORS:
-         unget_char (dtp, c);
          goto done;
 
        default:
@@ -1215,6 +1204,15 @@ parse_real (st_parameter_dt *dtp, void *buffer, int length)
 
   return m;
 
+ done_infnan:
+  unget_char (dtp, c);
+  push_char (dtp, '\0');
+
+  m = convert_infnan (dtp, buffer, dtp->u.p.saved_string, length);
+  free_saved (dtp);
+
+  return m;
+
  inf_nan:
   /* Match INF and Infinity.  */
   if ((c == 'i' || c == 'I')
@@ -1235,7 +1233,7 @@ parse_real (st_parameter_dt *dtp, void *buffer, int length)
             push_char (dtp, 'i');
             push_char (dtp, 'n');
             push_char (dtp, 'f');
-            goto done;
+            goto done_infnan;
          }
     } /* Match NaN.  */
   else if (((c = next_char (dtp)) == 'a' || c == 'A')
@@ -1259,7 +1257,7 @@ parse_real (st_parameter_dt *dtp, void *buffer, int length)
          if (is_separator (c))
            unget_char (dtp, c);
        }
-      goto done;
+      goto done_infnan;
     }
 
  bad:
@@ -1273,9 +1271,9 @@ parse_real (st_parameter_dt *dtp, void *buffer, int length)
       hit_eof (dtp);
       return 1;
     }
-  else
+  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);
 
@@ -1289,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))
@@ -1310,15 +1308,22 @@ read_complex (st_parameter_dt *dtp, void * dest, int kind, size_t size)
       goto bad_complex;
     }
 
+eol_1:
   eat_spaces (dtp);
+  c = next_char (dtp);
+  if (c == '\n' || c== '\r')
+    goto eol_1;
+  else
+    unget_char (dtp, c);
+
   if (parse_real (dtp, dest, kind))
     return;
 
-eol_1:
+eol_2:
   eat_spaces (dtp);
   c = next_char (dtp);
   if (c == '\n' || c== '\r')
-    goto eol_1;
+    goto eol_2;
   else
     unget_char (dtp, c);
 
@@ -1326,18 +1331,25 @@ eol_1:
       !=  (dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';'))
     goto bad_complex;
 
-eol_2:
+eol_3:
   eat_spaces (dtp);
   c = next_char (dtp);
   if (c == '\n' || c== '\r')
-    goto eol_2;
+    goto eol_3;
   else
     unget_char (dtp, c);
 
   if (parse_real (dtp, dest + size / 2, kind))
     return;
-
+    
+eol_4:
   eat_spaces (dtp);
+  c = next_char (dtp);
+  if (c == '\n' || c== '\r')
+    goto eol_4;
+  else
+    unget_char (dtp, c);
+
   if (next_char (dtp) != ')')
     goto bad_complex;
 
@@ -1363,9 +1375,9 @@ eol_2:
       hit_eof (dtp);
       return;
     }
-  else    
+  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);
 }
@@ -1376,7 +1388,7 @@ eol_2:
 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;
@@ -1704,7 +1716,15 @@ read_real (st_parameter_dt *dtp, void * dest, int length)
     }
 
   free_line (dtp);
-  goto done;
+  unget_char (dtp, c);
+  eat_separator (dtp);
+  push_char (dtp, '\0');
+  if (convert_infnan (dtp, dest, dtp->u.p.saved_string, length))
+    return;
+
+  free_saved (dtp);
+  dtp->u.p.saved_type = BT_REAL;
+  return;
 
  unwind:
   if (dtp->u.p.namelist_mode)
@@ -1726,9 +1746,10 @@ read_real (st_parameter_dt *dtp, void * dest, int length)
       hit_eof (dtp);
       return;
     }
-  else
+  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);
 }
@@ -1740,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);
 
@@ -1757,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);
@@ -2008,6 +2029,7 @@ calls:
 static try
 nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
                     array_loop_spec *ls, int rank, char *parse_err_msg,
+                    size_t parse_err_msg_size,
                     int *parsed_rank)
 {
   int dim;
@@ -2077,9 +2099,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;
@@ -2096,10 +2120,11 @@ nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
 
                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;
                }
 
@@ -2107,9 +2132,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;
                }
 
@@ -2117,15 +2144,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;
                }
@@ -2140,12 +2169,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;
@@ -2155,11 +2186,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.  */
@@ -2167,13 +2198,12 @@ 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)
                    ls[dim].end = ls[dim].start;
                  else
@@ -2197,22 +2227,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;
        }
 
@@ -2700,7 +2733,8 @@ nml_get_obj_data (st_parameter_dt *dtp, namelist_info **pprev_nl,
        return FAILURE;
       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, '=');
@@ -2715,7 +2749,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 '/':
@@ -2806,7 +2841,8 @@ get_name:
     {
       parsed_rank = 0;
       if (nml_parse_qualifier (dtp, nl->dim, nl->ls, nl->var_rank,
-                              nml_err_msg, &parsed_rank) == FAILURE)
+                              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,
@@ -2861,7 +2897,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, nml_err_msg, 
+                              nml_err_msg_size, &parsed_rank)
          == FAILURE)
        {
          char *nml_err_msg_end = strchr (nml_err_msg, '\0');
@@ -2970,6 +3007,11 @@ namelist_read (st_parameter_dt *dtp)
 {
   int c;
   char nml_err_msg[200];
+
+  /* Initialize the error string buffer just in case we get an unexpected fail
+     somewhere and end up at nml_err_ret.  */
+  strcpy (nml_err_msg, "Internal namelist read error");
+
   /* Pointer to the previously read object, in case attempt is made to read
      new object name.  Should this fail, error message can give previous
      name.  */
@@ -3043,6 +3085,11 @@ find_nml_name:
            goto nml_err_ret;
          generate_error (&dtp->common, LIBERROR_READ_VALUE, nml_err_msg);
         }
+
+      /* Reset the previous namelist pointer if we know we are not going
+        to be doing multiple reads within a single namelist object.  */
+      if (prev_nl && prev_nl->var_rank == 0)
+       prev_nl = NULL;
     }
 
   free_saved (dtp);