This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch, fortran] Wide character I/O Part 1


Hi all,

This patch implements wide character I/O with default encoding for list directed formatted and formatted I/O.

I have not developed too many test cases yet, so obviously all testing is encouraged.

I don't want to let the patch get too big so if I may, I would like to commit in parts. Part 2 will take care of anything remaining for unformatted wide char I/O and move on to ENCODING="UTF-8".

I have regression tested this on x86-64 and ppc64. The patch takes care of endianess.

OK for trunk?

Jerry

2008-05-28 Jerry DeLisle <jvdelisle@gcc.gnu.org>

	PR fortran/35863
	* trans-io.c (gfc_build_io_library_fndecls): Build declaration for
	transfer_character_wide which includes passing in the character kind to
	support wide character IO. (transfer_expr): If the kind == 4, create the
	argument and build the call.
	
	libfortran/
	* runtime/main.c: Fix error in comment.
	* gfortran.map: Add symbol for new _gfortran_transfer_character_wide.
	* io/io.h: Add prototype declarations for new functions.
	* io/read.c (read_a_char4): New function to handle formatted read.
	* io/write.c (write_a_char4): New fucntion to handle formatted write.
	(write_character): Modify to accept the kind parameter and adjust for
	endianess of the machine. (list_formatted_write): Calculate the stride
	resulting from the kind and adjust the list_formatted_write_scalar call
	accordingly. (nml_write_obj): Adjust calls to write_chracter.
	(namelist_write): Likewise.
	* io/transfer.c (formatted_transfer_scaler): Rename 'len' argument to
	'kind' argument to better describe what it is. Add calls to new
	functions for kind == 4. (formatted_transfer): Modify to handle the case
	of type character and kind equals 4 to pass in the kind to the transfer
	routines. (transfer_character_wide): Add this new fucntion.
	(transfer_array): Don't set kind to the character string length.
	
Index: gcc/fortran/trans-io.c
===================================================================
--- gcc/fortran/trans-io.c	(revision 136136)
+++ gcc/fortran/trans-io.c	(working copy)
@@ -121,6 +121,7 @@ enum iocall
   IOCALL_X_INTEGER,
   IOCALL_X_LOGICAL,
   IOCALL_X_CHARACTER,
+  IOCALL_X_CHARACTER_WIDE,
   IOCALL_X_REAL,
   IOCALL_X_COMPLEX,
   IOCALL_X_ARRAY,
@@ -327,6 +328,13 @@ gfc_build_io_library_fndecls (void)
 				     void_type_node, 3, dt_parm_type,
 				     pvoid_type_node, gfc_int4_type_node);
 
