#!/bin/bash

# get parameters 
while true; do
    case "$1" in
	-h | --help ) echo "syntax: install-imp77 <BASEDIR>"
		      echo "        install-imp77 --src <SRCDIR> --bin <BINDIR> --lib <LIBDIR> --inc <INCDIR>"
		      echo ""
		      exit 0
		      ;;
	-v | --verbose ) VERBOSE=true; echo "install-imp77 version 1.03" ; shift ;;
	-d | --debug ) DEBUG=true; shift ;;
	-s | --src ) SRCDIR="$2"; shift 2 ;;
	-b | --bin ) BINDIR="$2"; shift 2 ;;
	-l | --lib ) LIBDIR="$2"; shift 2 ;;
	-i | --inc | --include ) INCDIR="$2"; shift 2 ;;
	-- ) shift; break ;;
	"-"* )
	    echo "Unknown option: $1"
	    exit 1
	  ;;
	* ) break ;;
    esac
done

if [ "$1" != "" ] ; then
    prefix="$1"
    if [ "$SRCDIR" == "" ] ; then
        SRCDIR="$prefix/src"
    fi
    if [ "$BINDIR" == "" ] ; then
        BINDIR="$prefix/bin"
    fi
    if [ "$LIBDIR" == "" ] ; then
        LIBDIR="$prefix/lib"
    fi
    if [ "$INCDIR" == "" ] ; then
        INCDIR="$prefix/include"
    fi
else
    prefix=""
fi

if [ "$SRCDIR" == "" ] && [ "$BINDIR" == "" ] && [ "$LIBDIR" == "" ] && [ "$INCDIR" == "" ] ; then
    echo "Suitable locations include: ~ /tmp ~/usr/local /usr/local"
    read -p "Default build location [~]:" prefix
    prefix="${prefix:-~}"
    if [ "$SRCDIR" == "" ] ; then
        SRCDIR="$prefix/src"
    fi
    if [ "$BINDIR" == "" ] ; then
        BINDIR="$prefix/bin"
    fi
    if [ "$LIBDIR" == "" ] ; then
        LIBDIR="$prefix/lib"
    fi
    if [ "$INCDIR" == "" ] ; then
        INCDIR="$prefix/include"
    fi
fi

if [ "$SRCDIR" == "" ] ; then
    read -p "Build source in [~/src]:" SRCDIR
    SRCDIR="${SRCDIR:-~/src}"
fi
if [ "$BINDIR" == "" ] ; then
    read -p "Put binaries in [~/bin]:" BINDIR
    BINDIR="${BINDIR:-~/bin}"
fi
if [ "$LIBDIR" == "" ] ; then
    read -p "Put libraries in [~/lib]:" LIBDIR
    LIBDIR="${LIBDIR:-~/lib}"
fi
if [ "$INCDIR" == "" ] ; then
    read -p "Put include files in [~/include]:" LIBDIR
    INCDIR="${INCDIR:-~/include}"
fi

echo "Building imp77 in $SRCDIR"
echo "      Binaries in $BINDIR"
echo "     Libraries in $LIBDIR"
echo " Include files in $INCDIR"

# remove quoted ~
SRCDIR="${SRCDIR/#\~/$HOME}"
BINDIR="${BINDIR/#\~/$HOME}"
LIBDIR="${LIBDIR/#\~/$HOME}"
INCDIR="${INCDIR/#\~/$HOME}"

( mkdir -p $SRCDIR $BINDIR $LIBDIR $INCDIR > /dev/null ) >& /dev/null

(echo $$ > $SRCDIR/.$$) >& /dev/null
if [ ! -f $SRCDIR/.$$ ] ; then
    echo "Unable to create files in $SRCDIR"
    exit 1
fi
rm -f $SRCDIR/.$$

(echo $$ > $BINDIR/.$$) >& /dev/null
if [ ! -f $BINDIR/.$$ ] ; then
    echo "Unable to create files in $BINDIR"
    exit 1
