Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data::Dumper mangles dualvars #7238

Closed
p5pRT opened this issue Apr 15, 2004 · 7 comments
Closed

Data::Dumper mangles dualvars #7238

p5pRT opened this issue Apr 15, 2004 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 15, 2004

Migrated from rt.perl.org#28839 (status was 'rejected')

Searchable as RT28839$

@p5pRT
Copy link
Author

p5pRT commented Apr 15, 2004

From zefram@fysh.org

Created by zefram@fysh.org

I'm working with Data​::Dumper version 2.121 for this bug report.

Data​::Dumper, if given a dualvar (such as $!), only dumps the string
value. It ought to dump both values, in the form of a dualvar()
expression. Here's a patch that implements this in the Perl version of
the dump function​:

Inline Patch
--- /usr/lib/perl/5.8.3/Data/Dumper.pm	2004-03-27 06:52:27.000000000 +0000
+++ Dumper.pm	2004-04-15 19:22:43.000000000 +0100
@@ -449,17 +449,25 @@
     elsif (!defined($val)) {
       $out .= "undef";
     }
-    elsif ($val =~ /^(?:0|-?[1-9]\d{0,8})\z/) { # safe decimal number
-      $out .= $val;
-    }
-    else {				 # string
+    else {				 # string/number
+      my $strval;
       if ($s->{useqq} or $val =~ tr/\0-\377//c) {
         # Fall back to qq if there's unicode
-	$out .= qquote($val, $s->{useqq});
+	$strval = qquote($val, $s->{useqq});
       }
       else {
 	$val =~ s/([\\\'])/\\$1/g;
-	$out .= '\'' . $val .  '\'';
+	$strval = '\'' . $val .  '\'';
+      }
+      no warnings "numeric";
+      if(0+$val eq $val) {
+	$out .= 0+$val;
+      }
+      elsif("$val" == $val) {
+	$out .= $strval;
+      }
+      else {
+	$out .= "dualvar(".(0+$val).", ".$strval.")";
       }
     }
   }

I haven't tackled the C version. Example of old and new behaviour \(setting Useqq to force use of the Perl dump code\)​:

$ perl -MData​::Dumper -we '$Data​::Dumper​::Useqq=1; print Dumper($!)'
$VAR1 = "Bad file descriptor";
$ perl -I. -MData​::Dumper -we '$Data​::Dumper​::Useqq=1; print Dumper($!)'
$VAR1 = dualvar(2, "No such file or directory");

Both before and after the patch, the code has a problem with floating
point numbers. It really needs a way to output the exact value
of a floating point number, whereas at the moment it uses builtin
stringification, which loses some digits. That's a separate issue that
just happens to be in the same chunk of code.

See also bug #28538 for the discussion of dualvars that led to this
bug report.

Perl Info

Flags:
    category=library
    severity=medium

Site configuration information for perl v5.8.3:

Configured by Debian Project at Sat Mar 27 17:07:14 EST 2004.

Summary of my perl5 (revision 5.0 version 8 subversion 3) configuration:
  Platform:
    osname=linux, osvers=2.4.25-ti1211, archname=i386-linux-thread-multi
    uname='linux kosh 2.4.25-ti1211 #1 thu feb 19 18:20:12 est 2004 i686 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.3 -Dsitearch=/usr/local/lib/perl/5.8.3 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.3 -Dd_dosuid -des'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O3',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include'
    ccversion='', gccversion='3.3.3 (Debian 20040314)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libperl.so.5.8.3
    gnulibc_version='2.3.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.3:
    /etc/perl
    /usr/local/lib/perl/5.8.3
    /usr/local/share/perl/5.8.3
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.8
    /usr/share/perl/5.8
    /usr/local/lib/site_perl
    .


Environment for perl v5.8.3:
    HOME=/home/zefram
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/zefram/pub/i686-pc-linux-gnu/bin:/home/zefram/pub/common/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/local/bin:/usr/games:/opt/libunsn/bin
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Apr 16, 2004

From @hvds

Zefram (via RT) <perlbug-followup@​perl.org> wrote​:
:$ perl -MData​::Dumper -we '$Data​::Dumper​::Useqq=1; print Dumper($!)'
:$VAR1 = "Bad file descriptor";
:$ perl -I. -MData​::Dumper -we '$Data​::Dumper​::Useqq=1; print Dumper($!)'
:$VAR1 = dualvar(2, "No such file or directory");

Hmm, that should probably be​:
$VAR1 = do { require Scalar​::Util; Scalar​::Util​::dualvar(2, "No such file or directory"); };

Hugo

@p5pRT
Copy link
Author

p5pRT commented Apr 16, 2004

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Apr 16, 2004

From @demerphq

I'm working with Data​::Dumper version 2.121 for this bug report.

Data​::Dumper, if given a dualvar (such as $!), only dumps the string
value. It ought to dump both values, in the form of a dualvar()
expression. Here's a patch that implements this in the Perl
version of
the dump function​:

--- /usr/lib/perl/5.8.3/Data/Dumper.pm 2004-03-27
06​:52​:27.000000000 +0000
+++ Dumper.pm 2004-04-15 19​:22​:43.000000000 +0100
@​@​ -449,17 +449,25 @​@​
elsif (!defined($val)) {
$out .= "undef";
}
- elsif ($val =~ /^(?​:0|-?[1-9]\d{0,8})\z/) { # safe decimal number
- $out .= $val;
- }
- else { # string
+ else { # string/number
+ my $strval;
if ($s->{useqq} or $val =~ tr/\0-\377//c) {
# Fall back to qq if there's unicode
- $out .= qquote($val, $s->{useqq});
+ $strval = qquote($val, $s->{useqq});
}
else {
$val =~ s/([\\\'])/\\$1/g;
- $out .= '\'' . $val . '\'';
+ $strval = '\'' . $val . '\'';
+ }
+ no warnings "numeric";
+ if(0+$val eq $val) {
+ $out .= 0+$val;
+ }
+ elsif("$val" == $val) {
+ $out .= $strval;
+ }
+ else {
+ $out .= "dualvar(".(0+$val).", ".$strval.")";
}
}
}

I haven't tackled the C version. Example of old and new behaviour
(setting Useqq to force use of the Perl dump code)​:

$ perl -MData​::Dumper -we '$Data​::Dumper​::Useqq=1; print Dumper($!)'
$VAR1 = "Bad file descriptor";
$ perl -I. -MData​::Dumper -we '$Data​::Dumper​::Useqq=1; print
Dumper($!)'
$VAR1 = dualvar(2, "No such file or directory");

Both before and after the patch, the code has a problem with floating
point numbers. It really needs a way to output the exact value
of a floating point number, whereas at the moment it uses builtin
stringification, which loses some digits. That's a separate
issue that
just happens to be in the same chunk of code.

FWIW I agree that Data​::Dumper should probably have this. However I have
some reservations.

Currently Data​::Dumper doesnt use subs to do its thing at all. Other dumpers
like Data​::Dump and Data​::Dump​::Streamer do however. One question I think
has been of where the responsibility of require()ing or use()ing the module
lies. Data​::Dump IIRC takes the view that the dump will include the require
statement, and in Data​::Dump​::Streamer I decided that it wont include it.
Related questions are that should simply use()ing Data​::Dumper provide the
required subs? If so should the dump output use() them into the right
namespace, or should it call directly in the dumper module or into the
loaded module. In Data​::Dump I believe the call is into the second party
module (Symbol​::gensym) and in Data​::Dump​::Streamer the person evaling the
dump is expected to have use()d Data​::Dump​::Streamer qw(​:undump);

Anyway, I dont claim that my choices are correct here but I think its worth
thinking about before patching Data​::Dumper.

Also, I seem to recall that Scalar​::Util​::dualvar doesnt work on some
builds, how should Data​::Dumper handle that properly?

And once all these policies are decided there are a whole host of attributes
that Data​::Dumper doesnt handle that are resolvable by allowing and patching
dumper to emit the appropriate sub calls​: Readonlyness, aliases, blessed
regexes with overriden stringification, blessed format refs, anonymous
typeglobs, and restricted hashes are some that come mind now. forward
references to members of composite structures are another Data​::Dumper
failing, but thats resolvable without recourse to external subs (i m pretty
sure anyway).

Food for thought.
Yves
ps​: Data​::Dump​::Streamer doesnt handle dualvar either. :-( Ill have to fix
that.

@p5pRT
Copy link
Author

p5pRT commented Apr 16, 2004

From @rgs

Orton, Yves wrote​:

FWIW I agree that Data​::Dumper should probably have this. However I have
some reservations.

I share these; Data​::Dumper is a simple and a fast tool ; IMHO a
specialized CPAN module would be a better place to have a really good,
accurate and nit-picking dumper that reconstitutes every information it
can find (and you list some below).

...

And once all these policies are decided there are a whole host of attributes
that Data​::Dumper doesnt handle that are resolvable by allowing and patching
dumper to emit the appropriate sub calls​: Readonlyness, aliases, blessed
regexes with overriden stringification, blessed format refs, anonymous
typeglobs, and restricted hashes are some that come mind now. forward
references to members of composite structures are another Data​::Dumper
failing, but thats resolvable without recourse to external subs (i m pretty
sure anyway).

@p5pRT
Copy link
Author

p5pRT commented Apr 19, 2004

From @demerphq

FWIW I agree that Data​::Dumper should probably have this.
However I have
some reservations.

I share these; Data​::Dumper is a simple and a fast tool ; IMHO a
specialized CPAN module would be a better place to have a really good,
accurate and nit-picking dumper that reconstitutes every
information it
can find (and you list some below).

For the record the only one of the below that Data​::Dump​::Streamer doesnt
handle is the dualvar stuff. and thats mostly cause I forgot about it this
weekend.

Regarding Speed. DDS is a lot slower than DD. BUT, I believe that many or
even all of the below can be done without sacrificing speed. In fact some of
the techniques I use in DDS could be used in DD to make it more memory
efficient without sacrificing speed and handle most of the below. (classic
example is that it does NOT need to keep track of having seen any variables
with a refcount of less than 2 (or 3 depending on your POV, XS or Perl) as
these variables CANNOT cause a cyclic link and as such can simply be
traversed without keeping track fo them, furthermore dumping an SV with a
refcount larger than 2 suggests its multiply referenced, possibly even
aliased, and as such needs to be managed carefully. These types of checks
would actually speed things up not slow them down), Ive been meaning to
look into it. But my C is barely up to the task and DD has historically had
a caveat from Sarathy that it doesnt get changed unless the change is in
both the C and and the Perl.

...

And once all these policies are decided there are a whole
host of attributes
that Data​::Dumper doesnt handle that are resolvable by
allowing and patching
dumper to emit the appropriate sub calls​: Readonlyness,
aliases, blessed
regexes with overriden stringification, blessed format
refs, anonymous
typeglobs, and restricted hashes are some that come mind
now. forward
references to members of composite structures are another
Data​::Dumper
failing, but thats resolvable without recourse to external
subs (i m pretty
sure anyway).

@p5pRT
Copy link
Author

p5pRT commented Sep 15, 2004

@iabyn - Status changed from 'open' to 'rejected'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant