#!/bin/sh

# usage:
#    document [options] file
#    [ plus any legacy usage ]
#
# options:
#    --index
#       Run makeindex on the input file
#
#    --latex
#       Typeset input file assuming it a LaTeX file
#
#    --mode=what
#       In conjunction with --tag=lang, indicates what to do
#       with input files assumed to contain program source code.
#       Valid values are: compile, translate, save-image, link.
#
#    --output=outfile
#       Set the output filename.
#
#    --tag=lang
#       Process input files as programs written in language
#       indicated by lang.  Valid values are: boot, lisp.
#
#    --tangle
#    --tangle=chunk
#       Run notangle on the input file assumed to be a pamphlet.
#
#    --use=cmd
#       Use cmd for translation or compilation.
#
#    --weave 
#       Run noweave on the input file assumed to be a pamphlet
#       When combined with --output, also run latex.
#    --
#       Anything that comes after is treated as an argument, even
#       if it looks like an option

## 2007-04-10:
##   After moving to a recent version of MSYS, and GCL-2.6.8pre, I
##   noticed that double-colon ('::' in boottran::boottocl) will be
##   translated to semi-colon (';') as if interpreted for path
##   separator.  I don't who is doing that, and I have no time to
##   investigate it, and even if I do, it would not help much.  
##   Therefore, I've changed the script not to use double-colon. 
##      -- Gaby


# set -x

latex="@LATEX@"
index="@MAKEINDEX@"

notangle="@NOTANGLE@"
noweave="@NOWEAVE@"

# Flags used to invoke the Lisp compiler in batch mode
quiet="@fricas_quiet_flags@"
eval_flags="@fricas_eval_flags@"


# The flavor of Lisp implementation we're using
lisp_flavor=@fricas_lisp_flavor@

# Issue a diagnostic message and exit with non-zero status.
error() {
    echo "error: $1"
    exit 1
}

# Issue a diagnostic if an option ($1) requires a argument
# and its value ($2) is empty.
maybe_missing_value_for() {
    if test -z $2; then
	error "missing value for $1"
    fi
}

# Check validity of --tag.  At the moment
# we support only "boot" and "lisp"
check_tag_value() {
    case $1 in
	boot|lisp) 
           tag=$1
           ;;
	*)
	   error "invalid tag $1"
	   ;;
    esac
}

# Validate argument for --mode.  We support only
#  - "compile", for Lisp source file
#  - "translate", for Boot source file
#  - "save-image", for saving a $command after reading Lisp files.
check_mode_value() {
    case $1 in
	compile|translate|save-image|link)
           mode=$1
	   ;;
	*)
	   error "invalid mode $1"
	   ;;
    esac
}

# Compile a program written in Lisp to FASL code.
# $1 is the input file name
# $2 is the output file name
compile_lisp_file() {
    case $lisp_flavor in
	gcl|sbcl|cmucl|clisp|openmcl|ecl|lispworks)
	   if [ -z "$output" ] ; then 
	       # $command $quiet $eval_flags \
	       echo "(in-package \"FRICAS-LISP\")" \
	            "(progn (fricas-compile-file \"$1\") (quit))" | $command
	   else
	       # $command $quiet $eval_flags 
	       echo "(in-package \"FRICAS-LISP\")" \
	            "(progn (fricas-compile-file \"$1\" :output-file" \
                    "\"$output\") (quit))" | $command
	   fi
	   ;;
	*)
	   error "don't know how to compile with '$lisp_flavor' Lisp"
	   ;;
    esac
    return $?
}

# Build an executable out of (compiled) Lisp files.
make_program() {
    case $lisp_flavor in
	gcl|sbcl|cmucl|clisp|openmcl|ecl|lispworks)
           ## $command $eval_flags \
	   echo "(in-package \"FRICAS-LISP\") \
	         (make-program \"$output\" (quote ($*)))" | $command
	   ;;
	*)
	   error "don't know how to build program with '$lisp_flavor' Lisp"
	   ;;
    esac
}

