#!/bin/sh
###########################################################################
# 
#  TinyFugue builder
# 
###########################################################################
# 
#  Don't edit this file.
#
#  If Build has trouble, or you want to change some defaults or enable
#  some optional features, see README and edit the Config file.
#
#  Just type "Build" to install everything.
# 
###########################################################################

### A few portability notes.
# Some versions of 'test' have the wrong precedence for unary operators,
# so we use the shell's '&&' and '||' operators instead of '-a' and '-o'.
# 4.3 BSD 'test' does not have '-x'.  Use '-f' or '-r' instead.
# Some old shells do not support the ':' in ${VAR:-default}.  Don't use it.

### Initialize variables, just in case they're already defined.

ANSI_C=0
BINDIR=''
CC=''
CCFLAGS=''
CONNECT=''
EXE=''
FLAGS=''
GNU_C=0
HELPFILE=''
INCDIR=''
LIBC=''
LIBDIR=''
LIBS=''
MAILDIR=''
MAKE=''
MANPAGE=''
MANTYPE=''
OPT=''
POSIX=1
#POSIX=unknown
RAND=''
RESTRICT=''
SYSTEM=''
TERMINAL=''
TFCONNECT=''
TFLIBRARY=''
TTYDRIVER=''

if [ ! -f ./Build ]; then
    echo "You should run Build in the directory extracted from the archive."
    exit 2
fi

VERSION=`egrep 'char version' src/main.c | sed 's/^.*\"\(.*\)\".*$/\1/'`

