From 5cdc4b0ef0381439be6cebd6ba8925f69e4d51d6 Mon Sep 17 00:00:00 2001 From: Jerry DeLisle Date: Fri, 16 Dec 2016 20:27:51 +0000 Subject: re PR fortran/78662 ([F03] Incorrect parsing of quotes in the char-literal-constant of the DT data descriptor) 2016-12-16 Jerry DeLisle PR fortran/78622 * io.c (format_lex): Continue of string delimiter seen. * io/transfer.c (get_dt_format): New static function to alloc and set the DT iotype string, handling doubled quotes. (formatted_transfer_scalar_read, formatted_transfer_scalar_write): Use new function. * gfortran.dg/dtio_20.f03: New test. From-SVN: r243765 --- libgfortran/io/transfer.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) (limited to 'libgfortran/io') diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c index 5830362..c90e8c5 100644 --- a/libgfortran/io/transfer.c +++ b/libgfortran/io/transfer.c @@ -1264,6 +1264,33 @@ require_numeric_type (st_parameter_dt *dtp, bt actual, const fnode *f) return 1; } +static char * +get_dt_format (char *p, gfc_charlen_type *length) +{ + char delim = p[-1]; /* The delimiter is always the first character back. */ + char c, *q, *res; + gfc_charlen_type len = *length; /* This length already correct, less 'DT'. */ + + res = q = xmalloc (len + 2); + + /* Set the beginning of the string to 'DT', length adjusted below. */ + *q++ = 'D'; + *q++ = 'T'; + + /* The string may contain doubled quotes so scan and skip as needed. */ + for (; len > 0; len--) + { + c = *q++ = *p++; + if (c == delim) + p++; /* Skip the doubled delimiter. */ + } + + /* Adjust the string length by two now that we are done. */ + *length += 2; + + return res; +} + /* This function is in the main loop for a formatted data transfer statement. It would be natural to implement this as a coroutine @@ -1420,7 +1447,7 @@ formatted_transfer_scalar_read (st_parameter_dt *dtp, bt type, void *p, int kind gfc_charlen_type child_iomsg_len; int noiostat; int *child_iostat = NULL; - char *iotype = f->u.udf.string; + char *iotype; gfc_charlen_type iotype_len = f->u.udf.string_len; /* Build the iotype string. */ @@ -1430,13 +1457,7 @@ formatted_transfer_scalar_read (st_parameter_dt *dtp, bt type, void *p, int kind iotype = dt; } else - { - iotype_len += 2; - iotype = xmalloc (iotype_len); - iotype[0] = dt[0]; - iotype[1] = dt[1]; - memcpy (iotype + 2, f->u.udf.string, f->u.udf.string_len); - } + iotype = get_dt_format (f->u.udf.string, &iotype_len); /* Set iostat, intent(out). */ noiostat = 0; @@ -1890,7 +1911,7 @@ formatted_transfer_scalar_write (st_parameter_dt *dtp, bt type, void *p, int kin gfc_charlen_type child_iomsg_len; int noiostat; int *child_iostat = NULL; - char *iotype = f->u.udf.string; + char *iotype; gfc_charlen_type iotype_len = f->u.udf.string_len; /* Build the iotype string. */ @@ -1900,13 +1921,7 @@ formatted_transfer_scalar_write (st_parameter_dt *dtp, bt type, void *p, int kin iotype = dt; } else - { - iotype_len += 2; - iotype = xmalloc (iotype_len); - iotype[0] = dt[0]; - iotype[1] = dt[1]; - memcpy (iotype + 2, f->u.udf.string, f->u.udf.string_len); - } + iotype = get_dt_format (f->u.udf.string, &iotype_len); /* Set iostat, intent(out). */ noiostat = 0; -- cgit v1.1