^PY^-
^IOP^IL0600^IS404^IC1000^IJ00700^IT00700^PN^-


D. LISTINGS OF THE AIPS INSTALLATION AND PROGRAMMING SHELL SCRIPTS
 
   The following listings of the shell scripts used in the installation
and programming of AIPS under UNIX are by no means considered finished.
You may find it necessary to modify them to suit your programming
environment.  If you make modifications that you feel could benefit the
general UNIX/AIPS community, please send us your changes or suggestions.
A listing with notes will suffice, but a tar tape would also be nice.
 
 
1.  ILOAD

: set -x

: "This is the first step of the installation procedure for AIPS under"
: "UNIX.  It must be run from the directory $HOME/xxx/UNIX where it"
: "resides."

   cc ILOAD.c

   a.out

: set -


2.  MAKSRC

: "A procedure to generate the file $UNIX/SOURCE containing the full"
: "pathname of all the source code pertinent to a given implementation"
: "of AIPS under UNIX.  It can be run from any AIPS account directory."

: "Get the $POPS source code."

find $AIPPGM \( -name '*.FOR' -o -name '*.c' \) -print >  $UNIX/SOURCE.TMP
find $AIPSUB \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $AIPZ   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
ZPGM=$POPS/ZPGM/UNIX/LOC
if test -d $ZPGM
then
find $ZPGM   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
fi

: "Get the $APL source code."

find $APLAPG \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $APLPGM \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $APLSUB \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $APLY   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $APLZ   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
ZPGM=$APL/ZPGM/UNIX/LOC
if test -d $ZPGM
then
find $ZPGM   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
fi

: "Get the $NOTST source code."

find $NOTAPG \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $NOTPGM \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $NOTSUB \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $NOTZ   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
ZPGM=$NOTST/ZPGM/UNIX/LOC
if test -d $ZPGM
then
find $ZPGM   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
fi

: "Get the $PSAP source code."

find $SAPSUB \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $SAPZ   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
ZPGM=$PSAP/ZPGM/UNIX/LOC
if test -d $ZPGM
then
find $ZPGM   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
fi

: "Get the $AP source code if $AP != $PSAP."

if test "$AP" != "$PSAP."
then
find $APSUB  \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $APZ    \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
fi

: "Get the $LOCAL source code."

find $SAPSUB \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP
find $LOCAL/APGM \( -name '*.FOR' -o -name '*.c' \) -print >> \
   $UNIX/SOURCE.TMP
find $LOCAL/PGM  \( -name '*.FOR' -o -name '*.c' \) -print >> \
   $UNIX/SOURCE.TMP
find $LOCAL/SUB  \( -name '*.FOR' -o -name '*.c' \) -print >> \
   $UNIX/SOURCE.TMP

: "Get the $UNIX source code (if any)."

find $UNIX   \( -name '*.FOR' -o -name '*.c' \) -print >> $UNIX/SOURCE.TMP

chmod +w $UNIX/SOURCE
sed -n -f MAKSRC.SED $UNIX/SOURCE.TMP > $UNIX/SOURCE
rm $UNIX/SOURCE.TMP
chmod -w $UNIX/SOURCE


3.  CRLIBS

: "Command procedure for doing the mass compilation of AIPS subrotines."
: "This procedure should be executed only AFTER executing ILOAD as well"
: "as filling the 'local' (e.g., $APLZ) Z-routine directories with the"
: "appropriate code (i.e., 'generic' or system specific)."

: "Command sequence: CRLIBS (can be run from any directory)"
: "Calls:  CRLIB"

: "Only one CRLIBS/CRLIB should be running at a time.  Check to see"
: "if CRLIB.RUN exists at any of the major nodes $APL, $POPS, $NOTST,"
: "$PSAP or $AP.  If so, CRLIBS/CRLIB is already running.  Tell the"
: "user and exit."

NODE=""

if   test -f $APL/CRLIB.RUN  ;  then NODE='$APL'   ;
elif test -f $POPS/CRLIB.RUN ;  then NODE='$POPS'  ;
elif test -f $NOTST/CRLIB.RUN;  then NODE='$NOTST' ;
elif test -f $PSAP/CRLIB.RUN ;  then NODE='$PSAP'  ;
elif test -f $AP/CRLIB.RUN   ;  then NODE='$AP'    ;
fi

if test "$NODE" != ""
then
   echo 'CRLIB is already running on major node $NODE !!!'
   exit
fi

cd $APLSUB
   CRLIB $APL < $UNIX/APLSUB.LIS

cd $APLY
   CRLIB $APL < $UNIX/APLY.LIS

cd $APLZ
   CRLIB $APL < $UNIX/APLZ.LIS

cd $APL
   ar cr SUBLIBU `lorder *.o | tsort`

cd $AIPSUB
   CRLIB $POPS < $UNIX/AIPSUB.LIS

cd $AIPZ
   CRLIB $POPS < $UNIX/AIPZ.LIS

cd $POPS
   ar cr SUBLIBU `lorder *.o | tsort`

cd $NOTSUB
   CRLIB $NOTST < $UNIX/NOTSUB.LIS

