#!/bin/sh
#
# Shell script for compiling Curry modules
#
# $Id: cyc.in,v 1.8 2004/12/06 18:19:47 berrueta Exp $
#
# Copyright (c) 2002, Wolfgang Lux
# See LICENSE for the full license.
#

# Configuration parameters
cyc=`basename $0`
version=\1.0.2
build="20050329"
prefix=/usr
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
libdir=${exec_prefix}/lib
: ${CURRY_BIN=${exec_prefix}/bin}
: ${CURRY_AUX_BIN=${exec_prefix}/lib/zinc-compiler}
: ${CURRY_RTS_LIBS=${exec_prefix}/lib}
: ${CURRY_IMPORTS=${prefix}/include/libcurry-stdlib}
: ${CURRY_RTS_INCLUDE=${prefix}/include/libcurry-rts}
: ${CC="x86_64-linux-gcc "}
export CURRY_BIN CURRY_AUX_BIN CURRY_RTS_LIBS CURRY_IMPORTS CURRY_RTS_INCLUDE

# Local variables
exec=
verbose=
toC=
toS=
toO=
cycc=${CURRY_AUX_BIN}/cycc
cyccopts=
rtopts=
debug=
ccopts=
ldopts="-L${CURRY_RTS_LIBS} "
hsize=
ssize=
tsize=
stats=
trace=
saveTemps=
libs=
dbglib=
curry=
files=
temps=
linkfiles=
imports="-i ${CURRY_IMPORTS} "
main=
goal=
typeIt=
ofile=
gc=

# functions
check_size ( ) {
    eval _x=\$"$2"
    case $_x in
      "" ) echo 1>&2 "$cyc: missing size after $1"; exit 1;;
      *[kK] ) _y=`expr "$_x" : '\([0-9]*\)[kK]$'`"*k";;
      *[mM] ) _y=`expr "$_x" : '\([0-9]*\)[mM]$'`"*M";;
      * ) _y=`expr "$_x" : '\([0-9]*\)$'`;;
    esac
    case $_y in
      [0-9]* ) eval $2=$_y;;
      * ) echo 1>&2 "$cyc: illegal size after $1: $_x"; exit 1;;
    esac
}

incr ( ) {
    eval _x=\$"$1"; test -n "$_x" || _x=0
    _y="$2"; test -n "$_y" || _y=1
    eval $1=`expr "$_x" + "$_y"`
}

