#!/bin/sh
# -*- Shell-script -*-

unixize () {
    echo "$1" | sed -e 's%\\\\%/%g' | sed -e 's%^\([A-Za-z]\):%/\1%'
}

setup_vars() {
  if [ -z "$MAXIMA_VERSION" ]; then
    MAXIMA_VERSION="5.42.0"
  fi
  prefix=`unixize "/usr"`
  exec_prefix=`unixize "${prefix}"`
  PACKAGE=maxima
  top_srcdir=`unixize "/build/maxima-ecl/src/maxima-5.42.0"`
  libdir=`unixize "${exec_prefix}/lib"`
  if [ -n "$MAXIMA_LAYOUT_AUTOTOOLS" ]; then
      layout_autotools="$MAXIMA_LAYOUT_AUTOTOOLS"
  else
      layout_autotools=true
  fi
  if [ "$layout_autotools" = "true" ]; then
      MAXIMA_DEFAULT_IMAGESDIR=$libdir/$PACKAGE/$MAXIMA_VERSION
  else
      MAXIMA_DEFAULT_IMAGESDIR=$top_srcdir/src
  fi  
  if [ -n "$MAXIMA_PREFIX" ]; then
      if [ "$layout_autotools" = "true" ]; then
	  MAXIMA_IMAGESDIR=`unixize "$MAXIMA_PREFIX"`/lib/$PACKAGE/$MAXIMA_VERSION
      else
	  MAXIMA_IMAGESDIR=`unixize "$MAXIMA_PREFIX"`/src
      fi  
  else
      MAXIMA_IMAGESDIR="$MAXIMA_DEFAULT_IMAGESDIR"
  fi
  MAXIMA_DEFAULT_LISP=ecl
  # If the the binary directory for the default lisp is not present,
  # choose the first one we find.
  if [ ! -d "$MAXIMA_IMAGESDIR/binary-$MAXIMA_DEFAULT_LISP" ]; then
    MAXIMA_DEFAULT_LISP=`ls -1 $MAXIMA_IMAGESDIR 2>/dev/null | head -n 1 | sed 's/binary-//'`
  fi
  if [ -z "$MAXIMA_LISP" ]; then
    MAXIMA_LISP=$MAXIMA_DEFAULT_LISP
  fi
}

unsetup_vars () {
  unset MAXIMA_IMAGESDIR
  unset MAXIMA_LISP
}

process_userdir_argument() {
    while [ -n "$1" ]; do
        case $1 in 
        --userdir ) MAXIMA_USERDIR=$2 ; shift;;
        --userdir=* ) MAXIMA_USERDIR=`echo "$1" | sed 's/--userdir=//'` ;;
        esac
        shift
    done
if [ -n "$MAXIMA_USERDIR" ]; then
    export MAXIMA_USERDIR
fi
}

# make a special check for --userdir argument, because it influences location
# of maximarc, which is sourced before  other command-line options are
# processed
process_userdir_argument "$@"

if [ -z "$MAXIMA_USERDIR" ]; then
  maximarc_path="$HOME/.maxima/maximarc"
else
  maximarc_path="`unixize \"$MAXIMA_USERDIR\"`/maximarc"
fi
if [ -f "$maximarc_path" ]; then
  . "$maximarc_path"
fi

# For some reason TeXmacs sets MAXIMA_DIRECTORY to the empty string,
# which breaks maxima's internal path logic. This is a workaround.
if [ -z "$MAXIMA_DIRECTORY" ]; then
  unset MAXIMA_DIRECTORY
fi

# GCL in its default settings tends to run out of memory frequently quickly.
# For example 8 Gigabytes of RAM aren't enough to run the testbench when sbcl
# and clisp need <0,5 Gigabytes by default.
# The following lines make GCL's garbage collector more aggressive by default.
if [ -z "$GCL_GC_PAGE_THRESH" ]; then
    export GCL_GC_PAGE_THRESH=0.05
fi;
if [ -z "$GCL_GC_ALLOC_MIN" ]; then
    export GCL_GC_ALLOC_MIN=0.01