cd $NOTZ
   CRLIB $NOTST < $UNIX/NOTZ.LIS

cd $NOTST
   ar cr SUBLIBU `lorder *.o | tsort`

cd $SAPSUB
   CRLIB $PSAP < $UNIX/SAPSUB.LIS

cd $SAPZ
   CRLIB $PSAP < $UNIX/SAPZ.LIS

cd $PSAP
   ar cr SUBLIBU `lorder *.o | tsort`

if test "$AP" != "$PSAP"
then
   cd $APSUB
      CRLIB $AP < $UNIX/APSUB.LIS

   cd $APZ
      CRLIB $AP < $UNIX/APZ.LIS

   cd $AP
      ar cr SUBLIBU `lorder *.o | tsort`
fi

echo "CRLIBS is finished!!!"


4.  CRLIB

: set -x

: "AIPS list driven subroutine compilation procedure (normally run"
: "under the control of CRLIBS)."

: "Command sequence: CRLIB node < file (where file is a list of routine"
: "                                     names without .F or .c extension)"

: "Where 'file' contains a list of source code files to be compiled"
: "and 'node' is where the resulting .o file should be move for"
: "archiving later."

NODE=$1

if test -f $NODE/CRLIB.RUN
then
   echo "CRLIB is already running on major node $NODE!!!"
   echo "*** ABORT ***"
   exit
else
   echo "" > $NODE/CRLIB.RUN
   trap 'rm $NODE/CRLIB.RUN; exit' 1 2 3 15
fi

: "Get 'pwd' for UTS GETBASE/PUTBASE.  If this is not UTS, this command"
: "can be commented out or deleted."

DIR=`pwd`

echo `date` | tee -a $NODE/CRLIB.LOG >> $NODE/CRLIB.ERR
echo "--- Begin CRLIB for "`pwd`" ---" | \
   tee -a $NODE/CRLIB.LOG >> $NODE/CRLIB.ERR

: "********************************************************************"
: "*                                                                  *"
: "*                     --- COMPILER OPTIONS ---                     *"
: "*                                                                  *"
: "********************************************************************"

: "Set compiler options.  These will undoubtably be different from"
: "UNIX to UNIX.  The installer should think about these carefully."
: "In general, we recommend avoiding turning on optimization for f77"
: "(we don't even trust the VMS optimizer) but it should be okay for"
: "cc.  The only one on which AIPS relies is the I2 (or i2) option."
: "This option forces all integer constants, integers declared INTEGER"
: "and variables that are implicitly INTEGER by the normal rules of"
: "Fortran to be 2-byte items.  This is the desired case in all but a"
: "very small fraction of AIPS.  With the I2 option selected, the only"
: "4-byte integers are those explicitly declared as such (e.g.,"
: "INTEGER*4).  Some UNIX compilers also support LOGICAL's that have a"
: "length something other than the ANSI standard of one numeric storage"
: "unit (4 bytes on most machines).  With the 'I2' option selected, some"
: "systems even make it a syntax error to explicitly declare LOGICAL"
: "variables as-4 byte items (e.g., LOGICAL*4).  This is very curious"
: "since they don't enforce the same restriction on INTEGER variables"
: "(once you've introduced INTEGER*2, the issue is muddied anyway)."
: "This also complicates some Z-routines written in C since some"
: "UNIX compilers DON'T support 2 byte LOGICAL's and in several cases,"
: "AIPS passes LOGICAL's as arguments to these routines.  This interface"
: "problem is solved by mapping the values of LOGICAL's to INTEGER*2"
: "variables (0 = .FALSE. and 1 = .TRUE.) and passing these as arguments"
: "instead.  Since this involves only lower level Z-routines, this"
: "mapping of LOGICAL's to INTEGER's is confined entirely within Z-code"
: "(i.e., the machine independent code is not involved)."

: "Examples:"

: "=============================== UTS ================================"

: "Compiler options:"

F77="-w -I2 -c"
CC="-w -O -c"

: "where -w ==> suppress warning messages."
: "     -I2 ==> variables that normally default to 4-byte integers"
: "             default instead to 2-byte integers (applies to integer"
: "             constants as well;  AIPS depends heavily on this)."
: "      -c ==> suppress loading phase and force object file to be"
: "             formed from source file."
: "      -O ==> optimize the output of the compiler (this is probably"
: "             okay for 'cc')."

: "=============================== UTS ================================"

: "============================ Masscomp =============================="
: "For Masscomp:"

: "Compiler options:"

: "F77= -w -I2 -c -Nn1001 -v"
: "CC=-w -O -c"

: "where -w ==> suppress warning messages."
: "             heavily on this)"
: "     -I2 ==> variables that normally default to 4-byte integers"
: "             default instead to 2-byte integers (applies to integer"
: "             constants as well;  AIPS depends heavily on this)."
: "      -c ==> suppress loading phase and force object file to be"
: "             formed from source file."
: " -Nn1001 ==> increase maximum number of unique identifiers in a"
: "             single program unit to 1001 (default is 401;  any value"
: "             should be an odd integer;  1001 may be overkill)."
: "      -v ==> print a phase-by-phase progress report during"
: "             compilation/loading."
: "      -O ==> optimize the output of the compiler (this is probably"
: "             okay for 'cc')."