{
### Everything after this point is logged to Build.log

echo "Building:  $VERSION"

### Read in user definitions.
if [ -r ./Config ]; then . ./Config; fi

### I keep development definitions in dev/config so I don't have to keep
### editing the default version.
if [ -r dev/config ]; then . dev/config; fi

### Make sure the PATH is sane.
PATH="/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc:/usr/new:/usr/new/bin:/usr/nbin:$PATH"

if [ -z "$INCDIR" ]; then
    INCDIR='/usr/include'
fi

# ### Try to detect ability to support nonblocking connect
#
# ### This doesn't work.  Some systems (notably SunOS) define I_SENDFD
# ### and I_RECVFD, but don't actually support it.  And, OSF defines
# ### SCM_RIGHTS, but then requires special hacks to get 4.4 BSD behavior.
# 
# if [ -z "$CONNECT" ]; then
#     if egrep 'I_SENDFD' ${INCDIR}/stropts.h >/dev/null 2>&1; then
#         CONNECT='CONNECT_SVR4'
#         echo 'Your system appears to support nonblocking connect.'
#     elif egrep 'SCM_RIGHTS' ${INCDIR}/sys/socket.h >/dev/null 2>&1; then
#         CONNECT='CONNECT_BSD'
#         echo 'Your system appears to support nonblocking connect.'
#     fi
# else
if [ "$CONNECT" = "blocking" ]; then
    CONNECT=''
fi

### Pick user's or default definitions.

if [ -w /usr/local/bin ] && [ -w /usr/local/lib ]; then
    BINDIR=/usr/local/bin
    LIBDIR=/usr/local/lib
else
    [ -d $HOME/bin ] && BINDIR=$HOME/bin || BINDIR=$HOME
    [ -d $HOME/lib ] && LIBDIR=$HOME/lib || LIBDIR=$HOME
fi

[ -z "$EXE" ]       && EXE=${BINDIR}/tf
[ -z "$TFLIBRARY" ] && TFLIBRARY=${LIBDIR}/tf.library
[ -z "$TFCONNECT" ] && TFCONNECT=${BINDIR}/tf.connect
[ -z "$HELPFILE" ]  && HELPFILE=${LIBDIR}/tf.help
[ -z "$MODE" ]      && MODE=755

if [ -z "$CONNECT" ]; then
    TFCONNECT=""
fi

### Build DEFS list.

DEFS="$DEFS EXE=${EXE} TFLIBRARY=${TFLIBRARY} HELPFILE=${HELPFILE}"
DEFS="$DEFS MAKE=${MAKE} MODE=${MODE}"
# DEFS="$DEFS MODE=${MODE}"

if [ -n "$TFCONNECT" ]; then
    DEFS="$DEFS TFCONNECT=${TFCONNECT}"
else
    CONNECT=""
fi

if [ -n "$MANPAGE" ]; then
    [ -z "$MANTYPE" ] && MANTYPE=cat
    DEFS="$DEFS MANTYPE=${MANTYPE} MANPAGE=${MANPAGE}"
fi

### Sanity check for filenames (some people do pretty stupid things)

if echo "$TFLIBRARY" | egrep "^[^/~]" ||
   echo "$HELPFILE"  | egrep "^[^/~]" ||
   echo "$EXE"       | egrep "^[^/~]"
then
   echo "You should not use relative paths to install files."
   echo "Edit Config and try again."
   exit 2
fi


if echo "$TFLIBRARY" | egrep "^`/bin/pwd`/" ||
   echo "$HELPFILE"  | egrep "^`/bin/pwd`/" ||
   echo "$EXE"       | egrep "^`/bin/pwd`/"
then
    echo "You should not install files in `/bin/pwd`."
    echo "Edit Config and try again."
    exit 2
fi

if echo "$TFLIBRARY" | egrep "^~" >/dev/null; then
    TFLIBRARY=`echo $TFLIBRARY | sed "s;~;$HOME;"`
fi
if echo "$HELPFILE"  | egrep "^~" >/dev/null; then
    HELPFILE=`echo $HELPFILE | sed "s;~;$HOME;"`
fi
if echo "$EXE"       | egrep "^~" >/dev/null; then
    EXE=`echo $EXE | sed "s;~;$HOME;"`
fi

### Find mail directory by looking at $MAIL, then looking in the usual places.

if [ -z "$MAILDIR" ]; then
    if [ -n "$MAIL" ]; then
#       Not everybody has dirname.  sigh.
        MAILDIR=`echo $MAIL | sed 's;[^/]*$;;'`
    elif [ -d /usr/spool/mail ]; then
        MAILDIR="/usr/spool/mail/"
    elif [ -d /var/spool/mail ]; then
        MAILDIR="/var/spool/mail/"
    elif [ -d /usr/mail ]; then
        MAILDIR="/usr/mail/"
    elif [ -d /var/mail ]; then
        MAILDIR="/var/mail/"
    else
        MAILDIR=""
    fi
fi


### Confirm.

if [ -z "$*" ]; then
    echo
    echo "TF binary will be installed in    $EXE"
    echo "Library will be installed in      $TFLIBRARY"
    if [ -n "$CONNECT" ]; then
        echo "Connector will be installed in    $TFCONNECT"
    else
        echo "Nonblocking connect will not be enabled."
    fi
    if [ -n "$HELPFILE" ]; then
        echo "Helpfile will be installed in     $HELPFILE"
    else
        echo "Online help will not be available."
    fi
    if [ -n "$MAILDIR" ]; then
        echo "Mail will be checked in directory $MAILDIR"
    else
        echo "Mail directory unknown.  TF may not be able to check mail."
    fi
    if [ -n "$MANPAGE" ]; then
        echo "Man page will be installed in     $MANPAGE in $MANTYPE format"
    else
        echo "Man page will not be installed."
    fi
    echo
    echo 'To change these defaults type "n" now and edit the Config file.'
    while [ -z "$ans" ]; do
        echo 'Continue? (y/n)'
        read ans;
        case "$ans" in
        y|Y)  break
              ;;
        n|N)  exit 1
              ;;
        *)    ans=
              echo 'Please answer "y" or "n".'
              ;;
        esac
    done
fi


### Compiler.
### SVr4 and some others have a "ucb" compiler that works better with socket
### stuff (e.g., automatically links in -lsocket -lnsl), so look for that.
### Otherwise, use GNU C if it's available.
### Note that GNU C's -ansi option does not guarantee existance of ANSI
### headers or libraries, so we must still verify them seperately.

