J3/98-134r2
Date: Feb. 18, 1998
To: X3J3
From: JOR (R. Bleikamp)
Subject: Edits for derived type I/O
Richard Maine: See the two lines with "+" in the left column.
I replaced text about the "processors formatting routines" with
"processors default input/output formatting". Feel free to fix this.
Edits are based on the functional description in paper 97-217r1.
Changes since 98-134 are marked with "|" in the left margin.
The text strings and delimit text to be italicized.
Many quoted names (i.e. "w", "d") are to be italicized or bold also.
"*"s in the left margin are used to highlight really important concepts.
Two minor functional changes from 97-217r1. The processor no longer resets
the state of BN/BZ/SP/SS/P to the unit default. They are still pushed/popped
around the call to the user defined derived type I/O routine. Second,
these routines are now callable by the user (it was too hard to avoid).
Edits are based on 98-007 (Jan 13, 1998).
Section 9.2.2.1 [143:38], list item (7),
change "data transfer" to
"data transfer, except for child data transfer input/output
statements (9.4.4.4.3)"
Section 9.4.2 [156:10], change "A" to
"Except when the object is processed by a user defined derived type
input/output procedure, as described in section 9.4.4.4.3, a"
Section 9.4.2 [156:15]
Change "If a derived type" to
"Except when the object is processed by a user defined derived type
input/output procedure, as described in section 9.4.4.4.3, when a
derived type"
Section 9.4.2 [156:18]
Change the "If a derived-type object" to
"Except when the object is processed by a user defined derived type
input/output procedure, as described in section 9.4.4.4.3, a
derived-type object that"
and on the next line (line 19), delete ", it"
Section 9.4.2 [156:27]
Change "An" to
"Except when the list item is processed by a user defined derived
type input/output procedure, as described in section 9.4.4.4.3,
an "
Section 9.4.4 [157:41], in the first list,
In list item (5),
change "Position"
to "Except when executing a child data transfer statement
(9.4.4.4.3), position"
Section 9.4.4 [158:1], in the first list,
In list item (8) (in the first list on that page),
change "Position" to
| "Except when executing an unformatted child data transfer statement
(9.4.4.4.3), position"
If we decide to support ASYNC I/O in a user defined derived type
I/O routine, then the second list in this section needs a similar edit.
No edits for now.
Section 9.4.4.4.2 [161:3],
Change "objects." to
"objects, except when the derived type object is processed by a user
defined derived type input/output procedure, as described in
section 9.4.4.4.3."
Add a new section, 9.4.4.4.3 [161:26+]:
"9.4.4.4.3 User Defined Derived Type Input/Output Procedures
User defined derived type input/output procedures allow a program to
alter the default handling of derived type objects and values in
data transfer input/output statements as described in section 9.4.2.
A user defined derived type input/output procedure is any procedure
whose interface matches one of the interfaces described in this
section. A particular user defined derived type input/output
procedure is selected based on the direction of the data transfer
(input or output), the type of data transfer statement (formatted
or unformatted), and the type of the datum transfered.
When an interface for a corresponding user defined derived type
input/output procedure is visible in a scoping unit, and other
requirements are met, the processor will not process those
derived types list items as described in 9.4.2. Instead, it will
call the corresponding user defined derived type input/output
procedure, for any data transfer input/output statements executed in
that scoping unit. The user defined derived type input/output
procedure controls the actual data transfer operations for the
derived type list item.
* An input/output statement that includes a derived type list item, and that
* causes a user defined derived type input/output procedure to be invoked,
* is called a parent data transfer input/output statement.
* Any other input/output data transfer statement executed specifying
* the unit passed into a user defined derived type input/output procedure
* while the parent data transfer input/output statement is being
* processed is
* called a child data transfer input/output statement.
Note: A user defined derived type input/output procedure will
usually contain child data transfer input/output statements, that
read values from, or write values to, the current record. The
effect of executing the user defined derived type input/output
procedure is similar to substituting the list items from any child
data transfer statements into the parent data transfer input/output
statement's list item list, along with similar substitutions in
the format specification.
Note: A particular execution of a READ, WRITE or PRINT statement can
be both a parent and a child data transfer input/output statement.
A user defined derived type input/output procedure can indirectly
call itself or another user defined derived type input/output procedure
by executing a child data transfer input/output statement containing
a list item of derived type, where a matching interface is visible
for that derived type.
If a user defined derived type input/output procedure calls itself
indirectly in this manner, it must be declared RECURSIVE.
* A child data transfer input/output statement is processed differently
* from a non-child data transfer input/output statement in the
* following ways:
* - Executing a child data transfer statement does not position
* the file prior to data transfer.
* - An unformatted child data transfer input/output statement does not
* position the file after data transfer is complete.
For a particular derived type, there are four possible user defined
derived type input/output procedures; one each for formatted input,
formatted output, unformatted input, and unformatted output. The user
need not supply all four procedures for a particular type.
The four allowable interfaces for user defined derived type
input/output procedures are:
INTERFACE READ ( FORMATTED )
SUBROUTINE my_read_routine_formatted &
(unit, &
dtv, &
iotype, w, d, m, &
eof, err, eor, errmsg)
INTEGER, INTENT(IN) :: unit ! unit number
! the derived type value/variable
TYPE (whateveritis), INTENT(OUT) :: dtv
! the edit descriptor string
CHARACTER, (LEN=*), INTENT(IN) :: iotype
INTEGER, OPTIONAL, INTENT(IN) :: w,d,m
LOGICAL, INTENT(OUT) :: eof, err, eor
CHARACTER, (LEN=*), INTENT(OUT) :: errmsg
END
END INTERFACE
INTERFACE READ ( UNFORMATTED )
SUBROUTINE my_read_routine_unformatted &
(unit, &
dtv, &
eof, err, eor, errmsg)
INTEGER, INTENT(IN) :: unit
! the derived type value/variable
TYPE (whateveritis) INTENT(OUT) :: dtv
LOGICAL, INTENT(OUT) :: eof, err, eor
CHARACTER, (LEN=*), INTENT(OUT) :: errmsg
END
END INTERFACE
INTERFACE WRITE ( FORMATTED )
SUBROUTINE my_write_routine_formatted &
(unit, &
dtv, &
iotype, w, d, m, &
err, errmsg)
INTEGER, INTENT(IN) :: unit
! the derived type value/variable
TYPE (whateveritis), INTENT(IN) :: dtv
! the edit descriptor string
CHARACTER, (LEN=*), INTENT(IN) :: iotype
INTEGER, OPTIONAL, INTENT(IN) :: w,d,m
LOGICAL, INTENT(OUT) :: err
CHARACTER, (LEN=*), INTENT(OUT) :: errmsg
END
END INTERFACE
INTERFACE WRITE ( UNFORMATTED )
SUBROUTINE my_write_routine_unformatted &
(unit, &
dtv, &
err, errmsg)
INTEGER, INTENT(IN) :: unit
! the derived type value/variable
TYPE (whateveritis), INTENT(IN) :: dtv
LOGICAL, INTENT(OUT) :: err
CHARACTER, (LEN=*), INTENT(OUT) :: errmsg
END
END INTERFACE
The actual specific procedure names (the my_..._routine_...
| procedure names above) and the dummy argument names are not significant.
| The dummy arguments shall have the type, type parameters, and
| rank as described above. No other attributes shall be specified
| for a dummy argument, except that the "dtv" dummy
| argument may also be given the VOLATILE attribute.
The user defined derived type input/output procedures are invoked
during the processing of input/output data transfer statements when
the input/output data transfer statement is processing a derived
type list item and:
- for unformatted, list directed, and namelist input/output, a
corresponding interface for the derived type of that list
item is accessible
- for input/output statements with a ,
a corresponding interface for the derived type of that list
item is accessible, and the list item's corresponding edit
descriptor is a DT edit descriptor,
The "unit" dummy argument will have the same unit value as
specified by the user in the originating input/output statement
for all external units except "*". When an internal unit or
the "*" external unit was specified in the originating input/output
statement, the "unit" dummy argument will have a processor
dependent negative value.
Note: Since the "unit" dummy argument value will be negative when
the parent input/output statement specified an internal file,
the "*" unit or no unit, a user defined derived type input/output
procedure should not execute an INQUIRE statement without checking
for a positive value of the "unit" dummy argument.
The "iotype" argument will have the value:
- "LISTDIRECTED" if the originating input/output statement
specified list directed input/output,
- "NAMELIST" if the original input/output statement contained
a , or
- "DT[letters]" if the originating input/output statement
contained a format specification and the list item's
corresponding edit descriptor was a DT edit descriptor.
The "DT" in "iotype" and the letters after the "DT"
will be converted to upper case.
If the original input/output statement is a READ statement, a
value assigned to the "dtv" dummy argument (or some portion thereof)
by the user defined derived type input/output read procedure will
define the input list item object.
If the original input/output statement is a WRITE or PRINT, the
"dtv" dummy argument contains the value of the list item from the
original input/output statement.
The "w", "d", and "m" arguments contain the user specified
values from the edit descriptor (e.g. FORMAT(DT12.5.2 ) ).
If the user did not specify "w", "d", and/or "m", those dummy
arguments will not be present. They will not be present if
the original input/output statement was a list directed or
namelist input/output statement.
The user defined derived type input/output procedures for reads
shall assign a value of .FALSE. or .TRUE. to the "err", "eof", and
"eor" dummy args. The values assigned to these dummy arguments
determine whether or not the corresponding condition is
triggered by the processor in the parent input/output statement
when the user defined derived type input/output procedure returns.
If the value true is assigned to the "err" dummy argument,
the "errmsg" dummy argument shall be defined also, before the
user defined derived type input/output procedure returns.
When "err" is set to true, and the parent input/output statement
contains neither an ERR= nor an IOSTAT= specifier, the
processor shall attempt to output the "errmsg" value and stop
execution of the program.
Note to the reader: If we add an ERRMSG= specifier to all read/write
statements, this value would be returned thereto.
A DT edit descriptor shall not correspond with a list item that
is not of a derived type.
A DT edit descriptor shall not correspond with a list item of a
derived type unless a corresponding interface for a user defined
derived type input/output procedure is accessible.
Note: The users procedure may chose to interpret the "w" argument as a
field width, but this is not required. If it does, it would be
appropriate to fill an output field with "*"s if "w" is too small.
If a parent READ statement is active, input/output statements
shall not READ from any other external unit other than the one
specified by the dummy arg "unit", nor perform output to any
external unit.
If a parent WRITE or PRINT statement is active, input/output
statements shall not perform output to any other external unit
other than the one specified by the dummy arg "unit, nor perform
input from any external unit.
When a parent input/output statement is active, data transfer
input/output statements that specify an internal file are permitted.
OPEN, CLOSE, BACKSPACE, ENDFILE, and REWIND statements shall not
be executed while a user defined derived type input/output procedure
is active.
The user defined derived type input/output procedures may
use a FORMAT with a DT edit descriptor, for handling components
of the derived type that are themselves of a derived type.
A child input/output statement that is a list directed or namelist
input/output statement may contain a list item of derived type.
Child WRITE and PRINT statements write into the record started
by the parent output statement, starting at the position in the
record where the last edit descriptor finished.
Record boundaries may be created by output statements
in the user defined derived type input/output procedures for
formatted input/output.
A child formatted WRITE or PRINT statement does not position the file
to the next record before the list items are processed, but it
does end the current record when the child output statement
completes, unless the child output statement is non-advancing.
Child READ statements start reading from the postion in the current
record where the last edit descriptor from the parent
input/output statement finished. Multiple records may be read from a
formatted file. A child formatted READ statement positions
the file at the next record when the child READ statement completes,
unless the child READ statement is non-advancing.
Record positioning edit descriptors, such as TL and TR,
used on "unit" by a child input/output statement, shall not cause the
record position to be positioned before the record position at
the time the user defined derived type input/output procedure
was invoked.
Note: A robust user defined derived type input/output procedure may
wish to use INQUIRE to determine the settings of BLANK=, PAD=
and DELIM= for an external unit.
Edit descriptors that affect subsequent edit descriptors
behavior, such as BN, SP, P, etc., are permitted in FORMATs in
child input/output statements. The processor saves the state
of BN, BZ, S, SP, SS, and P before calling a user defined
derived type input/output procedure, calls the user defined derived
type input/output procedure, and restores the processor's state of
BN, BZ, S, SP, SS, and P to the saved state when the user defined
derived type input/output procedure returns.
A child input/output statement is free to use these state changing
edit descriptors without having any effect on the formatting of list
items in the parent input/output list.
Note to the reader: If directed rounding mode edit descriptors are added,
these will be added to the list of "saved" states.
READ and WRITE statements executed in a user defined derived
type input/output procedure, or executed in a procedure invoked (directly
or indirectly) from a user defined derived type input/output procedure
shall not contain an ASYNCHRONOUS="YES" specifier, nor shall
the parent READ or WRITE statement contain an ASYNCHRONOUS="YES"
specifier.
A user defined derived type input/output procedure, and any procedures
invoked therefrom, shall not define, nor cause to become undefined,
any storage location referenced by any input/output list item,
the corresponding format, or any specifer in any active parent
input/output statement, except through the "dtv" dummy argument.
In section 10.2.1 [173:1+], add
"or DT [letter] ... [w[.d[.m]]] "
In section 10.2.1 [173:11+] add
"Constraint: The string of letters following a DT edit descriptor
shall not contain more than 253 characters."
Add a new section 10.5.5 [181:28+]:
"10.5.5 User defined derived type editing
The DT edit descriptor allows a user provided procedure to be used
+ instead of the processors default input/output formatting for
+ processing a list item of derived type.
The DT characters may be followed by up to 253 letters
(additional interspersed blanks are permitted) (ex. "DT LNK LST").
The text of the edit descriptor, including the initial "DT" and
the string of letters, up to but not including w,
is converted to uppercase and has all blanks removed.
The resulting character value is passed to the user defined
derived type input/output procedure as the "iotype" argument.
Note: The letters after "DT" could be used to request different
formatting rules for various components in the derived type.
If a derived type variable or value corresponds with a DT
edit descriptor, the user shall provide the corresponding
derived type input/output procedure for that derived type, with
an accessible interface as specified in section 9.4.4.4.3.
In section 12.3.2.1, in R1207 [204:14+] add,
"or READ (FORMATTED)
or READ (UNFORMATTED)
or WRITE (FORMATTED)
or WRITE (UNFORMATTED)"
| In section 12.3.2.1 [206:5+] add a new paragraph:
| "An interface-stmt containing the keywords READ or WRITE,
| followed by "(FORMATTED)" or "(UNFORMATTED)", is an interface
| for a user defined derived type input/output procedure (9.4.4.4.3).
|
| Add sections as follows:
| "12.3.2.1.3 User defined derived type input/output procedure interfaces
| All of the procedures specified in an interface block for
| a user defined derived type input/output procedure shall be subroutines
| that have an interface as described in section
| 9.4.4.4.3.
|
| For any derived type, there shall be at most one procedure for
| that type in all "READ (FORMATTED)" interface blocks accessible
| in a scoping unit,
| at most one procedure for that type in all "READ (UNFORMATTED)"
| interface blocks accessible
| in a scoping unit,
| at most one procedure for that type in all "WRITE (FORMATTED)"
| interface blocks accessible
| in a scoping unit, and
| at most one procedure for that type in all "WRITE (UNFORMATTED)"
| interface blocks accessible
| in a scoping unit.
OPTIONAL edits for Richard Maine, for the F2000 Introduction, summary of
new features.
User control of derived type input/output
F2000 provides a portable mechanism for the implementor of opaque
data types to implement (in Fortran) the input/output conversion
procedures for an opaque data type, and access those I/O conversion
routines using standard Fortran READ and WRITE statements, for both
formatted and unformatted input/output.