Yary has asked for the wisdom of the Perl Monks concerning the following question:

Is there any trick to have perldb break when it reaches a line of source matching some pattern I give it?

In particular I'd like for it to break anytime it is about to execute a print statement, as if the line before said $DB::single=1.

I tried being "clever" with this debugger command, but it had no effect:

b $DB::dbline[$DB::lineno] =~ /\bprint\b/

As a side issue, even though I have a $DB::single=1 command in my code, saying x $DB::single in the debugger afterwards tells me undef. Can one not access the DB package from the debugger command line?

Replies are listed 'Best First'.
Re: Make debugger break on source lines matching a pattern
by LanX (Saint) on Jan 11, 2014 at 17:43 UTC
    Not sure if $DB::dbline[$DB::lineno] does what you want², but I think you are looking for w watch expression¹ not b breakpoint.

    In your case I'd rather try to temporarily overwrite print with a wraper sub which sets $DB::single=1

    > Can one not access the DB package from the debugger command line?

    Thats a value set at run-time , and I suppose it's immediately deleted after causing a break.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

    see also

    update

    ¹) Sorry watch doesn't do what I thought. It monitors variable changes w/o conditions. And there are no global break conditions, they are bound to line-numbers.

    There are several possible workarounds but IMHO overwriting print seems the simplest.

    ²) no it doesn't '@dbline' is where breakpoints are stored

      On further thought, the line-search should be a "watch" and not a "breakpoint," as every breakpoint must be associated with a line. "b expr" tests expr on the current line, not every line!

      And now that I've figured that out, I've found the wisdom I seek, based on the search result changing state

      w $main::{"_<".(caller 2)[1]}[(caller 2)[2]] =~ /\bprint\b/
      I welcome any improvements- such as
      1. not having to call "caller 2" twice
      2. have the expression only change value when it first hits the "print" statment, and not when it goes to the next line- perhaps by using the flip-flop operator
      3. somehow using perl5db's English-named variables
          OK changing it to (caller 3) made it work for me! =)

          DB<100> w $main::{"_<".(caller 3)[1]}[(caller 3)[2]] =~ /\bprint\b/ DB<101> r 0 1 Watchpoint 0: $main::{"_<".(caller 3)[1]}[(caller 3)[2]] =~ /\bprin +t\b/ changed: old value: '' new value: '1' main::(tst.pl:13): print $x++;

          my suggestion is to define a new debugger command for "global-break-line" via an alias like bl in your '.perldb'.

          Like that  bl REGEX is translated to w @{ [ DB::breakline(regex) ] }

          sub DB::breakline { } is also defined in '.perldb' and handles the details to access the line's source and to return a new value.

          tomorrow more!

          Cheers Rolf

          ( addicted to the Perl Programming Language)

          This really works???

          Anyway I think I have a better idea, you can use this hack to evaluate code within a pseudo-var

          DB<100> w @{[$z++]}

          this watch-point will break at each line, cause the value changes.

          Now if you include a condition to change only, if your filter matches, you got what you need! :)

          edit

          DB<101> w @{[$z++]} DB<102> r 0 Watchpoint 0: @{[$z++]} changed: old value: '0' new value: '1' main::(tst.pl:12): say $x++; DB<102> r 1 Watchpoint 0: @{[$z++]} changed: old value: '1' new value: '2' main::(tst.pl:13): print $x++;

          Cheers Rolf

          ( addicted to the Perl Programming Language)

        Howdy Rolf,

        I had the same thought about overriding "print" but that's one of the core ops that it won't work for, since there's no prototype letting the parser treat it like a sub. (And there's no CORE::print to break on either).

        Possible to completely hack a solution along the lines of perl -pi.bak -e "s/\bprint\b/$DB_single=1;\nprint/" or do something exceedingly clever with B::Util- though simply adding a few breakpoints by hand will do all I need to do with far less room for making things worse!

        ps. thanks for the link to obsidianrook, I always enjoy those presentations!

          > no prototype letting the parser treat it like a sub.

          true, most probably cause of it's magic behavior as handle-method. Though looking into IO::Handle might help.

          Anyway, I don't know what your prints are supposed to do, but before relying on source-filtering I'd rather rename them like dbout or out or say.

          The following code breaks on each output, simply uncommenting use feature disables this behavior.

          #use feature 'say'; sub say { print @_,"\n"; no warnings 'once'; $DB::single=1; } say $x++; say $x++; say $x++; say $x++; say $x++;

          > ps. thanks for the link to obsidianrook, I always enjoy those presentations!

          Well, better thank doom directly! =)

          Cheers Rolf

          ( addicted to the Perl Programming Language)