PR 78534, 83704 Handle large formatted I/O
[gcc.git] / libgfortran / io / read.c
index c8ea6434547601677703bc1e6085b815635e4f57..87adfb8a41db1c9f776aa292788ee8786af623d5 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
    Contributed by Andy Vaught
    F2003 I/O support contributed by Jerry DeLisle
 
@@ -29,7 +29,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "unix.h"
 #include <string.h>
 #include <ctype.h>
-#include <stdlib.h>
 #include <assert.h>
 
 typedef unsigned char uchar;
@@ -273,7 +272,7 @@ void
 read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
 {
   char *p;
-  int w;
+  size_t w;
 
   w = f->u.w;
 
@@ -317,11 +316,11 @@ read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
 
 
 static gfc_char4_t
-read_utf8 (st_parameter_dt *dtp, int *nbytes) 
+read_utf8 (st_parameter_dt *dtp, size_t *nbytes)
 {
   static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 };
   static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-  int i, nb, nread;
+  size_t nb, nread;
   gfc_char4_t c;
   char *s;
 
@@ -354,7 +353,7 @@ read_utf8 (st_parameter_dt *dtp, int *nbytes)
   if (s == NULL)
     return 0;
   /* Decode the bytes read.  */
-  for (i = 1; i < nb; i++)
+  for (size_t i = 1; i < nb; i++)
     {
       gfc_char4_t n = *s++;
 
@@ -384,12 +383,11 @@ read_utf8 (st_parameter_dt *dtp, int *nbytes)
 
 
 static void
-read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, int width)
+read_utf8_char1 (st_parameter_dt *dtp, char *p, size_t len, size_t width)
 {
   gfc_char4_t c;
   char *dest;
-  int nbytes;
-  int i, j;
+  size_t nbytes, j;
 
   len = (width < len) ? len : width;
 
@@ -408,16 +406,16 @@ read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, int width)
     }
 
   /* If there was a short read, pad the remaining characters.  */
-  for (i = j; i < len; i++)
+  for (size_t i = j; i < len; i++)
     *dest++ = ' ';
   return;
 }
 
 static void
-read_default_char1 (st_parameter_dt *dtp, char *p, int len, int width)
+read_default_char1 (st_parameter_dt *dtp, char *p, size_t len, size_t width)
 {
   char *s;
-  int m, n;
+  size_t m;
 
   s = read_block_form (dtp, &width);
   
@@ -429,18 +427,16 @@ read_default_char1 (st_parameter_dt *dtp, char *p, int len, int width)
   m = (width > len) ? len : width;
   memcpy (p, s, m);
 
-  n = len - width;
-  if (n > 0)
-    memset (p + m, ' ', n);
+  if (len > width)
+    memset (p + m, ' ', len - width);
 }
 
 
 static void
-read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, int width)
+read_utf8_char4 (st_parameter_dt *dtp, void *p, size_t len, size_t width)
 {
   gfc_char4_t *dest;
-  int nbytes;
-  int i, j;
+  size_t nbytes, j;
 
   len = (width < len) ? len : width;
 
@@ -457,16 +453,16 @@ read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, int width)
     }
 
   /* If there was a short read, pad the remaining characters.  */
-  for (i = j; i < len; i++)
+  for (size_t i = j; i < len; i++)
     *dest++ = (gfc_char4_t) ' ';
   return;
 }
 
 
 static void
-read_default_char4 (st_parameter_dt *dtp, char *p, int len, int width)
+read_default_char4 (st_parameter_dt *dtp, char *p, size_t len, size_t width)
 {
-  int m, n;
+  size_t m, n;
   gfc_char4_t *dest;
 
   if (is_char4_unit(dtp))
@@ -480,15 +476,18 @@ read_default_char4 (st_parameter_dt *dtp, char *p, int len, int width)
       if (width > len)
         s4 += (width - len);
 
-      m = ((int) width > len) ? len : (int) width;
+      m = (width > len) ? len : width;
 
       dest = (gfc_char4_t *) p;
 
       for (n = 0; n < m; n++)
        *dest++ = *s4++;
 
-      for (n = 0; n < len - (int) width; n++)
-       *dest++ = (gfc_char4_t) ' ';
+      if (len > width)
+       {
+         for (n = 0; n < len - width; n++)
+           *dest++ = (gfc_char4_t) ' ';
+       }
     }
   else
     {
@@ -501,15 +500,18 @@ read_default_char4 (st_parameter_dt *dtp, char *p, int len, int width)
       if (width > len)
         s += (width - len);
 
-      m = ((int) width > len) ? len : (int) width;
+      m = (width > len) ? len : width;
 
       dest = (gfc_char4_t *) p;
 
       for (n = 0; n < m; n++, dest++, s++)
        *dest = (unsigned char ) *s;
 
-      for (n = 0; n < len - (int) width; n++, dest++)
-       *dest = (unsigned char) ' ';
+      if (len > width)
+       {
+         for (n = 0; n < len - width; n++, dest++)
+           *dest = (unsigned char) ' ';
+       }
     }
 }
 
