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.