PROGRAMMING STANDARDS FOR THE FORTRAN PROGRAMMING TOOLS PACKAGE (FORTRAN 77 Version) November 1985 BACKGROUND Large scale computer programs, particularly when designed and coded by engineers or scientists, have a tendency to lack a clear and ordered structure. This is especially true if portions of the program are written be several different people, or if the program is modified over an extended period of time. A classic example of this was recently delivered to the author. During debugging of the program, a subroutine was found that performed a handful of arithmetic operations and then returned to the calling routine without saving the results of any of the calculations. This routine was called each time through the major control loop of the program. Inspection of the code revealed that this was most likely the result of uncontrolled evolution, perhaps by several programmers. The programming standards put forth in this document are meant to complement the concept of top-down, structured programming. The composite term "top-down, structured programming" refers to system design as well as program coding. Top-down design ensures logical arrangement of bocks of code in hierarchical order. The definition of top-down design is that, "the design of any portion of the software is independent of any heretofore undesigned portion of software." Note that this applies not only to subprograms, but also to lines of code within a subprogram. "Structured programming" is a technique in which all coding conforms to a finite number of logic structures. Although references disagree on the exact number of structures, McCabe who seems to have developed this concept to a greater degree than most others, specifies six constructs from which any structural program can be built. Furthermore, two of these constructions are variant forms of the others, leaving only four basic constructs that need by considered from a design standpoint. The reference further develops the method of reducibility as a test of truly structured code. (The method of reducibility involves continual replacement of basic constructs with a single node point. A structured code will eventually reduce to a single, sequential construct.) The programming standards put forth in this document reflect an attempt to define programming and design requirements that will enhance certain obviously desirable traits. It is anticipated that strict adherence to a properly defined set of standards will improve: transportability, reliability, legibility, maintainability, and ease of debugging. The final result of these benefits are that the product will be delivered on time, within cost requirements, and will be more thoroughly tested and validated. These goals are realistic if combined with the proper management attitude, reflected in the approach to design, coding, and testing. STANDARDS FORTRAN subprograms (i.e., Main Program, SUBROUTINE, FUNCTION, and BLOCKDATA) shall be restricted to ANS-1977 FORTRAN standards to ensure transportability and shall, additionally, adhere to the following list of standards: 1. Subprogram Characteristics a. Each subprogram shall have a unique name (i.e., the symbolic name by which the subprogram is referenced by other parts of the System must be different from any other subprogram name, variable name, or other symbolic name referenced within the System). b. The coding within a subprogram shall be related to a single, distinct function. c. A subprogram shall consist of a single compilation entity. d. As a guideline, not more than 100 lines of executable code shall be used within a single subprogram. e. A subprogram shall have only one point entry. f. A subprogram shall not invoke itself. g. When a subprogram is invoked, and upon completion of its task, it shall return to the point immediately following the invocation. Alternate (numbered) RETURNS shall not be used. h. A subprogram shall not relinquish control, except by invocation of another subprogram or by return to the subprogram that invoked it. i. A subprogram shall be documented as a unit. j. A subprogram shall be written and commented in such a manner that the code can be easily related to the System design, the requirements definition, and the subprogram or program documentation. k. A subprogram's logic shall be independent from the logic of all other sub- programs, to the maximum extent practical. l. A subprogram shall be serially reusable (i.e., assumptions shall not be made regarding any previous execution). Any values which are to be retained shall either appear in a COMMON block which appears in the main program, shall be specified in a SAVE statement, or shall be in a SAVEd COMMON block. 2. Subprogram Prologue Commentary Each subprogram shall contain a set of comment statements, the subprogram prologue, positioned immediately following the subprogram definition statement. These statements shall contain all the information necessary to evaluate the subprogram design and correlate the code with the design. Prologue commentary shall be distinguished from embedded commentary in a manner that permits retrieval by and automated tool. The format which is recommended is a "C" in column one and an asterisk ("*") in column two. The contents and order of the prologue are described in the following elements: a. Subprogram Invocation Name - Shall be the unique name as specified in la. b. Subprogram English Name - Shall be the full name or phrase from which the Subprogram Invocation Name was derived. c. Author's Name(s) - The name(s) and organizational affiliation of the subprogram designer(s) and programmer(s). d. Purpose - A very brief statement giving the general purpose of the subprogram. e. Input Arguments - Each calling sequence input argument shall be listed by name; each shall be described by: value restrictions (i.e., value range, units), type (e.g., real, integer, logical, or complex), and dimensions. f. Output Arguments - Each calling sequence output argument shall be listed by name; each shall be described by: value restrictions, type, and dimensions. g. Internal Tables/Work Areas - All nontrivial internal tables and work areas shall be described briefly. h. COMMON blocks referenced - Each externally COMMON block shall be listed by name and purpose of reference. i. Data Base or File References - Each element in the data base or on a file referenced by the subprogram shall be listed as well as the file or data element on which it resides, purpose of reference, and type of reference (i.e., read, write, replace, delete, create). If an internal file is used, its name and length shall be listed. j. External Subprogram References - All System and library subprograms invoked shall be listed. k. Error Processing - All conditions checked for error shall be identified together with the response to a detected error. l. Transportability Limitation - Any characteristics which prohibit or reduce the subprogram's transportability shall be identified. This may include language extensions, device-dependent processes, or operating system features. m. Assumption/Restrictions - All assumptions and restrictions regarding logic or data which affect other subprograms shall be specified. n. Language and Compiler used. o. Method - If applicable, the specialized method used by a subprogram to perform its major processes shall be described by a brief narrative including references in the literature, where appropriate. p. Version Number - The subprogram's present version number and date. q. Change History - The subprogram's version number for previous versions shall be followed by a very brief history of changes since the last release. Each version shall be identified with the programmer's name and affiliation and the date of that version. 3. Subprogram Organization The organization of a subprogram shall be in the following order: a. Subprogram definition statement (i.e., PROGRAM, SUBROUTINE, FUNCTION, or BLOCKDATA). The PROGRAM statement shall not be omitted from the main subprogram. b. Prologue Commentary. c. COMMON blocks. d. Specification Statements and Equivalences. e. Data Initialization Statements. f. Arithmetic Statement Function Definitions. g. Executable Statements. h. RETURN or STOP Statement. The RETURN statement shall be used in all SUBROUTINES and FUNCTIONs (ie, the END statement shall not be considered a substitute for a RETURN statement). A STOP statement shall be used to end program execution. i. Format Statements. j. END Statement. 4. Naming Conventions For the discussion in this section, "variable" shall refer to constant and parameter names as well as time-variant data. a. Variable names shall coincide as much as possible with analysis variable names as used in the subprogram or program documentation. b. All subprogram names and COMMON block names shall be six(6) or fewer characters in length. The name shall relate to the technological or analytical discipline to which it applies and/or to the functional portion of the System to which it belongs. In the case of COMMON block, the relationship shall be made to the contents of the COMMON block. All system-wide variable, subprogram, and COMMON block names shall be unique. c. All analysis variables referenced in multiple subprograms shall be assigned unique names that shall be the same in any subprogram referencing the variable (regardless of whether or not the variable is communicated between the subprograms). These unique names shall be used only to reference the corres- ponding analysis variable. Dummy arguments to utility subprograms shall not be so restricted. 5. Implementation Language Selection a. Embedded assembly language code shall not be used within FORTRAN subprograms. b. Embedded dynamic compilation statements shall not be used. c. FORTRAN 77 reserved words shall not be used as variable names even when such use is unambiguous and permitted by the compiler. Examples of illegal variable names, under this standard, include: READ , DATA , DO5 , END 6. Data and Storage Specification Statements a. Dimension Restrictions (DIMENSION, type, or COMMON statements) 1) An array shall not have more than seven dimensions. 2) If an array appears in COMMON, the array shall be dimensioned in the COMMON statement. 3) If an array does not appear in COMMON, but does appear in a type specifi- cation statement, the array shall be dimensioned in the type specification statement. b. Type Statements 1) Only LOGICAL, INTEGER, CHARACTER, REAL, DOUBLE PRECISION, and COMPLEX type statements shall be used. 2) IMPLICIT type statements shall not be used. 3) Data length qualifiers (e.g., INTEGER*4, LOGICAL*4) shall not be used, except for character data. 4) FUNCTIONs whose type disagrees with the default type of the FUNCTION name shall be typed in the FUNCTION definition statement (eg, LOGICAL FUNCTION X ( Y ) ). c. EQUIVALENCE statements 1) EQUIVALENCE statements shall be used only when their use does not conflict with the standards on uniquely defined variables. 2) The number of variables appearing in EQUIVALENCE statements shall be re- stricted to those required for tasks which can not be performed in any other manner. 3) Single-precision, floating-point variables shall not be EQUIVALENCED with double-precision, floating-point variables for the purpose of type or precision conversion. 4) Array lengths shall not be extended by EQUIVALENCE statements. 5) All array names appearing in EQUIVALENCE statements shall be subscripted (e.g., EQUIVALENCE (A(1), B(1)), rather than; EQUIVALENCE (A,B)). 6) Character and non-character data shall not be equivalenced. Character data shall not be assigned storage locations coincident with non-character data by passing of dissimilar data types or manipulation in COMMON. d. COMMON Statements 1) Blank (unlabeled) COMMON shall not be used. 2) A COMMON block shall appear in a subprogram only if the subprogram references items in the COMMON block. The exception to this rule is the inclusion of COMMON blocks in the main program for the purpose of maintaining defined values (see 1.l above). 3) If a COMMON block is included in a subprogram, it shall be included in its entirety. 4) The specification of items in a COMMON block shall be identical in name, number, length, and form each time it appears. 5) All storage assigned to complex and double-precision variables or arrays shall be on even numbered storage location (double-word boundaries.) 6) Character and non-character data shall not both appear in a COMMON block. (Note: this restriction is not required explicitly by the ANSI standard, but there are sections of the ANSI standard which refer to sharing of storage which can be interpreted as such. As a result, some compiler writers have restricted the mixing of character and non-character data resulting in a transportability problem). e. Data Initialization 1) All initialization of data in COMMON areas shall be done in BLOCKDATA subprograms. 2) All character constants shall be delimited by apostrophes; Hollerith data shall not be used. 3) The dimensions and type of variable names used in DATA statements shall be specified before the data statement . 4) No assumptions shall be made regarding the content of any variable, array, or COMMON block which has not been explicitly initialized. 7. Data and Character Values a. Binary, octal, or hexadecimal data values shall not be used in subprograms coded in FORTRAN. b. The magnitude of integer constants or integer variables shall not exceed 2,147,483,647 (2**31 - 1). c. The characters used for coding shall be restricted to the following set of 49 characters: A through Z ( O through 9 ) + b (blank) - . * = / , (comma) $ : ' (single quote) d. The characters used for text and data shall be restricted to characters in item c plus the additional characters: > ? < ; ! & " e. To the maximum extent possible, processing based on the number of characters per word shall be avoided. 8. Parameterization Parameterization is defined as the specification of global constant in a single location such that all other references to the item are by name only. a. The use of constants in executable statements shall be limited to integer numbers and whole floating-point numbers. All other constants shall be parameterized. b. Internal, computer-oriented characteristics (e.g., word and character size) shall be parameterized. c. System-dependent characteristics (e.g., number of lines per page, number of fields per card) shall be parameterized. d. Input/output device-oriented characteristics (e.g., unit numbers) shall be parameterized. 9. Comments a. All comment cards shall begin with a "C" in card column 1. b. Commentary shall not appear on the same line as any other FORTRAN statement. c. Comment cards shall not immediately precede any statement continuation cards. d. Each block of consecutive comment cards shall be preceded and followed by a blank comment card ("C" in column 1, blanks in column 2 through 72). e. Subprogram prologue commentary shall contain an asterisk in card column 2. No other commentary shall contain an asterisk in card column 2. f. Blank cards shall not be used as comment cards (i.e., a card without identifi- cation as to its purpose as a comment card. g. Statements or subfunctions that are dependent on unique peripheral, computer, or operating system architectural considerations shall be clearly identified by commentary indicating this dependency and shall be restricted to single sub- program that is clearly identified. 10. Statement Formats and Labels a. Statement Restrictions 1) Multiple assignment statements shall not be used (e.g., A=B=C is not permitted). 2) Vector assignment statements shall not be used (e.g., A=B where A and B are dimensioned arrays is not permitted). 3) CONTINUE statements shall always be assigned a statement number. 4) Specification Type statements shall not be mixed on a single card image. 5) Sequencing or identification information on source code shall be restricted to numerical values or numerical values with an alphanumerical identifier attached. The numerical values shall monotonically increase within a subprogram. 6) A card image shall be defined as 80 contiguous character images; the first 72 of which contain the coding and the last eight (8) are reserved for sequencing or identification information. b. Statement Labels 1) All statement labels shall be integer numbers greater than zero. 2) All statement numbers shall end in column 5. 3) Initial numbering of statements shall begin with 10 and shall increase in increments of 10. Subsequent changes requiring the insertion of labeled statements shall take advantage of intermediate numbers; e.g., 100 statement 110 statement 115 revised or inserted statement 120 statement 4) The block of statement numbers beginning with the digit 9 and having 3 or more digits (i.e., 900-999, 9000-9999, 90000-99999) shall be reserved for FORMAT statements. 5) Statement numbers within a subprogram shall be assigned in ascending order from beginning to end. 6) Statement numbers assigned to FORMAT statements shall be assigned in ascending order based upon the order of initial reference within the subprogram. 7) All FORMAT statements shall be grouped together immediately following the executable code and shall be in ascending order. c. Statement Continuation 1) Continuation shall be marked in column 6. The character '0' shall not be used. 2) No more than 19 continuation lines shall be used for any FORTRAN statement. 3) The continuation of arithmetic statements shall occur only after the following operators: * - + / = 4) Statement continuation shall not occur within an index expression (e.g., (25*I+1)). 11. Code Indentation a. Statements in the outermost hierarchy of decision paths shall begin in column 7. b. Each successively nested decision path or loop shall be indented three columns to the right of the higher level decision path. c. Continuation cards shall begin one column to the right of the initial statement. d. ELSE and ENDIF statements shall be indented to the same level as the correspon- ding IF statement. e. Indentation shall be used to clarify subprogram logic or structure, by excessive indentation, which tends to confuse the reader, shall be avoided. As a guide- line, more than 6 levels of indentation shall not be used. This probably would indicate excessively convoluted logic. 12. Subprogram Interface a. Non-standard returns (e.g., RETURN 2) shall not be used. b. The type specification of an external function in the invoking subprogram shall be consistent with the type specification in the invoked subprogram. c. The number and type of arguments shall be identical in the invoking statement and subprogram definition statement. 13. Addressing a. Subscript expressions shall be restricted to the following seven (7) forms: i*K+k J-k i*J-k J i*J k J+K where i and k are integer constants and J is an integer variable. b. Subscript values shall be greater than zero but not greater than 131,071 (2**15 - 1). c. Array references shall always be subscripted except in CALL, Subprogram Definition, READ, or WRITE Statements. 14. Loop Processing a. DO-loop control parameters shall be integer constants or non-array integer variables. b. The value of an integer DO-loop control parameter shall be greater than -131,071 and not greater than 131,071. c. Each DO-loop shall end on a unique CONTINUE statement. d. Branching into a DO-loop from outside of the loop or branching out of a DO-loop and then back in shall not be permitted. e. The level of nesting of DO-loops and "IF-loops: (looping as the result of a conditional GOTO statement) shall not exceed six(6) levels. f. The modification of DO-loop control parameters or index shall not be permitted within a DO-loop. 15. Control Processing a. The ASSIGN statement shall not be used. ASSIGNed GOTO statements shall not be used. b. Arithmetic IF statements shall be used only for three-way branches in which each branch is to a unique statement number. c. Logical IF or Block IF statements shall be used for all two-way branches. d. The label(s) specified in an arithmetic IF, a GOTO, or a computed GOTO shall be below the statement causing the branching. The only exception shall be the implementation of a DO-UNTIL via a conditional GOTO; in this case the DO-UNTIL loop shall be clearly labeled with commentary describing the loop. The DO-UNTIL loop construct shall be restricted to functions for which limits can not be determined during System design (e.g., interactive decision paths). 16. Computational Processing a. When a whole number is used as an exponent, the exponent shall be expressed as an integer. b. The use of .5 as an exponent shall be prohibited. SQRT shall be used instead because of the increased efficiency and accuracy. c. There shall be no mixed-mode arithmetic expressions (other than the use of integer exponents.). d. Assumptions shall not be made regarding the results of a division by zero. e. Conversion between single and double precision numbers shall be restricted to the SNGL and DBLE library functions. 17. Input/Output Processing a. The NAMELIST capability shall not be used. b. PRINT and PUNCH statements shall not be used. c. Device-oriented statements shall not be used (e.g., READ TAPE, READ ECS). d. Buffer control statements (e.g., BUFFERIN/BUFFEROUT) shall not be used. e. Explicit record identification in READ or WRITE statements shall not be used (e.g., READ(8=4), READ(8'16, 10)). f. Integer variables shall be used for all unit references. g. No function invocations shall be permitted in the I/O list for a write statement except for FORTRAN intrinsic functions. h. All sequential files written by the System shall be closed with an ENDFILE or CLOSE statement before stopping or referencing with a REWIND statement. i. There shall be no explicit messages to the computer operator's console. j. Format Statements. 1) Fixed character strings shall be delimited by apostrophes. 2) Hexadecimal, octal, and binary conversion codes shall not be used. 3) Only the "D" and "G" data conversions shall be used for reading double- precision values. 4) Carriage control characters shall be restricted to 0, 1, blank and +. The ASCII formfeed (decimal 12) and linefeed (decimal 10) characters may be used in files which support these characters. 18. Computer Dependencies a. Processing that is dependent on internal number representations shall be prohibited. b. Processing that is dependent on internal hardware characteristics or architecture shall be avoided. c. Processing that is dependent on special timing knowledge shall be avoided. 19. Miscellaneous a. Arithmetic statement functions whose type is not implicit shall be "typed" in the function definition statement; e.g., DOUBLE PRECISION ABC (X) = ... rather than DOUBLE PRECISION ABC ABC (X) = ... b. Data encoding and decoding instructions (e.g., ENCODE, DECODE) shall not be used. c. The PAUSE statement shall not be used. d. Calls to the EXIT, DUMP, or PDUMP standard FORTRAN subprograms shall not be included in a subprogram. e. Every subprogram shall have a STOP or RETURN statement; an END statement shall not be treated as executable. VAX ADDENDUM The following VAX FORTRAN extensions shall be permitted in transportable code as a special exception, and subject to any stated restrictions, on the basis that the capability is widely available or can be readily converted by automated means. 1. "D" comment cards. 2. "!" comments, with the restriction that the exclamation point can not be used for any other purpose (except within LITERAL text constants) within the program. 3. Character data and non-character data may be mixed in a single COMMON block if all character data appears before all non-character data. 4. Calls to the system DATE and TIME routine. 5. Lower case letters may be used in string constants. Lower case letters may also be used in the coding but, since it may be required to use the CAPITAL program to make the code transportable, all characters in the file will be capitalized. 6. The INCLUDE statement may be used. Note, the INCLUDER program may be used to standardize sources with included files. 7. The SAVE statement may safely be omitted. 8. The CARRIAGECONTROL keyword may be used in OPEN statements.