[Patch, libfortran, 2/3] Introduce a ssize member function

2011-10-18 Thread Janne Blomqvist
Hi,

the attached patch introduces a new "member function" ssize in order
to determine the size of a unit. The benefit is that with unbuffered
IO, when getting the size of a file we can replace 3 lseek() calls
with one fstat() call, and also that for unseekable file we get a size
of 0 rather than -1 (which would indicate that the syscall failed).

Regtested on x86_64-unknown-linux-gnu, Ok for trunk?

2011-10-18  Janne Blomqvist  

* io/unix.h (struct stream): Add size function pointer.
(ssize): New inline function.
(file_length): Remove prototype.
* io/unix.c (raw_size): New function.
(raw_init): Initialize st.size pointer.
(buf_size): New function.
(buf_init): Initialize st.size pointer.
(open_internal): Likewise.
(open_internal4): Likewise.
(file_length): Remove function.
* io/file_pos.c (st_rewind): Use ssize instead of file_length.
* io/open.c (test_endfile): Likewise.
* io/transfer.c (data_transfer_init): Likewise.
(next_record_r): Likewise.
(next_record_w): Likewise.
* io/unit.c (update_position): Likewise.


-- 
Janne Blomqvist
diff --git a/libgfortran/io/file_pos.c b/libgfortran/io/file_pos.c
index 2caf601..c8ecc3a 100644
--- a/libgfortran/io/file_pos.c
+++ b/libgfortran/io/file_pos.c
@@ -408,7 +408,7 @@ st_rewind (st_parameter_filepos *fpp)
 	generate_error (&fpp->common, LIBERROR_OS, NULL);
 
 	  /* Set this for compatibilty with g77 for /dev/null.  */
-	  if (file_length (u->s) == 0)
+	  if (ssize (u->s) == 0)
 	u->endfile = AT_ENDFILE;
 	  else
 	{
diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c
index b26d14d..0102b9c 100644
--- a/libgfortran/io/open.c
+++ b/libgfortran/io/open.c
@@ -153,7 +153,7 @@ static const st_option async_opt[] =
 static void
 test_endfile (gfc_unit * u)
 {
-  if (u->endfile == NO_ENDFILE && file_length (u->s) == stell (u->s))
+  if (u->endfile == NO_ENDFILE && ssize (u->s) == stell (u->s))
 u->endfile = AT_ENDFILE;
 }
 
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 1e054f8..26263ae 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -2627,7 +2627,7 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
 	 a partial record needs to exist.  */
 
   if (dtp->u.p.mode == READING && (dtp->rec - 1)
-	  * dtp->u.p.current_unit->recl >= file_length (dtp->u.p.current_unit->s))
+	  * dtp->u.p.current_unit->recl >= ssize (dtp->u.p.current_unit->s))
 	{
 	  generate_error (&dtp->common, LIBERROR_BAD_OPTION,
 			  "Non-existing record number");
@@ -2944,7 +2944,7 @@ next_record_r (st_parameter_dt *dtp, int done)
 	{
 	  bytes_left = (int) dtp->u.p.current_unit->bytes_left;
 	  bytes_left = min_off (bytes_left, 
-		  file_length (dtp->u.p.current_unit->s)
+		  ssize (dtp->u.p.current_unit->s)
 		  - stell (dtp->u.p.current_unit->s));
 	  if (sseek (dtp->u.p.current_unit->s, 
 			 bytes_left, SEEK_CUR) < 0)
@@ -3309,7 +3309,7 @@ next_record_w (st_parameter_dt *dtp, int done)
 	{
 	  dtp->u.p.current_unit->strm_pos += len;
 	  if (dtp->u.p.current_unit->strm_pos
-		  < file_length (dtp->u.p.current_unit->s))
+		  < ssize (dtp->u.p.current_unit->s))
 		unit_truncate (dtp->u.p.current_unit,
dtp->u.p.current_unit->strm_pos - 1,
&dtp->common);
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index d2fb6d0..1d36214 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -719,7 +719,7 @@ update_position (gfc_unit *u)
 return;
   else if (cur == 0)
 u->flags.position = POSITION_REWIND;
-  else if (file_length (u->s) == cur)
+  else if (ssize (u->s) == cur)
 u->flags.position = POSITION_APPEND;
   else
 u->flags.position = POSITION_ASIS;
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index 00f7c72..c87be13 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -332,6 +332,16 @@ raw_tell (unix_stream * s)
   return lseek (s->fd, 0, SEEK_CUR);
 }
 
+static gfc_offset
+raw_size (unix_stream * s)
+{
+  struct stat statbuf;
+  int ret = fstat (s->fd, &statbuf);
+  if (ret == -1)
+return ret;
+  return statbuf.st_size;
+}
+
 static int
 raw_truncate (unix_stream * s, gfc_offset length)
 {
@@ -398,6 +408,7 @@ raw_init (unix_stream * s)
   s->st.write = (void *) raw_write;
   s->st.seek = (void *) raw_seek;
   s->st.tell = (void *) raw_tell;
+  s->st.size = (void *) raw_size;
   s->st.trunc = (void *) raw_truncate;
   s->st.close = (void *) raw_close;
   s->st.flush = (void *) raw_flush;
@@ -584,6 +595,12 @@ buf_tell (unix_stream * s)
   return buf_seek (s, 0, SEEK_CUR);
 }
 
+static gfc_offset
+buf_size (unix_stream * s)
+{
+  return s->file_length;
+}
+
 static int
 buf_truncate (unix_stream * s, gfc_offset length)
 {
@@ -613,6 +630,7 @@ buf_init (unix_stream * s)
   s->st.write = (void *) buf_write;
   s->st.seek = (void *) bu

Re: [Patch, libfortran, 2/3] Introduce a ssize member function

2011-10-28 Thread Mikael Morin
On Tuesday 18 October 2011 16:51:15 Janne Blomqvist wrote:
> Hi,
> 
> the attached patch introduces a new "member function" ssize in order
> to determine the size of a unit. The benefit is that with unbuffered
> IO, when getting the size of a file we can replace 3 lseek() calls
> with one fstat() call, and also that for unseekable file we get a size
> of 0 rather than -1 (which would indicate that the syscall failed).
> 
> Regtested on x86_64-unknown-linux-gnu, Ok for trunk?
> 
OK.

Mikael