Fortran 77 for C/C++/Java/C# programmers

Content:

  1. Introduction
  2. History
  3. Compilers
  4. Source format
  5. Data types and constants
  6. Operators and functions
  7. Conditional statements
  8. Loops
  9. Subroutines and functions
  10. IO
  11. Arrays
  12. Other features
  13. The ugly part

Introduction:

Fortran is not widely used today - mostly in the scientific computing / super computing / number crunching field.

But Fortran was my first programming language, so I always had a special connection to it.

History:

Fortran is one of the oldest high level languages. First Fortran compiler was completed in 1957.

Back then the name was usually all uppercase aka FORTRAN, but I will use the modern captitalization Fortran.

The language is standardized via ANSI/ISO:

This article will describe Fortran 77, which was the last Fortran version to be part of mainstream programming. Newer versions has been overshadowed by newer programming languages.

Compilers:

The traditional platforms for Fortran were:

Examples are tested with GCC g77 on Windows and HP Fortran on OpenVMS Alpha.

If you need a Fortran compiler then get GCC. Older versions include g77 and newer versions include gfortran.

Source format:

Fortran 77 source code is not free format like newer programming languages but fixed format where position matters (newer Fortran versions support free format).

Structure is:

A program starts with a PROGRAM statement and ends with an END statement.

helloworld.for:

      PROGRAM HELLOWORLD
      WRITE(*,*) 'Hello world !'
      END

Note that the statements start in position 7.

WRITE(*,*) will be explained later, but the meaning is rather obvious.

Traditionally Fortran code is written in all upper case, but it is not required. Fortran is not case sensitive.

Comments are indicated by a C in position 1.

Any character not space can be used in position 6 to indicate that the line is a continutation, but traditionally a + is used.

Modified helloworld.for:

C
C This is a hello world example in Fortran
C
      PROGRAM HELLOWORLD
      WRITE(*,*)
     +     'Hello world !'
      END

Note that spaces are insiginificant in Fortran.

      MYVAR=1

and:

      M Y V A R = 1

has the exact same meaning.

Obviously you would never write code like the last version.

Data types and constants:

Fortran 77 standard defines the following data types:

There is a de facto industry standard that also numerical types can be suffixed with *length (where length is number of bytes).

So usually the following types are available:

Fortran type Meaning (common platforms) C/C++ equivalent (typical compiler) Java equivalent C# equivalent
INTEGER*2 16 bit integer short int short short
INTEGER*4 32 bit integer int or long int int int
INTEGER*8 64 bit integer long long int long long
LOGICAL*4 true or false bool boolean bool
CHARACTER*length Fixed length string with specified length char[length+1] in C, string in C++ (variable length) String (variable length) string (variable length)
REAL*4 32 bit floating point float float float
REAL*8 64 bit floating point double double double
REAL*16 128 bit floating point (none) (none) (none)
COMPLEX*8 64 bit complex = 32 bit real part + 32 bit imaginary part (none) (none) (none)
COMPLEX*16 128 bit complex = 64 bit real part + 64 bit imaginary part (none) (none) (none)

It seems obvious from the above that Fortran is a great language for scientific calcultaions due to the rich REAL and COMPLEX data types and a poor language for text processing due to only having fixed length strings.

Example with declarations and some assignments:

      PROGRAM VARASGN
      INTEGER*2 V1
      INTEGER*4 V2
      INTEGER*8 V3
      LOGICAL*4 V4
      CHARACTER*16 V5
      REAL*4 V6
      REAL*8 V7
      REAL*16 V8
      COMPLEX*8 V9
      COMPLEX*16 V10
      V1=123
      V2=123
      V3=123
      V4=.TRUE.
      V5='This is a test'
      V6=123.456
      V7=123.456D0
      V8=123.456Q0
      V9=(1.2,3.4)
      V10=(1.2D0,3.4D0)
      WRITE(*,*) V1
      WRITE(*,*) V2
      WRITE(*,*) V3
      WRITE(*,*) V4
      WRITE(*,*) V5
      WRITE(*,*) V6
      WRITE(*,*) V7
      WRITE(*,*) V8
      WRITE(*,*) V9
      WRITE(*,*) V10
      END

