#! /bin/sh
#
# Information that characterize a shared library to build:
#
LIBNAME=libm3                # library name (libm3, libui ...)
                             # where the library built should go
ADDRESS=0x80000000           # a virtual address assigned to that library
JUMPSIZE=0x8000              # size of the jump table with space for growth
GOTSIZE=0x4000               # size of the got table with space for growth
MAJOR=3                      # major release number
MINOR=3                      # minor release number
IMPORTLIBS_TAIL="/usr/lib/libc /usr/lib/libm" # shared libs on which it depends
LDLIBS_TAIL="-lm -lc -lgcc -lc"   # all libs on which it depends
IMPORTLIBS=""
LDLIBS=""

#
# These values can be read from the command line
#
USAGE="buildShared \
  -n library_name\
  -a shared_lib_address\
  -j jump_table_size\
  -g got_table_size\
  -x major_version_no\
  -y minor_version_no\
  -l libraries_to_link\
  "

while getopts n:a:j:g:x:y:l: name
  do
  case $name in
    n)   LIBNAME=$OPTARG;;
    a)   ADDRESS=$OPTARG;;
    j)   JUMPSIZE=$OPTARG;;
    g)   GOTSIZE=$OPTARG;;
    x)   MAJOR=$OPTARG;;
    y)   MINOR=$OPTARG;;
    l)   LDLIBS=$OPTARG;;
    \?)  echo $USAGE
         exit 2;;
  esac
  shift; shift; OPTIND=1;
  done
shift `expr $OPTIND - 1`

#
# Fix the list of libraries
#

IMPORTLIBS=`echo "$LDLIBS" | sed -e 's+-L\([^ ]*\) -l\([^ ]*\)+\1/lib\2+g'`
IMPORTLIBS="$IMPORTLIBS $IMPORTLIBS_TAIL"
LDLIBS="$LDLIBS $LDLIBS_TAIL"

#
# The shared lib toolkit needs some info to be passed by the JUMP_DIR
# and JUMP_LIB environment variables.
#

JUMP_DIR=`pwd`/jump
export JUMP_DIR
if test -n "`ls jump`"; then rm jump/*; fi

JUMP_LIB=$LIBNAME
export JUMP_LIB
VERSION=$MAJOR.$MINOR
IMAGE=$LIBNAME

#
# For libm3 we must insert dummy definitions for the symbols to appear in 
# the file _m3main.c produced by m3build when a program is compiled.
#

if test $LIBNAME = libm3; then (cat >jumpas/_tmpm3main.s <<EOF); fi
	.file	"_tmpm3main.c"
gcc2_compiled.:
___gnu_compiled_c:
.data
.globl __type_names
	.align 2
__type_names:
	.long 2
.text
	.align 4
.globl _main
_main:
	ret
.lcomm __types,852
.comm __alloc_cnts,852
.comm __alloc_bytes,852
.comm __m3_exporters,4
EOF

#
# Everything must be built. The outcome is the file jump/jump.log which lists
# all the global symbols in the library
#

AS="/usr/dll/jump/as"
#AS="echo as"

cd jumpas
for i in `ls *s`; do
  echo $AS -o `basename $i s`o $i
  $AS -o `basename $i s`o $i
done
cd ..

#
# The global variables and functions are extracted from jump/jump.log.
# Because m3build recompiles some modules when it finds new opaque info,
# duplicate entries must be removed from jump.log.
#
#(cd $JUMP_DIR; mv jump.log jump.log.old; sort <jump.log.old | uniq >jump.log)

(cd $JUMP_DIR; /usr/dll/bin/getvars;)

#
# we test the grep first. Most M3 modules only have a global variable pointing
# to functions but no functions. Getfuncs does not like that.
#
(cd $JUMP_DIR;/usr/bin/grep ' T ' jump.log >jump.funcs && /usr/dll/bin/getfuncs)
(cd $JUMP_DIR; mv jump.log jump.log.old)

#
# Global symbols imported from other shared libs must be in jump/jump.import
#
if test -f $JUMP_DIR/jump.import; then rm $JUMP_DIR/jump.import; fi

for i in $IMPORTLIBS; do
  if test -f $i.sa; then
    nm --no-cplus -o $i.sa | grep __GOT_ | \
      sed 's/ __GOT__/ _/' >>$JUMP_DIR/jump.import
  fi
done

#
# Now that we have the jump.vars, jump.funcs and jump.import files, we
# rebuild everything a second time. All the calls to global variables
# and functions will be intercepted and treated appropriately.
#

cd jumpas
for i in `ls *s`; do
  echo $AS -o `basename $i s`o $i
  $AS -o `basename $i s`o $i
done
cd ..

#
# The size of each global variable is measured before building the jump table
#
(cd $JUMP_DIR; /usr/dll/bin/getsize >jump.vars.new; \
  mv jump.vars jump.vars.old; mv jump.vars.new jump.vars)

#
# The shared library is finally constructed and verified.
#

MKIMAGE=/usr/dll/bin/mkimage
#MKIMAGE="echo mkimage"

$MKIMAGE -f -l $IMAGE -v $VERSION -a $ADDRESS -j $JUMPSIZE \
  -g $GOTSIZE -- 'jumpas/*o' $LDLIBS

MKSTUBS=/usr/dll/bin/mkstubs
#MKSTUBS="echo mkstubs"
$MKSTUBS -l $IMAGE -v $VERSION -a $ADDRESS -j $JUMPSIZE \
  -g $GOTSIZE -- $LIBNAME

VERIFY=/usr/dll/bin/verify-shlib
#VERIFY="echo verify"

$VERIFY -l $IMAGE.so.$VERSION $IMAGE.sa

#
# A symlink redirects all requests to the major version to this specific
# major.minor version
#
#if test -f $IMAGE.so.$MAJOR; then rm $IMAGE.so.$MAJOR; fi
#ln -s $IMAGE.so.$MAJOR.$MINOR $IMAGE.so.$MAJOR
