#!/bin/bash

# This script creates lists of all the dependencies and symbols required
# by each shared library in $CERNLEVEL/shlib and program in $CERNLEVEL/bin.
# Should be run while in the top-level cernlib-<version> source dir.

errormsg() {
	echo "Not in correct directory or cernlib not compiled with shlibs"
	exit 1
}

# remove old files
for file in `(ls -1 *.txt) 2> /dev/null` libdeps bindeps ; do
	rm -rf $file
done
if [ ! -d shlib ] ; then errormsg ; fi

mkdir -p libdeps
[ -d bin ] && mkdir -p bindeps

# add in several other of the usual suspects
cd shlib
ln -sf /lib/libc.so.6 ./libc.so
ln -sf /lib/libm.so.6 ./libm.so
ln -sf /usr/lib/libgfortran.so
ln -sf /usr/lib/libcrypt.so
ln -sf /usr/lib/libdl.so
ln -sf /usr/lib/libblas.so
ln -sf /usr/lib/liblapack.so
ln -sf /usr/lib/libXm.so
for file in /usr/X11R6/lib/libX*.so ; do
	ln -sf $file
done

# create symbol lists...
for lib in lib*.so ; do
	if [ -z "`ls -l $lib | egrep -- '-> (/usr(|/X11R6|/local)|)/lib/'`" ] ; then
		nm -D $lib | fgrep ' U ' | awk '{print $2}' > ../${lib%%.so}.undef.txt
	fi
	nm -D $lib | fgrep -v ' U ' | sed 's/@@.*$//g' | \
		awk '{print $3}' > ../${lib%%.so}.def.txt
done

if [ -d "../bin" ] ; then
	cd ../bin
	for prog in * ; do
		if [ -n "`nm -D $prog 2> /dev/null`" ] ; then
			nm -D $prog | fgrep ' U ' | awk '{print $2}' \
			| sed 's/@@.*$//g' > ../$prog.undef.txt
		fi
	done
fi
	
# create lists of symbol dependencies
cd ..
for symlist in *.undef.txt ; do
	(
		for symbol in `cat $symlist` ; do
			grep '^'$symbol'$' *.def.txt
		done
	) | tr ':.' '  ' | awk '{print $1 " " $4}' | sort | \
	grep -v '^libc ' >> ${symlist%%.undef.txt}.symdeps.txt
done

cat *.def.txt > defined.txt

for symlist in *.undef.txt ; do
	(
		for symbol in `cat $symlist` ; do
			if [ -z "`grep -l '^'$symbol'$' defined.txt`" ] ; then
				echo $symbol
			fi
		done
		) | c++filt | sort > ${symlist%%.undef.txt}.unknown.txt
done

# delete unneeded files
rm -f defined.txt *.def.txt *.undef.txt
for file in shlib/lib*.so ; do
	if [ -n "`ls -l $file | egrep -- '-> (/usr(|/X11R6|/local)|)/lib/'`" ] ; then
		libname=${file##shlib/}
		rm -f ${libname%%.so}.*.txt
	fi
done

# create lists of file dependencies with number of dependent symbols
for file in *.symdeps.txt ; do
	tempfile=${file%%.symdeps.txt}.filedeps.txt.tmp
	awk '{ print $1 }' < $file | sort | uniq > $tempfile
	for file2 in `cat $tempfile` ; do
		echo "$file2 `grep $file2 $file | wc -l`" >> ${tempfile%%.tmp}
	done
	rm -f $tempfile
	c++filt < $file | sort > $file.tmp
	mv -f $file.tmp $file
done

# move to proper places
mv lib*.txt libdeps/
[ -d bindeps ] && mv *.txt bindeps/
for file in libdeps/* bindeps/* ; do
	[ ! -s $file ] && rm -f $file
done

exit 0
