3 GENERAL CODING STANDARD

 3.1 Language
 3.2 Design
 3.3 Quality
 3.4 Presentation

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:

IMPLICIT NONE encouraged

END DO permitted

DO WHILE permitted but worth avoiding

INCLUDE encouraged

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:

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:
      IF (X) 10,10,20

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:
      REAL A(512,512)

must be used, rather than:

      DIMENSION A(512,512)


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:
      X = REAL(N-1)

rather than:

      X = N-1

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:

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:
unused statement labels

unused declarations

unused FORMAT statements

unreachable code

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 ± 10±38 & 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:
      A = B+(DELTA1+DELTA2)


Validate inputs !!! 42
Everything coming into the program from outside must be validated.

There are only two exemptions permitted:


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:


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).