Variables do not need to be declared in Fortran. If they are not declared they get a type based on the variable name:

This feature can be disabled with:

      IMPLICIT NONE

It is recommended to use that option.

Multiple variables of the same type can be declared in a single declaration.

Constants can be defined via PARAMETER declaration.

Example:

      PROGRAM VARASGN
      IMPLICIT NONE
      INTEGER*4 A,B,C,ZERO
      PARAMETER(ZERO=0)
      A=1
      B=2
      C=3
      WRITE(*,*) A,B,C,ZERO
      END

Operators and functions:

Fortran has all the basic operators and functions.

Fortran Meaning C/C++ equivalent Java equivalent C# equivalent
+ arithmetic plus + + +
- arithmetic minus - - -
* arithmetic multiply * * *
/ arithmetic integer division / / /
MOD function arithmetic modulus % % %
** power pow function Math.pow method Math.Pow method
ABS function absolute value abs/fabs function Math.abs method Math.Abs method
AINT function round down to integer floor function Math.floor method Math.Floor method
NINT function round to nearest integer round function Math.round method Math.Round method
MIN function smallest value min function Math.min method Math.Min method
MAX function greatest value max function Math.max method Math.Max method
.EQ. equal == == ==
.NE. not equal != != !=
.LT. less than < < <
.LE. less than or equal <= <= <=
.GT. greater than > > >
.GE. greater than or equal >= >= >=
.AND. logical and (not short circuit) & (often short circuit logical and && is used) & (often short circuit logical and && is used) & (often short circuit logical and && is used)
.OR. logical or (not short ciruit) | (often short circuit logical or || is used) | (often short circuit logical or || is used) | (often short circuit logical or || is used)
.NOT. logical negation ! ! !

Fortran also has a bunch of mathematical functions:

Note that these functions exist for all precisions of floating point.

Fortran also have a few functions for strings:

Note that character indexes in strings are 1 based not 0 based.

Example:

      PROGRAM OPS
      INTEGER*4 N,M
      REAL*8 X
      CHARACTER*15 S
      N=7
      M=5
      WRITE(*,*) N+M,N-M,N*M,N/M,MOD(N,M)
      WRITE(*,*) N.EQ.M,N.NE.M,N.LT.M,N.GT.M
      X=2.5
      WRITE(*,*) SQRT(X**2),LOG(EXP(X)),LOG10(10**X) 
      WRITE(*,*) ACOS(0.0),ASIN(1.0)
      WRITE(*,*) COSD(90.0),SIND(90.0)
      S='This is a test'
      WRITE(*,*) LEN(S),INDEX(S,'is'),S(6:7)
      END

Again we see rich support for scientific calculations and poor support for text processing.

Conditional statements:

Fortran has 5 different flavors of IF statement.

Three of them are very simple and similar to other languauges:

      IF(condition) singlestatement
      IF(condition) THEN
         multistatements
      ENDIF
      IF(condition) THEN
         multistatements
      ELSE
         multistatements
      ENDIF

Then there is an IF/GOTO construct to jump to 3 different labels depending on whether a value is negative, zero or positive:

      IF(someexpr) labelfornegative,labelforzero,labelforpositive

And then there is a IF/GOTO to jump to different labels based on value that is used as index into the labels:

      GOTO(label1,label2,label3,label4) someexpr

The latter construct is really a switch statement that can only be used for sequential integer values.

Example:

      PROGRAM COND
      INTEGER*4 V
      V=2
C single statement IF
      IF(V.GT.1) WRITE(*,*) 'V > 1'
C block statement IF ELSE
      IF(V.GT.1) THEN
        WRITE(*,*) 'V > 1'
      ELSE
        WRITE(*,*) 'V <= 1'
      ENDIF
