#! /bin/dash
#
# compile/run/debug project files
#
# this script is invoked via chroot+setuidgid
#
# R. Perry, Jan. 2003
#
# ZZ marks local customization sections

#PATH="/vecr/bin:/opt/jdk/bin:/opt/bin:/bin:/usr/bin:/sbin:/usr/sbin"
PATH="/vecr/bin:/opt/bin:/usr/bin:/usr/sbin"
export PATH

# user PATH, includes ".", by popular demand, in spite of insecurity
#
UPATH="$PATH:."

mode="$1"
top="$2"
sub="$3"
file="$4"
args="$5"

dir="$top/$sub"

cd "$dir" || exit 1

TMP="/htdocs/tmp"
WAV="/vecr/bin/wav"
CONVERT="/usr/bin/convert"
M="/bin/octave-cli"
PYTHON="/opt/bin/python3"

###
# function to present WAV audio
#
# Using the HTML5 <audio> tag as suggested by Brian Kim, 11 March 2014
#
view_wav() {
  echo "Content-type: text/html\n
<!DOCTYPE html>
<html><head><title>VECR/Audio</title></head><body bgcolor=white text=black>
${sub}/${file}"
  #
  echo "$args" | sed -e 's/\&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g'
  umask 022
  exec 2>/dev/null
  #
  if [ "$1" = "file" ]; then
    fname="${user}-${COURSE}-${sub}-${file}"
    "$WAV" < "$file" > "${TMP}/${fname}"
  else
    fname="${user}-${COURSE}-${sub}-${file}-$$.wav"
    PATH="$UPATH"
    eval $run $args | "$WAV" > "${TMP}/${fname}"
  fi
  #
  echo "<p><audio controls autoplay loop>
<source src=\"https://www.ece.villanova.edu/tmp/${fname}\" type=\"audio/wav\">
Your browser does not support the audio element.
</audio></body></html>"
  #
  exit
}
#
###

###
# function to present PPM image by converting it to PNG
#
view_image() {
  echo "Content-type: image/png\n"
  #
  if [ "$1" = "file" ]; then
    "$CONVERT" "ppm:-" "png:-" < "$file"
  else
    PATH="$UPATH"
    eval $run $args | "$CONVERT" "ppm:-" "png:-"
  fi
  #
  exit
}
#
###

text_type="Content-type: text/plain\n"
html_type="Content-type: text/html\n"

type="$text_type"

# ZZ - osp/a9/p1.c runs p1.sh
#
# if [ "$COURSE" = "osp" -a "$sub" = "a9" -a "$file" = "p1.c" -a "$mode" = "run" ]; then
#   file="p1.sh"
# fi

