#!/bin/bash -e
#
# (C) 2008 Xavier Maillard <xma@gnu.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
# --------------------------------------------------------------------------
# Documentation:
#
# Original code and idea: http://stumpwm.antidesktop.net/cgi-bin/wiki/SetUp
#
# Installation:
# Put this script wherever you want and just call it from your .xinitrc file
#
# The first time you will launch it, it will build the final
# executable and then call it. To force a rebuild of your executable
# (say you have updated something in the CLFSWM source tree), just
# delete the image and restart your X session.
# --------------------------------------------------------------------------


no_start=no

lisp=clisp   # +config+
lisp_bin=''   # +config+
lisp_opt=''   # +config+
dump_path="$XDG_CACHE_HOME/clfswm/"   # +config+
clfswm_asd_path="$(pwd)"   # +config+
asdf_path="$(pwd)/contrib"   # +config+

tmp_dir=/tmp


usage() {

    echo "$0 [options]
  -n, --no-start           don't start CLFSWM after image dump
  -f, --force              force image dump
  --rebuild                same as -f, --force
  -l, --with-lisp          use <lisp> as the common lisp implementation [$lisp]
  -b, --lisp-bin            use <bin> as the common lisp program [$lisp_bin] (default: same as with-lisp type)
  -o, --lisp-opt           use <opt> as lisp option [$lisp_opt]
  -d, --dump-path          path to the dump directory [$dump_path]
  --with-clfswm            path to clfswm.asd file [$clfswm_asd_path]
  --with-asdf              path to the asdf.lisp file [$asdf_path]"

    exit 0
}

die() {
	echo >&2 "$@"
	exit 1
}

build_clisp ()
{
    $lisp_bin $lisp_opt -m 8MB -E ISO-8859-1 -q -i "$asdf_path"/asdf.lisp -x "(load \"$clfswm_asd_path/clfswm.asd\")
                (asdf:oos 'asdf:load-op :clfswm) \
       		(EXT:SAVEINITMEM \"$dump_image\" :INIT-FUNCTION (lambda () (clfswm:main) (quit)) :EXECUTABLE t :norc t)"
}

build_sbcl()
{
   $lisp_bin $lisp_opt --disable-debugger --eval "(require :asdf)" \
       --eval "(require :sb-posix)" \
       --eval "(load \"$clfswm_asd_path/clfswm.asd\")" \
       --eval "(require :clfswm)" \
       --eval "(save-lisp-and-die \"$dump_image\" :toplevel 'clfswm:main)"
}

build_cmucl()
{
   $lisp_bin $lisp_opt -eval "(require :clx)" \
       -eval "(load \"$asdf_path/asdf.lisp\")" \
       -eval "(load \"$clfswm_asd_path/clfswm.asd\")" \
       -eval "(asdf:oos 'asdf:load-op :clfswm)" \
       -eval "(save-lisp \"$dump_image\" :init-function (lambda () (clfswm:main) (quit)))"
}

build_ccl()
{
    $lisp_bin $lisp_opt --eval "(require :asdf)" \
	--eval "(load \"$clfswm_asd_path/clfswm.asd\")" \
	--eval "(asdf:oos 'asdf:load-op :clfswm)" \
	--eval "(save-application \"$dump_image\" :toplevel-function (lambda () (clfswm:main) (quit)))"
}

build_ecl()
{
    $lisp_bin $lisp_opt -eval "(require :asdf)" \
	-eval "(load \"$clfswm_asd_path/clfswm.asd\")" \
	-eval "(asdf:make-build :clfswm :type :program :monolithic t :move-here \".\" :prologue-code '(progn (require :asdf) (require :clx)))" \
	-eval "(ext:quit 0)"
    mv ./clfswm-mono "$dump_image"
    echo "$dump_image"
}


while test $# != 0
do
    case "$1" in
	-n|--no-start)
	    no_start=yes ;;
	-f|--force|--rebuild)
	    force=yes ;;
	-d|--dump-path)
	    shift
	    dump_path="$1" ;;
	--with-clfswm)
	    shift
	    clfswm_asd_path="$1" ;;
	--with-asdf)
	    shift
	    asdf_path="$1" ;;
	-l|--with-lisp)
	    shift
	    case "$1" in
		'')
		    usage;;
		clisp|sbcl|cmucl|ccl|ecl)
		    lisp="$1" ;;
	    esac
	    ;;
        -b|--lisp-bin)
            shift
            lisp_bin="$1" ;;
	-o|--lisp-opt)
	    shift
	    lisp_opt="$1" ;;
	--)
	    shift
	    break ;;
	-h|--help)
	    usage ;;
	*)
	    ARGS="$ARGS $1" ;;
    esac
    shift
done

if [ "x$lisp_bin" == "x" ]; then
    lisp_bin=$lisp
fi

dump_image="$dump_path/clfswm-$(cksum $(type -p $lisp) | cut -d ' ' -f 1).core"

if test yes = "$force" && test -e "$dump_image"
then
    echo "Removing old image."
    rm -f "$dump_image"
fi

clfswm_asd="$clfswm_asd_path"/clfswm.asd
if test -L "$clfswm_asd_path"; then
    clfswm_asd=$(readlink "$clfswm_asd")
fi

older_image=0
for i in "$(dirname $clfswm_asd)"/src/*.lisp; do
    test "$dump_image" -ot "$i" && older_image=1
done

if test ! -e "$dump_image" || test $older_image -eq 1
then
    echo "Image is nonexistent or older than sources. Rebuilding clfswm."
    test -x $(type -p "$lisp") || die "$lisp can't be found."
    test -e "$clfswm_asd_path"/clfswm.asd || die "can't find clfswm.asd in $clfswm_asd_path"
    test -e "$asdf_path"/asdf.lisp || die "can't find asdf.lisp in $asdf_path"

    # Move clfswm sources to $tmp_dir if there is no write permission on $clfswm_asd_path
    if test ! -w "$clfswm_asd_path" ; then
	echo "* Note: No write access in sources ($clfswm_asd_path),
 -> copying in a writable directory ($tmp_dir/clfswm-tmp)"
	rm -rf "$tmp_dir"/clfswm-tmp
	mkdir "$tmp_dir"/clfswm-tmp
	cp -R "$clfswm_asd_path"/* "$tmp_dir"/clfswm-tmp
	clfswm_asd_path="$tmp_dir"/clfswm-tmp
	asdf_path="$tmp_dir"/clfswm-tmp/contrib
    fi

    mkdir -p "$dump_path"
    mkdir -p "$dump_path/contrib"
    eval build_"$lisp"
    rm -rf "$dump_path/contrib"
    cp -R "$clfswm_asd_path/contrib/" "$dump_path/"
    rm -rf $(find "$dump_path/" -name "*svn")

    rm -rf "$tmp_dir"/clfswm-tmp

    echo "CLFSWM image is: $dump_image"
fi

# Run the resulting image
if test no = "$no_start"
then
    cd "$dump_path"
    echo "Arguments: $* and $ARGS"
    case $lisp in
	clisp ) "$dump_image" -- $ARGS ;;
	sbcl ) exec $lisp_bin --core "$dump_image" $ARGS ;;
	cmucl ) exec $lisp_bin -core "$dump_image" $ARGS ;;
	ccl ) exec $lisp_bin -I "$dump_image" -- $ARGS ;;
	ecl ) "$dump_image" -eval "(progn (clfswm:main) (ext:quit 0))" $ARGS ;;
	*) echo "..." ;;
    esac
else
    echo "As requested, we have just dumped the image."
fi