C arithmentic IF
      IF(V) 100,200,300
100   WRITE(*,*) 'V < 0'
      GOTO 400
200   WRITE(*,*) 'V = 0'
      GOTO 400
300   WRITE(*,*) 'V > 0'
400   CONTINUE
C  computed GOTO
      GOTO (500,600,700,800) V
500   WRITE(*,*) 'V = 1'
      GOTO 900
600   WRITE(*,*) 'V = 2'
      GOTO 900
700   WRITE(*,*) 'V = 3'
      GOTO 900
800   WRITE(*,*) 'V = 4'
      GOTO 900
900   CONTINUE
      END

The example also uses simple GOTO statements, but their meaning should be obvious.

It is possible to write horrible spagetti code in Fortran. But it is also possible to write nice structured code.

Loops:

Standard Fortran only got one type of loop the DO loop, which is equivalent to for loop in many other languages:

      DO label counter=startval,endval
         multistatements
label CONTINUE
      DO label counter=startval,endval,step
         multistatements
label CONTINUE

But most Fortran 77 dialects also have a DO WHILE loop:

      DO WHILE expression
        multistatement
      ENDDO

Example:

      PROGRAM LOOPS
      INTEGER*4 I
      DO 100 I=1,5
        WRITE(*,*) I
100   CONTINUE
      DO 200 I=1,5,2
        WRITE(*,*) I
200   CONTINUE
      I=1
      DO WHILE(I.LE.5)
        WRITE(*,*) I
        I=I+2
      ENDDO
      END

Note that if these loops are not sufficient then it is always possible to use IF and GOTO. These are actually used in Fortran.

Subroutines and functions:

In Fortran one distinguishes between subroutines that does not return a value and functions that return a value. Subroutines are known as void functions/methods in C/C++/Java/C#.

Example showing syntax:

      PROGRAM SUB
      INTEGER*4 I
      DO 100 I=1,10
        CALL TESTFAC(I)
100   CONTINUE
      END
C
      SUBROUTINE TESTFAC(N)
      INTEGER*4 N
      INTEGER*4 FAC
      EXTERNAL FAC
      WRITE(*,*) N,FAC(N)
      RETURN
      END
C
      INTEGER*4 FUNCTION FAC(N)
      INTEGER*4 N
      INTEGER*4 RES,I
      RES=1
      DO 100 I=1,N
        RES=RES*I
100   CONTINUE
      FAC=RES
      RETURN
      END

The construct:

      EXTERNAL FAC

tell Fortran that FAC is a user specified function not a builtin function.

Note that standard Fortran 77 does not support recursion. Many Fortran 77 compilers do support recursion though. And newer Fortran standards require support for recursion.

Some Fortran 77 compilers that do not support recursion store local variables on heap instead of stack. This mean that they can maintain their values between calls. This is not guaranteed to work with all compilers.

To make it work with all compilers use:

      typeofvariable variablename
      SAVE variablename

Fortran does not have real global variables as known from C/C++ or equivalent in Java/C# public static fields.

Instead Fortran has an advanced export/import feature called common blocks to share data between subroutines/functions.

Syntax:

      COMMON /commonname/var1,var2,var3

Example:

      PROGRAM COMM
      INTEGER*4 I,J,K
      COMMON /B1/I
      COMMON /B2/J
      COMMON /B3/K
      I=123
      J=456
      K=65537
      CALL SUB1
      CALL SUB2
      CALL SUB3
      END
C
      SUBROUTINE SUB1
      INTEGER*4 I
      COMMON /B1/I
      WRITE(*,*) I
      RETURN
      END
C
      SUBROUTINE SUB2
      INTEGER*4 J
      COMMON /B2/J
      WRITE(*,*) J
      RETURN
      END
C
      SUBROUTINE SUB3
      INTEGER*2 K1,K2
      COMMON /B3/K1,K2
      WRITE(*,*) K1,K2
      RETURN
      END