case "$file" in
  *.c)
	name=`basename "$file" .c`
	compile="make $name"
	preproc="gcc -E -std=c11 -pedantic -Wall $file | sed '/^ *$/d'"
	asm="gcc -S -std=c11 -pedantic -Wall $file"
	asmopt="gcc -S -O3 -std=c11 -pedantic -Wall $file"
	disasm="objdump -d $name"
	run="./$name"
	debug="gdb -x ./gdb.batch -batch ./$name"
	;;
  *.h)
	name=`basename "$file" .h`
	compile="make $name"
	preproc="gcc -E -std=c11 -pedantic -Wall $file | sed '/^ *$/d'"
	asm="gcc -S -std=c11 -pedantic -Wall $file"
	asmopt="gcc -S -O3 -std=c11 -pedantic -Wall $file"
	disasm="objdump -d $name"
	run="./$name"
	debug="gdb -x ./gdb.batch -batch ./$name"
	;;
  *.cc)
	name=`basename "$file" .cc`
	compile="make $name"
	preproc="g++ -E -std=c++17 -pedantic -Wall $file | sed '/^ *$/d'"
	asm="g++ -S -std=c++17 -pedantic -Wall $file"
	asmopt="g++ -S -O3 -std=c++17 -pedantic -Wall $file"
	disasm="objdump -d $name"
	run="./$name"
	debug="gdb -iex \"set auto-load safe-path /\" -x ./gdb.batch -batch ./$name"
	;;
  *.hh)
	name=`basename "$file" .hh`
	compile="make $name"
	preproc="g++ -E -std=c++17 -pedantic -Wall $file | sed '/^ *$/d'"
	asm="g++ -S -std=c++17 -pedantic -Wall $file"
	asmopt="g++ -S -O3 -std=c++17 -pedantic -Wall $file"
	disasm="objdump -d $name"
	run="./$name"
	debug="gdb -iex \"set auto-load safe-path /\" -x ./gdb.batch -batch ./$name"
	;;
  *.java)
	if [ "$mode" = "debug" ]; then
	  echo "Content-type: text/plain\n"
	  echo "debug mode not available for java"
	  exit 1
	fi
	name=`basename "$file" .java`
	compile="make $name.class"
	preproc="echo preproc not available for java"
	asm='echo "asm not available for java"; exit 1'
	asmopt='echo "asmopt not available for java"; exit 1'
	disasm="javap -p -c $name.class"
	run="java $name"
	;;
  scan.l|parse.y)
	name="parse"
	compile="make $name"
	preproc="echo preproc not available for parser"
	asm='echo "asm not available for parser"; exit 1'
	asmopt='echo "asmopt not available for parser"; exit 1'
	disasm="objdump -d $name"
	run="./$name"
	debug="gdb -x ./gdb.batch -batch ./$name"
	;;
  *.ss)
	if [ "$mode" = "debug" ]; then
	  echo "Content-type: text/plain\n"
	  echo "debug mode not available for spreadsheet"
	  exit 1
	fi
	name=`basename "$file" .ss`
	compile="echo compile not available for spreadsheet"
	preproc="cpp -x c -std=c11 $file | sed '/^ *$/d'"
	asm='echo "asm not available for spreadsheet"; exit 1'
	asmopt='echo "asmopt not available for spreadsheet"; exit 1'
	disasm="echo disasm not available for spreadsheet"
	run="./$name"
	;;
  *.sh)
	name=""
	compile="echo can not compile shell script"
	preproc="echo preproc not available for sh"
	asm='echo "asm not available for sh"; exit 1'
	asmopt='echo "asmopt not available for sh"; exit 1'
	disasm="echo disasm not available for sh"
	run="/bin/dash ./$file"
	debug="/bin/dash -x ./$file"
	;;
  *.m)
	name=""
	compile="echo can not compile m script"
	preproc="echo preproc not available for m"
	asm='echo "asm not available for m"; exit 1'
	asmopt='echo "asmopt not available for m"; exit 1'
	disasm="echo disasm not available for m"
	export OCTAVE_HISTFILE=/dev/null OCTAVE_BUILT_IN_DOCSTRINGS_FILE=/dev/null
	run="$M -q ./$file"
	debug="$M -q --eval 'echo on' ./$file"
	;;
  *.py)
	name=""
	compile="echo can not compile py script"
	preproc="echo preproc not available for py"
	asm='echo "asm not available for py"; exit 1'
	asmopt='echo "asmopt not available for py"; exit 1'
	disasm="echo disasm not available for py"
	run="$PYTHON ./$file"
	debug="$PYTHON -m pdb ./$file"
	;;
  *)
	if [ "$mode" = "view" -o "$mode" = "cmd" ]; then
	  :
	  # file=`echo "$file" | sed -e 's/\.\.//g' -e 's;/;;g'`
	else
	  echo "Content-type: text/plain\n"
	  echo "Can not perform $mode on $file"
	  exit 1
	fi
esac

# disallow ">" for plot and audio
#
args_check() {
 case "$1" in
  *">"*) echo "Content-type: text/plain\n
redirecting output using >\ndoes not work for plot, audio, and image view"
  exit;;
 esac
}

