#!/bin/sh

if test $# -ne 1 -a $# -ne 2; then
	echo "usage: mprmap nmfile [flfile] <mpr.log" >&2
	exit 1
fi

nmfile=$1
flfile=$2

awk -v nmfile=$nmfile -v flfile=$flfile '

	BEGIN {
		FS="	"	# tab
		i=1
		while (getline <nmfile) {	# create pc->fn mapping
			addr[i] = $1
			fn[i++] = $2
			if (flfile != "")
				continue
			if ($2 in seen)		# duplicate name
				for (j=0; j<seen[$2]; j++)
					fn[i-1] = fn[i-1]"+"
			seen[$2]++
		}
		addr[i] = addr[i-1]	# sentinel
		naddr = i-1
		if (naddr == 0) {	# no symbols
			printf "mpr: no symbol table\n" |"cat 1>&2"
			exit 0
		}
		if (flfile)		# create pc->file/line mapping
			while (getline <flfile)
				fl[$1] = "("$2","$3")"
		FS=OFS=":"
	}

	function bt(n, i) {	# backtrace
		printf "%s", $1
		if (flfile)
			for (i=2; i<n; i++)
				printf ":%s%s", mapfn($i), mapfl($i)
		else
			for (i=2; i<n; i++)
				printf ":%s", mapfn($i)
		for (i=n; i<=NF; i++)
			printf ":%s", $i
		printf "\n"
	}

	function mapfn(pc, l,u,m) {	# map pc->fn
		if (pc in memoize)
			return memoize[pc]
		l=1; u=naddr
		while (l <= u) {	# binary search
			m = int((l+u)/2)
			if (addr[m] > pc)
				u=m-1
			else if (addr[m+1] <= pc)
				l=m+1
			else
				return memoize[pc] = fn[m]
		}
		# not found
		printf "mpr: oops (pc=%d; NR=%d)\n", pc, NR |"cat 1>&2"
		return memoize[pc] = pc
	}

	function mapfl(pc) {	# map pc->file/line
		if (pc in fl)
			return fl[pc]
		else
			return "()"
	}

	/^m/ { bt(NF-1) }
	/^f/ { bt(NF) }
	/^r/ { bt(NF-2) }'

exit 0
