-/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
Contributed by Andy Vaught
F2003 I/O support contributed by Jerry DeLisle
#include "format.h"
#include "unix.h"
#include <string.h>
-#include <errno.h>
#include <ctype.h>
-#include <stdlib.h>
#include <assert.h>
typedef unsigned char uchar;
read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
{
char *p;
- int w;
+ size_t w;
w = f->u.w;
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;
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++;
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;
}
/* 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);
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;
}
/* 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))
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
{
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) ' ';
+ }
}
}
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;
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;
}
/* 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 (;;)
{
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;
/* 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;
if (c == ' ')
{
- if (dtp->u.p.blank_status == BLANK_NULL) continue;
+ if (dtp->u.p.blank_status == BLANK_NULL)
+ {
+ /* Skip spaces. */
+ for ( ; w > 0; p++, w--)
+ if (*p != ' ') break;
+ continue;
+ }
if (dtp->u.p.blank_status == BLANK_ZERO) c = '0';
}
/* 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,
{
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;
void
read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
{
- int w, seen_dp, exponent;
+#define READF_TMP 50
+ char tmp[READF_TMP];
+ size_t buf_size = 0;
+ size_t w;
+ int seen_dp, exponent;
int exponent_sign;
const char *p;
char *buffer;
exponent_sign = 1;
exponent = 0;
w = f->u.w;
+ buffer = tmp;
/* Read in the next block. */
p = read_block_form (dtp, &w);
exponent because of an implicit decimal point or the like. Thus allocating
strlen ("+0.0e-1000") == 10 characters plus one for NUL more than the
original buffer had should be enough. */
- buffer = gfc_alloca (w + 11);
+ buf_size = w + 11;
+ if (buf_size > READF_TMP)
+ buffer = xmalloc (buf_size);
+
out = buffer;
/* Optional sign */
goto bad_float;
convert_infnan (dtp, dest, buffer, length);
+ if (buf_size > READF_TMP)
+ free (buffer);
return;
}
the d parameter before explict conversion takes place. */
if (w == 0)
- goto bad_float;
+ {
+ /* Extension: allow default exponent of 0 when omitted. */
+ if (dtp->common.flags & IOPARM_DT_DEFAULT_EXP)
+ goto done;
+ else
+ goto bad_float;
+ }
if (dtp->u.p.blank_status == BLANK_UNSPECIFIED)
{
/* Do the actual conversion. */
convert_real (dtp, dest, buffer, length);
-
+ if (buf_size > READF_TMP)
+ free (buffer);
return;
/* The value read is zero. */
return;
bad_float:
+ if (buf_size > READF_TMP)
+ free (buffer);
generate_error (&dtp->common, LIBERROR_READ_VALUE,
"Bad value during floating point read");
next_record (dtp, 1);
/* 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)
q = fbuf_getc (dtp->u.p.current_unit);
if (q == EOF)
break;
- else if (q == '\n' || q == '\r')
+ else if (dtp->u.p.current_unit->flags.cc != CC_NONE
+ && (q == '\n' || q == '\r'))
{
/* Unexpected end of line. Set the position. */
dtp->u.p.sf_seen_eor = 1;
}
done:
- if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
- dtp->u.p.size_used += (GFC_IO_INT) n;
+ if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
+ dtp->u.p.current_unit->has_size)
+ dtp->u.p.current_unit->size_used += (GFC_IO_INT) n;
dtp->u.p.current_unit->bytes_left -= n;
dtp->u.p.current_unit->strm_pos += (gfc_offset) n;
}