# Compaq Fortran
User Manual for
Tru64 UNIX and
Linux Alpha Systems

Previous | Contents | Index

# Chapter 7
Compaq Fortran Input/Output (I/O)

This chapter describes input/output (I/O) as implemented for Compaq Fortran and discusses the following topics:

- Section 7.1, Logical I/O Units
- Section 7.2, Types of I/O Statements
- Section 7.3, Forms of I/O Statements
- Section 7.4, Types of Files and File Characteristics
- Section 7.5, Opening Files: OPEN Statement
- Section 7.6, Obtaining File Information: INQUIRE Statement
- Section 7.7, Closing a File: CLOSE Statement
- Section 7.8, Record Operations
- Section 7.9, User-Supplied OPEN Procedures: USEROPEN Specifier
- Section 7.10, Format of Compaq Fortran Record Types

For More Information:

- On native data types, see Chapter 9.
- On reading and writing nonnative unformatted numeric data (originally written to the file using unformatted I/O statements), see Chapter 10.
- On porting Compaq OpenVMS Fortran data, see Section A.4.
- On performing I/O to the same unit with Compaq Fortran and Compaq Fortran 77 object files, see Section A.5.3.

# 7.1 Logical I/O Units

In Compaq Fortran, a logical unit is a channel through which data transfer occurs between the program and a device or file. You identify each logical unit with a logical unit number, which can be any nonnegative integer from 0 to a maximum value of 2,147,483,647 (2**31--1). For example:

    READ (2,100) I,X,Y

This READ statement specifies that data is to be entered from the device or file corresponding to logical unit 2, in the format specified by the FORMAT statement labeled 100. When opening a file, use the UNIT specifier to indicate the unit number.

Fortran 95/90 (Fortran) programs are inherently device-independent. The association between the logical unit number and the physical file can occur at run-time. Instead of changing the logical unit numbers specified in the source program, you can change this association at run time to match the needs of the program and the available resources. For example, before running the program, a script file can set the appropriate environment variable or allow the terminal user to type a directory path, file name, or both.

Use the same logical unit number specified in the OPEN statement for other I/O statements to be applied to the opened file, such as READ and WRITE.

The OPEN statement connects a unit number with an external file and allows you to explicitly specify file attributes and run-time options using OPEN statement specifiers (all files except internal files are called external files).

Certain unit numbers are preconnected to standard devices. Unit number 5 is associated with `stdin` , unit 6 with `stdout` , and unit 0 with `stderr` . At run time, if units 5 and 6 are specified by a record I/O statement (such as READ or WRITE) without having been explicitly opened by an OPEN statement, Compaq Fortran implicitly opens units 5, 6, and 0 and associates them with their respective operating system standard I/O files (if the corresponding FORTn environment variable is not set).

For More Information:

On the OPEN statement and preconnected files, see Section 7.5.

# 7.2 Types of I/O Statements

Table 7-1 lists the Compaq Fortran I/O statements.

Table 7-1 Summary of I/O Statements
Category and Statement Name | Description
--- | ---
File Connection |
OPEN | Connects a unit number with an external file and specifies file connection characteristics.
CLOSE | Disconnects a unit number from an external file.
File Inquiry |
INQUIRE | Returns information about a named file, a connection to a unit, or the length of an output item list.
Record Position |
BACKSPACE | Moves the record position to the beginning of the previous record (sequential access only).
ENDFILE | Writes an end-of-file marker after the current record (sequential access only).
REWIND | Sets the record position to the beginning of the file (sequential access only).
Record Input |
READ | Transfers data from an external file record or an internal file to internal storage.
Record Output |
WRITE | Transfers data from internal storage to an external file record or to an internal file.
PRINT | Transfers data from internal storage to `stdout` (standard output device). Unlike WRITE, PRINT only provides formatted sequential output and does not specify a unit number.
Compaq Fortran Extensions |
ACCEPT | Reads input from `stdin` . Unlike READ, ACCEPT only provides formatted sequential output and does not specify a unit number.
DELETE | Marks a record at the current record position in a relative file as deleted (direct access only).
REWRITE | Transfers data from internal storage to an external file record at the current record position (direct access relative files only).
UNLOCK | Releases a lock held on the current record when file sharing was requested when the file was opened. Ignored in the current version of Compaq Fortran for Tru64 UNIX and Linux Systems (see Section 7.8.2).
TYPE | Writes record output to `stdout` (same as PRINT).
DEFINE FILE | Specifies file characteristics for a direct access relative file and connects the unit number to the file, similar to an OPEN statement. Provided for compatibility with compilers before FORTRAN-77.
FIND | Changes the record position in a direct access file. Provided for compatibility with compilers older than FORTRAN-77.

In addition to the READ, WRITE, REWRITE, TYPE, and PRINT statements, other I/O record-related statements are limited to a specific file organization. For instance:

- The DELETE statement only applies to relative files. 1
- The BACKSPACE statement only applies to sequential files open for sequential access.
- The REWIND statement only applies to sequential files open for sequential access and to direct access files.
- The ENDFILE statement only applies to certain types of sequential files open for sequential access and to direct access files.

The file-related statements (OPEN, INQUIRE, and CLOSE) apply to any relative or sequential file.

Note #### 1 Detecting deleted records is only available if the `-vms` option was specified when the program was compiled. For more information on the `-vms` option, see Section 3.98.

# 7.3 Forms of I/O Statements

Each type of record I/O statement can be coded in a variety of forms. The form you select depends on the nature of your data and how you want it treated. When opening a file, specify the form using the FORM specifier. The following are the forms of I/O statements:

- Formatted I/O statements contain explicit format specifiers that are used to control the translation of data from internal (binary) form within a program to external (readable character) form in the records, or vice versa.
- List-directed and namelist I/O statements are similar to formatted statements in function. However, they use different mechanisms to control the translation of data: formatted I/O statements use explicit format specifiers, and list-directed and namelist I/O statements use data types.
- Unformatted I/O statements do not contain format specifiers and therefore do not translate the data being transferred (important when writing data that will be read later).

Formatted, list-directed, and namelist I/O forms require translation of data from internal (binary) form within a program to external (readable character) form in the records. Consider using unformatted I/O for the following reasons:

- Unformatted data avoids the translation process, so I/O tends to be faster.
- Unformatted data avoids the loss of precision in floating-point numbers when the output data will subsequently be used as input data.
- Unformatted data conserves file storage space (stored in binary form).

To write data to a file using formatted, list-directed, or namelist I/O statements, specify FORM= `'` FORMATTED `'` when opening the file. To write data to a file using unformatted I/O statements, specify FORM= `'` UNFORMATTED `'` when opening the file.

Data written using formatted, list-directed, or namelist I/O statements is referred to as formatted data; data written using unformatted I/O statements is referred to as unformatted data.

When reading data from a file, you should use the same I/O statement form that was used to write the data to the file. For instance, if data was written to a file with a formatted I/O statement, you should read data from that file with a formatted I/O statement.

Although I/O statement form is usually the same for reading and writing data in a file, a program can read a file containing unformatted data (using unformatted input) and write it to a separate file containing formatted data (using formatted output). Similarly, a program can read a file containing formatted data and write it to a different file containing unformatted data.

As described in Section 7.8.2, you can access records in any sequential or relative file using sequential access. For relative files and certain (fixed-length) sequential files, you can also access records using direct access.

Table 7-2 shows the main record I/O statements, by category, that can be used in Compaq Fortran programs.

Table 7-2 Available I/O Statements and Record I/O Forms
File Type, Access, and I/O Form | Available Statements
--- | ---
External file, sequential access
Formatted List-Directed Namelist Unformatted | READ, WRITE, PRINT, ACCEPT 1, TYPE 1, REWRITE 1,2 READ, WRITE, PRINT, ACCEPT 1, TYPE 1, REWRITE 1,2 READ, WRITE, PRINT, ACCEPT 1, TYPE 1, REWRITE 1,2 READ, WRITE, REWRITE 1,2
External file, direct access
Formatted Unformatted | READ, WRITE, and REWRITE 1,2 READ, WRITE, and REWRITE 1,2
Internal file 3
Formatted List-Directed Unformatted | READ, WRITE READ, WRITE None

1This statement is a Compaq extension to the Fortran 95/90 standard.
2You can use the REWRITE statement only for relative files, using direct access.
3An internal file is a way to reference character data in a buffer using sequential access (see Section 7.4.2).

# 7.4 Types of Files and File Characteristics