if [ -z "$CC" ]; then
    if [ -f /usr/ucb/cc-bsd ]; then
        CC='/usr/ucb/cc-bsd'
        CCFLAGS='-g'
        echo "Your system has /usr/ucb/cc-bsd.  I'll try that."
    elif [ -f /usr/ucb/cc ]; then
        CC='/usr/ucb/cc'
        CCFLAGS='-g'
        echo "Your system has /usr/ucb/cc.  I'll try that."
    elif { gcc -v; } > /dev/null 2>&1; then
        CC='gcc'
        CCFLAGS="-O -ansi $CCFLAGS"
#        CCFLAGS="-g -ansi $CCFLAGS"
        ANSI_C=1
        GNU_C=1
        echo "Your system has gcc.  Cool.  I'll use it."
    else
        CC='cc'
        CCFLAGS='-g'
        echo "I'll use cc to compile."
    fi
fi

DEFS="$DEFS CC=${CC}"

### Test for ANSI.
### ansi.c returns 1 for GNU C, 0 for any other ANSI compiler, 2 otherwise.

if [ "$ANSI_C" != "1" ]; then
    cat > ansi.c <<EOP
main() {
#ifdef __GNUC__
    exit(1);
#endif
#ifdef __STDC__
# if __STDC__ == 1
    exit(0);
# endif
#endif
    exit(2);
}
EOP
    ${CC} ${CCFLAGS} ${FLAGS} ansi.c >/dev/null 2>&1
    if [ $? != 0 ] ; then
        echo "Ack!  Your compiler doesn't work.  Maybe you used invalid flags."
        echo "Edit Config and fix it.  I give up."
        exit 2
    fi
    ./a.out
    result=$?
    if [ $result = 0 ]; then
        echo "Cool, you have an ANSI compiler."
        ANSI_C=1
    elif [ $result = 1 ]; then
        echo "Ah ha, ${CC} is really GNU C.  Cool, I'll use it with -ansi."
        ANSI_C=1
        GNU_C=1
        CCFLAGS="${CCFLAGS} -ansi"
    else
        echo "Your compiler doesn't appear to be ANSI."
        ANSI_C=0
    fi
    rm ansi.c
fi

### Test for POSIX.
### If posix.c fails to compile, unistd.h must be missing (and system is not
### POSIX).  Otherwise, a.out returns 0 if posix, 1 if not.

if [ ${POSIX} = "unknown" ]; then
    cat > posix.c <<EOP
#include <unistd.h>
int main() {
#ifdef _POSIX_VERSION
    exit(0);
#else
    exit(1);
#endif
}
EOP
    if ${CC} ${CCFLAGS} ${FLAGS} posix.c >/dev/null 2>&1; then
        FLAGS="$FLAGS -DHAVE_UNISTD_H"
        if ./a.out; then
            echo "Right on, your system is POSIX."
            POSIX=1
        else
            echo "This doesn't appear to be a POSIX system."
            POSIX=0
        fi
    else
        echo "I can't find unistd.h.  The compiler may produce a lot of"
        echo "warnings, but you can probably ignore them."
        echo
        echo "This doesn't appear to be a POSIX system."
        POSIX=0
    fi
    rm posix.c
fi

rm a.out


### Try to detect unusual systems by looking for files required on those
### systems.  This is a hack.  If you can think of a better way, let me know.

if [ -z "$SYSTEM" ]; then
    if { ver && lvolfs; } >/dev/null 2>&1; then
        SYSTEM="DOMAIN_OS"
        echo "This looks like a Domain/OS system to me."
    elif [ -r ${INCDIR}/sys/in.h ] && [ -r ${INCDIR}/sys/inet.h ] && \
         [ -r /usr/lib/libnet.a ] && [ -r /usr/lib/libnsl_s.a ]; then
        SYSTEM="WINS"
        echo "This looks like a system with WINS networking to me."
    elif [ -r /usr/lib/libsocket.a ] && [ -r /usr/lib/libinet.a ] && \
        [ -r /usr/lib/libnsl.a ]; then
        SYSTEM="DYNIX_PTX"
        echo "This looks like a Dynix/PTX system to me."
    fi
    if [ -n "$SYSTEM" ]; then
        echo "If this is incorrect, set SYSTEM in the Config file."
        echo
    fi
else
    FLAGS="$FLAGS -D$SYSTEM"
fi

