function_backtrace_1.0/
#!/usr/bin/perl

# debug.pl
# by Richard Lawrence (silver@ewtoo.org)

use strict;

my $mode = 0;
my $prevline;

# these shouldn't have any calls to ENTERFUNCTION or EXITFUNCTION
my @functions = qw(get_string get_string_safe get_int get_int_safe send_to_debug end_string addstack endstack debug_wall);

open(FILE, "$ARGV[0]") || die "can't open: $ARGV[0]: $!";
while(<FILE>)
{
  chomp;

  if (/^[\S ]+?\s{10}.+?(\S+?)\(/ && $mode == 0)
  {
    unless (dont_log($1))
    {
      $mode = 1;
    }
    print "$_\n";
  }
  
  elsif (/^\{$/ && $mode == 1)
  {
    $mode = 2;
    print "$_\n";
  }

  elsif ($mode == 2)
  {
    if (!$_)
    {
      print "$_\n";
    }
    else
    {
      unless (/^    \S[\S ]+?\s{10}.+?;.*$/)
      {
        if (/ENTERFUNCTION/)
        {
          # we've already tagged this function so ignore
          $mode = 0;
          print "$_\n";
        }
        else
        {
          print "ENTERFUNCTION;\n";
          $mode = 3;
          print "$_\n";
        }
      }
      else
      {
        print "$_\n";
      }
    }
  }

  elsif (/^\s+?(return.*?;)$/ && $mode == 3)
  {
    my $ret = $1;
    if ($prevline =~ /^\s+?if\s*\(/ || $prevline =~ /^\s+?else.*/)
    {
      print "{ EXITFUNCTION; ";
      print "$ret }\n";
    }
    else
    {
      print "EXITFUNCTION;\n$1\n";
    }
  }

  elsif (/^\}$/)
  {
    if ($mode == 3)
    {
      # don't display a leave if the last thing called was a return
      # ie. we've returned at the end of a function
      unless ($prevline =~ /^\s+?(return.*?;)$/)
      {
        print "EXITFUNCTION;\n";
      }
    }
    $mode = 0;
    print "$_\n";
  }

  else
  {
    print "$_\n";
  }

  $prevline = $_;
}

exit;

sub dont_log
{
  my $chk = $_[0];
  $chk =~ tr/A-Z/a-z/;

  foreach my $fn (@functions)
  {
    $fn =~ tr/A-Z/a-z/;
    return 1 if ($chk eq $fn);
  }
  return 0;
}