This section discusses file organization, internal and scratch files, record type, record length, and other file characteristics.

## 7.4.1 File Organizations

File organization refers to the way records are physically arranged on a storage device.

Compaq Fortran supports two kinds of file organizations:

- Sequential organization
- Relative organization

The default file organization is always ORGANIZATION= `'` SEQUENTIAL `'` for an OPEN statement. The organization of a file is specified by means of the ORGANIZATION specifier in the OPEN statement, as described in the Compaq Fortran Language Reference Manual.

You must store relative files on a disk device. You can store sequential files on magnetic tape or disk devices, and can use other peripheral devices, such as terminals, pipes, and line printers as sequential files.

Sequential Organization

A sequentially organized file consists of records arranged in the sequence in which they are written to the file (the first record written is the first record in the file, the second record written is the second record in the file, and so on). As a result, records can be added only at the end of the file.

Sequential files are usually read sequentially, starting with the first record in the file. Sequential files with a fixed-length record type that are stored on disk can also be accessed by relative record number (direct access).

Relative Organization

Within a relative file are numbered positions, called cells. These cells are of fixed equal length and are consecutively numbered from 1 to n, where 1 is the first cell, and n is the last available cell in the file. Each cell either contains a single record or is empty.

Records in a relative file are accessed according to cell number. A cell number is a record's relative record number (its location relative to the beginning of the file). By specifying relative record numbers, you can directly retrieve, add, or delete records regardless of their locations (direct access). (Detecting deleted records is only available if you specified the `-vms` option when the program was compiled. For information on the `-vms` option, see Section 3.98.)

When creating a relative file, specify the RECL value to determine the size of the fixed-length cells. Within the cells, you can store records of varying length, as long as their size does not exceed the cell size.

## 7.4.2 Internal Files and Scratch Files

Compaq Fortran also supports two other types of files that are not file organizations:

- Internal files
- Scratch files

Internal Files

When you use sequential access, you can use an internal file to reference character data in a buffer. The transfer occurs between internal storage and internal storage (unlike external files), such as between character variables and a character array.

An internal file consists of any of the following:

- Character variable
- Character-array element
- Character array
- Character substring
- Character array section without a vector subscript

Instead of specifying a unit number for the READ or WRITE statement, use an internal file specifier in the form of a character scalar memory reference or a character-array name reference.

An internal file is a designated internal storage space (variable buffer) of characters that is treated as a sequential file of fixed-length records. To perform internal I/O, use formatted and list-directed sequential READ and WRITE statements. You cannot use file-related statements such as OPEN and INQUIRE on an internal file (no unit number is used).

If an internal file is made up of a single character variable, array element, or substring, that file comprises a single record whose length is the same as the length of the character variable, array element, or substring it contains. If an internal file is made up of a character array, that file comprises a sequence of records, with each record consisting of a single array element. The sequence of records in an internal file is determined by the order of subscript progression.

A record in an internal file can be read only if the character variable, array element, or substring comprising the record has been defined (a value has been assigned to the record).

Prior to each READ and WRITE statement, an internal file is always positioned at the beginning of the first record.

Scratch Files

Scratch files are created by specifying STATUS= `'` SCRATCH `'` in an OPEN statement. By default, these temporary files are created in (and later deleted from) the directory specified in the OPEN statement DEFAULTFILE (if specified). To request a different directory to contain the scratch (temporary) files, set the `TMPDIR` environment variable.

## 7.4.3 Record Types, Record Overhead, and Maximum Record Length

Record type refers to whether records in a file are all the same length, are of varying length, or use other conventions to define where one record ends and another begins.

You can use fixed-length and variable-length record types with sequential or relative files. You can use any of the record types with sequential files. Relative files require the fixed-length record type.

Records are stored in one of the types described in Table 7-3. When creating a new file or opening an existing file, specify one of the record types listed in this table.

Table 7-3 Compaq Fortran Record Types
Record Type | Description
--- | ---
Fixed-length | Records in a file must contain the same length. You must specify the record length (RECL) when the file is opened and can obtain it before opening the file with unformatted data using a form of the INQUIRE statement (see Section 7.6.3). See Section 7.10.1, Fixed-Length Records.
Variable-length | Records in a file can vary in length. This is the most portable record type across multivendor U*X platforms (such as Compaq Tru64 UNIX). Record length information is stored as control bytes at the beginning and end of each record. See Section 7.10.2, Variable-Length Records.
Segmented | This pertains to a single logical record containing one or more unformatted records of varying length, which can only be used for unformatted sequential access. The segmented record type is unique to Compaq Fortran products. Avoid the segmented record type when the application requires that the same file be used for programs written in languages other than Fortran and for non-Compaq platforms. However, because the segmented record type is unique to Compaq Fortran products, segmented files can be ported across Compaq Fortran platforms. See Section 7.10.3, Segmented Records.
Stream | A stream file is not grouped into records and uses no record delimiters. Stream files contain character or binary data that is read or written to the extent of the variables specified. Specify CARRIAGECONTROL= `'` NONE `'` for stream files. See Section 7.10.4, Stream File Data.
Stream_LF and Stream_CR | Records are of varying length where the line feed (LF) or the carriage return (CR) character serve as record delimiters (LF for Stream_LF files and CR for Stream_CR files). Stream_LF files must not contain embedded LF characters or use CARRIAGECONTROL= `'` LIST `'` . Instead, specify CARRIAGECONTROL= `'` NONE `'` . Stream_CR files must not contain embedded CR characters. The Stream_LF record type is the usual record type for text files. See Section 7.10.5, Stream_CR and Stream_LF Records.

Before you choose a record type, consider whether your application will use formatted or unformatted data. If you are using formatted data, you can choose any record type except segmented. If you are using unformatted data, avoid the stream, stream_CR, and stream_LF record types.

The segmented record type can only be used for unformatted sequential access with sequential files. You should not use segmented records for files that are read by programs written in languages other than Compaq Fortran products.

The stream, stream_CR, stream_LF, and segmented record types can be used only with sequential files.

### 7.4.3.1 Portability Considerations of Record Types

Consider the following portability needs when choosing a record type:

- Data files from Compaq Fortran on Compaq Tru64 UNIX and Linux Alpha systems, and Compaq Fortran 77 on Compaq Tru64 UNIX systems, are interchangeable.
- Data files from Compaq Fortran on Tru64 UNIX Alpha systems and Compaq Fortran on Linux Alpha systems are interchangeable.
- When using files with Compaq Fortran and Compaq Fortran 77 on Tru64 UNIX, Linux, and OpenVMS systems, use:
  - The segmented record type for unformatted data. However, be aware that the segmented record type is used only by Compaq Fortran and Compaq Fortran 77 but not by other Compaq languages.
  - The stream_LF format for formatted data.
- The stream_LF record type is usually the most portable on U*X systems.
- Any record type except segmented with other non-Fortran Compaq languages.

For more information on porting Compaq OpenVMS Fortran data, see Section A.4.

The default record type (RECORDTYPE) depends on the values for the ACCESS and FORM specifiers for the OPEN statement, as described in the Compaq Fortran Language Reference Manual.

The record type of the file is not maintained as an attribute of the file. The results of using a record type other than the one used to create the file are indeterminate.

For information on choosing the most efficient record type, see Section 5.6.9.

An I/O record is a collection of fields (data items) that are logically related and are usually processed as a unit.

Unless you specify nonadvancing I/O (ADVANCE specifier), each Compaq Fortran I/O statement transfers one record. The exceptions are described in Section 7.8.5.

### 7.4.3.2 Record Overhead

Record overhead refers to bytes associated with each record that are used internally by the file system and are not available when a record is read or written. Knowing the record overhead helps when estimating the storage requirements for an application. Although the overhead bytes exist on the storage media, do not include them when specifying the record length with the RECL specifier in an OPEN statement.

The various record types each require a different number of bytes for record overhead, as described in Table 7-4.

Table 7-4 Bytes Required for Record Overhead
Record Type | Organization | Record Overhead
--- | --- | ---
Fixed-length | Sequential files | None.
Fixed-length | Relative files | None if the `-vms` option was omitted (the default). One byte if the `-vms` option was specified.
Variable-length | Sequential files | Eight bytes per record for overhead.
Segmented | Sequential files | Four bytes per record for overhead. One additional padding byte (space) is added if the specified record size is an odd number.
Stream | Sequential files | None required.
Stream_CR | Sequential files | One byte per record for overhead.
Stream_LF | Sequential files | One byte per record for overhead.

### 7.4.3.3 Maximum Record Length

