This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran 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, libgfortran] PR24224 Generalized internal array IO notimplemented.


The attached patch fixes this PR. One new test case provided, revised test case arrayio_4.f90 to reflect the new behavior.

regtested on i686.

RFC I have a common block of code in next_record_r and next_record_w that could be placed in its own function and called. It traverses the elements in the array based on the array descriptor, taking into account for strides.

I will prepare a gomp version of this after commit to mainline.

OK for mainline?

We never committed the original patch to 4.0 is this OK for 4.0.3 also?
If so, I will have to back port at least one other previous patch to 4.0 for this to work.


Comments much appreciated.

2005-10-15 Jerry DeLisle <jvdelisle@verizon.net>

        PR libgfortran/24224
        * libgfortran.h: Remove array stride error code.
        * runtime/error.c: Remove array stride error.
        * io/io.h: Change name of 'nml_loop_spec' to 'array_loop_spec' to be
          generic.  Add pointer to array_loop_spec to gfc_unit structure.
        * io/list_read.c: Revise nml_loop_spec references to array_loop_spec.
        * io/transfer.c (next_record_r): Add array looping code.
          (next_record_w): Add array looping code.
          (finalize_transfer): Free memory allocated for array_loop_spec.
        * io/unit.c (get_array_unit_len) Add initialization of array_loop_spec.

Regards,

Jerry
Index: libgfortran.h
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/libgfortran.h,v
retrieving revision 1.38
diff -c -3 -p -r1.38 libgfortran.h
*** libgfortran.h	12 Oct 2005 20:21:31 -0000	1.38
--- libgfortran.h	15 Oct 2005 23:27:48 -0000
*************** typedef enum
*** 392,398 ****
    ERROR_BAD_US,
    ERROR_READ_VALUE,
    ERROR_READ_OVERFLOW,
-   ERROR_ARRAY_STRIDE,
    ERROR_LAST			/* Not a real error, the last error # + 1.  */
  }
  error_codes;
--- 392,397 ----
Index: io/io.h
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/io.h,v
retrieving revision 1.33
diff -c -3 -p -r1.33 io.h
*** io/io.h	7 Oct 2005 20:02:28 -0000	1.33
--- io/io.h	15 Oct 2005 23:27:48 -0000
*************** stream;
*** 78,103 ****
  #define sread(s, buf, nbytes) ((s)->read)(s, buf, nbytes)
  #define swrite(s, buf, nbytes) ((s)->write)(s, buf, nbytes)
  
! /* Representation of a namelist object in libgfortran
! 
!    Namelist Records
!       &GROUPNAME  OBJECT=value[s] [,OBJECT=value[s]].../
!      or
!       &GROUPNAME  OBJECT=value[s] [,OBJECT=value[s]]...&END
! 
!    The object can be a fully qualified, compound name for an instrinsic
!    type, derived types or derived type components.  So, a substring
!    a(:)%b(4)%ch(2:4)(1:7) has to be treated correctly in namelist
!    read. Hence full information about the structure of the object has
!    to be available to list_read.c and write.
! 
!    These requirements are met by the following data structures.
! 
!    nml_loop_spec contains the variables for the loops over index ranges
     that are encountered.  Since the variables can be negative, ssize_t
     is used.  */
  
! typedef struct nml_loop_spec
  {
  
    /* Index counter for this dimension.  */
--- 78,88 ----
  #define sread(s, buf, nbytes) ((s)->read)(s, buf, nbytes)
  #define swrite(s, buf, nbytes) ((s)->write)(s, buf, nbytes)
  
! /* The array_loop_spec contains the variables for the loops over index ranges
     that are encountered.  Since the variables can be negative, ssize_t
     is used.  */
  
! typedef struct array_loop_spec
  {
  
    /* Index counter for this dimension.  */
*************** typedef struct nml_loop_spec
*** 112,121 ****
    /* Step for the index counter.  */
    ssize_t step;
  }
! nml_loop_spec;
  
! /* namelist_info type contains all the scalar information about the
!    object and arrays of descriptor_dimension and nml_loop_spec types for
     arrays.  */
  
  typedef struct namelist_type
--- 97,121 ----
    /* Step for the index counter.  */
    ssize_t step;
  }
