#!/bin/sh
#-----------------------------------------------------------------------
#;  Copyright (C) 1995, 1997-1999, 2003, 2009, 2020, 2024
#;  Associated Universities, Inc. Washington DC, USA.
#;
#;  This program is free software; you can redistribute it and/or
#;  modify it under the terms of the GNU General Public License as
#;  published by the Free Software Foundation; either version 2 of
#;  the License, or (at your option) any later version.
#;
#;  This program is distributed in the hope that it will be useful,
#;  but WITHOUT ANY WARRANTY; without even the implied warranty of
#;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#;  GNU General Public License for more details.
#;
#;  You should have received a copy of the GNU General Public
#;  License along with this program; if not, write to the Free
#;  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge,
#;  MA 02139, USA.
#;
#;  Correspondence concerning AIPS should be addressed as follows:
#;         Internet email: aipsmail@nrao.edu.
#;         Postal address: AIPS Project Office
#;                         National Radio Astronomy Observatory
#;                         520 Edgemont Road
#;                         Charlottesville, VA 22903-2475 USA
#-----------------------------------------------------------------------
# Usage: AILINK [directory-path/][@@]file[.o] [AIPS-sytle-options]
#             [UNIX-style-options] [file.OPT] [file.LOG]
#-----------------------------------------------------------------------
# Link a program and if appropriate, move binary to $AIPS_VERSION/LOAD.
# For files NOT in the $AIPS_VERSION tree, or *in* $APLCONTR, the move
# is suppressed.  If NOREPLACE is specified, it is suppressed too.
#
#  Inputs (can appear in any order):
#
#    1) [directory-path/][@@]program[.o]
#
#       Object module(s).  Current working directory assumed if the
#       directory-path is omitted.  If a '@@' is prepended to the
#       filename, it indicates a list file, one line per file.
#
#    2) [AIPS-style-options]
#
#       AIPS-style options.  The $SYSLOCAL/LDOPTS.SH file can redefine
#       these as needed.  The options include:
#
#       DEbug   - generate code suitable for debuggers: implies NOSTRIP
#       DIrty   - use options DIRTY is set to in LDOPTS.SH
#       LIst    - generate line numbered listing of source code
#                   (only if compilation is necessary)
#       MAP     - generate a link map
#       OPTn    - optimization level (n = 0 to 9) as in LDOPTS.SH
#       PRofile - generate code suitable for profiling
#       PUrge   - delete preprocessed file and log files after
#                   successful compilation
#       REplace - move binary to LOAD areas if appropriate.
#       SAve    - save old copies of binaries in LOAD area as *.EXE.OLD
#                   but DELETE them after the rename (this seemingly
#                   silly step prevents bus errors from occuring if an
#                   instance of the program is currently running when
#                   the AILINK finishes and the new .EXE is moved into
#                   place).
#       STrip   - strip symbol table from executable (saves space)
#
#       Uppercase part of option is minimum required for recognition.
#       The above can be prefixed with NO to negate the option, e.g.
#       NOPURGE will cancel any deleting of files.
#
#    3) [UNIX-style-options]
#
#       UNIX-style options which are passed on to the local compiler.
#
#    4) [file.OPT]
#
#       Link list file of the form '*.OPT'.  This is intended for
#       programs outside the main $AIPS_VERSION directory tree, or those
#       in $APLCONTR.  It contains a list of libraries and possibly
#       local copies of object files for debugging.  These .OPT files
#       can be generated by the LIBS script; when given the pathname of
#       an AIPS program area, it will print out the default link list,
#       e.g. LIBS $APLPGM -d >MY.OPT will create an options file based
#       on the $LIBRDBG area (leave out -d to get $LIBR) for a program
#       suited to the $APLPGM area.
#
#    5) [file.LOG]
#
#       Optional log filename of the form '*.LOG'.  If not given, log
#       files are automatically generated (or appended to) for each
#       program being processed.  If purging is enabled either by
#       default or by specifying PURGE on the command line and all goes
#       well, these log files as well as preprocessor intermediate files
#       are deleted.  If the user specifies a '.LOG' file on the command
#       line, it is either generated or appended to but never deleted.
#
# Generic UNIX version with support for two sets of libraries: debug
# (not optimized) and nodebug (optimized).  Also shared library support
# for certain systems (Sun4, Sol, HP for now; maybe Linux later)
#-----------------------------------------------------------------------
#                                       Cleanup on signals 1,2,3 & 15.
trap 'rm -f \
     $PREP/LINK.${HOST}.$$ $PREP/RPL.${HOST}.$$ $PREP/AT.${HOST}.$$ \
     $PREP/LD.${HOST}.$$; exit 1' 1 2 3 15