For all but variable-length sequential records on 64-bit addressable systems, the maximum record length is 2.147 billion bytes (2,147,483,647 minus the bytes for record overhead). For variable-length sequential records on 64-bit addressable systems, the theoretical maximum record length is about 17,000 gigabytes. When considering very large record sizes, also consider limiting factors such as system virtual memory.

For More Information:

- On the detailed format of each record type, see Section 7.10.
- On converting nonnative numeric unformatted data, see Chapter 10.
- On I/O performance considerations, see Section 5.6.
- On porting data files from other vendors that can use different units for the record length, see Section 7.4.4.

## 7.4.4 Other File Characteristics

Other file characteristics include:

- Carriage control attributes of each record (CARRIAGECONTROL specifier)
- Whether formatted or unformatted data is contained in the records (FORM specifier)
- The record length (RECL specifier)

When you need to display or print formatted data that uses Fortran carriage control, consider using the `fpr` command as a filter through a pipe to reformat the records into operating system line printer format.

The units used for specifying record length depend on the form of the data:

- For formatted files (FORM= `'` FORMATTED `'` ), specify the record length in bytes.
- For unformatted files (FORM= `'` UNFORMATTED `'` ), specify the record length in 4-byte units, unless you specify the `-assume byterecl` option to request 1-byte units (see Section 3.7).

For More Information:

- On statement syntax and specifier values (including defaults), see the Compaq Fortran Language Reference Manual.
- On file characteristics, see Section 7.5.2 and the OPEN statement in the Compaq Fortran Language Reference Manual.
- On the `fpr` command and carriage control characters, see `fpr(1)`.
- On I/O performance considerations, see Section 5.6.

# 7.5 Opening Files: OPEN Statement

To open a file, you should use a preconnected file (such as for terminal output) or explicitly OPEN files. Although you can also implicitly open a file, this prevents you from using the OPEN statement to specify the file connection characteristics and other information.

## 7.5.1 Using Preconnected Standard I/O Files

If you do not use an OPEN statement to open logical unit 5, 6, or 0 and do not set the appropriate environment variable (FORTn), unit number 5 is associated with `stdin` , unit 6 with `stdout` , and unit 0 with `stderr` . At run time, Compaq Fortran implicitly opens (preconnects) units 5, 6, and 0 and associates them with their respective operating system standard I/O files if the corresponding FORTn environment variable is not set.

You can change these preconnected files by using one of the following:

- An OPEN statement to open unit 5, 6, or 0.
  When you explicitly OPEN a file for unit 5, 6, or 0, the OPEN statement keywords specify the file-related information to be used instead of the preconnected standard I/O file.
- Set the appropriate environment variable (FORTn) to redirect I/O to an external disk file.
  If you set the corresponding Compaq Fortran FORTn environment variable, the file specified by that Compaq Fortran environment variable is used.

Table 7-5 lists the Compaq Fortran environment variables and the standard I/O file associations for the preconnected files.

Table 7-5 Environment Variables and Preconnected Files
Unit | Compaq Fortran Environment Variable | Equivalent Tru64 UNIX Standard I/O File
--- | --- | ---
5 | FORT5 | Standard input, `stdin`
6 | FORT6 | Standard output, `stdout`
0 | FORT0 | Standard error, `stderr`

To change the characteristics of the connection to a preconnected unit, explicitly open the preconnected unit number.

To redirect input or output from the standard preconnected files at run-time, you can set the appropriate Compaq Fortran I/O environment variable (see Section 7.5.7) or use the appropriate shell redirection character in a pipe (such as > or <).

For More Information:

- On the shell commands you can use to set or unset environment variables, see Appendix B.
- Other I/O environment variables recognized by Compaq Fortran, see Section 7.5.7.

## 7.5.2 OPEN Statement Specifiers

The OPEN statement connects a unit number with an external file and allows you to explicitly specify file attributes and run-time options using OPEN statement specifiers. Once you open a file, you should close it before opening it again unless it is a preconnected file.

If you open a unit number that was opened previously (without being closed), one of the following occurs:

- If you specify a file specification that does not match the one specified for the original open, the Compaq Fortran run-time system closes the file and then reopens it.
  This resets the current record position for the second file.
- If you specify a file specification that does match the one specified for the original open, the file is reconnected without the internal equivalent of the CLOSE and OPEN.
  This lets you change one or more OPEN statement run-time specifiers while maintaining the record position context.

You can use the INQUIRE statement (see Section 7.6) to obtain information about a whether or not a file is opened by your program.

Especially when creating a new file using the OPEN statement, examine the defaults (see the description of the OPEN statement in the Compaq Fortran Language Reference Manual) or explicitly specify file attributes with the appropriate OPEN statement specifiers.

Table 7-6 lists the OPEN statement functions and their specifiers.

Table 7-6 OPEN Statement Functions and Specifiers
Category, Functions, and OPEN Statement Specifiers
Identify File and Unit
| UNIT specifies the logical unit number.
| FILE (or NAME 1) and DEFAULTFILE 1 specify the directory and/or file name of an external file.
| STATUS or TYPE 1 indicates whether to create a new file, overwrite an existing file, open an existing file, or use a scratch file.
| STATUS or DISPOSE 1 specifies the file existence status after CLOSE.
File and Record Characteristics
| ORGANIZATION 1 indicates the file organization (sequential or relative).
| RECORDTYPE 1 indicates which record type to use.
| FORM indicates whether records are formatted or unformatted.
| CARRIAGECONTROL 1 indicates the terminal control type.
| RECL or RECORDSIZE 1 specifies the record size (see Section 7.4.4).
Special File Open Routine
| USEROPEN 1 names the routine that will open the file to establish special context that changes the effect of subsequent Compaq Fortran I/O statements (see Section 7.9).
File Access, Processing, and Position
| ACCESS indicates the access mode (direct or sequential).
| SHARED 1 indicates that other users can access the same file and activates record locking. Ignored in the current version of Compaq Fortran for Tru64 UNIX and Linux Systems (see Section 7.8.2).
| POSITION indicates whether to position the file at the beginning of file, before the end-of-file record, or leave it as is (unchanged).
| ACTION or READONLY 1 indicates whether statements will be used to only read records, only write records, or both read and write records.
| MAXREC 1 specifies the maximum record number for direct access.
| ASSOCIATEVARIABLE 1 specifies the variable containing next record number for direct access.
Record Transfer Characteristics
| BLANK indicates whether to ignore blanks in numeric fields.
| DELIM specifies the delimiter character for character constants in list-directed or namelist output.
| PAD, when reading formatted records, indicates whether padding characters should be added if the item list and format specification require more data than the record contains.
| BLOCKSIZE 1 specifies the block physical I/O buffer size.
| BUFFERCOUNT 1 specifies the number of physical I/O buffers.
| CONVERT 1 specifies the format of unformatted numeric data (see Chapter 10).
Error Handling Capabilities
| ERR specifies a label to branch to if an error occurs.
| IOSTAT specifies the integer variable to receive the error (IOSTAT) number if an error occurs.
File Close Action
| DISPOSE identifies the action to take when the file is closed.

1This specifier is a Compaq Fortran extension.

For More Information:

- On specifier syntax and complete information, see the Compaq Fortran Language Reference Manual.
- On the UNIT, FILE, and DEFAULTFILE specifiers, see Section 7.5.3 to Section 7.5.7.
- On the FORM specifier, see Section 7.3.
- On file organizations, see Section 7.4.1.
- On available record types, see Section 7.4.3 and Section 7.10.
- On the CARRIAGECONTROL specifier, see Section 7.4.4 and `fpr(1)`.
- On the RECL (record length) specifier, see Section 7.4.4.
- On the ERR and IOSTAT specifiers, see Chapter 8.
- On obtaining file information using the INQUIRE statement, see Section 7.6.
- On closing files, see Section 7.7.
- Record I/O transfer, see Section 7.8.5.
- Record advancement, see Section 7.8.4.
- Record positioning, see Section 7.8.3.
- On I/O performance considerations, see Section 5.6.

## 7.5.3 Methods to Specify the Unit, File Name, and Directory

You can choose to assign files to logical units by using one of the following methods:

- By using default values, such as a preconnected unit. In the following example, the PRINT statement is associated with a preconnected unit ( `stdout` ) by default.

      PRINT *,100

  The READ statement associates the logical unit 7 with the file `fort.7` (because the FILE specifier was omitted) by default:

      OPEN (UNIT=7,STATUS='NEW')
      READ (7,100)

