#!/bin/sh
# XXX duplicates functionality of mprnm and mprfl

TMP=${MPRTMP-/tmp}
MPRAWK=${MPRAWK-awk}

pcfile=$TMP/mprfl.pc.$$
gdbfile=$TMP/mprfl.gdb.$$
gdbcmdfile=$TMP/mprfl.gdbcmd.$$
tmpnmfile=$TMP/mprfll.nm.$$
fofiles=
nmfile=
flfile=
popt=

for arg in "$@"; do
	case "$1" in
	-p)	popt=-p;;
	-n )	nmfile="$2"; shift;;
	-n*)	nmfile=`echo "$1" | sed 's/-n//'`;;
	-f )	flfile=$2; shift;;
	-f*)	flfile=`echo "$1" | sed 's/-f//'`;;
	-F )	fofiles="$2"; shift;;
	-F*)	fofiles=`echo "$1" | sed 's/-F//'`;;
	--)	shift; break;;
	-*)	echo "mprfl-so: warning: ignoring unknown option $1" >&2;;
	*)	break;;
	esac
	shift
done

usage()
{
	echo "usage: mprfl-so -n nmfile -f flfile [-F foo.c,bar.c,..] a.out [log]" >&2
	exit 1
}

case "$nmfile" in
"")	usage;;
esac

case "$flfile" in
"")	usage;;
esac

case "$#" in
1|2)	;;
*)	usage;;
esac

aout=`mprwhich "$1"` || exit 1; shift
MPRFILTER=`mprfilter mprfl-so "$@"` || exit 1

(mprnm "$aout"; mprnm -D "$aout") 2>/dev/null | grep '	_init$' >/dev/null
case "$?" in
0)	;;
*)	echo mprfl-so: error: cannot find symbol _init in "$aout" >&2
	exit 1;;
esac

unset MPRFI
set -e
status=1
trap 'set +e; rm -f $pcfile $gdbfile $gdbcmdfile $tmpnmfile; trap 0; exit $status' 0 1 2 13 15

$MPRFILTER |

$MPRAWK -F: '
	function savepc(n, i) { for (i=2; i<=n; i++) pc[$i]=1 }
	/^m/ { savepc(NF-2) }
	/^r/ { savepc(NF-3) }
	/^f/ { savepc(NF-1) }
	END  { for (i in pc) print i }
' |

sort -n | tee $pcfile |

(
	echo set prompt
	echo set confirm 0
	echo set width 0
	echo set print demangle off
	echo set print asm-demangle off
	case "$MPRLD_PRELOAD" in
	?*)	echo set env LD_PRELOAD "$MPRLD_PRELOAD${LD_PRELOAD:+:}$LD_PRELOAD";;
	esac
	echo break _init
	echo run
	$MPRAWK '{ printf "info line *%s\n", $1 }'
	echo quit
) >$gdbcmdfile

(gdb -nx -q --command=$gdbcmdfile "$aout" 2>/dev/null; echo) |

$MPRAWK '
	{
		gsub(/\(gdb\) /, "")
	}
	/^$/ {
		next
	}
	/^Line/ {
		gsub(/"/, "", $4)
		sub(/\.$/, "", $(NF-5))
		sub(/^</, "", $(NF-5))
		sub(/\+[0-9]+>$/, "", $(NF-5))
		sub(/>$/, "", $(NF-5))
		if ($4 ~ /^\.\//)	# delete leading ./
			$4 = substr($4, 3)
		printf "%s\t%s\t%s\n", $(NF-5), $4, $2
		next
	}
	/No line number.*>/ {
		sub(/\.$/, "", $NF)
		sub(/^</, "", $NF)
		sub(/\+[0-9]+>$/, "", $NF)
		sub(/>$/, "", $NF)
		printf "%s\txxx\n", $NF
		next
	}
	/No line number/ {
		printf "xxx\n"
		next
	}
	/^(Breakpoint [0-9]|Current language|\(no debugging|\[New|\[Switching)/ {
		next
	}
	/Program exited normally/ {
		next
	}
	# unexpected output from gdb -> print a warning
	{
		printf "*** mprfl-so: warning: unexpected output from gdb\n" |"cat 1>&2"
		printf "*** mprfl-so: [%s]\n", $0 |"cat 1>&2"
	}
' >$gdbfile

>$flfile
>$tmpnmfile

paste $pcfile $gdbfile |

$MPRAWK -v nmfile="$tmpnmfile" -v flfile="$flfile" -v fofiles="$fofiles" '
	BEGIN {
		OFS="\t"
		if (fofiles != "") {
			gsub(",", "|", fofiles)
			gsub(" ", "|", fofiles)
			gsub("/", "\\/", fofiles)
			gsub("\\.", "\\.", fofiles)
		}
	}
	{
		sub(/	xxx$/, "")
	}
	NF==1 {
		next
	}
	NF==2 {
		print >>nmfile
		next
	}
	NF==4 {
		print $1, $2 >>nmfile
		if (fofiles == "" || $3 ~ "^("fofiles")$")
			print $1, $3, $4 >>flfile
		next
	}
	# unexpected output from paste -> bail out
	{
		printf "*** mprfl-so: error: unexpected output from paste\n" |"cat 1>&2"
		printf "*** mprfl-so: [%s]\n", $0 |"cat 1>&2"
		exit 1
	}'

mprdem $popt <$tmpnmfile |

sed -e 's/global destructors keyed to /_GLOBAL_$D$/' \
    -e 's/global constructors keyed to /_GLOBAL_$C$/' \
    -e 's/::/<>/g' >"$nmfile"

status=0