#                                       old (PWD) or new (AIPWD)?
if [ -f $SYSLOCAL/AIPWD ] ; then
   LPWD=AIPWD
else
   LPWD=PWD
fi
#                                       Any command line argument(s)?
if [ "$*" = "" ] ; then
   echo "Usage: AILINK [directory-path/][@@]file[.o] [AIPS-options] \\"
   echo "            [UNIX-options] [file.OPT] [file.LOG]"
   echo "See the precursor comments in $0 for more details."
   exit 1
fi
#                                       Could override STRIPFLAG in
#                                       LDOPTS.SH if necessary
STRIPFLAG="-s"
#                                       Get host loader definitions.
. $SYSLOCAL/LDOPTS.SH
#                                       Initialize OPTS, LDOPTS,
#                                       OPTFIL and ULOG.
OPTS=""
LDOPTS=$LINK
OPTFIL=""
ULOG=""
[ "$LIBRDBG" = "" ] && LIBRDBG=`echo $LIBR | sed -e 's#/LIBR#/LIBRDBG#'`
[ -d $LIBRDBG ] || LIBRDBG=$LIBR
DODEBUG=NO
DEBUGON=FALSE
#                                       Alias LOAD logical to make up
#                                       illogical naming convention.
LOAD0=$LOAD
#                                       Parse argument(s).
for i
do
   case $i in
#                                       User (or COMLNK) specified log
#                                       filename.  Add pwd if needed...
      *.LOG | *.log)
         case $i in
            */*) ULOG=$i ;;
            *)   ULOG=`$LPWD`/$i ;;
         esac
      ;;
#                                       Optional link list file.
      *.OPT | *.opt)
         if [ "$OPTFIL" != "" ] ; then
            echo "AILINK      : You can only specify one *.OPT file."
            rm -f $PREP/LINK.${HOST}.$$
            echo "AILINK      : Dies of unnatural causes"
            exit 1
         else
            if [ -f $i ] ; then
               OPTFIL=$i
#                                       Record options.
               OPTS="$OPTS$i "
            else
               echo "AILINK      : File       $i"
               echo "AILINK      : not found!"
               rm -f $PREP/LINK.${HOST}.$$
               echo "AILINK      : Dies of unnatural causes"
               exit 1
            fi
         fi
      ;;
      *@@*)
#                                       An '@@' file list of pathnames.
#                                       Append it to pathname list.
         AT=`echo $i | sed -e 's/@@//'`
         if [ -f $AT ] ; then
            sed -n -e 's/^[^-]/&/p' $AT >> $PREP/LINK.${HOST}.$$
         else
            echo "AILINK      : '@@' file    $AT"
            echo "AILINK      : not found!"
            rm -f $PREP/LINK.${HOST}.$$
            echo "AILINK      : Dies for want of a missing '@@' file."
            exit 1
         fi
      ;;
#                                       Object module.
      *.o | */*)
#                                       Pathname or just filename?
         case $i in