- By supplying a file name (and possibly a directory) in an OPEN statement. For example:

      OPEN (UNIT=7, FILE='FILNAM.DAT', STATUS='OLD')

- By using environment variables. You can also use shell commands to set the appropriate environment variable to a value that indicates a directory (if needed) and a file name to associate a unit with an external file.

The following sections discuss these methods.

## 7.5.4 Accessing Files: Implied and Explicit File and Pathnames

Most I/O operations involve a disk file, keyboard, or screen display. Other devices can also be used:

- Sockets can be read from or written to if a USEROPEN routine (usually written in C) is used to open the socket.
- Pipes opened for read and write access block (wait until data is available) if you issue a READ to an empty pipe.
- Pipes opened for read-only access return EOF if you issue a READ to an empty pipe.

For information on USEROPEN routines, see Section 7.9.

You can access the terminal screen or keyboard by using preconnected files, as described in Section 7.5. Otherwise, this chapter discusses disk files.

A complete file specification consists of a file name usually preceded by a pathname that specifies a directory. The pathname can be in one of two forms:

- An absolute pathname, where the directory is specified relative to the root directory. The first character is a slash (/). For example, the following directory and file name refers to the file named `testdata` in the `/usr/users/gdata` directory:

      /usr/users/gdata/testdata

- A relative pathname, where the specified directory is relative to the current directory. Relative pathnames do not begin with a slash (/). The following example uses a relative pathname from the current directory `/usr/users` to refer to the same file `testdata` in the `gdata/` subdirectory:

      gdata/testdata

Directory names and file names should not contain any operating system wildcard characters (such as *, ?, and the [ ] construct). You can use the tilde (~) character as the first character in a pathname to refer to a top-level directory as in the C shell.

When specifying files, keep in mind that trailing and leading blanks are removed from character expression names, but not from Hollerith (numeric array) names.

File names are case sensitive and can consist of uppercase and lowercase letters. For example, the following file names represent three different files:

    myfile.for
    MYfile.for
    MYFILE.for

You can associate a logical unit with a directory (if needed) and file name by using an environment variable assignment (see Section 7.5.7) or by using the OPEN statement (see Section 7.5.6). When an OPEN statement provides a pathname that contains only a directory (no file name) and an environment variable provides the file name, the OPEN statement and environment variable can work together to provide the complete directory and file name.

## 7.5.5 How Compaq Fortran Applies a Default Pathname and File Name

Compaq Fortran provides the following possible ways of specifying all or part of a file specification (directory and file name), such as `/usr/proj/testdata` :

- The FILE specifier in an OPEN statement typically specifies only a file name (such as `testdata` ) or contains both a directory and file name (such as `/usr/proj/testdata` ).
- The DEFAULTFILE specifier (a Compaq extension) in an OPEN statement typically specifies a pathname that contains only a directory (such as `/usr/proj/` ) or both a directory and file name (such as `/usr/proj/testdata` ).
- If you used an implied OPEN or if the FILE specifier in an OPEN statement did not specify a file name, you can use an environment variable to specify a file name or a pathname that contains both a directory and file name (see Section 7.5.7).

Compaq Fortran recognizes environment variables for each logical I/O unit number in the form of FORTn, where n is the logical I/O unit number. If a file name is not specified in the OPEN statement and the corresponding FORTn environment variable is not set for that unit number, Compaq Fortran generates a file name in the form `fort.n` , where `n` is the logical unit number.

Certain Compaq Fortran environment variables are recognized and preconnected files exist for certain unit numbers, as described in Section 7.5.7.

When using scratch files, you can use the TMPDIR environment variable to specify where the scratch file gets created (see Section 7.4.2).

Performing an implied OPEN means that the FILE and DEFAULTFILE specifier values are not specified and an environment variable is used, if present.

Examples of Applying Default Pathnames and File Names

For example, for an implied OPEN of unit number 3, Compaq Fortran would check the environment variable FORT3. If the environment variable FORT3 was set, its value is used. If it is not set, the system supplies the file name `fort.3` .

In Table 7-7, assume the current directory is `/usr/smith` and the I/O uses unit 1, as in the statement `READ (1,100)` .

Table 7-7 Examples of Applying Default Pathnames and File Names
OPEN FILE Value | OPEN DEFAULTFILE Value | FORT1 Environment Variable Value | Resulting Pathname
--- | --- | --- | ---
not specified | not specified | not specified | `/usr/smith/fort.1` (1)
not specified | not specified | `test.dat` | `/usr/smith/test.dat` (2)
not specified | not checked | `/usr/tmp/t.dat` | `/usr/tmp/t.dat` (3)
not specified | `/tmp` | not specified | `/tmp/fort.1` (4)
not specified | `/tmp` | `testdata` | `/tmp/testdata` (5)
not specified | `/usr` | `lib/testdata` | `/usr/lib/testdata` (6)
`file.dat` | `/usr/group` | not checked | `/usr/group/file.dat` (7)
`/tmp/file.dat` | not checked | not checked | `/tmp/file.dat` (8)
`file.dat` | not specified | not specified | `/usr/smith/file.dat` (9)

1. The current directory is used and the unit number determines the file name.
2. The current directory is used and the environment variable provides the file name.
3. The environment variable provides both the directory and file name.
4. The directory is provided by the OPEN DEFAULTFILE specifier value, and the unit number determines the file name.
5. The directory is provided by the OPEN DEFAULTFILE specifier value, and the environment variable provides the file name.
6. The directory is provided by the OPEN DEFAULTFILE specifier value, and the environment variable provides a subdirectory and file name.
7. The directory is provided by the OPEN DEFAULTFILE specifier value, and the file name is provided by the OPEN FILE specifier value.
8. The directory and file name are provided by the OPEN FILE specifier value.
9. The current directory is used and the OPEN FILE specifier value provides the file name.

When the resulting file pathname begins with a tilde character (~), C shell style pathname substitution is used (regardless of what shell is being used), such as a top-level directory (below the root). For additional information on tilde pathname substitution, see `csh(1)`.

Rules for Applying Default Pathnames and File Names

Compaq Fortran determines file name and the directory path based on certain rules. It determines a file name string as follows:

- If the FILE specifier is present, its value is used.
- If the FILE specifier is not present, Compaq Fortran examines the corresponding environment variable.
  - If the corresponding environment variable is set, that value is used.
  - If the corresponding environment variable is not set, a file name in the form `fort.n` is used.

Once Compaq Fortran determines the resulting file name string, it determines the directory (which optionally precedes the file name) as follows:

- If the resulting file name string contains an absolute pathname, it is used and the DEFAULTFILE specifier, environment variable, and current directory values are ignored.
- If the resulting file name string does not contain an absolute pathname, Compaq Fortran examines the DEFAULTFILE specifier and current directory value:
  - If the corresponding environment variable is set and specifies an absolute pathname, Compaq Fortran uses that value.
  - The DEFAULTFILE specifier value is examined and, if present, Compaq Fortran uses its value.
  - If the DEFAULTFILE specifier is not present, Compaq Fortran uses the current directory as an absolute pathname.

## 7.5.6 Coding File Locations in an OPEN Statement

You can use the FILE and DEFAULTFILE specifiers of the OPEN statement to specify the complete definition of a particular file to be opened on a logical unit. (The Compaq Fortran Language Reference Manual describes the OPEN statement in greater detail.) For example:

    OPEN (UNIT=4, FILE='/usr/users/smith/test.dat', STATUS='OLD')

The file `test.dat` in directory `/usr/users/smith` is opened on logical unit 4. No defaults are applied since both the directory and file name were specified. The value of the FILE specifier can be a character constant, variable, or expression.

In the following interactive example, the user supplies the file name and the DEFAULTFILE specifier supplies the default values for the full pathname string. The file to be opened is in `/usr/users/smith` and is concatenated with the file name typed by the user into the variable DOC:

         CHARACTER(LEN=9) DOC
         WRITE (6,*)  'Type file name '
         READ (5,*) DOC
         OPEN (UNIT=2, FILE=DOC, DEFAULTFILE='/usr/users/smith',STATUS='OLD')

A slash is appended to the end of the default file string if it does not have one.

For an example program that reads a typed file name, uses the typed name to open a file, and handles such errors as the "file not found" error, see Example 8-2.

## 7.5.7 Using Environment Variables

You can use the environment variable mechanism of the operating system and shells to associate logical units with external files. For example, setting the environment variable FORT6 to a file lets you redirect `stdout` to the specified file (see Table 7-5).