Part 3 illustrates an ugly little detail. Common blocks are just pieces of memory and they are not type safe.

To make it easier to manage then most Fortran 77 dialects support an INCLUDE statement.

If comm2.inc contains:

      INTEGER*4 I,J
      COMMON /B/I,J

then we can use:

      PROGRAM COMM
      INCLUDE 'comm2.inc'
      I=123
      J=456
      CALL SUB1
      CALL SUB2
      END
C
      SUBROUTINE SUB1
      INCLUDE 'comm2.inc'
      WRITE(*,*) I
      RETURN
      END
C
      SUBROUTINE SUB2
      INCLUDE 'comm2.inc'
      WRITE(*,*) J
      RETURN
      END

IO:

Fortran IO is a bit special but is actually rather powerful.

The two primary IO statements are READ and WRITE.

They exist in many flavors including:

      READ(*,*) var1,var2,...
      READ(n,*) var1,var2,...
      READ(*,formatlabel) var1,var2,...
      READ(n,formatlabel) var1,var2,...
      READ(UNIT=n,FMT=formatlabel) var1,var2,...
      WRITE(*,*) var1,var2,...
      WRITE(n,*) var1,var2,...
      WRITE(*,formatlabel) var1,var2,...
      WRITE(n,formatlabel) var1,var2,...
      WRITE(UNIT=n,FMT=formatlabel) var1,var2,...

UNIT is a file number. * means console. 5 means console input. 6 means console output. Per old tradition.

A format label consist of:

label FORMAT(formatinfo)

where format info consist of a number of comma separated format specifications of the form:

nX
n spaces
Iw
integer with width w
Fw.d
floating point with width w and number of decimals d
A
character data
Aw
character data with width w
'xxx'
string literal (new form)
nHxxx
string literal (old form)
n(...)
n occurences of sub format
$
no new line for output (not standard but commonly supported)

Note that per very old tradition then the first column in output is used for printer control.

Simple example:

      PROGRAM IO
      INTEGER*4 I,N
      INTEGER*4 FAC
      EXTERNAL FAC
      WRITE(6,1000)
      READ(5,1100) N
      DO 100 I=1,N
        WRITE(6,1200) I,FAC(I)
100   CONTINUE
1000  FORMAT(1X,'Enter max value: ',$)
1100  FORMAT(I2)
1200  FORMAT(1X,I2,1X,I8)
      END
C
      INTEGER*4 FUNCTION FAC(N)
      INTEGER*4 N
      INTEGER*4 RES,I
      RES=1
      DO 100 I=1,N
        RES=RES*I
100   CONTINUE
      FAC=RES
      RETURN
      END

More advanced example:

      PROGRAM IO
      INTEGER*4 I,N
      INTEGER*4 FAC
      EXTERNAL FAC
      WRITE(6,1000)
      READ(5,1100) N
      DO 100 I=1,N
        WRITE(6,1200) 'I=',I,'FAC(I)=',FAC(I),
     +                'I=',N+I,'FAC(I)=',FAC(N+I)
100   CONTINUE
1000  FORMAT(1X,'Enter max value: ',$)
1100  FORMAT(I2)
1200  FORMAT(1X,2(A2,I2,1X,A7,I8,1X))
      END
C
      INTEGER*4 FUNCTION FAC(N)
      INTEGER*4 N
      INTEGER*4 RES,I
      RES=1
      DO 100 I=1,N
        RES=RES*I
100   CONTINUE
      FAC=RES
      RETURN
      END

For files then besides READ and WRITE statements then OPEN and CLOSE statements are also needed.

Example:

      PROGRAM FCOPY
      INTEGER*4 IX
      CHARACTER*80 LINE
      OPEN(UNIT=1,FILE='in.txt',STATUS='OLD')
      OPEN(UNIT=2,FILE='out.txt',STATUS='NEW')