#                                       Pathname.  Extract directory
#                                       and filename.
            */*.o) echo $i >> $PREP/LINK.${HOST}.$$
            ;;
#                                       Filename only.  Use current
#                                       working directory.
            *.o) echo `$LPWD`/$i >> $PREP/LINK.${HOST}.$$
            ;;
#                                       Pathname without '.o' extension.
#                                       Tag one on and append it to
#                                       object module list.
            *)
               if [ -f $i.o ] ; then
                  echo $i.o >> $PREP/LINK.${HOST}.$$
               else
                  echo "AILINK      : File       $i.o"
                  echo "AILINK      : not found!"
                  rm -f $PREP/LINK.${HOST}.$$
                  echo "AILINK      : Dies for want of an object file"
                  exit 1
               fi
            ;;
         esac
      ;;

      -*)
#                                       UNIX-style option.
#                                       Some Linux systems seem to
#                                       want these reversed.
         if [ "$ARCH" = "LINUX" -o  "$ARCH" = "LNX64" ] ; then
            LDOPTS="$i $LDOPTS"
         else
            LDOPTS="$LDOPTS $i"
         fi
#                                       Record options.
         OPTS="$OPTS$i "
      ;;

#                                       To get here, the argument is
#                                       probably, but not necessarily,
#                                       an option.  Check it out.
      *) j=`echo $i | tr '[a-z]' '[A-Z]'`

         case $j in
            DE | DEB | DEBU | DEBUG)
               OPTS="$OPTS$i "
               XLATE='$DEBUG'
               OPTION=`eval echo $XLATE`
               LDOPTS=`echo $LDOPTS | sed -e 's/ *'$OPTION'//'`
               if [ "$ARCH" = "LINUX" -o  "$ARCH" = "LNX64" ] ; then
#                                       Some Linux systems seem to
#                                       want these reversed.
                  LDOPTS="$OPTION $LDOPTS"
               else
                  LDOPTS="$LDOPTS $OPTION"
               fi
               [ -f $SYSLOCAL/DOTWOLIB ] && DODEBUG=YES
               DEBUGON=TRUE
            ;;
            NODE | NODEB | NODEBU | NODEBUG)
               OPTS="$OPTS$i "
               XLATE='$DEBUG'
               OPTION=`eval echo $XLATE`
               LDOPTS=`echo $LDOPTS | sed -e 's/ *'$OPTION'//'`
               DODEBUG=NO
               DEBUGON=FALSE
            ;;
            NOOPT)
               OPTS="$OPTS NOOPT"
            ;;
            LI | LIS | LIST)
               OPTS="$OPTS$i "
               LIST=TRUE
            ;;
            NOLI | NOLIS | NOLIST)
               OPTS="$OPTS$i "
               LIST=FALSE
            ;;
            MA | MAP)
               OPTS="$OPTS$i "
               XLATE='$MAP'
               OPTION=`eval echo $XLATE`
               LDOPTS=`echo $LDOPTS | sed -e 's/ *'$OPTION'//'`
               LDOPTS="$LDOPTS $OPTION"
            ;;
            NOMA | NOMAP)
               OPTS="$OPTS$i "
               XLATE='$MAP'
               OPTION=`eval echo $XLATE`
               LDOPTS=`echo $LDOPTS | sed -e 's/ *'$OPTION'//'`
            ;;

            OPT[0-9])
               OPTS="$OPTS$i "
               XLATE=\$$i
               OPTION=`eval echo $XLATE`
               LDOPTS=`echo $LDOPTS | sed -e 's/ *'$OPTION'//'`
               LDOPTS="$LDOPTS $OPTION"
            ;;
            DI | DIR | DIRT | DIRTY)
               OPTS="$OPTS$i "
               XLATE='$DIRTY'
               OPTION=`eval echo $XLATE`
               LDOPTS=`echo $LDOPTS | sed -e 's/ *'$OPTION'//'`
               LDOPTS="$LDOPTS $OPTION"
            ;;
            NODI | NODIR | NODIRT | NODIRTY)
               OPTS="$OPTS$i "
               XLATE='$DIRTY'
               OPTION=`eval echo $XLATE`
               LDOPTS=`echo $LDOPTS | sed -e 's/ *'$OPTION'//'`
            ;;
            PU | PUR | PURG | PURGE)
               OPTS="$OPTS$i "
               PURGE=TRUE
            ;;
            NOPU | NOPUR | NOPURG | NOPURGE)
               OPTS="$OPTS$i "
               PURGE=FALSE
            ;;
            RE | REP | REPL | REPLA | REPLAC | REPLACE)
               OPTS="$OPTS$i "
               REPLACE=TRUE
            ;;
            NORE | NOREP | NOREPL | NOREPLA | NOREPLAC | NOREPLACE)
               OPTS="$OPTS$i "
               REPLACE=FALSE
            ;;
            SA | SAV | SAVE)
               OPTS="$OPTS$i "
               SAVE=TRUE
            ;;
            NOSA | NOSAV | NOSAVE)
               OPTS="$OPTS$i "
               SAVE=FALSE
            ;;
            ST | STR | STRI | STRIP)
               OPTS="$OPTS$i "
               STRIP=TRUE
            ;;
            NOST | NOSTR | NOSTRI | NOSTRIP)
               OPTS="$OPTS$i "
               STRIP=FALSE
            ;;
            PR | PRO | PROF | PROFI | PROFIL | PROFILE)
               OPTS="$OPTS$i "
               XLATE='$PROFILE'
               OPTION=`eval echo $XLATE`
               LDOPTS=`echo $LDOPTS | sed -e 's/ *'$OPTION'//'`
               LDOPTS="$LDOPTS $OPTION"
            ;;
            NOPR | NOPRO | NOPROF | NOPROFI | NOPROFIL | NOPROFILE)
               OPTS="$OPTS$i "
               XLATE='$PROFILE'
               OPTION=`eval echo $XLATE`
               LDOPTS=`echo $LDOPTS | sed -e 's/ *'$OPTION'//'`
               LDOPTS="$LDOPTS $OPTION"
            ;;
            *)
#                                       Not a recognizable AIPS-style
#                                       option.  Tag '.o' to it and test
#                                       for it as an object module.
               if [ -f `$LPWD`/$i.o ] ; then
                  echo "`$LPWD`/$i.o" >> $PREP/LINK.${HOST}.$$
               else
                  echo "AILINK      : File       `$LPWD`/$i.o"
                  echo "AILINK      : not found!"
                  rm -f $PREP/LINK.${HOST}.$$
                  echo "AILINK      : Dies for want of an object file"
                  exit 1
               fi
            ;;
         esac
      ;;

      *)
#                                       User error.
         echo "Usage: AILINK [directory-path/][@@]file[.o]" \
            "[AIPS-sytle-options] \\"
         echo "            [UNIX-style-options] [file.OPT] [file.LOG]"
         rm -f $PREP/LINK.${HOST}.$$
         echo "AILINK      : Dies from confusing user input"
         exit 1
      ;;
   esac
done
#                                       Strip executable?
if [ "$DEBUGON" = "TRUE" ] ; then
    STRIP=FALSE
fi
if [ "$STRIP" = "TRUE" ] ; then
    LDOPTS="$LDOPTS $STRIPFLAG"
fi
#                                       Squeeze out extra blanks
#                                       No!  LDOPTS=-native plays havoc!
#                                       "echo" interprets it as -n!!
#                                       Default OPTFIL to
#                                       $SYSLOCAL/LIBR.DAT.
[ "$OPTFIL" = "" ] && OPTFIL=$SYSLOCAL/LIBR.DAT
#                                       Any programs to link?
if [ ! -f $PREP/LINK.${HOST}.$$ ] ; then
   echo "Usage: AILINK [directory-path/][@@]file[.o]" \
      "[AIPS-sytle-options] \\"
   echo "            [UNIX-style-options] [file.OPT] [file.LOG]"
   echo "AILINK      : Dies from perplexing user input"
   exit 1
fi
#                                       Link modules one at a time.
cat $PREP/LINK.${HOST}.$$ | \
   while read PATHNAME ; do
#                                       this is needed within the loop.
     trap 'echo "AILINK      : Dies from user interrupt"; rm -f \
     $PREP/LINK.${HOST}.$$ $PREP/RPL.${HOST}.$$ $PREP/AT.${HOST}.$$ \
     $PREP/LD.${HOST}.$$; exit 1' 1 2 3 15
#                                       Save $PATHNAME in case we are
#                                       being '@@' file driven.
      ATNAME=$PATHNAME
#                                       Directory used to determine the
#                                       library list.
      LDIR=`echo $PATHNAME | sed -e 's#\(/.*\)/.*#\1#'`
#                                       File name without extension.
      FILE="`basename $PATHNAME | sed -e 's#\..*##'`"
#                                       Reset PATHNAME to point to the
#                                       real object module.
      case $PATHNAME in
         $APLCONTR*)     ;;
         $AIPS_VERSION*) PATHNAME="$PREP/${FILE}.o" ;;
      esac
#                                       Make sure the object module
#                                       actually exists.
      if [ -f $PATHNAME ] ; then
#                                       Separate directory and
#                                       filename.
         FILE=`basename $PATHNAME | sed -e 's/\.o//'`
         DIR=`echo $PATHNAME | sed -e 's#\(/.*\)/.*#\1#'`
#                                       If log filename specified,
#                                       append to it.  If not, form log
#                                       filename from $DIR and $FILE,
#                                       then delete any extant version.
         if [ "$ULOG" = "" ] ; then
            LOG=$DIR/$FILE.LOG
            rm -f $LOG
         else
            LOG=$ULOG
         fi
#                                       Is $LDIR an AIPS program source
#                                       code area?
         if grep $LDIR$ $SYSLOCAL/SEARCH[0-9].DAT > /dev/null
         then
#                                       DIR is an AIPS program source
#                                       code area.  Get ALTS list from
#                                       $SYSLOCAL/LIBR.DAT.
            ALTS=`sed -n -e 's/\(.*:\)\([0-9]\)\(:.*\)/\2/p' \
               $SYSLOCAL/LIBR.DAT | sort -u`
         else
#                                       DIR is NOT an AIPS program
#                                       source code area.  Just link
#                                       once using user provided
#                                       options file.
            ALTS="0"
         fi
#                                       Link as many times as there
#                                       are items in $ALTS list.
         for ALT in $ALTS
         do
#                                       $OPTFIL determines link list.
            case $OPTFIL in

               $SYSLOCAL/LIBR.DAT*)
#                                       Select proper load library.
                  LOAD=\$LOAD$ALT
                  LOAD=`eval echo $LOAD`
#                                       Use AIPS system object libs.
                  ENV=`PRINTENV | grep -v '^[CcPp][Ww][Dd]=' | \
                     grep $LDIR$ | grep -v 'ENV=' | sed -e 's/=.*//'`
