Description of old FORTRAN idioms

I have mentioned it before, but my description of old FORTRAN idioms, like COMMON blocks and the use of ARRAY(1) instead of ARRAY(*) and the like, is nearing completion. You can find the result at https://github.com/arjenmarkus/old-programming-idioms/tree/main/doc, in the hope it is useful. And otherwise it was fun anyway :slight_smile: to write it up.

I will not be making any more changes until I am back from my holiday (beginning of august), but I do appreciate comments, additions, corrections and other suggestions for improvement.

11 Likes

@Arjen
Excellent work. For those of us who have had the unfortunate task of trying to teach younger people about the differences in what I like to call Jurassic FORTRAN and Modern Fortran, having a Rosetta stone is a big help. One omission I would like to point out though is SENSE SWITCH :laughing:. Just kidding but you would be surprised how often it appears in old 1960 era NASA reports that contain full code listings.

Edit.

Also, if you can find a copy in a library somewhere, I would recommend you look at Fredrick Stuart’s " Fortran Programming" book circa 1970 (my first Fortran book). It has some nice fold out tables on the capabilities of various compilers and hardware from that period and also does a good job of covering what was I guess the unofficial standard at the time sometimes referred to as Fortran IV.

@Arjen,

Great effort to capture this.

Please take a look at this “Rosetta Stone” at Fortran-lang.org on Python-Fortran:
Python Fortran Rosetta Stone — Fortran Programming Language

Perhaps you will consider working Fortran-lang folks to create a “Rosetta Stone”, as mentioned by @rwmsu upthread, and strive toward a link to it under Learn — Fortran Programming Language?

It can then be a Community-driven effort where other contributors can submit PRs for additional idioms and other idiosyncrasies to keep in mind when it comes to working with or reviewing legacy FORTRAN code?

1 Like

Likely more suitable for short intermittent use, there is a digitized copy on archive.org of Wiley’s edition by 1969 (requires their free libary card; pending availability, the book can borrowed in slots of an hour each). Else, entry worldcat.org.

It so happens that the library of the university next door owns a paper copy of that book. So, I have asked to get it on loan :slight_smile:

Thanks for all your reactions - I will pick it up again in a few weeks’ time.

@Arjen thanks for sharing the link to your old-programming-idioms github repo, as it describes legacy Fortran constructs illustrated with example codes. We will add it to the online references of Fortran best practices that we are using to create the GitHub Open Catalog.

The first thing that comes to my mind is which are the Top 5 old-style Fortran idioms that the GitHub Open Catalog is not covering properly today. Any first suggestions or thoughts?

None yet, but I will have a look at the catalogue :slight_smile:

@Arjen - I’m a little late to the party, but here is some feedback. I hope these are useful!


2.2 – C (or c) in col 1 is a comment. A numeric character indicates a statement label (and continued into cols 2-5). * was a common extension. D also somewhat common for ‘debug’ lines – as you mention later.

If col 6 had anything other than blank or zero, it is a continuation. Some interpretations of F66 allowed for cols 1-5 to have other characters as commentary when col 6 indicated continuation. But this was later clarified to be illegal.

2.7 – Nowadays best to have subroutines and functions contained within modules to allow interfaces to be explicit. If it is required to have them in separate files, use a module with the necessary INCLUDE statements to incorporate the procedures into the module at compile time.

3.2.1 – I’ve never found a use for DIM either.

3.3 – Better yet, function A should be in a module – which is USEd by the program. If this is not possible, an interface block should be written so the compiler can do proper argument checking.

3.6 – Use procedures in a module. The module can hold state variables between calls to the procedures. (Better yet, define a derived type that can be passed around. That way your example could have multiple accumulators.)

3.8 – You can also make the function return value an ALLOCATABLE. Again, you’ll want the function to be in a module so the interface is explicit to the caller.

