3 GENERAL CODING STANDARD
The rules and guidelines in this section apply to all applications programming irrespective of what
‘software environment’ they run under. They fall into four groups – language, design, quality and
presentation.
3.1 Language
Fortran only !!! 1
For the time being, writers of Starlink application programs are urged to use
Fortran exclusively. Increasing amounts of Starlink systems code are being written in ANSI C (SGP/4
is the present document’s counterpart for the C language), but use of C is discouraged for
applications code. A few pieces of Starlink system software use various dialects of assembler
and Pascal, but these are being eliminated. There may conceivably be future interest in
ADA.
The only permitted dialect of Fortran is ANSI X3.9-1978 (known as Fortran 77) plus certain US
Department of Defense extensions and – in a few cases only – some extensions provided in DEC and
several other proprietary Fortrans.
Discriminating Fortran users were disappointed with the 1978 standard, which failed to contain many
expected improvements. Experience with preprocessors (RATFOR for example) had shown the
feasibility of turning Fortran into a much better language with a minimum of disruption;
unfortunately, many features which could easily have been added to the language weren’t. DEC
Fortran, however, does have a few of these features, and it was decided that certain of these should be
permitted within the Starlink standard. The rationale was (i) it would not be hard to eliminate these
extensions manually if necessary, (ii) they have become almost universal, and (iii) similar facilities
will be part of later Fortran standards. Note that anyone wishing to adhere more rigidly to the
Fortran 77 standard is permitted to do so. The latest version of Fortran, called Fortran 90,
contains many improvements over Fortran 77 and almost eliminates the need to use any
platform-specific features. Extra facilities not available in existing Fortran 77 implementations (for
example the processing of whole arrays as primitive data items) are also available. The
Fortran 90 standard identifies certain features as ‘deprecated’ or ‘obsolescent’, candidates
for deletion in future standards; almost all of these are already prohibited by the Starlink
standard. Fortran 90 compilers are not presently provided on Starlink but will be in due
course.
The following extensions to the Fortran 77 standard are permitted within Starlink:
DO WHILE | permitted but worth avoiding |
IMPLICIT NONE, END DO, DO WHILE and INCLUDE are all in Fortran 90. See Section 5, Writing
Portable Programs, for detailed advice on INCLUDE statements.
Here are some examples of features which are part of neither the Fortran 77 standard nor the Starlink
standard, and are to be avoided:
INTEGER*4, REAL*4, REAL*8, LOGICAL*1 etc. (see note 1, below)
Names
6 characters (note 2)
More than 19 continuation lines
Data initialization in a type declaration
Departures from Fortran 77 permitted statement order
Overlapping character substrings on both sides of an assignment
Data structures
Bit handling functions (note 3)
VMS specific OPEN keywords (note 4)
$, O, Q, or Z edit descriptors in FORMAT statements (note 5)
%VAL, %REF, %DESCR (note 6)
Certain other non-standard features are dealt with later sections. The DEC Fortran manual has all
extensions to the ANSI standard printed in blue, and these features should be avoided
unless expressly sanctioned in the Starlink standard. If an extension has to be used for any
reason (because the required result simply cannot be obtained any other way) this should be
highlighted with comments. If you are unsure about whether your program conforms
to the Fortran 77 standard, try compiling it with the /STANDARD qualifier (on VMS
systems).
Notes:
-
(1)
- INTEGER*2 and BYTE data types may be used where they are essential to deal with input
data sets containing 8 or 16 bit values.
-
(2)
- Many programmers refuse point-blank to stick to 6 character names, and some even like
using whole sentences with underscores between the words. Opinions vary on whether
long names help readability all that much, but what is certain is that several computer
systems of considerable potential importance to UK astronomers do not support long
names (for example some mainframes, certain attached processors, some workstations).
Some computers accept names longer than 6 characters but only a little longer; others
accept long names but ignore all but the first n characters.
Though names internal to a Starlink program must be no more than 6 characters long, the
use of names of more than 6 characters is permissible (and indeed strongly encouraged)
in the case of program unit and labelled COMMON block names, in order to reduce the
chances of name clashes between different facilities (especially the C run-time library).
Such names should be constructed by prefixing the name proper, which must be no
more than 6 characters long, with a facility name of the form ‘FAC_’. An example
is SGS_OPEN: the facility name is SGS and the name of the routine OPEN. For the
utmost portability, it is wise to limit the name proper to 5 characters rather than the
full 6; thus SGS_ZSIZE can readily be preprocessed to SZSIZE (for example) if merely
dropping the SGS_ gives name clashes. Within a given package, the name proper should
be unique even if different facility names are being used. A further Starlink convention
is that routines called only internally within a package are given names prefixed with
‘FAC1_’ rather than simply ‘FAC_’. Application programmers should never use existing
facility names (see Appendix A) unless contributing solicited and debugged software for
inclusion in the facility concerned.
Fortran 90 allows names of up to 32 characters.
-
(3)
- Use of bit manipulation routines will be unavoidable in instrument specific
processing but is prohibited for general applications. (Note that Fortran 90 contains
bit-manipulation facilities.)
-
(4)
- Certain VAX extensions to the OPEN and INQUIRE statements overcome serious omissions
from the Fortran 77 standard and may be used if necessary:
- READONLY
- CARRIAGECONTROL=‘LIST’
- ACCESS=‘APPEND’ (worth avoiding)
Highlight these VAX-specific items with comments, and use them only in short routines which
can be re-coded for other platforms.
-
(5)
- In FORMAT statements, O (octal) and Z (hexadecimal) edit descriptors may be required for the
early stages of instrument specific processing, but must not be used otherwise. Q (number of
characters input) and $ (suppress carriage return) should be avoided. Sometimes they have to be
used, typically at just one place in an application, and when this happens they should be
prominently commented as VAX-specific and preferably isolated inside a short routine which
can be re-coded for other platforms.
-
(6)
- The DEC Fortran %VAL etc. may be required to interface to ‘software environment’ routines.
(ADAM is one such software environment – see section 4.) They should not be used for any
other purpose.
Stick to the Fortran 77 character set !! 2
The Fortran 77 standard permits use of only the following
characters (except in comments and character strings):
0-9, A-Z, space, currency symbol, +-*/(),’.:
Though a few other characters are sufficiently common for trouble to be unlikely it is best to avoid
them even in comments as they may appear different on different terminals and printers – hash and
pounds sign are particular examples of this. Backslash is best avoided because it has a special meaning
in almost all Unix Fortrans. Applications should not depend on the presence of nonstandard
characters – stick to the Fortran 77 set.
An exception is made for lowercase letters a-z, which are (a) permitted in program source code,
and (b) encouraged in output messages. The recommended style is to use upper- and
lowercase freely in comments but to use uppercase in the Fortran proper. If you must use
lowercase characters in Fortran statements, it is important to be consistent, not just to make the
code easier to read, but also because the Fortran compilers on some Unix systems regard
upper- and lowercase characters as different (so N and n would be different entities for
example).
The character set allowed by Fortran 90 includes _ ! " % & ; < > ? [ ].
Take care with collating sequence. The letters A-Z appear in the expected order, but you cannot assume
that they are contiguous in the collating sequence. Similar remarks apply to 0-9. Do not
assume that the numbers appear before the letters. Assume nothing about the collating
sequence of punctuation characters, except that blank comes before both the letters and the
numbers.
Input must not be case sensitive !!! 3
Applications must not distinguish between upper- and
lowercase in data they receive.
Avoid end of line comments ! 4
End of line comments (preceded by ‘!’) are not in the Fortran 77
standard, and are best avoided, though they are in Fortran 90 and are supported by many
current compilers. There is some justification for using them with data declarations. If used
at all they must be neatly aligned by means of spaces, not TAB characters (see the next
rule).
Don’t use TABs !!! 5
The use of TAB characters is prohibited, both in source code and as required
data input to a program. Though their use in source code may give an illusion of good layout with a
minimum of effort, tab settings on different terminals and printers will in general be different and will
not reproduce what appeared on the screen when the program was being written. With most
editors it is easy to program rarely used keys or special function keys to produce multiple
spaces – for instance 3 and 6 – which will reduce the number of keystrokes when entering
Fortran.
Arithmetic IF banned !!! 6
The use of the arithmetic IF:
is prohibited. It offers even more opportunity for unstructured programming than the discredited
GO TO and, moreover, doesn’t read naturally in English. (The arithmetic IF is a fossil of
one of the machine instructions on the computer for which Fortran was first devised, the
IBM 704.)
Use the computed GO TO sparingly ! 7
Don’t use the computed GO TO unless you have to, and
then only to implement a properly laid out ‘case’ construct. In such instances, a good plan is to use
comments to indicate the case for each destination. For example:
* Switch according to command
GO TO ( 1000, 2000, 3000, 9000 )
* Go Hold Stop Abort
ASSIGN banned !!! 8
The ASSIGN statement is prohibited. It offers endless opportunities for
incomprehensible code, and is a peculiar historical feature not found in other languages. Though it
can be used in conjunction with the assigned GO TO (also banned) to implement a sort of internal
subroutine call, the temptation to do clever things with saved or multiple return pointers etc. will
prove too great for some practitioners – so the feature is outlawed by Starlink. (See also
rule 29.)
Don’t use PAUSE !!! 9
PAUSE is prohibited. It produces different results on different
sorts of computers and is sure to interfere with whatever software environment you are
using.
STOP, RETURN, ENTRY banned !!! 10
STOP, RETURN and ENTRY are all prohibited.
STOP produces a message that is usually uninformative and is incompatible with software
environments. It is also redundant – the main program’s END statement causes program
termination.
RETURN is redundant – a subprogram’s END statement returns to the caller.
The key reason for prohibiting STOP and RETURN is to force the programmer to have one
exit point only per routine, at the end, to aid debugging. This complements the ban on
multiple entry points (and hence on alternate RETURN) in satisfying structured programming
requirements.
Note that the ban on ENTRY and RETURN means that multiple ENTRYs and RETURNs are similarly
prohibited.
Don’t use DIMENSION !!! 11
The DIMENSION statement should not be used; arrays must be
given explicit type declarations. For example:
must be used, rather than:
Don’t try to overprint !!! 12
In FORMAT statements, the use of the printer control character ‘+’ is
prohibited. Assume that overprinting is not possible; this is almost always the case.
Don’t devise your own character handling mechanisms !!! 13
Characters must be handled only by
the character string mechanisms of Fortran 77. Private mechanisms (involving for example integer
arrays) are banned.
Remember to use SAVE !!! 14
The SAVE statement must be used in all cases where subprograms
assume that their local variables retain their values between successive invocations. If you don’t do
this, your programs will not run correctly on some computers even though they happen to work on
VAX/VMS and other compilers that allocate static storage by default. Note that SAVE is also
required when using labelled COMMON, unless the COMMON block is declared in at least
one other program unit in the calling chain (the main program for instance); in this case
the SAVE specifies the COMMON block itself rather than the individual variables. Avoid
using the form of the SAVE statement where the variable and COMMON block names are
omitted.
The rules in the ANSI standard concerning SAVE are rather complex and no further attempt will be
made to summarize them here.
Statement labels on FORMAT and CONTINUE only !!! 15
Statement labels are permitted
on FORMAT and CONTINUE statements only. They should be less than 10000, increase
monotonically through the routine, occupy columns 2-5 only and be consistently justified, left or
right.
Declare everything explicitly !!! 16
All variables, parametric constants and functions (except the
Fortran 77 generic functions) must be given explicit type declarations. To force this, it is
strongly recommended that the IMPLICIT NONE statement be used, with the additional
advantage that undeclared arrays, functions, etc., and many typing errors are exposed during
debugging.
The use of a consistent naming scheme to indicate type, though unfashionable, is worth considering.
The standard Fortran convention of an initial I-N can be used to highlight integers, and where REAL
and DOUBLE PRECISION variables are being mixed it can be helpful to reserve initial D for the latter.
CHARACTER, LOGICAL and COMPLEX entities are more rarely confused and there is usually less
need for naming conventions.
Arrays appearing in COMMON must have their type and dimensions declared in separate statements
which precede the COMMON declaration. For example:
REAL ARRAY(512)
COMMON /fac_BLOCK/ ARRAY
The types of subprogram arguments must be specified explicitly.
Use CHARACTER()
!! 17
Dummy arguments of type character, and character functions, should be declared
CHARACTER*(*) in order to pass the length implicitly.
Keep I/O out of mainline code !! 18
Portability considerations make it desirable that all Fortran I/O
(except to internal files) be encapsulated within suitable primitive subroutines.
Avoid list-directed I/O, which may give different results on different machines. There are library
routines for input and output conversions (see sla_DFLTIN in SLALIB for example); use
these.
In many ‘software environments’ (ADAM for example – see section 4), Fortran I/O to the terminal is
not permitted, and any Fortran I/O to files should be done in accordance with any special rules of the
software environment concerned.
Don’t use literal I/O unit numbers !!! 19
The external unit identifiers (logical unit numbers) used in
OPEN, READ, WRITE, etc. must not be hardwired – the number itself should appear at a
maximum of just one place in the program, in a PARAMETER statement. Keep to the range
0-255.
The various ‘software environments’ usually have ways of supplying such logical unit numbers from
a pool, and this is recommended.
Don’t use mixed mode arithmetic !! 20
Avoid mixed mode arithmetic or change of type across an
assignment statement. Use explicit type conversions; for example:
rather than:
Changing from one number format to another is a very significant event in an algorithm and should
be clearly expressed. Great circumspection should be employed when deciding where such
conversions should occur.
Data type must not change across a CALL !!! 21
Data types must not be mixed across a function
reference or subroutine call, even in cases where it appears to work on a VAX (between REAL and
DOUBLE PRECISION for example).
LOGICAL and INTEGER are different !!! 22
LOGICAL and INTEGER usage must not be mixed.
For example:
INTEGER JFLAG
:
:
IF (.NOT.JFLAG) ...
is not permitted.
Use only INTEGER DO-variables !! 23
Don’t use REAL or DOUBLE PRECISION DO-variables,
just integers. The way the iteration count is determined and the measures taken to avoid cumulative
rounding errors are important parts of the algorithm and should be spelt out.
Don’t use EQUIVALENCE !! 24
EQUIVALENCE should only be used if there is a very good reason,
and even then only in a straightforward way. In particular:
- Do not use EQUIVALENCE to ‘extend’ an array.
- Do not EQUIVALENCE anything in COMMON.
- Do not EQUIVALENCE entities of different data types.
3.2 Design
Use Structured Programming !! 25
The principles of structured programming should be followed
except in cases where this obscures the program logic.
Programs written using structured programming techniques are built out of three basic elements:
(a) processing sequences, (b) decisions, and (c) loops. Each of these three elements has only one
entry point (at the top) and only one exit (at the bottom), and its relationship with the data it uses is
clearly defined. The whole program consists of a hierarchy of these elements. In Fortran 77, (a) is just
a series of statements, (b) is an IF THEN ELSE construct and (c) is one of the DO constructs. The most
conspicuous feature of structured programs is the absence of (or, depending on the suitability of the
programming language being used, the relative absence of) GO TO statements. Such programs are
incomparably easier to follow than ones containing tangled GO TO logic, but may be harder to write,
especially if you have not completely grasped what you are trying to do before you start
coding.
To conform to the Starlink standard, a program must not show signs of having been written
‘bottom-up’, or having ‘grown like Topsy’. It can be a good plan to begin by writing the program in
a ‘structured English’ pseudo-language; this can then become, as comments, part of the
program.
The SPAG utility (SUN/63) can re-arrange GOTO- and arithmetic-IF-infested code into
block-structured form, and this is a good first step when working up old code into a maintainable
form.
Keep program units small ! 26
Modules should be small wherever possible, ideally a page or less
(not including prologue comments). Programs which, despite being longer than this, are nevertheless
not difficult to follow – because they consist of a simple top-to-bottom flow or contain a single main
loop with a simple flow inside it — may be acceptable.
Avoid the GO TO !! 27
The GO TO must not be used unnecessarily. Use the DO and IF structures
unless they make the program difficult to follow. There are cases where use of GO TO is justified by
the need to jump downwards in a program as the result of some exceptional condition, and use of IF
… ELSE IF together with indenting of code would give a less satisfactory appearance. If you have to
form structures using the GO TO, clarify what is going on by means of commenting and
indenting.
If you are prepared to use the non-ANSI-standard DO WHILE, you can write a loop which includes
tests for exit and repeat conditions, without using the GO TO:
LOGICAL LOOP
:
LOOP = .TRUE.
DO WHILE (LOOP)
:
IF (‘exit’ condition) THEN
LOOP = .FALSE.
:
ELSE IF (‘next’ condition) THEN
:
END IF
END DO
Don’t loop using GO TO !! 28
Do not implement loops by jumping backwards using
GO TO.
Don’t use GO TO to drive internal subroutines !!! 29
Internal subroutines driven by GO TO
statements are prohibited, whether using the assigned GO TO or not. (See also rules 8 and
28.)
FUNCTIONs must not have side effects !!! 30
FUNCTION subprograms must only be used when a
single argument is returned and there are no side-effects. All other procedures should be
SUBROUTINE subprograms.
Minimize use of COMMON !!! 31
No unnecessary use of COMMON must be made. The use of
COMMON can lead to code which is difficult to maintain. It should not be used simply as a lazy way
of passing arguments to subprograms; when it is used for passing arguments there must be a good
reason and every item referenced must be mentioned in the prologue comments just as for formal
arguments.
The names of entities in COMMON must not change from one program unit to another; the use of
dummies is discouraged.
All COMMON block source should be stored in separate files from the rest of the source, and be
inserted using the INCLUDE statement.
Blank common must not be used – only labelled common (with a fac_ prefix to the name, as described
in rule 1 note 2).
Note that the Fortran 77 standard does not permit initialization of common blocks via DATA
statements in main programs or normal subprograms; BLOCK DATA must be used. (Avoid potential
linking difficulties when using BLOCK DATA by referring to the name of the BLOCK DATA module
in an EXTERNAL statement in at least one of the subprograms that makes use of the relevant
COMMON block.)
No garbage !!! 32
The following are prohibited:
FORCHECK (see SUN/73) will detect all of these conditions.
Be device-independent !!! 33
Do not make unwarranted assumptions about the hardware being
used, especially the properties of terminals or printers. If your application requires use of
special features, either include mechanisms external to the program which can be configured
to match the hardware available, or have the user make explicit assertions. A common
crime, for example, is to assume that the terminal is ANSI standard (VT100 etc.) and to
output escape sequences in order to control scrolling or to output large characters etc.; these
will have unpredictable effects on other types of terminal. A solution is to include in your
program’s repertoire of commands one which allows the user to announce that he is on
an ANSI terminal and only to output ANSI escape sequences if that command has been
invoked.
Be environment independent !!! 34
Be careful when specifying filenames or device names in
application programs. There are, unfortunately, no platform-independent ways of handling such
names, but difficulties will in practice be minimized if filenames (i) contain no uppercase letters,
(ii) are no longer than eight characters or eight plus a period and a further three, and (iii) contain
only letters, numbers and a maximum of one period.
When soliciting a file or device name from the user, make no assumptions about its format and pass
on the string received (to an OPEN statement typically) without altering it or trying to deduce things
from it.
Be aware of floating-point limitations !!! 35
Programs must not rely on more than the following
ranges and accuracies:
type | range | accuracy |
|
REAL | & zero | 6 dp |
|
DOUBLE PRECISION | " | 14 dp |
Don’t access uninitialized variables !!! 36
Never access an uninitialized variable. Relying on
variables being initially zero (usually the case for VAX Fortran) is not permitted.
Don’t use VAX system service or RTL calls !! 37
Any programs which call system services (QIO
etc.) or Run-Time Library routines will clearly be non-portable, and these techniques should not in
general be used. This may not always be possible, and where a VAX-specific call is required it should
be kept separate from the application proper by encapsulating it in a subprogram of its own.
Occasional use in mainline code is excusable if removing the call happens still to result in a runnable
program (albeit of reduced capability), and if prominent commenting is used to highlight the
VAX-specific code.
3.3 Quality
Use meaningful names !! 38
Use sensible names which (within the 6-character limit) offer some
indication of the meaning of the entity concerned. The use of I, N, W, X, etc. for purely local and
temporary use is permissible; daft or misleading names are banned.
Don’t re-use variables !! 39
Use a variable for a specific purpose; use a different one if the meaning
has changed.
Define sizes parametrically ! 40
In general, the sizes of tables, queues, buffers and work arrays
should be defined parametrically. For example:
* Reference star positions
PARAMETER (NREFS=1000)
REAL REFS(2,NREFS)
If a size is required in more than one program unit, it should be declared in an INCLUDE
file.
Minimize rounding errors !! 41
In cases where control over execution order within a statement is
important in order to minimize rounding, this can be achieved by means of otherwise redundant
parentheses. For example, if DELTA1 and DELTA2 are small compared with B, their sum could be
computed without avoidable loss of precision as follows:
Validate inputs !!! 42
Everything coming into the program from outside must be validated.
There are only two exemptions permitted:
- Subprograms called exclusively by programs which can guarantee to present valid
arguments.
- Subprograms which explicitly put the onus of validation onto the caller to achieve some
real efficiency advantage.
Don’t output error messages at too low a level ! 43
Subprograms will be more flexible if they do not
output error messages themselves but instead leave this to the caller by returning a status. (Using
PAUSE and STOP is even worse – see rules 9 & 10.)
Applications running under a ‘software environment’ (for example ADAM – see Section 4)
should adopt the error reporting strategy provided by that environment. The ERR_ and
MSG_ packages (SUN/104) provide error reporting that works both in ADAM-based and
freestanding programs. These packages enable subprograms to report errors in detail while still
allowing higher levels to decide whether or not messages will actually appear on the user’s
screen.
Don’t terminate by count !!! 44
Terminate input by end-of-file or by a special end record, not by
count.
Don’t test REALs for equality !!! 45
REAL or DOUBLE PRECISION variables must never be tested
for equality against non-zero numbers. Testing for zero is also frowned on by most experts but can be
difficult to avoid.
(But see remarks about bad-pixel handling in ADAM applications – section 4.)
Use the standard order for arguments !! 46
The order of arguments in subroutines should be as
follows:
Given
Given and altered
Returned
Status return
Note that the Fortran 77 standard prohibits use of the same actual argument more than once when
calling a subprogram which gives one of the arguments concerned a new value. Thus a subroutine
P(A,B,R), which computes some function of A and B and finally returns it in R, must not be called
with arguments (X,Y,X) even though this technique happens usually to work in VAX Fortran (for
example).
Use generic names ! 47
Use the generic names of intrinsic functions, for example MAX(A,B) rather
than AMAX1(A,B).
Don’t re-invent existing routines !! 48
Starlink library routines should be used whenever possible,
rather than writing routines which duplicate (or almost duplicate) the functions of existing Starlink
routines. It is permissible to adapt Starlink code where the required changes are substantial and the
code uses only published interfaces; the source must be seamlessly blended with the new application
and be given a new name.
Do not include in a package copies or slight variants of Starlink routines in an attempt to make the
package self-contained. Assume the availability of the required Starlink library, and if the package has
to be run on an installation which does not have the Starlink software collection make proper
arrangements with the Starlink Software Librarian to have the up-to-date libraries sent
there.
Avoid using the Run-Time-Library routines available on VAX/VMS and other platforms. Many of the
facilities included in these libraries are also provided by POSIX, an industry-standard Portable
Operating System Interface. Fortran-callable versions of many of these routines are provided in the
Starlink PSX library.
Many of the libraries which form part of the ADAM Software Environment (see Section 4) are
available in two forms: an ADAM version and a free-standing version. Programmers are strongly
recommended to use these libraries even where there is no immediate intention of running under
ADAM.
Don’t write clever code !! 49
Programs must not be obscure in the name of efficiency.
The first version of the program should be coded for clarity rather than efficiency (within
reason). If there are found to be worthwhile (i.e. obvious to the user) improvements in
efficiency possible, at the expense of clarity, then changes can be made. The reduction in clarity
must then be made good by extra comments – perhaps including the original code. (If the
changes do not reduce the clarity of the program, then it was badly written in the first
place.)
3.4 Presentation
Begin modules properly !! 50
The first statement in a program unit must be one of the following:
PROGRAM, FUNCTION, SUBROUTINE or BLOCK DATA. Preceding comments are discouraged, to
avoid confusion (either to the reader or to software) over where each new module begins in a
concatenated sequence of such modules. (Likewise, comments following an END statement are not
allowed.)
All program units must have sensible and self explanatory names, as far as is possible
given the limitations imposed by the 6 character or fac_ + 5 character rule (see rule 1
note 2).
Include prologue comments !!! 51
There must be one or more blocks of comments at the beginning
of every program unit, which together form a ‘prologue’. The prologue must include the name of the
program unit, a brief description of what it does, and full details of its interactions with
the calling environment. The author, organization, and date should be given, expressed
compactly.
To enable automatic recognition, each block of prologue comments must begin with a comment which starts
and ends with a
comment which starts .
Elsewhere in the program, do not have any statements with
or
in the
second column.
Main programs must have a prologue which says what files will be read or written, and gives the I/O
unit identifiers used (numbers or symbols).
Subprogram prologues must list all the arguments, clearly describing their function, type (unless
obvious), units (where applicable) and any special properties (e.g. whether an array). The words
‘given’ and ‘returned’ are recommended for direction, rather than ‘input’, ‘output’, ‘source’,
‘destination’ and other possibly ambiguous terms. Access to COMMON blocks should be treated
similarly, with every item referenced fully described.
It is recommended that the names of all subprograms called (except the Fortran 77 intrinsic functions)
be given in the prologue. It is extremely important that all the information given in the prologue is
accurate and up to date. Prologues can be automatically extracted from source held in text libraries by
using the LIBPRE facility (see SUN/8).
Example:
SUBROUTINE sla_NUT (DATE, RMATN)
*+
* - - - -
* N U T
* - - - -
*
* Form the matrix of nutation for a given date (IAU 1980 theory).
*
* (double precision)
*
* References:
* Final report of the IAU Working Group on Nutation,
* chairman P.K.Seidelmann, 1980.
* Kaplan,G.H., 1981, USNO circular no. 163, pA3-6.
*
* Given:
* DATE dp TDB (loosely ET) as Modified Julian Date
* (=JD-2400000.5)
* Returned:
* RMATN dp(3,3) nutation matrix
*
* The matrix is in the sense V(true) = RMATN * V(mean) .
*
* Called: sla_NUTC, sla_DEULER
*
* P.T.Wallace Starlink 10 May 1990
*-
Note, however, that much of the freedom implied by the above recommendations may not be
available to programs which conform to the documentation standards of a particular ‘software
environment’, especially if automatic documentation facilities are involved. For details of the prologue
requirements of the ADAM software environment, see section 4.
Begin comments with . 52
The comment symbol ‘’
should be used in preference to the old-fashioned ‘C’.
Use blank lines to improve layout. 53
Blank lines should be used freely to break up
code.
Make comments stand out from code !! 54
Comments must be clearly distinguished from code. The
recommended style is begin the text some fixed amount (1-3 characters) to the left of the code, and to
follow the same indenting scheme in comments and code alike. An alternative style, less likely to be
spoiled by editors and reformatters which change the code indentation, is to begin the comments
always in column 3 or 4. Comments should use lowercase freely, but the code should be in
uppercase.
Comments beginning in column 7 are strongly discouraged, even if preceded by C***** and the
like.
Be considerate !!! 55
Every effort must be made to present the program in the clearest and most
agreeable way from the point of view of the support programmer – who has a much more
difficult job to do than the original author. The layout must be neat, clean and consistent,
and there must be liberal commenting, both at the start of each module and within the
code.
The comments, which should in general precede the code they describe:
- must accurately reflect the behaviour of the program;
- must be detailed without merely stating the obvious;
- must not be cryptic – ‘clues’ are not enough;
- must be in English, without spelling or grammatical errors;
- must not contain attempts at humour, meretricious phraseology, catchwords, superfluous
pleasantries, private jargon and clever abbreviations.
Modifications must blend in !!! 56
When a program is changed, the modifications must be
‘invisibly mended’ into the coding; scars are not permitted. The original style and conventions of the
program must be preserved – which will be much easier and more palatable if the program conformed
to the Starlink standard in the first place.
There should be no need for elaborate and unsightly ‘revision-flag’ schemes except, perhaps, during
debugging or where software that runs on more than one machine has machine specific
inclusions.
Fix bad code !!! 57
Bad code must be rewritten, not merely commented.
Use ‘:’ as the continuation character ! 58
Only one continuation character should be used,
preferably ‘:’. (If you do choose something else, remember it should be in the Fortran 77 character set.
The dollar sign is a popular choice because it has no syntactical function in ANSI Fortran outside a
character string.
Using 1,2,3 … for successive lines is specifically discouraged as it leads to annoying editing problems
(and, after all, protection against shuffling is no more necessary than for any other region of the
program).
Lines longer than 72 characters are not allowed !!! 59
Program lines (including comments) must not
be longer than the legal 72 character maximum (even though compiler options such as
/EXTEND_SOURCE on VAX/VMS can override this maximum). A lengthy statement (that for some
reason cannot be broken up into several shorter statements) should be split at natural breakpoints and
the pieces neatly aligned. Statements must not be split between lines simply by exploiting the break at
column 72. Take care with character constants, where this can easily happen inadvertently – especially
inside format specifications.
Use spaces to improve readability. 60
Spaces should be used freely within Fortran statements to
make them easier to read. A space before and after the equals sign in an assignment statement is
particularly recommended.
Use indenting to show structure !!! 61
It is essential that the structure of a program be reflected in a
consistent and pleasing indentation scheme.
A suggested scheme is as follows. The normal starting columns for comments and code should be 5
and 7 respectively. For each block between a DO and END DO, or between IF, ELSE IF, ELSE and
END IF, both comments and code should be indented a further 3 columns. Blank lines should be used
freely to improve presentation further.
This scheme is used in the following example. This is, of course, only one acceptable layout, and tastes
vary.
* Reset bad pixel count
NBLEM = 0
* Look at all pixels except edge
DO IY = 2, NY-1
DO IX = 2, NX-1
* Reset blemish flag
IBLEM = 0
* Pick up pixel
PXV = A(IX,IY)
* Expected value = mean of surrounding eight
S = 0.0
DO J = IY-1, IY+1
DO I = IX-1, IX+1
S = S+A(I,J)
END DO
END DO
EV = (S-PXV)/8.0
* ’Blemish’ criterion
BLEM = SIGMAS*SQRT(ABS(EV))
* Decide whether in star or not
IF (EV.GT.STAR) THEN
* In star
IF (PXV.LT.EV/4.0-BLEM) IBLEM=1
IF (PXV.GT.4.0*EV+BLEM) IBLEM=2
ELSE
* Not in star
D = PXV-EV
IF (D.LT.-BLEM) IBLEM=3
IF (D.GT.BLEM) IBLEM=4
END IF
* Override if negative or small
IF (PXV.LT.DIM) IBLEM=0
IF (PXV.LT.0.0) IBLEM=5
* If blemish, fix and report
IF (IBLEM.NE.0) THEN
B(IX,IY) = EV
NBLEM = NBLEM+1
WRITE (LINE,’(’’Blemish at (’’,’ //
: ’I4,’’,’’,I4,’’)’’,’ //
: ’G16.4,’’ changed to’’,’ //
: ’G16.4)’) IX-1,IY-1,PXV,EV
CALL WRUSER(LINE,JSTAT)
END IF
END DO
END DO
* Final report
WRITE (LINE,’(I6,’’ blemishes removed’’)’) NBLEM
Put FORMAT statements inline ! 62
FORMAT statements should be inline (following
the appropriate READs or WRITEs) rather than, for example, massed at the end of the
program. When a given format specification is required once only it can be incorporated
into the READ or WRITE itself as a character constant, unless the result is less clear (for
example because of multiple apostrophes). When using this technique, be sure the constant
doesn’t continue through multiple lines (see rule 59, and the example in the previous
rule).