#! /bin/sh
#----------------------------------------------------------------------------
#   c           Compile ANSI C program ('UNIX' multiplatform, includes OS/2)
#
#   Written:    95/03/10  iMatix <tools@imatix.com>
#   Revised:    98/01/27  iMatix <tools@imatix.com>
#
#   Authors:    General: Pieter Hintjens <ph@imatix.com>
#               For OS/2: Ewen McNeill <ewen@imatix.com>
#               For SCO: Vance Shipley <vances@vambo.telco.on.ca>
#               For FreeBSD: Bruce Walter <walter@fortean.com>
#
#   Syntax:     c filename...     Compile ANSI C program(s)
#               c -l main...      Compile and link main program(s)
#               c -L main...      Link main program(s), no compile
#               c -S              Report detected system name
#               c -C              Report C compiler command syntax
#               c -r lib file     Replace file.o into library
#
#   Requires:   Bourne shell
#   Usage:      Compiles a subroutine or compiles/links a main program.
#               When linking, searches all libraries (lib*.a) in the current
#               directory, and libsfl.a in /usr/lib if it exists.
#               Assumes the compiler is called 'cc' if you don't set CCNAME
#               to something else in your environment.  Defines the compiler
#               symbol "-D DEBUG" unless you set CCDEFINES to something else
#               in your environment.  Searches libraries specified in CCLIBS.
#               Does SQL precompilation if required (currently does Oracle).
#               Return code: 0 = okay, 1 = compile error.
#
#   Copyright:  Copyright (c) 1995-98 iMatix
#   License:    This is free software; you can redistribute it and/or modify
#               it under the terms of the SFL License Agreement as provided
#               in the file LICENSE.TXT.  This software is distributed in
#               the hope that it will be useful, but without any warranty.
#----------------------------------------------------------------------------

#   Detect UNIX system type.  This algorithm returns one of these system
#   names, as far as I know at present:
#
#       AIX      APOLLO   A/UX     BSD/OS    FreeBSD   HP-UX    IRIX
#       Linux    NCR      NetBSD   NEXT      OSF1      SCO      Pyramid
#       SunOS    ULTRIX   OS/2     UnixWare  Generic   SINIX-N
#
#   Sets the variable UTYPE to one of the UNIX system names above, and
#   CCOPTS to the appropriate compiler options for ANSI C compilation.

UTYPE=Generic                       #   Default system name
if [ -s /usr/bin/uname       ]; then UTYPE=`/usr/bin/uname`; fi
if [ -s /bin/uname           ]; then UTYPE=`/bin/uname`;     fi

if [ -s /usr/apollo/bin      ];               then UTYPE=APOLLO;   fi
if [ -s /usr/bin/ncrm        ];               then UTYPE=NCR;      fi
if [ -s /usr/bin/swconfig    ];               then UTYPE=SCO;      fi
if [ -s /usr/lib/NextStep/software_version ]; then UTYPE=NEXT;     fi
if [ "$UTYPE" = "SMP_DC.OSx" ];               then UTYPE=Pyramid;  fi
if [ -d /var/sadm/pkg/UnixWare ];             then UTYPE=UnixWare; fi
if [ -n "$COMSPEC" -o -n "$OS2_SHELL" ];      then UTYPE=OS/2;     fi

#   If CCDEFINES is not already set by the caller, we'll use "-DDEBUG".
#   You can set this to " " to switch-off debug support (e.g. assertions)
#   or add your own definitions.
#
test "$CCDEFINES" = "" && CCDEFINES="-DDEBUG"

#   Set specific system compiler options and other flags
#   CCOPTS      Compiler options, except -c
#   LINKPATH    If 1, -L path must come before library list
#   RANLIB      Use ranlib command to reindex library; else use 'ar rs'
#
LINKPATH=0                              #   By default, accept '-lsfl... -L.'
if [ "$CCNAME" = "gcc" ]; then
    CCOPTS="-O2 -Wall -pedantic"

elif [ "$UTYPE" = "AIX" ]; then
    CCOPTS="-O"

elif [ "$UTYPE" = "BSD/OS" ]; then
    CCOPTS="-O -Dbsd"
    RANLIB=1