! array_loop_spec;
! 
! /* Representation of a namelist object in libgfortran
! 
!    Namelist Records
!       &GROUPNAME  OBJECT=value[s] [,OBJECT=value[s]].../
!      or
!       &GROUPNAME  OBJECT=value[s] [,OBJECT=value[s]]...&END
! 
!    The object can be a fully qualified, compound name for an instrinsic
!    type, derived types or derived type components.  So, a substring
!    a(:)%b(4)%ch(2:4)(1:7) has to be treated correctly in namelist
!    read. Hence full information about the structure of the object has
!    to be available to list_read.c and write.
! 
!    These requirements are met by the following data structures.
  
!    namelist_info type contains all the scalar information about the
!    object and arrays of descriptor_dimension and array_loop_spec types for
     arrays.  */
  
  typedef struct namelist_type
*************** typedef struct namelist_type
*** 146,152 ****
    index_type string_length;
  
    descriptor_dimension * dim;
!   nml_loop_spec * ls;
    struct namelist_type * next;
  }
  namelist_info;
--- 146,152 ----
    index_type string_length;
  
    descriptor_dimension * dim;
!   array_loop_spec * ls;
    struct namelist_type * next;
  }
  namelist_info;
*************** typedef struct gfc_unit
*** 326,331 ****
--- 326,332 ----
       maxrec         -- Maximum record number in a direct access file
       bytes_left     -- Bytes left in current record.  */
  
+   array_loop_spec *ls;  /* For traversing arrays */
    int file_len;
    char file[1];	      /* Filename is allocated at the end of the structure.  */
  }
Index: io/list_read.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/list_read.c,v
retrieving revision 1.28
diff -c -3 -p -r1.28 list_read.c
*** io/list_read.c	26 Sep 2005 20:24:44 -0000	1.28
--- io/list_read.c	15 Oct 2005 23:27:49 -0000
*************** calls:
*** 1469,1475 ****
        static void nml_untouch_nodes (void)
        static namelist_info * find_nml_node (char * var_name)
        static int nml_parse_qualifier(descriptor_dimension * ad,
! 				     nml_loop_spec * ls, int rank)
        static void nml_touch_nodes (namelist_info * nl)
        static int nml_read_obj (namelist_info * nl, index_type offset)
  calls:
--- 1469,1475 ----
        static void nml_untouch_nodes (void)
        static namelist_info * find_nml_node (char * var_name)
        static int nml_parse_qualifier(descriptor_dimension * ad,
! 				     array_loop_spec * ls, int rank)
        static void nml_touch_nodes (namelist_info * nl)
        static int nml_read_obj (namelist_info * nl, index_type offset)
  calls:
