> 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