|
|
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.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.