fi;
if [ -z "$GCL_GC_PAGE_MAX" ]; then
    export GCL_GC_PAGE_MAX=0.05
fi;


# GCL also by default tells the garbage collector to limit the memory usage to
# allocate half of the physical RAM installed in the current machine.
# Which works fine in a single-user system and even takes in account the amount
# of memory the other gcl processes use but is too far in the multitasking versus
# speed tradeoff for us.
#
# See also:
# https://lists.gnu.org/archive/html/gcl-devel/2017-09/msg00000.html
if [ -z "$GCL_MEM_MULTIPLE" ]; then
    export GCL_MEM_MULTIPLE=0.2
fi;

# Will be promoted to be gcl's default. But for the time being: Allow concurrent
# gcl processes to communicate about how much memory each of them can use.
if [ -z "$GCL_MULTIPROCESS_MEMORY_POOL" ]; then
    export GCL_MULTIPROCESS_MEMORY_POOL=t
fi;

# process the command line arguments. This must be done in a function, because
# "shift" should only shift the function parameters, not the global parameters.
process_commandline_arguments() {
    while [ -n "$1" ]; do
	case $1 in
	    -l|--lisp ) MAXIMA_LISP=$2 ; shift;;
	    --lisp=*) MAXIMA_LISP=`echo "$1" | sed 's/--lisp=//'` ;;
	    -u|--use-version ) MAXIMA_VERSION=$2 ; shift;;
	    --use-version=*) MAXIMA_VERSION=`echo "$1" | sed 's/--use-version=//'` ;;
	    -X|--lisp-options) MAXIMA_LISP_OPTIONS="$2" ; shift ;;
	    --lisp-options=*) MAXIMA_LISP_OPTIONS=`echo "$1" | sed 's/--lisp-options=//'` ;;
	    --userdir ) : ; shift;; # noop; handled by process_userdir_argument
	    --userdir=*) : ;; # noop; handled by process_userdir_argument
	    -v|--verbose ) verbose=true;;
	    *) ;;
	esac
	shift
    done
}

process_commandline_arguments "$@"


# Allow ccl as an alias of openmcl.
if [ "$MAXIMA_LISP" = "ccl" ]; then
    MAXIMA_LISP=openmcl
fi


setup_vars

if [ ! -d "$MAXIMA_IMAGESDIR" ]; then
# Have we been moved?
  MAXIMA_PREFIX=`(cd "\`dirname "$0"\`" 1>/dev/null 2>/dev/null; dirname "\`pwd\`")`
  export MAXIMA_PREFIX
  unsetup_vars
  setup_vars
  if [ ! -d "$MAXIMA_IMAGESDIR" ]; then
    echo "$0: unable to determine MAXIMA_PREFIX" 1>&2
    exit 1
  fi
fi

# This step should only be necessary in order to be in sync with the windows
# version of maxima.
if [ -d "$MAXIMA_INITIAL_FOLDER" ]; then
    cd $MAXIMA_INITIAL_FOLDER
fi

maxima_image_base="$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima"

if [ "$verbose" = "true" ]; then
    set -x
fi
if [ "$MAXIMA_LISP" = "clisp" ]; then
    if [ "$layout_autotools" = "true" ]; then
      if [ -x "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" ]; then
        exec "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" $MAXIMA_LISP_OPTIONS -q "" -- "$@"
      else
	exec "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/lisp.run" $MAXIMA_LISP_OPTIONS -q -M "$maxima_image_base.mem" "" -- "$@"
      fi
    else
      if [ -x "$maxima_image_base" ]; then
        exec "$maxima_image_base"  $MAXIMA_LISP_OPTIONS -q  "" -- "$@"
      else
	exec "clisp" $MAXIMA_LISP_OPTIONS -q -M "$maxima_image_base.mem" "" -- "$@"
      fi
    fi