elif [ "$UTYPE" = "FreeBSD" ]; then
    CCOPTS="-O2 -Wall -pedantic"
    test "$CCNAME" = "" && CCNAME="gcc"
    RANLIB=1

elif [ "$UTYPE" = "HP-UX" ]; then
    CCOPTS="-O -Aa"
    LINKPATH=1

elif [ "$UTYPE" = "Linux" ]; then
    CCOPTS="-O2 -Wall -pedantic"
    test "$CCNAME" = "" && CCNAME="gcc"

elif [ "$UTYPE" = "NetBSD" ]; then
    RANLIB=1

elif [ "$UTYPE" = "OS/2" ]; then
    #  EDM, 96/04/02: -Zsysv-signals turns on SysV-style signal handling
    #  which is used in a lot of iMatix code.
    CCOPTS="-O2 -Wall -pedantic -Zsysv-signals"
    test "$CCNAME" = "" && CCNAME="gcc"

elif [ "$UTYPE" = "SCO" ]; then
    CCOPTS="-Dsco"                      #   -O switch can cause problems
    LINKPATH=1

elif [ "$UTYPE" = "SunOS" ]; then
    CCOPTS="-O -Xa"
    LINKPATH=1

elif [ "$UTYPE" = "UnixWare" ]; then
    LINKPATH=1

elif [ "$UTYPE" = "SINIX-N" ]; then
    CCOPTS="-WO"

else
    CCOPTS=""
fi
CCOPTS="$CCOPTS $CCDEFINES"

#   If CCNAME is not already set by the caller, we'll use 'cc'.  You may
#   want to use 'gcc' for GNU C, or 'acc' on some Sun installations.
#
test "$CCNAME" = "" && CCNAME="cc"

#   Build list of libraries to link with
#   Modified for OS/2, EDM, 96/12/30 (OS/2 uses name.a, rather than libname.a)

LIBSFL=0
LIBLIST=""
for LIBRARY in lib*.a; do
    test $LIBRARY = "lib*.a" && break
    LIBNAME=`echo $LIBRARY | cut -d"." -f1 | cut -c4-`

    #  libsfl.a must come last, so we will just flag it
    if [ "$LIBNAME" = "sfl" ]; then
        LIBSFL=1
    else
        #  In OS/2 we must link with the whole name, including lib prefix
        if [ "$UTYPE" = "OS/2" ]; then
             LIBNAME=`echo $LIBRARY | cut -d"." -f1`
        fi
        LIBLIST="$LIBLIST -l$LIBNAME"
    fi
done

#   Build list of libraries to include in the link command, including those
#   referred to by libsfl.a:
#
#      - /usr/lib/libsfl.a, if not found locally
#      - /local/emx/lib/libsfl.a, under OS/2, if present
#      - /usr/lib/libsocket.a, if found in /usr/lib
#      - /usr/lib/libnsl.a, if found in /usr/lib
#      - the $CCLIBS variable
#
#   Modified for OS/2, by EDM, 96/12/30 (we look for libsfl.a in two places)

if [ "$UTYPE" = "OS/2" ]; then
    if test $LIBSFL -eq 1 \
    -o -f /usr/lib/libsfl.a \
    -o -f /local/emx/lib/libsfl.a; then
       LIBLIST="$LIBLIST -llibsfl -lsocket"
    fi
else
    if test $LIBSFL -eq 1 \
    -o -f /usr/lib/libsfl.a; then
        LIBLIST="$LIBLIST -lsfl"
        test -f /usr/lib/libsocket.a && LIBLIST="$LIBLIST -lsocket"
        test -f /usr/lib/libnsl.a    && LIBLIST="$LIBLIST -lnsl"
    fi
fi
LIBLIST="$LIBLIST $CCLIBS"

#   Show help if no arguments
if test /$1/ = //; then
    echo "Detected system=$UTYPE, compiles with $CCNAME -c $CCOPTS"
    echo "Syntax: c filename...  Compile ANSI C program(s)"
    echo "        c -l main...   Compile and link main program(s)"
    echo "        c -L main...   Link main(s) with" ${LIBLIST-"no libraries"}
    echo "        c -S           Report detected system name"
    echo "        c -C           Report C compiler command syntax"
    echo "        c -r lib file  Replace file into specified library"
    exit
fi

