#!/bin/sh

echo
echo ".a to .ixlibrary converter, version 2.0"
echo

prefix="/gg/share/a2ixlibrary"

eval `/gg/bin/date "+day=%d;month=%m;year=%y"`
day=`expr $day + 0`
month=`expr $month + 0`
year=`expr $year + 0`
debug=0
resident=-mresident32
modifier=W
gccflags= #-DDEBUG

while true
do
	if [ "$1" = "-debug" ]
	then
		debug=1
		shift
		echo "Entered debug mode"
	elif [ "$1" = "-32" ]
	then
		resident="-resident32"
		modifier=L
		shift
	else
		break
	fi
done

if [ X"$1" = X ]
then
	data=a2ixlibrary.data
else
	data=$1
fi

if [ ! -f $data ]
then
	echo could not find $data!
	exit 2
fi

echo scan $data
name=`egrep "^#define NAME " $data | sed -e "s/#define NAME *//" -e "s/ *$//"`
filename=`egrep "^#define FILENAME " $data | sed -e "s/#define FILENAME *//" -e "s/ *$//"`
safename=`$prefix/a2ixsafename $name`
libs=`egrep "^#define LIBS_LIST " $data | sed -e "s/#define LIBS_LIST *//" -e "s/ *$//"`
dirs=`egrep "^#define LINK_DIRS " $data | sed -e "s/#define LINK_DIRS *//" -e "s/ *$//"`
internals=`egrep "^#define INTERNALS " $data`

if [ X"$filename" = X ]
then
	filename=$name
fi

if [ ! -f lib$filename.a ]
then
	echo could not find lib$filename.a!
	exit 2
fi

if [ X"$libs" != X ]
then
	for i in $libs
	do
		if [ -f $prefix/ldscripts/${i}.x ]
		then
			shared_libs="$shared_libs $i"
			static_libs="$static_libs -l${i}_ixlibrary"
		else
			static_libs="$static_libs -l$i -l${i}_ixlibrary"
		fi
	done
fi

if [ X"$dirs" != X ]
then
	for i in $dirs
	do
		link_dirs="$link_dirs -L$i"
	done
fi

rm -rf amigaobj
mkdir amigaobj

if [ ! X"$internals" = X ]
then
	cp $data amigaobj/x.c
	echo "
	INTERNALS" >>amigaobj/x.c
	internals=`gcc $gccflags -E -P amigaobj/x.c`
	rm -f amigaobj/x.c
fi

echo collect init routines
call_inits="#define CALL_INITS "`egrep -s amiga_init_ *.c | sed -e 's/^.*amiga/amiga/' -e 's/(void)/();\\\\/' | sort`

cd amigaobj

echo pre-linking lib$filename.o
mkdir tmp
cd tmp
ar x ../../lib$filename.a
ld -r -o ../lib$filename.o *.o
cd ..
rm -rf tmp

echo create stubs
rm -f ../lib${filename}_ixlibrary.a
mkdir tmp
cd tmp
$prefix/build_glues ../lib$filename.o $internals
ar q ../../lib${filename}_ixlibrary.a *.o
cd ..
rm -rf tmp

echo create relocation data
$prefix/build_link_info lib$filename.o lib_funcs.o $internals

echo find globals in lib$filename.a
nm --extern-only ../lib$filename.a | egrep " D | C " | sort +2 >g2.lst
if [ X"$internals" != X ]
then
	echo remove internals
	for i in $internals
	do
		egrep -v " ${i}$" <g2.lst >gg.lst
		cp gg.lst g2.lst
	done
	rm -f gg.lst
fi 
cut -c 12- <g2.lst >g.lst

echo create $filename.h
mkdir -p /gg/include/a2ixlibrary
hdr=/gg/include/a2ixlibrary/$filename.h
echo "/* This file is automatically generated by a2ixlibrary. Do not change.
   Only shared library sources can include this header, do not use this header
   in your own programs! */
