|
|
1.1 root 1: . \"define f2c % "\f(CWf2c\fP" %
2: . \"define F2c % "\f(CWF2c\fP" %
3: .de Bp
4: .ft R
5: .sp .5
6: .in \w'\(bu\ 'u
7: .ti 0
8: \(bu\ \c
9: ..
10: .EQ
11: define dollar % "\f(CW$\fP" %
12: delim $$
13: define f2c % "f\|2c" %
14: define F2c % "F\^2c" %
15: define libF77 % "libF77" %
16: define libI77 % "libI77" %
17: define LibF77 % "LibF77" %
18: define LibI77 % "LibI77" %
19: .EN
20: .TL
21: A Fortran to C Converter
22: .AU
23: S. I. Feldman
24: .AI
25: Bellcore
26: Morristown, NJ 07960
27: .AU
28: David M. Gay
29: .AI
30: .MH
31: .AU
32: Mark W. Maimone
33: .AI
34: Carnegie-Mellon University
35: Pittsburgh, PA 15213
36: .AU
37: N. L. Schryer
38: .AI
39: .MH
40: .AB
41: We describe $f2c$, a program that translates Fortran 77
42: into C or C++. $F2c$ lets one portably mix C and Fortran
43: and makes a large body of well-tested Fortran
44: source code available to C environments.
45: .AE
46: .SH
47: 1. INTRODUCTION
48: .PP
49: Automatic conversion of Fortran 77
50: .[ [
51: ANSI FORTRAN 1978
52: .]]
53: to C
54: .[ [
55: Kernighan Ritchie 1978
56: .]
57: .[
58: Kernighan Ritchie 1988
59: .]]
60: is desirable for
61: several reasons. Sometimes it is useful to run a
62: well-tested Fortran program on a machine that has a C
63: compiler but no Fortran compiler. At other times, it
64: is convenient to mix C and Fortran. Some things are
65: impossible to express in Fortran 77 or are harder
66: to express in Fortran than in C
67: (e.g. storage management, some character operations,
68: arrays of functions, heterogeneous data structures,
69: and calls that depend on the operating system),
70: and some programmers simply prefer C to Fortran.
71: There is a large body of well tested
72: Fortran source code for carrying out a wide variety of
73: useful calculations, and it is sometimes desirable to
74: exploit some of this Fortran source in a C environment.
75: Many vendors provide some way of mixing C and Fortran, but
76: the details vary from system to system.
77: Automatic Fortran to C conversion lets one create a
78: .I portable
79: C program that exploits Fortran source code.
80: .PP
81: A side benefit of automatic Fortran 77 to C conversion is that
82: it allows such tools as
83: .I cyntax (1)
84: and
85: .I lint (1)
86: \
87: .[[
88: v101
89: .]]
90: to provide Fortran 77 programs with some of the consistency
91: and portability checks that the Pfort Verifier
92: .[ [
93: Ryder 1974
94: .]]
95: provided to Fortran 66 programs.
96: The consistency checks
97: detect errors in calling sequences
98: and are thus a boon to debugging.
99: .PP
100: This paper describes $f2c$, a Fortran 77 to C converter
101: based on Feldman's original $f77$ compiler
102: .[ [
103: Feldman Weinberger Portable Fortran
104: .]].
105: We have used $f2c$ to convert various large programs and
106: subroutine libraries to C automatically (i.e., with no manual intervention);
107: these include the \s-2PORT3\s+2 subroutine library (\s-2PORT1\s+2
108: is described in
109: .[ [
110: Fox Hall Schryer Algorithm 1978
111: .]
112: .[
113: Fox Hall Schryer port 1978
114: .]]),
115: MINOS
116: .[ [
117: Murtagh Saunders 1987
118: .]],
119: and Schryer's floating-point test
120: .[ [
121: Schryer floating
122: .]].
123: The floating-point test is of particular interest, as it relies
124: heavily on correct evaluation of parenthesized expressions and
125: is bit-level self-testing.
126: .PP
127: As a debugging aid, we sought bit-level compatibility between
128: objects compiled from the C produced by $f2c$ and objects
129: produced by our local $f77$ compiler. That is, on the VAX
130: where we developed $f2c$, we sought to make it impossible to
131: tell by running a Fortran program whether some of its
132: modules had been compiled by $f2c$ or
133: all had been compiled by $f77$. This meant that $f2c$
134: should follow the same calling conventions as $f77$
135: .[ [
136: Feldman Weinberger Portable Fortran
137: .]]
138: and should use $f77$'s support libraries, $libF77$ and $libI77$.
139: .PP
140: Although we have tried to make $f2c$'s output reasonably readable,
141: our goal of strict compatibility with $f77$ implies some nasty
142: looking conversions. Input/output statements, in particular,
143: generally get expanded into
144: a series of calls on routines in $libI77$, $f77$'s I/O library.
145: Thus the C output of $f2c$ would probably be something of a nightmare
146: to maintain as C; it would be much more sensible to maintain the original
147: Fortran, translating it anew each time it changed. Some commercial
148: vendors, e.g., those listed in Appendix A,
149: seek to perform translations yielding C that one
150: might reasonably maintain directly; these translations generally
151: require some manual intervention.
152: .PP
153: The rest of this paper is organized as follows.
154: Section 2 describes the interlanguage conventions used by $f2c$ (and $f77$).
155: \(sc3 summarizes some extensions to Fortran 77 that $f2c$ recognizes.
156: . \"The extensions to Fortran 77 that $f2c$ recognizes are summarized in \(sc3.
157: Example invocations of $f2c$ appear in \(sc4.
158: \(sc5 illustrates various details of $f2c$'s translations, and
159: \(sc6 considers portability issues.
160: \(sc7 discusses the generation and use of
161: .I prototypes ,
162: which can be used both by C++ and ANSI C compilers and by
163: $f2c$ to check consistency of calling sequences.
164: \(sc8 describes our experience with
165: an experimental $f2c$ service provided by $netlib$
166: .[ [
167: Dongarra Grosse 1987
168: .]],
169: and \(sc9 considers possible extensions.
170: Appendix A lists some vendors who offer
171: conversion of Fortran to C that one might maintain as C.
172: Finally, Appendix B contains a $man$ page telling how to use $f2c$.
173: .SH
174: 2. INTERLANGUAGE CONVENTIONS
175: .PP
176: Much of the material in this section is taken from
177: .[ [
178: Feldman Weinberger Portable Fortran
179: .]].
180: .SH
181: Names
182: .PP
183: An $f2c$ extension
184: inspired by Fortran 90 (until recently called Fortran 8x
185: .[ [
186: Fort8x
187: .]])
188: is that long names are allowed ($f2c$ truncates names that are longer
189: than 50 characters), and names may contain underscores. To avoid conflict
190: with the names of library routines and with names that $f2c$ generates,
191: Fortran names may have one or two underscores appended.
192: Fortran names are forced to lower case (unless the
193: .CW \%-U
194: option described in Appendix B is in effect); external names, i.e., the names
195: of Fortran procedures and common blocks, have a single underscore appended
196: if they do not contain any underscores and have a pair of underscores
197: appended if they do contain underscores.
198: Thus Fortran subroutines named
199: .CW ABC ,
200: .CW A_B_C ,
201: and
202: .CW A_B_C_
203: result in C functions named
204: .CW abc_ ,
205: .CW a_b_c_\|\^_ ,
206: and
207: .CW a_b_c_\|\^_\|\^_ .
208: .SH
209: Types
210: .PP
211: The table below shows
212: corresponding Fortran and C declarations;
213: the C declarations use types defined in
214: .CW f2c.h ,
215: a header file upon which $f2c$'s translations rely.
216: The table also shows the C types defined in the standard
217: version of
218: .CW f2c.h .
219: .KS
220: .TS
221: center box;
222: c c c
223: l l l.
224: Fortran C standard \f(CWf2c.h\fP
225: .sp .5
226: integer\(**2 x shortint x; short int x;
227: integer x integer x; long int x;
228: logical x long int x; long int x;
229: real x real x; float x;
230: double precision x doublereal x; double x;
231: complex x complex x; struct { float r, i; } x;
232: double complex x doublecomplex x; struct { double r, i; } x;
233: character\(**6 x char x[6]; char x[6];
234: .TE
235: .KE
236: By the rules of Fortran,
237: .CW integer,
238: .CW logical,
239: and
240: .CW real
241: data occupy the same amount of memory, and
242: .CW "double precision"
243: and
244: .CW complex
245: occupy twice this amount; $f2c$
246: assumes that the types in the C column above are
247: chosen (in
248: .CW f2c.h )
249: so that these assumptions are valid.
250: The translations of the Fortran
251: .CW equivalence
252: and
253: .CW data
254: statements depend on these assumptions.
255: On some machines, one must modify
256: .CW f2c.h
257: to make these assumptions hold. See \(sc6 for examples
258: and further discussion.
259: .SH
260: Return Values
261: .PP
262: A function of type
263: .CW integer ,
264: .CW logical ,
265: or
266: .CW "double precision"
267: must be declared as a C function that returns the corresponding type.
268: If the
269: .CW \%-R
270: option is in effect (see Appendix B), the same is true
271: of a function of type
272: .CW real ;
273: otherwise, a
274: .CW real
275: function must be declared as a C function that returns
276: .CW doublereal ;
277: this hack facilitates our VAX regression testing, as it
278: duplicates the behavior of our local Fortran compiler ($f77$).
279: A
280: .CW complex
281: or
282: .CW "double complex"
283: function is equivalent to a C routine
284: with an additional
285: initial argument that points to the place where the return value is to be stored.
286: Thus,
287: .P1
288: complex function f( . . . )
289: .P2
290: is equivalent to
291: .P1
292: void f_(temp, . . .)
293: complex \(**temp;
294: . . .
295: .P2
296: A character-valued function is equivalent to a C routine with
297: two extra initial arguments:
298: a data address and a length.
299: Thus,
300: .P1
301: character\(**15 function g( . . . )
302: .P2
303: is equivalent to
304: .P1
305: g_(result, length, . . .)
306: char \(**result;
307: ftnlen length;
308: . . .
309: .P2
310: and could be invoked in C by
311: .P1
312: char chars[15];
313: . . .
314: g_(chars, 15L, . . . );
315: .P2
316: Subroutines are invoked as if they were
317: .CW int -valued
318: functions whose value specifies which alternate return to use.
319: Alternate return arguments (statement labels) are not passed to the function,
320: but are used to do an indexed branch in the calling procedure.
321: (If the subroutine has no entry points with alternate return arguments,
322: the returned value is undefined.)
323: The statement
324: .P1
325: call nret(\(**1, \(**2, \(**3)
326: .P2
327: is treated exactly as if it were the Fortran computed
328: .CW goto
329: .P1
330: goto (1, 2, 3), nret( )
331: .P2
332: .SH
333: Argument Lists
334: .PP
335: All Fortran arguments are passed by address.
336: In addition,
337: for every non-function argument that is of type character,
338: an argument giving the length of the value is passed.
339: (The string lengths are
340: .CW ftnlen
341: values, i.e.,
342: .CW "long int"
343: quantities passed by value). In summary, the order of arguments is:
344: extra arguments for complex and character functions,
345: an address for each datum or function, and a
346: .CW ftnlen
347: for each character argument (other than character-valued functions).
348: Thus, the call in
349: .P1
350: external f
351: character\(**7 s
352: integer b(3)
353: . . .
354: call sam(f, b(2), s)
355: .P2
356: is equivalent to that in
357: .P1
358: int f();
359: char s[7];
360: long int b[3];
361: . . .
362: sam_(f, &b[1], s, 7L);
363: .P2
364: Note that the first element of a C array always has subscript zero,
365: but Fortran arrays begin at 1 by default.
366: Because Fortran arrays are stored in column-major order, whereas
367: C arrays are stored in row-major order,
368: $f2c$ translates multi-dimensional Fortran arrays into one-dimensional
369: C arrays and issues appropriate subscripting expressions.
370: .SH
371: 3. EXTENSIONS TO FORTRAN 77
372: .PP
373: Since it is derived from $f77$, $f2c$ supports all of the $f77$ extensions
374: described in
375: .[ [
376: Feldman Weinberger Portable Fortran
377: .]].
378: $F2c$'s extensions include the following.
379: .Bp
380: Type
381: .CW "double complex"
382: (alias
383: .CW "complex*16" )
384: is a double-precision version of
385: .CW complex .
386: Specific intrinsic functions for
387: .CW "double complex"
388: have names that start with
389: .CW z
390: rather than
391: .CW c .
392: An exception to this rule is
393: .CW dimag ,
394: which returns the imaginary part of a
395: .CW "double complex"
396: value;
397: .CW imag
398: is the corresponding generic intrinsic function.
399: The generic intrinsic function
400: .CW real
401: is extended so that it returns the real part of a
402: .CW "double complex"
403: value as a
404: .CW "double precision"
405: value;
406: .CW dble
407: is the specific intrinsic function that does this job.
408: .Bp
409: The ``types'' that may appear in an
410: .CW implicit
411: statement include
412: .CW undefined ,
413: which implies that variables
414: whose names begin with the associated letters
415: must be explicitly declared in a type statement. $F2c$ also
416: recognizes the Fortran 90 statement
417: .P1
418: implicit none
419: .P2
420: as equivalent to
421: .P1
422: implicit undefined(a-z)
423: .P2
424: The command-line option
425: .CW \%-u
426: has the effect of inserting
427: .P1
428: implicit none
429: .P2
430: at the beginning of each Fortran procedure.
431: .Bp
432: Procedures may call themselves recursively, i.e.,
433: may call themselves either directly or indirectly
434: through a chain of other calls.
435: .Bp
436: The keywords
437: .CW static
438: and
439: .CW automatic
440: act as ``types'' in type and implicit statements;
441: they specify storage classes.
442: There is exactly one copy of each
443: .CW static
444: variable, and such variables retain their values between
445: invocations of the procedure in which they appear.
446: On the other hand, each invocation of a procedure gets
447: new copies of the procedure's
448: .CW automatic
449: variables.
450: .CW Automatic
451: variables may not appear in
452: .CW equivalence ,
453: .CW data ,
454: .CW namelist ,
455: or
456: .CW save
457: statements. The command-line option
458: .CW \%-a
459: changes the default storage class from
460: .CW static
461: to
462: .CW automatic
463: (for all variables except those that appear in
464: .CW common ,
465: .CW data ,
466: .CW equivalence ,
467: .CW namelist ,
468: or
469: .CW save
470: statements).
471: .Bp
472: A tab in the first 6 columns signifies that the current line is
473: a free-format line, which may extend beyond column 72.
474: An ampersand
475: .CW &
476: in column 1 indicates that the current line is a free-format
477: continuation line. Lines that have neither an ampersand in column 1
478: nor a tab in the first 6 columns are treated as Fortran 77 fixed-format
479: lines: if shorter than 72 characters, they are padded on the right
480: with blanks until they are 72 characters long; if longer than 72
481: characters, the characters beyond column 72 are discarded.
482: After taking continuations into account,
483: statements may be up to 1320 characters long; this is the only
484: constraint on the length of free-format lines. (This limit is
485: implied by the Fortran 77 standard, which allows at most 19 continuation lines;
486: $1320 ~=~ (1^+^19) ~times~ 66$.)
487: .Bp
488: Aside from quoted strings, $f2c$ ignores case (unless the
489: .CW \%-U
490: option is in effect).
491: .Bp
492: The statement
493: .P1
494: include 'stuff'
495: .P2
496: is replaced by the contents of the file
497: .CW stuff.
498: .CW Include s
499: may be nested to a reasonable depth, currently ten.
500: The command-line option
501: .CW \%-!I
502: disables
503: .CW include s;
504: this option is used by the $netlib$ $f2c$
505: service described in \(sc8 (for which
506: .CW include
507: obviously makes no sense).
508: .Bp
509: $F77$ allows binary, octal, and hexadecimal constants
510: to appear in
511: .CW data
512: statements; $f2c$ goes somewhat further, allowing
513: such constants to appear anywhere; they are treated just
514: like a decimal integer constant having the equivalent value.
515: Binary, octal, and hexadecimal constants may assume one of
516: two forms: a letter followed by a quoted string of digits,
517: or a decimal base, followed by a sharp sign
518: .CW # ,
519: followed by a string of digits (not quoted). The letter is
520: .CW b
521: or
522: .CW B
523: for binary constants,
524: .CW o
525: or
526: .CW O
527: for octal constants, and
528: .CW x ,
529: .CW X ,
530: .CW z ,
531: or
532: .CW Z
533: for hexadecimal constants. Thus, for example,
534: .CW z'a7' ,
535: .CW 16#a7 ,
536: .CW o'247' ,
537: .CW 8#247 ,
538: .CW b'10100111'
539: and
540: .CW 2#10100111
541: are all treated just like the integer
542: .CW 167 .
543: .Bp
544: For compatibility with C, quoted strings may contain the following
545: escapes:
546: .TS
547: center box;
548: lFCW l a lFCW l.
549: \e0 null \ \en newline
550: \e\e \e \ \er carriage return
551: \eb backspace \ \et tab
552: \ef form feed \ \ev vertical tab
553: .sp .5
554: .T&
555: aFCW l s s s.
556: \e' apostrophe (does not terminate a string)
557: \e" quotation mark (does not terminate a string)
558: \e\fIx\fP \fIx\fR, where \fIx\fR is any other character
559: .TE
560: The
561: .CW \%-!bs
562: option tells $f2c$ not to recognize these escapes.
563: Quoted strings may be delimited either by double quotes (\ \f(CW"\fR\ )
564: or by single quotes (\ \f(CW\(fm\fR\ ); if a string starts with
565: one kind of quote, the other kind may be embedded in the string
566: without being repeated or quoted by a backslash escape.
567: Where possible, translated strings are null-terminated.
568: .Bp
569: Hollerith strings are treated as character strings.
570: .Bp
571: In
572: .CW equivalence
573: statements, a multiply-dimensioned array may be given a single
574: subscript, in which case the missing subscripts are taken to be 1
575: (for backward compatibility with Fortran 66)
576: and a warning message is issued.
577: .Bp
578: In a formatted read of non-character variables, the I/O
579: library ($libI77$) allows a field to be terminated by a comma.
580: .Bp
581: Type
582: .CW real*4
583: is equivalent to
584: .CW real ,
585: .CW integer*4
586: to
587: .CW integer ,
588: .CW real*8
589: to
590: .CW "double precision" ,
591: .CW complex*8
592: to
593: .CW complex ,
594: and, as stated before,
595: .CW complex*16
596: to
597: .CW "double complex" .
598: .Bp
599: The type
600: .CW integer*2
601: designates short integers (translated to type
602: .CW shortint ,
603: which by default is
604: .CW "short int" ).
605: Such integers are expected to occupy half a ``unit'' of storage.
606: The command-line options
607: .CW \%-I2
608: and
609: .CW \%-i2
610: turn type
611: .CW integer
612: into
613: .CW integer*2 ;
614: see the $man$ page (appendix B) for more details.
615: .Bp
616: The intrinsic functions
617: .CW and ,
618: .CW or ,
619: .CW xor ,
620: and
621: .CW not
622: perform bitwise Boolean operations.
623: .Bp
624: $LibF77$ provides two functions for accessing command-line arguments:
625: .CW iargc(dummy)
626: returns the number of command-line arguments (and ignores its argument);
627: .CW getarg(k,c)
628: sets the character string
629: .CW c
630: to the $k$th command-line argument (or to blanks if $k$ is out of range).
631: .Bp
632: Variable,
633: .CW common ,
634: and procedure names may be arbitrarily long, but they
635: are truncated after the 50th character. These names may
636: contain underscores (in which case their translations will
637: have a pair of underscores appended).
638: .Bp
639: MAIN programs may have arguments, which are ignored.
640: .Bp
641: .CW Common
642: variables may be initialized by a
643: .CW data
644: statement in any module, not just in a
645: .CW "block data"
646: subprogram.
647: .Bp
648: The label may be omitted from a
649: .CW do
650: loop if the loop
651: is terminated by an
652: .CW enddo
653: statement.
654: .Bp
655: Unnamed Fortran 90
656: .CW "do while"
657: loops are allowed.
658: Such a loop begins with a statement of the form
659: .ce
660: \f(CWdo \fR[\fIlabel\^\fR] [\f(CW,\fR] \f(CWwhile(\fIlogical expression\f(CW)\fR
661: and ends either after the statement labelled by $label$ or after a matching
662: .CW enddo .
663: .Bp
664: $F2c$ recognizes the Fortran 90 synonyms
665: .CW < ,
666: .CW <= ,
667: .CW == ,
668: .CW >= ,
669: .CW > ,
670: and
671: .CW <>
672: for the Fortran comparison operators
673: .CW .LT. ,
674: .CW .LE. ,
675: .CW .EQ. ,
676: .CW .GE. ,
677: .CW .GT. ,
678: and
679: .CW .NE.
680: .Bp
681: \f(CWNamelist\fR
682: works as in Fortran 90
683: .[ [
684: Fort8x
685: .]],
686: with a minor restriction on
687: .CW namelist
688: input: subscripts must have the form
689: .ce
690: $subscript$ [ : $subscript$ [ : $stride$ ] ]
691: For example, the Fortran
692: .P1
693: integer m(8)
694: real x(10,10)
695: namelist /xx/ m, x
696: \&. . .
697: read(*,xx)
698: .P2
699: could read
700: .P1
701: &xx x(1,1) = 2, x(1:3,8:10:2) = 1,2,3,4,5,6 m(7:8) = 9,10/
702: .P2
703: but would elicit error messages on the inputs
704: .P1
705: &xx x(:3,8:10:2) = 1,2,3,4,5,6/
706: &xx x(1:3,8::2) = 1,2,3,4,5,6/
707: &xx m(7:) = 9,10/
708: .P2
709: (which inputs would be legal in Fortran 90).
710: For compatibility with the
711: .CW namelist
712: variants supplied by several vendors as Fortran 77 extensions,
713: $f2c$'s version of $libI77$ permits $dollar$ to be used instead of
714: .CW &
715: and
716: .CW /
717: in
718: .CW namelist
719: input. Thus the Fortran shown above could read
720: .P1
721: $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
722: .P2
723: .in 0
724: .Bp
725: Internal list-directed and namelist I/O are allowed.
726: .Bp
727: In an
728: .CW open
729: statement,
730: .CW name=
731: is treated as
732: .CW file= .
733: .SH
734: 4. INVOCATION EXAMPLES
735: .PP
736: To convert the Fortran files
737: .CW main.f
738: and
739: .CW subs.f ,
740: one might use the UNIX\u\(rg\d command:
741: .P1
742: f2c main.f subs.f
743: .P2
744: This results in translated files suffixed with
745: .CW .c ,
746: i.e., the resulting C files are
747: .CW main.c
748: and
749: .CW subs.c .
750: To translate all the Fortran files in the current
751: directory, compile the resulting C,
752: and create an executable program named
753: .CW myprog ,
754: one might use the following pair of UNIX commands:
755: .P1
756: f2c *.f
757: cc -o myprog *.c -lF77 -lI77 -lm
758: .P2
759: The above
760: .CW -lF77
761: and
762: .CW -lI77
763: options assume that the ``standard'' Fortran support libraries
764: $libF77$ and $libI77$
765: are appropriate for use with $f2c$. On some systems this is
766: not the case (as further discussed in \(sc6); if one had
767: installed a combination of the appropriate $libF77$ and $libI77$
768: in the appropriate place, then the above example might become
769: .P1
770: f2c *.f
771: cc -o myprog *.c -lf2c -lm
772: .P2
773: Sometimes it is desirable to use $f2c$'s
774: .CW -R
775: option, which tells $f2c$ not to force all floating-point operations
776: to be done in double precision. (One might argue that
777: .CW -R
778: should be the default, but we find the current arrangement
779: more convenient for testing $f2c$.) With
780: .CW -R
781: specified, the previous example becomes
782: .P1
783: f2c -R *.f
784: cc -o myprog *.c -lf2c -lm
785: .P2
786: Sometimes it is desirable to translate several Fortran source
787: files into a single C file. This is easily done by using $f2c$
788: as a filter:
789: .P1
790: cat *.f | f2c >mystuff.c
791: .P2
792: The
793: .CW -A
794: option lets $f2c$ use ANSI C constructs
795: .[ [
796: ANSIC
797: .]],
798: which yields more readable C when
799: .CW character
800: variables are initialized. With both
801: .CW -A
802: and
803: .CW -R
804: specified, the last example becomes
805: .P1
806: cat *.f | f2c -A -R >mystuff.c
807: .P2
808: For use with C++
809: .[ [
810: Stroustrup C++ Programming Language 1986
811: .]],
812: one would specify
813: .CW -C++
814: rather than
815: .CW -A ;
816: the last example would then become
817: .P1
818: cat *.f | f2c -C++ -R >mystuff.c
819: .P2
820: The
821: .CW -C++
822: option gives ANSI-style headers and old-style C formatting
823: of character strings and
824: .CW float
825: constants (since some C++ compilers reject the ANSI versions
826: of these constructs).
827: .LP
828: With ANSI C, one can use
829: .I prototypes ,
830: i.e., a special syntax describing the calling sequences
831: of procedures, to help catch errors in argument passing. To
832: make using prototypes convenient, the
833: .CW -P
834: option causes $f2c$ to create a \fIfile\f(CW.P\fR of prototypes
835: for the procedures defined in
836: each input \fIfile\f(CW.f\fR (or \fIfile\f(CW.F\fR, i.e., the
837: suffix
838: .CW .f '' ``
839: or
840: .CW .F '' ``
841: is replaced by
842: .CW .P ''). ``
843: One could concatenate all relevant prototype files into
844: a header file and arrange for the header to be
845: .CW #include d
846: with each C file compiled.
847: Since
848: .CW -P
849: implies
850: .CW -A
851: unless
852: .CW -C++
853: is specified, one could
854: convert all the Fortran files in the current directory
855: to ANSI C
856: and get corresponding prototype files by issuing the command
857: .P1
858: f2c -P *.f
859: .P2
860: Several command options may be combined if none but perhaps the
861: last takes an argument; thus to specify
862: .CW -R
863: and get C++ prototypes for all the
864: files in the current directory, one could say either
865: .P1
866: f2c -C++ -P -R *.f
867: .P2
868: or
869: .P1
870: f2c -C++PR *.f
871: .P2
872: or
873: .P1
874: f2c -RPC++ *.f
875: .P2
876: \(em options can come in any order.
877: .LP
878: For numeric variables initialized by character data, the
879: .CW -W
880: option specifies the (machine-dependent!)
881: number of characters per word and is further discussed
882: in \(sc6. This option takes a numeric argument, as in
883: .CW -W8 ;
884: such an option must be listed either separately or at the end
885: of a string of other options, as in
886: .P1
887: f2c -C++RPW8 *.f
888: .P2
889: .SH
890: 5. TRANSLATION DETAILS
891: .PP
892: $F2c$ is based on the ancient $f77$ Fortran compiler of
893: .[ [
894: Feldman Weinberger Portable Fortran
895: .]].
896: That compiler produced a C parse-tree,
897: which it converted into input for the second pass of the
898: portable C compiler (PCC)
899: .[ [
900: Johnson portable compiler
901: .]].
902: The compiler has been used for many years and is the
903: direct ancestor of many current Fortran compilers.
904: Thus, it provided us with a solid base of Fortran knowledge
905: and a nearly complete C representation.
906: The converter $f2c$ is a copy of the $f77$ Fortran compiler
907: which has been altered to print out a C representation
908: of the program being converted.
909: The program $f2c$ is a \fIhorror\fP, based on ancient code and
910: hacked unmercifully.
911: Users are only supposed to look at its C output,
912: not at its appalling inner workings.
913: .PP
914: Here are some examples that illustrate $f2c$'s translations.
915: For starters, it is helpful to see a short but complete
916: example: $f2c$ turns the
917: Fortran inner product routine
918: .P1
919: .so dot.f
920: .P2
921: into
922: .P1
923: .so dot.c
924: .P2
925: The translated C always starts with a ``translated by f2c'' comment
926: and a
927: .CW #include
928: of
929: .CW f2c.h .
930: $F2c$ forces the variable and procedure names to lower-case and
931: appends an underscore to the external name
932: .CW dot
933: (to avoid possible conflicts with library names).
934: The parameter adjustments
935: .CW --x '' ``
936: and
937: .CW --y '' ``
938: account for the fact that C arrays start at index 0.
939: Unused labels are retained in comments for orienteering purposes.
940: Within a function, Fortran references to the function name are turned into
941: references to the local variable
942: .CW ret_val ,
943: which holds the value to be returned. Unless the
944: .CW -R
945: option is specified, $f2c$ converts the return type of
946: .CW real
947: function values to
948: .CW doublereal .
949: Because using the C ``op='' operators
950: leads to greater efficiency on some machines, $f2c$ looks for opportunities
951: to use these operators, as in the line
952: .CW "ret_val += ..." '' ``
953: above.
954: .PP
955: $F2c$ generally dispenses with superfluous parentheses: ANSI C
956: specifies a clear order of evaluation for floating-point expressions,
957: and $f2c$ uses the ANSI C rules to decide when parentheses are required
958: to faithfully translate a parenthesized Fortran expression.
959: Non-ANSI compilers are free to violate parentheses; by default, $f2c$ does
960: not attempt to break an expression into several statements to
961: foil pernicious non-ANSI C compilers. Thus, for example, the Fortran
962: .P1
963: x = a*(b*c)
964: y = (a*b)*c
965: .P2
966: becomes
967: .P1
968: x = a * (b * c);
969: y = a * b * c;
970: .P2
971: The
972: .CW \%-kr
973: and
974: .CW \%-krd
975: options cause $f2c$ to use temporary variables to force correct
976: evaluation order with non-ANSI C compilers.
977: .ig
978: If, for instance,
979: .CW a ,
980: .CW b ,
981: and
982: .CW c ,
983: are
984: .CW real
985: variables, then under
986: .CW \%-kr
987: the above Fortran results in
988: .P1
989: /* System generated locals */
990: real r_1;
991: \&. . .
992: r_1 = b * c;
993: x = a * r_1;
994: r_1 = a * b;
995: y = r_1 * c;
996: .P2
997: ..
998: .PP
999: Fortran I/O is complicated; like $f77$, $f2c$ converts
1000: a Fortran I/O statement into calls on the Fortran I/O library $libI77$.
1001: For Fortran
1002: .CW read s
1003: and
1004: .CW write s,
1005: there is generally one call to start the statement, one to end it,
1006: and one for each item read or written. Given the Fortran declarations
1007: .P1
1008: integer count(10)
1009: real val(10)
1010: .P2
1011: the Fortran
1012: .P1
1013: read(*,*) count, val
1014: .P2
1015: is turned into some header lines:
1016: .P1
1017: static integer c_\|\^_3 = 3;
1018: static integer c_\|\^_10 = 10;
1019: static integer c_\|\^_4 = 4;
1020: \&. . .
1021: /* Builtin functions */
1022: integer s_rsle(), do_lio(), e_rsle();
1023: \&. . .
1024: /* Fortran I/O blocks */
1025: static cilist io_\|\^_1 = { 0, 5, 0, 0, 0 };
1026: .P2
1027: and the executable lines
1028: .P1
1029: s_rsle(&io_\|\^_1);
1030: do_lio(&c_\|\^_3, &c_\|\^_10, (char *)&count[0], (ftnlen)sizeof(integer));
1031: do_lio(&c_\|\^_4, &c_\|\^_10, (char *)&val[0], (ftnlen)sizeof(real));
1032: e_rsle();
1033: .P2
1034: Implicit Fortran do-loops, e.g.
1035: .P1
1036: read(*,*) (count(i), val(i), i = 1, 10)
1037: .P2
1038: get turned into explicit C loops:
1039: .P1
1040: s_rsle(&io_\|\^_4);
1041: for (i = 1; i <= 10; ++i) {
1042: do_lio(&c_\|\^_3, &c_\|\^_1, (char *)&count[i - 1], (ftnlen)sizeof(integer));
1043: do_lio(&c_\|\^_4, &c_\|\^_1, (char *)&val[i - 1], (ftnlen)sizeof(real));
1044: }
1045: e_rsle();
1046: .P2
1047: The Fortran
1048: .CW end=
1049: and
1050: .CW err=
1051: specifiers make the resulting C even less readable, as they require
1052: tests to be inserted. For example,
1053: .P1
1054: read(*,*,err=10) count, val
1055: 10 continue
1056: .P2
1057: becomes
1058: .P1
1059: i_\|\^_1 = s_rsle(&io_\|\^_1);
1060: if (i_\|\^_1 != 0) {
1061: goto L10;
1062: }
1063: i_\|\^_1 = do_lio(&c_\|\^_3, &c_\|\^_10, (char *)&count[0], (ftnlen)sizeof(integer));
1064: if (i_\|\^_1 != 0) {
1065: goto L10;
1066: }
1067: i_\|\^_1 = do_lio(&c_\|\^_4, &c_\|\^_10, (char *)&val[0], (ftnlen)sizeof(real));
1068: if (i_\|\^_1 != 0) {
1069: goto L10;
1070: }
1071: i_\|\^_1 = e_rsle();
1072: L10:
1073: ;
1074: .P2
1075: .PP
1076: A Fortran routine containing $n$ \f(CWentry\fR statements
1077: is turned into $n^+^2$ C functions, a big one containing
1078: the translation of everything but the \f(CWentry\fR statements,
1079: and $n^+^1$ little ones that invoke the big one. Each little
1080: one passes a different integer to the big one to tell
1081: it where to begin; the big one starts with a switch
1082: that branches to the code for the appropriate entry.
1083: For instance, the Fortran
1084: .P1
1085: function sine(x)
1086: data pi/3.14159265358979324/
1087: sine = sin(x)
1088: return
1089: entry cosneg(y)
1090: cosneg = cos(y+pi)
1091: return
1092: end
1093: .P2
1094: is turned into the big procedure
1095: .P1
1096: doublereal sine_0_(n_\|\^_, x, y)
1097: int n_\|\^_;
1098: real *x, *y;
1099: {
1100: /* Initialized data */
1101:
1102: static real pi = (float)3.14159265358979324;
1103:
1104: /* System generated locals */
1105: real ret_val;
1106:
1107: /* Builtin functions */
1108: double sin(), cos();
1109:
1110: switch(n_\|\^_) {
1111: case 1: goto L_cosneg;
1112: }
1113:
1114: ret_val = sin(*x);
1115: return ret_val;
1116:
1117: L_cosneg:
1118: ret_val = cos(*y + pi);
1119: return ret_val;
1120: } /* sine_ */
1121: .P2
1122: and the little invoking procedures
1123: .P1
1124: doublereal sine_(x)
1125: real *x;
1126: {
1127: return sine_0_(0, x, (real *)0);
1128: }
1129:
1130: doublereal cosneg_(y)
1131: real *y;
1132: {
1133: return sine_0_(1, (real *)0, y);
1134: }
1135: .P2
1136: .LP
1137: Fortran
1138: .CW common
1139: regions are turned into C
1140: .CW struct s.
1141: For example, the Fortran declarations
1142: .P1
1143: common /named/ c, d, r, i, l
1144: complex c(10)
1145: double precision d(10)
1146: real r(10)
1147: integer i(10)
1148: logical m(10)
1149:
1150: if (m(i(2))) d(3) = d(4)/d(5)
1151: .P2
1152: result in
1153: .P1
1154: struct {
1155: complex c[10];
1156: doublereal d[10];
1157: real r[10];
1158: integer i[10];
1159: logical m[10];
1160: } named_;
1161:
1162: #define named_1 named_
1163: \&. . .
1164:
1165: if (named_1.m[named_1.i[1] - 1]) {
1166: named_1.d[2] = named_1.d[3] / named_1.d[4];
1167: }
1168: .P2
1169: Under the
1170: .CW -p
1171: option, the above
1172: .CW if
1173: statement becomes more readable:
1174: .P1
1175: \&. . .
1176: #define c (named_1.c)
1177: #define d (named_1.d)
1178: #define r (named_1.r)
1179: #define i (named_1.i)
1180: #define m (named_1.m)
1181: \&. . .
1182: if (m[i[1] - 1]) {
1183: d[2] = d[3] / d[4];
1184: .P2
1185: If the above
1186: .CW common
1187: block were involved in a
1188: .CW "block data"
1189: subprogram, e.g.
1190: .P1
1191: block data
1192: common /named/ c, d, r, i, l, m
1193: complex c(10)
1194: double precision d(10)
1195: real r(10)
1196: integer i(10)
1197: logical m(10)
1198: data c(1)/(1.0,0e0)/, d(2)/2d0/, r(3)/3e0/, i(4)/4/,
1199: * m(5)/.false./
1200: end
1201: .P2
1202: then the
1203: .CW struct
1204: would begin
1205: .CW "struct named_1_ {" '', ``
1206: and $f2c$ would issue a more elaborate
1207: .CW #define :
1208: .P1
1209: #define named_1 (*(struct named_1_ *) &named_)
1210:
1211: /* Initialized data */
1212:
1213: struct {
1214: complex e_1;
1215: doublereal fill_2[10];
1216: doublereal e_3;
1217: doublereal fill_4[9];
1218: real e_5;
1219: integer fill_6[10];
1220: integer e_7;
1221: integer fill_8[11];
1222: logical e_9;
1223: integer fill_10[5];
1224: } named_ = { (float)1., (float)0., {0}, 2., {0}, (float)3., {0}, 4,
1225: {0}, FALSE_ };
1226: .P2
1227: In this example, $f2c$ relies on C's structure initialization rules
1228: to supply zeros to the
1229: \f(CWfill_\fIn\fR
1230: arrays that take up the space for which no
1231: .CW data
1232: values were given. (The logical constants
1233: .CW TRUE_
1234: and
1235: .CW FALSE_
1236: are defined in
1237: .CW f2c.h .)
1238: .PP
1239: Character manipulations of multiple-character strings
1240: generally result in function calls. For example,
1241: the Fortran
1242: .P1
1243: character*(*) function cat(a,b)
1244: character*(*) a, b
1245: cat = a // b
1246: end
1247: .P2
1248: yields
1249: .P1
1250: \&. . .
1251: static integer c_\|\^_2 = 2;
1252:
1253: /* Character */ int cat_(ret_val, ret_val_len, a, b, a_len, b_len)
1254: char *ret_val;
1255: ftnlen ret_val_len;
1256: char *a, *b;
1257: ftnlen a_len;
1258: ftnlen b_len;
1259: {
1260:
1261: /* System generated locals */
1262: address a_\|\^_1[2];
1263: integer i_\|\^_1[2];
1264:
1265: /* Builtin functions */
1266: /* Subroutine */ int s_cat();
1267:
1268: /* Writing concatenation */
1269: i_\|\^_1[0] = a_len, a_\|\^_1[0] = a;
1270: i_\|\^_1[1] = b_len, a_\|\^_1[1] = b;
1271: s_cat(ret_val, a_\|\^_1, i_\|\^_1, &c_\|\^_2, ret_val_len);
1272: } /* cat_ */
1273: .P2
1274: Note how the return-value length
1275: .CW ret_val_len ) (
1276: and parameter lengths
1277: .CW a_len "" (
1278: and
1279: .CW b_len )
1280: are used.
1281: Single character operations are generally done in-line.
1282: For example, the body of the Fortran
1283: .P1
1284: character*1 function lastnb(x,n)
1285: character*1 x(n)
1286: lastnb = ' '
1287: do 10 i = n, 1, -1
1288: if (x(i) .ne. ' ') then
1289: lastnb = x(i)
1290: return
1291: end if
1292: 10 continue
1293: end
1294: .P2
1295: becomes
1296: .P1
1297: *ret_val = ' ';
1298: for (i = *n; i >= 1; --i) {
1299: if (x[i] != ' ') {
1300: *ret_val = x[i];
1301: return ;
1302: }
1303: /* L10: */
1304: }
1305: .P2
1306: .PP
1307: $F2c$ uses
1308: .CW struct s
1309: and
1310: .CW #define s
1311: to translate
1312: .CW equivalence s.
1313: For a complicated example showing the interaction of
1314: .CW data
1315: with
1316: .CW common ,
1317: .CW equivalence ,
1318: and, for good measure, Hollerith notation,
1319: consider the Fortran
1320: .P1
1321: common /cmname/ c
1322: complex c(10)
1323: double precision d(10)
1324: real r(10)
1325: integer i(10)
1326: logical m(10)
1327: equivalence (c(1),d(1),r(1),i(1),m(1))
1328: data c(1)/(1.,0.)/
1329: data d(2)/2d0/, r(5)/3e0/, i(6)/4/, m(7)/.true./
1330: call sam(c,d(1),r(2),i(3),m(4),14hsome hollerith,14)
1331: end
1332: .P2
1333: The resulting C is
1334: .P1
1335: \&. . .
1336: struct cmname_1_ {
1337: complex c[10];
1338: };
1339:
1340: #define cmname_1 (*(struct cmname_1_ *) &cmname_)
1341:
1342: /* Initialized data */
1343:
1344: struct {
1345: complex e_1;
1346: doublereal e_2;
1347: real e_3;
1348: integer e_4;
1349: logical e_5;
1350: integer fill_6[13];
1351: } cmname_ = { (float)1., (float)0., 2., (float)3., 4, TRUE_ };
1352:
1353:
1354: /* Table of constant values */
1355:
1356: static integer c_\|\^_14 = 14;
1357:
1358: /* Main program */ MAIN_\|\^_()
1359: {
1360:
1361: /* Local variables */
1362:
1363: #define d ((doublereal *)&cmname_1)
1364: #define i ((integer *)&cmname_1)
1365: #define l ((logical *)&cmname_1)
1366: #define r ((real *)&cmname_1)
1367: extern /* Subroutine */ int sam_();
1368:
1369: sam_(cmname_1.c, d, &r[1], &i[2], &m[3], "some hollerith", &c_\|\^_14, 14L);
1370: } /* MAIN_\|\^_ */
1371:
1372: #undef r
1373: #undef l
1374: #undef i
1375: #undef d
1376: .P2
1377: As this example shows, $f2c$ turns a Fortran MAIN program into
1378: a C function named
1379: .CW MAIN_\|\^_ .
1380: Why not
1381: .CW main ?
1382: Well, $libF77$ contains a C main routine that arranges
1383: for files to be closed automatically when the Fortran program stops,
1384: arranges for an error message to be printed if a floating-point
1385: exception occurs, and arranges for the command-line argument
1386: accessing functions
1387: .CW iargc
1388: and
1389: .CW getarg
1390: to work properly. This C main routine invokes
1391: .CW MAIN_\|\^_ .
1392: .SH
1393: 6. PORTABILITY ISSUES
1394: .PP
1395: Three portability issues are relevant to $f2c$:
1396: the portability of the support libraries ($libF77$ and $libI77$)
1397: upon which the translated C programs rely,
1398: that of the converter $f2c$ itself,
1399: and that of the C it produces.
1400: .PP
1401: Regarding the first issue,
1402: some vendors (e.g., Sun and MIPS) have changed the calling conventions for
1403: their $libI77$ from the original conventions (those of
1404: .[ [
1405: Feldman Weinberger Portable Fortran
1406: .]]).
1407: Other vendors (e.g., MIPS) have changed the $libF77$ calling conventions
1408: (e.g., for
1409: .CW complex -valued
1410: functions).
1411: Thus, having libraries $libF77$ and $libI77$
1412: or otherwise having library routines with the names
1413: that $f2c$ expects is insufficient.
1414: When using a machine whose vendor provides but has gratuitously changed
1415: $libF77$ or $libI77$, one cannot safely mix objects compiled
1416: from the C produced by $f2c$ with objects compiled by the vendor's
1417: Fortran compiler, and one must use the correct libraries with
1418: programs translated by $f2c$. In such a case, the recommended procedure
1419: is to obtain source for the libraries (e.g. from
1420: .I netlib
1421: \(em see \(sc8), combine them into a single library, say
1422: .CW libf2c ,
1423: and install the library where it they can be conveniently accessed.
1424: On a UNIX system, for example, one might install
1425: .CW libf2c
1426: in
1427: .CW /usr/lib/libf2c.a ;
1428: then one could issue the command
1429: .P1
1430: cc *.c -lf2c -lm
1431: .P2
1432: to compile and link a program translated by $f2c$.
1433: .PP
1434: The converter itself is reasonably portable and has run successfully on Apollo,
1435: Cray, IBM, MIPS, SGI, Sun and DEC VAX equipment, all running some
1436: version of the UNIX operating system.
1437: However, we shall see that the C it produces may not be portable due to
1438: subtle storage management issues in Fortran 77.
1439: In any case, the C output of $f2c$ will run fine, at least if
1440: the \f(CW\%-W\fIn\fR option (see Appendix B) is used to set the
1441: number of characters per word correctly, and if C
1442: .CW double
1443: values may fall on an odd-word boundary.
1444: .PP
1445: The Fortran 77 standard says that \f(CWComplex\fP and \f(CWDouble Precision\fP
1446: objects occupy two ``units'' of space while other non-character data types
1447: occupy one ``unit.''
1448: It may be necessary to edit the header file
1449: .CW f2c.h
1450: to make these assumptions hold, if possible.
1451: On the Cray, for example,
1452: .CW float
1453: and
1454: .CW double
1455: are the same C types, and Fortran double precision, if
1456: available, would correspond to the C type
1457: .CW "long double" .
1458: In this case, changing the definition of
1459: .CW doublereal
1460: in
1461: .CW f2c.h
1462: from
1463: .P1
1464: typedef double doublereal;
1465: .P2
1466: to
1467: .P1
1468: typedef long double doublereal;
1469: .P2
1470: would be appropriate. For the Think C compiler on the
1471: Macintosh, on the other hand, this line would need to become
1472: .P1
1473: typedef short double doublereal;
1474: .P2
1475: .PP
1476: If your C compiler predefines symbols that could clash with
1477: translated Fortran variable names, then you should also
1478: add appropriate
1479: .CW #undef
1480: lines to
1481: .CW f2c.h .
1482: The current default
1483: .CW f2c.h
1484: provides the following
1485: .CW #undef
1486: lines for the following symbols:
1487: .TS
1488: center;
1489: lfCW lfCW lfCW lfCW lfCW lfCW.
1490: cray mc68020 sgi sun2 u370 u3b5
1491: gcos mips sparc sun3 u3b unix
1492: mc68010 pdp11 sun sun4 u3b2 vax
1493: .TE
1494: .PP
1495: As an extension to the Fortran 77 Standard, $f2c$
1496: allows noncharacter variables to be initialized with character
1497: data. This extension is inherently nonportable, as the number
1498: of characters storable per ``unit'' varies from machine to machine.
1499: Since 32 bit machines are the most plentiful, $f2c$
1500: assumes 4 characters per Fortran ``unit'', but this assumption
1501: can be overridden by the \f(CW\%-W\fIn\fR command-line option.
1502: For example,
1503: .CW \%-W8
1504: is appropriate for C that is to be run on Cray computers,
1505: since Crays store 8 characters per word.
1506: An example is helpful here: the Fortran
1507: .P1
1508: data i/'abcd'/
1509: j = i
1510: end
1511: .P2
1512: turns into
1513: .P1
1514: /* Initialized data */
1515:
1516: static struct {
1517: char e_1[4];
1518: } equiv_3 = { {'a', 'b', 'c', 'd'} };
1519:
1520: #define i (*(integer *)&equiv_3)
1521:
1522: static integer j;
1523:
1524: j = i;
1525: \&. . .
1526: #undef i
1527: .P2
1528: (Some use of
1529: .CW i ,
1530: e.g. ``\f(CWj = i\fR'', is necessary or $f2c$
1531: will see that
1532: .CW i
1533: is not used and will not initialize it.) If the target
1534: machine were a Cray and the string were
1535: .CW 'abcdefgh'
1536: or \f(CW"abcdefhg"\fR,
1537: then the Fortran would run fine, but the C produced by $f2c$ would only
1538: store \f(CW"abcd"\fR
1539: in i, $4$ being the default number of characters per word.
1540: The $f2c$ command-line option
1541: .CW \%-W8
1542: gives the correct initialization for a Cray.
1543: .PP
1544: The initialization above is clumsy, using $4$ separate characters.
1545: Using the option
1546: .CW -A ,
1547: for ANSI, produces
1548: .P1
1549: \&. . .
1550: } equiv_3 = { "abcd" };
1551: \&. . .
1552: .P2
1553: See Appendix B.
1554: .PP
1555: The above examples explain why the Fortran 77 standard excludes
1556: Hollerith data statements: the number of characters per word is
1557: not specified and hence such code is not portable even in Fortran.
1558: (Fortran that conservatively assumes only 1 or 2 characters per word is
1559: portable but messy. Note that Fortran 77 forbids the mixing, via
1560: .CW common ,
1561: .CW data ,
1562: or
1563: .CW equivalence ,
1564: of character and noncharacter types. Like many Fortran compilers,
1565: $f2c$ permits such nonportable mixing;
1566: initialization of numeric variables with Hollerith data is one
1567: example of this mixing.)
1568: .PP
1569: Some Fortran 66 programs pass Hollerith strings to
1570: .CW integer
1571: variables. $F2c$ treats a Hollerith string as a character string,
1572: but this may lead to bus errors on some systems if the character
1573: string winds up being improperly aligned. The
1574: .CW \%-h
1575: option instructs $f2c$ to try to give character variables
1576: and constants the same alignment as
1577: .CW integer s.
1578: Under
1579: .CW \%-h ,
1580: for example, the Fortran
1581: .P1
1582: call foo("a string")
1583: call goo(8ha string)
1584: .P2
1585: is translated to
1586: .P1
1587: static struct { integer fill; char val[8+1]; char fill2[3]; } c_b1_st = { 0,
1588: "a string" };
1589: #define c_b1 c_b1_st.val
1590: \&. . .
1591: foo_(c_b1, 8L);
1592: goo_(c_b1, 8L);
1593: \&. . .
1594: .P2
1595: .PP
1596: Some systems require that C values of type
1597: .CW double
1598: be aligned on a double-word boundary. Fortran
1599: .CW common
1600: and
1601: .CW equivalence
1602: statements may require some C
1603: .CW double
1604: values to be aligned on an odd-word boundary.
1605: On systems where double-word alignment is required,
1606: C compilers pad structures, if necessary, to arrange
1607: for the right alignment. Often such padding has no effect on
1608: the validity of $f2c$'s
1609: translation, but using
1610: .CW common
1611: or
1612: .CW equivalence ,
1613: it is easy to contrive examples in which
1614: the translated C works incorrectly.
1615: $F2c$ issues a warning message when double-word alignment may
1616: cause trouble, but, like $f77$,
1617: it makes no attempt to circumvent this trouble;
1618: the run-time costs of circumvention would be substantial.
1619: .PP
1620: Long decimal strings in \f(CWdata\fP statements are passed to C unaltered.
1621: However, expressions involving long decimal strings are rounded
1622: in a machine-dependent manner.
1623: On a VAX 8550, the Fortran
1624: .P1
1625: x=1.2**10
1626: end
1627: .P2
1628: yields the C
1629: .P1
1630: static real x;
1631:
1632: x = (float)6.1917364224000008;
1633: .P2
1634: .PP
1635: ANSI C compilers require that all but one instance of any entity with external scope,
1636: such as the \f(CWstruct\fPs into which $f2c$ translates \f(CWcommon\fP,
1637: be declared \f(CWextern\fP and that exactly one declaration should define the entity,
1638: i.e., should not be declared \f(CWextern\fP.
1639: Most older C compilers have no such restriction.
1640: To be compatible with ANSI usage, the $f2c$
1641: command-line option
1642: .CW -ec
1643: causes the \f(CWstruct\fP corresponding
1644: to an uninitialized \f(CWcommon\fP region to be declared \f(CWextern\fP
1645: and makes a
1646: .CW union
1647: of all successive declarations of that
1648: \f(CWcommon\fP region into a defining declaration placed in a file with the
1649: name \f(CWcname_com.c\fR, where
1650: .CW cname
1651: is the name of the \f(CWcommon\fP region.
1652: For example, the Fortran
1653: .P1
1654: common /cmname/ c
1655: complex c(10)
1656: c(1)=cmplx(1.,0.)
1657: call sam(c)
1658: end
1659: subroutine sam(c)
1660: complex c
1661: common /cmname/ca
1662: complex ca(10)
1663: ca(2) = cmplx(1e0,2e0)
1664: return
1665: end
1666: .P2
1667: when converted by \f(CWf2c -ec\fP produces
1668: .P1
1669: /* Common Block Declarations */
1670:
1671: union {
1672: struct {
1673: complex c[10];
1674: } _1;
1675: struct {
1676: complex ca[10];
1677: } _2;
1678: } cmname_;
1679:
1680: #define cmname_1 (cmname_._1)
1681: #define cmname_2 (cmname_._2)
1682:
1683: /* Main program */ MAIN_\|\^_()
1684: {
1685:
1686: extern /* Subroutine */ int sam_();
1687:
1688: cmname_1.c[0].r = (float)1., cmname_1.c[0].i = (float)0.;
1689: sam_(cmname_1.c);
1690: } /* MAIN_\|\^_ */
1691:
1692: /* Subroutine */ int sam_(c)
1693: complex *c;
1694: {
1695: cmname_2.ca[1].r = (float)1., cmname_2.ca[1].i = (float)2.;
1696: return 0;
1697: } /* sam_ */
1698: .P2
1699: as well as the file
1700: .CW cmname_com.c :
1701: .P1
1702: #include "f2c.h"
1703: union {
1704: struct {
1705: complex c[10];
1706: } _1;
1707: struct {
1708: complex ca[10];
1709: } _2;
1710: } cmname_;
1711: .P2
1712: The files
1713: .CW *_com.c
1714: may be compiled into a library
1715: against which one can load to satisfy overly fastidious ANSI C compilers.
1716: .PP
1717: The rules of Fortran 77 apparently permit a situation in which
1718: $f2c$ declares a function to be of type
1719: .CW int ,
1720: then defines it to be of another type, as illustrated by the
1721: first example in \(sc7. In that example, $f2c$ discovers too late that
1722: .CW f
1723: is not a subroutine. With some C compilers, this causes nothing
1724: worse than a warning message; with others, it causes the compilation
1725: to be aborted. With unforgiving C compilers, one can usually avoid
1726: trouble by splitting the Fortran source into one file per
1727: procedure, e.g., with the
1728: .I fsplit (1)
1729: command, and converting each procedure separately.
1730: Another solution is to use prototypes, as discussed in \(sc7.
1731: .PP
1732: With an ANSI C system that enforced consistent
1733: prototype declarations across separate compilations,
1734: it would be impossible to translate the main program correctly
1735: in the last example just by looking at the main program.
1736: Recent C++ compilers do enforce the consistency of
1737: prototype declarations across separate compilations,
1738: e.g., by encoding calling sequences into the translated names of functions,
1739: except for functions that are declared \f(CWextern "C"\fR and
1740: compiled separately.
1741: $F2c$ allows one to use this escape hatch: under
1742: .CW -C++ ,
1743: $f2c$ inserts
1744: .P1
1745: #ifdef _\|\^_cplusplus
1746: extern "C" {
1747: #endif
1748: .P2
1749: at the beginning of its C++ output and places
1750: .P1
1751: #ifdef _\|\^_cplusplus
1752: }
1753: #endif
1754: .P2
1755: at the end of its C++ output. The
1756: .CW "#ifdef _\|\^_cplusplus"
1757: lines are for the benefit of older C++ compilers that
1758: do not recognize \f(CWextern "C"\fR.
1759: .SH
1760: 7. PROTOTYPES
1761: .PP
1762: In ANSI C and C++, a
1763: .I prototype
1764: describes the calling sequence of a function.
1765: Prototypes can save debugging time by helping catch
1766: errors in calling sequences. The
1767: .CW \%-P
1768: option instructs $f2c$ to emit prototypes for all
1769: the functions defined in the C it produces; specifically,
1770: $f2c$ creates a \fIfile\f(CW.P\fR of prototypes
1771: for each input \fIfile\f(CW.f\fR or \fIfile\f(CW.F\fR.
1772: One can then arrange for relevant prototype files
1773: to be seen by the C compiler.
1774: For instance, if $f2c$'s
1775: header file
1776: .CW f2c.h
1777: is installed as
1778: .CW /usr/include/f2c.h ,
1779: one could issue the UNIX command
1780: .P1
1781: cat /usr/include/f2c.h *.P >f2c.h
1782: .P2
1783: to create a local copy of
1784: .CW f2c.h
1785: that has in it all the prototypes in
1786: .CW *.P .
1787: Since the C produced by $f2c$ always specifies
1788: .P1
1789: #include "f2c.h"
1790: .P2
1791: (rather than
1792: .CW "#include <f2c.h>" ),
1793: the C compiler will look first in the current directory for
1794: .CW f2c.h
1795: and thus will find the local copy that contains the prototypes.
1796: .PP
1797: $F2c$ can also read the prototype files it writes;
1798: one simply specifies them as arguments to $f2c$.
1799: In fact, $f2c$ reads all prototype files before any
1800: Fortran files; although multiple Fortran files are handled
1801: independently, any prototype file arguments apply to all of them.
1802: $F2c$ has more detailed knowledge of Fortran types than it conveys
1803: in the C it puts out; for example,
1804: .CW logical
1805: and
1806: .CW integer
1807: are different Fortran types, but are mapped to the same C type.
1808: Moreover,
1809: .CW character ,
1810: .CW complex ,
1811: and
1812: .CW "double complex"
1813: Fortran functions are all translated to
1814: .CW VOID
1815: C functions, and, unless the
1816: .CW \%-R
1817: option is specified, both
1818: .CW real
1819: and
1820: .CW "double precision"
1821: Fortran functions are translated to
1822: .CW doublereal
1823: C functions. Because $f2c$ denotes all these
1824: types differently in its prototype files, it
1825: can catch errors that are invisible to an ANSI C
1826: (or C++) compiler.
1827: .PP
1828: The following table shows the types
1829: that $f2c$ uses for procedure arguments:
1830: .TS
1831: center box;
1832: lfCW lfCW.
1833: C_fp complex
1834: D_fp doublereal
1835: E_fp real\fR under \f(CW-!R\fR (the default)\fP
1836: H_fp character
1837: I_fp integer\fR or \f(CWinteger*4
1838: J_fp integer*2
1839: K_fp shortlogical\fR (\f(CWlogical\fR under \f(CW-i2\fR or \f(CW-I2\fR)\fP
1840: L_fp logical
1841: R_fp real\fR under \f(CW-R
1842: S_fp subroutine\fR
1843: U_fp \fRuntyped \f(CWexternal
1844: Z_fp doublecomplex
1845: .TE
1846: These types are defined in
1847: .CW f2c.h ;
1848: they appear in prototypes and, under
1849: .CW \%-A
1850: or
1851: .CW \%-C++ ,
1852: in the C that $f2c$ writes. Prototypes also use special
1853: .CW void
1854: types to denote the return values of
1855: .CW complex ,
1856: .CW "double complex",
1857: and
1858: .CW character
1859: functions:
1860: .TS
1861: center box;
1862: lfCW lfCW.
1863: C_f complex
1864: H_f character
1865: Z_f double complex
1866: .TE
1867: .PP
1868: $F2c$ also writes special comments in prototype files giving
1869: the length of each
1870: .CW common
1871: block; when given prototype files as arguments, $f2c$ reads
1872: these special comments so it can issue a warning message if its
1873: Fortran input specifies a different length for some
1874: .CW common
1875: block.
1876: .PP
1877: Sometimes people write otherwise valid Fortran 77 that
1878: specifies different lengths for a
1879: .CW common
1880: block. If such Fortran is split into several files and converted
1881: to C, the loader could end up giving too little space to the
1882: .CW common
1883: block in question. One can avoid the confusion this could cause by
1884: running $f2c$ twice, first with
1885: .CW \%-P!c ,
1886: then with the resulting prototypes as additional arguments;
1887: the prototypes let $f2c$ determine (and convey to all of its
1888: output C files) the true length needed for
1889: each
1890: .CW common
1891: block.
1892: .PP
1893: One complication with prototypes comes from Fortran subprograms that
1894: declare a procedure to be
1895: .CW external
1896: but do not explicitly specify a type for it and only
1897: pass it as a parameter to another procedure. (If the
1898: subprogram also invokes the
1899: .CW external
1900: procedure, then $f2c$ can tell whether the procedure is
1901: a subroutine or a function; in the latter case, Fortran's
1902: implicit typing rules specify a type for the procedure.)
1903: If it can do no better, then $f2c$ assumes that untyped
1904: .CW external
1905: procedures are subroutines (and hence become
1906: .CW int -valued
1907: functions in C).
1908: This can cause the generated C to have
1909: multiple and inconsistent declarations for some procedures.
1910: For example,
1911: .P1
1912: external f
1913: call foo(f)
1914: end
1915: function f(x)
1916: double precision f, x
1917: f = x
1918: end
1919: .P2
1920: results in
1921: .CW MAIN_\|\^_
1922: declaring
1923: .P1
1924: extern /* Subroutine */ int f_();
1925: .P2
1926: and in the subsequent definition of
1927: .CW "doublereal f_(x)"
1928: in the same C file.
1929: Such inconsistencies are grounds for some C compilers
1930: to abort compilation.
1931: .PP
1932: $F2c$'s type inferences only apply sequentially to
1933: the procedures in a file, because $f2c$ writes C for each procedure
1934: before reading the next one. Thus, as just illustrated, if procedure
1935: .CW xyz
1936: comes after
1937: .CW abc
1938: in a Fortran input file, then $f2c$ cannot use information
1939: it gains when it sees the definition of
1940: .CW xyz
1941: to deduce types for
1942: .CW external
1943: procedures passed as arguments to
1944: .CW xyz
1945: by
1946: .CW abc .
1947: By using the
1948: .CW \%-P
1949: option and running $f2c$ several times, one can
1950: get around this deficiency. For instance, if file
1951: .CW zap.f
1952: contains the Fortran shown above, then the commands
1953: .P1
1954: f2c -P!c zap.f
1955: f2c -A zap.[fP]
1956: .P2
1957: result in a file
1958: .CW zap.c
1959: in which
1960: .CW MAIN_\|\^_
1961: correctly types
1962: .CW f_
1963: and
1964: .CW foo_
1965: as
1966: .P1
1967: extern doublereal f_();
1968: extern /* Subroutine */ int foo_(D_fp);
1969: .P2
1970: rather than
1971: .P1
1972: extern /* Subroutine */ int f_();
1973: extern /* Subroutine */ int foo_(U_fp);
1974: .P2
1975: The first invocation of $f2c$ results in a file
1976: .CW zap.P
1977: containing
1978: .P1
1979: extern doublereal f_(doublereal *x);
1980: /*:ref: foo_ 10 1 200 */
1981: .P2
1982: The second invocation of $f2c$ is able to type
1983: .CW f_
1984: and
1985: .CW foo_
1986: correctly because of the first line in
1987: .CW zap.P .
1988: .PP
1989: The second line in
1990: .CW zap.P
1991: is a special comment that records the incomplete type
1992: information that $f2c$ has about
1993: .CW foo_ .
1994: $F2c$ puts one such special comment in the prototype file for each
1995: Fortran procedure that is referenced but not defined in the Fortran file.
1996: When it reads prototype files, $f2c$ deciphers these comments and
1997: uses them to check the consistency of calling sequences.
1998: As it learns more about untyped external procedures, $f2c$ updates
1999: the information it has on them; the
2000: .CW :ref:
2001: comments it writes in a prototype file reflect $f2c$'s latest knowledge.
2002: .PP
2003: Ordinarily $f2c$ tries to infer the type of an untyped
2004: .CW external
2005: procedure from its use as arguments to procedures of
2006: known argument types. For example, if
2007: .CW f.f
2008: contains just
2009: .P1
2010: external f
2011: call foo(f)
2012: end
2013: .P2
2014: and if
2015: .CW foo.P
2016: contains
2017: .P1
2018: extern int foo_(D_fp);
2019: .P2
2020: then
2021: .P1
2022: f2c -A f.f foo.P
2023: .P2
2024: results in the declaration
2025: .P1
2026: extern doublereal f_();
2027: .P2
2028: Under unusual circumstances, such type inferences
2029: can lead to erroneous error messages or to incorrect typing.
2030: Here is an example:
2031: .P1
2032: subroutine zoo
2033: external f
2034: double precision f
2035: external g
2036: call zap(1,f)
2037: call zap(2,g)
2038: end
2039: subroutine goo
2040: call g
2041: end
2042: .P2
2043: $F2c$ first infers g to be a double precision function, then discovers
2044: that it must be a subroutine and issues a warning message about
2045: inconsistent declarations for
2046: .CW g .
2047: This example is legal Fortran 77;
2048: .CW zap
2049: could be defined, for instance, by
2050: .P1
2051: subroutine zap(n,f)
2052: external f
2053: if (n .le. 1) call zap1(f)
2054: if (n .ge. 2) call zap2(f)
2055: end
2056: .P2
2057: In such a case one can specify the
2058: .CW \%-!it
2059: option to instruct $f2c$ not to infer the types of otherwise
2060: untypable
2061: .CW external
2062: procedures from their appearance as arguments to known procedures.
2063: Here is another (somewhat far-fetched) example where
2064: .CW \%-!it
2065: is useful:
2066: .P1
2067: subroutine grok(f,g,h)
2068: external f, g, h
2069: logical g
2070: call foo(1,g)
2071: call foo(2,f)
2072: call zit(1,f)
2073: call zit(2,h)
2074: call zot(f(3))
2075: end
2076: .P2
2077: Without
2078: .CW \%-!it ,
2079: $f2c$ first infers
2080: .CW f_
2081: to be a
2082: .CW logical
2083: function, then discovers that Fortran's implicit typing
2084: rules require it to be a
2085: .CW real
2086: function.
2087: $F2c$ issues the
2088: warning message
2089: .CW "fixing wrong type inferred for f" '', ``
2090: which should serve as a warning that $f2c$ may have made some
2091: incorrect type inferences in the mean time.
2092: Indeed, $f2c$ ends up typing
2093: .CW h_
2094: as a
2095: .CW logical
2096: function; with
2097: .CW \%-!it
2098: specified, $f2c$ types
2099: .CW h_
2100: as an
2101: .CW external
2102: procedure unknown type, i.e., a
2103: .CW U_fp ,
2104: which to the C compiler appears to be a subroutine.
2105: (Even with
2106: .CW \%-!it
2107: specified, $f2c$ issues a warning message about inconsistent
2108: calling sequences for
2109: .CW foo .)
2110: .PP
2111: Because $f2c$ writes its latest knowledge of types into
2112: prototype files, it is easy to write a crude (Bourne) shell script
2113: that will glean the maximum possible type information:
2114: .P1
2115: >f.p
2116: until
2117: f2c -Pit f.p f.f
2118: cmp -s f.p f.P
2119: do
2120: mv f.P f.p
2121: done
2122: .P2
2123: In such scripts, use of the
2124: .CW \%-Ps
2125: option can save an iteration;
2126: .CW \%-Ps
2127: implies
2128: .CW \%-P
2129: and instructs $f2c$ to issue return code 4 if another
2130: iteration might change a declaration or prototype.
2131: Thus the following script is more efficient:
2132: .EQ
2133: delim off
2134: .EN
2135: .P1
2136: while :; do
2137: f2c -Ps f.[fP]
2138: case $? in 4) ;; *) break;; esac
2139: done
2140: .P2
2141: .EQ
2142: delim $$
2143: .EN
2144: The number of iterations depends on the call graph of the
2145: procedures in
2146: .CW f.f
2147: and on their order of appearance in
2148: .CW f.f .
2149: Sorting them into topological order (so that if
2150: .CW abc
2151: calls
2152: .CW def ,
2153: then
2154: .CW abc
2155: precedes
2156: .CW def )
2157: and reverse topological order and alternating between
2158: the two orders
2159: is probably a good heuristic.
2160: For example, we were able to completely type
2161: the \s-2PORT3\s+2 subroutine library
2162: in two passes by first processing it in reverse topological order,
2163: then in forward order. Unfortunately, one can devise situations
2164: where arbitrarily many iterations are required. This is slightly
2165: annoying, since with appropriate data structures (in an extensively
2166: reorganized version of $f2c$), one could do this calculation
2167: in linear time.
2168: .SH
2169: 8. EXPERIENCE WITH \f(BInetlib\fP
2170: .PP
2171: With the help of Eric Grosse, we arranged for the $netlib$
2172: .[ [
2173: Dongarra Grosse 1987
2174: .]]
2175: server
2176: .CW [email protected]
2177: to provide an experimental Fortran-to-C translation service
2178: by electronic mail.
2179: By executing the UNIX command
2180: .sp .5
2181: .ce
2182: \f(CW(echo execute f2c; cat foo.f) | mail [email protected]\fR
2183: .sp .5
2184: one submits the Fortran in
2185: .CW foo.f
2186: to $netlib$'s $f2c$ service;
2187: $netlib$ replies with the C and diagnostic messages produced by $f2c$ from
2188: .CW foo.f .
2189: (The
2190: .CW include
2191: mechanism described in \(sc3 makes no sense in this
2192: context, so it is disabled.) To start using this service,
2193: one would generally execute
2194: .sp .5
2195: .ce
2196: \f(CWecho 'send index from f2c' | mail [email protected]\fR
2197: .sp .5
2198: to check on the current status of the service.
2199: Before compiling the returned C, it is necessary to get a copy of
2200: .CW f2c.h :
2201: .sp .5
2202: .ce
2203: \f(CWecho 'send f2c.h from f2c' | mail [email protected]\fR
2204: .sp .5
2205: Most likely it would also be necessary to obtain source for the
2206: versions of $libF77$ and $libI77$ assumed by $f2c$:
2207: .sp .5
2208: .ce
2209: \f(CWecho 'send libf77 libi77 from f2c' | mail [email protected]\fR
2210: .PP
2211: For testing purposes, we retain the original Fortran submitted to
2212: $netlib$'s
2213: .CW "execute f2c" '' ``
2214: service. Observing $f2c$'s behavior on over 400,000 lines
2215: of submitted Fortran helped
2216: us find many obscure bugs and led us to make some of the
2217: extensions described in \(sc3. For example, a
2218: .CW "block data"
2219: subprogram initializing a variable that does not appear
2220: in any
2221: .CW common
2222: blocks now elicits a warning message (rather than causing
2223: $f2c$ to drop core). Another example is that $f2c$
2224: now gives the warning message
2225: .CW "Statement order error: declaration after DATA" '' ``
2226: and declines to produce any C
2227: if a declaration comes after a
2228: .CW data
2229: statement (for reasons discussed in \(sc9);
2230: $f2c$ formerly gave a more obscure error message
2231: and then produced invalid C.
2232: .PP
2233: Now that $netlib$ offers source for $f2c$ itself (as explained
2234: in the
2235: .CW index
2236: file mentioned above), we expect to curtail $netlib$'s
2237: .CW "execute f2c" '' ``
2238: service, perhaps limiting it to employees of AT&T and Bellcore;
2239: to learn the current state of affairs, request the current
2240: .CW index
2241: file.
2242: .SH
2243: 9. POSSIBLE EXTENSIONS
2244: .PP
2245: Currently $f2c$ simplifies constant expressions.
2246: It would be nice if constant expressions were simply
2247: passed through, and if Fortran
2248: .CW parameter s
2249: were translated as
2250: .CW #define s.
2251: Unfortunately, several things conspire to make this
2252: nearly impossible to do in full generality.
2253: Perhaps worst is that
2254: .CW parameter s
2255: may be assigned
2256: .CW complex
2257: or
2258: .CW doublecomplex
2259: expressions that might, for example, involve complex division
2260: and exponentiation to a large integer power.
2261: .CW Parameter s
2262: may appear in
2263: .CW data
2264: statements, which may initialize
2265: .CW common
2266: variables and so be moved near the beginning of the C output.
2267: Arranging to have the right
2268: .CW #define s
2269: in effect for the data initialization would, in this worst case,
2270: be a nightmare. Of course, one could arrange to
2271: handle ``easy'' cases with unsimplified constant expressions
2272: and
2273: .CW #define s
2274: for parameters.
2275: .PP
2276: Prototypes and the argument consistency checks currently ignore
2277: alternate return specifiers. Prototypes could be adorned with
2278: special comments indicating where alternate return specifiers
2279: are supposed to come, or at least telling the number of such
2280: specifiers, which is all that really matters.
2281: Since alternate return specifiers are rarely used
2282: (Fortran 90 calls them ``obsolescent''),
2283: we have so far refrained from this exercise.
2284: .PP
2285: Fortran 90 allows
2286: .CW data
2287: statements to appear anywhere. It would be nice if $f2c$ could
2288: do the same, but that would entail major rewriting of $f2c$.
2289: Presently
2290: .CW data
2291: values are written to a file as soon as they are seen; among
2292: the information in the file is the offset of each value.
2293: If an
2294: .CW equivalence
2295: statement could follow the
2296: .CW data
2297: statement, then the offsets would be invalidated.
2298: .PP
2299: It would be fairly straightforward to extend $f2c$'s I/O
2300: to encompass the new specifiers introduced by Fortran 90.
2301: Unfortunately, that would mean changing $libI77$ in ways
2302: that would make it incompatible with $f77$.
2303: .PP
2304: Of course, it would be nice to translate all of Fortran 90, but
2305: some of the Fortran 90 array manipulations would require new
2306: calling conventions and large enough revisions to $f2c$ that
2307: one might be better off starting from scratch.
2308: .PP
2309: With sufficient hacking,
2310: $f2c$ could be modified to recognize
2311: Fortran 90 control structures
2312: .CW case , (
2313: .CW cycle ,
2314: .CW exit ,
2315: and named loops), local arrays of
2316: dimensions that depend on arguments and common values,
2317: and such types as
2318: .CW logical*1 ,
2319: .CW logical*2 ,
2320: .CW integer*1
2321: or
2322: .CW byte .
2323: Since our main concern is with making portable Fortran 77
2324: libraries available to the C world, we have so far refrained
2325: from these further extensions. Perhaps commercial
2326: vendors will wish to provide some of these extensions.
2327: .SH
2328: 10. REFERENCES
2329: .LP
2330: .so tmac.sdisp1
2331: .[
2332: $LIST$
2333: .]
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.