Compaq Fortran attempts to use certain environment variables in the absence of a file name.

When using scratch files, you can use the TMPDIR environment variable to specify where the scratch file gets created (see Section 7.4.2).

Setting and Unsetting Environment Variables

Before program execution, you can use shell commands to specify a value for an environment variable. This specified value might be a directory and/or file name of an external file you want to associate with a preconnected unit or a specific unit number.

With the C Shell, use the `setenv` command to set an environment variable:

    % setenv FORT8 /usr/users/smith/test.dat

To remove the association of an environment variable and an external file with the C shell, use the `unsetenv` command.

    % unsetenv FORT8

With the Bourne shell ( `sh` ) and Korn shell ( `ksh` ) and `bash` shell (L*X ONLY), use the `export` command and assignment command to set the environment variable:

    $ export FORT8
    $ FORT8=/usr/users/smith/test.dat

To remove the association of an environment variable and an external file with the Bourne shell or Korn shell or `bash` shell (L*X ONLY), use the `unset` command:

    $ unset FORT8

Implied Compaq Fortran Logical Unit Numbers

The ACCEPT, PRINT, and TYPE statements, and the use of an asterisk (*) in place of a unit number in READ and WRITE statements, do not include an explicit logical unit number. Each of these Fortran 95/90 statements uses an implicit internal logical unit number and environment variable. Each environment variable is in turn associated by default with one of the Fortran 95/90 file names that are associated with standard I/O files. Table 7-8 shows these relationships.

Table 7-8 Implicit Compaq Fortran Logical Units
Compaq Fortran Statement | Environment Variable When -vms Specified | Environment Variable When -vms Omitted | Standard I/O File Name
--- | --- | --- | ---
READ (*,f) iolist | FOR_READ | FORT5 | `stdin`
READ f,iolist | FOR_READ | FORT5 | `stdin`
ACCEPT f,iolist | FOR_ACCEPT | FORT5 | `stdin`
WRITE (*,f) iolist | FOR_PRINT | FORT6 | `stdout`
PRINT f,iolist | FOR_PRINT | FORT6 | `stdout`
TYPE f,iolist | FOR_TYPE | FORT6 | `stdout`

You can change the file associated with these Compaq Fortran environment variables, as you would any other environment variable, by means of the environment variable assignment command. For example, with the C shell:

    % setenv FOR_READ /usr/users/smith/test.dat

After executing the preceding command, the environment variable for the READ statement using an asterisk refers to file `test.dat` in directory `/usr/users/smith` .

For More Information:

- On a list of Compaq Fortran I/O statements, see Table 7-1.
- On the shell commands you can use to set or unset environment variables, see Appendix B.
- On record I/O, see Section 7.8.
- On Compaq Fortran I/O statements and specifier values, including defaults, see Table 7-1.
- On statement syntax, see the Compaq Fortran Language Reference Manual.
- On the ERR and IOSTAT specifiers, see Chapter 8.
- On closing files, see Section 7.7.

# 7.6 Obtaining File Information: INQUIRE Statement

The INQUIRE statement returns information about a file and has three forms:

- Inquiry by unit
- Inquiry by file name
- Inquiry by output item list

## 7.6.1 Inquiry by Unit

An inquiry by unit is usually done for an opened (connected) file. An inquiry by unit causes the Compaq Fortran RTL to check whether the specified unit is connected or not. One of the following occurs:

- If the unit is connected:
  - The EXIST and OPENED specifier variables indicate a true value
  - The pathname and file name are returned in the NAME specifier variable (if the file is named)
  - Other information requested on the previously connected file is returned
  - Default values are usually returned for the INQUIRE specifiers also associated with the OPEN statement (see Table 7-6)
  - The RECL value unit for connected formatted files is always 1-byte units. For unformatted files, the RECL unit is 4-byte units, unless you specify the `-assume byterecl` option to request 1-byte units (see Section 3.7).
- If the unit is not connected:
  - The OPENED specifier indicates a false value
  - The unit NUMBER specifier variable is returned as a value of --1
  - Any other information returned will be undefined or default values for the various specifiers

For example, the following INQUIRE statement shows whether unit 3 has a file connected (OPENED specifier) in logical variable I_OPENED, the name (case sensitive) in character variable I_NAME, and whether the file is opened for READ, WRITE, or READWRITE access in character variable I_ACTION:

    INQUIRE (3, OPENED=I_OPENED, NAME=I_NAME, ACTION=I_ACTION)

## 7.6.2 Inquiry by File Name

An inquiry by name causes the Compaq Fortran RTL to scan its list of open files for a matching file name. One of the following occurs:

- If a match occurs:
  - The EXIST and OPENED specifier variables indicate a true value.
  - The pathname and file name are returned in the NAME specifier variable.
  - The UNIT number is returned in the NUMBER specifier variable.
  - Other information requested on the previously connected file is returned.
  - Default values are usually returned for the INQUIRE specifiers also associated with the OPEN statement (see Table 7-6).
  - The RECL value unit for connected formatted files is always 1-byte units. For unformatted files, the RECL unit is 4-byte units, unless you specify the `-assume byterecl` option to request 1-byte units (see Section 3.7).
- If no match occurs:
  - The OPENED specifier variable indicates a false value.
  - The unit NUMBER specifier variable is returned as a value of --1.
  - The EXIST specifier variable indicates (true or false) whether the named file exists on the device or not.
  - If the file does exist, the NAME specifier variable contains the pathname and file name.
  - Any other information returned will be default values for the various specifiers, based on any information specified when calling INQUIRE.

The following INQUIRE statement returns whether the file named `log_file` is a file connected in logical variable I_OPEN, whether the file exists in logical variable I_EXIST, and the unit number in integer variable I_NUMBER:

    INQUIRE (FILE='log_file', OPENED=I_OPEN, EXIST=I_EXIST, NUMBER=I_NUMBER)

## 7.6.3 Inquiry by Output Item List

Unlike inquiry by unit or inquiry by name, inquiry by output item list does not attempt to access any external file. It returns the length of a record for a list of variables that would be used for unformatted WRITE, READ, and REWRITE statements (REWRITE is a Compaq Fortran extension).

The following INQUIRE statement returns the maximum record length of the variable list in variable I_RECLENGTH. This variable is then used to specify the RECL value in the OPEN statement:

    INQUIRE (IOLENGTH=I_RECLENGTH) A, B, H
    OPEN (FILE='test.dat', FORM='UNFORMATTED', RECL=I_RECLENGTH, UNIT=9)

For an unformatted file, the RECL value is returned using 4-byte units, unless you specify the `-assume byterecl` option to request 1-byte units.

For More Information:

- On the INQUIRE statement and its specifiers, see the Compaq Fortran Language Reference Manual.
- On record I/O, see Section 7.8.
- On OPEN statement specifiers, see Table 7-6.
- On the `-assume byterecl` option, see Section 3.7.

# 7.7 Closing a File: CLOSE Statement

Usually, any external file opened should be closed by the same program before it completes. The CLOSE statement disconnects the unit and its external file. You must specify the unit number (UNIT specifier) to be closed.

You can also specify:

- Whether the file should be deleted or kept (STATUS specifier)
- Error handling information (ERR and IOSTAT specifiers)

To delete a file when closing it:

- In the OPEN statement, specify the ACTION keyword (such as ACTION='READ'). Avoid using the READONLY keyword, because a file opened using the READONLY keyword cannot be deleted when it is closed.
- In the CLOSE statement, specify the keyword STATUS='DELETE'.

If you opened an external file and did an inquire by unit, but do not like the default value for the ACCESS specifier, you can close the file and then reopen it, explicitly specifying the ACCESS desired.

There usually is no need to close preconnected units. Internal files are neither opened nor closed.

For More Information:

- On a list of Compaq Fortran I/O statements, see Table 7-1.
- On opening files using a C routine (USEROPEN) and then using Compaq Fortran I/O statements, see Section 7.9.
- On OPEN statement specifiers, see Section 7.5.2.
- On statement syntax and specifier values, see the Compaq Fortran Language Reference Manual.

# 7.8 Record Operations

After you open a file or use a preconnected file, you can use the following statements:

- READ, WRITE and PRINT to perform record I/O.
- BACKSPACE, ENDFILE, REWIND to set record position within the file.
- ACCEPT, DELETE, REWRITE, TYPE, DEFINE FILE, and FIND to perform various operations. These statements are Compaq extensions.

These statements are described in Section 7.2 and in the Compaq Fortran Language Reference Manual.

