#!/bin/sh

## Compile and link the modules in the specified directory to a shared library

## Location of the header files (adjust this to an absolute path)
INCLUDES="-I./Compilation/runtime"
## Definitions to pass to the C compiler
##  RED_BLACK:
##	keep multi-sets in red-black trees instead of unbalanced trees
##	(useful if the places in the net have more than a few tokens)
##  NO_INVARIANT_CHECK(p)
##	even if the (p+1)th place defined in the net
##	has a marking-dependent initialization expression,
##	do not check its validity when encoding markings
##	(use only if you are sure that the invariants hold)
##  TRANSITION_EMPTY(t)
##	before instance analysis, check whether any of the inputs
##	has an insufficient number of tokens for the (t+1)th transition
##	defined in the net to be enabled
##	(may be useful for seldomly enabled transitions)
#: ${DEFINES="-DRED_BLACK"}
#: ${DEFINES="-DRED_BLACK -D'NO_INVARIANT_CHECK(p)=1'"}
: ${DEFINES="-DRED_BLACK -D'TRANSITION_EMPTY(t)=1' -D'NO_INVARIANT_CHECK(p)=1'"}

## Function to execute compiler and linker commands
perform() { eval "$@" || exit $?; }
#perform() { echo "$@" >&2; eval "$@" || exit $?; }

set -eu
<&-

case "`uname`" in
Linux|FreeBSD|NetBSD|OpenBSD)
    : ${CC="gcc"}
    : ${CFLAGS="-ansi -O3 -fomit-frame-pointer"}
    : ${LD="ld"}
    : ${LDFLAGS="-shared -s -lc"}
    ;;
AIX)
    : ${CC="gcc"}
    : ${CFLAGS="-ansi -O3 -fomit-frame-pointer"}
    : ${LD="gcc"}
    : ${LDFLAGS="-shared -s -lc"}
    ;;
OSF1)
    : ${CC="cc"}
    : ${CFLAGS="-arch host -assume trusted_short_alignment -O5 -std1"}
    : ${LD="ld"}
    : ${LDFLAGS="-shared -s -lc"}
    ;;
HP-UX)
    : ${CC="cc"}
    : ${CFLAGS="-fast"}
    : ${LD="ld"}
    : ${LDFLAGS="-b -s -lc"}
    ;;
SunOS)
    : ${CC="gcc"}
    : ${CFLAGS="-ansi -Werror -O3 -fomit-frame-pointer"}
    : ${LD="ld"}
    : ${LDFLAGS="-G -s -lc"}
    ;;
IRIX64)
    : ${CC="cc"}
    : ${CFLAGS="-n32 -O2"}
    : ${LD="ld"}
    : ${LDFLAGS="-n32 -shared -s -lc"}
    ;;
Darwin)
    : ${CC="cc"}
    : ${CFLAGS="-ansi -O3 -fomit-frame-pointer -fno-common"}
    : ${LD="ld"}
    : ${LDFLAGS="-dynamic -bundle -lbundle1.o -lc"}
    ;;
*)
    echo "Unknown operating system." >&2
    exit 1
    ;;
esac

DIR="${1:-}"
LIB="${2:-}"
[ $# -ge 2 -a -d "$DIR" ] || \
{
    echo "Usage: $0 directory library.so source1.c source2.c ..." >&2
    exit 1
}

shift 2
if [ $# -eq 1 ]
then
    i="`basename "$1" .c`"
    perform $CC $DEFINES $CFLAGS -I"$DIR" $INCLUDES \
	    -c "$DIR/$i.c" -o "$DIR/$i.o"
    perform $LD -o "$LIB" "$DIR/$i.o" $LDFLAGS
    exit
fi
(
    cd "$DIR"
    cksum mset.h > mset.sum1
    cmp -s mset.sum mset.sum1 || rm -f c.sum || exit $?
    mv -f mset.sum1 mset.sum
    cksum "$@" > c.sum1
    touch c.sum
) || exit $?

diff "$DIR/c.sum" "$DIR/c.sum1" \
| sed -ne 's/^> [0-9]*[ 	]*[0-9]*[ 	]*\(.*\)\.c$/\1/p' \
| {
    NEED_LINK=""
    while read i
    do
	perform $CC $DEFINES $CFLAGS -I"$DIR" $INCLUDES \
		-c "$DIR/$i.c" -o "$DIR/$i.o"
	NEED_LINK=true
    done
    mv -f "$DIR/c.sum1" "$DIR/c.sum"
    if [ -n "$NEED_LINK" -o ! -f "$LIB" ]
    then
	perform $LD -o "$LIB" `sed -ne '{i\\
'"$DIR/"'
s/[0-9]*[ 	]*[0-9]*[ 	]*\(.*\)\.c$/\1.o /p
}' < "$DIR/c.sum" | tr -d \\\\012` $LDFLAGS
    fi
}
