We ❤️ Open Source
A community education resource
A Linux and Unix experiment – Part 1: Writing a FORTRAN 66 program
Here's what writing a FORTRAN 66 program was like using Unix from fifty years ago.
This article is a part of a series called “A throwback experiment with Linux and Unix.” Read the Introduction and set-up to the series.
For my “throwback” experiment, I wanted to demonstrate that you can still do real work on Linux, using just a terminal and the command line, just like the original Unix.
As a proof of concept, I worked for a week in Linux like it was Unix from fifty years ago. During this experiment, I assigned myself three tasks. The first task was to write a FORTRAN 66 program. This is my experience.
For reference, I’ve included a list of all user commands in Unix 4th edition.
Unix 4th edition commands reference guide
Write a FORTRAN 66 program
I learned FORTRAN 77 when I was an undergraduate physics student, so I associate “FORTRAN” with scientific computing. I wrote a FORTRAN program to iterate the physics equation of motion, of dropping an object from a certain height. Enter the height and the time step increment, and the program prints out the height of that object at each increment.
But my experiment was working in Linux like it was Unix 4th Edition, which means the then-current version of FORTRAN was FORTRAN 66. In that version of the language, FORTRAN 66 had added several programming constructs that were quite nice, such as DO
loops and GOTO
statements.
And while FORTRAN supported an IF
statement, the language wouldn’t support IF
.. ELSEIF
.. ELSE
.. ENDIF
blocks until FORTRAN 77. To do the equivalent in FORTRAN 66, I had to write my IF
blocks the old fashioned way.
If you don’t know FORTRAN, let me show you what this means using a kind of pseudocode. Let’s test if a number is greater than zero. Using a more modern programming language, you might write the test this way, in pseudocode:
print 'enter starting height:'
do {
read height;
} until (height > 0);
But old-style FORTRAN doesn’t have a loop like that; instead, you had to do it with IF
tests and GOTO
statements. With IF
, FORTRAN could jump to lines that were labeled with a number. So to write a test to make sure a number is greater than zero, you might write pseudocode like this:
10 print 'enter starting height:'
read height
if (height less than or equal to zero) then {
print 'must be greater than zero'
goto 10
}
But that uses an if-else
style block. To write this without using an if-else
block, you’d have to test for the opposite and jump around a bit, like this pseudocode:
10 print 'enter starting height:'
read height
if (height greater than zero) then goto 20
print 'must be greater than zero'
goto 10
20 .. rest of the program ..
And that’s why you may notice this FORTRAN 66 program uses IF
and GOTO
every time it needs to read a value from the user.
Because I was pretending to use Unix 4th Edition, I wrote the program using ed
, not a visual editor like Emacs or Vim or Visual Studio Code. To edit a file using ed
, you start by launching the editor with the name of the file to work on:
$ ed drop.f
With ed
, you don’t get a prompt, so it may appear that that program isn’t doing anything – but really, it’s just waiting for you to type a command. Like Vim, the ed
editor operates in one of two modes: command mode or edit mode. You start in command mode; to start entering lines, you need to give the i
(insert) command. You can then enter new lines of text; enter .
on a line by itself to stop:
i
C A PROGRAM TO SIMULATE DROPPING AN OBJECT
PROGRAM DROP
DOUBLEPRECISION Y0,Y,T
10 WRITE(*,*)'ENTER STARTING Y:'
READ(*,*)Y
IF (Y.GT.0.0) GOTO 20
WRITE(*,*)'** Y0 MUST BE GREATER THAN ZERO'
GOTO 10
.
As I was typing that, I realized that I meant to use Y0
instead of Y
on the READ
and IF
lines. I fixed it for the WRITE
line, but I needed to go back and fix it on the previous lines before I forgot about it. To search backwards, use the ?
command with the text to search for. In my case, let’s search backwards for the READ
line:
?READ
READ(*,*)Y
I just need to change Y
to Y0
, so I can use the s
(swap text) command for that. The search set the active line to the READ
line, so I can use s
to swap text on the active line like this:
s/Y/Y0/
To print the new line, use the p
(print) command:
p
READ(*,*)Y0
That worked! Now we just need to do the same for the IF line, on the next line. This time, we can search forwards with the / command:
/IF
IF (Y.GT.0.0) GOTO 20
s/Y/Y0/
p
IF (Y0.GT.0.0) GOTO 20
Having made those fixes, I’m ready to write the rest of the program. To jump to a specific line in the file, type its number. For example, to jump to to first line of the file and have ed
print it, you would type 1
:
1
C A PROGRAM TO SIMULATE DROPPING AN OBJECT
To skip to the bottom of the file, type $
:
$
GOTO 10
With ed
, you have to keep a mental “map” of the file you’re working on, tracking the approximate location in a file where a procedure might be defined. With some practice, this becomes natural. But because you can only work one line at a time, I find it’s much easier to sketch out an outline of the program on a piece of paper, and use that to guide me through writing the program.
From there, I was able to use ed
to finish editing the program. To save and exit the ed
editor, use the w
command to write the file to disk, then q
to quit.
C A PROGRAM TO SIMULATE DROPPING AN OBJECT
PROGRAM DROP
DOUBLEPRECISION Y0,Y,T
DOUBLEPRECISION INC
T=0.0
10 WRITE(*,*)'ENTER STARTING Y:'
READ(*,*)Y0
IF (Y0.GT.0.0) GOTO 20
WRITE(*,*)'** Y0 MUST BE GREATER THAN ZERO'
GOTO 10
20 WRITE(*,*)'ENTER TIME INCREMENT:'
READ(*,*)INC
IF (INC.GT.0.0001) GOTO 30
WRITE(*,*)'** TIME INCREMENT IS TOO SMALL'
GOTO 20
30 Y=Y0 - (0.5 * 9.8 * T*T)
WRITE(*,*)T,Y
T=T+INC
IF (Y.GT.0.0) GOTO 30
WRITE(*,*)'DONE'
END
Now I’m ready to compile my program with the fc
FORTRAN compiler! Note that fc
didn’t use -o
to set the output file name; it always saved to a.out
. To get the final program as drop
, you need to rename it:
$ fc drop.f
$ mv a.out drop
And now we know that dropping an object from 1 meter will take less than half a second to reach the ground:
$ ./drop
ENTER STARTING Y:
0
** Y0 MUST BE GREATER THAN ZERO
ENTER STARTING Y:
1
ENTER TIME INCREMENT:
0
** TIME INCREMENT IS TOO SMALL
ENTER TIME INCREMENT:
.1
0.0000000000000000 1.0000000000000000
0.10000000000000001 0.95099999904632571
0.20000000000000001 0.80399999618530271
0.30000000000000004 0.55899999141693102
0.40000000000000002 0.21599998474121085
0.50000000000000000 -0.22500002384185791
DONE
More from We Love Open Source
- Read: A throwback experiment with Linux and Unix: Introduction and set-up
- Read part two of this tutorial series: Prepare a document using
nroff
- Read part three of this tutorial series: Writing several C programs
- Read: Technology history: Where Unix came from
The opinions expressed on this website are those of each author, not of the author's employer or All Things Open/We Love Open Source.