The record I/O statement must use the appropriate record I/O form (formatted, list-directed, namelist, or unformatted), as described in Section 7.3.

## 7.8.1 Record I/O Statement Specifiers

You can use the following specifiers with the READ and WRITE record I/O statements:

- UNIT specifies the unit number to or from which input or output will occur.
- END specifies a label to branch to if an error occurs; only applies to input statements like READ.
- ERR specifies a label to branch to if an error occurs.
- IOSTAT specifies an integer variable to contain the IOSTAT number if an error occurs.
- FMT specifies a label of a FORMAT statement.
- NML specifies a label of a NAMELIST statement.
- REC specifies a record number for direct access.

When using nonadvancing I/O, use the ADVANCE, EOR, and SIZE specifiers, as described in Section 7.8.4.

When using the REWRITE statement (a Compaq Fortran extension), you can use the UNIT, FMT, ERR, and IOSTAT specifiers.

For More Information:

- On specifier syntax and complete information, see the Compaq Fortran Language Reference Manual.
- On available record types, see Section 7.4.3 and Section 7.10.
- On the error-related record I/O specifiers ERR, END, and IOSTAT, see Chapter 8.
- On the ADVANCE, EOR, and SIZE specifiers, see Section 7.8.4.
- Record positioning, see Section 7.8.3.
- Record I/O transfer, see Section 7.8.5.
- Record advancement, see Section 7.8.4.

## 7.8.2 Record Access Modes and File Sharing

Record access refers to how records will be read from or written to a file, regardless of its organization. Record access is specified each time you open a file; it can be different each time. The type of record access permitted is determined by the combination of file organization and record type.

For instance, you can:

- Add records to a sequential file with ORGANIZATION= `'` SEQUENTIAL `'` and POSITION= `'` APPEND `'` (or use the Compaq extension ACCESS= `'` APPEND `'` ).
- Add records sequentially by using multiple WRITE statements, close the file, and then open it again with ORGANIZATION= `'` SEQUENTIAL `'` and ACCESS= `'` SEQUENTIAL `'` (or ACCESS= `'` DIRECT `'` if the sequential file has fixed-length records).

### 7.8.2.1 Sequential Access

Sequential access transfers records sequentially to or from files or I/O devices such as terminals. You can use sequential I/O with any type of supported file organization and record type.

If you select sequential access mode for files with sequential or relative organization, records are written to or read from the file starting at the beginning of the file and continuing through it, one record after another. A particular record can be retrieved only after all of the records preceding it have been read; new records can be written only at the end of the file.

### 7.8.2.2 Direct Access

Direct access transfers records selected by record number to and from either sequential files stored on disk with a fixed-length record type or relative organization files.

If you select direct access mode, you can determine the order in which records are read or written. Each READ or WRITE statement must include the relative record number, indicating the record to be read or written.

You can directly access a sequential disk file only if it contains fixed-length records. Because direct access uses cell numbers to find records, you can enter successive READ or WRITE statements requesting records that either precede or follow previously requested records. For example, the first of the following statements reads record 24; the second reads record 10:

    READ (12,REC=24) I
    READ (12,REC=10) J

### 7.8.2.3 Limitations of Record Access by File Organization and Record Type

You can use both access modes on sequential and relative files. However, direct access to a sequential organization file can only be done if the file resides on disk and contains fixed-length records.

Table 7-9 summarizes the types of access permitted for the various combinations of file organizations and record types.

Table 7-9 Allowed Record Access for File Organizations and Record Types
Organization | Record Type | Sequential Access | Direct Access
--- | --- | --- | ---
Sequential file | Fixed Variable Segmented Stream Stream_CR Stream_LF | Yes Yes Yes Yes Yes Yes | Yes 1 No No No No No
Relative file 1 | Fixed | Yes | Yes

1Direct access and relative files require that the file resides on a disk device.

### 7.8.2.4 File Sharing

Depending on the value specified by the ACTION (or READONLY) specifier in the OPEN statement, the file will be opened by your program for reading, writing, or both reading and writing records. This simply checks that the program itself executes the type of statements intended.

For performance reasons, record-locking and shared-file checking are not supported by the current version of Compaq Fortran on Compaq Tru64 UNIX and Linux systems. When you open the file, access is always granted, regardless of whether:

- The OPEN statement SHARED specifier was specified
- Other processes have already opened the file

Similarly, the UNLOCK statement is ignored using the current version of Compaq Fortran.

You might open a file for writing records (or reading and writing records) and know another process might simultaneously have the file open and be writing records. In this case, you need to coordinate access times among those processes to handle the possibility of simultaneous WRITE and REWRITE statements on the same record positions.

## 7.8.3 Specifying the Initial Record Position

When you open a disk file, you can use the OPEN statement's POSITION specifier to request one of the following initial record positions within the file:

- The initial position before the first record (POSITION= `'` REWIND `'` ). A sequential access READ or WRITE statement will read or write the first record in the file.
- A point beyond the last record in the file (POSITION= `'` APPEND `'` ), just before the end-of-file record, if one exists. For a new file, this is the initial position before the first record (same as `'` REWIND `'` ). You might specify `'` APPEND `'` before you write records to an existing sequential file using sequential access.
- The current position (ASIS). This is usually used only to maintain the current record position when reconnecting a file. The second OPEN specifies the same unit number and specifies the same file name (or omits it), which leaves the file open, retaining the current record position.
  However, if the second OPEN specifies a different file name for the same unit number, the file will be closed and then opened, causing a loss of current record position.

The following I/O statements allow you to change the current record position:

- REWIND sets the record position to the initial position before the first record. A sequential access READ or WRITE statement would read or write the first record in the file.
- BACKSPACE sets the record position to the previous record in a file. Using sequential access, if you wrote record 5, issued a BACKSPACE to that unit, and then read from that unit, you would read record 5.
- ENDFILE writes an end-of-file marker. This is typically done after writing records using sequential access just before you close the file.

Unless you use nonadvancing I/O (see Section 7.8.4), reading and writing records usually advances the current record position by one record. As discussed in Section 7.8.5, more than one record might be transferred using a single record I/O statement.

## 7.8.4 Advancing and Nonadvancing Record I/O

After you open a file, if you omit the ADVANCE specifier (or specify ADVANCE= `'` YES `'` ) in READ and WRITE statements, advancing I/O (normal FORTRAN-77 I/O) will be used for record access. When using advancing I/O:

- Record I/O statements transfer one entire record (or multiple records).
- Record I/O statements advance the current record position to a position before the next record.

You can request nonadvancing I/O for the file by specifying the ADVANCE= `'` NO `'` specifier in a READ and WRITE statement. You can use nonadvancing I/O only for sequential access to external files using formatted I/O (not list-directed or namelist).

When you use nonadvancing I/O, the current record position does not change, and part of the record might be transferred, unlike advancing I/O where one entire record or records are always transferred.

You can alternate between advancing and nonadvancing I/O by specifying different values for the ADVANCE specifier ( `'` YES `'` and `'` NO `'` ) in the READ and WRITE record I/O statements.

When reading records with either advancing or nonadvancing I/O, you can use the END branch specifier to branch to a specified label when the end of the file is read.

Because nonadvancing I/O might not read an entire record, it also supports an EOR branch specifier to branch to a specified label when the end of the record is read. If you omit the EOR and the IOSTAT specifiers when using nonadvancing I/O, an error results when the end-of-record is read.

When using nonadvancing input, you can use the SIZE specifier to return the number of characters read. For example, in the following READ statement, SIZE=X (where variable X is an integer) returns the number of characters read in X and an end-of-record condition causes a branch to label 700:

    150 FORMAT (F10.2, F10.2, I6)
        READ (UNIT=20, FMT=150, SIZE=X, ADVANCE='NO', EOR=700) A, F, I

## 7.8.5 Record Transfer

I/O statements transfer all data as records. The amount of data that a record can contain depends on the following circumstances:

- With formatted I/O (except for fixed-length records), the number of items in the I/O statement and its associated format specifier jointly determine the amount of data to be transferred.
- With namelist and list-directed output, the items listed in the NAMELIST statement or I/O statement list (in conjunction with the NAMELIST or list-directed formatting rules) determine the amount of data to be transferred.
- With unformatted I/O (except for fixed-length records), the I/O statement alone specifies the amount of data to be transferred.
- When you specify fixed-length records (RECORDTYPE= `'` FIXED `'` ), all records are the same size. If the size of an I/O record being written is less than the record length (RECL), extra bytes are added (padding).

