#! /usr/local/bin/bash
#
# epix: wrapper script for ePiX
#
# Options: --help for usage, --version for version and license
#
# Compiler flags may be specified on the command line or in the config
# file ~/.epixrc. The script attempts to deal intelligently with missing
# or multiple extensions. If the input file has a recognized extension,
# there's no issue. If only the root name <infile> is given, the script
# searches for completions in the order of preference dictated by the
# variable EPIX_EXTENSIONS. A warning is issued for multiple matches.
#
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
# Andrew D. Hwang   <For address, do "epix -V">
# 

. "/usr/local/lib/epix/epix-lib.sh"

EPIX_CONFIG_FILE="$HOME/.epixrc"
# Search these extensions in order of preference
EPIX_EXTENSIONS="xp flx cc c C cpp" # or NULL
EPIX_DOT_EXT=".${EPIX_EXTENSIONS// /|.}" # for usage message

# Default inc/lib directories and compiler
DEFAULT_INC="-I/usr/local/include"
DEFAULT_LIB="-L/usr/local/lib/epix"
COMPILER="c++"

# Use default library unless we're called by version number
LIBS="-lm"
POSTLIBS="-lepix"
EPIX_SRC_EXT=cc

declare EPIX_MYINCLUDES
declare EPIX_MYLIBDIRS
declare EPIX_MYLIBS
declare EPIX_MYWARNS
declare EPIX_MYFLAGS

declare -a EPIX_FILE_LIST

declare -a TEMPFILES
trap '[ -n "${TEMPFILES[*]}" ] && rm -f "${TEMPFILES[@]}"' 0 1 2 3 7 10 13 15

function epix_help()
{
cat <<"HELP"
Options:
    -h, --help
      Show this message and exit

    -V, --version
      Show version and exit

    -v, --verbose
      Show success/failure messages

    --gpl
      Show license

    -o, --output
      Specify output file name (ONLY for use with a single input file)

    --pst
      Write output file using PSTricks macros

    --tikz
      Write output file using tikz macros

    --eepic
      Write output file using eepic macros

    -I<include>
      Append include directory

    -L<library>
      Append library directory

    -l<lib>
      Link against lib

    --no-defaults
      Do not use default include/library directories or libraries

    -cc, --compiler)
      Specify the compiler (e.g., gcc)

    All other options are passed to the compiler. Valid options, 
    one per line, may be placed in $HOME/.epixrc. 

HELP
ePiX_bugreport

} # End of epix_help


# Parse command line/config file for compiler flags/options
function epix_parse_options {
while [ "$1" != "${1#-}" ]; do
    case "$1" in

    -I)
        if [ $# -lt 2 ]; then ePiX_die "Missing argument to \"$1\" option"; fi
	EPIX_MYINCLUDES="$EPIX_MYINCLUDES -I$2"; shift 2; continue
	;;

    -L)
        if [ $# -lt 2 ]; then ePiX_die "Missing argument to \"$1\" option"; fi
	EPIX_MYLIBDIRS="$EPIX_MYLIBDIRS -L$2"; shift 2; continue
	;;

    -l)
        if [ $# -lt 2 ]; then ePiX_die "Missing argument to \"$1\" option"; fi
	EPIX_MYLIBS="$EPIX_MYLIBS -l$2"; shift 2; continue
	;;

    -W)
        if [ $# -lt 2 ]; then ePiX_die "Missing argument to \"$1\" option"; fi
	EPIX_MYWARNS="$EPIX_MYWARNS -W$2"; shift 2; continue
	;;

    -I*)
	EPIX_MYINCLUDES="$EPIX_MYINCLUDES $1"; shift; continue
	;;

    -L*)
	EPIX_MYLIBDIRS="$EPIX_MYLIBDIRS $1"; shift; continue
	;;

    -l*)
	EPIX_MYLIBS="$EPIX_MYLIBS $1"; shift; continue
	;;

    -W*)
	EPIX_MYWARNS="$EPIX_MYWARNS $1"; shift; continue
	;;

    -i*|-u|-x)
        if [ $# -lt 2 ]; then ePiX_die "Missing argument to \"$1\" option"; fi
	EPIX_MYFLAGS="$EPIX_MYFLAGS $1 $2"; shift 2; continue
	;;

    -b) 
	ePiX_warn "Skipping option \"$1 $2\""
	shift 2; continue
	;;

    -o|--output)
        if [ $# -lt 2 ]; then ePiX_die "Missing argument to \"$1\" option"; fi
        EPIX_OUTFILE="$2"
      	EPIX_OUTROOT="${EPIX_OUTFILE%%.eepic}"
        shift 2; continue
        ;;

    --pst)
        EPIX_MYFLAGS="$EPIX_MYFLAGS -DEPIX_FMT_PSTRICKS"
	shift; continue
	;;

    --tikz)
	EPIX_MYFLAGS="$EPIX_MYFLAGS -DEPIX_FMT_TIKZ"
	shift; continue
	;;

    --eepic)
	EPIX_MYFLAGS="$EPIX_MYFLAGS -DEPIX_FMT_EEPIC"
	shift; continue
	;;

    # Deliberately undocumented
    -q|--quiet)
        EPIX_STDOUT="$SYSTEM_DEVNULL"
        EPIX_STDERR="$SYSTEM_DEVNULL"
        shift; continue
        ;;

    -v|--verbose)
        if [ -z "$2" ]; then 
            echo "Please use -V for version"
            exit 0
        fi
        EPIX_STDOUT="$SYSTEM_STDOUT"
        EPIX_STDERR="$SYSTEM_STDERR"
        shift; continue
        ;;

    -vv)
        echo "Discontinued option -vv; please use -v for verbose output"
        exit 0
        ;;


    -h|--help)
	ePiX_usage epix $EPIX_DOT_EXT
	epix_help
	exit 0
	;;

    -V|--version|--gpl)
        ePiX_version epix
        ePiX_license
        exit 0
        ;;

    --no-defaults)
        POSTLIBS=
	DEFAULT_INC=
	DEFAULT_LIB=
        shift; continue
        ;;

    -cc|--compiler)
        if [ $# -lt 2 ]; then ePiX_die "Missing argument to \"$1\" option"; fi
        COMPILER=$2
        COMP_NAME=$(basename "$COMPILER")
        if [ "${COMP_NAME: -2}" = cc ]; then EPIX_SRC_EXT=c; fi
        shift 2; continue
        ;;

    *)
	EPIX_MYFLAGS="$EPIX_MYFLAGS $1"; shift; continue
	;;
    esac

