Hi Janus,

On Thu, Feb 20, 2014 at 06:51:30PM +0100, Janus Weil wrote:
> > Build and regtested on x86-64-gnu-linux.
> > OK for the trunk?
> 
> the patch looks pretty much trivial, int the sense that you just
> hard-wire the expected values for the std* units as a special case. I
> wonder why the 'inquire_read' and 'inquire_write' functions don't
> actually return the correct values?

One can inquire by FILE= name and by UNIT=; inquire_read() is using
the file name - either via FILE= directly or for an opened unit
via u->file; it then calls POSIX's access() function on the file name
to determine the permissions. Obviously, that fails if no file
actually exists.

Thus, simply calling the function won't work - and as all three cases
are slightly different, hardcoding the condition is simplest.


However, I now wonder whether one should also take care of other cases,
where no file name exists - but which could be queried. In that case,
one could simply use the mode in which the file was opened - which
one could do in general for files in the UNIT= mode - contrary to
the FILE= mode. I am in particular thinking of scratch files - they
are often opened, then deleted and only file descriptor remains.


Namely, either unconditionally using for UNIT=:

if ((cf & IOPARM_INQUIRE_HAS_READWRITE) != 0)
  p = (u->flags.action == ACTION_READWRITE) ? yes : no;

We probably still need some special case for stdin/stdout/stderr.


Or adding as additional condition:
  if (u->flags->status == STATUS_SCRATCH)
    p = (u->flags.action == ACTION_READWRITE) ? yes : no;
to also handle SCRATCH correctly.


* Advantage of access(): Gives the true file mode by the OS.
* Advantage of the open mode: Gives the permissions for which the
unit was opened. Also works in corner cases (scratch, stdout, ...).
Simpler code.

I have no idea what users prefer - but when using the unit directly,
the OPEN's ACCTION= mode feels a bit more natural than access().

Thoughts?

What about the new version of the patch?
It was built and regtested on x86-64-gnu-linux.

Tobias

PS: I also fixed the PR number - thanks Uros!
2014-02-20  Tobias Burnus  <bur...@net-b.de>

	PR fortran/60286
	* libgfortran/io/inquire.c (yes, no): New static const char vars.
	(inquire_via_unit): Use them. Use OPEN mode instead of using
	POSIX's access to query about write=, read= and readwrite=.

2014-02-20  Tobias Burnus  <bur...@net-b.de>

	PR fortran/60286
	* gfortran.dg/inquire_16.f90: New.

diff --git a/gcc/testsuite/gfortran.dg/inquire_16.f90 b/gcc/testsuite/gfortran.dg/inquire_16.f90
new file mode 100644
index 0000000..03b735e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/inquire_16.f90
@@ -0,0 +1,29 @@
+! { dg-do run }
+!
+! PR fortran/60286
+!
+! Contributed by  Alexander Vogt
+!
+program test_inquire
+  use, intrinsic :: ISO_Fortran_env
+  implicit none
+  character(len=20) :: s_read, s_write, s_readwrite
+
+  inquire(unit=input_unit, read=s_read, write=s_write, &
+          readwrite=s_readwrite)
+  if (s_read /= "YES" .or. s_write /= "NO" .or. s_readwrite /="NO") then
+    call abort()
+  endif
+
+  inquire(unit=output_unit, read=s_read, write=s_write, &
+          readwrite=s_readwrite)
+  if (s_read /= "NO" .or. s_write /= "YES" .or. s_readwrite /="NO") then
+    call abort()
+  endif
+
+  inquire(unit=error_unit, read=s_read, write=s_write, &
+          readwrite=s_readwrite)
+  if (s_read /= "NO" .or. s_write /= "YES" .or. s_readwrite /="NO") then
+    call abort()
+  endif
+end program test_inquire
diff --git a/libgfortran/io/inquire.c b/libgfortran/io/inquire.c
index b12ee51..6801d01 100644
--- a/libgfortran/io/inquire.c
+++ b/libgfortran/io/inquire.c
@@ -30,7 +30,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include <string.h>
 
 
-static const char undefined[] = "UNDEFINED";
+static const char yes[] = "YES", no[] = "NO", undefined[] = "UNDEFINED";
 
 
 /* inquire_via_unit()-- Inquiry via unit number.  The unit might not exist. */