#                                       Extract object library link list
#                                       from $SYSLOCAL/LIBR.DAT or
#                                       LIBR.DAT.[UN]SHARED based on $ENV
                  SHARED=NO
                  LIBRDAT=$SYSLOCAL/LIBR.DAT
                  [ -f $SYSLOCAL/LIBR.DAT.UNSHARED ] && \
                     LIBRDAT=$SYSLOCAL/LIBR.DAT.UNSHARED
                  if [ -f $SYSLOCAL/USESHARED ] ; then
                     if grep -s $FILE $SYSLOCAL/NOSHARE.LIS ; then
                        echo "AILINK      : $FILE found in NOSHARE.LIS" \
                           | tee -a $LOG
                     else
#                                       Shared libs on these ONLY.
                        case $ARCH in
                           SUN* | HP | HP2 | SOL* | SUL )
                              SHARED=YES
                              [ -f $SYSLOCAL/LIBR.DAT.SHARED ] && \
                                 LIBRDAT=$SYSLOCAL/LIBR.DAT.SHARED
                              ;;
                           *) echo "AILINK      : ignoring USESHARED" \
                                 "for architecture $ARCH" | tee -a $LOG
                           ;;
                        esac
                     fi
                  fi
#                                       If debug, use LIBRDBG libraries

                  if [ "$DODEBUG" = YES ] ; then
                     LINKLIST=`grep ':'$ALT':\$'$ENV'$' \
                        $LIBRDAT | sed -n -e 's/:.*//p' | \
                        sed -e 's#LIBR#LIBRDBG#'`