case "$SYSTEM" in
    WINS)
        FLAGS="$FLAGS -DWINS"
        LIBS="$LIBS -lnet -lnsl_s"
        ;;
    DYNIX_PTX)
        LIBS="$LIBS -lsocket -linet -lnsl"
        ;;
    DOMAIN_OS)
        FLAGS="$FLAGS -U__STDC__"
        ;;
esac

### This isn't required, but it helps.
if [ -r ${INCDIR}/stdlib.h ]; then
    FLAGS="$FLAGS -DHAVE_STDLIB_H"
elif [ "$ANSI_C" = "1" ] && [ "$GNU_C" = "0" ]; then
    FLAGS="$FLAGS -DHAVE_STDLIB_H"
else
    echo "I can't find stdlib.h.  The compiler may produce a lot of"
    echo "warnings, but you can probably ignore them."
    echo
fi

### Figure out which string file to include, if compiler isn't ANSI.
if [ "$ANSI_C" = "1" ] && [ "$GNU_C" = 0 ]; then
    FLAGS="$FLAGS -DUSE_STRING_H"
elif [ -r ${INCDIR}/string.h ]; then
    FLAGS="$FLAGS -DUSE_STRING_H"
elif [ -r ${INCDIR}/strings.h ]; then
    FLAGS="$FLAGS -DUSE_STRINGS_H"
else
    echo "    I can't find string.h or strings.h.  I'll try to use string.h."
    FLAGS="$FLAGS -DUSE_STRING_H"
fi

### This isn't required, but it helps.
if [ -r ${INCDIR}/sys/wait.h ]; then
    FLAGS="$FLAGS -DHAVE_SYS_WAIT_H"
else
    echo "    I can't find sys/wait.h.  No big deal."
fi

### Look through the contents of the C library to see if certain functions
### are available.  This is a bit of a hack.  But hey, it works.  Most of
### the time, anyway.

echo "Checking your system for availability of certain features..."

if [ -z "$LIBC" ] || [ ! -f "$LIBC" ]; then
    if [ -r /lib/libc.a ]; then
        LIBC='/lib/libc.a'
    elif [ -r /usr/lib/libc.a ]; then
        LIBC='/usr/lib/libc.a'
    elif [ -r /usr/ccs/lib/libc.a ]; then
        LIBC='/usr/ccs/lib/libc.a'
    elif [ -r /usr/lib/libNeXT_s.a ]; then
        LIBC='/usr/lib/libNeXT_s.a'
    else
        LIBC=''
    fi
fi

if [ -n "$LIBC" ]; then
    echo "    Found C library in $LIBC."
    echo "    The next step may be slow.  Be patient."
    nm $LIBC >libc.list 2>/dev/null
    if [ ! -s libc.list ]; then ar t $LIBC >libc.list 2>/dev/null; fi
else
    echo "    I can't find your C library!"
    echo "    I'll need to make some assumptions.  If I'm wrong, edit Config."
    :>libc.list
fi

### Look for rand() or random().
### rand() is ANSI, but random() is more random.

if [ -z "$RAND" ]; then
    if egrep '(^|[^a-z])random([^a-z]|$)' libc.list >/dev/null 2>&1; then
        echo "    Found random() in your C library."
        RAND='-DRANDOM=random -DSRANDOM=srandom'
    elif egrep '(^|[^a-z])rand([^a-z]|$)' libc.list >/dev/null 2>&1; then
        echo "    Found rand() in your C library."
        RAND='-DRANDOM=rand -DSRANDOM=srand'
    elif [ "$ANSI_C" = "1" ]; then
        RAND='-DRANDOM=rand -DSRANDOM=srand'
        echo "    Since this is ANSI, I'm assuming you have rand()."
    else
        RAND='-DRANDOM=rand -DSRANDOM=srand'
        echo "    I can't find rand() or random().  I'll assume you have"
        echo "    rand().  If not, edit the RAND line in the Config file."
    fi
fi
FLAGS="$FLAGS $RAND"

### If this is POSIX, use getcwd().  If not, see if getcwd(), getwd(),
### or neither is available.  This isn't vital.

if [ "$POSIX" = "1" ]; then
    FLAGS="$FLAGS -DHAVE_GETCWD"