@@ -518,15 +520,14 @@ read_default_char4 (st_parameter_dt *dtp, char *p, int len, int width)
    processing UTF-8 encoding if necessary.  */
 
 void
-read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length)
+read_a (st_parameter_dt *dtp, const fnode *f, char *p, size_t length)
 {
-  int wi;
-  int w;
+  size_t w;
 
-  wi = f->u.w;
-  if (wi == -1) /* '(A)' edit descriptor  */
-    wi = length;
-  w = wi;
+  if (f->u.w == -1) /* '(A)' edit descriptor  */
+    w = length;
+  else
+    w = f->u.w;
 
   /* Read in w characters, treating comma as not a separator.  */
   dtp->u.p.sf_read_comma = 0;
@@ -545,13 +546,14 @@ read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length)
    processing UTF-8 encoding if necessary.  */
 
 void
-read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, int length)
+read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, size_t length)
 {
-  int w;
+  size_t w;
 
-  w = f->u.w;
-  if (w == -1) /* '(A)' edit descriptor  */
+  if (f->u.w == -1) /* '(A)' edit descriptor  */
     w = length;
+  else
+    w = f->u.w;
 
   /* Read in w characters, treating comma as not a separator.  */
   dtp->u.p.sf_read_comma = 0;
@@ -566,10 +568,10 @@ read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, int length)
 }
 
 /* eat_leading_spaces()-- Given a character pointer and a width,
* ignore the leading spaces.  */
  ignore the leading spaces.  */
 
 static char *
-eat_leading_spaces (int *width, char *p)
+eat_leading_spaces (size_t *width, char *p)
 {
   for (;;)
     {
@@ -585,7 +587,7 @@ eat_leading_spaces (int *width, char *p)
 
 
 static char
-next_char (st_parameter_dt *dtp, char **p, int *w)
+next_char (st_parameter_dt *dtp, char **p, size_t *w)
 {
   char c, *q;
 
@@ -618,14 +620,15 @@ next_char (st_parameter_dt *dtp, char **p, int *w)
 
 
 /* read_decimal()-- Read a decimal integer value.  The values here are
* signed values. */
  signed values. */
 
 void
 read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
 {
   GFC_UINTEGER_LARGEST value, maxv, maxv_10;
   GFC_INTEGER_LARGEST v;
-  int w, negative; 
+  size_t w;
+  int negative;
   char c, *p;
 
   w = f->u.w;
@@ -723,9 +726,9 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
 
 
 /* read_radix()-- This function reads values for non-decimal radixes.
* The difference here is that we treat the values here as unsigned
* values for the purposes of overflow.  If minus sign is present and
* the top bit is set, the value will be incorrect. */
  The difference here is that we treat the values here as unsigned
  values for the purposes of overflow.  If minus sign is present and
  the top bit is set, the value will be incorrect. */
 
 void
 read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
@@ -733,7 +736,8 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
 {
   GFC_UINTEGER_LARGEST value, maxv, maxv_r;
   GFC_INTEGER_LARGEST v;
-  int w, negative;
+  size_t w;
+  int negative;
   char c, *p;
 
   w = f->u.w;
@@ -883,7 +887,8 @@ read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
 #define READF_TMP 50
   char tmp[READF_TMP];
   size_t buf_size = 0;
-  int w, seen_dp, exponent;
+  size_t w;
+  int seen_dp, exponent;
   int exponent_sign;
   const char *p;
   char *buffer;
@@ -1228,15 +1233,16 @@ bad_float:
 
 
 /* read_x()-- Deal with the X/TR descriptor.  We just read some data
* and never look at it. */
  and never look at it. */
 
 void
-read_x (st_parameter_dt *dtp, int n)
+read_x (st_parameter_dt *dtp, size_t n)
 {
-  int length, q, q2;
+  size_t length;
+  int q, q2;
 
   if ((dtp->u.p.current_unit->pad_status == PAD_NO || is_internal_unit (dtp))
-       && dtp->u.p.current_unit->bytes_left < n)
+      && dtp->u.p.current_unit->bytes_left < (gfc_offset) n)
     n = dtp->u.p.current_unit->bytes_left;
     
   if (n == 0)