. \"define f2c % "\f(CWf2c\fP" %
. \"define F2c % "\f(CWF2c\fP" %
.de Bp
.ft R
.sp .5
.in \w'\(bu\ 'u
.ti 0
\(bu\ \c
..
.EQ
define dollar % "\f(CW$\fP" %
delim $$
define f2c % "f\|2c" %
define F2c % "F\^2c" %
define libF77 % "libF77" %
define libI77 % "libI77" %
define LibF77 % "LibF77" %
define LibI77 % "LibI77" %
.EN
.TL
A Fortran to C Converter
.AU
S. I. Feldman
.AI
Bellcore
Morristown, NJ 07960
.AU
David M. Gay
.AI
.MH
.AU
Mark W. Maimone
.AI
Carnegie-Mellon University
Pittsburgh, PA 15213
.AU
N. L. Schryer
.AI
.MH
.AB
We describe $f2c$, a program that translates Fortran 77
into C or C++.  $F2c$ lets one portably mix C and Fortran
and makes a large body of well-tested Fortran
source code available to C environments.
.AE
.SH
1. INTRODUCTION
.PP
Automatic conversion of Fortran 77
.[ [
ANSI FORTRAN 1978
.]]
to C
.[ [
Kernighan Ritchie 1978
.]
.[
Kernighan Ritchie 1988
.]]
is desirable for
several reasons.  Sometimes it is useful to run a
well-tested Fortran program on a machine that has a C
compiler but no Fortran compiler.  At other times, it
is convenient to mix C and Fortran.  Some things are
impossible to express in Fortran 77 or are harder
to express in Fortran than in C
(e.g. storage management, some character operations,
arrays of functions, heterogeneous data structures,
and calls that depend on the operating system),
and some programmers simply prefer C to Fortran.
There is a large body of well tested
Fortran source code for carrying out a wide variety of
useful calculations, and it is sometimes desirable to
exploit some of this Fortran source in a C environment.
Many vendors provide some way of mixing C and Fortran, but
the details vary from system to system.
Automatic Fortran to C conversion lets one create a
.I portable
C program that exploits Fortran source code.
.PP
A side benefit of automatic Fortran 77 to C conversion is that
it allows such tools as
.I cyntax (1)
and
.I lint (1)
\ 
.[[
v101
.]]
to provide Fortran 77 programs with some of the consistency
and portability checks that the Pfort Verifier
.[ [
Ryder 1974
.]]
provided to Fortran 66 programs.
The consistency checks
detect errors in calling sequences
and are thus a boon to debugging.
.PP
This paper describes $f2c$, a Fortran 77 to C converter
based on Feldman's original $f77$ compiler
.[ [
Feldman Weinberger Portable Fortran
.]].
We have used $f2c$ to convert various large programs and
subroutine libraries to C automatically (i.e., with no manual intervention);
these include the \s-2PORT3\s+2 subroutine library (\s-2PORT1\s+2
is described in
.[ [
Fox Hall Schryer Algorithm 1978
.]
.[
Fox Hall Schryer port 1978
.]]),
MINOS
.[ [
Murtagh Saunders 1987
.]],
and Schryer's floating-point test
.[ [
Schryer floating
.]].
The floating-point test is of particular interest, as it relies
heavily on correct evaluation of parenthesized expressions and
is bit-level self-testing.
.PP
As a debugging aid, we sought bit-level compatibility between
objects compiled from the C produced by $f2c$ and objects
produced by our local $f77$ compiler.  That is, on the VAX
where we developed $f2c$, we sought to make it impossible to
tell by running a Fortran program whether some of its
modules had been compiled by $f2c$ or
all had been compiled by $f77$.  This meant that $f2c$
should follow the same calling conventions as $f77$
.[ [
Feldman Weinberger Portable Fortran
.]]
and should use $f77$'s support libraries, $libF77$ and $libI77$.
.PP
Although we have tried to make $f2c$'s output reasonably readable,
our goal of strict compatibility with $f77$ implies some nasty
looking conversions.  Input/output statements, in particular,
generally get expanded into
a series of calls on routines in $libI77$, $f77$'s I/O library.
Thus the C output of $f2c$ would probably be something of a nightmare
to maintain as C; it would be much more sensible to maintain the original
Fortran, translating it anew each time it changed.  Some commercial
vendors, e.g., those listed in Appendix A,
seek to perform translations yielding C that one
might reasonably maintain directly; these translations generally
require some manual intervention.
.PP
The rest of this paper is organized as follows.
Section 2 describes the interlanguage conventions used by $f2c$ (and $f77$).
\(sc3 summarizes some extensions to Fortran 77 that $f2c$ recognizes.
. \"The extensions to Fortran 77 that $f2c$ recognizes are summarized in \(sc3.
Example invocations of $f2c$ appear in \(sc4.
\(sc5 illustrates various details of $f2c$'s translations, and
\(sc6 considers portability issues.
\(sc7 discusses the generation and use of
.I prototypes ,
which can be used both by C++ and ANSI C compilers and by
$f2c$ to check consistency of calling sequences.
\(sc8 describes our experience with
an experimental $f2c$ service provided by $netlib$
.[ [
Dongarra Grosse 1987
.]],
and \(sc9 considers possible extensions.
Appendix A lists some vendors who offer
conversion of Fortran to C that one might maintain as C.
Finally, Appendix B contains a $man$ page telling how to use $f2c$.
.SH
2. INTERLANGUAGE CONVENTIONS
.PP
Much of the material in this section is taken from
.[ [
Feldman Weinberger Portable Fortran
.]].
.SH
Names
.PP
An $f2c$ extension
inspired by Fortran 90 (until recently called Fortran 8x
.[ [
Fort8x
.]])
is that long names are allowed ($f2c$ truncates names that are longer
than 50 characters), and names may contain underscores.  To avoid conflict
with the names of library routines and with names that $f2c$ generates,
Fortran names may have one or two underscores appended.
Fortran names are forced to lower case (unless the
.CW \%-U
option described in Appendix B is in effect); external names, i.e., the names
of Fortran procedures and common blocks, have a single underscore appended
if they do not contain any underscores and have a pair of underscores
appended if they do contain underscores.
Thus Fortran subroutines named
.CW ABC ,
.CW A_B_C ,
and
.CW A_B_C_
result in C functions named
.CW abc_ ,
.CW a_b_c_\|\^_ ,
and
.CW a_b_c_\|\^_\|\^_ .
.SH
Types
.PP
The table below shows
corresponding Fortran and C declarations;
the C declarations use types defined in
.CW f2c.h ,
a header file upon which $f2c$'s translations rely.
The table also shows the C types defined in the standard
version of
.CW f2c.h .
.KS
.TS
center box;
c c c
l l l.
Fortran	C	standard \f(CWf2c.h\fP
.sp .5
integer\(**2 x	shortint x;	short int x;
integer x	integer x;	long int x;
logical x	long int x;	long int x;
real x	real x;	float x;
double precision x	doublereal x;	double x;
complex x	complex x;	struct { float r, i; } x;
double complex x	doublecomplex x;	struct { double r, i; } x;
character\(**6 x	char x[6];	char x[6];
.TE
.KE
By the rules of Fortran,
.CW integer,
.CW logical,
and
.CW real
data occupy the same amount of memory, and
.CW "double precision"
and
.CW complex
occupy twice this amount; $f2c$
assumes that the types in the C column above are
chosen (in
.CW f2c.h )
so that these assumptions are valid.
The translations of the Fortran
.CW equivalence
and
.CW data
statements depend on these assumptions.
On some machines, one must modify
.CW f2c.h
to make these assumptions hold.  See \(sc6 for examples
and further discussion.
.SH
Return Values
.PP
A function of type
.CW integer ,
.CW logical ,
or
.CW "double precision"
must be declared as a C function that returns the corresponding type.
If the
.CW \%-R
option is in effect (see Appendix B), the same is true
of a function of type
.CW real ;
otherwise, a
.CW real
function must be declared as a C function that returns
.CW doublereal ;
this hack facilitates our VAX regression testing, as it
duplicates the behavior of our local Fortran compiler ($f77$).
A
.CW complex
or
.CW "double complex"
function 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,
.P1
complex function f( . . . )
.P2
is equivalent to
.P1
void f_(temp, . . .)
complex \(**temp;
 . . .
.P2
A character-valued function is equivalent to a C routine with
two extra initial arguments:
a data address and a length.
Thus,
.P1
character\(**15 function g( . . . )
.P2
is equivalent to
.P1
g_(result, length, . . .)
char \(**result;
ftnlen length;
 . . .
.P2
and could be invoked in C by
.P1
char chars[15];
 . . .
g_(chars, 15L, . . . );
.P2
Subroutines are invoked as if they were
.CW int -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 subroutine has no entry points with alternate return arguments,
the returned value is undefined.)
The statement
.P1
call nret(\(**1, \(**2, \(**3)
.P2
is treated exactly as if it were the Fortran computed
.CW goto
.P1
goto (1, 2, 3),  nret( )
.P2
.SH
Argument Lists
.PP
All Fortran arguments are passed by address.
In addition,
for every non-function argument that is of type character,
an argument giving the length of the value is passed.
(The string lengths are
.CW ftnlen
values, i.e.,
.CW "long int"
quantities passed by value).  In summary, the order of arguments is:
extra arguments for complex and character functions,
an address for each datum or function, and a
.CW ftnlen
for each character argument (other than character-valued functions).
Thus, the call in
.P1
external f
character\(**7 s
integer b(3)
 . . .
call sam(f, b(2), s)
.P2
is equivalent to that in
.P1
int f();
char s[7];
long int b[3];
 . . .
sam_(f, &b[1], s, 7L);
.P2
Note that the first element of a C array always has subscript zero,
but Fortran arrays begin at 1 by default.
Because Fortran arrays are stored in column-major order, whereas
C arrays are stored in row-major order,
$f2c$ translates multi-dimensional Fortran arrays into one-dimensional
C arrays and issues appropriate subscripting expressions.
.SH
3. EXTENSIONS TO FORTRAN 77
.PP
Since it is derived from $f77$, $f2c$ supports all of the $f77$ extensions
described in
.[ [
Feldman Weinberger Portable Fortran
.]].
$F2c$'s extensions include the following.
.Bp
Type
.CW "double complex"
(alias
.CW "complex*16" )
is a double-precision version of
.CW complex .
Specific intrinsic functions for
.CW "double complex"
have names that start with
.CW z
rather than
.CW c .
An exception to this rule is
.CW dimag ,
which returns the imaginary part of a
.CW "double complex"
value;
.CW imag
is the corresponding generic intrinsic function.
The generic intrinsic function
.CW real
is extended so that it returns the real part of a
.CW "double complex"
value as a
.CW "double precision"
value;
.CW dble
is the specific intrinsic function that does this job.
.Bp
The ``types'' that may appear in an
.CW implicit
statement include
.CW undefined ,
which implies that variables
whose names begin with the associated letters
must be explicitly declared in a type statement.  $F2c$ also
recognizes the Fortran 90 statement
.P1
implicit none
.P2
as equivalent to
.P1
implicit undefined(a-z)
.P2
The command-line option
.CW \%-u
has the effect of inserting
.P1
implicit none
.P2
at the beginning of each Fortran procedure.
.Bp
Procedures may call themselves recursively, i.e.,
may call themselves either directly or indirectly
through a chain of other calls.
.Bp
The keywords
.CW static
and
.CW automatic
act as ``types'' in type and implicit statements;
they specify storage classes.
There is exactly one copy of each
.CW static
variable, and such variables retain their values between
invocations of the procedure in which they appear.
On the other hand, each invocation of a procedure gets
new copies of the procedure's
.CW automatic
variables.
.CW Automatic
variables may not appear in
.CW equivalence ,
.CW data ,
.CW namelist ,
or
.CW save
statements.  The command-line option
.CW \%-a
changes the default storage class from
.CW static
to
.CW automatic
(for all variables except those that appear in
.CW common ,
.CW data ,
.CW equivalence ,
.CW namelist ,
or
.CW save
statements).
.Bp
A tab in the first 6 columns signifies that the current line is
a free-format line, which may extend beyond column 72.
An ampersand
.CW &
in column 1 indicates that the current line is a free-format
continuation line.  Lines that have neither an ampersand in column 1
nor a tab in the first 6 columns are treated as Fortran 77 fixed-format
lines:  if shorter than 72 characters, they are padded on the right
with blanks until they are 72 characters long; if longer than 72
characters, the characters beyond column 72 are discarded.
After taking continuations into account,
statements may be up to 1320 characters long; this is the only
constraint on the length of free-format lines.  (This limit is
implied by the Fortran 77 standard, which allows at most 19 continuation lines;
$1320 ~=~ (1^+^19) ~times~ 66$.)
.Bp
Aside from quoted strings, $f2c$ ignores case (unless the
.CW \%-U
option is in effect).
.Bp
The statement
.P1
include 'stuff'
.P2
is replaced by the contents of the file
.CW stuff.
.CW Include s
may be nested to a reasonable depth, currently ten.
The command-line option
.CW \%-!I
disables
.CW include s;
this option is used by the $netlib$ $f2c$
service described in \(sc8 (for which
.CW include
obviously makes no sense).
.Bp
$F77$ allows binary, octal, and hexadecimal constants
to appear in
.CW data
statements; $f2c$ goes somewhat further, allowing
such constants to appear anywhere; they are treated just
like a decimal integer constant having the equivalent value.
Binary, octal, and hexadecimal constants may assume one of
two forms: a letter followed by a quoted string of digits,
or a decimal base, followed by a sharp sign
.CW # ,
followed by a string of digits (not quoted).  The letter is
.CW b
or
.CW B
for binary constants,
.CW o
or
.CW O
for octal constants, and
.CW x ,
.CW X ,
.CW z ,
or
.CW Z
for hexadecimal constants.  Thus, for example,
.CW z'a7' ,
.CW 16#a7 ,
.CW o'247' ,
.CW 8#247 ,
.CW b'10100111'
and
.CW 2#10100111
are all treated just like the integer
.CW 167 .
.Bp
For compatibility with C, quoted strings may contain the following
escapes:
.TS
center box;
lFCW l a lFCW l.
\e0	null	\ 	\en	newline
\e\e	\e	\ 	\er	carriage return
\eb	backspace	\ 	\et	tab
\ef	form feed	\ 	\ev	vertical tab
.sp .5
.T&
aFCW l s s s.
 \e'	apostrophe (does not terminate a string)
 \e"	quotation mark (does not terminate a string)
 \e\fIx\fP	\fIx\fR, where \fIx\fR is any other character
.TE
The
.CW \%-!bs
option tells $f2c$ not to recognize these escapes.
Quoted strings may be delimited either by double quotes (\ \f(CW"\fR\ )
or by single quotes (\ \f(CW\(fm\fR\ ); if a string starts with
one kind of quote, the other kind may be embedded in the string
without being repeated or quoted by a backslash escape.
Where possible, translated strings are null-terminated.
.Bp
Hollerith strings are treated as character strings.
.Bp
In
.CW equivalence
statements, a multiply-dimensioned array may be given a single
subscript, in which case the missing subscripts are taken to be 1
(for backward compatibility with Fortran 66)
and a warning message is issued.
.Bp
In a formatted read of non-character variables, the I/O
library ($libI77$) allows a field to be terminated by a comma.
.Bp
Type
.CW real*4
is equivalent to
.CW real ,
.CW integer*4
to
.CW integer ,
.CW real*8
to
.CW "double precision" ,
.CW complex*8
to
.CW complex ,
and, as stated before,
.CW complex*16
to
.CW "double complex" .
.Bp
The type
.CW integer*2
designates short integers (translated to type
.CW shortint ,
which by default is
.CW "short int" ).
Such integers are expected to occupy half a ``unit'' of storage.
The command-line options
.CW \%-I2
and
.CW \%-i2
turn type
.CW integer
into
.CW integer*2 ;
see the $man$ page (appendix B) for more details.
.Bp
The intrinsic functions
.CW and ,
.CW or ,
.CW xor ,
and
.CW not
perform bitwise Boolean operations.
.Bp
$LibF77$ provides two functions for accessing command-line arguments:
.CW iargc(dummy)
returns the number of command-line arguments (and ignores its argument);
.CW getarg(k,c)
sets the character string
.CW c
to the $k$th command-line argument (or to blanks if $k$ is out of range).
.Bp
Variable,
.CW common ,
and procedure names may be arbitrarily long, but they
are truncated after the 50th character.  These names may
contain underscores (in which case their translations will
have a pair of underscores appended).
.Bp
MAIN programs may have arguments, which are ignored.
.Bp
.CW Common
variables may be initialized by a
.CW data
statement in any module, not just in a
.CW "block data"
subprogram.
.Bp
The label may be omitted from a
.CW do
loop if the loop
is terminated by an
.CW enddo
statement.
.Bp
Unnamed Fortran 90
.CW "do while"
loops are allowed.
Such a loop begins with a statement of the form
.ce
\f(CWdo \fR[\fIlabel\^\fR] [\f(CW,\fR] \f(CWwhile(\fIlogical expression\f(CW)\fR
and ends either after the statement labelled by $label$ or after a matching
.CW enddo .
.Bp
$F2c$ recognizes the Fortran 90 synonyms
.CW < ,
.CW <= ,
.CW == ,
.CW >= ,
.CW > ,
and
.CW <>
for the Fortran comparison operators
.CW .LT. ,
.CW .LE. ,
.CW .EQ. ,
.CW .GE. ,
.CW .GT. ,
and
.CW .NE.
.Bp
\f(CWNamelist\fR
works as in Fortran 90
.[ [
Fort8x
.]],
with a minor restriction on
.CW namelist
input:  subscripts must have the form
.ce
$subscript$ [ : $subscript$ [ : $stride$ ] ]
For example, the Fortran
.P1
integer m(8)
real x(10,10)
namelist /xx/ m, x
\&. . .
read(*,xx)
.P2
could read
.P1
&xx x(1,1) = 2, x(1:3,8:10:2) = 1,2,3,4,5,6  m(7:8) = 9,10/
.P2
but would elicit error messages on the inputs
.P1
&xx x(:3,8:10:2) = 1,2,3,4,5,6/
&xx x(1:3,8::2)  = 1,2,3,4,5,6/
&xx m(7:) = 9,10/
.P2
(which inputs would be legal in Fortran 90).
For compatibility with the
.CW namelist
variants supplied by several vendors as Fortran 77 extensions,
$f2c$'s version of $libI77$ permits $dollar$ to be used instead of
.CW &
and
.CW /
in
.CW namelist
input.  Thus the Fortran shown above could read
.P1
$dollar$xx x(1,1) = 2, x(1:3,8:10:2) = 1,2,3,4,5,6  m(7:8) = 9,10$dollar$end
.P2
.in 0
.Bp
Internal list-directed and namelist I/O are allowed.
.Bp
In an
.CW open
statement,
.CW name=
is treated as
.CW file= .
.SH
4. INVOCATION EXAMPLES
.PP
To convert the Fortran files
.CW main.f
and
.CW subs.f ,
one might use the UNIX\u\(rg\d command:
.P1
f2c main.f subs.f
.P2
This results in translated files suffixed with
.CW .c ,
i.e., the resulting C files are
.CW main.c
and
.CW subs.c .
To translate all the Fortran files in the current
directory, compile the resulting C,
and create an executable program named
.CW myprog ,
one might use the following pair of UNIX commands:
.P1
f2c *.f
cc -o myprog *.c -lF77 -lI77 -lm
.P2
The above
.CW -lF77
and
.CW -lI77
options assume that the ``standard'' Fortran support libraries
$libF77$ and $libI77$
are appropriate for use with $f2c$.  On some systems this is
not the case (as further discussed in \(sc6); if one had
installed a combination of the appropriate $libF77$ and $libI77$
in the appropriate place, then the above example might become
.P1
f2c *.f
cc -o myprog *.c -lf2c -lm
.P2
Sometimes it is desirable to use $f2c$'s
.CW -R
option, which tells $f2c$ not to force all floating-point operations
to be done in double precision.  (One might argue that
.CW -R
should be the default, but we find the current arrangement
more convenient for testing $f2c$.)  With
.CW -R
specified, the previous example becomes
.P1
f2c -R *.f
cc -o myprog *.c -lf2c -lm
.P2
Sometimes it is desirable to translate several Fortran source
files into a single C file.  This is easily done by using $f2c$
as a filter:
.P1
cat *.f | f2c >mystuff.c
.P2
The
.CW -A
option lets $f2c$ use ANSI C constructs
.[ [
ANSIC
.]],
which yields more readable C when
.CW character
variables are initialized.  With both
.CW -A
and
.CW -R
specified, the last example becomes
.P1
cat *.f | f2c -A -R >mystuff.c
.P2
For use with C++
.[ [
Stroustrup C++ Programming Language 1986
.]],
one would specify
.CW -C++
rather than
.CW -A ;
the last example would then become
.P1
cat *.f | f2c -C++ -R >mystuff.c
.P2
The
.CW -C++
option gives ANSI-style headers and old-style C formatting
of character strings and
.CW float
constants (since some C++ compilers reject the ANSI versions
of these constructs).
.LP
With ANSI C, one can use
.I prototypes ,
i.e., a special syntax describing the calling sequences
of procedures, to help catch errors in argument passing.  To
make using prototypes convenient, the
.CW -P
option causes $f2c$ to create a \fIfile\f(CW.P\fR of prototypes
for the procedures defined in
each input \fIfile\f(CW.f\fR (or \fIfile\f(CW.F\fR, i.e., the
suffix
.CW .f '' ``
or
.CW .F '' ``
is replaced by
.CW .P ''). ``
One could concatenate all relevant prototype files into
a header file and arrange for the header to be
.CW #include d
with each C file compiled.
Since
.CW -P
implies
.CW -A
unless
.CW -C++
is specified, one could
convert all the Fortran files in the current directory
to ANSI C
and get corresponding prototype files by issuing the command
.P1
f2c -P *.f
.P2
Several command options may be combined if none but perhaps the
last takes an argument; thus to specify
.CW -R
and get C++ prototypes for all the
files in the current directory, one could say either
.P1
f2c -C++ -P -R *.f
.P2
or
.P1
f2c -C++PR *.f
.P2
or
.P1
f2c -RPC++ *.f
.P2
\(em options can come in any order.
.LP
For numeric variables initialized by character data, the
.CW -W
option specifies the (machine-dependent!)
number of characters per word and is further discussed
in \(sc6.  This option takes a numeric argument, as in
.CW -W8 ;
such an option must be listed either separately or at the end
of a string of other options, as in
.P1
f2c -C++RPW8 *.f
.P2
.SH
5. TRANSLATION DETAILS
.PP
$F2c$ is based on the ancient $f77$ Fortran compiler of
.[ [
Feldman Weinberger Portable Fortran
.]].
That compiler produced a C parse-tree,
which it converted into input for the second pass of the
portable C compiler (PCC)
.[ [
Johnson portable compiler
.]].
The compiler has been used for many years and is the
direct ancestor of many current Fortran compilers.
Thus, it provided us with a solid base of Fortran knowledge
and a nearly complete C representation.
The converter $f2c$ is a copy of the $f77$ Fortran compiler
which has been altered to print out a C representation
of the program being converted.
The program $f2c$ is a \fIhorror\fP, based on ancient code and
hacked unmercifully.
Users are only supposed to look at its C output,
not at its appalling inner workings.
.PP
Here are some examples that illustrate $f2c$'s translations.
For starters, it is helpful to see a short but complete
example: $f2c$ turns the
Fortran inner product routine
.P1
.so dot.f
.P2
into
.P1
.so dot.c
.P2
The translated C always starts with a ``translated by f2c'' comment
and a
.CW #include
of
.CW f2c.h .
$F2c$ forces the variable and procedure names to lower-case and
appends an underscore to the external name
.CW dot
(to avoid possible conflicts with library names).
The parameter adjustments
.CW --x '' ``
and
.CW --y '' ``
account for the fact that C arrays start at index 0.
Unused labels are retained in comments for orienteering purposes.
Within a function, Fortran references to the function name are turned into
references to the local variable
.CW ret_val ,
which holds the value to be returned.  Unless the
.CW -R
option is specified, $f2c$ converts the return type of
.CW real
function values to
.CW doublereal .
Because using the C ``op='' operators
leads to greater efficiency on some machines, $f2c$ looks for opportunities
to use these operators, as in the line
.CW "ret_val += ..." '' ``
above.
.PP
$F2c$ generally dispenses with superfluous parentheses: ANSI C
specifies a clear order of evaluation for floating-point expressions,
and $f2c$ uses the ANSI C rules to decide when parentheses are required
to faithfully translate a parenthesized Fortran expression.
Non-ANSI compilers are free to violate parentheses; by default, $f2c$ does
not attempt to break an expression into several statements to
foil pernicious non-ANSI C compilers.  Thus, for example, the Fortran
.P1
     x = a*(b*c)
     y = (a*b)*c
.P2
becomes
.P1
    x = a * (b * c);
    y = a * b * c;
.P2
The
.CW \%-kr
and
.CW \%-krd
options cause $f2c$ to use temporary variables to force correct
evaluation order with non-ANSI C compilers.
.ig
If, for instance,
.CW a ,
.CW b ,
and
.CW c ,
are
.CW real
variables, then under
.CW \%-kr
the above Fortran results in
.P1
    /* System generated locals */
    real r_1;
\&. . .
    r_1 = b * c;
    x = a * r_1;
    r_1 = a * b;
    y = r_1 * c;
.P2
..
.PP
Fortran I/O is complicated; like $f77$, $f2c$ converts
a Fortran I/O statement into calls on the Fortran I/O library $libI77$.
For Fortran
.CW read s
and
.CW write s,
there is generally one call to start the statement, one to end it,
and one for each item read or written.  Given the Fortran declarations
.P1
      integer count(10)
      real val(10)
.P2
the Fortran
.P1
      read(*,*) count, val
.P2
is turned into some header lines:
.P1
static integer c_\|\^_3 = 3;
static integer c_\|\^_10 = 10;
static integer c_\|\^_4 = 4;
\&. . .
    /* Builtin functions */
    integer s_rsle(), do_lio(), e_rsle();
\&. . .
    /* Fortran I/O blocks */
    static cilist io_\|\^_1 = { 0, 5, 0, 0, 0 };
.P2
and the executable lines
.P1
s_rsle(&io_\|\^_1);
do_lio(&c_\|\^_3, &c_\|\^_10, (char *)&count[0], (ftnlen)sizeof(integer));
do_lio(&c_\|\^_4, &c_\|\^_10, (char *)&val[0], (ftnlen)sizeof(real));
e_rsle();
.P2
Implicit Fortran do-loops, e.g.
.P1
      read(*,*) (count(i), val(i), i = 1, 10)
.P2
get turned into explicit C loops:
.P1
s_rsle(&io_\|\^_4);
for (i = 1; i <= 10; ++i) {
    do_lio(&c_\|\^_3, &c_\|\^_1, (char *)&count[i - 1], (ftnlen)sizeof(integer));
    do_lio(&c_\|\^_4, &c_\|\^_1, (char *)&val[i - 1], (ftnlen)sizeof(real));
}
e_rsle();
.P2
The Fortran
.CW end=
and
.CW err=
specifiers make the resulting C even less readable, as they require
tests to be inserted.  For example,
.P1
      read(*,*,err=10) count, val
 10   continue
.P2
becomes
.P1
    i_\|\^_1 = s_rsle(&io_\|\^_1);
    if (i_\|\^_1 != 0) {
        goto L10;
    }
    i_\|\^_1 = do_lio(&c_\|\^_3, &c_\|\^_10, (char *)&count[0], (ftnlen)sizeof(integer));
    if (i_\|\^_1 != 0) {
        goto L10;
    }
    i_\|\^_1 = do_lio(&c_\|\^_4, &c_\|\^_10, (char *)&val[0], (ftnlen)sizeof(real));
    if (i_\|\^_1 != 0) {
        goto L10;
    }
    i_\|\^_1 = e_rsle();
L10:
    ;
.P2
.PP
A Fortran routine containing $n$ \f(CWentry\fR statements
is turned into $n^+^2$ C functions, a big one containing
the translation of everything but the \f(CWentry\fR statements,
and $n^+^1$ little ones that invoke the big one.  Each little
one passes a different integer to the big one to tell
it where to begin; the big one starts with a switch
that branches to the code for the appropriate entry.
For instance, the Fortran
.P1
      function sine(x)
      data pi/3.14159265358979324/
      sine = sin(x)
      return
      entry cosneg(y)
      cosneg = cos(y+pi)
      return
      end
.P2
is turned into the big procedure
.P1
doublereal sine_0_(n_\|\^_, x, y)
int n_\|\^_;
real *x, *y;
{
    /* Initialized data */

    static real pi = (float)3.14159265358979324;

    /* System generated locals */
    real ret_val;

    /* Builtin functions */
    double sin(), cos();

    switch(n_\|\^_) {
	case 1: goto L_cosneg;
	}

    ret_val = sin(*x);
    return ret_val;

L_cosneg:
    ret_val = cos(*y + pi);
    return ret_val;
} /* sine_ */
.P2
and the little invoking procedures
.P1
doublereal sine_(x)
real *x;
{
    return sine_0_(0, x, (real *)0);
    }

doublereal cosneg_(y)
real *y;
{
    return sine_0_(1, (real *)0, y);
    }
.P2
.LP
Fortran
.CW common
regions are turned into C
.CW struct s.
For example, the Fortran declarations
.P1
      common /named/ c, d, r, i, l
      complex c(10)
      double precision d(10)
      real r(10)
      integer i(10)
      logical m(10)

      if (m(i(2))) d(3) = d(4)/d(5)
.P2
result in
.P1
struct {
    complex c[10];
    doublereal d[10];
    real r[10];
    integer i[10];
    logical m[10];
} named_;

#define named_1 named_
\&. . .

    if (named_1.m[named_1.i[1] - 1]) {
	named_1.d[2] = named_1.d[3] / named_1.d[4];
	}
.P2
Under the
.CW -p
option, the above
.CW if
statement becomes more readable:
.P1
\&. . .
#define c (named_1.c)
#define d (named_1.d)
#define r (named_1.r)
#define i (named_1.i)
#define m (named_1.m)
\&. . .
    if (m[i[1] - 1]) {
	d[2] = d[3] / d[4];
.P2
If the above
.CW common
block were involved in a
.CW "block data"
subprogram, e.g.
.P1
      block data
      common /named/ c, d, r, i, l, m
      complex c(10)
      double precision d(10)
      real r(10)
      integer i(10)
      logical m(10)
      data c(1)/(1.0,0e0)/, d(2)/2d0/, r(3)/3e0/, i(4)/4/,
     *     m(5)/.false./
      end
.P2
then the
.CW struct
would begin
.CW "struct named_1_ {" '', ``
and $f2c$ would issue a more elaborate
.CW #define :
.P1
#define named_1 (*(struct named_1_ *) &named_)

/* Initialized data */

struct {
    complex e_1;
    doublereal fill_2[10];
    doublereal e_3;
    doublereal fill_4[9];
    real e_5;
    integer fill_6[10];
    integer e_7;
    integer fill_8[11];
    logical e_9;
    integer fill_10[5];
    } named_ = { (float)1., (float)0., {0}, 2., {0}, (float)3., {0}, 4,
	    {0},  FALSE_ };
.P2
In this example, $f2c$ relies on C's structure initialization rules
to supply zeros to the
\f(CWfill_\fIn\fR
arrays that take up the space for which no
.CW data
values were given.  (The logical constants
.CW TRUE_
and
.CW FALSE_
are defined in
.CW f2c.h .)
.PP
Character manipulations of multiple-character strings
generally result in function calls.  For example,
the Fortran
.P1
      character*(*) function cat(a,b)
      character*(*) a, b
      cat = a // b
      end
.P2
yields
.P1
\&. . .
static integer c_\|\^_2 = 2;

/* Character */ int cat_(ret_val, ret_val_len, a, b, a_len, b_len)
char *ret_val;
ftnlen ret_val_len;
char *a, *b;
ftnlen a_len;
ftnlen b_len;
{

    /* System generated locals */
    address a_\|\^_1[2];
    integer i_\|\^_1[2];

    /* Builtin functions */
    /* Subroutine */ int s_cat();

/* Writing concatenation */
    i_\|\^_1[0] = a_len, a_\|\^_1[0] = a;
    i_\|\^_1[1] = b_len, a_\|\^_1[1] = b;
    s_cat(ret_val, a_\|\^_1, i_\|\^_1, &c_\|\^_2, ret_val_len);
} /* cat_ */
.P2
Note how the return-value length
.CW ret_val_len ) (
and parameter lengths
.CW a_len "" (
and
.CW b_len )
are used.
Single character operations are generally done in-line.
For example, the body of the Fortran
.P1
      character*1 function lastnb(x,n)
      character*1 x(n)
      lastnb = ' '
      do 10 i = n, 1, -1
         if (x(i) .ne. ' ') then
            lastnb = x(i)
            return
            end if
 10      continue
      end
.P2
becomes
.P1
    *ret_val = ' ';
    for (i = *n; i >= 1; --i) {
	if (x[i] != ' ') {
	    *ret_val = x[i];
	    return ;
	}
/* L10: */
    }
.P2
.PP
$F2c$ uses
.CW struct s
and
.CW #define s
to translate
.CW equivalence s.
For a complicated example showing the interaction of
.CW data
with
.CW common ,
.CW equivalence ,
and, for good measure, Hollerith notation,
consider the Fortran
.P1
      common /cmname/ c
      complex c(10)
      double precision d(10)
      real r(10)
      integer i(10)
      logical m(10)
      equivalence (c(1),d(1),r(1),i(1),m(1))
      data c(1)/(1.,0.)/
      data d(2)/2d0/, r(5)/3e0/, i(6)/4/, m(7)/.true./
      call sam(c,d(1),r(2),i(3),m(4),14hsome hollerith,14)
      end
.P2
The resulting C is
.P1
\&. . .
struct cmname_1_ {
    complex c[10];
};

#define cmname_1 (*(struct cmname_1_ *) &cmname_)

/* Initialized data */

struct {
    complex e_1;
    doublereal e_2;
    real e_3;
    integer e_4;
    logical e_5;
    integer fill_6[13];
    } cmname_ = { (float)1., (float)0., 2., (float)3., 4, TRUE_ };


/* Table of constant values */

static integer c_\|\^_14 = 14;

/* Main program */ MAIN_\|\^_()
{

    /* Local variables */

#define d ((doublereal *)&cmname_1)
#define i ((integer *)&cmname_1)
#define l ((logical *)&cmname_1)
#define r ((real *)&cmname_1)
    extern /* Subroutine */ int sam_();

    sam_(cmname_1.c, d, &r[1], &i[2], &m[3], "some hollerith", &c_\|\^_14, 14L);
} /* MAIN_\|\^_ */

#undef r
#undef l
#undef i
#undef d
.P2
As this example shows, $f2c$ turns a Fortran MAIN program into
a C function named
.CW MAIN_\|\^_ .
Why not
.CW main ?
Well, $libF77$ contains a C main routine that arranges
for files to be closed automatically when the Fortran program stops,
arranges for an error message to be printed if a floating-point
exception occurs, and arranges for the command-line argument
accessing functions
.CW iargc
and
.CW getarg
to work properly.  This C main routine invokes
.CW MAIN_\|\^_ .
.SH
6.  PORTABILITY ISSUES
.PP
Three portability issues are relevant to $f2c$:
the portability of the support libraries ($libF77$ and $libI77$)
upon which the translated C programs rely,
that of the converter $f2c$ itself,
and that of the C it produces.
.PP
Regarding the first issue,
some vendors (e.g., Sun and MIPS) have changed the calling conventions for
their $libI77$ from the original conventions (those of
.[ [
Feldman Weinberger Portable Fortran
.]]).
Other vendors (e.g., MIPS) have changed the $libF77$ calling conventions
(e.g., for
.CW complex -valued
functions).
Thus, having libraries $libF77$ and $libI77$
or otherwise having library routines with the names
that $f2c$ expects is insufficient.
When using a machine whose vendor provides but has gratuitously changed
$libF77$ or $libI77$, one cannot safely mix objects compiled
from the C produced by $f2c$ with objects compiled by the vendor's
Fortran compiler, and one must use the correct libraries with
programs translated by $f2c$.  In such a case, the recommended procedure
is to obtain source for the libraries (e.g. from
.I netlib
\(em see \(sc8), combine them into a single library, say
.CW libf2c ,
and install the library where it they can be conveniently accessed.
On a UNIX system, for example, one might install
.CW libf2c
in
.CW /usr/lib/libf2c.a ;
then one could issue the command
.P1
cc *.c -lf2c -lm
.P2
to compile and link a program translated by $f2c$.
.PP
The converter itself is reasonably portable and has run successfully on Apollo,
Cray, IBM, MIPS, SGI, Sun and DEC VAX equipment, all running some
version of the UNIX operating system.
However, we shall see that the C it produces may not be portable due to
subtle storage management issues in Fortran 77.
In any case, the C output of $f2c$ will run fine, at least if
the \f(CW\%-W\fIn\fR option (see Appendix B) is used to set the
number of characters per word correctly, and if C
.CW double
values may fall on an odd-word boundary.
.PP
The Fortran 77 standard says that \f(CWComplex\fP and \f(CWDouble Precision\fP
objects occupy two ``units'' of space while other non-character data types
occupy one ``unit.''
It may be necessary to edit the header file
.CW f2c.h
to make these assumptions hold, if possible.
On the Cray, for example,
.CW float
and
.CW double
are the same C types, and Fortran double precision, if
available, would correspond to the C type
.CW "long double" .
In this case, changing the definition of
.CW doublereal
in
.CW f2c.h
from
.P1
typedef double doublereal;
.P2
to
.P1
typedef long double doublereal;
.P2
would be appropriate.  For the Think C compiler on the
Macintosh, on the other hand, this line would need to become
.P1
typedef short double doublereal;
.P2
.PP
If your C compiler predefines symbols that could clash with
translated Fortran variable names, then you should also
add appropriate
.CW #undef
lines to
.CW f2c.h .
The current default
.CW f2c.h
provides the following
.CW #undef
lines for the following symbols:
.TS
center;
lfCW lfCW lfCW lfCW lfCW lfCW.
cray	mc68020	sgi	sun2	u370	u3b5
gcos	mips	sparc	sun3	u3b	unix
mc68010	pdp11	sun	sun4	u3b2	vax
.TE
.PP
As an extension to the Fortran 77 Standard, $f2c$
allows noncharacter variables to be initialized with character
data.  This extension is inherently nonportable, as the number
of characters storable per ``unit'' varies from machine to machine.
Since 32 bit machines are the most plentiful, $f2c$
assumes 4 characters per Fortran ``unit'', but this assumption
can be overridden by the \f(CW\%-W\fIn\fR command-line option.
For example,
.CW \%-W8
is appropriate for C that is to be run on Cray computers,
since Crays store 8 characters per word.
An example is helpful here:  the Fortran
.P1
      data i/'abcd'/
      j = i
      end
.P2
turns into
.P1
    /* Initialized data */

    static struct {
	char e_1[4];
	} equiv_3 = { {'a', 'b', 'c', 'd'} };

#define i (*(integer *)&equiv_3)

    static integer j;

    j = i;
\&. . .
#undef i
.P2
(Some use of
.CW i ,
e.g. ``\f(CWj = i\fR'', is necessary or $f2c$
will see that
.CW i
is not used and will not initialize it.)  If the target
machine were a Cray and the string were
.CW 'abcdefgh'
or \f(CW"abcdefhg"\fR,
then the Fortran would run fine, but the C produced by $f2c$ would only
store \f(CW"abcd"\fR
in i, $4$ being the default number of characters per word.
The $f2c$ command-line option
.CW \%-W8
gives the correct initialization for a Cray.
.PP
The initialization above is clumsy, using $4$ separate characters.
Using the option
.CW -A ,
for ANSI, produces
.P1
\&. . .
	} equiv_3 = { "abcd" };
\&. . .
.P2
See Appendix B.
.PP
The above examples explain why the Fortran 77 standard excludes
Hollerith data statements: the number of characters per word is
not specified and hence such code is not portable even in Fortran.
(Fortran that conservatively assumes only 1 or 2 characters per word is
portable but messy.  Note that Fortran 77 forbids the mixing, via
.CW common ,
.CW data ,
or
.CW equivalence ,
of character and noncharacter types.  Like many Fortran compilers,
$f2c$ permits such nonportable mixing;
initialization of numeric variables with Hollerith data is one
example of this mixing.)
.PP
Some Fortran 66 programs pass Hollerith strings to
.CW integer
variables.  $F2c$ treats a Hollerith string as a character string,
but this may lead to bus errors on some systems if the character
string winds up being improperly aligned.  The
.CW \%-h
option instructs $f2c$ to try to give character variables
and constants the same alignment as
.CW integer s.
Under
.CW \%-h ,
for example,  the Fortran
.P1
      call foo("a string")
      call goo(8ha string)
.P2
is translated to
.P1
static struct { integer fill; char val[8+1]; char fill2[3]; } c_b1_st = { 0,
	"a string" };
#define c_b1 c_b1_st.val
\&. . .
    foo_(c_b1, 8L);
    goo_(c_b1, 8L);
\&. . .
.P2
.PP
Some systems require that C values of type
.CW double
be aligned on a double-word boundary.  Fortran
.CW common
and
.CW equivalence
statements may require some C
.CW double
values to be aligned on an odd-word boundary.
On systems where double-word alignment is required,
C compilers pad structures, if necessary, to arrange
for the right alignment.  Often such padding has no effect on
the validity of $f2c$'s
translation, but using
.CW common
or
.CW equivalence ,
it is easy to contrive examples in which
the translated C works incorrectly.
$F2c$ issues a warning message when double-word alignment may
cause trouble, but, like $f77$,
it makes no attempt to circumvent this trouble;
the run-time costs of circumvention would be substantial.
.PP
Long decimal strings in \f(CWdata\fP statements are passed to C unaltered.
However, expressions involving long decimal strings are rounded
in a machine-dependent manner.
On a VAX 8550, the Fortran
.P1
      x=1.2**10
      end
.P2
yields the C
.P1
    static real x;

    x = (float)6.1917364224000008;
.P2
.PP
ANSI C compilers require that all but one instance of any entity with external scope,
such as the \f(CWstruct\fPs into which $f2c$ translates \f(CWcommon\fP,
be declared \f(CWextern\fP and that exactly one declaration should define the entity,
i.e., should not be declared \f(CWextern\fP.
Most older C compilers have no such restriction.
To be compatible with ANSI usage, the $f2c$
command-line option
.CW -ec
causes the \f(CWstruct\fP corresponding
to an uninitialized \f(CWcommon\fP region to be declared \f(CWextern\fP
and makes a
.CW union
of all successive declarations of that
\f(CWcommon\fP region into a defining declaration placed in a file with the
name \f(CWcname_com.c\fR, where
.CW cname
is the name of the \f(CWcommon\fP region.
For example, the Fortran
.P1
      common /cmname/ c
      complex c(10)
      c(1)=cmplx(1.,0.)
      call sam(c)
      end
      subroutine sam(c)
      complex c
      common /cmname/ca
      complex ca(10)
      ca(2) = cmplx(1e0,2e0)
      return
      end
.P2
when converted by \f(CWf2c -ec\fP produces
.P1
/* Common Block Declarations */

union {
    struct {
	complex c[10];
    } _1;
    struct {
	complex ca[10];
    } _2;
} cmname_;

#define cmname_1 (cmname_._1)
#define cmname_2 (cmname_._2)

/* Main program */ MAIN_\|\^_()
{

    extern /* Subroutine */ int sam_();

    cmname_1.c[0].r = (float)1., cmname_1.c[0].i = (float)0.;
    sam_(cmname_1.c);
} /* MAIN_\|\^_ */

/* Subroutine */ int sam_(c)
complex *c;
{
    cmname_2.ca[1].r = (float)1., cmname_2.ca[1].i = (float)2.;
    return 0;
} /* sam_ */
.P2
as well as the file
.CW cmname_com.c :
.P1
#include "f2c.h"
union {
    struct {
	complex c[10];
    } _1;
    struct {
	complex ca[10];
    } _2;
} cmname_;
.P2
The files
.CW *_com.c
may be compiled into a library
against which one can load to satisfy overly fastidious ANSI C compilers.
.PP
The rules of Fortran 77 apparently permit a situation in which
$f2c$ declares a function to be of type
.CW int ,
then defines it to be of another type, as illustrated by the
first example in \(sc7.  In that example, $f2c$ discovers too late that
.CW f
is not a subroutine.  With some C compilers, this causes nothing
worse than a warning message; with others, it causes the compilation
to be aborted.  With unforgiving C compilers, one can usually avoid
trouble by splitting the Fortran source into one file per
procedure, e.g., with the
.I fsplit (1)
command, and converting each procedure separately.
Another solution is to use prototypes, as discussed in \(sc7.
.PP
With an ANSI C system that enforced consistent
prototype declarations across separate compilations,
it would be impossible to translate the main program correctly
in the last example just by looking at the main program.
Recent C++ compilers do enforce the consistency of
prototype declarations across separate compilations,
e.g., by encoding calling sequences into the translated names of functions,
except for functions that are declared \f(CWextern "C"\fR and
compiled separately.
$F2c$ allows one to use this escape hatch:  under
.CW -C++ ,
$f2c$ inserts
.P1
#ifdef _\|\^_cplusplus
extern "C" {
#endif
.P2
at the beginning of its C++ output and places
.P1
#ifdef _\|\^_cplusplus
	}
#endif
.P2
at the end of its C++ output.  The
.CW "#ifdef _\|\^_cplusplus"
lines are for the benefit of older C++ compilers that
do not recognize \f(CWextern "C"\fR.
.SH
7. PROTOTYPES
.PP
In ANSI C and C++, a
.I prototype
describes the calling sequence of a function.
Prototypes can save debugging time by helping catch
errors in calling sequences.  The
.CW \%-P
option instructs $f2c$ to emit prototypes for all
the functions defined in the C it produces; specifically,
$f2c$ creates a \fIfile\f(CW.P\fR of prototypes
for each input \fIfile\f(CW.f\fR or \fIfile\f(CW.F\fR.
One can then arrange for relevant prototype files
to be seen by the C compiler.
For instance, if $f2c$'s
header file
.CW f2c.h
is installed as
.CW /usr/include/f2c.h ,
one could issue the UNIX command
.P1
cat /usr/include/f2c.h *.P >f2c.h
.P2
to create a local copy of
.CW f2c.h
that has in it all the prototypes in
.CW *.P .
Since the C produced by $f2c$ always specifies
.P1
#include "f2c.h"
.P2
(rather than
.CW "#include <f2c.h>" ),
the C compiler will look first in the current directory for
.CW f2c.h
and thus will find the local copy that contains the prototypes.
.PP
$F2c$ can also read the prototype files it writes;
one simply specifies them as arguments to $f2c$.
In fact, $f2c$ reads all prototype files before any
Fortran files; although multiple Fortran files are handled
independently, any prototype file arguments apply to all of them.
$F2c$ has more detailed knowledge of Fortran types than it conveys
in the C it puts out; for example,
.CW logical
and
.CW integer
are different Fortran types, but are mapped to the same C type.
Moreover,
.CW character ,
.CW complex ,
and
.CW "double complex"
Fortran functions are all translated to
.CW VOID
C functions, and, unless the
.CW \%-R
option is specified, both
.CW real
and
.CW "double precision"
Fortran functions are translated to
.CW doublereal
C functions.  Because $f2c$ denotes all these
types differently in its prototype files, it
can catch errors that are invisible to an ANSI C
(or C++) compiler.
.PP
The following table shows the types
that $f2c$ uses for procedure arguments:
.TS
center box;
lfCW lfCW.
C_fp	complex
D_fp	doublereal
E_fp	real\fR under \f(CW-!R\fR (the default)\fP
H_fp	character
I_fp	integer\fR or \f(CWinteger*4
J_fp	integer*2
K_fp	shortlogical\fR (\f(CWlogical\fR under \f(CW-i2\fR or \f(CW-I2\fR)\fP
L_fp	logical
R_fp	real\fR under \f(CW-R
S_fp	subroutine\fR
U_fp	\fRuntyped \f(CWexternal
Z_fp	doublecomplex
.TE
These types are defined in
.CW f2c.h ;
they appear in prototypes and, under
.CW \%-A
or
.CW \%-C++ ,
in the C that $f2c$ writes.  Prototypes also use special
.CW void
types to denote the return values of
.CW complex ,
.CW "double complex",
and
.CW character
functions:
.TS
center box;
lfCW lfCW.
C_f	complex
H_f	character
Z_f	double complex
.TE
.PP
$F2c$ also writes special comments in prototype files giving
the length of each
.CW common
block; when given prototype files as arguments, $f2c$ reads
these special comments so it can issue a warning message if its
Fortran input specifies a different length for some
.CW common
block.
.PP
Sometimes people write otherwise valid Fortran 77 that
specifies different lengths for a
.CW common
block.  If such Fortran is split into several files and converted
to C, the loader could end up giving too little space to the
.CW common
block in question.  One can avoid the confusion this could cause by
running $f2c$ twice, first with
.CW \%-P!c ,
then with the resulting prototypes as additional arguments;
the prototypes let $f2c$ determine (and convey to all of its
output C files) the true length needed for
each
.CW common
block.
.PP
One complication with prototypes comes from Fortran subprograms that
declare a procedure to be
.CW external
but do not explicitly specify a type for it and only
pass it as a parameter to another procedure.  (If the
subprogram also invokes the
.CW external
procedure, then $f2c$ can tell whether the procedure is
a subroutine or a function; in the latter case, Fortran's
implicit typing rules specify a type for the procedure.)
If it can do no better, then $f2c$ assumes that untyped
.CW external
procedures are subroutines (and hence become
.CW int -valued
functions in C).
This can cause the generated C to have
multiple and inconsistent declarations for some procedures.
For example,
.P1
	external f
	call foo(f)
	end
	function f(x)
	double precision f, x
	f = x
	end
.P2
results in
.CW MAIN_\|\^_
declaring
.P1
    extern /* Subroutine */ int f_();
.P2
and in the subsequent definition of
.CW "doublereal f_(x)"
in the same C file.
Such inconsistencies are grounds for some C compilers
to abort compilation.
.PP
$F2c$'s type inferences only apply sequentially to
the procedures in a file, because $f2c$ writes C for each procedure
before reading the next one.  Thus, as just illustrated, if procedure
.CW xyz
comes after
.CW abc
in a Fortran input file, then $f2c$ cannot use information
it gains when it sees the definition of
.CW xyz
to deduce types for
.CW external
procedures passed as arguments to
.CW xyz
by
.CW abc .
By using the
.CW \%-P
option and running $f2c$ several times, one can
get around this deficiency.  For instance, if file
.CW zap.f
contains the Fortran shown above, then the commands
.P1
	f2c -P!c zap.f
	f2c -A zap.[fP]
.P2
result in a file
.CW zap.c
in which
.CW MAIN_\|\^_
correctly types
.CW f_
and
.CW foo_
as
.P1
    extern doublereal f_();
    extern /* Subroutine */ int foo_(D_fp);
.P2
rather than
.P1
    extern /* Subroutine */ int f_();
    extern /* Subroutine */ int foo_(U_fp);
.P2
The first invocation of $f2c$ results in a file
.CW zap.P
containing
.P1
extern doublereal f_(doublereal *x);
/*:ref: foo_ 10 1 200 */
.P2
The second invocation of $f2c$ is able to type
.CW f_
and
.CW foo_
correctly because of the first line in
.CW zap.P .
.PP
The second line in
.CW zap.P
is a special comment that records the incomplete type
information that $f2c$ has about
.CW foo_ .
$F2c$ puts one such special comment in the prototype file for each
Fortran procedure that is referenced but not defined in the Fortran file.
When it reads prototype files, $f2c$ deciphers these comments and
uses them to check the consistency of calling sequences.
As it learns more about untyped external procedures, $f2c$ updates
the information it has on them; the
.CW :ref:
comments it writes in a prototype file reflect $f2c$'s latest knowledge.
.PP
Ordinarily $f2c$ tries to infer the type of an untyped
.CW external
procedure from its use as arguments to procedures of
known argument types.  For example, if
.CW f.f
contains just
.P1
	external f
	call foo(f)
	end
.P2
and if
.CW foo.P
contains
.P1
extern int foo_(D_fp);
.P2
then
.P1
f2c -A f.f foo.P
.P2
results in the declaration
.P1
    extern doublereal f_();
.P2
Under unusual circumstances, such type inferences
can lead to erroneous error messages or to incorrect typing.
Here is an example:
.P1
	subroutine zoo
	external f
	double precision f
	external g
	call zap(1,f)
	call zap(2,g)
	end
	subroutine goo
	call g
	end
.P2
$F2c$ first infers g to be a double precision function, then discovers
that it must be a subroutine and issues a warning message about
inconsistent declarations for
.CW g .
This example is legal Fortran 77;
.CW zap
could be defined, for instance, by
.P1
	subroutine zap(n,f)
	external f
	if (n .le. 1) call zap1(f)
	if (n .ge. 2) call zap2(f)
	end
.P2
In such a case one can specify the
.CW \%-!it
option to instruct $f2c$ not to infer the types of otherwise
untypable
.CW external
procedures from their appearance as arguments to known procedures.
Here is another (somewhat far-fetched) example where
.CW \%-!it
is useful:
.P1
	subroutine grok(f,g,h)
	external f, g, h
	logical g
	call foo(1,g)
	call foo(2,f)
	call zit(1,f)
	call zit(2,h)
	call zot(f(3))
	end
.P2
Without
.CW \%-!it ,
$f2c$ first infers
.CW f_
to be a
.CW logical
function, then discovers that Fortran's implicit typing
rules require it to be a
.CW real
function.
$F2c$ issues the
warning message
.CW "fixing wrong type inferred for f" '', ``
which should serve as a warning that $f2c$ may have made some
incorrect type inferences in the mean time.
Indeed, $f2c$ ends up typing
.CW h_
as a
.CW logical
function; with
.CW \%-!it
specified, $f2c$ types
.CW h_
as an
.CW external
procedure unknown type, i.e., a
.CW U_fp ,
which to the C compiler appears to be a subroutine.
(Even with
.CW \%-!it
specified, $f2c$ issues a warning message about inconsistent
calling sequences for
.CW foo .)
.PP
Because $f2c$ writes its latest knowledge of types into
prototype files, it is easy to write a crude (Bourne) shell script
that will glean the maximum possible type information:
.P1
>f.p
until
	f2c -Pit f.p f.f
	cmp -s f.p f.P
do
	mv f.P f.p
	done
.P2
In such scripts, use of the
.CW \%-Ps
option can save an iteration;
.CW \%-Ps
implies
.CW \%-P
and instructs $f2c$ to issue return code 4 if another
iteration might change a declaration or prototype.
Thus the following script is more efficient:
.EQ
delim off
.EN
.P1
while :; do
	f2c -Ps f.[fP]
	case $? in 4) ;; *) break;; esac
	done
.P2
.EQ
delim $$
.EN
The number of iterations depends on the call graph of the
procedures in
.CW f.f
and on their order of appearance in
.CW f.f .
Sorting them into topological order (so that if
.CW abc
calls
.CW def ,
then
.CW abc
precedes
.CW def )
and reverse topological order and alternating between
the two orders
is probably a good heuristic.
For example, we were able to completely type
the \s-2PORT3\s+2 subroutine library
in two passes by first processing it in reverse topological order,
then in forward order.  Unfortunately, one can devise situations
where arbitrarily many iterations are required.  This is slightly
annoying, since with appropriate data structures (in an extensively
reorganized version of $f2c$), one could do this calculation
in linear time.
.SH
8. EXPERIENCE WITH \f(BInetlib\fP
.PP
With the help of Eric Grosse, we arranged for the $netlib$
.[ [
Dongarra Grosse 1987
.]]
server
.CW netlib@research.att.com
to provide an experimental Fortran-to-C translation service
by electronic mail.
By executing the UNIX command
.sp .5
.ce
\f(CW(echo execute f2c; cat foo.f) | mail netlib@research.att.com\fR
.sp .5
one submits the Fortran in
.CW foo.f
to $netlib$'s $f2c$ service;
$netlib$ replies with the C and diagnostic messages produced by $f2c$ from
.CW foo.f .
(The
.CW include
mechanism described in \(sc3 makes no sense in this
context, so it is disabled.)  To start using this service,
one would generally execute
.sp .5
.ce
\f(CWecho 'send index from f2c' | mail netlib@research.att.com\fR
.sp .5
to check on the current status of the service.
Before compiling the returned C, it is necessary to get a copy of
.CW f2c.h :
.sp .5
.ce
\f(CWecho 'send f2c.h from f2c' | mail netlib@research.att.com\fR
.sp .5
Most likely it would also be necessary to obtain source for the
versions of $libF77$ and $libI77$ assumed by $f2c$:
.sp .5
.ce
\f(CWecho 'send libf77 libi77 from f2c' | mail netlib@research.att.com\fR
.PP
For testing purposes, we retain the original Fortran submitted to
$netlib$'s
.CW "execute f2c" '' ``
service.  Observing $f2c$'s behavior on over 400,000 lines
of submitted Fortran helped
us find many obscure bugs and led us to make some of the
extensions described in \(sc3.  For example, a
.CW "block data"
subprogram initializing a variable that does not appear
in any
.CW common
blocks now elicits a warning message (rather than causing
$f2c$ to drop core).  Another example is that $f2c$
now gives the warning message
.CW "Statement order error: declaration after DATA" '' ``
and declines to produce any C
if a declaration comes after a
.CW data
statement (for reasons discussed in \(sc9);
$f2c$ formerly gave a more obscure error message
and then produced invalid C.
.PP
Now that $netlib$ offers source for $f2c$ itself (as explained
in the
.CW index
file mentioned above), we expect to curtail $netlib$'s
.CW "execute f2c" '' ``
service, perhaps limiting it to employees of AT&T and Bellcore;
to learn the current state of affairs, request the current
.CW index
file.
.SH
9. POSSIBLE EXTENSIONS
.PP
Currently $f2c$ simplifies constant expressions.
It would be nice if constant expressions were simply
passed through, and if Fortran
.CW parameter s
were translated as
.CW #define s.
Unfortunately, several things conspire to make this
nearly impossible to do in full generality.
Perhaps worst is that
.CW parameter s
may be assigned
.CW complex
or
.CW doublecomplex
expressions that might, for example, involve complex division
and exponentiation to a large integer power.
.CW Parameter s
may appear in
.CW data
statements, which may initialize
.CW common
variables and so be moved near the beginning of the C output.
Arranging to have the right
.CW #define s
in effect for the data initialization would, in this worst case,
be a nightmare.  Of course, one could arrange to
handle ``easy'' cases with unsimplified constant expressions
and
.CW #define s
for parameters.
.PP
Prototypes and the argument consistency checks currently ignore
alternate return specifiers.  Prototypes could be adorned with
special comments indicating where alternate return specifiers
are supposed to come, or at least telling the number of such
specifiers, which is all that really matters.
Since alternate return specifiers are rarely used
(Fortran 90 calls them ``obsolescent''),
we have so far refrained from this exercise.
.PP
Fortran 90 allows
.CW data
statements to appear anywhere.  It would be nice if $f2c$ could
do the same, but that would entail major rewriting of $f2c$.
Presently
.CW data
values are written to a file as soon as they are seen; among
the information in the file is the offset of each value.
If an
.CW equivalence
statement could follow the
.CW data
statement, then the offsets would be invalidated.
.PP
It would be fairly straightforward to extend $f2c$'s I/O
to encompass the new specifiers introduced by Fortran 90.
Unfortunately, that would mean changing $libI77$ in ways
that would make it incompatible with $f77$.
.PP
Of course, it would be nice to translate all of Fortran 90, but
some of the Fortran 90 array manipulations would require new
calling conventions and large enough revisions to $f2c$ that
one might be better off starting from scratch.
.PP
With sufficient hacking,
$f2c$ could be modified to recognize
Fortran 90 control structures
.CW case , (
.CW cycle , 
.CW exit ,
and named loops), local arrays of
dimensions that depend on arguments and common values,
and such types as
.CW logical*1 ,
.CW logical*2 ,
.CW integer*1
or
.CW byte .
Since our main concern is with making portable Fortran 77
libraries available to the C world, we have so far refrained
from these further extensions.  Perhaps commercial
vendors will wish to provide some of these extensions.
.SH
10. REFERENCES
.LP
.so tmac.sdisp1
.[
$LIST$
.]