fi
rm -f $BINDIR/.$$

(echo $$ > $LIBDIR/.$$) >& /dev/null
if [ ! -f $LIBDIR/.$$ ] ; then
    echo "Unable to create files in $LIBDIR"
    exit 1
fi
rm -f $LIBDIR/.$$

(echo $$ > $INCDIR/.$$) >& /dev/null
if [ ! -f $INCDIR/.$$ ] ; then
    echo "Unable to create files in $INCDIR"
    exit 1
fi
rm -f $INCDIR/.$$


cd $SRCDIR
if [ -f main.zip ] ; then
    echo "Saving previous $SRCDIR/main.zip as $SRCDIR/main-`date +"%Y%m%d%H%M"`.zip"
    mv main.zip main-`date +"%Y%m%d%H%M"`.zip
fi


# not too many external programs needed.
if [ "`which wget`" = "" ] ; then
    echo wget is not available - perhaps you need to: sudo apt-get install wget
    exit 1
fi

if [ "`which gcc`" = "" ] ; then
    echo gcc is not available - perhaps you need to: sudo apt-get install build-essential gcc-multilib
    exit 1
fi

ECCE="`which ecce`"
if [ "$ECCE" = "" ] ; then
    if [ -f "$BINDIR/ecce" ] ; then
	# even if $BINDIR is not in the path, which it likely isn't.
        ECCE="$BINDIR/ecce"
    fi
fi

if [ "$ECCE" = "" ] ; then
    # We'll just do this one for you...  The places where I use ecce are rather
    # complicated and I'm not up to providing a replacement using
    echo "I'm installing a local copy of ecce for you in $BINDIR"
    pushd $SRCDIR > /dev/null
    wget -q http://ecce.sourceforge.net/ecce.c
    gcc -o $BINDIR/ecce ecce.c
    ECCE="$BINDIR/ecce"
    gcc -o $BINDIR/ecce8 -DWANT_UTF8 ecce.c
    rm -f ecce.c
    popd > /dev/null
fi

if [ "`which dos2unix`" = "" ] ; then
    # I know what to suggest for Ubuntu.  Should implement the suggestion part
    # more portably for other systems.
    echo dos2unix is not available - perhaps you need to: sudo apt-get install dos2unix
    exit 1
    # Ideally there should be *no* DOS-format files in the github. Not even for Windows targets.
    # The makefiles clean up *.imp and *.c but I did notice one Makefile that had Windows line endings as well
fi

if [ "`which unzip`" = "" ] ; then
    echo unzip is not available - perhaps you need to: sudo apt-get install unzip
    exit 1
fi

M32="-m32"
gcc $M32 -o /dev/null -c /dev/null 2> /tmp/$$
fgrep "unrecognized command line option" /tmp/$$ && M32=""
# echo M32 option set to $M32
rm -f /tmp/$$

if [ "$M32" = "" ] ; then
    echo ""
    echo " You are probably running on a 32-bit host, so all the calls in the scripts and Makefiles"
    echo " which use the -m32 option are not going to work."
    echo ""
    echo " This script is patching a few things to make the installation work but that many changes"
    echo " are too much for this script to handle. Please contact John McMullin and ask him to replace"
    echo " all instances of \"-m32\" with \$M32, if Imp is to be built on 32-bit systems."
    echo ""
    exit 1
fi

# Hopefully patch and install will come with build-essentials
if [ "`which patch`" = "" ] ; then
    echo patch is not available - perhaps you need to: sudo apt-get install patch
    exit 1
fi

if [ "`which install`" = "" ] ; then
    # should come pre-installed.  Not sure if this is really how to install it if missing...
    echo install is not available - perhaps you need to: sudo apt-get install install
    exit 1
fi

wget -q https://github.com/siliconsam/imp2022/archive/refs/heads/main.zip
if [ -d imp2022-main ] ; then
    echo "Saving previous $SRCDIR/imp2022-main as $SRCDIR/imp2022-main-`date +"%Y%m%d%H%M"`"
    mv imp2022-main imp2022-main-`date +"%Y%m%d%H%M"`
