A Portable Fortran 77 Compiler S. I. Feldman P. J. Weinberger Bell Laboratories Murray Hill, New Jersey 07974 J. Berkman University of California Berkeley, CA 94720 _A_B_S_T_R_A_C_T The Fortran language has been revised. The new language, known as Fortran 77, became an official American National Standard on April 3, 1978. We report here on a compiler and run-time system for the new extended language. It is believed to be the first complete Fortran 77 system to be implemented. This com- piler is designed to be portable, to be correct and complete, and to generate code compatible with calling sequences produced by C compilers. In particular, this Fortran is quite usable on UNIX* systems. In this paper, we describe the language compiled, interfaces between procedures, and file formats assumed by the I/O system. Appendix A describes the Fortran 77 language extensions. This is a standard Bell Laboratories document reproduced with minor modifications to the text. The Bell Laboratory's appendix on ``Differences Between Fortran 66 and Fortran 77'' has been changed to Appendix A, and a local appendix has been added. Appendix B contains a list of Fortran 77 references (some from the original Bell docu- ment and some added at Berkeley). Revised September, 1985 __________________________ * UNIX is a Trademark of Bell Laboratories. - 2 - _1. _I_N_T_R_O_D_U_C_T_I_O_N _1. _I_n_t_r_o_d_u_c_t_i_o_n The Fortran language has been revised. The new language, known as Fortran 77, became an official American National Standard [1] on April 3, 1978. Fortran 77 supplants 1966 Standard Fortran [2]. We report here on a compiler and run-time system for the new extended language. The compiler and computation library were written by S.I.F., the I/O sys- tem by P.J.W. We believe ours to be the first complete For- tran 77 system to be implemented. This compiler is designed to be portable to a number of different machines, to be correct and complete, and to generate code compatible with calling sequences produced by compilers for the C language [3]. In particular, it is in use on UNIX systems. Two fam- ilies of C compilers are in use at Bell Laboratories, those based on D. M. Ritchie's PDP-11 compiler [4] and those based on S. C. Johnson's portable C compiler [5]. This Fortran compiler can drive the second passes of either family. In this paper, we describe the language compiled, interfaces between procedures, and file formats assumed by the I/O sys- tem. We will describe implementation details in companion papers. _1._1. _U_s_a_g_e _1._1. _U_s_a_g_e At present, versions of the compiler run on and compile for the PDP-11, the VAX-11/780, and the Interdata 8/32 UNIX systems. The command to run the compiler is f77 _f_l_a_g_s _f_i_l_e . . . _f_7_7 is a general-purpose command for compiling and loading Fortran and Fortran-related files. EFL [6] and Ratfor [7] source files will be preprocessed before being presented to the Fortran compiler. C and assem- bler source files will be compiled by the appropriate programs. Object files will be loaded. (The _f_7_7 and _c_c commands cause slightly different loading sequences to be generated, since Fortran programs need a few extra libraries and a different startup routine than do C programs.) The following file name suffixes are understood: .f Fortran source file .F Fortran source file .e EFL source file .r Ratfor source file .c C source file .s Assembler source file .o Object file Arguments whose names end with .f are taken to be - 4 - Fortran 77 source programs; they are compiled, and each object program is left on the file in the current directory whose name is that of the source with .o sub- stituted for .f. Arguments whose names end with .F are also taken to be Fortran 77 source programs; these are first processed by the C preprocessor before being compiled by f77. Arguments whose names end with .r or .e are taken to be Ratfor or EFL source programs, respectively; these are first transformed by the appropriate preprocessor, then compiled by f77. In the same way, arguments whose names end with .c or .s are taken to be C or assembly source programs and are compiled or assembled, producing a .o file. The following flags are understood: 9 -c Compile but do not load. Output for _x._f, _x._F, _x._e, _x._r, _x._c, or _x._s is put on file _x._o. 9 -d Used in debugging the compiler. 9 -g Have the compiler produce additional symbol table information for _d_b_x(_1). This flag is incompatible with -O. See section 1.4 for more details. 9 -i2 On machines which support short integers, make the default integer constants and variables short (see section 2.14). (-i4 is the standard value of this option). All logical quantities will be short. 9 -m Apply the M4 macro preprocessor to each EFL or Ratfor source file before using the appropriate compiler. 9 -o _f_i_l_e Put executable module on file _f_i_l_e. (Default is a.out). 9 -onetrip or -1 Compile code that performs every _d_o loop at least once (see section 2.12). 9 -p Generate code to produce usage profiles. 9 -pg Generate code in the manner of -p, but invoke a run-time recording mechanism that keeps more extensive statistics. See _g_p_r_o_f(1). 9 -q Suppress printing of file names and program unit names during compilation. 9 -r8 Treat all floating point variables, constants, functions and intrinsics as double precision and all complex quantities as double complex. 9 - 5 - See section 2.17. 9 -u Make the default type of a variable _u_n_d_e_f_i_n_e_d (see section 2.3). 9 -v Print the version number of the compiler and the name of each pass. 9 -w Suppress all warning messages. 9 -w66 Suppress warnings about Fortran 66 features used. 9 -C Compile code that checks that subscripts are within array bounds. For multi-dimensional arrays, only the equivalent linear subscript is checked. 9 -D_n_a_m_e=_d_e_f 9 -D_n_a_m_e Define the _n_a_m_e to the C preprocessor, as if by `#define'. If no definition is given, the name is defined as "1". (.F files only). 9 -E_s_t_r Use the string _s_t_r as an EFL option in process- ing .e files. 9 -F Ratfor, EFL, and .F source files are pre- processed into .f files, and those .f files are left on the disk without being compiled. 9 -I_d_i_r `#include' files whose names do not begin with `/' are always sought first in the directory of the _f_i_l_e argument, then in directories named in -I options, then in directories on a standard list. (.F files only). 9 -N[qxscn]_n_n_n Make static tables in the compiler bigger. The compiler will complain if it overflows its tables and suggest you apply one or more of these flags. These flags have the following meanings: q Maximum number of equivalenced variables. Default is 150. x Maximum number of external names (common block names, subroutine and function names). Default is 200. s Maximum number of statement numbers. Default is 401. c Maximum depth of nesting for control statements (e.g. DO loops). Default is 20. n Maximum number of identifiers. Default is 1009. 9 - 6 - -O Invoke the object code optimizer. Incompatible with -g. 9-R_s_t_r Use the string _s_t_r as a Ratfor option in processing .r files. 9-U Do not convert upper case letters to lower case. The default is to convert Fortran programs to lower case except within character string constants. 9-S Generate assembler output for each source file, but do not assemble it. Assembler output for a source file _x._f, _x._F, _x._e, _x._r, or _x._c is put on file _x._s. Other flags, all library names (arguments beginning -l), and any names not ending with one of the under- stood suffixes are passed to the loader. _1._2. _D_o_c_u_m_e_n_t_a_t_i_o_n _C_o_n_v_e_n_t_i_o_n_s _1._2. _D_o_c_u_m_e_n_t_a_t_i_o_n _C_o_n_v_e_n_t_i_o_n_s In running text, we write Fortran keywords and other literal strings in boldface lower case. Examples will be presented in lightface lower case. Names represent- ing a class of values will be printed in italics. _1._3. _I_m_p_l_e_m_e_n_t_a_t_i_o_n _S_t_r_a_t_e_g_y _1._3. _I_m_p_l_e_m_e_n_t_a_t_i_o_n _S_t_r_a_t_e_g_y The compiler and library are written entirely in C. The compiler generates C compiler intermediate code. Since there are C compilers running on a variety of machines, relatively small changes will make this For- tran compiler generate code for any of them. Further- more, this approach guarantees that the resulting pro- grams are compatible with C usage. The runtime compu- tational library is complete. The runtime I/O library makes use of D. M. Ritchie's Standard C I/O package [8] for transferring data. With the few exceptions described below, only documented calls are used, so it should be relatively easy to modify to run on other operating systems. _1._4. _D_e_b_u_g_g_i_n_g _A_i_d_s _1._4. _D_e_b_u_g_g_i_n_g _A_i_d_s A memory image is sometimes written to a file core in the current directory upon abnormal termination for errors caught by the f77 libraries, user calls to abort, and certain signals (see sigvec(2) in the _U_N_I_X _P_r_o_g_r_a_m_m_e_r'_s _M_a_n_u_a_l). Core is normally created only if the -g flag was specified to f77 during loading.|- The __________________________ |-Specify -g when loading with cc or f77; specify -lg as a library when using ld directly. 9 - 7 - source-level debugger _d_b_x(1) may be used with the exe- cutable and the _c_o_r_e file to examine the image and determine what went wrong. In the event that it is necessary to override this default behavior, the user may set the environment variable f77_dump_flag. If f77_dump_flag is set to a value beginning with n, a core file is not produced regardless of whether -g was specified at compile time, and if the value begins with y, dumps are produced even if -g was not specified. _2. _L_A_N_G_U_A_G_E _E_X_T_E_N_S_I_O_N_S _2. _L_a_n_g_u_a_g_e _E_x_t_e_n_s_i_o_n_s Fortran 77 includes almost all of Fortran 66 as a subset. We describe the differences briefly in Appendix A. The most important additions are a character string data type, file- oriented input/output statements, and random access I/O. Also, the language has been cleaned up considerably. In addition to implementing the language specified in the new Standard, our compiler implements a few extensions described in this section. Most are useful additions to the language. The remainder are extensions to make it easier to communicate with C procedures or to permit compilation of old (1966 Standard) programs. _2._1. _D_o_u_b_l_e _C_o_m_p_l_e_x _D_a_t_a _T_y_p_e _2._1. _D_o_u_b_l_e _C_o_m_p_l_e_x _D_a_t_a _T_y_p_e The new type _d_o_u_b_l_e _c_o_m_p_l_e_x is defined. Each datum is represented by a pair of double precision real values. The statements z1 = ( 0.1d0, 0.2d0 ) z2 = dcmplx( dx, dy ) assign double complex values to z1 and z2. The double precision values which constitute the double complex value may be isolated by using dreal or dble for the real part and imag or dimag for the imaginary part. To compute the double complex conjugate of a double com- plex value, use conjg or dconjg. The other double com- plex intrinsic functions may be accessed using their generic names or specific names. The generic names are: abs, sqrt, exp, log, sin, and cos. The specific names are the same as the generic names preceded by either cd or z, e.g. you may code sqrt, zsqrt or cdsqrt to compute the square root of a double complex value. _2._2. _I_n_t_e_r_n_a_l _F_i_l_e_s _2._2. _I_n_t_e_r_n_a_l _F_i_l_e_s The Fortran 77 standard introduces ``internal files'' - 8 - (memory arrays), but restricts their use to formatted sequential I/O statements. Our I/O system also permits internal files to be used in formatted direct reads and writes and list directed sequential read and writes. _2._3. _I_m_p_l_i_c_i_t _U_n_d_e_f_i_n_e_d _S_t_a_t_e_m_e_n_t _2._3. _I_m_p_l_i_c_i_t _U_n_d_e_f_i_n_e_d _S_t_a_t_e_m_e_n_t Fortran 66 has a fixed rule that the type of a variable that does not appear in a type statement is _i_n_t_e_g_e_r if its first letter is i, j, k, l, m or n, and _r_e_a_l other- wise. Fortran 77 has an _i_m_p_l_i_c_i_t statement for over- riding this rule. As an aid to good programming prac- tice, we permit an additional type, _u_n_d_e_f_i_n_e_d. The statement implicit undefined(a-z) turns off the automatic data typing mechanism, and the compiler will issue a diagnostic for each variable that is used but does not appear in a type statement. Specifying the -_u compiler flag is equivalent to begin- ning each procedure with this statement. _2._4. _R_e_c_u_r_s_i_o_n _2._4. _R_e_c_u_r_s_i_o_n Procedures may call themselves, directly or through a chain of other procedures. Since Fortran variables are by default _s_t_a_t_i_c, it is often necessary to use the _a_u_t_o_m_a_t_i_c storage extension to prevent unexpected results from recursive functions. _2._5. _A_u_t_o_m_a_t_i_c _S_t_o_r_a_g_e _2._5. _A_u_t_o_m_a_t_i_c _S_t_o_r_a_g_e Two new keywords are recognized, _s_t_a_t_i_c and _a_u_t_o_m_a_t_i_c. These keywords may appear as ``types'' in type state- ments and in _i_m_p_l_i_c_i_t statements. Local variables are static by default; there is only one instance of the variable. For variables declared _a_u_t_o_m_a_t_i_c, there is a separate instance of the variable for each invocation of the procedure. Automatic variables may not appear in _e_q_u_i_v_a_l_e_n_c_e, _d_a_t_a, or _s_a_v_e statements. Neither type of variable is guaranteed to retain its value between calls to a subprogram (see the save statement in Appen- dix A). _2._6. _S_o_u_r_c_e _I_n_p_u_t _F_o_r_m_a_t _2._6. _S_o_u_r_c_e _I_n_p_u_t _F_o_r_m_a_t The Standard expects input to the compiler to be in 72-column format: except in comment lines, the first five characters are the statement number, the next is - 9 - the continuation character, and the next 66 are the body of the line. (If there are fewer than 72 charac- ters on a line, the compiler pads it with blanks; char- acters after the seventy-second are ignored.) In order to make it easier to type Fortran programs, our compiler also accepts input in variable length lines. An ampersand ``&'' in the first position of a line indicates a continuation line; the remaining char- acters form the body of the line. A tab character in one of the first six positions of a line signals the end of the statement number and continuation part of the line; the remaining characters form the body of the line. A tab elsewhere on the line is treated as another kind of blank by the compiler. In the Standard, there are only 26 letters - Fortran is a one-case language. Consistent with ordinary UNIX system usage, our compiler expects lower case input. By default, the compiler converts all upper case char- acters to lower case except those inside character con- stants. However, if the -_U compiler flag is specified, upper case letters are not transformed. In this mode, it is possible to specify external names with upper case letters in them, and to have distinct variables differing only in case. If -U is specified, keywords will only be recognized in lower case. _2._7. _I_n_c_l_u_d_e _S_t_a_t_e_m_e_n_t _2._7. _I_n_c_l_u_d_e _S_t_a_t_e_m_e_n_t The statement include 'stuff' is replaced by the contents of the file _s_t_u_f_f; _i_n_c_l_u_d_e statements may be nested to a reasonable depth, currently ten. _2._8. _B_i_n_a_r_y _I_n_i_t_i_a_l_i_z_a_t_i_o_n _C_o_n_s_t_a_n_t_s _2._8. _B_i_n_a_r_y _I_n_i_t_i_a_l_i_z_a_t_i_o_n _C_o_n_s_t_a_n_t_s A variable may be initialized in a _d_a_t_a statement by a binary constant, denoted by a letter followed by a quoted string. If the letter is b, the string is binary, and only zeroes and ones are permitted. If the letter is o, the string is octal, with digits 0-7. If the letter is z or x, the string is hexadecimal, with digits 0-9, a-f. Thus, the statements integer a(3) data a / b'1010', o'12', z'a' / initialize all three elements of _a to ten. - 10 - _2._9. _C_h_a_r_a_c_t_e_r _S_t_r_i_n_g_s _2._9. _C_h_a_r_a_c_t_e_r _S_t_r_i_n_g_s For compatibility with C usage, the following backslash escapes are recognized: \n newline \t tab \b backspace \f form feed \0 null \' apostrophe (does not terminate a string) \" quotation mark (does not terminate a string) \\ \ \_x _x, where _x is any other character Fortran 77 only has one quoting character, the apos- trophe. Our compiler and I/O system recognize both the apostrophe `` ' '' and the double-quote `` " ''. If a string begins with one variety of quote mark, the other may be embedded within it without using the repeated quote or backslash escapes. Each character string constant appearing outside a _d_a_t_a statement is followed by a null character to ease com- munication with C routines. _2._1_0. _H_o_l_l_e_r_i_t_h _2._1_0. _H_o_l_l_e_r_i_t_h Fortran 77 does not have the old Hollerith ``_nh'' nota- tion, though the new Standard recommends implementing the old Hollerith feature in order to improve compati- bility with old programs. In our compiler, Hollerith data may be used in place of character string con- stants, and may also be used to initialize non- character variables in _d_a_t_a statements. _2._1_1. _E_q_u_i_v_a_l_e_n_c_e _S_t_a_t_e_m_e_n_t_s _2._1_1. _E_q_u_i_v_a_l_e_n_c_e _S_t_a_t_e_m_e_n_t_s As a very special and peculiar case, Fortran 66 permits an element of a multiply-dimensioned array to be represented by a singly-subscripted reference in _e_q_u_i_v_a_l_e_n_c_e statements. Fortran 77 does not permit this usage, since subscript lower bounds may now be different from 1. Our compiler permits single sub- scripts in _e_q_u_i_v_a_l_e_n_c_e statements, under the interpre- tation that all missing subscripts are equal to 1. A warning message is printed for each such incomplete subscript. - 11 - _2._1_2. _O_n_e-_T_r_i_p _D_O _L_o_o_p_s _2._1_2. _O_n_e-_T_r_i_p _D_O _L_o_o_p_s The Fortran 77 Standard requires that the range of a _d_o loop not be performed if the initial value is already past the limit value, as in do 10 i = 2, 1 The 1966 Standard stated that the effect of such a statement was undefined, but it was common practice that the range of a _d_o loop would be performed at least once. In order to accommodate old programs, though they were in violation of the 1966 Standard, the -_o_n_e_t_r_i_p or -_1 compiler flags causes non-standard loops to be generated. _2._1_3. _C_o_m_m_a_s _i_n _F_o_r_m_a_t_t_e_d _I_n_p_u_t _2._1_3. _C_o_m_m_a_s _i_n _F_o_r_m_a_t_t_e_d _I_n_p_u_t The I/O system attempts to be more lenient than the Standard when it seems worthwhile. When doing a for- matted read of non-character variables, commas may be used as value separators in the input record, overrid- ing the field lengths given in the format statement. Thus, the format (i10, f20.10, i4) will read the record -345,.05e-3,12 correctly. _2._1_4. _S_h_o_r_t _I_n_t_e_g_e_r_s _2._1_4. _S_h_o_r_t _I_n_t_e_g_e_r_s On machines that support halfword integers, the com- piler accepts declarations of type _i_n_t_e_g_e_r*_2. (Ordi- nary integers follow the Fortran rules about occupying the same space as a real variable; they are assumed to be of C type _l_o_n_g _i_n_t; halfword integers are of C type _s_h_o_r_t _i_n_t.) An expression involving only objects of type _i_n_t_e_g_e_r*_2 is of that type. Generic functions return short or long integers depending on the actual types of their arguments. If a procedure is compiled using the -_i_2 flag, all small integer constants will be of type _i_n_t_e_g_e_r*_2. If the precision of an integer- valued intrinsic function is not determined by the gen- eric function rules, one will be chosen that returns the prevailing length (integer*2 when the -i2 command flag is in effect). When the -_i_2 option is in effect, all quantities of type _l_o_g_i_c_a_l will be short. Note - 12 - that these short integer and logical quantities do not obey the standard rules for storage association. _2._1_5. _A_d_d_i_t_i_o_n_a_l _I_n_t_r_i_n_s_i_c _F_u_n_c_t_i_o_n_s _2._1_5. _A_d_d_i_t_i_o_n_a_l _I_n_t_r_i_n_s_i_c _F_u_n_c_t_i_o_n_s This compiler supports all of the intrinsic functions specified in the Fortran 77 Standard. In addition, there are built-in functions for performing bitwise logical and boolean operations on integer and logical values (or, and, xor, not, lshift, and rshift), and intrinsic functions for double complex values (see sec- tion 2.1). The f77 library contains many other func- tions, such as accessing the UNIX command arguments (getarg and iargc) and environment (getenv). See intro(3f) and bit(3f) in the _U_N_I_X _P_r_o_g_r_a_m_m_e_r'_s _M_a_n_u_a_l for more information. _2._1_6. _N_a_m_e_l_i_s_t _I/_O _2._1_6. _N_a_m_e_l_i_s_t _I/_O Namelist I/O provides an easy way to input and output information without formats. Although not part of the standard, namelist I/O was part of many Fortran 66 sys- tems and is a common extension to Fortran 77 systems. Variables and arrays to be used in namelist I/O are declared as part of a namelist in a namelist statement, e.g.: character str*12 logical flags(20) complex c(2) real arr1(2,3), arr2(0:3,4) namelist /basic/ arr1, arr2, key, str, c /flglst/ key, flags This defines two namelists: list basic consists of variables key and str and arrays arr1, arr2, and c; list flglst consists of variable key and array flags. A namelist can include variables and arrays of any type, and a variable or array may be in several dif- ferent namelists. However dummy arguments and array elements may not be in a namelist. A namelist name may be used in external sequential read, write and print statements wherever a format could be used. In a namelist read, column one of each data record is ignored. The data begins with an ampersand in column 2 followed by the namelist name and a blank. Then there is a sequence of value assignments separated by commas and finally an ``&end''. A simple example of input data corresponding to namelist basic is: &basic key=5, str='hi there' &end - 13 - For compatibility with other systems, dollar signs may be used instead of the ampersands: $basic key=5, str='hi there' $end A value assignment in the data record must be one of three forms. The simplest is a variable name followed by an equal sign followed by a data value which is assigned to that variable, e.g. ``key=5''. The second form consists of an array name followed by ``='' fol- lowed by one or more values to be assigned to the array, e.g.: c=(1.1,-2.9),(-1.8e+10,14.0e-3) assigns values to c(1) and c(2) in the complex array c. As in other read statements, values are assigned in the order of the array in memory, i.e. column-major order for two dimensional arrays. Multiple copies of a value may be represented by a repetition count followed by an asterisk followed by the value; e.g. ``3*55.4'' is the same as ``55.4, 55.4, 55.4''. It is an error to specify more values than the array can hold; if less are specified, only that number of elements of the array are changed. The third form of a value assign- ment is a subscripted variable name followed by ``='' followed by a value or values, e.g.: ``arr2(0,4)=15.2''. Only integer constant subscripts may be used. The correct number of subscripts must be used and the subscripts must be legal. This form is the same as the form with an array name except the array is filled starting at the named element. In all three forms, the variable or array name must be declared in the namelist. The form of the data values is the same as in list directed input except that in namelist I/O, character strings in the data must be enclosed in apostrophes or double quotes, and repeti- tion counts must be followed by data values. One use of namelist input is to read in a list of options or flags. For example: - 14 - logical flags(14) namelist /pars/ flags, iters, xlow, xhigh, xinc data flags/14*.false./ 10 read(5,pars,end=900) print pars call calc( xlow, xhigh, xinc, flags, iters ) go to 10 900 continue end could be run with the following data (each record begins with a space): &pars iters=10, xlow=0.0, xhigh=1.0, xinc=0.1 &end &pars xinc=0.2, flags(2)=2*.true., flags(8)=.true. &end &pars xlow=2.0, xhigh=8.0 &end The program reads parameters for the run from the first data set and computes using them. Then it loops and each successive set of namelist input data specifies only those data items which need to be changed. Note the second data set sets the 278_n_d999, 378_r_d999, and 878_t_h999 elements in the array flags to .true.. When a namelist name is used in a write or print state- ment, all the values in the namelist are output together with their names. For example the print in the program above prints the following: &pars flags= f, f, f, f, f, f, f, f, f, f, f, f, f, f, iters= 10, xlow= 0., xhigh= 1.00000, xinc= 0.100000 &end &pars flags= f, t, t, f, f, f, f, t, f, f, f, f, f, f, iters= 10, xlow= 0., xhigh= 1.00000, xinc= 0.200000 &end &pars flags= f, t, t, f, f, f, f, t, f, f, f, f, f, f, iters= 10, xlow= 2.00000, xhigh= 8.00000, xinc= 0.200000 &end Each line begins with a space so that namelist output can be used as input to a namelist read. The default is to use ampersands in namelist print and write. How- ever, dollar signs will be used if the last preceding namelist read data set used dollar signs. The charac- ter to be used is stored as the first character of the common block namelistkey. - 15 - _2._1_7. _A_u_t_o_m_a_t_i_c _P_r_e_c_i_s_i_o_n _I_n_c_r_e_a_s_e _2._1_7. _A_u_t_o_m_a_t_i_c _P_r_e_c_i_s_i_o_n _I_n_c_r_e_a_s_e The -r8 flag allows a user to run a program with increased precision without changing any of the program source, i.e. it allows a user to take a program coded in single precision and compile and execute it as if it had been coded in double precision. The option extends the precision of all single precision real and complex constants, variables, external functions, and intrinsic functions. For example, the source: implicit complex(c) real last intrinsic sin, csin data last/0.3/ x = 0.1 y = sqrt(x)+sqrt(last) c1 = (0.1,0.2) c2 = sqrt(c1) x = real(i) y = aimag(c1) call fun(sin,csin) is compiled under this flag as if it had been written as: implicit double precision (a-b,d-h,o-z), double complex(c) double precision last intrinsic dsin, cdsin data last/0.3d0/ x = 0.1d0 y = sqrt(x)+sqrt(last) c1 = (0.1d0,0.2d0) c2 = sqrt(c1) x = dreal(i) y = dimag(c1) call fun(dsin,cdsin) When the -r8 flag is invoked, the calls using the gen- eric name sqrt will refer to a different specific func- tion since the types of the arguments have changed. This option extends the precision of all single preci- sion real and complex variables and functions, includ- ing those declared real*4 and complex*8. In order to successfully use this flag to increase pre- cision, the entire program including all the subrou- tines and functions it calls must be recompiled. Pro- grams which use dynamic memory allocation or use equivalence or common statements to associate variables of different types may have to be changed by hand. - 16 - Similar caveats apply to the sizes of records in unfor- matted I/O. _2._1_8. _C_h_a_r_a_c_t_e_r_s _a_n_d _I_n_t_e_g_e_r_s _2._1_8. _C_h_a_r_a_c_t_e_r_s _a_n_d _I_n_t_e_g_e_r_s A character constant of integer length or less may be assigned to an integer variable. Individual bytes are packed into the integer in the native byte order. The character constant is padded with blanks to the width of the integer during the assignment. Use of this feature is deprecated; it is intended only as a porting aid for extended Fortran 66 programs. Note that the intrinsic _i_c_h_a_r function behaves as the standard requires, converting only single bytes to integers. _3. _V_I_O_L_A_T_I_O_N_S _O_F _T_H_E _S_T_A_N_D_A_R_D _3. _V_i_o_l_a_t_i_o_n_s _o_f _t_h_e _S_t_a_n_d_a_r_d We know only a few ways in which our Fortran system violates the new standard: _3._1. _D_o_u_b_l_e _P_r_e_c_i_s_i_o_n _A_l_i_g_n_m_e_n_t _3._1. _D_o_u_b_l_e _P_r_e_c_i_s_i_o_n _A_l_i_g_n_m_e_n_t The Fortran Standards (both 1966 and 1977) permit _c_o_m_- _m_o_n or _e_q_u_i_v_a_l_e_n_c_e statements to force a double preci- sion quantity onto an odd word boundary, as in the fol- lowing example: real a(4) double precision b,c 9 equivalence (a(1),b), (a(4),c) Some machines (e.g., Honeywell 6000, IBM 360) require that double precision quantities be on double word boundaries; other machines (e.g., IBM 370), run ineffi- ciently if this alignment rule is not observed. It is possible to tell which equivalenced and common vari- ables suffer from a forced odd alignment, but every double precision argument would have to be assumed on a bad boundary. To load such a quantity on some machines, it would be necessary to use separate opera- tions to move the upper and lower halves into the halves of an aligned temporary, then to load that dou- ble precision temporary; the reverse would be needed to store a result. We have chosen to require that all double precision real and complex quantities fall on even word boundaries on machines with corresponding hardware requirements, and to issue a diagnostic if the source code demands a violation of the rule. 9 - 17 - _3._2. _D_u_m_m_y _P_r_o_c_e_d_u_r_e _A_r_g_u_m_e_n_t_s _3._2. _D_u_m_m_y _P_r_o_c_e_d_u_r_e _A_r_g_u_m_e_n_t_s If any argument of a procedure is of type character, all dummy procedure arguments of that procedure must be declared in an _e_x_t_e_r_n_a_l statement. This requirement arises as a subtle corollary of the way we represent character string arguments and of the one-pass nature of the compiler. A warning is printed if a dummy pro- cedure is not declared _e_x_t_e_r_n_a_l. Code is correct if there are no _c_h_a_r_a_c_t_e_r arguments. _3._3. _T _a_n_d _T_L _F_o_r_m_a_t_s _3._3. _T _a_n_d _T_L _F_o_r_m_a_t_s The implementation of the _t (absolute tab) and _t_l (leftward tab) format codes is defective. These codes allow rereading or rewriting part of the record which has already been processed (section 6.3.2 in Appendix A). The implementation uses seeks, so if the unit is not one which allows seeks, such as a terminal, the program is in error. A benefit of the implementation chosen is that there is no upper limit on the length of a record, nor is it necessary to predeclare any record lengths except where specifically required by Fortran or the operating system. _3._4. _C_a_r_r_i_a_g_e _C_o_n_t_r_o_l _3._4. _C_a_r_r_i_a_g_e _C_o_n_t_r_o_l The Standard leaves as implementation dependent which logical unit(s) are treated as ``printer'' files. In this implementation there is no printer file and thus by default, no carriage control is recognized on for- matted output. This can be changed using form='print' in the open statement for a unit, or by using the fpr(1) filter for output; see [9]. _3._5. _A_s_s_i_g_n_e_d _G_o_t_o _3._5. _A_s_s_i_g_n_e_d _G_o_t_o The optional _l_i_s_t associated with an assigned _g_o_t_o statement is not checked against the actual assigned value during execution. _4. _I_N_T_E_R-_P_R_O_C_E_D_U_R_E _I_N_T_E_R_F_A_C_E _4. _I_n_t_e_r-_P_r_o_c_e_d_u_r_e _I_n_t_e_r_f_a_c_e To be able to write C procedures that call or are called by Fortran procedures, it is necessary to know the conventions for procedure names, data representation, return values, and argument lists that the compiled code obeys. - 18 - _4._1. _P_r_o_c_e_d_u_r_e _N_a_m_e_s _4._1. _P_r_o_c_e_d_u_r_e _N_a_m_e_s On UNIX systems, the name of a common block or a For- tran procedure has an underscore appended to it by the compiler to distinguish it from a C procedure or exter- nal variable with the same user-assigned name. Fortran built-in procedure names have embedded underscores to avoid clashes with user-assigned subroutine names. _4._2. _D_a_t_a _R_e_p_r_e_s_e_n_t_a_t_i_o_n_s _4._2. _D_a_t_a _R_e_p_r_e_s_e_n_t_a_t_i_o_n_s The following is a table of corresponding Fortran and C declarations: _F_o_r_t_r_a_n _C 9 integer*2 x short int x; integer x long int x; logical x long int x; real x float x; double precision x double x; complex x struct { float r, i; } x; double complex x struct { double dr, di; } x; character*6 x char x[6]; (By the rules of Fortran, _i_n_t_e_g_e_r, _l_o_g_i_c_a_l, and _r_e_a_l data occupy the same amount of memory.) _4._3. _A_r_r_a_y_s _4._3. _A_r_r_a_y_s The first element of a C array always has subscript zero, while Fortran arrays begin at 1 by default. For- tran arrays are stored in column-major order in con- tiguous storage, C arrays are stored in row-major order. Many mathematical libraries have subroutines which transpose a two dimensional matrix, e.g. f01crf in the NAG library and vtran in the IMSL library. These may be used to transpose a two-dimensional array stored in C in row-major order to Fortran column-major order or vice-versa. _4._4. _R_e_t_u_r_n _V_a_l_u_e_s _4._4. _R_e_t_u_r_n _V_a_l_u_e_s A function of type _i_n_t_e_g_e_r, _l_o_g_i_c_a_l, _r_e_a_l, or _d_o_u_b_l_e _p_r_e_c_i_s_i_o_n declared as a C function returns the corresponding type. A _c_o_m_p_l_e_x or _d_o_u_b_l_e _c_o_m_p_l_e_x func- tion is equivalent to a C routine with an additional initial argument that points to the place where the return value is to be stored. Thus, 9 - 19 - complex function f( . . . ) is equivalent to f_(temp, . . .) struct { float r, i; } *temp; . . . A character-valued function is equivalent to a C rou- tine with two extra initial arguments: a data address and a length. Thus, character*15 function g( . . . ) is equivalent to g_(result, length, . . .) char result[ ]; long int length; . . . and could be invoked in C by char chars[15]; . . . g_(chars, 15L, . . . ); Subroutines are invoked as if they were integer-valued functions whose value specifies which alternate return to use. Alternate return arguments (statement labels) are not passed to the function, but are used to do an indexed branch in the calling procedure. (If the sub- routine has no entry points with alternate return argu- ments, the returned value is undefined.) The statement call nret(*1, *2, *3) is treated exactly as if it were the computed _g_o_t_o goto (1, 2, 3), nret( ) _4._5. _A_r_g_u_m_e_n_t _L_i_s_t_s _4._5. _A_r_g_u_m_e_n_t _L_i_s_t_s All Fortran arguments are passed by address. In addi- tion, for every argument that is of type character or that is a dummy procedure, an argument giving the length of the value is passed. (The string lengths are _l_o_n_g _i_n_t quantities passed by value.) The order of arguments is then: - 20 - Extra arguments for complex and character functions Address for each datum or function A long int for each character or procedure argument Thus, the call in external f character*7 s integer b(3) . . . call sam(f, b(2), s) is equivalent to that in int f(); char s[7]; long int b[3]; . . . sam_(f, &b[1], s, 0L, 7L); _4._6. _S_y_s_t_e_m _I_n_t_e_r_f_a_c_e _4._6. _S_y_s_t_e_m _I_n_t_e_r_f_a_c_e To run a Fortran program, the system invokes a small C program which first initializes signal handling, then calls f_init to initialize the Fortran I/O library, then calls your Fortran main program, and then calls f_exit to close any Fortran files opened. f_init initializes Fortran units 0, 5, and 6 to stan- dard error, standard input, and standard output respec- tively. It also calls setlinebuf to initiate line buffering of standard error. If you are using Fortran subroutines which may do I/O and you have a C main pro- gram, call f_init before calling the Fortran subrou- tines. Otherwise, Fortran units 0, 5, and 6 will be connected to files fort.0, fort.5, and fort.6, and error messages from the f77 libraries will be written to fort.0 instead of to standard error. If your C pro- gram terminates by calling the C function exit, all files are automatically closed. If there are Fortran scratch files to be deleted, first call f_exit. F_init and f_exit do not have any arguments. The -d flag will show what libraries are used in load- ing Fortran programs. _5. _F_I_L_E _F_O_R_M_A_T_S _5. _F_i_l_e _F_o_r_m_a_t_s - 21 - _5._1. _S_t_r_u_c_t_u_r_e _o_f _F_o_r_t_r_a_n _F_i_l_e_s _5._1. _S_t_r_u_c_t_u_r_e _o_f _F_o_r_t_r_a_n _F_i_l_e_s Fortran requires four kinds of external files: sequen- tial formatted and unformatted, and direct formatted and unformatted. On UNIX systems, these are all imple- mented as ordinary files which are assumed to have the proper internal structure. Fortran I/O is based on _r_e_c_o_r_d_s. When a direct file is opened in a Fortran program, the record length of the records must be given, and this is used by the Fortran I/O system to make the file look as if it is made up of records of the given length. In the special case that the record length is given as 1, the files are not con- sidered to be divided into records, but are treated as byte-addressable byte strings; that is, as ordinary UNIX file system files. (A read or write request on such a file keeps consuming bytes until satisfied, rather than being restricted to a single record.) The peculiar requirements on sequential unformatted files make it unlikely that they will ever be read or written by any means except Fortran I/O statements. Each record is preceded and followed by an integer con- taining the record's length in bytes. The Fortran I/O system breaks sequential formatted files into records while reading by using each newline as a record separator. The result of reading off the end of a record is undefined according to the Standard. The I/O system is permissive and treats the record as being extended by blanks. On output, the I/O system will write a newline at the end of each record. It is also possible for programs to write newlines for them- selves. This is an error, but the only effect will be that the single record the user thought he wrote will be treated as more than one record when being read or backspaced over. _5._2. _P_o_r_t_a_b_i_l_i_t_y _C_o_n_s_i_d_e_r_a_t_i_o_n_s _5._2. _P_o_r_t_a_b_i_l_i_t_y _C_o_n_s_i_d_e_r_a_t_i_o_n_s The Fortran I/O system uses only the facilities of the standard C I/O library, a widely available and fairly portable package, with the following two nonstandard features: the I/O system needs to know whether a file can be used for direct I/O, and whether or not it is possible to backspace. Both of these facilities are implemented using the _f_s_e_e_k routine, so there is a rou- tine _c_a_n_s_e_e_k which determines if _f_s_e_e_k will have the desired effect. Also, the _i_n_q_u_i_r_e statement provides the user with the ability to find out if two files are the same, and to get the name of an already opened file - 22 - in a form which would enable the program to reopen it. Therefore there are two routines which depend on facil- ities of the operating system to provide these two ser- vices. In any case, the I/O system runs on the PDP-11, VAX-11/780, and Interdata 8/32 UNIX systems. _5._3. _L_o_g_i_c_a_l _U_n_i_t_s _a_n_d _F_i_l_e_s _5._3. _L_o_g_i_c_a_l _U_n_i_t_s _a_n_d _F_i_l_e_s Fortran logical unit numbers may be any integer between 0 and 99. The number of simultaneously open files is currently limited to 48. Units 5, 6, and 0 are connected before the program begins to standard input, standard output, and standard error respectively. If an unit is opened explicitly by an open statement with a file= keyword, then the file name is the name from the open statement. Otherwise, the default file name corresponding to unit _n is fort._n. If there is an environment variable whose name is the same as the tail of the file name after periods are deleted, then the contents of that environment variable are used as the name of the file. See [9] for details. The default connection for all units is for sequential formatted I/O. The Standard does not specify where a file which has been explicitly opened for sequential I/O is initially positioned. The I/O system will posi- tion the file at the beginning. Therefore a _w_r_i_t_e will destroy any data already in the file, but a _r_e_a_d will work reasonably. To position a file to its end, use a read loop, or the system dependent function fseek. The preconnected units 0, 5, and 6 are positioned as they come from the program's parent process. - 23 - _A_P_P_E_N_D_I_X _A: _D_i_f_f_e_r_e_n_c_e_s _B_e_t_w_e_e_n _F_o_r_t_r_a_n _6_6 _a_n_d _F_o_r_t_r_a_n _7_7 _A_p_p_e_n_d_i_x _A. _D_i_f_f_e_r_e_n_c_e_s _B_e_t_w_e_e_n _F_o_r_t_r_a_n _6_6 _a_n_d _F_o_r_t_r_a_n _7_7 The following is a very brief description of the differences between the 1966 [2] and the 1977 [1] Standard languages. We assume that the reader is familiar with Fortran 66. We do not pretend to be complete, precise, or unbiased, but plan to describe what we feel are the most important aspects of the new language. The best current information on the 1977 Standard is in publications of the X3J3 Subcommittee of the American National Standards Institute, and the ANSI X3.9-1978 document, the official description of the language. The Standard is written in English rather than a meta-language, but it is forbidding and legalistic. A number of tutorials and textbooks are available (see Appen- dix B). _1. _F_e_a_t_u_r_e_s _D_e_l_e_t_e_d _f_r_o_m _F_o_r_t_r_a_n _6_6 _1. _F_e_a_t_u_r_e_s _D_e_l_e_t_e_d _f_r_o_m _F_o_r_t_r_a_n _6_6 _1._1. _H_o_l_l_e_r_i_t_h _1._1. _H_o_l_l_e_r_i_t_h All notions of ``Hollerith'' (_nh) as data have been officially removed, although our compiler, like almost all in the foreseeable future, will continue to support this archaism. _1._2. _E_x_t_e_n_d_e_d _R_a_n_g_e _o_f _D_O _1._2. _E_x_t_e_n_d_e_d _R_a_n_g_e _o_f _D_O In Fortran 66, under a set of very restrictive and rarely-understood conditions, it is permissible to jump out of the range of a _d_o loop, then jump back into it. Extended range has been removed in the Fortran 77 language. The restrictions are so special, and the implementation of extended range is so unreliable in many compilers, that this change really counts as no loss. _2. _P_r_o_g_r_a_m _F_o_r_m _2. _P_r_o_g_r_a_m _F_o_r_m _2._1. _B_l_a_n_k _L_i_n_e_s _2._1. _B_l_a_n_k _L_i_n_e_s Completely blank lines are now legal comment lines. _2._2. _P_r_o_g_r_a_m _a_n_d _B_l_o_c_k _D_a_t_a _S_t_a_t_e_m_e_n_t_s _2._2. _P_r_o_g_r_a_m _a_n_d _B_l_o_c_k _D_a_t_a _S_t_a_t_e_m_e_n_t_s A main program may now begin with a statement that gives that program an external name: - 24 - program work Block data procedures may also have names. block data stuff There is now a rule that only _o_n_e unnamed block data procedure may appear in a program. (This rule is not enforced by our system.) The Standard does not specify the effect of the program and block data names, but they are clearly intended to aid conventional loaders. _2._3. _E_N_T_R_Y _S_t_a_t_e_m_e_n_t _2._3. _E_N_T_R_Y _S_t_a_t_e_m_e_n_t Multiple entry points are now legal. Subroutine and function subprograms may have additional entry points, declared by an _e_n_t_r_y statement with an optional argu- ment list. entry extra(a, b, c) Execution begins at the first statement following the _e_n_t_r_y line. All variable declarations must precede all executable statements in the procedure. If the pro- cedure begins with a _s_u_b_r_o_u_t_i_n_e statement, all entry points are subroutine names. If it begins with a _f_u_n_c_- _t_i_o_n statement, each entry is a function entry point, with type determined by the type declared for the entry name. If any entry is a character-valued function, then all entries must be. In a function, an entry name of the same type as that where control entered must be assigned a value. Arguments do not retain their values between calls. (The ancient trick of calling one entry point with a large number of arguments to cause the procedure to ``remember'' the locations of those argu- ments, then invoking an entry with just a few arguments for later calculation, is still illegal. Furthermore, the trick doesn't work in our implementation, since arguments are not kept in static storage.) _2._4. _D_O _L_o_o_p_s _2._4. _D_O _L_o_o_p_s _d_o variables and range parameters may now be of integer, real, or double precision types. (The use of floating point _d_o variables is very dangerous because of the possibility of unexpected roundoff, and we strongly recommend against their use.) The action of the _d_o statement is now defined for all values of the _d_o parameters. The statement do 10 i = l, u, d - 25 - performs max(0,|(_u-_l+_d)/_d|) iterations. The _d_o vari- able has a predictable value when exiting a loop: the value at the time a _g_o_t_o or _r_e_t_u_r_n terminates the loop; otherwise the value that failed the limit test. _2._5. _A_l_t_e_r_n_a_t_e _R_e_t_u_r_n_s _2._5. _A_l_t_e_r_n_a_t_e _R_e_t_u_r_n_s In a _s_u_b_r_o_u_t_i_n_e or subroutine _e_n_t_r_y statement, some of the arguments may be noted by an asterisk, as in subroutine s(a, *, b, *) The meaning of the ``alternate returns'' is described in section 5.2 of Appendix A. _3. _D_e_c_l_a_r_a_t_i_o_n_s _3. _D_e_c_l_a_r_a_t_i_o_n_s _3._1. _C_H_A_R_A_C_T_E_R _D_a_t_a _T_y_p_e _3._1. _C_H_A_R_A_C_T_E_R _D_a_t_a _T_y_p_e One of the biggest improvements to the language is the addition of a character-string data type. Local and common character variables must have a length denoted by a constant expression: character*17 a, b(3,4) character*(6+3) c If the length is omitted entirely, it is assumed equal to 1. A character string argument may have a constant length, or the length may be declared to be the same as that of the corresponding actual argument at run time by a statement like character*(*) a (There is an intrinsic function _l_e_n that returns the actual length of a character string.) Character arrays and common blocks containing character variables must be packed: in an array of character variables, the first character of one element must follow the last character of the preceding element, without holes. _3._2. _I_M_P_L_I_C_I_T _S_t_a_t_e_m_e_n_t _3._2. _I_M_P_L_I_C_I_T _S_t_a_t_e_m_e_n_t The traditional implied declaration rules still hold: a variable whose name begins with i, j, k, l, m, or n is of type integer; other variables are of type _r_e_a_l, unless otherwise declared. This general rule may be overridden with an _i_m_p_l_i_c_i_t statement: implicit real(a-c,g), complex(w-z), character*(17) (s) - 26 - declares that variables whose name begins with an a ,b, c, or g are _r_e_a_l, those beginning with w, x, y, or z are assumed _c_o_m_p_l_e_x, and so on. It is still poor prac- tice to depend on implicit typing, but this statement is an industry standard. _3._3. _P_A_R_A_M_E_T_E_R _S_t_a_t_e_m_e_n_t _3._3. _P_A_R_A_M_E_T_E_R _S_t_a_t_e_m_e_n_t It is now possible to give a constant a symbolic name, as in character str*(*) parameter (x=17, y=x/3, pi=3.14159d0, str='hello') The type of each parameter name is governed by the same implicit and explicit rules as for a variable. Sym- bolic names for character constants may be declared with an implied length ``(*)''. The right side of each equal sign must be a constant expression (an expression made up of constants, operators, and already defined parameters). _3._4. _A_r_r_a_y _D_e_c_l_a_r_a_t_i_o_n_s _3._4. _A_r_r_a_y _D_e_c_l_a_r_a_t_i_o_n_s Arrays may now have as many as seven dimensions. (Only three were permitted in 1966.) The lower bound of each dimension may be declared to be other than 1 by using a colon. Furthermore, an adjustable array bound may be an integer expression involving constants, arguments, and variables in _c_o_m_m_o_n. real a(-5:3, 7, m:n), b(n+1:2*n) The upper bound on the last dimension of an array argu- ment may be denoted by an asterisk to indicate that the upper bound is not specified: integer a(5, *), b(*), c(0:1, -2:*) _3._5. _S_A_V_E _S_t_a_t_e_m_e_n_t _3._5. _S_A_V_E _S_t_a_t_e_m_e_n_t A little known rule of Fortran 66 is that variables in a procedure do not necessarily retain their values between invocations of that procedure. This rule per- mits overlay and stack implementations for the affected variables. In Fortran 77, three types of variables automatically keep there values: variables in blank common, variables defined in data statements and never changed, and variables in named common blocks which have not become undefined. At any instant in the - 27 - execution of a program, if a named common block is declared neither in the currently executing procedure nor in any of the procedures in the chain of callers, all of the variables in that common block become unde- fined. Fortran 77 permits one to specify that certain variables and common blocks are to retain their values between invocations. The declaration save a, /b/, c leaves the values of the variables _a and _c and all of the contents of common block _b unaffected by an exit from the procedure. The simple declaration save has this effect on all variables and common blocks in the procedure. A common block must be saved in every procedure in which it is declared if the desired effect is to occur. _3._6. _I_N_T_R_I_N_S_I_C _S_t_a_t_e_m_e_n_t _3._6. _I_N_T_R_I_N_S_I_C _S_t_a_t_e_m_e_n_t All of the functions specified in the Standard are in a single category, ``intrinsic functions'', rather than being divided into ``intrinsic'' and ``basic external'' functions. If an intrinsic function is to be passed to another procedure, it must be declared _i_n_t_r_i_n_s_i_c. Declaring it _e_x_t_e_r_n_a_l (as in Fortran 66) causes a func- tion other than the built-in one to be passed. _4. _E_x_p_r_e_s_s_i_o_n_s _4. _E_x_p_r_e_s_s_i_o_n_s _4._1. _C_h_a_r_a_c_t_e_r _C_o_n_s_t_a_n_t_s _4._1. _C_h_a_r_a_c_t_e_r _C_o_n_s_t_a_n_t_s Character string constants are marked by strings sur- rounded by apostrophes. If an apostrophe is to be included in a constant, it is repeated: 'abc' 'ain''t' Although null (zero-length) character strings are not allowed in the standard Fortran, they may be used with f77. Our compiler has two different quotation marks, `` ' '' and `` " ''. (See section 2.9 in the main text.) _4._2. _C_o_n_c_a_t_e_n_a_t_i_o_n _4._2. _C_o_n_c_a_t_e_n_a_t_i_o_n One new operator has been added, character string - 28 - concatenation, marked by a double slash ``//''. The result of a concatenation is the string containing the characters of the left operand followed by the charac- ters of the right operand. The character expressions 'ab' // 'cd' 'abcd' are equal. Dummy arguments of type character may be declared with implied lengths: subroutine s ( a, b ) character a*(*), b*(*) Such dummy arguments may be used in concatenations in assign statements: s = a // b but not in other contexts. For example: if( a // b .eq. 'abc' ) key = 1 call sub( a // b ) are legal statements if ``a'' and ``b'' are dummy argu- ments declared with explicit lengths, or if they are not arguments. These are illegal if they are declared with implied lengths. _4._3. _C_h_a_r_a_c_t_e_r _S_t_r_i_n_g _A_s_s_i_g_n_m_e_n_t _4._3. _C_h_a_r_a_c_t_e_r _S_t_r_i_n_g _A_s_s_i_g_n_m_e_n_t The left and right sides of a character assignment may not share storage. (The assumed implementation of character assignment is to copy characters from the right to the left side.) If the left side is longer than the right, it is padded with blanks. If the left side is shorter than the right, trailing characters are discarded. Since the two sides of a character assign- ment must be disjoint, the following are illegal: str = ' ' // str str = str(2:) These are not flagged as errors during compilation or execution, however the result is undefined. _4._4. _S_u_b_s_t_r_i_n_g_s _4._4. _S_u_b_s_t_r_i_n_g_s It is possible to extract a substring of a character variable or character array element, using the colon - 29 - notation: a(i,j) (m:n) is the string of (_n-_m+1) characters beginning at the _m78_t_h999 character of the character array element _a9_i_j8. Results are undefined unless _m<__n. Substrings may be used on the left sides of assignments and as procedure actual arguments. _4._5. _E_x_p_o_n_e_n_t_i_a_t_i_o_n _4._5. _E_x_p_o_n_e_n_t_i_a_t_i_o_n It is now permissible to raise real quantities to com- plex powers, or complex quantities to real or complex powers. (The principal part of the logarithm is used.) Also, multiple exponentiation is now defined: a**b**c is equivalent to a ** (b**c) _4._6. _R_e_l_a_x_a_t_i_o_n _o_f _R_e_s_t_r_i_c_t_i_o_n_s _4._6. _R_e_l_a_x_a_t_i_o_n _o_f _R_e_s_t_r_i_c_t_i_o_n_s Mixed mode expressions are now permitted. (For instance, it is permissible to combine integer and com- plex quantities in an expression.) Constant expressions are permitted where a constant is allowed, except in _d_a_t_a statements and _f_o_r_m_a_t state- ments. (A constant expression is made up of explicit constants and parameters and the Fortran operators, except for exponentiation to a floating-point power.) An adjustable dimension may now be an integer expres- sion involving constants, arguments, and variables in _c_o_m_m_o_n. Subscripts may now be general integer expressions; the old _c_v+__c' rules have been removed. _d_o loop bounds may be general integer, real, or double precision expres- sions. Computed _g_o_t_o expressions and I/O unit numbers may be general integer expressions. _5. _E_x_e_c_u_t_a_b_l_e _S_t_a_t_e_m_e_n_t_s _5. _E_x_e_c_u_t_a_b_l_e _S_t_a_t_e_m_e_n_t_s _5._1. _I_F-_T_H_E_N-_E_L_S_E _5._1. _I_F-_T_H_E_N-_E_L_S_E At last, the if-then-else branching structure has been added to Fortran. It is called a ``Block If''. A Block If begins with a statement of the form if ( . . . ) then - 30 - and ends with an end if statement. Two other new statements may appear in a Block If. There may be several else if (. . .) then statements, followed by at most one else statement. If the logical expression in the Block If statement is true, the statements following it up to the next _e_l_s_e _i_f, _e_l_s_e, or _e_n_d _i_f are executed. Other- wise, the next _e_l_s_e _i_f statement in the group is exe- cuted. If none of the _e_l_s_e _i_f conditions are true, control passes to the statements following the _e_l_s_e statement, if any. (The _e_l_s_e block must follow all _e_l_s_e _i_f blocks in a Block If. Of course, there may be Block Ifs embedded inside of other Block If struc- tures.) A case construct may be rendered: if (s .eq. 'ab') then . . . else if (s .eq. 'cd') then . . . else . . . end if _5._2. _A_l_t_e_r_n_a_t_e _R_e_t_u_r_n_s _5._2. _A_l_t_e_r_n_a_t_e _R_e_t_u_r_n_s Some of the arguments of a subroutine call may be statement labels preceded by an asterisk, as in: call joe(j, *10, m, *2) A _r_e_t_u_r_n statement may have an integer expression, such as: return k If the entry point has _n alternate return (asterisk) arguments and if 1<__k<__n, the return is followed by a branch to the corresponding statement label; otherwise the usual return to the statement following the _c_a_l_l is executed. - 31 - _6. _I_n_p_u_t/_O_u_t_p_u_t _6. _I_n_p_u_t/_O_u_t_p_u_t _6._1. _F_o_r_m_a_t _V_a_r_i_a_b_l_e_s _6._1. _F_o_r_m_a_t _V_a_r_i_a_b_l_e_s A format may be the value of a character expression (constant or otherwise), or be stored in a character array, as in: write(6, '(i5)') x _6._2. _E_N_D=, _E_R_R=, _a_n_d _I_O_S_T_A_T= _C_l_a_u_s_e_s _6._2. _E_N_D=, _E_R_R=, _a_n_d _I_O_S_T_A_T= _C_l_a_u_s_e_s A _r_e_a_d or _w_r_i_t_e statement may contain _e_n_d=, _e_r_r=, and _i_o_s_t_a_t= clauses, as in: write(6, 101, err=20, iostat=a(4)) read(5, 101, err=20, end=30, iostat=x) Here 5 and 6 are the _u_n_i_t_s on which the I/O is done, 101 is the statement number of the associated format, 20 and 30 are statement numbers, and _a and _x are integer variables. If an error occurs during I/O, con- trol returns to the program at statement 20. If the end of the file is reached, control returns to the pro- gram at statement 30. In any case, the variable referred to in the _i_o_s_t_a_t= clause is given a value when the I/O statement finishes. (Yes, the value is assigned to the name on the right side of the equal sign.) This value is zero if all went well, negative for end of file, and some positive value for errors. _6._3. _F_o_r_m_a_t_t_e_d _I/_O _6._3. _F_o_r_m_a_t_t_e_d _I/_O _6._3._1. _C_h_a_r_a_c_t_e_r _C_o_n_s_t_a_n_t_s Character constants in formats are copied literally to the output. A format may be specified as a character constant within the _r_e_a_d or _w_r_i_t_e statement. write(6,'(i2,'' isn''''t '',i1)') 7, 4 produces 7 isn't 4 In the example above, the format is the character con- stant - 32 - (i2,' isn''t ',i1) and the embedded character constant isn't is copied into the output. The example could have been written more legibly by taking advantage of the two types of quote marks. write(6,'(i2," isn''t ",i1)') 7, 4 However, the double quote is not standard Fortran 77. The standard does not allow reading into character con- stants or Hollerith fields. In order to facilitate running older programs, the Fortran I/O library allows reading into Hollerith fields; however this is a prac- tice to be avoided. _6._3._2. _P_o_s_i_t_i_o_n_a_l _E_d_i_t_i_n_g _C_o_d_e_s _t, _t_l, _t_r, and _x codes control where the next character is in the record. tr_n or _nx specifies that the next character is _n to the right of the current position. tl_n specifies that the next character is _n to the left of the current position, allowing parts of the record to be reconsidered. t_n says that the next character is to be character number _n in the record. (See section 3.3 in the main text.) _6._3._3. _C_o_l_o_n A colon in the format terminates the I/O operation if there are no more data items in the I/O list, otherwise it has no effect. In the fragment x='("hello", :, " there", i4)' write(6, x) 12 write(6, x) the first _w_r_i_t_e statement prints hello there 12 while the second only prints hello - 33 - _6._3._4. _O_p_t_i_o_n_a_l _P_l_u_s _S_i_g_n_s According to the Standard, each implementation has the option of putting plus signs in front of non-negative numeric output. The _s_p format code may be used to make the optional plus signs actually appear for all subse- quent items while the format is active. The _s_s format code guarantees that the I/O system will not insert the optional plus signs, and the _s format code restores the default behavior of the I/O system. (Since we never put out optional plus signs, _s_s and _s codes have the same effect in our implementation.) _6._3._5. _B_l_a_n_k_s _o_n _I_n_p_u_t Blanks in numeric input fields, other than leading blanks, will be ignored following a _b_n code in a format statement, and will be treated as zeros following a _b_z code in a format statement. The default for a unit may be changed by using the _o_p_e_n statement. (Blanks are ignored by default.) _6._3._6. _U_n_r_e_p_r_e_s_e_n_t_a_b_l_e _V_a_l_u_e_s The Standard requires that if a numeric item cannot be represented in the form required by a format code, the output field must be filled with asterisks. (We think this should have been an option.) _6._3._7. _I_w._m There is a new integer output code, i_w._m. It is the same as i_w, except that there will be at least _m digits in the output field, including, if necessary, leading zeros. The case i_w.0 is special, in that if the value being printed is 0, the output field is entirely blank. i_w.1 is the same as i_w. _6._3._8. _F_l_o_a_t_i_n_g _P_o_i_n_t On input, exponents may start with the letter E, D, e, or d. All have the same meaning. On output we always use e or d. The _e and _d format codes also have identi- cal meanings. A leading zero before the decimal point in _e output without a scale factor is optional with the implementation. There is a g_w._d format code which is the same as e_w._d and f_w._d on input, but which chooses _f or _e formats for output depending on the size of the number and of _d. _6._3._9. ``_A'' _F_o_r_m_a_t _C_o_d_e The _a code is used for character data. a_w uses a field width of _w, while a plain _a uses the length of the - 34 - internal character item. _6._4. _S_t_a_n_d_a_r_d _U_n_i_t_s _6._4. _S_t_a_n_d_a_r_d _U_n_i_t_s There are default formatted input and output units. The statement read 10, a, b reads from the standard unit using format statement 10. The default unit may be explicitly specified by an asterisk, as in read(*, 10) a, b Similarly, the standard output unit is specified by a _p_r_i_n_t statement or an asterisk unit: print 10 write(*, 10) _6._5. _L_i_s_t-_D_i_r_e_c_t_e_d _I/_O _6._5. _L_i_s_t-_D_i_r_e_c_t_e_d _I/_O List-directed I/O is a kind of free form input for sequential I/O. It is invoked by using an asterisk as the format identifier, as in read(6, *) a,b,c On input, values are separated by strings of blanks and possibly a comma. On UNIX, tabs may be used inter- changeably with blanks as separators. Values, except for character strings, cannot contain blanks. End of record counts as a blank, except in character strings, where it is ignored. Complex constants are given as two real constants separated by a comma and enclosed in parentheses. A null input field, such as between two consecutive commas, means the corresponding variable in the I/O list is not changed. Values may be preceded by repetition counts, as in 4*(3.,2.) 2*, 4*'hello' which stands for 4 complex constants, 2 null values, and 4 string constants. The Fortran standard requires data being read into character variables by a list-directed read to be enclosed in quotes. In our system, the quotes are optional for strings which do not start with a digit or - 35 - quote and do not contain separators. For output, suitable formats are chosen for each item. The values of character strings are printed; they are not enclosed in quotes. According to the standard, they could not be read back using list-directed input. However much of this data could be read back in with list-directed I/O on our system. _6._6. _D_i_r_e_c_t _I/_O _6._6. _D_i_r_e_c_t _I/_O A file connected for direct access consists of a set of equal-sized records each of which is uniquely identi- fied by a positive integer. The records may be written or read in any order, using direct access I/O state- ments. Direct access _r_e_a_d and _w_r_i_t_e statements have an extra argument, _r_e_c=, which gives the record number to be read or written. read(2, rec=13, err=20) (a(i), i=1, 203) reads the thirteenth record into the array _a. The size of the records must be given by an _o_p_e_n state- ment (see below). Direct access files may be connected for either formatted or unformatted I/O. _6._7. _I_n_t_e_r_n_a_l _F_i_l_e_s _6._7. _I_n_t_e_r_n_a_l _F_i_l_e_s Internal files are character string objects, such as variables or substrings, or arrays of type character. In the former cases there is only a single record in the file; in the latter case each array element is a record. The Standard includes only sequential format- ted I/O on internal files. (I/O is not a very precise term to use here, but internal files are dealt with using _r_e_a_d and _w_r_i_t_e.) Internal files are used by giv- ing the name of the character object in place of the unit number, as in character*80 x read(5,'(a)') x read(x,'(i3,i4)') n1,n2 which reads a character string into _x and then reads two integers from the front of it. A sequential _r_e_a_d or _w_r_i_t_e always starts at the beginning of an internal file. We also support two extensions of the standard. The - 36 - first is direct I/O on internal files. This is like direct I/O on external files, except that the number of records in the file cannot be changed. In this case a record is a single element of an array of character strings. The second extension is list-directed I/O on internal files. _6._8. _O_P_E_N, _C_L_O_S_E, _a_n_d _I_N_Q_U_I_R_E _S_t_a_t_e_m_e_n_t_s _6._8. _O_P_E_N, _C_L_O_S_E, _a_n_d _I_N_Q_U_I_R_E _S_t_a_t_e_m_e_n_t_s These statements are used to connect and disconnect units and files, and to gather information about units and files. _6._8._1. _O_P_E_N The _o_p_e_n statement is used to connect a file with a unit, or to alter some properties of the connection. The following is a minimal example. open(1, file='fort.junk') _o_p_e_n takes a variety of arguments with meanings described below. unit= an integer between 0 and 99 inclusive which is the unit to which the file is to be connected (see section 5.3 in the text). If this parameter is the first one in the _o_p_e_n statement, the _u_n_i_t= can be omitted. iostat= is the same as in _r_e_a_d or _w_r_i_t_e. err= is the same as in _r_e_a_d or _w_r_i_t_e. file= a character expression, which when stripped of trailing blanks, is the name of the file to be connected to the unit. The file name should not be given if the _s_t_a_t_u_s='_s_c_r_a_t_c_h'. status= one of '_o_l_d', '_n_e_w', '_s_c_r_a_t_c_h', or '_u_n_k_n_o_w_n'. If this parameter is not given, '_u_n_k_n_o_w_n' is assumed. The meaning of '_u_n_k_n_o_w_n' is processor dependent; our system will create the file if it doesn't exist. If '_s_c_r_a_t_c_h' is given, a temporary file will be created. Temporary files are destroyed at the end of execution. If '_n_e_w' is given, the file must not exist. It will be created for both reading and writing. If '_o_l_d' is given, it is an error for the file not to exist. access= '_s_e_q_u_e_n_t_i_a_l' or '_d_i_r_e_c_t', depending on whether the file is to be opened for sequential or direct I/O. - 37 - form= '_f_o_r_m_a_t_t_e_d' or '_u_n_f_o_r_m_a_t_t_e_d'. On UNIX systems, _f_o_r_m='_p_r_i_n_t' implies '_f_o_r_m_a_t_t_e_d' with vertical format control. (See section 3.4 of the text). recl= a positive integer specifying the record length of the direct access file being opened. We meas- ure all record lengths in bytes. On UNIX systems a record length of 1 has the special meaning explained in section 5.1 of the text. blank= '_n_u_l_l' or '_z_e_r_o'. This parameter has meaning only for formatted I/O. The default value is '_n_u_l_l'. '_z_e_r_o' means that blanks, other than leading blanks, in numeric input fields are to be treated as zeros. Opening a new file on a unit which is already connected has the effect of first closing the old file. _6._8._2. _C_L_O_S_E _c_l_o_s_e severs the connection between a unit and a file. The unit number must be given. The optional parameters are _i_o_s_t_a_t= and _e_r_r= with their usual meanings, and _s_t_a_t_u_s= either '_k_e_e_p' or '_d_e_l_e_t_e'. For scratch files the default is '_d_e_l_e_t_e'; otherwise '_k_e_e_p' is the default. '_d_e_l_e_t_e' means the file will be removed. A simple example is close(3, err=17) _6._8._3. _I_N_Q_U_I_R_E The _i_n_q_u_i_r_e statement gives information about a unit (``inquire by unit'') or a file (``inquire by file''). Simple examples are: inquire(unit=3, name=xx) inquire(file='junk', number=n, exist=l) file= a character variable specifies the file the _i_n_q_u_i_r_e is about. Trailing blanks in the file name are ignored. unit= an integer variable specifies the unit the _i_n_q_u_i_r_e is about. Exactly one of _f_i_l_e= or _u_n_i_t= must be used. iostat=, err= are as before. - 38 - exist= a logical variable. The logical variable is set to ._t_r_u_e. if the file or unit exists and is set to ._f_a_l_s_e. otherwise. opened= a logical variable. The logical variable is set to ._t_r_u_e. if the file is connected to a unit or if the unit is connected to a file, and it is set to ._f_a_l_s_e. otherwise. number= an integer variable to which is assigned the number of the unit connected to the file, if any. named= a logical variable to which is assigned ._t_r_u_e. if the file has a name, or ._f_a_l_s_e. otherwise. name= a character variable to which is assigned the name of the file (inquire by file) or the name of the file connected to the unit (inquire by unit). access= a character variable to which will be assigned the value '_s_e_q_u_e_n_t_i_a_l' if the connection is for sequential I/O, '_d_i_r_e_c_t' if the connection is for direct I/O, '_u_n_k_n_o_w_n' if not connected. sequential= a character variable to which is assigned the value '_y_e_s' if the file could be connected for sequential I/O, '_n_o' if the file could not be con- nected for sequential I/O, and '_u_n_k_n_o_w_n' if we can't tell. direct= a character variable to which is assigned the value '_y_e_s' if the file could be connected for direct I/O, '_n_o' if the file could not be con- nected for direct I/O, and '_u_n_k_n_o_w_n' if we can't tell. form= a character variable to which is assigned the value '_u_n_f_o_r_m_a_t_t_e_d' if the file is connected for unformatted I/O, '_f_o_r_m_a_t_t_e_d' if the file is con- nected for formatted I/O, '_p_r_i_n_t' for formatted I/O with vertical format control, or '_u_n_k_n_o_w_n' if not connected. formatted= a character variable to which is assigned the value '_y_e_s' if the file could be connected for formatted I/O, '_n_o' if the file could not be con- nected for formatted I/O, and '_u_n_k_n_o_w_n' if we can't tell. unformatted= a character variable to which is assigned the value '_y_e_s' if the file could be connected for unformatted I/O, '_n_o' if the file could not be connected for unformatted I/O, and '_u_n_k_n_o_w_n' if we can't tell. - 39 - recl= an integer variable to which is assigned the record length of the records in the file if the file is connected for direct access. nextrec= an integer variable to which is assigned one more than the number of the the last record read from a file connected for direct access. blank= a character variable to which is assigned the value '_n_u_l_l' if null blank control is in effect for the file connected for formatted I/O, '_z_e_r_o' if blanks are being converted to zeros and the file is connected for formatted I/O. For information on file permissions, ownership, etc., use the Fortran library routines stat and access. For further discussion of the UNIX Fortran I/O system see ``Introduction to the f77 I/O Library'' [9]. - 40 - _A_P_P_E_N_D_I_X _B: _R_e_f_e_r_e_n_c_e_s _a_n_d _B_i_b_l_i_o_g_r_a_p_h_y _A_p_p_e_n_d_i_x _B. _R_e_f_e_r_- _e_n_c_e_s _a_n_d _B_i_b_l_i_o_g_r_a_p_h_y _R_e_f_e_r_e_n_c_e_s 1. _A_m_e_r_i_c_a_n _N_a_t_i_o_n_a_l _S_t_a_n_d_a_r_d _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e _F_O_R_T_R_A_N, _A_N_S_I _X_3._9-_1_9_7_8. New York: American National Standards Institute, 1978. 2. _U_S_A _S_t_a_n_d_a_r_d _F_O_R_T_R_A_N, _U_S_A_S _X_3._9-_1_9_6_6. New York: United States of America Standards Institute, 1966. Clarified in _C_o_m_m. _A_C_M 12:289 (1969) and _C_o_m_m. _A_C_M 14:628 (1971). 3. Kernighan, B. W., and D. M. Ritchie. _T_h_e _C _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e. Englewood Cliffs: Prentice-Hall, 1978. 4. Ritchie, D. M. Private communication. 5. Johnson, S. C. ``A Portable Compiler: Theory and Prac- tice,'' _P_r_o_c_e_e_d_i_n_g_s _o_f _F_i_f_t_h _A_C_M _S_y_m_p_o_s_i_u_m _o_n _P_r_i_n_c_i_p_l_e_s _o_f _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e_s. 1978. 6. Feldman, S. I. ``An Informal Description of EFL,'' internal memorandum. 7. Kernighan, B. W. ``RATFOR-A Preprocessor for Rational Fortran,'' _B_e_l_l _L_a_b_o_r_a_t_o_r_i_e_s _C_o_m_p_u_t_i_n_g _S_c_i_e_n_c_e _T_e_c_h_n_i_c_a_l _R_e_p_o_r_t #_5_5. 1977. 8. Ritchie, D. M. Private communication. 9. Wasley, D. L. ``Introduction to the f77 I/O Library'', _U_N_I_X _P_r_o_g_r_a_m_m_e_r'_s _M_a_n_u_a_l, _V_o_l_u_m_e _2_c. _B_i_b_l_i_o_g_r_a_p_h_y The following books or documents describe aspects of Fortran 77. This list cannot pretend to be complete. Certainly no particular endorsement is implied. 1. Brainerd, Walter S., et al. _F_o_r_t_r_a_n _7_7 _P_r_o_g_r_a_m_m_i_n_g. Harper Row, 1978. 2. Day, A. C. _C_o_m_p_a_t_i_b_l_e _F_o_r_t_r_a_n. Cambridge University Press, 1979. 3. Dock, V. Thomas. _S_t_r_u_c_t_u_r_e_d _F_o_r_t_r_a_n _I_V _P_r_o_g_r_a_m_m_i_n_g. West, 1979. 4. Feldman, S. I. ``The Programming Language EFL,'' _B_e_l_l _L_a_b_o_r_a_t_o_r_i_e_s _T_e_c_h_n_i_c_a_l _R_e_p_o_r_t. June 1979. - 41 - 5. Hume, J. N., and R. C. Holt. _P_r_o_g_r_a_m_m_i_n_g _F_o_r_t_r_a_n _7_7. Reston, 1979. 6. Katzan, Harry, Jr. _F_o_r_t_r_a_n _7_7. Van Nostrand-Reinhold, 1978. 7. Meissner, Loren P., and Organick, Elliott I. _F_o_r_t_r_a_n _7_7 _F_e_a_t_u_r_i_n_g _S_t_r_u_c_t_u_r_e_d _P_r_o_g_r_a_m_m_i_n_g, Addison-Wesley, 1979. 8. Merchant, Michael J. _A_B_C'_s _o_f _F_o_r_t_r_a_n _P_r_o_g_r_a_m_m_i_n_g. Wadsworth, 1979. 9. Page, Rex, and Richard Didday. _F_o_r_t_r_a_n _7_7 _f_o_r _H_u_m_a_n_s. West, 1980. 10.Wagener, Jerrold L. _P_r_i_n_c_i_p_l_e_s _o_f _F_o_r_t_r_a_n _7_7 _P_r_o_g_r_a_m_- _m_i_n_g. Wiley, 1980. - 2 -