Search

Porting EM/32 Programs to LF95

From the Lahey Technical Support Staff

1.  Introduction

This porting guide recommends steps to move Fortran programs from F77L-EM/32 to the LF95 compiler included in the Lahey Fortran 95 v5.x or LF Fortran v7.x products. The intended audience is the EM/32 user; however, the suggestions should work when porting from any Lahey language system.

For the most part, compiled object and library program units are incompatible between EM/32 and LF95. Therefore, we strongly recommended all program units and libraries be recompiled.

LF95 is a 32-bit high-performance Fortran 77/90/95 language system targeted for Intel's Pentium, Pentium Pro, and Pentium 4 processors. LF95 does not support EM/32 features that reduce performance nor does it support technology that has not kept up with Intel's chip evolution. In general, all currently non-documented (accidental) extensions are not supported in LF95.

The steps detailed below begin with setting a goal and finish with the program executing under LF95. Section 8 is an inventory of incompatibilities between EM/32 and LF95 and the associated actions to correct them.

For more detailed information towards adopting Fortran 90/95, Lahey offers Migrating to Fortran 90, by James F. Kerrigan for $27.95 plus shipping and handling.
 

2.  Porting Procedure

This guide is intended more as a guide than a cookbook; individuals should feel free to make changes (possibly even ignore suggestions) appropriate to their way of doing things.

2.1  Decide upon a goal:  1) Cleaner, more portable, FORTRAN 77 source code (which could also be used for EM/32) or,  2) moving code towards Fortran 95 by beginning to introduce Fortran 95 features into the code.

Your goal affects what changes are made to EM/32 source files (see below).

2.2  Make backup copies of all EM/32 source and data files.

2.3  Choose an extension for fixed-format source files; .for (same as EM/32) is suggested. The extension can be anything, but .f90 which is the default to denote the other Fortran 95 source form: free. Rename the EM/32 fixed-format source files to the chosen extension.

2.4  Using FFTOSTD.EXE (provided with EM/32), convert EM/32 free-format source files to Fortran 95 fixed-format source (same as FORTRAN 77) using the extension decided upon above. This is necessary because the Fortran 95 Standard supports a free-format source format that conflicts with the free form EM/32 supports.

2.5  If the source file contains conditional compilation, use FPP (provided with EM/32) and the set of variables to create the LF95 source file(s). Alternatively, create a .BAT file to run FPP to generate the LF95 source file each time an LF95 compile is required.

2.6  Using EM/32, compile the fixed-format files using the /C/H/L/X options. These options cause a source listing with cross-reference information to be generated and non-conformance with the FORTRAN 77 Standard noted. Non-standard features are noted with one of the following messages:

WARNING - Non-standard FORTRAN 77 usage (see FORTRAN 77 extensions in Lahey Language Reference Manual index).

WARNING - Non-standard Fortran 77 usage, a Fortran 90 feature (see Fortran 90 features in Lahey Language Reference Manual index).

Since the compiler is unable to report every incompatibility, see "FORTRAN 77 extensions" and "Fortran 90 features" in the EM/32 Language Reference.

2.7  Link and execute the EM/32 program. Then execute the program with redirection of output, e.g.,

 program >filename.77

This .77 file will be used to compare with LF95 output to help ensure the program has been ported successfully.

2.8  Make backup copies of all the new (if any) EM/32 source files.

2.9  Install LF95, follow the directions on the screen.

2.10  Port and compile the source files. It is likely compilation or runtime errors will occur when first building with LF95. Read the error messages carefully and use the LF95 User's Guide and Language Reference manuals to make the necessary changes to the source code.

Some of the errors might be caused by the following:

2.10.1  External file formats are different. See the SEQUNF.F90 and HDRSTRIP.F90 conversion programs (meant for LF90, but okay for EM/32) in the WIN32\SRC subfolder of the LF95 installation folder.

2.10.2  Some of the specifiers for I/O intrinsics are different, removed, or have new requirements.

2.10.3  LF95 does not allow the same COMMON to be initialized in multiple BLOCK DATA program units. Initialize a common in a single block data with LF95.

2.10.4  No support for EM/32's non-standard namelist format.

2.11  Create the executable file and capture the output; use the extension ".95".

2.12  Compare the .77 and .95 files. Due to different code generation algorithms in EM/32 and LF95, numbers might not compare due to round off. Also, list-directed output might be formatted differently. Other than this, the files should compare. If not, carefully review the changes that have been made and repeat these last three steps until the port has been accomplished.
 

3.  Driver (LF95.EXE)

Depending on the command-line options, the driver invokes the compiler, library manager, and linker to compile source files, create module libraries, and link objects and libraries to create an executable file. More than one source file and/or object file may be specified. To use the driver to compile a source file to an object file without invoking the linker, use the -c option.

Type "LF95" with no arguments to list the command-line syntax and optional arguments.  See the LF95 User's Guide for the complete description of the Driver.
 

4.  Fig Converter (CNVFIG95.EXE)

Download CNVFIG95.EXE. Save it in the BIN subfolder of the LF95 installation folder.

Lahey FORTRAN 77 compilers (*.FIG) and LF95 (LF95.FIG) have different sets of options with different syntax for specifying the option. To facilitate this change, we provide CNVFIG95.EXE, an executable that converts existing *.FIG files into an LF95.FIG in the same directory. CNVFIG95 either maps each option into the corresponding LF95 option or the option is eliminated. The first list of options (from all the Lahey compilers) below are eliminated; the second list are converted as noted.

4.1  Eliminated Options
/2, /3, /4, /a, /a1, /c1, /d, /d1, /e1, /e2, /i, /k, /kh, /q1, /q2, /q3, /t, /u, /v

4.2  Translated Options

 From        To  
/[n]0      -[n]in
/[n]7      -[n]ap
/[n]a2     -[n]dal
/[n]b      -[n]chk
/[n]c      -[n]f95
/f         -nfix
/nf        -fix
/[n]h      -[n]lst
/[n]o      -[n]co
/[n]p      -[n]pca
/[n]r      -[n]sav
/[n]s      -[n]g
/[n]w      -[n]w
/[n]x      -[n]xref
/z1        -o1
/nz1       -o0

For a complete description of the LF95 options, including the default values, see the LF95 User's Guide.
 

5.  Make Utilities and makefiles

Make utilities and makefiles are used for managing larger software projects where there are many source files, header files, and libraries, often scattered among different directories. While the compiler itself will unconditionally compile all files, the Make utility will only compile files that have been changed recently (along with other files that depend on them), resulting in considerable time savings. The LF95 compiler is being distributed with a new Make utility called Automake, written by Polyhedron Software Ltd. Automake has certain advantages over the old Make utility written by Opus Software, but some users may wish to retain their use of the old Make. Note that the .f90.exe inference rules are already known to both Make utilities.
 

5.1  Opus MAKE (MAKE.EXE)
If you wish to continue using Opus MAKE, you'll need to change the following lines in your makefile:

 From                                      To  
FC      = F77L3                          FC      = LF95
LINKER  = 386LINK                        LINKER  = LF95
FFLAGS  = <EM/32 options>                FFLAGS  = -c <other LF95 options>
LDFLAGS = -SYMBOLS <other link options>  LDFLAGS = <link options>
 

If your makefile uses compiler response files, you'll need to change the following lines as well:

 From                                      To  
DEL F77L3.RSP                            DEL LF95.RSP
ECHO $<,$@ $(FFLAGS) >>F77L3.RSP         ECHO $< $(FFLAGS) >>LF95.RSP
!IF -e F77L3.RSP                         !IF -e LF95.RSP
   $(FC) @F77L3.RSP                         $(FC) @LF95.RSP
 

5.2  AUTOMAKE (AM.BAT)
Automake was chosen for its ability to handle Fortran 95 module dependencies. It is also, on average, easier to use than Opus Make for most applications. Unfortunately, complex makefiles developed under Opus Make are not easily ported to Automake (it is usually easier to start from scratch). There is nothing wrong with continuing to use Opus Make; just be sure that MAKE.EXE, MAKEL.EXE and MKMF.EXE are on the PATH, and be sure that MAKE.INI, MAKEFILE.LIB, and MAKEFILE.PRG reside in the same directory as these EXE files.

To set up Automake for a large project with components in multiple directories, it is easiest to copy all components of the project into a single (temporary) directory and run AM so it can figure out the dependencies. Copy the resulting AUTOMAKE.DEP file over to your working directory. You will also need to copy the AUTOMAKE.FIG file from the BIN subfolder of the LF95 installation folder into the working directory and edit it so that the placemarkers for the various components describe the actual paths of those components.

The LF95 User's Guide and the file AUTOMAKE.FIG provide sufficient information on using Automake.
 

6.  LINKER (LINK.EXE)

Under LF95, the linker is automatically run by the driver unless the -c option is specified.

If you submit filenames to the driver with the extension .obj, the driver will only run the linker.

The driver will read linker command files except for the following imcompatibilities:

     - Comment lines must begin with a # in column one.
     - Object file names must include the extension .obj and be separated by white space (no commas).
 

7.  Library Manager (LM.EXE)

The Library Manager (LM.EXE, distributed with LF95) provides the same functionality as the PharLap Librarian (386LIB.EXE), although command syntax and options are different. The following is a list of differences and/or equivalences between 386LIB and LM.

7.1 Command Files
LM uses command files (or response files) in much the same way as 386LIB, albeit with differences in syntax and structure. For example, an ampersand (&) is used to continue a line in an LM response file, and a new line is treated as a comma on the LM command line. LM also has an interactive command mode that is activated when LM is invoked without arguments.

7.2 386LIB Environment Variable
There are no environment variables pertaining to LM operations. Options that were specifed by the 386LIB environment variable will have to be explicitly specified for LM on the command line or in a response file.

7.3 Command Line Syntax
While the Pharlap Librarian is invoked as 386LIB followed by a list of filenames and switches, LM is invoked as
LM [old-library-name][switches][commands][,[list-filename][,[new-library-name]];
Where:
old-library-name is the name of an existing library, or the library to be created if it does not exist.
switches is zero or more command-line switches.
list-filename is the name of the listing file (same as the 386LIB -map file).
new-library-name is the name of a new library to create if you want to preserve the old library.

7.4 Switches
The following is a list of 386LIB switches, accompanied by LM equivalents wherever possible.
 
386LIB Switch  Example LM Replacement
-Add  386lib mylib -add mod1, mod2... LM mylib +mod1+mod2...
-(NO)Backup 386lib myilb -delete mod4 -backup specify new-library-name in command line above.
-Create 386lib newlib -create mod1, mod2... LM newlib +mod1+mod2...
-Delete 386lib mylib -delete mod4 LM mylib -mod4
-Extract 386lib mylib -extract trigfunc LM mylib *trigfunc
-ExtractALL 386lib mylib -extractall LM mylib/extractall
-(NO)Map 386lib mylib -map mymap
(outputs a listing to file mymap)
LM mylib, mymap.map
-PAGESIZE 386lib mylib -pagesize 64 LM mylib/pa:64 (note: -pagesize option for lf95 driver remains in effect when creating libraries using lf95)
-Replace 86lib mylib -replace newmod LM mylib -+newmod
-TwoCase  386lib mylib -add trigfunc -twocase No equivalent
 
 

8. User Actions

What follows is an inventory of incompatibilities between EM/32 and LF95. Actions must be taken to remedy each of them. There are six sections below; each section requires a different action for the group of incompatibilities.

8.1  Hardware Not Supported

8.1.1  80287 coprocessor
Note -- since the 80287 is not supported, SETUNDR0.OBJ is not provided.

8.1.2  Weitek coprocessor
Not supported in LF95.

8.2  RPC interface
Not supported in LF95.

8.3  Source Code Extension Changes
This group of changes requires source code changes from an EM/32 FORTRAN 77 extension to a Fortran 95 feature, i.e., the new source program will not be backward compatible with EM/32 but is Fortran 95 standard conforming.

8.3.1  NARGS, number of arguments passed to a program unit.
Action:  Assuming the EM/32 code is something like

SUBROUTINE S(a, b, c)
REAL a, b, c
IF ( NARGS() .GT. 2 ) THEN
    a = c
ELSE
    a = b
END IF

change the code to use the Fortran 95 intrinsic PRESENT

SUBROUTINE S(a, b, c)
REAL a, b, c
OPTIONAL c
IF ( PRESENT(c) ) THEN
...

8.3.2  VAX Extensions
Action, Fortran 95 Solution:  change the intrinsics to use generic Fortran 95 code, e.g., INT2 and INT4 to INT, and CDSIN to SIN.

8.3.2  NAMELIST Statement
In Fortran 95, a namelist group object must have its type and/or shape specified by previous specification statements or implicit typing rules in effect. This differs from the statement order allowed in EM/32. For example, with IMPLICIT NONE in effect, the following two lines would work in EM/32:

NAMELIST /mylist/ a, b, c
INTEGER a, b, c

But would have to be changed in LF95:

INTEGER a, b, c
NAMELIST /mylist/ a, b, c

8.4  Source Code Extension Eliminations
This group requires the source code be modified to eliminate EM/32 extensions that are not in LF95 but the resulting code conforms to the FORTRAN 77 Standard. In addition, where appropriate, suggestions are given to port to Fortran 95.

8.4.1  Hollerith constants.  LF95 support is limited to within the FORMAT Statement.
Action:  Convert each nH to CHARACTER constants and change the source code accordingly.

8.4.2  Character declaration.  LF95 does not support ch*5(10).
Action:  Change to CHARACTER*5 ch(10) or CHARACTER (LEN=5), DIMENSION(10) :: ch

8.4.3  EM/32 allows statement function actual arguments to differ in type from the dummy arguments.
For example,

real x
f(x) = x + 1.
print*, f(1)

LF95 doesn't allow it.
Action:  Use same type arguments

8.4.4  Generic intrinsics.  LF95 does not allow SIN (int), etc., and mixed types with MAX, MIN, MOD, etc.
Action:  Convert arguments to appropriate type using INTRINSIC functions REAL, DOUBLE, ...

8.4.5 Non-Integer Numerics.  LF95 does not allow non-integers in computed goto, subscripts, substrings, unit numbers, etc.
Action:  Using the INTRINSIC function INT, convert non-integer expressions to INTEGER.

8.4.6  ALLOCATE Statement.  STAT= specifier
Action:  If the optional STAT= Specifier is present it must be the last item in the list.

8.4.7  IF (nonCOMPLEX numeric exp) [label],[label],[label]
Where:   Missing statement labels reference the immediately following executable statement
Action, simplest solution:  convert to IF (non-COMPLEX numeric exp) label,label,label
Action, better solution:  replace the Arithmetic IF with the FORTRAN 77 LOGICAL IF THEN ELSE construct

Note: Arithmetic IF may be removed from the Fortran Standard

8.4.8 Statement label without an executable statement
Action, FORTRAN 77 solution:  place  word "CONTINUE" after column 6
Action, Fortran 95 solution:  if the label identifies a DO loop, use END DO and eliminate the label

8.4.9  Substring of parenthetical expressions and function results
Action:  Replace the code charexpression(from:to) with:

char_temp = charexpression
 ... char_temp(from:to)

Where:  char_temp is a CHARACTER scalar of appropriate length

8.4.10  Declarations appearing after the first executable statement
Action:  Move the declaration(s) to the declaration statements section of the program unit.

8.4.11  .XOR
Action:  Change .XOR. to .NEQV.

8.4.12  HC EXTERNAL
Action:  Delete "HC" so the statement becomes an EXTERNAL statement.

8.4.13  OPEN Statement.  ACTION=READ/WRITE
Action:  Change READ/WRITE to READWRITE.

8.4.14  IOSTAT/STAT numbers are different.

8.5  Non-Standard Changes
This group of statements requires changes that results in code that does not meet either the FORTRAN 77 or the Fortran 95 Standard, i.e., the Fortran Standard Committees have not standardized these features.

8.5.1  %val
Action:  Convert all instances of %val to val, i.e., eliminate the percent sign.

8.5.2  OPTION BREAK(label), OPTION BREAK[(logical variable)] and OPTION NBREAK
Action:  This code must be redone since only CALL BREAK(logical variable), CALL BREAK, and CALL NBREAK are available in LF95.

8.6  Changes That Are Not Required
This group of changes, although recommended, are not required since LF95 has these subprograms as undocumented features.  Alternatively, the source below may be utilized in programs resulting in code that meets the Fortran 95 standard.

8.6.1  CALL TIME(result)
Action:  Convert the code to:

CALL
DATE_AND_TIME(TIME=char_temp)
result = char_temp(1:2) // ':' // char_temp(3:4) // ':' &  //  char_temp(5:9)

Where:   char_temp is a CHARACTER scalar of at least length 9

8.6.2  CALL DATE(result)
Action:  Convert the code to:

CALL DATE_AND_TIME(DATE=char_temp)
result = char_temp(5:6) // '/' // char_temp(7:8) // '/' &  //  char_temp(3:4)

Where:  char_temp is a CHARACTER scalar of at least length 8

8.6.3  NBLANK(char_exp)
Action:  Convert the code to:  LEN_TRIM(char_exp)

8.6.4  CHARNB(char-exp)
Action:  Convert the code to:  TRIM(char-exp)