fi
unzip -q main.zip
cd imp2022-main

# Fix the loader script:
if [ -f  pass3/ld.i77.script.ORIG ] ;  then
echo ""
echo "Using the previously-created pass3/ld.i77.script"
echo ""
else
echo ""
echo ""
echo "Creating a local version of pass3/ld.i77.script from the output of ld --verbose"
echo ""
echo ""
ld --verbose > ld.script ; cp ld.script ld.script.ORIG
# one way of finding end of .text is looking for next '.'
# an alternative might be t0/}/m
$ECCE ld.script <<EOF > /dev/null 2>&1
(  (v/ /r)0 v/.text/\ m)0
m
(  (v/ /r)0 v/./\ m)0
g0
  . = ALIGN(32);
  .trap : { *(.imp.trap.B) *(.imp.trap.D) *(.imp.trap.F) }
  .rel.trap : { *(.rel.imp.trap.B) *(.rel.imp.trap.D) }

  .imp.switch : { *(.switch ) }
  .rel.imp.switch : { *(.rel.imp.switch) }                              /* include the IMP switch data */
:
m-0f/==============/kk-0
m0f-/==============/k0
%C
EOF
mv  pass3/ld.i77.script  pass3/ld.i77.script.ORIG
mv  ld.script  pass3/ld.i77.script
diff -C 3 pass3/ld.i77.script ld.script.ORIG
rm -f ld.script.ORIG
echo ""
echo ""
fi

# make locations available to Makefiles
export BINDIR="$BINDIR"
export LIBDIR="$LIBDIR"
export SRCDIR="$SRCDIR/imp2022-main"
export INCDIR="$INCDIR"
export M32="$M32"

MAKEOPTS="-f Makefile-gt"

# Now set up bootstrapping environment:

# build the pass3 program (used to generate the Elf .o files from .ibj files)
# The pass3 program is generated from the pass3elf.c source (generates .rel relocations)

cd $SRCDIR/pass3
cp Makefile Makefile-gt
patch -o Makefile-gt Makefile <<EOF
*** Makefile    2023-12-13 09:22:04.000000000 -0600
--- Makefile-gt 2024-05-08 15:30:12.791784336 -0500
***************
*** 5,9 ****

! BASEDIR = /usr/local

  BINDIR = \${BASEDIR}/bin

--- 5,11 ----

! # BASEDIR = /usr/local

+ ifndef BINDIR
  BINDIR = \${BASEDIR}/bin
+ endif

EOF
echo
echo "Making install in `pwd`"
echo
echo BINDIR=$BINDIR
echo LIBDIR=$LIBDIR
echo SRCDIR=$SRCDIR
echo INCDIR=$INCDIR
echo WD=`pwd`
echo
make $MAKEOPTS install

# build the library
cd $SRCDIR/lib
cp Makefile Makefile-gt
# yeah, I generated this patch the wrong way round :-/
patch -R -o Makefile-gt Makefile <<EOF
*** Makefile	2024-05-08 15:53:48.003933286 -0500
--- Makefile-gt	2023-12-13 09:22:04.000000000 -0600
***************
*** 1,6 ****
  .RECIPEPREFIX = >
! ifndef M32
! M32= -m32
! endif
! CC = gcc \$(M32)
  CCFLAGS = -O
--- 1,3 ----
  .RECIPEPREFIX = >
! CC = gcc -m32
  CCFLAGS = -O
***************
*** 8,20 ****
  # LOOK! Change these three if they don't match your local policies
! # BASEDIR = /usr/local
  
- ifndef BINDIR
  BINDIR = \${BASEDIR}/bin
- endif
- ifndef LIBDIR
  LIBDIR = \${BASEDIR}/lib
- endif
- ifndef INCDIR
  INCDIR = \${BASEDIR}/include
