home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / perl / scripts-convex / profiling / perlpf.pl < prev    next >
Encoding:
Perl Script  |  1993-07-14  |  4.9 KB  |  209 lines

  1. #! /HOME/waynet/bin/perl
  2. #
  3. #    @(#)perlpf    1.0 (waynet@sun) 12/14/88
  4. #
  5. # Author:
  6. #     Wayne Thompson
  7. #
  8. # Description:
  9. #     Perlpf is a profiler for perl scripts. The profile is sent to stdout.
  10. #     Perlpf is blatantly based on perldb.
  11. #
  12. # Options:
  13. #     -o filename - put generated script in filename.
  14. #
  15. # Files:
  16. #     /tmp/ppf$$     i/o>    default file for temporary generated script.
  17. #
  18. # Diagnostics:
  19. #
  20. # Dependencies:
  21. #
  22. # Bugs:
  23. #
  24.  
  25. $tmp = "/tmp/ppf$$";        # default temporary file, -o overrides.
  26.  
  27. # parse any switches
  28.  
  29. while ($ARGV[0] =~ /^-/) {
  30.     $_ = shift;
  31.     /^-o$/ && ($tmp = shift,next);
  32.     die "Unrecognized switch: $_";
  33. }
  34.  
  35. $filename = shift;
  36. die "Usage: perlpf [-o output] scriptname arguments" unless $filename;
  37.  
  38. open(script,$filename) || die "Can't find $filename";
  39.  
  40. open(tmp, ">$tmp") || die "Can't make temp script";
  41.  
  42. $perl = '/usr/bin/perl';
  43. $init = 1;
  44. $state = 'statement';
  45.  
  46. # now translate script to contain PF calls at the appropriate places
  47.  
  48. while (<script>) {
  49.     chop;
  50.     if ($. == 1) {
  51.     if (/^#! *([^ \t]*) (-[^ \t]*)/) {
  52.         $perl = $1;
  53.         $switch = $2;
  54.     }
  55.     elsif (/^#! *([^ \t]*)/) {
  56.         $perl = $1;
  57.     }
  58.     }
  59.     s/ *$//;
  60.     push(@script,$_);        # remember line for PFinit
  61.     $line = $_;
  62.     next if /^$/;        # blank lines are uninteresting
  63.     next if /^[ \t]*#/;        # likewise comment lines
  64.     if ($init) {
  65.     print tmp "do PFinit($.);"; $init = '';
  66.     }
  67.     if ($inform) {        # skip formats
  68.     if (/^\.$/) {
  69.         $inform = '';
  70.         $state = 'statement';
  71.     }
  72.     next;
  73.     }
  74.     if (/^[ \t]*format /) {
  75.     $inform++;
  76.     next;
  77.     }
  78.     if ($state eq 'statement' &&
  79.       !/^[ \t]*}|^[ \t]*else|^[ \t]*continue|^[ \t]*elsif/) {
  80.     if (s/^([ \t]*[A-Za-z_0-9]+:)//) {
  81.         $label = $1;
  82.     }
  83.     else {
  84.         $label = '';
  85.     }
  86.     $line = $label . "do PF($.); " . $_;    # all that work for this line
  87.     }
  88.     else {
  89.     $script[$#script - 1] .= ' ';    # mark line as having continuation
  90.     }
  91.     do parse();                # set $state to correct eol value
  92. }
  93. continue {
  94.     print tmp $line,"\n";
  95. }
  96.  
  97. # now put out our profiling subroutines.  First the one that's called all over.
  98.  
  99. print tmp '
  100. do PFend ();
  101.  
  102. sub PF {
  103.     $PFline=pop(@_);
  104.     $PFcnt[$PFline]++;
  105. }
  106.  
  107. sub PFinit {
  108. ';
  109. print tmp "    \$0 = '$script';\n";
  110. print tmp "    \$PFmax = $.;\n";
  111. print tmp "    unlink '/tmp/ppf$$';\n";        # expected to fail on -o.
  112. for ($i = 1; $#script >= 0; $i++) {
  113.     $_ = shift(@script);
  114.     s/'/\\'/g;
  115.     print tmp "    \$PFline[$i] = '$_';\n";
  116. }
  117. print tmp '}
  118.  
  119. sub PFend {
  120.     for ($PFi = 1; $PFi <= $PFmax; $PFi++) {
  121.     printf ("%6s\t%s\n", $PFcnt[$PFi], $PFline[$PFi]);
  122.     }
  123. }
  124. ';
  125.  
  126. close tmp;
  127.  
  128. # prepare to run the new script
  129.  
  130. unshift(@ARGV,$tmp);
  131. unshift(@ARGV,$switch) if $switch;
  132. unshift(@ARGV,$perl);
  133. exec @ARGV;
  134.  
  135. # This routine tokenizes one perl line good enough to tell what state we are
  136. # in by the end of the line, so we can tell if the next line should contain
  137. # a call to PF or not.
  138.  
  139. sub parse {
  140.     until ($_ eq '') {
  141.     $ord = ord($_);
  142.     if ($quoting) {
  143.         if ($quote == $ord) {
  144.         $quoting--;
  145.         }
  146.         s/^.//            if /^[\\]/;
  147.         s/^.//;
  148.         last if $_ eq "\n";
  149.         $state = 'term'        unless $quoting;
  150.         next;
  151.     }
  152.     if ($ord > 64) {
  153.         do quote(ord($1),1), next    if s/^m\b(.)//;
  154.         do quote(ord($1),2), next    if s/^s\b(.)//;
  155.         do quote(ord($1),2), next    if s/^y\b(.)//;
  156.         do quote(ord($1),2), next    if s/^tr\b(.)//;
  157.         do quote($ord,1), next    if s/^`//;
  158.         next            if s/^[A-Za-z_][A-Za-z_0-9]*://;
  159.         $state = 'term', next    if s/^eof\b//;
  160.         $state = 'term', next    if s/^shift\b//;
  161.         $state = 'term', next    if s/^split\b//;
  162.         $state = 'term', next    if s/^tell\b//;
  163.         $state = 'term', next    if s/^write\b//;
  164.         $state = 'operator', next    if s/^[A-Za-z_][A-Za-z_0-9]*//;
  165.         $state = 'operator', next    if s/^[~^|]+//;
  166.         $state = 'statement', next    if s/^{//;
  167.         $state = 'statement', next    if s/^}[ \t]*$//;
  168.         $state = 'statement', next    if s/^}[ \t]*#/#/;
  169.         $state = 'term', next    if s/^}//;
  170.         $state = 'operator', next    if s/^\[//;
  171.         $state = 'term', next    if s/^]//;
  172.         die "Illegal character $_";
  173.     }
  174.     elsif ($ord < 33) {
  175.         next if s/[ \t\n\f]+//;
  176.         die "Illegal character $_";
  177.     }
  178.     else {
  179.         $state = 'statement', next    if s/^;//;
  180.         $state = 'term', next    if s/^\.[0-9eE]+//;
  181.         $state = 'term', next    if s/^[0-9][0-9xaAbBcCddeEfF.]*//;
  182.         $state = 'term', next    if s/^\$[A-Za-z_][A-Za-z_0-9]*//;
  183.         $state = 'term', next    if s/^\$.//;
  184.         $state = 'term', next    if s/^@[A-Za-z_][A-Za-z_0-9]*//;
  185.         $state = 'term', next    if s/^@.//;
  186.         $state = 'term', next    if s/^<[A-Za-z_0-9]*>//;
  187.         next            if s/^\+\+//;
  188.         next            if s/^--//;
  189.         $state = 'operator', next    if s/^[-(!%&*=+:,.<>]//;
  190.         $state = 'term', next    if s/^\)+//;
  191.         do quote($ord,1), next    if s/^'//;
  192.         do quote($ord,1), next    if s/^"//;
  193.         if (s|^[/?]||) {
  194.         if ($state =~ /stat|oper/) {
  195.             $state = 'term';
  196.             do quote($ord,1), next;
  197.         }
  198.         $state = 'operator', next;
  199.         }
  200.         next            if s/^#.*//;
  201.     }
  202.     }
  203. }
  204.  
  205. sub quote {
  206.     ($quote,$quoting) = @_;
  207.     $state = 'quote';
  208. }
  209.