#!/bin/perl
#File: perlwatch

system ("clear");
print <<END;
 This program will run on a file or interactively from the prompt. It will 
 display the currently defined symbol tables, their entries, addresses and 
 values as you enter code from the command line or it is read from the file.  
 At the  bottom a prompt will be displayed to allow the user to enter
 a perl command or the next line of an existing file.  When the user presses
 enter, any symbol table updates will be displayed , along with
 the output of the command, if any.  You may ONLY enter SIMPLE one-line
 statements or statement blocks or expressions;
 If you run this program on a file, be sure that the last line begins with 
 a "q".  To record your session, you may invoke as follows:

	  $0 |tee watch.out
                 or
          $0 file |tee watch.out

Enter a "q" at the "-->" prompt to quit.
<cr> to cont...
END
$junk = <STDIN>;
$| = 1;
#open (OUT,"&>STDOUT);
$package = "main";
@predefined_keys = keys(%main::);
#print "@predefined_keys\n";
#&setup_screen();
print "\n\n--> ";
while (($inline = <>) !~ /^q/)
 {
  chomp $inline;
  $inline =~ s/[\00..\039]//g; # to strip backspaces, etc
  print "$inline\n";
  print "-->>> ";
  eval $inline;
  print_symbol_table();
  print "\n\n--> ";
 }

#setup screen size
sub setup_screen
 {
  for ($i = 100;$i>=1;$i--)
   {
    print "$i\n";
   }
  print "Enter the number at the top of the screen: ";
  $rows = <STDIN>;
  print "\$rows is $rows\n";
 }
 
sub print_symbol_table
 {
  print "\nPackage main::\n";
  foreach $key (sort (keys %main::))
   {
    if (! grep /^$key$/, @predefined_keys)
     {
	if (defined &{$key})
	 {
          $outline = sprintf ("sub    %s ","\&".$key);
	  print "$outline\n";
	 }
	if (defined $$key)
	 {
          $outline = sprintf ("scalar %s = \"%s\" at %s","\$".$key,$$key,\$$key);
	  print "$outline\n";
	 }
	if (defined @$key)
	 {
          $outline = sprintf ("array  %s = \"%s\" at %s","\@".$key,"@$key",\@$key);
	  print "$outline\n";
	 }
	if (defined %$key)
	 {
	  $hash_val = "";
	  while (($mkey,$val) = each (%{$key}))
	   {
	    $hash_val .= $mkey."=>".$val." ";
	   }
          $outline = sprintf ("hash   %s = \"%s\" at %s","\%".$key,$hash_val,\%$key);
	  print "$outline\n";
	 }
     }
    #eval print "$key: -> ",\$key,"\n" ; 
   }
  #exit 0;
  foreach $key (sort (keys %main::))
   {
    if ( $key =~ /::$/)
     {
      if (!grep /^$key$/, @predefined_keys)
       {
        $package = $key;
        print "\nPackage ${package}\n";
        foreach $inner_key (sort (keys %$package))
         {
	  if (defined ${$package.$inner_key})
	   {
            $outline = sprintf ("     %s = \"%s\" at %s","\$".$inner_key,
						  ${$package.$inner_key},
						  \${$package.$inner_key});
	    print "$outline\n";
	   }
	  if (defined @{$package.$inner_key})
	   {
            $outline = sprintf ("     %s = \"%s\" at %s","\@".$inner_key,
						  @{$package.$inner_key},
						  \@{$package.$inner_key});
	    print "$outline\n";
	   }
	  if (defined %{$package.$inner_key})
	   {
            $outline = sprintf ("     %s = \"%s\" at %s","\%".$inner_key,
						  %{$package.$inner_key},
						  \%{$package.$inner_key});
	    print "$outline\n";
	   }
          #  print "    $inner_key\n";# if (! grep /^$inner_key$/, @predefined_keys);
         }
       }
     }
   }
 }
