1#!./perl -w 2 3# 4# Tests derived from Japhs. 5# 6# These test use obscure features of Perl, or surprising combinations 7# of features. The tests were added because in the past, they have 8# exposed several bugs in Perl. 9# 10# Some of these tests may actually (mis)use bugs or use undefined behaviour. 11# These tests are still useful - behavioural changes or bugfixes will be 12# noted, and a remark can be put in the documentation. (Don't forget to 13# disable the test!) 14# 15# Getting everything to run well on the myriad of platforms Perl runs on 16# is unfortunately not a trivial task. 17# 18# WARNING: these tests are obfuscated. Do not get frustrated. 19# Ask Abigail <abigail@abigail.be>, or use the Deparse or Concise 20# modules (the former parses Perl to Perl, the latter shows the 21# op syntax tree) like this: 22# ./perl -Ilib -MO=Deparse foo.pl 23# ./perl -Ilib -MO=Concise foo.pl 24# 25 26BEGIN { 27 if (ord("A") == 193) { 28 print "1..0 # Skip: EBCDIC\n"; # For now, until someone has time. 29 exit(0); 30 } 31 chdir 't' if -d 't'; 32 @INC = '../lib'; 33 require "./test.pl"; 34 undef &skip; 35} 36 37# 38# ./test.pl does real evilness by jumping to a label. 39# This function copies the skip from ./test, omitting the goto. 40# 41sub skip { 42 my $why = shift; 43 my $n = @_ ? shift : 1; 44 for (1..$n) { 45 my $test = curr_test; 46 print STDOUT "ok $test # skip: $why\n"; 47 next_test; 48 } 49} 50 51 52# 53# ./test.pl doesn't give use 'notok', so we make it here. 54# 55sub notok { 56 my ($pass, $name, @mess) = @_; 57 _ok(!$pass, _where(), $name, @mess); 58} 59 60my $JaPH = "Just another Perl Hacker"; 61my $JaPh = "Just another Perl hacker"; 62my $JaPH_n = "Just another Perl Hacker\n"; 63my $JaPh_n = "Just another Perl hacker\n"; 64my $JaPH_s = "Just another Perl Hacker "; 65my $JaPh_s = "Just another Perl hacker "; 66my $JaPH_c = "Just another Perl Hacker,"; 67my $JaPh_c = "Just another Perl hacker,"; 68 69plan tests => 130; 70 71{ 72 my $out = sprintf "Just another Perl Hacker"; 73 is ($out, $JaPH); 74} 75 76 77{ 78 my @primes = (2, 3, 7, 13, 53, 101, 557, 1429); 79 my @composites = (4, 10, 25, 32, 75, 143, 1333, 1728); 80 81 my %primeness = ((map {$_ => 1} @primes), 82 (map {$_ => 0} @composites)); 83 84 while (my ($num, $is_prime) = each %primeness) { 85 my $comment = "$num is " . ($is_prime ? "prime." : "composite."); 86 87 my $sub = $is_prime ? "ok" : "notok"; 88 89 &$sub (( 1 x $num) !~ /^1?$|^(11+?)\1+$/, $comment); 90 &$sub (( 0 x $num) !~ m 0^\0?$|^(\0\0+?)\1+$0, $comment); 91 &$sub (("m" x $num) !~ m m^\m?$|^(\m\m+?)\1+$mm, $comment); 92 } 93} 94 95 96{ # Some platforms use different quoting techniques. 97 # I do not have access to those platforms to test 98 # things out. So, we'll skip things.... 99 if ($^O eq 'MSWin32' || 100 $^O eq 'NetWare' || 101 $^O eq 'VMS') { 102 skip "Your platform quotes differently.", 3; 103 last; 104 } 105 106 my $expected = $JaPH; 107 $expected =~ s/ /\n/g; 108 $expected .= "\n"; 109 is (runperl (switches => [qw /'-weprint<<EOT;' -eJust -eanother 110 -ePerl -eHacker -eEOT/], 111 verbose => 0), 112 $expected, "Multiple -e switches"); 113 114 is (runperl (switches => [q !'-wle$_=<<EOT;y/\n/ /;print;'!, 115 qw ! -eJust -eanother -ePerl -eHacker -eEOT!], 116 verbose => 0), 117 $JaPH . " \n", "Multiple -e switches"); 118 119 is (runperl (switches => [qw !-wl!], 120 progs => [qw !print qq-@{[ qw+ Just 121 another Perl Hacker +]}-!], 122 verbose => 0), 123 $JaPH_n, "Multiple -e switches"); 124} 125 126{ 127 if ($^O eq 'MSWin32' || 128 $^O eq 'NetWare' || 129 $^O eq 'VMS') { 130 skip "Your platform quotes differently.", 1; 131 last; 132 } 133 is (runperl (switches => [qw /-sweprint --/, 134 "-_='Just another Perl Hacker'"], 135 nolib => 1, 136 verbose => 0), 137 $JaPH, 'setting $_ via -s'); 138} 139 140{ 141 my $datafile = "datatmp000"; 142 1 while -f ++ $datafile; 143 END {unlink_all $datafile if $datafile} 144 145 open MY_DATA, "> $datafile" or die "Failed to open $datafile: $!"; 146 print MY_DATA << " --"; 147 One 148 Two 149 Three 150 Four 151 Five 152 Six 153 -- 154 close MY_DATA or die "Failed to close $datafile: $!\n"; 155 156 my @progs; 157 my $key; 158 while (<DATA>) { 159 last if /^__END__$/; 160 161 if (/^#{7}(?:\s+(.*))?/) { 162 push @progs => {COMMENT => $1 || '', 163 CODE => '', 164 SKIP_OS => [], 165 ARGS => [], 166 SWITCHES => [],}; 167 $key = 'CODE'; 168 next; 169 } 170 elsif (/^(COMMENT|CODE|ARGS|SWITCHES|EXPECT|SKIP|SKIP_OS) 171 (?::\s+(.*))?$/sx) { 172 $key = $1; 173 $progs [-1] {$key} = '' unless exists $progs [-1] {$key}; 174 next unless defined $2; 175 $_ = $2; 176 } 177 elsif (/^$/) { 178 next; 179 } 180 181 if (ref ($progs [-1] {$key})) { 182 push @{$progs [-1] {$key}} => $_; 183 } 184 else { 185 $progs [-1] {$key} .= $_; 186 } 187 } 188 189 foreach my $program (@progs) { 190 if (exists $program -> {SKIP}) { 191 chomp $program -> {SKIP}; 192 skip $program -> {SKIP}, 1; 193 next; 194 } 195 196 chomp @{$program -> {SKIP_OS}}; 197 if (@{$program -> {SKIP_OS}}) { 198 if (grep {$^O eq $_} @{$program -> {SKIP_OS}}) { 199 skip "Your OS uses different quoting.", 1; 200 next; 201 } 202 } 203 204 map {s/\$datafile/$datafile/} @{$program -> {ARGS}}; 205 $program -> {EXPECT} = $JaPH unless exists $program -> {EXPECT}; 206 $program -> {EXPECT} =~ s/\$JaPH_s\b/$JaPH_s/g; 207 $program -> {EXPECT} =~ s/\$JaPh_c\b/$JaPh_c/g; 208 $program -> {EXPECT} =~ s/\$JaPh\b/$JaPh/g; 209 chomp ($program -> {EXPECT}, @{$program -> {SWITCHES}}, 210 @{$program -> {ARGS}}); 211 fresh_perl_is ($program -> {CODE}, 212 $program -> {EXPECT}, 213 {switches => $program -> {SWITCHES}, 214 args => $program -> {ARGS}, 215 verbose => 0}, 216 $program -> {COMMENT}); 217 } 218} 219 220{ 221 my $progfile = "progtmp000"; 222 1 while -f ++ $progfile; 223 END {unlink_all $progfile if $progfile} 224 225 my @programs = (<< ' --', << ' --'); 226#!./perl 227BEGIN{$|=$SIG{__WARN__}=sub{$_=$_[0];y-_- -;print/(.)"$/;seek _,-open(_ 228,"+<$0"),2;truncate _,tell _;close _;exec$0}}//rekcaH_lreP_rehtona_tsuJ 229 -- 230#!./perl 231BEGIN{$SIG{__WARN__}=sub{$_=pop;y-_- -;print/".*(.)"/; 232truncate$0,-1+-s$0;exec$0;}}//rekcaH_lreP_rehtona_tsuJ 233 -- 234 chomp @programs; 235 236 if ($^O eq 'VMS' or $^O eq 'MSWin32') { 237 # VMS needs extensions for files to be executable, 238 # but the Japhs above rely on $0 being exactly the 239 # filename of the program. 240 skip $^O, 2 * @programs; 241 last 242 } 243 244 use Config; 245 unless (defined $Config {useperlio}) { 246 skip "Uuseperlio", 2 * @programs; 247 last 248 } 249 250 my $i = 1; 251 foreach my $program (@programs) { 252 open my $fh => "> $progfile" or die "Failed to open $progfile: $!\n"; 253 print $fh $program; 254 close $fh or die "Failed to close $progfile: $!\n"; 255 256 chmod 0755 => $progfile or die "Failed to chmod $progfile: $!\n"; 257 my $command = "./$progfile 2>&1"; 258 if ( $^O eq 'qnx' ) { 259 skip "#!./perl not supported in QNX4"; 260 skip "#!./perl not supported in QNX4"; 261 } else { 262 my $output = `$command`; 263 264 is ($output, $JaPH, "Self correcting code $i"); 265 266 $output = `$command`; 267 is ($output, "", "Self corrected code $i"); 268 } 269 $i ++; 270 } 271} 272 273__END__ 274####### Funky loop 1. 275$_ = q ;4a75737420616e6f74686572205065726c204861636b65720as;; 276 for (s;s;s;s;s;s;s;s;s;s;s;s) 277 {s;(..)s?;qq qprint chr 0x$1 and \161 ssq;excess;} 278 279####### Funky loop 2. 280$_ = q *4a75737420616e6f74686572205065726c204861636b65720a*; 281for ($*=******;$**=******;$**=******) {$**=*******s*..*qq} 282print chr 0x$& and q 283qq}*excess********} 284SKIP: $* was removed. 285 286####### Funky loop 3. 287$_ = q *4a75737420616e6f74686572205065726c204861636b65720a*; 288for ($*=******;$**=******;$**=******) {$**=*******s*..*qq} 289print chr 0x$& and q 290qq}*excess********} 291SKIP: $* was removed. 292 293####### Funky loop 4. 294$_ = q ?4a75737420616e6f74686572205065726c204861636b65720as?;??; 295for (??;(??)x??;??) 296 {??;s;(..)s?;qq ?print chr 0x$1 and \161 ss?;excess;??} 297SKIP: Abuses a fixed bug. 298 299####### Funky loop 5. 300for (s??4a75737420616e6f74686572205065726c204861636b65720as?;??;??) 301 {s?(..)s\??qq \?print chr 0x$1 and q ss\??excess} 302SKIP: Abuses a fixed bug. 303 304####### Funky loop 6. 305$a = q 94a75737420616e6f74686572205065726c204861636b65720a9 and 306${qq$\x5F$} = q 97265646f9 and s g..g; 307qq e\x63\x68\x72\x20\x30\x78$&eggee; 308{eval if $a =~ s e..eqq qprint chr 0x$& and \x71\x20\x71\x71qeexcess} 309 310####### Roman Dates. 311@r=reverse(M=>(0)x99=>CM=>(0)x399=>D=>(0)x99=>CD=>( 3120)x299=>C=>(0)x9=>XC=>(0)x39=>L=>(0)x9=>XL=>(0)x29=>X=>IX=>0=>0=>0=>V=>IV=>0=>0 313=>I=>$==-2449231+gm_julian_day+time);do{until($=<$#r){$_.=$r[$#r];$=-=$#r}for(; 314!$r[--$#r];){}}while$=;$,="\x20";print+$_=>September=>MCMXCIII=>=>=>=>=>=>=>=> 315SWITCHES 316-MTimes::JulianDay 317-l 318SKIP: Times::JulianDay not part of the main distribution. 319 320####### Autoload 1. 321sub _'_{$_'_=~s/$a/$_/}map{$$_=$Z++}Y,a..z,A..X;*{($_::_=sprintf+q=%X==>"$A$Y". 322"$b$r$T$u")=~s~0~O~g;map+_::_,U=>T=>L=>$Z;$_::_}=*_;sub _{print+/.*::(.*)/s};;; 323*{chr($b*$e)}=*_'_;*__=*{chr(1<<$e)}; # Perl 5.6.0 broke this... 324_::_(r(e(k(c(a(H(__(l(r(e(P(__(r(e(h(t(o(n(a(__(t(us(J()))))))))))))))))))))))) 325EXPECT: Just__another__Perl__Hacker 326 327####### Autoload 2. 328$"=$,;*{;qq{@{[(A..Z)[qq[0020191411140003]=~m[..]g]]}}}=*_=sub{print/::(.*)/}; 329$\=$/;q<Just another Perl Hacker>->(); 330 331####### Autoload 3. 332$"=$,;*{;qq{@{[(A..Z)[qq[0020191411140003]=~m[..]g]]}}}=*_; 333sub _ {push @_ => /::(.*)/s and goto &{ shift}} 334sub shift {print shift; @_ and goto &{+shift}} 335Hack ("Just", "Perl ", " ano", "er\n", "ther "); # YYYYMMDD 336 337####### Autoload 4. 338$, = " "; sub AUTOLOAD {($AUTOLOAD =~ /::(.*)/) [0];} 339print+Just (), another (), Perl (), Hacker (); 340 341####### Look ma! No letters! 342$@="\145\143\150\157\040\042\112\165\163\164\040\141\156\157\164". 343 "\150\145\162\040\120\145\162\154\040\110\141\143\153\145\162". 344 "\042\040\076\040\057\144\145\166\057\164\164\171";`$@` 345SKIP: Unix specific 346 347####### sprintf fun 1. 348sub f{sprintf$_[0],$_[1],$_[2]}print f('%c%s',74,f('%c%s',117,f('%c%s',115,f( 349'%c%s',116,f('%c%s',32,f('%c%s',97,f('%c%s',0x6e,f('%c%s',111,f('%c%s',116,f( 350'%c%s',104,f('%c%s',0x65,f('%c%s',114,f('%c%s',32,f('%c%s',80,f('%c%s',101,f( 351'%c%s',114,f('%c%s',0x6c,f('%c%s',32,f('%c%s',0x48,f('%c%s',97,f('%c%s',99,f( 352'%c%s',107,f('%c%s',101,f('%c%s',114,f('%c%s',10,))))))))))))))))))))))))) 353 354####### sprintf fun 2. 355sub f{sprintf'%c%s',$_[0],$_[1]}print f(74,f(117,f(115,f(116,f(32,f(97, 356f(110,f(111,f(116,f(104,f(0x65,f(114,f(32,f(80,f(101,f(114,f(0x6c,f(32, 357f(0x48,f(97,f(99,f(107,f(101,f(114,f(10,q ff))))))))))))))))))))))))) 358 359####### Hanoi. 360%0=map{local$_=$_;reverse+chop,$_}ABC,ACB,BAC,BCA,CAB,CBA;$_=3 .AC;1while+ 361s/(\d+)((.)(.))/($0=$1-1)?"$0$3$0{$2}1$2$0$0{$2}$4":"$3 => $4\n"/xeg;print 362EXPECT 363A => C 364A => B 365C => B 366A => C 367B => A 368B => C 369A => C 370 371####### Funky -p 1 372}{$_=$. 373SWITCHES: -wlp 374ARGS: $datafile 375EXPECT: 6 376 377####### Funky -p 2 378}$_=$.;{ 379SWITCHES: -wlp 380ARGS: $datafile 381EXPECT: 6 382 383####### Funky -p 3 384}{$_=$.}{ 385SWITCHES: -wlp 386ARGS: $datafile 387EXPECT: 6 388 389####### Funky -p 4 390}{*_=*.}{ 391SWITCHES: -wlp 392ARGS: $datafile 393EXPECT: 6 394 395####### Funky -p 5 396}for($.){print 397SWITCHES: -wln 398ARGS: $datafile 399EXPECT: 6 400 401####### Funky -p 6 402}{print$. 403SWITCHES: -wln 404ARGS: $datafile 405EXPECT: 6 406 407####### Funky -p 7 408}print$.;{ 409SWITCHES: -wln 410ARGS: $datafile 411EXPECT: 6 412 413####### Abusing -M 4141 415SWITCHES 416-Mstrict='}); print "Just another Perl Hacker"; ({' 417-l 418SKIP: No longer works in 5.8.2 and beyond. 419SKIP_OS: MSWin32 420SKIP_OS: NetWare 421 422####### rand 423srand 123456;$-=rand$_--=>@[[$-,$_]=@[[$_,$-]for(reverse+1..(@[=split 424//=>"IGrACVGQ\x02GJCWVhP\x02PL\x02jNMP"));print+(map{$_^q^"^}@[),"\n" 425SKIP: Solaris specific. 426 427####### print and __PACKAGE__ 428package Just_another_Perl_Hacker; sub print {($_=$_[0])=~ s/_/ /g; 429 print } sub __PACKAGE__ { & 430 print ( __PACKAGE__)} & 431 __PACKAGE__ 432 ( ) 433 434####### Decorations. 435* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 436/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / 437% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %; 438BEGIN {% % = ($ _ = " " => print "Just another Perl Hacker\n")} 439 440####### Tie 1 441sub J::FETCH{Just }$_.='print+"@{[map';sub J::TIESCALAR{bless\my$J,J} 442sub A::FETCH{another}$_.='{tie my($x),$';sub A::TIESCALAR{bless\my$A,A} 443sub P::FETCH{Perl }$_.='_;$x}qw/J A P';sub P::TIESCALAR{bless\my$P,P} 444sub H::FETCH{Hacker }$_.=' H/]}\n"';eval;sub H::TIESCALAR{bless\my$H,H} 445 446####### Tie 2 447package Z;use overload'""'=>sub{$b++?Hacker:another}; 448sub TIESCALAR{bless\my$y=>Z}sub FETCH{$a++?Perl:Just} 449$,=$";my$x=tie+my$y=>Z;print$y,$x,$y,$x,"\n";#Abigail 450EXPECT: $JaPH_s 451 452####### Tie 3 453sub A::TIESCALAR{bless\my$x=>A};package B;@q[0..3]=qw/Hacker Perl 454another Just/;use overload'""'=>sub{pop @q};sub A::FETCH{bless\my 455$y=>B}; tie my $shoe => qq 'A';print "$shoe $shoe $shoe $shoe\n"; 456 457####### Tie 4 458sub A::TIESCALAR{bless\my$x=>'A'};package B;@q=qw/Hacker Perl 459another Just/;use overload'""',sub{pop @q};sub A::FETCH{bless 460\my $y=>B};tie my$shoe=>'A';print"$shoe $shoe $shoe $shoe\n"; 461 462####### Tie 5 463tie $" => A; $, = " "; $\ = "\n"; @a = ("") x 2; print map {"@a"} 1 .. 4; 464sub A::TIESCALAR {bless \my $A => A} # Yet Another silly JAPH by Abigail 465sub A::FETCH {@q = qw /Just Another Perl Hacker/ unless @q; shift @q} 466SKIP: Pending a bug fix. 467 468####### Prototype fun 1 469sub camel (^#87=i@J&&&#]u'^^s]#'#={123{#}7890t[0.9]9@+*`"'***}A&&&}n2o}00}t324i; 470h[{e **###{r{+P={**{e^^^#'#i@{r'^=^{l+{#}H***i[0.9]&@a5`"':&^;&^,*&^$43##@@####; 471c}^^^&&&k}&&&}#=e*****[]}'r####'`=437*{#};::'1[0.9]2@43`"'*#==[[.{{],,,1278@#@); 472print+((($llama=prototype'camel')=~y|+{#}$=^*&[0-9]i@:;`"',.| |d)&&$llama."\n"); 473SKIP: Abuses a fixed bug. 474 475####### Prototype fun 2 476print prototype sub "Just another Perl Hacker" {}; 477SKIP: Abuses a fixed bug. 478 479####### Prototype fun 3 480sub _ "Just another Perl Hacker"; print prototype \&_ 481SKIP: Abuses a fixed bug. 482 483####### Split 1 484 split // => '"'; 485${"@_"} = "/"; split // => eval join "+" => 1 .. 7; 486*{"@_"} = sub {foreach (sort keys %_) {print "$_ $_{$_} "}}; 487%{"@_"} = %_ = (Just => another => Perl => Hacker); &{%{%_}}; 488SKIP: Hashes are now randomized. 489EXPECT: $JaPH_s 490 491####### Split 2 492$" = "/"; split // => eval join "+" => 1 .. 7; 493*{"@_"} = sub {foreach (sort keys %_) {print "$_ $_{$_} "}}; 494%_ = (Just => another => Perl => Hacker); &{%_}; 495SKIP: Hashes are now randomized. 496EXPECT: $JaPH_s 497 498####### Split 3 499$" = "/"; split $, => eval join "+" => 1 .. 7; 500*{"@_"} = sub {foreach (sort keys %_) {print "$_ $_{$_} "}}; 501%{"@_"} = %_ = (Just => another => Perl => Hacker); &{%{%_}}; 502SKIP: Hashes are now randomized. 503EXPECT: $JaPH_s 504 505####### Here documents 1 506$_ = "\x3C\x3C\x45\x4F\x54"; s/<<EOT/<<EOT/e; print; 507Just another Perl Hacker 508EOT 509 510####### Here documents 2 511$_ = "\x3C\x3C\x45\x4F\x54"; 512print if s/<<EOT/<<EOT/e; 513Just another Perl Hacker 514EOT 515 516####### Here documents 3 517$_ = "\x3C\x3C\x45\x4F\x54" and s/<<EOT/<<EOT/e and print; 518Just another Perl Hacker 519EOT 520 521####### Here documents 4 522$_ = "\x3C\x3C\x45\x4F\x54\n" and s/<<EOT/<<EOT/ee and print; 523"Just another Perl Hacker" 524EOT 525 526####### Self modifying code 1 527$_ = "goto F.print chop;\n=rekcaH lreP rehtona tsuJ";F1:eval 528SWITCHES: -w 529 530####### Overloaded constants 1 531BEGIN {$^H {q} = sub {pop and pop and print pop}; $^H = 2**4.2**12} 532"Just "; "another "; "Perl "; "Hacker"; 533SKIP_OS: qnx 534 535####### Overloaded constants 2 536BEGIN {$^H {q} = sub {$_ [1] =~ y/S-ZA-IK-O/q-tc-fe-m/d; $_ [1]}; $^H = 0x28100} 537print "Just another PYTHON hacker\n"; 538EXPECT: $JaPh 539 540####### Overloaded constants 3 541BEGIN {$^H {join "" => ("a" .. "z") [8, 13, 19, 4, 6, 4, 17]} = sub 542 {["", "Just ", "another ", "Perl ", "Hacker\n"] -> [shift]}; 543 $^H = hex join "" => reverse map {int ($_ / 2)} 0 .. 4} 544print 1, 2, 3, 4; 545 546####### Overloaded constants 4 547BEGIN {$^H {join "" => ("a" .. "z") [8, 13, 19, 4, 6, 4, 17]} = sub 548 {["", "Just ", "another ", "Perl ", "Hacker"] -> [shift]}; 549 $^H = hex join "" => reverse map {int ($_ / 2)} 0 .. 4} 550print 1, 2, 3, 4, "\n"; 551 552####### Overloaded constants 5 553BEGIN {my $x = "Knuth heals rare project\n"; 554 $^H {integer} = sub {my $y = shift; $_ = substr $x => $y & 0x1F, 1; 555 $y > 32 ? uc : lc}; $^H = hex join "" => 2, 1, 1, 0, 0} 556print 52,2,10,23,16,8,1,19,3,6,15,12,5,49,21,14,9,11,36,13,22,32,7,18,24; 557 558####### v-strings 1 559print v74.117.115.116.32; 560print v97.110.111.116.104.101.114.32; 561print v80.101.114.108.32; 562print v72.97.99.107.101.114.10; 563 564####### v-strings 2 565print 74.117.115.116.32; 566print 97.110.111.116.104.101.114.32; 567print 80.101.114.108.32; 568print 72.97.99.107.101.114.10; 569 570####### v-strings 3 571print v74.117.115.116.32, v97.110.111.116.104.101.114.32, 572 v80.101.114.108.32, v72.97.99.107.101.114.10; 573 574####### v-strings 4 575print 74.117.115.116.32, 97.110.111.116.104.101.114.32, 576 80.101.114.108.32, 72.97.99.107.101.114.10; 577 578####### v-strings 5 579print v74.117.115.116.32.97.110.111.116.104.101.114. 580 v32.80.101.114.108.32.72.97.99.107.101.114.10; 581 582####### v-strings 6 583print 74.117.115.116.32.97.110.111.116.104.101.114. 584 32.80.101.114.108.32.72.97.99.107.101.114.10; 585 586####### Symbolic references. 587map{${+chr}=chr}map{$_=>$_^ord$"}$=+$]..3*$=/2; 588print "$J$u$s$t $a$n$o$t$h$e$r $P$e$r$l $H$a$c$k$e$r\n"; 589 590####### $; fun 591$; # A lone dollar? 592=$"; # Pod? 593$; # The return of the lone dollar? 594{Just=>another=>Perl=>Hacker=>} # Bare block? 595=$/; # More pod? 596print%; # No right operand for %? 597 598####### @; fun 599@;=split//=>"Joel, Preach sartre knuth\n";$;=chr 65;%;=map{$;++=>$_} 6000,22,13,16,5,14,21,1,23,11,2,7,12,6,8,15,3,19,24,14,10,20,18,17,4,25 601;print@;[@;{A..Z}]; 602EXPECT: $JaPh_c 603 604####### %; fun 605$;=$";$;{Just=>another=>Perl=>Hacker=>}=$/;print%; 606 607####### &func; 608$_ = "\112\165\163\1648\141\156\157\164\150\145\1628\120\145" 609 . "\162\1548\110\141\143\153\145\162\0128\177" and &japh; 610sub japh {print "@_" and return if pop; split /\d/ and &japh} 611SKIP: As of 5.12.0, split() in void context no longer populates @_. 612 613####### magic goto. 614sub _ {$_ = shift and y/b-yB-Y/a-yB-Y/ xor !@ _? 615 exit print : 616 print and push @_ => shift and goto &{(caller (0)) [3]}} 617 split // => "KsvQtbuf fbsodpmu\ni flsI " xor & _ 618SKIP: As of 5.12.0, split() in void context no longer populates @_. 619 620####### $: fun 1 621:$:=~s:$":Just$&another$&:;$:=~s: 622:Perl$"Hacker$&:;chop$:;print$:#: 623 624####### $: fun 2 625 :;$:=~s: 626-:;another Perl Hacker 627 :;chop 628$:;$:=~y 629 :;::d;print+Just. 630$:; 631 632####### $: fun 3 633 :;$:=~s: 634-:;another Perl Hacker 635 :;chop 636$:;$:=~y:;::d;print+Just.$: 637 638####### $! 639s[$,][join$,,(split$,,($!=85))[(q[0006143730380126152532042307]. 640q[41342211132019313505])=~m[..]g]]e and y[yIbp][HJkP] and print; 641SKIP: Platform dependent. 642 643####### die 1 644eval {die ["Just another Perl Hacker"]}; print ${$@}[$#{@${@}}] 645 646####### die 2 647eval {die ["Just another Perl Hacker\n"]}; print ${$@}[$#{@${@}}] 648 649####### die 3 650eval {die ["Just another Perl Hacker"]}; print ${${@}}[$#{@{${@}}}] 651 652####### die 4 653eval {die ["Just another Perl Hacker\n"]}; print ${${@}}[$#{@{${@}}}] 654 655####### die 5 656eval {die [[qq [Just another Perl Hacker]]]};; print 657${${${@}}[$#{@{${@}}}]}[$#{${@{${@}}}[$#{@{${@}}}]}] 658SKIP: Abuses a fixed bug; what is in $#{...} must be an arrayref, not an array 659 660####### Closure returning itself. 661$_ = "\nrekcaH lreP rehtona tsuJ"; my $chop; $chop = sub {print chop; $chop}; 662$chop -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () 663-> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () 664 665####### Special blocks 1 666BEGIN {print "Just " } 667CHECK {print "another "} 668INIT {print "Perl " } 669END {print "Hacker\n"} 670 671####### Special blocks 2 672END {print "Hacker\n"} 673INIT {print "Perl " } 674CHECK {print "another "} 675BEGIN {print "Just " } 676 677####### Recursive regex. 678 my $qr = qr/^.+?(;).+?\1|;Just another Perl Hacker;|;.+$/; 679 $qr =~ s/$qr//g; 680print $qr, "\n"; 681 682####### use lib 'coderef' 683use lib sub {($\) = split /\./ => pop; print $"}; 684eval "use Just" || eval "use another" || eval "use Perl" || eval "use Hacker"; 685EXPECT 686 Just another Perl Hacker 687