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