@@
Chapter II.  Programming Language and Style


     The magnitude of the AIPS project and the desire to achieve
portability of the software require a high degree of standardization in
the programming language and style.  One must code in a language which
can be compiled on all machines.  One must follow strict rules in
statement ordering and location so that simple preprocessors may, when
necessary, locate and modify the standard code.  Everyone must type
code in the same way so that all programmers will be able to read it
with as little effort and confusion as possible.  All experienced pro-
grammers develop a personal typing style which they prefer.  To them,
the rules given in this chapter may seem arbitrary, capricious, and
unworkable.  Nonetheless, they are the rules to be followed when coding
for the AIPS system.  Routines which do not meet these standards will
not be accepted.  This project is too important and too large to allow
compromise at this level.  Also, we have found these rules to be fairly
comfortable - after we got used to them.

     The programming language will be ANSI standard FORTRAN 66, except
for the addition of INCLUDE, ENCODE, and DECODE statements and the use
of a minimum number of local assembly language in Z routines when
absolutely required.  I cannot review the entire language here, but I
urge programmers to reread a basic reference.  (Do not read your local
FORTRAN IV PLUS or FORTRAN 77 manual.  Use a fundamental reference such
as IBM's Fortran Language manual.)  In particular, I remind programmers
that the names of commons, variables, functions, and subroutines must
begin with a letter and contain no more than six (6) characters.  In
AIPS, program names may have no more than five characters because of
the need to append the value of NPOPS.  Comments are introduced by
placing the capital letter C in column 1 of the card.  No in-line
comments are allowed.  Continuation statements are formed by placing a
non-blank character in column 6 of the card.  In AIPS, this character
shall be an asterisk (*).  There may be no more than 19 continuations
of a single statement.  Only card columns 1 - 72 are used, even in
comments.  Executable statements at the first level of indentation
begin in column 7.  TAB characters must not be left in the code after
it is typed and editted.  The three non-standard statements have the
forms:

  (1)  INCLUDE ' <name> '
     where INCLUDE begins in column 7, the first single quote is in
     column 15, the <name> is a left justified character string of no
     more than 8 characters, and the second single quote follows <name>
     with no blanks.  The conventions for <name> will be described
     later.  The statement causes the file called <name> to be inserted
     in the routine in place of the INCLUDE statement.

  (2)  ENCODE ( <nchar> , <format> , <array> )   <list>
     where <nchar> is the total number of characters to be encoded,
     <format> is the format number, <array> is the variable into which
     the data are to be encoded, and <list> is an optional list of the
     variables whose values are to be encoded.  The value of <nchar>
     may exceed the actual number of characters to be encoded, but may
     not exceed the number of characters which will fit in <array>.
     ENCODE performs a formatted write into memory.
  (3)  DECODE ( <nchar> , <format> , <array> )   <list>
     where <nchar> is the total number of characters to be decoded,
     <format> is the format number, <array> is the variable from which
     the data are to be decoded, and <list> is the list of variables to
     receive the decoded values.  DECODE performs a formatted read
     from memory.

     Statements must be ordered as follows.  The PROGRAM, FUNCTION, or
SUBROUTINE statement must occupy the first line and must begin in
column 7.  Then come the prologue comments, the body of the program,
the format statements, and the END statement.  Each of these segments
will be separated by a comment delimiter line (i.e. C followed by 71
or so minus signs).  The last line of the body of the routine must have
the statement number 999 and be a STOP (for programs) or RETURN (for
functions and subroutines) statement.  There must be no other STOP or
RETURN statement in the routine.

     Many computer systems allow declaration statements to occur in
almost any order.  However, some of the simpler compilers do not.
Therefore, in AIPS, we will use the following order:

  (1) Data type and dimension statements: INTEGER*2, LOGICAL*2, REAL*4,
      and REAL*8 in any order.  We prohibit DIMENSION, INTEGER, REAL,
      DOUBLE PRECISION, INTEGER*3, INTEGER*4, LOGICAL*1, LOGICAL*4,
      REAL*6, and CHARACTER statements and any use of these statements
      for data initialization.  COMPLEX*8 and COMPLEX*16 are allowed.

  (2) Common statements: COMMON.  We prohibit unlabeled common and use
      of the COMMON statement to give the types and dimensions of
      variables.

  (3) Equivalence statements: EQUIVALENCE.

  (4) Data initialization statements: DATA.  We prohibit the use of
      DATA statements to initialize variables in commons.  Character
      data must be typed correctly.  Thus, although
           INTEGER*2  IC(2)
           DATA  IC /'IAMC'/
      will work on many computers, we prohibit it.  The use of octal
      and hexadecimal numbers in data statements is strongly
      discouraged.

  (5) Function definitions.

Of course, these rules may be bent when necessary, but only in Z
routines.  INCLUDE statements are used in AIPS primarily to provide a
fixed and uniform set of declarations for commons and data structures.
The naming conventions for such INCLUDEs is 'accc.INC' , where 'a' is
D, C, E, and V for the above types 1, 2, 3, and 4, respectively and
'ccc' is a one to three character name for the INCLUDE.  Since the
statement order is fixed, an include text file may contain statements
of only one of the above types.  For example,

            INCLUDE 'DBWT.INC'
            INCLUDE 'CBWT.INC'
causes the text
      C                                       Include DBWT
            INTEGER*2 BWTLUN,BWTIND,BWTREC,BWTDAT(256)
            LOGICAL*2 WASERR
      C                                       End DBWT
      C                                       Include CBWT
            COMMON /BWTCH/ BWTLUN,BWTIND,BWTREC,WASERR,BWTDAT
      C                                       End CBWT
to be inserted.  All declaration statements must begin in column 7.

     The programmer is urged to declare every variable in the routine.
This will avoid any problems with the various default data types in
various computer systems.  Of particular importance, in this regard,
are those variables and constants which appear in CALL statements.
Using the example of the subroutine COPY given below, the statement
                CALL COPY (2, KF, KT)
will work on some machines, but will not work on computers which
default to INTEGER*4 with an address which points to the high-order
byte.  The right way to code this is
                INTEGER*2  KF(n), KT(n), N2
                ...
                DATA  N2 / 2 /
                ...
                CALL COPY (N2, KF, KT)

     The main point of this exercise is to make routines comprehensible
to programmers who read them.  Comment statements are the most powerful
tool for this purpose.  "Prologue" comments are placed immediately
following the PROGRAM, SUBROUTINE, or FUNCTION statement.  These
comments explain the purpose and methods of the routine, the input and
output arguments, any use of variables in commons, and any special
coding techniques or limitations in the transportability of the routine.
Prologue comments do not need to be verbose, but they must explain most
things which a programmer must know about calling the routine.
Routines must have acceptable prologue comments before they will be
accepted into the AIPS system.  As an indication of their importance,
Volume III of this manual is simply a listing of the prologue comments
for all routines in the AIPS system.  As a simple example, which is
typed the way I like, consider

             SUBROUTINE COPY (N, KFROM, KTO)
       C----------------------------------------------------------
       C   COPY copies integer words from one array to another
       C   Inputs:  N      I*2     number of words to be copied
       C            KFROM  I*2(N)  source array
       C   Outputs: KTO    I*2(N)  destination array
       C----------------------------------------------------------
             INTEGER*2  N, KFROM(1), KTO(1)
       C----------------------------------------------------------
       C                                        no copy: N <= 0
             IF (N.LE.0) GO TO 999
                DO 10 I = 1,N
                   KTO(I) = KFROM(I)
        10         CONTINUE
       C
        999  RETURN
             END

     "Body" comments are placed at strategic locations throughout the
body of the code.  They act as sign posts to alert the reader to each
logical block of code and also to clarify any difficult portions.
Ideal places for body comments are prior to DO loops and IF clauses.
Body comments within a routine must all begin in the same column and
that column should be near column 41.  Body comments (and prologue
comments) should be typed in lower case letters.  This helps to sepa-
rate visually the comments from the program text (which must be all in
upper case!!!).

     Another powerful tool to illustrate to the reader the logical
structure of a routine is indentation.  By indenting statements to
indicate that they belong together, one can enhance greatly the reada-
bility of one's programs.  Each step of indentation shall be three (3)
spaces, beginning in column 7.  Numbered CONTINUE statements should be
employed to enhance the indentation pattern.  DO loops and IF clauses
are prime candidates for indentation.  As an example, consider

C                                        Multiply by transform matrix
      DO 10 I = 1,3
         VEC(I) = 0.0
         DO 10 J = 1,3
            VEC(I) = VEC(I) + TMATX(I,J)*VEC0(J)
 10         CONTINUE
C                                        Unit vector to polar
C                                        Case at pole
      IF ((X.NE.0.0) .OR. (Y.NE.0.0)) GO TO 20
         ALPHA = 0.0
         DELTA = 0.0
         GO TO 30
 20   CONTINUE
         ALPHA = ATAN2 (X, Y)
         DELTA = SQRT (X*X + Y*Y)
 30   PDIST = ATAN2 (Z, DELTA)
C                                        Swap to increasing order
      IF (A.LT.B) GO TO 40
         C = A
         A = B
         B = C
 40      CONTINUE
      Z = Z ** (B-A)

Note that all DO loops end with CONTINUE statements rather than some
executable statement.  This enhances legibility as well as preventing
compilation errors on those statements which are not allowed, by some
compilers, to be the last statement in a DO loop.

     The use of GO TO statements is the cause of most logic errors in
programming.  Unfortunately, FORTRAN offers us no alternative.  However
with the use of standard indentation and statement numbering schemes,
errors can be reduced and readability enhanced.  Statement numbers must
increase through the routine and should be integer multiples of 5 or
10.  They should not exceed 999.  Format numbers should have 4 digits
with the low order 3 giving the nearest preceding statement number to
the first statement using that format.  All statement numbers are left
justified beginning in column 2.

     Statement numbers can help to clarify the logical structure of a
routine.  Let us consider the common example of a routine which begins
with some setup operations (e.g. file opening), then does operation set
A or B or C or D, and then does some close down operations (e.g. file
closing) before returning.  Where possible, such a routine should use
statement numbers 5 - 95 for the setup, 100 - 195 for set A, 200 - 295
for set B, 300 - 395 for set C, 400 - 495 for set D, and 900 - 995 for
the close down.

     Blank spaces can improve the readability of the routine as can
parentheses.  Blanks should surround equals signs and separate multiple
word statements.  Parentheses are a great help in compound logical
expressions.  For example,
               A = B
               DO 10 I = 1,10
               GO TO 999
               CALL KPACK (IX,IY)
               IF ((A.GT.B) .AND. (C.LE.D)) GO TO 20

     Modularity  in program design is a very important asset for many
reasons.  Complicated tasks become clearer, to coder and reader alike,
when constructed from a logical sequence of smaller operations
performed by subroutine call.  Such well-ordered tasks are far easier
to design, to understand, and to make work correctly than vast mono-
lithic single programs.  Furthermore, the small operation subroutines
will often turn out to be fairly general and useful to many other tasks
as well.  Programmers will have to remember that their tasks will have
to run not only in the "unlimited" address space of 32-bit virtual
computers, but also in the very limited address space of 16-bit compu-
ters.  The task should be designed in a modular way to allow it to be
overlayed on the "smaller" machines.

     The code of AIPS is intended to achieve a very high degree of
portability between computers.  Programmers for the system must be
aware of this requirement and avoid the easy assumptions about such
matters as word and character lengths.  The basic common /DCHCOM/
contains parameters giving the number of bits/word, words/floating
point, words/double precision floating point, and characters/floating
point.  These must be used, rather than simple equivalence statements,
when dealing with "data structures" (arrays containing a mixture of
integer, character, and floating point variables).  One may use DATA
statements to assign two characters to an integer and four characters
to a real and then use formats A2 and A4, respectively, to print them.
However, one cannot regard these variables as being fully packed with
characters.  The technique one must use to handle data structures, such
as the map catalog data block described later in this manual, goes as
follows:  One equivalences integer, real, and double precision arrays
to the full structure.  Then one computes, using the parameters in
/DCHCOM/, the subscripts needed with the three types of arrays to
extract the desired quantities.  The routine VHDRIN performs this
computation for catalog blocks, storing its results in the common
/HDRCOM/.  Programmers will find this routine instructive.  There are
a wide variety of service routines to manipulate characers and to
compute addresses.  Consult the lists at the end of this volume to
find out what is available.

     All of the things mentioned in this chapter should be used in
moderation.  One can bury good code in a plethora of inane comments.
One can inundate statements with parentheses or spread them out with
blanks until they are no longer legible.  Vastly elaborate indentation
and numbering schemes can confuse rather than aid the reader.  The
creation of large numbers of very short, special purpose subroutines
will overburden linkage editors and AIPS's bookkeeping schemes.  (In
this regard, AIPS already contains a wide range of useful utility
subroutines.  Programmers should consult the lists given at the back of
this volume before creating additional subroutines.)  Basically,
programmers should use good common sense in applying the standards
described in this chapter.