- endif
  
--- 5,11 ----
  # LOOK! Change these three if they don't match your local policies
! BASEDIR = /usr/local
  
  BINDIR = \${BASEDIR}/bin
  LIBDIR = \${BASEDIR}/lib
  INCDIR = \${BASEDIR}/include
  
***************
*** 68,70 ****
  libimp77.so: \$(OBJS)
! > \$(CC)  -shared -fPIC -Wl,-soname,libimp77.so -o libimp77.so \$(OBJS)
  
--- 59,61 ----
  libimp77.so: \$(OBJS)
! > gcc -m32 -shared -fPIC -Wl,-soname,libimp77.so -o libimp77.so \$(OBJS)
  
***************
*** 101,103 ****
  %.o: %.ibj
! > \$(BINDIR)/pass3elf \$<
  
--- 92,94 ----
  %.o: %.ibj
! > pass3elf \$<
  
***************
*** 105,107 ****
  # Ensure all IMP source files have Unix line-endings
! > \$(BINDIR)/imp77 -c -Fc -Fs -Fi \$<
  
--- 96,98 ----
  # Ensure all IMP source files have Unix line-endings
! > imp77 -c -Fc -Fs -Fi \$<
  
EOF
echo
echo "Making bootstrap in `pwd`"
echo
echo BINDIR=$BINDIR
echo LIBDIR=$LIBDIR
echo SRCDIR=$SRCDIR
echo INCDIR=$INCDIR
echo WD=`pwd`
echo
make $MAKEOPTS bootstrap # |& more

# build the pass1, pass2 programs
cd ${SRCDIR}/compiler

cp Makefile Makefile-gt
patch -o Makefile-gt Makefile <<EOF
*** Makefile	2023-12-13 09:22:04.000000000 -0600
--- Makefile-gt	2024-05-08 16:33:12.509967500 -0500
***************
*** 1,3 ****
  .RECIPEPREFIX = >
! 
  CC = gcc -no-pie \${M32}
--- 1,5 ----
  .RECIPEPREFIX = >
! ifndef M32
! M32 = -m32
! endif
  CC = gcc -no-pie \${M32}
***************
*** 5,11 ****
  
! BASEDIR = /usr/local
  
  BINDIR = \${BASEDIR}/bin
  LIBDIR = \${BASEDIR}/lib
  INCDIR = \${BASEDIR}/include
  
--- 7,19 ----
  
! # BASEDIR = /usr/local
  
+ ifndef BINDIR
  BINDIR = \${BASEDIR}/bin
+ endif
+ ifndef LIBDIR
  LIBDIR = \${BASEDIR}/lib
+ endif
+ ifndef INCDIR
  INCDIR = \${BASEDIR}/include
+ endif
  
***************
*** 37,43 ****
  # First create the .o files from the .obj files
! > pass3elf takeon.ibj
! > pass3elf ibj.utils.ibj
! > pass3elf icd.utils.ibj
! > pass3elf pass1.ibj
! > pass3elf pass2.ibj
  
--- 45,51 ----
  # First create the .o files from the .obj files
! > \$(BINDIR)/pass3elf takeon.ibj
! > \$(BINDIR)/pass3elf ibj.utils.ibj
! > \$(BINDIR)/pass3elf icd.utils.ibj
! > \$(BINDIR)/pass3elf pass1.ibj
! > \$(BINDIR)/pass3elf pass2.ibj
  
***************
*** 81,83 ****
  i77.tables.inc: i77.grammar takeon
! > takeon i77.grammar=i77.tables.inc,i77.par.debug,i77.lex.debug
  
--- 89,91 ----
  i77.tables.inc: i77.grammar takeon
! > \$(BINDIR)/takeon i77.grammar=i77.tables.inc,i77.par.debug,i77.lex.debug
  
EOF