case "$mode" in

  view)

	case "$file" in
	  *.audio) view_wav file; exit;;
	  *.ppm) view_image file; exit;;
	  *.c|*.cc|*.java|*.sh|*.txt|Makefile|*.h|*.l|*.y) mimetype="text/plain";;
	  *) mimetype=$(file -L --brief --mime "$file");;
	esac

	if [ -z "$mimetype" ]; then
	  mimetype="application/octet-stream"
	fi

	if [ -d "$file" ]; then
	  echo "Content-type: text/plain\n"
	  cd "$file"
	  ls -al
	else
	  echo "Content-type: $mimetype\n"
	  cat "$file"
	fi
	;;

  compile)
	echo "Content-type: text/plain\n"
	echo "$compile\n---\n"
	$compile # 2>&1 | fmt -25
	echo "\n\n---\nDone."
	;;

  cerr)
	echo "Content-type: text/plain\n"
	echo "$compile 2>&1 | error\n---"
	$compile 2>&1 | error
	echo "\n---\nDone."
	;;

  clean)
	echo "Content-type: text/plain\n"
	echo "make clean\n---"
	make clean 2>&1
	echo "\n---\nDone."
	;;

  preproc)
	echo "Content-type: text/plain\n"
	echo "$preproc\n---\n"
	eval "$preproc"
	echo "\n\n---\nDone."
	;;

  asm)
	echo "Content-type: text/plain\n"
	echo "$asm\n---\n"
	eval $asm
	echo "\n\n---\nDone."
	echo "\ncat $name.s\n---\n"
	cat "$name.s"
	;;

  asmopt)
	echo "Content-type: text/plain\n"
	echo "$asmopt\n---\n"
	eval $asmopt
	echo "\n\n---\nDone."
	echo "\ncat $name.s\n---\n"
	cat "$name.s"
	;;

  disasm)
	echo "Content-type: text/plain\n"
	echo "$disasm\n---\n"
	$disasm
	echo "\n\n---\nDone."
	;;

  run)
	case "$sub" in
	  iPlot|HTML|SS) type="$html_type" ;;
	esac
	# ZZ:
	#-- case "$COURSE/$sub/$file" in
	#--   osp/a9/scan.l) type="$html_type" ;;
	#-- esac
	#
	echo "$type"
	PATH="$UPATH"
	if [ "$type" = "$text_type" ]; then
	  echo "$run $args\n---\n"
	  eval $run $args
	  echo "\n\n---\nExit status = $?"
	else
	  eval $run $args
	fi
	;;

  input)
	case "$sub" in
	  iPlot|HTML|SS) type="$html_type" ;;
	esac
	#
	echo "$type"
	PATH="$UPATH"
	if [ "$type" = "$text_type" ]; then
	  echo "echo '$args' | $run\n---\n"
	  eval echo '$args' | $run
	  echo "\n\n---\nExit status = $?"
	else
	  eval echo "$args" | $run
	fi
	;;

  crun)
	echo "Content-type: text/plain\n"
	echo "$compile\n---\n"
	$compile # 2>&1 | fmt -25
	PATH="$UPATH"
	echo "\n$run $args\n---\n"
	eval $run $args
	echo "\n\n---\nExit status = $?"
	;;

  plot|splot)
	args_check "$args"
	echo "Content-type: image/gif\nPragma: no-cache\nExpires: Thu, 01 Dec 1994 16:00:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0\n"
	PATH="$UPATH"
	# ZZ
	# if [ "$COURSE" = "osp" -a "$sub" = "a7" ]; then
	#   eval $run $args | "/vecr/bin/mazeplot"
	# else
	#   eval $run $args | "/vecr/bin/$mode"
	# fi
	eval $run $args | "/vecr/bin/$mode" "$sub/$file $args"
	;;

  wav)
	args_check "$args"
	view_wav run
	;;

  image)
	args_check "$args"
	view_image run
	;;

  debug)
	echo "Content-type: text/plain\n"
	echo "$debug"
	if [ -n "$name" ]; then # was compiled
	  echo "run $args\nwhere\nquit" > gdb.batch
	  cat gdb.batch
	fi
	echo "---\n"
	PATH="$UPATH"
	eval $debug
	echo "\n\n---\nDone."
	;;

  tester)
	case "$file" in
	  p1.*|scan.l|parse.y) tester="./test1" ;;
	  p2.*) tester="./test2" ;;
	  p3.*) tester="./test3" ;;
	  p4.*) tester="./test4" ;;
	     *) tester="echo Bad test request" ;;
	esac
	echo "Content-type: text/plain\n"
	PATH="$UPATH"
	echo "$tester"
	eval $tester
	;;

  cmd)
	echo "Content-type: text/plain\n"
	echo "$args\n---\n"
	PATH="$UPATH"
	eval $args
	;;

  *)
	echo "Content-type: text/plain\n"
	echo "Bad mode"
	exit 1
	;;
esac