#!/bin/sh 
#
#
# debauch: find memory errors
#
#

if [ $# -lt 1 ]
then
   echo usage: $0 [-a] program_name [program args]
   echo        -a: all warnings
   exit
fi

if [ $1 = "-a" ]
then
   fullwarn=1   
   shift
else
   fullwarn=0
fi

OBJ=$1
OUT=$OBJ.$$.out
LINES=$OBJ.$$.lines
SED=$OBJ.$$.sed
ADDRS=$OBJ.$$.addrs
GDBCMD=$OBJ.$$.gdb
trap "rm -f $SED $LINES $ADDRS $OUT $GDBCMD" 0
shift

#
# run program and collect output
#

DebauchWarnReferenced=$fullwarn DebauchWarnUnreferenced=$fullwarn LD_PRELOAD=/usr/lib/libdebauch.so $OBJ $* 2>$OUT

if [ $? -ne 0 ] 
then
   echo "Warning: program had non-zero exit status."
   echo "         It may have dumped core."
fi

#cat $OUT

#
# get list of addresses to look up
# note: the newline in the sed statements are important
#
sed 's;Saved;\
  ;' $OUT  |
sed 's;Current;\
  ;' | grep 'return stack:' | 
	tr ' ' '\012' | 
	grep 0x | sort -u > $ADDRS

#cat $ADDRS

#
# get file / line information from GDB
#
cat > $GDBCMD <<EOF
set env LD_PRELOAD=/usr/lib/libdebauch.so
break main
run
EOF

sed 's;^;info line *;' $ADDRS |
      gdb $OBJ -x $GDBCMD | grep 'address' | 
      sed 's/No line number information available for/Line ?? of "???" starts at/' |
      sed 's/(gdb) //' > $LINES

#cat $LINES

#
# create sed script to merge file/line info into output
#
paste $ADDRS $LINES | awk '{ printf("s;%s;%s:%s (%s) %s;\n", $1, $5, $3, $1, $10) }' > $SED
echo "s;\";;g" >> $SED

#cat $SED


#
# Write non-stack output
#
grep -v Saved $OUT | grep -v Current | sed 's;^$;;' | uniq

#
# generate unique list of errors with file/line info
# note: the newline in the sed statement is important
#
sort -t\t +1 $OUT | grep "return stack" | uniq -c -f5 |
sed 's;Current;\
  ;' |
sed 's;Saved;\
  ;' | sed 's/^\ */ /' |
    awk '/return stack/	{ printf ("\treturn stack:\n");
			  for (i = 3; i <= NF; i++)
				printf ("\t\t%s\n", $i); }
     /^\ *[0-9]/		{ print }' |
     sed -f $SED 