elif [ "$MAXIMA_LISP" = "cmucl" ]; then
    # CMUCL can use either an executable image or a regular lisp core
    # file.  Check for the executable image and run that if possible.
    # Otherwise, fallback and use the lisp core file.
    if [ "$layout_autotools" = "true" ]; then
	if [ -x "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" ]; then
	    exec "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" $MAXIMA_LISP_OPTIONS -quiet -- "$@"
	else
	    exec "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/lisp" $MAXIMA_LISP_OPTIONS -quiet -core "$maxima_image_base.core" -eval '(cl-user::run)' -- "$@"
	fi
    else
	if [ -x "$maxima_image_base" ]; then
	    exec "$maxima_image_base" $MAXIMA_LISP_OPTIONS -quiet -- "$@"
	else
	    exec "lisp" $MAXIMA_LISP_OPTIONS -quiet -core "$maxima_image_base.core" -eval '(cl-user::run)' -- "$@"
	fi
    fi
elif [ "$MAXIMA_LISP" = "scl" ]; then
    if [ "$layout_autotools" = "true" ]; then
	exec "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/lisp" $MAXIMA_LISP_OPTIONS -quiet -core "$maxima_image_base.core" -eval '(cl-user::run)' -- "$@"
    else
	exec "scl" $MAXIMA_LISP_OPTIONS -quiet -core "$maxima_image_base.core" -eval '(cl-user::run)' -- "$@"
    fi
elif [ "$MAXIMA_LISP" = "gcl" ]; then
    exec "$maxima_image_base" -eval '(cl-user::run)' $MAXIMA_LISP_OPTIONS -f -- "$@"
elif [ "$MAXIMA_LISP" = "acl" ]; then
# FIXME: arguments need in a manner consistent with the way they are extracted
#        in the function get-application-args in command-line.lisp
    exec "lisp" -I "$maxima_image_base.dxl" $MAXIMA_LISP_OPTIONS -e '(cl-user::run)' -- "$@"
elif [ "$MAXIMA_LISP" = "openmcl" ]; then
# OPENMCL can use either an executable image or a regular lisp core
# file.  Check for the executable image and run that if possible.
# Otherwise, fallback and use the lisp core file.
# FIXME: arguments need in a manner consistent with the way they are extracted
#        in the function get-application-args in command-line.lisp
    if [ -x "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" ]; then
      exec "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" $MAXIMA_LISP_OPTIONS -e '(cl-user::run)' -- "$@"
    else
      exec "openmcl" -I "$maxima_image_base.image" $MAXIMA_LISP_OPTIONS -e '(cl-user::run)' -- "$@"
   fi
elif [ "$MAXIMA_LISP" = "ccl64" ]; then
# Ccl64 can use either an executable image or a regular lisp core
# file.  Check for the executable image and run that if possible.
# Otherwise, fallback and use the lisp core file.
# FIXME: arguments need in a manner consistent with the way they are extracted
#        in the function get-application-args in command-line.lisp
    if [ -x "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" ]; then
      exec "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" $MAXIMA_LISP_OPTIONS -e '(cl-user::run)' -- "$@"
    else
      exec "dx86cl64" -I "$maxima_image_base.image" $MAXIMA_LISP_OPTIONS -e '(cl-user::run)' -- "$@"
   fi

elif [ "$MAXIMA_LISP" = "ecl" ]; then
   exec "$maxima_image_base" --frame-stack 4096 --lisp-stack 65536 $MAXIMA_LISP_OPTIONS -- "$@"

elif [ "$MAXIMA_LISP" = "sbcl" ]; then
# Use executable image if it exists.
# Since compiling lapack already needed >1200 Megabytes of RAM in August of 2015 
# one has to extend the amount of memory sbcl will be able to claim by using the
# switch --dynamic-space-size in order to do so.
  if [ -x "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" ]; then
    exec "$MAXIMA_IMAGESDIR/binary-$MAXIMA_LISP/maxima" --noinform $MAXIMA_LISP_OPTIONS --end-runtime-options --eval '(cl-user::run)' --end-toplevel-options "$@"
  else
    exec "sbcl" --core "$maxima_image_base.core" --noinform $MAXIMA_LISP_OPTIONS --end-runtime-options --eval '(cl-user::run)' --end-toplevel-options "$@"
  fi

else
    echo "$0: lisp=\"$MAXIMA_LISP\" not known. Use --list-avail to see possible options." >&2
    exit 1
fi