: "============================ Masscomp =============================="

: "Read source file list until end or null file name encountered."

while read i
do
   if test "$i" = "" ; then break ; fi
   echo "==============================================================" \
      | tee -a $NODE/CRLIB.LOG >> $NODE/CRLIB.ERR

: "If this $i is Fortran source code, preprocess it via PP and"
: "compile via f77"

   if test -f $i.FOR
   then

:    "Preprocess file $i.FOR into file $i.F using 'sed' scripts found"
:    "in directory $VER/UNIX and 'm4'."

      PP $i 2>> $NODE/CRLIB.ERR

:    "Compile $i.F storing errors in file $NODE/CRLIB.ERR"

      echo `date` "f77 $F77 $i.F" | tee -a $NODE/CRLIB.LOG >> \
                                           $NODE/CRLIB.ERR

:    "If UTS, get base registers from history file $UNIX/BASEREGS.  If"
:    "this is not UTS, comment out or delete this command."

      F77="$F77 `GETBASE $i $DIR`"

      if f77 $F77 $i.F 1>> $NODE/CRLIB.LOG 2>> $i.ERR
      then

:       "If UTS, check $i.ERR for base register messages from f77 and"
:       "store in history file $UNIX/BASEREGS.  If this is not UTS,"
:       "comment out or delete this command."

         PUTBASE $i $DIR CRLIB >> $NODE/CRLIB.LOG

:       "Append $i.ERR to $NODE/CRLIB.ERR"

         cat $i.ERR >> $NODE/CRLIB.ERR

:       "Delete $i.ERR"

         rm $i.ERR

:       "Move $i.o to $NODE"

         mv $i.o $NODE

:       "Remove $i.F"

         rm $i.F

         echo "Successfully compiled and $i.o moved to $NODE" >> \
            $NODE/CRLIB.LOG
         echo "No fatal compiler errors" >> $NODE/CRLIB.ERR

      else

:       "Append $i.ERR to $NODE/CRLIB.ERR"

         cat $i.ERR >> $NODE/CRLIB.ERR

         echo "*** Fatal compiler error(s)! ***" >> $NODE/CRLIB.LOG
         echo "Examine $NODE/CRLIB.ERR or $i.ERR and $i.F" \
            >> $NODE/CRLIB.LOG
      fi

: "Otherwise if this $i is C source code, compile via cc"

   elif test -f $i.c
   then

:    "Compile $i.c storing errors in file $NODE/CRLIB.ERR"

      echo `date` "cc $CC $i.c" | tee -a $NODE/CRLIB.LOG >> \
                                         $NODE/CRLIB.ERR

      if cc $CC $i.c 1>> $NODE/CRLIB.LOG 2>> $NODE/CRLIB.ERR
      then

:       "Move $i.o to $NODE"

         mv $i.o $NODE

         echo "Compiled successfully and $i.o moved to $NODE" >> \
            $NODE/CRLIB.LOG
         echo "No fatal compiler errors!" >> $NODE/CRLIB.ERR

      else
         echo "*** Fatal compiler error(s)! ***" >> $NODE/CRLIB.LOG
         echo "Examine $NODE/CRLIB.ERR and $i.c" >> $NODE/CRLIB.LOG
      fi

   fi

done

rm $NODE/CRLIB.RUN

echo "==============================================================" \
   | tee -a $NODE/CRLIB.LOG >> $NODE/CRLIB.ERR
echo `date` | tee -a $NODE/CRLIB.LOG >> $NODE/CRLIB.ERR
echo "--- End CRLIB for   "`pwd`" ---" | \
   tee -a $NODE/CRLIB.LOG >> $NODE/CRLIB.ERR

: set -


5.  PP

   This script serves as the preprocessor for all the AIPS Fortran source
code.  Fortran files have names of the form *.FOR and are maintained in
the unpreprocessed for (i.e., just as are under VMS).  As you can see,
PP pipes the text of the *.FOR files through a sequence of "sed" and "m4"
executions.  Sed is used to perform text tranformations and m4 is used to
insert the required "included" text where necessary.  The included text
is always found in the files stored in the directory $INCS.  When piping
the text through m4, it will occasionally report 'shift not implemented
yet'.  Documentation on m4 does not explain this message, however our
experience is that it's a spurious message that can be ignored.  The output
of PP is a file with the name of the form *.F which can then used as the
source file argument to "f77".  The sed scripts used by PP are also
listed below.  A great deal of care has gone into the design of these
scripts to insure that they will work for most UNIX systems although
it is possible that they may require modification.  Mostly they transform
VAXisms into ANSI standard Fortran.  If you suspect that they need to be
modified for your system, it would be wise to consult with us first.

PP :

: set -x

: "Preprocessor for Fortran source code.  AIPS code is exported in the"
: "same form that it is found under VMS in Charlottesville (i.e., the"
: "*.FOR files).  PP transforms this code into something suitable for"
: "UNIX 'f77' compilation using 'sed' and 'm4'.  The sed scripts should"
: "not require any modification and are known to work for all cases in"
: "the 15JUL84 release of AIPS.  The only known change is in regard to"
: "Masscomp installations with version 2.1A compilers where all I/O"
: "parameters must be 4-byte items (or constants).  This means that"
: "INTFIL.SED should declare IOSERR as INTEGER*4 (see INTFIL.SED.MC)."

if test -f $1.FOR
then
   sed -f $UNIX/INC.SED $1.FOR | \
   (cd $INCS; m4) | \
   sed -f $UNIX/DCL.SED | \
   sed -f $UNIX/INTFIL.SED | \
   sed -n -f $UNIX/NDCODE.SED > $1.F
else
   echo "PP: Can't find $1.FOR"
   echo "PP: ABORT!"
fi

INC.SED :

   Transforms text of the form "       INCLUDE 'INCS:filename'" into
include(filename) which can then be interpreted by the "m4" step of PP
to include the appropriate text file.  The text of INC.SED follows:

s/^^\([^^C] *INCLUDE *' *INCS *: *\)\([^^ ']*\)\(.*\)/include(\2)/

DCL.SED :

   Transforms nonstandard Fortran type declarations to ANSI standard form.
In addition, it will transform quoted backslashes (\) to quoted double
backslashes (\\).  This is necessary because UNIX Fortran compilers often
convert Fortran code into quasi C code and compile the result via a
special purpose C compiler (i.e., not cc).  This is how the "portable"
Fortran compiler was developed.  We have found that as a result of this,
the first backslash is interpreted as a metacharacter (i.e., to escape the
next character) and gets lost somehow.  For example, a 2 byte data item
intialized by the statement DATA item /'\ '/ has to be intialized by the
statement DATA /'\\ ' instead.  Strange but true, at least under all three
of NRAO's UNIX systems.  The text of DCL.SED follows:

s/^^\([^^C] *\)REAL\*4/\1REAL  /
s/^^\([^^C] *\)REAL\*8\(.*\)/\1DOUBLE PRECISION\
\ \ \ \ \ *\ \ \2/
s/^^\([^^C] *\)LOGICAL *\*./\1LOGICAL/
s/^^\([^^C] *\)\(.*'[^^\\]*\)\([\\][\\]*\)\([^^']*'\)/\1\2\3\3\4/g


INTFIL.SED :

   The purpose of this script is to insert the declaration of a 120 byte
CHARACTER variable called INTFIL and an INTEGER variable IOSERR at the
beginning of every program unit.  INTFIL is used as the internal file
variable for internal READs and WRITEs.  VMS AIPS code uses ENCODE and
DECODE statements which are not part of any ANSI standard for Fortran.
PP will transform these into equivalent internal READs and WRITEs via
the NDCODE.SED script.  IOSERR serves as the IOSTAT variable for these
I/O statements and is necessary for error branching.  The text of
INTFIL.SED follows:

s/^^[^^C] *PROGRAM /&/
s/^^[^^C] *SUBROUTINE /&/
s/^^[^^C] *FUNCTION /&/
s/^^[^^C] *INTEGER *FUNCTION /&/
s/^^\([^^C] *\)INTEGER\*2\( *FUNCTION \)/\1INTEGER\2/
s/^^\([^^C] *\)INTEGER\*4\( *FUNCTION \)/\1INTEGER\2/
s/^^[^^C] *REAL *FUNCTION /&/
s/^^[^^C] *DOUBLE *PRECISION *FUNCTION /&/
t more?
: quit
b
: more?
s/, *$/@/
t append
b insert
: append
N
b more?
:insert
a\
\ \ \ \ \ \ CHARACTER*120 INTFIL
a\
\ \ \ \ \ \ COMMON /UNXCOM/ INTFIL
a\
\ \ \ \ \ \ INTEGER*2 IOSERR
s/@/,/g
t quit


NDCODE.SED :

   This monstrous script is used to transform ENCODE statements into
equivalent internal WRITEs followed by a call ZCH2R4 which copies the
contents of the internal file variable (INTFIL) into the variable used
as the receiving argument of the orginal ENCODE statement.  This is
necessary because the receiving argument of the ENCODE statements are
almost always numeric arrays which are illegal as receiving arguments
in internal I/O statements.  Any error branch label appearing in the
original ENCODE statement as well IOSERR (the internal WRITE IOSTAT
variable) are also passed to ZCH2R4.  If IOSERR is non-zero, ZCH2R4
will perform an alternate return to the error branch label if it is
also non-zero.  In the case of DECODE statments, a call to ZR42CH is
first performed to copy the contents of the DECODE argument variable
to INTFIL and then an equvalent internal READ statment is constructed.
Where necessary, IF-THEN-ELSE constructs are also inserted to handle
IF ... ENCODE/DECODE statements.  The text of NDCODE.SED follows:

