Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question: How can I debug the _content_ of output formats?

1 view
Skip to first unread message

Ami

unread,
Apr 7, 2002, 6:03:38 AM4/7/02
to
I can't present a neat little snippet that reproduces my problem.
This question is sort of about how to get to the little snippet.

I'm using format, in an eval(), and write() to create reports. In the
debugger I can see the values of $~ and $^ and $% and $-. Everything
looks good. Before the first call to write() $- is zero but after the
call $- is 9999998 (I may be off a 9 or two.)

Apparently the value of $- gets messed up early because no page
headers come out. And once $- is that big, there won't be a page two.

Fudging $- just before calling write() works most of the way around
the problem:
$- = 0 if $- > 999;
One detail section is printed, 3 text lines in this case, than before
the next detail there's a page header and the next detail and the rest
of the report appears normal, pages and headers and all. It's not
totaly pretty, but people can work with it.


Is my format messing up $-? What is in the format? $~ and $^ are set
to the correct names, the debugger plainly displays them. I can trace
all the code that uses eval() to create the formats. I know what I
think is in the formats, what does Perl think? Is there any way to
display the content of a format? Where are they stored?


I've looked at the symbol tables of package main and the package of
the class that creates the format and I've looked in the manual and
FAQ and etc. for information on where the formats are stored and I
didn't find a thing. I spent about an hour searching the web for
"debug output formats". Didn't find a thing that isn't already in the
perlform.1 man page. And while not really believing what I've heard,
I did take the precaution of hooking up the oldest (they don't make
them like we used to), heaviest duty keyboard I have before entering
the surrealistic Mount Sinai of writ, the very large mound of highly
evolved C called Perl 5. Wow. I had to lay down for a while. I've
no idea where Perl puts formats.


This class uses eval() to create formats. Something like
=====cut=====
$format_name = "SNAFU";
$format_string = $this->make_format_line_string();
$data_expr_list_string = $this->make_data_expr_list_string();
$code = eval(<<"FOOBAR");
format ${format_name} =
$format_string
$data_expr_list_string
.
FOOBAR
eval($code)
=====cut=====

Tracing this in the debugger, $code looks correct just before the
eval().

If it's not enough that a class creating a format in an eval() is
causing write() to do strange things, I use this class in several
report programs. About half are fine, and half have had this problem
for a couple of weeks. These are production reports that run weekly,
some daily, and have been running for eons. Why, some of these
programs are nearly as old as Perl 5! :-) Crisp, the editor I use, or
CRiSP as its author Paul Fox would type it (give Crisp a plug: GREAT
editor, www.vital.com), has an audit trail feature that tracks when a
file is modified. I haven't touched any of these files for... well, I
didn't touch it, I mean, not THERE. OK, so maybe I did change
something. I was working in the neighborhood, some other features of
this class. But not that part, I didn't go near the parts that...
well, maybe I did. But how can I tell? I can't see what Perl thinks
the format is.

Arggg.

!

! ! . . . and !

help...?

hello

hello!

hello!?

HELLOOOO-OOOOO!!!
(pee wee herman)

IS THERE ANYBODY OUT THERE?
(ping floyd)
(grr... I mean pink)


help...?


--
ami bar-yadin (a...@txdirect.net)
- - no I ain't got no cutesy line here - -

Yitzchak Scott-Thoennes

unread,
Apr 7, 2002, 7:00:34 PM4/7/02
to
In article <54636d3f.02040...@posting.google.com>,

a...@txdirect.net (Ami) wrote:
>This class uses eval() to create formats.
>I can't see what Perl thinks the format is.

There is a dump_format in perl's dump.c, but it probably won't help
you much. (It seems to dump the actual code the format is compiled
into, which presumably has all the info you need, but not in a
particularly readable form.)

In case you want to try it, here's a patch to Devel::Peek to add a
DumpFormat (which you pass a glob to: e.g. format STDOUT=..., then
Devel::Peek::DumpFormat *STDOUT). I tried it only with bleadperl (and
its Devel::Peek) and gave up since it seemed less than useful.

--- ext/Devel/Peek/Peek.xs.orig Sun Apr 7 12:02:28 2002
+++ ext/Devel/Peek/Peek.xs Sun Apr 7 16:07:46 2002
@@ -347,6 +347,19 @@
}

void
+DumpFormat(sv)
+SV * sv
+PPCODE:
+{
+ if (SvTYPE(sv) == SVt_PVGV && GvFORM(sv)) {
+ I32 save_dumpindent = PL_dumpindent;
+ PL_dumpindent = 2;
+ dump_form((GV*)sv);
+ PL_dumpindent = save_dumpindent;
+ }
+}
+
+void
DumpArray(lim,...)
I32 lim
PPCODE:
End of Patch.

