Supported Fortran Common Extensions

The front end accepts the FORTRAN 77 language defined by ANSI X3.9-1978. It also accepts the features described in MIL-STD-1753, the military standard supplement to that document.

The following extensions are accepted (these are flagged if the -A option is specified):

INCLUDE

The INCLUDE statement, in the form
    
    INCLUDE 'file-name'

This causes the source text in the indicated file to be compiled at the point of the INCLUDE statement. INCLUDE files may be nested. The file file-name is searched for in several directories; see the documentation of the -I option for details. If the file is not found, compilation is terminated with a catastrophic error.

The INCLUDE statement must be alone on a single line, i.e., it may not be continued and it may not share the line with other statements separated from it by semicolons. If the statement is labeled, the label is ignored. (The INCLUDE statement is part of MIL-STD-1753.)

Hexadecimal and octal constants

Hexadecimal and octal constants, in two forms each. The MIL-STD-1753 (and Fortran 90) form is

    O'7777'
    Z'FFFF'

for octal and hexadecimal constants, respectively. Somewhat surprisingly, the apostrophes do not enclose a "character context," which means that extra blanks may be used within the constant to improve readability.

The VAX/VMS form for these constants is

      '7777'O
    'FFFF'X

In this case, the apostrophes do enclose a character context (since one cannot distinguish such a constant from a character constant until after the closing apostrophe).

In both forms, the case of letters is not significant. Any of these constants may appear anywhere an arithmetic expression may appear. (The MIL-STD-1753 restriction to DATA statements is not enforced.) They may be as large as the largest arithmetic type, which is usually the largest COMPLEX type. Hexadecimal and octal constants have no intrinsic type; they acquire a type based on context. If such a constant appears as an operand of a two-operand operation, and the other operand has a type, the constant is given the type of the other operand. In all other cases, the constant is converted to the default INTEGER type.

Hollerith constants

Hollerith constants have the form

      countHcharacters

The count indicates the number of characters following the H. For example, 5Habcde is a hollerith constant containing 5 characters. A hollerith constant may appear anywhere an arithmetic or logical expression may appear. It is given a type according to the rules given above for hexadecimal and octal constants, with the exceptions that (a) a hollerith constant may be given a logical type, and (b) when a hollerith constant is used as an actual argument or a format, it is left typeless (the address of the first character is passed, but no conversion is done). The maximum size allowed for a hollerith constant is ordinarily the size of the largest arithmetic or logical type, but when a hollerith constant is passed as an actual argument, there is no limit except the restriction on statement size.

Hollerith constants and non-character arrays may be used as FORMAT specifiers in I/O statements.

Long identifiers

Identifiers are not limited to 6 characters. They may have any length, subject only to the overall statement size restrictions, and all characters are significant (external names will be truncated in object code to conform to any host system restrictions). The case of letters in identifiers is not ordinarily significant, but can be made significant by the -U option. The characters $ and _ may be used in identifiers, but not as the first character.

Lines shorter or longer than 72 characters

Lines shorter or longer than 72 characters allowed in the default fixed form. No blanks are assumed on the ends of lines shorter than 72 columns, so in

      v = 'abc
    1def'

the c is considered to be next to the d if the first line ends at the c.

Comments to end-of-line indicated by !

Comments to end-of-line indicated by !. Any characters following the ! on the same line are ignored. Continuation lines following such comments continue the statement, not the comment. If a ! is the first nonblank character on a line, the line is treated as a comment line and is ignored. However, a ! in column 6 in fixed form is treated as a continuation indication rather than a comment indication.

Horizontal tabs in input lines

In character contexts, tabs are significant characters (i.e., a tab character within a character constant produces a tab character in the string). Outside of character contexts, tab characters are treated like blanks, and are ignored. In fixed form, a tab in the first 6 columns is handled specially: if it is followed by a nonzero digit, the line is taken to be a continuation line, with the character following the nonzero digit considered to be in column 7. If the tab is not followed by a nonzero digit, the line is taken to be an initial line, with the character following the tab considered to be in column 7.