NOTE: Some of the lines of NDCODE.SED exceed 80 characters.  Where this
      occurs, the line has been split to fit the page of this document.
      Therefore, some newlines don't exist in the script as it is found
      in $UNIX.

: begin
s/^^[^^C][ 0-9]*.*ENCODE/&/
s/^^[^^C][ 0-9]*.*DECODE/&/
t ndcode
: quit
p
b
: ndcode
h
: more
n
s/^^[^^C]    [^^ ]/&/
t append
b xlate
: append
x
G
h
b more
:xlate
x
s/^^\(......\)\( *\)\(IF .*\)ENCODE/\1\2\3THEN\
\ \ \ \ \ \ \2\ \ \ ENCODE/
s/^^\(......\)\( *\)\(IF .*\)DECODE/\1\2\3THEN\
\ \ \ \ \ \ \2\ \ \ DECODE/
s/^^\(......\)\( *\)\(.*\)ENCODE *\n*[^^(]*(\( *[^^,]*\),\( *[^^,]*\),
\( *[A-Z][A-Z0-9]*([^^)][^^)]*)\)[^^0-9)]*\([0-9]*\)[^^)]*)\(.*\)/\1\2\3
WRITE(INTFIL,\5,IOSTAT=IOSERR)\
\ \ \ \ \ \*\2\ \ \8\
\ \ \ \ \ \ \2CALL ZCH2R4 (\4,INTFIL,IOSERR,\7,\6)/g
s/^^\(......\)\( *\)\(.*\)ENCODE *\n*[^^(]*(\( *[^^,]*\),\( *[^^,]*\),
\( *[A-Z][A-Z0-9]*\)[^^0-9)]*\([0-9]*\)[^^)]*)\(.*\)/\1\2\3WRITE(INTFIL,\5,
IOSTAT=IOSERR)\
\ \ \ \ \ \*\2\ \ \8\
\ \ \ \ \ \ \2CALL ZCH2R4 (\4,INTFIL,IOSERR,\7,\6)/g
s/^^\(......\)\( *\)\(.*\)DECODE *\n*[^^(]*(\( *[^^,]*\),\( *[^^,]*\),
\( *[A-Z][A-Z0-9]*([^^)][^^)]*)\)\([^^)]*\))\(.*\)/\1\2\3CALL ZR42CH
(\4, \6, INTFIL)\
\ \ \ \ \ \ \2READ(INTFIL,\5\7)\
\ \ \ \ \ \*\2\ \ \8/g
s/^^\(......\)\( *\)\(.*\)DECODE *\n*[^^(]*(\( *[^^,]*\),\( *[^^,]*\),
\( *[A-Z][A-Z0-9]*\)\([^^)]*\))\(.*\)/\1\2\3CALL ZR42CH (\4, \6, INTFIL)\
\ \ \ \ \ \ \2READ(INTFIL,\5\7)\
\ \ \ \ \ \*\2\ \ \8/g
s/IOSERR, *,/IOSERR,0,/g
s/\ \ \ \ \ \* *\n//g
t dummy
: dummy
s/.* IF /&/
t endif
p
g
b begin
: endif
s/.*/&\
\ \ \ \ \ \ \ \ \ ENDIF/
s/READ/   &/
s/\ \ \ \ \ \*/&   /
s/CALL ZCH2R4/   &/
p
g
t begin


6.  CREXES

: set -x

: "Command procedure for doing the mass compiles and linking of AIPS"
: "stand alone programs and AIPS tasks.  It should only be run after"
: "executing ILOAD and CRLIBS, if at all.  It is probably wiser to"
: "compile and link the programs via COMLNK on an individual basis"
: "until some faith in the subroutine libraries is developed.  CREXES"
: "is provided only for the optimistic, the naive or those with CPU"
: "time and disk space to burn."

: "Command sequence: CREXES (can be run from any directory)"
: "Calls:  CREXE"

: "Generate executable modules for stand alone programs in $AIPPGM."

   CREXE < $UNIX/AIPPGM.LIS

: "Generate executable modules for standard non-array processor tasks"
: "in $APLPGM."

   CREXE < $UNIX/APLPGM.LIS

: "Generate executable modules for standard array processor tasks in"
: "$APLAPG."

   CREXE < $UNIX/APLAPG.LIS

: "Generate executable modules for non-standard non-array processor"
: "tasks in $NOTPGM."

   CREXE < $UNIX/NOTPGM.LIS

: "Generate executable modules for non-standard array processor tasks"
: "in $NOTAPG."

   CREXE < $UNIX/NOTAPG.LIS

echo "CREXES is finished!!!"

: set -


7.  CREXE

: set -x

: "A list driven compile/link procedure.  Serves only as the driver for"
: "CREXES but could be abused in other ways with a little imagination."

while read i
do
   COMLNK $i > $i.LOG
done

: set -


8.  COMLNK

: set -x

: "Command sequence:  COMLNK $MAIN $OBJS where"
: "                      $MAIN  = source file name minus .FOR extension"
: "                      $OBJS  = optional object modules/libraries"

: "********************************************************************"
: "*                                                                  *"
: "*                 --- COMPILER/LOADER OPTIONS ---                  *"
: "*                                                                  *"
: "********************************************************************"