*************** static index_type chigh;
*** 1500,1506 ****
  
  static try
  nml_parse_qualifier(descriptor_dimension * ad,
! 		    nml_loop_spec * ls, int rank)
  {
    int dim;
    int indx;
--- 1500,1506 ----
  
  static try
  nml_parse_qualifier(descriptor_dimension * ad,
! 		    array_loop_spec * ls, int rank)
  {
    int dim;
    int indx;
*************** get_name:
*** 2222,2228 ****
    if (c == '(' && nl->type == GFC_DTYPE_CHARACTER)
      {
        descriptor_dimension chd[1] = { {1, clow, nl->string_length} };
!       nml_loop_spec ind[1] = { {1, clow, nl->string_length, 1} };
  
        if (nml_parse_qualifier (chd, ind, 1) == FAILURE)
  	{
--- 2222,2228 ----
    if (c == '(' && nl->type == GFC_DTYPE_CHARACTER)
      {
        descriptor_dimension chd[1] = { {1, clow, nl->string_length} };
!       array_loop_spec ind[1] = { {1, clow, nl->string_length, 1} };
  
        if (nml_parse_qualifier (chd, ind, 1) == FAILURE)
  	{
Index: io/transfer.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/transfer.c,v
retrieving revision 1.63
diff -c -3 -p -r1.63 transfer.c
*** io/transfer.c	7 Oct 2005 20:02:28 -0000	1.63
--- io/transfer.c	15 Oct 2005 23:27:50 -0000
*************** data_transfer_init (int read_flag)
*** 1460,1467 ****
  static void
  next_record_r (void)
  {
!   int rlength, length, bytes_left;
    gfc_offset new;
    char *p;
  
    switch (current_mode ())
--- 1460,1468 ----
  static void
  next_record_r (void)
  {
!   int i, bytes_left, rlength, length, record, carry, rank;
    gfc_offset new;
+   array_loop_spec *ls;
    char *p;
  
    switch (current_mode ())
*************** next_record_r (void)
*** 1516,1526 ****
  
        if (is_internal_unit())
  	{
! 	  bytes_left = (int) current_unit->bytes_left;
! 	  p = salloc_r (current_unit->s, &bytes_left);
! 	  if (p != NULL)
  	    current_unit->bytes_left = current_unit->recl;
! 	  break;
  	}
        else do
  	{
--- 1517,1565 ----
  
        if (is_internal_unit())
  	{
! 	  if (is_array_io())
! 	  {
!             /* Determine where the next record in the array is by moving 
!                through the loop specification. */
!                  
!             carry = 1;
!             record = 0;
!             rank = GFC_DESCRIPTOR_RANK(ioparm.internal_unit_desc);
!             ls = current_unit->ls;
!             for (i = 0; i < rank; i++)
!               {
!                 if (carry)
!                   {
!                     ls[i].idx++;
!                     if (ls[i].idx > ls[i].end)
!                       {
!                         ls[i].idx = ls[i].start;
!                         carry = 1;
!                       }
!                     else
!                       carry = 0;
!                   }
!                 record = record + (ls[i].idx - 1) * ls[i].step;
!               }
!                  
!             /* Now seek to this record */
!             record = record * current_unit->recl;
!   
!             if (sseek (current_unit->s, record) == FAILURE)
!               {
!                 generate_error (ERROR_OS, NULL);
!                 break;
!               }
  	    current_unit->bytes_left = current_unit->recl;
!           }
!         else  
!           {
! 	    bytes_left = (int) current_unit->bytes_left;
! 	    p = salloc_r (current_unit->s, &bytes_left);
! 	    if (p != NULL)
! 	      current_unit->bytes_left = current_unit->recl;
! 	  } 
! 	break;
  	}
        else do
  	{
*************** static void
*** 1554,1560 ****
  next_record_w (void)
  {
    gfc_offset c, m;
!   int length, bytes_left;
    char *p;
  
    /* Zero counters for X- and T-editing.  */
--- 1593,1601 ----
  next_record_w (void)
  {
    gfc_offset c, m;
!   int bytes_left, carry, i, length, rank;
!   gfc_offset record;
!   array_loop_spec *ls;
    char *p;
  
    /* Zero counters for X- and T-editing.  */
*************** next_record_w (void)
*** 1633,1638 ****
--- 1674,1710 ----
  		  return;
  		}
                memset(p, ' ', bytes_left);
+               
+               /* Now that the current record has been padded out,
+                  determine where the next record in the array is by moving 
+                  through the loop specification. */
+                  
+               carry = 1;
+               record = 0;
+               rank = GFC_DESCRIPTOR_RANK(ioparm.internal_unit_desc);
+               ls = current_unit->ls;
+               for (i = 0; i < rank; i++)
+                 {
+                   if (carry)
+                     {
+                       ls[i].idx++;
+                       if (ls[i].idx > ls[i].end)
+                         {
+                           ls[i].idx = ls[i].start;
+                           carry = 1;
+                         }
+                       else
+                         carry = 0;
+                     }
+                   record = record + (ls[i].idx - 1) * ls[i].step;
+                 }
+                
+               /* Now seek to this record */
+               record = record * current_unit->recl;
+               
+               if (sseek (current_unit->s, record) == FAILURE)
+                 goto io_error;
+                 
                current_unit->bytes_left = current_unit->recl;
  	    }
  	  else
*************** finalize_transfer (void)
*** 1766,1772 ****
    sfree (current_unit->s);
  
    if (is_internal_unit ())
!     sclose (current_unit->s);
  }
  
  
--- 1838,1848 ----
    sfree (current_unit->s);
  
    if (is_internal_unit ())
!     {
!       if (current_unit->ls != NULL)
!         free_mem (current_unit->ls);
!       sclose (current_unit->s);
!     }
  }
  
  
*************** st_set_nml_var (void * var_addr, char * 
*** 1957,1964 ****
      {
        nml->dim = (descriptor_dimension*)
  		   get_mem (nml->var_rank * sizeof (descriptor_dimension));
!       nml->ls = (nml_loop_spec*)
! 		  get_mem (nml->var_rank * sizeof (nml_loop_spec));
      }
    else
      {
--- 2033,2040 ----
      {
        nml->dim = (descriptor_dimension*)
  		   get_mem (nml->var_rank * sizeof (descriptor_dimension));
!       nml->ls = (array_loop_spec*)
! 		  get_mem (nml->var_rank * sizeof (array_loop_spec));
      }
    else
      {
Index: io/unit.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/unit.c,v
retrieving revision 1.16
diff -c -3 -p -r1.16 unit.c
*** io/unit.c	1 Oct 2005 11:50:09 -0000	1.16
--- io/unit.c	15 Oct 2005 23:27:50 -0000
*************** gfc_offset
*** 251,270 ****
  get_array_unit_len (gfc_array_char *desc)
  {
    gfc_offset record_count;
!   int i, rank, stride;
    rank = GFC_DESCRIPTOR_RANK(desc);
!   record_count = stride = 1;
!   for (i=0;i<rank;++i)
      {
!       /* Check that array is contiguous */
        
!       if (desc->dim[i].stride != stride)
! 	{
! 	  generate_error (ERROR_ARRAY_STRIDE, NULL);
! 	  return 0;
! 	}
!       stride *= desc->dim[i].ubound;
!       record_count *= desc->dim[i].ubound;
      }
    return record_count;
  }
--- 251,276 ----
  get_array_unit_len (gfc_array_char *desc)
  {
    gfc_offset record_count;
!   int i, rank;
    rank = GFC_DESCRIPTOR_RANK(desc);
!   
!   record_count = 1;
!   internal_unit.ls = (array_loop_spec*)
!                       get_mem (rank * sizeof (array_loop_spec));
!   
!   for (i=0; i<rank; ++i)
      {
!       /* Initialize the loop specification */
        
!       internal_unit.ls[i].idx = 1;
!       internal_unit.ls[i].start = desc->dim[i].lbound;
!       internal_unit.ls[i].end = desc->dim[i].ubound;
!       internal_unit.ls[i].step = desc->dim[i].stride;
!       
!       /* Determine the number of records */
!       
!       record_count += (desc->dim[i].ubound - desc->dim[i].lbound)
!                       * desc->dim[i].stride;
      }
    return record_count;
  }
Index: runtime/error.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/runtime/error.c,v
retrieving revision 1.16
diff -c -3 -p -r1.16 error.c
*** runtime/error.c	1 Oct 2005 11:50:09 -0000	1.16
--- runtime/error.c	15 Oct 2005 23:27:50 -0000
*************** translate_error (int code)
*** 427,436 ****
        p = "Numeric overflow on read";
        break;
  
-     case ERROR_ARRAY_STRIDE:
-       p = "Array unit stride must be 1";
-       break;
- 
      default:
        p = "Unknown error code";
        break;
--- 427,432 ----

Attachment: arrayio_4.f90
Description: application/extension-f90

Attachment: arrayio_6.f90
Description: application/extension-f90


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