#! /bin/sh
# $Id: umake.in 708 2007-03-13 19:48:17Z demaille $

test -f /bin/ksh && test -z "$RUNNING_KSH" \
  && { UNAMES=`uname -s`; test "x$UNAMES" = xULTRIX; } 2>/dev/null \
  && { RUNNING_KSH=true; export RUNNING_KSH; exec /bin/ksh $0 ${1+"$@"}; }
unset RUNNING_KSH

# No failure shall remain unpunished.
set -e

usage ()
{
   echo "Usage: $program [OPTION]... [FILE]...

General options:
  -D, --debug         turn on shell debugging (set -x)
  -h, --help          display this help and exit successfully
  -q, --quiet         no output unless errors (implies --batch)
  -v, --version       display version information and exit successfully
  -V, --verbose       report on what is done

Compilation options:
  -c, --clean         clean
  -l, --library       produce a library, don't link to a particular core
  -o, --output=output output file name
  -C, --core=CORE
  -H, --host=HOST

Developper options:
  -p, --prefix=DIR     library file location [$prefix]
  -P, --param-mk=FILE  param.mk location [$(param_mk)]

Exit codes:
   1   some tool failed
   2   invalid command line option
   3   unknown command line argument
   4   enable to find param.mk -- probably a bad --host argument

FILE may be C/C++ source files, headers, libraries or directory that
will be searched for such files"
  exit 0
}

version ()
{
  echo "URBI Make 1.0RC
\$Id: umake.in 708 2007-03-13 19:48:17Z demaille $"
  exit 0
}

# Return the location of param_mk
param_mk ()
{
  if test -n "$param_mk"; then
    echo "$param_mk"
  else
    echo "$prefix/gostai/core/$host/param.mk"
  fi
}

# We have to initialize IFS to space tab newline since we save and
# restore IFS and apparently POSIX allows stupid/broken behavior with
# empty-but-set IFS.
# http://lists.gnu.org/archive/html/automake-patches/2006-05/msg00008.html
# We need space, tab and new line, in precisely that order.  And don't
# leave trailing blanks.
newline='
'
IFS=" 	$newline"

# Pacify verbose cds.
CDPATH=${ZSH_VERSION+.}$path_sep

# In case someone crazy insists on using grep -E.
: ${EGREP=egrep}


# Initialize variables for option overriding and otherwise.
# FIXME: Something fishy with defaultenv...
EXEEXT=''
core=remote     # we link to core by default
debug=false
defaultenv='remote'
havearg=false   # we have at least one path or file arg
host='powerpc-linux'
prefix='/usr'
quiet=false     # by default let the tools' message be displayed
target=         # target name
verb=false      # true for verbose mode

libs=
sources=
headers=
makeargs=

## --------------------- ##
## Auxiliary functions.  ##
## --------------------- ##


# In case `local' is not supported by the shell.
(
  foo=bar
  test_local () {
    local foo=foo
  }
  test_local
  test $foo = bar
) || local () {
  case $1 in
    *=*) eval "$1";;
  esac
}


# report LINE1 LINE2...
# ---------------------
# Report some information on stderr.
report ()
{
  for i in "$@"
  do
    echo >&2 "$0: $i"
  done
}

# verbose WORD1 WORD2
# -------------------
# Report some verbose information.
verbose ()
{
  if $verb; then
    echo >&2 "$0: $@"
  fi
}

# run COMMAND-LINE
# ----------------
# Run the COMMAND-LINE verbosely, and catching errors as failures.
run ()
{
  verbose "Running $@"
  "$@" 2>&5 1>&2 ||
     error 1 "$1 failed"
}


# error EXIT_STATUS LINE1 LINE2...
# --------------------------------
# Report an error and exit with failure if EXIT_STATUS is non null.
error ()
{
  local s=$1
  shift
  report "$@"
  if test "$s" != 0; then
    exit $s
  fi
}


## ---------------------- ##
## Command line parsing.  ##
## ---------------------- ##