Another approach is to use Deparse. I cobbled this together using the
example of how Data::Dumper deparses code refs, and have not tested it
very much. The necessary stuff seems to be there in B::Deparse in
5.6.1, but the *FOO{FORMAT} syntax doesn't seem to work right there.
So again, I only tried it with bleadperl.

I imagine volunteers would be welcome to change this into a patch to
B::Deparse/Data::Dumper to allow Dumper(*FOO{FORMAT}) to work.

package Devel::DeparseFormat;
use strict;
use warnings;
use B 'svref_2object';
use B::Deparse ();
use Carp;
use Exporter ();

our @ISA = 'Exporter';
our @EXPORT = 'deparse_format';

# Usage:
# use Devel::DeparseFormat;
#
# format FOO=
# any ole format
# .
#
# $formatstring = deparse_format(*FOO{FORMAT});
# # $formatstring is now "any ole format\n."

sub deparse_format($) {
my $fmt = shift;
croak "Usage: deparse_format(*FOO{FORMAT})" unless ref($fmt) eq "FORMAT";

my $deparser = B::Deparse::->new();
$deparser->init();

return $deparser->indent($deparser->deparse_format(svref_2object($fmt)));
}

1;

Yitzchak Scott-Thoennes

unread,
Apr 8, 2002, 3:28:37 AM4/8/02
to
I wrote:
>a...@txdirect.net (Ami) wrote:
>>This class uses eval() to create formats.
>>I can't see what Perl thinks the format is.
>
>The necessary stuff seems to be there in B::Deparse in 5.6.1, but the
>*FOO{FORMAT} syntax doesn't seem to work right there. So again, I
>only tried it with bleadperl.

New version, works on 5.6.1, takes ref to format (*FOO{FORMAT}),
glob (*FOO), or ref to glob.

sub deparse_format {
use B::Deparse;
# translate arg (or reference to it) into a B::* object
my $Bobj = B::svref_2object(ref $_[0] ? $_[0] : \$_[0]);
# if passed a glob or globref, get the format
$Bobj = B::GV::FORM($Bobj) if ref $Bobj eq 'B::GV';

if (ref $Bobj ne 'B::FM') {
require Carp;
Carp::croak "deparse_format: expected a glob, globref, or format ref";
}

my $deparser = B::Deparse::->new();

return $deparser->indent($deparser->deparse_format($Bobj));
}

Ami

unread,
Apr 8, 2002, 11:02:31 PM4/8/02
to
a...@txdirect.net (Ami) wrote in message news:<54636d3f.02040...@posting.google.com>...

> I can't present a neat little snippet that reproduces my problem.
> This question is sort of about how to get to the little snippet.
>

With help from Yitzchak Scott-Thoennes I was able to eliminate my
formats as the cause, and arrive at the snippet below.

If the $^ variable is not set, the $- variable is set to a very large
number during the first call to write(), which effectively bypasses
page breaking and with it page headers.


This behaviour is fairly logical so it may be that it is the behavior
expected by people versed in the innards of Perl, but it is not
documented in perlform.1 nor in perlvar.1.

I'd guess this will result in documentation not a code patch
:-)


=====cut=====
#!/usr/local/bin/perl

# START:

# selected file defaults to STDOUT

print STDERR "* page size was $=\n";

$= = 3;

# $^ = "XXXX";
# $^ = "YYYY";
# $^ = "AAA_TOP";
# $^ = "STDOUT_TOP";

print STDERR "* formats : $~ and $^ \n";
$~ = "AAA";
print STDERR "* formats : $~ and $^ \n";
write;
print STDERR "* lines left: $-\n";

# END of executable code

format AAA =
this is a detail line @### with a count
++$count
.

format XXXX =
abcd header efgh
.
=====cut=====


run it, and try uncommenting different top format names.


--
Ami Bar-Yadin (a...@txdirect.net)

Ami

unread,
Apr 8, 2002, 9:08:43 PM4/8/02
to
stho...@efn.org (Yitzchak Scott-Thoennes) wrote in message news:<laUs8gzk...@efn.org>...

> New version, works on 5.6.1, takes ref to format (*FOO{FORMAT}),
> glob (*FOO), or ref to glob.
>
> sub deparse_format {
...
> }

This works great!


Thanks,
--
Ami Bar-Yadin (a...@txdirect.net)

0 new messages