A Three Ring Circus: multi-window perldb 
Author Message
 A Three Ring Circus: multi-window perldb

In debugging plum, which is now split up into something like 200 files,
I got tired of manually telling vi to switch into whatever function I've
hit a breakpoint for.    So I fixed it.  

Here's the current setup:

    Window 1:   de{*filter*} command window
    Window 2:   program input/output window
    Window 3:   program source window

You issue breakpoints etc in window 1, your program runs in window 2
(screen-oriented program REALLY need alternate windows while debuging
them), and vi will automatically position itself to the proper line and
file.  This means that you can keep hitting return in window 2 and watch
the window 3 cursor bop around.  For a REALLY fun time, set trace mode in
window 1. :-)

If you'd like to use this, you should support TIOCSTI, named pipes, and
xterm.  It's not in a generic, prettified state, so you'll have to edit
pathnames, etc.  But for some applications, it seems worth it.

Here's how I did it: first, you modify perldb to talk to a FIFO if
there's one defined in $perldb_fifo in your environment. Here's the diff
to the existing perldb.pl:

*** /usr/local/lib/perl/perldb.pl       Sat Dec 14 16:29:17 1991
--- fifoperldb.pl   Mon Feb 10 12:12:02 1992
***************
*** 9,14 ****
--- 9,24 ----
  # a do DB'DB(<linenum>); in front of every place that can
  # have a breakpoint.  It also inserts a do 'perldb.pl' before the first line.

+ if ($fifo = $ENV{'perldb_fifo'}) {
+     unless (-p $fifo) {
+       warn "ignoring non pipe $fifo";
+       undef $fifo;
+     } else {
+       open(FIFO, "> $fifo") || die "can't open $fifo: $!";
+       select((select(FIFO), $| = 1)[0]);
+     }
+ }
+
  open(IN, "</dev/tty") || open(IN,  "<&STDIN");        # so we don't dingle stdin
  open(OUT,">/dev/tty") || open(OUT, ">&STDOUT");       # so we don't dongle stdout
  select(OUT);