# Option processing
while test $# -gt 0; do
  case $1 in
    # Version
    --version ) verbose=-v;;

    # Overall options
    -c ) toO=1;;
    -C ) toC=1;;
    -S ) toS=1;;
    -o ) ofile=$2; shift;;
    -o* ) ofile=`expr "$1" : '-o\(.*\)'`;;
    -n ) exec=echo;;
    -v ) verbose=-v; ccopts="$ccopts -v";;

    # (C-)Preprocessor definitions
    -[DU] ) ccopts="$ccopts $1 $2"; shift;;
    -[DU]* ) ccopts="$ccopts $1";;

    # Special definitions
    -gg ) debug=-g;;
    -gc-2space | --gc-2space ) gc=;;
    -gc-compact | --gc-compact ) gc="$CURRY_RTS_LIBS/gc_compact.o";;
    -save-temps ) saveTemps=$1;;

    # cyc options
    -no-intf | --no-intf | -no-icurry | --no-icurry ) 
	cyccopts="$cyccopts --no-icurry";;
    -dump* ) cyccopts="$cyccopts -$1";;
    --dump* ) cyccopts="$cyccopts $1";;
    -g | -debug | --debug ) cyccopts="$cyccopts --debug"; dbglib=-lcurry_g;;
    -trusted | --trusted ) cyccopts="$cyccopts --trusted";;

    # goal options
    -M ) main=$2; shift;;
    -M* ) main=`expr "$1" : '-M\(.*\)'`;;
    -e ) goal=$2; shift;;
    -e* ) goal=`expr "$1" : '-e\(.*\)'`;;
    -y ) typeIt=$2; shift;;
    -y* ) typeIt=`expr "$1" : '-t\(.*\)'`;;

    # C Compiler options
    -cc ) CC=$2; shift;;
    -ccopts-* | --ccopts-* ) ccopts=$ccopts\ `expr "$1" : '-*ccopts\(.*\)'`;;
    -ccopts | --ccopts ) ccopts="$ccopts $2"; shift;;
    -O* ) ccopts="$ccopts $1";;

    # Include files and imported modules
    -I ) ccopts="$ccopts -I$2"; shift;;
    -I* ) ccopts="$ccopts $1";;
    -i ) ccopts="$ccopts -I$2"; imports="$imports -i $2"; shift;;
    -i* ) ccopts="$ccopts -I`expr "$1" : '-i\(.*\)'`"; imports="$imports $1";;

    # Linker options
    -ldopts-* |--ldopts-* ) ldopts=$ldopts\ `expr "$1" : '-*ldopts\(.*\)'`;;
    -ldopts | --ldopts ) ldopts="$ldopts $2"; shift;;
    -L ) ldopts="$ldopts -L$2"; shift;;
    -L* ) ldopts="$ldopts $1";;
    -l ) libs="$libs -l$2"; shift;;
    -l* ) libs="$libs $1";;

    # Runtime system options for cycc
    -H* ) rtopts="$rtopts $1";;
    +RTS )
	shift
	while test $# -gt 0 -a "$1" != "-RTS"; do
	  rtopts="$rtopts $1";
	  shift
	done;;

    # Default values for the executable
    -d ) incr trace 1;;
    -p ) incr stats 1;;
    -h ) hsize=$2; shift; check_size -h hsize;;
    -h* ) hsize=`expr "$1" : '-h\(.*\)'`; check_size -h hsize;;
    -k ) ssize=$2; shift; check_size -k ssize;;
    -k* ) ssize=`expr "$1" : '-k\(.*\)'`; check_size -k ssize;;
    -t ) tsize=$2; shift; check_size -t tsize;;
    -t* ) tsize=`expr "$1" : '-t\(.*\)'`; check_size -t tsize;;

    # Pass all other flags to the C compiler
    -* ) ccopts="$ccopts $1";;

    # Save all files
    * ) files="$files $1";;
  esac
  shift
done

# Add runtime options to cycc
test -n "$rtopts" && cycc="$cycc +RTS $rtopts -RTS"

# Eventually display the compiler version
if test -n "$verbose"; then
  echo 1>&2 "Zinc $cyc version $version (built on $build)"
  test "$exec" && verbose=
fi
# Check for conflicting options
if test -n "$goal" -a -n "$typeIt"; then
  echo 1>&2 "$cyc: only of -e and -t must be specified"
  exit 1
fi

# Check for input files
if test -z "$files$goal$typeIt"; then
  test -n "$verbose" && exit 0
  echo 1>&2 "$cyc: no input files"
  exit 1
fi

# Add runtime includes to the C compiler include search path
ccopts="$ccopts -I$CURRY_RTS_INCLUDE"

# Add all default include directories to the C compiler's flags
ifs=$IFS
IFS=:
for d in $CURRY_IMPORTS; do 
  ccopts="$ccopts -I$d"; ldopts="$ldopts -L$d"
done
IFS=$ifs

# Cygpath workaround: converts path to Windows-style
if test -n ""; then
  CURRY_IMPORTS=` -w -p $CURRY_IMPORTS`
fi

# Remove all temporary files upon exit
# NB check for empty temps for non POSIX compliant rm's (e.g. Mac OS X 10.1)
trap 'test "$temps" && rm -f $temps' 0 1 2 3 15

# Process all files
set -- $files
if test -n "$ofile" -a -n "$toC$toS$toO" -a $# -gt 1; then
  echo 1>&2 "$cyc: cannot specify -o with -c, -S, or -C and multiple input files"
  exit 1
fi

if test -n "$typeIt"; then
  if test $# -gt 1; then
    echo 1>&2 "$cyc: cannot specify -t with multiple input files"
    exit 1
  fi

  test -n "$verbose" && echo 1>&2 $cycc $imports -t \"$typeIt\" $cyccopts $1
  $exec $cycc $imports -t "$typeIt" $cyccopts ${1-$main}
  exit $?