Typically, the data transferred by an I/O statement is read from or written to a single record. It is possible, however, for a single I/O statement to transfer data from or to more than one record, depending on the form of I/O used.

### 7.8.5.1 Input Record Transfer

When using advancing I/O, if an input statement specifies fewer data fields (less data) than the record contains, the remaining fields are ignored.

If an input statement specifies more data fields than the record contains, one of the following occurs:

- For formatted input using advancing I/O, if the file was opened with PAD= `'` YES `'` , additional fields are read as spaces. If the file is opened with PAD= `'` NO `'` , an error occurs (the input statement should not specify more data fields than the record contains).
  For formatted input using nonadvancing I/O (ADVANCE= `'` NO `'` ), an end-of-record (EOR) condition is returned. If the file was opened with PAD= `'` YES `'` , additional fields are read as spaces.
- For list-directed input, another record is read.
- For namelist input, another record is read.
- For unformatted input, an error occurs.

### 7.8.5.2 Output Record Transfer

If an output statement specifies fewer data fields than the record contains (less data than required to fill a record), the following occurs:

- With fixed-length records (RECORDTYPE= `'` FIXED `'` ), all records are the same size. If the size of an I/O record being written is less than the record length (RECL), extra bytes are added (padding) in the form of spaces (for a formatted record) or zeros (for an unformatted record).
- With other record types, the fields present are written and those omitted are not written (might result in a short record).

If the output statement specifies more data than the record can contain, an error occurs, as follows:

- With formatted or unformatted output using fixed-length records.
  If the items in the output statement and its associated format specifier result in a number of bytes that exceed the maximum record length (RECL), an error occurs.
- With formatted or unformatted output not using fixed-length records.
  If the items in the output statement and its associated format specifier result in a number of bytes that exceed the maximum record length (RECL), the Compaq Fortran RTL attempts to increase the RECL value and write the longer record. To obtain the RECL value, use an INQUIRE statement.
- For list-directed output and namelist output, if the data specified exceeds the maximum record length (RECL), another record is written.

For More Information:

- On Compaq Fortran I/O statements, see Table 7-1.
- On record I/O specifiers, see Section 7.8.1.
- On statement syntax and specifier values, see the Compaq Fortran Language Reference Manual.
- On improving Compaq Fortran I/O performance, see Section 5.6.

# 7.9 User-Supplied OPEN Procedures: USEROPEN Specifier

You can use the USEROPEN specifier in a Compaq Fortran OPEN statement to pass control to a routine that directly opens a file. The called routine can use system calls or library routines to open the file and establish special context that changes the effect of subsequent Compaq Fortran I/O statements.

The Compaq Fortran Run-Time Library (RTL) I/O support routines call the USEROPEN function in place of the system calls usually used when the file is first opened for I/O. The USEROPEN specifier in an OPEN statement specifies the name of a function to receive control. The called function must open the file (or pipe) and return the file descriptor of the file when it returns control to the calling Compaq Fortran program.

When opening the file, the called function usually specifies options different from those provided by a normal OPEN statement.

You can obtain the file descriptor from the Compaq Fortran Run-Time Library (RTL) for a specific unit number with the `getfd` routine, described in `getfd(3f)`.

Although the called function can be written in other languages (such as Fortran), C is usually the best choice for making system calls, such as `open` or `create` .

The USEROPEN specifier for the OPEN statement has the form:

    USEROPEN = function-name

The function-name value represents the name of an external open function. In the calling Compaq Fortran program, the function must be declared in an EXTERNAL statement. For example, the following Compaq Fortran code might be used to call the USEROPEN procedure UOPEN (known to the linker as `uopen_` ):

    EXTERNAL  UOPEN
    INTEGER   UOPEN
    .
    .
    .
    OPEN (UNIT=10, FILE='/usr/test/data', STATUS='NEW', USEROPEN=UOPEN)

After the OPEN statement, the uopen_ function receives control. The function opens the file, may perform other operations, and subsequently returns control (with the file descriptor) to the calling Compaq Fortran program.

If the USEROPEN function is written in C, declare it as a C function that returns a 4-byte integer (int) result to contain the file descriptor. For example:

    int   uopen_ (                (1)
          char  *file_name,       (2)
          int   *open_flags,      (3)
          int   *create_mode,     (4)
          int   *lun,             (5)
          int   file_length);     (6)

The function definition and the arguments passed from the Compaq Fortran RTL are as follows:

1. The function must be declared as a 4-byte integer (int).
2. The first argument is the pathname (includes the file name) to be opened.
3. The open flags are described in the header file `/usr/include/sys/file.h` or `open(2)`.
4. The create mode (protection needed when creating a file), is described in `open(2)`.
5. The logical unit number.
6. The fifth (last) argument is the pathname length (hidden length argument of the pathname).

Of the arguments, the `open` system call (see `open(2)`) requires the passed pathname, the open flags (that define the type access needed, whether the file exists, and so on), and the create mode. The logical unit number specified in the Compaq Fortran OPEN statement is passed in case the called function needs it. The hidden length of the pathname is also passed.

When creating a new file, the `create` system call might be used in place of `open` (see `create(2)`). You can usually use other appropriate system calls or library routines within the called function; restrictions are listed in Section 7.9.1.

In most cases, the called function modifies the open flags argument passed by the Compaq Fortran RTL or uses a new value before the `open` (or `create` ) system call. After the called function opens the file, it must return control to the main Compaq Fortran program, which can do I/O with Fortran 95/90 statements to the file.

The `open` system call returns the file descriptor, which must be returned as a 4-byte integer to the Compaq Fortran program (and Compaq Fortran RTL). After control (and the file descriptor) is returned from the called function, the main Compaq Fortran program can perform I/O to that logical unit with Fortran 95/90 statements and eventually close it.

If the USEROPEN function is written in Fortran, declare it as a FUNCTION with an INTEGER (KIND=4) result, perhaps with an interface block. In any case, the called function must return the file descriptor as a 4-byte integer to the calling Compaq Fortran program.

If your application requires that you use C to perform the file open and close, as well as all record operations, call the appropriate C procedure from the Compaq Fortran program without using the Fortran OPEN statement. For more information on calling between Fortran and C, see Section 11.3.

## 7.9.1 Restrictions of Called USEROPEN Functions

The Compaq Fortran RTL uses exactly one file descriptor per logical unit, which must be returned by the called function. Because of this, only certain Compaq Tru64 UNIX system calls or library routines can be used to open the file.

System calls and library routines that do not return a file descriptor include `mknod` (see `mknod(2)`) and `fopen` (see `fopen(3)`). For example, the `fopen` routine returns a file pointer instead of a file descriptor.

## 7.9.2 Example USEROPEN Program and Function

The following Compaq Fortran code calls the USEROPEN function named UOPEN:

    EXTERNAL  UOPEN
    INTEGER   UOPEN
      .
      .
      .
    OPEN (UNIT=1,FILE='ex1.dat',STATUS='NEW',USEROPEN=UOPEN, ERR=9,IOSTAT=errnum)

If the default `f90` options are used, the external name is passed using lowercase letters with an appended trailing underscore (_). In the preceding example, the external function UOPEN would be known as uopen_ to the linker and must be declared in C as uopen_. The function might be given the file name `uopen_.c` .

Compiling and Linking the C and Compaq Fortran Programs

Use a single `f90` command to compile the called uopen_ C function `uopen_.c` and the Compaq Fortran calling program `ex1.f` . The same command also links both object files by using the appropriate libraries to create the file `a.out` file, as follows:

    % f90 ex1.f uopen_.c

If appropriate for large applications, you can specify object modules ( `.o` files) on the `f90` command line. For more information on retaining object files, see Section 2.1.5.

Source Code for the C Function and Header File

Example 7-1 shows the C language function called `uopen_` and its associated header file.

