summaryrefslogtreecommitdiff
path: root/libgfortran/io/write.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgfortran/io/write.c')
-rw-r--r--libgfortran/io/write.c252
1 files changed, 227 insertions, 25 deletions
diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c
index ee2ce0c3915..775425d6d77 100644
--- a/libgfortran/io/write.c
+++ b/libgfortran/io/write.c
@@ -36,10 +36,32 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <errno.h>
#define star_fill(p, n) memset(p, '*', n)
-#include "write_float.def"
-
typedef unsigned char uchar;
+/* Helper functions for character(kind=4) internal units. These are needed
+ by write_float.def. */
+
+static inline void
+memset4 (gfc_char4_t *p, gfc_char4_t c, int k)
+{
+ int j;
+ for (j = 0; j < k; j++)
+ *p++ = c;
+}
+
+static inline void
+memcpy4 (gfc_char4_t *dest, const char *source, int k)
+{
+ int j;
+
+ const char *p = source;
+ for (j = 0; j < k; j++)
+ *dest++ = (gfc_char4_t) *p++;
+}
+
+/* This include contains the heart and soul of formatted floating point. */
+#include "write_float.def"
+
/* Write out default char4. */
static void
@@ -58,7 +80,13 @@ write_default_char4 (st_parameter_dt *dtp, gfc_char4_t *source,
p = write_block (dtp, k);
if (p == NULL)
return;
- memset (p, ' ', k);
+ if (is_char4_unit (dtp))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ memset4 (p4, ' ', k);
+ }
+ else
+ memset (p, ' ', k);
}
/* Get ready to handle delimiters if needed. */
@@ -76,25 +104,48 @@ write_default_char4 (st_parameter_dt *dtp, gfc_char4_t *source,
}
/* Now process the remaining characters, one at a time. */
- for (j = k; j < src_len; j++)
+ for (j = 0; j < src_len; j++)
{
c = source[j];
-
- /* Handle delimiters if any. */
- if (c == d && d != ' ')
+ if (is_char4_unit (dtp))
{
- p = write_block (dtp, 2);
- if (p == NULL)
- return;
- *p++ = (uchar) c;
+ gfc_char4_t *q;
+ /* Handle delimiters if any. */
+ if (c == d && d != ' ')
+ {
+ p = write_block (dtp, 2);
+ if (p == NULL)
+ return;
+ q = (gfc_char4_t *) p;
+ *q++ = c;
+ }
+ else
+ {
+ p = write_block (dtp, 1);
+ if (p == NULL)
+ return;
+ q = (gfc_char4_t *) p;
+ }
+ *q = c;
}
else
{
- p = write_block (dtp, 1);
- if (p == NULL)
- return;
+ /* Handle delimiters if any. */
+ if (c == d && d != ' ')
+ {
+ p = write_block (dtp, 2);
+ if (p == NULL)
+ return;
+ *p++ = (uchar) c;
+ }
+ else
+ {
+ p = write_block (dtp, 1);
+ if (p == NULL)
+ return;
+ }
+ *p = c > 255 ? '?' : (uchar) c;
}
- *p = c > 255 ? '?' : (uchar) c;
}
}
@@ -258,6 +309,19 @@ write_a (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
if (p == NULL)
return;
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ if (wlen < len)
+ memcpy4 (p4, source, wlen);
+ else
+ {
+ memset4 (p4, ' ', wlen - len);
+ memcpy4 (p4 + wlen - len, source, len);
+ }
+ return;
+ }
+
if (wlen < len)
memcpy (p, source, wlen);
else
@@ -478,8 +542,17 @@ write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
if (p == NULL)
return;
- memset (p, ' ', wlen - 1);
n = extract_int (source, len);
+
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ memset4 (p4, ' ', wlen -1);
+ p4[wlen - 1] = (n) ? 'T' : 'F';
+ return;
+ }
+
+ memset (p, ' ', wlen -1);
p[wlen - 1] = (n) ? 'T' : 'F';
}
@@ -503,8 +576,13 @@ write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n)
p = write_block (dtp, w);
if (p == NULL)
return;
-
- memset (p, ' ', w);
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ memset4 (p4, ' ', w);
+ }
+ else
+ memset (p, ' ', w);
goto done;
}
@@ -528,6 +606,35 @@ write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n)
nblank = w - (nzero + digits);
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ if (nblank < 0)
+ {
+ memset4 (p4, '*', w);
+ return;
+ }
+
+ if (!dtp->u.p.no_leading_blank)
+ {
+ memset4 (p4, ' ', nblank);
+ q += nblank;
+ memset4 (p4, '0', nzero);
+ q += nzero;
+ memcpy4 (p4, q, digits);
+ }
+ else
+ {
+ memset4 (p4, '0', nzero);
+ q += nzero;
+ memcpy4 (p4, q, digits);
+ q += digits;
+ memset4 (p4, ' ', nblank);
+ dtp->u.p.no_leading_blank = 0;
+ }
+ return;
+ }
+
if (nblank < 0)
{
star_fill (p, w);
@@ -582,8 +689,13 @@ write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
p = write_block (dtp, w);
if (p == NULL)
return;
-
- memset (p, ' ', w);
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ memset4 (p4, ' ', w);
+ }
+ else
+ memset (p, ' ', w);
goto done;
}
@@ -621,6 +733,37 @@ write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
nblank = w - (nsign + nzero + digits);
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t * p4 = (gfc_char4_t *) p;
+ if (nblank < 0)
+ {
+ memset4 (p4, '*', w);
+ goto done;
+ }
+
+ memset4 (p4, ' ', nblank);
+ p4 += nblank;
+
+ switch (sign)
+ {
+ case S_PLUS:
+ *p4++ = '+';
+ break;
+ case S_MINUS:
+ *p4++ = '-';
+ break;
+ case S_NONE:
+ break;
+ }
+
+ memset4 (p4, '0', nzero);
+ p4 += nzero;
+
+ memcpy4 (p4, q, digits);
+ return;
+ }
+
if (nblank < 0)
{
star_fill (p, w);
@@ -1055,7 +1198,15 @@ write_x (st_parameter_dt *dtp, int len, int nspaces)
if (p == NULL)
return;
if (nspaces > 0 && len - nspaces >= 0)
- memset (&p[len - nspaces], ' ', nspaces);
+ {
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ memset4 (&p4[len - nspaces], ' ', nspaces);
+ }
+ else
+ memset (&p[len - nspaces], ' ', nspaces);
+ }
}
@@ -1066,15 +1217,21 @@ write_x (st_parameter_dt *dtp, int len, int nspaces)
something goes wrong. */
static int
-write_char (st_parameter_dt *dtp, char c)
+write_char (st_parameter_dt *dtp, int c)
{
char *p;
p = write_block (dtp, 1);
if (p == NULL)
return 1;
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ *p4 = c;
+ return 0;
+ }
- *p = c;
+ *p = (uchar) c;
return 0;
}
@@ -1132,6 +1289,23 @@ write_integer (st_parameter_dt *dtp, const char *source, int length)
p = write_block (dtp, width);
if (p == NULL)
return;
+
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ if (dtp->u.p.no_leading_blank)
+ {
+ memcpy4 (p4, q, digits);
+ memset4 (p4 + digits, ' ', width - digits);
+ }
+ else
+ {
+ memset4 (p4, ' ', width - digits);
+ memcpy4 (p4 + width - digits, q, digits);
+ }
+ return;
+ }
+
if (dtp->u.p.no_leading_blank)
{
memcpy (p, q, digits);
@@ -1184,6 +1358,29 @@ write_character (st_parameter_dt *dtp, const char *source, int kind, int length)
if (p == NULL)
return;
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t d4 = (gfc_char4_t) d;
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+
+ if (d4 == ' ')
+ memcpy4 (p4, source, length);
+ else
+ {
+ *p4++ = d4;
+
+ for (i = 0; i < length; i++)
+ {
+ *p4++ = (gfc_char4_t) source[i];
+ if (source[i] == d)
+ *p4++ = d4;
+ }
+
+ *p4 = d4;
+ }
+ return;
+ }
+
if (d == ' ')
memcpy (p, source, length);
else
@@ -1316,8 +1513,13 @@ write_separator (st_parameter_dt *dtp)
p = write_block (dtp, options.separator_len);
if (p == NULL)
return;
-
- memcpy (p, options.separator, options.separator_len);
+ if (unlikely (is_char4_unit (dtp)))
+ {
+ gfc_char4_t *p4 = (gfc_char4_t *) p;
+ memcpy4 (p4, options.separator, options.separator_len);
+ }
+ else
+ memcpy (p, options.separator, options.separator_len);
}