#
                  elif [ "$SHARED" = YES ] ; then

#                                       Not debug.  Check if shared,
#                                       if so, change to <lib>.so

                     LINKLIST=`grep ':'$ALT':\$'$ENV'$' \
                        $LIBRDAT | sed -n -e 's/:.*//p' | \
                        sed -n -e 's#/SUBLIB#.so#p' \
                               -e 's#GNU/libreadline.a#libreadline.so#p'`
                  else
#                                       nodebug, noshare.  The old way.

                     LINKLIST=`grep ':'$ALT':\$'$ENV'$' \
                        $LIBRDAT | sed -n -e 's/:.*//p'`
                  fi
#                                       Null $LINKLIST means $DIR not
#                                       defined either for this $ALT
#                                       or the host implementation
#                                       (i.e., not defined for ALT=0).
                  if [ "$LINKLIST" = "" -a "$ALT" = "0" ] ; then
                     echo "AILINK      : Directory  $LDIR not defined"   \
                        | tee -a $LOG
                     echo "AILINK      : in         $LIBRDAT"            \
                        | tee -a $LOG
                     echo "AILINK      : Provide    '.OPT' file!"        \
                        | tee -a $LOG
                     echo "AILINK      : Link of    $PATHNAME"           \
                        | tee -a $LOG
                     echo "AILINK      : dies from inadequate $LIBRDAT." \
                        | tee -a $LOG
                     rm -f $PREP/LINK.${HOST}.$$
                     exit 1
                  elif [ "$LINKLIST" = "" ] ; then
#                                       ALT=0 must have worked.  Null
#                                       LINKLIST simply means there is
#                                       no $ALT alternate link list
#                                       for this program.  Continue.
                     continue
                  fi
#                                       Extract list of AIPS system
#                                       object library directories
#                                       from $LINKLIST.
                  SYSLIBS=`grep ':'$ALT':\$'$ENV'$' \
                     $LIBRDAT | sort -u | \
                     sed -n -e 's/\/SUBLIB:.*//p'`
#                                       Evaluate $SYSLIBS.
                  SYSLIBS=`eval echo $SYSLIBS`
               ;;

               *)
#                                       User provided OPTFIL.
                  LINKLIST=`cat $OPTFIL`
                  ITEMS=`sort -u $OPTFIL`
#                                       Extract AIPS system object
#                                       library directories from
#                                       $ITEMS.  These are used to
#                                       see if LIBR needs to be
#                                       called below.
                  for ITEM in $ITEMS
                  do
#                                       Evaluate $ITEM.
                     ITEM=`eval echo $ITEM`