Example 7-1 C Function Called by USEROPEN Procedure

    /*
    ** File: uopen.h -- header file for uopen_.c
    */

    #ifndef UOPEN
    #define UOPEN 1

    /*
    **
    **    Function Prototypes
    **
    */
    int   uopen_ (
          char  *file_name,    /* access read: name of the file to open. */
          int   *open_flags,   /* access read: READ/WRITE, see file.h or open(2)*/
          int   *create_mode,  /* access read: set if new file (to be created).*/
          int   *lun,          /* access read: logical unit file opened on.*/
          int  file_length);   /* access read: number of characters in file_name*/

    #endif

    /* End of file uopen.h */

    /*
    ** File: uopen_.c
    */

    /*
    ** This routine opens a file using data passed by Compaq Fortran RTL.
    **
    **  INCLUDE FILES
    */

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/file.h>
    #include "uopen.h"/* Include file for this module */

    int uopen_ (file_name, open_flags, create_mode, lun, file_length)

    /*
    ** Open a file using the parameters passed by the calling Compaq
    **   Fortran 95/90 program.
    **
    **  Formal Parameters:
    */

    char  *file_name;    /* access read: name of the file to open. */
    int   *open_flags;   /* access read: READ/WRITE, see file.h */
    int   *create_mode;  /* access read: set if new file (to be created). */
    int   *lun;          /* access read: logical unit number file opened on. */
    int   file_length;   /* access read: number of characters in file_name. */

    /*
    **  Function Value/Completion Code
    **
    ** Whatever is returned by open, is immediately returned to the
    ** Fortran OPEN.  the returned value is the following :
    **    value >= 0 is a valid fd.
    **    value <  0 is an error.
    **
    **  Modify open flags (logical OR) to specify the file be opened for
    **  write access only, with records appended at the end (such as
    **  writing to a shared log file).
    */

    {
           int    result ;           /* Function result value */

           *open_flags =
                 O_CREAT  |
                 O_WRONLY |
                 O_APPEND;

           result = open (file_name, *open_flags, *create_mode) ;

           return (result) ;         /* return file descriptor or error */

           }/* End of routine uopen_ */

           /* End of file uopen_.c */

Source Code for the Calling Compaq Fortran Program

Example 7-2 shows the Fortran 95/90 program that calls the uopen_ C function and then performs I/O.

Example 7-2 Compaq Fortran USEROPEN Main Calling Program

    C
    C  Program EX1 opens a file using USEROPEN and writes records to it.
    C  It closes and re-opens the file (without USEROPEN) and reads 10 records.

     PROGRAM EX1

         EXTERNAL    UOPEN         ! The USEROPEN function.
         INTEGER     ERRNUM, CTR, I

     1   FORMAT (I)

         ERRNUM = 0

         WRITE (6,*) 'EX1. Access data using formatted I/O.'
         WRITE (6,*) 'EX1. Open file with USEROPEN and put some data in it.'
         OPEN (UNIT=1, FILE='ex1.dat', STATUS='NEW', USEROPEN=UOPEN, ERR=9, &
              IOSTAT=errnum)

         DO CTR=1,10
           WRITE (1,1) CTR
         END DO

         WRITE (6,*) 'EX1. Close and re-open without USEROPEN.'

         CLOSE (UNIT=1)

         OPEN (UNIT=1, FILE='ex1.dat', STATUS='OLD', FORM='FORMATTED', ERR=99, &
              IOSTAT=errnum)

         WRITE (6,*) 'EX1. Read and display what is in file.'

         DO CTR=1,10
            READ (1,1) i
            WRITE (6,*) i
         END DO

         WRITE (6,*) 'EX1.  Successful if 10 records shown.'

         CLOSE (UNIT=1,STATUS='DELETE')
         STOP

       9 WRITE (6,*) 'EX1.  Error on USEROPEN is ', errnum
         STOP

      99 WRITE (6,*) 'EX1.  Error on 2nd open is ', errnum

     END PROGRAM EX1

# 7.10 Format of Compaq Fortran Record Types

For general information, see Section 7.4.3, Record Types, Record Overhead, and Maximum Record Length and Table 7-3, Compaq Fortran Record Types.

## 7.10.1 Fixed-Length Records

When you specify fixed-length records, all records in the file contain the same number of bytes. When you open a file that is to contain fixed-length records, you must specify the record size by using the RECL specifier. A sequentially organized file opened for direct access must contain fixed-length records, to allow the record position in the file to be computed correctly.

For relative files, the layout and overhead of fixed-length records depends on whether the program accessing the file was compiled with the `-vms` option or whether the `-vms` option was omitted:

- For relative files where the `-vms` option was omitted (the default), each record has no control information.
- For relative files where the `-vms` option was specified, each record has one byte of control information at the beginning of the record.

Figure 7-1 shows the record layout of fixed-length records.

Figure 7-1 Fixed-Length Records

For More Information:

- On the default value and size limit for fixed-length records, see the RECL specifier for the OPEN statement in the Compaq Fortran Language Reference Manual.

## 7.10.2 Variable-Length Records

Variable-length records can contain any number of bytes up to a specified maximum record length, and apply only to sequential files.

Variable-length records are prefixed and suffixed by four bytes of control information containing length fields. The trailing length field allows a BACKSPACE request to skip back over records efficiently. The 4-byte integer value stored in each length field indicates the number of data bytes (excluding overhead bytes) in that particular variable-length record.

The character count field of a variable-length record is available when you read the record by issuing a READ statement with a Q format descriptor. You can then use the count field information to determine how many bytes should be in an I/O list.

The record layout of variable-length records that are less than two gigabytes appears in Figure 7-2.

Figure 7-2 Variable-Length Records Less Than 2 Gigabytes

For a record length greater than 2,147,483,639 bytes, the record is divided into subrecords. The subrecord can be of any length from 1 to 2,147,483,639, inclusive.

The sign bit of the leading length field indicates whether the record is continued or not. The sign bit of the trailing length field indicates the presence of a preceding subrecord. The position of the sign bit is determined by the endian format of the file.

A subrecord that is continued has a leading length field with a sign bit value of 1. The last subrecord that makes up a record has a leading length field with a sign bit value of 0. A subrecord that has a preceding subrecord has a trailing length field with a sign bit value of 1. The first subrecord that makes up a record has a trailing length field with a sign bit value of 0.

The record layout of variable-length records that are greater than two gigabytes appears in Figure 7-3.

Figure 7-3 Variable-Length Records Greater Than 2 Gigabytes

Files written with variable-length records by Compaq Fortran programs usually cannot be accessed as text files. Instead, use the Stream_LF record format for text files with records of varying length.

## 7.10.3 Segmented Records

A segmented record is a single logical record consisting of one or more variable-length, unformatted records in a sequentially organized disk file. Unformatted data written to sequentially organized files using sequential access is stored as segmented records by default.

Segmented records are useful when you want to write exceptionally long records but cannot or do not wish to define one long variable-length record, perhaps because virtual memory limitations can prevent program execution. By using smaller, segmented records, you reduce the chance of problems caused by virtual memory limitations on systems on which the program may execute.

For disk files, the segmented record is a single logical record that consists of one or more segments. Each segment is a physical record. A segmented (logical) record can exceed the absolute maximum record length (2.14 billion bytes), but each segment (physical record) individually cannot exceed the maximum record length.

To access an unformatted sequential file that contains segmented records, specify FORM= `'` UNFORMATTED `'` and RECORDTYPE= `'` SEGMENTED `'` when you open the file. Otherwise, the file may be processed erroneously.

As shown in Figure 7-4, the layout of segmented records consists of four bytes of control information followed by the user data.

Figure 7-4 Segmented Records

The control information consists of a 2-byte integer record size count (includes the two bytes used by the segment identifier), followed by a 2-byte integer segment identifier that identifies this segment as one of the following:

Identifier Value | Segment Identified
--- | ---
0 | One of the segments between the first and last segments.
1 | First segment.
2 | Last segment.
3 | Only segment.

If the specified record length is an odd number, the user data will be padded with a single blank (one byte), but this extra byte is not added to the 2-byte integer record size count.

## 7.10.4 Stream File Data

A Stream file is not grouped into records and contains no control information. Stream files are used with CARRIAGECONTROL= `'` NONE `'` and contain character or binary data that is read or written only to the extent of the variables specified on the input or output statement.

The layout of a Stream file appears in Figure 7-5.

Figure 7-5 Stream File Records

## 7.10.5 Stream_CR and Stream_LF Records

A Stream_CR or Stream_LF record is a variable-length record whose length is indicated by explicit record terminators embedded in the data, not by a count. These terminators are automatically added when you write records to a stream-type file and are removed when you read records.

Each variety uses a different 1-byte record terminator:

- Stream_CR files use only a carriage-return as the terminator, so Stream_CR files must not contain embedded carriage-return characters.
- Stream_LF files use only a line-feed (new line) as the terminator, so Stream_LF files must not contain embedded line-feed (new line) characters. This is the usual operating system text file record type.

The layout of Stream_CR and Stream_LF records appears in Figure 7-6.

Figure 7-6 Stream_CR and Stream_LF Records

Previous | Next | Contents | Index