Patchwork [libfortran] PR44477 Sequential I/O with END FILE: File position should be at EoF

login
register
mail settings
Submitter Jerry DeLisle
Date June 18, 2010, 3:19 a.m.
Message ID <4C1AE5DD.3040900@verizon.net>
Download mbox | patch
Permalink /patch/56100/
State New
Headers show

Comments

Jerry DeLisle - June 18, 2010, 3:19 a.m.
Hi,

This patch adds checks and issues errors if ENDFILE is executed when the file is 
already positioned after thee EOF marker.  It also gives errors if a read or 
write is attempted when positioned after the EOF marker.

Another problem is that ENDFILE should create the file if it does not exist.

Regression tested on x86-64-gnu-linux.  Test cases provided.

OK for trunk?

Regards,

Jerry

2010-06-17 Jerry DeLisle <jvdelisle@gcc.gnu.org>

	PR libfortran/44477
	* io/file_pos.c (st_endfile): Add check for ENDFILE when file is
	already positioned after the EOF marker. Use find_or_create_unit
	instead of find_unit. If unit is not connected, connect it and create
	the file with default settings.
	* io/transfer.c (data_transfer_init):  Add check for attempted READ or
	WRITE when file is already positioned after the EOF marker.
Tobias Burnus - June 18, 2010, 7:20 a.m.
On 06/18/2010 05:19 AM, Jerry DeLisle wrote:
> This patch adds checks and issues errors if ENDFILE is executed when
> the file is already positioned after thee EOF marker.  It also gives
> errors if a read or write is attempted when positioned after the EOF
> marker.
> Another problem is that ENDFILE should create the file if it does not
> exist.
>
> Regression tested on x86-64-gnu-linux.  Test cases provided.
> OK for trunk?

Thanks for the patch. OK after considering the following items.

You seem to have copied the initialization (if no file exists) from
data_transfer_init.
a) The /* Is it unformatted?  */ comment does not make sense, can you
remove it?
b) You use GFC_CONVERT_NATIVE; shouldn't that use the environment
variable / compile-time option? In data_transfer_init, one checks
"get_unformatted_convert (dtp->common.unit)" and compile_options.convert.

Tobias

> 2010-06-17 Jerry DeLisle <jvdelisle@gcc.gnu.org>
>
>     PR libfortran/44477
>     * io/file_pos.c (st_endfile): Add check for ENDFILE when file is
>     already positioned after the EOF marker. Use find_or_create_unit
>     instead of find_unit. If unit is not connected, connect it and create
>     the file with default settings.
>     * io/transfer.c (data_transfer_init):  Add check for attempted
> READ or
>     WRITE when file is already positioned after the EOF marker.

Patch

Index: file_pos.c
===================================================================
--- file_pos.c	(revision 160770)
+++ file_pos.c	(working copy)
@@ -283,11 +283,20 @@  st_endfile (st_parameter_filepos *fpp)
       if (u->flags.access == ACCESS_DIRECT)
 	{
 	  generate_error (&fpp->common, LIBERROR_OPTION_CONFLICT,
-			  "Cannot perform ENDFILE on a file opened"
-			  " for DIRECT access");
+			  "Cannot perform ENDFILE on a file opened "
+			  "for DIRECT access");
 	  goto done;
 	}
 
+      if (u->flags.access == ACCESS_SEQUENTIAL
+      	  && u->endfile == AFTER_ENDFILE)
+	{
+	  generate_error (&fpp->common, LIBERROR_OPTION_CONFLICT,
+			  "Cannot perform ENDFILE on a file already "
+			  "positioned after the EOF marker");
+	  goto done;
+	}
+
       /* If there are previously written bytes from a write with ADVANCE="no",
 	 add a record marker before performing the ENDFILE.  */
 
@@ -309,10 +318,51 @@  st_endfile (st_parameter_filepos *fpp)
       u->endfile = AFTER_ENDFILE;
       if (0 == stell (u->s))
         u->flags.position = POSITION_REWIND;
-    done:
-      unlock_unit (u);
     }
+  else
+    {
+      if (fpp->common.unit < 0)
+	{
+	  generate_error (&fpp->common, LIBERROR_BAD_OPTION,
+			  "Bad unit number in statement");
+	  return;
+	}
 
+      u = find_or_create_unit (fpp->common.unit);
+      if (u->s == NULL)
+	{  /* Open the unit with some default flags.  */
+	  st_parameter_open opp;
+	  unit_flags u_flags;
+
+	  memset (&u_flags, '\0', sizeof (u_flags));
+	  u_flags.access = ACCESS_SEQUENTIAL;
+	  u_flags.action = ACTION_READWRITE;
+
+	  /* Is it unformatted?  */
+	  u_flags.form = FORM_UNSPECIFIED;
+	  u_flags.delim = DELIM_UNSPECIFIED;
+	  u_flags.blank = BLANK_UNSPECIFIED;
+	  u_flags.pad = PAD_UNSPECIFIED;
+	  u_flags.decimal = DECIMAL_UNSPECIFIED;
+	  u_flags.encoding = ENCODING_UNSPECIFIED;
+	  u_flags.async = ASYNC_UNSPECIFIED;
+	  u_flags.round = ROUND_UNSPECIFIED;
+	  u_flags.sign = SIGN_UNSPECIFIED;
+	  u_flags.status = STATUS_UNKNOWN;
+	  u_flags.convert = GFC_CONVERT_NATIVE;
+
+	  opp.common = fpp->common;
+	  opp.common.flags &= IOPARM_COMMON_MASK;
+	  u = new_unit (&opp, u, &u_flags);
+	  if (u == NULL)
+	    return;
+	  u->endfile = AFTER_ENDFILE;
+	}
+    }
+
+  done:
+    unlock_unit (u);
+
   library_end ();
 }
 
Index: transfer.c
===================================================================
--- transfer.c	(revision 160770)
+++ transfer.c	(working copy)
@@ -2267,15 +2267,25 @@  data_transfer_init (st_parameter_dt *dtp, int read
       return;
     }
 
-  if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL
-      && (cf & IOPARM_DT_HAS_REC) != 0)
+  if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
     {
-      generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
-		      "Record number not allowed for sequential access "
-		      "data transfer");
-      return;
+      if ((cf & IOPARM_DT_HAS_REC) != 0)
+	{
+	  generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
+			"Record number not allowed for sequential access "
+			"data transfer");
+	  return;
+	}
+
+      if (dtp->u.p.current_unit->endfile == AFTER_ENDFILE)
+      	{
+	  generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
+			"Sequential READ or WRITE not allowed after "
+			"EOF marker, possibly use REWIND or BACKSPACE");
+	  return;
+	}
+
     }
-
   /* Process the ADVANCE option.  */
 
   dtp->u.p.advance_status