#                                       Check if it's under LIBR(DBG)
                     case $ITEM in
#                                       Limit update checks to $LIBR*.
                        $LIBR*)
#                                       Add to library directory list.
                           SYSLIBS="$SYSLIBS `echo $ITEM | \
                              sed -e 's/\/SUBLIB//'`"
                        ;;
                     esac
                  done
               ;;
            esac
#                                       Check for object modules that
#                                       need to be archived in any
#                                       AIPS system object libraries
#                                       in $SYSLIBS.
            for LIB in $SYSLIBS
            do
#                                       Are there any object modules
#                                       that need to be archived?
               rm -f $PREP/RPL.${HOST}.$$ >/dev/null 2>&1
               ls $LIB | grep '\.o' 1> $PREP/RPL.${HOST}.$$ 2> /dev/null
               if [ -s $PREP/RPL.${HOST}.$$ ] ; then
#                                       If so, get LIBR to do it.
                  if LIBR $LIB $LOG ; then
#                                       LIBR sucessful.
                     continue
                  else
#                                       LIBR unsuccessful.
                     echo "AILINK      : LIBR failed, cannot continue" | \
                        tee -a $LOG
                     echo "AILINK      : Link of    $PATHNAME" | \
                        tee -a $LOG
                     echo "AILINK      : dies from LIBR betrayal." | \
                        tee -a $LOG
                     rm -f $PREP/LINK.${HOST}.$$ $PREP/RPL.${HOST}.$$
#                                       This was "break 2".  Why????
                     exit 1
                  fi
               else
#                                       No object modules to archive.
                  rm -f $PREP/RPL.${HOST}.$$
               fi
            done
#                                       Delete any extant
#                                       $DIR/$FILE.EXE.
            rm -f $DIR/$FILE.EXE
#                                       So far, so good.  Go ahead and
#                                       try to link.

            echo "AILINK      : Date is... `date`"                  | \
               tee -a $LOG
            echo "AILINK      : Interpret  LINK $OPTS\\"            | \
               tee -a $LOG
            echo "AILINK      :            $PATHNAME"               | \
               tee -a $LOG
            echo "AILINK      : as         PURGE=$PURGE"              \
               "REPLACE=$REPLACE SAVE=$SAVE STRIP=$STRIP"         | \
               tee -a $LOG
            echo "AILINK      : plus       $COMPILER \\"            | \
               tee -a $LOG
            echo "AILINK      :            $PATHNAME \\"            | \
               tee -a $LOG
            eval echo $LINKLIST | awk '{ for (i = 1; i <= NF; i++)  \
               printf "AILINK      :            %s \\ \n", $i }'    | \
               tee -a $LOG
            echo "AILINK      :            $LDOPTS \\"              | \
               tee -a $LOG
            echo "AILINK      :            -o $DIR/$FILE.EXE"       | \
               tee -a $LOG
            $COMPILER $PATHNAME `eval echo $LINKLIST` $LDOPTS \
               -o $DIR/$FILE.EXE >$PREP/LD.$HOST.$$ 2>&1
            CSTAT=$?
            [ -s $PREP/LD.$HOST.$$ ] && cat $PREP/LD.$HOST.$$ | \
                awk -f $SYSUNIX/WIDTH132.AWK | tee -a $LOG
            rm -f $PREP/LD.$HOST.$$
#                                       Does executable module exist?
#                                       This is the only generic way
#                                       to test for success since
#                                       compilers/loaders don't always
#                                       have an error return (sigh).
            if [ $CSTAT -ne 0 ] ; then
               echo "AILINK      : Status from $COMPILER is $CSTAT" | \
                tee -a $LOG
               echo "AILINK      : Link of    $PATHNAME"    | tee -a $LOG
               echo "AILINK      : dies from wimpy compiler" | tee -a $LOG
               rm -f $PREP/LINK.${HOST}.$$
#                                       was "break 2"; why???
               exit 1
            elif [ -s $DIR/$FILE.EXE ] ; then
#                                       Exists, but is it executable?
#                                       test -x is not universal.
               X=`ls -l $DIR/$FILE.EXE | grep '^...-'`
               if [ "$X" = "" ] ; then
#                                       If optional link list provided
#                                       or object module does not
#                                       belong to $AIPS_VERSION, don't
#                                       replace executable in $LOAD.
                  case $LDIR in

                    *$AIPS_VERSION*)

                      case $OPTFIL in

                        $SYSLOCAL/LIBR.DAT*)