#ifndef UNDEF_amiga_$safename
" >$hdr
sed -e 's/^/extern void *__/' -e 's/$/_'$safename'_shared_ptr;/' <g.lst >>$hdr
sed -e 's/^\(.*\)/#define \1 (*((__typeof__(\1) *)__\1_'$safename'_shared_ptr))/' <g.lst >>$hdr
echo "#define UNDEF_amiga_$safename
#else" >>$hdr
sed -e 's/^/#undef /' <g.lst >>$hdr
echo "#undef UNDEF_amiga_$safename
#endif" >>$hdr
rm -f g.lst

echo create a2ixlibrary.h
cd ..
cp $data amigaobj/a2ixlibrary.h
cd amigaobj
cat <<EOF >>a2ixlibrary.h
#define xstr(s) str(s)
#define str(s) #s
#define SNAME xstr(NAME)
#define SVERSION xstr(VERSION)
#define SREVISION xstr(REVISION)
#define FULLNAME \"lib$name.ixlibrary\"
#define IDSTRING \"lib$name \" SVERSION \".\" SREVISION \" ($day.$month.$year)\"
#define BASE ${safename}Base
#define CLOSEINST __${safename}CloseInstance
#define RELOCINST __${safename}RelocateInstance
#define SETVARSINST __${safename}SetVarsInstance
#define RELOCTABLE __reloc_table_${safename}
$call_inits

EOF