fi

i=0
for f in $files; do
  i=`expr $i + 1`
  stem=

  # Compile Curry source files into C code
  case $f in
    *.curry | *.lcurry )
      curry=$f
      stem=`expr "$f" : '\(.*\)\.curry'`
      stem=$stem`expr "$f" : '\(.*\)\.lcurry'`
      if test -n "$toC"; then
        if test -n "$ofile"; then
	  target=$ofile
	else
	  target=$stem.c
	fi
      else
        if test -n "$debug$saveTemps"; then
	  target=$stem.c
	else
          target=/tmp/cyc$$_$i.c
	  temps="$temps $target"
	fi
      fi
      # Cygpath workaround: converts paths to Windows-style
      if test -n ""; then
        target2=` -w $target`
        f2=` -w $f`
       else 
        target2=$target
        f2=$f
      fi
      test -n "$verbose" && echo 1>&2 $cycc $imports $cyccopts -o $target2 $f2
      $exec $cycc $imports $cyccopts -o $target2 $f2 || exit $?
      # End of Cygpath workaround
      f=$target
      ;;
  esac
  test -n "$toC" && continue

  # Compile C/assembler code into assembler code or object files
  case $f in
    *.[cs] )
      test -n "$stem" || stem=`expr "$f" : '\(.*\)\.[cs]'`
      if test -n "$toS"; then c=-S suffix=.s; else c=-c suffix=.o; fi
      if test -n "$toS$toO"; then
        if test -n "$ofile"; then
	  target=$ofile
	else
	  target=$stem$suffix
	fi
      else
        if test -n "$saveTemps"; then
	  target=$stem.o
	else
          target=/tmp/cyc$$_$i.o
	  temps="$temps $target"
	fi
      fi
      test -n "$verbose" && echo 1>&2 $CC $ccopts $debug $saveTemps $c -o $target $f
      $exec $CC $ccopts $debug $saveTemps $c -o $target $f || exit $?
      f=$target
      ;;
  esac
  test -n "$toS$toO" && continue

  # Add all files for the link step
  linkfiles="$linkfiles $f"
done

# Eventually link the program
if test -z "$toC$toS$toO"; then
  temps="$temps /tmp/cyc$$.c"
  if test -n "$goal"; then
    test -n "$main" || main="$curry"
    case $main in
      "" | *.curry | *.lcurry ) ;;
      * ) test -f $main.curry && main=$main.curry
	  test -f $main.lcurry && main=$main.lcurry;;
    esac
  fi
  # Cygpath workaround: converts path to Windows-style
  target=/tmp/cyc$$.c
  if test -n ""; then
    target2=` -w $target`
  else
    target2=$target
  fi
  test -n "$verbose" && echo 1>&2 $cycc $imports -e\"$goal\" $cyccopts $main -o $target2
  $exec $cycc $imports $cyccopts -e"$goal" $main -o $target2 || exit $?
  # End of Cygpath workaround

  test -n "$hsize" && ldopts="$ldopts -DDEFAULT_HEAPSIZE=$hsize"
  test -n "$ssize" && ldopts="$ldopts -DDEFAULT_STACKSIZE=$ssize"
  test -n "$tsize" && ldopts="$ldopts -DDEFAULT_TRAILSIZE=$tsize"
  test -n "$stats" && ldopts="$ldopts -DDEFAULT_SHOW_STATS=$stats"
  test -n "$trace" && ldopts="$ldopts -DDEFAULT_DO_TRACE=$trace"
  test -n "$ofile" && ldopts="$ldopts -o $ofile"
  test -n "$verbose" && echo 1>&2 $CC $ccopts $ldopts $debug $lddefs /tmp/cyc$$.c $linkfiles $gc $libs $dbglib -lcurry
  $exec $CC $ccopts $ldopts $debug $lddefs /tmp/cyc$$.c $linkfiles $gc $libs $dbglib -lcurry || exit $?
fi

# done
exit 0