elif egrep '(^|[^a-z])getcwd([^a-z]|$)' libc.list >/dev/null 2>&1; then
    echo "    Found getcwd() in your C library."
    FLAGS="$FLAGS -DHAVE_GETCWD"
elif egrep '(^|[^a-z])getwd([^a-z]|$)' libc.list >/dev/null 2>&1; then
    echo "    Found getwd() in your C library."
    FLAGS="$FLAGS -DHAVE_GETWD"
else
    echo "    I can't find getwd() or getcwd().  No big deal."
fi

### Look for memcpy() or bcpy().

if egrep '(^|[^a-z])memcpy([^a-z]|$)' libc.list >/dev/null 2>&1; then
    echo "    Found mempcy() in your C library."
    FLAGS="$FLAGS -DHAVE_MEMCPY"
elif egrep '(^|[^a-z])bcpy([^a-z]|$)' libc.list >/dev/null 2>&1; then
    echo "    Found bcpy() in your C library."
    FLAGS="$FLAGS -DHAVE_BCPY"
else
    echo "    I can't find memcpy() or bcpy().  Good luck."
    if [ "$ANSI_C" = "1" ]; then
        echo "    Since this is ANSI, I'll assume you have memcpy()."
    else
        echo "    I'll assume you have bcpy()."
    fi
fi

### Look for strchr() or index().

if egrep '(^|[^a-z])strchr([^a-z]|$)' libc.list >/dev/null 2>&1; then
    echo "    Found strchr() in your C library."
    FLAGS="$FLAGS -DHAVE_STRCHR"
elif egrep '(^|[^a-z])index([^a-z]|$)' libc.list >/dev/null 2>&1; then
    echo "    Found index() in your C library."
    FLAGS="$FLAGS -DHAVE_INDEX"
else
    echo "    I can't find strchr() or index().  Good luck."
    if [ "$ANSI_C" = "1" ]; then
        echo "    Since this is ANSI, I'll assume you have strchr()."
    else
        echo "    I'll assume you have index()."
    fi
fi

### Look for strstr().

if egrep '(^|[^a-z])strstr([^a-z]|$)' libc.list >/dev/null 2>&1; then
    echo "    Found strstr() in your C library."
    FLAGS="$FLAGS -DHAVE_STRSTR"
else
    echo "    I can't find strstr().  That's okay, I'll use my own."
fi

### Look for strtol().

if egrep '(^|[^a-z])strtol([^a-z]|$)' libc.list >/dev/null 2>&1; then
    echo "    Found strtol() in your C library."
    FLAGS="$FLAGS -DHAVE_STRTOL"
else
    echo "    I can't find strtol().  That's okay, I'll use my own."
fi

### If we can't find gethostbyname() in libc, look for libresolv.

if [ "$SYSTEM" = "DYNIX_PTX" ] || [ "$SYSTEM" = "WINS" ]; then
    : We already know where to find the network libraries.
elif egrep '(^|[^a-z])gethostbyname([^a-z]|$)' libc.list >/dev/null 2>&1; then
    echo "    Found gethostbyname() in your C library."
else
    echo "    Your C library doesn't have gethostbyname()."
    if [ -r /lib/libresolv.a ]; then
        RESOLV='/lib/libresolv.a';
    elif [ -r /usr/lib/libresolv.a ]; then
        RESOLV='/usr/lib/libresolv.a';
    elif [ -r /usr/ccs/lib/libresolv.a ]; then
        RESOLV='/usr/ccs/lib/libresolv.a';
    else
        RESOLV=''
    fi
    if [ -n "$RESOLV" ]; then
        echo "    But, your system does have $RESOLV.  I'll link that in."
        LIBS="$LIBS -lresolv"
    else
        echo "    And, I can't find a 'resolv' library.  Good luck."
    fi
fi

rm libc.list

### Figure out which terminal driver to use.

if [ "$POSIX" = "1" ]; then
    if [ -z "$TTYDRIVER" ]; then
        TTYDRIVER=-DUSE_TERMIOS
    fi