#   -S means report system type
if [ /$1/ = /-S/ ]; then
    echo "$UTYPE"
    exit
fi

#   -C means report compiler syntax type
if [ /$1/ = /-C/ ]; then
    echo "$CCNAME -c $CCOPTS"
    exit
fi

#   -r means replace object file into library
#   The RANLIB symbol should be set to 1 if 'ar rs' does not work.
#   If the library is specified as 'any', uses value of CCLIBNAME, or
#   first lib*.a file in directory.  Creates library if necessary.
#   If 'any' library is specified but no library exists and CCLIBNAME
#   is not defined, uses libany.a.
#
if [ /$1/ = /-r/ ]; then
    if [ /$2/ = /any/ ]; then
        if [ "$CCLIBNAME" != "" ]; then
            LIBRARY=$CCLIBNAME
        else
            LIBRARY=libany.a
            for LIBFILE in lib*.a; do
                if test -f $LIBFILE; then
                    LIBRARY=$LIBFILE
                    break
                fi
            done
        fi
    fi
    LIBNAME=`echo $LIBRARY | cut -d"." -f1`
    OBJECT=`echo $3 | cut -d"." -f1`.o
    echo "Replacing object $OBJECT in library $LIBRARY..."
    if [ "$RANLIB" = "1" ]; then
        ar r $LIBNAME.a $OBJECT
        ranlib $LIBNAME.a
    else
        ar rs $LIBNAME.a $OBJECT
    fi
    exit
fi

#   Compile/link main if -l is first argument
if [ /$1/ = /-l/ ]; then
    LINKUP=yes
    shift
fi

#   Link main if -L is first argument
if [ /$1/ = /-L/ ]; then
    LINKUP=yes
    COMPILE=no
    shift
else
    COMPILE=yes
fi

#   Compile and maybe link each filename on the command line
for i in $*; do
    shift
    FILENAME=`echo $i | cut -d"." -f1`

    #   Precompilation is required if program contains 'EXEC SQL'
    egrep "EXEC SQL" $FILENAME.c >/dev/null
    if [ $? -eq 0 ]; then
        PRECOMPILE=yes
    else
        PRECOMPILE=no
    fi

    if test "$COMPILE" = "yes" -o ! -f $FILENAME.o; then
        if [ "$PRECOMPILE" = "yes" ]; then
            mv $FILENAME.c $FILENAME.pc
            if [ /$ORACLE_HOME/ != // ]; then
                nice proc16 $PCCFLAGS code=ansi_c ireclen=255 \
                            iname=$FILENAME.pc oname=$FILENAME.c
            fi
        fi
        test -f $FILENAME.o && rm $FILENAME.o
        echo "Compiling $FILENAME..."
        nice $CCNAME -c $CCOPTS $FILENAME.c 2> $FILENAME.lst
        STATUS=$?
        test "$PRECOMPILE" = "yes" && mv $FILENAME.pc $FILENAME.c

        if [ $STATUS -eq 0 ]; then
            cat $FILENAME.lst
            rm  $FILENAME.lst

            #   Insert compiled object into local library unless it is
            #   a 'main (' function.  Uses any local library file.
            egrep "main *\(" $FILENAME.c >/dev/null
            test $? -eq 1 && ./c -r any $FILENAME
        else
            cat $FILENAME.lst
            exit 1
        fi
    fi
    #  If okay, link if required; else show error listing
    if [ "$LINKUP" = "yes" ]; then
        echo Linking $FILENAME...
        if   [ "$UTYPE" = "OS/2" ]; then
            nice $CCNAME $CCOPTS $FILENAME.o -o $FILENAME.exe $LIBLIST -L. \
                2> $FILENAME.lst
        elif [ "$LINKPATH" = "1" ]; then
            nice $CCNAME $CCOPTS $FILENAME.o -o $FILENAME -L. $LIBLIST \
               2> $FILENAME.lst
        else
            nice $CCNAME $CCOPTS $FILENAME.o -o $FILENAME $LIBLIST -L. \
               2> $FILENAME.lst
        fi
        if [ $? -eq 0 ]; then
            cat $FILENAME.lst
            rm  $FILENAME.lst
        else
            cat $FILENAME.lst
            exit 1
        fi
    fi
done