: "Setup compiler/loader options.  As in the case of CRLIB, the options"
: "required or desired here will vary from UNIX to UNIX.  In general,"
: "the options for compilation will be the same however, each UNIX"
: "system may have its peculiar options for the loader.  Consult your"
: "system documentation on the 'ld' command for these.  Some that you"
: "should probably consider are those that maximize the usefulness of"
: "your debugger, enable profiling or that link in special floating point"
: "hardware libraries.  UNIX tends to generate some rather large"
: "executable modules.  You may want to take advantage of some 'ld'"
: "options that strip or partially strip these modules (i.e., remove"
: "the symbol tables).  Some systems allow you to generate modules with"
: "shareable text segments (i.e., two executions of the same module"
: "require only one copy of the program instructions to be in memory)."
: "Again, you should probably avoid the optimizing option even if it"
: "has never failed you before (at least avoid it until the program"
: "works without it)."

: "Examples:"

: "=============================== UTS ================================"

: "Compiler options:"

F77="-w -I2 -c"

: "where -w ==> suppress warning messages."
: "     -I2 ==> variables that normally default to 4-byte integers"
: "             default instead to 2-byte integers (applies to integer"
: "             constants as well;  AIPS depends heavily on this)."
: "      -c ==> suppress loading phase and force object file to be"
: "             formed from source file."

: "Loader options:"

LD="-n -x"

: "where -n ==> generate shareable text segment."
: "      -x ==> strip all but external symbols from the symbol table."

: "=============================== UTS ================================"

: "============================ Masscomp =============================="
: "For Masscomp:"

: "Compiler options:"

: "F77= -w -I2 -c -Nn1001 -v"

: "where -w ==> suppress warning messages."
: "             heavily on this)"
: "     -I2 ==> variables that normally default to 4-byte integers"
: "             default instead to 2-byte integers (applies to integer"
: "             constants as well;  AIPS depends heavily on this)."
: "      -c ==> suppress loading phase and force object file to be"
: "             formed from source file."
: " -Nn1001 ==> increase maximum number of unique identifiers in a"
: "             single program unit to 1001 (default is 401;  any value"
: "             should be an odd integer;  1001 may be overkill)."
: "      -v ==> print a phase-by-phase progress report during"
: "             compilation/loading."

: "Loader options:"

: "LD= -x"

: "where -x ==> strip all but external symbols from the symbol table."

: "============================ Masscomp =============================="

MAIN=$1
shift

: "Get user provided object modules/subroutine libraries, if any."

if test "$1" != ""
then
   OBJS=$1
   shift
   while test "$1" != ""
   do
      OBJS="$OBJS
              $1"
      shift
   done
fi

: "Locate source code for $MAIN.  If not found in current directory,"
: "look in $UNIX/SOURCE to find full pathname.  If not found in"
: "$UNIX/SOURCE, exit."

echo "COMLNK: `date`"
echo "        $MAIN compile/link begins."

PWD=`pwd`
DIR=$PWD

if test ! -f $DIR/$MAIN.FOR
then
   DIR=`WHERE $MAIN | sed -e 's/\/[^^\/]*\.FOR//'`
   if test "$DIR" = "=== $MAIN NOT FOUND! ==="
   then
      echo "COMLNK: `date`"
      echo "        $DIR"
      echo ""
      echo "        ABORT!"
      exit 1
   fi
fi

: "If UTS, get base registers from history file $UNIX/BASEREGS.  If"
: "this is not UTS, comment out or delete this command."

F77="$F77 `GETBASE $MAIN $DIR`"

: "Determine SUBLIBU's required ($APL/SUBLIBU at least)."

LIBS=$APL/SUBLIBU

: "Is this a POPS program, i.e., those found in $AIPPGM?"

if echo $DIR | fgrep $POPS > /dev/null;
   then LIBS="$POPS/SUBLIBU
              $LIBS"
fi

: "Standard or non-standard program, i.e., those found in $NOTPGM and"
: "$NOTAPG?"

if echo $DIR | fgrep $NOTST > /dev/null;
   then LIBS="$NOTST/SUBLIBU
              $LIBS"
fi

: "Array processor program, i.e., those found in $APLAPG, $NOTAPG or"
: "$LOCAL/APGM?  In the case where a real AP exists, $AP should not"
: "be equal to $PSAP and we must add real AP libraries to link $LIBS."
: "After linking with the real AP libraries, COMLNK sets AP to $PSAP"
: "and LOAD to $PSAP/LOAD and re-executes itself to generate the"
: "the pseudo array processor version.  If no real AP exists, $AP is"
: "always equal to $PSAP and array processor programs will only be"
: "COMLNK'ed once.  Also, where no AP exists, array processor executable"
: "modules are stored in $VER/LOAD."

if echo $DIR | fgrep APGM > /dev/null;
   then
   if test "$AP" != "$PSAP"
      then
        LIBS="$LIBS
              $AP/SUBLIBU"
        LIBS="$LIBS
              $APLIB"
      else
        LIBS="$LIBS
              $PSAP/SUBLIBU"
   fi
   else
   AP=$PSAP