echo
echo "Making bootstrap in `pwd`"
echo
echo BINDIR=$BINDIR
echo LIBDIR=$LIBDIR
echo SRCDIR=$SRCDIR
echo INCDIR=$INCDIR
echo WD=`pwd`
echo
make $MAKEOPTS bootstrap # |& more

cd ${SRCDIR}/tools/ibj
# This file should not have windows line endings.
dos2unix Makefile
cp Makefile Makefile-gt
patch -o Makefile-gt Makefile <<EOF
*** Makefile	2023-12-13 09:22:04.000000000 -0600
--- Makefile-gt	2024-05-08 16:19:10.537692667 -0500
***************
*** 2,8 ****
  
! BASEDIR = /usr/local
  
  BINDIR = \${BASEDIR}/bin
  LIBDIR = \${BASEDIR}/lib
  INCDIR = \${BASEDIR}/include
  
--- 2,14 ----
  
! # BASEDIR = /usr/local
  
+ ifndef BINDIR
  BINDIR = \${BASEDIR}/bin
+ endif
+ ifndef LIBDIR
  LIBDIR = \${BASEDIR}/lib
+ endif
+ ifndef INCDIR
  INCDIR = \${BASEDIR}/include
+ endif
  
***************
*** 57,59 ****
  slimibj:
! > imp77link slimibj ibjconversion symbols labels
  
--- 63,65 ----
  slimibj:
! > \$(BINDIR)/imp77link slimibj ibjconversion symbols labels
  
EOF


cd ${SRCDIR}/tools/icd
# This file should not have windows line endings.
dos2unix Makefile
cp Makefile Makefile-gt
patch -o Makefile-gt Makefile <<EOF
*** Makefile	2023-12-13 09:22:04.000000000 -0600
--- Makefile-gt	2024-05-08 16:21:20.683251333 -0500
***************
*** 2,8 ****
  
! BASEDIR = /usr/local
  
  BINDIR = \${BASEDIR}/bin
  LIBDIR = \${BASEDIR}/lib
  INCDIR = \${BASEDIR}/include
  
--- 2,14 ----
  
! # BASEDIR = /usr/local
  
+ ifndef BINDIR
  BINDIR = \${BASEDIR}/bin
+ endif
+ ifndef LIBDIR
  LIBDIR = \${BASEDIR}/lib
+ endif
+ ifndef INCDIR
  INCDIR = \${BASEDIR}/include
+ endif
  
EOF

# clean up
cd ${SRCDIR}/pass3
echo BINDIR=$BINDIR
echo LIBDIR=$LIBDIR
echo SRCDIR=$SRCDIR
echo INCDIR=$INCDIR
echo WD=`pwd`
echo
make $MAKEOPTS superclean
cd ${SRCDIR}/lib
echo BINDIR=$BINDIR
echo LIBDIR=$LIBDIR
echo SRCDIR=$SRCDIR
echo INCDIR=$INCDIR
echo WD=`pwd`
echo
make $MAKEOPTS superclean
cd ${SRCDIR}/compiler
echo BINDIR=$BINDIR
echo LIBDIR=$LIBDIR
echo SRCDIR=$SRCDIR
echo INCDIR=$INCDIR
echo WD=`pwd`
echo
make $MAKEOPTS superclean

patch ${BINDIR}/imp77 <<EOF
*** bin/imp77	2024-05-08 16:58:00.227304418 -0500
--- imp77	2024-05-08 17:06:18.719791813 -0500
***************
*** 4,7 ****
  # Compiler source and binary folders 
! SOURCEDIR=~/winhome/tools/imp2022
! RELEASEDIR=/usr/local
  
--- 4,7 ----
  # Compiler source and binary folders 
! SRCDIR=${SRCDIR} ; INCDIR=${INCDIR} ; BINDIR=${BINDIR} ; LIBDIR=${LIBDIR}
! # RELEASEDIR=/usr/local
  
***************
*** 63,77 ****
  if \${TEST_MODE}; then