# Translate a program written in Boot to Lisp
# $1 designates the translator 
# $2 is the input file
# $3 is a temporary file where we dump compiler diagnostics
translate_boot_file() {
    case $lisp_flavor in
	gcl|sbcl|cmucl|clisp|openmcl|ecl|lispworks)
	   if [ -z "$output" ] ; then
	      o_arg=nil
	   else
	      o_arg=\""$output"\"
	   fi
	   # $command $quiet $eval_flags "(in-package \"BOOTTRAN\")" \
	   echo "(in-package \"BOOTTRAN\") (progn (boottoclc \"$1\" $o_arg))" \
	         "(quit)" | $command

	   ;;
	*)
	   error "don't know how to translate with '$lisp_flavor' Lisp"
	   ;;
    esac
    return $?
}

do_index=
do_latex=
do_tangle=
do_weave=
chunk=
file=
output=
tag=
mode=
command=

while test $# -gt 0 ; do
    optval=$1

    case $optval in
	--)
	   break
	   ;;
	--*=*)
	   arg=`echo $optval | sed -e 's/^[-a-zA-Z]*=//'`
	   opt=`echo $optval | sed -e 's/=.*$//'`
	   shift;
	   ;;
	--*)
	   opt=$optval
	   arg=
	   shift
	   ;;
	*)
	   break
	   ;;
    esac

    case $opt in
	--weave)
	   do_weave=yes
	   ;;

        --latex)
	   do_latex=yes
           ;;

        --index)
	   do_index=yes
	   # FIXME: --index may be used only with --latex.  Check.
           ;;

	--tangle)
	   do_tangle=yes
	   if test -n "$arg"; then
	       chunk=$arg
	   fi
	   # --tangle may not be combined with any other
	   # options.  FIXME:  Check that. 
	   ;;

	--output)
	   maybe_missing_value_for $opt $arg
	   output=$arg
	   ;;

	--tag)
	   maybe_missing_value_for $opt $arg
	   check_tag_value $arg
	  ;;
	
	--mode)
 	   maybe_missing_value_for $opt $arg
	   check_mode_value $arg
	   ;;
	--use)
	   command=$arg
	   ;;

	--*)
	   echo unrecognized option $opt
	   exit 1
	   ;;
    esac
done

if test x$do_tangle = xyes; then
    # FIXME: Check that the input file name does indeed have
    # a pamphlet extension.
    file=$1
    if [ -z "$output" ]; then
	output=`basename $file .pamphlet`;
    fi

    # FIXME: Ideally, we should just prepend -R to $chunk
    #        if it is non-null, and say $tangle $chunk $file > $output
    #        Alternatively, we could initialize chunk to '*' and
    #        unconditionally use -R"$chunk".
    if [ -z "$chunk" ]; then
	$notangle $file > $output
    else
	$notangle -R"$chunk" $file > $output
    fi
    # FIXME: Handle errors.
    exit $?;
fi


if test x$do_weave = xyes; then
    file=`basename $1 .pamphlet`
    $noweave -delay $1 > $file.tex
    if test x$do_latex != xyes; then
	exit 0;
    fi
fi

if test x$do_latex = xyes; then
    if [ -z $file ]; then
	file=`basename $1 .tex`
    fi
    $latex --interaction nonstopmode $file;
    if [ x$do_index = xyes ]; then
	$makeindex $file.idx
    fi
    $latex --interaction nonstopmode $file;
    exit $?
fi

# We only support translation of Boot source files, and
# compilation of Lisp source files
case $mode,$tag in
    translate,boot)
       # The bootsys image is currently unable to pass up an
       # exit status that we can hand to the shell.  When an error
       # occurs, bootsys just prints a message and exits as if 
       # everything went well.  To work around that, we have to 
       # capture its output, look for specific patterns, and then
       # return an appropriate exit status.
       # mktemp is used to create a temporary file; for systems that
       # lack support for mktemp, e.g. MinGW/MSYS, we use the common
       # trick of forging a filename based on the pid.
       # if test -z "@MKTEMP@"; then
       #   tmpfile=document.$$
       # else
       #   tmpfile=`mktemp document.XXXXXX` || exit 1
       # fi
       # trap "rm -f $tmpfile" 1 2 15
       translate_boot_file $1
       exit 0
       # grep 'ERROR IN' $tmpfile >/dev/null && { rm $tmpfile; exit 1; }
       # rm $tmpfile && exit 0
       ;;

    compile,lisp)
       compile_lisp_file $1 $output
       exit $?
       ;;

    save-image,lisp)
       load_lisp_and_save_image $1
       exit $?
       ;;
    link,lisp)
       make_program $@
       exit $?
       ;;
esac

echo "document [ -o redirect ] pamphlet"

# set +x