fi

: "Local program, i.e., those found in $LOCAL/PGM or $LOCAL/APGM?"

if echo $DIR | fgrep LOCAL > /dev/null;
   then LIBS="$LOCAL/SUBLIBU
              $LIBS"
   LOAD=$LOCAL/LOAD
fi

: "Add special vendor provided TV device link library, if any."

if test "$TVLIB" != ""
   then LIBS="$LIBS
              $TVLIB"
fi

: "START with the newest.  If $MAIN.FOR is newer (newest) preprocess/"
: "compile/link.  If $MAIN.F exists and is newer than $MAIN.FOR as well"
: "as any $MAIN.o that might also exist, compile/link.  Otherwise, if"
: "$MAIN.o exists, is newer than $MAIN.FOR and $MAIN.F does not exist,"
: "or $MAIN.o coexists with a $MAIN.F that is newer than $MAIN.FOR,"
: "simply link.  However, if $MAIN.o coexists with a $MAIN.F that is"
: "older than $MAIN.FOR, preprocess/compile/link (i.e., you should never"
: "generate a $MAIN.o from an outdated $MAIN.F any more than you should"
: "generate a $MAIN.EXE from an outdated $MAIN.o)."

START=""
cd $DIR

if test -f $MAIN.F
then
   START=`find . \( -name $MAIN.FOR -newer $MAIN.F \) -print`
   if test "$START" = ""
   then
      if test -f $MAIN.o
      then
         START=`find . \( -name $MAIN.o -newer $MAIN.F \) -print`
         if test "$START" = ""
         then
            START=$MAIN.F
         else
            START=$MAIN.o
         fi
      else
         START=$MAIN.F
      fi
   else
      START=$MAIN.FOR
   fi
elif test -f $MAIN.o
then
   START=`find . \( -name $MAIN.FOR -newer $MAIN.o \) -print`
   if test "$START" = ""
   then
      START=$MAIN.o
   else
      START=$MAIN.FOR
   fi
else
   START=$MAIN.FOR
fi

cd $PWD

: "Initialize $DIR/$MAIN.ERR."

if test -f $DIR/$MAIN.ERR
then
   rm $DIR/$MAIN.ERR
fi

touch $DIR/$MAIN.ERR

: "If START = $MAIN.FOR, preprocess $MAIN.FOR into $MAIN.F"

if test "$START" = "$MAIN.FOR"
then
   trap 'rm $DIR/$MAIN.F; exit 1' 1 2 3 15
   echo "COMLNK: `date`"
   echo "        $DIR/$MAIN.FOR is newer than"
   echo "        $DIR/$MAIN.F (if it exists) and"
   echo "        $DIR/$MAIN.o (if it exists)."
   echo ""
   echo "        Preprocess $DIR/$MAIN.FOR"
   echo "        into       $DIR/$MAIN.F"
   echo "Preprocess $DIR/$MAIN.FOR" >> $DIR/$MAIN.ERR
   echo "into       $DIR/$MAIN.F" >> $DIR/$MAIN.ERR
   PP $DIR/$MAIN >> $DIR/$MAIN.ERR
   trap 1 2 3 15
elif test "$START" = "$MAIN.F"
then
   echo "COMLNK: `date`"
   echo "        $DIR/$MAIN.F exists and is newer than"
   echo "        $DIR/$MAIN.FOR and"
   echo "        $DIR/$MAIN.o (if it exists)."
   echo ""
   echo "        No need to preprocess, just compile/link!"
   echo ""
elif test "$START" = "$MAIN.o"
then
   echo "COMLNK: `date`"
   echo "        $DIR/$MAIN.o exists, is newer than"
   echo "        $DIR/$MAIN.FOR and"
   echo "        $DIR/$MAIN.F does not exist."
   echo ""
   echo "        or"
   echo ""
   echo "        $DIR/$MAIN.o exists and is newer than an extant"
   echo "        $DIR/$MAIN.F which is also newer than"
   echo "        $DIR/$MAIN.FOR"
   echo ""
   echo "        No need to compile, just link!"
   echo ""
fi

if test "$START" != "$MAIN.o"
then
   : "Compile $DIR/$MAIN.F."

   echo "COMLNK: `date`"
   echo "        Compile $DIR/$MAIN.F with options:"
   echo ""
   echo "           $F77"
   echo ""

   echo "Compile:  f77 $F77 $MAIN.F" >> $DIR/$MAIN.ERR
   echo "" >> $DIR/$MAIN.ERR

   trap 'rm -f $DIR/$MAIN.o; exit 1' 1 2 3 15

   if f77 $F77 $DIR/$MAIN.F 2>> $DIR/$MAIN.ERR
   then

: "Move $MAIN.o to $DIR."

   mv $MAIN.o $DIR

