#! /bin/sh

# workarea
# Copyright 1984-2017 Cisco Systems, Inc.
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
# http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

srcdir=`dirname "$0"`

if [ $# != 1 -a $# != 2 -a $# != 3 -a $# != 4 ] ; then
    echo "Usage: workarea <machine-type> { <workarea name> <pb host machine-type> <boot machine-name>}"
    exit 1
fi

# set M to machine type and W to workarea name
M=$1
if [ "$2" = "" ] ; then
    W=$M
else
    W=$2
fi
if [ "$3" != "" ] ; then
   Mpbhost=$3
else
   Mpbhost=""
fi
if [ "$4" != "" ] ; then
   Mboot=$4
else
   Mboot="$M"
fi

Muni=""

case "$M" in
  pb*|tpb*) Mhost=$Mpbhost ;;
  *) Mhost=$M ;;
esac

case "$Mhost" in
  a6fb) ;;
  a6le) ;;
  a6nb) ;;
  a6nt) ;;
  a6ob) ;;
  a6osx) ;;
  a6s2) ;;
  arm32le) ;;
  arm32fb) ;;
  arm32ob) ;;
  arm32nb) ;;
  arm64le) ;;
  arm64fb) ;;
  arm64ob) ;;
  arm64nb) ;;
  arm64osx) ;;
  arm64nt) ;;
  i3fb) ;;
  i3le) ;;
  i3nb) ;;
  i3nt) ;;
  i3ob) ;;
  i3osx) ;;
  i3qnx) ;;
  i3s2) ;;
  ppc32le) ;;
  ppc32fb) ;;
  ppc32ob) ;;
  ppc32nb) ;;
  ppc32osx) ;;
  pb) ;;
  pb64l) ;;
  pb64b) ;;
  pb32l) ;;
  pb32b) ;;
  tpb) ;;
  tpb64l) ;;
  tpb64b) ;;
  tpb32l) ;;
  tpb32b) ;;
  ta6fb) ;;
  ta6le) ;;
  ta6nb) ;;
  ta6nt) ;;
  ta6ob) ;;
  ta6osx) ;;
  ta6s2) ;;
  tarm32le) ;;
  tarm32fb) ;;
  tarm32ob) ;;
  tarm32nb) ;;
  tarm64le) ;;
  tarm64fb) ;;
  tarm64ob) ;;
  tarm64nb) ;;
  tarm64osx) ;;
  tarm64nt) ;;
  ti3fb) ;;
  ti3le) ;;
  ti3nb) ;;
  ti3nt) ;;
  ti3ob) ;;
  ti3osx) ;;
  ti3s2) ;;
  tppc32le) ;;
  tppc32fb) ;;
  tppc32ob) ;;
  tppc32nb) ;;
  tppc32osx) ;;
  em) ;;
  *) echo "unrecognized machine name: $Mhost"; exit 1 ;;
esac

Muni=`echo $M | sed -e 's/^t//'`
Mhostuni=`echo $Mhost | sed -e 's/^t//'`

# If Mtype is set, then Mf-$Mtype is used,
# otherwise Mf-$M and Mf-$Muni (or Mf-$Mhost and Mf-$Mhostuni) is used
case "$Mhost" in
  *nt) ;;
  *) Mtype=unix ;;
esac

if [ "$Muni" != "" ] ; then
    Muniarch=$Muni
else
    Muniarch=$Mhost
fi    

case "$Muni" in
    a6*)
        March=a6
        archincludes=x86_64.ss
        ;;
    arm32*)
        March=arm32
        archincludes=arm32.ss
        ;;
    arm64*)
        March=arm64
        archincludes=arm64.ss
        ;;
    i3*)
        March=i3
        archincludes=x86.ss
        ;;
    ppc32*)
        March=ppc32
        archincludes=ppc32.ss
        ;;
    pb*)
        March=pb
        archincludes=pb.ss
        Mword=64
        case "$Muni" in
            *64l)
                Mword=64
                Mend=little
                ;;
            *64b)
                Mword=64
                Mend=big
                ;;
            *32l)
                Mword=32
                Mend=little
                ;;
            *32b)
                Mword=32
                Mend=big
                ;;
        esac
        ;;
    *)
        March=""
        archincludes=""
        ;;