#                                       Okay to move to AIPS system
#                                       load module library.
                          if [ "$REPLACE" = "TRUE" ] ; then
                            if [ "$SAVE" = "TRUE" ] ; then
                              if [ -f $LOAD/$FILE.EXE.OLD ] ; then
                                rm -f $LOAD/$FILE.EXE.OLD
                                if [ $? -ne 0 ] ; then
                                  echo "AILINK     :" \
                                    "Remove of  $LOAD/$FILE.EXE.OLD" | \
                                    tee -a $LOG
                                  echo "AILINK      : Failed!" \
                                    " BUT, Proceeding anyway..." | \
                                    tee -a $LOG
                                fi
                              fi
#                                       Only move it if it's there.  Duh
                              if [ -f $LOAD/$FILE.EXE ] ; then
#                                       Split up into ln, rm
                                if ln $LOAD/$FILE.EXE \
                                      $LOAD/$FILE.EXE.OLD ; then
                                  echo "AILINK      : Hardinked " \
                                     "$LOAD/$FILE.EXE" | tee -a $LOG
                                  echo "AILINK      : to        " \
                                     "$LOAD/$FILE.EXE.OLD" | tee -a $LOG
#                                       Remove it.  It will stay around
#                                       as long as any currently running
#                                       instances are active.  Failure
#                                       to follow this step invariably
#                                       results in full disks!!!!
                                  /bin/rm -f $LOAD/$FILE.EXE
				  if [ -f $LOAD/$FILE.EXE ] ; then
                                    echo "AILINK      : delete of" \
                                     | tee -a $LOG
                                    echo "AILINK      : $FILE.EXE" \
                                     | tee -a $LOG
                                    echo "AILINK      : Failed!" \
                                     | tee -a $LOG
                                    echo "AILINK      : dies dies dies!" \
                                     | tee -a $LOG
                                    rm -f $PREP/LINK.${HOST}.$$
#                                       Is this the right number?
#                                       break 4?  Who cares; it's wrong!
                                    exit 1
                                  else
                                    echo "AILINK      : Deleted   " \
                                     "$LOAD/$FILE.EXE" | tee -a $LOG
                                  fi
                                  /bin/rm -f $LOAD/$FILE.EXE.OLD
				  if [ -f $LOAD/$FILE.EXE.OLD ] ; then
                                    echo "AILINK      : delete of" \
                                     | tee -a $LOG
                                    echo "AILINK      : $FILE.EXE.OLD" \
                                     | tee -a $LOG
                                    echo "AILINK      : Failed!" \
                                    " BUT, Proceeding anyway..." \
                                     | tee -a $LOG
                                  else
                                    echo "AILINK      : Deleted   " \
                                     "$LOAD/$FILE.EXE.OLD" \
                                     "(boom!)" \
                                     | tee -a $LOG
                                  fi
                                else
                                  echo "AILINK      : Link of   " \
                                     "$LOAD/$FILE.EXE" | tee -a $LOG
                                  echo "AILINK      : to        " \
                                     "$LOAD/$FILE.EXE.OLD" | tee -a $LOG
                                  echo "AILINK     : Failed!" \
                                     " BUT, Proceeding anyway..." | \
                                     tee -a $LOG
                                fi
                              fi
                            fi
                            if mv $DIR/$FILE.EXE $LOAD/ ; then
                              echo "AILINK      :" \
                                   "Moved      $DIR/$FILE.EXE" | \
                                    tee -a $LOG
                              echo "AILINK      :" \
                                   "to         $LOAD/$FILE.EXE" | \
                                    tee -a $LOG
                            else
                              echo "AILINK      :" \
                                   "Move of    $DIR/$FILE.EXE" | \
                                    tee -a $LOG
                              echo "AILINK      :" \
                                   "to         $LOAD/$FILE.EXE" | \
                                    tee -a $LOG
                              echo "AILINK      : Failed!"      | \
                                    tee -a $LOG
                              echo "AILINK      :" \
                                   "Link of    $PATHNAME"       | \
                                    tee -a $LOG
                              echo "AILINK      :" \
                                   "dies from moving exhaustion." | \
                                    tee -a $LOG
                              rm -f $PREP/LINK.${HOST}.$$
#                                       was "break 2"
                              exit 1
                            fi
                          fi
                        ;;

                        *)
#                                       Move executable to current
#                                       working directory, if necessary.
#                                       $DIR = current working
#                                       directory?
                              if [ $DIR != "`$LPWD`" ] ; then
