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