esac

case "$Mhost" in
  *nt) Mos=nt ;;
  *) Mos="" ;;
esac

if [ "$OS" = "Windows_NT" ]
then
    ln="cp -R"
else
    ln="ln -s"
fi

# This shell script creates a workarea for local modifications to the
# Chez Scheme source code.  Invoke with the name of a machine type:
# i3le, i3nt, ti3osx, etc., plus an optional workarea name.  The script
# creates a subdirectory in the current working (release) directory.
# If the workarea name argument is not given, this subdirectory is
# named by the machine type.  The workarea contains subdirectories
# that correspond to various subdirectories of the release directory.
# Initially, all of the files in the workarea are links back into the
# source directories.  Furthermore, many of the files are simply make
# files that are used to rebuild the system, and in most cases, the
# make files themselves create links for the source files as needed.
# To make local modifications, convert the links into local copies.

case "$srcdir" in
    /*)
        upsrcdir=$srcdir
        upupsrcdir=$srcdir
        upupupsrcdir=$srcdir
        ;;
    *)
        upsrcdir=../$srcdir
        upupsrcdir=../../$srcdir
        upupupsrcdir=../../../$srcdir
        ;;
esac

if [ -f boot/$Mboot/scheme.boot ] ; then
    bootdir=.
    upbootdir=..
    upupupbootdir=../../..
else
    bootdir=$srcdir
    upbootdir=$upsrcdir
    upupupbootdir=$upupupsrcdir
fi

# workln source dest
# creates link if dest does not exist and source does
workln()
{
    if [ ! -e $2 -a -e "$1" ] ; then
        $ln "$1" $2 2> /dev/null
    fi
}

# forceworkln source dest
# attempts to create link even if source does not exist
forceworkln()
{
    if [ -h $2 ] ; then
        rm $2
    fi
    if [ ! -e $2 ] ; then
        ln -s "$1" $2 2> /dev/null
    fi
}

forceworkln2()
{
    if [ ! -e $2 ] ; then
        $ln "$1" $2 2> /dev/null
    fi
}

# workdir directory-name
workdir()
{
    if [ ! -e $1 ] ; then
        mkdir $1
    fi
}

workdir $W

workdir $W/c
if [ "$Mtype" != "" ] ; then
  (cd $W/c; workln "$upupsrcdir"/c/Mf-$Mtype Mf-$Mtype)
  (cd $W/c; forceworkln Mf-$Mtype Makefile)
else
  (cd $W/c; workln "$upupsrcdir"/c/Mf-$Mhost Mf-$Mhost)
  (cd $W/c; forceworkln Mf-$Mhost Makefile)
  if [ "$Mhostuni" != "" ] ; then
    (cd $W/c; workln "$upupsrcdir"/c/Mf-$Mhostuni Mf-$Mhostuni)
  fi
  if [ "$Mos" != "" ] ; then
    (cd $W/c; workln "$upupsrcdir"/c/Mf-$Mos Mf-$Mos)
  fi
fi
(cd $W/c; workln "$upupsrcdir"/c/Mf-base Mf-base)
if [ ! -e $W/c/config.h ] ; then
  touch $W/c/config.h
fi
if [ ! -e $W/c/Mf-config ] ; then
  touch $W/c/Mf-config
fi
case $Mhost in
  *nt)
    (cd $W/c; workln "$upupsrcdir"/c/vs.bat vs.bat)
    ;;
esac

workdir $W/s
if [ "$Mtype" != "" ] ; then
  (cd $W/s; workln ${upupsrcdir}/s/Mf-$Mtype Mf-$Mtype)
  (cd $W/s; forceworkln Mf-$Mtype Makefile)
else
  (cd $W/s; workln ${upupsrcdir}/s/Mf-$M Mf-$M)
  (cd $W/s; forceworkln Mf-$M Makefile)
  if [ "$Muni" != "" ] ; then
    (cd $W/s; workln ${upupsrcdir}/s/Mf-$Muni Mf-$Muni)
  fi
fi
(cd $W/s; workln "$upupsrcdir"/s/Mf-base Mf-base)
(cd $W/s; workln "$upupsrcdir"/s/Mf-cross Mf-cross)
if [ -e "$srcdir"/s/$M.def ] ; then
  (cd $W/s; workln "$upupsrcdir"/s/$M.def $M.def)
else
    # synthesize generic Unix or pb .def file;
    # this process is duplicated in "s/make-xpatch.ss"
    if [ -h $W/s/$M.def ] ; then
        rm $W/s/$M.def
    fi
    if [ "$March" = "pb" ] ; then
        if [ "$M" = "$Muni" ] ; then
            Mpb=pbarch
        else
            Mpb=tpbarch
        fi
        sed -e 's/$(M)/'$M'/g'\
            -e 's/$(March)/'$March'/g'\
            -e 's/$(Mword)/'$Mword'/g'\
            -e 's/$(Mend)/'$Mend'/g'\
            "$srcdir"/s/${Mpb}.def > $W/s/$M.def
    else
        if [ "$M" = "$Muni" ] ; then
            Munix=unix
        else
            Munix=tunix
        fi
        sed -e 's/$(M)/'$M'/g'\
            -e 's/$(March)/'$March'/g'\
            "$srcdir"/s/${Munix}.def > $W/s/$M.def
    fi
fi
(cd $W/s; forceworkln2 $M.def machine.def)
if [ "$March" != "" ] ; then
  (cd $W/s; workln "$upupsrcdir"/s/$March.def $March.def)
  if [ "$March" = "pb" ] ; then
    (cd $W/s; workln "$upupsrcdir"/s/pbcommon.def pbcommon.def)
    (cd $W/s; workln "$upupsrcdir"/s/pbcommon$Mword.def pbcommon$Mword.def)
  fi
fi
if [ "$Mos" != "" ] ; then
  (cd $W/s; workln "$upupsrcdir"/s/$Mos.def $Mos.def)
fi
(cd $W/s; workln "$upupsrcdir"/s/default.def default.def)

workdir $W/mats
if [ "$Mtype" != "" ] ; then
  (cd $W/mats; workln "$upupsrcdir"/mats/Mf-$Mtype Mf-$Mtype)
  (cd $W/mats; forceworkln Mf-$Mtype Makefile)
else
  (cd $W/mats; workln "$upupsrcdir"/mats/Mf-$M Mf-$M)
  (cd $W/mats; forceworkln Mf-$M Makefile)
  if [ "$Muni" != "" ] ; then
    (cd $W/mats; workln "$upupsrcdir"/mats/Mf-$Muni Mf-$Muni)
  fi
  if [ "$Mos" != "" ] ; then
    (cd $W/mats; workln "$upupsrcdir"/mats/Mf-$Mos Mf-$Mos)
  fi
fi
if [ "$Mpbhost" != "" ] ; then
  (cd $W/mats; workln "$upupsrcdir"/mats/Mf-$Mpbhost Mf-$Mpbhost)
  (cd $W/mats; forceworkln Mf-$Mpbhost Mf-pbhost)
fi
(cd $W/mats; workln "$upupsrcdir"/mats/Mf-base Mf-base)
(cd $W/mats; workln "$upupsrcdir"/mats/Mf-exobj Mf-exobj)
case $Mhost in
  *nt)
    (cd $W/mats; workln "$upupsrcdir"/mats/vs.bat vs.bat)
    ;;
esac

linkeach()
{
    dir=$1
    workdir $W/$dir
    for file in `(cd "$srcdir"/$dir ; echo *)` ; do
        (cd $W/$dir ; workln "$upupsrcdir"/$dir/$file $file)
    done
}

linkeach examples
linkeach unicode

# deep copy submodules where builds occur so changes don't propagate through symlinks
for dir in `echo zlib` ; do
  if [ ! -e $W/$dir ] ; then
    cp -R "$srcdir"/$dir $W/$dir
  fi
done

for dir in `echo lz4` ; do
  if [ ! -e $W/$dir ] ; then
    cp -R "$srcdir"/$dir $W/$dir
  fi
done

workdir $W/boot
workdir $W/boot/$M
(cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/scheme.h scheme.h)
(cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/equates.h equates.h)
(cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/gc-ocd.inc gc-ocd.inc)
(cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/gc-oce.inc gc-oce.inc)
(cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/gc-par.inc gc-par.inc)
(cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/vfasl.inc vfasl.inc)
(cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/heapcheck.inc heapcheck.inc)
if [ -e "$bootdir"/boot/"$Mboot" ] ; then
    for file in `(cd "$bootdir"/boot/"$Mboot" ; echo *.boot)` ; do
        (cd $W/boot/$M ; workln "$upupupbootdir"/boot/$Mboot/$file $file)
    done
    for file in `(cd "$bootdir"/boot/"$Mboot" ; echo *.c)` ; do
        (cd $W/boot/$M ; workln "$upupupbootdir"/boot/$Mboot/$file $file)
    done
fi
case $M in
  *nt)
    (cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/mainmd.obj mainmd.obj)
    (cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/mainmt.obj mainmt.obj)
    (cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/csv957md.lib csv957md.lib)
    (cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/csv957mt.lib csv957mt.lib)
    (cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/scheme.res scheme.res)
    ;;
  *)
    (cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/main.o main.o)
    (cd $W/boot/$M; workln "$upupupbootdir"/boot/$Mboot/kernel.o kernel.o)
    ;;
esac

workdir $W/bin
workdir $W/bin/$M
case $M in
  *nt)
    (cd $W/bin/$M; workln "$upupupsrcdir"/bin/$M/scheme.exe scheme.exe)
    (cd $W/bin/$M; forceworkln2 scheme.exe petite.exe)
    (cd $W/bin/$M; workln "$upupupsrcdir"/bin/$M/csv957.dll csv957.dll)
    (cd $W/bin/$M; workln "$upupupsrcdir"/bin/$M/csv957.lib csv957.lib)
    ;;
  *)
    (cd $W/bin/$M; workln "$upupupsrcdir"/bin/$M/scheme scheme)
    (cd $W/bin/$M; forceworkln scheme petite)
    ;;
esac

# crutch links for fingers that remember old release structure
case $M in
  *nt)
    (cd $W/bin; forceworkln $M/scheme.exe scheme)
    (cd $W/bin; forceworkln $M/petite.exe petite)
    ;;
  *)
    (cd $W/bin; forceworkln $M/scheme scheme)
    (cd $W/bin; forceworkln $M/petite petite)
    ;;
esac

workdir $W/bintar
(cd $W/bintar; workln "$upupsrcdir"/bintar/Makefile Makefile)

workdir $W/rpm
(cd $W/rpm; workln "$upupsrcdir"/rpm/Makefile Makefile)

workdir $W/pkg
(cd $W/pkg; workln "$upupsrcdir"/pkg/Makefile Makefile)
(cd $W/pkg; workln "$upupsrcdir"/pkg/rmpkg rmpkg)

(cd $W; workln ../LOG LOG)
(cd $W; forceworkln2 "$upsrcdir"/nanopass nanopass)
(cd $W; workln "$upsrcdir"/makefiles/installsh installsh)
(cd $W; workln "$upsrcdir"/scheme.1.in scheme.1.in)

cat > $W/s/Mf-config << END
upupsrcdir=$upupsrcdir
upupupbootdir=$upupupbootdir
m=$M
archincludes=$archincludes
END

cat > $W/Mf-config << END
srcdir=$srcdir
END

# temporary; replaced by `configure`, but needed for *nt
cat > $W/c/Mf-config << END
upupsrcdir=$upupsrcdir
m=$M
END

# temporary; replaced by `configure`, but needed for *nt
cat > $W/mats/Mf-config << END
upupsrcdir=$upupsrcdir
m=$M
END

case $Mhost in
  *nt)
    (cd $W/c; make source > /dev/null 2>&1)
    (cd $W/s; make source > /dev/null 2>&1)
    (cd $W/mats; make source > /dev/null 2>&1)
    ;;
esac

exit 0