The DLINES option

In fixed form, a line with a D or d in column 1 is ordinarily considered to be a comment. If the -D option is specified, such lines are compiled as if column 1 contained a blank. This allows programs to contain debugging code that can be selectively included or excluded by a command-line option.

Semicolons as statement separators

Several statements may be put on one line, or in one fixed-form "statement," by separating them with semicolons. The semicolon is a separator, so a semicolon should not be placed after the final statement. Two or more semicolons with only blanks between them are treated the same as a single semicolon.

Free-form source

When the -F option is specified, source is in free form. This is the new source form of Fortran 90 drafts. Source lines do not have fixed size; they may be up to 132 characters long. C and * comments are not allowed; ! must be used. There are no columns with special meanings. Statements begin in column 1. They may be continued to additional lines by ending each line with a &. If the first nonblank character of the next line is also a &, the statement continues with the character following the &; otherwise, the statement continues with the first nonblank character of the continuation line. In a non-character context, the & on the line being continued may be followed by blanks and an end-of-line comment.

Blanks are significant in free form. They are not allowed in the middle of tokens, except for keywords that are compound words (e.g., both ENDIF and END IF are accepted). Blanks are required to separate adjacent tokens that could otherwise be taken as a single token (e.g., INTEGER I). The double-& form of continuation continues a token onto the next line (this is required, for example, to continue character constants); the single-& form causes a token break.

Any statement that may be labeled in fixed form may also be labeled in free form, by putting the numeric label at the start of the statement (since no statement in Fortran begins with a digit, this is always unambiguous). Unlike in fixed form, statements following semicolons may also be labeled.

#line directives

#line directives are lines generated by C preprocessors to preserve information about where source lines originally came from. They have the form

     #line line-number "file-name"

indicating that the source line following the directive came originally from the indicated line of the indicated file. That information will thereafter be used in generating the positions for errors and for symbolic debug information. file-name (and the quotes) may be omitted to indicate no change in the file name. The keyword line may also be omitted. Anything following the file-name on the line is ignored. Except for its position-indicating function, a line directive is treated as a comment line.

IMPLICIT NONE

This statement eliminates implicit typing except for intrinsic functions. All variables, functions, etc., must therefore be explicitly typed. IMPLICIT NONE may appear in a program unit at the position where other IMPLICIT statements would appear. However, no other IMPLICIT statements are allowed if IMPLICIT NONE is specified. (This is a MIL-STD-1753 extension.)

Interspersed DATA statements

DATA statements are allowed to appear intermixed with specification statements in addition to the standard places (i.e., intermixed with statement function definitions and executable statements). All specifications relating to a variable must appear before any DATA statement that initializes that variable.

DOUBLE COMPLEX

The type name DOUBLE COMPLEX may be used wherever a type name is allowed, i.e., a type-specification statement, IMPLICIT, and FUNCTION. It represents a COMPLEX type whose real and imaginary components have type DOUBLE PRECISION. The intrinsic functions DIMAG and DCMPLX provide double-precision complex versions of the standard AIMAG and CMPLX intrinsic functions.

Length specifications on data types

Data types in FUNCTION and type-specification statements with associated length specifications:

      INTEGER*2 FUNCTION(X)
    REAL*8 X