if [ X"$shared_libs" != X ]
then
	echo "	#define INSTANCE_LIBS \\
		extern char * const __section_table[]; \\" >>a2ixlibrary.h
	for i in $shared_libs
	do
		safei=`$prefix/a2ixsafename $i`
		linklibs="$linklibs -l$i" 
		echo "struct Library *${safei}Base = NULL; \\
		      extern const unsigned long * const __reloc_table_${safei} __attribute__((section(\".rodata\"))); \\
		      extern unsigned long _${safei}_shared_ptr_table[]; \\
		      void _shared_start_lib${safei}(); \\
		      int __${safei}RelocateInstance(char * const *bases, const unsigned long *relocs, char *old_data, char *new_data) \\
		      { \\
			struct EmulCaos caos; \\
			caos.reg_d0 = (LONG)bases; \\
			caos.reg_d1 = (LONG)relocs; \\
			caos.reg_d2 = (LONG)old_data; \\
			caos.reg_d3 = (LONG)new_data; \\
			caos.reg_a6 = (LONG)${safei}Base; \\
			caos.caos_Un.Offset = -36; \\
			return MyEmulHandle->EmulCallOS(&caos); \\
		      } \\" >>a2ixlibrary.h
	done
	echo "static int open_libs(void) { \\
		char *old_data = __get_data(); \\
		char *r13; asm volatile (\"mr %0,13\" : \"=r\" (r13)); r13 -= 0x8000; \\" >>a2ixlibrary.h

	for i in $shared_libs
	do
		safei=`$prefix/a2ixsafename $i`
		echo "if (!(${safei}Base = OpenLibrary(\"lib$i.ixlibrary\", 0))) return 0; \\
		      if (!__${safei}RelocateInstance(__section_table,__reloc_table_${safei},old_data,r13)) \\
			{ CloseLibrary(${safei}Base); return 0; } \\" >>a2ixlibrary.h
	done
	echo "return 1; } \\
	      static void close_libs(void) { \\" >>a2ixlibrary.h
	for i in $shared_libs
	do
		safei=`$prefix/a2ixsafename $i`
		echo "if (${safei}Base) CloseLibrary(${safei}Base); \\" >>a2ixlibrary.h
	done
	echo "}

	      #define MISC_SETVARS \\" >>a2ixlibrary.h
	for i in $shared_libs
	do
		safei=`$prefix/a2ixsafename $i`
		echo "extern struct Library *${safei}Base; \\
		      const unsigned long * const __reloc_table_${safei} __attribute__((section(\".rodata\"))) = 0; \\
		      void __${safei}SetVarsInstance(int argc, void *ixbase, \\
				       int *errnoptr, char *ctype, void **sf) \\
		      { \\
			struct EmulCaos caos; \\
			caos.reg_d0 = (LONG)argc; \\
			caos.reg_d1 = (LONG)ixbase; \\
			caos.reg_d2 = (LONG)errnoptr; \\
			caos.reg_d3 = (LONG)ctype; \\
			caos.reg_d4 = (LONG)sf; \\
			caos.reg_a6 = (LONG)${safei}Base; \\
			caos.caos_Un.Offset = -42; \\
			MyEmulHandle->EmulCallOS(&caos); \\
		      } \\" >>a2ixlibrary.h
	done
	echo "
		#define CALL_SETVARS \\" >>a2ixlibrary.h
	for i in $shared_libs
	do
		safei=`$prefix/a2ixsafename $i`
		echo "__${safei}SetVarsInstance(argc, ixbase, errnoptr, ctype, sf);\\" >>a2ixlibrary.h
	done
	echo "
		void *__get_data(void);
	" >>a2ixlibrary.h
fi

echo compile start.c
gcc $gccflags -O -I. -c $prefix/start.c -o start.o
echo compile instance.c

# This source *must* be compiled with -malways-restore-r13!
gcc $gccflags $resident -malways-restore-r13 -I. -c -O $prefix/instance.c -o instance.o
echo compile relocate.c
gcc $gccflags -I. -I$prefix $resident -mrestore-r13 -c -O $prefix/relocate.c -o relocate.o
echo compile setvars.c
gcc $gccflags -I. $resident -mrestore-r13 -c -O $prefix/setvars.c -o setvars.o

echo create link script
cp $prefix/morphos_lib_script.x .

if [ X"$shared_libs" != X ]
then
	for i in $shared_libs
	do
		cat $prefix/ldscripts/${i}.x >>morphos_lib_script.x
	done
fi
echo "
  }
  PROVIDE (__sbss_size = __sbss_end - __sbss_start);
}" >>morphos_lib_script.x

if [ X"$internals" != X ]
then
	echo rename internals
	for i in $internals
	do
		sed -e "s/${i}/XX${i}/g" <morphos_lib_script.x >a
		cp a morphos_lib_script.x
	done
	rm -f a
fi 

echo link lib$filename.ixlibrary
gcc $gccflags -static $resident -o ../lib$filename.ixlibrary -nostdlib -nostartfiles -L.. start.o \
		instance.o relocate.o setvars.o lib_funcs.o \
		lib$filename.o $static_libs -lc -lgcc -lc -lamiga -lamigastubs -lsyscall -Xlinker -Tmorphos_lib_script.x $link_dirs

if [ ! -f ../lib$filename.ixlibrary ]
then
	echo failed to link lib$filename.ixlibrary
	rm -f ../lib$filename.a
	exit 2
fi

echo create $filename.x
mkdir -p $prefix/ldscripts
$prefix/build_script ../lib$filename.ixlibrary lib$filename.o $prefix/ldscripts/$filename.x $safename $internals

echo compile auto_init.c
gcc $gccflags -g -I. -c -O $prefix/auto_init.c -o auto_init.o

cd ..

echo create new lib${filename}_ixlibrary.a
ar q lib${filename}_ixlibrary.a amigaobj/auto_init.o
ranlib lib${filename}_ixlibrary.a

echo postprocess lib$filename.ixlibrary
postlink -library lib$filename.ixlibrary

if [ "$debug" -ne 0 ]
then
	cp lib$filename.ixlibrary amigaobj/lib$filename.debug
fi

strip lib$filename.ixlibrary

if [ "$debug" -eq 0 ]
then
	rm -rf amigaobj
fi

exit 0