: "If UTS, check for base register messages from f77 and store in"
: "history file $UNIX/BASEREGS.  If this is not UTS, comment out or"
: "delete this command."

      PUTBASE $MAIN $DIR COMLNK

      trap 1 2 3 15

   else
      echo "COMLNK: `date`"
      echo "        $MAIN compile ends with fatal errors!"
      if test -f $MAIN.o
      then
         echo "COMLNK: `date`"
         echo "        Delete $MAIN.o"
         rm $MAIN.o
      fi
      echo "$DIR/$MAIN.ERR:"
      cat $DIR/$MAIN.ERR
      exit 1
   fi
fi

: "Link $DIR/$MAIN.o"

echo "COMLNK: `date`"
echo "        Link $DIR/$MAIN.o with ..."
echo ""
echo "           1) loader options:"
echo ""
echo "              $LD -o $DIR/$MAIN.EXE"
echo "Link:     f77 $LD -o $MAIN.EXE $MAIN.o \\" >> $DIR/$MAIN.ERR
echo ""
echo "           2) user specified object modules/subroutine libraries:"
echo ""
if test "$OBJS" = ""
then
   echo "              (none)"
else
   echo "              $OBJS"
   echo "              $OBJS" | sed -e 's/$/ \\/' >> $DIR/$MAIN.ERR
fi
echo ""
echo "           3) AIPS subroutine object libraries:"
echo ""
echo "              $LIBS"
echo "              $LIBS" | sed -e 's/$/ \\/' | sed -e '$s/ \\$//' \
   >> $DIR/$MAIN.ERR
echo ""
echo "" >> $DIR/$MAIN.ERR

trap 'rm $DIR/$MAIN.EXE; exit 1 ' 1 2 3 15

f77 $LD -o $DIR/$MAIN.EXE $DIR/$MAIN.o $OBJS $LIBS 2>> $DIR/$MAIN.ERR

trap 1 2 3 15

if test -x $DIR/$MAIN.EXE
then
   echo "COMLNK: `date`"
   echo "        Move $DIR/$MAIN.EXE"
   echo "        to   $LOAD/$MAIN.EXE"

   mv $DIR/$MAIN.EXE $LOAD/$MAIN.EXE

: "If this is a array processor program and there is a real AP (i.e.,"
: "$AP != $PSAP), relink $DIR/$MAIN.o with $APSUB and $APLIB."

   if test "$AP" = "$PSAP"
   then
      if test -f $DIR/$MAIN.F
      then
         echo "COMLNK: `date`"
         echo "        Delete $DIR/$MAIN.F"
         rm $DIR/$MAIN.F
      fi

      rm $DIR/$MAIN.ERR

      echo "COMLNK: `date`"
      echo "        $MAIN compile/link ends successfully!"
   fi
else
   echo "COMLNK: `date`"
   echo "        $MAIN compile/link ends with fatal errors!"
   echo ""

   echo "$DIR/$MAIN.ERR:"
   cat $DIR/$MAIN.ERR

   if test -f $DIR/$MAIN.EXE
   then
      echo ""
      echo "COMLNK: `date`"
      echo "        Delete $DIR/$MAIN.EXE"
      rm $DIR/$MAIN.EXE
   fi
fi

: "If we have just created a real AP module, set shell variables and"
: "re-execute this shell script such that pseudo AP version will be"
: "created."

if test "$AP" != "$PSAP"
then
   AP=$PSAP; export AP
   LOAD=$PSAP/LOAD; export LOAD
   echo "COMLNK: `date`"
   echo "        Relink $DIR/$MAIN.o with pseudo AP library"
   echo "        to create $LOAD/$MAIN.EXE"
   COMLNK $MAIN $OBJS
fi

: set -


9.  WATCH

: set -x

: "Shell procedure to monitor progress of procedure CRLIB while it is"
: "compiling subroutines into a library."

NODE=NONE

while test "$NODE" != ""
do

: "Determine node where CRLIB is running"

NODE=""

if   test -f $APL/CRLIB.RUN  ;  then NODE="$APL"  ;
elif test -f $POPS/CRLIB.RUN ;  then NODE="$POPS" ;
elif test -f $NOTST/CRLIB.RUN;  then NODE="$NOTST";
elif test -f $PSAP/CRLIB.RUN ;  then NODE="$PSAP" ;
elif test -f $AP/CRLIB.RUN   ;  then NODE="$AP"   ;
fi

if test "$NODE" = ""; then break; fi

until
   case $OS in
       UTS)  ascii ff
             ;;
       BSD1) clear
             ;;
       BSD2) clear
             ;;
       MC)   clear
             ;;
        *)
             ;;
   esac

   if test -f $NODE/CRLIB.LOG
   then
      echo \
      "**************************************************************"
      echo ""
      echo "$NODE/CRLIB.LOG :"
      tail -6 $NODE/CRLIB.LOG
   fi
   echo ""
   if test -f $NODE/CRLIB.ERR
   then
      echo "$NODE/CRLIB.ERR :"
      tail -8 $NODE/CRLIB.ERR
      echo ""
      echo \
      "**************************************************************"
   fi
   test ! -f $NODE/CRLIB.RUN
do
   sleep 30
done
done
echo "CRLIB is not running."

: set -
