Annotation of researchv10no/cmd/f2c/doc/proto, revision 1.1.1.1

1.1       root        1: .SH
                      2: 7. PROTOTYPES
                      3: .PP
                      4: In ANSI C and C++, a
                      5: .I prototype
                      6: describes the calling sequence of a function.
                      7: Prototypes can save debugging time by helping catch
                      8: errors in calling sequences.  The
                      9: .CW \%-P
                     10: option instructs $f2c$ to emit prototypes for all
                     11: the functions defined in the C it produces; specifically,
                     12: $f2c$ creates a \fIfile\f(CW.P\fR of prototypes
                     13: for each input \fIfile\f(CW.f\fR or \fIfile\f(CW.F\fR.
                     14: One can then arrange for relevant prototype files
                     15: to be seen by the C compiler.
                     16: For instance, if $f2c$'s
                     17: header file
                     18: .CW f2c.h
                     19: is installed as
                     20: .CW /usr/include/f2c.h ,
                     21: one could issue the UNIX command
                     22: .P1
                     23: cat /usr/include/f2c.h *.P >f2c.h
                     24: .P2
                     25: to create a local copy of
                     26: .CW f2c.h
                     27: that has in it all the prototypes in
                     28: .CW *.P .
                     29: Since the C produced by $f2c$ always specifies
                     30: .P1
                     31: #include "f2c.h"
                     32: .P2
                     33: (rather than
                     34: .CW "#include <f2c.h>" ),
                     35: the C compiler will look first in the current directory for
                     36: .CW f2c.h
                     37: and thus will find the local copy that contains the prototypes.
                     38: .PP
                     39: $F2c$ can also read the prototype files it writes;
                     40: one simply specifies them as arguments to $f2c$.
                     41: In fact, $f2c$ reads all prototype files before any
                     42: Fortran files; although multiple Fortran files are handled
                     43: independently, any prototype file arguments apply to all of them.
                     44: $F2c$ has more detailed knowledge of Fortran types than it conveys
                     45: in the C it puts out; for example,
                     46: .CW logical
                     47: and
                     48: .CW integer
                     49: are different Fortran types, but are mapped to the same C type.
                     50: Moreover,
                     51: .CW character ,
                     52: .CW complex ,
                     53: and
                     54: .CW "double complex"
                     55: Fortran functions are all translated to
                     56: .CW VOID
                     57: C functions, and, unless the
                     58: .CW \%-R
                     59: option is specified, both
                     60: .CW real
                     61: and
                     62: .CW "double precision"
                     63: Fortran functions are translated to
                     64: .CW doublereal
                     65: C functions.  Because $f2c$ denotes all these
                     66: types differently in its prototype files, it
                     67: can catch errors that are invisible to an ANSI C
                     68: (or C++) compiler.
                     69: .PP
                     70: The following table shows the types
                     71: that $f2c$ uses for procedure arguments:
                     72: .TS
                     73: center box;
                     74: lfCW lfCW.
                     75: C_fp   complex
                     76: D_fp   doublereal
                     77: E_fp   real\fR under \f(CW-!R\fR (the default)\fP
                     78: H_fp   character
                     79: I_fp   integer\fR or \f(CWinteger*4
                     80: J_fp   integer*2
                     81: K_fp   shortlogical\fR (\f(CWlogical\fR under \f(CW-i2\fR or \f(CW-I2\fR)\fP
                     82: L_fp   logical
                     83: R_fp   real\fR under \f(CW-R
                     84: S_fp   subroutine\fR
                     85: U_fp   \fRuntyped \f(CWexternal
                     86: Z_fp   doublecomplex
                     87: .TE
                     88: These types are defined in
                     89: .CW f2c.h ;
                     90: they appear in prototypes and, under
                     91: .CW \%-A
                     92: or
                     93: .CW \%-C++ ,
                     94: in the C that $f2c$ writes.  Prototypes also use special
                     95: .CW void
                     96: types to denote the return values of
                     97: .CW complex ,
                     98: .CW "double complex",
                     99: and
                    100: .CW character
                    101: functions:
                    102: .TS
                    103: center box;
                    104: lfCW lfCW.
                    105: C_f    complex
                    106: H_f    character
                    107: Z_f    double complex
                    108: .TE
                    109: .PP
                    110: $F2c$ also writes special comments in prototype files giving
                    111: the length of each
                    112: .CW common
                    113: block; when given prototype files as arguments, $f2c$ reads
                    114: these special comments so it can issue a warning message if its
                    115: Fortran input specifies a different length for some
                    116: .CW common
                    117: block.
                    118: .PP
                    119: Sometimes people write otherwise valid Fortran 77 that
                    120: specifies different lengths for a
                    121: .CW common
                    122: block.  If such Fortran is split into several files and converted
                    123: to C, the loader could end up giving too little space to the
                    124: .CW common
                    125: block in question.  One can avoid the confusion this could cause by
                    126: running $f2c$ twice, first with
                    127: .CW \%-P!c ,
                    128: then with the resulting prototypes as additional arguments;
                    129: the prototypes let $f2c$ determine (and convey to all of its
                    130: output C files) the true length needed for
                    131: each
                    132: .CW common
                    133: block.
                    134: .PP
                    135: One complication with prototypes comes from Fortran subprograms that
                    136: declare a procedure to be
                    137: .CW external
                    138: but do not explicitly specify a type for it and only
                    139: pass it as a parameter to another procedure.  (If the
                    140: subprogram also invokes the
                    141: .CW external
                    142: procedure, then $f2c$ can tell whether the procedure is
                    143: a subroutine or a function; in the latter case, Fortran's
                    144: implicit typing rules specify a type for the procedure.)
                    145: If it can do no better, then $f2c$ assumes that untyped
                    146: .CW external
                    147: procedures are subroutines (and hence become
                    148: .CW int -valued
                    149: functions in C).
                    150: This can cause the generated C to have
                    151: multiple and inconsistent declarations for some procedures.
                    152: For example,
                    153: .P1
                    154:        external f
                    155:        call foo(f)
                    156:        end
                    157:        function f(x)
                    158:        double precision f, x
                    159:        f = x
                    160:        end
                    161: .P2
                    162: results in
                    163: .CW MAIN_\|_
                    164: declaring
                    165: .P1
                    166:     extern /* Subroutine */ int f_();
                    167: .P2
                    168: and in the subsequent definition of
                    169: .CW "doublereal f_(x)"
                    170: in the same C file.
                    171: Such inconsistencies are grounds for some C compilers
                    172: to abort compilation.
                    173: .PP
                    174: $F2c$'s type inferences only apply sequentially to
                    175: the procedures in a file, because $f2c$ writes C for each procedure
                    176: before reading the next one.  Thus, as just illustrated, if procedure
                    177: .CW xyz
                    178: comes after
                    179: .CW abc
                    180: in a Fortran input file, then $f2c$ cannot use information
                    181: it gains when it sees the definition of
                    182: .CW xyz
                    183: to deduce types for
                    184: .CW external
                    185: procedures passed as arguments to
                    186: .CW xyz
                    187: by
                    188: .CW abc .
                    189: By using the
                    190: .CW \%-P
                    191: option and running $f2c$ several times, one can
                    192: get around this deficiency.  For instance, if file
                    193: .CW zap.f
                    194: contains the Fortran shown above, then the commands
                    195: .P1
                    196:        f2c -P!c zap.f
                    197:        f2c -A zap.[fP]
                    198: .P2
                    199: result in a file
                    200: .CW zap.c
                    201: in which
                    202: .CW MAIN_\|_
                    203: correctly types
                    204: .CW f_
                    205: and
                    206: .CW foo_
                    207: as
                    208: .P1
                    209:     extern doublereal f_();
                    210:     extern /* Subroutine */ int foo_(D_fp);
                    211: .P2
                    212: rather than
                    213: .P1
                    214:     extern /* Subroutine */ int f_();
                    215:     extern /* Subroutine */ int foo_(U_fp);
                    216: .P2
                    217: The first invocation of $f2c$ results in a file
                    218: .CW zap.P
                    219: containing
                    220: .P1
                    221: extern doublereal f_(doublereal *x);
                    222: /*:ref: foo_ 10 1 200 */
                    223: .P2
                    224: The second invocation of $f2c$ is able to type
                    225: .CW f_
                    226: and
                    227: .CW foo_
                    228: correctly because of the first line in
                    229: .CW zap.P .
                    230: .PP
                    231: The second line in
                    232: .CW zap.P
                    233: is a special comment that records the incomplete type
                    234: information that $f2c$ has about
                    235: .CW foo_ .
                    236: $F2c$ puts one such special comment in the prototype file for each
                    237: Fortran procedure that is referenced but not defined in the Fortran file.
                    238: When it reads prototype files, $f2c$ deciphers these comments and
                    239: uses them to check the consistency of calling sequences.
                    240: As it learns more about untyped external procedures, $f2c$ updates
                    241: the information it has on them; the
                    242: .CW :ref:
                    243: comments it writes in a prototype file reflect $f2c$'s latest knowledge.
                    244: .PP
                    245: Ordinarily $f2c$ tries to infer the type of an untyped
                    246: .CW external
                    247: procedure from its use as arguments to procedures of
                    248: known argument types.  For example, if
                    249: .CW f.f
                    250: contains just
                    251: .P1
                    252:        external f
                    253:        call foo(f)
                    254:        end
                    255: .P2
                    256: and if
                    257: .CW foo.P
                    258: contains
                    259: .P1
                    260: extern int foo_(D_fp);
                    261: .P2
                    262: then
                    263: .P1
                    264: f2c -A f.f foo.P
                    265: .P2
                    266: results in the declaration
                    267: .P1
                    268:     extern doublereal f_();
                    269: .P2
                    270: Under unusual circumstances, such type inferences
                    271: can lead to erroneous error messages or to incorrect typing.
                    272: Here is an example:
                    273: .P1
                    274:        subroutine zoo
                    275:        external f
                    276:        double precision f
                    277:        external g
                    278:        call zap(1,f)
                    279:        call zap(2,g)
                    280:        end
                    281:        subroutine goo
                    282:        call g
                    283:        end
                    284: .P2
                    285: $F2c$ first infers g to be a double precision function, then discovers
                    286: that it must be a subroutine and issues a warning message about
                    287: inconsistent declarations for
                    288: .CW g .
                    289: This example is legal Fortran 77;
                    290: .CW zap
                    291: could be defined, for instance, by
                    292: .P1
                    293:        subroutine zap(n,f)
                    294:        external f
                    295:        if (n .le. 1) call zap1(f)
                    296:        if (n .ge. 2) call zap2(f)
                    297:        end
                    298: .P2
                    299: In such a case one can specify the
                    300: .CW \%-!it
                    301: option to instruct $f2c$ not to infer the types of otherwise
                    302: untypable
                    303: .CW external
                    304: procedures from their appearance as arguments to known procedures.
                    305: Here is another (somewhat far-fetched) example where
                    306: .CW \%-!it
                    307: is useful:
                    308: .P1
                    309:        subroutine grok(f,g,h)
                    310:        external f, g, h
                    311:        logical g
                    312:        call foo(1,g)
                    313:        call foo(2,f)
                    314:        call zit(1,f)
                    315:        call zit(2,h)
                    316:        call zot(f(3))
                    317:        end
                    318: .P2
                    319: Without
                    320: .CW \%-!it ,
                    321: $f2c$ first infers
                    322: .CW f_
                    323: to be a
                    324: .CW logical
                    325: function, then discovers that Fortran's implicit typing
                    326: rules require it to be a
                    327: .CW real
                    328: function.
                    329: $F2c$ issues the
                    330: warning message
                    331: .CW "fixing wrong type inferred for f" '', ``
                    332: which should serve as a warning that $f2c$ may have made some
                    333: incorrect type inferences in the mean time.
                    334: Indeed, $f2c$ ends up typing
                    335: .CW h_
                    336: as a
                    337: .CW logical
                    338: function; with
                    339: .CW \%-!it
                    340: specified, $f2c$ types
                    341: .CW h_
                    342: as an
                    343: .CW external
                    344: procedure unknown type, i.e., a
                    345: .CW U_fp ,
                    346: which to the C compiler appears to be a subroutine.
                    347: (Even with
                    348: .CW \%-!it
                    349: specified, $f2c$ issues a warning message about inconsistent
                    350: calling sequences for
                    351: .CW foo .)
                    352: .PP
                    353: Because $f2c$ writes its latest knowledge of types into
                    354: prototype files, it is easy to write a crude script
                    355: that will glean the maximum possible type information:
                    356: .P1
                    357: >f.p
                    358: until
                    359:        f2c -Pit f.p f.f
                    360:        cmp -s f.p f.P
                    361: do
                    362:        mv f.P f.p
                    363:        done
                    364: .P2
                    365: In such scripts, use of the
                    366: .CW \%-Ps
                    367: option can save an iteration;
                    368: .CW \%-Ps
                    369: implies
                    370: .CW \%-P
                    371: and instructs $f2c$ to issue return code 4 if another
                    372: iteration might change a declaration or prototype.
                    373: Thus the following script is more efficient:
                    374: .EQ
                    375: delim off
                    376: .EN
                    377: .P1
                    378: while :; do
                    379:        f2c -Ps f.[fP]
                    380:        case $? in 4) ;; *) break;; esac
                    381:        done
                    382: .P2
                    383: .EQ
                    384: delim $$
                    385: .EN
                    386: The number of iterations depends on the call graph of the
                    387: procedures in
                    388: .CW f.f
                    389: and on their order of appearance in
                    390: .CW f.f .
                    391: Sorting them into topological order (so that if
                    392: .CW abc
                    393: calls
                    394: .CW def ,
                    395: then
                    396: .CW abc
                    397: precedes
                    398: .CW def )
                    399: and reverse topological order and alternating between
                    400: the two orders
                    401: is probably a good heuristic.
                    402: For example, we were able to completely type
                    403: the \s-2PORT3\s+2 subroutine library
                    404: in two passes by first processing it in reverse topological order,
                    405: then in forward order.  Unfortunately, one can devise situations
                    406: where arbitrarily many iterations are required.  This is slightly
                    407: annoying, since with appropriate data structures (in an extensively
                    408: reorganized version of $f2c$), one could do this calculation
                    409: in linear time.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.