1#!./perl -T 2 3BEGIN { 4 require Config; import Config; 5 if ($Config{'extensions'} !~ /\bDevel\/Peek\b/) { 6 print "1..0 # Skip: Devel::Peek was not built\n"; 7 exit 0; 8 } 9 { 10 package t; 11 my $core = !!$ENV{PERL_CORE}; 12 require($core ? '../../t/test.pl' : './t/test.pl'); 13 } 14} 15 16use Test::More; 17 18use Devel::Peek; 19 20our $DEBUG = 0; 21open(SAVERR, ">&STDERR") or die "Can't dup STDERR: $!"; 22 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 25# maintain that. 26format PIE = 27Pie @<<<<< 28$::type 29Good @>>>>> 30$::mmmm 31. 32 33use constant thr => $Config{useithreads}; 34 35sub do_test { 36 my $todo = $_[3]; 37 my $repeat_todo = $_[4]; 38 my $pattern = $_[2]; 39 my $do_eval = $_[5]; 40 if (open(OUT,'>', "peek$$")) { 41 open(STDERR, ">&OUT") or die "Can't dup OUT: $!"; 42 if ($do_eval) { 43 my $sub = eval "sub { Dump $_[1] }"; 44 $sub->(); 45 print STDERR "*****\n"; 46 # second dump to compare with the first to make sure nothing 47 # changed. 48 $sub->(); 49 } 50 else { 51 Dump($_[1]); 52 print STDERR "*****\n"; 53 # second dump to compare with the first to make sure nothing 54 # changed. 55 Dump($_[1]); 56 } 57 open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!"; 58 close(OUT); 59 if (open(IN, '<', "peek$$")) { 60 local $/; 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; 65 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. 76 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 80 s/\s*# (\$\].*)$// 81 ? (eval $1 ? $_ : '') 82 : $_ # Didn't match, so this line is in 83 } split /^/, $pattern; 84 85 $pattern =~ s/\$PADMY,/ 86 $] < 5.012005 ? 'PADMY,' : ''; 87 /mge; 88 $pattern =~ s/\$RV/ 89 ($] < 5.011) ? 'RV' : 'IV'; 90 /mge; 91 $pattern =~ s/^\h+COW_REFCNT = .*\n//mg 92 if $Config{ccflags} =~ 93 /-DPERL_(?:OLD_COPY_ON_WRITE|NO_COW)\b/ 94 || $] < 5.019003; 95 print $pattern, "\n" if $DEBUG; 96 my ($dump, $dump2) = split m/\*\*\*\*\*\n/, scalar <IN>; 97 print $dump, "\n" if $DEBUG; 98 like( $dump, qr/\A$pattern\Z/ms, $_[0]) 99 or note("line " . (caller)[2]); 100 101 local $TODO = $repeat_todo; 102 is($dump2, $dump, "$_[0] (unchanged by dump)") 103 or note("line " . (caller)[2]); 104 105 close(IN); 106 107 return $1; 108 } else { 109 die "$0: failed to open peek$$: !\n"; 110 } 111 } else { 112 die "$0: failed to create peek$$: $!\n"; 113 } 114} 115 116our $a; 117our $b; 118my $c; 119local $d = 0; 120 121END { 122 1 while unlink("peek$$"); 123} 124 125do_test('assignment of immediate constant (string)', 126 $a = "foo", 127'SV = PV\\($ADDR\\) at $ADDR 128 REFCNT = 1 129 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\) 130 PV = $ADDR "foo"\\\0 131 CUR = 3 132 LEN = \\d+ 133 COW_REFCNT = 1 134'); 135 136do_test('immediate constant (string)', 137 "bar", 138'SV = PV\\($ADDR\\) at $ADDR 139 REFCNT = 1 140 FLAGS = \\(.*POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005 141 FLAGS = \\(.*POK,(?:IsCOW,)?READONLY,PROTECT,pPOK\\) # $] >=5.021005 142 PV = $ADDR "bar"\\\0 143 CUR = 3 144 LEN = \\d+ 145 COW_REFCNT = 0 146'); 147 148do_test('assignment of immediate constant (integer)', 149 $b = 123, 150'SV = IV\\($ADDR\\) at $ADDR 151 REFCNT = 1 152 FLAGS = \\(IOK,pIOK\\) 153 IV = 123'); 154 155do_test('immediate constant (integer)', 156 456, 157'SV = IV\\($ADDR\\) at $ADDR 158 REFCNT = 1 159 FLAGS = \\(.*IOK,READONLY,pIOK\\) # $] < 5.021005 160 FLAGS = \\(.*IOK,READONLY,PROTECT,pIOK\\) # $] >=5.021005 161 IV = 456'); 162 163do_test('assignment of immediate constant (integer)', 164 $c = 456, 165'SV = IV\\($ADDR\\) at $ADDR 166 REFCNT = 1 167 FLAGS = \\($PADMY,IOK,pIOK\\) 168 IV = 456'); 169 170# If perl is built with PERL_PRESERVE_IVUV then maths is done as integers 171# where possible and this scalar will be an IV. If NO_PERL_PRESERVE_IVUV then 172# maths is done in floating point always, and this scalar will be an NV. 173# ([NI]) captures the type, referred to by \1 in this regexp and $type for 174# building subsequent regexps. 175my $type = do_test('result of addition', 176 $c + $d, 177'SV = ([NI])V\\($ADDR\\) at $ADDR 178 REFCNT = 1 179 FLAGS = \\(PADTMP,\1OK,p\1OK\\) # $] < 5.019003 180 FLAGS = \\(\1OK,p\1OK\\) # $] >=5.019003 181 \1V = 456'); 182 183($d = "789") += 0.1; 184 185do_test('floating point value', 186 $d, 187 $] < 5.019003 188 || $Config{ccflags} =~ /-DPERL_(?:NO_COW|OLD_COPY_ON_WRITE)\b/ 189 ? 190'SV = PVNV\\($ADDR\\) at $ADDR 191 REFCNT = 1 192 FLAGS = \\(NOK,pNOK\\) 193 IV = \d+ 194 NV = 789\\.(?:1(?:000+\d+)?|0999+\d+) 195 PV = $ADDR "789"\\\0 196 CUR = 3 197 LEN = \\d+' 198 : 199'SV = PVNV\\($ADDR\\) at $ADDR 200 REFCNT = 1 201 FLAGS = \\(NOK,pNOK\\) 202 IV = \d+ 203 NV = 789\\.(?:1(?:000+\d+)?|0999+\d+) 204 PV = 0'); 205 206do_test('integer constant', 207 0xabcd, 208'SV = IV\\($ADDR\\) at $ADDR 209 REFCNT = 1 210 FLAGS = \\(.*IOK,READONLY,pIOK\\) # $] < 5.021005 211 FLAGS = \\(.*IOK,READONLY,PROTECT,pIOK\\) # $] >=5.021005 212 IV = 43981'); 213 214do_test('undef', 215 undef, 216'SV = NULL\\(0x0\\) at $ADDR 217 REFCNT = \d+ 218 FLAGS = \\(READONLY\\) # $] < 5.021005 219 FLAGS = \\(READONLY,PROTECT\\) # $] >=5.021005 220'); 221 222do_test('reference to scalar', 223 \$a, 224'SV = $RV\\($ADDR\\) at $ADDR 225 REFCNT = 1 226 FLAGS = \\(ROK\\) 227 RV = $ADDR 228 SV = PV\\($ADDR\\) at $ADDR 229 REFCNT = 2 230 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\) 231 PV = $ADDR "foo"\\\0 232 CUR = 3 233 LEN = \\d+ 234 COW_REFCNT = 1 235'); 236 237my $c_pattern; 238if ($type eq 'N') { 239 $c_pattern = ' 240 SV = PVNV\\($ADDR\\) at $ADDR 241 REFCNT = 1 242 FLAGS = \\(IOK,NOK,pIOK,pNOK\\) 243 IV = 456 244 NV = 456 245 PV = 0'; 246} else { 247 $c_pattern = ' 248 SV = IV\\($ADDR\\) at $ADDR 249 REFCNT = 1 250 FLAGS = \\(IOK,pIOK\\) 251 IV = 456'; 252} 253do_test('reference to array', 254 [$b,$c], 255'SV = $RV\\($ADDR\\) at $ADDR 256 REFCNT = 1 257 FLAGS = \\(ROK\\) 258 RV = $ADDR 259 SV = PVAV\\($ADDR\\) at $ADDR 260 REFCNT = 1 261 FLAGS = \\(\\) 262 ARRAY = $ADDR 263 FILL = 1 264 MAX = 1 265 FLAGS = \\(REAL\\) 266 Elt No. 0 267 SV = IV\\($ADDR\\) at $ADDR 268 REFCNT = 1 269 FLAGS = \\(IOK,pIOK\\) 270 IV = 123 271 Elt No. 1' . $c_pattern); 272 273do_test('reference to hash', 274 {$b=>$c}, 275'SV = $RV\\($ADDR\\) at $ADDR 276 REFCNT = 1 277 FLAGS = \\(ROK\\) 278 RV = $ADDR 279 SV = PVHV\\($ADDR\\) at $ADDR 280 REFCNT = [12] 281 FLAGS = \\(SHAREKEYS\\) 282 ARRAY = $ADDR \\(0:7, 1:1\\) 283 hash quality = 100.0% 284 KEYS = 1 285 FILL = 1 286 MAX = 7 287 Elt "123" HASH = $ADDR' . $c_pattern, 288 '', 289 ($] < 5.015) ? 'The hash iterator used in dump.c sets the OOK flag' : undef); 290 291do_test('reference to anon sub with empty prototype', 292 sub(){@_}, 293'SV = $RV\\($ADDR\\) at $ADDR 294 REFCNT = 1 295 FLAGS = \\(ROK\\) 296 RV = $ADDR 297 SV = PVCV\\($ADDR\\) at $ADDR 298 REFCNT = 2 299 FLAGS = \\($PADMY,POK,pPOK,ANON,WEAKOUTSIDE,CVGV_RC\\) # $] < 5.015 || !thr 300 FLAGS = \\($PADMY,POK,pPOK,ANON,WEAKOUTSIDE,CVGV_RC,DYNFILE\\) # $] >= 5.015 && thr 301 PROTOTYPE = "" 302 COMP_STASH = $ADDR\\t"main" 303 START = $ADDR ===> \\d+ 304 ROOT = $ADDR 305 GVGV::GV = $ADDR\\t"main" :: "__ANON__[^"]*" 306 FILE = ".*\\b(?i:peek\\.t)" 307 DEPTH = 0(?: 308 MUTEXP = $ADDR 309 OWNER = $ADDR)? 310 FLAGS = 0x490 # $] < 5.015 || !thr 311 FLAGS = 0x1490 # $] >= 5.015 && thr 312 OUTSIDE_SEQ = \\d+ 313 PADLIST = $ADDR 314 PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\) 315 OUTSIDE = $ADDR \\(MAIN\\)'); 316 317do_test('reference to named subroutine without prototype', 318 \&do_test, 319'SV = $RV\\($ADDR\\) at $ADDR 320 REFCNT = 1 321 FLAGS = \\(ROK\\) 322 RV = $ADDR 323 SV = PVCV\\($ADDR\\) at $ADDR 324 REFCNT = (3|4) 325 FLAGS = \\((?:HASEVAL(?:,NAMED)?)?\\) # $] < 5.015 || !thr 326 FLAGS = \\(DYNFILE(?:,HASEVAL(?:,NAMED)?)?\\) # $] >= 5.015 && thr 327 COMP_STASH = $ADDR\\t"main" 328 START = $ADDR ===> \\d+ 329 ROOT = $ADDR 330 NAME = "do_test" # $] >=5.021004 331 GVGV::GV = $ADDR\\t"main" :: "do_test" # $] < 5.021004 332 FILE = ".*\\b(?i:peek\\.t)" 333 DEPTH = 1(?: 334 MUTEXP = $ADDR 335 OWNER = $ADDR)? 336 FLAGS = 0x(?:[c4]00)?0 # $] < 5.015 || !thr 337 FLAGS = 0x[cd145]000 # $] >= 5.015 && thr 338 OUTSIDE_SEQ = \\d+ 339 PADLIST = $ADDR 340 PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\) 341 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$todo" 342 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$repeat_todo" 343 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$pattern" 344 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$do_eval" 345 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$sub" 346 \\d+\\. $ADDR<\\d+> FAKE "\\$DEBUG" flags=0x0 index=0 347 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$dump" 348 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$dump2" 349 OUTSIDE = $ADDR \\(MAIN\\)'); 350 351if ($] >= 5.011) { 352# note the conditionals on ENGINE and INTFLAGS were introduced in 5.19.9 353do_test('reference to regexp', 354 qr(tic), 355'SV = $RV\\($ADDR\\) at $ADDR 356 REFCNT = 1 357 FLAGS = \\(ROK\\) 358 RV = $ADDR 359 SV = REGEXP\\($ADDR\\) at $ADDR 360 REFCNT = 1 361 FLAGS = \\(OBJECT,POK,FAKE,pPOK\\) 362 PV = $ADDR "\\(\\?\\^:tic\\)" 363 CUR = 8 364 LEN = 0 365 STASH = $ADDR\\t"Regexp"' 366. ($] < 5.013 ? '' : 367' 368 COMPFLAGS = 0x0 \(\) 369 EXTFLAGS = 0x680000 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\) 370(?: ENGINE = $ADDR \(STANDARD\) 371)? INTFLAGS = 0x0(?: \(\))? 372 NPARENS = 0 373 LASTPAREN = 0 374 LASTCLOSEPAREN = 0 375 MINLEN = 3 376 MINLENRET = 3 377 GOFS = 0 378 PRE_PREFIX = 4 379 SUBLEN = 0 380 SUBOFFSET = 0 381 SUBCOFFSET = 0 382 SUBBEG = 0x0 383(?: ENGINE = $ADDR 384)? MOTHER_RE = $ADDR' 385. ($] < 5.019003 ? '' : ' 386 SV = REGEXP\($ADDR\) at $ADDR 387 REFCNT = 2 388 FLAGS = \(POK,pPOK\) 389 PV = $ADDR "\(\?\^:tic\)" 390 CUR = 8 391 LEN = \d+ 392 COMPFLAGS = 0x0 \(\) 393 EXTFLAGS = 0x680000 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\) 394(?: ENGINE = $ADDR \(STANDARD\) 395)? INTFLAGS = 0x0(?: \(\))? 396 NPARENS = 0 397 LASTPAREN = 0 398 LASTCLOSEPAREN = 0 399 MINLEN = 3 400 MINLENRET = 3 401 GOFS = 0 402 PRE_PREFIX = 4 403 SUBLEN = 0 404 SUBOFFSET = 0 405 SUBCOFFSET = 0 406 SUBBEG = 0x0 407(?: ENGINE = $ADDR 408)? MOTHER_RE = 0x0 409 PAREN_NAMES = 0x0 410 SUBSTRS = $ADDR 411 PPRIVATE = $ADDR 412 OFFS = $ADDR 413 QR_ANONCV = 0x0(?: 414 SAVED_COPY = 0x0)?') . ' 415 PAREN_NAMES = 0x0 416 SUBSTRS = $ADDR 417 PPRIVATE = $ADDR 418 OFFS = $ADDR 419 QR_ANONCV = 0x0(?: 420 SAVED_COPY = 0x0)?' 421)); 422} else { 423do_test('reference to regexp', 424 qr(tic), 425'SV = $RV\\($ADDR\\) at $ADDR 426 REFCNT = 1 427 FLAGS = \\(ROK\\) 428 RV = $ADDR 429 SV = PVMG\\($ADDR\\) at $ADDR 430 REFCNT = 1 431 FLAGS = \\(OBJECT,SMG\\) 432 IV = 0 433 NV = 0 434 PV = 0 435 MAGIC = $ADDR 436 MG_VIRTUAL = $ADDR 437 MG_TYPE = PERL_MAGIC_qr\(r\) 438 MG_OBJ = $ADDR 439 PAT = "\(\?^:tic\)" 440 REFCNT = 2 441 STASH = $ADDR\\t"Regexp"'); 442} 443 444do_test('reference to blessed hash', 445 (bless {}, "Tac"), 446'SV = $RV\\($ADDR\\) at $ADDR 447 REFCNT = 1 448 FLAGS = \\(ROK\\) 449 RV = $ADDR 450 SV = PVHV\\($ADDR\\) at $ADDR 451 REFCNT = [12] 452 FLAGS = \\(OBJECT,SHAREKEYS\\) 453 STASH = $ADDR\\t"Tac" 454 ARRAY = 0x0 455 KEYS = 0 456 FILL = 0 457 MAX = 7', '', 458 $] >= 5.015 459 ? undef 460 : 'The hash iterator used in dump.c sets the OOK flag'); 461 462do_test('typeglob', 463 *a, 464'SV = PVGV\\($ADDR\\) at $ADDR 465 REFCNT = 5 466 FLAGS = \\(MULTI(?:,IN_PAD)?\\) 467 NAME = "a" 468 NAMELEN = 1 469 GvSTASH = $ADDR\\t"main" 470 FLAGS = $ADDR # $] >=5.021004 471 GP = $ADDR 472 SV = $ADDR 473 REFCNT = 1 474 IO = 0x0 475 FORM = 0x0 476 AV = 0x0 477 HV = 0x0 478 CV = 0x0 479 CVGEN = 0x0 480 GPFLAGS = 0x0 \(\) # $] >= 5.021004 481 LINE = \\d+ 482 FILE = ".*\\b(?i:peek\\.t)" 483 FLAGS = $ADDR # $] < 5.021004 484 EGV = $ADDR\\t"a"'); 485 486if (ord('A') == 193) { 487do_test('string with Unicode', 488 chr(256).chr(0).chr(512), 489'SV = PV\\($ADDR\\) at $ADDR 490 REFCNT = 1 491 FLAGS = \\((?:PADTMP,)?POK,READONLY,pPOK,UTF8\\) # $] < 5.019003 492 FLAGS = \\((?:PADTMP,)?POK,(?:IsCOW,)?pPOK,UTF8\\) # $] >=5.019003 493 PV = $ADDR "\\\214\\\101\\\0\\\235\\\101"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\] 494 CUR = 5 495 LEN = \\d+ 496 COW_REFCNT = 1 # $] < 5.019007 497'); 498} else { 499do_test('string with Unicode', 500 chr(256).chr(0).chr(512), 501'SV = PV\\($ADDR\\) at $ADDR 502 REFCNT = 1 503 FLAGS = \\((?:PADTMP,)?POK,READONLY,pPOK,UTF8\\) # $] < 5.019003 504 FLAGS = \\((?:PADTMP,)?POK,(?:IsCOW,)?pPOK,UTF8\\) # $] >=5.019003 505 PV = $ADDR "\\\304\\\200\\\0\\\310\\\200"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\] 506 CUR = 5 507 LEN = \\d+ 508 COW_REFCNT = 1 # $] < 5.019007 509'); 510} 511 512if (ord('A') == 193) { 513do_test('reference to hash containing Unicode', 514 {chr(256)=>chr(512)}, 515'SV = $RV\\($ADDR\\) at $ADDR 516 REFCNT = 1 517 FLAGS = \\(ROK\\) 518 RV = $ADDR 519 SV = PVHV\\($ADDR\\) at $ADDR 520 REFCNT = [12] 521 FLAGS = \\(SHAREKEYS,HASKFLAGS\\) 522 ARRAY = $ADDR \\(0:7, 1:1\\) 523 hash quality = 100.0% 524 KEYS = 1 525 FILL = 1 526 MAX = 7 527 Elt "\\\214\\\101" \[UTF8 "\\\x\{100\}"\] HASH = $ADDR 528 SV = PV\\($ADDR\\) at $ADDR 529 REFCNT = 1 530 FLAGS = \\(POK,(?:IsCOW,)?pPOK,UTF8\\) 531 PV = $ADDR "\\\235\\\101"\\\0 \[UTF8 "\\\x\{200\}"\] 532 CUR = 2 533 LEN = \\d+ 534 COW_REFCNT = 1 # $] < 5.019007 535', '', 536 $] >= 5.015 537 ? undef 538 : 'The hash iterator used in dump.c sets the OOK flag'); 539} else { 540do_test('reference to hash containing Unicode', 541 {chr(256)=>chr(512)}, 542'SV = $RV\\($ADDR\\) at $ADDR 543 REFCNT = 1 544 FLAGS = \\(ROK\\) 545 RV = $ADDR 546 SV = PVHV\\($ADDR\\) at $ADDR 547 REFCNT = [12] 548 FLAGS = \\(SHAREKEYS,HASKFLAGS\\) 549 ARRAY = $ADDR \\(0:7, 1:1\\) 550 hash quality = 100.0% 551 KEYS = 1 552 FILL = 1 553 MAX = 7 554 Elt "\\\304\\\200" \[UTF8 "\\\x\{100\}"\] HASH = $ADDR 555 SV = PV\\($ADDR\\) at $ADDR 556 REFCNT = 1 557 FLAGS = \\(POK,(?:IsCOW,)?pPOK,UTF8\\) 558 PV = $ADDR "\\\310\\\200"\\\0 \[UTF8 "\\\x\{200\}"\] 559 CUR = 2 560 LEN = \\d+ 561 COW_REFCNT = 1 # $] < 5.019007 562', '', 563 $] >= 5.015 564 ? undef 565 : 'The hash iterator used in dump.c sets the OOK flag'); 566} 567 568my $x=""; 569$x=~/.??/g; 570do_test('scalar with pos magic', 571 $x, 572'SV = PVMG\\($ADDR\\) at $ADDR 573 REFCNT = 1 574 FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?pPOK\\) 575 IV = \d+ 576 NV = 0 577 PV = $ADDR ""\\\0 578 CUR = 0 579 LEN = \d+ 580 COW_REFCNT = [12] 581 MAGIC = $ADDR 582 MG_VIRTUAL = &PL_vtbl_mglob 583 MG_TYPE = PERL_MAGIC_regex_global\\(g\\) 584 MG_FLAGS = 0x01 # $] < 5.019003 585 MG_FLAGS = 0x41 # $] >=5.019003 586 MINMATCH 587 BYTES # $] >=5.019003 588'); 589 590# 591# TAINTEDDIR is not set on: OS2, AMIGAOS, WIN32, MSDOS 592# environment variables may be invisibly case-forced, hence the (?i:PATH) 593# C<scalar(@ARGV)> is turned into an IV on VMS hence the (?:IV)? 594# Perl 5.18 ensures all env vars end up as strings only, hence the (?:,pIOK)? 595# Perl 5.18 ensures even magic vars have public OK, hence the (?:,POK)? 596# VMS is setting FAKE and READONLY flags. What VMS uses for storing 597# ENV hashes is also not always null terminated. 598# 599if (${^TAINT}) { 600 # Save and restore PATH, since fresh_perl ends up using that in Windows. 601 my $path = $ENV{PATH}; 602 do_test('tainted value in %ENV', 603 $ENV{PATH}=@ARGV, # scalar(@ARGV) is a handy known tainted value 604'SV = PVMG\\($ADDR\\) at $ADDR 605 REFCNT = 1 606 FLAGS = \\(GMG,SMG,RMG(?:,POK)?(?:,pIOK)?,pPOK\\) 607 IV = 0 608 NV = 0 609 PV = $ADDR "0"\\\0 610 CUR = 1 611 LEN = \d+ 612 MAGIC = $ADDR 613 MG_VIRTUAL = &PL_vtbl_envelem 614 MG_TYPE = PERL_MAGIC_envelem\\(e\\) 615(?: MG_FLAGS = 0x01 616 TAINTEDDIR 617)? MG_LEN = -?\d+ 618 MG_PTR = $ADDR (?:"(?i:PATH)"|=> HEf_SVKEY 619 SV = PV(?:IV)?\\($ADDR\\) at $ADDR 620 REFCNT = \d+ 621 FLAGS = \\((?:TEMP,)?POK,(?:FAKE,READONLY,)?pPOK\\) 622(?: IV = 0 623)? PV = $ADDR "(?i:PATH)"(?:\\\0)? 624 CUR = \d+ 625 LEN = \d+) 626 MAGIC = $ADDR 627 MG_VIRTUAL = &PL_vtbl_taint 628 MG_TYPE = PERL_MAGIC_taint\\(t\\)'); 629 $ENV{PATH} = $path; 630} 631 632do_test('blessed reference', 633 bless(\\undef, 'Foobar'), 634'SV = $RV\\($ADDR\\) at $ADDR 635 REFCNT = 1 636 FLAGS = \\(ROK\\) 637 RV = $ADDR 638 SV = PVMG\\($ADDR\\) at $ADDR 639 REFCNT = 2 640 FLAGS = \\(OBJECT,ROK\\) 641 IV = -?\d+ 642 NV = $FLOAT 643 RV = $ADDR 644 SV = NULL\\(0x0\\) at $ADDR 645 REFCNT = \d+ 646 FLAGS = \\(READONLY\\) # $] < 5.021005 647 FLAGS = \\(READONLY,PROTECT\\) # $] >=5.021005 648 PV = $ADDR "" 649 CUR = 0 650 LEN = 0 651 STASH = $ADDR\s+"Foobar"'); 652 653sub const () { 654 "Perl rules"; 655} 656 657do_test('constant subroutine', 658 \&const, 659'SV = $RV\\($ADDR\\) at $ADDR 660 REFCNT = 1 661 FLAGS = \\(ROK\\) 662 RV = $ADDR 663 SV = PVCV\\($ADDR\\) at $ADDR 664 REFCNT = (2) 665 FLAGS = \\(POK,pPOK,CONST,ISXSUB\\) # $] < 5.015 666 FLAGS = \\(POK,pPOK,CONST,DYNFILE,ISXSUB\\) # $] >= 5.015 667 PROTOTYPE = "" 668 COMP_STASH = 0x0 # $] < 5.021004 669 COMP_STASH = $ADDR "main" # $] >=5.021004 670 XSUB = $ADDR 671 XSUBANY = $ADDR \\(CONST SV\\) 672 SV = PV\\($ADDR\\) at $ADDR 673 REFCNT = 1 674 FLAGS = \\(.*POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005 675 FLAGS = \\(.*POK,(?:IsCOW,)?READONLY,PROTECT,pPOK\\) # $] >=5.021005 676 PV = $ADDR "Perl rules"\\\0 677 CUR = 10 678 LEN = \\d+ 679 COW_REFCNT = 0 680 GVGV::GV = $ADDR\\t"main" :: "const" 681 FILE = ".*\\b(?i:peek\\.t)" 682 DEPTH = 0(?: 683 MUTEXP = $ADDR 684 OWNER = $ADDR)? 685 FLAGS = 0xc00 # $] < 5.013 686 FLAGS = 0xc # $] >= 5.013 && $] < 5.015 687 FLAGS = 0x100c # $] >= 5.015 688 OUTSIDE_SEQ = 0 689 PADLIST = 0x0 # $] < 5.021006 690 HSCXT = $ADDR # $] >= 5.021006 691 OUTSIDE = 0x0 \\(null\\)'); 692 693do_test('isUV should show on PVMG', 694 do { my $v = $1; $v = ~0; $v }, 695'SV = PVMG\\($ADDR\\) at $ADDR 696 REFCNT = 1 697 FLAGS = \\(IOK,pIOK,IsUV\\) 698 UV = \d+ 699 NV = 0 700 PV = 0'); 701 702do_test('IO', 703 *STDOUT{IO}, 704'SV = $RV\\($ADDR\\) at $ADDR 705 REFCNT = 1 706 FLAGS = \\(ROK\\) 707 RV = $ADDR 708 SV = PVIO\\($ADDR\\) at $ADDR 709 REFCNT = 3 710 FLAGS = \\(OBJECT\\) 711 IV = 0 # $] < 5.011 712 NV = 0 # $] < 5.011 713 STASH = $ADDR\s+"IO::File" 714 IFP = $ADDR 715 OFP = $ADDR 716 DIRP = 0x0 717 LINES = 0 718 PAGE = 0 719 PAGE_LEN = 60 720 LINES_LEFT = 0 721 TOP_GV = 0x0 722 FMT_GV = 0x0 723 BOTTOM_GV = 0x0 724 TYPE = \'>\' 725 FLAGS = 0x4'); 726 727do_test('FORMAT', 728 *PIE{FORMAT}, 729'SV = $RV\\($ADDR\\) at $ADDR 730 REFCNT = 1 731 FLAGS = \\(ROK\\) 732 RV = $ADDR 733 SV = PVFM\\($ADDR\\) at $ADDR 734 REFCNT = 2 735 FLAGS = \\(\\) # $] < 5.015 || !thr 736 FLAGS = \\(DYNFILE\\) # $] >= 5.015 && thr 737(?: PV = 0 738)? COMP_STASH = 0x0 739 START = $ADDR ===> \\d+ 740 ROOT = $ADDR 741 GVGV::GV = $ADDR\\t"main" :: "PIE" 742 FILE = ".*\\b(?i:peek\\.t)"(?: 743 DEPTH = 0)?(?: 744 MUTEXP = $ADDR 745 OWNER = $ADDR)? 746 FLAGS = 0x0 # $] < 5.015 || !thr 747 FLAGS = 0x1000 # $] >= 5.015 && thr 748 OUTSIDE_SEQ = \\d+ 749 LINES = 0 # $] < 5.017_003 750 PADLIST = $ADDR 751 PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\) 752 OUTSIDE = $ADDR \\(MAIN\\)'); 753 754do_test('blessing to a class with embedded NUL characters', 755 (bless {}, "\0::foo::\n::baz::\t::\0"), 756'SV = $RV\\($ADDR\\) at $ADDR 757 REFCNT = 1 758 FLAGS = \\(ROK\\) 759 RV = $ADDR 760 SV = PVHV\\($ADDR\\) at $ADDR 761 REFCNT = [12] 762 FLAGS = \\(OBJECT,SHAREKEYS\\) 763 STASH = $ADDR\\t"\\\\0::foo::\\\\n::baz::\\\\t::\\\\0" 764 ARRAY = $ADDR 765 KEYS = 0 766 FILL = 0 767 MAX = 7', '', 768 $] >= 5.015 769 ? undef 770 : 'The hash iterator used in dump.c sets the OOK flag'); 771 772do_test('ENAME on a stash', 773 \%RWOM::, 774'SV = $RV\\($ADDR\\) at $ADDR 775 REFCNT = 1 776 FLAGS = \\(ROK\\) 777 RV = $ADDR 778 SV = PVHV\\($ADDR\\) at $ADDR 779 REFCNT = 2 780 FLAGS = \\(OOK,SHAREKEYS\\) 781 AUX_FLAGS = 0 # $] > 5.019008 782 ARRAY = $ADDR 783 KEYS = 0 784 FILL = 0 785 MAX = 7 786 RITER = -1 787 EITER = 0x0 788 RAND = $ADDR 789 NAME = "RWOM" 790 ENAME = "RWOM" # $] > 5.012 791'); 792 793*KLANK:: = \%RWOM::; 794 795do_test('ENAMEs on a stash', 796 \%RWOM::, 797'SV = $RV\\($ADDR\\) at $ADDR 798 REFCNT = 1 799 FLAGS = \\(ROK\\) 800 RV = $ADDR 801 SV = PVHV\\($ADDR\\) at $ADDR 802 REFCNT = 3 803 FLAGS = \\(OOK,SHAREKEYS\\) 804 AUX_FLAGS = 0 # $] > 5.019008 805 ARRAY = $ADDR 806 KEYS = 0 807 FILL = 0 808 MAX = 7 809 RITER = -1 810 EITER = 0x0 811 RAND = $ADDR 812 NAME = "RWOM" 813 NAMECOUNT = 2 # $] > 5.012 814 ENAME = "RWOM", "KLANK" # $] > 5.012 815'); 816 817undef %RWOM::; 818 819do_test('ENAMEs on a stash with no NAME', 820 \%RWOM::, 821'SV = $RV\\($ADDR\\) at $ADDR 822 REFCNT = 1 823 FLAGS = \\(ROK\\) 824 RV = $ADDR 825 SV = PVHV\\($ADDR\\) at $ADDR 826 REFCNT = 3 827 FLAGS = \\(OOK,SHAREKEYS\\) # $] < 5.017 828 FLAGS = \\(OOK,OVERLOAD,SHAREKEYS\\) # $] >=5.017 && $]<5.021005 829 FLAGS = \\(OOK,SHAREKEYS,OVERLOAD\\) # $] >=5.021005 830 AUX_FLAGS = 0 # $] > 5.019008 831 ARRAY = $ADDR 832 KEYS = 0 833 FILL = 0 834 MAX = 7 835 RITER = -1 836 EITER = 0x0 837 RAND = $ADDR 838 NAMECOUNT = -3 # $] > 5.012 839 ENAME = "RWOM", "KLANK" # $] > 5.012 840'); 841 842my %small = ("Perl", "Rules", "Beer", "Foamy"); 843my $b = %small; 844do_test('small hash', 845 \%small, 846'SV = $RV\\($ADDR\\) at $ADDR 847 REFCNT = 1 848 FLAGS = \\(ROK\\) 849 RV = $ADDR 850 SV = PVHV\\($ADDR\\) at $ADDR 851 REFCNT = 2 852 FLAGS = \\($PADMY,SHAREKEYS\\) 853 ARRAY = $ADDR \\(0:[67],.*\\) 854 hash quality = [0-9.]+% 855 KEYS = 2 856 FILL = [12] 857 MAX = 7 858(?: Elt "(?:Perl|Beer)" HASH = $ADDR 859 SV = PV\\($ADDR\\) at $ADDR 860 REFCNT = 1 861 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\) 862 PV = $ADDR "(?:Rules|Foamy)"\\\0 863 CUR = \d+ 864 LEN = \d+ 865 COW_REFCNT = 1 866){2}'); 867 868$b = keys %small; 869 870do_test('small hash after keys', 871 \%small, 872'SV = $RV\\($ADDR\\) at $ADDR 873 REFCNT = 1 874 FLAGS = \\(ROK\\) 875 RV = $ADDR 876 SV = PVHV\\($ADDR\\) at $ADDR 877 REFCNT = 2 878 FLAGS = \\($PADMY,OOK,SHAREKEYS\\) 879 AUX_FLAGS = 0 # $] > 5.019008 880 ARRAY = $ADDR \\(0:[67],.*\\) 881 hash quality = [0-9.]+% 882 KEYS = 2 883 FILL = [12] 884 MAX = 7 885 RITER = -1 886 EITER = 0x0 887 RAND = $ADDR 888(?: Elt "(?:Perl|Beer)" HASH = $ADDR 889 SV = PV\\($ADDR\\) at $ADDR 890 REFCNT = 1 891 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\) 892 PV = $ADDR "(?:Rules|Foamy)"\\\0 893 CUR = \d+ 894 LEN = \d+ 895 COW_REFCNT = 1 896){2}'); 897 898$b = %small; 899 900do_test('small hash after keys and scalar', 901 \%small, 902'SV = $RV\\($ADDR\\) at $ADDR 903 REFCNT = 1 904 FLAGS = \\(ROK\\) 905 RV = $ADDR 906 SV = PVHV\\($ADDR\\) at $ADDR 907 REFCNT = 2 908 FLAGS = \\($PADMY,OOK,SHAREKEYS\\) 909 AUX_FLAGS = 0 # $] > 5.019008 910 ARRAY = $ADDR \\(0:[67],.*\\) 911 hash quality = [0-9.]+% 912 KEYS = 2 913 FILL = ([12]) 914 MAX = 7 915 RITER = -1 916 EITER = 0x0 917 RAND = $ADDR 918(?: Elt "(?:Perl|Beer)" HASH = $ADDR 919 SV = PV\\($ADDR\\) at $ADDR 920 REFCNT = 1 921 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\) 922 PV = $ADDR "(?:Rules|Foamy)"\\\0 923 CUR = \d+ 924 LEN = \d+ 925 COW_REFCNT = 1 926){2}'); 927 928# Dump with arrays, hashes, and operator return values 929@array = 1..3; 930do_test('Dump @array', '@array', <<'ARRAY', '', undef, 1); 931SV = PVAV\($ADDR\) at $ADDR 932 REFCNT = 1 933 FLAGS = \(\) 934 ARRAY = $ADDR 935 FILL = 2 936 MAX = 3 937 FLAGS = \(REAL\) 938 Elt No. 0 939 SV = IV\($ADDR\) at $ADDR 940 REFCNT = 1 941 FLAGS = \(IOK,pIOK\) 942 IV = 1 943 Elt No. 1 944 SV = IV\($ADDR\) at $ADDR 945 REFCNT = 1 946 FLAGS = \(IOK,pIOK\) 947 IV = 2 948 Elt No. 2 949 SV = IV\($ADDR\) at $ADDR 950 REFCNT = 1 951 FLAGS = \(IOK,pIOK\) 952 IV = 3 953ARRAY 954 955do_test('Dump @array,1', '@array,1', <<'ARRAY', '', undef, 1); 956SV = PVAV\($ADDR\) at $ADDR 957 REFCNT = 1 958 FLAGS = \(\) 959 ARRAY = $ADDR 960 FILL = 2 961 MAX = 3 962 FLAGS = \(REAL\) 963 Elt No. 0 964 SV = IV\($ADDR\) at $ADDR 965 REFCNT = 1 966 FLAGS = \(IOK,pIOK\) 967 IV = 1 968ARRAY 969 970%hash = 1..2; 971do_test('Dump %hash', '%hash', <<'HASH', '', undef, 1); 972SV = PVHV\($ADDR\) at $ADDR 973 REFCNT = 1 974 FLAGS = \(SHAREKEYS\) 975 ARRAY = $ADDR \(0:7, 1:1\) 976 hash quality = 100.0% 977 KEYS = 1 978 FILL = 1 979 MAX = 7 980 Elt "1" HASH = $ADDR 981 SV = IV\($ADDR\) at $ADDR 982 REFCNT = 1 983 FLAGS = \(IOK,pIOK\) 984 IV = 2 985HASH 986 987$_ = "hello"; 988do_test('rvalue substr', 'substr $_, 1, 2', <<'SUBSTR', '', undef, 1); 989SV = PV\($ADDR\) at $ADDR 990 REFCNT = 1 991 FLAGS = \(PADTMP,POK,pPOK\) 992 PV = $ADDR "el"\\0 993 CUR = 2 994 LEN = \d+ 995SUBSTR 996 997# Dump with no arguments 998eval 'Dump'; 999like $@, qr/^Not enough arguments for Devel::Peek::Dump/, 'Dump;'; 1000eval 'Dump()'; 1001like $@, qr/^Not enough arguments for Devel::Peek::Dump/, 'Dump()'; 1002 1003SKIP: { 1004 skip "Not built with usemymalloc", 2 1005 unless $Config{usemymalloc} eq 'y'; 1006 my $x = __PACKAGE__; 1007 ok eval { fill_mstats($x); 1 }, 'fill_mstats on COW scalar' 1008 or diag $@; 1009 my $y; 1010 ok eval { fill_mstats($y); 1 }, 'fill_mstats on undef scalar'; 1011} 1012 1013# This is more a test of fbm_compile/pp_study (non) interaction than dumping 1014# prowess, but short of duplicating all the gubbins of this file, I can't see 1015# a way to make a better place for it: 1016 1017use constant { 1018 1019 # The length of the rhs string must be such that if chr() is applied to it 1020 # doesn't yield a character with a backslash mnemonic. For example, if it 1021 # were 'rules' instead of 'rule', it would have 5 characters, and on 1022 # EBCDIC, chr(5) is \t. The dumping code would translate all the 5's in 1023 # MG_PTR into "\t", and this test code would be expecting \5's, so the 1024 # tests would fail. No platform that Perl works on translates chr(4) into 1025 # a mnemonic. 1026 perl => 'rule', 1027 beer => 'foam', 1028}; 1029 1030unless ($Config{useithreads}) { 1031 # These end up as copies in pads under ithreads, which rather defeats the 1032 # point of what we're trying to test here. 1033 1034 do_test('regular string constant', perl, 1035'SV = PV\\($ADDR\\) at $ADDR 1036 REFCNT = 5 1037 FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005 1038 FLAGS = \\(POK,(?:IsCOW,)?READONLY,pPOK\\) # $] >=5.021005 1039 PV = $ADDR "rule"\\\0 1040 CUR = 4 1041 LEN = \d+ 1042 COW_REFCNT = 0 1043'); 1044 1045 eval 'index "", perl'; 1046 1047 do_test('string constant now an FBM', perl, 1048'SV = PVMG\\($ADDR\\) at $ADDR 1049 REFCNT = 5 1050 FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?READONLY,(?:IsCOW,)?pPOK\\) 1051 PV = $ADDR "rule"\\\0 1052 CUR = 4 1053 LEN = \d+ 1054 COW_REFCNT = 0 1055 MAGIC = $ADDR 1056 MG_VIRTUAL = &PL_vtbl_regexp 1057 MG_TYPE = PERL_MAGIC_bm\\(B\\) 1058 MG_LEN = 256 1059 MG_PTR = $ADDR "(?:\\\\\d){256}" 1060 RARE = \d+ # $] < 5.019002 1061 PREVIOUS = 1 # $] < 5.019002 1062 USEFUL = 100 1063'); 1064 1065 is(study perl, '', "Not allowed to study an FBM"); 1066 1067 do_test('string constant still an FBM', perl, 1068'SV = PVMG\\($ADDR\\) at $ADDR 1069 REFCNT = 5 1070 FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?READONLY,(?:IsCOW,)?pPOK\\) 1071 PV = $ADDR "rule"\\\0 1072 CUR = 4 1073 LEN = \d+ 1074 COW_REFCNT = 0 1075 MAGIC = $ADDR 1076 MG_VIRTUAL = &PL_vtbl_regexp 1077 MG_TYPE = PERL_MAGIC_bm\\(B\\) 1078 MG_LEN = 256 1079 MG_PTR = $ADDR "(?:\\\\\d){256}" 1080 RARE = \d+ # $] < 5.019002 1081 PREVIOUS = 1 # $] < 5.019002 1082 USEFUL = 100 1083'); 1084 1085 do_test('regular string constant', beer, 1086'SV = PV\\($ADDR\\) at $ADDR 1087 REFCNT = 6 1088 FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005 1089 FLAGS = \\(POK,(?:IsCOW,)?READONLY,pPOK\\) # $] >=5.021005 1090 PV = $ADDR "foam"\\\0 1091 CUR = 4 1092 LEN = \d+ 1093 COW_REFCNT = 0 1094'); 1095 1096 is(study beer, 1, "Our studies were successful"); 1097 1098 do_test('string constant quite unaffected', beer, 'SV = PV\\($ADDR\\) at $ADDR 1099 REFCNT = 6 1100 FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005 1101 FLAGS = \\(POK,(?:IsCOW,)?READONLY,pPOK\\) # $] >=5.021005 1102 PV = $ADDR "foam"\\\0 1103 CUR = 4 1104 LEN = \d+ 1105 COW_REFCNT = 0 1106'); 1107 1108 my $want = 'SV = PVMG\\($ADDR\\) at $ADDR 1109 REFCNT = 6 1110 FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?READONLY,(?:IsCOW,)?pPOK\\) 1111 PV = $ADDR "foam"\\\0 1112 CUR = 4 1113 LEN = \d+ 1114 COW_REFCNT = 0 1115 MAGIC = $ADDR 1116 MG_VIRTUAL = &PL_vtbl_regexp 1117 MG_TYPE = PERL_MAGIC_bm\\(B\\) 1118 MG_LEN = 256 1119 MG_PTR = $ADDR "(?:\\\\\d){256}" 1120 RARE = \d+ # $] < 5.019002 1121 PREVIOUS = \d+ # $] < 5.019002 1122 USEFUL = 100 1123'; 1124 1125 is (eval 'index "not too foamy", beer', 8, 'correct index'); 1126 1127 do_test('string constant now FBMed', beer, $want); 1128 1129 my $pie = 'good'; 1130 1131 is(study $pie, 1, "Our studies were successful"); 1132 1133 do_test('string constant still FBMed', beer, $want); 1134 1135 do_test('second string also unaffected', $pie, 'SV = PV\\($ADDR\\) at $ADDR 1136 REFCNT = 1 1137 FLAGS = \\($PADMY,POK,(?:IsCOW,)?pPOK\\) 1138 PV = $ADDR "good"\\\0 1139 CUR = 4 1140 LEN = \d+ 1141 COW_REFCNT = 1 1142'); 1143} 1144 1145# (One block of study tests removed when study was made a no-op.) 1146 1147{ 1148 open(OUT, '>', "peek$$") or die "Failed to open peek $$: $!"; 1149 open(STDERR, ">&OUT") or die "Can't dup OUT: $!"; 1150 DeadCode(); 1151 open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!"; 1152 pass "no crash with DeadCode"; 1153 close OUT; 1154} 1155# note the conditionals on ENGINE and INTFLAGS were introduced in 5.19.9 1156do_test('UTF-8 in a regular expression', 1157 qr/\x{100}/, 1158'SV = IV\($ADDR\) at $ADDR 1159 REFCNT = 1 1160 FLAGS = \(ROK\) 1161 RV = $ADDR 1162 SV = REGEXP\($ADDR\) at $ADDR 1163 REFCNT = 1 1164 FLAGS = \(OBJECT,POK,FAKE,pPOK,UTF8\) 1165 PV = $ADDR "\(\?\^u:\\\\\\\\x\{100\}\)" \[UTF8 "\(\?\^u:\\\\\\\\x\{100\}\)"\] 1166 CUR = 13 1167 LEN = 0 1168 STASH = $ADDR "Regexp" 1169 COMPFLAGS = 0x0 \(\) 1170 EXTFLAGS = $ADDR \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\) 1171(?: ENGINE = $ADDR \(STANDARD\) 1172)? INTFLAGS = 0x0(?: \(\))? 1173 NPARENS = 0 1174 LASTPAREN = 0 1175 LASTCLOSEPAREN = 0 1176 MINLEN = 1 1177 MINLENRET = 1 1178 GOFS = 0 1179 PRE_PREFIX = 5 1180 SUBLEN = 0 1181 SUBOFFSET = 0 1182 SUBCOFFSET = 0 1183 SUBBEG = 0x0 1184(?: ENGINE = $ADDR 1185)? MOTHER_RE = $ADDR' 1186. ($] < 5.019003 ? '' : ' 1187 SV = REGEXP\($ADDR\) at $ADDR 1188 REFCNT = 2 1189 FLAGS = \(POK,pPOK,UTF8\) 1190 PV = $ADDR "\(\?\^u:\\\\\\\\x\{100\}\)" \[UTF8 "\(\?\^u:\\\\\\\\x\{100\}\)"\] 1191 CUR = 13 1192 LEN = \d+ 1193 COMPFLAGS = 0x0 \(\) 1194 EXTFLAGS = $ADDR \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\) 1195(?: ENGINE = $ADDR \(STANDARD\) 1196)? INTFLAGS = 0x0(?: \(\))? 1197 NPARENS = 0 1198 LASTPAREN = 0 1199 LASTCLOSEPAREN = 0 1200 MINLEN = 1 1201 MINLENRET = 1 1202 GOFS = 0 1203 PRE_PREFIX = 5 1204 SUBLEN = 0 1205 SUBOFFSET = 0 1206 SUBCOFFSET = 0 1207 SUBBEG = 0x0 1208(?: ENGINE = $ADDR 1209)? MOTHER_RE = 0x0 1210 PAREN_NAMES = 0x0 1211 SUBSTRS = $ADDR 1212 PPRIVATE = $ADDR 1213 OFFS = $ADDR 1214 QR_ANONCV = 0x0(?: 1215 SAVED_COPY = 0x0)?') . ' 1216 PAREN_NAMES = 0x0 1217 SUBSTRS = $ADDR 1218 PPRIVATE = $ADDR 1219 OFFS = $ADDR 1220 QR_ANONCV = 0x0(?: 1221 SAVED_COPY = 0x0)? 1222'); 1223 1224{ # perl #117793: Extend SvREFCNT* to work on any perl variable type 1225 my %hash; 1226 my $base_count = Devel::Peek::SvREFCNT(%hash); 1227 my $ref = \%hash; 1228 is(Devel::Peek::SvREFCNT(%hash), $base_count + 1, "SvREFCNT on non-scalar"); 1229 ok(!eval { &Devel::Peek::SvREFCNT(1) }, "requires prototype"); 1230} 1231{ 1232# utf8 tests 1233use utf8; 1234 1235sub _dump { 1236 open(OUT, '>', "peek$$") or die $!; 1237 open(STDERR, ">&OUT") or die "Can't dup OUT: $!"; 1238 Dump($_[0]); 1239 open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!"; 1240 close(OUT); 1241 open(IN, '<', "peek$$") or die $!; 1242 my $dump = do { local $/; <IN> }; 1243 close(IN); 1244 1 while unlink "peek$$"; 1245 return $dump; 1246} 1247 1248sub _get_coderef { 1249 my $x = $_[0]; 1250 utf8::upgrade($x); 1251 eval "sub $x {}; 1" or die $@; 1252 return *{$x}{CODE}; 1253} 1254 1255like( 1256 _dump(_get_coderef("\x{df}::\xdf")), 1257 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\xdf" :: "\xdf"/, 1258 "GVGV's are correctly escaped for latin1 :: latin1", 1259); 1260 1261like( 1262 _dump(_get_coderef("\x{30cd}::\x{30cd}")), 1263 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cd}" :: "\x{30cd}"/, 1264 "GVGV's are correctly escaped for UTF8 :: UTF8", 1265); 1266 1267like( 1268 _dump(_get_coderef("\x{df}::\x{30cd}")), 1269 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\xdf" :: "\x{30cd}"/, 1270 "GVGV's are correctly escaped for latin1 :: UTF8", 1271); 1272 1273like( 1274 _dump(_get_coderef("\x{30cd}::\x{df}")), 1275 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cd}" :: "\xdf"/, 1276 "GVGV's are correctly escaped for UTF8 :: latin1", 1277); 1278 1279like( 1280 _dump(_get_coderef("\x{30cb}::\x{df}::\x{30cd}")), 1281 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cb}::\x{df}" :: "\x{30cd}"/, 1282 "GVGV's are correctly escaped for UTF8 :: latin 1 :: UTF8", 1283); 1284 1285my $dump = _dump(*{"\x{30cb}::\x{df}::\x{30dc}"}); 1286 1287like( 1288 $dump, 1289 qr/NAME = \Q"\x{30dc}"/, 1290 "NAME is correctly escaped for UTF8 globs", 1291); 1292 1293like( 1294 $dump, 1295 qr/GvSTASH = 0x[[:xdigit:]]+\s+\Q"\x{30cb}::\x{df}"/, 1296 "GvSTASH is correctly escaped for UTF8 globs" 1297); 1298 1299like( 1300 $dump, 1301 qr/EGV = 0x[[:xdigit:]]+\s+\Q"\x{30dc}"/, 1302 "EGV is correctly escaped for UTF8 globs" 1303); 1304 1305$dump = _dump(*{"\x{df}::\x{30cc}"}); 1306 1307like( 1308 $dump, 1309 qr/NAME = \Q"\x{30cc}"/, 1310 "NAME is correctly escaped for UTF8 globs with latin1 stashes", 1311); 1312 1313like( 1314 $dump, 1315 qr/GvSTASH = 0x[[:xdigit:]]+\s+\Q"\xdf"/, 1316 "GvSTASH is correctly escaped for UTF8 globs with latin1 stashes" 1317); 1318 1319like( 1320 $dump, 1321 qr/EGV = 0x[[:xdigit:]]+\s+\Q"\x{30cc}"/, 1322 "EGV is correctly escaped for UTF8 globs with latin1 stashes" 1323); 1324 1325like( 1326 _dump(bless {}, "\0::\1::\x{30cd}"), 1327 qr/STASH = 0x[[:xdigit:]]+\s+\Q"\0::\x{01}::\x{30cd}"/, 1328 "STASH for blessed hashrefs is correct" 1329); 1330 1331BEGIN { $::{doof} = "\0\1\x{30cd}" } 1332like( 1333 _dump(\&doof), 1334 qr/PROTOTYPE = \Q"\0\x{01}\x{30cd}"/, 1335 "PROTOTYPE is escaped correctly" 1336); 1337 1338{ 1339 my $coderef = eval <<"EOP"; 1340 use feature 'lexical_subs'; 1341 no warnings 'experimental::lexical_subs'; 1342 my sub bar (\$\x{30cd}) {1}; \\&bar 1343EOP 1344 like( 1345 _dump($coderef), 1346 qr/PROTOTYPE = "\$\Q\x{30cd}"/, 1347 "PROTOTYPE works on lexical subs" 1348 ) 1349} 1350 1351sub get_outside { 1352 eval "sub $_[0] { my \$x; \$x++; return sub { eval q{\$x} } } $_[0]()"; 1353} 1354sub basic { my $x; return eval q{sub { eval q{$x} }} } 1355like( 1356 _dump(basic()), 1357 qr/OUTSIDE = 0x[[:xdigit:]]+\s+\Q(basic)/, 1358 'OUTSIDE works' 1359); 1360 1361like( 1362 _dump(get_outside("\x{30ce}")), 1363 qr/OUTSIDE = 0x[[:xdigit:]]+\s+\Q(\x{30ce})/, 1364 'OUTSIDE + UTF8 works' 1365); 1366 1367# TODO AUTOLOAD = stashname, which requires using a XS autoload 1368# and calling Dump() on the cv 1369 1370 1371 1372sub test_utf8_stashes { 1373 my ($stash_name, $test) = @_; 1374 1375 $dump = _dump(\%{"${stash_name}::"}); 1376 1377 my $format = utf8::is_utf8($stash_name) ? '\x{%2x}' : '\x%2x'; 1378 $escaped_stash_name = join "", map { 1379 $_ eq ':' ? $_ : sprintf $format, ord $_ 1380 } split //, $stash_name; 1381 1382 like( 1383 $dump, 1384 qr/\QNAME = "$escaped_stash_name"/, 1385 "NAME is correct escaped for $test" 1386 ); 1387 1388 like( 1389 $dump, 1390 qr/\QENAME = "$escaped_stash_name"/, 1391 "ENAME is correct escaped for $test" 1392 ); 1393} 1394 1395for my $test ( 1396 [ "\x{30cd}", "UTF8 stashes" ], 1397 [ "\x{df}", "latin 1 stashes" ], 1398 [ "\x{df}::\x{30cd}", "latin1 + UTF8 stashes" ], 1399 [ "\x{30cd}::\x{df}", "UTF8 + latin1 stashes" ], 1400) { 1401 test_utf8_stashes(@$test); 1402} 1403 1404} 1405 1406my $runperl_args = { switches => ['-Ilib'] }; 1407sub test_DumpProg { 1408 my ($prog, $expected, $name, $test) = @_; 1409 $test ||= 'like'; 1410 1411 my $u = 'use Devel::Peek "DumpProg"; DumpProg();'; 1412 1413 # Interface between Test::Builder & test.pl 1414 my $builder = Test::More->builder(); 1415 t::curr_test($builder->current_test() + 1); 1416 1417 utf8::encode($prog); 1418 1419 if ( $test eq 'is' ) { 1420 t::fresh_perl_is($prog . $u, $expected, $runperl_args, $name) 1421 } 1422 else { 1423 t::fresh_perl_like($prog . $u, $expected, $runperl_args, $name) 1424 } 1425 1426 $builder->current_test(t::curr_test() - 1); 1427} 1428 1429my $threads = $Config{'useithreads'}; 1430 1431for my $test ( 1432[ 1433 "package test;", 1434 qr/PACKAGE = "test"/, 1435 "DumpProg() + package declaration" 1436], 1437[ 1438 "use utf8; package \x{30cd};", 1439 qr/PACKAGE = "\\x\Q{30cd}"/, 1440 "DumpProg() + UTF8 package declaration" 1441], 1442[ 1443 "use utf8; sub \x{30cc}::\x{30cd} {1}; \x{30cc}::\x{30cd};", 1444 ($threads ? qr/PADIX = \d+/ : qr/GV = \Q\x{30cc}::\x{30cd}\E/) 1445], 1446[ 1447 "use utf8; \x{30cc}: { last \x{30cc} }", 1448 qr/LABEL = \Q"\x{30cc}"/ 1449], 1450) 1451{ 1452 test_DumpProg(@$test); 1453} 1454 1455{ 1456 local $TODO = 'This gets mangled by the current pipe implementation' if $^O eq 'VMS'; 1457 my $e = <<'EODUMP'; 1458dumpindent is 4 at -e line 1. 1459 14601 leave LISTOP(0xNNN) ===> [0x0] 1461 PARENT ===> [0x0] 1462 TARG = 1 1463 FLAGS = (VOID,KIDS,PARENS,SLABBED) 1464 PRIVATE = (REFC) 1465 REFCNT = 1 1466 | 14672 +--enter OP(0xNNN) ===> 3 [nextstate 0xNNN] 1468 | FLAGS = (VOID,SLABBED,MORESIB) 1469 | 14703 +--nextstate COP(0xNNN) ===> 4 [pushmark 0xNNN] 1471 | FLAGS = (VOID,SLABBED,MORESIB) 1472 | LINE = 1 1473 | PACKAGE = "t" 1474 | | 14755 +--entersub UNOP(0xNNN) ===> 1 [leave 0xNNN] 1476 TARG = 1 1477 FLAGS = (VOID,KIDS,STACKED,SLABBED) 1478 PRIVATE = (TARG) 1479 | 14806 +--null (ex-list) UNOP(0xNNN) ===> 5 [entersub 0xNNN] 1481 FLAGS = (UNKNOWN,KIDS,SLABBED) 1482 | 14834 +--pushmark OP(0xNNN) ===> 7 [gv 0xNNN] 1484 | FLAGS = (SCALAR,SLABBED,MORESIB) 1485 | 14868 +--null (ex-rv2cv) UNOP(0xNNN) ===> 6 [null 0xNNN] 1487 FLAGS = (SCALAR,KIDS,SLABBED) 1488 PRIVATE = (0x1) 1489 | 14907 +--gv SVOP(0xNNN) ===> 5 [entersub 0xNNN] 1491 FLAGS = (SCALAR,SLABBED) 1492 GV_OR_PADIX 1493EODUMP 1494 1495 $e =~ s/GV_OR_PADIX/$threads ? "PADIX = 2" : "GV = t::DumpProg (0xNNN)"/e; 1496 $e =~ s/SVOP/PADOP/g if $threads; 1497 my $out = t::runperl 1498 switches => ['-Ilib'], 1499 prog => 'package t; use Devel::Peek q-DumpProg-; DumpProg();', 1500 stderr=>1; 1501 $out =~ s/ *SEQ = .*\n//; 1502 $out =~ s/0x[0-9a-f]{2,}\]/${1}0xNNN]/g; 1503 $out =~ s/\(0x[0-9a-f]{3,}\)/(0xNNN)/g; 1504 is $out, $e, "DumpProg() has no 'Attempt to free X prematurely' warning"; 1505} 1506done_testing(); 1507