100   READ(UNIT=1,FMT=1000,END=300) LINE
      IX=80
200   IF(LINE(IX:IX).EQ.' ') THEN
        IX=IX-1
        GOTO 200
      ENDIF
      WRITE(UNIT=2,FMT=1100) LINE(1:IX)
      GOTO 100
300   CLOSE(UNIT=2)
      CLOSE(UNIT=1)
1000  FORMAT(A)
1100  FORMAT(A)
      END

The manual trimming of extra space in fixed length strings again emphasizes what Fortran is not good at.

Standard Fortran 77 supports unformatted IO and direct access to fixed length files by line number and that is really a primitive database.

Create file with records:

      PROGRAM DIRCRE
      INTEGER*4 I
      CHARACTER*80 BUF
      OPEN(UNIT=1,FILE='db.dat',STATUS='NEW',
     +     FORM='UNFORMATTED',ACCESS='DIRECT',RECL=80)
      DO 100 I=1,100
        WRITE(BUF,1000) I
        WRITE(UNIT=1,REC=I) BUF
100   CONTINUE
      CLOSE(UNIT=1)
1000  FORMAT('This is record ',I3)
      END

Lookup by record number:

      PROGRAM DIRLOOKUP
      INTEGER*4 R,IX
      CHARACTER*80 BUF
      OPEN(UNIT=1,FILE='db.dat',STATUS='OLD',
     +     FORM='UNFORMATTED',ACCESS='DIRECT',RECL=80)
      WRITE(6,1000)
      READ(5,1100) R
      READ(UNIT=1,REC=R) BUF
      IX=80
100   IF(BUF(IX:IX).EQ.' ') THEN
        IX=IX-1
        GOTO 100
      ENDIF
      WRITE(6,1200) BUF(1:IX)
      CLOSE(UNIT=1)
1000  FORMAT(1X,'Enter record number: ',$)
1100  FORMAT(I3)
1200  FORMAT(1X,A)
      END

Arrays:

Fortran obviously supports arrays. In fact Fortran has one of the best implementations of multi dimensional arrays.

Declaration of arrays:

      typeofvar varname(dim1)
      typeofvar varname(dim1,dim2)
      typeofvar varname(dim1,dim2,dim3)

And elements are referenced as:

Note that array element indexes are 1 based and not 0 based.

Example:

      PROGRAM ARR
      INTEGER*4 N
      PARAMETER(N=10)
      INTEGER*4 I
      REAL*8 X(N)
      DO 100 I=1,N
        X(I)=SQRT(1.0D0*I)
100   CONTINUE
      DO 200 I=1,N
        WRITE(*,*) I,X(I)
200   CONTINUE
      END

Another example with multi dimensional array and use of subroutine/function:

      PROGRAM MULTIARR
      INTEGER*4 N,M
      PARAMETER(N=10,M=10)
      INTEGER*4 I,J
      REAL*8 X(N,M)
      REAL*8 MXSUM
      EXTERNAL MXSUM
      DO 200 I=1,N
        DO 100 J=1,M
          X(I,J)=I*J
100     CONTINUE
200   CONTINUE
      WRITE(*,*) MXSUM(X,N,M)
      END
C
      REAL*8 FUNCTION MXSUM(X,N,M)
      INTEGER*4 N,M
      REAL*8 X(N,M)
      INTEGER*4 I,J
      REAL*8 RES
      RES=0
      DO 200 I=1,N
        DO 100 J=1,M
          RES=RES+X(I,J)
100     CONTINUE
200   CONTINUE
      MXSUM=RES
      END

Note that the dimension of the array is passsed as arguments to the function, so the function can be reused for all possible dimensions.

Example using array initialization with DATA statement and implied loop in output:

      PROGRAM MOREARR
      INTEGER*4 N,M
      PARAMETER(N=10,M=10)
      INTEGER*4 I,J
      REAL*8 X(N,M)
      DATA X/1*1.0d0,2*2.0d0,4*3.0d0,8*4.0d0,16*5.0d0,32*6.0d0,37*7.0/
      DO 100 I=1,N
        WRITE(6,1000) (X(I,J),J=1,M)