+  iocall[IOCALL_X_CHARACTER_WIDE] =
+    gfc_build_library_function_decl (get_identifier
+				     (PREFIX("transfer_character_wide")),
+				     void_type_node, 4, dt_parm_type,
+				     pvoid_type_node, gfc_int4_type_node,
+				     gfc_int4_type_node);
+
   iocall[IOCALL_X_REAL] =
     gfc_build_library_function_decl (get_identifier (PREFIX("transfer_real")),
 				     void_type_node, 3, dt_parm_type,
@@ -1977,7 +1985,7 @@ transfer_array_component (tree expr, gfc
 static void
 transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
 {
-  tree tmp, function, arg2, field, expr;
+  tree tmp, function, arg2, arg3, field, expr;
   gfc_component *c;
   int kind;
 
@@ -2009,6 +2017,7 @@ transfer_expr (gfc_se * se, gfc_typespec
   kind = ts->kind;
   function = NULL;
   arg2 = NULL;
+  arg3 = NULL;
 
   switch (ts->type)
     {
@@ -2033,6 +2042,25 @@ transfer_expr (gfc_se * se, gfc_typespec
       break;
 
     case BT_CHARACTER:
+      if (kind == 4)
+	{
+	  if (se->string_length)
+	    arg2 = se->string_length;
+	  else
+	    {
+	      tmp = build_fold_indirect_ref (addr_expr);
+	      gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
+	      arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
+	    }
+	  arg3 = build_int_cst (NULL_TREE, kind);
+	  function = iocall[IOCALL_X_CHARACTER_WIDE];
+	  tmp = build_fold_addr_expr (dt_parm);
+	  tmp = build_call_expr (function, 4, tmp, addr_expr, arg2, arg3);
+	  gfc_add_expr_to_block (&se->pre, tmp);
+	  gfc_add_block_to_block (&se->pre, &se->post);
+	  return;
+	}
+      /* Fall through. */
     case BT_HOLLERITH:
       if (se->string_length)
 	arg2 = se->string_length;
Index: libgfortran/runtime/main.c
===================================================================
--- libgfortran/runtime/main.c	(revision 136136)
+++ libgfortran/runtime/main.c	(working copy)
@@ -47,7 +47,7 @@ stupid_function_name_for_static_linking 
 
 /* This is the offset (in bytes) required to cast from logical(8)* to
    logical(4)*. and still get the same result.  Will be 0 for little-endian
-   machines and 4 for big-endian machines.  */
+   machines and 1 for big-endian machines.  */
 int l8_to_l4_offset = 0;
 
 
Index: libgfortran/gfortran.map
===================================================================
--- libgfortran/gfortran.map	(revision 136136)
+++ libgfortran/gfortran.map	(working copy)
@@ -1083,6 +1083,7 @@ GFORTRAN_1.1 {
     _gfortran_string_trim_char4;
     _gfortran_string_verify_char4;
     _gfortran_st_wait;
+    _gfortran_transfer_character_wide;
     _gfortran_transpose_char4;
     _gfortran_unpack0_char4;
     _gfortran_unpack1_char4;
Index: libgfortran/io/read.c
===================================================================
--- libgfortran/io/read.c	(revision 136136)
+++ libgfortran/io/read.c	(working copy)
@@ -270,6 +270,43 @@ read_a (st_parameter_dt *dtp, const fnod
     memset (p + m, ' ', n);
 }
 
+void
+read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, int length)
+{
+  const int endian_off = 3 * l8_to_l4_offset;
+  char *s, *dest;
+  int m, n, o, wi, status;
+  size_t w;
+
+  wi = f->u.w;
+  if (wi == -1) /* '(A)' edit descriptor  */
+    wi = length;
+
+  w = wi;
+
+  s = gfc_alloca (w);
+
+  /* Read in w bytes, treating comma as not a separator.  */
+  dtp->u.p.sf_read_comma = 0;
+  status = read_block_form (dtp, s, &w);
+  dtp->u.p.sf_read_comma =
+    dtp->u.p.decimal_status == DECIMAL_COMMA ? 0 : 1;
+  
+  if (status == FAILURE)
+    return;
+  if (w > (size_t) length)
+     s += (w - length);
+
+  m = ((int) w > length) ? length : (int) w;
+  
+  dest = p;
+  
+  for (n = 0; n < m; n++, dest += 4, s++)
+      dest[endian_off] = *s;
+
+  for (n = 0; n < length - (int) w; n++, dest++)
+      dest[endian_off] = ' ';
+}
 
 /* eat_leading_spaces()-- Given a character pointer and a width,
  * ignore the leading spaces.  */
Index: libgfortran/io/io.h
===================================================================
--- libgfortran/io/io.h	(revision 136136)
+++ libgfortran/io/io.h	(working copy)
@@ -869,6 +869,9 @@ internal_proto(convert_real);
 extern void read_a (st_parameter_dt *, const fnode *, char *, int);
 internal_proto(read_a);
 
+extern void read_a_char4 (st_parameter_dt *, const fnode *, char *, int);
+internal_proto(read_a);
+
 extern void read_f (st_parameter_dt *, const fnode *, char *, int);
 internal_proto(read_f);
 
@@ -904,6 +907,9 @@ internal_proto(namelist_write);
 extern void write_a (st_parameter_dt *, const fnode *, const char *, int);
 internal_proto(write_a);
 
+extern void write_a_char4 (st_parameter_dt *, const fnode *, const char *, int);
+internal_proto(write_a_char4);
+
 extern void write_b (st_parameter_dt *, const fnode *, const char *, int);
 internal_proto(write_b);
 
Index: libgfortran/io/transfer.c
===================================================================
--- libgfortran/io/transfer.c	(revision 136136)
+++ libgfortran/io/transfer.c	(working copy)
@@ -54,6 +54,7 @@ Boston, MA 02110-1301, USA.  */
       transfer_integer
       transfer_logical
       transfer_character
+      transfer_character_wide
       transfer_real
       transfer_complex
 
@@ -76,6 +77,9 @@ export_proto(transfer_logical);
 extern void transfer_character (st_parameter_dt *, void *, int);
 export_proto(transfer_character);
 
+extern void transfer_character_wide (st_parameter_dt *, void *, int, int);
+export_proto(transfer_character_wide);
+
 extern void transfer_complex (st_parameter_dt *, void *, int);
 export_proto(transfer_complex);
 
@@ -904,7 +908,7 @@ require_type (st_parameter_dt *dtp, bt e
    of the next element, then comes back here to process it.  */
 
 static void
-formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int len,
+formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
 			   size_t size)
 {
   char scratch[SCRATCH_SIZE];
@@ -1004,9 +1008,9 @@ formatted_transfer_scalar (st_parameter_
 	    return;
 
 	  if (dtp->u.p.mode == READING)
-	    read_decimal (dtp, f, p, len);
+	    read_decimal (dtp, f, p, kind);
 	  else
-	    write_i (dtp, f, p, len);
+	    write_i (dtp, f, p, kind);
 
 	  break;
 
@@ -1019,9 +1023,9 @@ formatted_transfer_scalar (st_parameter_
 	    return;
 
 	  if (dtp->u.p.mode == READING)
-	    read_radix (dtp, f, p, len, 2);
+	    read_radix (dtp, f, p, kind, 2);
 	  else
-	    write_b (dtp, f, p, len);
+	    write_b (dtp, f, p, kind);
 
 	  break;
 
@@ -1034,9 +1038,9 @@ formatted_transfer_scalar (st_parameter_
 	    return;
 
 	  if (dtp->u.p.mode == READING)
-	    read_radix (dtp, f, p, len, 8);
+	    read_radix (dtp, f, p, kind, 8);
 	  else
-	    write_o (dtp, f, p, len);
+	    write_o (dtp, f, p, kind);
 
 	  break;
 
@@ -1049,9 +1053,9 @@ formatted_transfer_scalar (st_parameter_
 	    return;
 
 	  if (dtp->u.p.mode == READING)
-	    read_radix (dtp, f, p, len, 16);
+	    read_radix (dtp, f, p, kind, 16);
 	  else
-	    write_z (dtp, f, p, len);
+	    write_z (dtp, f, p, kind);
 
 	  break;
 
@@ -1059,11 +1063,23 @@ formatted_transfer_scalar (st_parameter_
 	  if (n == 0)
 	    goto need_data;
 
-	  if (dtp->u.p.mode == READING)
-	    read_a (dtp, f, p, len);
+	  /* It is possible to have FMT_A with something not BT_CHARACTER such
+	     as when writing out hollerith strings, so check both type
+	     and kind before calling wide character routines.  */
+	  if (type == BT_CHARACTER && kind == 4)
+	    {
+	      if (dtp->u.p.mode == READING)
+		read_a_char4 (dtp, f, p, size);
+	      else
+		write_a_char4 (dtp, f, p, size);
+	    }
 	  else
-	    write_a (dtp, f, p, len);
-
+	    {
+	      if (dtp->u.p.mode == READING)
+		read_a (dtp, f, p, size);
+	      else
+		write_a (dtp, f, p, size);
+	    }
 	  break;
 
 	case FMT_L:
@@ -1071,9 +1087,9 @@ formatted_transfer_scalar (st_parameter_
 	    goto need_data;
 
 	  if (dtp->u.p.mode == READING)
-	    read_l (dtp, f, p, len);
+	    read_l (dtp, f, p, kind);
 	  else
-	    write_l (dtp, f, p, len);
+	    write_l (dtp, f, p, kind);
 
 	  break;
 
@@ -1084,9 +1100,9 @@ formatted_transfer_scalar (st_parameter_
 	    return;
 
 	  if (dtp->u.p.mode == READING)
-	    read_f (dtp, f, p, len);
+	    read_f (dtp, f, p, kind);
 	  else
-	    write_d (dtp, f, p, len);
+	    write_d (dtp, f, p, kind);
 
 	  break;
 
@@ -1097,9 +1113,9 @@ formatted_transfer_scalar (st_parameter_
 	    return;
 
 	  if (dtp->u.p.mode == READING)
-	    read_f (dtp, f, p, len);
+	    read_f (dtp, f, p, kind);
 	  else
-	    write_e (dtp, f, p, len);
+	    write_e (dtp, f, p, kind);
 	  break;
 
 	case FMT_EN:
@@ -1109,9 +1125,9 @@ formatted_transfer_scalar (st_parameter_
 	    return;
 
 	  if (dtp->u.p.mode == READING)
-	    read_f (dtp, f, p, len);
+	    read_f (dtp, f, p, kind);
 	  else
-	    write_en (dtp, f, p, len);
+	    write_en (dtp, f, p, kind);
 
 	  break;
 
@@ -1122,9 +1138,9 @@ formatted_transfer_scalar (st_parameter_
 	    return;
 
 	  if (dtp->u.p.mode == READING)
-	    read_f (dtp, f, p, len);
+	    read_f (dtp, f, p, kind);
 	  else
-	    write_es (dtp, f, p, len);
+	    write_es (dtp, f, p, kind);
 
 	  break;
 
@@ -1135,9 +1151,9 @@ formatted_transfer_scalar (st_parameter_
 	    return;
 
 	  if (dtp->u.p.mode == READING)
-	    read_f (dtp, f, p, len);
+	    read_f (dtp, f, p, kind);
 	  else
-	    write_f (dtp, f, p, len);
+	    write_f (dtp, f, p, kind);
 
 	  break;
 
@@ -1148,16 +1164,16 @@ formatted_transfer_scalar (st_parameter_
 	    switch (type)
 	      {
 	      case BT_INTEGER:
-		read_decimal (dtp, f, p, len);
+		read_decimal (dtp, f, p, kind);
 		break;
 	      case BT_LOGICAL:
-		read_l (dtp, f, p, len);
+		read_l (dtp, f, p, kind);
 		break;
 	      case BT_CHARACTER:
-		read_a (dtp, f, p, len);
+		read_a (dtp, f, p, kind);
 		break;
 	      case BT_REAL:
-		read_f (dtp, f, p, len);
+		read_f (dtp, f, p, kind);
 		break;
 	      default:
 		goto bad_type;
@@ -1166,16 +1182,16 @@ formatted_transfer_scalar (st_parameter_
 	    switch (type)
 	      {
 	      case BT_INTEGER:
-		write_i (dtp, f, p, len);
+		write_i (dtp, f, p, kind);
 		break;
 	      case BT_LOGICAL:
-		write_l (dtp, f, p, len);
+		write_l (dtp, f, p, kind);
 		break;
 	      case BT_CHARACTER:
-		write_a (dtp, f, p, len);
+		write_a (dtp, f, p, kind);
 		break;
 	      case BT_REAL:
-		write_d (dtp, f, p, len);
+		write_d (dtp, f, p, kind);
 		break;
 	      default:
 	      bad_type:
@@ -1406,10 +1422,23 @@ formatted_transfer (st_parameter_dt *dtp
   tmp = (char *) p;
 
   /* Big loop over all the elements.  */
-  for (elem = 0; elem < nelems; elem++)
+  if (type == BT_CHARACTER && kind == 4)
     {
-      dtp->u.p.item_count++;
-      formatted_transfer_scalar (dtp, type, tmp + size*elem, kind, size);
+      size_t stride;
+      stride = size * 4;
+      for (elem = 0; elem < nelems; elem++)
+	{
+	  dtp->u.p.item_count++;
+	  formatted_transfer_scalar (dtp, type, tmp + stride*elem, kind, size);
+	}
+    }
+  else
+    {
+      for (elem = 0; elem < nelems; elem++)
+	{
+	  dtp->u.p.item_count++;
+	  formatted_transfer_scalar (dtp, type, tmp + size*elem, kind, size);
+	}
     }
 }
 
@@ -1462,10 +1491,26 @@ transfer_character (st_parameter_dt *dtp
   if (len == 0 && p == NULL)
     p = empty_string;
 
-  /* Currently we support only 1 byte chars, and the library is a bit
-     confused of character kind vs. length, so we kludge it by setting
-     kind = length.  */
-  dtp->u.p.transfer (dtp, BT_CHARACTER, p, len, len, 1);
+  /* Set kind here to 1.  */
+  dtp->u.p.transfer (dtp, BT_CHARACTER, p, 1, len, 1);
+}
+
+void
+transfer_character_wide (st_parameter_dt *dtp, void *p, int len, int kind)
+{
+  static char *empty_string[0];
+
+  if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
+    return;
+
+  /* Strings of zero length can have p == NULL, which confuses the
+     transfer routines into thinking we need more data elements.  To avoid
+     this, we give them a nice pointer.  */
+  if (len == 0 && p == NULL)
+    p = empty_string;
+
+  /* Here we pass the actual kind value.  */
+  dtp->u.p.transfer (dtp, BT_CHARACTER, p, kind, len, 1);
 }
 
 
@@ -1525,7 +1570,6 @@ transfer_array (st_parameter_dt *dtp, gf
 	 non-8-bit charsets we need to fix dtype to contain
 	 sizeof(chartype) and fix the code below.  */
       size = charlen;
-      kind = charlen;
       break;
     case GFC_DTYPE_DERIVED:
       internal_error (&dtp->common,
Index: libgfortran/io/write.c
===================================================================
--- libgfortran/io/write.c	(revision 136136)
+++ libgfortran/io/write.c	(working copy)
@@ -122,6 +122,99 @@ write_a (st_parameter_dt *dtp, const fno
 #endif
 }
 
+
+/* The primary difference between write_a_char4 and write_a is that we have to
+   deal with writing from the first byte of the 4-byte character and take care
+   of endianess.  This currently implements encoding="default" which means we
+   ignore the upper 3 bytes of the character.  TODO: Implement encoding="UTF-8"
+   which will process all 4 bytes and translate to the encoded output.  */
+void
+write_a_char4 (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
+{
+  const int endian_off = 3 * l8_to_l4_offset;
+  int k, wlen;
+  char *p;
+
+  wlen = f->u.string.length < 0 ? len : f->u.string.length;
+
+#ifdef HAVE_CRLF
+  /* If this is formatted STREAM IO convert any embedded line feed characters
+     to CR_LF on systems that use that sequence for newlines.  See F2003
+     Standard sections 10.6.3 and 9.9 for further information.  */
+  if (is_stream_io (dtp))
+    {
+      const char crlf[] = "\r\n";
+      int i, j, kk, bytes;
+      q = bytes = 0;
+
+      /* Write out any padding if needed.  */
+      if (len < wlen)
+	{
+	  p = write_block (dtp, wlen - len);
+	  if (p == NULL)
+	    return;
+	  memset (p, ' ', wlen - len);
+	}
+
+      /* Scan the source string looking for '\n' and convert it if found.  */
+      for (i = kk = 0; i < wlen; i++, kk += 4)
+	{
+	  if (source[kk + endian_off] == '\n')
+	    {
+	      /* Write out the previously scanned characters in the string.  */
+	      if (bytes > 0)
+		{
+		  p = write_block (dtp, bytes);
+		  if (p == NULL)
+		    return;
+		  for (j = k = 0; j < bytes; j++, k += 4)
+		    p[j] = source[k + endian_off];
+		  bytes = 0;
+		}
+
+	      /* Write out the CR_LF sequence.  */ 
+	      p = write_block (dtp, 2);
+              if (p == NULL)
+                return;
+	      memcpy (p, crlf, 2);
+	    }
+	  else
+	    bytes++;
+	}
+
+      /*  Write out any remaining bytes if no LF was found.  */
+      if (bytes > 0)
+	{
+	  p = write_block (dtp, bytes);
+	  if (p == NULL)
+	    return;
+	  for (j = k =0; j < bytes; j++, k += 4)
+	    p[j] = source[k + endian_off];
+	}
+    }
+  else
+    {
+#endif
+      int j;
+      p = write_block (dtp, wlen);
+      if (p == NULL)
+	return;
+
+      if (wlen < len)
+	for (j = k = 0; j < wlen; j++, k += 4)
+	  p[j] = source[k + endian_off];
+      else
+	{
+	  memset (p, ' ', wlen - len);
+	  for (j = k = wlen - len; j < wlen; j++, k += 4)
+	    p[j] = source[k + endian_off];
+	}
+#ifdef HAVE_CRLF
+    }
+#endif
+}
+
+
 static GFC_INTEGER_LARGEST
 extract_int (const void *p, int len)
 {
@@ -635,9 +728,9 @@ write_integer (st_parameter_dt *dtp, con
    the strings if the file has been opened in that mode.  */
 
 static void
-write_character (st_parameter_dt *dtp, const char *source, int length)
+write_character (st_parameter_dt *dtp, const char *source, int kind, int length)
 {
-  int i, extra;
+  int i, endian_off, extra;
   char *p, d;
 
   switch (dtp->u.p.delim_status)
@@ -653,6 +746,11 @@ write_character (st_parameter_dt *dtp, c
       break;
     }
 
+  if (kind == 4)
+    endian_off = 3 * l8_to_l4_offset;
+  else
+    endian_off = 0;
+
   if (d == ' ')
     extra = 0;
   else
@@ -660,7 +758,7 @@ write_character (st_parameter_dt *dtp, c
       extra = 2;
 
       for (i = 0; i < length; i++)
-	if (source[i] == d)
+	if (source[i * kind + endian_off] == d)
 	  extra++;
     }
 
@@ -669,15 +767,19 @@ write_character (st_parameter_dt *dtp, c
     return;
 
   if (d == ' ')
-    memcpy (p, source, length);
+    for (i = 0; i < length; i++)
+      p[i] = (unsigned int) source[i * kind] > 255 ?
+	     '?' : source[i * kind + endian_off];
   else
     {
       *p++ = d;
 
       for (i = 0; i < length; i++)
 	{
-	  *p++ = source[i];
-	  if (source[i] == d)
+	  *p++ = (unsigned int) source[i * kind] > 255 ?
+		 '?' : source[i * kind + endian_off];
+	  if ((unsigned int) source[i * kind] <= 255
+	      && source[i * kind + endian_off] == d)
 	    *p++ = d;
 	}
 
@@ -792,7 +894,7 @@ list_formatted_write_scalar (st_paramete
       write_logical (dtp, p, kind);
       break;
     case BT_CHARACTER:
-      write_character (dtp, p, kind);
+      write_character (dtp, p, kind, size);
       break;
     case BT_REAL:
       write_real (dtp, p, kind);
@@ -812,16 +914,20 @@ void
 list_formatted_write (st_parameter_dt *dtp, bt type, void *p, int kind,
 		      size_t size, size_t nelems)
 {
-  size_t elem;
+  size_t elem, stride;
   char *tmp;
 
   tmp = (char *) p;
+  if (type == BT_CHARACTER)
+    stride = kind * size;
+  else
+    stride = size;
 
   /* Big loop over all the elements.  */
   for (elem = 0; elem < nelems; elem++)
     {
       dtp->u.p.item_count++;
-      list_formatted_write_scalar (dtp, type, tmp + size*elem, kind, size);
+      list_formatted_write_scalar (dtp, type, tmp + elem * stride, kind, size);
     }
 }
 
@@ -885,9 +991,9 @@ nml_write_obj (st_parameter_dt *dtp, nam
   if (obj->type != GFC_DTYPE_DERIVED)
     {
 #ifdef HAVE_CRLF
-      write_character (dtp, "\r\n ", 3);
+      write_character (dtp, "\r\n ", 1, 3);
 #else
-      write_character (dtp, "\n ", 2);
+      write_character (dtp, "\n ", 1, 2);
 #endif
       len = 0;
       if (base)
@@ -896,15 +1002,15 @@ nml_write_obj (st_parameter_dt *dtp, nam
 	  for (dim_i = 0; dim_i < (index_type) strlen (base_name); dim_i++)
             {
 	      cup = toupper (base_name[dim_i]);
-	      write_character (dtp, &cup, 1);
+	      write_character (dtp, &cup, 1, 1);
             }
 	}
       for (dim_i =len; dim_i < (index_type) strlen (obj->var_name); dim_i++)
 	{
 	  cup = toupper (obj->var_name[dim_i]);
-	  write_character (dtp, &cup, 1);
+	  write_character (dtp, &cup, 1, 1);
 	}
-      write_character (dtp, "=", 1);
+      write_character (dtp, "=", 1, 1);
     }
 
   /* Counts the number of data output on a line, including names.  */
@@ -974,7 +1080,7 @@ nml_write_obj (st_parameter_dt *dtp, nam
 	  if (rep_ctr > 1)
 	    {
 	      sprintf(rep_buff, " %d*", rep_ctr);
-	      write_character (dtp, rep_buff, strlen (rep_buff));
+	      write_character (dtp, rep_buff, 1, strlen (rep_buff));
 	      dtp->u.p.no_leading_blank = 1;
 	    }
 	  num++;
@@ -999,7 +1105,7 @@ nml_write_obj (st_parameter_dt *dtp, nam
 		dtp->u.p.delim_status = DELIM_QUOTE;
 	      if (dtp->u.p.nml_delim == '\'')
 		dtp->u.p.delim_status = DELIM_APOSTROPHE;
-	      write_character (dtp, p, obj->string_length);
+	      write_character (dtp, p, 1, obj->string_length);
 	      dtp->u.p.delim_status = tmp_delim;
               break;
 
@@ -1089,14 +1195,14 @@ nml_write_obj (st_parameter_dt *dtp, nam
 	     to column 2. Reset the repeat counter.  */
 
 	  dtp->u.p.no_leading_blank = 0;
-	  write_character (dtp, &semi_comma, 1);
+	  write_character (dtp, &semi_comma, 1, 1);
 	  if (num > 5)
 	    {
 	      num = 0;
 #ifdef HAVE_CRLF
-	      write_character (dtp, "\r\n ", 3);
+	      write_character (dtp, "\r\n ", 1, 3);
 #else
-	      write_character (dtp, "\n ", 2);
+	      write_character (dtp, "\n ", 1, 2);
 #endif
 	    }
 	  rep_ctr = 1;
@@ -1160,13 +1266,13 @@ namelist_write (st_parameter_dt *dtp)
   /* Temporarily disable namelist delimters.  */
   dtp->u.p.delim_status = DELIM_NONE;
 
-  write_character (dtp, "&", 1);
+  write_character (dtp, "&", 1, 1);
 
   /* Write namelist name in upper case - f95 std.  */
   for (i = 0 ;i < dtp->namelist_name_len ;i++ )
     {
       c = toupper (dtp->namelist_name[i]);
-      write_character (dtp, &c ,1);
+      write_character (dtp, &c, 1 ,1);
     }
 
   if (dtp->u.p.ionml != NULL)
@@ -1180,9 +1286,9 @@ namelist_write (st_parameter_dt *dtp)
     }
 
 #ifdef HAVE_CRLF
-  write_character (dtp, "  /\r\n", 5);
+  write_character (dtp, "  /\r\n", 1, 5);
 #else
-  write_character (dtp, "  /\n", 4);
+  write_character (dtp, "  /\n", 1, 4);
 #endif
 
   /* Restore the original delimiter.  */
! { dg-do run }
! Wide chracter I/O test 1
! Test case developed by Jerry DeLisle <jvdelisle@gcc.gnu.org>
program test1
  integer, parameter :: k4 = 4
  character(len=10,kind=4) :: wide
  character(len=10,kind=1) :: thin
  character(kind=1,len=25) :: buffer
  wide=k4_"Goodbye!"
  thin="Hello!"
  write(buffer, '(a)') wide
  if (buffer /= "Goodbye!") call abort
  open(10, form="formatted", access="stream")
  write(10, '(a)') thin
  rewind(10)
  read(10, '(a)') wide
  if (wide /= k4_"Hello!") call abort
  write(buffer,*) thin, ">",wide,"<"
  if (buffer /= " Hello!    >Hello!    <") call abort
end program test1
! { dg-do run }
! Wide chracter I/O test 2
! Test case developed by Jerry DeLisle <jvdelisle@gcc.gnu.org>
program chkdata
    integer, parameter :: k4=4
    character(len=7, kind=k4), dimension(3) :: mychar
    character(50) :: buffer
    mychar(1) = k4_"abc1234"
    mychar(2) = k4_"def5678"
    mychar(3) = k4_"ghi9012"
    buffer = ""
    write(buffer,'(3(a))') mychar(2:3), mychar(1)
    if (buffer /= "def5678ghi9012abc1234") call abort
    write(buffer, '(3(a))') mychar
    if (buffer /= "abc1234def5678ghi9012") call abort
end program chkdata

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]