modification of a read-only value

David Alban extasia at extasia.org
Tue Jun 3 03:41:03 BST 2008


greetings,

as a fan of the Readonly module, i've seen and corrected many
situations where i get "Modification of a read-only value attempted".
but i got one today i don't quite grok.

i have a routine ql() that i use often.  apparently i first used it on
a Readonly only just today.  i seems that Data::Dumper::Dumper() is
doing something to offend Readonly.  in my example below, old_ql() is
a boiled down version of my subroutine and new_ql() is the
modification i made to get it to work with Readonly constants.  the
program below outputs:

$VAR1 = "\177";
Modification of a read-only value attempted at
/usr/lib/perl5/5.8.5/i386-linux-thread-multi/Data/Dumper.pm line 611
Modification of a read-only value attempted at junk line 0

Here's the test program:

#!/usr/bin/perl

use warnings;
use strict;

use Data::Dumper;
use Readonly;

Readonly::Scalar my $c => chr hex "7f";

print new_ql( $c );
print old_ql( $c );

sub new_ql {
  my @args_copy = @_;

  "@args_copy" =~ m{ [^[:print:]] }xms and $Data::Dumper::Useqq  = 1;
  return join( ", ", map { Dumper $_; } @args_copy );
} # new_ql

sub old_ql {
  "@_" =~ m{ [^[:print:]] }xms and $Data::Dumper::Useqq  = 1;
  return join( ", ", map { Dumper $_; } @_ );
} # old_ql

the only difference between the old and new routines is using a copy of @_.

lines near 611 in Dumper.pm are:

    608
    609 # put a string value in double quotes
    610 sub qquote {
    611   local($_) = shift;
    612   s/([\\\"\@\$])/\\$1/g;
    613   my $bytes; { use bytes; $bytes = length }
    614   s/([^\x00-\x7f])/'\x{'.sprintf("%x",ord($1)).'}'/ge if
$bytes > length;
    615   return qq("$_") unless
    616     /[^ !"\#\$%&'()*+,\-.\/0-9:;<=>?\@A-Z[\\\]^_`a-z{|}~]/;  # fast exit
    617
    618   my $high = shift || "";
    619   s/([\a\b\t\n\f\r\e])/$esc{$1}/g;
    620
    621   if (ord('^')==94)  { # ascii
    622     # no need for 3 digits in escape for these
    623     s/([\0-\037])(?!\d)/'\\'.sprintf('%o',ord($1))/eg;
    624     s/([\0-\037\177])/'\\'.sprintf('%03o',ord($1))/eg;
    625     # all but last branch below not supported --BEHAVIOR
SUBJECT TO CHANGE--
    626     if ($high eq "iso8859") {
    627       s/([\200-\240])/'\\'.sprintf('%o',ord($1))/eg;
    628     } elsif ($high eq "utf8") {
    629 #     use utf8;
    630 #     $str =~ s/([^\040-\176])/sprintf "\\x{%04x}", ord($1)/ge;
    631     } elsif ($high eq "8bit") {
    632         # leave it as it is
    633     } else {
    634       s/([\200-\377])/'\\'.sprintf('%03o',ord($1))/eg;
    635       s/([^\040-\176])/sprintf "\\x{%04x}", ord($1)/ge;
    636     }
    637   }
    638   else { # ebcdic
    639       s{([^ !"\#\$%&'()*+,\-.\/0-9:;<=>?\@A-Z[\\\]^_`a-z{|}~])(?!\d)}
    640        {my $v = ord($1); '\\'.sprintf(($v <= 037 ? '%o' :
'%03o'), $v)}eg;
    641       s{([^ !"\#\$%&'()*+,\-.\/0-9:;<=>?\@A-Z[\\\]^_`a-z{|}~])}
    642        {'\\'.sprintf('%03o',ord($1))}eg;
    643   }
    644
    645   return qq("$_");
    646 }

i have a simple fix, but i'm curious as to why this is happening.  it
seems as though Dumper() should be able to what it needs only reading
the value it's trying to print.

thanks,
david
-- 
Live in a world of your own, but always welcome visitors.


More information about the london.pm mailing list