> I looked in RecDescent.pm and discovered that Damien 
> explicitly opens STDERR and writes out the errors to it.
> 
> Has anyone successfully solved this or  a similar problem?  
> I'm open to any solution (it doesn't have to be redirecting 
> to a file) that will allow me to capture in a program 
> variable the output from Parse::RecDescent.

Given Damians implementation this _isnt_ going to pretty at all.

Its the file duping and formats thats the problem here (or at least part of
it).  So any fix that I can envisage will involve patching recdescent.  From
what I can tell you should a search for >&STD you should get three entries:

open (TRACECONTEXT, ">&STDERR");
open (TRACE, ">&STDERR");
open (ERROR, ">&STDERR");

What you will need to do is to create a new IO::Scalar before the above
opens are called.  Presumably you will want access to this variable from the
object (this is one of the problems, the filehandles are package scoped. So
_all_ instances of P::RD objects invoked within a given Perl instance are
going to get piped to the same Handle.) you will need to create an accessor
method to get access to the scalar being used.

Then before the opens occur you need to add code like (and this is the
variable you need to provide accessors)

  our $DEBUG_BUFFER="";

and then replace each open call with something like:

  my $io_scalar_obj = tie *TRACE, 'IO::Scalar', \$DEBUG_BUFFER;
  select( (select(TRACE),$|++)[0]);

And now all the output on the TRACE, ERROR, and TRACECONTEXT should get
stuffed in $DEBUG_BUFFER (i believe that the select() statement is critical
to avoid buffering mishaps, but i may be wrong.)

Note however the above approach means that a single instance of perl using
P::RD would have ONLY ONE buffer.  This could cause problems..

Also, you will need to modify some code to make sure that the buffer gets
reset when a newparse begins.

----

A more ambitious approach would be to use Symbol::gensym to create
"anonymous GLOBS" to use as the filehandles. The reason being that formats
(which P::RD uses) dont work on anonymous file handles (that I know of
anyway).  This would involve hacking the P::RD constructor, putting the
scalar and the tie's and format declarations inside (possibly via an eval...
this is hokey stuff here :-).  Then you would need to hack the _trace sub
and friends to take a self reference, then you would need to change all the
calls to these subs to pass the appropriate self.  You would also have to
probably hack the constructors to keep track of the "root" Parse::RecDescent
object so that they knew which object to call the new _trace commands
against.

Ultimately the ambitious approach involves some pretty serious changes to
P::RD.  I think it could take quite a while.  The other approach probably
would work fine so long as you arent running under mod_perl.

Whatever you do, please post the patches you make to this list, or at least
to me personally. Id like to see how this gets solved.

Hope this helps,
yves






Reply via email to