!   INC_DIR=\${SOURCEDIR}/include
!   P1_PROG=\${SOURCEDIR}/compiler/pass1
!   P2_PROG=\${SOURCEDIR}/compiler/pass2
!   P3_PROG=\${SOURCEDIR}/pass3/pass3elf
!   LD_SCRIPT=\${SOURCEDIR}/pass3/ld.i77.script
!   LIB_DIR=\${SOURCEDIR}/lib
  else
!   INC_DIR=\${RELEASEDIR}/include
!   P1_PROG=\${RELEASEDIR}/bin/pass1
!   P2_PROG=\${RELEASEDIR}/bin/pass2
!   P3_PROG=\${RELEASEDIR}/bin/pass3elf
!   LD_SCRIPT=\${RELEASEDIR}/bin/ld.i77.script
!   LIB_DIR=\${RELEASEDIR}/lib
  fi
--- 63,77 ----
  if \${TEST_MODE}; then
!   INC_DIR=\${SRCDIR}/include
!   P1_PROG=\${SRCDIR}/compiler/pass1
!   P2_PROG=\${SRCDIR}/compiler/pass2
!   P3_PROG=\${SRCDIR}/pass3/pass3elf
!   LD_SCRIPT=\${SRCDIR}/pass3/ld.i77.script
!   LIB_DIR=\${SRCDIR}/lib
  else
!   INC_DIR=\${INCDIR}
!   P1_PROG=\${BINDIR}/pass1
!   P2_PROG=\${BINDIR}/pass2
!   P3_PROG=\${BINDIR}/pass3elf
!   LD_SCRIPT=\${BINDIR}/ld.i77.script
!   LIB_DIR=\${LIBDIR}
  fi
EOF

patch ${BINDIR}/imp77link <<EOF
*** bin/imp77link	2024-05-08 16:58:00.231304363 -0500
--- imp77link	2024-05-08 17:07:36.162527659 -0500
***************
*** 2,5 ****
  
! BINDIR=/usr/local/bin
! LIBDIR=/usr/local/lib
  IMPLIB=\${LIBDIR}/libimp77.a
--- 2,6 ----
  
! BINDIR=${BINDIR}
! LIBDIR=${LIBDIR}
! 
  IMPLIB=\${LIBDIR}/libimp77.a
EOF

# and finally use the bootstrap to rebuild:

cd $LIBDIR
make $MAKEOPTS

cd $SRCDIR/compiler
make $MAKEOPTS

cd $LIBDIR
make $MAKEOPTS install

cd $SRCDIR/compiler
make $MAKEOPTS install


cd ${SRCDIR}/tests
${BINDIR}/imp77 bilbo.imp
./bilbo "Test program compiled and ran successfully!" 2>&1 | fgrep "BILBO: Param(1)"

if [ "$BINDIR" != "/usr/local/bin" ] ; then
    echo ""
    echo "** If you now want to install this compiler without overwriting a previous installation,"
    echo "** create a script in /usr/local/bin/imp2022 (or whatever you want to call it) containing"
    echo ""
    echo "#!/bin/bash"
    #echo "export SRCDIR=\"$SRCDIR\""
    #echo "export BINDIR=\"$BINDIR\""
    #echo "export LIBDIR=\"$LIBDIR\""
    #echo "export INCDIR=\"$INCDIR\""
    echo "${BINDIR}/imp77 \$*"
    echo ""
    echo "** You should do something similar for imp77link as imp2022link."
    echo "** "
    echo "** Note that the imp77 script itself ensures that subsidiary commands (e.g. pass3elf)"
    echo "** are called with explicit paths, so no other files need to be renamed or aliased."
    echo "** "
    echo "** "
    echo ""

    echo
    echo However, if you prefer to use this local build, add these to your ~/.bash_profile
    echo or whatever is the appropriate file on your system:
    echo
    echo export PATH=$BINDIR/bin:\$PATH
    echo and possibly...
    echo export LD_LIBRARY_PATH=$LIBDIR/lib
    echo

fi