***************
*** 40,45 ****
--- 50,56 ----
      if ($single || $trace || $signal) {
        print OUT "$package'" unless $sub =~ /'/;
        print OUT "$sub($filename:$line):\t",$dbline[$line];
+       print FIFO "$filename:$line\n" if $fifo;
        for ($i = $line + 1; $i <= $max && $dbline[$i] == 0; ++$i) {
            last if $dbline[$i] =~ /^\s*(;|}|#|\n)/;
            print OUT "$sub($filename:$i):\t",$dbline[$i];

I almost think this should eventually become a standard thing, since
it's so neat, but for now, copy it into a personal file and set
your PERLDB envariable to "require 'fifoperldb.pl';" or whatever.

In order to start a vi with somebody to feed him file and line commands,
you run him through this script:

    #!/usr/local/bin/perl
    # muxvi.

    $TIOCSTI = 0x80017472;

    $pgrp = -$$;
    if (!fork) {
        system "vi";
        warn "vi exited $?" if $?;
        kill(15, $pgrp);
    }

    $fifo =  $ENV{'perldb_fifo'} || "/tmp/muxpipe.$$";

    open(FIFO, "< $fifo") || die "can't open $fifo: $!";

    while (<FIFO>) {
        s/(.*):(\d+)/:n +$2 $1/;
        next if $1 eq '(eval)';
        $_ = "$2G"    if $1 eq $lastfile;
        $lastfile = $1;
        &jam($_);
    }

    &jam("ZZ");
    print STDERR "$0: all done\n";
    unlink($fifo);

    sub jam {
        for (split(//, $_[0])) {
            ioctl(STDERR, $TIOCSTI, $_) || die "bad TIOCSTI: $!";
        }
    }

As you see, we keep reading de{*filter*} information from the pipe, and
stuff the appropriate command down vi's throat.  The following is
a really ugly hack that works for this program.  I've made plum accept a
"-t /dev/ttyp9" kind of option and then do this:

    open (STDIN,  "< $ttyname")  || die "can't open $ttyname: $!";
    open (STDOUT, "> $ttyname") || die "can't open $ttyname: $!";

I tried it with simple cmd line i/o redirection, but this didn't
seem to work.  (BTW, I've got autowrite set.)

The initial things I jam into the de{*filter*} only make sense for this
program.  See below for explanations.

    #!/usr/local/bin/perl
    # 3db: run debug session in 3 windows

    system("stty -echo");
    &jam(<<EOJAM);
b main
b de{*filter*}_escape
c
EOJAM
    system("stty echo");

    open(TMP, ">/tmp/plumdebug.$$");
    print TMP <<EOF;
        tty > /tmp/plumdebugtty.$$
        stty intr undef
        echo DEBUGGING
        sleep 77777777
    EOF
    close TMP;

    $fifo = "/tmp/muxpipe.$$";
    unlink($fifo); system ("mknod $fifo p") && die "mknod failure: $?";

    $ENV{'perldb_fifo'} = $fifo;
    $ENV{PERLDB} = 'require "../tools/myperldb.pl";' unless defined $ENV{PERLDB};
    # XXX: put in your personal db path here, or prese in your environment

    system "xterm +ls -ut -n 'perldb source' -e muxvi &";
    system "xterm +ls -ut -n 'perldb inferior' -e sh /tmp/plumdebug.$$ 2>/dev/null &";
    sleep 1 until -e "/tmp/plumdebugtty.$$";
    chop($bugtty = `cat /tmp/plumdebugtty.$$`);
    print "slave tty is $bugtty\n";
    $SIG{INT} = 'done';
    system "perl -d $ARGV[0] -t $bugtty 2>&1 1>$bugtty";
    &done;

    sub done {
        print "\n";
        unlink </tmp/plumdebug*>, $fifo;
        exit 0;
    }

    sub jam {
        $TIOCSTI = 0x80017472;
        for (split(//, $_[0])) {
            ioctl(STDERR, $TIOCSTI, $_) || die "bad TIOCSTI: $!";
        }
    }

Finally, when I build a plum to debug, instead of having everything
merged together, I have everything except main be required:

    require './activate_folder.pl';
    require './alternate_folder.pl';
    require './assert.pl';
    require './auto_refile.pl';
    require './autoload.pl';
    # ...
    require './version.pl';
    require './warn.pl';
    require './yorn.pl';
    require './zedzed.pl';


    sub de{*filter*}_escape { 0; }
    sub main {
        # main code starts here
    }

&de{*filter*}_escape is just a dummy routine that I have the ESC key bound
to in plum, which allows me to get back to the de{*filter*} at will.

BTW, all your windows go away on a ^C, which is nice, but it does so
even if you're trapping it, which isn't. :-(

--tom



Sat, 30 Jul 1994 03:10:54 GMT  
 A Three Ring Circus: multi-window perldb
One guy here at Convex already has an enhancement request: he wants to
be able to set breakpoints in the de{*filter*} from within vi!

Anyone else care to try?  The tricky part is finding the current line
number from within in vi.  A macro equating to ":1,.w !proc - %" should do
it, albeit in a suboptimal manner.  The proc could count the lines in
stdin to find the current lineno, get the filename in %, and then jam
a breakpoint down perldb's throat the way muxvi is doing to vi.  At
least that way you wouldn't have to modify perldb again.

--tom



Sat, 30 Jul 1994 04:12:47 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. perldb for windows

2. perldb on WIndows NT

3. Using LWP, HTTP::Cookies etc in multi-threading on Windows 2000

4. Using LWP, HTTP::Cookies etc in multi-threading in Windows 2000

5. Multi process under windows NT

6. multi windows with controling input focus

7. Ring a bell?

8. Comments/Help on Ring Element Id Subroutine?

9. Ringing the BEL in perl.

10. PERL web ring script

11. Q: How do I ring the terminal bell

12. Web-ring Code

 

 
Powered by phpBB® Forum Software