#!/bin/sh

usage1='usage: para [-j <n>] [-s] (<command>|<command> <switches...> -) <file> ...'
usage2="para runs several instances of a program in parallel.  Gnu make with
  	its -j option is used to run the <command> with each file argument.
	If the command is to be passed command-line switches, they have to
	be followed by a \"-\" to mark the start of the file arguments.
	If available, taskset is used to obtain the number of commands to
	run simultaneously.  That number can also be given by the -j option.
	-s silences make's command echoing."

if [ $# -lt 2 ]; then
  echo $usage1
  echo $usage2 | fmt
  exit 1
fi

function gettaskset
{
  threadopt=0
  tset=`taskset -pc $$`
  tset=${tset##*:}
  while [ -n "$tset" ]; do
    nextinlist=${tset%%,*}
    from=${nextinlist%%-*}
    if [ "$from" = "$nextinlist" ]; then	# no dash in $nextinlist
      threadopt=$((threadopt + 1))
    else
      to=${nextinlist##*-}
      threadopt=$((threadopt + to - from + 1))
    fi
    tset=${tset#$nextinlist}
    tset=${tset#,}
  done
}

if which gmake &>/dev/null; then
  makecmd=gmake
elif make -v | grep  -i "gnu make" &>/dev/null; then
  makecmd=make
else
  echo "No GNU make found.  Looked for gmake and at make -v.  Aborting."
  exit 1
fi

while [ "${1:0:1}" = "-" ]; do
  if [ "${1:0:2}" = "-j" ]; then
    if [ "$1" != "-j" ]; then
      threadopt=${1:2}
    else
      threadopt=$2
      shift
    fi
    if [ "${threadopt//[0-9]/}" != "" ]; then
      echo "Wrong argument to -j option.  Aborting."
      exit 1;
    fi
  elif [ "$1" = "-s" ]; then
    silentopt=-s
  elif [ "$1" = "-h" -o "$1" = "--help" ]; then
    echo $usage1
    echo $usage2 | fmt
    exit 1;
  else
    echo "Unrecognised option $1.  Aborting"
    exit 1
  fi
  shift
done

if [ -z "$threadopt" ]; then
  if which taskset &>/dev/null; then
    gettaskset
  fi
fi
threadopt="-j$threadopt"

mfile=/tmp/para-$$
echo > $mfile
command="$1"
shift

target=0
while [ $# -gt 0 ]; do
  if [ "$1" = "-" ]; then
    echo > $mfile
    switches=$arglist
    target=0
    targetlist=
  else
    cat >>$mfile <<EOF
.PHONY : target$target
target$target :
	$command $switches "$1"

EOF
    arglist="$arglist\"$1\" "
    targetlist="$targetlist target$target"
  fi
  target=$((target + 1))
  shift
done

if [ $target -eq 0 ]; then
  echo "No target files given.  Aborting."
  exit 1
fi

cat >>$mfile <<EOF
.PHONY : all
all : $targetlist

EOF

$makecmd $threadopt $silentopt -k -f $mfile all

rm -f $mfile

