Intel® Fortran Compiler 17.0 Developer Guide and Reference
The USEROPEN specifier lets you pass control to a routine that directly opens a file. The file can use system calls or library routines to establish a special context that changes the effect of subsequent Fortran I/O statements.
The USEROPEN specifier takes the following form:
USEROPEN = function-name
function-name |
Is the name of an external function of type INTEGER(INT_PTR_KIND()) on Windows and INTEGER(4) on Linux and OS X. The external function can be written in Fortran, C, or other languages. |
If the function is written in Fortran, do not execute a Fortran OPEN statement to open the file named in USEROPEN.
The Intel® Fortran Run-time Library (RTL) I/O support routines call the function named in USEROPEN in place of the system calls normally used when the file is first opened for I/O.
On Windows* systems, the Fortran RTL normally calls CreateFile( ) to open a file. When USEROPEN is specified, the called function opens the file (or pipe, etc.) by using CreateFile( ) and returns the handle of the file (return value from CreateFile( )) when it returns control to the calling Fortran program.
On Linux* and OS X* systems, the Fortran RTL normally calls the open function to open a file. When USEROPEN is specified, the called function opens the file by calling open and returns the file descriptor of the file when it returns control to the calling Fortran program.
When opening the file, the called function usually specifies options different from those provided by a normal Fortran OPEN statement.
You may get unexpected results if you specify OPEN with a filename and a USEROPEN specifier that opens a different filename, and then use a CLOSE statement with STATUS=DELETE (or DISPOSE=DELETE). In this case, the run-time library assumes you want to delete the file named in the OPEN statement, not the one you specified in the USEROPEN function. For more information about how to use the USEROPEN specifier, see User-Supplied OPEN Procedures/USEROPEN Specifier.
The following shows an example on Linux and OS X systems and an example on Windows systems.
Example on Linux and OS X systems:
PROGRAM UserOpenMain
IMPLICIT NONE
EXTERNAL UOPEN
INTEGER(4) UOPEN
CHARACTER(10) :: FileName="UOPEN.DAT"
INTEGER :: IOS
CHARACTER(255):: InqFullName
CHARACTER(100):: InqFileName
INTEGER :: InqLun
CHARACTER(30) :: WriteOutBuffer="Write_One_Record_to_the_File. "
CHARACTER(30) :: ReadInBuffer ="??????????????????????????????"
110 FORMAT( X,"FortranMain: ",A," Created (iostat=",I0,")")
115 FORMAT( X,"FortranMain: ",A,": Creation Failed (iostat=",I0,")")
120 FORMAT( X,"FortranMain: ",A,": ERROR: INQUIRE Returned Wrong FileName")
130 FORMAT( X,"FortranMain: ",A,": ERROR: ReadIn and WriteOut Buffers Do Not Match")
WRITE(*,'(X,"FortranMain: Test the USEROPEN Facility of Open")')
OPEN(UNIT=10,FILE='UOPEN.DAT',STATUS='REPLACE',USEROPEN=UOPEN, &
IOSTAT=ios, ACTION='READWRITE')
! When the OPEN statement is executed, the uopen_ function receives control.
! The uopen_ function opens the file by calling open(), and subsequently
! returns control with the handle returned by open().
IF (IOS .EQ. 0) THEN
WRITE(*,110) TRIM(FileName), IOS
INQUIRE(10, NAME=InqFullName)
CALL ParseForFileName(InqFullName,InqFileName)
IF (InqFileName .NE. FileName) THEN
WRITE(*,120) TRIM(FileName)
END IF
ELSE
WRITE(*,115) TRIM(FileName), IOS
GOTO 9999
END IF
WRITE(10,*) WriteOutBuffer
REWIND(10)
READ(10,*) ReadInBuffer
IF (ReadinBuffer .NE. WriteOutbuffer) THEN
WRITE(*,130) TRIM(FileName)
END IF
CLOSE(10)
WRITE(*,'(X,"FortranMain: Test of USEROPEN Completed")')
9999 CONTINUE
END
!---------------------------------------------------------------
! SUBROUTINE: ParseForFileName
! Takes a full pathname and returns the filename
! with its extension.
!---------------------------------------------------------------
SUBROUTINE ParseForFileName(FullName,FileName)
CHARACTER(255):: FullName
CHARACTER(255):: FileName
INTEGER :: P
P = INDEX(FullName,'/',.TRUE.)
FileName = FullName(P+1:)
END
//
// File: UserOpen_Sub.c
//
// This routine opens a file using data passed from the Intel(c) Fortran OPEN statement.
//
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <errno.h>
int uopen_ ( char *file_name, /* access read: name of the file to open (null terminated) */
int *open_flags, /* access read: READ/WRITE, see file.h or open(2) */
int *create_mode, /* access read: set if the file is to be created */
int *unit_num, /* access read: logical unit number to be opened */
int filenam_len ) /* access read: number of characters in file_name */
{
/*
** The returned value is the following:
** value >= 0 is a valid file descriptor
** value < 0 is an error
*/
int return_value;
printf(" %s: Opening FILENAME = %s\n", __FILE__, file_name);
printf(" %s: open_flags = 0x%8.8x\n", __FILE__, *open_flags);
if ( *open_flags & O_CREAT ) {
printf(" %s: the file is being created, create_mode = 0x%8.8x\n", __FILE__, *create_mode);
}
printf(" %s: open() ", __FILE__);
return_value = open(file_name, *open_flags, *create_mode);
if (return_value < 0) {
printf("FAILED.\n");
} else {
printf("SUCCEEDED.\n");
}
return (return_value);
} /* end of uopen_() */
Example on Windows systems:In the calling Fortran program, the function named in USEROPEN must first be declared in an EXTERNAL statement. For example, the following Fortran code might be used to call the USEROPEN procedure UOPEN:
IMPLICIT INTEGER (A-Z) EXTERNAL UOPEN INTEGER(INT_PTR_KIND()) UOPEN ... OPEN(UNIT=10,FILE='UOPEN.DAT',STATUS='NEW',USEROPEN=UOPEN)
When the OPEN statement is executed, the UOPEN function receives control. The function opens the file by calling CreateFile( ), performs whatever operations were specified, and subsequently returns control (with the handle returned by CreateFile( )) to the calling Fortran program.
Here is what the UOPEN function might look like:
INTEGER(INT_PTR_KIND()) FUNCTION UOPEN( FILENAME, &
DESIRED_ACCESS, &
SHARE_MODE, &
A_NULL, &
CREATE_DISP, &
FLAGS_ATTR, &
B_NULL, &
UNIT, &
FLEN )
!DIR$ ATTRIBUTES C, ALIAS:'_UOPEN' :: UOPEN
!DIR$ ATTRIBUTES REFERENCE :: FILENAME
!DIR$ ATTRIBUTES REFERENCE :: DESIRED_ACCESS
!DIR$ ATTRIBUTES REFERENCE :: SHARE_MODE
!DIR$ ATTRIBUTES REFERENCE :: CREATE_DISP
!DIR$ ATTRIBUTES REFERENCE :: FLAGS_ATTR
!DIR$ ATTRIBUTES REFERENCE :: UNIT
USE IFWIN
IMPLICIT INTEGER (A-Z)
CHARACTER*(FLEN) FILENAME
TYPE(T_SECURITY_ATTRIBUTES), POINTER :: NULL_SEC_ATTR
! Set the FILE_FLAG_WRITE_THROUGH bit in the flag attributes to CreateFile( )
! (for whatever reason)
FLAGS_ATTR = FLAGS_ATTR + FILE_FLAG_WRITE_THROUGH
! Do the CreateFile( ) call and return the status to the Fortran rtl
STS = CreateFile( FILENAME, &
DESIRED_ACCESS, &
SHARE_MODE, &
NULL_SEC_ATTR, &
CREATE_DISP, &
FLAGS_ATTR, &
0 )
UOPEN = STS
RETURN
END
The UOPEN function is declared to use the cdecl calling convention, so it matches the Fortran rtl declaration of a useropen routine.
The following function definition and arguments are passed from the Intel Fortran Run-time Library to the function named in USEROPEN:
INTEGER(INT_PTR_KIND()) FUNCTION UOPEN( FILENAME, &
DESIRED_ACCESS, &
SHARE_MODE, &
A_NULL, &
CREATE_DISP, &
FLAGS_ATTR, &
B_NULL, &
UNIT, &
FLEN )
!DIR$ ATTRIBUTES C, ALIAS:'_UOPEN' :: UOPEN
!DIR$ ATTRIBUTES REFERENCE :: DESIRED_ACCESS
!DIR$ ATTRIBUTES REFERENCE :: SHARE_MODE
!DIR$ ATTRIBUTES REFERENCE :: CREATE_DISP
!DIR$ ATTRIBUTES REFERENCE :: FLAGS_ATTR
!DIR$ ATTRIBUTES REFERENCE :: UNIT
The first 7 arguments correspond to the CreateFile( ) api arguments. The value of these arguments is set according the caller's OPEN( ) arguments:
FILENAME |
Is the address of a null terminated character string that is the name of the file. |
DESIRED_ACCESS |
Is the desired access (read-write) mode passed by reference. |
SHARE_MODE |
Is the file sharing mode passed by reference. |
A_NULL |
Is always null. The Fortran runtime library always passes a NULL for the pointer to a SECURITY_ATTRIBUTES structure in its CreateFile( ) call. |
CREATE_DISP |
Is the creation disposition specifying what action to take on files that exist, and what action to take on files that do not exist. It is passed by reference. |
FLAGS_ATTR |
Specifies the file attributes and flags for the file. It is passed by reference. |
B_NULL |
Is always null. The Fortran runtime library always passes a NULL for the handle to a template file in it's CreateFile( ) call. |
The last 2 arguments are the Fortran unit number and length of the file name:
UNIT |
Is the Fortran unit number on which this OPEN is being done. It is passed by reference. |
FLEN |
Is the length of the file name, not counting the terminating null, and passed by value. |