get_options ()
{
  # Push a token among the arguments that will be used to notice when we
  # ended options/arguments parsing.
  # Use "set dummy ...; shift" rather than 'set - ..." because on
  # Solaris set - turns off set -x (but keeps set -e).
  # Use ${1+"$@"} rather than "$@" because Digital Unix and Ultrix 4.3
  # still expand "$@" to a single argument (the empty string) rather
  # than nothing at all.
  arg_sep="$$--$$"
  set dummy ${1+"$@"} "$arg_sep"; shift

  # Parse command line arguments.
  while test x"$1" != x"$arg_sep"
  do
    # Handle --option=value by splitting apart and putting back on argv.
    case "$1" in
      --*=*)
	opt=`echo "$1" | sed -e 's/=.*//'`
	val=`echo "$1" | sed -e 's/[^=]*=//'`
	shift
	set dummy "$opt" "$val" ${1+"$@"}; shift
	;;
    esac

    case "$1" in
      -D | --debug  ) debug=true;;
      -V | --verbose) verb=true;;
      -h | --help   ) usage;;
      -q | --quiet  ) quiet=true;;
      -v | --version) version;;

      -l | --library)  core= ;;
      -c | --clean)  core="clean" ;;
      -C | --core  ) shift; core=$1;;
      -H | --host  ) shift; host=$1;;
      -o | --output) shift; target=$1;;

      -p | --prefix) shift; prefix=$1;;
      -P | --param-mk) shift; param_mk=$1;;

      --) # What remains are not options.
	shift
	while test x"$1" != x"$arg_sep"
	do
  	    set dummy ${1+"$@"} "$1"; shift
  	    shift
	done
	break
	;;
      -*)
	error 2 "Unknown or ambiguous option \`$1'." \
  	      "Try \`--help' for more information."
	;;
      *) set dummy ${1+"$@"} "$1"; shift;;
     esac
     shift
  done
  # Pop the token
  shift

  # Interpret remaining command line args as filenames.
  case $# in
   0|1);;
   *)
    if test -n "$oname"; then
      error 2 "Can't use option \`--output' with more than one argument."
    fi
    ;;
  esac

  while test x"$1" != x || test $havearg = false
  do
    if test x"$1" = x && test $havearg = false; then
      set dummy . ${1+"$@"}; shift
      havearg=true
    fi

    # If this is a directory, append a slash.
    case $1$(test -d "$1" && echo '/') in
      *=*)                   makeargs="$makeargs '$1'" ;;
      *.h |*.hh|*.hxx|*.hpp) headers="$headers '$1'";   havearg=true ;;
      *.cc|*.cpp|*.c|*.C)    sources="$sources '$1'";   havearg=true ;;
      *.a)                   libs="$libs '$1'";         havearg=true ;;
      */)
	# Is it a directory
    	files=$(find "$1"     -iname '*.h'	\
    			  -or -iname '*.hh'	\
    			  -or -iname '*.hxx'	\
    			  -or -iname '*.hpp'	\
    			  -or -iname '*.c'	\
    			  -or -iname '*.C'	\
    			  -or -iname '*.cc'	\
    			  -or -iname '*.cpp'    \
    			  -or -iname '*.a')
    	  havearg=true;
    	  shift
    	  set dummy $files ${1+"$@"};;
       *)
    	  error 3 "unknown type of file '$1'"
	;;
    esac
    shift
  done
}

get_options "$@"

# File descriptor usage:
# 0 standard input
# 1 standard output (--verbose messages)
# 2 standard error
# 3 some systems may open it to /dev/tty
# 4 used on the Kubota Titan
# 5 tools output (turned off by --quiet)
# 6 tracing/debugging (set -x output, etc.)


# Main tools' output (TeX, etc.) that TeX users are used to seeing.
#
# If quiet, discard, else redirect to the message flow.
if $quiet; then
  exec 5>/dev/null
else
  exec 5>&1
fi

# Enable tracing, and auxiliary tools output.
#
# Should be used where you'd typically use /dev/null to throw output
# away.  But sometimes it is convenient to see that output (e.g., from
# a grep) to aid debugging.  Especially debugging at distance, via the
# user.
if $debug; then
  exec 6>&1
  set -x
else
  exec 6>/dev/null
fi

verbose "run."

if test x$core = xdefault; then
  core=$defaultenv
fi

# Produce objects in the current directory, not in the source tree.
objects=
vpath=.
for s in $(eval echo "$sources")
do
  objects="$objects '"$(basename "$s" | sed 's/\.[^.]*$/.o/g')"'"
  vpath="$vpath:"$(dirname "$s")
done

# Select target name if unspecified.
case $target:$core in
    *:clean) target="clean"; core="clean" ;;
    :)  target=uobject-$host.a;;
    :*) target=urbiengine-$host-$core$EXEEXT;;
    # FIXME: Shamelessly discarding any part of the name if it has
    # a dot in it (e.g., urbi.my-uobject).
    *:) target=$(echo $target | sed -e 's/\.[^.]*//')
	target="$target.a";;
    *:*)target=$(echo $target | sed -e 's/\.[^.]*//')
	target="$target$EXEEXT";;
esac

# Remove ourselves from library list in lib generation mode, add OUTBIN
# option otherwise.
if test x$core = x; then
  libs=$(echo "$libs" | sed -e "s/$target//")
  makeargs="$makeargs OUTLIB=$target"
else
  if test x$core != "xclean"; then
    makeargs="$makeargs OUTBIN=$target"
  fi
fi

# Then pass env.
makeargs="$makeargs URBI_ENV=$core prefix=$prefix"
verbose "libs='$libs'"
verbose "sources='$sources'"
verbose "headers='$headers'"
verbose "vpath='$vpath'"
verbose "objects='$objects'"
verbose "make options='$makeargs'"

# Make sure we can find param.mk (to give a better error message).
if test ! -f "$(param_mk)"; then
  error 4 "no such file: $(param_mk)"
fi

# Invoke make.
verbose "invoking make -f $(param_mk) $target"
run eval make -f "$(param_mk)" "$target" HEADERS="'$headers'" LIBS="'$libs'" VPATH="'$vpath'" OBJECTS="'$objects'" "$makeargs"
verbose "done."

exit 0