100   CONTINUE
1000  FORMAT(1X,10(F4.2,1X))
      END

Here we see that Fortran store two dimensional arrays by column and not by row like most other languages.

Other features:

GOTO can use a variable a socalled assigned GOTO.

Example:

      PROGRAM ASGNGOTO
      IMPLICIT NONE
      INTEGER*4 MYJUMP
      ASSIGN 100 TO MYJUMP
      GOTO MYJUMP
      WRITE(*,*) 'You will not see this'
      GOTO 200
100   WRITE(*,*) 'OK'
200   CONTINUE
      END

Usage of this feature may not be good for code readability.

It is possible to overlay two variables so they are the same place in memory (similar to C/C++ union).

Example:

      PROGRAM EQ
      INTEGER*2 A(2)
      INTEGER*4 B
      EQUIVALENCE(A,B)
      B=65537
      WRITE(*,*) A(1),A(2)
      END

Subroutines and functions can have multiple returns like in most other languages, but they can also have multiple entry points, which is more unusual.

Example:

      PROGRAM ENT
      CALL SUB2(1,2)
      CALL SUB1(1)
      CALL SUB0()
      END
C
      SUBROUTINE SUB2(I,J)
      INTEGER*4 I,J
      INTEGER*4 I2,J2
      I2=I
      J2=J
      GOTO 100
      ENTRY SUB1(I)
      I2=I
      J2=0
      GOTO 100
      ENTRY SUB0()
      I2=0
      J2=0
100   WRITE(*,*) I2,J2
      RETURN
      END

Fortran IO has a rather unique capability when reading a text file. It is possible to move backwards to read the same lines again using the BACKSPACE statement.

Example:

      PROGRAM BKSP
      INTEGER*4 IV
      CHARACTER*80 SV
      OPEN(UNIT=1,FILE='demo.txt',STATUS='OLD')
100   READ(UNIT=1,FMT=1000,END=500) SV
      IX=80
200   IF(SV(IX:IX).EQ.' ') THEN
        IX=IX-1
        GOTO 200
      ENDIF
      DO 300 I=1,IX
        IF(INDEX('0123456789',SV(I:I)).LE.0) GOTO 400
300   CONTINUE
      BACKSPACE(UNIT=1)
      READ(UNIT=1,FMT=1100,END=500) IV
      WRITE(*,*) 'IV=',IV      
      GOTO 100
400   WRITE(*,*) 'SV=',SV(1:IX)
      GOTO 100
500   CLOSE(UNIT=1)
1000  FORMAT(A)
1100  FORMAT(I8)
      END

It is possible to have one line functions inline socalled statement functions.

Example:

      PROGRAM FP
      REAL*8 F1,F2,F3
      REAL*8 X
      F1(X)=2*X+1
      F2(X)=X*X-2
      F3(X)=X**3+7
      DO 100 I=0,3
        WRITE(*,*) I,F1(I),F2(I),F3(I)
100   CONTINUE
      END

It is possible to pass subroutines/functions as argument to subroutine/function.

Example:

      PROGRAM FP
      REAL*8 F
      EXTERNAL F
      DO 100 I=1,16
        WRITE(*,*) I,SOLVE(F,DBLE(I))
100   CONTINUE
      END
C
      REAL*8 FUNCTION F(A,X)
      REAL*8 A,X
      F=X**2-A
      RETURN
      END
C
      REAL*8 FUNCTION SOLVE(F,A)
      REAL*8 A
      REAL*8 F
      EXTERNAL F
      REAL*8 X,XN
      REAL*8 DIFF
      EXTERNAL DIFF
      XN=1
100   X=XN
      XN=X-F(A,X)/DIFF(F,A,X)
      IF(ABS(XN-X).GE.0.0000001) GOTO 100
      SOLVE=X
      RETURN
      END