@@ -130,10 +130,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
 	  {
 	  case ACCESS_DIRECT:
 	  case ACCESS_STREAM:
-	    p = "NO";
+	    p = no;
 	    break;
 	  case ACCESS_SEQUENTIAL:
-	    p = "YES";
+	    p = yes;
 	    break;
 	  default:
 	    internal_error (&iqp->common, "inquire_via_unit(): Bad access");
@@ -151,10 +151,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
 	  {
 	  case ACCESS_SEQUENTIAL:
 	  case ACCESS_STREAM:
-	    p = "NO";
+	    p = no;
 	    break;
 	  case ACCESS_DIRECT:
-	    p = "YES";
+	    p = yes;
 	    break;
 	  default:
 	    internal_error (&iqp->common, "inquire_via_unit(): Bad access");
@@ -191,10 +191,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
 	switch (u->flags.form)
 	  {
 	  case FORM_FORMATTED:
-	    p = "YES";
+	    p = yes;
 	    break;
 	  case FORM_UNFORMATTED:
-	    p = "NO";
+	    p = no;
 	    break;
 	  default:
 	    internal_error (&iqp->common, "inquire_via_unit(): Bad form");
@@ -211,10 +211,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
 	switch (u->flags.form)
 	  {
 	  case FORM_FORMATTED:
-	    p = "NO";
+	    p = no;
 	    break;
 	  case FORM_UNFORMATTED:
-	    p = "YES";
+	    p = yes;
 	    break;
 	  default:
 	    internal_error (&iqp->common, "inquire_via_unit(): Bad form");
@@ -266,10 +266,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
 	switch (u->flags.pad)
 	  {
 	  case PAD_YES:
-	    p = "YES";
+	    p = yes;
 	    break;
 	  case PAD_NO:
-	    p = "NO";
+	    p = no;
 	    break;
 	  default:
 	    internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
@@ -336,10 +336,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
 	    switch (u->flags.async)
 	    {
 	      case ASYNC_YES:
-		p = "YES";
+		p = yes;
 		break;
 	      case ASYNC_NO:
-		p = "NO";
+		p = no;
 		break;
 	      default:
 		internal_error (&iqp->common, "inquire_via_unit(): Bad async");
@@ -423,10 +423,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
 	      {
 	      case ACCESS_SEQUENTIAL:
 	      case ACCESS_DIRECT:
-		p = "NO";
+		p = no;
 		break;
 	      case ACCESS_STREAM:
-		p = "YES";
+		p = yes;
 		break;
 	      default:
 		internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
@@ -499,25 +499,19 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
 
   if ((cf & IOPARM_INQUIRE_HAS_READ) != 0)
     {
-      p = (u == NULL) ? inquire_read (NULL, 0) :
-	inquire_read (u->file, u->file_len);
-
+      p = (!u || u->flags.action == ACTION_WRITE) ? no : yes;
       cf_strcpy (iqp->read, iqp->read_len, p);
     }
 
   if ((cf & IOPARM_INQUIRE_HAS_WRITE) != 0)
     {
-      p = (u == NULL) ? inquire_write (NULL, 0) :
-	inquire_write (u->file, u->file_len);
-
+      p = (!u || u->flags.action == ACTION_READ) ? no : yes;
       cf_strcpy (iqp->write, iqp->write_len, p);
     }
 
   if ((cf & IOPARM_INQUIRE_HAS_READWRITE) != 0)
     {
-      p = (u == NULL) ? inquire_readwrite (NULL, 0) :
-	inquire_readwrite (u->file, u->file_len);
-
+      p = (!u || u->flags.action != ACTION_READWRITE) ? no : yes;
       cf_strcpy (iqp->readwrite, iqp->readwrite_len, p);
     }
 
@@ -552,10 +546,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
 	switch (u->flags.pad)
 	  {
 	  case PAD_NO:
-	    p = "NO";
+	    p = no;
 	    break;
 	  case PAD_YES:
-	    p = "YES";
+	    p = yes;
 	    break;
 	  default:
 	    internal_error (&iqp->common, "inquire_via_unit(): Bad pad");

Reply via email to