Index of Topics
- - $ -
- $ or \ Editing (Extension)
- A -
- Absolute Value
Actual Arguments
Actual Arguments for a Subroutine
Actual Arguments for an External Function
Actual Array Declarator
Adjustable Array Declarator
ADMIT Statement
Allocatable Array Declarator
ALLOCATE Statement
Allocated Array
Apostrophe Editing
Arccosine
Arcsine
Arctangent
Arithmetic Assignment
Arithmetic Constant Expression
Arithmetic Expressions
Arithmetic IF Statement
Arithmetic Operators
Arithmetic Relational Expressions
Array Elements
Arrays
Arrays as Dummy Arguments
Arrays of Records
Assigned GO TO Statement
Assignment Statements
Association of Actual and Dummy Arguments
Assumed-size Array Declarator
Asterisks as Dummy Arguments
AT END
AT END Statement
- B -
- BACKSPACE Statement
Binary Pattern Processing Functions: Arithmetic Shift
Binary Pattern Processing Functions: Arithmetic Shifts
Binary Pattern Processing Functions: Bit Testing
Binary Pattern Processing Functions: Boolean AND
Binary Pattern Processing Functions: Boolean Complement
Binary Pattern Processing Functions: Boolean Exclusive OR
Binary Pattern Processing Functions: Boolean Inclusive OR
Binary Pattern Processing Functions: Change Bit
Binary Pattern Processing Functions: Circular Shift
Binary Pattern Processing Functions: Clear Bit
Binary Pattern Processing Functions: Logical Shift
Binary Pattern Processing Functions: Set Bit
BLOCK DATA Statement
Block IF Statement
Block WHILE Statement
BN and BZ Editing
- C -
- CALL Statement
CASE Statement
Character Assignment
Character Constant
Character Constant Expressions
Character Expressions
Character Operators
Character Relational Expressions
Character Set
CHARACTER Statement
Character Substrings
Choosing Largest Value
Choosing Smallest Value
Classifying Array Declarators by Array Name
Classifying Array Declarators by Dimension Declarator
Classifying Statements
CLOSE Statement
Colon Editing
Comment Line
Common Logarithm
COMMON Statement
Complement of Error Function
Complex Constant
Complex Editing
COMPLEX Statement
Computed GO TO Statement
Conjugate of a Complex Number
Constant Array Declarator
Constant Expressions
Constants
Continuation Line
CONTINUE Statement
Cosine
Cotangent
CYCLE
CYCLE Statement
- D -
- DATA Statement
Data Type of a Name
Data Type of Arithmetic Expressions
Data Types
DEALLOCATE Statement
Debug Line (Extension)
Definition Status of Specifiers - Inquire by File
Definition Status of Specifiers - Inquire by Unit
Description of DO Statement
Description of IMPLICIT Statement
Description of PRINT Statement
Description of READ Statement
DIMENSION Statement
DO - END DO
DO Statement
DO WHILE - END DO
DO WHILE Statement
DOUBLE COMPLEX Statement
DOUBLE COMPLEX Statement: Data Initialization
Double Precision Complex Constant (Extension)
Double Precision Constant
Double Precision Product
DOUBLE PRECISION Statement
Dummy Arguments
Dummy Array Declarator
- E -
- E and D Editing
A Edit Descriptor
Editing
ELSE IF
ELSE IF Statement
ELSE Statement
END AT END Statement
END BLOCK Statement
END DO Statement
END GUESS Statement
END IF Statement
END LOOP Statement
END MAP Statement
END SELECT Statement
END Statement
END STRUCTURE Statement
END UNION Statement
END WHILE Statement
End-of-File Specifier
Endfile Record
ENDFILE Statement
ENTRY Statement
The ENTRY Statement
ENTRY Statement Restrictions
ENTRY Statements in External Functions
EQUIVALENCE Statement
Error Function
Error Specifier
Evaluating Expressions
Examples
EXECUTE and REMOTE BLOCK
EXECUTE Statement
EXIT
EXIT Statement
Exponential
Expressions
Extended Assignment Statement
Extended Block IF Statement
Extended Character Set
Extended CHARACTER Statement: Data Initialization
Extended COMPLEX Statement: Data Initialization
Extended COMPLEX Statement: Length Specification
Extended DO Statement
Extended DOUBLE PRECISION Statement: Data Initialization
Extended FUNCTION Statement
Extended IMPLICIT Statement
Extended INTEGER Statement: Data Initialization
Extended INTEGER Statement: Length Specification
Extended LOGICAL Statement: Data Initialization
Extended LOGICAL Statement: Length Specification
Extended PRINT Statement
Extended READ Statement
Extended REAL Statement: Data Initialization
Extended REAL Statement: Length Specification
Extensions
External Files
External Function Subprogram Restrictions
External Functions
EXTERNAL Statement
- F -
- F Editing
Files
Floating-point Editing: F, E, D and G Edit Descriptors
Form of a Relational Expression
Format
FORMAT as a Character Expression
Format Specification
Format Specifier
FORMAT Statement
The FORMAT Statement
Format-Directed Input/Output
Formatted Record
FORTRAN Source Program Format
FORTRAN Statement Summary
FORTRAN Statements
FUNCTION Statement
Functions and Subroutines
- G -
- G Editing
Gamma Function
GUESS Statement
GUESS-ADMIT-END GUESS
- H -
- H Editing
Hexadecimal Constants (Extension)
Hollerith Constants (Extension)
Hyperbolic Cosine
Hyperbolic Sine
Hyperbolic Tangent
- I -
- IF - ELSE - END IF
Imaginary Part of Complex Number
IMPLICIT NONE Statement
IMPLICIT Statement
INCLUDE Statement
Index of a Substring
Initial Line
Input/Output
Input/Output Status Specifier
INQUIRE by FILE
INQUIRE by UNIT
INQUIRE Statement
Inquiry Specifiers
Integer Constants
Integer Editing: Iw and Iw.m Edit Descriptors
INTEGER Statement
Internal Files
Intrinsic Functions
INTRINSIC Statement
- L -
- L Edit Descriptor
Length
Length of Character Actual and Dummy Arguments
Length Without Trailing Blanks
Lexically Greater Than
Lexically Greater Than or Equal
Lexically Less Than
Lexically Less Than or Equal
List-Directed Formatting
List-Directed Input
List-Directed Output
Logical Assignment
Logical Constant
Logical Constant Expressions
Logical Expressions
Logical IF Statement
Logical Operators
LOGICAL Statement
LOOP - END LOOP
LOOP Statement
- M -
- MAP Statement
Memory Location
- N -
- NAMELIST Statement
Namelist-Directed Formatting (Extension)
Namelist-Directed Input (Extension)
Namelist-Directed Output
Names, Data Types and Constants
Natural Log of Gamma Function
Natural Logarithm
Nearest Integer
Nearest Whole Number
Nonrepeatable Edit Descriptors
Notes on Structured Programming Statements
Numeric Editing: I, F, E, D and G Edit Descriptors
- O -
- Octal Constants (Extension)
OPEN Statement
Open Watcom FORTRAN 77 Extensions to Standard FORTRAN 77
Order of FORTRAN Statements and Lines
OTHERWISE Statement
- P -
- P Editing
PARAMETER Statement
PAUSE Statement
Positional Editing: T, TL, TR and X Editing
Positive Difference
PRINT Statement
Printing of Formatted Records
Procedures as Dummy Arguments
PROGRAM Statement
Program Structure Control Statements
Properties of Arrays
- Q -
- QUIT
QUIT Statement
- R -
- READ Statement
Reading and Writing
Real Constants
REAL Statement
Record Specifier
RECORD Statement
Records
Referencing a Statement Function
Referencing a Subroutine: The CALL Statement
Referencing an External Function
Relational Expressions
Relational Operators
Remainder
REMOTE BLOCK Statement
Repeatable Edit Descriptors
RETURN Statement
The RETURN Statement
RETURN Statement in Function Subprograms
RETURN Statement in Subroutine Subprograms
RETURN Statement in the Main Program (Extension)
REWIND Statement
Rules for Forming Character Expressions
Rules for Forming Logical Expressions
Rules for Forming Standard Arithmetic Expressions
- S -
- S, SP and SS Editing
SAVE Statement
SELECT - END SELECT
SELECT Statement
Significance of Lower Case Characters (Extension)
Significance of the Blank Character
Simple DOUBLE COMPLEX Statement
Sine
Size of Variable or Structure
Slash Editing
Source Program Format
Specific Names and Generic Names of Intrinsic Functions
Specifiers
Square Root
Standard Block IF Statement
Standard CHARACTER Statement
Standard COMPLEX Statement
Standard DO Statement
Standard DOUBLE PRECISION Statement
Standard FUNCTION Statement
Standard IMPLICIT Statement
Standard INTEGER Statement
Standard LOGICAL Statement
Standard PRINT Statement
Standard READ Statement
Standard REAL Statement
Statement Function Restrictions
Statement Functions
Statement Label Assignment
Statement Label Assignment (ASSIGN) Statement
STOP Statement
String Constant (Extension)
STRUCTURE Statement
Structures and Records
Structures, Unions and Records
Subprogram Arguments
SUBROUTINE Statement
Subroutine Subprogram Restrictions
Subroutines
Substring Names
Symbolic Constants
Symbolic Names
- T -
- Tangent
Transfer of Sign
Truncation
Type Conversion: Character conversion to integer
Type Conversion: Conversion to character
Type Conversion: Conversion to complex
Type Conversion: Conversion to double complex
Type Conversion: Conversion to double precision
Type Conversion: Conversion to integer
Type Conversion: Conversion to real
- U -
- Unconditional GO TO Statement
Unformatted Record
UNION Statement
Unions
The Unit Specifier
Units
UNTIL
UNTIL Statement
Use of Array Names
- V -
- Variables as Dummy Arguments
Volatile Reference
VOLATILE Statement
- W -
- WHILE - END WHILE
WHILE - Executable-statement
WHILE Statement
WRITE Statement
- Z -
- Z Editing (Extension)
The following sections describe input rules for FORTRAN source programs.
Character Set
The FORTRAN character set consists of twenty-six letters, ten digits, and thirteen special characters.
The letters are:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
The digits are: 0 1 2 3 4 5 6 7 8 9
The special characters are:
+-----------+-----------------------+
| Character | Name of Character |
+-----------+-----------------------+
| | Blank
|
| = | Equals
|
| + | Plus
|
| - | Minus
|
| * | Asterisk
|
| / | Slash
|
| ( | Left Parenthesis
|
| ) | Right Parenthesis
|
| , | Comma
|
| . | Decimal Point
|
| $ | Currency Symbol
|
| ' | Apostrophe
|
| : | Colon
|
+-----------+-----------------------+
The FORTRAN character set is a subset of the character set of the computing system which you are using. We shall
refer to the larger character set as the processor character set.
Extended Character Set
Open Watcom FORTRAN 77 also includes the following special characters.
+-----------+-----------------------+
| Character | Name of Character |
+-----------+-----------------------+
| ! | Exclamation Mark
|
| % | Percentage Symbol
|
| \ | Back slash
|
+-----------+-----------------------+
Open Watcom FORTRAN 77 supports one source program format. A FORTRAN program is composed of lines.
There are three types of lines; the comment line, the initial line, and the continuation line.
Comment lines are denoted by placing a "C" or "*" in column one of the line. Open Watcom
FORTRAN 77 also allows the use of a lowercase "c" as a comment indicator. Blank lines are treated
as comment lines. Comment lines may be placed anywhere in the program source (i.e., they may appear before a FORTRAN
statement, they may be intermingled with continuation lines, or they may appear after a statement). There is no restriction
on the number of comment lines. Comment lines may contain any characters from the processor character set.
Open Watcom FORTRAN 77 allows end-of-line comments. If a "!" character appears in column 1 or anywhere
in the statement portion of a source line, the remainder of that line is treated as a comment unless the "!" appears
inside quotation marks or in column 6.
Debug Line (Extension)
Debug lines are denoted by placing a "D" or "d" in column one of the line. Debug lines
contain FORTRAN statements. There is no restriction on the number of debug lines. Normally, the FORTRAN statements
on debug lines are ignored by the compiler. See the User's Guide for information on activating debug statements.
Initial Line
An initial line is the first line of a FORTRAN statement. Column 6 of this line must be blank or contain
the digit "0". A comment line can never be an initial line. Columns 1 through 5 of an initial line
may contain a statement label. Statement labels are composed entirely of digits. The statement label may
be thought of as an integral number and, as such, leading 0 digits are not significant. For example, the label composed
of the digits "00123" is the same as the label "123". The same label may not identify more than
one statement in a program unit. A program unit is a series of comment lines and FORTRAN statements ending in
an END statement. The body of the FORTRAN statement is entered starting in column 7 and stopping at
column 72. Column 73 and on is called the sequence field and is ignored by the compiler.
Continuation Line
A statement may be continued on a new line. A continuation character is placed in column 6. The continuation
character may not be a blank character or a "0" character. FORTRAN 77 requires that the continuation character
be selected from the FORTRAN character set but Open Watcom FORTRAN 77 allows any character from the processor's character
set. The statement number field must be blank. The previous statement is continued on the new line, starting
in column 7 and continuing to column 72. Under the control of a compiler option, Open Watcom FORTRAN 77 permits the
source statement to extend to column 132.
FORTRAN 77 allows up to 19 continuation lines to continue a statement. Open Watcom FORTRAN 77 extends this by
allowing more than 19 continuation lines. A minimum of 61 continuation lines are permitted when the source statement
ends at column 72. A minimum of 31 continuation lines are permitted when the source statement ends at column 132.
The maximum number of continuation lines depends on the sum of the lengths of all the continuation lines.
Significance of the Blank Character
Except in the following cases, blank characters have no meaning within a program unit.
- (1)
- Character and Hollerith constants.
(2)
- Apostrophe and H edit descriptors in format specifications.
For example, the symbolic name A B is the same as the symbolic name AB.
Significance of Lower Case Characters (Extension)
Except in the following cases, lower case characters are treated as if they were the upper case equivalent. This
is a Open Watcom FORTRAN 77 extension to the usual rules of FORTRAN.
- (1)
- Character and Hollerith constants.
(2)
- Apostrophe and H edit descriptors in format specifications.
Hence, TOTAL, total, and Total represent the same symbolic name and 3F10.2 and
3f10.2 represent the same format edit descriptor.
Examples
Example:
C This and the following five lines are comment lines.
c The following statement "INDEX = INDEX + 2" has a
c statement number and is continued by placing a "$"
c in column 6.
* Column Numbers
*234567890
10 INDEX = INDEX
$ + 2
* The above blank lines are treated like comment lines.
The following example demonstrates the use of comment lines, blanks lines, and continuation lines. We use the
symbol "$" to denote continuation lines although any character other than a blank or "0" could have been
used.
Example:
* From the quadratic equation
*
* 2
* ax + bx + c = 0
*
* we derive the following two equations:
* ____________
* + / 2
* -b - \/ b - 4ac
* x = ---------------------
* 2a
*
* and express these equations in FORTRAN as:
X1 = ( -B + SQRT( B**2 - 4 * A * C ) )
$ /
( 2 * A )
X2 = ( -B - SQRT( B**2 - 4 * A * C ) )
$ /
( 2 * A )
Order of FORTRAN Statements and Lines
The first statement of a program unit may be a PROGRAM, FUNCTION, SUBROUTINE, or BLOCK
DATA statement. The PROGRAM statement identifies the start of a main program and there may only be one
of these in an executable FORTRAN program. Execution of a FORTRAN program begins with the first executable statement
in the main program. The other statements identify the start of a subprogram. If the first statement of a program
unit is not one of the above then the program unit is considered to be a main program.
Although you may not be familiar with all of the terms used here, it is important that you understand that FORTRAN
77 has specific rules regarding the ordering of FORTRAN statements. You may wish to refer to this section at later
times. In general, the following rules apply to the order of statements and comment lines within a program unit:
- Comment lines and INCLUDE statements may appear anywhere.
- FORMAT statements may appear anywhere in a subprogram.
- All specification statements must precede all DATA statements, statement function statements, and executable
statements.
- All statement function statements must precede all executable statements.
- DATA statements may appear anywhere after the specification statements.
- ENTRY statements may appear anywhere except between a block IF statement and its corresponding
END IF statement, or between a DO statement and its corresponding terminal statement. Open Watcom FORTRAN
77 extends these rules to apply to all program structure blocks resulting from the use of statements introduced to the language
by Open Watcom FORTRAN 77 (e.g., WHILE, LOOP, SELECT).
- IMPLICIT statements must precede all other specification statements, except PARAMETER statements.
A specification statement that defines the type of a symbolic constant must appear before the PARAMETER statement
that defines the name and value of a symbolic constant. A PARAMETER statement that defines the name and value
of a symbolic constant must precede all other statements containing a reference to that symbolic constant.
The following chart illustrates the required order of FORTRAN statements. Vertical lines delineate varieties of
statements that may be interspersed, while horizontal lines mark varieties of statements that may not be interspersed.
+-----------+-------------------------------------------+
| | PROGRAM, FUNCTION, SUBROUTINE,
or |
| | BLOCK DATA Statement
|
| +-----------+---------------+---------------+
| |
| | IMPLICIT
|
| |
| PARAMETER | Statements |
| |
| +---------------+
| Comment | ENTRY | Statements | Other
|
| Lines |
| | Specification |
| | and
| | Statements
|
| |
|---------------+---------------+
| | FORMAT
| | Statement
|
| INCLUDE | |
| Function |
| Statement | Statements| DATA | Statements
|
| |
| +---------------+
| |
| Statements | Executable |
| |
| | Statements
|
| +-----------+---------------+---------------+
| | END Statement
|
+-----------+-------------------------------------------+
Required Order of Comment Lines and Statements
For example, DATA statements may be interspersed with statement function statements and executable
statements but statement function statements must precede executable statements.
FORTRAN Statements
The following sections describe each FORTRAN 77 statement.
Classifying Statements
The following table is a summary of Open Watcom FORTRAN 77 statement classification.
- Column 1
- indicates that the statement is a specification statement.
Column 2
- indicates that the statement is not allowed as the terminal statement of a DO-loop.
Column 3
- indicates that the statement is not executable.
Column 4
- indicates that the statement is not allowed as the object of a logical IF
or WHILE statement.
Column 5
- indicates that the statement cannot have control of execution transferred to it by using a statement label.
Column 6
- indicates that the statement is allowed in a block data subprogram.
+---------------------+------+------+------+------+------+------+
|Statement | 1
| 2 | 3 | 4 | 5 | 6 |
+---------------------+------+------+------+------+------+------+
|ADMIT
| | * | | * |
* | |
|ALLOCATE |
| | | |
| |
|ASSIGN
| | | |
| | |
|AT END
| | * | | * | *
| |
|BACKSPACE |
| | | |
| |
|BLOCK DATA |
| * | * | * | * |
|
|CALL
| | | |
| | |
|CASE
| | * | | * |
* | |
|CHARACTER | *
| * | * | * | * | * |
|CLOSE
| | | |
| | |
|COMMON
| * | * | * | * | * | *
|
+---------------------+------+------+------+------+------+------+
+---------------------+------+------+------+------+------+------+
|Statement | 1
| 2 | 3 | 4 | 5 | 6
+---------------------+------+------+------+------+------+------+
|COMPLEX |
* | * | * | * | * | *
|
|CONTINUE |
| | | |
| |
|CYCLE
| | | |
| | |
|DATA
| | * | * | * | *
| * |
|DEALLOCATE |
| | | |
| |
|DIMENSION | *
| * | * | * | * | * |
|DO
| | * | | *
| | |
|DOUBLE COMPLEX | * | *
| * | * | * | * |
|DOUBLE PRECISION | * | * |
* | * | * | * |
|DO WHILE |
| * | | * |
| |
|ELSE
| | * | | * |
* | |
|ELSE IF |
| * | | * | *
| |
|END
| | * | | *
| | * |
|END AT END |
| * | | * | * |
|
|END BLOCK |
| * | | * | * |
|
|END DO
| | | | * |
* | |
|ENDFILE |
| | |
| | |
|END GUESS |
| * | | * |
| |
|END IF
| | * | | * |
| |
|END LOOP |
| * | | * | *
| |
|END MAP |
* | * | * | * | * | *
|
|END SELECT | *
| * | * | * | * | |
|END STRUCTURE | * | *
| * | * | * | * |
|END UNION |
| * | | * | * |
* |
|END WHILE |
| * | | * | * |
|
|ENTRY
| | * | | * |
* | |
|EQUIVALENCE | *
| * | * | * | * | * |
|EXECUTE |
| | |
| | |
|EXIT
| | | |
| | |
|EXTERNAL |
* | * | * | * | * |
|
|FORMAT
| | * | * | * | * |
|
|FUNCTION |
| * | * | * | * |
|
|assigned GO TO | |
* | | | |
|
|computed GO TO | |
| | | |
|
|unconditional GO TO | | * |
| | | |
|GUESS
| | * | | * |
| |
|arithmetic IF |
| * | | | |
|
|logical IF |
| | | * |
| |
|block IF |
| * | | * |
| |
+---------------------+------+------+------+------+------+------+
+---------------------+------+------+------+------+------+------+
|Statement | 1
| 2 | 3 | 4 | 5 | 6
+---------------------+------+------+------+------+------+------+
|IMPLICIT |
* | * | * | * | * | *
|
|INCLUDE |
| * | * | * | * |
* |
|INQUIRE |
| | |
| | |
|INTEGER |
* | * | * | * | * | *
|
|INTRINSIC | *
| * | * | * | * |
|
|LOGICAL |
* | * | * | * | * | *
|
|LOOP
| | * | | * |
| |
|MAP
| * | * | * | * | *
| * |
|NAMELIST |
* | * | * | * | * |
|
|OPEN
| | | |
| | |
|OTHERWISE |
| * | | * | * |
|
|PARAMETER | *
| * | * | * | * | * |
|PAUSE
| | | |
| | |
|PRINT
| | | |
| | |
|PROGRAM |
| * | * | * | * |
|
|QUIT
| | | |
| | |
|READ
| | | |
| | |
|REAL
| * | * | * | * | *
| * |
|RECORD
| * | * | * | * | * | *
|
|REMOTE BLOCK |
| * | * | * | * | |
|RETURN
| | * | | |
| |
|REWIND
| | | |
| | |
|SAVE
| * | * | * | * | *
| * |
|SELECT
| | * | | * |
| |
|STOP
| | * | |
| | |
|STRUCTURE | *
| * | * | * | * | * |
|SUBROUTINE |
| * | * | * | * |
|
|UNION
| * | * | * | * | * |
* |
|UNTIL
| | * | | * |
* | |
|VOLATILE |
* | * | * | * | * | *
|
|WHILE
| | * | | * |
| |
|WRITE
| | | |
| | |
+---------------------+------+------+------+------+------+------+
FORTRAN Statement Summary
The following sections describe each FORTRAN 77 statement. The statement descriptions are organized alphabetically
for quick reference. The syntax models for each statement are presented in shaded or unshaded boxes. The unshaded
box denotes a standard FORTRAN 77 statement. The shaded box denotes a Open Watcom FORTRAN 77 extension to the language.
Users should note that extensions which are supported by this compiler may not be supported by other compilers.
We leave the choice to use a particular extension to the discretion of the programmer.
In the following sections the use of square brackets ([ ]) denotes items which may be optionally specified.
The use of the ellipsis (...) denotes items which may be repeated as often as desired.
ADMIT Statement
ADMIT
The ADMIT statement is used in conjunction with the structured GUESS statement. The ADMIT
statement marks the beginning of an alternative block of statements that are executed if a QUIT statement is executed
in a previous GUESS or ADMIT block.
Example:
* Assume incorrect sex code
GUESS
IF( SEX .EQ. 'F' )QUIT
IF( SEX .EQ. 'M' )QUIT
PRINT *, 'Invalid sex code encountered'
CALL INVSEX( SEX )
.
.
.
* Wrong assumption - sex code is fine
ADMIT
.
.
.
END GUESS
For more information, see the chapter entitled Program Structure Control Statements.
ALLOCATE Statement
ALLOCATE (array([l:]u[,[l:]u,...])[,...][,LOCATION=loc])
or
ALLOCATE (array([l:]u[,[l:]u,...])[,...][,STAT=ierr])
or
ALLOCATE (char*len)
- where:
-
array
- is the name of an allocatable array.
l
- is an integer expression that sets the lower bound of the array dimension.
u
- is an integer expression that sets the upper bound of the array dimension.
char
- is the name of an allocatable character variable.
len
- is an integer expression that sets the length of the character variable.
LOCATION = loc
-
loc is an integer expression that specifies the location of the allocated memory.
STAT = ierr
-
ierr is an allocation status specifier. The integer variable or integer array element ierr is
defined with 0 if the allocation succeeded, 1 if the allocation failed, and 2 if the array is already allocated. The
STAT= specifier may not be used with the LOCATION= specifier.
Allocatable arrays and character variables may be dynamically allocated and deallocated at execution time. An array
must have been declared allocatable by specifying its dimensions using colons only. No array bounds are specified.
Example:
DIMENSION A(:), B(:,:)
In the above example, A is declared to be a one-dimensional allocatable array and B is declared
to be a two-dimensional allocatable array.
A character variable must have been declared allocatable by specifying its size as (*).
Example:
CHARACTER C*(*)
For an allocatable array, the ALLOCATE statement establishes the lower and upper bounds of each array dimension
and calculates the amount of memory required for the array.
For an allocatable character variable, the ALLOCATE statement establishes the number of characters in the
character variable and thus the size of the character variable.
If there is no LOCATION= specifier, it then attempts to dynamically allocate memory for the array or character
variable. The success of the allocation can be checked by using the STAT= specifier.
If there is a LOCATION= specifier, the expression in the specification is evaluated and that value is used
as the address of the array or character variable. This permits the programmer to specify a substitute memory allocator
or to map the array or character variable onto a fixed memory location.
Example:
DIMENSION A(:), B(:,:)
.
.
.
ALLOCATE( A(N) )
ALLOCATE( B(0:4,5) )
More than one allocatable array or character variable may appear in an ALLOCATE statement, separated by commas.
Example:
DIMENSION A(:), B(:,:)
.
.
.
ALLOCATE( A(N), B(0:4,5) )
If the allocation fails and the STAT= specifier was not used, an execution-time error occurs. If the
STAT= specifier is used, the specified variable returns a zero value if the allocation succeeded, and a non-zero value
if the allocation failed.
Example:
DIMENSION A(:), B(:,:)
.
.
.
ALLOCATE( A(N), B(0:4,5), STAT=IALLOC )
IF( IALLOC .NE. 0 ) PRINT *, 'Allocation failure'
An attempt to allocate a previously allocated array or character variable results in an execution-time error.
If the LOCATION= specifier was not used, the array or character variable must be deallocated first before it can
be allocated a second time (see the DEALLOCATE statement).
An absolute memory location may be specified using the LOCATION= specifier.
Example:
CHARACTER*1 SCREEN(:,:)
N = 80*25
*$IFDEF __386__
ALLOCATE( SCREEN(0:1,0:N-1), LOCATION='B8000'x )
*$ELSE
ALLOCATE( SCREEN(0:1,0:N-1), LOCATION='B8000000'x )
*$ENDIF
DO I = 0, N-1
SCREEN(0,I) = '*'
ENDDO
END
The above example maps the array SCREEN onto the IBM PC colour monitor screen memory and then fills the screen
with asterisks (16-bit real-mode only). The character is stored in SCREEN(0,I) and the character attribute
(unchanged in this example) is stored in SCREEN(1,I). The column major ordering of arrays must be taken into
consideration when mapping an array onto a fixed area of memory.
The following example is similar but uses an allocatable character variable.
Example:
CHARACTER*(*) SCREEN
INTEGER SCRSIZE, I
PARAMETER ( SCRSIZE = 80*25*2 )
*$IFDEF __386__
ALLOCATE( SCREEN*SCRSIZE, LOCATION='B8000'X )
*$ELSE
ALLOCATE( SCREEN*SCRSIZE, LOCATION='B8000000'X )
*$ENDIF
DO I = 1, SCRSIZE, 2
SCREEN(I:I) = '*'
ENDDO
END
A user-defined memory allocator may be specified using the LOCATION= specifier.
Example:
CHARACTER*1 BUFFER(:)
N = 128
ALLOCATE( BUFFER(0:N-1), LOCATION=MYALLOC(N) )
.
.
.
END
Perhaps a better way to check for a successful allocation, in this case, would be the following.
Example:
CHARACTER*1 BUFFER(:)
N = 128
LOC = MYALLOC( N )
IF( LOC .EQ. 0 ) STOP
ALLOCATE( BUFFER(0:N-1), LOCATION=LOC )
.
.
.
END
For more information on arrays, see the chapter entitled Arrays.
Statement Label Assignment (ASSIGN) Statement
ASSIGN s TO i
- where:
-
s
- is a statement label
i
- is an integer variable name
The statement label s is assigned to the integer variable i. The statement label must appear in
the same program unit as the ASSIGN statement. The statement label must be that of an executable statement
or a FORMAT statement.
After a statement label has been assigned to an integer variable, that variable may only be used in an assigned
GO TO statement or as a format identifier in an input/output statement. The integer variable must not be used
in any other way (e.g., in an arithmetic expression). It may, however, be redefined with another statement label using
the ASSIGN statement or it may be assigned an integer value (e.g., in an arithmetic assignment statement).
Example:
INTEGER RET
X = 0.0
ASSIGN 100 TO RET
GO TO 3000
100 X = X + 1
ASSIGN 110 TO RET
GO TO 3000
110 X = X + 1
.
.
.
* Print both X and its square root
3000 Y = SQRT( X )
PRINT *, X, Y
GO TO RET
In the above example, we illustrate the use of the ASSIGN statement and the assigned GO TO statement
to implement a "local subroutine" in a program unit. A sequence of often-used code can be "called"
using the unconditional GO TO statement and "return" is accomplished using the assigned GO TO
statement. Care must be exercised to properly assign the return label value.
Example:
IF( FIRST )THEN
ASSIGN 100 TO LFRMT
ELSE
ASSIGN 200 TO LFRMT
END IF
WRITE( UNIT=5, FMT=LFRMT) X, Y, Z
100 FORMAT(1X,3F10.5)
200 FORMAT(1X,3E15.7)
It should be noted that the ASSIGN statement does not assign the numeric value of the statement label to
the variable.
Example:
ASSIGN 100 TO LABEL2
PRINT *, LABEL2
Try the above example; the value printed will not be 100.
Consider the following example.
Example:
* Illegal use of a GOTO statement.
LABEL2 = 123
LABEL3 = LABEL2 + 10
GO TO LABEL3
LABEL3 is assigned the integer value 133. The assigned GO TO statement, which follows it,
is illegal and a run-time error will occur when it is executed.
Statement label values are quite different from integer values and the two should never be mixed. In the following
example, the assignment statement is illegal since it involves an integer variable that was specified in an ASSIGN
statement.
Example:
* Illegal use of an ASSIGNed variable in an expression.
ASSIGN 100 TO LABEL2
LABEL3 = LABEL2 + 10
Note that if the assignment statement was preceded by
LABEL2 = 100
the assignment statement would have been legal.
AT END Statement
AT END DO [: block-label]
or
AT END, stmt
- where:
-
stmt
- is an executable statement other than an AT END statement.
The AT END control statement is an extension of the END= option of the READ statement for sequential
files. It allows a statement or a block of code following the READ statement to be executed when an end-of-file
condition is encountered during the read. The AT END statement or block is by-passed if no end-of-file occurs.
It is not valid to use this control statement with direct-access or internal files. It is not valid to use this
statement when END= is also specified in the READ statement. The AT END statement or block
must immediately follow the READ statement to which it applies.
Example:
READ( UNIT=1, FMT='(I5,F10.4)' ) I, X
AT END DO
PRINT *, 'END-OF-FILE ENCOUNTERED
ON UNIT 1'
EOFSW = .TRUE.
END AT END
The second form of the AT END statement is illustrated below.
Example:
READ( UNIT=1, FMT='(F10.4)' ) X
AT END, EOFSW = .TRUE.
For more information, see the chapter entitled Program Structure Control Statements.
BACKSPACE Statement
BACKSPACE u
BACKSPACE (alist)
- where:
-
u
- is an external unit identifier.
alist
- is a list of backspace specifiers separated by commas:
[UNIT =] u
IOSTAT = ios
ERR = s
Execution of a BACKSPACE statement causes the file connected to the specified unit to be positioned at the beginning
of the preceding record. If the preceding record is an endfile record then the file is positioned at the beginning
of the endfile record.
- Backspace Specifiers
-
[UNIT =] u
-
u is an external unit identifier. An external unit identifier is a non-negative integer expression.
If the optional UNIT= specifier is omitted then the specifier must be the first item in the list of specifiers.
IOSTAT = ios
-
is an input/output status specifier. The integer variable or integer array element ios is defined
with zero if no error condition occurs or a positive integer value if an error condition occurs.
ERR = s
-
is an error specifier and s is a statement label. When an error occurs, execution is transferred
to the statement labelled by s.
Example:
LOOP
READ( UNIT=8, END=100, FMT=200
) RECORD
ENDLOOP
100 BACKSPACE( UNIT=8 )
WRITE( UNIT=8, FMT=200 ) NEWREC
In the previous example, we illustrate how one might append a record to the end of an existing file.
Notes:
- The unit must be connected for sequential access.
- If the file is positioned before the first record then the BACKSPACE statement has no effect.
- It is illegal to backspace a file that does not exist.
The FORTRAN 77 standard specifies that it is illegal to backspace over records that were written using list-directed formatting;
Open Watcom FORTRAN 77 allows it.
If the file has been opened with access 'APPEND', which is a form of sequential access in which the file
is positioned at the endfile record, then the BACKSPACE statement cannot be used.
For more information on input/output, see the chapter entitled Input/Output.
BLOCK DATA Statement
BLOCK DATA [sub]
- where:
-
sub
- is an optional symbolic name of the block data subprogram and must not be the name of an external procedure, main program,
common block, other block data subprogram, or any local name in the block data subprogram.
The BLOCK DATA statement is used to define the start of a block data subprogram. A block data subprogram
is used to provide initial values for variables and array elements in named common blocks.
The only statements which are allowed to appear in a block data subprogram are:
- IMPLICIT
- PARAMETER
- DIMENSION
- COMMON
- SAVE
- EQUIVALENCE
- DATA
- STRUCTURE, END STRUCTURE
- UNION, END UNION
- MAP, END MAP
- RECORD
- END
- type statements
Example:
BLOCK DATA INITCB
DIMENSION A(10), B(10)
COMMON /CB/ A, B
DATA A/10*1.0/, B/10*2.0/
END
In the above example, the arrays A and B in the named common block CB are initialized.
Notes:
- More than one named common block may appear in a block data subprogram.
- All entities of the named common block(s) must be specified.
- Not all entities need be given initial values.
- Only entities that appear in (or are associated, through the EQUIVALENCE statement, with entries in) a named
common block may be given initial values.
- Only one unnamed block data subprogram may occur in an executable program.
- A named block data subprogram may occur only once in an executable program.
CALL Statement
CALL sub [( [a [, a] ... ] )]
- where:
-
sub
- is a symbolic name of a subroutine and must not be the name of a main program, function, common block, or block data subprogram.
As an extension to FORTRAN 77, Open Watcom FORTRAN 77 permits the calling of functions.
a
- is an actual argument.
The CALL statement is used to invoke the execution of a subroutine subprogram or function.
Example:
X = 1.0
Y = 1.1
Z = 1.2
CALL QUAD( X, Y, Z )
.
.
.
END
SUBROUTINE QUAD( ARGA, ARGB, ARGC )
REAL ARGA, ARGB, ARGC
PRINT *, 2.0*ARGA**2 + 4.0*ARGB + ARGC
END
In the above example, the variables X, Y and Z are passed to the subroutine QUAD.
This subroutine computes an expression and prints the result.
Notes:
- The parameters in the CALL statement are called actual arguments.
- The parameters in the SUBROUTINE statement are called dummy arguments.
- The actual arguments in a subroutine or function reference must agree in order, number and type with the corresponding
dummy arguments.
- An actual argument may be an expression, array name, intrinsic function name, external procedure name (i.e., a subroutine
or function name), a dummy procedure name (i.e., one that was an argument to the calling subroutine or function), or an
alternate return specifier (subroutines only). An alternate return specifier takes the form *s, where
s is the statement label of an executable statement that appears in the same program unit as the CALL statement.
An expression may not be a character expression involving the concatenation of an operand whose length specification
is (*) unless the operand is the symbolic name of a constant.
- Actual arguments are associated with dummy arguments by passing the address of the actual arguments.
It is important to note that versions of FORTRAN compilers that implement the previous FORTRAN language standard may
have associated arguments by passing the value of the actual argument and assigning it to the dummy argument and then updating
the actual argument upon return from the subprogram (this is called "value-result" argument handling). The
FORTRAN 77 language standard prohibits this technique for handling argument association.
The following example illustrates the importance of this rule.
Example:
I=1
CALL ASSOC( I, I )
END
SUBROUTINE ASSOC( M, N )
M = M + 1
PRINT *, M, N
END
In the above example, M and N refer to the same variable; they are both associated to I
in the calling subprogram. The value 2 will be printed twice.
For more information, see the chapter entitled Functions and Subroutines.
CASE Statement
CASE cl
- where:
-
cl
- is a list, enclosed in parentheses, of one or more cases separated by commas, or the DEFAULT keyword.
A case is either
- (a)
- a single integer, logical or character constant expression or
(b)
- an integer, logical or character constant expression followed by a colon followed by another expression or the same type.
This form of a case defines a range of values consisting of all integers or characters greater than or equal to the
value of the expression preceding the colon and less than or equal to the value of the expression following the colon.
The CASE statement is used in conjunction with the SELECT statement. The CASE statement
marks the start of a new CASE block which is a series of zero or more statements ending in another CASE
statement, a CASE DEFAULT statement, or an END SELECT statement.
A particular case value or range of values must not be contained in more than one CASE block.
The CASE DEFAULT statement is used to indicate a block of statements that are to be executed when no other
case is selected.
Example:
SELECT CASE ( CH )
CASE ( 'a' : 'z' )
PRINT *, 'Lower case letter'
CASE ( 'A' : 'Z' )
PRINT *, 'Upper case letter'
CASE ( '0' : '9' )
PRINT *, 'Digit'
CASE DEFAULT
PRINT *, 'Special character'
END SELECT
In order to retain compatibility with earlier versions of WATCOM FORTRAN 77 compilers, the OTHERWISE statement
may be used in place of the CASE DEFAULT statement.
For more information, see the chapter entitled Program Structure Control Statements.
CHARACTER Statement
The CHARACTER statement is a type declaration statement and can be used to declare a name to be of type character.
The implicit type of the name, whether defined by the "first letter rule" (see the chapter entitled Names, Data Types and Constants)
or by an IMPLICIT statement, is either confirmed or overridden. However, once a name has been declared to
be of type character, it cannot appear in another type declaration statement.
There are various forms of the CHARACTER statement. The following sections describe them.
Standard CHARACTER Statement
CHARACTER[*len [,]] name [,name] ...
- where:
-
name
- is one of the following forms:
v[*len]
a(d)[*len]
a[*len](d)
v
- is a variable name, symbolic name of a constant, function name or dummy procedure name.
a
- is an array name.
(d)
- is that part of the array declarator defining the dimensions of the array.
len
- is called the length specification and is the length (number of characters) of a character variable, character array
element, symbolic character constant or character function. It has one of the following forms:
- (1)
- An unsigned positive integer constant.
(2)
- A positive integer constant expression enclosed in parentheses.
(3)
- An asterisk in parentheses (*).
The length specification immediately following the word CHARACTER is the length specification for each entity
in the statement not having its own length specification. If omitted, the default is 1. An entity with its own
length specification overrides the default length specification or the length specification immediately following the word
CHARACTER. Note that for an array the length specification applies to each element of the array.
Example:
DIMENSION C(-5:5)
CHARACTER A, B*10(10), C*20
CHARACTER*7 X, Y, Z*4
The (*) length specification is only allowed for external functions, dummy arguments or symbolic character
constants. If a dummy argument has a length specification of (*), it assumes the length of the corresponding
actual argument. If the actual argument is an array name, the length assumed by the dummy argument is the length of
an array element of the actual array.
Example:
SUBROUTINE OUTCHR( STR )
CHARACTER STR*(*)
PRINT *, STR
END
In this example, STR is a character variable whose length is the length of the actual argument. Thus
OUTCHR can be called with a character entity of any length.
If an external function has a length specification of (*) declared in a function subprogram, the function
name must appear as the name of a function in a FUNCTION or ENTRY statement in the same subprogram.
When the function is called, the function assumes the length specified in the program unit that called it. In the following
example, when F is called its length is assumed to be 10.
Example:
CHARACTER*(10) F
.
.
.
PRINT *, F()
.
.
.
END
CHARACTER*(*) FUNCTION F
F = 'HELLO'
END
The following example is illegal since F does not appear in a FUNCTION or ENTRY statement.
Example:
* Illegal definition of function F.
CHARACTER*(*) F
.
.
.
PRINT *, F()
.
.
.
END
The length specified for a character function in the program unit that referenced it must agree with the length specified
in the subprogram that defines the character function. Note that there is always agreement if the function is defined
to have a length specification of (*).
If a symbolic name is of type character and has a length specification of (*), it assumes the length of the
corresponding character constant expression in the PARAMETER statement.
The length specification of a character statement function or statement function dummy argument must not be (*).
Extended CHARACTER Statement: Data Initialization
CHARACTER[*len[,]] name [/cl/] [,name[/cl/]]
...
- where:
-
name
- is as described in the previous section.
len
- is as described in the previous section.
cl
- is a list of the form:
k [,k] ...
k
- is one of the forms:
c
r*c (equivalent to r successive appearances of c)
c
- is a constant or the symbolic name of a constant
r
- is an unsigned positive integer constant or the symbolic name of a constant.
This form of the CHARACTER statement is an extension to the FORTRAN 77 language. The rules for data initialization
are the same as for the DATA statement.
Example:
CHARACTER*5 A/'AAAAA'/, B*3(10)/10*'111'/
In the previous example, A is initialized with the character constant 'AAAAA' and each element of
the array B is initialized with the character constant '111'.
CLOSE Statement
CLOSE (cllist)
- where:
-
cllist
- is a list of close specifiers separated by commas:
[UNIT =] u
IOSTAT = ios
ERR = s
STATUS = sta
A CLOSE statement is used to terminate the connection of a file to the specified unit.
- Close Specifiers
-
[UNIT =] u
-
u is an external unit identifier. An external unit identifier is a non-negative integer expression.
If the optional UNIT= specifier is omitted then the specifier must be the first item in the list of specifiers.
IOSTAT = ios
-
is an input/output status specifier. The integer variable or integer array element ios is defined with
zero if no error condition occurs or a positive integer value if an error condition occurs.
ERR = s
-
is an error specifier and s is a statement label. When an error occurs, execution is transferred to the
statement labelled by s.
STATUS = sta
-
is a status specifier and sta is a character expression whose value when trailing blanks are removed evaluates
to one of 'KEEP' or 'DELETE'.
- KEEP
- 'KEEP' may not be specified for a file whose status is 'SCRATCH' (see description of the OPEN
statement). If the file exists, it will exist after execution of the CLOSE statement. If the file does
not exist, it will not exist after execution of the CLOSE statement. If not specified, 'KEEP' is
assumed, unless the file status is 'SCRATCH' in which case 'DELETE' is assumed.
DELETE
- If 'DELETE' is specified, the file will not exist after execution of the CLOSE statement.
Example:
LOOP
READ( UNIT=8, END=100, FMT=200
) RECORD
ENDLOOP
100 CLOSE( UNIT=8 )
In the previous example, we illustrate how one might process the records in a file and then terminate the connection
of the file to unit 8 using the CLOSE statement.
Notes:
- Execution of a CLOSE statement specifying a unit that is not connected to a file or a unit that is connected
to a file that does not exist has no effect.
- It is possible to connect the unit to another file after a CLOSE statement has been executed.
- It is possible to connect the unit to the same file after a CLOSE statement has been executed, provided that
the file still exists.
- It is possible to connect the file to another unit after a CLOSE statement has been executed, provided that the
file still exists.
- At the termination of execution of the program, for whatever the reason of termination, any units that are connected are
closed. Each unit is closed with status 'KEEP' unless the file status was 'SCRATCH', in which case
the unit is closed with status 'DELETE'. The effect is the same as if a CLOSE statement is executed
without a STATUS= specifier.
For more information on input/output, see the chapter entitled Input/Output.
COMMON Statement
COMMON [/[cb]/] nlist [[,]/[cb]/
nlist] ...
- where:
-
cb
- is a common block name.
nlist
- is a list of names each separated by a comma.
If cb is omitted, the blank common block is assumed. If specified, cb is called a named
common block. The names appearing in nlist can be variable names, array names, and array declarators.
Dummy arguments are not allowed in nlist.
The COMMON statement allows sharing of blocks of storage between subprograms. Each name appearing in
the nlist following a common block name cb is declared to belong to that common block. A variable
or an array name can belong to only one common block. A common block name can occur more than once in the same
COMMON statement as well as in more than one COMMON statement. Lists following successive appearances
of the same common block name in COMMON statements are considered a continuation of the list of names belonging
to the common block. A variable or an array can appear in a COMMON statement only once.
Common blocks are defined as follows. A common block is one consecutive block of storage. It consists
of all the storage sequences of all the entities specified in all the lists declared to belong to that common block.
The order in which each entity appears in a common block is defined by the order in which they appear in the lists.
Storage sequences associated to a common block through the EQUIVALENCE statement are considered to belong to that
common block. In this way a common block may only be extended beyond the last storage unit. The size of a common
block is the sum of all the storage sequences of all the names belonging to that common block plus any storage sequence which
extends the common block through equivalence association.
An EQUIVALENCE statement must not cause storage sequences of two different common blocks to become associated
nor should they extend the common block by adding storage units preceding the first storage unit of the common block.
Example:
DIMENSION A(5)
COMMON /COMBLK/ A,B(10),C
In this example, the common block COMBLK contains the array A followed by the array B and
finally the variable C.
Example:
REAL A,B,C,D
DIMENSION D(5)
EQUIVALENCE (B,D)
COMMON A,B,C
In this example, A, B, C, and D belong to the blank common block; A, B, and C
have been explicitly defined to be in the blank common block whereas D has been equivalenced to a variable in common,
namely B. Also note that the EQUIVALENCE statement has caused the extension of the common block beyond
its last storage unit. In this example, array D has extended the common block by 3 storage units.
Example:
* Illegal definition of a common block.
DIMENSION A(5)
EQUIVALENCE (A(2),B)
COMMON /XYZ/ B
This example demonstrates an illegal use of the COMMON statement. B is in the named common
block XYZ since it appeared in a COMMON statement. A is in the common block XYZ
since it was equivalenced to B. However, A illegally extends the common block by adding 1 storage
unit before the first storage unit of the common block.
The following outlines the differences between a blank common block and a named common block.
- (1)
- All named common blocks with the same name in an executable program must be the same size. Blank common blocks do not
have to be the same size.
(2)
- Entities in named common blocks can be initialized by using DATA statements in block data subprograms; entities in
blank common blocks cannot.
(3)
- Entities in named common blocks can become undefined after the execution of a RETURN or END statement; entities
in blank common blocks cannot. This situation can arise when all subprograms which refer to the named common block
become inactive. A typical case occurs when program overlays are used. If the named common block is placed in
an overlay, then the entities in the named common block will become undefined when the overlay is replaced by another.
Of course, if the named common block is referenced in the main program then this could never happen. The main program
and any named common blocks referenced in the main program remain memory-resident until the application terminates.
The SAVE statement should be used if entities in named common blocks must not become undefined.
The FORTRAN 77 standard specifies that a common block cannot contain both numeric and character data; Open Watcom FORTRAN
77 allows common blocks to contain both numeric and character data.
The FORTRAN 77 standard specifies that a named common block must be initialized in a block data subprogram.
Open Watcom FORTRAN 77 permits the initialization of named common blocks in other subprograms.
COMPLEX Statement
The COMPLEX statement is a type declaration statement and can be used to declare a name to be of type complex.
The implicit type of the name, whether defined by the "first letter rule" (see the chapter entitled Names, Data Types and Constants)
or by an IMPLICIT statement, is either confirmed or overridden. However, once a name has been declared to
be of type complex, it cannot appear in another type declaration statement.
There are various forms of the COMPLEX statement. The following sections describe them.
Standard COMPLEX Statement
COMPLEX name [,name] ...
- where:
-
name
- is a variable name, array name, array declarator, symbolic name of a constant, function name or dummy procedure name.
This form is the standard form of the COMPLEX statement.
Example:
DIMENSION C(-5:5)
COMPLEX A, B(10), C
In the previous example, A is defined to be a variable of type complex and B and C are
defined to be arrays of type complex.
Extended COMPLEX Statement: Length Specification
COMPLEX[*len[,]] name [,name] ...
- where:
-
name
- is one of the following forms:
v[*len]
a[*len](d)
a(d)[*len]
v
- is a variable name, array name, symbolic name of a constant, function name or dummy procedure name.
a
- is an array name.
(d)
- is that part of the array declarator defining the dimensions of the array.
len
- is called the length specification and is an unsigned positive integer constant or an integer constant expression enclosed
in parentheses whose value is 8 or 16.
This form of the COMPLEX statement is a Open Watcom FORTRAN 77 extension to the FORTRAN 77 language. The
length specification specifies the number of bytes of storage that will be allocated for the name appearing in the COMPLEX
statement. The default length specification is 8. A length specification of 16 specifies that the data type of
the name appearing in the COMPLEX statement is to be double precision complex.
The length specification immediately following the word COMPLEX is the length specification for each entity
in the statement not having its own length specification. If a length specification is not specified the default length
specification is used. An entity with its own specification overrides the default length specification or the length
specification immediately following the word COMPLEX. Note that for an array the length specification applies
to each element of the array.
Example:
DIMENSION C(-5:5)
COMPLEX A, B*16(10), C*16
COMPLEX*16 X
In the previous example, X is declared to be a variable of type double precision complex, A is declared
to be a variable of type complex and B and C are declared to be arrays of type double precision complex.
Extended COMPLEX Statement: Data Initialization
COMPLEX[*len[,]] name [/cl/] [,name[/cl/]]
...
- where:
-
name
- is as described in the previous section.
len
- is as described in the previous section.
cl
- is a list of the form:
k [,k] ...
k
- is one of the forms:
c
r*c (equivalent to r successive appearances of c)
c
- is a constant or the symbolic name of a constant
r
- is an unsigned positive integer constant or the symbolic name of a constant.
This form of the COMPLEX statement is an extension to the FORTRAN 77 language. The rules for data initialization
are the same as for the DATA statement.
Example:
COMPLEX A/(.4,-.3)/, B(10)/10*(0,1)/
In the previous example, A is initialized with the complex constant (.4,-.3) and each element of
the array B is initialized with the complex constant (0,1).
CONTINUE Statement
CONTINUE
Execution of a CONTINUE statement has no effect. This statement is often used in conjunction with DO
statements. It is usually identified with a label. It often provides a convenient reference for statements which
have the ability to transfer control of execution.
Example:
DO 10 X = -5.1, 12.8, 0.125
.
.
.
10 CONTINUE
IF( A .LT. B ) GO TO 20
IF( A .GT. C ) GO TO 20
.
.
.
20 CONTINUE
CYCLE Statement
CYCLE [: block-label]
The CYCLE statement may be used to cause a transfer of control from within a loop to the terminal statement of
a corresponding DO, DO WHILE, WHILE or LOOP statement. If block-label
is present then control is transferred to the terminal statement of the block identified by that block label. The
CYCLE statement is an extension to the FORTRAN 77 language.
Example:
LOOP
WRITE( UNIT=*, FMT='(A)' ) 'Enter
a number'
READ( UNIT=*, FMT='(F10.4)',
IOSTAT=IOS ) X
IF( IOS .NE. 0 ) CYCLE
IF( X .LT. 0 ) EXIT
PRINT *, X, SQRT( X )
END LOOP
END
For more information, see the chapter entitled Program Structure Control Statements.
DATA Statement
DATA nlist/clist/ [[,]nlist/clist/] ...
- where:
-
nlist
- is a list of variable names, array element names, substring names and implied-DO lists.
clist
- is a list of the form:
a [,a] ...
a
- is one of the forms:
c
r*c (equivalent to r successive appearances of c)
c
- is a constant or the symbolic name of a constant
r
- is an unsigned positive integer constant or the symbolic name of a constant.
The items of nlist are initialized with the values specified in clist in the following manner.
The first item in nlist is assigned the value of the first item in clist, the second item in nlist
is assigned the value of the second item in clist, etc. In this way all items of nlist are initialized.
The number of items in nlist must equal the number of items in clist so that a one-to-one correspondence
exists between the two lists. If an array without a subscript list appears in nlist there must be an element
in clist for each element of the array.
If the type of an entity in nlist is character or logical then the type of its corresponding item in
clist must also be character or logical respectively. As an extension to FORTRAN 77, Open Watcom FORTRAN 77 permits
an item of type character to be initialized with integer data.
An item of type character is initialized using the rules of assignment. If the length of the item in nlist
is greater than the length of the corresponding character constant in clist, the rightmost remaining characters
in the item are initialized with blanks. If the length of the item in nlist is less than the length of the
character constant in clist, the character constant is truncated to the length of the item in nlist.
Note that initializing a character entity causes all of the characters in the entity to become defined and that each character
constant defines exactly one character variable, array element or substring.
If the type of an entity in nlist is integer, real, double precision or complex then the corresponding item
in clist can be one of integer, real, double precision or complex. If necessary the constant in clist
is converted to the type of the item in nlist according to the rules of arithmetic conversion (see the chapter entitled
Assignment Statements).
A variable, array element or substring can only be initialized once. If two entities are associated (for example
equivalenced), only one of the items can be initialized.
Example:
CHARACTER*30 MSG
LOGICAL TRUE
REAL X, Y(10)
DATA X/1.0/, TRUE/.TRUE./, MSG/'ENTER DATA'/
DATA Y/10*5/
An implied-DO list in a DATA statement has the following form:
( dlist, i = m1, m2[, m3] )
- where:
-
dlist
- is a list of array element names and implied-DO lists.
i
- is the name of an integer variable called the implied-DO-variable.
m1,m2,m3
- are each integer constant expressions. The expressions may contain implied-DO-variables of other implied-DO lists that
have this implied-DO list in their ranges.
The range of the implied-DO list is the list dlist. An iteration count and the value of the implied-DO-variable
are computed from m1,m2 and m3 in the same way as for a DO-loop except that the iteration count must be
positive. An implied-DO-variable does not affect the definition of a variable by the same name in the same program
unit. An implied-DO list is processed as follows. Each item in the implied-DO list is processed once for each
iteration with the appropriate substitution of values for any occurrence of the implied-DO-variable. The following
example initializes the upper right triangle of the array A.
Example:
DIMENSION A(5,5)
DATA ((A(I,J),J=1,I),I=1,5)/15*0/
Dummy arguments, functions, and entities in blank common are not allowed in nlist. Entities in a named
common block can be initialized only within a block data subprogram.
The following extensions to data initialization are supported by Open Watcom FORTRAN 77.
- Character constants can initialize a variable of any type. If the item in nlist is of numeric type and
is being initialized with character data, the size of the item in nlist is the maximum number of characters that
can be stored in the space allocated for that item. The rules for initializing such items, are the same as for items
of type character. See the chapter entitled Names, Data Types and Constants
for the number of bytes required for a particular data type.
Example:
INTEGER I,J
DATA I/'AA'/,J/'123456'/
In the previous example, I and J each occupy 4 character storage units. I will be
initialized with the characters AA followed by 2 blank characters. J will be initialized with the
characters 1234. Note the the character constant initializing J is truncated on the right to the
number of character storage units occupied by J.
- As an extension to FORTRAN 77, Open Watcom FORTRAN 77 permits an item of type character to be initialized with integer
data.
Example:
CHARACTER C, D
DATA C/65/, D/66/
END
- Open Watcom FORTRAN 77 allows data initialization using hollerith constants. Initializing items using hollerith
constants behaves in the same way as initializing items using character constants. Note that hollerith data can initialize
entities of any type. See the chapter entitled Names, Data Types and Constants
for a description of hollerith constants.
- Open Watcom FORTRAN 77 allows data initialization using hexadecimal or octal constants. Hexadecimal or octal constants
can be used to initialize memory with any binary pattern.
Items are initialized with hexadecimal constants in the following way. Two hexadecimal digits are required to
initialize one byte of storage. If the number of characters in the hexadecimal constant is less than 2 times the number
of bytes of storage allocated for the entity being initialized, the entity is padded on the left with zeroes. If the
number of characters in the hexadecimal constant is greater than 2 times the number of bytes of storage allocated for the
entity being initialized, the constant is truncated on the left to the size (in bytes) of the entity being initialized.
Items are initialized with octal constants in the following way. Each octal digit initializes three bits of
storage. If the number of digits in the octal constant times 3 is less than the number of bits of storage allocated
for the entity being initialized, the entity is padded on the left with zero bits. If the number of digits in the octal
constant times 3 is greater than the number of bits of storage allocated for the entity being initialized, bits are truncated
on the left to the size (in bits) of the entity being initialized.
Note that hexadecimal or octal data can initialize entities of any type. See the chapter entitled Names, Data Types and Constants
for a description of hexadecimal and octal constants.
Example:
DOUBLE PRECISION DPREC
COMPLEX CMPLX
* Initialize an integer variable with the value 5
DATA I/Z05/
* Initialize a real variable with the value 5.0
DATA X/Z41500000/
* Initialize a double precision variable
* with the value 5D0
DATA DPREC/Z4150000000000000/
* Initialize a complex variable
* with the value (5.0,5.0)
DATA CMPLX/Z4150000041500000/
.
.
.
END
Caution should be used when initializing items with hexadecimal constants, in particular those whose type is real
or double precision, since the data they represent depends on the computer being used. In the previous example, the
hexadecimal constant used to initialize the variable X, represents the number 5.0 on a computer with an IBM 370
architecture. The number 5.0 will have a different floating-point representation on other computers.
DEALLOCATE Statement
DEALLOCATE (arraylist [, STAT = ierr])
- where:
-
arraylist
- is a list of allocatable array names separated by commas.
ierr
- is an integer variable that returns the status of the attempted deallocation.
Allocatable arrays may be dynamically allocated and deallocated at execution time. An array must have been declared
allocatable by specifying its dimensions using colons only. No array bounds are specified.
Example:
DIMENSION A(:), B(:,:)
In the above example, A is declared to be a one-dimensional allocatable array and B is declared
to be a two-dimensional allocatable array.
The DEALLOCATE statement frees up any memory allocated for the specified array(s). It then disassociates
the specified array(s) from the memory to which it was associated. The deallocation does not necessarily succeed.
For example, an attempt to deallocate an array that was not previously allocated will cause an error.
Example:
DIMENSION A(:), B(:,:)
.
.
.
ALLOCATE( A(N), B(0:4,5) )
.
.
.
DEALLOCATE( A )
More than one allocatable array may appear in an DEALLOCATE statement, separated by commas.
Example:
DIMENSION A(:), B(:,:)
.
.
.
ALLOCATE( A(N), B(0:4,5) )
.
.
.
DEALLOCATE( A, B )
If the deallocation fails and the STAT= specifier was not used, an execution-time error occurs. If
the STAT= specifier is used, the specified variable returns a zero value if the deallocation succeeded, and a non-zero
value if the deallocation failed.
Example:
DIMENSION A(:), B(:,:)
.
.
.
ALLOCATE( A(N), B(0:4,5), STAT=IALLOC )
IF( IALLOC .NE. 0 ) PRINT *, 'Allocation failure'
.
.
.
DEALLOCATE( A, B, STAT=IFREE )
IF( IFREE .NE. 0 ) PRINT *, 'Deallocation failure'
An attempt to deallocate an unallocated array results in an execution-time error. The array must be allocated
first (see the ALLOCATE statement).
An array that was allocated using the LOCATION= specifier need not be deallocated.
For more information on arrays, see the chapter entitled Arrays.
DIMENSION Statement
DIMENSION a(d) [,a(d)] ...
- where:
-
a
- is the name of the array.
d
- defines the dimension of the array and the range of its subscripts. See the chapter entitled Arrays
for more information on dimensioning arrays.
Each name a appearing in a DIMENSION statement defines a to be an array in the program unit
containing the DIMENSION statement. A name can only be dimensioned once in a program unit. Note that
a name can also be dimensioned in a COMMON statement and type declaration statements.
Example:
DIMENSION A(10), B(-5:5), C(I,J), D(4,*)
In this example A is a 1-dimensional array containing 10 elements, each element referenced as A(1),
A(2), '...', A(9), A(10). B is a 1-dimensional array containing 11 elements,
each element referenced as B(-5), B(-4), '...', B(4), B(5). C
is a 2-dimensional array containing I rows and J columns. C, I, and J
must be dummy arguments or belong to a common block. D is a 2-dimensional array containing 4 rows.
The * in the last dimension indicates that D is an assumed size array. D must
be a dummy argument. The number of columns is determined from the number of elements of the actual argument.
For example, if the actual argument contains 8 elements then D would contain 2 columns (i.e., 8 elements /
4 rows).
For more information on dimensioning arrays refer to the chapter entitled Arrays. See
also the description of the ALLOCATE and DEALLOCATE statements for information on dynamically allocatable
arrays.
DO Statement
Two forms of the DO statement are presented. The second form is a Open Watcom FORTRAN 77 extension to the
FORTRAN 77 language.
Standard DO Statement
DO s [,] i = e1, e2 [, e3]
- where:
-
s
- is the statement label of an executable statement, called the terminal statement, which follows the DO statement
in the same program unit.
i
- is an integer, real, or double precision variable, called the DO-variable.
e1, e2, e3
- are each an integer, real, or double precision expression.
Extended DO Statement
DO [s[,]] i = e1, e2 [, e3]
[: block-label]
- where:
-
s
- is an optional statement label of an executable statement, called the terminal statement, which follows the DO
statement in the same program unit.
i
- is an integer, real, or double precision variable, called the DO-variable.
e1, e2, e3
- are each an integer, real, or double precision expression.
block-label
- is an optional block label.
This form of the DO statement is an extension to the FORTRAN 77 language. If no statement label is present
then the terminal statement of the DO-loop must be an END DO statement. In all other respects, the rules are
the same as those given for the standard DO statement.
Description of DO Statement
The range of a DO-loop consists of all of the executable statements that appear following the DO statement that
specifies the DO-loop, up to and including the terminal statement of the DO-loop. Only certain statements can be the
terminal statement of a DO-loop. See the section entitled Classifying Statements
at the beginning of this chapter for a list of these statements.
Transfer of control into the range of a DO-loop from outside the range is not permitted.
A DO-loop may be executed 0 or more times. The following sequence occurs when a DO statement is encountered.
- (i)
- An initial value, m1, is calculated by evaluating expression e1. A terminal value,
m2, is calculated by evaluating expression e2. An incrementation value, m3, is calculated
by evaluating expression e3 if it is present; otherwise m3 has the value one. If e3 is specified,
m3 must not be zero. The type of m1, m2, and m3 is determined from the DO-variable and any conversions
of type are done as required.
(ii)
- The DO-variable is defined with the initial value m1.
(iii)
- The iteration count (i.e., the maximum number of times that the DO-loop will be executed) is calculated as follows:
MAX( INT((m2 - m1 + m3)/m3), 0 )
The iteration count will be zero whenever:
m1 > m2 and m3 > 0, or
m1 < m2 and m3 < 0.
The number of times that the DO-loop is executed may be reduced if control is transferred outside the range of the
DO-loop, or if a RETURN or STOP statement is executed.
The steps involved in each iteration of the DO-loop are as follows:
- (i)
- Check the iteration count. If it is not zero then start execution of the first executable statement of the DO-loop.
If the count is zero then iteration of the DO-loop is complete.
(ii)
- Execute statements until the terminal statement is encountered. During this time, the DO-variable may not be redefined.
(iii)
- Execute the terminal statement. Unless execution of the terminal statement causes a transfer of control, proceed with
the next step which is "incrementation" processing.
(iv)
- The DO-variable is incremented by the value m3. The iteration count is decremented by one. Go back to
step (i).
Example:
DO 10 I = -5, 5
PRINT *, I, I*I
10 CONTINUE
In this example, the initial value is -5, the terminal value is 5, and the incrementation value is 1 (the default).
The DO-variable is I. The DO-loop is executed
MAX( INT((5 - (-5) + 1)/1), 0 )
or 11 times. The successive values of I, inside the range of the DO-loop, are -5, -4, -3, ..., 0, 1,
..., 4, 5. When the DO-loop is terminated, the value of I will be 6. It should be noted that when a
DO-loop variable is of type real, the iteration count may be one less than expected. Because of rounding errors, the
value of m2 - m1 + m3 may be slightly less than the exact value and when the INT function is applied, the resulting
iteration count is one less than expected.
Example:
DO 10 X = -5, 6, 2
PRINT *, X, X*X
10 CONTINUE
In this example, the terminal value has been changed to 6 and the incrementation value has been changed to 2.
The DO-variable is X, a real variable. Thus the values of e1, e2 and e3 are converted to
type real. The DO-loop is executed
MAX( INT((6 - (-5) + 2)/2), 0 )
MAX( INT( 13 /
2), 0 )
or 6 times. The successive values of X, inside the range of the DO-loop, are -5.0, -3.0, -1.0, 1.0,
3.0, 5.0. When the DO-loop is terminated, the value of X will be 7.0.
DO-loops may be nested, that is, another DO-loop may be contained within the range of the outer DO-loop. More
than one DO-loop may have the same terminal statement.
Example:
DO 10 I = -5, 5
DO 10 J = -2, 3
10 ARRAY( I, J ) = 0.0
This is equivalent to the following example.
Example:
DO 10 I = -5, 5
DO 20 J = -2, 3
ARRAY(
I, J ) = 0.0
20 CONTINUE
10 CONTINUE
If a DO statement appears within the range of a DO-loop, its range must be entirely contained within the
range of the outer DO-loop.
Example:
* Illegal use of nested DO-loops.
DO 20 I = -5, 5
DO 10 J = -2, 3
ARRAY(
I, J ) = 0.0
20 CONTINUE
10 CONTINUE
The above example is illegal since the terminal statement of the first DO-loop precedes that of the second DO-loop.
Similarly, the range of a DO-loop that appears within the range of an IF-block, ELSE IF-block, or ELSE-block must
be entirely contained within that IF-block, ELSE IF-block, or ELSE-block, respectively. This rule applies to all Open
Watcom FORTRAN 77 structured block extensions.
Example:
* Illegal nesting of a DO-loop and an IF-block.
IF( A .LT. B )THEN
DO 10 I = 1, 5
PRINT
*, 'Iteration number', I
END IF
VECTOR(
I ) = I
10 CONTINUE
The above example is illegal since the range of the IF-block must terminate after the range of the DO-loop.
Note how statement indentation helps to illustrate the problem with this example.
It is also illegal to attempt to transfer control into the range of a DO-loop. The following example illustrates
this error.
Example:
* Illegal transfer into the range of a DO-loop.
GO TO 20
.
.
.
DO 10, I = 100, 0, -1
PRINT *, 'Counting down from
100 to 0', I
20 PRINT *, I, SQRT( FLOAT(I) )
10 CONTINUE
The following example shows a more subtle form of this error.
Example:
* Illegal transfer into the range of a DO-loop.
DO 10 I = 1, 10
* Skip row 5 of 10x10 matrix
IF( I .EQ. 5 )GO TO 10
DO 10 J = 1, 10
A( I,
J ) = 0.0
10 CONTINUE
Since the CONTINUE statement is included in the range of the inner DO-loop, an error message is issued.
The following example illustrates the Open Watcom FORTRAN 77 structured DO statement.
Example:
DO I = -5, 5
DO J = -2, 3
ARRAY(
I, J ) = 0.0
END DO
END DO
In keeping with more modern programming practices, this feature allows the programmer to write DO-loops without resorting
to the use of statement labels. A well-chosen indentation style further enhances the readability of the program.
For more information, see the chapter entitled Program Structure Control Statements.
DOUBLE COMPLEX Statement
The DOUBLE COMPLEX statement is a type declaration statement and can be used to declare a name to be of type
double complex. The implicit type of the name, whether defined by the "first letter rule" (see the chapter
entitled Names, Data Types and Constants) or by an IMPLICIT statement,
is either confirmed or overridden. However, once a name has been declared to be of type double complex, it cannot appear
in another type declaration statement.
There are various forms of the DOUBLE COMPLEX statement. The following sections describe them.
Simple DOUBLE COMPLEX Statement
DOUBLE COMPLEX name [,name] ...
- where:
-
name
- is a variable name, array name, array declarator, symbolic name of a constant, function name or dummy procedure name.
The DOUBLE COMPLEX statement is an extension to the FORTRAN 77 language.
Example:
DIMENSION C(-5:5)
DOUBLE COMPLEX A, B(10), C
In the previous example, A is defined to be a variable of type double complex and B and C
are defined to be arrays of type double complex.
DOUBLE COMPLEX Statement: Data Initialization
DOUBLE COMPLEX name [/cl/] [,name[/cl/]]
...
- where:
-
name
- is as described in the previous section.
cl
- is a list of the form:
k [,k] ...
k
- is one of the forms:
c
r*c (equivalent to r successive appearances of c)
c
- is a constant or the symbolic name of a constant
r
- is an unsigned positive integer constant or the symbolic name of a constant.
This form of the DOUBLE COMPLEX statement is also an extension to the FORTRAN 77 language. The rules for
data initialization are the same as for the DATA statement.
Example:
DOUBLE COMPLEX A/(4D4,5.1D4)/, B(10)/10*(5D1,3.1D1)/
In the previous example, A is initialized with the double precision complex constant (4D4,5.1D4)
and each element of the array B is initialized with the double precision complex constant (5D1,3.1D1).
DOUBLE PRECISION Statement
The DOUBLE PRECISION statement is a type declaration statement and can be used to declare a name to be of type
double precision. The implicit type of the name, whether defined by the "first letter rule" (see the chapter
entitled Names, Data Types and Constants) or by an IMPLICIT statement,
is either confirmed or overridden. However, once a name has been declared to be of type double precision, it cannot
appear in another type declaration statement.
There are various forms of the DOUBLE PRECISION statement. The following sections describe them.
Standard DOUBLE PRECISION Statement
DOUBLE PRECISION name [,name] ...
- where:
-
name
- is a variable name, array name, array declarator, symbolic name of a constant, function name or dummy procedure name.
This form is the standard form of the DOUBLE PRECISION statement.
Example:
DIMENSION C(-5:5)
DOUBLE PRECISION A, B(10), C
In the previous example, A is defined to be a variable of type double precision and B and C
are defined to be arrays of type double precision.
Extended DOUBLE PRECISION Statement: Data Initialization
DOUBLE PRECISION name [/cl/] [,name[/cl/]]
...
- where:
-
name
- is as described in the previous section.
cl
- is a list of the form:
k [,k] ...
k
- is one of the forms:
c
r*c (equivalent to r successive appearances of c)
c
- is a constant or the symbolic name of a constant
r
- is an unsigned positive integer constant or the symbolic name of a constant.
This form of the DOUBLE PRECISION statement is an extension to the FORTRAN 77 language. The rules for data
initialization are the same as for the DATA statement.
Example:
DOUBLE PRECISION A/4D4/, B(10)/10*5D1/
In the previous example, A is initialized with the double precision constant 4D4 and each element
of the array B is initialized with the double precision constant 5D1.
DO WHILE Statement
DO [s[,]] WHILE (e) [:
block-label]
- where:
-
s
- is an optional statement label of an executable statement, called the terminal statement, which follows the DO
statement in the same program unit.
e
- is a logical expression or integer arithmetic expression, in which case the result of the integer expression is compared for
inequality to the integer value 0.
block-label
- is an optional block label.
The DO WHILE statement is an extension to the FORTRAN 77 language.
Example:
X = 0.0
DO 10 WHILE( X .LT. 100.0 )
PRINT *, X, SQRT( X )
X = X + 1.0
10 CONTINUE
If no statement label is present, the terminal statement of the DO-loop must be an END DO statement.
Example:
X = 0.0
DO WHILE( X .LT. 100.0 )
PRINT *, X, SQRT( X )
X = X + 1.0
ENDDO
The following example illustrates the use of an integer arithmetic expression.
Example:
I = 10
DO WHILE( I )
PRINT *, I
I = I - 1
ENDDO
END
The DO WHILE statement, is similar to the DO statement. All nesting rules that apply to the
DO statement also apply to the DO WHILE statement. The difference is the way in which the looping is
accomplished; the DO-loop is executed while the logical expression of the DO WHILE statement has a true value or
until control is transferred out of the DO-loop.
For more information, see the chapter entitled Program Structure Control Statements.
ELSE Statement
ELSE
The ELSE statement is used in conjunction with the IF or ELSE IF statement. The range
of the ELSE block is terminated by a matching END IF statement.
Example:
IF( A .LT. B )THEN
PRINT *, 'A is less than B'
ELSE
PRINT *, 'A is greater than or
equal to B'
END IF
Transfer of control into the range of an ELSE block is illegal. It is interesting to note that the
ELSE statement may be identified by a statement label but it must not be referenced by any statement!
Example:
* Illegal branch to a labelled ELSE statement.
IF( A .LT. B )THEN
PRINT *, 'A is less than B'
100 ELSE
PRINT *, 'A is greater than or
equal to B'
GO TO 100
END IF
The above is an example of an illegal way to construct an infinitely repeating loop. The following is the correct
way to do this.
Example:
IF( A .LT. B )THEN
PRINT *, 'A is less than B'
ELSE
100 PRINT *, 'A is greater than or equal to B'
GO TO 100
END IF
For more information, see the chapter entitled Program Structure Control Statements.
ELSE IF Statement
ELSE IF (e) THEN
- where:
-
e
- is a logical expression or integer arithmetic expression, in which case the result of the integer expression is compared for
inequality to the integer value 0.
The ELSE IF statement is used in conjunction with the IF statement. The range of the ELSE
IF block is terminated by another ELSE IF statement, an ELSE statement, or an END IF statement.
Example:
IF( A .LT. B )THEN
PRINT *, 'A is less than B'
ELSE IF( A .EQ. B )THEN
PRINT *, 'A is equal to B'
ELSE
PRINT *, 'A is greater than B'
END IF
Transfer of control into the range of an ELSE IF block is illegal. It is interesting to note that the
ELSE IF statement may be identified by a statement label but it must not be referenced by any statement!
Example:
* Illegal transfer into the range of
* an ELSE IF statement.
IF( A .EQ. 0.0 )GO TO 110
IF( A .LT. B )THEN
PRINT *, 'A is less than B'
ELSE IF( A .EQ. B )THEN
PRINT *, 'A is equal to B or'
110 PRINT *, 'A is equal to 0'
ELSE
PRINT *, 'A is greater than B'
END IF
The above is an example of an illegal attempt to branch into the range of an ELSE IF block.
For more information, see the chapter entitled Program Structure Control Statements.
END Statement
END
The END statement indicates the end of a sequence of statements and comment lines of a program unit. Execution
of an END statement in a function or subroutine subprogram has the same effect as a RETURN statement.
Control is returned to the invoking program unit. Execution of an END statement in a main program causes termination
of execution of the program.
Example:
SUBROUTINE EULER( X, Y, Z )
.
.
.
END
Upon executing the END statement, execution control is returned to the calling program unit.
Example:
PROGRAM PAYROL
.
.
.
END
Upon executing the END statement, execution of the program is terminated.
Some rather special rules apply to the END statement. The statement is written in columns 7 to 72 of
an initial line. In other words, it must not be continued. Also, no other statement in the program unit may have
an initial line that appears to be an END statement.
Example:
* An illegal ENDIF statement.
IF( A .LT. B )THEN
.
.
.
END
&IF
The above END IF statement is illegal since the initial line appears to be an END statement.
END AT END Statement
END AT END
The END AT END statement is used in conjunction with the structured AT END statement. The
END AT END statement marks the end of a sequence of statements which are part of an AT END-block. The AT END
statement marks the beginning of the AT END-block. The AT END-block is executed when the preceding READ statement
terminates because of an end-of-file condition.
Example:
READ( UNIT=1, FMT='(3I5)' ) I, J, K
AT END DO
PRINT *, 'END-OF-FILE ENCOUNTERED
ON UNIT 1'
EOFSW = .TRUE.
END AT END
For more information, see the chapter entitled Program Structure Control Statements.
END BLOCK Statement
END BLOCK
The END BLOCK statement is used to terminate a REMOTE-block. The END BLOCK statement is implicitly
a transfer statement, since it returns program control from a REMOTE-block.
Example:
REMOTE BLOCK A
I=I+1
PRINT *, 'I=',I
END BLOCK
For more information, see the description of the EXECUTE and REMOTE BLOCK statements or the chapter
entitled Program Structure Control Statements.
END DO Statement
END DO
The END DO statement is used to terminate the range of a "structured" DO statement.
A structured DO statement is one in which a statement label is not present. For more information, see the
description of the structured DO statement or the chapter entitled Program Structure Control Statements.
Example:
DO X = -5.1, 12.8, 0.125
.
.
.
END DO
Example:
X = -5.1
DO WHILE( X .LE. 12.8 )
.
.
.
X = X + 0.125
END DO
ENDFILE Statement
ENDFILE u
ENDFILE (alist)
- where:
-
u
- is an external unit identifier.
alist
- is a list of endfile specifiers separated by commas:
[UNIT =] u
IOSTAT = ios
ERR = s
Execution of an ENDFILE statement causes an endfile record to be written to the file connected to the specified
unit. The file is then positioned after the endfile record. If the file may be connected for direct access,
only those records before the endfile record are considered to have been written. Thus, only those records before the
endfile record may be read during subsequent direct access connections to the file.
- Endfile Specifiers
-
[UNIT =] u
-
u is an external unit identifier. An external unit identifier is a non-negative integer expression.
If the optional UNIT= specifier is omitted then the specifier must be the first item in the list of specifiers.
IOSTAT = ios
-
is an input/output status specifier. The integer variable or integer array element ios is defined
with zero if no error condition exists or a positive integer value if an error condition exists.
ERR = s
-
is an error specifier and s is a statement label. When an error occurs, execution is transferred
to the statement labelled by s.
Example:
LOOP
READ( UNIT=7, END=100, FMT=200
)RECORD
WRITE( UNIT=8, FMT=200 )RECORD
ENDLOOP
100 ENDFILE( UNIT=8 )
In the previous example, we illustrate how one might read all the records from one file (unit 7), write them to another
file (unit 8) and then write an endfile record to the end of the file on unit 8.
Notes:
- The unit must be connected for sequential access.
- After execution of an ENDFILE statement, a BACKSPACE or REWIND statement must be used to reposition
the file before any other input/output statement which refers to this file can be executed.
- If the file did not exist before execution of the ENDFILE statement then it will be created after execution of
this statement.
For more information on input/output, see the chapter entitled Input/Output.
END GUESS Statement
END GUESS
The END GUESS statement is used in conjunction with the structured GUESS statement. The END
GUESS statement marks the end of a series of GUESS-ADMIT blocks.
Example:
CHARACTER CH
READ *, CH
GUESS
IF( CH .LT. 'a' )QUIT
IF( CH .GT. 'z' )QUIT
PRINT *, 'Lower case letter'
ADMIT
IF( CH .LT. 'A' )QUIT
IF( CH .GT. 'Z' )QUIT
PRINT *, 'Upper case letter'
ADMIT
IF( CH .LT. '0' )QUIT
IF( CH .GT. '9' )QUIT
PRINT *, 'Digit'
ADMIT
PRINT *, 'Special character'
END GUESS
END
For more information, see the chapter entitled Program Structure Control Statements.
END IF Statement
END IF
The END IF statement is used in conjunction with the block IF statement. The END IF statement
marks the end of a sequence of statements which are to be conditionally executed.
Example:
IF( X .LT. 100.0 )THEN
PRINT *, 'X IS LESS THAN 100'
END IF
The END IF statement can also be used in conjunction with the ELSE and ELSE IF statements.
For more information, see the chapter entitled Program Structure Control Statements.
END LOOP Statement
END LOOP
The END LOOP statement is used in conjunction with the structured LOOP statement. The END
LOOP statement marks the end of a sequence of statements which are to be repeated. The LOOP statement
marks the beginning of the loop. The LOOP-block is executed until control is transferred out of the LOOP-block.
The QUIT statement may be used to transfer control out of a LOOP-block.
Example:
LOOP
READ *, X
IF( X .GT. 99.0 ) QUIT
PRINT *, X
END LOOP
For more information, see the chapter entitled Program Structure Control Statements.
END MAP Statement
END MAP
The END MAP statement is used in conjunction with the MAP declarative statement. The END MAP
statement marks the end of a MAP structure. The following example maps out a 4-byte integer on an Intel 80x86-based
processor.
Example:
STRUCTURE /MAPINT/
UNION
MAP
INTEGER*4 LONG
END MAP
MAP
INTEGER*2 LO_WORD
INTEGER*2 HI_WORD
END MAP
MAP
INTEGER*1 BYTE_0
INTEGER*1 BYTE_1
INTEGER*1 BYTE_2
INTEGER*1 BYTE_3
END MAP
END UNION
END STRUCTURE
RECORD /MAPINT/ I
I%LONG = '01020304'x
PRINT '(2Z4)', I%LO_WORD, I%HI_WORD
END
For more information, see the chapter entitled Structures, Unions and Records.
END SELECT Statement
END SELECT
The END SELECT statement is used in conjunction with the SELECT statement. The END SELECT
statement marks the end of a series of CASE blocks.
Example:
SELECT CASE ( CH )
CASE ( 'a' : 'z' )
PRINT *, 'Lower case letter'
CASE ( 'A' : 'Z' )
PRINT *, 'Upper case letter'
CASE ( '0' : '9' )
PRINT *, 'Digit'
CASE DEFAULT
PRINT *, 'Special character'
END SELECT
For more information, see the chapter entitled Program Structure Control Statements.
END STRUCTURE Statement
END STRUCTURE
The END STRUCTURE statement is used in conjunction with the STRUCTURE declarative statement. The
END STRUCTURE statement marks the end of a structure definition.
Example:
STRUCTURE /ADDRESS/
CHARACTER*20 STREET
CHARACTER*20 CITY
CHARACTER*20 STATE
CHARACTER*20 COUNTRY
CHARACTER*10 ZIP_CODE
END STRUCTURE
STRUCTURE /PEOPLE/
CHARACTER*20 NAME
RECORD /ADDRESS/ ADDR
INTEGER*2 AGE
END STRUCTURE
For more information, see the chapter entitled Structures, Unions and Records.
END UNION Statement
END UNION
The END UNION statement is used in conjunction with the UNION declarative statement. The END
UNION statement marks the end of a series of MAP structures. The following example maps out a 4-byte
integer on an Intel 80x86-based processor.
Example:
STRUCTURE /MAPINT/
UNION
MAP
INTEGER*4 LONG
END MAP
MAP
INTEGER*2 LO_WORD
INTEGER*2 HI_WORD
END MAP
MAP
INTEGER*1 BYTE_0
INTEGER*1 BYTE_1
INTEGER*1 BYTE_2
INTEGER*1 BYTE_3
END MAP
END UNION
END STRUCTURE
RECORD /MAPINT/ I
I%LONG = '01020304'x
PRINT '(2Z4)', I%LO_WORD, I%HI_WORD
END
For more information, see the chapter entitled Structures, Unions and Records.
END WHILE Statement
END WHILE
The END WHILE statement is used in conjunction with the structured WHILE statement. The END
WHILE statement marks the end of a sequence of statements which are to be repeated. The WHILE statement
marks the beginning of the WHILE-block. The WHILE-block is executed while the logical expression (or integer arithmetic
expression) of the WHILE statement has a true (or non-zero) value or until control is transferred out of the WHILE-block.
Example:
X = 1.0
WHILE( X .LT. 100 )DO
PRINT *, X, SQRT( X )
X = X + 1.0
END WHILE
Example:
I = 10
WHILE( I )DO
PRINT *, I
I = I - 1
ENDWHILE
END
For more information, see the chapter entitled Program Structure Control Statements.
ENTRY Statement
ENTRY name [( [d [, d] ...] )]
- where:
-
name
- is a symbolic name of an entry in a function or subroutine subprogram. If the ENTRY statement appears in a
subroutine subprogram then name is a subroutine name. If the ENTRY statement appears in a
function subprogram then name is an external function name.
d
- is a variable name, array name, dummy procedure name, or an asterisk. d is called a dummy argument.
An asterisk is allowed only in a subroutine subprogram.
The ENTRY statement is used to define an alternate entry into a subprogram.
Example:
PRINT *, TMAX2( 121.0, -290.0 )
PRINT *, TMAX3( -1.0, 12.0, 5.0 )
END
FUNCTION TMAX3( ARGA, ARGB, ARGC )
T3 = ARGC
GO TO 10
ENTRY TMAX2( ARGA, ARGB )
T3 = ARGA
10 TMAX2 = ARGA
IF( ARGB .GT. TMAX2 ) TMAX2 =
ARGB
IF( T3 .GT. TMAX2 ) TMAX2 = T3
END
In the above example, an entry was defined to permit us to find the maximum of two real variables. Either the
entry name TMAX2 or the function name TMAX3 could have been used as the variable for returning the maximum
value since they agree in type. It is not necessary to precede an ENTRY statement with a transfer statement
as the ENTRY statement is not an executable statement; the next statement executed will be the first executable
statement following the ENTRY statement.
Notes:
- No dummy arguments need be specified in the ENTRY statement. If this is the case, the parentheses () are
optional.
For more information, see the chapter entitled Functions and Subroutines.
EQUIVALENCE Statement
EQUIVALENCE (nlist) [,(nlist)] ...
- where:
-
nlist
- is a list of at least two names, each name separated by a comma.
The names appearing in nlist can be variable names, array names, array element names, character names, character
substring names, and character array element substring names. Dummy arguments are not allowed in nlist.
The EQUIVALENCE statement specifies that the storage occupied by the entities appearing in nlist
all start at the same place. It in no way changes the characteristics of an object. For example, if a variable
is equivalenced to an array, the variable does not inherit the properties of the array. Similarly, if a variable of
type integer is equivalenced to a variable of type real, there is no implied type conversion.
If an array element name appears in an EQUIVALENCE statement, the number of subscript expressions must be
the same as the number of dimensions specified when the array was declared and each subscript expression must be in the range
specified. As an extension to FORTRAN 77, Open Watcom FORTRAN 77 allows a single subscript expression for a multi-dimensional
array. An array name used by itself is equivalent to specifying the first element of the array.
If a character substring appears in an EQUIVALENCE statement, the substring defined by the substring expression
must be properly contained in the character entity being substring. A character name used by itself is equivalent to
specifying the first character of the character variable.
Example:
REAL A,B
DIMENSION A(10),B(20)
EQUIVALENCE (A,B(16))
In the above example, the first 5 elements of A occupy the same storage as the last 5 elements of B.
Example:
DIMENSION A(10)
EQUIVALENCE (C,A(2)),(D,A(4))
In the above example, C is assigned the same storage unit as A(2) and D is assigned the
same storage unit as A(4).
The following example illustrates a Open Watcom FORTRAN 77 extension.
Example:
REAL A(2,10),B(20),C(2,2,5)
EQUIVALENCE (A(5),B(1)),(B(1),C(1))
In the above example, a single subscript is specified for arrays A and C. The following table
shows the mapping of a 2-dimensional array onto a 1-dimensional array.
A(1,1) == A(1)
A(2,1) == A(2)
A(1,2) == A(3)
A(2,2) == A(4)
A(1,3) == A(5)
A(2,3) == A(6)
.
.
.
In the above table, "==" is read as "is equivalent to". In FORTRAN, arrays are stored in
"column major" format (i.e., arrays are stored column by column rather than row by row).
Example:
CHARACTER*5 A, D
EQUIVALENCE (A(3:5), D(1:3))
In this example, the last 3 characters of A occupy the same character storage units as the first 3 characters
of D.
There are certain restrictions on EQUIVALENCE statements. It is not possible to equivalence a storage
unit to 2 different storage units. This is illustrated by the following example.
Example:
* Illegally equivalencing a storage unit to
* 2 different storage units.
DIMENSION A(2)
EQUIVALENCE (A(1),B),(A(2),B)
B has been given 2 different storage units.
It is also not possible to specify that consecutive storage units be non-consecutive. For example,
Example:
* Illegally equivalencing consecutive storage units to
* non-consecutive storage units.
DIMENSION A(2),B(2)
EQUIVALENCE (A(1),B(2)),(A(2),B(1))
A(1) and A(2) are consecutive but B(1) and B(2) are not.
The FORTRAN 77 standard specifies that character and numeric data cannot be equivalenced; Open Watcom FORTRAN 77 allows
character and numeric data to be equivalenced.
EXECUTE Statement
EXECUTE name
- where:
-
name
- is the name of a REMOTE BLOCK located in the same program unit.
The EXECUTE statement allows a named block of code to be executed. The named block of code may be defined
anywhere in the same program unit and is delimited by the REMOTE BLOCK and END BLOCK statements.
Executing a REMOTE-block is similar in concept to calling a subroutine, with the advantage that shared variables do not need
to be placed in a COMMON block or passed in an argument list. When execution of the REMOTE-block is complete
(i.e., when the END BLOCK statement is executed), control returns to the statement following the EXECUTE
statement which invoked it.
Example:
EXECUTE INCR
PRINT *, 'FIRST'
EXECUTE INCR
PRINT *, 'SECOND'
.
.
.
REMOTE BLOCK INCR
I=I+1
PRINT *, 'I=',I
END BLOCK
For more information, see the chapter entitled Program Structure Control Statements.
EXIT Statement
EXIT [: block-label]
The EXIT statement is used to transfer control:
- from within a loop (DO, DO WHILE, WHILE or LOOP) to the statement following the loop,
- from within a GUESS or ADMIT block to the statement following the ENDGUESS statement, or
- from within a remote block to the statement following the EXECUTE statement that invoked the remote block.
The EXIT statement may be used to cause a transfer of control to the first executable statement that follows
the terminal statement of the block which contains it. Examples of such terminal statements are END DO,
END LOOP, END WHILE, UNTIL, etc. If block-label is present then control is transferred
out of the block identified by that block label. The EXIT statement is an extension to the FORTRAN 77 language.
Example:
LOOP
WRITE( UNIT=*, FMT='(A)' ) 'Enter
a number'
READ( UNIT=*, FMT='(F10.4)',
IOSTAT=IOS ) X
IF( IOS .NE. 0 ) EXIT
IF( X .LT. 0 ) EXIT
PRINT *, X, SQRT( X )
END LOOP
END
For more information, see the chapter entitled Program Structure Control Statements.
EXTERNAL Statement
EXTERNAL p [,p] ...
- where:
-
p
- is the name of an external procedure, dummy procedure or block data subprogram.
The EXTERNAL statement identifies a symbolic name to be a dummy procedure or an external procedure and allows
these names to be passed as an actual argument. In the following example, SAM, ERRRTN and POLY are
declared to be external procedures.
Example:
EXTERNAL SAM, ERRRTN, POLY
In the following example, F is declared to be an external procedure and is passed as such to subroutine
SAM. If the EXTERNAL statement were eliminated then the variable F would be passed on to subroutine
SAM since there is no way of knowing that F is an external function.
Example:
EXTERNAL F
.
.
.
CALL SAM( F )
The appearance of an intrinsic function in an EXTERNAL statement declares that name to be an external procedure
and the intrinsic function by that name is no longer available in that program unit. This allows the programmer to
define a function by the same name as an intrinsic function. In the following example, the programmer's SIN
function will be called instead of the intrinsic SIN function.
Example:
EXTERNAL SIN
.
.
.
CALL SIN( .1 )
A statement function name must not appear in an EXTERNAL statement. A name must only appear in an
EXTERNAL statement once.
label FORMAT fs
- where:
-
fs
- is a format specification and is described in the chapter entitled Format.
label
- is the statement label used by an I/O statement to identify the FORMAT statement to be used. The FORMAT
statement must be labelled.
Example:
REAL X
X = 234.43
PRINT 100, X
100 FORMAT(F10.2)
END
In the previous example, the PRINT statement uses the format specification in the FORMAT statement
whose statement label is 100 to display the value of X.
For more information on the FORMAT statement, see the chapter entitled Format.
FUNCTION Statement
A FUNCTION statement is used to define the start of a function subprogram. There are two forms of the
FUNCTION function statement. The second form is a Open Watcom FORTRAN 77 extension.
Standard FUNCTION Statement
[type] FUNCTION fun ( [d [, d] ...]
)
- where:
-
type
- is one of LOGICAL, INTEGER, REAL, DOUBLE PRECISION, COMPLEX or CHARACTER [*len].
fun
- is a symbolic name of a function subprogram.
d
- is a variable name, array name, or a dummy procedure name. d is called a dummy argument.
len
- is called the length specification and is the length (number of characters) of the result of the character function.
It has one of the following forms:
- (1)
- An unsigned positive integer constant.
(2)
- A positive integer constant expression enclosed in parentheses.
(3)
- An asterisk in parentheses, (*).
Example:
PRINT *, TMAX3( -1.0, 12.0, 5.0 )
END
FUNCTION TMAX3( ARGA, ARGB, ARGC )
TMAX3 = ARGA
IF( ARGB .GT. TMAX3 ) TMAX3 =
ARGB
IF( ARGC .GT. TMAX3 ) TMAX3 =
ARGC
END
In the above example, the function TMAX3 is defined to find the maximum of three real variables.
Notes:
- No dummy arguments need be specified in the FUNCTION statement. However, the parentheses () are mandatory.
For more information, see the chapter entitled Functions and Subroutines.
Extended FUNCTION Statement
[type[*len]] FUNCTION fun[*len] (
[d [, d] ...] )
- where:
-
type
- is one of LOGICAL, INTEGER, REAL, DOUBLE PRECISION, COMPLEX, CHARACTER or RECORD /typename/
fun
- is a symbolic name of a function subprogram.
d
- is a variable name, array name, or a dummy procedure name. d is called a dummy argument.
len
- is called the length specification and has one of the following forms:
- (1)
- An unsigned positive integer constant.
(2)
- A positive integer constant expression enclosed in parentheses.
(3)
- An asterisk in parentheses, (*).
For valid values of len, refer to the appropriate type declaration statement.
This form of the FUNCTION statement is an extension to the FORTRAN 77 language.
Example:
INTEGER*2 MOD2, I, J
I = 12
J = 5
PRINT *, MOD2( I, J )
END
INTEGER*2 FUNCTION MOD2( I, J )
INTEGER*2 I, J
INTEGER II, JJ
II = I
JJ = J
MOD2 = MOD(II, JJ)
END
Notes:
- No dummy arguments need be specified in the FUNCTION statement. However, the parentheses () are mandatory.
- The length specification can appear only once in the FUNCTION statement.
For more information, see the chapter entitled Functions and Subroutines.
Unconditional GO TO Statement
GO TO s
- where:
-
s
- is the statement label of an executable statement that appears in the same program unit as the GO TO statement.
Example:
GO TO 10
.
.
.
10 S = S + 1
When the GO TO statement is executed, control is transferred to the statement identified by that label.
In the above example, the GO TO statement causes execution to proceed to the statement labelled 10.
Example:
* An illegal GO TO statement
GO TO 100
.
.
.
100 FORMAT( 1X, 3F10.2 )
The above example contains an illegal GO TO statement since the statement identified by the label 100 is
not executable.
Computed GO TO Statement
GO TO (s [,s]...) [,] i
- where:
-
i
- is an integer expression.
s
- is the statement label of an executable statement that appears in the same program unit as the computed GO TO statement.
The integer expression i is evaluated and the ith label is selected for transfer of control. If
i is less than 1 or greater than the number of statement labels in the list then execution control continues with the
next executable statement that follows the computed GO TO statement.
Example:
GO TO (110, 120, 130, 140) INDEX
100 CALL AUDIT
In the above example, control is transferred to the statement identified by the label 110 if INDEX has the
value 1, the label 120 if INDEX has the value 2, etc. If INDEX has a value that is negative, zero
or larger than 4, control continues with the statement labelled 100. In this example, the integer expression consists
simply of an integer variable.
Example:
GO TO (100, 200, 100, 200, 100, 200), I/10
The above example illustrates that statement labels may be repeated in the list and that a "," may follow
the closing right parenthesis.
Assigned GO TO Statement
GO TO i [[,] (s [,s]...)]
- where:
-
i
- is an integer variable name.
s
- is the statement label of an executable statement that appears in the same program unit as the assigned GO TO statement.
The variable i must be defined with the value of a statement label of an executable statement that appears in
the same program unit (see the ASSIGN statement). The execution of the assigned GO TO statement causes
a transfer of control to the statement that is identified by that label.
Example:
INTEGER RET
X = 0.0
ASSIGN 100 TO RET
GO TO 3000
100 X = X + 1
ASSIGN 110 TO RET
GO TO 3000
110 X = X + 1
.
.
.
* Print both X and its square root
3000 Y = SQRT( X )
PRINT *, X, Y
GO TO RET
In the above example, we illustrate the use of the ASSIGN statement and the assigned GO TO statement
to implement a "local subroutine" in a program unit. A sequence of often-used code can be "called"
using the unconditional GO TO statement and "return" is accomplished using the assigned GO TO
statement. Care must be exercised to properly assign the return label value.
If a list of statement labels is present then the statement label assigned to i must be in the list.
If it is not in the list, an error will occur when the assigned GO TO statement is executed. Unlike the computed
GO TO statement, execution does not continue with the next statement. This is demonstrated by the following example.
Note that the "," preceding the statement label list is optional.
Example:
* Illegal use of the assigned GO TO:
* Statement label 100 does not appear in the statement
* label list of the assigned GO TO statement.
ASSIGN 100 TO ICASE
GO TO ICASE, (110, 120, 130)
* beginning of selections
100 PRINT *, 100
GO TO 200
110 PRINT *, 110
GO TO 200
120 PRINT *, 120
GO TO 200
130 PRINT *, 130
* end of selections
200 END
GUESS Statement
GUESS [: block-label]
The GUESS statement is an extension to the FORTRAN 77 language. The GUESS statement marks the
beginning of a block of statements for which a certain assumption or hypothesis has been made. This hypothesis may
be tested using logical IF statements in conjunction with QUIT statements. The ADMIT statement
may be used to mark the beginning of an alternate hypothesis. The END GUESS statement is used to mark the
end of a series of GUESS-ADMIT blocks.
Example:
CHARACTER CH
READ *, CH
GUESS
IF( CH .LT. 'a' )QUIT
IF( CH .GT. 'z' )QUIT
PRINT *, 'Lower case letter'
ADMIT
IF( CH .LT. 'A' )QUIT
IF( CH .GT. 'Z' )QUIT
PRINT *, 'Upper case letter'
ADMIT
IF( CH .LT. '0' )QUIT
IF( CH .GT. '9' )QUIT
PRINT *, 'Digit'
ADMIT
PRINT *, 'Special character'
END GUESS
END
An optional block label may be specified with the GUESS statement.
For more information, see the chapter entitled Program Structure Control Statements.
Arithmetic IF Statement
IF (e) s1, s2, s3
- where:
-
e
- is an integer, real, or double precision expression.
s1, s2, s3
- are statement labels of executable statements that appear in the same program unit as the arithmetic IF statement.
The expression e is evaluated and if the value is less than zero then transfer is made to the statement identified
by label s1. If the value is equal to zero then transfer is made to the statement identified by label
s2. If the value is greater than zero then transfer is made to the statement identified by label s3.
Example:
IF( SIN( X ) ) 10, 20, 30
10 PRINT *, 'SIN(X) IS < 0'
GO TO 40
20 PRINT *, 'SIN(X) = 0'
GO TO 40
30 PRINT *, 'SIN(X) > 0'
40 CONTINUE
The above example evaluates the sine of the real variable X and prints whether the result is less than 0,
equal to 0, or greater than 0.
The same label may appear more than once in the arithmetic IF statement.
Example:
IF( SIN( X ) ) 10, 10, 30
10 PRINT *, 'SIN(X) IS <= 0'
GO TO 40
30 PRINT *, 'SIN(X) > 0'
40 CONTINUE
The above example evaluates the sine of the real variable X and prints whether the result is less than or
equal to zero, or that it is greater than 0.
Logical IF Statement
IF (e) st
- where:
-
e
- is a logical expression or integer arithmetic expression, in which case the result of the integer expression is compared for
inequality to the integer value 0.
st
- is an executable statement. Only certain executable statements are allowed. See the section entitled Classifying Statements
at the beginning of this chapter for a list of allowable statements.
The expression e is evaluated and must result in a true or a false value. If the result is true then the
statement st is executed, otherwise it is not executed.
Example:
IF( A .LT. B )PRINT *, 'A < B'
In the above example, the logical expression A .LT. B is evaluated and, if it is true, the message
A < B is printed. A logical expression is one in which the result is either true or false. An expression
such as 1 + 2 is clearly not an example of a logical expression.
Logical variables have logical values of true or false and may also be used in the logical expression. Consider
the following two examples.
Example:
LOGICAL RESULT
RESULT = A .LT. B
IF( RESULT )PRINT *, 'A < B'
The above example is equivalent to the preceding one but introduces the use of a logical variable.
Example:
LOGICAL RESULT
RESULT = A .LT. B
IF( .NOT. RESULT )PRINT *, 'A >= B'
In the above example, the logical expression is negated through the use of the .NOT. operator in order
to test for the inverse condition, namely .GE..
Much more complex logical expressions can be constructed and then tested for their truth value.
Example:
IF( A.LT.B .OR. C.GE.D )PRINT *, 'A<B or C>=D'
An example of an integer expression in an IF statement follows:
Example:
I = 1
* Integer arithmetic expression
IF( I )THEN
PRINT
*, 'Yes'
ENDIF
* Equivalent logical expression
IF( I .NE. 0 )THEN
PRINT
*, 'Yes'
ENDIF
END
Block IF Statement
There are two forms of the block IF statement. The second is a Open Watcom FORTRAN 77 extension.
Standard Block IF Statement
IF (e) THEN
- where:
-
e
- is a logical expression.
The block IF statement is used in conjunction with the ELSE IF, ELSE, and END IF statements.
Example:
IF( A .LT. B )THEN
PRINT *, 'A < B'
END IF
For more information, see the chapter entitled Program Structure Control Statements.
Extended Block IF Statement
IF (e) THEN [: block-label]
- where:
-
e
- is a logical expression or integer arithmetic expression, in which case the result of the integer expression is compared for
inequality to the integer value 0.
block-label
- is an optional block label.
This form of the block IF statement is an extension to the FORTRAN 77 language. It is identical to the
standard form of the block IF statement with the exception that an integer arithmetic expression and an optional
block label are permitted.
Example:
IF( I .EQ. 10 )THEN : IFBLK
IF( J .EQ. 20 )THEN
.
.
.
IF( K.
EQ. 0 )QUIT : IFBLK
.
.
.
END IF
.
.
.
END IF
In the previous example, the QUIT statement will transfer control to the statement following the second
END IF statement.
IMPLICIT Statement
Open Watcom FORTRAN 77 supports three forms of the IMPLICIT statement. The second and third forms are extensions
to the FORTRAN 77 language.
Standard IMPLICIT Statement
IMPLICIT type (a [,a] ...) [,type (a [,a]
...)]...
- where:
-
type
- is one of LOGICAL, INTEGER, REAL, DOUBLE PRECISION, COMPLEX or CHARACTER[*len].
a
- is either a single letter or a range of letters denoted by separating the first letter in the range from the last letter in
the range by a minus sign.
len
- is the length of the character entities and is a positive unsigned integer constant or a positive integer constant expression
enclosed in parentheses. If len is not specified, the length is 1.
Extended IMPLICIT Statement
IMPLICIT type[*len] (a [,a] ...)
[,type[*len]
(a [,a] ...)] ...
- where:
-
type
- is one of LOGICAL, INTEGER, REAL, DOUBLE PRECISION, COMPLEX or CHARACTER.
len
- is a positive unsigned integer constant or a positive integer constant expression enclosed in parentheses. If type
is CHARACTER then (*) is also allowed. The possible values of len are as follows:
- If type is LOGICAL then len can be 1 or 4. The default is 4.
- If type is INTEGER then len can be 1, 2 or 4. The default is 4.
- If type is REAL then len can be 4 or 8. The default is 4.
- If type is DOUBLE PRECISION then len cannot be specified.
- If type is COMPLEX then len can be 8 or 16. The default is 8.
- If type is CHARACTER then len can be (*) or any positive integer.
IMPLICIT NONE Statement
IMPLICIT NONE
Description of IMPLICIT Statement
The IMPLICIT statement defines the default type and length for all variables, arrays, symbolic constants, external
functions and statement functions that begin with any letter that has appeared in an IMPLICIT statement as a single
letter or as a member of a range of letters.
The following example specifies that any name beginning with the letters A, D, E, F or G will have
default a default type of integer and any name beginning with the letters X, Y or Z will have a default
type of character and length 3.
Example:
IMPLICIT INTEGER (A,D-G), CHARACTER*3 (X-Z)
The next example illustrates the extended form of the IMPLICIT statement.
Example:
IMPLICIT INTEGER*2 (A,B), LOGICAL*1 (C-F)
IMPLICIT COMPLEX*16 (X,Y,Z), REAL*8 (P)
Specifying NONE in the IMPLICIT statement will cause Open Watcom FORTRAN 77 to issue an error when a symbol
is used and has not appeared in a type specification statement.
Example:
* Referencing X will cause an error
IMPLICIT NONE
X = 13143.383
In the above example, the IMPLICIT statement specifies that the type of all symbols must be explicitly declared
in a type specification statement. The assignment statement will cause an error since the type of X has not
been explicitly declared.
Notes:
- The implicit type set by an IMPLICIT statement may be overridden or confirmed for any variable, array, symbolic
constant, external function or statement function name by its appearance in a type statement. The default length specification
may also be overridden or confirmed in a type statement.
Example:
IMPLICIT CHARACTER*10 (S-U)
IMPLICIT INTEGER*2 (P)
CHARACTER STRING
INTEGER POINTS
In the above example, the variable STRING is of type character but its length is 1 since it has appeared
in a CHARACTER statement which has a default length of 1. Also, the variable POINTS is of type integer
but its length is 4 since it has appeared in an INTEGER statement which has a default length of 4.
- A letter cannot appear more than once as a single letter or be included in a range of letters in all IMPLICIT
statements in a program unit.
- An IMPLICIT statement applies only to the program unit that contains it.
- The IMPLICIT statement does not change the type of intrinsic functions.
- A program unit can contain more than one IMPLICIT statement.
- Within the specification statements of a program unit, IMPLICIT statements must precede all other specification
statements except PARAMETER statements.
- The IMPLICIT NONE statement is allowed only once in a program unit. Furthermore, no other IMPLICIT
statement can be specified in the program unit containing an IMPLICIT NONE statement.
INCLUDE Statement
INCLUDE 'inc_spec'
- where:
-
inc_spec
- is an include specification. You should refer to the compiler's User's Guide for a detailed description of an include
specification and include file processing.
Example:
INCLUDE 'GBLDEFS'
.
.
.
END
INQUIRE Statement
The INQUIRE statement is used to ask about certain properties of a named file or its connection to a particular
unit. There are two forms of the INQUIRE statement; inquire by file name and inquire by unit.
INQUIRE by FILE
INQUIRE (iflist)
- where:
-
iflist
- includes the FILE= specifier and may include at most one of each of the inquiry specifiers listed below. Specifiers
are separated by commas. The FILE= specifier has the form
FILE = fin
where fin is a character expression whose value when trailing blanks are removed is the name of a file being
inquired about. The file need not exist or be connected to a unit.
Example:
LOGICAL EX, OD
INTEGER NUM
INQUIRE( FILE='ROLL',EXIST=EX,OPENED=OD,NUMBER=NUM )
In the above example, information is requested on the file PAYROLL. In particular, we want to know
if it exists, whether it is connected to a unit, and what the unit number is (if it is indeed connected).
INQUIRE by UNIT
INQUIRE (iulist)
- where:
-
iulist
- includes the UNIT= specifier and may include at most one of each of the inquiry specifiers listed below. Specifiers
are separated by commas. The UNIT= specified has the form
[UNIT =] u
where u is an external unit identifier. An external unit identifier is a non-negative integer
expression. If the optional UNIT= specifier is omitted then the specifier must be the first item in the list
of specifiers.
Example:
LOGICAL EX, OD
CHARACTER*30 FN
INQUIRE( UNIT=7, EXIST=EX, OPENED=OD, NAME=FN )
In the above example, information is requested on unit 7. In particular, we want to know if the unit exists,
whether it is connected to a file, and, if so, what the file name is.
Inquiry Specifiers
The following inquiry specifiers are supported.
IOSTAT = ios
ERR = s
EXIST = ex
OPENED = od
NUMBER = num
NAMED = nmd
NAME = fn
ACCESS = acc
SEQUENTIAL = seq
DIRECT = dir
FORM = fm
FORMATTED = fmt
UNFORMATTED = unf
RECL = rcl
NEXTREC = nr
BLANK = blnk
As an extension to the FORTRAN 77 language, the following inquiry specifiers are also supported.
ACTION = act
CARRIAGECONTROL = cc
RECORDTYPE = rct
BLOCKSIZE = bl
- IOSTAT = ios
- is an input/output status specifier. The integer variable or integer array element ios is defined with
zero if no error condition exists or a positive integer value if an error condition exists.
ERR = s
- is an error specifier and s is a statement label. When an error occurs, execution is transferred to
the statement labelled by s.
EXIST = ex
- ex is a logical variable or logical array element.
Inquire by file: The value .TRUE. is assigned if a file exists with the specified name; otherwise the value
.FALSE. is assigned.
Inquire by unit: The value .TRUE. is assigned if the specified unit exists; otherwise the value .FALSE.
is assigned.
OPENED = od
- od is a logical variable or logical array element.
Inquire by file: The value .TRUE. is assigned if the specified file is connected to a unit; otherwise the
value .FALSE. is assigned.
Inquire by unit: The value .TRUE. is assigned if the specified unit is connected to a file; otherwise
the value .FALSE. is assigned.
NUMBER = num
- num is an integer variable or integer array element that is assigned the value of the unit number to which the file
is connected. If no unit is connected to the file then num becomes undefined.
NAMED = nmd
- nmd is a logical variable or logical array element name that is assigned the value .TRUE. if the file has
a name; otherwise the value .FALSE. is assigned.
NAME = fn
- fn is a character variable or character array element. Open Watcom FORTRAN 77 also permits fn to
be a character substring.
It is assigned the name of the file, if the file has a name; otherwise it becomes undefined. The file name that
is returned need not be the same as that given in a FILE= specifier but it must be suitable for use in the FILE=
specification of an OPEN statement (e.g., the file name returned may have additional system qualifications attached
to it).
ACCESS = acc
- acc is a character variable or character array element. Open Watcom FORTRAN 77 also permits acc to
be a character substring.
It is assigned the value 'SEQUENTIAL' if the file is connected for sequential access. It is assigned the
value 'DIRECT' if the file is connected for direct access. It is assigned an undefined value if there is no
connection.
SEQUENTIAL = seq
- seq is a character variable or character array element. Open Watcom FORTRAN 77 also permits seq to
be a character substring.
It is assigned the value 'YES' if SEQUENTIAL is included in the set of allowed access methods for the
file, the value 'NO' if SEQUENTIAL is not included in the set of allowed access methods for the file, or
'UNKNOWN' if Open Watcom FORTRAN 77 is unable to determine whether or not SEQUENTIAL is included in the set
of allowed access methods for the file.
DIRECT = dir
- dir is a character variable or character array element. Open Watcom FORTRAN 77 also permits dir to
be a character substring.
It is assigned the value 'YES' if DIRECT is included in the set of allowed access methods for the file,
the value 'NO' if DIRECT is not included in the set of allowed access methods for the file, or 'UNKNOWN'
if Open Watcom FORTRAN 77 is unable to determine whether or not DIRECT is included in the set of allowed access
methods for the file.
FORM = fm
- fm is a character variable or character array element. Open Watcom FORTRAN 77 also permits fm to
be a character substring.
It is assigned the value 'FORMATTED' if the file is connected for formatted input/output, the value 'UNFORMATTED'
if the file is connected for unformatted input/output, or an undefined value if there is no connection.
FORMATTED = fmt
- fmt is a character variable or character array element. Open Watcom FORTRAN 77 also permits fmt to
be a character substring.
It is assigned the value 'YES' if FORMATTED is included in the set of allowed forms for the file, the
value 'NO' if FORMATTED is not included in the set of allowed forms for the file, or 'UNKNOWN'
if Open Watcom FORTRAN 77 is unable to determine whether or not FORMATTED is included in the set of allowed forms
for the file.
UNFORMATTED = unf
- unf is a character variable or character array element. Open Watcom FORTRAN 77 also permits unf to
be a character substring.
It is assigned the value 'YES' if UNFORMATTED is included in the set of allowed forms for the file,
the value 'NO' if UNFORMATTED is not included in the set of allowed forms for the file, or 'UNKNOWN'
if Open Watcom FORTRAN 77 is unable to determine whether or not UNFORMATTED is included in the set of allowed forms
for the file.
RECL = rcl
- rcl is an integer variable or integer array element that is assigned the value of the record length of the file
connected for direct access. If the file is connected for formatted input/output, the length is the number of characters.
If the file is connected for unformatted input/output, the length is measured in processor-dependent units (bytes).
See the compiler User's Guide for a discussion of record length or size. If there is no connection or if the
file is not connected for direct access then the value is undefined. The RECL= specifier is also allowed if
the file is connected for sequential access.
NEXTREC = nr
- nr is an integer variable or integer array element that is assigned the value n+1, where n is
the record number of the last record read or written on the file connected for direct access. If the file is connected
but no records have been read or written then the value is 1. If the file is not connected for direct access or if
the position of the file can not be determined because of an input/output error then nr becomes undefined.
BLANK = blnk
- blnk is a character variable or character array element. Open Watcom FORTRAN 77 also permits blnk
to be a character substring.
It is assigned the value 'NULL' if null blank control is in effect for the file connected for formatted input/output,
and is assigned the value 'ZERO' if zero blank control is in effect for the file connected for formatted input/output.
If there is no connection, or if the file is not connected for formatted input/output, blnk becomes undefined.
ACTION = act
- act is a character variable or character array element. Open Watcom FORTRAN 77 also permits act to
be a character substring.
It is assigned the value 'READ' if data can only be read from the file, 'WRITE' if data can only be
written from the file, and 'READWRITE' if data can be both read and written.
CARRIAGECONTROL = cc
- cc is a character variable or character array element. Open Watcom FORTRAN 77 also permits cc to
be a character substring.
It is assigned the value 'YES' if the first character of each record is interpreted as a carriage control character
and 'NO' if no interpretation is placed on the first character of each record.
RECORDTYPE = rct
- rct is a character variable or character array element. Open Watcom FORTRAN 77 also permits rct to
be a character substring.
It is assigned a value that represents the record type (or record structure) that is used for the file. The value
assigned depends on the system on which you are running the program. See the compiler User's Guide for a discussion
of record types.
BLOCKSIZE = bl
- bl is an integer variable or integer array element.
It is assigned a value that represents the internal buffer size that is used for input/output operations on the file.
The value assigned depends on the system on which you are running the program. See the compiler User's Guide
for a discussion of default internal buffer size.
Definition Status of Specifiers - Inquire by File
The following table summarizes which specifier variables or array elements become defined with values under what conditions
when using the FILE= specifier.
IOSTAT = ios
(1)
EXIST = ex
(2)
OPENED = od
(2)
NUMBER = num
(4)
NAMED = nmd
(3)
NAME = fn
(3)
ACCESS = acc
(5)
SEQUENTIAL = seq (3)
DIRECT = dir
(3)
FORM = fm
(5)
FORMATTED = fmt (3)
UNFORMATTED = unf (3)
RECL = rcl
(5)
NEXTREC = nr
(5)
BLANK = blnk
(5)
ACTION = act
(5)
CARRIAGECONTROL = cc (5)
RECORDTYPE = rct (5)
BLOCKSIZE = bl (5)
- The IOSTAT= specifier variable is always defined with the most recent error status. If an error occurs
during execution of the INQUIRE statement then the error status is defined with a positive integer; otherwise the
status is that of the most recent input/output statement which referenced that file.
- The specifier always becomes defined unless an error condition occurs.
- This specifier becomes defined with a value only if the file name specified in the FILE= specifier is an acceptable
file name and the named file exists. Also, no error condition can occur during the execution of the INQUIRE
statement.
- This specifier becomes defined with a value if and only if od becomes defined with the value .TRUE.. Also,
no error condition can occur during the execution of the INQUIRE statement.
- This specifier may become defined with a value only if od becomes defined with the value .TRUE..
However, there may be other conditions under which this specifier does not become defined with a value. In other words,
(5) is a necessary, but not sufficient condition. For example, blnk is undefined if the file is not connected
for formatted input/output.
Definition Status of Specifiers - Inquire by Unit
The following table summarizes which specifier variables or array elements become defined with values under what conditions
when using the UNIT= specifier.
IOSTAT = ios
(1)
EXIST = ex
(2)
OPENED = od
(2)
NUMBER = num
(3)
NAMED = nmd
(3)
NAME = fn
(3)
ACCESS = acc
(3)
SEQUENTIAL = seq (3)
DIRECT = dir
(3)
FORM = fm
(3)
FORMATTED = fmt (3)
UNFORMATTED = unf (3)
RECL = rcl
(3)
NEXTREC = nr
(3)
BLANK = blnk
(3)
ACTION = act
(3)
CARRIAGECONTROL = cc (3)
RECORDTYPE = rct (3)
BLOCKSIZE = bl (3)
- The IOSTAT= specifier variable is always defined with the most recent error status. If an error occurs
during execution of the INQUIRE statement then the error status is defined with a positive integer; otherwise the
status is that of the most recent input/output statement which referenced that unit.
- This specifier always becomes defined unless an error condition occurs.
- This specifier becomes defined with a value only if the specified unit exists and if a file is connected to the unit.
Also, no error condition can occur during the execution of the INQUIRE statement.
For more information on input/output, see the chapter entitled Input/Output.
INTEGER Statement
The INTEGER statement is a type declaration statement and can be used to declare a name to be of type integer.
The implicit type of the name, whether defined by the "first letter rule" (see the chapter entitled Names, Data Types and Constants)
or by an IMPLICIT statement, is either confirmed or overridden. However, once a name has been declared to
be of type integer, it cannot appear in another type declaration statement.
There are various forms of the INTEGER statement. The following sections describe them.
Standard INTEGER Statement
INTEGER name [,name] ...
- where:
-
name
- is a variable name, array name, array declarator, symbolic name of a constant, function name or dummy procedure name.
This form is the standard form of the INTEGER statement.
Example:
DIMENSION C(-5:5)
INTEGER A, B(10), C
In the previous example, A is defined to be a variable of type integer and B and C are
defined to be arrays of type integer.
Extended INTEGER Statement: Length Specification
INTEGER[*len[,]] name [,name] ...
- where:
-
name
- is one of the following forms:
v[*len]
a[*len](d)
a(d)[*len]
v
- is a variable name, array name, symbolic name of a constant, function name or dummy procedure name.
a
- is an array name.
(d)
- is that part of the array declarator defining the dimensions of the array.
len
- is called the length specification and is an unsigned positive integer constant or an integer constant expression enclosed
in parentheses whose value is 1, 2 or 4.
This form of the INTEGER statement is a Open Watcom FORTRAN 77 extension to the FORTRAN 77 language. The
length specification specifies the number of bytes of storage that will be allocated for the name appearing in the INTEGER
statement. The default length specification is 4. A length specification of 1 or 2 does not change the data type;
it merely restricts the magnitude of the integer that can be represented. See the chapter entitled Names, Data Types and Constants
for more information.
The length specification immediately following the word INTEGER is the length specification for each entity
in the statement not having its own length specification. If a length specification is not specified the default length
specification is used. An entity with its own specification overrides the default length specification or the length
specification immediately following the word INTEGER. Note that for an array the length specification applies
to each element of the array.
Example:
DIMENSION C(-5:5)
INTEGER A, B*2(10), C*2
INTEGER*1 X
In the previous example, X is declared to be a variable of type integer and occupying 1 byte of storage,
A is declared to be a variable of type integer and occupying 4 bytes of storage and B and C are declared
to be arrays of type integer with each element of the array occupying 2 bytes.
Extended INTEGER Statement: Data Initialization
INTEGER[*len[,]] name [/cl/] [,name[/cl/]]
...
- where:
-
name
- is as described in the previous section.
len
- is as described in the previous section.
cl
- is a list of the form:
k [,k] ...
k
- is one of the forms:
c
r*c (equivalent to r successive appearances of c)
c
- is a constant or the symbolic name of a constant
r
- is an unsigned positive integer constant or the symbolic name of a constant.
This form of the INTEGER statement is an extension to the FORTRAN 77 language. The rules for data initialization
are the same as for the DATA statement.
Example:
INTEGER A/100/, B(10)/10*0/
In the previous example, A is initialized with the integer constant 100 and each element of the
array B is initialized with the integer constant 0.
INTRINSIC Statement
INTRINSIC f [,f] ...
- where:
-
f
- is the name of an intrinsic function name.
An INTRINSIC statement is used to identify a symbolic name as the name of an intrinsic function. It also
allows a specific intrinsic function to be passed as an actual argument. The names of intrinsic functions for type
conversion (INT, IFIX, HFIX, IDINT, FLOAT, DFLOAT, SNGL, REAL, DREAL, DBLE, CMPLX, DCMPLX, ICHAR, CHAR), lexical relationship
(LGE, LGT, LLE, LLT), for choosing the largest or smallest value (MAX, MAX0, AMAX1, DMAX1, AMAX0, MAX1, MIN, MIN0, AMIN1,
DMIN1, AMIN0, MIN1), as well as ALLOCATED, ISIZEOF and LOC, must not be used as actual arguments.
A generic intrinsic function does not lose its generic property if it appears in an INTRINSIC statement.
A name must only appear in an INTRINSIC statement once. A symbolic name must not appear in both an
INTRINSIC and an EXTERNAL statement in a program unit.
Example:
INTRINSIC SIN
.
.
.
CALL SAM( SIN )
In the previous example, the intrinsic function SIN was passed to the subroutine SAM. If the
INTRINSIC statement were eliminated then the variable SIN would be passed to the subroutine SAM.
LOGICAL Statement
The LOGICAL statement is a type declaration statement and can be used to declare a name to be of type logical.
The implicit type of the name, whether defined by the "first letter rule" (see the chapter entitled Names, Data Types and Constants)
or by an IMPLICIT statement, is either confirmed or overridden. However, once a name has been declared to
be of type logical, it cannot appear in another type declaration statement.
There are various forms of the LOGICAL statement. The following sections describe them.
Standard LOGICAL Statement
LOGICAL name [,name] ...
- where:
-
name
- is a variable name, array name, array declarator, symbolic name of a constant, function name or dummy procedure name.
This form is the standard form of the LOGICAL statement.
Example:
DIMENSION C(-5:5)
LOGICAL A, B(10), C
In the previous example, A is defined to be a variable of type logical and B and C are
defined to be arrays of type logical.
Extended LOGICAL Statement: Length Specification
LOGICAL[*len[,]] name [,name] ...
- where:
-
name
- is one of the following forms:
v[*len]
a[*len](d)
a(d)[*len]
v
- is a variable name, array name, symbolic name of a constant, function name or dummy procedure name.
a
- is an array name.
(d)
- is that part of the array declarator defining the dimensions of the array.
len
- is called the length specification and is an unsigned positive integer constant or an integer constant expression enclosed
in parentheses whose value is 1 or 4.
This form of the LOGICAL statement is a Open Watcom FORTRAN 77 extension to the FORTRAN 77 language. The
length specification specifies the number of bytes of storage that will be allocated for the name appearing in the LOGICAL
statement. The default length specification is 4. A length specification of 1 only changes the storage requirement
from 4 bytes to 1 byte; the values of true and false can be represented regardless of the length specification.
The length specification immediately following the word LOGICAL is the length specification for each entity
in the statement not having its own length specification. If a length specification is not specified the default length
specification is used. An entity with its own specification overrides the default length specification or the length
specification immediately following the word LOGICAL. Note that for an array the length specification applies
to each element of the array.
Example:
DIMENSION C(-5:5)
LOGICAL A, B*1(10), C*1
LOGICAL*4 X
In the previous example, X is declared to be a variable of type logical and occupying 4 bytes of storage,
A is declared to be a variable of type logical and occupying 4 bytes of storage and B and C are declared
to be arrays of type logical with each element of the array occupying 1 byte.
Extended LOGICAL Statement: Data Initialization
LOGICAL[*len[,]] name [/cl/] [,name[/cl/]]
...
- where:
-
name
- is as described in the previous section.
len
- is as described in the previous section.
cl
- is a list of the form:
k [,k] ...
k
- is one of the forms:
c
r*c (equivalent to r successive appearances of c)
c
- is a constant or the symbolic name of a constant
r
- is an unsigned positive integer constant or the symbolic name of a constant.
This form of the LOGICAL statement is an extension to the FORTRAN 77 language. The rules for data initialization
are the same as for the DATA statement.
Example:
LOGICAL A/.TRUE./, B(10)/10*.FALSE./
In the previous example, A is initialized with the logical constant .TRUE. and each element
of the array B is initialized with the logical constant .FALSE..
LOOP Statement
LOOP [:block-label]
The LOOP statement is used in conjunction with the structured END LOOP or UNTIL statement.
The LOOP statement marks the beginning of a sequence of statements which are to be repeated. The
END LOOP or UNTIL statement marks the end of the loop. The LOOP-block is executed until control is transferred
out of the LOOP-block or the logical expression (or integer arithmetic expression) of the UNTIL statement has a
true (or non-zero) value.
The QUIT statement may be used to transfer control out of a LOOP-block.
Example:
LOOP
READ *, X
IF( X .GT. 99.0 ) QUIT
PRINT *, X
END LOOP
Example:
X = 1.0
LOOP
PRINT *, X, SQRT( X )
X = X + 1.0
UNTIL( X .GT. 10.0 )
An optional block label may be specified with the LOOP statement.
For more information, see the chapter entitled Program Structure Control Statements.
MAP Statement
MAP
The MAP statement is used in conjunction with the END MAP declarative statement. The MAP
statement marks the start of a memory mapping structure. A MAP structure must appear within a UNION
block. Any number of variables of any type may appear within a memory map. At least two MAP structures
must appear within a UNION block. A UNION block permits the mapping of the same storage in several
different ways.
The following example maps out a 4-byte integer on an Intel 80x86-based processor.
Example:
STRUCTURE /MAPINT/
UNION
MAP
INTEGER*4 LONG
END MAP
MAP
INTEGER*2 LO_WORD
INTEGER*2 HI_WORD
END MAP
MAP
INTEGER*1 BYTE_0
INTEGER*1 BYTE_1
INTEGER*1 BYTE_2
INTEGER*1 BYTE_3
END MAP
END UNION
END STRUCTURE
RECORD /MAPINT/ I
I%LONG = '01020304'x
PRINT '(2Z4)', I%LO_WORD, I%HI_WORD
END
For more information, see the chapter entitled Structures, Unions and Records.
NAMELIST Statement
NAMELIST /name/ vlist [[,]/name/ vlist] ...
- where:
-
name
- is the name, enclosed in slashes, of a group of variables. It may not be the same as a variable or array name.
vlist
- is a list of variable names and array names separated by commas.
The NAMELIST statement is used to declare a group name for a set of variables so that they may be read or written
with a single namelist-directed READ, WRITE, or PRINT statement.
The list of variable or array names belonging to a NAMELIST name ends with a new NAMELIST name enclosed
in slashes or with the end of the NAMELIST statement. The same variable name may appear in more than one namelist.
A dummy variable, dummy array name, or allocatable array may not appear in a NAMELIST list. Also, a
variable whose type is a user-defined structure may not appear in a NAMELIST list.
The NAMELIST statement must precede any statement function definitions and all executable statements.
A NAMELIST name must be declared in a NAMELIST statement and may be declared only once. The name
may appear only in input/output statements. The READ, WRITE, and PRINT statements may be
used to transmit data between a file and the variables specified in a namelist.
Example:
CHARACTER*20 NAME
CHARACTER*20 STREET
CHARACTER*15 CITY
CHARACTER*20 STATE
CHARACTER*20 COUNTRY
CHARACTER*10 ZIP_CODE
INTEGER AGE
INTEGER MARKS(10)
NAMELIST /PERSON/ NAME, STREET, CITY, STATE,
+
COUNTRY, ZIP_CODE, AGE, MARKS
OPEN( UNIT=1, FILE='PEOPLE' )
LOOP
READ( UNIT=1, FMT=PERSON, END=99
)
WRITE( UNIT=6, FMT=PERSON )
ENDLOOP
99 CLOSE( UNIT=1 )
END
The following example shows another form of a namelist-directed READ statement.
Example:
CHARACTER*20 NAME
CHARACTER*20 STREET
CHARACTER*15 CITY
CHARACTER*20 STATE
CHARACTER*20 COUNTRY
CHARACTER*10 ZIP_CODE
INTEGER AGE
INTEGER MARKS(10)
NAMELIST /PERSON/ NAME, STREET, CITY, STATE,
+
COUNTRY, ZIP_CODE, AGE, MARKS
READ PERSON
PRINT PERSON
END
The input data must be in a special format. The first character in each record must be blank. The second
character in the first record of a group of data records must be an ampersand (&) or dollar sign ($) immediately followed
by the NAMELIST name. The NAMELIST name must be followed by a blank and must not contain any imbedded
blanks. This name is followed by data items separated by commas. The end of a data group is signaled by the character
"&" or "$", optionally followed by the string "END". If the "&" character
was used to start the group, then it must be used to end the group. If the "$" character was used to start
the group, then it must be used to end the group.
The form of the data items in an input record is:
- Name = Constant
- The name may be a variable name or an array element name. The constant may be integer, real, complex, logical or character.
Logical constants may be in the form "T" or ".TRUE" and "F" or ".FALSE".
Character constants must be contained within apostrophes. Subscripts must be of integer type.
ArrayName = Set of Constants
- The set of constants consists of constants of the type integer, real, complex, logical or character. The constants are
separated by commas. The number of constants must be less than or equal to the number of elements in the array.
Successive occurrences of the same constant may be represented in the form r*constant, where r is a non-zero
integer constant specifying the number of times the constant is to occur.
The variable and array names specified in the input file must appear in the NAMELIST list, but the order is not
important. A name that has been made equivalent to a name in the input data cannot be substituted for that name in
the NAMELIST list. The list can contain names of items in COMMON but must not contain dummy argument
names.
Each data record must begin with a blank followed by a complete variable or array name or constant. Embedded
blanks are not permitted in name or constants. Trailing blanks after integers and exponents are treated as zeros.
Example:
&PERSON
NAME = 'John Doe'
STREET = '22 Main St.' CITY = 'Smallville'
STATE = 'Texas' COUNTRY
= 'U.S.A.'
ZIP_CODE = '78910-1203'
MARKS = 73, 82, 3*78, 89, 2*93, 91, 88
AGE = 23
&END
The form of the data items in an output record is suitable for input using a namelist-directed READ statement.
- Output records are written using the ampersand character (&), not the dollar sign ($), although the dollar sign is
accepted as an alternative during input. That is, the output data is preceded by "&name" and is followed
by "&END".
- All variable and array names specified in the NAMELIST list and their values are written out, each according
to its type.
- Character data is enclosed in apostrophes.
- The fields for the data are made large enough to contain all the significant digits.
- The values of a complete array are written out in columns.
For more information, see the chapters entitled Format and Input/Output.
OPEN Statement
OPEN (oplist)
- where:
-
oplist
- must include the UNIT= specifier and may include at most one of each of the open specifiers listed below. Specifiers
are separated by commas.
[UNIT =] u
IOSTAT = ios
ERR = s
FILE = fin
STATUS = sta
ACCESS = acc
FORM = fm
RECL = rcl
BLANK = blnk
As an extension to the FORTRAN 77 language, the following inquiry specifiers are also supported.
ACTION = act
CARRIAGECONTROL = cc
RECORDTYPE = rct
BLOCKSIZE = bl
SHARE = shr
The OPEN statement may be used to connect an existing file to a unit, create a file that is preconnected, create
a file and connect it to a unit, or change certain specifications of a connection between a file and a unit.
- Open Specifiers
-
[UNIT =] u
-
u is an external unit identifier. An external unit identifier is a non-negative integer expression.
If the optional UNIT= specifier is omitted then the specifier must be the first item in the list of specifiers.
IOSTAT = ios
-
is an input/output status specifier. The integer variable or integer array element ios is defined
with zero if no error condition exists or a positive integer value if an error condition exists.
ERR = s
-
is an error specifier and s is a statement label. When an error occurs, execution is transferred
to the statement labelled by s.
FILE = fin
-
fin is a character expression whose value when trailing blanks are removed is the name of a file to be connected
to the specified unit. If this specifier is omitted and the unit is not connected to a file, it becomes connected to
a file determined by Open Watcom FORTRAN 77. The name established by Open Watcom FORTRAN 77 is described in the section
entitled Units of the chapter entitled Input/Output.
STATUS = sta
-
sta is a character expression whose value when trailing blanks are removed is 'OLD', 'NEW', 'SCRATCH',
or 'UNKNOWN'.
- OLD
- When OLD is specified, a FILE= specifier must be given. The file must exist.
NEW
- When NEW is specified, a FILE= specifier must be given. The file must not exist. Successful
execution of the OPEN statement creates the file and changes the status to OLD.
SCRATCH
- SCRATCH may only be specified for an unnamed file (i.e. FILE= is not allowed). When the file
is closed, it is deleted.
UNKNOWN
- If UNKNOWN is specified, the status is ignored. If the STATUS= specifier is omitted then UNKNOWN
is assumed.
ACCESS = acc
-
acc is a character expression whose value when trailing blanks are removed is 'SEQUENTIAL' or 'DIRECT'.
It specifies the access method for the file. If the ACCESS= specifier is omitted then 'SEQUENTIAL'
is assumed. If the file exists then the access method must be in the set of allowed access methods for the file.
If the file does not exist then the file is created with a set of allowed access methods that includes the specified access
method.
Open Watcom FORTRAN 77 also supports access 'APPEND' which is a form of sequential access in which the file is
positioned at the endfile record. The file must exist or the append access method must be in the set of allowed access
methods for the file. In all other respects, the file is treated as if 'SEQUENTIAL' had been specified.
FORM = fm
-
fm is a character expression whose value when trailing blanks are removed is 'FORMATTED' or 'UNFORMATTED'.
It specifies that the file is being connected for formatted or unformatted input/output. If the FORM=
specifier is omitted and the file is being connected for direct access then 'UNFORMATTED' is assumed. If the
FORM= specifier is omitted and the file is being connected for sequential access then 'FORMATTED' is assumed.
If the file exists then the specified form must be included in the set of allowed forms for the file. If the
file does not exist then the file is created with a set of allowed forms that includes the specified form.
RECL = rcl
-
rcl is an integer expression whose value must be positive. It specifies the length of each record in a
file being connected for direct access. If the file is being connected for direct access, this specifier must be given;
otherwise it must be omitted. Open Watcom FORTRAN 77 allows the RECL= specifier for files opened for sequential
access.
BLANK = blnk
-
blnk is a character expression whose value when trailing blanks are removed is 'NULL' or 'ZERO'.
If 'NULL' is specified then all blank characters in numeric formatted input fields are ignored except that
an entirely blank field has a value of zero. If 'ZERO' is specified then all blank characters other than leading
blanks are treated as zeroes. If this specifier is omitted then 'NULL' is assumed. This specifier may
only be present for a file being connected for formatted input/output.
ACTION = act
-
act is a character expression whose value when trailing blanks are removed is 'READ', 'WRITE' or
'READWRITE'. If 'READ' is specified, data can only be read from the file. If 'WRITE' is
specified, data can only be written to the file. If 'READWRITE' is specified, data can both be read and written.
The default is 'READWRITE'.
CARRIAGECONTROL = cc
-
cc is a character expression whose value when trailing blanks are removed is 'YES', or 'NO'.
If 'YES' is specified, Open Watcom FORTRAN 77 will automatically add an extra character at the beginning of
each record. This character will be interpreted as a carriage control character. If 'NO' is specified,
records will be written to the file without adding a carriage control character at the beginning of the record. The
default is 'NO'.
RECORDTYPE = rct
-
rct is a character expression whose value when trailing blanks are removed specifies the type of record (or record
structure) to be used for the file. The allowed values for rct depend on the system on which you are running
the program. See the compiler User's Guide for a discussion of the RECORDTYPE= specifier.
BLOCKSIZE = bl
-
bl is an integer expression whose value specifies the internal buffer size to be used for file input/output.
The allowed values for bl depend on the system on which you are running the program. Generally, the
larger the buffer, the faster the input/output. See the compiler User's Guide for a discussion of the BLOCKSIZE=
specifier.
SHARE = shr
-
shr is a character expression whose value when trailing blanks are removed specifies the way in which other processes
can simultaneously access the file. The allowed values for shr depend on the system on which you are running
the program. See the compiler User's Guide for a discussion of the SHARE= specifier.
Example:
OPEN( UNIT=1, FILE='TEST', STATUS='UNKNOWN',
+ ACCESS='SEQUENTIAL',
+ FORM='FORMATTED', BLANK='ZERO'
)
In the above example, the file 'TEST', containing FORMATTED records, is connected to unit 1. The status
of the file is 'UNKNOWN' since we do not know if it already exists. We will access the file sequentially,
using formatted input/output statements. Blanks in numeric input data are to be treated as zeroes.
Notes:
- If the unit is already connected to a file that exists, the execution of an OPEN statement for that unit is permitted.
- (a)
- If the same file is opened then only the BLANK= specifier may be different. The same file is opened if no
FILE= specifier was given or if the FILE= specifier refers to the same file.
(b)
- If a different file is opened then the currently connected file is automatically closed.
- If the file to be connected to the unit does not exist, but is already preconnected to the unit, any properties specified
in the OPEN statement are merged with and supersede those of the preconnection. For example, the RECL=
specification will override the record length attribute defined by a preconnection of the file.
- The same file may not be connected to two or more different units.
For more information on input/output, see the chapter entitled Input/Output.
OTHERWISE Statement
OTHERWISE
The OTHERWISE statement is used in conjunction with the SELECT statement. The OTHERWISE
statement marks the start of a new CASE block which is a series of zero or more statements ending in an END
SELECT statement.
When this statement is used and the value of a case expression is not found in any case list then control
of execution is transferred to the first executable statement following the OTHERWISE statement.
The CASE DEFAULT statement may be used in place of the OTHERWISE statement.
Example:
SELECT CASE ( CH )
CASE ( 'a' : 'z' )
PRINT *, 'Lower case letter'
CASE ( 'A' : 'Z' )
PRINT *, 'Upper case letter'
CASE ( '0' : '9' )
PRINT *, 'Digit'
OTHERWISE
PRINT *, 'Special character'
END SELECT
In the above example, if the character CH is not a letter or digit then the OTHERWISE block is executed.
- Note:
- The OTHERWISE or CASE DEFAULT block must follow all other CASE blocks.
For more information, see the chapter entitled Program Structure Control Statements.
PARAMETER Statement
PARAMETER (p=e [,p=e] ...)
- where:
-
p
- is a symbolic name.
e
- is a constant expression. Refer to the chapter entitled Expressions for more information.
p is known as a symbolic constant whose value is determined by the value of the expression e according
to the rules of assignment as described in the chapter entitled Assignment Statements.
Any symbolic constant appearing in expression e must have been previously defined in the same or a previous
PARAMETER statement in the same program unit. A symbolic constant may not be defined more than once in a program
unit.
If the symbolic name p is of type integer, real, double precision or complex then the corresponding expression
e must be an arithmetic constant expression (see the chapter entitled Expressions).
If the symbolic name p is of type character or logical then the expression e must be a character constant
expression or a logical constant expression respectively (see the chapter entitled Expressions).
Example:
PARAMETER (PI=3.14159,BUFFER=80,PIBY2=PI/2)
PARAMETER (ERRMSG='AN ERROR HAS OCCURRED')
If a symbolic constant is not of default implied type, its type must be specified in an IMPLICIT statement
or a type statement before its occurrence in a PARAMETER statement. Similarly, if the length of a character
symbolic constant is not the default length of 1, its length must be specified in an IMPLICIT statement or a type
statement before its occurrence in a PARAMETER statement.
PAUSE Statement
PAUSE [n]
- where:
-
n
- is a character constant or an unsigned integer constant of no more than five digits.
Open Watcom FORTRAN 77 allows n to be any unsigned integer constant.
Execution of a PAUSE statement causes a cessation of execution of the program. Execution of the program
may be resumed by the program operator by pressing the terminal line entering key (e.g., ENTER or RETURN). The
PAUSE statement may appear in any program unit.
If the Open Watcom FORTRAN 77 debugger was requested then execution of the PAUSE statement will cause entry
into the debugger. Program execution may be resumed by issuing the debugger "go" command.
Example:
PAUSE 4341
The four digit number 4341 is displayed on the terminal. The program temporarily ceases execution.
Execution is resumed by pressing the terminal line entering key.
Example:
PAUSE 'Ready the paper and then resume execution'
The character string
Ready the paper and then resume execution
is displayed on the terminal. Execution of the program may be resumed.
PRINT Statement
Two forms of the PRINT statement are supported by Open Watcom FORTRAN 77.
Standard PRINT Statement
PRINT f [,olist]
- where:
-
f
- is a format identifier.
olist
- is an optional output list.
Extended PRINT Statement
PRINT, olist
- where:
-
olist
- is an output list.
Description of PRINT Statement
The PRINT statement is used to transfer data from the executing FORTRAN program to an external device or file.
Format Identifier - A format identifier is one of the following:
- A statement label of a FORMAT statement that appears in the same program unit as the format identifier.
- An integer variable name that has been assigned the statement label of a FORMAT statement that appears in the
same program unit as the format identifier (see the ASSIGN statement).
- An integer array name.
- A character array name.
- Any character expression except one involving the concatenation of an operand whose length specification is (*)
unless the operand is a symbolic constant (see the PARAMETER statement).
- An asterisk (*), indicating list-directed formatting.
Open Watcom FORTRAN 77 supports a variation of list-directed formatting in which the asterisk (*)
may be omitted. It is equivalent to
PRINT * [,olist]
- A NAMELIST name, indicating namelist-directed formatting.
Output list - An output list may contain one or more of the following:
- A variable name.
- An array element name.
- A character substring name.
- An array name except an assumed-size dummy array.
- Any other expression except a character expression involving concatenation of an operand whose length specification is
an asterisk in parentheses unless the operand is the symbol name of a constant (since the length can be determined at compile
time).
- An implied-DO list of the form:
( dlist, i = e1, e2 [,e3] )
where dlist is composed of one or more of items (1) through (6).
Example:
CHARACTER*5 S
COMPLEX C
S = 'Hello'
I = 123
X = 12.5
C = (12.5,4.58)
PRINT *, S, I, X, C
END
The above example illustrates list-directed formatting using the PRINT statement. The asterisk
specifies that the variables in the output list are to be displayed in some format that is appropriate to the type of the
variable (hence the term "list-directed"). The CHARACTER variable S is printed using a suitable
A format descriptor. The INTEGER variable I is printed using a suitable I format descriptor.
The REAL variable X is printed using a suitable G format descriptor. The COMPLEX variable
C is printed using a suitable G format descriptor and is displayed with enclosing parentheses and a comma.
Output from the above program would resemble the following.
Hello 123 12.5000000 (12.5000000,4.5799999)
Example:
CHARACTER*5 S
COMPLEX C
S = 'Hello'
I = 123
X = 12.5
C = (12.5,4.58)
PRINT, S, I, X, C
END
The above example illustrates a Open Watcom FORTRAN 77 extension of list-directed formatting using the
PRINT statement. The asterisk is omitted but the results are exactly the same as in the previous example.
Example:
PRINT 100, X, Y, Z
100 FORMAT( 3F10.5 )
PRINT '( 3F10.5 )', X, Y, Z
The above gives two examples of the PRINT statement. In both cases, the format conversion is identical
but it was specified in different ways. When executed, the effect of both PRINT statements is the same.
Example:
PRINT '(1X,100A1)', ('*',I=1,J)
The above example illustrates a technique for producing histograms using the implied DO-loop. Each time this
statement is executed, a number of asterisks are printed, depending on the value of J.
Notes:
- The PRINT statement is implicitly a formatted output statement.
- The unit number that is implicitly used in the PRINT statement is unit number 6.
- If no output list is specified then the effect of the PRINT statement is to produce one or more records whose
characters are all blanks.
- FORTRAN 77 leaves the format of output in list-directed formatting to the discretion of Open Watcom FORTRAN 77.
Hence other FORTRAN compilers may produce different results. If the format of output must be consistent from one compiler
to the next then list-directed formatting should not be used.
- An implication of point (6) above is that nesting of implied-DO lists is permitted. For example, the output list
( (A(I,J), B(I,J), J = 1, 5), I = 1, 10 )
may be broken down into the following components:
A(I,J), B(I,J)
(....dlist1...., J = 1, 5)
( .....dlist2..............., I = 1, 10 )
For more information on input/output, see the chapter entitled Input/Output. For more
information on formatted input/output, see the chapter entitled Format.
PROGRAM Statement
PROGRAM pgm
- where:
-
pgm
- is the symbolic name of the main program.
A PROGRAM statement is optional in an executable program. If it does appear, it must be the first statement
in the main program.
Example:
PROGRAM CALC
.
.
.
CALL COMPUTE
.
.
.
END
The main program can contain any Open Watcom FORTRAN 77 statement except a FUNCTION, SUBROUTINE,
BLOCK DATA, RETURN or ENTRY statement. Note that a SAVE statement is allowed but has
no effect in the main program.
QUIT Statement
QUIT [: block-label]
The QUIT statement may be used to cause a transfer of control to the first executable statement that follows
the terminal statement of the block which contains it. Examples of such terminal statements are ADMIT,
CASE, END DO, END LOOP, END WHILE, UNTIL, etc. If block-label is
present then control is transferred out of the block identified by that block label. The QUIT statement is
an extension to the FORTRAN 77 language.
Example:
LOOP
WRITE( UNIT=*, FMT='(A)' ) 'Enter
a number'
READ( UNIT=*, FMT='(F10.4)',
IOSTAT=IOS ) X
IF( IOS .NE. 0 ) QUIT
IF( X .LT. 0 ) QUIT
PRINT *, X, SQRT( X )
END LOOP
END
For more information, see the chapter entitled Program Structure Control Statements.
READ Statement
Three forms of the READ statement are supported by Open Watcom FORTRAN 77.
Standard READ Statement
READ (cilist) [ilist]
READ f [,ilist]
- where:
-
cilist
- is a control information list of specifiers separated by commas:
[UNIT =] u
[FMT =] f
REC = rn
IOSTAT = ios
ERR = s
END = s
f
- is a format identifier.
ilist
- is an optional input list.
Extended READ Statement
READ, ilist
- where:
-
ilist
- is an input list.
Description of READ Statement
The READ statement is used to transfer data from a device or file into the executing FORTRAN program. As
shown above, Open Watcom FORTRAN 77 supports three forms of the READ statement.
- Control Information List and Format Identifier
-
[UNIT =] u
-
u is an external unit identifier or an internal file identifier.
- An external unit identifier is a non-negative integer expression or an asterisk (*) in which case unit 5 is assumed.
- An internal file identifier is the name of a character variable, character array, character array element, or character
substring.
If the optional UNIT= specifier is omitted then the unit specifier must be the first item in the list of specifiers.
[FMT =] f
-
f is a format identifier. A format identifier is one of the following:
- A statement label of a FORMAT statement that appears in the same program unit as the format identifier.
- An integer variable name that has been assigned the statement label of a FORMAT statement that appears in the
same program unit as the format identifier (see the ASSIGN statement).
- An integer array name.
- A character array name.
- Any character expression except one involving the concatenation of an operand whose length specification is (*)
unless the operand is a symbolic constant (see the PARAMETER statement).
- An asterisk (*), indicating list-directed formatting.
Open Watcom FORTRAN 77 supports a third form of the READ statement in which the asterisk (*) may
be omitted. This is a form of list-directed formatting in which unit 5 is assumed. It is equivalent to
READ * [,ilist]
- A NAMELIST name, indicating namelist-directed formatting.
If the optional FMT= specifier is omitted then the format specifier must be the second item in the list of specifiers
and UNIT= must not be specified for the first item in the list.
REC = rn
-
rn is an integer expression whose value must be positive. It is the number of the record to be read when
a file is connected for direct access.
IOSTAT = ios
-
is an input/output status specifier. The integer variable or integer array element ios is defined with
zero if no error occurs, a positive integer value if an error occurs, or a negative integer value if an end-of-file occurs.
ERR = s
-
is an error specifier and s is a statement label. When an error occurs, execution is transferred to the
statement labelled by s.
END = s
-
is an end-of-file specifier and s is a statement label. When an end-of-file occurs, execution is transferred
to the statement labelled by s.
Input list - An input list may contain one or more of the following:
- A variable name.
- An array element name.
- A character substring name.
- An array name except an assumed-size dummy array.
- An implied-DO list of the form:
( dlist, i = e1, e2 [,e3] )
where dlist is composed of one or more of items (1) through (5).
Example:
READ( 5, 100 )X, Y, Z
READ( UNIT=5, FMT=100 )X, Y, Z
100 FORMAT( 3F10.5 )
READ( UNIT=5, FMT='( 3F10.5 )' )X, Y, Z
READ( 5, '( 3F10.5 )' )X, Y, Z
The above gives four examples of formatted READ statements, using the first of three supported forms of the
READ statement. In all cases, the format conversion is identical but it was specified in different ways.
When executed, the effect of all READ statements is the same. The unit number that is explicitly used
in this form of the READ statement is unit number 5. There are, in fact, many other ways in which the
READ statement could have been written, all of which would have the same effect when executed. We have not shown
the use of all the specifiers.
Example:
READ 100, X, Y, Z
100 FORMAT( 3F10.5 )
READ '( 3F10.5 )', X, Y, Z
The above gives two examples of formatted READ statements, using the second of three supported forms of the
READ statement. In both cases, the format conversion is identical but it was specified in different ways.
When executed, the effect of both READ statements is the same. The unit number that is implicitly used
in this form of the READ statement is unit number 5.
Example:
READ( 5, * )X, Y, Z
READ( *, * )X, Y, Z
READ( UNIT=5, FMT=* )X, Y, Z
READ( UNIT=*, FMT=* )X, Y, Z
READ *, X, Y, Z
READ , X, Y, Z
The above six examples of list-directed formatted input are all equivalent. Open Watcom FORTRAN 77 assumes unit
5 when the unit number identifier is an asterisk (as in the second and fourth examples). In the fifth example, the
asterisk is a format identifier indicating list-directed formatting. The fifth and sixth examples are examples of the
second and third forms, respectively, of the READ statement in which Open Watcom FORTRAN 77 assumes unit 5.
When the format identifier is an asterisk or when the third form of the READ statement is used, we call this list-directed
list-directed formatting.
Example:
READ( 8 )X, Y, Z
READ( UNIT=8 )X, Y, Z
The above gives two examples of unformatted READ statements. The unit number used in the example is
8. When executed, the effect of both of these statements is the same. The values of the variables X, Y
and Z are read from the file connected to unit 8. The values are stored in the file in their binary form (a
form quite incomprehensible to most human beings). An advantage to using this particular form of the READ
statement is that no conversion is required between the internal binary representation of the values and their textual (human-readable)
form (which means it takes less computer time to process the data).
Notes:
- The REC= specifier may not be used when list-directed output is specified.
- If no input list is specified then the effect of the READ statement is to skip one or more records in the file.
- An implication of point (5) above is that nesting of implied-DO lists is permitted. For example, the input list
( (A(I,J), B(I,J), J = 1, 5), I = 1, 10 )
may be broken down into the following components:
A(I,J), B(I,J)
(....dlist1...., J = 1, 5)
( .....dlist2..............., I = 1, 10 )
For more information on input/output, see the chapter entitled Input/Output. For more
information on formatted input/output, see the chapter Format.
REAL Statement
The REAL statement is a type declaration statement and can be used to declare a name to be of type real.
The implicit type of the name, whether defined by the "first letter rule" (see the chapter entitled Names, Data Types and Constants)
or by an IMPLICIT statement, is either confirmed or overridden. However, once a name has been declared to
be of type real, it cannot appear in another type declaration statement.
There are various forms of the REAL statement. The following sections describe them.
Standard REAL Statement
REAL name [,name] ...
- where:
-
name
- is a variable name, array name, array declarator, symbolic name of a constant, function name or dummy procedure name.
This form is the standard form of the REAL statement.
Example:
DIMENSION C(-5:5)
REAL A, B(10), C
In the previous example, A is defined to be a variable of type real and B and C are defined
to be arrays of type real.
Extended REAL Statement: Length Specification
REAL[*len[,]] name [,name] ...
- where:
-
name
- is one of the following forms:
v[*len]
a[*len](d)
a(d)[*len]
v
- is a variable name, array name, symbolic name of a constant, function name or dummy procedure name.
a
- is an array name.
(d)
- is that part of the array declarator defining the dimensions of the array.
len
- is called the length specification and is an unsigned positive integer constant or an integer constant expression enclosed
in parentheses whose value is 4 or 8.
This form of the REAL statement is a Open Watcom FORTRAN 77 extension to the FORTRAN 77 language. The length
specification specifies the number of bytes of storage that will be allocated for the name appearing in the REAL
statement. The default length specification is 4. A length specification of 8 specifies that the data type of
the name appearing in the REAL statement is to be double precision.
The length specification immediately following the word REAL is the length specification for each entity
in the statement not having its own length specification. If a length specification is not specified the default length
specification is used. An entity with its own specification overrides the default length specification or the length
specification immediately following the word REAL. Note that for an array the length specification applies
to each element of the array.
Example:
DIMENSION C(-5:5)
REAL A, B*8(10), C*8
REAL*8 X
In the previous example, X is declared to be a variable of type double precision, A is declared
to be a variable of type real and B and C are declared to be arrays of type double precision.
Extended REAL Statement: Data Initialization
REAL[*len[,]] name [/cl/] [,name[/cl/]]
...
- where:
-
name
- is as described in the previous section.
len
- is as described in the previous section.
cl
- is a list of the form:
k [,k] ...
k
- is one of the forms:
c
r*c (equivalent to r successive appearances of c)
c
- is a constant or the symbolic name of a constant
r
- is an unsigned positive integer constant or the symbolic name of a constant.
This form of the REAL statement is an extension to the FORTRAN 77 language. The rules for data initialization
are the same as for the DATA statement.
Example:
REAL A/1.2/, B(10)/10*5.0/
In the previous example, A is initialized with the real constant 1.2 and each element of the array
B is initialized with the real constant 5.0.
RECORD Statement
RECORD /typename/ name [,name] ...
- where:
-
typename
- is the name of a user-defined structure type.
name
- is a variable name, array name, array declarator, function name or dummy procedure name.
The RECORD statement is used to assign a structure type to a variable.
Example:
STRUCTURE /ADDRESS/
CHARACTER*20 STREET
CHARACTER*15 CITY
CHARACTER*20 STATE
CHARACTER*20 COUNTRY
CHARACTER*10 ZIP_CODE
END STRUCTURE
STRUCTURE /PEOPLE/
CHARACTER*20 NAME
RECORD /ADDRESS/ ADDR
INTEGER*2 AGE
END STRUCTURE
RECORD /PEOPLE/ CUSTOMER
CUSTOMER%NAME = 'John Doe'
CUSTOMER%ADDR%STREET = '22 Main St.'
CUSTOMER%ADDR%CITY = 'Smallville'
CUSTOMER%ADDR%STATE = 'Texas'
CUSTOMER%ADDR%COUNTRY = 'U.S.A.'
CUSTOMER%ADDR%ZIP_CODE = '78910-1203'
CUSTOMER%AGE = 23
For more information, see the chapter entitled Structures, Unions and Records.
REMOTE BLOCK Statement
REMOTE BLOCK name
- where:
-
name
- is a valid FORTRAN symbolic name.
The REMOTE BLOCK statement is used to define a block of statements which may be executed by an EXECUTE
statement. A REMOTE-block must be defined in the program unit in which it is used and is terminated by an END BLOCK
statement. A REMOTE-block is similar in concept to a subroutine, with the advantage that shared variables do not need
to be placed in a common block or passed in an argument list. When execution of the REMOTE-block is complete, control
returns to the statement following the EXECUTE statement which invoked it.
This feature is helpful in avoiding duplication of code for a common sequence of statements required in a number of
places throughout a program. It can also be an aid to writing a well structured program. This feature can be
mimicked using the ASSIGN and assigned GO TO statements. However, statement numbers must be introduced
which could lead to errors.
Each REMOTE-block must have a different name and it must not be a subprogram or variable name. Note that a REMOTE-block
is local to the program unit in which it is defined and may not be referenced (executed) from another program unit.
Note that the nested definition of REMOTE-blocks is not permitted.
Example:
EXECUTE INCR
PRINT *, 'FIRST'
EXECUTE INCR
PRINT *, 'SECOND'
.
.
.
REMOTE BLOCK INCR
I=I+1
PRINT *, 'I=',I
END BLOCK
Both EXECUTE statements will cause REMOTE-block INCR to be executed. That is, variable
I will be incremented and its value will be printed. When the block has been executed by the first EXECUTE
statement, control returns to the PRINT statement following it and the word FIRST is printed. Similarly,
when the block is executed by the second EXECUTE statement, control returns to the PRINT statement following
it and the word SECOND is printed.
For more information, see the chapter entitled Program Structure Control Statements.
RETURN Statement
RETURN [e]
- where:
-
e
- is an integer expression.
A RETURN statement is used to terminate execution of a subprogram and return control to the program unit that
referenced it. As an extension to FORTRAN 77, Open Watcom FORTRAN 77 permits the use of the RETURN statement
in the main program. When a RETURN statement is executed in the main program, program execution terminates
in the same manner as the STOP or END statement.
The expression e is not permitted when returning from an external function subprogram (or main program);
it can only be specified when returning from a subroutine subprogram.
Example:
FUNCTION ABS( A )
ABS = A
IF( A .GE. 0 )RETURN
ABS = -A
RETURN
END
For more information, see the chapter entitled Functions and Subroutines.
REWIND Statement
REWIND u
REWIND (alist)
- where:
-
u
- is an external unit identifier.
alist
- is a list of rewind specifiers separated by commas:
[UNIT =] u
IOSTAT = ios
ERR = s
Execution of a REWIND statement causes the file connected to the specified unit to be positioned at the beginning
(or before the first record) of the file.
- Rewind Specifiers
-
[UNIT =] u
-
u is an external unit identifier. An external unit identifier is a non-negative integer expression.
If the optional UNIT= specifier is omitted then the specifier must be the first item in the list of specifiers.
IOSTAT = ios
-
is an input/output status specifier. The integer variable or integer array element ios is defined
with zero if no error condition exists or a positive integer value if an error condition exists.
ERR = s
-
is an error specifier and s is a statement label. When an error occurs, execution is transferred
to the statement labelled by s.
Example:
LOOP
READ( UNIT=7, END=100, FMT=200
)RECORD
PRINT *, RECORD
ENDLOOP
100 REWIND( UNIT=7 )
LOOP
READ( UNIT=7, END=101, FMT=200
)RECORD
WRITE( UNIT=8, FMT=200 )RECORD
ENDLOOP
101 CONTINUE
In the previous example, we illustrate how one might process the records in a file twice. After reaching the
endfile record, a REWIND statement is executed and the file is read a second time.
Notes:
- The unit must be connected for sequential access.
- If the file is positioned at the beginning of the file then the REWIND statement has no effect.
- It is permissible to rewind a file that does not exist but it has no effect.
For more information on input/output, see the chapter entitled Input/Output.
SAVE Statement
SAVE [a [,a] ...]
- where:
-
a
- is a named common block preceded and followed by a slash (/), a variable name or an array name.
The SAVE statement is used to retain the value of an entity after the execution of a RETURN or END
statement in a subprogram. Upon re-entry to the subprogram, the entity will have the same value it had when exit was
made from the subprogram. However, an entity belonging to a common block that has appeared in a SAVE statement
may become redefined in another program unit.
Notes:
- A name cannot appear in a SAVE statement more than once in the same program unit.
- Dummy arguments, procedure names and names belonging to a common block are not permitted in a SAVE statement.
- A SAVE statement with no list is identical to a SAVE statement containing all allowable names in a program
unit.
- A common block name appearing in a SAVE statement has the same effect of specifying all names belonging to that
common block in the SAVE statement.
- If a named common block is specified in a SAVE statement in a subprogram, it must be specified in a SAVE
statement in every subprogram in which that common block appears. Furthermore, upon executing a RETURN or
END statement, the current values of the entities in that common block are made available to the next program unit executed
in which that common block appears.
- If a named common block is specified in a SAVE statement in the main program unit, the current values of the
entities in that common block are made available to every subprogram that specifies that common block. In this case,
a SAVE statement has no effect in the subprogram.
In the following example, the subroutine BLKINIT initializes the entities of the common block BLK and
uses a SAVE statement to ensure that their values are made available to subroutine BLKPRT.
Example:
PROGRAM MAIN
.
.
.
CALL BLKINIT
CALL BLKPRT
.
.
.
END
SUBROUTINE BLKINIT
COMMON /BLK/ A,B,C
SAVE /BLK/
A = 1.0
B = 2.0
C = 3.0
END
SUBROUTINE BLKPRT
COMMON /BLK/ A,B,C
SAVE /BLK/
PRINT *, A, B, C
END
SELECT Statement
SELECT [CASE] (e) [FROM] [: block-label]
The SELECT statement is used in conjunction with the CASE and END SELECT statements.
The form of a SELECT block is as follows:
SELECT [CASE] (e) [FROM] [: block-label]
CASE ( case-list )
statement (s)
CASE ( case-list )
statement (s)
.
.
.
CASE ( case-list )
statement(s)
CASE DEFAULT
statement(s)
END SELECT
- where:
-
e
- is an integer expression.
case-list
- is a list of one or more cases separated by commas. A case is either
- (a)
- a single integer, logical or character constant expression or
(b)
- an integer, logical or character constant expression followed by a colon followed by another expression or the same type.
This form of a case defines a range of values consisting of all integers or characters greater than or equal to the
value of the expression preceding the colon and less than or equal to the value of the expression following the colon.
The CASE and FROM keywords are optional in the SELECT statement. An optional block label
may be specified with the SELECT statement.
The case expression e is evaluated and if the result is equal to one of the values covered by case-list
then the control of execution is transferred to the associated CASE block.
Example:
SELECT CASE ( CH )
CASE ( 'a' : 'z' )
PRINT *, 'Lower case letter'
CASE ( 'A' : 'Z' )
PRINT *, 'Upper case letter'
CASE ( '0' : '9' )
PRINT *, 'Digit'
CASE DEFAULT
PRINT *, 'Special character'
END SELECT
In the above example, if the character CH is not a letter or digit then the CASE DEFAULT block is
executed.
The CASE DEFAULT statement is optional. If it is present and the case expression is out of range (i.e.,
no CASE blocks are executed) then the CASE DEFAULT block is executed. If it is not present and the
case expression is out of range then execution continues with the first executable statement following the END SELECT
statement. The CASE DEFAULT block must follow all other CASE blocks.
Example:
SELECT CASE ( I )
CASE ( 1 )
Y = Y + X
X = X * 3.2
CASE ( 2 )
Z = Y**2 + X
CASE ( 3 )
Y = Y * 13. + X
X = X - 0.213
CASE ( 4 )
Z = X**2 + Y**2 - 3.0
Y = Y + 1.5
X = X * 32.0
CASE DEFAULT
PRINT *, 'CASE is not in range'
END SELECT
PRINT *, X, Y, Z
In order to retain compatibility with earlier versions of WATCOM FORTRAN 77 compilers, the OTHERWISE statement
may be used in place of the CASE DEFAULT statement.
For more information, see the chapter entitled Program Structure Control Statements.
STOP Statement
STOP [n]
- where:
-
n
- is a character constant or an unsigned integer constant of no more than five digits.
Open Watcom FORTRAN 77 allows n to be any unsigned integer constant.
Execution of a STOP statement causes termination of execution of the program. A STOP statement
may appear in any program unit (although good programming practice suggests that the main program is the proper place for
this statement).
Example:
STOP 943
The three digit number 943 is displayed on the console prior to program termination.
Example:
STOP 'Finished at last'
The character string
Finished at last
is displayed on the console prior to program termination.
STRUCTURE Statement
STRUCTURE /typename/
- where:
-
typename
- is the name for a new, compound variable, data type.
The STRUCTURE statement is used in conjunction with the END STRUCTURE declarative statement. The
STRUCTURE statement marks the start of a structure definition.
The STRUCTURE statement defines a new variable type, called a structure. It does not declare
a specific program variable. The RECORD statement is used to declare variables and arrays to be of this particular
structure type.
Structures may be composed of simple FORTRAN types or more complex structure types. This is shown in the following
example.
Example:
STRUCTURE /ADDRESS/
CHARACTER*20 STREET
CHARACTER*20 CITY
CHARACTER*20 STATE
CHARACTER*20 COUNTRY
CHARACTER*10 ZIP_CODE
END STRUCTURE
STRUCTURE /PEOPLE/
CHARACTER*20 NAME
RECORD /ADDRESS/ ADDR
INTEGER*2 AGE
END STRUCTURE
RECORD /PEOPLE/ CUSTOMER
Element names are local to the structure in which they appear. The same element name can appear in more than
one structure. Nested structures may have elements with the same name. A particular element is specified by listing
the sequence of elements required to reach the desired element, separated by percent symbols (%) or periods (.).
Example:
CUSTOMER%NAME = 'John Doe'
CUSTOMER%ADDR%STREET = '22 Main St.'
CUSTOMER%ADDR%CITY = 'Smallville'
CUSTOMER%ADDR%STATE = 'Texas'
CUSTOMER%ADDR%COUNTRY = 'U.S.A.'
CUSTOMER%ADDR%ZIP_CODE = '78910-1203'
CUSTOMER%AGE = 23
For more information, see the chapter entitled Structures, Unions and Records.
SUBROUTINE Statement
SUBROUTINE sub [( [d [, d] ...] )]
- where:
-
sub
- is a symbolic name of a subroutine subprogram.
d
- is a variable name, array name, dummy procedure name or an asterisk (*). d is called a dummy argument.
A SUBROUTINE statement is used to define the start of a subroutine subprogram.
Example:
CALL TMAX3( -1.0, 12.0, 5.0 )
END
SUBROUTINE TMAX3( ARGA, ARGB, ARGC )
THEMAX = ARGA
IF( ARGB .GT. THEMAX ) THEMAX
= ARGB
IF( ARGC .GT. THEMAX ) THEMAX
= ARGC
PRINT *, THEMAX
END
In the above example, the subroutine TMAX3 is defined to find and print out the maximum value of three real
variables.
Notes:
- No dummy arguments need be specified in the SUBROUTINE statement. If such is the case, the parentheses
() are optional.
For more information, see the chapter entitled Functions and Subroutines.
UNION Statement
UNION
The UNION statement is used in conjunction with the END UNION declarative statement. The UNION
statement marks the start of a series of MAP structures. A UNION block must contain at least two
MAP structures. A UNION block permits the mapping of the same storage in several different ways.
The following example maps out a 4-byte integer on an Intel 80x86-based processor.
Example:
STRUCTURE /MAPINT/
UNION
MAP
INTEGER*4 LONG
END MAP
MAP
INTEGER*2 LO_WORD
INTEGER*2 HI_WORD
END MAP
MAP
INTEGER*1 BYTE_0
INTEGER*1 BYTE_1
INTEGER*1 BYTE_2
INTEGER*1 BYTE_3
END MAP
END UNION
END STRUCTURE
RECORD /MAPINT/ I
I%LONG = '01020304'x
PRINT '(2Z4)', I%LO_WORD, I%HI_WORD
END
For more information, see the chapter entitled Structures, Unions and Records.
UNTIL Statement
UNTIL (e)
- where:
-
e
- is a logical expression or integer arithmetic expression, in which case the result of the integer expression is compared for
inequality to the integer value 0.
The UNTIL statement is used in conjunction with the structured LOOP or block WHILE statement.
The LOOP or block WHILE statement marks the beginning of a sequence of statements which are to be
repeated. The UNTIL statement marks the end of the loop. The LOOP-block or WHILE-block is executed until
control is transferred out of the block or the logical expression of the UNTIL statement has a true value.
Example:
X = 1.0
LOOP
PRINT *, X, SQRT( X )
X = X + 1.0
UNTIL( X .GT. 10.0 )
Example:
I = 1
WHILE( I .LT. 100 )DO
J = 4 * I * I
K = 3 * I
PRINT *, '4x**2 + 3x + 6 = ',
J + K + 6
I = I + 1
UNTIL( ( J + K + 6 ) .GT. 100 )
For more information, see the chapter entitled Program Structure Control Statements.
VOLATILE Statement
VOLATILE [a [,a] ...]
- where:
-
a
- is a variable name or an array name.
The VOLATILE statement is used to indicate that a variable or an element of an array may be updated concurrently
by other code. A volatile variable or array element will not be cached (in a register) by the code generator.
Each time a volatile variable or array element is referenced, it is loaded from memory. Each time a volatile variable
or array element is updated, it is stored back into memory.
Notes:
- A name cannot appear in a VOLATILE statement more than once in the same program unit.
- Dummy arguments, procedure names, and common block names are not permitted in a VOLATILE statement.
In the following example, the subroutine A_THREAD waits on the HoldThreads semaphore. It uses
the VOLATILE statement to ensure that the variable is re-loaded from memory each time through the loop.
Example:
SUBROUTINE A_THREAD()
STRUCTURE /RTL_CRITICAL_SECTION/
INTEGER*4 DebugInfo
INTEGER*4 LockCount
INTEGER*4 RecursionCount
INTEGER*4 OwningThread
INTEGER*4 LockSemaphore
INTEGER*4 Reserved
END STRUCTURE
INTEGER NumThreads
LOGICAL HoldThreads
VOLATILE HoldThreads
RECORD /RTL_CRITICAL_SECTION/ CriticalSection
COMMON NumThreads, HoldThreads, CriticalSection
INTEGER threadid
WHILE( HoldThreads )DO
CALL Sleep( 1 )
END WHILE
PRINT '(''Hi from thread '', i4)', threadid()
CALL EnterCriticalSection( CriticalSection )
NumThreads = NumThreads - 1
CALL LeaveCriticalSection( CriticalSection )
CALL endthread()
END
Block WHILE Statement
WHILE (e) DO [: block-label]
- where:
-
e
- is a logical expression or integer arithmetic expression, in which case the result of the integer expression is compared for
inequality to the integer value 0.
The block WHILE statement is used in conjunction with the structured END WHILE or UNTIL statement.
The block WHILE statement marks the beginning of a sequence of statements which are to be repeated.
The END WHILE or UNTIL statement marks the end of the WHILE-block. The WHILE-block is executed while
the logical expression of the WHILE statement has a true value or until control is transferred out of the WHILE-block.
Example:
X = 1.0
WHILE( X .LT. 100 )DO
PRINT *, X, SQRT( X )
X = X + 1.0
END WHILE
Example:
I = 1
WHILE( I .LT. 100 )DO
J = 4 * I * I
K = 3 * I
PRINT *, '4x**2 + 3x + 6 = ',
J + K + 6
I = I + 1
UNTIL( ( J + K + 6 ) .GT. 100 )
END
An optional block label may be specified with the WHILE statement.
For more information, see the chapter entitled Program Structure Control Statements.
WHILE Statement
WHILE (e) stmt
- where:
-
e
- is a logical expression.
stmt
- is an executable statement. Only certain executable statements are allowed. See the section entitled Classifying Statements
at the beginning of this chapter for a list of allowed statements.
This form of the WHILE statement allows an executable statement to be repeatedly executed until the logical expression
e is false.
Example:
I = 0
WHILE( I .LE. 100 ) CALL PRTSQR( I )
END
SUBROUTINE PRTSQR( J )
PRINT *, J, J**2
J = J + 1
END
In the above example, the subroutine PRTSQR is called again and again until the value of I has been
incremented beyond 100. Note that the subroutine increments its argument thereby guaranteeing that the program will
eventually stop execution.
For more information, see the chapter entitled Program Structure Control Statements
Control Statements".
WRITE Statement
WRITE (cilist) [olist]
- where:
-
cilist
- is a control information list of specifiers separated by commas:
[UNIT =] u
[FMT =] f
REC = rn
IOSTAT = ios
ERR = s
olist
- is an output list.
The WRITE statement is used to transfer data from the executing FORTRAN program to an external device or file.
- Control Information List
-
[UNIT =] u
-
u is an external unit identifier or an internal file identifier.
- An external unit identifier is a non-negative integer expression or an asterisk (*) in which case unit 6 is assumed.
- An internal file identifier is the name of a character variable, character array, character array element, or character
substring.
If the optional UNIT= specifier is omitted then the unit specifier must be the first item in the list of specifiers.
[FMT =] f
-
f is a format identifier. A format identifier is one of the following:
- A statement label of a FORMAT statement that appears in the same program unit as the format identifier.
- An integer variable name that has been assigned the statement label of a FORMAT statement that appears in the
same program unit as the format identifier (see the ASSIGN statement).
- An integer array name.
- A character array name.
- Any character expression except one involving the concatenation of an operand whose length specification is (*)
unless the operand is a symbolic constant (see the PARAMETER statement).
- An asterisk (*), indicating list-directed formatting.
- A NAMELIST name, indicating namelist-directed formatting.
If the optional FMT= specifier is omitted then the format specifier must be the second item in the list of specifiers
and UNIT= must not be specified for the first item in the list.
REC = rn
-
rn is an integer expression whose value must be positive. It is the number of the record to be written
when a file is connected for direct access.
IOSTAT = ios
-
is an input/output status specifier. The integer variable or integer array element ios is defined with
zero if no error condition occurs or a positive integer value if an error condition occurs.
ERR = s
-
is an error specifier and s is a statement label. When an error occurs, execution is transferred to the
statement labelled by s.
Output list - An output list may contain one or more of the following:
- A variable name.
- An array element name.
- A character substring name.
- An array name except an assumed-size dummy array.
- Any other expression except a character expression involving concatenation of an operand whose length specification is
an asterisk in parentheses unless the operand is the symbolic name of a constant (since the length can be determined at compile
time).
- An implied-DO list of the form:
( dlist, i = e1, e2 [,e3] )
where dlist is composed of one or more of items (1) through (6).
Example:
WRITE( 6, 100 )X, Y, Z
WRITE( UNIT=6, FMT=100 )X, Y, Z
100 FORMAT( 3F10.5 )
WRITE( UNIT=6, FMT='( 3F10.5 )' )X, Y, Z
WRITE( 6, '( 3F10.5 )' )X, Y, Z
The above gives four examples of formatted WRITE statements. In all cases, the format conversion is
identical but it was specified in different ways. When executed, the effect of all WRITE statements is the
same. The unit number, used here, is 6. There are, in fact, many other ways in which the WRITE statement
could have been written, all of which would have the same effect when executed. We have not shown use of all the specifiers.
Example:
WRITE( 6, * )X, Y, Z
WRITE( *, * )X, Y, Z
WRITE( UNIT=6, FMT=* )X, Y, Z
WRITE( UNIT=*, FMT=* )X, Y, Z
The above four examples of list-directed formatted output are all equivalent. Open Watcom FORTRAN 77 assumes
unit 6 when the unit number identifier is an asterisk (as in the second and fourth examples). In the examples, the
format identifier is an asterisk indicating list-directed formatting.
Example:
WRITE( 8 )X, Y, Z
WRITE( UNIT=8 )X, Y, Z
The above gives two examples of unformatted WRITE statements. The unit number used in the example is
8. When executed, the effect of both of these statements is the same. The values of the variables X, Y
and Z are written to the file connected to unit 8 in their binary form (a form quite incomprehensible to most human
beings). An advantage to using this particular form of the WRITE statement is that no conversion is required
between the internal binary representation of the values and their textual (human-readable) form (which means it takes less
computer time to process the data).
Notes:
- If no output list is specified then the effect of the WRITE statement is to produce a record whose characters
are all blanks.
- The REC= specifier may not be used when list-directed output is specified.
- An implication of point (6) above is that nesting of implied-DO lists is permitted. For example, the output list
( (A(I,J), B(I,J), J = 1, 5), I = 1, 10 )
may be broken down into the following components:
A(I,J), B(I,J)
(....dlist1...., J = 1, 5)
( .....dlist2..............., I = 1, 10 )
For more information on input/output, see the chapter entitled Input/Output. For more
information on formatted input/output, see the chapter entitled Format.
Names, Data Types and Constants
The following sections describe naming rules, data types supported by Open Watcom FORTRAN 77, and formats for constants.
Symbolic Names
Symbolic names are names that represent variables, arrays, functions, etc. Names are formed using any of
the upper-case letters A-Z and the digits 0-9, the first of which must be a letter. Symbolic names are limited to 6
characters in length. The following are examples of symbolic names.
AMOUNT
AGE
CUST73
Open Watcom FORTRAN 77 extends the allowable characters that can make up a symbolic name to include the lower-case
letters a-z, the dollar sign ($) and the underscore (_). Note that the dollar sign and the underscore are treated as
letters and are therefore allowed as the first letter of a symbolic name. Furthermore, Open Watcom FORTRAN 77 allows
symbolic names of up to 32 characters. The following are examples of permissible symbolic names.
Evaluate
$Cheque
ComputeAverage
_device
IO$ERROR
student_total
Open Watcom FORTRAN 77 makes no distinction between upper and lower case letters. The following symbolic names
are identical.
Account
ACCount
ACCOUNT
Spaces are allowed in symbolic names and are ignored. The following symbolic names are identical.
C R E DIT
CRE D I T
FORTRAN 77 allows certain keywords such as WRITE to be used as symbolic names. In Open Watcom FORTRAN 77, all
keywords satisfy the requirements of a symbolic name. A keyword is a sequence of letters that is interpreted in
a special way by Open Watcom FORTRAN 77. Whether a string of characters is interpreted as a keyword or as a symbolic
name depends on the context in which it is used. In the following example, the first statement is an assignment statement
assigning the value 2 to the symbolic name DO10I. The second statement is the beginning of a DO-loop.
Example:
DO10I=1
DO10I=1,10
Data Types
There are 6 basic data types in FORTRAN 77; logical, integer, real, double precision, complex and character. Open
Watcom FORTRAN 77 provides an additional data type, namely double precision complex ( DOUBLE COMPLEX or COMPLEX*16).
Open Watcom FORTRAN 77 also supports the creation of more complex user-defined data types using the STRUCTURE
statement.
Each data type can be classified as numeric, logical or character. Each datum occupies a sequence of storage
units. Numeric data and logical data occupy numeric storage units whereas character data occupy character storage units.
In Open Watcom FORTRAN 77, a numeric storage unit occupies 4 bytes and a character storage unit occupies 1 byte.
The following table summarizes all data types supported by Open Watcom FORTRAN 77.
+--------------------+-----------+-------------+
| Data Type | Size
| Standard |
|
|(in bytes) | FORTRAN |
+--------------------+-----------+-------------+
| LOGICAL | 4
| yes |
| LOGICAL*1 | 1
| extension |
| LOGICAL*4 | 4
| extension |
| INTEGER | 4
| yes |
| INTEGER*1 | 1
| extension |
| INTEGER*2 | 2
| extension |
| INTEGER*4 | 4
| extension |
| REAL
| 4 | yes |
| REAL*4 | 4
| extension |
| REAL*8 | 8
| extension |
| DOUBLE PRECISION | 8 | yes
|
| COMPLEX | 8
| yes |
| COMPLEX*8 | 8
| extension |
| DOUBLE COMPLEX | 16 |
extension |
| COMPLEX*16 | 16
| extension |
| CHARACTER | 1
| yes |
| CHARACTER*n | n
| yes |
+--------------------+-----------+-------------+
Detailed information on the size and range of values supported by each of these data types is provided in the User's
Guide.
Data Type of a Name
A name must only have one data type. Its type is specified by the appearance of that name in a type statement.
If a name does not appear in any type statement then an implied type is assigned to it by the "first letter rule".
A name not appearing in any type statement and beginning with any of the letters I, J, K, L, M or N is assigned the
type integer. A name not appearing in any type statement and beginning with any other letter is assigned the type real.
The implied type of a letter can be changed by an IMPLICIT statement.
The type associated with a name defines the type of the data it is to contain. For example, if A is of type
integer, then the storage unit which A occupies is assumed to contain integer data. Note that the data type of an array
element is the same as the data type associated with the array name.
The data type of a function name specifies the type of the result returned by the function when it is referenced.
A name that identifies a specific intrinsic function has type as specified in the chapter entitled Functions and Subroutines.
A generic function name has no type associated with it; its type is determined by the type of its argument(s).
The appearance of a generic function in a type statement is not sufficient to remove the generic properties of that
name. For example, if SIN was declared to be of type real, it could still be called with an argument of type complex.
The type of an external function reference is determined in the same way as for variables and arrays. The actual
type of the external function is determined implicitly by its name or explicitly by its appearance in a FUNCTION
or type statement. Note that an IMPLICIT statement can affect the type of the external function being defined.
Constants
A constant can be one of arithmetic, logical or character. Each constant has a data type and value associated
with it and, once established in a program, cannot be changed. Arithmetic constants consist of those constants whose
data type is one of integer, real, double precision, complex or double precision complex. Logical constants consist
of those constants whose data type is logical and character constants consist of those constants whose data type is character.
The string of characters representing a constant determines its value and data type. The blank character is insignificant
for all but character constants.
Integer Constants
An integer constant is formed by a non-empty string of digits preceded by an optional sign.
The following are examples of integer constants.
1423
+345
-34565788
Real Constants
We first define a simple real constant as follows: an optional sign followed by an integer part followed
by a decimal point followed by a fractional part. The integer and fractional parts are non-empty strings of digits.
Either can be omitted but not both.
A real constant has one of the following forms.
- A simple real constant.
- A simple real constant followed by an E followed by an optionally signed integer constant.
- An integer constant followed by an E followed by an optionally signed integer constant.
The optionally signed integer constant that follows the E is called the exponent. The value of a
real constant that contains an exponent is the value of the constant preceding the E multiplied by the power of
ten determined by the exponent.
The following are examples of real constants.
123.764
.4352344
1423.34E12
+345.E-4
-.4565788E3
2E6
1234.
Double Precision Constant
A double precision constant has one of the following forms.
- A simple real constant followed by a D followed by an optionally signed integer constant.
- An integer constant followed by a D followed by an optionally signed integer constant.
The optionally signed integer constant that follows the D is called the exponent. The value of a
double precision constant that contains an exponent is the value of the constant preceding the D multiplied by the
power of ten determined by the double precision exponent. Note that the resulting approximation is of greater precision
than the equivalent real constant. The approximations may be of equal precision if the approximations are exact representations.
For example, 0D0 and 0E0 are double and single precision constants respectively, both representing
zero with the same precision.
The following are examples of double precision constants.
1423.34D12
+345.D-4
-.4565788D5
2D6
Complex Constant
A complex constant consists of a left parenthesis, followed by a real or integer constant representing the real
part of the complex constant, followed by a comma, followed by a real or integer constant representing the imaginary part
of the complex constant, followed by a right parenthesis.
The following are examples of complex constants.
( 1423.34E12, 3 )
( +345, 4 )
Double Precision Complex Constant (Extension)
A double precision complex constant has the same form as a complex constant except that at least one of the real
and imaginary parts must be a double precision constant.
The following are examples of double precision complex constants.
( 1423.34D12, 3 )
( +345, 4D2 )
Logical Constant
A logical constant can have one of the following forms.
- .TRUE. representing the value true.
- .FALSE. representing the value false.
Character Constant
A character constant consists of an apostrophe followed by any string of characters followed by an apostrophe.
The apostrophes are not part of the datum. If an apostrophe is to appear as part of the datum it must be followed
immediately by another apostrophe. Note that blanks are significant. The length of the character constant is
the number of characters appearing between the delimiting apostrophes. Consecutive apostrophes in a character datum
represent one character, namely the apostrophe. A character constant must not have length 0.
The following are examples of character constants.
'ABCDEFG1234567'
'There''s always tomorrow'
String Constant (Extension)
A string constant consists of an apostrophe followed by any string of characters followed by an apostrophe and
then the letter C or c. The apostrophes are not part of the datum. The datum is stored in memory
with a terminating NUL character (CHAR(0)). If an apostrophe is to appear as part of the datum it must be followed
immediately by another apostrophe. Note that blanks are significant. The length of the string constant is the
number of characters appearing between the delimiting apostrophes plus one for the terminating NUL character (CHAR(0)).
Consecutive apostrophes in a string datum represent one character, namely the apostrophe. A string constant must not
have length 0. A string constant may be used anywhere a character constant may be used.
The following are examples of string constants.
'Hello there'C
'There''s always tomorrow'c
'The result for %s=%d'c
Hollerith Constants (Extension)
A hollerith constant consists of a positive unsigned integer constant n followed by the letter H or
h followed by a string of exactly n characters. The actual data is the n characters following
the letter H or h. A hollerith constant is another way of representing character data.
Actually, hollerith constants are treated as character constants and can be used wherever a character constant can
be used. Hollerith constants are different from character constants in that a quote is represented by two quotes in
character constants and by a single quote in hollerith constants.
The following are examples of hollerith constants.
5HABCDEFG
10h xxxxx '44
Hexadecimal Constants (Extension)
Two forms of hexadecimal constant are supported. The first form can only be used in type declaration or
DATA statements. The second form may be used anywhere an integer constant may be used.
The first form of hexadecimal constant consists of the letter Z or z followed by a string of hexadecimal
digits. A hexadecimal digit can be any digit or one of the letters A, B, C, D, E or F (the lower
case of these letters is also acceptable). The actual data is the hexadecimal digits following the letter Z
or z. Hexadecimal constants of this form can only be used in type declaration statements and DATA
statements for initializing memory with binary patterns.
The following are examples of the first form of hexadecimal constant.
z1234
Zac
The first example is equivalent to the binary pattern 0001 0010 0011 0100. The second example is equivalent
to the binary pattern 1010 1100.
The second form of hexadecimal constant consists of an apostrophe followed by any string of hexadecimal digits followed
by an apostrophe and then the letter X or x. A hexadecimal digit can be any digit or one of the letters
A, B, C, D, E or F (the lower case of these letters is also acceptable). The actual data is the hexadecimal
digits placed inside apostrophes.
The following are examples of the second form of hexadecimal constant.
'1234'x
'ac'X
The first example is equivalent to the binary pattern 0001 0010 0011 0100. The second example is equivalent
to the binary pattern 1010 1100.
Octal Constants (Extension)
An octal constant consists of an apostrophe followed by any string of octal digits followed by an apostrophe and
then the letter O or o. An octal digit can be any of the digits 0 through 7. The actual data
is the octal digits placed inside apostrophes. An octal constant may be used anywhere an integer constant may be used.
The following are examples of octal constants.
'1234'o
'37'O
The first example is equivalent to the binary pattern 001 010 011 100. The second example is equivalent
to the binary pattern 011 111.
Symbolic Constants
It is possible to give a constant a symbolic name. This is done through PARAMETER statements. For
more details, see the section on the PARAMETER statement in the chapter entitled FORTRAN Statements.
Arrays
An array is a non-empty collection of data. Arrays allow a convenient way of manipulating large quantities of data.
An array can be referenced as an entity. In this way it is possible to conveniently pass large quantities of
data between subprograms. Alternatively, it is possible to reference each element of an array individually so that
data can be selectively processed. Consider the task of managing the marks of 100 students. Without arrays one
would have to have a unique name for each mark. They might be M1, M2, etc. up to M100. This is clearly
cumbersome. Instead, we can use an array called MARKS containing 100 elements. Now there is one name for all
the marks. Each mark can be referenced by using that name followed by a subscript. Furthermore, suppose the size
of the class doubled. Do we add the names M101, M102, etc. up to M200? Not if we use arrays. If the
size of the class doubled, all that need be done is to define the array to contain 200 elements. It is not hard to
see that programs that use arrays tend to be general in nature. Arrays also facilitate the repetitive computations
that must be performed on large amounts of data in that they lend themselves to loop processing.
Properties of Arrays
Arrays are defined by an array declarator. The form of an array declarator is:
a( d [,d] ... )
- where:
-
a
- is the symbolic name of the array
d
- is a dimension declarator.
The number of dimensions of the array is determined by the number of dimension declarators appearing in the array declarator.
Allowable dimensions for arrays range from 1 to 7. A 1-dimensional array can be viewed as a vector, a 2-dimensional
array as a matrix and a 3-dimensional array as a number of parallel matrices. Arrays with dimension higher than 3 are
generally difficult to intuitively describe and hence examples will deal with arrays whose dimension is 1, 2 or 3.
Each dimension has a range of values. When referencing elements in that dimension, the dimension expression
must fall in that range. The range of a dimension is defined in the dimension declarator. A dimension declarator
has the following form:
[lo:] hi
- where:
-
lo
- is the lower dimension bound.
hi
- is the upper dimension bound.
The lower and upper dimension bounds must be integer expressions and the upper dimension bound must be greater than or
equal to the lower dimension bound. The upper dimension bound of the last dimension may be an asterisk (*).
The meaning of this will be discussed later. If the lower dimension bound is not specified then a default of
1 is assumed. The size of a dimension is defined as hi - lo + 1. Note that if the lower dimension bound
is not specified the size of the dimension is just hi. The size of the array (or the number of elements in
the array) is defined as the product of all the sizes of the dimensions of the array. The maximum number of elements
in any dimension is limited to 65535. The maximum size of an array is limited by the amount of available memory.
Arrays are defined by the appearance of an array declarator in a DIMENSION statement, a type statement or
a COMMON statement.
Example:
DIMENSION A(10), B(-5:5,-10:10)
INTEGER C(10,20)
COMMON /DATA/ X,Y(30,30),Z
In the previous example, B is a 2-dimensional array with 11 rows and 21 columns and has 231 elements (i.e. 11
* 21).
Each array has a data type associated with it. This data type is inherited by all elements of the array.
Array Elements
Each array is comprised of a sequence of array elements. An array element is referenced by following the array name
with a subscript. Different elements of the array are referenced by simply changing the subscript. An
array element has the following form:
a(s[,s]...)
- where:
-
a
- is the array name.
(s[,s]...)
- is a subscript.
s
- is a subscript expression.
Each subscript expression must be an integer expression and must be in the range defined by the upper and lower
dimension bounds of the corresponding dimension. The number of subscript expressions must be equal to the dimension
of the array.
If an array has n elements then there is a 1-to-1 correspondence between the elements of the array and the
integers from 1 to n. Each subscript has a subscript value associated with it which determines which
element of the array is being referenced. If the subscript value is i then the ith element of the array
is the one referenced. The subscript value depends on the subscript expressions and on the dimensions of the array.
The following table describes how to compute the subscript value.
+---+--------------------+------------+----------------------------+
| n | Dimension | Subscript |
Subscript |
| | Declarator | Value
|
+---+--------------------+------------+----------------------------+
| 1 | (J1:K1) | (S1)
| 1+(S1-J1)
|
+---+--------------------+------------+----------------------------+
| 2 | (J1:K1,J2:K2) | (S1,S2) | 1+(S1-J1)
|
| |
| | +(S2-J2)*D1
|
+---+--------------------+------------+----------------------------+
| 3 | (J1:K1,J2:K2,J3:K3)| (S1,S2,S3) | 1+(S1-J1)
|
| |
| | +(S2-J2)*D1
|
| |
| | +(S3-J3)*D2*D1
|
+---+--------------------+------------+----------------------------+
| . | .
| . | .
|
| . | .
| . | .
|
| . | .
| . | .
|
+---+--------------------+------------+----------------------------+
| n | (J1:K1,...,Jn:Kn) | (S1,...,Sn)| 1+(S1-J1)
|
| |
| | +(S2-J2)*D1
|
| |
| | +(S3-J3)*D2*D1
|
| |
| | +
|
| |
| | +(Sn-Jn)*Dn-1*Dn-2*...*D1
|
+---+--------------------+------------+----------------------------+
Notes:
- n is the number of dimensions, 1 <= n <= 7.
- Ji is the value of the lower bound of the i'th dimension.
- Ki is the value of the upper bound of the i'th dimension.
- If only the upper bound is specified, then Ji = 1
- Si is the integer value of the i'th subscript expression.
- Di = Ki-Ji+1 is the size of the i'th dimension. If the value of the lower bound is 1, then Di = Ki.
- A subscript of the form (J1,...,Jn) has subscript value 1 and identifies the first element of the array. A subscript
of the form (K1,...,Kn) has subscript value equal to the size of the array and identifies the last element of the array.
Classifying Array Declarators by Dimension Declarator
Array declarators can be classified according to the characteristics of the dimension declarator. The following
sections discuss the three classifications.
Constant Array Declarator
A constant array declarator is one in which each of the dimension bound expressions is an integer constant expression.
It is called a constant array declarator because the dimension bound expressions can never change. In the following
example both A(10) and B(-5:5) are constant array declarators.
Example:
SUBROUTINE SQUARE( A )
DIMENSION A(10), B(-5:5)
.
.
.
END
Adjustable Array Declarator
An adjustable array declarator is one that contains at least one variable in all of its dimension bound expressions.
It is called an adjustable array declarator because the dimension bound expressions can change depending on the current
value of the variables in the dimension bound expressions. The array name must be a dummy argument. In the following
example, A(M,2*N) is an adjustable array declarator. If SQUARE is called with M having value
5 and N having value 10, then the array A will be a 2-dimensional array having 5 rows and 20 columns.
Example:
SUBROUTINE SQUARE( A, M, N )
DIMENSION A(M,2*N)
.
.
.
END
Assumed-size Array Declarator
An assumed-size array declarator is a constant array declarator or an adjustable array declarator whose upper dimension
bound of the last dimension is an asterisk (e.g., A(M,N,*)) or the integer value 1 (e.g., A(M,N,1)). The array name
must be a dummy argument. The value of the upper bound of the last dimension is determined by the number of elements
of the actual array argument and is computed as follows. First we compute the size of the dummy array. Note that
this size is really an upper bound.
- If the corresponding actual array argument is a non-character array name, the size of the dummy array is the size of the
actual array.
- If the corresponding actual array argument is a non-character array element name with a subscript value of r in
an array of size x, the size of the dummy array is x + 1 - r.
- If the corresponding actual argument is a character array name, character array element or a substring character array
element which begins at character t of an array with c characters then the size of the dummy array is INT((
c + 1 - t ) / e) where e is the size of an element of the dummy array.
If the assumed-size array has dimension n then the product of the first n - 1 dimensions must be less than
or equal to the size of the array as determined by one of the preceding rules. The value of the assumed dimension is
the largest integer such that the product of all of the dimensions is less than or equal to the size of the dummy array.
In the following example, A(4,*) is an assumed-size array declarator.
Example:
DIMENSION B(10)
.
.
.
CALL SQUARE( B )
.
.
.
END
SUBROUTINE SQUARE( A )
DIMENSION A(4,*)
.
.
.
END
By rule 1, the upper bound of the size of A is 10. We now look for the largest integer n such
that 4 * n is less than or equal to 10. Clearly, n is 2. A is therefore a 2-dimensional
array with 4 rows and 2 columns.
Allocatable Array Declarator
An allocatable array declarator is one that contains no dimension bound expressions. It is called an allocatable
array declarator because the dimension bounds are specified at run-time in an ALLOCATE statement.
Example:
DIMENSION A(:), B(:,:)
.
.
.
ALLOCATE( A(N) )
ALLOCATE( B(0:4,5) )
In the previous example, A(:) is a one-dimensional allocatable array declarator and B(:,:) is a
two-dimensional allocatable array declarator. The first ALLOCATE statement is used to allocate the array
A with bounds 1:N. The second ALLOCATE statement is used to allocate the array B with
bounds 0:4 in the first dimension and 1:5 in the second dimension.
Classifying Array Declarators by Array Name
Array declarators can also be classified according to the characteristic of the array name. The following sections
discuss the two classifications.
Actual Array Declarator
An actual array declarator is one in which the array name is not a dummy argument. All actual array declarators
must also be constant array declarators. An actual array declarator is permitted in a DIMENSION statement,
a type statement or a COMMON statement.
Dummy Array Declarator
A dummy array declarator is one in which the array name is a dummy argument and hence can only appear in a function
or subroutine subprogram. It can be a constant, adjustable or assumed-size array declarator. A dummy array declarator
can appear in a DIMENSION statement or a type statement but not in a COMMON statement. It should
be noted that the array declarator for a dummy array declarator need not be the same as the array declarator of the corresponding
actual array declarator. Also note that every array declarator in a main program must be a constant array declarator.
Use of Array Names
The appearance of an array name must always be as part of an array element name except in the following cases:
- in a list of dummy arguments. For example, a subroutine that has as one of its arguments an array.
- in a COMMON statement to define that array as belonging to a common block.
- in a type statement either as part of an array declarator or by itself to establish the type of the array.
- in an array declarator in a DIMENSION, type or COMMON statement.
- in an EQUIVALENCE statement.
- in a DATA statement.
- in the list of actual arguments when calling an external procedure.
- In the list of an input/output statement.
- as a unit identifier for an internal file in an input/output statement.
- as a format identifier in an input/output statement.
- in a SAVE statement.
Character Substrings
A substring is a contiguous portion of a character entity. The substring operation selects a substring from
a character entity. The resulting substring can then be treated as a character entity in itself. Substringing
also allows the replacement of substrings from character entities with other character entities.
Substring Names
Substrings are formed by specifying a substring name. The forms of a substring name are:
v( [ e1] : [ e2] )
a(s [,s] ...)( [ e1] : [ e2] )
- where:
-
v
- is a character variable name.
a(s[,s]...)
- is a character array element name.
e1
- is an integer expression identifying the leftmost character of the substring.
e2
- is an integer expression identifying the rightmost character of the substring.
e1 and e2 are called substring expressions. They must be such that
1 <= e1 <= e2 <= len
where len is the length of the character entity. If e1 is omitted, a value of 1 is assumed.
If e2 is omitted, a value of len is assumed. Both e1 and e2 may be omitted.
The length of the substring is e2 - e1 + 1.
Example:
CHARACTER A*8, B(4)*8, C*14
* A gets the string 'EVERYDAY'
A = 'EVERYDAY'
* Replace 'DAY' with 'ONE' in A
A(6:8) = 'ONE'
* B(1) gets the string 'OTHELLO'
B(1) = 'OTHELLO'
* B(2) gets same value as B(1)
B(2)(:) = 'OTHELLO'
* B(3) gets last 6 characters of B(1)
B(3) = B(1)(3:8)
* B(4) gets first 4 characters of B(1)
* concatenated with the letter 'R'
B(4) = B(1)(1:4) // 'R'
* C gets last 6 characters of B(1)
* concatenated with the variable A
C = B(1)(3:) // A
* Print out the results
PRINT *, A
PRINT '(A8)', B
PRINT *, C
END
Extensions
Open Watcom FORTRAN 77 allows an external character function reference or a character statement function reference as
part of the substring name (see the chapter entitled Functions and Subroutines.
for more information).
Example:
CHARACTER*10 F,G
CHARACTER*10 X
*
* DEFINE CHARACTER STATEMENT FUNCTION
*
G(X) = X
*
PRINT *, F('0123456789')(1:5)
PRINT *, G('0123456789')(6:10)
END
*
* DEFINE CHARACTER EXTERNAL FUNCTION
*
CHARACTER*(*) FUNCTION F( X )
CHARACTER*10 X
F = X
END
Structures, Unions and Records
The following sections describe support for composite data types.
Structures and Records
As an extension to the basic FORTRAN 77 types such as INTEGER, REAL, LOGICAL, etc., Open Watcom FORTRAN 77 supports the
creation of hierarchical, composite data types called structures. A structure is a template describing the form
of a record. It is composed of members or fields of various types, including other structures. A structure
does not reserve any storage.
For example, you could describe the structure of the COMPLEX data type using the following construction.
Example:
STRUCTURE /CMPLX/
REAL REAL_PART
REAL IMAG_PART
END STRUCTURE
Since the COMPLEX data type is an intrinsic type of FORTRAN, there is no need to do so. The STRUCTURE
and END STRUCTURE statements mark the start and end of a structure definition.
There are, however, many practical examples of collections of data that may be described using a structure.
Consider, for example, the contents of a data record on disk. It may contain fields such as last name, first name,
and middle initial which describe the name of a customer. Each of these fields are fixed in length. A sample
structure declaration might be:
STRUCTURE /NAME/
CHARACTER*20 LAST_NAME
CHARACTER*20 FIRST_NAME
CHARACTER*1 MIDDLE_INITIAL
END STRUCTURE
As we stated above, a structure does not allocate storage. Instead, we have created a new type called NAME
which may be used to describe objects. Objects of the new type are defined using the RECORD statement.
For example, the following statements describe two objects, STUDENT_1 and STUDENT_2, to be of type
NAME.
RECORD /NAME/ STUDENT_1
RECORD /NAME/ STUDENT_2
There are other attributes of a person besides one's name that could be recorded in the record. For example,
we can also store a person's date of birth and sex. First, let us define a DATE structure.
STRUCTURE /DATE/
INTEGER*1 DAY
INTEGER*1 MONTH
INTEGER*2 YEAR
END STRUCTURE
Now we can describe a person in terms of name, date of birth, and sex.
STRUCTURE /PERSON/
RECORD /NAME/ NAME
RECORD /DATE/ BIRTH_DATE
CHARACTER*1 SEX
END STRUCTURE
RECORD /PERSON/ STUDENT
Having declared STUDENT to be of type PERSON, how do we reference the component parts of STUDENT?
The following example illustrates this.
STUDENT.NAME.LAST_NAME = 'Pugsley'
STUDENT.NAME.FIRST_NAME = 'Elmar'
STUDENT.NAME.MIDDLE_INITIAL = 'M'
STUDENT.BIRTH_DATE.DAY = 21
STUDENT.BIRTH_DATE.MONTH = 11
STUDENT.BIRTH_DATE.YEAR = 1959
STUDENT.SEX = 'M'
The object's name is specified first, followed by a "." (or "%") and the structure member name.
If the structure member is itself a record then another "." (or "%") and member name is specified.
This continues until the desired structure member is identified. The "." or "%" is called
a field selection operator.
The previous example contained both a structure called NAME (RECORD /NAME/) and a structure member called
NAME (RECORD /NAME/ NAME). The structure name is enclosed within slashes ("/"). A structure name
must be unique among structure names. However, the same name can also be used to name either variables or structure
members (fields). Thus it is possible to have a variable named X, a structure named X, and one or
more fields named X.
Structure, field, and variable names are all local to the program unit in which they are defined.
Arrays of Records
It is often the case that the individual attributes of objects are stored in separate arrays. If, for example, your
application deals with 1000 objects with attributes "size", "weight", and "colour", the traditional
approach is to declare three different arrays.
PARAMETER (MAX_ELS=1000)
REAL SIZE(MAX_ELS)
INTEGER WEIGHT(MAX_ELS)
CHARACTER*2 COLOUR(MAX_ELS)
To read or write the attributes relating to an object, you would use a statement such as:
READ(UNIT=3) SIZE(I), WEIGHT(I), COLOUR(I)
Using a simple structure, we can express the problem as follows:
PARAMETER (MAX_ELS=1000)
STRUCTURE /OBJECT/
REAL
SIZE
INTEGER
WEIGHT
CHARACTER*2 COLOUR
END STRUCTURE
RECORD /OBJECT/ ITEM(MAX_ELS)
To read or write the attributes relating to an object, you would use a statement such as:
READ(UNIT=3) ITEM(I)
Unions
Sometimes it is useful to be able to describe parts of structures in different ways in much the same way that the
EQUIVALENCE statement is used to describe a specific storage area in different ways. The UNION -
END UNION statements are used to mark a section of a structure that will have alternate storage organizations (MAPs).
The MAP - END MAP statements are used to define the start and end of an alternate storage map.
Thus several MAP - END MAP pairs will appear between a UNION - END UNION section.
Consider the following example. The subroutine displays the contents of a field using different names and formats
depending on a TYPE field.
Example:
SUBROUTINE PRINT_ITEM( ITEM )
STRUCTURE /DATA_MAP/
INTEGER
TYPE
UNION
MAP
LOGICAL LGL
END MAP
MAP
INTEGER INT
END MAP
MAP
REAL
FLT
END MAP
MAP
DOUBLE PRECISION DBL
END MAP
END UNION
END STRUCTURE
RECORD /DATA_MAP/ ITEM
IF( ITEM%TYPE .EQ. 1 ) THEN
PRINT
'(L2)', ITEM%LGL
ELSEIF( ITEM%TYPE .EQ. 2 ) THEN
PRINT
'(I8)', ITEM%INT
ELSEIF( ITEM%TYPE .EQ. 3 ) THEN
PRINT
'(E12.5)', ITEM%FLT
ELSEIF( ITEM%TYPE .EQ. 4 ) THEN
PRINT
'(D12.5)', ITEM%DBL
ENDIF
END
The organization of the record in memory is as follows:
offset +0 +4
+8
integer
logical (slack)
integer (slack)
real (slack)
double precision
The first 4 bytes of storage are occupied by TYPE. The next 4 to 8 bytes of storage are occupied by
either LGL, INT, FLT, or DBL depending on the interpretation of the contents of the variable
TYPE. The size of the record ITEM is a total of 12 bytes. Based on the conventions of the above
program example, only 8 bytes of the record ITEM are used when TYPE is 1, 2, or 3. When TYPE
is 4 then 12 bytes of the record are used.
The following example maps out a 4-byte integer on an Intel 80x86-based processor.
Example:
STRUCTURE /MAPINT/
UNION
MAP
INTEGER*4 LONG
END MAP
MAP
INTEGER*2 LO_WORD
INTEGER*2 HI_WORD
END MAP
MAP
INTEGER*1 BYTE_0
INTEGER*1 BYTE_1
INTEGER*1 BYTE_2
INTEGER*1 BYTE_3
END MAP
END UNION
END STRUCTURE
RECORD /MAPINT/ I
I%LONG = '01020304'x
PRINT '(Z8)', I%LONG
PRINT '(Z4,1X,Z4)', I%LO_WORD, I%HI_WORD
PRINT '(Z2,3(1X,Z2))', I%BYTE_0, I%BYTE_1,
$
I%BYTE_2, I%BYTE_3
END
The above example produces the following output:
01020304
0304 0102
04 03 02 01
Expressions
The following topics are discussed in this chapter.
- Arithmetic Expressions
- Character Expressions
- Relational Expressions
- Logical Expressions
- Evaluating Expressions
- Constant Expressions
Arithmetic Expressions
Arithmetic expressions are used to describe computations involving operands with numeric data type, arithmetic operators
and left and right parentheses. The result of the computation is of numeric data type.
Arithmetic Operators
The following table lists the arithmetic operators and the operation they perform.
Operator Arithmetic Operation
** Exponentiation
/ Division
* Multiplication
- Subtraction or Negation
+ Addition or Identity
Some operators can be either binary or unary. A binary operator is one that requires two operands.
A unary operator is one that requires one operand. Each of the operators **, /, and * are binary operators.
The operators + and - can either be binary or unary operators. The following table describes how each operator
is used with their operands.
Operator Arithmetic Operation
x ** y x is raised to the power y
x / y x is divided by y
x * y x is multiplied by y
x - y y is subtracted from x
x + y y is added to x
- x x is negated
+ x identity
Arithmetic expressions can contain more than one operator. It is thus necessary to define rules of evaluation for
such expressions. A precedence relation is defined between operators. This relation defines the order
in which operands are combined and hence describes the evaluation sequence of an arithmetic expression. Operands of
higher precedence operators are combined using that operator to form an operand for an operator of lower precedence.
The following rules define the precedence relation among arithmetic operators.
- Exponentiation (**) has highest precedence.
- Multiplication (*) and division (/) have equal precedence but have lower precedence than exponentiation.
- Addition (+) and subtraction (-) have equal precedence but have lower precedence than multiplication and division.
For example, to evaluate the expression
A-B**4
B is raised to the exponent 4 first and the result is then subtracted from A.
Parentheses can be used to alter the evaluation sequence of an arithmetic expression. When a left parenthesis
is encountered, the entire expression enclosed in parentheses is evaluated. Consider the following expression.
3*(4+5)
We first evaluate the expression in the parentheses, the result being 9. We now multiply the result by 3 giving
a final result of 27. Now suppose we remove the parentheses. According to the precedence rules, * has
precedence over + so we perform the multiplication before the addition. The result in this case is 17.
The building blocks for arithmetic expressions are called arithmetic primaries. They are one of the following:
- unsigned arithmetic constant
- arithmetic symbolic constant
- arithmetic variable reference
- arithmetic array element reference
- arithmetic function reference
- ( arithmetic expression )
A grammar for forming arithmetic expressions can be described which reflects the precedence relation among arithmetic
operators.
Exponentiation has highest precedence. We define a factor as:
- primary
- primary ** factor
A factor is simply a sequence of primaries, each separated by the exponentiation operator. Rule (2) specifies that
the primaries involving exponentiation operators are combined from right to left when evaluating a factor.
Next in the precedence hierarchy are the multiplication and division operators. We define a term as:
- factor
- term / factor
- term * factor
A term is simply a sequence of factors, each separated by a multiplication operator or a division operator. Rules
(2) and (3) imply that in such a sequence, factors are combined from left to right when evaluating a term. Factors
can be interpreted as the result obtained from evaluating them. This implies that all factors are evaluated before
any of the multiplication or division operands are combined. This interpretation is consistent with the precedence
relation between the exponentiation operator and the division and multiplication operators.
An arithmetic expression can now be defined as follows.
- term
- + term
- - term
- arithmetic expression + term
- arithmetic expression - term
An arithmetic expression is simply a sequence of terms, each separated by an addition operator or a subtraction operator.
Rules (4) and (5) imply that terms are evaluated from left to right. Rules (2) and (3) imply that only the first
term of an arithmetic expression can be preceded by a unary + or - operator. Terms can be interpreted in the same way
as factors were interpreted in the definition of terms.
Note that consecutive operators are not permitted. For example, the expression
A+-B
is illegal. However, expressions of the form
A+(-B)
are allowed.
Arithmetic Constant Expression
An arithmetic constant expression is an arithmetic expression in which all primaries are one of the following.
- arithmetic constant
- symbolic arithmetic constant
- ( arithmetic constant expression )
There is a further restriction with the exponentiation operator; the exponent must be of type INTEGER.
As an extension to the FORTRAN 77 language, Open Watcom FORTRAN 77 supports the use of the intrinsic function
ISIZEOF in an arithmetic constant expression.
Example:
PARAMETER (INTSIZ = ISIZEOF(INTEGER))
An integer constant expression is an arithmetic constant expression in which all constants and symbolic constants
are of type INTEGER.
Example:
123
-753+2
-(12*13)
A real constant expression is an arithmetic constant expression in which at least one constant or symbolic
constant is of type REAL and all other constants or symbolic constants are of type REAL or INTEGER.
Example:
123.
-753+2.0
-(13E0*12)
A double precision constant expression is an arithmetic constant expression in which at least one constant
or symbolic constant is of type DOUBLE PRECISION and all other constants or symbolic constants are of type DOUBLE PRECISION,
REAL or INTEGER.
Example:
123.4D0
-753D0*2+.5
-(12D0*12.2)
A complex constant expression is an arithmetic constant expression in which at least one constant or symbolic
constant is of type COMPLEX and all other constants or symbolic constants are of type COMPLEX, REAL or INTEGER.
Example:
(123,0)
(-753,12.3)*2
-(12,-12.4)-(1.0,.2)
A double precision complex constant expression is an arithmetic constant expression in which at least one constant
or symbolic constant is of type COMPLEX*16 and all other constants or symbolic constants are of type COMPLEX*16, DOUBLE PRECISION,
REAL or INTEGER. If there are no constants or symbolic constants of type COMPLEX*16 in a constant expression, the type
of the constant expression will be COMPLEX*16 if it contains at least one constant or symbolic constant of type COMPLEX and
at least one constant or symbolic constant of type DOUBLE PRECISION. Open Watcom FORTRAN 77 supports this type of constant
expression as an extension of the FORTRAN 77 language.
Example:
(123,0D0)
(-753,12.3D0)*2
-(12D0,-12.4)-(1.0,.2)
Data Type of Arithmetic Expressions
Evaluating an arithmetic expression produces a result which has a type. The type of the result is determined by
the type of its operands. The following table describes the rules for determining the type of arithmetic expressions.
The letters I, R, D, C and Z stand for INTEGER, REAL, DOUBLE PRECISION, COMPLEX and COMPLEX*16 respectively.
An entry in the table represents the data type of the result when the operands are of the type indicated by the row and column
in which the entry belongs. The column represents the type of the operand to the right of the operator, and the row
represents the type of the operand to the left of the operator. The table is valid for all of the arithmetic operators.
+-------+-------+-------+-------+-------+-------+-------+-------+
| op | I*1 | I*2 | I*4 |
R | D | C | Z |
+-------+-------+-------+-------+-------+-------+-------+-------+
| I*1 | I*1 | I*2 | I*4 | R
| D | C | Z |
| I*2 | I*2 | I*2 | I*4 | R
| D | C | Z |
| I*4 | I*4 | I*4 | I*4 | R
| D | C | Z |
| R | R | R |
R | R | D | C | Z
|
| D | D | D |
D | D | D | Z | Z
|
| C | C | C |
C | C | Z | C | Z
|
| Z | Z | Z |
Z | Z | Z | Z | Z
|
+-------+-------+-------+-------+-------+-------+-------+-------+
Notes:
- I*1 represents the INTEGER*1 data type, I*2 represents the INTEGER*2 data type, and I*4 represents the
INTEGER or INTEGER*4 data type.
- The data type of the result obtained by dividing an integer datum by an integer datum is also of type INTEGER even though
the mathematical result may not be an integer. This result is called the integer quotient and is defined as
the integer part of the mathematical quotient.
- Open Watcom FORTRAN 77 supports the double precision complex data type (COMPLEX*16) as an extension of the FORTRAN 77
language. Combining an operand of type DOUBLE PRECISION with an operand of type COMPLEX yields a result of type COMPLEX*16.
Character Expressions
Character expressions are used to describe computations involving operands of type CHARACTER, the concatenation operator
(//) and left and right parentheses. The result of the computation is of type CHARACTER.
Character Operators
There is only one character operator, namely the concatenation operator (//). It requires two operands of type CHARACTER.
If x is the left operand and y is the right operand, then the result is y concatenated to
x. The length of the result is the sum of the lengths of the two operands. For example, the result of
'AAAAA'//'BBB'
is the string AAAAABBB.
The building blocks for character expressions are called character primaries. They are one of the following.
- character constant
- character symbolic constant
- character variable reference
- character array element reference
- character substring reference
- character function reference
- ( character expression )
Character expressions are defined as follows:
- character primary
- character expression // character primary
A character expression is simply a sequence of character primaries, each separated by the concatenation operator (//).
Rule 2 implies that character primaries are combined from left to right. Except in a character assignment statement,
the operands in a character expression must not contain operands whose length specification is (*) unless the operand is
a symbolic constant.
Note that, unlike arithmetic expressions, parentheses have no effect on the result of evaluating a character expression.
For example, the result of the expressions
'A'//'B'//'C'
and
'A'//('B'//'C')
is identically the string ABC.
Character Constant Expressions
A character constant expression is a character expression in which all primaries are one of the following.
- character constant
- symbolic character constant
- ( character constant expression )
As an extension to the FORTRAN 77 language, Open Watcom FORTRAN 77 supports the use of the intrinsic function CHAR
in a character constant expression.
Example:
CHARACTER*6 HELLO, WORLD
PARAMETER (HELLO = 'Hello'//CHAR(0))
PARAMETER (WORLD = 'world'//CHAR(7))
PRINT *, HELLO, WORLD
END
Relational Expressions
A relational expression is used to compare two arithmetic expressions or two character expressions. It is not possible
to compare a character expression to an arithmetic expression. Evaluation of a relational expression produces a result
of type logical.
Relational Operators
The following table lists the relational operators and the operation they perform.
Operator Relational Operation
.LT. Less than
.LE. Less than or equal
.EQ. Equal
.NE. Not equal
.GT. Greater than
.GE. Greater than or equal
The form of a relational expression is as follows.
e1 relop e2
- where:
-
relop
- is a relational operator.
e1, e2
- are both arithmetic expressions or both character expressions.
Arithmetic Relational Expressions
An arithmetic relational expression is a relational expression in which e1 and e2 are both arithmetic
expressions. An arithmetic relational expression has a value of true if the operands satisfy the relation specified
by the relational operator and false otherwise.
A complex operand is only permitted when using either the .EQ. or .NE. relational operators. Open
Watcom FORTRAN 77 allows operands of type COMPLEX*16.
Character Relational Expressions
Character relational expressions are relational expressions whose operands are of type CHARACTER. The value
of a relation between character strings is established by using the collating sequence of the processor character
set. The collating sequence is an ordering of the characters in the processor character set. Note, for example,
that the EBCDIC character set has a different collating sequence than that of the ASCII character set. For example,
e1 is greater than e2 if the value of e1 follows the value of e2 in the processor collating
sequence. The value of a character relational expression depends on the collating sequence. In the case of the
.NE. and .EQ. operators, the collating sequence has no effect.
Example:
IF( 'A' .LT. 'a' )THEN
PRINT *, 'The processor character
set'
PRINT *, 'appears to be ASCII'
ELSE
PRINT *, 'The processor character
set'
PRINT *, 'appears to be EBCDIC'
END IF
END
The above example is a crude test for determining the character set used on your processor.
It is possible to have operands of unequal length. In this case, the character string of smaller length is treated
as if blanks were padded to the right of it to the length of the larger string. The relational operator is then applied.
Logical Expressions
Logical expressions are used to describe computations involving operands whose type is LOGICAL or INTEGER, logical operators
and left and right parentheses. The result of the computation is of type LOGICAL unless both operands are of type INTEGER
in which case the result of the computation is of type INTEGER.
Logical Operators
The following table lists the logical operators and the operation they perform.
Operator Logical Operation
.NOT. Logical negation
.AND. Logical conjunction
.OR. Logical inclusive disjunction
.EQV. Logical equivalence
.NEQV. Logical non-equivalence
.XOR. Exclusive or
The logical operator .NOT. is a unary operator; all other logical operators are binary. The following tables
describe the result of each operator when it is used with logical operands.
x .NOT. x
true false
false true
x y
x .AND. y
true true true
true false false
false true false
false false false
x y
x .OR. y
true true true
true false true
false true true
false false false
x y
x .EQV. y
true true true
true false false
false true false
false false true
x y
x .NEQV. y
................ x .XOR. y
true true false
true false true
false true true
false false false
Note that the operators .NEQV. and .XOR. perform the same logical operation.
The following tables describe the result of the logical operators when they are used with integer operands.
These operators apply to bits in the operand(s), hence we show only the result of operations on individual bits. The
way to read the entries in the following tables is:
- If the bit in "x" is 0 then the corresponding bit in ".NOT.x" is 1, and so on.
- If the bit in "x" is 1 and the corresponding bit in "y" is 1 then the corresponding bit in "x.AND.y"
is 1, and so on.
x .NOT. x
0 1
1 0
x y x .AND. y
1 1
1
1 0
0
0 1
0
0 0
0
x y x .OR. y
1 1
1
1 0
1
0 1
1
0 0
0
x y x .EQV. y
1 1
1
1 0
0
0 1
0
0 0
1
x y x .NEQV.
y
.............. x .XOR. y
1 1
0
1 0
1
0 1
1
0 0
0
Note that the operators .NEQV. and .XOR. perform the same mathematical operation on bits.
As is the case with arithmetic operators, we must define rules in order to evaluate logical expressions. Again
we define rules of precedence for logical operators which dictate the evaluation sequence of logical expressions. The
following lists the logical operators in order of precedence.
- .NOT. (highest precedence)
- .AND.
- .OR.
- .EQV., .NEQV. and .XOR. (lowest precedence)
For example, in the expression
A .OR. B .AND. C
the .AND. operator has higher precedence than the .OR. operator so B and C are combined
first using the .AND. operator. The result is then combined with A using the .OR. operator.
Parentheses can be used to alter the sequence of evaluation of logical expressions. If in the previous example
we had written
(A .OR. B) .AND. C
then A and B would have been combined first.
Logical primaries are the building blocks for logical expressions. They are one of the following.
- logical or integer constant
- symbolic logical or integer constant
- logical or integer variable reference
- logical or integer array element reference
- logical or integer function reference
- relational expression
- ( logical or integer expression )
As was done with arithmetic expressions, a grammar can be defined which dictates the precedence relation among logical
operators.
The .NOT. logical operator has highest precedence. We define a logical factor as:
- logical primary
- .NOT. logical primary
Next in the precedence hierarchy is the .AND. operator. We define a logical term as:
- logical factor
- logical term .AND. logical factor
A logical term is simply a sequence of logical factors, each separated by the .AND. operator. Rule (2) specifies
that the logical factors are combined from left to right.
Next is the .OR. operator. We define a logical disjunct as:
- logical term
- logical disjunct .OR. logical term
A logical disjunct is simply a sequence of logical terms each separated by the .OR. operator. Rule (2) specifies
that the logical terms are combined from left to right.
A logical expression can now be defined as follows.
- logical disjunct
- logical expression .EQV. logical disjunct
- logical expression .NEQV. logical disjunct or logical expression .XOR. logical disjunct
A logical expression is therefore a sequence of logical disjuncts, each separated by the .EQV. operator or the .NEQV.
or .XOR. operator. Rules (2) and (3) indicate that logical disjuncts are combined from left to right.
Consider the following example.
A .OR. .NOT. B .AND. C
Since the .NOT. operator has highest precedence we first logically negate B. The result is then
combined with C using the .AND. operator. That result is then combined with A using the .OR.
operator to form the final result.
Logical Constant Expressions
A logical constant expression is a logical expression in which each primary is one of the following:
- logical constant
- symbolic logical constant
- a relational expression in which each primary is a constant expression
- ( logical constant expression )
The following are examples of a logical constant expression (assume that A, B, C and D
are arithmetic constants appearing in PARAMETER statements).
.TRUE. .AND. .NOT. .FALSE.
'A' .LT. 'a'
A * B .GT. C * D
Evaluating Expressions
Four different types of operators have been discussed; arithmetic, character, relational and logical. It is possible
to form an expression which contains all of these operators. Consider the following example.
A+B .LE. C .AND. X // Y .EQ. Z .AND. L
where A, B and C are of numeric type, X, Y and Z are of type
CHARACTER and L is of type LOGICAL. In this expression, + is an arithmetic operator, // is a character operator,
.EQ. is a relational operator and .AND. is a logical operator. Since we can mix these four types of operators,
it is necessary to define a precedence among these four classes of operators. The following defines this precedence
of operators.
- arithmetic operators (highest precedence)
- character operators
- relational operators
- logical operators (lowest precedence)
With this precedence any expression can now be evaluated without ambiguity.
Constant Expressions
A constant expression is an arithmetic constant expression, a character constant expression or a logical constant
expression.
Assignment Statements
Assignment statements are used to define entities. There are four different types of assignment.
- Arithmetic
- Logical
- Statement label (ASSIGN)
- Character
Arithmetic Assignment
The form of an arithmetic assignment statement is
v = e
- where:
-
v
- is a variable name or array element name of type INTEGER, REAL, DOUBLE PRECISION, COMPLEX or double precision complex (COMPLEX*16).
e
- is an arithmetic expression.
The following are examples of arithmetic assignment statements.
Y = X**2 + 4.0*X + 3.0
Z(10) = 4.3*(X+Y)
Executing an arithmetic assignment statement causes the evaluation of the arithmetic expression e, converting
the type of the expression e to the type of v, and defining v with the result.
If v is of type INTEGER*1 or INTEGER*2, then the value of the expression e is first converted to
type INTEGER. The resulting integer is then assigned to v in the following way.
- If v is of type INTEGER*2 and the value of e is such that -32768 <= e <= 32767, v
will be assigned the value of e. Otherwise, v will be undefined.
- If v is of type INTEGER*1 and the value of e is such that -128 <= e <= 127, v
will be assigned the value of e. Otherwise, v will be undefined.
Logical Assignment
The form of a logical assignment statement is
v = e
- where:
-
v
- is a variable name or array element name of type LOGICAL.
e
- is a logical expression.
The following are examples of logical assignment statements.
LOG1 = .TRUE.
LOG2 = (X.GT.Y) .AND. (X.LT.Z)
LOG3(2) = LOG2 .EQV. LOG1
Executing a logical assignment statement causes the evaluation of the logical expression e, and defining
v with the result. Note that the type of v and e must be LOGICAL.
Statement Label Assignment
The form of a statement label assignment is
ASSIGN s to i
- where:
-
s
- is a statement label.
i
- is the name of an integer variable.
The following is an example of a statement label assignment statement.
ASSIGN 10 TO I
The result of executing an ASSIGN statement causes the integer variable i to be defined with the
value of the statement label s. s must be the statement label of an executable statement or a format
statement in the same program unit in which the ASSIGN statement appears. It is possible to change the value
of i by executing another ASSIGN statement.
During execution when i is used in an assigned GO TO statement, an ASSIGN statement which
defines i must have been executed prior to the execution of the assigned GO TO statement.
While the variable i is defined with a statement label, it should not be used in any other way other than
in an assigned GO TO statement. Consider the following example.
Example:
10 ASSIGN 10 TO I
* Illegal use of an ASSIGNed variable
PRINT *, I
The output produced by the PRINT statement is not the integer 10. Its value is undefined and
should be treated that way.
Character Assignment
The form of a character assignment statement is
v = e
- where:
-
v
- is a character variable name, character array element, or character substring.
e
- is a character expression.
The following are examples of character assignment statements.
CHARACTER*20 C,D(5)
C='ABCDEF'
C(3:5)='XYZ'
D(5)(14:15)='12'
Executing a character assignment statement causes the evaluation of the character expression e and the definition
of v with the result.
None of the character positions defined in v may be referenced in e. The following example
is illegal since the 4th and 5th character positions of A appear on the left and right hand side of the equal sign.
Example:
* Illegal character assignment.
CHARACTER*10 A,B*5
A(2:6) = A(4:5) // B
The length of v and e may be different. If the length of v is less than the length
of e then the assignment has the effect of truncating e from the right to the length of v.
If the length of v is greater than the length of e, the value assigned to v is the value of
e padded on the right with blanks to the length of v.
Extended Assignment Statement
Open Watcom FORTRAN 77 supports an extension to the FORTRAN 77 assignment statement, namely the extended assignment
statement shown here:
v = v = v = ... =
v = e
1 2 3
n
- where:
-
v'i
- must be one of the following:
- Variable names or array element names of type INTEGER, REAL, DOUBLE PRECISION, COMPLEX or double precision complex (COMPLEX*16).
- Variable names or array element names of type LOGICAL.
- Character variable names, character array elements, or character substrings.
e
- must be one of the following and must follow the rules of the arithmetic, logical or character assignment statements:
- An arithmetic expression.
- A logical expression.
- A character expression.
The extended assignment statement is equivalent to the following individual statements.
v = e
n
v = v
n-1 n
.
.
.
v = v
2 3
v = v
1 2
When using an extended assignment statement involving variables of mixed type, it is important to understand the exact
way in which the assignments are performed. Assignment of each variable is made using the value of the variable to
its immediate right, starting with the rightmost variable which is assigned the value of the expression. To help make
this clear, consider the following program.
Example:
CHARACTER C1*10, C2*5, C3*7
LOGICAL L1, L2, L3
INTEGER*2 K, L
I = S = J = T = 1.25
PRINT *, I, S, J, T
I = K = J = L = 70000
PRINT *, I, K, J, L
C1 = C2 = C3 = 'ABCDEFGHIJKL'
PRINT *, C1, C2, C3
L1 = L2 = L3 = .TRUE.
PRINT *, L1, L2, L3
END
The output from this program would be:
1 1.0000000
1 1.2500000
4464 4464 4464
4464
ABCDE ABCDEABCDEFG
T T
T
Note that variables K and L are of type INTEGER*2 and cannot contain any value greater than 32767.
Truncation resulted and this value (4464) was propagated to the left.
Program Structure Control Statements
The use of structured programming statements has been found to encourage better programming and design practices among
beginners, and aids the more experienced programmer in writing error-free programs.
The format of these statements and their blocks is illustrated below. Following this, the use and meaning of
each statement is described and illustrated with examples. In each of these illustrations, the blocks are denoted by
statement(s) and are delimited by control statements.
In the descriptions, logical-expression can also be an integer expression, in which case the result of the
integer expression is compared for inequality to the integer value 0.
Example:
IF( LEN - 1 )THEN
In the preceding example, the expression LEN - 1 is interpreted as LEN - 1 .NE. 0.
IF - ELSE - END IF
The ELSE portion of this construct is optional, thus there are two possible formats.
(a) IF( logical-expression )THEN [: block-label]
statement(s)
END IF
(b) IF( logical-expression )THEN [: block-label]
statement(s)
ELSE
statement(s)
END IF
This construct is an enhancement of the FORTRAN logical IF statement. If the value of the parenthesized
logical expression is true in (a), the block of statements following the IF statement is executed, after which control
passes to the statement following the END IF statement; otherwise, control will pass directly to the statement following
the END IF statement. When the ELSE statement is used and the logical expression is true, the block
of statements between the IF and the ELSE statements is executed and then control passes to the statement
following the END IF statement; otherwise the block of statements following ELSE statement is executed
and then control passes to the statement following the END IF statement.
An optional block label may be specified with the IF statement (see the CYCLE, EXIT or
QUIT statement for more information).
Examples follow which illustrate the use of the two formats.
Example:
IF( I .EQ. 0 )THEN
PRINT *, 'I IS ZERO'
I = 1
END IF
If variable I is zero when the IF statement is executed, the string I IS ZERO will be printed,
variable I will be assigned the value 1, and the statement following the END IF will be executed.
If variable I is not zero when the IF statement is executed, control will pass to the statement following
the END IF statement.
Example:
IF( A .GT. B )THEN
PRINT *, 'A GREATER THAN B'
A = A - B
ELSE
PRINT *, 'A NOT GREATER THAN
B'
END IF
If the value of variable A is greater than the value of variable B when this IF statement
is executed, the string A GREATER THAN B will be printed and variable A will be assigned the value of the
expression A - B. Control will then pass to the statement following the END IF statement.
If the value of variable A is not greater than the value of variable B when the IF statement
is executed, the string A NOT GREATER THAN B will be printed and control will pass to the statement following the
END IF statement.
ELSE IF
A further enhancement of the IF-THEN-ELSE construct is the ELSE IF statement which may be used in the following
two formats:
(a) IF( logical-expression-1 )THEN [: block-label]
statement(s)
ELSE IF( logical-expression-2 )THEN
statement(s)
...
END IF
(b) IF( logical-expression-1 )THEN [: block-label]
statement(s)
ELSE IF( logical-expression-2 )THEN
statement(s)
...
ELSE
statement(s)
END IF
The presence of the "..." in the above formats indicates that the ELSE IF statement may be repeated
as often as desired. If the value of logical-expression-1 is true in case (a), the block of statements following
the IF statement up to the first ELSE IF statement is executed, after which control passes to the statement
following the END IF statement; otherwise, control will pass to the first ELSE IF statement. If the
value of logical-expression-2 is true, the block of statements following the first ELSE IF statement up
to the next ELSE IF statement or END IF statement is executed, after which control passes to the statement
following the END IF statement; otherwise, control will pass to the next ELSE IF statement, if there is
one, or directly to the statement following the END IF statement. When the ELSE statement is used,
as in case (b), and the values of all the logical expressions in the IF and ELSE IF statements are false,
the block of statements following the ELSE statement is executed and then control passes to the statement following
the END IF statement. An optional block label may be specified with the IF statement (see the
CYCLE, EXIT or QUIT statement for more information).
Examples follow which illustrate the use of the two formats.
Example:
IF( I .EQ. 0 )THEN
PRINT *, 'I IS ZERO'
ELSE IF( I .GT. 0 )THEN
PRINT *, 'I IS GREATER THAN ZERO'
END IF
If variable I is zero when the IF statement is executed, the string I IS ZERO will be printed
and the statement following the END IF statement will be executed. If variable I is not zero when
the IF statement is executed, control will pass to the ELSE IF statement. If variable I
is greater than zero, the string I IS GREATER THAN ZERO will be printed and the statement following the END
IF statement will be executed. If variable I is less than zero then nothing would be printed and control
passes from the ELSE IF statement to the statement following the END IF statement.
Example:
IF( A .GT. B )THEN
PRINT *, 'A GREATER THAN B'
A = A - B
ELSE IF( A .LT. B )THEN
PRINT *, 'A LESS THAN B'
A = B - A
ELSE
PRINT *, 'A EQUAL TO B'
A = 0.0
END IF
If the value of variable A is greater than the value of variable B when the IF statement
is executed, the string A GREATER THAN B will be printed and variable A will be assigned the value of the
expression A - B. Control will then pass to the statement following the END IF statement.
If the value of variable A is not greater than the value of variable B when the IF statement
is executed, control passes to the ELSE IF statement. If the value of variable A is less than the
value of variable B, the string A LESS THAN B will be printed and variable A will be assigned
the value of the expression B - A. Control will then pass to the statement following the END IF statement.
If the value of variable A is not less than the value of variable B when the ELSE IF statement
is executed, the string A EQUAL TO B will be printed and variable A will be assigned the value zero.
Control will pass to the statement following the END IF statement.
DO - END DO
DO init-expr,end-value[,inc-value] [: block-label]
statement(s)
END DO
This extension to FORTRAN 77 allows the creation of DO-loops without the introduction of statement numbers. An optional
block label may be specified (see the CYCLE, EXIT or QUIT statement for more information).
The END DO statement is used to indicate the end of the range of its corresponding DO statement.
A statement number may not be specified in the corresponding DO statement. Nested DO-loops of this form require
separate END DO statements to terminate the range of the corresponding DO statement. Since a statement
number may appear on the END DO statement, the number may be used to terminate outer DO-loops. This is not
a recommended practice (a CONTINUE statement or a structured DO statement should be used). A transfer
of control from within the DO-loop to a statement number on the END DO statement is treated in the same manner as
if the word CONTINUE had been used instead of END DO.
Some examples follow.
Example:
DO I = 1, 3
DO J = 1, 5
PRINT
*, MATRIX( I, J )
END DO
END DO
The above is equivalent to the following example which uses statement numbers.
Example:
DO 10 I = 1, 3
DO 20 J = 1, 5
PRINT
*, MATRIX( I, J )
20 CONTINUE
10 CONTINUE
The next example demonstrates the use of a GO TO statement to control execution of all or part of a DO-loop.
Example:
DO I = 1, 3
DO J = 1, 5
PRINT
*, 'INNER LOOP - J=', J
IF( J
.LE. 3 )GO TO 20
PRINT
*, 'J > 3'
20 END DO
PRINT *, 'OUTER LOOP - J=', J
END DO
A result of this example is that the character string J > 3 is printed 6 times (i.e., twice for each iteration
of the outer loop). Of course there is a much better way of coding this algorithm using the IF-END IF construct.
The example is included to illustrate the behaviour of transfers of control to an END DO statement. The following
example is an equivalent algorithm to the one above but the intent is much clearer.
Example:
DO I = 1, 3
DO J = 1, 5
PRINT
*, 'INNER LOOP - J=', J
IF( J
.GT. 3 )THEN
PRINT *, 'J > 3'
END IF
END DO
PRINT *, 'OUTER LOOP - J=', J
END DO
DO WHILE - END DO
DO WHILE (e) [: block-label]
statement(s)
END DO
This extension to FORTRAN 77 allows the creation of DO-loops without iterative techniques. Instead, the DO-loop
is executed while the parenthesized expression is true. The logical expression is evaluated before entry to the DO-loop.
If the value is false, control is transferred to the statement following the END DO statement. If the
logical expression if true, the statements of the DO-loop are executed. When the END DO statement is reached,
the expression is re-evaluated and program control proceeds as previously described. An optional block label may be
specified (see the CYCLE, EXIT or QUIT statement for more information).
An optional statement number can be specified after the DO keyword. When the END DO statement
is used to indicate the end of the range of its corresponding DO WHILE statement, a statement number may not be
specified.
Some examples follow.
Example:
I = 1
DO WHILE( I .LE. 3 )
J = 1
DO WHILE( J .LE. 5 )
PRINT
*, MATRIX( I, J )
END DO
END DO
The above is equivalent to the following example which uses statement numbers.
Example:
I = 1
DO 10 WHILE( I .LE. 3 )
J = 1
DO 20 WHILE( J .LE. 5 )
PRINT
*, MATRIX( I, J )
20 CONTINUE
10 CONTINUE
The next example demonstrates the use of a GO TO statement to control execution of all or part of a DO-loop.
Example:
I = 1
DO WHILE( I .LE. 3 )
J = 1
DO WHILE( J .LE. 5 )
PRINT
*, 'INNER LOOP - J=', J
IF( J
.LE. 3 )GO TO 20
PRINT
*, 'J > 3'
20 END DO
PRINT *, 'OUTER LOOP - J=', J
END DO
A result of this example is that the character string J > 3 is printed 6 times (i.e., twice for each iteration
of the outer loop). Of course there is a much better way of coding this algorithm using the IF-END IF construct.
The example is included to illustrate the behaviour of transfers of control to an END DO statement. The following
example is an equivalent algorithm to the one above but the intent is much clearer.
Example:
I = 1
DO WHILE( I .LE. 3 )
J = 1
DO WHILE( J .LE. 5 )
PRINT
*, 'INNER LOOP - J=', J
IF( J
.GT. 3 )THEN
PRINT *, 'J > 3'
END IF
END DO
PRINT *, 'OUTER LOOP - J=', J
END DO
LOOP - END LOOP
LOOP [: block-label]
statement(s)
END LOOP
This extension to FORTRAN 77 causes the statements between the LOOP and END LOOP statements to be repeated
until control is transferred out of the loop, usually by an EXIT or QUIT statement. An optional block
label may be specified (see the CYCLE, EXIT or QUIT statement for more information). An
example follows:
Example:
LOOP
READ *, X
IF( X .EQ. 99.0 )EXIT
PRINT *, X
END LOOP
The above statements cause values to be read and printed, one to a line, until the value 99.0 is read. When
variable X has this value, the logical expression in the IF statement evaluates as true and the EXIT
statement causes a transfer of control to the statement following the END LOOP statement. The EXIT
statement is discussed in more detail in a later section.
WHILE - END WHILE
WHILE( logical-expression )DO [: block-label]
statement(s)
END WHILE
This extension to FORTRAN 77 causes its block of code to be executed repeatedly while the parenthesized logical expression
is true. The logical expression is evaluated before entry to the block. If the value is false, control passes
to the statement following the END WHILE statement. If the logical expression is true, the statements of the
block are executed. When the END WHILE statement is reached, the WHILE logical expression is re-evaluated
and the above program control decisions are repeated. An optional block label may be specified (see the CYCLE,
EXIT or QUIT statement for more information). An example follows:
Example:
WHILE( J .GT. 0 )DO
A(J) = B(I + J)
J = J - 1
END WHILE
If variable J is zero or negative when the WHILE statement is executed, the WHILE block
of code will be by-passed and the statement following the END WHILE statement will be executed.
If variable J is greater than zero when the WHILE statement is executed, the WHILE block
will be executed repeatedly until J becomes equal to zero. The effect of this loop will be to assign values
to elements of array A from array B, starting with the element of A corresponding to the initial
value of variable J and working backwards down the array to element 1.
WHILE - Executable-statement
WHILE( logical-expression )stmt
- where:
-
stmt
- is an executable statement. Only certain executable statements are are allowed. See the section entitled Classifying Statements
in the chapter entitled FORTRAN Statements for a list of allowable statements.
This control statement is another form of the WHILE construct.
Example:
WHILE( I .GT. 0 )EXECUTE A
When this statement is executed, if the logical expression is not true, control passes to the next statement.
If the expression is true, REMOTE-block A (assumed to be defined elsewhere in the program unit) is executed, and
the logical expression is re-evaluated. This is repeated until the logical expression, when evaluated, is false; control
then passes to the next statement.
UNTIL
LOOP [: block-label]
statement(s)
UNTIL( logical-expression )
or
WHILE( logical-expression )DO [: block-label]
statement(s)
UNTIL( logical-expression )
The UNTIL statement, an extension to FORTRAN 77, may be combined with either a LOOP or WHILE
statement by replacing the END LOOP or END WHILE statement. It provides a way of specifying a condition
to be tested at the end of each iteration of a loop, which will determine whether or not the loop is repeated. After
all of the statements in the block have been executed, the logical expression in the UNTIL statement is evaluated.
If the result of the condition is false, the loop is repeated; otherwise, control passes to the statement following
the UNTIL statement.
In the following example, the statements between the LOOP and the UNTIL statements are executed
until the value of variable X is greater than 10.0.
Example:
X = 1.0
LOOP
PRINT *, X, SQRT( X )
X = X + 1.0
UNTIL( X .GT. 10.0 )
SELECT - END SELECT
SELECT [CASE] (e) [FROM] [: block-label]
CASE ( case-list )
statement (s)
CASE ( case-list )
statement (s)
.
.
.
CASE DEFAULT
statement(s)
END SELECT
- where:
-
case-list
- is a list of one or more cases separated by commas. A case is either
- (a)
- a single integer, logical or character constant expression or
(b)
- an integer, logical or character constant expression followed by a colon followed by another expression or the same type.
This form of a case defines a range of values consisting of all integers or characters greater than or equal to the
value of the expression preceding the colon and less than or equal to the value of the expression following the colon.
The SELECT construct, an extension to FORTRAN 77, is similar in concept to the FORTRAN computed GO TO
statement. It allows one of a number of blocks of code (case blocks) to be selected for execution by means of an integer
expression in the SELECT statement.
The SELECT statement keywords, CASE and FROM, are optional. The SELECT statement
may contain a block label (see the CYCLE, EXIT or QUIT statements for more information).
Each block must be started with a CASE statement; however, the last block may begin with a CASE DEFAULT
statement. The CASE DEFAULT block is optional. In order to retain compatibility with earlier versions
of WATCOM FORTRAN 77 compilers, the OTHERWISE statement may be used in place of the CASE DEFAULT statement.
The last block is ended by the END SELECT statement. The number of case blocks is optional, from one
to many; however, it is recommended that the SELECT construct not be used for fewer than 3 case blocks. The conditional
execution of one or two blocks of code is handled more efficiently by the IF-THEN-ELSE construct.
A particular case value or range of values must not be contained in more than one CASE-block. For example, the
following is illegal:
Example:
* Illegal SELECT block - case value in more
* than one CASE block.
SELECT CASE ( I - 3 )
CASE (1,3,7:10)
statement(s)
CASE (5,6,8)
statement(s)
CASE (-3:-2+4)
statement(s)
END SELECT
The second CASE-block includes 8 which is already handled by the first CASE-block. As well, the third CASE-block
handles cases -3, -2, -1, 0, 1, 2 but the first CASE-block also handles case 1. Thus the second and third CASE-ranges
are in error.
When the SELECT statement case expression is evaluated as i, the case block whose range contains
i is executed and control passes to the statement following the END SELECT statement. If no range contains
i, control is transferred to the statement following the CASE DEFAULT statement, if one is specified.
If the CASE DEFAULT block is omitted and the case expression is out of range when the SELECT statement
is executed (that is, none of the CASE-blocks handles the particular expression value), control is passed to the statement
following the END SELECT statement and none of the CASE-blocks is executed.
Example:
SELECT CASE ( I )
CASE (1)
Y = Y + X
X = X * 3.2
CASE (2)
Z = Y**2 + X
PRINT *, X, Y, Z
CASE (3)
Y = Y * 13. + X
X = X - 0.213
CASE (4)
Z = X**2 + Y**2 - 3.0
Y = Y + 1.5
X = X * 32.0
PRINT *, 'CASE 4', X, Y, Z
END SELECT
This example will execute in the manner described below for each of the possible values of variable I.
- (i)
- I is zero or negative:
- control will pass to the statement after the END SELECT statement
(ii)
- I = 1:
- the value of X will be added to Y
- X will be multiplied by 3.2
- control will pass to the statement after the END SELECT statement
(iii)
- I = 2:
- Z will be assigned the value of the expression Y**2 + X
- the values of X, Y and Z will be printed
- control will pass to the statement after the END SELECT statement
(iv)
- I = 3:
- Y will be assigned the value of the expression Y * 13. + X
- 0.213 will be subtracted from X
- control will pass to the statement after the END SELECT statement
(v)
- I = 4:
- Z, Y and X will be assigned new values
- the string CASE 4, followed by the values of X, Y and Z will be printed
- control will pass to the statement after the END SELECT statement
(vi)
- I = 5, 6, ...:
- control will pass to the statement after the END SELECT statement
CASE DEFAULT allows a block of code to be specified for execution when the SELECT expression is out
of range. It must follow all CASE-blocks and thus is ended by the END SELECT statement. The CASE
DEFAULT statement terminates the previous and last CASE-block. Note that only one CASE DEFAULT block
may be specified in a SELECT construct.
If a CASE DEFAULT block were included in the above example, it would be executed in cases (i) and (vi) of
the description. After a CASE DEFAULT block is executed, control then passes to the statement after the
END SELECT statement.
Empty or null case blocks are permitted (that is, two CASE statements with no statements between).
The net result of executing a null CASE-block is to effectively bypass the SELECT construct.
Example:
SELECT CASE ( I * 4 - J )
CASE (-10 : -5)
PRINT *,'First case:'
PRINT *,'-10 <= I*4-J <=
-5'
CASE (-4 : 2)
PRINT *,'Second case:'
PRINT *,'-4 <= I*4-J <=
2'
CASE (3, 5, 7)
PRINT *,'Third case:'
PRINT *,'I*4-J is one of 3, 5
or 7'
CASE (4, 6, 8:10)
PRINT *,'Fourth case:'
PRINT *,'I*4-J is one of 4, 6,
8, 9 or 10'
CASE DEFAULT
PRINT *,'All other cases:'
PRINT *,'I*4-J < -10 or I*4-J
> 10'
END SELECT
This example will execute in the manner described below for each of the possible values of expression I*4-J.
- (i)
- expression < -10
- control will pass to the statement after the CASE DEFAULT statement
- the string All other cases: will be printed
- the string I*4-J < -10 or I*4-J > 10 will be printed
(ii)
- -10 <= expression <= -5:
- control will pass to the statement after the first CASE statement
- the string First case: will be printed
- the string -10 <= I*J-4 <= -5 will be printed
- control will pass to the statement after the END SELECT statement
(iii)
- -4 <= expression <= 2:
- control will pass to the statement after the second CASE statement
- the string Second case: will be printed
- the string -4 <= I*J-4 <= 2 will be printed
- control will pass to the statement after the END SELECT statement
(iv)
- expression = 3, 5 or 7:
- control will pass to the statement after the third CASE statement
- the string Third case: will be printed
- the string I*J-4 is one of 3, 5 or 7 will be printed
- control will pass to the statement after the END SELECT statement
(v)
- expression = 4, 6, 8, 9 or 10:
- control will pass to the statement after the fourth CASE statement
- the string Fourth case: will be printed
- the string I*J-4 is one of 4, 6, 8, 9 or 10 will be printed.
- control will pass to the statement after the END SELECT statement
(vi)
- expression > 10:
- control will pass to the statement after the CASE DEFAULT statement
- the string All other cases: will be printed
- the string I*4-J < -10 or I*4-J > 10 will be printed
EXECUTE and REMOTE BLOCK
EXECUTE name
.
.
.
REMOTE BLOCK name
statement(s)
END BLOCK
- where:
-
name
- is a valid FORTRAN symbolic name.
The EXECUTE statement, an extension to FORTRAN 77, allows a named block of code to be executed. The named
block of code may be defined anywhere in the same program unit and is delimited by the REMOTE BLOCK and END
BLOCK statements. Executing a REMOTE-block is similar in concept to calling a subroutine, with the advantage that
shared variables do not need to be placed in a common block or passed in an argument list. In addition there is less
overhead involved in executing a REMOTE-block than in calling a subroutine (in both amount of object code and execution time).
When execution of the REMOTE-block is complete, control returns to the statement following the EXECUTE statement
which invoked it.
This feature is helpful in avoiding duplication of code for a function (such as I/O) required in a number of places
throughout a program. It can also be an aid to writing a well-structured program.
Each REMOTE-block within the same program unit must have a different name and it must not be a subprogram or variable
name. Note that a REMOTE-block is local to the program unit in which it is defined and may not be referenced (executed)
from another program unit.
REMOTE-blocks may be defined anywhere in the program unit except as follows.
- They must follow all specification statements.
- They must not be defined within a control structure.
If a REMOTE BLOCK statement is encountered during execution, control is transferred to the statement following
the corresponding END BLOCK statement.
Note that the nested definition of REMOTE-blocks is not permitted.
Example:
EXECUTE A
PRINT *, 'FIRST'
.
.
.
EXECUTE A
PRINT *, 'SECOND'
.
.
.
REMOTE BLOCK A
I = I + 1
PRINT *, 'I=', I
END BLOCK
Both EXECUTE statements will cause REMOTE-block A to be executed. That is, variable I
will be incremented and its value will be printed. When the block has been executed by the first EXECUTE statement,
control returns to the PRINT statement following it and the word FIRST is printed. Similarly, when
the block is executed by the second EXECUTE statement, control returns to the PRINT statement following
it and the word SECOND is printed.
REMOTE-blocks may be executed from other REMOTE-blocks. For example, REMOTE-block A might contain the
statement EXECUTE B, where B is a REMOTE-block defined elsewhere in the program unit. The execution
of REMOTE-blocks from other REMOTE-blocks may take place to any level; however, the recursive execution of REMOTE-blocks
is not permitted, either directly or through a chain of EXECUTE statements. Attempts to execute REMOTE-blocks
recursively are detected as errors at execution time.
GUESS-ADMIT-END GUESS
GUESS [: block-label]
statement(s)
ADMIT
statement(s)
ADMIT
statement(s)
.
.
.
ADMIT
statement(s)
END GUESS
The GUESS-ADMIT-END GUESS structure is a rejection mechanism which is useful when sets of statements are to be conditionally
chosen for execution, but not all of the conditions required to make a selection are available beforehand. It is an
extension to FORTRAN 77. The sets of statements to be chosen may be thought of as alternatives, the first alternative
being statements immediately after the GUESS statement. Execution begins with the statements in the first
alternative. If a condition is detected which indicates that the first alternative was the wrong choice, a QUIT
statement may be executed to cause control to be passed to the statements after the ADMIT statement (i.e., the second
alternative). A QUIT statement within the second alternative passes control to the third alternative, etc.
A QUIT statement within the last alternative passes control to the statement after the END GUESS
statement. If an alternative completes execution without encountering a QUIT statement (i.e., all statements
are executed up to the next ADMIT statement) then control is passed to the statement after the END GUESS
statement. An optional block label may be specified following the keyword GUESS (see the QUIT statement
for more information).
In the following example, two sets of codes and numbers are read in and some simple sequence checking is performed.
If a sequence error is detected an error message is printed and processing terminates; otherwise the numbers are processed
and another pair of numbers is read.
Example:
LOOP : PRLOOP
GUESS
LINE
= LINE + 1
READ
*, ICODE, X
AT END,
QUIT :PRLOOP
IF( ICODE
.NE. 1 )QUIT
LINE
= LINE + 1
READ
*, ICODE, Y
AT END,
QUIT
IF( ICODE
.NE. 2 )QUIT
PRINT
*, X, Y
CALL
PROCES(X, Y)
ADMIT
PRINT
*, 'INVALID SEQUENCE: LINE =', LINE
QUIT
:PRLOOP
END GUESS
END LOOP
The above example attempts to read a code and number. If an end of file occurs then the loop is terminated by
the QUIT statement.
If the code is not 1 then we did not get what we expected and an error situation has arisen. Control is passed
to the statement following the ADMIT statement. An error message is printed and the loop is terminated by
the QUIT statement.
If the code is 1 then a second code and number are read. If an end of file occurs then we are missing a set
of data and an error situation has arisen. Control is passed to the statement following the ADMIT statement.
An error message is printed and the loop is terminated by the QUIT statement. Similarly if the expected
code is not 2 an error situation has arisen. Control is passed to the statement following the ADMIT statement.
An error message is printed and the loop is terminated by the QUIT statement.
If the second code is 2, the values of variables X and Y are printed. A subroutine is then
called to process the data. Control resumes at the statement following the END GUESS statement. Since
this statement is an END LOOP, control is transferred to the beginning of the loop.
The above example illustrates the point that all the information required to make a choice (in this case between a
valid set of data and an invalid set) is not available from the beginning. In this case we make an assumption that
the data values are correct (our hypothesis) and then test the assumption at various points in the algorithm. If any
of the tests fail we reject the hypothesis (and, perhaps, select a new hypothesis).
It should be noted that no alternative selection need be coded (i.e., we need not use any ADMIT-blocks). This
is illustrated in the following example.
Example:
GUESS
X=SQRT( X )
IF( X .LT. EPS )QUIT
X=Y+SQRT(Y)
IF( X .LT. EPS )QUIT
CALL INTGRT( X, Y )
END GUESS
It might be noted that the IF-ELSE-END IF construct is simply a specific instance of the more general GUESS-ADMIT-END
GUESS construct wherein the data values are known beforehand (as could be illustrated using the previous example).
QUIT
QUIT [ : block-label]
The QUIT statement may be used to transfer control to the first executable statement following the terminal statement
of the block in which it is contained.
When transferring out of a loop, control is passed to the statement following the END DO, END WHILE,
END LOOP or UNTIL statement.
When transferring out of a GUESS block, control is passed to the statement after the next ADMIT or END
GUESS statement.
When transferring out of an IF-block or SELECT-block, control is passed to the statement after the corresponding
END IF or END SELECT statement.
When transferring out of a REMOTE-block, control passes to the statement following the EXECUTE statement
that invoked the REMOTE-block.
If no block label is specified in the QUIT statement, control is transferred from the immediately enclosing
structure. If several structures or DO-loops are nested, it is possible to exit from any one of them by specifying
the block label of the corresponding block structure.
The QUIT statement is most commonly used as the statement in a logical IF or AT END statement
but may also be used to cause an unconditional transfer of control. (The AT END statement is described in
a subsequent section).
Examples of the QUIT statement with and without a block label follow.
Example:
CHARACTER CH
READ *, CH
GUESS
IF( CH .LT. 'a' )QUIT
IF( CH .GT. 'z' )QUIT
PRINT *, 'Lower case letter'
ADMIT
IF( CH .LT. 'A' )QUIT
IF( CH .GT. 'Z' )QUIT
PRINT *, 'Upper case letter'
ADMIT
IF( CH .LT. '0' )QUIT
IF( CH .GT. '9' )QUIT
PRINT *, 'Digit'
ADMIT
PRINT *, 'Special character'
END GUESS
END
The above statements read and print values until an end of file occurs. At that point control is passed to the
QUIT statement, as specified by the AT END statement. The QUIT statement causes control to continue
with the statement after the END LOOP statement.
Example:
CHARACTER RECORD(80)
LOOP : RDREC
READ(5,100) RECORD
AT END, STOP
DO I = 1, 80
IF( RECORD(I)
.LT. '0'
+
.OR. RECORD(I) .GT. '9' )QUIT : RDREC
END DO
WRITE(6,101) RECORD
END LOOP
PRINT *, 'INVALID RECORD'
The above example reads in records and verifies that they contain only numeric data. The QUIT statement
is within two levels of nesting: the DO-loop and the LOOP-END LOOP structure. If a non-numeric character is found,
the QUIT : RDREC statement will cause control to be passed to the PRINT statement after the END
LOOP statement.
EXIT
EXIT [ : block-label]
The EXIT statement is used to transfer control:
- from within a loop (DO, DO WHILE, WHILE or LOOP) to the statement following the loop,
- from within a GUESS or ADMIT block to the statement following the ENDGUESS statement, or
- from within a remote block to the statement following the EXECUTE statement that invoked the remote block.
When transferring out of a loop, control is passed to the statement following the END DO, END WHILE,
END LOOP or UNTIL statement.
When transferring out of a GUESS block, control is passed to the statement after the corresponding END GUESS
statement.
When transferring out of a REMOTE-block, control passes to the statement following the EXECUTE statement
that invoked the REMOTE-block.
If no block label is specified in the EXIT statement, control is transferred from the immediately enclosing
structure. If several structures or DO-loops are nested, it is possible to exit from any one of them by specifying
the block label of the corresponding block structure.
The EXIT statement is most commonly used as the statement in a logical IF or AT END statement
but may also be used to cause an unconditional transfer of control. (The AT END statement is described in
a subsequent section).
Examples of the EXIT statement with and without a block label follow.
Example:
LOOP
READ *, X
AT END, EXIT
PRINT *, X
END LOOP
The above statements read and print values until an end of file occurs. At that point control is passed to the
EXIT statement, as specified by the AT END statement. The EXIT statement causes control to continue
with the statement after the END LOOP statement.
Example:
CHARACTER RECORD(80)
LOOP : RDREC
READ(5,100) RECORD
AT END, STOP
DO I = 1, 80
IF( RECORD(I)
.LT. '0'
+
.OR. RECORD(I) .GT. '9' )EXIT : RDREC
END DO
WRITE(6,101) RECORD
END LOOP
PRINT *, 'INVALID RECORD'
The above example reads in records and verifies that they contain only numeric data. The EXIT statement
is within two levels of nesting: the DO-loop and the LOOP-END LOOP structure. If a non-numeric character is found,
the EXIT : RDREC statement will cause control to be passed to the PRINT statement after the END
LOOP statement.
CYCLE
CYCLE [ : block-label]
The CYCLE statement is used to cause a transfer of control from within a loop to the terminal statement of a
corresponding DO, DO WHILE, WHILE or LOOP statement. If block-label is
present then control is transferred to the terminal statement of the block identified by that block label.
If no block label is specified in the CYCLE statement, control is transferred to the terminal statement of
the immediately enclosing loop structure. If several loop structures are nested, it is possible to cycle to the terminal
statement of any one of them by specifying the block label of the corresponding block structure.
The CYCLE statement is most commonly used as the statement in a logical IF statement but may also
be used to cause an unconditional transfer of control.
Examples of the CYCLE statement with and without a block label follow.
Example:
LOOP
WRITE( UNIT=*, FMT='(A)' ) 'Enter
a number'
READ( UNIT=*, FMT='(F10.4)',
IOSTAT=IOS ) X
IF( IOS .NE. 0 ) CYCLE
IF( X .LT. 0 ) EXIT
PRINT *, X, SQRT( X )
END LOOP
The above statements read and print values until a negative integer value is entered. If an input error occurs,
the input operation (READ) is retried using the CYCLE statement. The CYCLE statement causes control
to resume at the END LOOP statement which then immediately transfers control to the statement following the
LOOP statement.
Example:
CHARACTER RECORD(80)
LOOP : RDREC
READ(5,100) RECORD
AT END, STOP
DO I = 1, 80
IF( RECORD(I)
.LT. '0'
+
.OR. RECORD(I) .GT. '9' )THEN
PRINT *, 'INVALID RECORD'
CYCLE : RDREC
ENDIF
END DO
WRITE(6,101) RECORD
END LOOP
The above example reads in records and verifies that they contain only numeric data. If the record does not,
the input operation is tried again. The CYCLE statement is within three levels of nesting: the IF, the
DO-loop, and the LOOP-END LOOP structure. If a non-numeric character is found, the CYCLE : RDREC statement
will cause control to be passed to the READ statement that follows the LOOP statement.
AT END
(READ statement)
AT END DO [: block-label ]
statement(s)
END AT END
or
(READ statement)
AT END, statement
The AT END control statement, an extension to FORTRAN 77, is an extension of the END= option of the
FORTRAN READ statement for sequential files. It allows a statement or a block of code following the READ
statement to be executed when an end of file condition is encountered during the READ and to be by-passed immediately
following a READ statement. It is not valid to use this control statement with direct-access or memory-to-memory
reads. Clearly, it is not valid to use this statement when END= is specified in the READ statement.
Example:
READ(7, *) I, X
AT END DO
PRINT *, 'END-OF-FILE ENCOUNTERED'
EOFSW = .TRUE.
END AT END
If the READ statement is executed without encountering end of file, control passes to the statement following
the END AT END statement. If an end of file condition occurs during the read, the string, END-OF-FILE
ENCOUNTERED is printed, logical variable EOFSW is assigned the value .TRUE. and control passes
to the statement following the END AT END statement.
Example:
READ(7, *) X
AT END, EOFSW = .TRUE.
If an end of file is not encountered by the READ statement, control passes to the statement following the
AT END statement. If an end-of-file condition occurs, variable EOFSW is set to .TRUE.
and control then passes to the statement following the AT END statement. Note that the use of the second form
of the AT END statement requires the use of a comma (,) between the AT END word and the executable statement.
This is necessary to distinguish the case where the executable statement is an assignment statement. The executable
statement may be any statement that is also allowed as the operand of a logical IF statement.
Notes on Structured Programming Statements
In addition to the definitions and examples of these constructs, the following points should be noted:
- (i)
- Any of the new control statements with their blocks may be used within the block of any other statement. For example,
a WHILE-block may contain another WHILE or an IF-THEN-ELSE block. Blocks may be nested in this manner to any level
within storage limitations. An important exception to this rule is the REMOTE-block A REMOTE-block may contain other
types of blocks (nested to any level); however, another REMOTE-block may not be defined within it. Furthermore, REMOTE-blocks
may not be defined within another control structure. The following example is illegal.
Example:
* Illegal definition of a REMOTE-block.
IF( I .EQ. 3 )then
REMOTE BLOCK A
.
.
.
END BLOCK
END IF
(ii)
- When nesting blocks, the inner blocks must always be completed with the appropriate block-terminating END statement
before the outer blocks are terminated. Similarly, when nesting blocks with DO-loops, a DO-loop started within a block
must be completed before the block is completed. A block started within a DO-loop must be terminated before the DO-loop
is completed. Indenting the statements of each new block, as shown in the examples, is helpful in avoiding invalid
nesting and helps to make the structure of the program visually obvious.
(iii)
- The normal flow of control of the new programming constructs described earlier may be altered with standard FORTRAN control
statements. For example, the program may exit from a block using a GO TO, STOP, RETURN or
arithmetic IF statement. However, a block may not be entered in the middle through use of any control statement
such as GO TO or the arithmetic IF.
Consider the following example.
Example:
GO TO 20
10 IF( X .GT. Y )THEN
CALL REDUCE( X, Y )
20 X = X - 1
ELSE
CALL SCALE( X )
END IF
This is an example of an illegal attempt to transfer execution into the middle of an IF-block. The statement
X = X - 1 is contained within the IF-block and may only be transferred to from within the block.
Example:
IF( X .GT. Y )THEN
20 CALL REDUCE( X, Y )
X = X - 1
IF( X .GT. 0 )GO TO 20
ELSE
CALL SCALE( X )
END IF
This last example demonstrates a legal transfer of control within an IF-block. However, we have seen better
ways to express the loop with this IF-block.
Example:
IF( X .GT. Y )THEN
LOOP
CALL
REDUCE( X, Y )
X = X
- 1
UNTIL( X .LE. 0 )
ELSE
CALL SCALE( X )
END IF
(iv)
- Many control structure statements cannot be branched to using a GO TO statement. For a list of these statements,
see the section entitled Classifying Statements in the chapter entitled FORTRAN Statements.
(v)
- Many control structure statements cannot be the object statement of a logical IF statement, or be the last statement
of a DO-loop. For a list of these statements, see the section entitled Classifying Statements
in the chapter entitled FORTRAN Statements.
FORTRAN 77 provides a means of communicating information or data between a FORTRAN program and the computing environment.
The computing environment may include a number of devices which are capable of the recording, retrieval, display, and
input of data. Disk and magnetic tape devices are capable of storing large amounts of data. Other devices such
as printers and display terminals can be used to present a visual (i.e., human-readable) representation of the data.
Yet other devices such as terminal keyboards and card-readers make possible the entry of new data into the computing environment.
For the purposes of our discussion, data is any information which can be processed by an executing FORTRAN program.
Some examples of data are names, addresses, telephone numbers, credit card balances, flight trajectories, bus schedules,
athletic records, etc. In computing, such information is usually well-organized in order to make it useful for processing.
To use an example, consider the entries in a telephone book. There are essentially three pieces of data listed
for each entry; a name, an address, and a number.
Smith J 32 Arthur St--------------------------555-3208
Smith JW 512 King St--------------------------555-9229
Smith Jack 255-113 Queen St N-----------------555-0572
Each entry is a record. The organization of the book is clear. The name is always listed first,
the address second, and the number last. The records are sorted, for our convenience, by name (within each city
or geographical location). The length of each record is the same. This fixed length does sometimes lead
to problems since entries which have a long name or address won't fit in a record. The phone company solved this by
continuing the information in subsequent records. We might have solved this problem by increasing the length of a record
with the disadvantage of wasting a lot of printing space. Alternatively, we could have used a variable length
record. This solves the problem of wasted space but creates a severe problem when trying to display the records in
nice orderly columns. The telephone book itself is a collection of records or a file.
We have introduced much of the terminology of data processing: "data", "records", "fixed
and variable record sizes", "files", "sorted", etc.
Reading and Writing
FORTRAN provides a mechanism called "reading" for transferring data into the environment of an executing program.
The READ statement is used to do this. Similarly "writing" is the mechanism for transferring
data out of an executing program. The WRITE and PRINT statements are used to do this. Other
statements provide additional functions such as positioning to a certain record in a file, establishing which files are to
be processed by the program, or making inquiries about files.
Records
FORTRAN distinguishes between three kinds of records, namely:
- Formatted
- Unformatted
- Endfile
We shall describe each of these in the following sections.
A formatted record consists of characters. The length of a formatted record is determined by the number of characters
in it. A formatted record may contain no characters at all and thus has zero length. Formatted records are read
or written using formatted input/output statements. An excellent example of a file consisting of formatted records
is our telephone book example.
An unformatted record consists of values such as integers, real numbers, complex numbers, etc. It may also consist
of characters. Essentially, these values have the same representation in a record as they have in the computer's memory.
The length of an unformatted record depends on the amount of storage required to represent these values in the computer's
memory. For example, on this computer an integer value is stored using 4 bytes of memory (a byte is a grouping of 8
binary digits). Thus, integer values in unformatted records also require 4 bytes of storage. For example, 3 integer
values stored in an unformatted record would require 12 bytes of storage. Unformatted records are read or written using
unformatted input/output statements.
To illustrate the difference between a formatted and unformatted record consider the following example.
Example:
INTEGER NUMBER
NUMBER=12345
PRINT 100, NUMBER
100 FORMAT(1X,I5)
WRITE( UNIT=7 ) NUMBER
If you print the variable NUMBER on a printer, it requires 5 character positions. If you write it to
a file using an unformatted WRITE statement, it only requires 4 bytes or character positions in the record.
Note that a character is conveniently represented in one byte of storage, hence we sometimes use the term "byte"
or "character" interchangeably when talking about the size of variables.
Endfile Record
An endfile record is a special record that follows all other records in a file. Simply stated, an endfile record
occurs at the end of a file. Actually, an endfile record is a conceptual thing. It has no length. When
the end of a file is reached (i.e., an attempt to read a record results in the endfile record being read), an "end-of-file"
condition exists. There are no more records following the endfile record. There is only one endfile record so
it is strictly illegal to attempt to read another record after the endfile record has been read (i.e., when the end-of-file
condition exists).
Files
Earlier we described the notion of a file as a collection of records. In FORTRAN, there are two kinds of files:
- External
- Internal
External Files
External files are files that exist or can be created upon external media such as disks, printers, terminal displays,
etc. A file may exist before the execution of a FORTRAN program. It may be brought into existence or "created"
during execution. It may also be deleted and therefore not exist after the execution of a FORTRAN program.
All input/output statements may refer to files that exist. In addition, the INQUIRE, OPEN,
CLOSE, WRITE, PRINT, and ENDFILE statements may refer to files that do not exist (and in
so doing, may very well cause the file to be created).
- Properties of External Files
-
Name
- In FORTRAN, a file may or may not have a name. If it does have a name then, not surprisingly, it is called a named
file. All files in Open Watcom FORTRAN 77 have names and so it may seem odd to introduce this notion. However,
we do since the INQUIRE statement lets you find out if a file is named and, if so, what its name is. File
naming conventions may differ from one computing system to the next. As well, different FORTRAN 77 compilers may have
different file naming conventions.
Access
- "Access" simply refers to the way in which we can position to and read or write the data in a particular record
in a file. There are two ways in which records can be accessed in a file; sequentially or directly.
Using the sequential access method, records may be read or written in order starting with the first record and
proceeding to the last record. For example, it would be quite impossible to read or write the tenth record in a file
and then read or write the third record. Similarly the eleventh record must be read or written before we can access
the twelfth record. If we adopt the convention that each record in a file has a record number then the first record
is record number 1, the second is 2, and so on. This numbering convention is important when we look at the other access
method which is "direct".
Using the direct access method, records may be read or written in any order. It is possible to read or
write the tenth record of a file and then the third and then the twelfth and so on. A caveat: a record cannot
be read if it has never been written since the file was created. In direct access, the idea of a record number is very
important and so by convention, we number them starting at 1 as the first record and proceeding on up. With direct
access, if you create a new file and write record number 10 then the file has ten records regardless of the fact that only
one has been written. You could, at some later time, write records 1 through 9 (in whatever order you please) and add
additional records by writing records with record numbers greater than 10.
Some files have the property of being able to sustain both of these access methods. Some files may only have
one of these properties. For example, most line printers cannot be accessed directly. You have no choice but
to write records sequentially. Sometimes a file that was created using the sequential access method may not be accessed
using the direct method or vice versa. FORTRAN calls this property of a file the "set of allowed access methods".
Record Form
- Some files have the property of being able to handle both formatted and unformatted record formats. Some files may only
have one of these properties. For example, if you tried to write unformatted records to a line printer, the result
might be gibberish. On the other hand a graphics printer may readily accept unformatted records for reproducing graphical
images on paper. FORTRAN calls this property of a file the "set of allowed forms".
Record Length
- Another property of a file is record length. Some files may have restrictions on the length of a record. Some
files do not allow records of zero length. Other files, such as printers, may restrict the length of a record to some
maximum. FORTRAN calls this property the "set of allowed record lengths".
Internal Files
Internal files are special files that reside only in memory. They do not exist before or after the execution of
a FORTRAN program, only during the execution of a program. An internal file allows you to treat memory in the computer
as if it were one or more records in a file. The file must be a character variable, character array element, character
array, or character substring. A record in this file may be a character variable, character array element or character
substring.
Another way of looking at this is that an internal file that is either a character variable, character array element
or character substring can contain only one record but an internal file that is a character array can contain several records
(as many as there are elements in the array).
- Properties of Internal Files
-
Records
- Unless the name of a character array is used, only one record is contained in an internal file. The length of this record
is the same as the length of the variable, array element, or substring. If the file is a character array then each
element in the array is a record. The order of the records in the file is the same as the order of the elements in
the array. The length of a record in this case is the same as the length of the character array elements.
If the number of characters written to a record in an internal file is less than the length of the record then the record
is padded with blanks.
Definition
- A record may be read only if the variable, array element, or substring is defined (i.e., it has been assigned some value).
Definition may not only result from an output statement such as WRITE. It may also be defined through
other means; for example, a character assignment statement.
Position
- For all input/output statements, the file is positioned at the beginning of the first record. Multiple records may be
read or written using the "slash" format edit descriptor (see the chapter entitled Format).
Restrictions
- Only sequential access formatted input and output statements ( READ and WRITE) may be used to transfer data
to and from records in an internal file.
Although FORTRAN 77 states that list-directed formatted input/output to an internal file is not permitted, Open Watcom
FORTRAN 77 allows you to use list-directed formatted input/output statements. This is an extension to the language
standard.
Example:
WRITE(INTFIL,*) X, Y, Z
No other input/output statements ( OPEN, ENDFILE, REWIND, etc.) may be used.
Internal files may be used to convert data from one format to another. The following example illustrates one use
of internal files.
Example:
CHARACTER*11 INPUT
PRINT *, 'TYPE IN ''I'' FOLLOWED BY AN INTEGER'
PRINT *, 'OR TYPE IN ''R'' FOLLOWED BY A REAL'
READ 100, INPUT
100 FORMAT( A11 )
IF( INPUT(1:1) .EQ. 'I' )THEN
READ( UNIT=INPUT(2:11), FMT='(I10)'
) IVAR
PRINT *, 'AN INTEGER WAS ENTERED
', IVAR
ELSE IF( INPUT(1:1) .EQ. 'R' )THEN
READ( UNIT=INPUT(2:11), FMT='(F10.3)'
) RVAR
PRINT *, 'A REAL NUMBER WAS ENTERED
', RVAR
END IF
END
After checking for an "I" or "R" as the first character of the character variable
INPUT, the appropriate internal READ statement is executed.
Units
Many FORTRAN 77 input/output statements refer to external files using a mechanism called the unit. There
are many units available to the FORTRAN 77 programmer. Open Watcom FORTRAN 77 numbers these units from 0 to 999; thus
the unit number is a non-negative integer less than 1000.
A unit may be associated with a particular file. This association is called connection. Any unit
may or may not be connected to a file. There are a number of ways in which this connection may be established.
A unit may be preconnected to a file before execution of a program begins. The User's Guide describes
the mechanism for preconnecting a unit to a file.
Alternatively, a unit may become connected to a file by the execution of an OPEN statement.
All input/output statements except OPEN, CLOSE, and INQUIRE must refer to a unit that is
connected to a file. Open Watcom FORTRAN 77 automatically establishes a connection of the unit to a file if no connection
previously existed. Consider the following example in which unit number 1 is not previously connected to a file.
Example:
WRITE(1,*) 'Output on unit 1'
END
Open Watcom FORTRAN 77 constructs a file name using the specified unit number. The format of the file name is
described in the User's Guide since it varies from one computer system to the next.
Connection of a unit to a file does not imply that the file must exist. For example, it could be a new file.
When we speak of a unit being connected to a file, we can also say that a file is connected to a unit. Under
the rules of FORTRAN, it is illegal to connect the same file to more than one unit at the same time. However,
a file may be connected to different units at different times. We shall explain how this is possible.
A file may be disconnected from a unit by the use of the CLOSE statement.
Example:
CLOSE(UNIT=1)
Under certain circumstances, the file may be disconnected from a unit by the use of the OPEN statement.
Example:
OPEN(UNIT=1,FILE='FILE1')
.
.
.
OPEN(UNIT=1,FILE='FILE2')
In the above example, the second OPEN statement disconnects unit 1 from one file and connects it to a second
file. You may think of the second OPEN statement as automatically closing the first file and then establishing
a connection to the second file.
If a unit has been disconnected from a file through the execution of a CLOSE statement, the unit may subsequently
be connected to the same file or to a different file. It also follows that a file which has been disconnected from
one unit number may be connected to the same unit number or a different unit number. The following example may help
to illustrate this last point.
Example:
OPEN(UNIT=1,FILE='FILE1')
.
.
.
CLOSE(UNIT=1)
OPEN(UNIT=2,FILE='FILE1')
Once a file has been disconnected, the only means for referring to the file is by its name in an OPEN statement
or an INQUIRE statement.
Specifiers
All input/output statements contain one or more specifiers. They appear in a list separated by commas. Some
of the more common specifiers are those listed below. Not all of them need be used in every input/output statement.
You should consult the description of the input/output statement under consideration to discover which specifiers are
allowed and what they mean.
- [UNIT =] u
- the unit specifier
[FMT =] f
- the format specifier
REC = rn
- the record specifier
IOSTAT = ios
- the input/output status specifier
ERR = s
- the error specifier
END = s
- the end-of-file specifier
We shall look at these specifiers in more detail.
The Unit Specifier
The form of a unit specifier in an input/output statement is:
- [UNIT =] u
- u is an external unit identifier or an internal file identifier.
- An external unit identifier is a non-negative integer expression or an asterisk (*) in which case unit 5 is assumed
for an input statement and unit 6 is assumed for an output statement. The unit identifier must not be an asterisk for
the BACKSPACE, ENDFILE and REWIND statements.
- An internal file identifier is the name of a character variable, character array, character array element, or character
substring.
If the optional UNIT= specifier is omitted then the unit specifier must be the first item in the list of specifiers.
The form of a format specifier in an input/output statement is:
- [FMT =] f
- f is a format identifier. A format identifier is one of the following:
- A statement label of a FORMAT statement that appears in the same program unit as the format identifier.
- An integer variable name that has been assigned the statement label of a FORMAT statement that appears in the
same program unit as the format identifier (see the ASSIGN statement).
- An integer array name.
- A character array name.
- Any character expression except one involving the concatenation of an operand whose length specification is (*)
unless the operand is a symbolic constant (see the PARAMETER statement).
- An asterisk (*), indicating list-directed formatting.
- A NAMELIST name, indicating namelist-directed formatting.
If the optional FMT= specifier is omitted then the format specifier must be the second item in the list of specifiers
and UNIT= must not be specified for the first item in the list.
Record Specifier
The form of a record specifier in an input/output statement is:
- REC = rn
- rn is an integer expression whose value must be positive. It is the number of the record to be read when a
file is connected for direct access.
The form of an input/output status specifier in an input/output statement is:
- IOSTAT = ios
- ios is an integer variable or integer array element. It is defined with zero if no error occurs, a positive
integer value if an error occurs, or a negative integer value if an end-of-file occurs.
If an input/output error or end-of-file condition occurs during the execution of an input/output statement and the input/output
status specifier is present then execution of the program is not terminated. Input/output errors may result from a
violation of the rules of FORTRAN or from a file system error. For example, a negative unit number will result in an
error since this is a violation of the rules of FORTRAN. An example of a file system error might be an attempt to create
a file on a non-existent file storage device.
Consult the User's Guide for a list of Open Watcom FORTRAN 77 diagnostic messages. An input/output status of
nn corresponds to the message IO-nn. For example, if the status returned is 3 then the error is:
IO-03 ENDFILE statement requires sequential access mode
Error Specifier
The form of an error specifier in an input/output statement is:
- ERR = s
- s is a statement label. When an error occurs, execution is transferred to the statement labelled by s.
If an input/output error occurs during the execution of an input/output statement and the ERR= specifier is present
then execution of the program is not terminated.
End-of-File Specifier
The form of an end-of-file specifier in an input/output statement is:
- END = s
- s is a statement label. When an end-of-file condition occurs, execution is transferred to the statement labelled
by s.
If an end-of-file condition occurs during the execution of an input/output statement and the END= specifier is
present then execution of the program is not terminated.
Printing occurs when formatted records are transferred to a device which interprets the first character of the
record as a special spacing command. The remaining characters in the record are "printed". Printing
can be accomplished by use of either the PRINT statement or the WRITE statement. What actually determines
whether or not you are "printing" is the device (or file) to which records are transferred.
The first character of the record controls the vertical spacing. This feature is quite often called ASA (American
Standards Association) carriage control.
Character Vertical Spacing Before Printing
Blank One Line
0 Two
Lines
- Three
Lines
1 To First
Line of Next Page
+ No Advance
The "-" control character is an extension to the FORTRAN 77 language that is supported by many "printing"
devices.
A format specification used in conjunction with formatted I/O provides a means of specifying the way internal data
is converted to a character string and vice versa. A format specification can be given in two ways.
- In a FORMAT statement.
- As values of character expressions or character arrays.
The form of a FORMAT statement is
label FORMAT fs
- where:
-
label
- is the statement label used by an I/O statement to identify the FORMAT statement.
fs
- is a format specification which will be described later.
Example:
REAL X
X = 234.43
PRINT 100, X
100 FORMAT(F10.2)
END
In the previous example, the PRINT statement uses the format specification in the FORMAT statement
whose statement label is 100 to display the value of X.
Instead of specifying the statement label of a FORMAT statement, a character expression can be used. The
previous example could be modified as follows and achieve the identical result.
Example:
REAL X
X = 234.43
PRINT '(F10.2)', X
END
When using a character expression to represent a format specification, the format specification can be preceded by
blank characters and followed by any character data without affecting the format specification. The following example
produces the identical result to the previous example.
Example:
REAL X
X = 234.43
PRINT ' (F10.2) THIS IS FOR X', X
END
If a character array is used to describe the format specification, the format specification is considered to be the
concatenation of all the character array elements in the order given by array element ordering described in the chapter entitled
Arrays. Note that if a character array element is used, the format specification is considered
to be only that array element.
Example:
REAL X
CHARACTER*5 FMTSPEC(3)
X = 234.43
FMTSPEC(1)='('
FMTSPEC(2)='F10.2'
FMTSPEC(3)=')'
PRINT FMTSPEC, X
END
A format specification has the following form.
( [flist] )
- where:
-
flist
- is a list whose items are separated by commas. The forms of the items in flist are:
[r] ed
ned
[r] fs
ed
- is a repeatable edit descriptor.
ned
- is a nonrepeatable edit descriptor.
fs
- is a format specification with a nonempty list flist.
r
- is a positive unsigned integer constant called a repeat specification.
The comma separating the items of flist can be omitted in the following cases.
- Between a P edit descriptor and an F, E, D or G edit descriptor which immediately
follows.
- Before or after a slash edit descriptor.
- Before or after a colon edit descriptor.
Open Watcom FORTRAN 77 allows the omission of a comma between the items of flist. Care should be taken
when omitting commas between edit descriptors. For example, the format specification (I5 2I3) may appear to
be an I5 edit descriptor followed by two I3 edit descriptors when in actuality it is interpreted as an
I52 edit descriptor followed by an I3 edit descriptor.
Repeatable Edit Descriptors
The forms of repeatable edit descriptors are:
Iw
Iw.m
Fw.d
Ew.d
Ew.dEe
Dw.d
Gw.d
Gw.dEe
Lw
A
Aw
As an extension to the FORTRAN 77 language, the following repeatable edit descriptors are also supported.
Ew.dDe
Zw
- where:
-
- I, F, E, D, G, L, A and Z indicate the method of
editing.
w and e are positive unsigned integer constants.
d and m are unsigned integer constants.
Nonrepeatable Edit Descriptors
The forms of nonrepeatable edit descriptors are:
'hh...h' (apostrophe)
nHhh...h
Tc
TLc
TRc
nX
/
:
S
SP
SS
kP
BN
BZ
X
As an extension to the FORTRAN 77 language, the following nonrepeatable edit descriptors are also supported.
$
\
- where:
-
- Apostrophe, H, T, TL, TR, X, /, :, S, SP,
SS, P, BN, BZ, \ and $ indicate the method of editing.
h is a character.
n and c are positive unsigned integer constants.
k is an optionally signed integer constant.
Open Watcom FORTRAN 77 allows edit descriptors to be specified using lower case letters.
Editing
Edit descriptors are used to describe the way the editing between internal representation of data and the characters of
a record in a file is to take place. When the edit descriptors I, F, E, D,
G, L, A, H, Z or apostrophe are processed, they process a sequence of characters
called a field. On input, the field is the character data read from a record; on output it is the character
data written to a record. The number of characters in a field is called the field width.
Apostrophe Editing
The apostrophe edit descriptor has the same form as a character constant and can only be used on output.
It causes the characters in the format specification enclosed in quotes to be written. The field width is the number
of characters enclosed in quotes.
Example:
PRINT '(''HI THERE'')'
END
In the previous example, the string
HI THERE
would be the output produced by the PRINT statement.
H Editing
The nH edit descriptor causes the n characters following the H, including blanks, to be written.
Like the apostrophe edit descriptor, it can only appear in a format specification used for output.
Example:
PRINT '(8HHI THERE)'
END
In the previous example, the string
HI THERE
would be the output produced by the PRINT statement.
Positional Editing: T, TL, TR and X Editing
The T, TL, TR and X edit descriptors specify at which position the next character
will be read from or written to the record. In the case of input, this allows data to be read more than once with different
edit descriptors. On output, it is possible to overwrite data previously written.
On output it is possible to use positional editing to create a record in which gaps appear. That is, there may
be parts of the record where no data has been written. The parts of a record in which no data has been written are
filled with blanks. The effect is as if the record was previously initialized to blanks. Note that positioning
does not cause any data to be transmitted.
The Tc edit descriptor specifies that the next character to be transmitted is to be from the cth
character position in the record. The TLc edit descriptor specifies that the next character to be transmitted
is to be from the cth position backward from the current position. The TRc edit descriptor is identical
to the TLc edit descriptor except that positioning is forward from the current position. The nX edit
descriptor behaves identically to the TRc edit descriptor; the transmission of the next character is n
character positions forward from the current position. If n is omitted then the transmission of the next character
is 1 character position forward from the current position.
Example:
PRINT '(''THE NUMBER
IS AN INTEGER'',TL19,
$ ''12345'')'
END
The output produced is
THE NUMBER 12345 IS AN INTEGER
Slash Editing
The slash edit descriptor indicates the end of data transfer on the current record. On input from a record
connected for sequential access, the remaining characters in the record are skipped and the file is positioned to the start
of the next record. Note that entire records may be skipped. On output, a new record is created and becomes the
last and current record of the file. Note that a record with no characters can be written. If the file is an
internal file or a direct access file, the record is filled with blanks.
For a file connected for direct access, the current record number is increased by one and the file is positioned at
the beginning of that record.
Colon Editing
The colon edit descriptor terminates processing of the format specification if there are no more items in the I/O
list. If there are items remaining in the I/O list, the colon edit descriptor has no effect.
S, SP and SS Editing
The S, SP and SS edit descriptors control optional plus characters in numeric output fields.
They only effect the I, F, E, D and G edit descriptors during output and
have no effect on input. The FORTRAN 77 standard specifies that before processing a format specification, the appearance
of a plus sign in numeric output fields is optional and is determined by the processor. Open Watcom FORTRAN 77 does
not produce plus signs in numeric output fields. When an SP edit descriptor is encountered, a plus sign is
produced in any subsequent position that optionally contains a plus sign. When as SS edit descriptor is encountered,
a plus sign is not produced in any subsequent position that optionally contains a plus sign. If an S edit
descriptor is encountered, the option is returned to the processor.
Example:
PRINT '(1H<,I5,SP,I5,SS,I5,1H>)',1,2,3
END
The output produced by the PRINT statement in the previous example is:
< 1 +2 3>
P Editing
The form of a P edit descriptor is kP where k is an optionally signed integer constant called
the scale factor. The value of the scale factor is zero at the beginning of each I/O statement. The scale
factor applies to all subsequent F, E, D and G edit descriptors until another scale factor
is encountered. The scale factor affects editing in the following way.
- On input with F, E, D and G editing, provided that no exponent exists in the field,
the effect is that the represented number equals the internally represented number multiplied by 10**k.
- On input with F, E, D and G editing, the scale factor has no effect if there is an
exponent in the field.
- On F output editing, the effect is that the represented number equals the internally represented number multiplied
by 10**k.
- On output with E and D editing, the simple real constant (see the chapter entitled Names, Data Types and Constants)
part of the data is multiplied by 10**k and the exponent is reduced by k.
- On output with G editing, the scale factor has no effect unless the magnitude of the datum is outside the range
that allows F editing (see the section entitled G Editing). If E editing
is required, the scale factor has the same effect as with E output editing.
BN and BZ Editing
The BN and BZ edit descriptors are used to describe the interpretation of embedded blanks in numeric
input fields. They only effect I, F, E, D and G editing and have no effect
during output. When a BN edit descriptor is encountered in a format specification, embedded blanks in subsequent
numeric input fields are ignored. However, a field of all blanks has the value of zero. If a BZ edit
descriptor is encountered, then all embedded blanks in subsequent numeric input fields are treated as zeroes. At the
beginning of each I/O statement, all blanks are treated as zeroes or ignored depending on the value of the BLANK=
specifier (see the OPEN statement) currently in effect for the unit.
$ or \ Editing (Extension)
The $ and \ edit descriptors behave identically. The $ and \ edit descriptors are intended for output to an interactive
device such as a terminal. They are a Open Watcom FORTRAN 77 extensions. The output record is displayed at the
terminal leaving the cursor at the end of the record; the carriage return at the end of the line is suppressed. Its
use is intended for prompting for input so that the response can be entered immediately following the prompt.
Depending on the type of terminal, the prompt may be returned as part of the input. An application must be aware
of the way a particular terminal behaves. The following example demonstrates this. Note that the format specification
in the FORMAT statement labelled 20 ignores the first eleven characters of the response since the prompt
also appears in the response.
Example:
INTEGER AGE
WRITE(6,FMT=10)
10 FORMAT( 'Enter age: ',$ )
READ(5,20) AGE
20 FORMAT( 11X, I2 )
PRINT *,'Your age is ',AGE
END
If the terminal you are using does not return the prompt as part of the response (that is, a read from the terminal
only includes characters typed at the terminal), the format specification in the FORMAT statement labelled 20
must be changed, as in the following example, to achieve the same result.
Example:
INTEGER AGE
WRITE(6,FMT=10)
10 FORMAT( 'Enter age: ',\/ )
READ(5,20) AGE
20 FORMAT( I2 )
PRINT *,'Your age is ',AGE
END
Numeric Editing: I, F, E, D and G Edit Descriptors
Numeric edit descriptors are used to specify I/O of integer, real, double precision, complex and double precision complex
data. The following rules apply to all numeric edit descriptors.
- On input, leading blanks are not significant. The interpretation of blanks other than leading blanks is determined
by any BN or BZ edit descriptors in effect and the BLANK= specifier (see the OPEN statement).
A field of all blanks is always zero. Plus signs are optional.
- On input, with F, E, D and G editing, the decimal location specified in the edit descriptor
is overridden by a decimal point appearing in the input field.
- On output, the plus sign is optional and is determined by the S, SP and SS edit descriptors.
A negative quantity is represented by a negative sign. A minus sign is never produced when outputting a value
of zero.
- On output, the representation is always right justified in the field with leading blanks inserted at the beginning of
the field if the number of characters in the representation is less than the field width.
- On output, if the number of characters in the external representation is greater than the field width or an exponent exceeds
its specified length using Ew.dEe, Gw.dEe, Ew.dDe or Gw.dDe edit descriptors, the entire
field is filled with asterisks.
Integer Editing: Iw and Iw.m Edit Descriptors
The Iw and Iw.m edit descriptors indicate that the field width of the field to be edited is w.
The item in the I/O list must be of type integer; on input the I/O list item will be defined by integer data, on output
the I/O list item must be defined with an integer datum.
On input, the Iw.m edit descriptor is treated identically to the Iw edit descriptor. The output
field for the Iw edit descriptor consists of zero or more leading blanks followed by a minus sign if the value of
the I/O list item is negative or an optional plus sign otherwise, followed by the magnitude of the integer datum with no
leading zeroes. Note that the integer constant contains at least one digit. On output, the Iw.m edit
descriptor specifies that at least m digits are to be displayed with leading zeroes if necessary. The value
of m must be less than or equal to the value of w. If m is zero and the value of the datum
is zero, then the output field is filled with blanks.
Example:
PRINT '(1H<,I4.4,I5,1H>)',23,2345
The output produced by the PRINT statement in the previous example is the string:
<0023 2345>
Floating-point Editing: F, E, D and G Edit Descriptors
The F, E, D and G edit descriptors describe the editing of real, double precision,
complex and double precision complex data. The I/O list item corresponding to one of these edit descriptors must be
of type real, double precision, complex or double precision complex. On input, the I/O list item will become defined
with a datum whose type is the same as that of the I/O list item. On output, the I/O list item must be defined with
a datum whose type is that of the I/O list item.
F Editing
An F edit descriptor has the form Fw.d where w is the field width and d is the number
of digits in the fractional part. The input field consists of an optional sign, followed by a string of digits optionally
containing a decimal point. If the decimal point is omitted, the rightmost d digits with leading zeroes assumed
if necessary, are interpreted as the fractional part of the value represented. An exponent of one of the following
forms may follow.
- A signed integer constant.
- An E or D followed by an optionally signed integer constant.
Consider the following example, where the decimal point is omitted. The formula used in the evaluation is:
-d (exponent subfield)
(integer subfield) x 10 x 10
If the specification is F10.8 and the input quantity is 31415E+5 then the following conversion takes place.
-8 5
00031415 x 10 x 10
5
= .00031415 x 10
= 31.415
In other words, the decimal point is assumed to lie to the left of the 8 digits (padded with zeroes on the left) forming
the fractional part of the input value.
The output field produced by an F edit descriptor consists of blanks if necessary followed by a minus sign
if the item in the I/O list is negative or an optional plus sign otherwise, followed by a string of digits containing a decimal
point which represents the magnitude of the I/O list item. The string representing the magnitude of the I/O list item
is modified according to the scale factor and is rounded to d fractional digits. An optional leading zero
is produced only if the magnitude of the I/O list item is less than one. Note that a leading zero is required if there
would otherwise be no digits in the output field.
Example:
PRINT '(1H<,F8.4,1H>)', 234.43
The output produced by the PRINT statement in the previous example is the string:
<234.4300>
E and D Editing
The Ew.d, Dw.d and Ew.dEe edit descriptors indicate that the field width is w, the
fractional part contains d digits unless a scale factor greater than one is in effect, and the exponent consists
of e digits. The e has no effect on input.
The form of the input field and processing of it is the same as that for F editing. The form of the
output field is:
[+] [0] . x x ... x
exp
[-] 1
2 d
- where:
-
p
- indicates a plus or minus sign.
x's
- are the d most significant digits of the value after rounding.
exp
- is a decimal exponent.
The form of the exponent is as follows.
- When using the Ew.d edit descriptor, the form of the exponent is
E+nn
or if |exp| <= 99
E-nn
and
+nnn
or if 99 < |exp| <= 999
-nnn
- When using the Ew.dEe edit descriptor, the form of the exponent is
E+n ... n where |exp| <= (10**e)-1
- 1 e
- When using the Dw.d edit descriptor, the form of the exponent is
D+nn
or if |exp| <= 99
D-nn
and
+nnn
or if 99 < |exp| <= 999
-nnn
Note that a sign in the exponent is always present. If the exponent is 0, a plus sign is used. The forms
Ew.d and Dw.d are not to be used if |exp| > 999.
Example:
PRINT '(1H<,E10.4,1H>,1H<,E9.4,1H>,1H<,E12.4E3,1H>)',
$ .5, .5, .5
END
The output from the PRINT statement in the previous example is the string:
<0.5000E+00><.5000E+00>< 0.5000E+000>
The scale factor k in a P edit descriptor controls decimal normalization as follows:
- If -d < k <= 0, then the output field contains |k| leading zeroes and d-|k| significant
digits after the decimal point.
- If 0 < k < d+2, the output field contains exactly k significant digits to the left of the decimal
point and d-k+1 significant digits to the right of the decimal point.
- Other values of k are not permitted.
The Ew.dDe edit descriptor behaves in the same way as the Ew.dEe edit descriptor on input; on output
the only difference is that the letter D is used to mark the exponent instead of the letter E.
G Editing
The Gw.d and Gw.dEe edit descriptors indicate that the field width is w, the fractional part
contains d digits unless a scale factor greater than one is in effect, and the exponent consists of e digits.
G input editing is the same as F input editing.
The representation on G output editing depends on the magnitude of the datum being edited. Let
M be the magnitude of the datum being edited. Then G output editing behaves as follows.
- If M < 0.1 or M >= 10**d, Gw.d output editing is equivalent to kPEw.d output editing
and Gw.dEe output editing is equivalent to kPEw.dEe output editing where k is the scaling factor
currently in effect.
- If 0.1 <= M < 10**d, the scale factor has no effect and the value of M determines the editing
as shown in the following table.
+-----------------------+-----------------------------------+
| Magnitude of Datum | Equivalent Edit Descriptor
|
+-----------------------+-----------------------------------+
| 0.1<=M<1
| F<w-n>.d followed by n blanks |
| 1<=M<10
| F<w-n>.<d-1> followed by n blanks |
| .
| .
|
| .
| .
|
| .
| .
|
| 10**(d-2)<=M<10**(d-1)| F<w-n>.1 followed by n blanks
|
| 10**(d-1)<=M<10**d | F<w-n>.0 followed by n blanks
|
+-----------------------+-----------------------------------+
- where:
-
<w-n>
- stands for the integer represented by evaluating w-n.
<d-1>
- stands for the integer represented by evaluating d-1.
n
- is 4 for Gw.d editing and e+2 for Gw.dEe editing.
Example:
PRINT '(1H<,G12.6,1H>,1H<,G12.4E4,1H>)',
.5, .5
END
The output from the PRINT statement in the previous example is the string:
<0.500000 ><0.5000 >
Complex Editing
Since a complex datum consists of a pair of real or double precision data, the editing of a complex datum is specified
by two successive pairs of F, E, D or G edit descriptors. The two descriptors may
be different and may be separated by any number of non-repeatable edit descriptors. Double precision complex editing
is identical to complex editing.
L Edit Descriptor
The Lw edit descriptor is used for I/O list items of type logical. The field width is w.
On input the I/O list item will become defined with a datum of type logical. The input field consists of optional
blanks, followed by an optional decimal point followed by a T or F for true or false respectively.
The T and F may be followed by additional characters in the field. Open Watcom FORTRAN 77 allows
t and f in addition to T and F on input.
On output, the I/O list item must be defined with a datum of type logical. The output field consists of
w-1 blanks followed by a T for true or F for false.
Example:
PRINT '(1H<,L3,L5,1H>)',.TRUE.,.FALSE.
The output produced by the PRINT statement in the previous example is the string:
< T F>
A Edit Descriptor
The A[w] edit descriptor is used for I/O list items of type character. On input, the I/O list item
becomes defined with character data. On output, the I/O list item must be defined with character data. If
w is specified in the edit descriptor, the field width is w otherwise the field width is the number of characters
in the I/O list item.
Open Watcom FORTRAN 77 also permits I/O list items of non-character data types. On input, the I/O list item
becomes defined with the binary representation of the character data. On output, the I/O list item is assumed to be
defined with character data.
If len is the length of the I/O list item and w is specified in A input editing so that
w is greater than len, the rightmost len characters of the input field will be taken. If
w is less than len, then the w characters in the input field will be taken and padded with len-w
blanks.
If w is specified in A output editing so that w is greater than len, then the
output field will consist of w-len blanks followed by the len characters of the I/O list item. If
w is less than or equal to len, the output field will consist of the first w characters of the I/O
list item.
Example:
PRINT '(1H<,A5,A8,1H>)','ABCDEFG','123'
The output produced by the PRINT statement in the previous example is the string:
<ABCDE 123>
Z Editing (Extension)
The Zw edit descriptor is used to display the hexadecimal representation of data or read hexadecimal data.
It is a Open Watcom FORTRAN 77 extension. The Zw edit descriptor can be used for I/O list items of any type.
The field width is w.
On output, w must be greater than or equal to twice the size (in bytes) of the I/O list item since each byte
is represented by two hexadecimal digits. For example, real data requires four bytes. Hence, w must
be at least eight.
Example:
PRINT '(1H<,Z8,1H>)', 256
The output produced by the PRINT statement in the previous example is the string:
<00000100>
If w is greater then the number of hexadecimal digits required to represent the data, the leftmost print
positions of the output field are filled with blanks.
Example:
PRINT '(1H<,Z10,1H>)','ABCD'
The output produced by the PRINT statement in the previous example is the string
< C1C2C3C4>
if the EBCDIC character set is being used or
< 41424344>
if the ASCII character set is being used.
On input, if w is greater than twice the size (in bytes) of the I/O list item, the leftmost characters are
truncated from the input field. For example, if the input field contains the string
91A2C3D4
and is read into a character variable whose length is two, the character would contain the hexadecimal data C3D4.
If w is less than twice the size (in bytes) of the I/O item, the I/O item is padded to the left with hexadecimal
zeroes. For example, if the input field contains the string
81C1
and is read into a character variable whose length is four, the character would contain the hexadecimal data 000081C1.
Format-directed input/output (I/O) is formatted input or output controlled by a format specification. The
action taken during formatted input or output depends on the next edit descriptor in the format specification and the next
item in the input/output list if one exists.
A format specification is processed from left to right. An edit descriptor or a format specification with a
repeat specification of r is processed as a list of r edit descriptors or format specifications.
A repeat specification of one is equivalent to no repeat specification.
For each repeatable edit descriptor in the format specification, there corresponds one item in the I/O list except
an I/O list item of type complex where two repeatable floating-point edit descriptors are required. Non-repeatable
edit descriptors do not correspond to any I/O list item; they communicate information directly with the record. Whenever
a repeatable edit descriptor is encountered in a format specification, there must be a corresponding item in the I/O list.
The edited information is transmitted appropriately between the item and the record.
Format processing is terminated when any of the following conditions occur.
- When an edit descriptor has no corresponding item in the I/O list.
- When a colon edit descriptor is encountered and there are no more items in the I/O list.
- When the right parenthesis is encountered and there are no more items in the I/O list.
If the right parenthesis of the complete format specification is encountered and the I/O list has not been exhausted,
the file is positioned at the next record and format processing resumes at the start of the format specification terminated
by the last preceding right parenthesis. If there is no such right parenthesis, format processing resumes at the start
of the complete format specification. The part of the format specification that is reused must contain at least one
repeatable edit descriptor. If format processing resumes at a left parenthesis preceded by a repeat specification,
the repeat specification is also reused. The scale factor, sign control edit descriptors and blank control edit descriptors
are not affected when part of a format specification is reused.
List-directed formatting is input/output without a format specification.
Example:
READ( un, * ) X, Y, Z
READ( UNIT=un, FMT=* ) X, Y, Z
READ *, X, Y, Z
WRITE( un, * ) X, Y, Z
WRITE( UNIT=un, FMT=* ) X, Y, Z
PRINT *, X, Y, Z
In the previous example, an asterisk instead of a format specification indicates list-directed formatting.
Omitting the asterisk and format specification also indicates list-directed formatting.
Example:
READ, X, Y, Z
PRINT, X, Y, Z
Records used during list-directed formatting are called list-directed records. A list-directed record is a sequence
of values and value separators. Any sequence of blanks is treated as a single blank except when it appears in a character
constant. The end of a record has the same effect as a blank character.
A value is one of the following:
- A constant.
- A null value.
- r*c
- r*
- where:
-
r
- is an unsigned, nonzero integer constant.
c
- is a constant.
The r*c form is equivalent to r successive occurrences of c. The r* form is
equivalent to r successive occurrences of the null value. In these two forms, blanks are permitted only where
they are allowed in the constant c.
A value separator is one of the following:
- A comma preceded and followed by any number of blanks.
- A slash preceded and followed by any number of blanks. A slash as a value separator terminates the execution of
the input statement. The definition status of the remaining input items in the input list remains the same as it was
prior to the input statement.
- Any number of blanks between two values.
A null value is specified by having no character between successive value separators, no characters preceding the first
value separator in a record or the r* form. It has no effect on the current value of the input item.
Note that the end of record following a value separator does not specify a null value.
The input forms acceptable to format specifications for a given type are also acceptable for list-directed formatting
with certain exceptions.
- Blanks are never used as zeroes and blanks embedded in constants are not allowed except in character constants.
- An input item of type real or double precision must have an input field suitable for F editing except that no fractional
digits are assumed unless a decimal point is present in the field. Such a field will be called a numeric input field.
- An input item of type complex or double precision complex must consist of a left parenthesis followed by two numeric input
fields separated by a comma and followed by a right parenthesis. The numeric input fields may be preceded or followed
by blanks. The end of record can only appear between the first numeric field and the comma or between the comma and
the second numeric field. Note that a null value must not be used as the real or imaginary part but may represent the
entire complex constant.
- An input item of type logical must not include either a slash or a comma among the optional characters allowed in L editing.
- An input item of type character consists of a non-empty string of characters enclosed in apostrophes. Apostrophes
in character constants are represented by two consecutive apostrophes without a blank or end of record separating them.
Character constants may span records. If this is the case, the end of record does cause a blanks to be inserted into
the character constant. Note that a comma or slash in a character constant is not a value separator. A character
input field is assigned to a character input item as though it were a character assignment.
List-Directed Output
The form of the output field produced by list-directed output is similar to the form required by list-directed input.
The output of a character constant does not include the enclosing quotes and an apostrophe in a character constant
is output as a single apostrophe. The values are separated by one or more blanks. When printed, each record will
start with a blank if the file is a carriage-control oriented file. For example, the source listing file produced by
Open Watcom FORTRAN 77 is such a file.
The READ, WRITE, and PRINT statements may be used to transmit data between a file and the variables
specified in a NAMELIST statement.
Example:
CHARACTER*20 NAME
CHARACTER*20 STREET
CHARACTER*15 CITY
CHARACTER*20 STATE
CHARACTER*20 COUNTRY
CHARACTER*10 ZIP_CODE
INTEGER AGE
INTEGER MARKS(10)
NAMELIST /nl/ NAME, STREET, CITY, STATE,
+
COUNTRY, ZIP_CODE, AGE, MARKS
.
.
.
READ( un, nl )
READ( UNIT=un, FMT=nl )
READ nl
WRITE( un, nl )
WRITE( UNIT=un, FMT=nl )
PRINT nl
The input data must be in a special format. The first character in each record must be blank. The second character
in the first record of a group of data records must be an ampersand (&) or dollar sign ($) immediately followed by the
NAMELIST name. The NAMELIST name must be followed by a blank and must not contain any imbedded blanks.
This name is followed by data items, optionally separated by commas. The end of a data group is signaled by the
character "&" or "$", optionally followed by the string "END". If the "&"
character was used to start the group, then it must be used to end the group. If the "$" character was used
to start the group, then it must be used to end the group.
12345678901234567890...
&NL
item1, item2, item3,
item4, item5, ...
The form of the data items in an input record is:
- Name = Constant
- The name may be a variable name, an array element name, or a character substring name. The constant may be integer,
real, complex, logical or character. Logical constants may be in the form "T" or ".TRUE" and "F"
or ".FALSE". Character constants must be contained within apostrophes. Subscripts and substring indices
must be of integer type.
ArrayName = Set of Constants
- The set of constants consists of constants of the type integer, real, complex, logical or character. The constants are
separated by commas. The number of constants must be less than or equal to the number of elements in the array.
Successive occurrences of the same constant may be represented in the form r*constant, where r is a non-zero
integer constant specifying the number of times the constant is to occur. Consecutive commas within a list indicate
that the values of the array elements remain unchanged.
The variable and array names specified in the input file must appear in the NAMELIST list, but the order is not
important. A name that has been made equivalent to a name in the input data cannot be substituted for that name in
the NAMELIST list. The list can contain names of items in COMMON but must not contain dummy argument
names.
Each data record must begin with a blank followed by a complete variable or array name or constant. Embedded
blanks are not permitted in names or constants. Trailing blanks after integers and exponents are treated as zeros.
Example:
&PERSON
NAME = 'John Doe'
STREET = '22 Main St.' CITY = 'Smallville'
STATE = 'Texas' COUNTRY
= 'U.S.A.'
ZIP_CODE = '78910-1203'
MARKS = 73, 82, 3*78, 89, 2*93, 91, 88
AGE = 23
&END
The input forms acceptable to format specifications for a given type are also acceptable for namelist-directed formatting
with certain exceptions.
- Blanks are never used as zeroes and blanks embedded in constants are not allowed except in character constants.
- An input item of type real or double precision must have an input field suitable for F editing except that no fractional
digits are assumed unless a decimal point is present in the field. Such a field will be called a numeric input field.
- An input item of type complex or double precision complex must consist of a left parenthesis followed by two numeric input
fields separated by a comma and followed by a right parenthesis. The numeric input fields may be preceded or followed
by blanks. The end of record can only appear between the first numeric field and the comma or between the comma and
the second numeric field. Note that a null value must not be used as the real or imaginary part but may represent the
entire complex constant.
- An input item of type logical must not include either a slash or a comma among the optional characters allowed in L editing.
- An input item of type character consists of a non-empty string of characters enclosed in apostrophes. Apostrophes
in character constants are represented by two consecutive apostrophes without a blank or end of record separating them.
Character constants may span records. If this is the case, the end of record does cause a blank to be inserted into
the character constant. Note that a comma or slash in a character constant is not a value separator. A character
input field is assigned to a character input item as though it were a character assignment.
Namelist-Directed Output
The form of the data items in an output record is suitable for input using a namelist-directed READ statement.
- Output records are written using the ampersand character (&), not the dollar sign ($), although the dollar sign is
accepted as an alternative during input. That is, the output data is preceded by "&name" and is followed
by "&END".
- All variable and array names specified in the NAMELIST list and their values are written out, each according
to its type.
- Character data is enclosed in apostrophes.
- The fields for the data are made large enough to contain all the significant digits.
- The values of a complete array are written out in columns.
Functions and Subroutines
Functions and subroutines are procedures that fall into one of the following categories.
- Statement functions
- Intrinsic functions
- External functions
- Subroutines
First let us introduce some terminology.
A program unit is a collection of Open Watcom FORTRAN 77 statements and comments that can be either a main
program or a subprogram.
A main program identifies the program unit where execution is to begin. A main program is a program unit
which has as its first statement a PROGRAM statement or one which does not have a PROGRAM, FUNCTION,
SUBROUTINE or BLOCK DATA statement as its first statement. Complete execution of the main program implies
the complete execution of the program. Each executable program can contain only one main program.
A subprogram is a program unit that either has a FUNCTION, SUBROUTINE or BLOCK DATA
statement as its first statement. This chapter will only deal with subprograms that have a FUNCTION or
SUBROUTINE statement as its first statement.
Statement Functions
A statement function is a procedure defined by a single statement. Its definition must follow all specification
statements and precede the first executable statement. The statement defining a statement function is not an executable
statement.
A statement function has the following form.
sf ( [d [,d] ...] ) = e
- where:
-
sf
- is the name of the statement function.
d
- is a statement function dummy argument.
e
- is an expression.
The expression e and the statement function name sf must conform according to the rules of assignment
as described in the chapter entitled Assignment Statements.
The statement function dummy arguments are variable names and are used to indicate the order, number and type of the
arguments of the statement function. A dummy argument name of a statement function must only appear once in the dummy
argument list of the statement function. Its scope is the statement defining the statement function. That is,
it becomes defined when the statement function is referenced and undefined when execution of the statement function is completed.
A name that is a statement function dummy argument can also be the name of a variable, a common block, the dummy argument
of another statement function or appear in the dummy argument list of a FUNCTION, SUBROUTINE or ENTRY
statement. It cannot be used in any other context.
The expression e can contain any of the following as operands.
- A constant.
- A symbolic constant.
- A variable reference. This can be a reference to a statement function dummy argument or to a variable that appears
within the same program unit which defines the statement function. If the statement function dummy argument has the
same name as a variable in the same program unit, the statement function dummy argument is used. The variable reference
can also be a dummy argument that appears in the dummy argument list of a FUNCTION or SUBROUTINE statement.
If it is a dummy argument that has appeared in the dummy argument list of an ENTRY statement, then the
ENTRY statement must have previously appeared.
- An array element reference.
- An intrinsic function reference.
- A reference to a statement function whose defining statement has previously appeared.
- An external function reference.
- A dummy procedure reference.
- An expression enclosed in parentheses which adheres to the rules specified for the expression e.
Referencing a Statement Function
A statement function is referenced by its use in an expression. The process of executing a statement function involves
the following steps.
- The expressions that form the actual arguments to the statement function are evaluated.
- The dummy arguments of the statement function are associated with the actual arguments.
- The expression e is evaluated.
- The value of the result is converted to the type of the statement function according to the rules of assignment and is
available to the expression that contained the reference to the statement function.
The actual arguments must agree in order, number and type with the corresponding dummy arguments.
Example:
SUBROUTINE CALC( U, V )
REAL POLY, X, Y, U, V, Z, CONST
*
* Define a Statement Function.
*
POLY(X,Y) = X**2 + Y**2 + 2.0*X*Y + CONST
*
* Invoke the Statement Function.
*
CONST = 23.5
Z = POLY( U, V )
PRINT *, Z
END
In the previous example, note that after the execution of the statement function, the values of X and
Y are not equal to the value of U and V respectively; they are undefined.
Statement Function Restrictions
- A statement function is local to the program unit in which it is defined. Thus, a statement function name is not
allowed to appear in an EXTERNAL statement and cannot be passed to another procedure as an actual argument.
The following example illegally attempts to pass the statement function F to the subroutine SAM.
Example:
* Illegally passing a statement function
* to a subroutine.
PROGRAM MAIN
F(X) = X
.
.
.
CALL SAM( F )
.
.
.
END
- If a statement function F contains a reference to another statement function G, then the statement defining
G must have previously appeared. In the following example, the expression defining the statement function
F illegally references a statement function G whose defining statement follows the statement defining F.
Example:
* Illegal order of statement functions.
.
.
.
F(X) = X + G(X)
G(X) = X + 2
.
.
.
- The statement function name must not be the same name of any other entity in the program unit except possibly the name
of a common block.
- If a dummy argument of a statement function is of type CHARACTER, then its length specification must be an integer constant
expression. The following is illegal.
Example:
SUBROUTINE SAM( X )
CHARACTER*(*) X
* Illegal - CHARACTER*(*) dummy argument not
* allowed in statement function.
F(X) = X
PRINT *, F('ABC')
END
- An actual argument to a statement function can be any expression, except character expressions involving the concatenation
of an operand whose length specification is (*) unless the operand is a symbolic constant.
Intrinsic Functions
An intrinsic function is a function that is provided by Open Watcom FORTRAN 77.
Specific Names and Generic Names of Intrinsic Functions
All intrinsic functions can be referenced by using the generic name or the specific name of the intrinsic
function. The specific name uniquely identifies the function to be performed. The type of the result is predefined
thus its name need not appear in a type statement. For example, CLOG is a specific name of the generic LOG function
and computes the natural logarithm of a complex number. The type of the result is also COMPLEX.
When the generic name is used, a specific name is selected based on the data type of the actual argument. For
example, the generic name of the natural logarithm intrinsic function is LOG. To compute the natural logarithm of REAL,
DOUBLE PRECISION, COMPLEX or DOUBLE PRECISION COMPLEX data, the generic name LOG can be used. Generic names simplify
the use of intrinsic functions because the same name can be used with more than one type of argument.
Notes:
- It is also possible to pass intrinsic functions to subprograms. When doing so, only the specific name of the intrinsic
function can be used as an actual argument. The specific name must have appeared in an INTRINSIC statement.
- If an intrinsic function has more than one argument, each argument must be of the same type.
- The generic and specific name of an intrinsic function is the same for some intrinsic functions. For example, the
specific name of the intrinsic function which computes the sine of an argument whose type is REAL is called SIN which is
also the generic name of the sine function.
The following sections present all generic and specific names of intrinsic functions and describe how they are used.
The following is a guide to interpreting the information presented.
Data types are represented by letter codes.
- CHARACTER is represented by CH.
- LOGICAL is represented by L.
- INTEGER is represented by I.
- INTEGER*1 is represented by I1.
- INTEGER*2 is represented by I2.
- REAL (REAL*4) is represented by R.
- DOUBLE PRECISION (REAL*8) is represented by D.
- Single precision COMPLEX (COMPLEX*8) is represented by C.
- Double precision COMPLEX (COMPLEX*16) is represented by Z.
The "Definition" description gives the mathematical definition of the function performed by the intrinsic function.
There are two fields for each intrinsic function. The "Name" field lists the specific and generic names
of the intrinsic functions. When the name of an intrinsic function is a generic name, it is indicated by the letter
"g" in parentheses; all other names are specific names. The "Usage" field describes how the intrinsic
functions are used. "R<-ATAN2(R,R)" is a typical entry in this field. The name of the intrinsic
function always follows the "<-". In this example the name of the intrinsic function is ATAN2. The
data type of the arguments to the intrinsic function are enclosed in parentheses, are separated by commas, and always follow
the name of the intrinsic function. In this case, ATAN2 requires two arguments both of type REAL. The type of
the result of the intrinsic function is indicated by the type preceding the "<-". In this case, the result
of ATAN2 is of type REAL.
Open Watcom FORTRAN 77 extensions to the FORTRAN 77 language are flagged by an exclamation mark (!).
Type Conversion: Conversion to integer
- Definition:
- int(a)
Name / Usage:
-
INT (g)
- I<-INT(I), I<-INT(R), I<-INT(D), I<-INT(C), I<-INT(Z) !
INT
- I<-INT(R)
HFIX
- I2<-HFIX(R) !
IFIX
- I<-IFIX(R)
IDINT
- I<-IDINT(D)
Notes:
- The value of int(X) is X if X is of type INTEGER. If X is of type REAL or DOUBLE PRECISION, then int(X) is 0 if |X|<1
and the integer whose magnitude is the largest integer that does not exceed the magnitude of X and has the same sign of X
if |X| > 1. If X is of type COMPLEX or COMPLEX*16, int(X) is int(real part of X).
! is an extension to FORTRAN 77.
Type Conversion: Conversion to real
- Name / Usage:
-
REAL (g)
- R<-REAL(I), R<-REAL(R), R<-REAL(D), R<-REAL(C), R<-REAL(Z) !
REAL
- R<-REAL(I)
FLOAT
- R<-FLOAT(I)
SNGL
- R<-SNGL(D)
Notes:
- For X of type COMPLEX, REAL(X) is the real part of X. For X of type COMPLEX*16, REAL(X) is the single precision representation
of the real part of X.
! is an extension to FORTRAN 77.
Type Conversion: Conversion to double precision
- Name / Usage:
-
DBLE (g)
- D<-DBLE(I), D<-DBLE(R), D<-DBLE(D), D<-DBLE(C), D<-DBLE(Z) !
DREAL
- D<-DREAL(Z) !
DFLOAT
- D<-DFLOAT(I) !
Notes:
- For X of type COMPLEX, DBLE(X) is the double precision representation of the real part of X. For X of type COMPLEX*16,
DBLE(X) is the real part of X.
! is an extension to FORTRAN 77.
Type Conversion: Conversion to complex
- Name / Usage:
-
CMPLX (g)
- C<-CMPLX(I), C<-CMPLX(I,I), C<-CMPLX(R), C<-CMPLX(R,R), C<-CMPLX(D), C<-CMPLX(D,D), C<-CMPLX(C), C<-CMPLX(Z)
!
Notes:
- If X is of type COMPLEX, then CMPLX(X) is X. If X is of type COMPLEX*16, then CMPLX(X) is a complex number whose real
part is REAL(real part of X) and imaginary part is REAL(imaginary part of X).
If X is not of type COMPLEX, then CMPLX(X) is the complex number whose real part is REAL(X) and imaginary part is REAL(0).
CMPLX(X,Y) is the complex number whose real part is REAL(X) and whose imaginary part is REAL(Y) for X,Y not of type
COMPLEX.
! is an extension to FORTRAN 77.
Type Conversion: Conversion to double complex
- Name / Usage:
-
DCMPLX (g) !
- Z<-DCMPLX(I), Z<-DCMPLX(I,I), Z<-DCMPLX(R), Z<-DCMPLX(R,R), Z<-DCMPLX(D), Z<-DCMPLX(D,D), Z<-DCMPLX(C),
Z<-DCMPLX(Z)
Notes:
- If X is of type COMPLEX*16, then DCMPLX(X) is X. If X is of type COMPLEX, then DCMPLX(X) is a COMPLEX*16 number whose
real part is DBLE(real part of X) and imaginary part is DBLE(imaginary part of X).
If X is not of type COMPLEX*16, then DCMPLX(X) is the COMPLEX*16 number whose real part is DBLE(X) and imaginary part
is DBLE(0). DCMPLX(X,Y) is the COMPLEX*16 number whose real part is DBLE(X) and whose imaginary part is DBLE(Y) for
X,Y not of type COMPLEX.
! is an extension to FORTRAN 77.
Type Conversion: Character conversion to integer
- Name / Usage:
-
ICHAR
- I<-ICHAR(CH)
Notes:
- ICHAR returns an integer which describes the position of the character in the processor collating sequence. The first
character in the collating sequence is in position 0 and the last character of the collating sequence is in position n-1
where n is the number of characters in the collating sequence. The value of ICHAR(X) for X a character of length one
is such that 0 <= ICHAR(X) <= n-1. For any characters X and Y, the following holds true.
- X .LT. Y if and only if ICHAR(X) .LT. ICHAR(Y)
- X .EQ. Y if and only if ICHAR(X) .EQ. ICHAR(Y)
CHAR is the inverse of ICHAR.
Type Conversion: Conversion to character
- Name / Usage:
-
CHAR
- CH<-CHAR(I)
Notes:
- CHAR returns the character in the i'th position of the processor collating sequence. The first character in the collating
sequence is in position 0 and the last character of the collating sequence is in position n-1 where n is the number of characters
in the collating sequence. The value of CHAR(I) is of type CHARACTER of length one. The argument I must be in
the range 0 <= I <= n-1.
ICHAR is the inverse of CHAR.
Truncation
- Definition:
- int(a)
Name / Usage:
-
AINT (g)
- R<-AINT(R), D<-AINT(D)
AINT
- R<-AINT(R)
DINT
- D<-DINT(D)
Notes:
- The value of int(X) is X if X is of type INTEGER. If X is of type REAL or DOUBLE PRECISION, then int(X) is 0 if |X|<1
and the integer whose magnitude is the largest integer that does not exceed the magnitude of X and has the same sign of X
if |X| > 1. If X is of type COMPLEX or COMPLEX*16, int(X) is int(real part of X).
Nearest Whole Number
- Definition:
- int(a+.5) if a>=0; int(a-.5) if a<0
Name / Usage:
-
ANINT (g)
- R<-ANINT(R), D<-ANINT(D)
ANINT
- R<-ANINT(R)
DNINT
- D<-DNINT(D)
Nearest Integer
- Definition:
- int(a+.5) if a>=0; int(a-.5) if a<0
Name / Usage:
-
NINT (g)
- I<-NINT(R), I<-NINT(D)
NINT
- I<-NINT(R)
IDNINT
- I<-IDNINT(D)
Absolute Value
- Definition:
- (ar**2+ai**2)**1/2 if a is complex; |a| otherwise
Name / Usage:
-
ABS (g)
- I<-ABS(I), I1<-ABS(I1) !, I2<-ABS(I2) !, R<-ABS(R), D<-ABS(D), R<-ABS(C), D<-ABS(Z) !
IABS
- I<-IABS(I)
I1ABS
- I1<-I1ABS(I1) !
I2ABS
- I2<-I2ABS(I2) !
ABS
- R<-ABS(R)
DABS
- D<-DABS(D)
CABS
- R<-CABS(C)
CDABS !
- D<-CDABS(Z)
Notes:
- A complex number is an ordered pair of real numbers, (ar,ai) where ar is the real part and ai is
the imaginary part of the complex number.
! is an extension to FORTRAN 77.
Remainder
- Definition:
- mod(a1,a2) = a1-int(a1/a2)*a2
Name / Usage:
-
MOD (g)
- I<-MOD(I,I), I1<-MOD(I1,I1) !, I2<-MOD(I2,I2) !, R<-MOD(R,R), D<-MOD(D,D),
MOD
- I<-MOD(I,I)
I1MOD
- I1<-I1MOD(I1,I1) !
I2MOD
- I2<-I2MOD(I2,I2) !
AMOD
- R<-AMOD(R,R)
DMOD
- D<-DMOD(D,D)
Notes:
- The value of int(X) is X if X is of type INTEGER. If X is of type REAL or DOUBLE PRECISION, then int(X) is 0 if |X|<1
and the integer whose magnitude is the largest integer that does not exceed the magnitude of X and has the same sign of X
if |X| > 1. If X is of type COMPLEX or COMPLEX*16, int(X) is int(real part of X).
The value of MOD, I1MOD, I2MOD, AMOD or DMOD is undefined if the value of a2 is 0.
Transfer of Sign
- Definition:
- sign(a1,a2) = |a1| if a2>=0; -|a1| if a2<0
Name / Usage:
-
SIGN (g)
- I<-SIGN(I,I), I1<-SIGN(I1,I1) !, I2<-SIGN(I2,I2) !, R<-SIGN(R,R), D<-SIGN(D,D)
ISIGN
- I<-ISIGN(I,I)
I1SIGN
- I1<-I1SIGN(I1,I1) !
I2SIGN
- I2<-I2SIGN(I2,I2) !
SIGN
- R<-SIGN(R,R)
DSIGN
- D<-DSIGN(D,D)
Notes:
- If the value of a1 is 0, the result is 0 which has no sign.
Positive Difference
- Definition:
- a1-a2 if a1>a2; 0 if a1<=a2
Name / Usage:
-
DIM (g)
- I<-DIM(I,I), I1<-DIM(I1,I1) !, I2<-DIM(I2,I2) !, R<-DIM(R,R), D<-DIM(D,D)
IDIM
- I<-IDIM(I,I)
I1IDIM
- I1<-I1DIM(I1,I1) !
I2IDIM
- I2<-I2DIM(I2,I2) !
DIM
- R<-DIM(R,R)
DDIM
- D<-DDIM(D,D)
Double Precision Product
- Definition:
- a1*a2
Name / Usage:
-
DPROD
- D<-DPROD(R,R)
Choosing Largest Value
- Definition:
- max(a1,a2,...)
Name / Usage:
-
MAX (g)
- I<-MAX(I,...), I1<-MAX(I1,...) !, I2<-MAX(I2,...) !, R<-MAX(R,...), D<-MAX(D,...)
MAX0
- I<-MAX0(I,...)
I1MAX0
- I1<-I1MAX0(I1,...) !
I2MAX0
- I2<-I2MAX0(I2,...) !
AMAX1
- R<-AMAX1(R,...)
DMAX1
- D<-DMAX1(D,...)
AMAX0
- R<-AMAX0(I,...)
MAX1
- I<-MAX1(R,...)
Choosing Smallest Value
- Definition:
- min(a1,a2,...)
Name / Usage:
-
MIN (g)
- I<-MIN(I,...), I1<-MIN(I1,...) !, I2<-MIN(I2,...) !, R<-MIN(R,...), D<-MIN(D,...)
MIN0
- I<-MIN0(I,...)
I1MIN0
- I1<-I1MIN0(I1,...) !
I2MIN0
- I2<-I2MIN0(I2,...) !
AMIN1
- R<-AMIN1(R,...)
DMIN1
- D<-DMIN1(D,...)
AMIN0
- R<-AMIN0(I,...)
MIN1
- I<-MIN1(R,...)
Length
- Definition:
- Length of character entity
Name / Usage:
-
LEN
- I<-LEN(CH)
Notes:
- The argument to the LEN function need not be defined.
Length Without Trailing Blanks
- Definition:
- Length of character entity excluding trailing blanks
Name / Usage:
-
LENTRIM
- I<-LENTRIM(CH)
Index of a Substring
- Definition:
- index(a1,a2) is location of substring a2 in string a1
Name / Usage:
-
INDEX
- I<-INDEX(CH,CH)
Notes:
- INDEX(x,y) returns the starting position of a substring in x which is identical to y. The position of the first such
substring is returned. If y is not contained in x, zero is returned.
Imaginary Part of Complex Number
- Definition:
- ai
Name / Usage:
-
IMAG (g) !
- R<-IMAG(C), D<-IMAG(Z)
AIMAG
- R<-AIMAG(C)
DIMAG
- D<-DIMAG(Z) !
Notes:
- A complex number is an ordered pair of real numbers, (ar,ai) where ar is the real part and ai is
the imaginary part of the complex number.
! is an extension to FORTRAN 77.
Conjugate of a Complex Number
- Definition:
- (ar,-ai)
Name / Usage:
-
CONJG (g) !
- C<-CONJG(C), Z<-CONJG(Z)
CONJG
- C<-CONJG(C)
DCONJG
- Z<-DCONJG(Z) !
Notes:
- A complex number is an ordered pair of real numbers, (ar,ai) where ar is the real part and ai is
the imaginary part of the complex number.
! is an extension to FORTRAN 77.
Square Root
- Definition:
- a**1/2
Name / Usage:
-
SQRT (g)
- R<-SQRT(R), D<-SQRT(D), C<-SQRT(C), Z<-SQRT(Z) !
SQRT
- R<-SQRT(R)
DSQRT
- D<-DSQRT(D)
CSQRT
- C<-CSQRT(C)
CDSQRT
- Z<-CDSQRT(Z) !
Notes:
- The argument to SQRT must be >= 0. The result of CSQRT and CDSQRT is the principal value with the real part >=
0. When the real part of the result is 0, the imaginary part is >= 0.
! is an extension to FORTRAN 77.
Exponential
- Definition:
- e**a
Name / Usage:
-
EXP (g)
- R<-EXP(R), D<-EXP(D), C<-EXP(C), Z<-EXP(Z) !
EXP
- R<-EXP(R)
DEXP
- D<-DEXP(D)
CEXP
- C<-CEXP(C)
CDEXP
- Z<-CDEXP(Z) !
Notes:
- The result of a complex function is the principal value.
! is an extension to FORTRAN 77.
Natural Logarithm
- Definition:
-
log (a)
e
Name / Usage:
-
LOG (g)
- R<-LOG(R), D<-LOG(D), C<-LOG(C), Z<-LOG(Z) !
ALOG
- R<-ALOG(R)
DLOG
- D<-DLOG(D)
CLOG
- C<-CLOG(C)
CDLOG
- Z<-CDLOG(Z) !
Notes:
- The value of a must be > 0. The argument of CLOG and CDLOG must not be (0,0). The result of CLOG and
CDLOG is such that -pi < imaginary part of the result <= pi. The imaginary part of the result is pi only when
the real part of the argument is < 0 and the imaginary part of the argument = 0.
The result of a complex function is the principal value.
! is an extension to FORTRAN 77.
Common Logarithm
- Definition:
-
log (a)
10
Name / Usage:
-
LOG10 (g)
- R<-LOG10(R), D<-LOG10(D)
ALOG10
- R<-ALOG10(R)
DLOG10
- D<-DLOG10(D)
Sine
- Definition:
- sin(a)
Name / Usage:
-
SIN (g)
- R<-SIN(R), D<-SIN(D), C<-SIN(C), Z<-SIN(Z) !
SIN
- R<-SIN(R)
DSIN
- D<-DSIN(D)
CSIN
- C<-CSIN(C)
CDSIN
- Z<-CDSIN(Z) !
Notes:
- All angles are assumed to be in radians.
The result of a complex function is the principal value.
! is an extension to FORTRAN 77.
Cosine
- Definition:
- cos(a)
Name / Usage:
-
COS (g)
- R<-COS(R), D<-COS(D), C<-COS(C), Z<-COS(Z) !
COS
- R<-COS(R)
DCOS
- D<-DCOS(D)
CCOS
- C<-CCOS(C)
CDCOS
- Z<-CDCOS(Z) !
Notes:
- All angles are assumed to be in radians.
The result of a complex function is the principal value.
! is an extension to FORTRAN 77.
Tangent
- Definition:
- tan(a)
Name / Usage:
-
TAN (g)
- R<-TAN(R), D<-TAN(D)
TAN
- R<-TAN(R)
DTAN
- D<-DTAN(D)
Notes:
- All angles are assumed to be in radians.
Cotangent
- Definition:
- cotan(a)
Name / Usage:
-
COTAN (g) !
- R<-COTAN(R), D<-COTAN(D)
COTAN
- R<-COTAN(R) !
DCOTAN
- D<-DCOTAN(D) !
Notes:
- All angles are assumed to be in radians.
! is an extension to FORTRAN 77.
Arcsine
- Definition:
- arcsin(a)
Name / Usage:
-
ASIN (g)
- R<-ASIN(R), D<-ASIN(D)
ASIN
- R<-ASIN(R)
DASIN
- D<-DASIN(D)
Notes:
- The absolute value of the argument of ASIN and DASIN must be <= 1. The result is such that -pi/2 <= result <=
pi/2.
Arccosine
- Definition:
- arccos(a)
Name / Usage:
-
ACOS (g)
- R<-ACOS(R), D<-ACOS(D)
ACOS
- R<-ACOS(R)
DACOS
- D<-DACOS(D)
Notes:
- The absolute value of the argument of ACOS and DACOS must be <= 1. The result is such that 0 <= result <= pi.
Arctangent
- Definition:
- arctan(a)
Name / Usage:
-
ATAN (g)
- R<-ATAN(R), D<-ATAN(D)
ATAN
- R<-ATAN(R)
DATAN
- D<-DATAN(D)
Definition:
- arctan(a1/a2)
Name / Usage:
-
ATAN2 (g)
- R<-ATAN2(R,R), D<-ATAN2(D,D)
ATAN2
- R<-ATAN2(R,R)
DATAN2
- D<-DATAN2(D,D)
Notes:
- The result of ATAN and DATAN is such that -pi/2 <= result <= pi/2. If the value of the first argument of ATAN2
and DATAN2 is positive then the result is positive. If the value of the first argument is 0, the result is 0 if the
second argument is positive and pi if the second argument is negative. If the value of the first argument is negative,
the result is negative. If the value of the second argument is 0, the absolute value of the result is pi/2. The
arguments must not both be 0. The result of ATAN2 and DATAN2 is such that -pi < result <= pi.
Hyperbolic Sine
- Definition:
- sinh(a)
Name / Usage:
-
SINH (g)
- R<-SINH(R) D<-SINH(D)
SINH
- R<-SINH(R)
DSINH
- D<-DSINH(D)
Hyperbolic Cosine
- Definition:
- cosh(a)
Name / Usage:
-
COSH (g)
- R<-COSH(R), D<-COSH(D)
COSH
- R<-COSH(R)
DCOSH
- D<-DCOSH(D)
Hyperbolic Tangent
- Definition:
- tanh(a)
Name / Usage:
-
TANH (g)
- R<-TANH(R), D<-TANH(D)
TANH
- R<-TANH(R)
DTANH
- D<-DTANH(D)
Gamma Function
- Definition:
- gamma(a)
Name / Usage:
-
GAMMA (g)
- R<-GAMMA(R), D<-GAMMA(D)
GAMMA
- R<-GAMMA(R)
DGAMMA
- D<-DGAMMA(D)
Natural Log of Gamma Function
- Definition:
-
log (gamma(a))
e
Name / Usage:
-
LGAMMA (g)
- R<-LGAMMA(R), D<-LGAMMA(D)
ALGAMA
- R<-ALGAMA(R)
DLGAMA
- D<-DLGAMA(D)
Error Function
- Definition:
- erf(a)
Name / Usage:
-
ERF (g)
- R<-ERF(R), D<-ERF(D)
ERF
- R<-ERF(R)
DERF
- D<-DERF(D)
Complement of Error Function
- Definition:
- 1-erf(a)
Name / Usage:
-
ERFC (g)
- R<-ERFC(R), D<-ERFC(D)
ERFC
- R<-ERFC(R)
DERFC
- D<-DERFC(D)
Lexically Greater Than or Equal
- Definition:
- a1>=a2
Name / Usage:
-
LGE
- L<-LGE(CH,CH)
Notes:
- The ASCII collating sequence is used to evaluate the relation.
Lexically Greater Than
- Definition:
- a1>a2
Name / Usage:
-
LGT
- L<-LGT(CH,CH)
Notes:
- The ASCII collating sequence is used to evaluate the relation.
Lexically Less Than or Equal
- Definition:
- a1<=a2
Name / Usage:
-
LLE
- L<-LLE(CH,CH)
Notes:
- The ASCII collating sequence is used to evaluate the relation.
Lexically Less Than
- Definition:
- a1<a2
Name / Usage:
-
LLT
- L<-LLT(CH,CH)
Notes:
- The ASCII collating sequence is used to evaluate the relation.
Binary Pattern Processing Functions: Boolean AND
- Definition:
- iand(i,j) Boolean AND
Name / Usage:
-
IAND (g)
- I<-IAND(I,I), I1<-IAND(I1,I1), I2<-IAND(I2,I2)
IAND
- I<-IAND(I,I)
I1AND
- I1<-I1AND(I1,I1)
I2AND
- I2<-I2AND(I2,I2)
Binary Pattern Processing Functions: Boolean Inclusive OR
- Definition:
- ior(i,j) Boolean inclusive OR
Name / Usage:
-
IOR (g)
- I<-IOR(I,I), I1<-IOR(I1,I1), I2<-IOR(I2,I2)
IOR
- I<-IOR(I,I)
I1OR
- I1<-I1OR(I1,I1)
I2OR
- I2<-I2OR(I2,I2)
Binary Pattern Processing Functions: Boolean Exclusive OR
- Definition:
- ieor(i,j) Boolean exclusive OR
Name / Usage:
-
IEOR (g)
- I<-IEOR(I,I), I1<-IEOR(I1,I1), I2<-IEOR(I2,I2)
IEOR
- I<-IEOR(I,I)
I1EOR
- I1<-I1EOR(I1,I1)
I2EOR
- I2<-I2EOR(I2,I2)
Binary Pattern Processing Functions: Boolean Complement
- Definition:
- not(i) Boolean complement
Name / Usage:
-
NOT (g)
- I<-NOT(I), I1<-NOT(I1), I2<-NOT(I2)
NOT
- I<-NOT(I)
I1NOT
- I1<-I1NOT(I1)
I2NOT
- I2<-I2NOT(I2)
Binary Pattern Processing Functions: Logical Shift
- Definition:
- ishl(j,n) Logical shift
Name / Usage:
-
ISHL (g)
- I<-ISHL(I,I), I1<-ISHL(I1,I1), I2<-ISHL(I2,I2)
ISHL
- I<-ISHL(I,I)
I1ISHL
- I1<-I1SHL(I1,I1)
I2ISHL
- I2<-I2SHL(I2,I2)
- Definition:
- ishft(j,n) Logical shift
Name / Usage:
-
ISHFT (g)
- I<-ISHFT(I,I), I1<-ISHFT(I1,I1), I2<-ISHFT(I2,I2)
ISHFT
- I<-ISHFT(I,I)
I1ISHFT
- I1<-I1SHFT(I1,I1)
I2ISHFT
- I2<-I2SHFT(I2,I2)
Notes:
- There are three shift operations: logical, arithmetic and circular. These shift operations are implemented as
integer functions having two arguments. The first argument, j, is the value to be shifted and the second argument,
n, is the number of bits to shift. If n is less than 0, a right shift is performed. If n
is greater than 0, a left shift is performed. If n is equal to 0, no shift is performed. Note that the
arguments are not modified.
In a logical shift, bits shifted out from the left or right are lost. Zeros are shifted in from the opposite end.
In an arithmetic shift, j is considered a signed integer. In the case of a right shift, zeros are shifted
into the left if j is positive and ones if j is negative. Bits shifted out of the right are lost.
In the case of a left shift, zeros are shifted into the right and bits shifted out of the left are lost.
In a circular shift, bits shifted out one end are shifted into the opposite end. No bits are lost.
Binary Pattern Processing Functions: Arithmetic Shift
- Definition:
- isha(j,n) Arithmetic shift
Name / Usage:
-
ISHA (g)
- I<-ISHA(I,I), I1<-ISHA(I1,I1), I2<-ISHA(I2,I2)
ISHA
- I<-ISHA(I,I)
I1ISHA
- I1<-I1SHA(I1,I1)
I2ISHA
- I2<-I2SHA(I2,I2)
Notes:
- There are three shift operations: logical, arithmetic and circular. These shift operations are implemented as
integer functions having two arguments. The first argument, j, is the value to be shifted and the second argument,
n, is the number of bits to shift. If n is less than 0, a right shift is performed. If n
is greater than 0, a left shift is performed. If n is equal to 0, no shift is performed. Note that the
arguments are not modified.
In a logical shift, bits shifted out from the left or right are lost. Zeros are shifted in from the opposite end.
In an arithmetic shift, j is considered a signed integer. In the case of a right shift, zeros are shifted
into the left if j is positive and ones if j is negative. Bits shifted out of the right are lost.
In the case of a left shift, zeros are shifted into the right and bits shifted out of the left are lost.
In a circular shift, bits shifted out one end are shifted into the opposite end. No bits are lost.
Binary Pattern Processing Functions: Circular Shift
- Definition:
- ishc(j,n) Circular shift
Name / Usage:
-
ISHC (g)
- I<-ISHC(I,I), I1<-ISHC(I1,I1), I2<-ISHC(I2,I2)
ISHC
- I<-ISHC(I,I)
I1ISHC
- I1<-I1SHC(I1,I1)
I2ISHC
- I2<-I2SHC(I2,I2)
Notes:
- There are three shift operations: logical, arithmetic and circular. These shift operations are implemented as
integer functions having two arguments. The first argument, j, is the value to be shifted and the second argument,
n, is the number of bits to shift. If n is less than 0, a right shift is performed. If n
is greater than 0, a left shift is performed. If n is equal to 0, no shift is performed. Note that the
arguments are not modified.
In a logical shift, bits shifted out from the left or right are lost. Zeros are shifted in from the opposite end.
In an arithmetic shift, j is considered a signed integer. In the case of a right shift, zeros are shifted
into the left if j is positive and ones if j is negative. Bits shifted out of the right are lost.
In the case of a left shift, zeros are shifted into the right and bits shifted out of the left are lost.
In a circular shift, bits shifted out one end are shifted into the opposite end. No bits are lost.
Binary Pattern Processing Functions: Bit Testing
- Definition:
- Test bit - a2'th bit of a1 is tested. If it is 1, .TRUE. is returned. If it is 0, .FALSE. is returned.
Name / Usage:
-
BTEST (g)
- L<-BTEST(I,I), L<-BTEST(I1,I1), L<-BTEST(I2,I2)
BTEST
- L<-BTEST(I,I)
I1BTEST
- L<-I1BTEST(I1,I1)
I2BTEST
- L<-I2BTEST(I2,I2)
Binary Pattern Processing Functions: Set Bit
- Definition:
- Set bit - Return a1 with a2'th bit set.
Name / Usage:
-
IBSET (g)
- I<-IBSET(I,I), I1<-IBSET(I1,I1), I2<-IBSET(I2,I2)
IBSET
- I<-IBSET(I,I)
I1IBSET
- I1<-I1BSET(I1,I1)
I2IBSET
- I2<-I2BSET(I2,I2)
Binary Pattern Processing Functions: Clear Bit
- Definition:
- Clear bit - Return a1 with a2'th bit cleared.
Name / Usage:
-
IBCLR (g)
- I<-IBCLR(I,I), I1<-IBCLR(I1,I1), I2<-IBCLR(I2,I2)
IBCLR
- I<-IBCLR(I,I)
I1IBCLR
- I1<-I1BCLR(I1,I1)
I2IBCLR
- I2<-I2BCLR(I2,I2)
Binary Pattern Processing Functions: Change Bit
- Definition:
- Change bit - Return a1 with a2'th bit complemented.
Name / Usage:
-
IBCHNG (g)
- I<-IBCHNG(I,I), I1<-IBCHNG(I1,I1), I2<-IBCHNG(I2,I2)
IBCHNG
- I<-IBCHNG(I,I)
I1IBCHNG
- I1<-I1BCHNG(I1,I1)
I2IBCHNG
- I2<-I2BCHNG(I2,I2)
Binary Pattern Processing Functions: Arithmetic Shifts
- Definition:
- lshift(j,n) Arithmetic left shift
Name / Usage:
-
LSHIFT (g)
- I<-LSHIFT(I,I), I1<-LSHIFT(I1,I1), I2<-LSHIFT(I2,I2)
LSHIFT
- I<-LSHIFT(I,I)
I1LSHIFT
- I1<-I1LSHIFT(I1,I1)
I2LSHIFT
- I2<-I2LSHIFT(I2,I2)
- Definition:
- rshift(j,n) Arithmetic right shift
Name / Usage:
-
RSHIFT (g)
- I<-RSHIFT(I,I), I1<-RSHIFT(I1,I1), I2<-RSHIFT(I2,I2)
RSHIFT
- I<-RSHIFT(I,I)
I1RSHIFT
- I1<-I1RSHIFT(I1,I1)
I2RSHIFT
- I2<-I2RSHIFT(I2,I2)
Notes:
-
With these shift functions, n must be a non-negative integer. In an arithmetic shift, j is considered
a signed integer. In the case of a left shift, zeros are shifted into the right and bits shifted out of the left are
lost. In the case of a right shift, zeros are shifted into the left if j is positive and ones if j
is negative. Bits shifted out of the right are lost.
If n is equal to 0, no shift is performed. Note that the arguments are not modified.
These functions are compiled as in-line code unless they are passed as arguments.
Allocated Array
- Definition:
- Is array A allocated?
Name / Usage:
-
ALLOCATED
- L<-ALLOCATED(A)
Memory Location
- Definition:
- Location of A where A is any variable, array or array element
Name / Usage:
-
LOC
- I<-LOC(A)
Size of Variable or Structure
- Definition:
- Size of A in bytes where A is any constant, variable, array, or structure
Name / Usage:
-
ISIZEOF
- I<-ISIZEOF(A)
Notes:
- The size reported for a constant or simple variable is based on its type. The size of a CHARACTER constant is the number
of characters in the constant. The size reported for an array is the size of the storage area required for the array.
The size reported for a structure is the size of the storage area required for the structure. An assumed-size
CHARACTER variable, assumed-size array, or allocatable array has size 0.
Volatile Reference
- Definition:
- A is a volatile reference
Name / Usage:
-
VOLATILE
- A<-VOLATILE(A)
Notes:
- A volatile reference to a symbol indicates that the value of the symbol may be modified in ways that are unknown to the subprogram.
For example, a symbol in common being referenced in a subprogram may be modified by another subprogram that is processing
an asynchronous interrupt. Therefore, any subprogram that is referencing the symbol to determine its value should reference
this symbol using the VOLATILE intrinsic function so that the value currently being evaluated agrees with the value
last stored.
External Functions
An external function is a program unit that has a FUNCTION statement as its first statement. It
is defined externally to the program units that reference it. The form of a FUNCTION statement is defined
in the chapter entitled FORTRAN Statements.
The name of an external function is treated as if it was a variable. It is through the function name that the
result of an external function becomes defined. This variable must become defined before the execution of the external
function is completed. Once defined, it can be referenced or redefined. The value of this variable when a
RETURN or END statement is executed is the result returned by the external function.
Example:
INTEGER FUNCTION VECSUM( A, N )
INTEGER A(N), I
VECSUM = 0
DO 10 I = 1, N
VECSUM = VECSUM + A(I)
10 CONTINUE
END
If the variable representing the return value of the external function is of type CHARACTER with a length specification
of (*), it must not be the operand of a concatenation operator unless it appears in a character assignment statement.
It is also possible for an external function to return results through its dummy arguments by assigning to them.
The following example demonstrates this.
Example:
INTEGER MARKS(40), N
REAL AVG, STDDEV, MEAN
PRINT *, 'Enter number of marks'
READ( 5, * ) N
PRINT *, 'Enter marks'
READ( 5, * ) (MARKS(I), I = 1, N)
AVG = MEAN( MARKS, N, STDDEV )
PRINT *, 'Mean = ', AVG,
$ ' Standard
Deviation = ', STDDEV
END
*
* Define function MEAN to return the average by
* defining the function name and return the standard
* deviation by defining a dummy argument.
*
REAL FUNCTION MEAN( A, N, STDDEV )
INTEGER A, N, I
REAL STDDEV
DIMENSION A(N)
MEAN = 0
DO 10 I = 1, N
MEAN = MEAN + A(I)
10 CONTINUE
MEAN = MEAN / N
STDDEV = 0
DO 20 I = 1, N
STDDEV = STDDEV + ( A(I) - MEAN
)**2
20 CONTINUE
STDDEV = SQRT( STDDEV / (N - 1) )
END
Referencing an External Function
When an external function is referenced in an expression or a CALL statement, the following steps are performed.
- The actual arguments are evaluated.
- The actual arguments are associated with the corresponding dummy arguments.
- The external function is executed.
The type of the external function reference must be the same as the type of the function name in the external function
subprogram. If the external function is of type CHARACTER, the length must also match.
Actual Arguments for an External Function
An actual argument must be one of the following.
- Any expression except a character expression involving the concatenation of an operand whose length specification is
(*) unless the operand is a symbolic constant.
- An array name.
- An intrinsic function name (must be the specific name) that has appeared in an INTRINSIC statement.
- An external procedure name.
- A dummy procedure name.
The actual arguments of an external function reference must match the order, number and type of the corresponding dummy
arguments. If a subroutine is an actual argument, then type agreement is not required since a subroutine has no type.
External Function Subprogram Restrictions
- The name of an external function is a global name and must not be the same as any other global name or name local to the
subprogram whose name is that of the external function. Note that the external function name is treated as a variable
within the external function subprogram.
- The name of a dummy argument is a name local to the subprogram and must not appear in an EQUIVALENCE, PARAMETER,
SAVE, INTRINSIC or DATA statement within the same subprogram. It may appear in a COMMON
statement only as the name of a common block.
- The name of the external function can in no way, directly or indirectly, be referenced as a subprogram from within the
subprogram it defines. It can appear in a type statement to establish its type only if the type has not been established
in the FUNCTION statement.
Subroutines
A subroutine is a program unit that has a SUBROUTINE statement as it first statement. It is defined
externally to the program units that reference it. The form of a SUBROUTINE statement can be found in the
chapter entitled FORTRAN Statements.
A subroutine differs from a function in that it does not return a result and hence has no type associated with it.
However, it is possible to return values from a subroutine by defining or redefining the dummy arguments of the subroutine.
Referencing a Subroutine: The CALL Statement
Unlike a function, a subroutine cannot appear in an expression. Subroutines are referenced by using a CALL
statement. See the chapter entitled FORTRAN Statements for details on the CALL
statement. When a CALL statement is executed, the following steps are performed.
- The actual arguments are evaluated.
- The actual arguments are associated with the corresponding dummy arguments.
- The subroutine is executed.
A subroutine can be called from any subprogram but must not be called by itself, indirectly or directly.
Actual Arguments for a Subroutine
Each actual argument in a subroutine call must be one of the following.
- Any expression except a character expression involving the concatenation of an operand whose length specification is
(*) unless the operand is a symbolic constant.
- An array name.
- An intrinsic function name (must be the specific name) that has appeared in an INTRINSIC statement.
- An external procedure name.
- A dummy procedure name.
- An alternate return specifier of the form *s where s is a statement number of an executable statement
in the subprogram which contained the CALL statement. This will be covered in more detail when the RETURN
statement is discussed.
The actual arguments must agree in order, number and type with the corresponding dummy arguments. The type agreement
does not apply to an actual argument which is an alternate return specifier or a subroutine name since neither has a type.
Subroutine Subprogram Restrictions
- A subroutine subprogram can contain any statement except a FUNCTION, BLOCK DATA or PROGRAM
statement.
- The name of a subroutine is a global name and must not be used as another global name. Furthermore, no local name
in the subroutine subprogram can have the same name as the subroutine.
- The name of a dummy argument is local to the subroutine subprogram and must not appear in an EQUIVALENCE,
PARAMETER, SAVE, INTRINSIC or DATA statement. It may appear in a COMMON statement
only as the name of a common block.
The ENTRY Statement
An ENTRY statement allows execution of a subprogram to begin at a particular executable statement within the
subprogram in which it appears. An ENTRY statement defines an alternate entry point into a subprogram
and can appear anywhere after the FUNCTION statement in a function subprogram or the SUBROUTINE statement
in a subroutine subprogram. Also, it must not appear as a statement between the beginning and end of a control structure.
For example, an ENTRY statement cannot appear between a block IF statement and its corresponding
END IF statement or between a DO statement and the corresponding terminal statement. It is possible to
have more than one ENTRY statement in a subprogram. An ENTRY statement is a non-executable statement.
The form of an ENTRY statement can be found in the chapter entitled FORTRAN Statements.
Each entry name defines an external function if it appears in a function, or an external subroutine if it appears
in a subroutine and is referenced in the same way as the actual function or subroutine name would be referenced. Execution
begins at the first executable statement that follows the ENTRY statement. The order, number, type and names
of the dummy argument lists of an ENTRY statement may be different from that of a FUNCTION, SUBROUTINE
or other ENTRY statement. However, there must still be agreement between the actual argument list used to
reference an entry name and the dummy argument list in the corresponding ENTRY statement.
ENTRY Statements in External Functions
Entry names may also appear in type statements. Their type may or may not be the same type as other entry names
or the actual name of the external function unless the function is of type CHARACTER. If the function is of type CHARACTER
then the type of all the entry names must be of type CHARACTER. Conversely, if an entry name is of type CHARACTER,
then all other entry names and the function name must be of type CHARACTER. An entry name, like external function names,
is treated as a variable within the subprogram it appears. Within a function subprogram, there is an association between
variables whose name is an entry name and the variable whose name corresponds to the external function. When such a
variable becomes defined, all other such variables of the same type also become defined and other such variables not
of the same type become undefined. This can be best illustrated by an example.
Example:
PRINT *, EVAL(2), EVAL3(4.0)
END
INTEGER FUNCTION EVAL( X )
INTEGER EVAL2, X
REAL EVAL3, Y
C = 1
GOTO 10
ENTRY EVAL2( X )
C = 2
GOTO 10
ENTRY EVAL3( Y )
C = 3
10 EVAL2 = C * X
END
In the previous example, invoking EVAL would cause the result of 2 to be returned even though EVAL
was never assigned to in the function EVAL but since EVAL2 and EVAL are of the same type they
are associated and hence defining EVAL2 causes EVAL to be defined. However, invoking EVAL3
would cause an undefined result to be returned since EVAL3 is of type REAL and EVAL2 is of type INTEGER
and hence are not associated. EVAL3 does not become defined.
ENTRY Statement Restrictions
- An entry name may not appear in any statement previous to the ENTRY statement containing the entry name except
in a type statement.
- If an entry name in a function is of type CHARACTER, each entry name and the name of the function must also be of type
CHARACTER. If the name of the function or the name of any entry point has a length specification of (*), then
all such entities must have a length specification of (*) otherwise they must all have a length specification of
the same integer value.
- If a dummy argument appears in an executable statement, then that statement can be executed provided that the dummy argument
is in the dummy argument list of the procedure name referenced.
- A name that appears as a dummy argument in an ENTRY statement must not appear in the expression of a statement
function unless it is a dummy argument of the statement function, it has appeared in the dummy argument list of a FUNCTION
or SUBROUTINE statement, or the ENTRY statement appears before the statement function statement.
- A name that appears as a dummy argument in an ENTRY statement must not appear in an executable statement preceding
the ENTRY statement unless it has also appeared in a FUNCTION, SUBROUTINE, or ENTRY statement
that precedes the executable statement.
The RETURN Statement
A RETURN statement is a way to terminate the execution of a function or subroutine subprogram and return control
to the program unit that referenced it. As an extension to FORTRAN 77, Open Watcom FORTRAN 77 permits the use of the
RETURN statement in the main program. A subprogram (or main program) may contain more than one RETURN
statement or it may contain no RETURN statement. In the latter case, the END statement has the same
effect as a RETURN statement.
Execution of a RETURN or END statement causes all local entities to become undefined except for
the following.
- Entities specified in a SAVE statement.
- Entities in blank common.
- Initially defined entities that have neither been redefined nor become undefined.
- Entities in a named common block that appears in the subprogram and in a program unit that references the subprogram directly
or indirectly.
RETURN Statement in the Main Program (Extension)
The form of a RETURN statement in a main program is:
RETURN
When a RETURN statement is executed in the main program, program execution terminates in the same manner as the
STOP or END statement. This is an extension to FORTRAN 77.
RETURN Statement in Function Subprograms
The form of a RETURN statement in a function subprogram is:
RETURN
When a RETURN statement is executed in a function subprogram, the function value must be defined. Control
is then passed back to the program unit that referenced it.
RETURN Statement in Subroutine Subprograms
The form of a RETURN statement in a subroutine subprogram is:
RETURN [ e ]
- where:
-
e
- is an integer expression.
If the expression e is omitted or has a value less than one or greater than the number of asterisks appearing
in the dummy argument list of the subroutine or entry name referenced, then control is returned to the next executable statement
that follows the CALL statement in the referencing program unit. If 1 <= e <= n where
n is the number of asterisks appearing in the SUBROUTINE or ENTRY statement which contains the referenced
name, then the expression e identifies the eth asterisk in the dummy argument list. Control is returned
to the statement identified by the alternate return specified in the CALL statement that corresponds to the
eth asterisk in the dummy argument list of the referenced subroutine. The following example demonstrates the use
of alternate return specifiers in conjunction with the RETURN statement.
Example:
REAL X, Y
READ *, X, Y
CALL CMP( X, Y, *10, *20 )
PRINT *, 'X equals Y'
GOTO 30
10 PRINT *, 'X less than Y'
GOTO 30
20 PRINT *, 'X greater than Y'
30 END
SUBROUTINE CMP( X, Y, *, * )
IF( X .LT. Y )RETURN 1
IF( X .GT. Y )RETURN 2
RETURN
END
Subprogram Arguments
Arguments provide a means of communication between program units. Arguments are passed to subprograms through argument
lists and are received by subprograms through argument lists. The argument list used to pass arguments to a subprogram
is called the actual argument list and the arguments are called actual arguments. The argument list of
the receiving subprogram is called the dummy argument list and the arguments are called dummy arguments.
The actual argument list must agree with the dummy argument list in number, order and type.
Dummy Arguments
Statement function, external functions and subroutines use dummy arguments to define the type of actual arguments they
expect. A dummy argument is one of the following.
- Variable.
- Array.
- Dummy procedure.
- Asterisk (*) indicating a statement label.
Notes:
- A statement function dummy argument may only be a variable.
- An asterisk can only be a dummy argument for a subroutine subprogram.
Dummy arguments that are variables of type INTEGER can be used in dummy array declarators. No dummy argument may
appear in an EQUIVALENCE, DATA, PARAMETER, SAVE, INTRINSIC or COMMON
statement except as a common block name. A dummy argument must not be the same name as the subprogram name specified
in the FUNCTION, SUBROUTINE or ENTRY statement. Other than these restrictions, dummy arguments
can be used in the same way an actual name of the same class would be used.
Actual Arguments
Actual arguments specify the entities that are to be associated with the dummy arguments when referencing a subroutine
or function. Actual arguments can be any of the following.
- Any expression, except character expression involving the concatenation of an operand whose length specification is
(*) unless the operand is a symbolic constant.
- An array name.
- An intrinsic function name.
- An external function or subroutine name.
- A dummy procedure name.
- An alternate return specifier of the form *s where s is a statement number of an executable statement
in the subprogram which contained the CALL statement.
Notes:
- A statement function actual argument can only be a variable or an expression.
- An alternate return specifier can only be an actual argument in the actual argument list of a subroutine reference.
Association of Actual and Dummy Arguments
When a function or subroutine reference is executed, an association is established between the actual arguments and the
corresponding dummy arguments. The first dummy argument is associated with the first actual argument, the second dummy
argument is associated with the second actual argument, etc. Association requires that the types of the actual and
dummy arguments agree. A subroutine has no type and when used as an actual argument must be associated with a dummy
procedure. An alternate return specifier has no type and must be associated with an asterisk. Arguments can be
passed through more than one level of procedure reference. In this case, valid association must exist at all intermediate
levels as well as the last level. Argument association is terminated upon the execution of a RETURN or
END statement.
Length of Character Actual and Dummy Arguments
If a dummy argument is of type CHARACTER, the corresponding actual argument must also be of type CHARACTER and the length
of the dummy argument must be less than or equal to the length of the actual argument. If the length of the dummy argument
is len then the len leftmost characters of the actual argument are associated with the dummy argument.
If a dummy argument of type CHARACTER is an array name, then the restriction on the length is on the whole array and
not for each array element. The length of an array element of the dummy argument may be different from the length of
the array element of the corresponding actual array, array element, or array element substring, but the dummy array argument
must not extend beyond the end of the associated actual array.
Variables as Dummy Arguments
A dummy argument that is a variable may be associated with an actual argument that is a variable, array element, substring
or expression. Only if the actual argument is a variable, array element or substring can the corresponding actual argument
be redefined.
Arrays as Dummy Arguments
A dummy argument that is an array may be associated with an actual argument that is an array, array element or array element
substring. The number and size of the dimensions in the actual argument array declarator may be different from the
number and size of the dimensions in the dummy argument array declarator.
If the actual argument is a non-character array name, then the size of the dummy argument array must not exceed the
size of the actual argument array. An element of the actual array becomes associated with the element in the dummy
array with the same subscript value. Association by array element of character arrays exists only if the lengths of
the array elements are the same. If their lengths are not the same, the dummy and actual array elements will not consist
of the same characters.
If the actual argument is a non-character array element name whose subscript value is asv the size of the dummy
argument array must not exceed the size of the actual argument array less asv - 1. Furthermore, the dummy argument
array element whose subscript value is dsv becomes associated with the actual argument array element whose subscript
value is asv + dsv - 1. Consider the following example.
Example:
DIMENSION A(10)
CALL SAM( A(3) )
END
SUBROUTINE SAM( B )
DIMENSION B(5)
.
.
.
END
In the previous example, array A is an actual argument and the array B is the dummy argument.
Suppose we wanted to know which element of A is associated with the 4th element of B. Then asv
would have value 3 since the array element A(3) is the actual argument, and dsv is 4. Then the 4th
element in B is 3 + 4 - 1 = 6th element of A.
If the actual argument is a character array name, character array element name or character array element substring
which begins at character storage unit ach, then the character storage unit dch of the dummy argument array
is associated with the character storage unit ach + dch - 1 of the actual array. The size of the dummy character
array must not exceed the size of the actual argument array.
Procedures as Dummy Arguments
A dummy argument that is a dummy procedure can only be associated with an actual argument that is one of the following.
- Intrinsic function.
- External function.
- External Subroutine.
- Another dummy procedure.
If the dummy argument is used as a subroutine (that is it is invoked using a CALL statement) then the corresponding
actual argument must either be a subroutine or a dummy procedure. If the dummy argument is used as an external function,
then the corresponding actual argument must be an intrinsic function, external function or dummy procedure. Note that
it may not be possible to determine in a given program unit whether a dummy procedure is associated with a function or subroutine.
In the following example it is not possible to tell by looking at this program unit whether PROC is an external
subroutine or function.
Example:
SUBROUTINE SAM( PROC )
EXTERNAL PROC
.
.
CALL SAM1( PROC )
.
.
.
END
Asterisks as Dummy Arguments
A dummy argument that is an asterisk may only appear in the dummy argument list of a SUBROUTINE statement or
an ENTRY statement in a subroutine subprogram and may be associated only with an actual argument that is an alternate
return specifier in a CALL statement which references the subroutine.
Example:
CHARACTER*10 RECORD(5)
I = 2
CALL SAM( I, *999, 3HSAM )
PRINT *, 'I should be skipped'
999 PRINT *, 'I should be printed'
END
SUBROUTINE SAM( I, *, K)
CHARACTER*3 K
PRINT *, K
RETURN 1
END
Open Watcom FORTRAN 77 Extensions to Standard FORTRAN 77
This appendix summarizes the extensions supported by Open Watcom FORTRAN 77.
- The INCLUDE statement for embedding source from another file is supported.
INCLUDE 'SRC'
- Symbolic names are unique up to 32 characters. Also, '$', '_', and lowercase letters are allowed in symbolic names.
- Lowercase and uppercase letters are treated in the same way except in:
- character and hollerith constants
- apostrophe and H edit descriptors
- End-of-line comments are permitted.
PRINT *, 'Hello world' ! print 'Hello World'
- The IMPLICIT NONE statement is supported.
- An asterisk enclosed in parentheses is allowed with the type CHARACTER when specified in an IMPLICIT
statement.
IMPLICIT CHARACTER*(*) (Z)
- Length specifiers are allowed with types specified in IMPLICIT statements.
IMPLICIT INTEGER*2 (I-N)
- Length specifiers are allowed with type specification statements.
LOGICAL*1, LOGICAL*4
INTEGER*1, INTEGER*2, INTEGER*4
REAL*4, REAL*8
COMPLEX*8, COMPLEX*16
Length specifiers are also allowed with the type specified in FUNCTION statements.
COMPLEX*16 FUNCTION ZADD( X, Y )
- Length specifiers are allowed with symbol names.
INTEGER I*2, A*2(10), B(20)*2
COMPLEX FUNCTION ZADD*16( X, Y )
- The DOUBLE COMPLEX statement is supported (equivalent to COMPLEX*16).
- Double precision complex constants are allowed.
Z = (1D0, 2D0)
- Mixing operands of type DOUBLE PRECISION and COMPLEX to yield a COMPLEX*16 result is allowed.
DOUBLE PRECISION X
COMPLEX Y, Z*16
Z = X + Y
- User-defined structures are supported.
STRUCTURE/END STRUCTURE
UNION/END UNION
MAP/END MAP
RECORD
- Both character and non-character data are allowed in the same common block.
INTEGER X
CHARACTER C
COMMON /BLK/ X, C
- Data initialization of variables in common without a block data subprogram is allowed.
- Equivalencing character to non-character data is permitted.
INTEGER X
CHARACTER C
EQUIVALENCE (X, C)
- Single subscripts for multi-dimensional arrays is permitted in EQUIVALENCE statements.
- Data initialization in a type specification statement is allowed.
DOUBLE PRECISION X/4.3D1/
- Data initialization with hexadecimal constants is allowed.
INTEGER I/Z00000007/
- Initializing character items with numeric data is permitted.
- Hexadecimal and octal constants of the form 'abc'x and '567'o are supported.
- A character constant of the form 'abcdef'c places a NUL character (CHAR(0)) at the end of the character string.
- Hollerith constants can be used interchangeably with character constants.
CHARACTER*10 A, B
A = '1234567890'
B = 10H123456790
- Several additional intrinsic functions are supported:
ALGAMA ALLOCATED BTEST
CDABS
CDCOS CDSIN
CDEXP CDSQRT
CDLOG COTAN
DCMPLX DCONJG
DCOTAN DERF
DERFC DFLOAT
DGAMMA DIMAG
DLGAMA DREAL
ERF ERFC
GAMMA HFIX
IAND IBCHNG
IBCLR IBSET
IEOR IOR
ISHA ISHC
ISHFT ISHL
ISIZEOF LENTRIM
LGAMMA LOC
NOT VOLATILE
- The LOC intrinsic function returns the address of an expression.
- The ISIZEOF intrinsic function returns the size of a structure name, the size of an array with a constant array
declarator, or the size of a variable.
- The CHAR intrinsic function is allowed in constant expressions.
- The ALLOCATE and DEALLOCATE statements may be used to dynamically allocate and deallocate arrays.
- The ALLOCATED intrinsic function may be used to determine if an allocatable array is allocated.
- The following additional I/O specifiers for the OPEN statement are supported.
ACTION=
CARRIAGECONTROL=
RECORDTYPE=
RECL= is also allowed for files opened for
sequential access
ACCESS='APPEND'
BLOCKSIZE=
SHARE=
- The following additional I/O specifiers for the INQUIRE statement are supported.
ACTION=
CARRIAGECONTROL=
RECORDTYPE=
BLOCKSIZE=
SHARE=
- In the INQUIRE statement, character data may also be returned in variables or array elements with a substring
operation.
CHARACTER FN*20
INQUIRE( UNIT=1, FILE=FN(10:20) )
- List-directed I/O is allowed with internal files.
- No asterisk is required for list-directed I/O.
PRINT, X, Y
- The NAMELIST statement is supported.
- Non-character arrays are allowed as format specifiers.
- The following format edit descriptors are allowed:
- Z
- for displaying data in hexadecimal format
Ew.dDe
- same as Ew.dEe except D is used as exponentiation character
$ or \
- leave cursor at end of line
- A repeat count is not required for the X edit descriptor (a repeat count of one is assumed).
- Commas are optional between format edit descriptors.
100 FORMAT( 1X I5 )
- It is possible to substring the return values of functions and statement functions.
CHARACTER*7 F, G
F() = '1234567'
PRINT *, F()(1:3), G()(4:7)
- Functions may be invoked via the CALL statement. This allows the return value of functions to be ignored.
- A RETURN statement is allowed in the main program.
- Integer constants with more than 5 digits are allowed in the STOP and PAUSE statements.
PAUSE 123456
STOP 123456
- Multiple assignment is allowed.
X = Y = Z = 0.0
- The .XOR. operator is supported (equivalent to .NEQV.).
- The .AND., .OR., .NEQV., .EQV. and .XOR. operators may take integer
arguments. They can be used to perform bit operations on integers.
- Several additional program structure control statements are supported:
LOOP-ENDLOOP
UNTIL (can be used with WHILE and LOOP)
WHILE-ENDWILE
GUESS-ADMIT-ENDGUESS
ATENDDO-ENDATEND
ATEND
SELECT-ENDSELECT
DOWHILE-ENDDO
DO-ENDDO (no statement number)
REMOTEBLOCK-ENDBLOCK
EXECUTE
QUIT
EXIT
CYCLE
- Block labels can be used to identify blocks of code.
LOOP : OUTER_LOOP
<statements>
LOOP : INNER_LOOP
<statements>
IF( X
.GT.100 ) QUIT : OUTER_LOOP
<statements>
ENDLOOP
<statements>
ENDLOOP
- An integer expression in an IF, ELSE IF, DO WHILE, WHILE or UNTIL statement
is allowed. The result of the integer expression is compared for inequality to the integer value 0.