|
|
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.