5.1 – Hollerith constants, by Standard, were only allowed in DATA statements and as actual arguments in procedure calls. Though as an extension, they were often allowed in other contexts (e.g., right hand side of assignment statements.)

As few as three , or as many as 20 characters might be stored in a scalar variable or individual array element. (E.g., machines with 24-bit word integers vs CDC 60-bit word double precision on either end of the spectrum.) Oftentimes programmers used 1 character for portability and ease of usage. Since could be wasteful of memory, a good compromise was 4 characters per word. This often required non-Standard shifting and masking operations to extract or insert individual characters into the appropriate positions.

DATA statements are only supposed to initialize COMMON block items from within BLOCK DATA program units. To do so otherwise is non-Standard.

5.2 – Again, use modules.

5.3 – Generally the hidden argument should be a size_t these days, not an int. The hidden arguments almost always follow the formal arguments – following the convention of the original unix f77 compiler.

7.1 – Again, use modules instead of COMMON blocks (and BLOCK DATA). EQUIVALENCE is not always so easy to untangle.

7.2 – There were implementations of Fortran 66 which used stack allocation of local variables. (e.g., Burroughs and at least one or two others.) Since the Standard was silent on the issue, these were perfectly legal implementations.

7.3 – DANGER – when using the more modern form of initializing during declaration, the variable automatically gets the SAVE attribute. This may not be what the programmer wants! Unless it is a PARAMETER (or initializer in a derived type definition), it may be better to initialize via an assignment statement.

(Yes, you mention this later in 10.4.)

7.4 – Again, use modules.

8.1 – Originally, units 1-4 were often connected to magnetic tape drives. Unit 5 for card input. Unit 6 for line printer output. And unit 7 for card punch output. But these varied considerably.

8.2 – Prior to Fortran 77, there was no standard direct access (random) file I/O. IBM had DEFINE FILE statement, and the apostrophie syntax in READ/WRITE statements. Other compilers varied considerably. Often resorting to library calls.

9.1 – CRAY pointers were generally used for dynamic memory allocation in the days before ALLOCATABLE. Very very rare to see them used as procedure pointers.

9.2 - .EQV./.NEQV. - Added in Fortran 77. So older codes didn’t use them.

9.3 – Prior to Fortran 77, there were no Standard OPEN or CLOSE (or INQUIRE) statements. Units were assumed to be pre-connected to files/devices at program startup time. Of course this was universally extended in pre-77 compilers in a variety of ways…

1 Like

I often declare subroutines and functions after contains in a main program instead of a module, especially if they are unlikely to be wanted elsewhere and if the whole entire code is pretty short anyway. The interfaces are still explicit.

@wspector Thanks for this list :slight_smile: I will update the document with it.

@manuel.arenaz I had a quick look at the titles, but did not yet study the actual descriptions. That will come thoguh.

1 Like

@Arjen - Happy to help. To further elaborate on a few things:

On 7.2 - stack allocation really started taking off in the mid-1980s, when computers with parallel processing started to proliferate. For example on the CRAY-XMP, with up to 4 cpus, the compilers implemented a stack option (static was still the default) to enable safe parallel execution of code. A set of library calls allowed the initiation and control of parallel tasks.

It is funny how stack allocation in Fortran was so controversial back then, whereas today it seems so obvious. It would have saved me so much time trying to cram large codes into small memories back then - along with the dynamic arrays that ALGOL 60 had (and eventually/finally incorporated into Fortran 90.) Using overlaying facilities was such a PITA…

On 8.1/8.2/9.3, remember that Fortran pre-dates fancy newfangled stuff like disk drives and operating systems. So in the earliest days, the I/O units could literally be directly controlling hardware peripherals. When the program was run, it was often the only code running on the machine. No OS. If fact the original Fortran I/O statements included things like READ INPUT TAPE and WRITE OUTPUT TAPE, and the ability to read ‘sense switches’ on the front panel. As disk drives and disk operating systems came into use, the I/O operations became more virtualized. The lack of OPEN/CLOSE statements, especially for disk files, and also random access on disk files, was pretty acute. Lots of non-Standard ways of providing the services. F77 finally provided a Standard conforming version of them.