#                                       Is this code ever executed?
                                 if mv $DIR/$FILE.EXE . ; then
                                    echo "AILINK      :" \
                                       "Moved      $DIR/$FILE.EXE"  | \
                                       tee -a $LOG
                                    echo "AILINK      :" \
                                       "to         `$LPWD`/$FILE.EXE" | \
                                       tee -a $LOG
                                 else
                                    echo "AILINK      :" \
                                       "Move of    $DIR/$FILE.EXE"  | \
                                       tee -a $LOG
                                    echo "AILINK      :" \
                                       "to         `$LPWD`/$FILE.EXE" | \
                                          tee -a $LOG
                                    echo "AILINK      : Failed!"      | \
                                       tee -a $LOG
                                    echo "AILINK      :" \
                                       "Link of    $PATHNAME"       | \
                                       tee -a $LOG
                                    echo "AILINK      :" \
                                       "dies from moving fatigue."  | \
                                       tee -a $LOG
                                    rm -f $PREP/LINK.${HOST}.$$
#                                       was "break 2"
                                    exit 1
                                 fi
                              fi
#                                       For user provided *.OPT file,
#                                       always break from the ALT load
#                                       library loop, regardless of
#                                       $ALTS.
                              break 1
                           ;;
                        esac
                     ;;
                  esac
#                                       Not executable.  Delete.
               else
                  echo "AILINK      : Module     $DIR/$FILE.EXE" \
                     "not executable!" | tee -a $LOG
                  echo "AILINK      : Delete     $DIR/$FILE.EXE" | \
                     tee -a $LOG
                  rm $DIR/$FILE.EXE
                  echo "AILINK      : Link of    $PATHNAME"    | \
                     tee -a $LOG
                  echo "AILINK      : dies from compiler betrayal." | \
                     tee -a $LOG
                  rm -f $PREP/LINK.${HOST}.$$
#                                        was "break 2"
                  exit 1
               fi
#                                       $DIR/$FILE.EXE not found.
#                                       Something really went wrong.
            else
               echo "AILINK      : File       $DIR/$FILE.EXE missing!" | \
                   tee -a $LOG
               echo "AILINK      : Link of    $PATHNAME"    | tee -a $LOG
               echo "AILINK      : dies from total weirdness." | \
                   tee -a $LOG
               rm -f $PREP/LINK.${HOST}.$$
#                                       was "break 2"
               exit 1
            fi
         done
      else
#                                       Non-existent object module.
         if [ "$ULOG" = "" ] ; then
            echo "AILINK      : File       $PATHNAME"
            echo "AILINK      : not found!"
            echo "AILINK      : Link of    $PATHNAME"
            echo "AILINK      : dies from missing file."
         else
            echo "AILINK      : File       $PATHNAME"    | tee -a $LOG
            echo "AILINK      : not found!"              | tee -a $LOG
            echo "AILINK      : Link of    $PATHNAME"    | tee -a $LOG
            echo "AILINK      : dies from missing file." | tee -a $LOG
         fi
         rm -f $PREP/LINK.${HOST}.$$
#                                       was "break 2"
         exit 1
      fi
#                                       Success!  Delete '.o'?
      if [ "$PURGE" = "TRUE" ] ; then
         echo "AILINK      : Delete     $PATHNAME" | tee -a $LOG
         rm -f $PATHNAME
      fi
#                                       If we are being '@@' file
#                                       driven, auto-edit the '@@'
#                                       file prefixing this
#                                       $PATHNAME with a '-' to
#                                       indicate it as done.
      if [ "$AT" != "" ] ; then
         sed -e 's#^'$ATNAME'#-&#' $AT > $PREP/AT.${HOST}.$$
         cp $PREP/AT.${HOST}.$$ $AT
         rm $PREP/AT.${HOST}.$$
         echo "AILINK      : Changed    $ATNAME"  | tee -a $LOG
         echo "AILINK      : in         $AT"      | tee -a $LOG
         echo "AILINK      : to         -$ATNAME" | tee -a $LOG
      fi
#                                       Good news.
      echo "AILINK      : Link of    $PATHNAME"    | tee -a $LOG
      echo "AILINK      : ends successfully."      | tee -a $LOG
#                                       If non-user-specified log
#                                       file, delete it.
      if [ "$ULOG" = "" ] ; then
         echo "AILINK      : Delete     $LOG" | tee -a $LOG
         rm -f $LOG
      fi
#                                       Next program object module.
   done
rm -f $PREP/RPL.${HOST}.$$
if [ -f $PREP/LINK.${HOST}.$$ ] ; then
   rm $PREP/LINK.${HOST}.$$
   exit 0
else
   echo "AILINK      : Dies of unnatural causes."
   exit 1
fi
