| Index: gcc/libgfortran/io/write.c
|
| diff --git a/gcc/libgfortran/io/write.c b/gcc/libgfortran/io/write.c
|
| index b6d6e687736dab543896ac1375dfac38a2986a39..fa31b98665bcf5cc68da31522901717f611ab57f 100644
|
| --- a/gcc/libgfortran/io/write.c
|
| +++ b/gcc/libgfortran/io/write.c
|
| @@ -26,6 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
| <http://www.gnu.org/licenses/>. */
|
|
|
| #include "io.h"
|
| +#include "format.h"
|
| +#include "unix.h"
|
| #include <assert.h>
|
| #include <string.h>
|
| #include <ctype.h>
|
| @@ -293,7 +295,7 @@ write_a_char4 (st_parameter_dt *dtp, const fnode *f, const char *source, int len
|
| Standard sections 10.6.3 and 9.9 for further information. */
|
| if (is_stream_io (dtp))
|
| {
|
| - const char crlf[] = "\r\n";
|
| + const gfc_char4_t crlf[] = {0x000d,0x000a};
|
| int i, bytes;
|
| gfc_char4_t *qq;
|
| bytes = 0;
|
| @@ -446,9 +448,10 @@ extract_uint (const void *p, int len)
|
| }
|
| break;
|
| #ifdef HAVE_GFC_INTEGER_16
|
| + case 10:
|
| case 16:
|
| {
|
| - GFC_INTEGER_16 tmp;
|
| + GFC_INTEGER_16 tmp = 0;
|
| memcpy ((void *) &tmp, p, len);
|
| i = (GFC_UINTEGER_16) tmp;
|
| }
|
| @@ -482,20 +485,14 @@ write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
|
|
|
|
|
| static void
|
| -write_int (st_parameter_dt *dtp, const fnode *f, const char *source, int len,
|
| - const char *(*conv) (GFC_UINTEGER_LARGEST, char *, size_t))
|
| +write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n)
|
| {
|
| - GFC_UINTEGER_LARGEST n = 0;
|
| int w, m, digits, nzero, nblank;
|
| char *p;
|
| - const char *q;
|
| - char itoa_buf[GFC_BTOA_BUF_SIZE];
|
|
|
| w = f->u.integer.w;
|
| m = f->u.integer.m;
|
|
|
| - n = extract_uint (source, len);
|
| -
|
| /* Special case: */
|
|
|
| if (m == 0 && n == 0)
|
| @@ -511,7 +508,6 @@ write_int (st_parameter_dt *dtp, const fnode *f, const char *source, int len,
|
| goto done;
|
| }
|
|
|
| - q = conv (n, itoa_buf, sizeof (itoa_buf));
|
| digits = strlen (q);
|
|
|
| /* Select a width if none was specified. The idea here is to always
|
| @@ -538,7 +534,6 @@ write_int (st_parameter_dt *dtp, const fnode *f, const char *source, int len,
|
| goto done;
|
| }
|
|
|
| -
|
| if (!dtp->u.p.no_leading_blank)
|
| {
|
| memset (p, ' ', nblank);
|
| @@ -706,6 +701,202 @@ btoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
|
| return p;
|
| }
|
|
|
| +/* The following three functions, btoa_big, otoa_big, and ztoa_big, are needed
|
| + to convert large reals with kind sizes that exceed the largest integer type
|
| + available on certain platforms. In these cases, byte by byte conversion is
|
| + performed. Endianess is taken into account. */
|
| +
|
| +/* Conversion to binary. */
|
| +
|
| +static const char *
|
| +btoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
|
| +{
|
| + char *q;
|
| + int i, j;
|
| +
|
| + q = buffer;
|
| + if (big_endian)
|
| + {
|
| + const char *p = s;
|
| + for (i = 0; i < len; i++)
|
| + {
|
| + char c = *p;
|
| +
|
| + /* Test for zero. Needed by write_boz later. */
|
| + if (*p != 0)
|
| + *n = 1;
|
| +
|
| + for (j = 0; j < 8; j++)
|
| + {
|
| + *q++ = (c & 128) ? '1' : '0';
|
| + c <<= 1;
|
| + }
|
| + p++;
|
| + }
|
| + }
|
| + else
|
| + {
|
| + const char *p = s + len - 1;
|
| + for (i = 0; i < len; i++)
|
| + {
|
| + char c = *p;
|
| +
|
| + /* Test for zero. Needed by write_boz later. */
|
| + if (*p != 0)
|
| + *n = 1;
|
| +
|
| + for (j = 0; j < 8; j++)
|
| + {
|
| + *q++ = (c & 128) ? '1' : '0';
|
| + c <<= 1;
|
| + }
|
| + p--;
|
| + }
|
| + }
|
| +
|
| + *q = '\0';
|
| +
|
| + if (*n == 0)
|
| + return "0";
|
| +
|
| + /* Move past any leading zeros. */
|
| + while (*buffer == '0')
|
| + buffer++;
|
| +
|
| + return buffer;
|
| +
|
| +}
|
| +
|
| +/* Conversion to octal. */
|
| +
|
| +static const char *
|
| +otoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
|
| +{
|
| + char *q;
|
| + int i, j, k;
|
| + uint8_t octet;
|
| +
|
| + q = buffer + GFC_OTOA_BUF_SIZE - 1;
|
| + *q = '\0';
|
| + i = k = octet = 0;
|
| +
|
| + if (big_endian)
|
| + {
|
| + const char *p = s + len - 1;
|
| + char c = *p;
|
| + while (i < len)
|
| + {
|
| + /* Test for zero. Needed by write_boz later. */
|
| + if (*p != 0)
|
| + *n = 1;
|
| +
|
| + for (j = 0; j < 3 && i < len; j++)
|
| + {
|
| + octet |= (c & 1) << j;
|
| + c >>= 1;
|
| + if (++k > 7)
|
| + {
|
| + i++;
|
| + k = 0;
|
| + c = *--p;
|
| + }
|
| + }
|
| + *--q = '0' + octet;
|
| + octet = 0;
|
| + }
|
| + }
|
| + else
|
| + {
|
| + const char *p = s;
|
| + char c = *p;
|
| + while (i < len)
|
| + {
|
| + /* Test for zero. Needed by write_boz later. */
|
| + if (*p != 0)
|
| + *n = 1;
|
| +
|
| + for (j = 0; j < 3 && i < len; j++)
|
| + {
|
| + octet |= (c & 1) << j;
|
| + c >>= 1;
|
| + if (++k > 7)
|
| + {
|
| + i++;
|
| + k = 0;
|
| + c = *++p;
|
| + }
|
| + }
|
| + *--q = '0' + octet;
|
| + octet = 0;
|
| + }
|
| + }
|
| +
|
| + if (*n == 0)
|
| + return "0";
|
| +
|
| + /* Move past any leading zeros. */
|
| + while (*q == '0')
|
| + q++;
|
| +
|
| + return q;
|
| +}
|
| +
|
| +/* Conversion to hexidecimal. */
|
| +
|
| +static const char *
|
| +ztoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
|
| +{
|
| + static char a[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
| + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
| +
|
| + char *q;
|
| + uint8_t h, l;
|
| + int i;
|
| +
|
| + q = buffer;
|
| +
|
| + if (big_endian)
|
| + {
|
| + const char *p = s;
|
| + for (i = 0; i < len; i++)
|
| + {
|
| + /* Test for zero. Needed by write_boz later. */
|
| + if (*p != 0)
|
| + *n = 1;
|
| +
|
| + h = (*p >> 4) & 0x0F;
|
| + l = *p++ & 0x0F;
|
| + *q++ = a[h];
|
| + *q++ = a[l];
|
| + }
|
| + }
|
| + else
|
| + {
|
| + const char *p = s + len - 1;
|
| + for (i = 0; i < len; i++)
|
| + {
|
| + /* Test for zero. Needed by write_boz later. */
|
| + if (*p != 0)
|
| + *n = 1;
|
| +
|
| + h = (*p >> 4) & 0x0F;
|
| + l = *p-- & 0x0F;
|
| + *q++ = a[h];
|
| + *q++ = a[l];
|
| + }
|
| + }
|
| +
|
| + *q = '\0';
|
| +
|
| + if (*n == 0)
|
| + return "0";
|
| +
|
| + /* Move past any leading zeros. */
|
| + while (*buffer == '0')
|
| + buffer++;
|
| +
|
| + return buffer;
|
| +}
|
|
|
| /* gfc_itoa()-- Integer to decimal conversion.
|
| The itoa function is a widespread non-standard extension to standard
|
| @@ -757,22 +948,64 @@ write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
|
|
|
|
|
| void
|
| -write_b (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
|
| +write_b (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
|
| {
|
| - write_int (dtp, f, p, len, btoa);
|
| + const char *p;
|
| + char itoa_buf[GFC_BTOA_BUF_SIZE];
|
| + GFC_UINTEGER_LARGEST n = 0;
|
| +
|
| + if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
|
| + {
|
| + p = btoa_big (source, itoa_buf, len, &n);
|
| + write_boz (dtp, f, p, n);
|
| + }
|
| + else
|
| + {
|
| + n = extract_uint (source, len);
|
| + p = btoa (n, itoa_buf, sizeof (itoa_buf));
|
| + write_boz (dtp, f, p, n);
|
| + }
|
| }
|
|
|
|
|
| void
|
| -write_o (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
|
| +write_o (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
|
| {
|
| - write_int (dtp, f, p, len, otoa);
|
| + const char *p;
|
| + char itoa_buf[GFC_OTOA_BUF_SIZE];
|
| + GFC_UINTEGER_LARGEST n = 0;
|
| +
|
| + if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
|
| + {
|
| + p = otoa_big (source, itoa_buf, len, &n);
|
| + write_boz (dtp, f, p, n);
|
| + }
|
| + else
|
| + {
|
| + n = extract_uint (source, len);
|
| + p = otoa (n, itoa_buf, sizeof (itoa_buf));
|
| + write_boz (dtp, f, p, n);
|
| + }
|
| }
|
|
|
| void
|
| -write_z (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
|
| +write_z (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
|
| {
|
| - write_int (dtp, f, p, len, gfc_xtoa);
|
| + const char *p;
|
| + char itoa_buf[GFC_XTOA_BUF_SIZE];
|
| + GFC_UINTEGER_LARGEST n = 0;
|
| +
|
| + if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
|
| + {
|
| + p = ztoa_big (source, itoa_buf, len, &n);
|
| + write_boz (dtp, f, p, n);
|
| + }
|
| + else
|
| + {
|
| + n = extract_uint (source, len);
|
| + p = gfc_xtoa (n, itoa_buf, sizeof (itoa_buf));
|
| + write_boz (dtp, f, p, n);
|
| + }
|
| }
|
|
|
|
|
| @@ -1194,10 +1427,8 @@ namelist_write_newline (st_parameter_dt *dtp)
|
| if (is_array_io (dtp))
|
| {
|
| gfc_offset record;
|
| - int finished, length;
|
| + int finished;
|
|
|
| - length = (int) dtp->u.p.current_unit->bytes_left;
|
| -
|
| /* Now that the current record has been padded out,
|
| determine where the next record in the array is. */
|
| record = next_array_record (dtp, dtp->u.p.current_unit->ls,
|
| @@ -1316,8 +1547,8 @@ nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
|
| nelem = 1;
|
| for (dim_i = 0; dim_i < (size_t) obj->var_rank; dim_i++)
|
| {
|
| - obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
|
| - nelem = nelem * (obj->dim[dim_i].ubound + 1 - obj->dim[dim_i].lbound);
|
| + obj->ls[dim_i].idx = GFC_DESCRIPTOR_LBOUND(obj, dim_i);
|
| + nelem = nelem * GFC_DESCRIPTOR_EXTENT (obj, dim_i);
|
| }
|
|
|
| /* Main loop to output the data held in the object. */
|
| @@ -1484,9 +1715,9 @@ obj_loop:
|
| {
|
| obj->ls[dim_i].idx += nml_carry ;
|
| nml_carry = 0;
|
| - if (obj->ls[dim_i].idx > (index_type) obj->dim[dim_i].ubound)
|
| + if (obj->ls[dim_i].idx > (ssize_t) GFC_DESCRIPTOR_UBOUND(obj,dim_i))
|
| {
|
| - obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
|
| + obj->ls[dim_i].idx = GFC_DESCRIPTOR_LBOUND(obj,dim_i);
|
| nml_carry = 1;
|
| }
|
| }
|
|
|