done

# Assume remaining parameters are input files
EPIX_FILE_LIST=("$@")
} # End of epix_parse_options


# Compile specified files to eepic
function epix_compile_files {

    if [ -z "$1" ]; then
        ePiX_die "No input file specified"
    fi

    mkdir "$EPIX_TEMPDIR" || ePiX_die "Can't create \"${EPIX_TEMPDIR}\""

    # file counts
    local processed=0
    local success=0
    local failure=0

    for EPIX_INFILE in "${EPIX_FILE_LIST[@]}"; do

        # sets EPIX_INROOT, EPIX_SUFFIX, EPIX_NOTFOUND, touches EPIX_LOGFILE
        epix_parse_filename "$EPIX_INFILE" "$EPIX_EXTENSIONS"
        let processed=processed+1

        if [ "$EPIX_NOTFOUND" = "yes" ]; then ePiX_fail && continue; fi

        : ${EPIX_OUTROOT:=$EPIX_INROOT}
        EPIX_OUTFILE="$EPIX_OUTROOT".eepic

	# use .exe suffix for Cygwin
        { TEMP_BIN="$EPIX_INROOT".exe &&
            touch "${EPIX_TEMPDIR}/$TEMP_BIN" &&
            TEMPFILES=("{TEMPFILES[@]}" "${EPIX_TEMPDIR}/$TEMP_BIN") ; } ||
        { ePiX_fail "Couldn't create \"$EPIX_TEMPDIR/$TEMP_BIN\"" && continue;}

        # Create symlink to input file with appropriate extension for compiler
        TEMP_INPUT="${TEMP_BIN}-tmp.$EPIX_SRC_EXT"

        TEMPFILES=("{TEMPFILES[@]}" "${EPIX_TEMPDIR}/$TEMP_INPUT")

        # "cp -p" instead of "ln -s" for, e.g., vfat
        { cd ${EPIX_TEMPDIR} && \
            cp -p "../$EPIX_INFILE" "$TEMP_INPUT" && cd .. ; } || 
          { ePiX_fail "Couldn't create \"${EPIX_TEMPDIR}/$TEMP_INPUT\"" && \
            continue; }

        # Log message, and compile executable
        TMP_CMD=($COMPILER "${EPIX_TEMPDIR}/${TEMP_INPUT}" $EPIX_MYWARNS \
            -o "${EPIX_TEMPDIR}/${TEMP_BIN}" \
            $EPIX_MYFLAGS $EPIX_MYINCLUDES $DEFAULT_INC $EPIX_MYLIBDIRS \
            $DEFAULT_LIB $LIBS $EPIX_MYLIBS $POSTLIBS)

        ePiX_command "${TMP_CMD[@]}"

        # Write eepic file
        if [ -x "$EPIX_TEMPDIR/$TEMP_BIN" ]; then 
            echo "%% Generated from $EPIX_INFILE on $(date) by" \
                > "$EPIX_OUTFILE"
            ePiX_msg "Writing eepic file: ./$EPIX_TEMPDIR/$TEMP_BIN > $EPIX_OUTFILE"
            ./$EPIX_TEMPDIR/"$TEMP_BIN" >> "$EPIX_OUTFILE"

            if [ $? -ne 0 ]; then
                ePiX_warn "Could not create $EPIX_OUTFILE"
                let failure=failure+1
            else
                let success=success+1
            fi

        else
            ePiX_warn "Compilation of $EPIX_INFILE failed"
            let failure=failure+1
        fi

        # Clean up; for multiple input files, clear output name
        rm -f "$EPIX_TEMPDIR/$TEMP_BIN" "$EPIX_TEMPDIR/$TEMP_INPUT"
        if [ "$EPIX_OUTROOT" = "$EPIX_INROOT" ]; then unset EPIX_OUTROOT; fi

        echo -e "\nTranscript written on $EPIX_LOGFILE" > "$EPIX_STDOUT"

    done # for EPIX_INFILE in $INFILE_LIST

    if [ $processed -gt 1 ]; then
        echo "$processed files processed: $success successfully, $failure failed" > "$EPIX_STDERR"
    fi

    if [ -d "$EPIX_TEMPDIR" ]; then rm -Rf "$EPIX_TEMPDIR"; fi
} # end of epix_compile_files

## Script proper starts here ##

if [ $# -eq 0 ]; then 
    ePiX_usage epix $EPIX_DOT_EXT
    epix_help
    exit 0
fi

# Read options from the config file, if any
if [ -f "$EPIX_CONFIG_FILE" ]; then
    epix_parse_options $(cat $EPIX_CONFIG_FILE | grep -v "#")
fi

# Command line options override config file options
epix_parse_options "$@"

# Suppress all warnings if none are requested
if [ "$EPIX_MYWARNS" = "" ]; then EPIX_MYWARNS="-w"; fi

# Remaining option(s) assumed to be input file(s)
epix_compile_files "${EPIX_FILE_LIST[@]}"

exit 0
