4 require Config; import Config;
5 if ($Config{'extensions'} !~ /\bDevel\/Peek\b/) {
6 print "1..0 # Skip: Devel::Peek was not built\n";
11 my $core = !!$ENV{PERL_CORE};
12 require($core ? '../../t/test.pl' : './t/test.pl');
21 open(SAVERR, ">&STDERR") or die "Can't dup STDERR: $!";
23 # If I reference any lexicals in this, I get the entire outer subroutine (or
24 # MAIN) dumped too, which isn't really what I want, as it's a lot of faff to
33 use constant thr => $Config{useithreads};
37 my $repeat_todo = $_[4];
40 if (open(OUT,">peek$$")) {
41 open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
43 my $sub = eval "sub { Dump $_[1] }";
45 print STDERR "*****\n";
46 # second dump to compare with the first to make sure nothing
52 print STDERR "*****\n";
53 # second dump to compare with the first to make sure nothing
57 open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
59 if (open(IN, "peek$$")) {
61 $pattern =~ s/\$ADDR/0x[[:xdigit:]]+/g;
62 $pattern =~ s/\$FLOAT/(?:\\d*\\.\\d+(?:e[-+]\\d+)?|\\d+)/g;
63 # handle DEBUG_LEAKING_SCALARS prefix
64 $pattern =~ s/^(\s*)(SV =.* at )/(?:$1ALLOCATED at .*?\n)?$1$2/mg;
66 # Need some clear generic mechanism to eliminate (or add) lines
67 # of dump output dependant on perl version. The (previous) use of
68 # things like $IVNV gave the illusion that the string passed in was
69 # a regexp into which variables were interpolated, but this wasn't
70 # actually true as those 'variables' actually also ate the
71 # whitespace on the line. So it seems better to mark lines that
72 # need to be eliminated. I considered (?# ... ) and (?{ ... }),
73 # but whilst embedded code or comment syntax would keep it as a
74 # legitimate regexp, it still isn't true. Seems easier and clearer
75 # things that look like comments.
77 # Could do this is in a s///mge but seems clearer like this:
78 $pattern = join '', map {
79 # If we identify the version condition, take *it* out whatever
82 : $_ # Didn't match, so this line is in
83 } split /^/, $pattern;
85 $pattern =~ s/\$PADMY/
86 ($] < 5.009) ? 'PADBUSY,PADMY' : 'PADMY';
88 $pattern =~ s/\$PADTMP/
89 ($] < 5.009) ? 'PADBUSY,PADTMP' : 'PADTMP';
92 ($] < 5.011) ? 'RV' : 'IV';
94 $pattern =~ s/^\h+COW_REFCNT = .*\n//mg
95 if $Config{ccflags} =~
96 /-DPERL_(?:OLD_COPY_ON_WRITE|NO_COW)/
98 print $pattern, "\n" if $DEBUG;
99 my ($dump, $dump2) = split m/\*\*\*\*\*\n/, scalar <IN>;
100 print $dump, "\n" if $DEBUG;
101 like( $dump, qr/\A$pattern\Z/ms, $_[0])
102 or note("line " . (caller)[2]);
104 local $TODO = $repeat_todo;
105 is($dump2, $dump, "$_[0] (unchanged by dump)")
106 or note("line " . (caller)[2]);
112 die "$0: failed to open peek$$: !\n";
115 die "$0: failed to create peek$$: $!\n";
125 1 while unlink("peek$$");
128 do_test('assignment of immediate constant (string)',
130 'SV = PV\\($ADDR\\) at $ADDR
132 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
139 do_test('immediate constant (string)',
141 'SV = PV\\($ADDR\\) at $ADDR
143 FLAGS = \\(.*POK,READONLY,(?:IsCOW,)?pPOK\\)
150 do_test('assignment of immediate constant (integer)',
152 'SV = IV\\($ADDR\\) at $ADDR
154 FLAGS = \\(IOK,pIOK\\)
157 do_test('immediate constant (integer)',
159 'SV = IV\\($ADDR\\) at $ADDR
161 FLAGS = \\(.*IOK,READONLY,pIOK\\)
164 do_test('assignment of immediate constant (integer)',
166 'SV = IV\\($ADDR\\) at $ADDR
168 FLAGS = \\($PADMY,IOK,pIOK\\)
171 # If perl is built with PERL_PRESERVE_IVUV then maths is done as integers
172 # where possible and this scalar will be an IV. If NO_PERL_PRESERVE_IVUV then
173 # maths is done in floating point always, and this scalar will be an NV.
174 # ([NI]) captures the type, referred to by \1 in this regexp and $type for
175 # building subsequent regexps.
176 my $type = do_test('result of addition',
178 'SV = ([NI])V\\($ADDR\\) at $ADDR
180 FLAGS = \\(PADTMP,\1OK,p\1OK\\) # $] < 5.019003
181 FLAGS = \\(\1OK,p\1OK\\) # $] >=5.019003
186 do_test('floating point value',
189 || $Config{ccflags} =~ /-DPERL_(?:NO_COW|OLD_COPY_ON_WRITE)/
191 'SV = PVNV\\($ADDR\\) at $ADDR
193 FLAGS = \\(NOK,pNOK\\)
195 NV = 789\\.(?:1(?:000+\d+)?|0999+\d+)
200 'SV = PVNV\\($ADDR\\) at $ADDR
202 FLAGS = \\(NOK,pNOK\\)
204 NV = 789\\.(?:1(?:000+\d+)?|0999+\d+)
207 do_test('integer constant',
209 'SV = IV\\($ADDR\\) at $ADDR
211 FLAGS = \\(.*IOK,READONLY,pIOK\\)
216 'SV = NULL\\(0x0\\) at $ADDR
218 FLAGS = \\(READONLY\\)');
220 do_test('reference to scalar',
222 'SV = $RV\\($ADDR\\) at $ADDR
226 SV = PV\\($ADDR\\) at $ADDR
228 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
238 SV = PVNV\\($ADDR\\) at $ADDR
240 FLAGS = \\(IOK,NOK,pIOK,pNOK\\)
246 SV = IV\\($ADDR\\) at $ADDR
248 FLAGS = \\(IOK,pIOK\\)
251 do_test('reference to array',
253 'SV = $RV\\($ADDR\\) at $ADDR
257 SV = PVAV\\($ADDR\\) at $ADDR
268 SV = IV\\($ADDR\\) at $ADDR
270 FLAGS = \\(IOK,pIOK\\)
272 Elt No. 1' . $c_pattern);
274 do_test('reference to hash',
276 'SV = $RV\\($ADDR\\) at $ADDR
280 SV = PVHV\\($ADDR\\) at $ADDR
282 FLAGS = \\(SHAREKEYS\\)
284 NV = $FLOAT # $] < 5.009
285 ARRAY = $ADDR \\(0:7, 1:1\\)
286 hash quality = 100.0%
290 Elt "123" HASH = $ADDR' . $c_pattern,
292 $] > 5.009 && $] < 5.015
293 && 'The hash iterator used in dump.c sets the OOK flag');
295 do_test('reference to anon sub with empty prototype',
297 'SV = $RV\\($ADDR\\) at $ADDR
301 SV = PVCV\\($ADDR\\) at $ADDR
303 FLAGS = \\($PADMY,POK,pPOK,ANON,WEAKOUTSIDE,CVGV_RC\\) # $] < 5.015 || !thr
304 FLAGS = \\($PADMY,POK,pPOK,ANON,WEAKOUTSIDE,CVGV_RC,DYNFILE\\) # $] >= 5.015 && thr
308 COMP_STASH = $ADDR\\t"main"
309 START = $ADDR ===> \\d+
311 XSUB = 0x0 # $] < 5.009
312 XSUBANY = 0 # $] < 5.009
313 GVGV::GV = $ADDR\\t"main" :: "__ANON__[^"]*"
314 FILE = ".*\\b(?i:peek\\.t)"
318 FLAGS = 0x404 # $] < 5.009
319 FLAGS = 0x490 # $] >= 5.009 && ($] < 5.015 || !thr)
320 FLAGS = 0x1490 # $] >= 5.015 && thr
323 PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\)
324 OUTSIDE = $ADDR \\(MAIN\\)');
326 do_test('reference to named subroutine without prototype',
328 'SV = $RV\\($ADDR\\) at $ADDR
332 SV = PVCV\\($ADDR\\) at $ADDR
334 FLAGS = \\((?:HASEVAL)?\\) # $] < 5.015 || !thr
335 FLAGS = \\(DYNFILE(?:,HASEVAL)?\\) # $] >= 5.015 && thr
338 COMP_STASH = $ADDR\\t"main"
339 START = $ADDR ===> \\d+
341 XSUB = 0x0 # $] < 5.009
342 XSUBANY = 0 # $] < 5.009
343 GVGV::GV = $ADDR\\t"main" :: "do_test"
344 FILE = ".*\\b(?i:peek\\.t)"
348 FLAGS = 0x(?:400)?0 # $] < 5.015 || !thr
349 FLAGS = 0x[145]000 # $] >= 5.015 && thr
352 PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\)
353 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$todo"
354 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$repeat_todo"
355 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$pattern"
356 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$do_eval"
357 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$sub"
358 \\d+\\. $ADDR<\\d+> FAKE "\\$DEBUG" # $] < 5.009
359 \\d+\\. $ADDR<\\d+> FAKE "\\$DEBUG" flags=0x0 index=0 # $] >= 5.009
360 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$dump"
361 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$dump2"
362 OUTSIDE = $ADDR \\(MAIN\\)');
365 # note the conditionals on ENGINE and INTFLAGS were introduced in 5.19.9
366 do_test('reference to regexp',
368 'SV = $RV\\($ADDR\\) at $ADDR
372 SV = REGEXP\\($ADDR\\) at $ADDR
374 FLAGS = \\(OBJECT,POK,FAKE,pPOK\\) # $] < 5.017006
375 FLAGS = \\(OBJECT,FAKE\\) # $] >= 5.017006
376 PV = $ADDR "\\(\\?\\^:tic\\)"
378 LEN = 0 # $] < 5.017006
379 STASH = $ADDR\\t"Regexp"'
383 EXTFLAGS = 0x680000 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
384 (?: ENGINE = $ADDR \(STANDARD\)
385 )? INTFLAGS = 0x0(?: \(\))?
398 )? MOTHER_RE = $ADDR'
399 . ($] < 5.019003 ? '' : '
400 SV = REGEXP\($ADDR\) at $ADDR
403 PV = $ADDR "\(\?\^:tic\)"
406 EXTFLAGS = 0x680000 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
407 (?: ENGINE = $ADDR \(STANDARD\)
408 )? INTFLAGS = 0x0(?: \(\))?
427 SAVED_COPY = 0x0)?') . '
436 do_test('reference to regexp',
438 'SV = $RV\\($ADDR\\) at $ADDR
442 SV = PVMG\\($ADDR\\) at $ADDR
444 FLAGS = \\(OBJECT,SMG\\)
450 MG_TYPE = PERL_MAGIC_qr\(r\)
452 PAT = "\(\?^:tic\)" # $] >= 5.009
453 REFCNT = 2 # $] >= 5.009
454 STASH = $ADDR\\t"Regexp"');
457 do_test('reference to blessed hash',
459 'SV = $RV\\($ADDR\\) at $ADDR
463 SV = PVHV\\($ADDR\\) at $ADDR
465 FLAGS = \\(OBJECT,SHAREKEYS\\)
468 STASH = $ADDR\\t"Tac"
476 : 'The hash iterator used in dump.c sets the OOK flag'
477 : "Something causes the HV's array to become allocated");
481 'SV = PVGV\\($ADDR\\) at $ADDR
483 FLAGS = \\(MULTI(?:,IN_PAD)?\\) # $] >= 5.009
484 FLAGS = \\(GMG,SMG,MULTI(?:,IN_PAD)?\\) # $] < 5.009
488 MAGIC = $ADDR # $] < 5.009
489 MG_VIRTUAL = &PL_vtbl_glob # $] < 5.009
490 MG_TYPE = PERL_MAGIC_glob\(\*\) # $] < 5.009
491 MG_OBJ = $ADDR # $] < 5.009
494 GvSTASH = $ADDR\\t"main"
504 GPFLAGS = 0x0 # $] < 5.009
506 FILE = ".*\\b(?i:peek\\.t)"
510 if (ord('A') == 193) {
511 do_test('string with Unicode',
512 chr(256).chr(0).chr(512),
513 'SV = PV\\($ADDR\\) at $ADDR
515 FLAGS = \\((?:$PADTMP,)?POK,READONLY,pPOK,UTF8\\) # $] < 5.019003
516 FLAGS = \\((?:$PADTMP,)?POK,(?:IsCOW,)?pPOK,UTF8\\) # $] >=5.019003
517 PV = $ADDR "\\\214\\\101\\\0\\\235\\\101"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\]
520 COW_REFCNT = 1 # $] < 5.019007
523 do_test('string with Unicode',
524 chr(256).chr(0).chr(512),
525 'SV = PV\\($ADDR\\) at $ADDR
527 FLAGS = \\((?:$PADTMP,)?POK,READONLY,pPOK,UTF8\\) # $] < 5.019003
528 FLAGS = \\((?:$PADTMP,)?POK,(?:IsCOW,)?pPOK,UTF8\\) # $] >=5.019003
529 PV = $ADDR "\\\304\\\200\\\0\\\310\\\200"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\]
532 COW_REFCNT = 1 # $] < 5.019007
536 if (ord('A') == 193) {
537 do_test('reference to hash containing Unicode',
538 {chr(256)=>chr(512)},
539 'SV = $RV\\($ADDR\\) at $ADDR
543 SV = PVHV\\($ADDR\\) at $ADDR
545 FLAGS = \\(SHAREKEYS,HASKFLAGS\\)
547 NV = $FLOAT # $] < 5.009
548 ARRAY = $ADDR \\(0:7, 1:1\\)
549 hash quality = 100.0%
553 Elt "\\\214\\\101" \[UTF8 "\\\x\{100\}"\] HASH = $ADDR
554 SV = PV\\($ADDR\\) at $ADDR
556 FLAGS = \\(POK,(?:IsCOW,)?pPOK,UTF8\\)
557 PV = $ADDR "\\\235\\\101"\\\0 \[UTF8 "\\\x\{200\}"\]
560 COW_REFCNT = 1 # $] < 5.019007
565 : 'The hash iterator used in dump.c sets the OOK flag'
566 : 'sv_length has been called on the element, and cached the result in MAGIC');
568 do_test('reference to hash containing Unicode',
569 {chr(256)=>chr(512)},
570 'SV = $RV\\($ADDR\\) at $ADDR
574 SV = PVHV\\($ADDR\\) at $ADDR
576 FLAGS = \\(SHAREKEYS,HASKFLAGS\\)
579 ARRAY = $ADDR \\(0:7, 1:1\\)
580 hash quality = 100.0%
584 Elt "\\\304\\\200" \[UTF8 "\\\x\{100\}"\] HASH = $ADDR
585 SV = PV\\($ADDR\\) at $ADDR
587 FLAGS = \\(POK,(?:IsCOW,)?pPOK,UTF8\\)
588 PV = $ADDR "\\\310\\\200"\\\0 \[UTF8 "\\\x\{200\}"\]
591 COW_REFCNT = 1 # $] < 5.019007
596 : 'The hash iterator used in dump.c sets the OOK flag'
597 : 'sv_length has been called on the element, and cached the result in MAGIC');
602 do_test('scalar with pos magic',
604 'SV = PVMG\\($ADDR\\) at $ADDR
606 FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?pPOK\\)
614 MG_VIRTUAL = &PL_vtbl_mglob
615 MG_TYPE = PERL_MAGIC_regex_global\\(g\\)
616 MG_FLAGS = 0x01 # $] < 5.019003
617 MG_FLAGS = 0x41 # $] >=5.019003
619 BYTES # $] >=5.019003
623 # TAINTEDDIR is not set on: OS2, AMIGAOS, WIN32, MSDOS
624 # environment variables may be invisibly case-forced, hence the (?i:PATH)
625 # C<scalar(@ARGV)> is turned into an IV on VMS hence the (?:IV)?
626 # Perl 5.18 ensures all env vars end up as strings only, hence the (?:,pIOK)?
627 # Perl 5.18 ensures even magic vars have public OK, hence the (?:,POK)?
628 # VMS is setting FAKE and READONLY flags. What VMS uses for storing
629 # ENV hashes is also not always null terminated.
632 # Save and restore PATH, since fresh_perl ends up using that in Windows.
633 my $path = $ENV{PATH};
634 do_test('tainted value in %ENV',
635 $ENV{PATH}=@ARGV, # scalar(@ARGV) is a handy known tainted value
636 'SV = PVMG\\($ADDR\\) at $ADDR
638 FLAGS = \\(GMG,SMG,RMG(?:,POK)?(?:,pIOK)?,pPOK\\)
645 MG_VIRTUAL = &PL_vtbl_envelem
646 MG_TYPE = PERL_MAGIC_envelem\\(e\\)
650 MG_PTR = $ADDR (?:"(?i:PATH)"|=> HEf_SVKEY
651 SV = PV(?:IV)?\\($ADDR\\) at $ADDR
653 FLAGS = \\((?:TEMP,)?POK,(?:FAKE,READONLY,)?pPOK\\)
655 )? PV = $ADDR "(?i:PATH)"(?:\\\0)?
659 MG_VIRTUAL = &PL_vtbl_taint
660 MG_TYPE = PERL_MAGIC_taint\\(t\\)');
664 do_test('blessed reference',
665 bless(\\undef, 'Foobar'),
666 'SV = $RV\\($ADDR\\) at $ADDR
670 SV = PVMG\\($ADDR\\) at $ADDR
672 FLAGS = \\(OBJECT,ROK\\)
676 SV = NULL\\(0x0\\) at $ADDR
678 FLAGS = \\(READONLY\\)
682 STASH = $ADDR\s+"Foobar"');
688 do_test('constant subroutine',
690 'SV = $RV\\($ADDR\\) at $ADDR
694 SV = PVCV\\($ADDR\\) at $ADDR
696 FLAGS = \\(POK,pPOK,CONST,ISXSUB\\) # $] < 5.015
697 FLAGS = \\(POK,pPOK,CONST,DYNFILE,ISXSUB\\) # $] >= 5.015
701 COMP_STASH = 0x0 # $] < 5.021004
702 COMP_STASH = $ADDR "main" # $] >=5.021004
703 ROOT = 0x0 # $] < 5.009
705 XSUBANY = $ADDR \\(CONST SV\\)
706 SV = PV\\($ADDR\\) at $ADDR
708 FLAGS = \\(.*POK,READONLY,(?:IsCOW,)?pPOK\\)
709 PV = $ADDR "Perl rules"\\\0
713 GVGV::GV = $ADDR\\t"main" :: "const"
714 FILE = ".*\\b(?i:peek\\.t)"
718 FLAGS = 0x200 # $] < 5.009
719 FLAGS = 0xc00 # $] >= 5.009 && $] < 5.013
720 FLAGS = 0xc # $] >= 5.013 && $] < 5.015
721 FLAGS = 0x100c # $] >= 5.015
724 OUTSIDE = 0x0 \\(null\\)');
726 do_test('isUV should show on PVMG',
727 do { my $v = $1; $v = ~0; $v },
728 'SV = PVMG\\($ADDR\\) at $ADDR
730 FLAGS = \\(IOK,pIOK,IsUV\\)
737 'SV = $RV\\($ADDR\\) at $ADDR
741 SV = PVIO\\($ADDR\\) at $ADDR
746 STASH = $ADDR\s+"IO::File"
757 SUBPROCESS = 0 # $] < 5.009
763 'SV = $RV\\($ADDR\\) at $ADDR
767 SV = PVFM\\($ADDR\\) at $ADDR
769 FLAGS = \\(\\) # $] < 5.015 || !thr
770 FLAGS = \\(DYNFILE\\) # $] >= 5.015 && thr
775 START = $ADDR ===> \\d+
777 XSUB = 0x0 # $] < 5.009
778 XSUBANY = 0 # $] < 5.009
779 GVGV::GV = $ADDR\\t"main" :: "PIE"
780 FILE = ".*\\b(?i:peek\\.t)"(?:
784 FLAGS = 0x0 # $] < 5.015 || !thr
785 FLAGS = 0x1000 # $] >= 5.015 && thr
787 LINES = 0 # $] < 5.017_003
789 PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\)
790 OUTSIDE = $ADDR \\(MAIN\\)');
792 do_test('blessing to a class with embedded NUL characters',
793 (bless {}, "\0::foo::\n::baz::\t::\0"),
794 'SV = $RV\\($ADDR\\) at $ADDR
798 SV = PVHV\\($ADDR\\) at $ADDR
800 FLAGS = \\(OBJECT,SHAREKEYS\\)
803 STASH = $ADDR\\t"\\\\0::foo::\\\\n::baz::\\\\t::\\\\0"
811 : 'The hash iterator used in dump.c sets the OOK flag'
812 : "Something causes the HV's array to become allocated");
814 do_test('ENAME on a stash',
816 'SV = $RV\\($ADDR\\) at $ADDR
820 SV = PVHV\\($ADDR\\) at $ADDR
822 FLAGS = \\(OOK,SHAREKEYS\\)
824 NV = $FLOAT # $] < 5.009
825 AUX_FLAGS = 0 # $] > 5.019008
828 FILL = 0 \(cached = 0\)
834 ENAME = "RWOM" # $] > 5.012
839 do_test('ENAMEs on a stash',
841 'SV = $RV\\($ADDR\\) at $ADDR
845 SV = PVHV\\($ADDR\\) at $ADDR
847 FLAGS = \\(OOK,SHAREKEYS\\)
849 NV = $FLOAT # $] < 5.009
850 AUX_FLAGS = 0 # $] > 5.019008
853 FILL = 0 \(cached = 0\)
859 NAMECOUNT = 2 # $] > 5.012
860 ENAME = "RWOM", "KLANK" # $] > 5.012
865 do_test('ENAMEs on a stash with no NAME',
867 'SV = $RV\\($ADDR\\) at $ADDR
871 SV = PVHV\\($ADDR\\) at $ADDR
873 FLAGS = \\(OOK,SHAREKEYS\\) # $] < 5.017
874 FLAGS = \\(OOK,OVERLOAD,SHAREKEYS\\) # $] >=5.017
876 NV = $FLOAT # $] < 5.009
877 AUX_FLAGS = 0 # $] > 5.019008
880 FILL = 0 \(cached = 0\)
885 NAMECOUNT = -3 # $] > 5.012
886 ENAME = "RWOM", "KLANK" # $] > 5.012
889 my %small = ("Perl", "Rules", "Beer", "Foamy");
891 do_test('small hash',
893 'SV = $RV\\($ADDR\\) at $ADDR
897 SV = PVHV\\($ADDR\\) at $ADDR
899 FLAGS = \\(PADMY,SHAREKEYS\\)
901 NV = $FLOAT # $] < 5.009
902 ARRAY = $ADDR \\(0:[67],.*\\)
903 hash quality = [0-9.]+%
907 (?: Elt "(?:Perl|Beer)" HASH = $ADDR
908 SV = PV\\($ADDR\\) at $ADDR
910 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
911 PV = $ADDR "(?:Rules|Foamy)"\\\0
919 do_test('small hash after keys',
921 'SV = $RV\\($ADDR\\) at $ADDR
925 SV = PVHV\\($ADDR\\) at $ADDR
927 FLAGS = \\(PADMY,OOK,SHAREKEYS\\)
929 NV = $FLOAT # $] < 5.009
930 AUX_FLAGS = 0 # $] > 5.019008
931 ARRAY = $ADDR \\(0:[67],.*\\)
932 hash quality = [0-9.]+%
934 FILL = [12] \\(cached = 0\\)
939 (?: Elt "(?:Perl|Beer)" HASH = $ADDR
940 SV = PV\\($ADDR\\) at $ADDR
942 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
943 PV = $ADDR "(?:Rules|Foamy)"\\\0
951 do_test('small hash after keys and scalar',
953 'SV = $RV\\($ADDR\\) at $ADDR
957 SV = PVHV\\($ADDR\\) at $ADDR
959 FLAGS = \\(PADMY,OOK,SHAREKEYS\\)
961 NV = $FLOAT # $] < 5.009
962 AUX_FLAGS = 0 # $] > 5.019008
963 ARRAY = $ADDR \\(0:[67],.*\\)
964 hash quality = [0-9.]+%
966 FILL = ([12]) \\(cached = \1\\)
971 (?: Elt "(?:Perl|Beer)" HASH = $ADDR
972 SV = PV\\($ADDR\\) at $ADDR
974 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
975 PV = $ADDR "(?:Rules|Foamy)"\\\0
981 # This should immediately start with the FILL cached correctly.
982 my %large = (0..1999);
984 do_test('large hash',
986 'SV = $RV\\($ADDR\\) at $ADDR
990 SV = PVHV\\($ADDR\\) at $ADDR
992 FLAGS = \\(PADMY,OOK,SHAREKEYS\\)
994 NV = $FLOAT # $] < 5.009
995 AUX_FLAGS = 0 # $] > 5.019008
996 ARRAY = $ADDR \\(0:\d+,.*\\)
997 hash quality = \d+\\.\d+%
999 FILL = (\d+) \\(cached = \1\\)
1007 # Dump with arrays, hashes, and operator return values
1009 do_test('Dump @array', '@array', <<'ARRAY', '', '', 1);
1010 SV = PVAV\($ADDR\) at $ADDR
1019 SV = IV\($ADDR\) at $ADDR
1021 FLAGS = \(IOK,pIOK\)
1024 SV = IV\($ADDR\) at $ADDR
1026 FLAGS = \(IOK,pIOK\)
1029 SV = IV\($ADDR\) at $ADDR
1031 FLAGS = \(IOK,pIOK\)
1035 do_test('Dump @array,1', '@array,1', <<'ARRAY', '', '', 1);
1036 SV = PVAV\($ADDR\) at $ADDR
1045 SV = IV\($ADDR\) at $ADDR
1047 FLAGS = \(IOK,pIOK\)
1052 do_test('Dump %hash', '%hash', <<'HASH', '', '', 1);
1053 SV = PVHV\($ADDR\) at $ADDR
1055 FLAGS = \(SHAREKEYS\)
1056 ARRAY = $ADDR \(0:7, 1:1\)
1057 hash quality = 100.0%
1061 Elt "1" HASH = $ADDR
1062 SV = IV\($ADDR\) at $ADDR
1064 FLAGS = \(IOK,pIOK\)
1069 do_test('rvalue substr', 'substr $_, 1, 2', <<'SUBSTR', '', '', 1);
1070 SV = PV\($ADDR\) at $ADDR
1072 FLAGS = \(PADTMP,POK,pPOK\)
1078 # Dump with no arguments
1080 like $@, qr/^Not enough arguments for Devel::Peek::Dump/, 'Dump;';
1082 like $@, qr/^Not enough arguments for Devel::Peek::Dump/, 'Dump()';
1085 skip "Not built with usemymalloc", 2
1086 unless $Config{usemymalloc} eq 'y';
1087 my $x = __PACKAGE__;
1088 ok eval { fill_mstats($x); 1 }, 'fill_mstats on COW scalar'
1091 ok eval { fill_mstats($y); 1 }, 'fill_mstats on undef scalar';
1094 # This is more a test of fbm_compile/pp_study (non) interaction than dumping
1095 # prowess, but short of duplicating all the gubbins of this file, I can't see
1096 # a way to make a better place for it:
1103 unless ($Config{useithreads}) {
1104 # These end up as copies in pads under ithreads, which rather defeats the
1105 # the point of what we're trying to test here.
1107 do_test('regular string constant', perl,
1108 'SV = PV\\($ADDR\\) at $ADDR
1110 FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\)
1111 PV = $ADDR "rules"\\\0
1117 eval 'index "", perl';
1119 # FIXME - really this shouldn't say EVALED. It's a false posistive on
1120 # 0x40000000 being used for several things, not a flag for "I'm in a string
1123 do_test('string constant now an FBM', perl,
1124 'SV = PVMG\\($ADDR\\) at $ADDR
1126 FLAGS = \\(PADMY,SMG,POK,READONLY,(?:IsCOW,)?pPOK,VALID,EVALED\\)
1127 PV = $ADDR "rules"\\\0
1132 MG_VIRTUAL = &PL_vtbl_regexp
1133 MG_TYPE = PERL_MAGIC_bm\\(B\\)
1135 MG_PTR = $ADDR "(?:\\\\\d){256}"
1136 RARE = \d+ # $] < 5.019002
1137 PREVIOUS = 1 # $] < 5.019002
1141 is(study perl, '', "Not allowed to study an FBM");
1143 do_test('string constant still an FBM', perl,
1144 'SV = PVMG\\($ADDR\\) at $ADDR
1146 FLAGS = \\(PADMY,SMG,POK,READONLY,(?:IsCOW,)?pPOK,VALID,EVALED\\)
1147 PV = $ADDR "rules"\\\0
1152 MG_VIRTUAL = &PL_vtbl_regexp
1153 MG_TYPE = PERL_MAGIC_bm\\(B\\)
1155 MG_PTR = $ADDR "(?:\\\\\d){256}"
1156 RARE = \d+ # $] < 5.019002
1157 PREVIOUS = 1 # $] < 5.019002
1161 do_test('regular string constant', beer,
1162 'SV = PV\\($ADDR\\) at $ADDR
1164 FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\)
1165 PV = $ADDR "foamy"\\\0
1171 is(study beer, 1, "Our studies were successful");
1173 do_test('string constant quite unaffected', beer, 'SV = PV\\($ADDR\\) at $ADDR
1175 FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\)
1176 PV = $ADDR "foamy"\\\0
1182 my $want = 'SV = PVMG\\($ADDR\\) at $ADDR
1184 FLAGS = \\(PADMY,SMG,POK,READONLY,(?:IsCOW,)?pPOK,VALID,EVALED\\)
1185 PV = $ADDR "foamy"\\\0
1190 MG_VIRTUAL = &PL_vtbl_regexp
1191 MG_TYPE = PERL_MAGIC_bm\\(B\\)
1193 MG_PTR = $ADDR "(?:\\\\\d){256}"
1194 RARE = \d+ # $] < 5.019002
1195 PREVIOUS = \d+ # $] < 5.019002
1199 is (eval 'index "not too foamy", beer', 8, 'correct index');
1201 do_test('string constant now FBMed', beer, $want);
1205 is(study $pie, 1, "Our studies were successful");
1207 do_test('string constant still FBMed', beer, $want);
1209 do_test('second string also unaffected', $pie, 'SV = PV\\($ADDR\\) at $ADDR
1211 FLAGS = \\(PADMY,POK,(?:IsCOW,)?pPOK\\)
1212 PV = $ADDR "good"\\\0
1219 # (One block of study tests removed when study was made a no-op.)
1222 open(OUT,">peek$$") or die "Failed to open peek $$: $!";
1223 open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
1225 open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
1226 pass "no crash with DeadCode";
1229 # note the conditionals on ENGINE and INTFLAGS were introduced in 5.19.9
1230 do_test('UTF-8 in a regular expression',
1232 'SV = IV\($ADDR\) at $ADDR
1236 SV = REGEXP\($ADDR\) at $ADDR
1238 FLAGS = \(OBJECT,FAKE,UTF8\)
1239 PV = $ADDR "\(\?\^u:\\\\\\\\x\{100\}\)" \[UTF8 "\(\?\^u:\\\\\\\\x\{100\}\)"\]
1241 STASH = $ADDR "Regexp"
1242 COMPFLAGS = 0x0 \(\)
1243 EXTFLAGS = 0x680040 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
1244 (?: ENGINE = $ADDR \(STANDARD\)
1245 )? INTFLAGS = 0x0(?: \(\))?
1258 )? MOTHER_RE = $ADDR'
1259 . ($] < 5.019003 ? '' : '
1260 SV = REGEXP\($ADDR\) at $ADDR
1263 PV = $ADDR "\(\?\^u:\\\\\\\\x\{100\}\)" \[UTF8 "\(\?\^u:\\\\\\\\x\{100\}\)"\]
1265 COMPFLAGS = 0x0 \(\)
1266 EXTFLAGS = 0x680040 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
1267 (?: ENGINE = $ADDR \(STANDARD\)
1268 )? INTFLAGS = 0x0(?: \(\))?
1287 SAVED_COPY = 0x0)?') . '
1296 { # perl #117793: Extend SvREFCNT* to work on any perl variable type
1298 my $base_count = Devel::Peek::SvREFCNT(%hash);
1300 is(Devel::Peek::SvREFCNT(%hash), $base_count + 1, "SvREFCNT on non-scalar");
1301 ok(!eval { &Devel::Peek::SvREFCNT(1) }, "requires prototype");
1308 open(OUT,">peek$$") or die $!;
1309 open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
1311 open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
1313 open(IN, "peek$$") or die $!;
1314 my $dump = do { local $/; <IN> };
1316 1 while unlink "peek$$";
1323 eval "sub $x {}; 1" or die $@;
1328 _dump(_get_coderef("\x{df}::\xdf")),
1329 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\xdf" :: "\xdf"/,
1330 "GVGV's are correctly escaped for latin1 :: latin1",
1334 _dump(_get_coderef("\x{30cd}::\x{30cd}")),
1335 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cd}" :: "\x{30cd}"/,
1336 "GVGV's are correctly escaped for UTF8 :: UTF8",
1340 _dump(_get_coderef("\x{df}::\x{30cd}")),
1341 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\xdf" :: "\x{30cd}"/,
1342 "GVGV's are correctly escaped for latin1 :: UTF8",
1346 _dump(_get_coderef("\x{30cd}::\x{df}")),
1347 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cd}" :: "\xdf"/,
1348 "GVGV's are correctly escaped for UTF8 :: latin1",
1352 _dump(_get_coderef("\x{30cb}::\x{df}::\x{30cd}")),
1353 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cb}::\x{df}" :: "\x{30cd}"/,
1354 "GVGV's are correctly escaped for UTF8 :: latin 1 :: UTF8",
1357 my $dump = _dump(*{"\x{30cb}::\x{df}::\x{30dc}"});
1361 qr/NAME = \Q"\x{30dc}"/,
1362 "NAME is correctly escaped for UTF8 globs",
1367 qr/GvSTASH = 0x[[:xdigit:]]+\s+\Q"\x{30cb}::\x{df}"/,
1368 "GvSTASH is correctly escaped for UTF8 globs"
1373 qr/EGV = 0x[[:xdigit:]]+\s+\Q"\x{30dc}"/,
1374 "EGV is correctly escaped for UTF8 globs"
1377 $dump = _dump(*{"\x{df}::\x{30cc}"});
1381 qr/NAME = \Q"\x{30cc}"/,
1382 "NAME is correctly escaped for UTF8 globs with latin1 stashes",
1387 qr/GvSTASH = 0x[[:xdigit:]]+\s+\Q"\xdf"/,
1388 "GvSTASH is correctly escaped for UTF8 globs with latin1 stashes"
1393 qr/EGV = 0x[[:xdigit:]]+\s+\Q"\x{30cc}"/,
1394 "EGV is correctly escaped for UTF8 globs with latin1 stashes"
1398 _dump(bless {}, "\0::\1::\x{30cd}"),
1399 qr/STASH = 0x[[:xdigit:]]+\s+\Q"\0::\x{01}::\x{30cd}"/,
1400 "STASH for blessed hashrefs is correct"
1403 BEGIN { $::{doof} = "\0\1\x{30cd}" }
1406 qr/PROTOTYPE = \Q"\0\x{01}\x{30cd}"/,
1407 "PROTOTYPE is escaped correctly"
1411 my $coderef = eval <<"EOP";
1412 use feature 'lexical_subs';
1413 no warnings 'experimental::lexical_subs';
1414 my sub bar (\$\x{30cd}) {1}; \\&bar
1418 qr/PROTOTYPE = "\$\Q\x{30cd}"/,
1419 "PROTOTYPE works on lexical subs"
1424 eval "sub $_[0] { my \$x; \$x++; return sub { eval q{\$x} } } $_[0]()";
1426 sub basic { my $x; return eval q{sub { eval q{$x} }} }
1429 qr/OUTSIDE = 0x[[:xdigit:]]+\s+\Q(basic)/,
1434 _dump(get_outside("\x{30ce}")),
1435 qr/OUTSIDE = 0x[[:xdigit:]]+\s+\Q(\x{30ce})/,
1436 'OUTSIDE + UTF8 works'
1439 # TODO AUTOLOAD = stashname, which requires using a XS autoload
1440 # and calling Dump() on the cv
1444 sub test_utf8_stashes {
1445 my ($stash_name, $test) = @_;
1447 $dump = _dump(\%{"${stash_name}::"});
1449 my $format = utf8::is_utf8($stash_name) ? '\x{%2x}' : '\x%2x';
1450 $escaped_stash_name = join "", map {
1451 $_ eq ':' ? $_ : sprintf $format, ord $_
1452 } split //, $stash_name;
1456 qr/\QNAME = "$escaped_stash_name"/,
1457 "NAME is correct escaped for $test"
1462 qr/\QENAME = "$escaped_stash_name"/,
1463 "ENAME is correct escaped for $test"
1468 [ "\x{30cd}", "UTF8 stashes" ],
1469 [ "\x{df}", "latin 1 stashes" ],
1470 [ "\x{df}::\x{30cd}", "latin1 + UTF8 stashes" ],
1471 [ "\x{30cd}::\x{df}", "UTF8 + latin1 stashes" ],
1473 test_utf8_stashes(@$test);
1478 my $runperl_args = { switches => ['-Ilib'] };
1480 my ($prog, $expected, $name, $test) = @_;
1483 my $u = 'use Devel::Peek "DumpProg"; DumpProg();';
1485 # Interface between Test::Builder & test.pl
1486 my $builder = Test::More->builder();
1487 t::curr_test($builder->current_test() + 1);
1489 utf8::encode($prog);
1491 if ( $test eq 'is' ) {
1492 t::fresh_perl_is($prog . $u, $expected, $runperl_args, $name)
1495 t::fresh_perl_like($prog . $u, $expected, $runperl_args, $name)
1498 $builder->current_test(t::curr_test() - 1);
1501 my $threads = $Config{'useithreads'};
1506 qr/PACKAGE = "test"/,
1507 "DumpProg() + package declaration"
1510 "use utf8; package \x{30cd};",
1511 qr/PACKAGE = "\\x\Q{30cd}"/,
1512 "DumpProg() + UTF8 package declaration"
1515 "use utf8; sub \x{30cc}::\x{30cd} {1}; \x{30cc}::\x{30cd};",
1516 ($threads ? qr/PADIX = \d+/ : qr/GV = \Q\x{30cc}::\x{30cd}\E/)
1519 "use utf8; \x{30cc}: { last \x{30cc} }",
1520 qr/LABEL = \Q"\x{30cc}"/
1524 test_DumpProg(@$test);
1528 dumpindent is 4 at - line 1.
1530 1 TYPE = leave ===> NULL
1532 FLAGS = (VOID,KIDS,PARENS,SLABBED,LASTSIB)
1536 2 TYPE = enter ===> 3
1537 FLAGS = (UNKNOWN,SLABBED)
1540 3 TYPE = nextstate ===> 4
1541 FLAGS = (VOID,SLABBED)
1546 5 TYPE = entersub ===> 1
1548 FLAGS = (VOID,KIDS,STACKED,SLABBED,LASTSIB)
1551 6 TYPE = null ===> (5)
1553 FLAGS = (UNKNOWN,KIDS,SLABBED,LASTSIB)
1555 4 TYPE = pushmark ===> 7
1556 FLAGS = (SCALAR,SLABBED)
1559 8 TYPE = null ===> (6)
1561 FLAGS = (SCALAR,KIDS,SLABBED,LASTSIB)
1565 FLAGS = (SCALAR,SLABBED,LASTSIB)
1574 $e =~ s/GV_OR_PADIX/$threads ? "PADIX = 2" : "GV = t::DumpProg"/e;
1575 $e =~ s/.*PRIVATE = \(0x1\).*\n// if $] < 5.021004;
1577 test_DumpProg("package t;", $e, "DumpProg() has no 'Attempt to free X prematurely' warning", "is" );