Updating FORTRAN code

I’m in the process of porting code written on VAX in FORTRAN77 – and some routines have optional parameters. FORTRAN 77 cannot handle these, but on VAX, it’s easy to retrieve them using a small MACRO module. Not so on Alpha, and Itanium would be even more troublesome – if possible at all due to the architectural differences and processor technology. (See earlier thredas in this catergory).

So I have to choose: re-write the code in another language, or update it to a newer FORTRAN version that allows checking of arguments, as Hoff suggested.

I choose the latter – it proved a far less troublesome task than anticipated.

Consider a routine A, with 4 arguments K, L M and N. K being required and L, M and N optional; however, any of these could be present.

This is the basic FORTRAN 77 code:


SUBROUTINE A (K, L, M, N)

C arguments

INTEGER*4 K
INTEGER*4 L (*)
CHARACTER*(*) M
LOGICAL*4 N

C Local variables

INTEGER*4 S, nmbr, mask

C Routine used to see whether args are present
C Bits in Mask will be set when present

INTEGER*4 GETARGS

C main code

S = GETARGS (Nmbr, Mask)
...
IF (BTEST (Mask,2)) THEN
C
C Parameter L is present
C
ENDIF
....

This routine can be called as:

F = 1
G(1) = 1
G(2) = 1
G(3) = 1
H = "This can be a text of arbitrary length"
I = 0

CALL A (F,G,H,I)
CALL A (F,,H) ! so L and N are missing

Updating the routine to FORTRAN 95 so the optional parameters can be handled, are really minimal: add a line that specifies which arguments are optional, remove the call of the GETARG routine, and use PRESENT (arguments) in stead of BTEST(Mask, bit).
The FORTRAN95 code look like this:

SUBROUTINE A (K, L, M, N)

C arguments

INTEGER*4 K
INTEGER*4 L (*)
CHARACTER*(*) M
LOGICAL*4 N

OPTIONAL :: L, M, N

C Local variables

INTEGER*4 S

C main code

...
IF (PRESENT (L)) THEN
C
C Parameter L is present
C
ENDIF
....

To use this, the routine calling this subroutine must specify the interface. If a routine is heavily used, it’s worthwhile to create an INCLUDE file containing the interface:


INTERFACE
SUBROUTINE A (K, L, M, N)

C arguments

INTEGER*4 K
INTEGER*4 L (*)
CHARACTER*(*) M
LOGICAL*4 N

OPTIONAL :: L, M, N
END SUBROUTINE
END INTERFACE

Add this into calling routines:


INCLUDE 'A_IF.INC'
...
F = 1
G(1) = 1
G(2) = 1
G(3) = 1
H = "This can be a text of arbitrary length"
I = 0

CALL A (F,G,H,I)
CALL A (F,,H) ! so L and N are missing

This is still to be done, but it looks good!

I ran into one problem still to cope with:
CALL B (%VAL (Args))
does not compile: %VAL is out of context here.
The routine in which this code occurs is rather basic – and the mechanism is used heavily in calling routines, where the addresses of allocated memory are passed….
UPDATE
It turned out pretty straight forward. This particular reference turned out to be a parameter to a routine that could easily be bypassed by assigning the right value to a separate variable and use that one instead.

Well, all modules have been built now – except for the ones requiring a missing file but I don’t need that one in due time – and the libraries are created. Next is translating the macro containing the translation vectors into an option file, and vreate the shared image. Afther that, I can start creating the drivers to test it all

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.