#!/usr/local/bin/perl5 -w
#
# Read everything in, find routines that are only on right.
local($tmp);
local($i);
local(@sl);
local($nmain1);
local($nmain3);

# $extra_spaces="                                  ";
$extra_spaces="                        ";

$total_lines = -1;
while (<stdin>) {
  $total_lines++;
  $line[$total_lines] = $_;
  @sl = split(/\s+/, $line[$total_lines]);
  $nmain1 = &fix_name($sl[1]);
  $nmain3 = &fix_name($sl[3]);
  $linesplit0[$total_lines] = $sl[0];
  $linesplit1[$total_lines] = $nmain1;
  $linesplit2[$total_lines] = $sl[2];
  $linesplit3[$total_lines] = $nmain3;
  if ($sl[0] eq '') {
    next;
  }

  if ($#ARGV != 0) {
    if (!defined($rn{$nmain3})) {
      $rn{$nmain3} = 1;
    }
    if ($nmain1 ne $nmain3) {		# Special don't do if both are same -- _snapshot_mcount
					# or recursive routine.
      $rn{$nmain1} = 0;
    }
  }
}

$indentation = 0;

if ($#ARGV == 0) {
  $rn{$ARGV[0]} = 1;
}

# For routines only on right, use them as starting points for display.

foreach $i ( keys(%rn)) {
  if ($rn{$i} != 0) {
    print "\n";
    print "entry $i is a starting point\n";
    for ($j = 0; $j <= $total_lines; $j++) {
      $used[$j] = 0;
    }
    $tmp = substr($line[0], 84);
    printf "%8s %-33s %-8s %-33s%s %s", "", "From Routine", "Address", "To Routine", $extra_spaces, $tmp;
    handle_entry($i);
  }
}

exit(0);


#-----------------------------------------------------------------------------
sub fix_name
{
  local($entry) = $_[0];

  if ($entry eq "ret_from_fork") {
    return("handle_sys");
  } elsif ($entry eq "stack_done") {
    return("handle_sys");
  } elsif ($entry eq "reschedule") {
    return("handle_sys");
  }

# handle_cpu_int is a good thing.
# start_kernel is a good thing.

  return($entry);
}

#-----------------------------------------------------------------------------
sub handle_entry
{
  local($starting) = $_[0];
  local($i);
  local(@list);
#  local(@sl);
#  local($n3);
#  local($addr3);
#  local($n1);
#  local($addr1);
  local($tmp);

  @list = getright($starting);

  foreach $i ( @list ) {
# print "loop=$i\n";
    for ($tmp=0; $tmp < $indentation; $tmp++) {
      print " ";
    }
#    @sl = split(/\s+/, $line[$i]);
#    $n1 = &fix_name($sl[1]);
#    $n3 = &fix_name($sl[3]);
#    $addr1 = $sl[0];
#    $addr3 = $sl[2];
    $tmp = substr($line[$i], 84);
    printf "$linesplit2[$i] %-33s $linesplit0[$i] %-33s%s $tmp", $linesplit3[$i], $linesplit1[$i], substr($extra_spaces,$indentation);
    $indentation++;
    handle_entry($linesplit1[$i]);
    $indentation--;
  }
}

#-----------------------------------------------------------------------------
sub getright
{
  local($starting) = $_[0];
  local($i);
#  local(@sl);
#  local($nrte3);
  local(@ret);

  for ($i = 0; $i <= $total_lines; $i++) {
    if ($used[$i] != 0) {
      next;
    }
#    @sl = split(/\s+/, $line[$i]);
#    $nrte3 = &fix_name($sl[3]);
    if ($linesplit3[$i] eq $starting) {
      $used[$i] = 1;
      push(@ret, $i);
    }
  }
  @ret = sort sortaddress @ret;
# print "return=@ret\n";
  return(@ret);
}

#-----------------------------------------------------------------------------
# sortaddress(string $a, $b)
# returns -1, 0, 1
sub sortaddress
{
#  local(@sa);
#  local(@sb);

#  @sa = split(/\s+/, $line[$a]);
#  @sb = split(/\s+/, $line[$b]);
#  return ($sa[2] cmp $sb[2]);
  return($linesplit2[$a] cmp $linesplit2[$b]);
}
#-----------------------------------------------------------------------------