The size indicates the size in bytes of the data item. Only certain combinations of data type and size are allowed; see the section on configuration. A length may be specified for INTEGER, LOGICAL, REAL, COMPLEX, and CHARACTER (the CHARACTER case is not an extension; it's part of FORTRAN 77). DOUBLE PRECISION and DOUBLE COMPLEX may not have their lengths specified. REAL*n is the same as DOUBLE PRECISION for some configuration-dependent value of n (usually 8).

The length specification has the same syntax as the character length specification in the FORTRAN 77 standard. That is, a length specification is a * followed by either (a) an integer constant, or (b) an integral constant expression enclosed in parentheses. In type-specification statements, both the statement type and each variable may have a length:

     INTEGER*2 I*4, J, K(5)*4

(I is INTEGER*4, J is INTEGER*2, and K is an array of 5 elements, each of which is INTEGER*4. When both a length and an array dimension appear, as in the last case, either the dimension may appear first (K(5)*4, which is compatible with the UNIX f77 compiler) or the length may appear first (K*4(5), which is compatible with VAX/VMS FORTRAN). For CHARACTER items, the dimension must appear first (as required by FORTRAN 77). The length specification at the beginning of a type-specification statement may be followed by a comma, by analogy with the standard CHARACTER statement.

Integer constants considered "unsized"

Integer constants considered "unsized," and given a size on the basis of context. If such a constant is used as an operand of a two-operand operation, and the other operand is not an unsized integer, the unsized constant is converted to the type of the other operand. If the other operand is an unsized integer, or if the unsized constant is the operand of a unary operator, the operation is done on the unsized integer(s) and the result is considered still an unsized integer constant. In all other cases, the unsized integer is converted to the default INTEGER type.

Pointer variables

The statement

    POINTER (P, A)

declares P as a pointer variable, and A as a variable based on that pointer. P may not be dimensioned, may not be given a type, and may not appear as the second operand in a POINTER statement. It may appear as the first operand in another pointer specification. A may be a simple variable or an array, of arithmetic, logical, or character type. It may not be a dummy argument, a function result variable, a constant, a function, or a subroutine. It may not be EQUIVALENCEd, placed in COMMON, or SAVEd. If A is dimensioned, it may have adjustable bounds or an assumed size. The adjustable bound expressions will be computed on entry to the subprogram, as is done for dummy argument adjustable array bounds. No storage is allocated for A. Its address is always given by the value of P.

The statement allows specification of more than one pointer, and may include an array declarator on the second operand:

    POINTER (P, A), (P2, A2), (P3, A3(100))

The LOC function may be used to create a pointer value:

    P = LOC(X)

This sets P to the address of X. A pointer value may have an integer expression added to or subtracted from it, and the result is a pointer value:

    P2 = P + 500

The integer expression is treated as a byte offset relative to the original pointer, i.e., P2 points 500 bytes past where P points.

A pointer may also be given an integer constant value:

    P = 0

(A DATA statement may be used instead.)

Smallest integer

The smallest (most negative) integer on a twos' complement machine may be used, even though its specification is an expression that negates the (too-large) absolute value of that constant.

Expressions combining COMPLEX and DOUBLE PRECISION

COMPLEX and DOUBLE PRECISION expressions may be combined in expressions, without explicit type conversions, and in general any size of COMPLEX may be combined with any size of REAL. In such cases, both operands of the operation are converted to a type that is COMPLEX with a component precision that is equal to the larger of the precisions involved. For example, if a COMPLEX*8 (component precision: 4) is combined with a REAL*8 (precision: 8), both are converted to COMPLEX*16 before the operation is done, and the result has type COMPLEX*16.

Consecutive arithmetic operators

Consecutive arithmetic operators, as in

    X = A**-B
    X = A+-B

The FORTRAN 77 standard does not allow those cases.

DO WHILE

The DO WHILE statement (part of MIL-STD-1753). Its form is

    DO WHILE (logical-expression)
    ...
    END DO

The enclosed statements are executed repeatedly as long as the logical-expression is true. The test is done before the first iteration, so the enclosed statements may be executed not at all. A label may be given on the DO WHILE; if it is supplied, the END DO must be labeled with the same label:

    DO label, WHILE (logical-expression)
    ...
    label END DO

The comma following the label in the above is optional.

A labeled DO WHILE may also be terminated by a labeled statement that is not an END DO, as is done in the standard DO. The usual restrictions on the type of the terminal statement apply. (This feature is not part of MIL-STD-1753.)

END DO

An END DO statement may also be used to terminate a standard DO statement:

    DO 11111 I = 1, 10
    ...
    11111 END DO

Or, omitting the label (this is not part of MIL-STD-1753),

    DO I = 1, 10
    ...
    END DO

A labeled END DO may terminate several DO or DO WHILE statements, but otherwise each END DO terminates exactly one DO or DO WHILE. (MIL-STD-1753 requires that each DO WHILE be terminated by a separate END DO; this front end does not.)

One-trip DO loops

If the -l option is specified, normal DO loops (not DO WHILE loops) are forced to execute the enclosed statements at least once. This is provided for compatibility with some FORTRAN 66 compilers.

Long constants in STOP and PAUSE statements

A display constant that is a string of digits may be longer than 5 digits. It's not interpreted as an integer constant, so it may also be longer than is allowed for integer constants.

Function or subroutine may be used as a procedural actual argument

A function or subroutine may be used as a procedural actual argument without appearing in an EXTERNAL statement if it has been called previously in the program unit.

Octal and hexadecimal conversion in FORMATs

In FORMATs, the O and Z edit descriptors are recognized for octal and hexadecimal conversion, respectively. The syntax is the same as for the I edit descriptor, with I replaced by O or Z. That is,

    Ow
    Ow.m
    Zw
    Zw.m

The processing is likewise the same, except for the number base for the conversions.

The ENCODE and DECODE statements

ENCODE is similar to an internal-file WRITE, and DECODE is similar to an internal-file READ. Their form is:

    ENCODE(buf-size, format, buf, IOSTAT=svar, ERR=label) io-list
    DECODE(buf-size, format, buf, IOSTAT=svar, ERR=label) io-list

format is the label of the FORMAT statement that will direct the formatting. buf is a variable or array name whose size in bytes is at least buf-size. The IOSTAT and ERR clauses are optional. If IOSTAT is specified, svar is set to a positive integer if an error occurs, or to zero if no error occurs. If ERR is specified, control is transferred to label if an error occurs (it must be the label of an executable statement). io-list is an optional input/output list with the same syntax as for the READ and WRITE statements.

For ENCODE, the variables in io-list are converted from internal form to character form according to the format, and the resulting characters are placed in buf. If fewer than buf-size characters are written, the remaining characters are set to blanks.

For DECODE, the characters in buf are converted to internal form according to the format, and placed in the variables in io-list. At most buf-size characters are converted.

For either statement, the formatting must not require more than one record.

Bit-manipulation

The bit-manipulation intrinsics of MIL-STD-1753:

    IOR(m, n) 
returns m or-ed with n.

    IAND(m, n)
returns m and-ed with n.

    NOT(m)
returns the logical complement of m.

    IEOR(m, n)
returns m exclusive-or-ed with n.

    ISHFT(m, k)
returns m shifted left k bits (if k is positive) or shifted right -k bits (if k is negative)

    ISHFTC(m, k, ic)
returns m shifted circularly left k bits (if k is positive) or shifted circularly right -k bits (if k is negative)

    IBITS(m, i, len)
returns len bits of m starting from bit i as the least-significant bit (bits are numbered according to the power of two they represent).

    CALL MVBITS(m, i, len, n, j)
moves len bits of m starting from bit i as the least-significant bit to len bits of n starting at bit j as the least significant bit.

    BTEST(n, i)
returns .TRUE. if bit i of n is a 1, .FALSE. otherwise.

    IBSET(n, i)
returns n with bit i set to 1.

   IBCLR(n, i)
returns n with bit i set to 0.

These routines may not be passed as actual arguments.

Other extensions

The following extensions are also supported:

Character and non-character variables mixed in COMMON blocks.

Named COMMON blocks initialized in any program unit, not just in a BLOCK DATA. Blank COMMON initialized in any program unit.

Functions and subroutines are allowed to call themselves recursively (see the configuration flag TARG_RECURSION_ALLOWED). Statement functions may not be recursive.

List-directed formatting may be used with internal-file input/output.

In character values given as the values of input/output specifiers, lower-case letters are accepted and considered the same as the corresponding upper-case letters.