On 9.1 - Now that I think about it, using CRAY pointers for procedure pointers was a DEC extension to the CRAY extension. As for CRAY code, one would use the heap manager subroutine calls, such as HPALLOC and HPDEALLOC, to obtain and free memory. These were equivalent to the malloc and free calls in C.

DEC fortran compilers on their mainframes (the 36-bit DECSYSTEM), pdp-11 minicomputers, and later on their VAX minicomputers had open/close statements before f77. I don’t know when these were introduced, and it could well have been after the f77 standardization process had begun. I remember that they had some extra keywords compared to the later f77 compilers. One example was a DIR= keyword that specified the directory separately from the FILE= keyword for the file name itself. At least the VAX fortran compiler also had a CARRIAGECONTROL= keyword to account for the multiple conventions that text files could be stored on the VAX file system.

An old Fortran idiom that gfortran still allows as an extension is the FLUSH intrinsic subroutine. Did it antedate the F2003 standard’s FLUSH statement? The subroutine has one optional argument, the unit number. The statement requires the unit number and allows three more specifiers: IOSTAT=, IOMSG= and ERR= .

Yes. If I remember correctly I first encountered the FLUSH routine on 1990s CRAY systems but it might have been on either DEC or IBM systems from that era

An idiom that’s not as old as I had thought is output of a row of asterisks when a numerical value could not be written in the specified format. It first appeared in F77 13.5.9 (5); F66 7.2.3.6 (5) had forbidden the attempt. McCracken (1961) p48 did not, but pointed out that the output would be wrong, e.g. getting 23.45678 from writing -123.45678 with F8.5 format.

DEC had open/close long before the F77 standard. So did Data General and some others. On some systems there were library call equivalents. For example on CDC, one could make Cyber Record Manager (often referred to as “Record Mangler”) calls. On others you had to do it at the assembler level.

Doing random access was another level of incompatibility. Then there were multiple variations of encode/decode…

All this got straightened out with F77.

It was on the Cray systems. Really important with multi-tasking.

Arjen,
Thanks much for your FORTRAN idioms. I can relate to these as I am a bit past 7 decades of age (7 sounds better than 70, eh?). I grew up with the WATFOR (Waterloo Fortran) with the Wat 4 or perhaps Wat 5 compiler (my acronym spelling might be wrong), which I used at the University of Akron circa 1972 - 1976. It is sweet to hear people speak of those old conventions we followed so religiously back in the day when I ran those punched Hollerith cards to generate FORTRAN code. Yep, everything was capitalized, I don’t think lowercase was valid for compilation. For me, branching was a spaghetti of GOTO 3400 and the comparison symbols: .EQ. and so forth, “==” was unknown. I might be a good source for your program-idioms as they are clear as a bell in my memory.

Just a word on the Wang computers which I used when co-op at B&W nuclear, those dixie lights with layered digits were mesmerizing. It was circa 1977. We were designing the Trident series subs using, I think 8-digit ticker tape punched instructions with cylindrical printing heads and we had IBM typewriters with spherical print heads which you had to interchange to change fonts.

I want to add my condolences for Absoft which I had used in the past decade to write a continuous beam design program I call TomBeam that is out on SourceForge for free download. I used Absoft in conjunction with a GUI called “Winteracter” which as far as I know is still supported to write TomBeam.

I’ll talk with anyone who wants to chew the fat on the so-called good-old-days of pixie light digital display and the card readers that sounded like a vacuum cleaner starting up until the cards started rifling through like the sound of the playing cards that we used to attach to our bicycle spokes to make engine sounds. None of us had heard of block-if’s and what in the world is Structured Programming?

1 Like

What do you mean? There was structured programming. This picture proves it …
(Definitely looks like a structure to me) :grinning:

4 Likes