C
      REAL*8 FUNCTION DIFF(F,A,X)
      REAL*8 A,X
      REAL*8 F
      EXTERNAL F
      REAL*8 DELTA
      PARAMETER(DELTA=0.0000001)
      DIFF=(F(A,X+DELTA)-F(A,X))/DELTA
      RETURN
      END

The last two examples again show Fortran used for floating point scientific calculations.

The ugly part

Fortran does have a reputation for being an ugly language. And while it is possible to write very nice Fortran code, then it is possible to write some really ugly code using various obscure features.

Let us see a couple of examples.

      PROGRAM MODFUN
      I = 12
      J = I MOD 5
      WRITE(*,*) I,J
      END

produces an "unexpected" output like:

 12 4198999

The explanation is that the code is really:

      PROGRAM MODFUN
      INTEGER*4 I,J,IMOD5
      I = 12
      J = IMOD5
      WRITE(*,*) I,J
      END

This is due to some rules in Fortran:

And the code that produces the "expected" output is:

      PROGRAM MODFUN
      I = 12
      J = MOD(I,5)
      WRITE(*,*) I,J
      END

Let us see the same issue being triggered by using a period instead of a comma.

      PROGRAM DOFUN
      DO 100 I=1.10
        WRITE(*,*) I
100   CONTINUE
      END

produces an "unexpected" output like:

 39167304

The explanation is that the code is really:

      PROGRAM DOFUN
      INTEGER*4 I
      REAL*4 DO100I
      DO100I = 1.10
      WRITE(*,*) I
100   CONTINUE
      END

due to the same rules as in the previous example.

And the code that produces the "expected" output is:

      PROGRAM DOFUN
      DO 100 I=1,10
        WRITE(*,*) I
100   CONTINUE
      END

And now let us see an absolutely horror with lots of jumping around in the code.

What does the following code write out?

      PROGRAM GOTOFUN
      INTEGER*4 LBL
      INTEGER*4 I
731   GOTO 113
      ASSIGN 399 TO LBL
113   I=0
      WRITE(*,*) I
247   ASSIGN 601 TO LBL
      IF(I) 588,922,399
588   I=I+1
      WRITE(*,*) I
      GOTO 399
761   GOTO LBL
922   I=I+1
      WRITE(*,*) I
      GOTO(588,399,922) I
399   GOTO 761
601   CONTINUE
      END

Answer:

 0
 1
 2

Explanation:

      PROGRAM GOTOFUN
      INTEGER*4 LBL
      INTEGER*4 I
731   GOTO 113 ! 1: jump to 113
      ASSIGN 399 TO LBL
113   I=0 ! 2: I=0
      WRITE(*,*) I ! 3: write 0
247   ASSIGN 601 TO LBL ! 4: save 601 in lbl
      IF(I) 588,922,399 ! 5: I is 0 so jump to 922 (arithmethic if is 3 labels for value <0 =0 and >0)
588   I=I+1 ! 9: I=I+1=2
      WRITE(*,*) I ! 10: write 2
      GOTO 399 ! 11: jump tp 399
761   GOTO LBL ! 13: jump to lbl=601
922   I=I+1 ! 6: I=I+1=1
      WRITE(*,*) I ! 7: write 1
      GOTO(588,399,922) I ! 8: I is 1 so jump to 588 (computed goto jumps to label 1,2,3,... depending on value)
399   GOTO 761 ! 12: jump to 761
601   CONTINUE ! 14: done
      END

Article history:

Version Date Description
1.0 July 20th 2008 Initial version (in Danish) published on Eksperten.dk
2.0 August 27th 2016 Translation to English and complete reformatting and publishing here
2.1 October 8th 2016 Add content overview
2.2 July 6th 2017 Add ugly examples

Other articles:

See list of all articles here

Comments:

Please send comments to Arne Vajhøj