perl 5.002beta1h patch: Configure
[p5sagit/p5-mst-13.2.git] / lib / perl5db.pl
1 package DB;
2
3 # modified Perl debugger, to be run from Emacs in perldb-mode
4 # Ray Lischner (uunet!mntgfx!lisch) as of 5 Nov 1990
5 # Johan Vromans -- upgrade to 4.0 pl 10
6
7 $header = '$RCSfile: perl5db.pl,v $$Revision: 4.1 $$Date: 92/08/07 18:24:07 $';
8 #
9 # This file is automatically included if you do perl -d.
10 # It's probably not useful to include this yourself.
11 #
12 # Perl supplies the values for @line and %sub.  It effectively inserts
13 # a &DB'DB(<linenum>); in front of every place that can
14 # have a breakpoint.  It also inserts a do 'perldb.pl' before the first line.
15 #
16 # $Log: perldb.pl,v $
17
18 # Is Perl being run from Emacs?
19 $emacs = ((defined $main::ARGV[0]) and ($main::ARGV[0] eq '-emacs'));
20 shift(@main::ARGV) if $emacs;
21
22 #require Term::ReadLine;
23
24 local($^W) = 0;
25
26 if (-e "/dev/tty") {
27     $console = "/dev/tty";
28     $rcfile=".perldb";
29 }
30 elsif (-e "con") {
31     $console = "con";
32     $rcfile="perldb.ini";
33 }
34 else {
35     $console = "sys\$command";
36     $rcfile="perldb.ini";
37 }
38
39 # Around a bug:
40 if (defined $ENV{'OS2_SHELL'}) { # In OS/2
41   if ($DB::emacs) {
42     $console = undef;
43   } else {
44     $console = "/dev/con";
45   }
46 }
47
48 open(IN, "<$console") || open(IN,  "<&STDIN");  # so we don't dingle stdin
49 open(OUT,">$console") || open(OUT, ">&STDERR")
50     || open(OUT, ">&STDOUT");   # so we don't dongle stdout
51 select(OUT);
52 $| = 1;                         # for DB::OUT
53 select(STDOUT);
54 $| = 1;                         # for real STDOUT
55 $sub = '';
56
57 $header =~ s/.Header: ([^,]+),v(\s+\S+\s+\S+).*$/$1$2/;
58 print OUT "\nLoading DB routines from $header\n";
59 print OUT ("Emacs support ",
60            $emacs ? "enabled" : "available",
61            ".\n");
62 print OUT "\nEnter h for help.\n\n";
63
64 @ARGS;
65
66 sub DB {
67     &save;
68     ($pkg, $filename, $line) = caller;
69     $usercontext = '($@, $!, $,, $/, $\, $^W) = @saved;' .
70         "package $pkg;";                # this won't let them modify, alas
71     local(*dbline) = "::_<$filename";
72     $max = $#dbline;
73     if (($stop,$action) = split(/\0/,$dbline{$line})) {
74         if ($stop eq '1') {
75             $signal |= 1;
76         }
77         else {
78             $evalarg = "\$DB::signal |= do {$stop;}"; &eval;
79             $dbline{$line} =~ s/;9($|\0)/$1/;
80         }
81     }
82     if ($single || $trace || $signal) {
83         if ($emacs) {
84             print OUT "\032\032$filename:$line:0\n";
85         } else {
86             $prefix = $sub =~ /'|::/ ? "" : "${pkg}::";
87             $prefix .= "$sub($filename:";
88             if (length($prefix) > 30) {
89                 print OUT "$prefix$line):\n$line:\t",$dbline[$line];
90                 $prefix = "";
91                 $infix = ":\t";
92             }
93             else {
94                 $infix = "):\t";
95                 print OUT "$prefix$line$infix",$dbline[$line];
96             }
97             for ($i = $line + 1; $i <= $max && $dbline[$i] == 0; ++$i) {
98                 last if $dbline[$i] =~ /^\s*(}|#|\n)/;
99                 print OUT "$prefix$i$infix",$dbline[$i];
100             }
101         }
102     }
103     $evalarg = $action, &eval if $action;
104     if ($single || $signal) {
105         $evalarg = $pre, &eval if $pre;
106         print OUT $#stack . " levels deep in subroutine calls!\n"
107             if $single & 4;
108         $start = $line;
109       CMD:
110         while ((print OUT "  DB<", $#hist+1, "> "), $cmd=&gets) {
111             {
112                 $single = 0;
113                 $signal = 0;
114                 $cmd eq '' && exit 0;
115                 chop($cmd);
116                 $cmd =~ s/\\$// && do {
117                     print OUT "  cont: ";
118                     $cmd .= &gets;
119                     redo CMD;
120                 };
121                 $cmd =~ /^q$/ && exit 0;
122                 $cmd =~ /^$/ && ($cmd = $laststep);
123                 push(@hist,$cmd) if length($cmd) > 1;
124                 ($i) = split(/\s+/,$cmd);
125                 eval "\$cmd =~ $alias{$i}", print OUT $@ if $alias{$i};
126                 $cmd =~ /^h$/ && do {
127                     print OUT "
128 T               Stack trace.
129 s               Single step.
130 n               Next, steps over subroutine calls.
131 r               Return from current subroutine.
132 c [line]        Continue; optionally inserts a one-time-only breakpoint 
133                 at the specified line.
134 <CR>            Repeat last n or s.
135 l min+incr      List incr+1 lines starting at min.
136 l min-max       List lines.
137 l line          List line;
138 l               List next window.
139 -               List previous window.
140 w line          List window around line.
141 l subname       List subroutine.
142 f filename      Switch to filename.
143 /pattern/       Search forwards for pattern; final / is optional.
144 ?pattern?       Search backwards for pattern.
145 L               List breakpoints and actions.
146 S               List subroutine names.
147 t               Toggle trace mode.
148 b [line] [condition]
149                 Set breakpoint; line defaults to the current execution line; 
150                 condition breaks if it evaluates to true, defaults to \'1\'.
151 b subname [condition]
152                 Set breakpoint at first line of subroutine.
153 d [line]        Delete breakpoint.
154 D               Delete all breakpoints.
155 a [line] command
156                 Set an action to be done before the line is executed.
157                 Sequence is: check for breakpoint, print line if necessary,
158                 do action, prompt user if breakpoint or step, evaluate line.
159 A               Delete all actions.
160 V [pkg [vars]]  List some (default all) variables in package (default current).
161 X [vars]        Same as \"V currentpackage [vars]\".
162 < command       Define command before prompt.
163 > command       Define command after prompt.
164 ! number        Redo command (default previous command).
165 ! -number       Redo number\'th to last command.
166 H -number       Display last number commands (default all).
167 q or ^D         Quit.
168 p expr          Same as \"print DB::OUT expr\" in current package.
169 = [alias value] Define a command alias, or list current aliases.
170 command         Execute as a perl statement in current package.
171
172 ";
173                     next CMD; };
174                 $cmd =~ /^t$/ && do {
175                     $trace = !$trace;
176                     print OUT "Trace = ".($trace?"on":"off")."\n";
177                     next CMD; };
178                 $cmd =~ /^S$/ && do {
179                     foreach $subname (sort(keys %sub)) {
180                         print OUT $subname,"\n";
181                     }
182                     next CMD; };
183                 $cmd =~ s/^X\b/V $pkg/;
184                 $cmd =~ /^V$/ && do {
185                     $cmd = "V $pkg"; };
186                 $cmd =~ /^V\b\s*(\S+)\s*(.*)/ && do {
187                     local ($savout) = select(OUT);
188                     $packname = $1;
189                     @vars = split(' ',$2);
190                     do 'dumpvar.pl' unless defined &main::dumpvar;
191                     if (defined &main::dumpvar) {
192                         &main::dumpvar($packname,@vars);
193                     }
194                     else {
195                         print DB::OUT "dumpvar.pl not available.\n";
196                     }
197                     select ($savout);
198                     next CMD; };
199                 $cmd =~ /^f\b\s*(.*)/ && do {
200                     $file = $1;
201                     if (!$file) {
202                         print OUT "The old f command is now the r command.\n";
203                         print OUT "The new f command switches filenames.\n";
204                         next CMD;
205                     }
206                     if (!defined $main::{'_<' . $file}) {
207                         if (($try) = grep(m#^_<.*$file#, keys %main::)) {
208                             $file = substr($try,2);
209                             print "\n$file:\n";
210                         }
211                     }
212                     if (!defined $main::{'_<' . $file}) {
213                         print OUT "There's no code here anything matching $file.\n";
214                         next CMD;
215                     }
216                     elsif ($file ne $filename) {
217                         *dbline = "::_<$file";
218                         $max = $#dbline;
219                         $filename = $file;
220                         $start = 1;
221                         $cmd = "l";
222                     } };
223                 $cmd =~ /^l\b\s*([':A-Za-z_][':\w]*)/ && do {
224                     $subname = $1;
225                     $subname = "main::" . $subname unless $subname =~ /'|::/;
226                     $subname = "main" . $subname if substr($subname,0,1)eq "'";
227                     $subname = "main" . $subname if substr($subname,0,2)eq "::";
228                     ($file,$subrange) = split(/:/,$sub{$subname});
229                     if ($file ne $filename) {
230                         *dbline = "::_<$file";
231                         $max = $#dbline;
232                         $filename = $file;
233                     }
234                     if ($subrange) {
235                         if (eval($subrange) < -$window) {
236                             $subrange =~ s/-.*/+/;
237                         }
238                         $cmd = "l $subrange";
239                     } else {
240                         print OUT "Subroutine $1 not found.\n";
241                         next CMD;
242                     } };
243                 $cmd =~ /^w\b\s*(\d*)$/ && do {
244                     $incr = $window - 1;
245                     $start = $1 if $1;
246                     $start -= $preview;
247                     $cmd = 'l ' . $start . '-' . ($start + $incr); };
248                 $cmd =~ /^-$/ && do {
249                     $incr = $window - 1;
250                     $cmd = 'l ' . ($start-$window*2) . '+'; };
251                 $cmd =~ /^l$/ && do {
252                     $incr = $window - 1;
253                     $cmd = 'l ' . $start . '-' . ($start + $incr); };
254                 $cmd =~ /^l\b\s*(\d*)\+(\d*)$/ && do {
255                     $start = $1 if $1;
256                     $incr = $2;
257                     $incr = $window - 1 unless $incr;
258                     $cmd = 'l ' . $start . '-' . ($start + $incr); };
259                 $cmd =~ /^l\b\s*(([\d\$\.]+)([-,]([\d\$\.]+))?)?/ && do {
260                     $end = (!$2) ? $max : ($4 ? $4 : $2);
261                     $end = $max if $end > $max;
262                     $i = $2;
263                     $i = $line if $i eq '.';
264                     $i = 1 if $i < 1;
265                     if ($emacs) {
266                         print OUT "\032\032$filename:$i:0\n";
267                         $i = $end;
268                     } else {
269                         for (; $i <= $end; $i++) {
270                             print OUT "$i:\t", $dbline[$i];
271                             last if $signal;
272                         }
273                     }
274                     $start = $i;        # remember in case they want more
275                     $start = $max if $start > $max;
276                     next CMD; };
277                 $cmd =~ /^D$/ && do {
278                     print OUT "Deleting all breakpoints...\n";
279                     for ($i = 1; $i <= $max ; $i++) {
280                         if (defined $dbline{$i}) {
281                             $dbline{$i} =~ s/^[^\0]+//;
282                             if ($dbline{$i} =~ s/^\0?$//) {
283                                 delete $dbline{$i};
284                             }
285                         }
286                     }
287                     next CMD; };
288                 $cmd =~ /^L$/ && do {
289                     for ($i = 1; $i <= $max; $i++) {
290                         if (defined $dbline{$i}) {
291                             print OUT "$i:\t", $dbline[$i];
292                             ($stop,$action) = split(/\0/, $dbline{$i});
293                             print OUT "  break if (", $stop, ")\n" 
294                                 if $stop;
295                             print OUT "  action:  ", $action, "\n" 
296                                 if $action;
297                             last if $signal;
298                         }
299                     }
300                     next CMD; };
301                 $cmd =~ /^b\b\s*([':A-Za-z_][':\w]*)\s*(.*)/ && do {
302                     $subname = $1;
303                     $cond = $2 || '1';
304                     $subname = "${pkg}::" . $subname
305                         unless $subname =~ /'|::/;
306                     $subname = "main" . $subname if substr($subname,0,1) eq "'";
307                     $subname = "main" . $subname if substr($subname,0,2) eq "::";
308                     ($filename,$i) = split(/:/, $sub{$subname});
309                     $i += 0;
310                     if ($i) {
311                         *dbline = "::_<$filename";
312                         ++$i while $dbline[$i] == 0 && $i < $#dbline;
313                         $dbline{$i} =~ s/^[^\0]*/$cond/;
314                     } else {
315                         print OUT "Subroutine $subname not found.\n";
316                     }
317                     next CMD; };
318                 $cmd =~ /^b\b\s*(\d*)\s*(.*)/ && do {
319                     $i = ($1?$1:$line);
320                     $cond = $2 || '1';
321                     if ($dbline[$i] == 0) {
322                         print OUT "Line $i not breakable.\n";
323                     } else {
324                         $dbline{$i} =~ s/^[^\0]*/$cond/;
325                     }
326                     next CMD; };
327                 $cmd =~ /^d\b\s*(\d+)?/ && do {
328                     $i = ($1?$1:$line);
329                     $dbline{$i} =~ s/^[^\0]*//;
330                     delete $dbline{$i} if $dbline{$i} eq '';
331                     next CMD; };
332                 $cmd =~ /^A$/ && do {
333                     for ($i = 1; $i <= $max ; $i++) {
334                         if (defined $dbline{$i}) {
335                             $dbline{$i} =~ s/\0[^\0]*//;
336                             delete $dbline{$i} if $dbline{$i} eq '';
337                         }
338                     }
339                     next CMD; };
340                 $cmd =~ /^<\s*(.*)/ && do {
341                     $pre = action($1);
342                     next CMD; };
343                 $cmd =~ /^>\s*(.*)/ && do {
344                     $post = action($1);
345                     next CMD; };
346                 $cmd =~ /^a\b\s*(\d+)(\s+(.*))?/ && do {
347                     $i = $1;
348                     if ($dbline[$i] == 0) {
349                         print OUT "Line $i may not have an action.\n";
350                     } else {
351                         $dbline{$i} =~ s/\0[^\0]*//;
352                         $dbline{$i} .= "\0" . action($3);
353                     }
354                     next CMD; };
355                 $cmd =~ /^n$/ && do {
356                     $single = 2;
357                     $laststep = $cmd;
358                     last CMD; };
359                 $cmd =~ /^s$/ && do {
360                     $single = 1;
361                     $laststep = $cmd;
362                     last CMD; };
363                 $cmd =~ /^c\b\s*(\d*)\s*$/ && do {
364                     $i = $1;
365                     if ($i) {
366                         if ($dbline[$i] == 0) {
367                             print OUT "Line $i not breakable.\n";
368                             next CMD;
369                         }
370                         $dbline{$i} =~ s/(\0|$)/;9$1/;  # add one-time-only b.p.
371                     }
372                     for ($i=0; $i <= $#stack; ) {
373                         $stack[$i++] &= ~1;
374                     }
375                     last CMD; };
376                 $cmd =~ /^r$/ && do {
377                     $stack[$#stack] |= 2;
378                     last CMD; };
379                 $cmd =~ /^T$/ && do {
380                     local($p,$f,$l,$s,$h,$a,@a,@sub);
381                     for ($i = 1; ($p,$f,$l,$s,$h,$w) = caller($i); $i++) {
382                         @a = ();
383                         for $arg (@args) {
384                             $_ = "$arg";
385                             s/'/\\'/g;
386                             s/([^\0]*)/'$1'/
387                                 unless /^(?: -?[\d.]+ | \*[\w:]* )$/x;
388                             s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg;
389                             s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
390                             push(@a, $_);
391                         }
392                         $w = $w ? '@ = ' : '$ = ';
393                         $a = $h ? '(' . join(', ', @a) . ')' : '';
394                         push(@sub, "$w$s$a from file $f line $l\n");
395                         last if $signal;
396                     }
397                     for ($i=0; $i <= $#sub; $i++) {
398                         last if $signal;
399                         print OUT $sub[$i];
400                     }
401                     next CMD; };
402                 $cmd =~ /^\/(.*)$/ && do {
403                     $inpat = $1;
404                     $inpat =~ s:([^\\])/$:$1:;
405                     if ($inpat ne "") {
406                         eval '$inpat =~ m'."\a$inpat\a";        
407                         if ($@ ne "") {
408                             print OUT "$@";
409                             next CMD;
410                         }
411                         $pat = $inpat;
412                     }
413                     $end = $start;
414                     eval '
415                     for (;;) {
416                         ++$start;
417                         $start = 1 if ($start > $max);
418                         last if ($start == $end);
419                         if ($dbline[$start] =~ m'."\a$pat\a".'i) {
420                             if ($emacs) {
421                                 print OUT "\032\032$filename:$start:0\n";
422                             } else {
423                                 print OUT "$start:\t", $dbline[$start], "\n";
424                             }
425                             last;
426                         }
427                     } ';
428                     print OUT "/$pat/: not found\n" if ($start == $end);
429                     next CMD; };
430                 $cmd =~ /^\?(.*)$/ && do {
431                     $inpat = $1;
432                     $inpat =~ s:([^\\])\?$:$1:;
433                     if ($inpat ne "") {
434                         eval '$inpat =~ m'."\a$inpat\a";        
435                         if ($@ ne "") {
436                             print OUT "$@";
437                             next CMD;
438                         }
439                         $pat = $inpat;
440                     }
441                     $end = $start;
442                     eval '
443                     for (;;) {
444                         --$start;
445                         $start = $max if ($start <= 0);
446                         last if ($start == $end);
447                         if ($dbline[$start] =~ m'."\a$pat\a".'i) {
448                             if ($emacs) {
449                                 print OUT "\032\032$filename:$start:0\n";
450                             } else {
451                                 print OUT "$start:\t", $dbline[$start], "\n";
452                             }
453                             last;
454                         }
455                     } ';
456                     print OUT "?$pat?: not found\n" if ($start == $end);
457                     next CMD; };
458                 $cmd =~ /^!+\s*(-)?(\d+)?$/ && do {
459                     pop(@hist) if length($cmd) > 1;
460                     $i = ($1?($#hist-($2?$2:1)):($2?$2:$#hist));
461                     $cmd = $hist[$i] . "\n";
462                     print OUT $cmd;
463                     redo CMD; };
464                 $cmd =~ /^!(.+)$/ && do {
465                     $pat = "^$1";
466                     pop(@hist) if length($cmd) > 1;
467                     for ($i = $#hist; $i; --$i) {
468                         last if $hist[$i] =~ $pat;
469                     }
470                     if (!$i) {
471                         print OUT "No such command!\n\n";
472                         next CMD;
473                     }
474                     $cmd = $hist[$i] . "\n";
475                     print OUT $cmd;
476                     redo CMD; };
477                 $cmd =~ /^H\b\s*(-(\d+))?/ && do {
478                     $end = $2?($#hist-$2):0;
479                     $hist = 0 if $hist < 0;
480                     for ($i=$#hist; $i>$end; $i--) {
481                         print OUT "$i: ",$hist[$i],"\n"
482                             unless $hist[$i] =~ /^.?$/;
483                     };
484                     next CMD; };
485                 $cmd =~ s/^p( .*)?$/print DB::OUT$1/;
486                 $cmd =~ /^=/ && do {
487                     if (local($k,$v) = ($cmd =~ /^=\s*(\S+)\s+(.*)/)) {
488                         $alias{$k}="s~$k~$v~";
489                         print OUT "$k = $v\n";
490                     } elsif ($cmd =~ /^=\s*$/) {
491                         foreach $k (sort keys(%alias)) {
492                             if (($v = $alias{$k}) =~ s~^s\~$k\~(.*)\~$~$1~) {
493                                 print OUT "$k = $v\n";
494                             } else {
495                                 print OUT "$k\t$alias{$k}\n";
496                             };
497                         };
498                     };
499                     next CMD; };
500             }
501             $evalarg = $cmd; &eval;
502             print OUT "\n";
503         }
504         if ($post) {
505             $evalarg = $post; &eval;
506         }
507     }
508     ($@, $!, $,, $/, $\, $^W) = @saved;
509     ();
510 }
511
512 sub save {
513     @saved = ($@, $!, $,, $/, $\, $^W);
514     $, = ""; $/ = "\n"; $\ = ""; $^W = 0;
515 }
516
517 # The following takes its argument via $evalarg to preserve current @_
518
519 sub eval {
520     eval "$usercontext $evalarg; &DB::save";
521     print OUT $@;
522 }
523
524 sub action {
525     local($action) = @_;
526     while ($action =~ s/\\$//) {
527         print OUT "+ ";
528         $action .= &gets;
529     }
530     $action;
531 }
532
533 sub gets {
534     local($.);
535     <IN>;
536 }
537
538 sub catch {
539     $signal = 1;
540 }
541
542 sub sub {
543     push(@stack, $single);
544     $single &= 1;
545     $single |= 4 if $#stack == $deep;
546     if (wantarray) {
547         @i = &$sub;
548         $single |= pop(@stack);
549         @i;
550     }
551     else {
552         $i = &$sub;
553         $single |= pop(@stack);
554         $i;
555     }
556 }
557
558 $trace = $signal = $single = 0; # uninitialized warning suppression
559
560 @hist = ('?');
561 $SIG{'INT'} = "DB::catch";
562 $deep = 100;            # warning if stack gets this deep
563 $window = 10;
564 $preview = 3;
565
566 @stack = (0);
567 @ARGS = @ARGV;
568 for (@args) {
569     s/'/\\'/g;
570     s/(.*)/'$1'/ unless /^-?[\d.]+$/;
571 }
572
573 if (-f $rcfile) {
574     do "./$rcfile";
575 }
576 elsif (-f "$ENV{'LOGDIR'}/$rcfile") {
577     do "$ENV{'LOGDIR'}/$rcfile";
578 }
579 elsif (-f "$ENV{'HOME'}/$rcfile") {
580     do "$ENV{'HOME'}/$rcfile";
581 }
582
583 1;