elif [ -z "$TTYDRIVER" ]; then
    if [ -r ${INCDIR}/termios.h ]; then
        echo "    Your system has termios.h, but doesn't define _POSIX_VERSION?"
        echo "    Okay, I'll use termios.h.  Edit Config if it doesn't work."
        TTYDRIVER="-DUSE_TERMIOS"
    elif [ -r ${INCDIR}/termio.h ] && [ -r ${INCDIR}/sgtty.h ]; then
        echo "    Your system has both termio.h and sgtty.h, but not termios.h."
#       Make a semi-educated guess, and warn the user.
#       Many USG systems have uname, many BSD systems don't.
        if { uname; } >/dev/null 2>&1; then
            TTYDRIVER="-DUSE_TERMIO"
            echo "    I'm going to assume I should use termio.h."
            echo "    If I'm wrong, set TTYDRIVER='-DUSE_SGTTY' in Config."
        else
            TTYDRIVER="-DUSE_SGTTY"
            echo "    I'm going to assume I should use sgtty.h."
            echo "    If I'm wrong, set TTYDRIVER='-DUSE_TERMIO' in Config."
        fi
    elif [ -r ${INCDIR}/termio.h ]; then
#       Only termio.h is available.
        echo "    Your system has termio.h."
        TTYDRIVER="-DUSE_TERMIO"
    elif [ -r ${INCDIR}/sgtty.h ] || [ -r ${INCDIR}/bsd/sgtty.h ]; then
#       Only sgtty.h is available.
        echo "    Your system has sgtty.h."
        TTYDRIVER="-DUSE_SGTTY"
    else
        echo "    I can't find any terminal driver headers on your system!"
        echo "    I'm going to try using sgtty.h anyway."
        echo "    If I'm wrong, edit Config and set TTYDRIVER yourself."
    fi
fi
FLAGS="$FLAGS $TTYDRIVER"

if [ -z "$TERMINAL" ]; then
    TERMINAL=-DTERMCAP
fi
if [ "$TERMINAL" = "-DTERMCAP" ]; then
    LIBS="$LIBS -ltermcap"
fi

DEFS="$DEFS MAILDIR=${MAILDIR}"

### If there were command line arguments, those are the make targets.
### Otherwise, make the default targets.

if [ -n "$*" ]; then
    TARGETS="$*"
else
    TARGETS="$EXE $TFLIBRARY"
    if [ -n "$CONNECT" ]; then
        TARGETS="$TARGETS $TFCONNECT"
    fi
    if [ "$HELPFILE" != "/dev/null" ]; then
        TARGETS="$TARGETS HELP"
    fi
    if [ -n "$MANPAGE" ]; then
        TARGETS="$TARGETS $MANPAGE"
    fi
fi

if [ -n "$CONNECT" ]; then
    FLAGS="$FLAGS -D$CONNECT"
fi

FLAGS="$FLAGS $TERMINAL $RESTRICT $CCFLAGS"

OBJS="main.o world.o util.o socket.o keyboard.o macro.o search.o \
command1.o command2.o special.o history.o process.o output.o \
expand.o dstring.o help.o signal.o variable.o tfio.o malloc.o"

if [ -z "$CONNECT" ]; then
    OBJS="$OBJS opensock.o"
fi

if [ -n "$DMALLOC" ]; then
    FLAGS="$FLAGS -DDMALLOC"
    OBJS="$OBJS dmalloc.o"
fi

### Last chance.

echo
echo "#### If any of my assumptions were wrong, press ^C now and edit Config."
echo

### Do it.

cd ./src

echo "$MAKE $DEFS FLAGS=\"$FLAGS\" LIBS=\"$LIBS\" OBJS=\"$OBJS\" \
    OPT=\"$OPT\" $TARGETS"

if $MAKE $DEFS FLAGS="$FLAGS" LIBS="$LIBS" OBJS="$OBJS" OPT="$OPT" $TARGETS
then
    if [ -z "$*" ]; then
        echo
        echo "#### TinyFugue Build successful."
        echo "#### You may remove the `/bin/pwd` directory if you wish."
        echo "#### But first check out CHANGES and examples."
    fi
else
    echo
    echo '#### TinyFugue Build FAILED.'
    echo '#### Read README to find out how to correct the problem.'
fi

} 2>&1 | tee Build.log
