aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorFrancois-Xavier Coudert <fxcoudert@gcc.gnu.org>2008-05-09 08:02:52 +0000
committerFrançois-Xavier Coudert <fxcoudert@gcc.gnu.org>2008-05-09 08:02:52 +0000
commit3ee6cb3f69311ba36ca1faf2a25bb536e0acc038 (patch)
treed21345dc9e4f8f7db29a2fdbef380d2d12b7f5fc /gcc/fortran
parentb70837af6043670029d43da7f795f0918f20a50a (diff)
downloadgcc-3ee6cb3f69311ba36ca1faf2a25bb536e0acc038.zip
gcc-3ee6cb3f69311ba36ca1faf2a25bb536e0acc038.tar.gz
gcc-3ee6cb3f69311ba36ca1faf2a25bb536e0acc038.tar.bz2
re PR fortran/36162 (Non-ASCII character in module string gives ICE)
PR fortran/36162 * module.c (quote_string, unquote_string, mio_allocated_wide_string): New functions. (mio_expr): Call mio_allocated_wide_string where needed. * gfortran.dg/module_widestring_1.f90: New test. From-SVN: r135109
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog7
-rw-r--r--gcc/fortran/module.c141
2 files changed, 139 insertions, 9 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 4906bbe..e93c004 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,10 @@
+2008-05-09 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/36162
+ * module.c (quote_string, unquote_string,
+ mio_allocated_wide_string): New functions.
+ (mio_expr): Call mio_allocated_wide_string where needed.
+
2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
* trans-decl.c (gfc_get_extern_function_decl, build_function_decl):
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 8d8b22a..2c3d88a 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -1474,6 +1474,130 @@ mio_allocated_string (const char *s)
}
+/* Functions for quoting and unquoting strings. */
+
+static char *
+quote_string (const gfc_char_t *s, const size_t slength)
+{
+ const gfc_char_t *p;
+ char *res, *q;
+ size_t len = 0, i;
+
+ /* Calculate the length we'll need: a backslash takes two ("\\"),
+ non-printable characters take 10 ("\Uxxxxxxxx") and others take 1. */
+ for (p = s, i = 0; i < slength; p++, i++)
+ {
+ if (*p == '\\')
+ len += 2;
+ else if (!gfc_wide_is_printable (*p))
+ len += 10;
+ else
+ len++;
+ }
+
+ q = res = gfc_getmem (len + 1);
+ for (p = s, i = 0; i < slength; p++, i++)
+ {
+ if (*p == '\\')
+ *q++ = '\\', *q++ = '\\';
+ else if (!gfc_wide_is_printable (*p))
+ {
+ sprintf (q, "\\U%08" HOST_WIDE_INT_PRINT "ux",
+ (unsigned HOST_WIDE_INT) *p);
+ q += 10;
+ }
+ else
+ *q++ = (unsigned char) *p;
+ }
+
+ res[len] = '\0';
+ return res;
+}
+
+static gfc_char_t *
+unquote_string (const char *s)
+{
+ size_t len, i;
+ const char *p;
+ gfc_char_t *res;
+
+ for (p = s, len = 0; *p; p++, len++)
+ {
+ if (*p != '\\')
+ continue;
+
+ if (p[1] == '\\')
+ p++;
+ else if (p[1] == 'U')
+ p += 9; /* That is a "\U????????". */
+ else
+ gfc_internal_error ("unquote_string(): got bad string");
+ }
+
+ res = gfc_get_wide_string (len + 1);
+ for (i = 0, p = s; i < len; i++, p++)
+ {
+ gcc_assert (*p);
+
+ if (*p != '\\')
+ res[i] = (unsigned char) *p;
+ else if (p[1] == '\\')
+ {
+ res[i] = (unsigned char) '\\';
+ p++;
+ }
+ else
+ {
+ /* We read the 8-digits hexadecimal constant that follows. */
+ int j;
+ unsigned n;
+ gfc_char_t c = 0;
+
+ gcc_assert (p[1] == 'U');
+ for (j = 0; j < 8; j++)
+ {
+ c = c << 4;
+ gcc_assert (sscanf (&p[j+2], "%01x", &n) == 1);
+ c += n;
+ }
+
+ res[i] = c;
+ p += 9;
+ }
+ }
+
+ res[len] = '\0';
+ return res;
+}
+
+
+/* Read or write a character pointer that points to a wide string on the
+ heap, performing quoting/unquoting of nonprintable characters using the
+ form \U???????? (where each ? is a hexadecimal digit).
+ Length is the length of the string, only known and used in output mode. */
+
+static const gfc_char_t *
+mio_allocated_wide_string (const gfc_char_t *s, const size_t length)
+{
+ if (iomode == IO_OUTPUT)
+ {
+ char *quoted = quote_string (s, length);
+ write_atom (ATOM_STRING, quoted);
+ gfc_free (quoted);
+ return s;
+ }
+ else
+ {
+ gfc_char_t *unquoted;
+
+ require_atom (ATOM_STRING);
+ unquoted = unquote_string (atom_string);
+ gfc_free (atom_string);
+ return unquoted;
+ }
+}
+
+
/* Read or write a string that is in static memory. */
static void
@@ -2708,7 +2832,6 @@ mio_expr (gfc_expr **ep)
{
gfc_expr *e;
atom_type t;
- char *s;
int flag;
mio_lparen ();
@@ -2833,10 +2956,10 @@ mio_expr (gfc_expr **ep)
break;
case EXPR_SUBSTRING:
- s = gfc_widechar_to_char (e->value.character.string, -1);
- s = CONST_CAST (char *, mio_allocated_string (s));
- e->value.character.string = gfc_char_to_widechar (s);
- gfc_free (s);
+ e->value.character.string
+ = CONST_CAST (gfc_char_t *,
+ mio_allocated_wide_string (e->value.character.string,
+ e->value.character.length));
mio_ref_list (&e->ref);
break;
@@ -2870,10 +2993,10 @@ mio_expr (gfc_expr **ep)
case BT_CHARACTER:
mio_integer (&e->value.character.length);
- s = gfc_widechar_to_char (e->value.character.string, -1);
- s = CONST_CAST (char *, mio_allocated_string (s));
- e->value.character.string = gfc_char_to_widechar (s);
- gfc_free (s);
+ e->value.character.string
+ = CONST_CAST (gfc_char_t *,
+ mio_allocated_wide_string (e->value.character.string,
+ e->value.character.length));
break;
default: