MORSE Coding Conventions
Last Updated: 27JUL05
CODING
- FORTRAN Standard
-
As far as possible the code has been written in `standard' FORTRAN-77.
However, a couple of commonly-implemented
non-standard extensions have also been used for convenience:
- IMPLICIT NONE in all modules, to force all variables to be
declared (which prevents any mis-typed variable names from being treated
as new variables)
- DO WHILE where possible, to avoid GOTO statements
- END DO terminating all DO loops, to avoid statement numbers
- In-line commenting, ie uses `!' to add comments to
ends of records, as well as the standard comment records beginning with
`C'
- COMMON Blocks
-
All COMMON data blocks (i.e., data which is passed between subroutines
via a COMMON block rather than via the argument list) are kept as
`include files' (ie *.inc). This avoids problems where the COMMON
block declaration in one subroutine may be inconsistent with the same
block declaration in another.
- BLOCK DATA
-
The standard way of initialising data held in COMMON blocks is using
the BLOCK DATA statement. However, this is not used in MORSE due to the
additional complexity required in the compile
statement. Instead, all data held in COMMON blocks is written explicitly
during run time.
- Array Dimensions
- Most of the array sizes are held as PARAMETER statements in
the file rfmsiz.inc. MORSE should always check array
dimensions before arrays are written so that array bound errors
should not occur. Instead, the program will stop with a
fatal error message indicating the subroutine
where the problem occurred and the array dimension which needs to be
increased.
- DATA Statements
- Where possible and necessary, subroutine variables are initialised using
DATA statements (and also SAVEd in subroutines called more than once).
In many cases, this isn't actually necessary since the code itself
should ensure that the initial value that is accessed is always defined,
however DATA statements are used anyway (often with an illegal `dummy'
value such as -1) to avoid nagging messages from the compiler or code-checking
programs.
- SAVE Statements
- SAVE statements are used sparingly to avoid unnecessary computational
overheads. Obviously these are only used in subroutines which are called
more than once, and usually only applied to specific variables (usually those
which are also initialised in DATA statements).
- Continuation
- In standard FORTRAN 77 almost any character can be used in `column 6'
of a record to indicate a continuation. However, in MORSE, only the
& character is used since it is distinct from character which might
appear as part of a legitimate statement.
- EXTERNAL
- All functions and subroutines called within a module are declared using
an EXTERNAL statement. Mostly this just serves to make the dependencies clear
but also prevents intrinsic functions being used which accidentally have the
same name as a MORSE subroutine/function.
Module Names
- Subroutine Modules
-
Most subroutine modules have 6-letter names (plus the .for extension).
These are often of structure abcxyz.for
where abc are the last 3 letters of the name of the parent
module (or mse in the cases of subroutines called directly
from the program module) and xyz relates to the operation
being performed in the subroutine.
-
For example, drvxsc.for is the module which reads the
*XSC section of the driver table,
which is called from msedrv.for and calls subroutines
xscchk.for and xscfil.for (as well as a couple of general
purpose modules
nxtfld.for which reads the next field from the driver table
section and rfmlog.for, which writes messages to morse.log).
- Include Files
-
Include files are of three types:
- Common Variables
- These have names like abccom.inc where ABCCOM is the
name of the FORTRAN COMMON BLOCK, and within the COMMON BLOCK are a
series of variables with names terminating in ...ABC. Where these
variables are 1-dimensional arrays, they will usually have a declared
array dimension MAXABC (stored as a PARAMETER in rfmsiz.inc)
and a COMMON VARIABLE NABC, indicating the number of array elements
which are actually used.
- Note that BLOCK DATA statements are not used in MORSE, ie all
elements of COMMON BLOCKS are filled during run time.
- Global Constants
- Names sometimes ending in ...con.inc but with some notable
exceptions such as rfmsiz.inc (containing most of the array
dimensions of common variables, MAX...) and mselun.inc
containin the list of Logical Unit Numbers used by MORSE.
- Large Data Statements
- Names sometimes ending in ...dat.inc, but also
h2ockd.inc and h2omtc.inc containing large tabulated
datasets such as molecular continuum and line-mixing data.
These are usually only required in single modules but make the
subroutine code unwieldy if directly included within the subroutine itself.
I/O Operations
- Terminal Input/Output
- Printing to the terminal uses a WRITE statement with * as
the unit number, giving the default output LUN (usually 6).
WRITE ( *, '(A)' ) 'Typical output statement'
- MORSE does not READ from the terminal, so the default input lun
(usually 5) is not used.
- Logical Unit Numbers
- MORSE LUNs are contained in file mselun.inc.
- Apart from avoiding
the default terminal input (5) and output (6) luns, most of these are
arbitrary. The only exception is LUNFRE which is used as the
base value for assigning LUNs to files which are opened and remain
open while MORSE is run. Therefore this should be at least 1 higher than
any other assigned LUN value.
- LUNTMP is recommended for files which are opened, read/written,
and immediately closed.
- I/O Errors
- On most (but not all) MORSE FORTRAN I/O statements
(OPEN, CLOSE, READ, WRITE, REWIND, BACKSPACE)
there is a test on the IOSTAT value returned.
- If IOSTAT is non-zero MORSE usually interprets
this as a fatal error, in which case the program terminates with a
MORSE-generated error message indicating the subroutine where the
error occurred and the IOSTAT value (this is preferable to just letting
the program crash with an I/O error message but no clue where in the
code it occurred).
- Unfortunately, these IOSTAT values are
compiler-dependent so it is not possible to uniquely identify each IOSTAT
value with a particular error.
- An exception is the end-of-file error, indicated by IOSTAT=-1 on all
compilers. However, in cases where this is expected (eg reading the
contents of a file or record until the end is detected) the END=nnn
switch is used in the FORTRAN READ statement to control the next action.
Back to MORSE Index