0
Perl Sucks!
(and what to do about it)
What this talk is not
• “Wah, no one uses ‘use strict’”
• “People’s perception of Perl is wrong”
• “The CPAN/mailing list/...
What this talk is


• What’s a few major annoyances with Perl
• What we the humble programmer can do to
  work around them
~/bin
scp ~/bin nethost:
ssh newhost
jabme -m ‘compile done’
Module “Jabber::Lite”
    not found
-bash: jabme: /usr/local/bin/
 perl: bad interpreter: No
   such file or directory
My Scripts Need


• A particular version of Perl
• A set of Perl modules
PAR
#!/usr/bin/perl

use strict;
use warnings;

use XML::LibXML;
use Template;
use DBD::SQLite;
use CGI;
use Parse::RecDescent...
Make an executable

• perl -MCPAN -e ‘install PAR::Packer’
• pp -o hellow hellow.pl
• ...copy “hellow” to new computer
• ....
#!/usr/bin/perl

use strict;
use warnings;

print quot;Hello Worldnquot;;
Build our own Perl and
 ship the whole thing
Get Stable Perl

• lwp-request $CPAN_URL >
  perl-5.8.8.tar.gz
• gunzip -c perl-5.8.8.tar.gz | tar -xvf -
• cd perl-5.8.8
Tell it where to go


• mkdir -p /User/mark/bin/perl5.8.8
• ./configure.gnu --prefix=/User/mark/bin/
  perl5.8.8
Install it

• make
• make test
• make install
We now have our own
    perl in ~/bin
We can install it’s own
     modules
~/bin/perl5.8.8/bin/perl
  -MCPAN -e ‘install
       Template’
Problem: different paths

• /home/mark/bin/myperl
• /home/mfowler/bin/myperl
• /home/nisuser/bin/myperl
mv ~/bin/perl5.8.8
    whatever
whatever/bin/perl -e
  ‘use Storable’
Can't locate Storable.pm in @INC (@INC
  contains: /User/mark/bin/perl5.8.8/lib/5.8.8/
   darwin-2level /User/mark/bin/per...
Can't locate Storable.pm in @INC (@INC
  contains: /User/mark/bin/perl5.8.8/lib/5.8.8/
   darwin-2level /User/mark/bin/per...
Can't locate Storable.pm in @INC (@INC
    contains: ../lib/5.8.8/darwin-2level
                       ../lib/5.8.8
     ....
bleed to the rescue
B
                                              E
                                                 TA
        Get Bleed Pe...
B
                                               E
                                                  TA
   Tell it where t...
B
                                               E
                                                  TA
   Tell it where t...
B
                               E
                                  TA
                 Install it

• make
• make test
• ...
B
                      E
                         TA




mv ~/bin/perl5.9.5
    whatever
B
                          E
                             TA




whatever/bin/perl5.9.5
  -e ‘use Storable’
Exception Handling
Java
try {
  throw new NoCheeseException(“redo”);
} catch (NoCheeseException e) {
  system.err.println(e.toString());
}
Perl
eval {
  die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
  $@->isa(“NoCheeseException”)) {
  print STDERR $...
Perl has SUCKY
   SYNTAX
Sins include:
Perl
eval {
  die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
  $@->isa(“NoCheeseException”)) {
  print STDERR $...
die “stop my program”;
die “some catchable exception”;
Perl
eval {
  die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
  $@->isa(“NoCheeseException”)) {
  print STDERR $...
eval “some code to be compiled”;
eval {
  # run some code to catch errors in
};
Perl
eval {
  die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
  $@->isa(“NoCheeseException”)) {
  print STDERR $...
Perl
eval {
  die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
  $@->isa(“NoCheeseException”)) {
  print STDERR $...
We can fix it!
(still) Perl
try {
  throw NoCheeseException “redo”;
}
catch NoCheeseException with {
   print STDERR $@;
};
try {
  throw NoCheeseException “redo”;
}
catch NoCheeseException with {
   print STDERR $@;
}
catch AnotherError with {
 ...
try {
  throw NoCheeseException “redo”;
}
catch NoCheeseException with {
   print STDERR $@;
}
catch AnotherError with {
 ...
try( sub {
   throw NoCheeseException “redo”;
},
catch NoCheeseException with(sub {
    print STDERR $@;
},
catch AnotherE...
try( sub {
   throw NoCheeseException “redo”;
},
catch NoCheeseException with(sub {
    print STDERR $@;
},
catch AnotherE...
try( sub {
   NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( with(sub {
    print STDERR $@;
},
AnotherE...
sub with (&;@) {
  return @_
}
try( sub {
   NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( with(sub {
    print STDERR $@;
},
AnotherE...
try( sub {
   NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( sub {
    print STDERR $@;
},
AnotherError-...
package OurErrorSuperclass;

sub catch {
  my $class = shift;
  my $action = shift;
  return +{
    class => $class,
    a...
try( sub {
   NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( sub {
    print STDERR $@;
},
AnotherError-...
try( sub {
   NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( sub {
    print STDERR $@;
}, +{
   class =...
try( sub {
  NoCheeseException->throw( “redo” );
}, +{
  class => “NoCheeseException”,
  action => sub { print STDERR $@; ...
try( sub {
  NoCheeseException->throw( “redo” );
}, +{
  class => “NoCheeseException”,
  action => sub { print STDERR $@; ...
try( sub {
  NoCheeseException->throw( “redo” );
}, +{
  class => “NoCheeseException”,
  action => sub { print STDERR $@; ...
try( sub {
  NoCheeseException->throw( “redo” );
}, +{
  class => “NoCheeseException”,
  action => sub { print STDERR $@; ...
(still) Perl
try {
  throw NoCheeseException “redo”;
}
catch NoCheeseException with {
   print STDERR $@;
};
sub foo {
  try {
    return “This doesn’t return from foo”;
  }
  catch NoCheeseException with {
     print STDERR $@;
  ...
sub foo {
  eval {
    return “This doesn’t return from foo”;
  };
  if ($@) { .... }
}
sub foo {
  try {
    return “This doesn’t return from foo”;
  }
  catch NoCheeseException with {
     print STDERR $@;
  ...
sub foo {
  try {
    rreturn “This doesn’t return from foo”;
  }
  catch NoCheeseException with {
     print STDERR $@;
 ...
sub foo {
  try {
    rreturn “This doesn’t return from foo”;
  }
  catch NoCheeseException with {
     print STDERR $@;
 ...
MyException


      NoDairyException
                                            NoSpreadException


 NoMilkException
    ...
package NoDairyException;
our @ISA = qw(MyError);

package NoMilkException;
our @ISA = qw(NoDairyException);

package NoSp...
Exceptions::define {
  exception NoDairyException;
  exception NoSpreadException extends NoDairyException;
  exception NoBu...
But it’s a scripting
    language!
Don’t you just love the
  Template Toolkit?
bash$ tpage
[% FOR a = [1..5]; a; END %]
^D
12345
bash$
#!perl

$whereami = “Vienna”;
print “Hello $whereami!n”;
#!tpage

[% whereami = “Vienna” -%]
Hello [% whereami %]!
bash$ ./hellov.tp
bash$ ./hellov.tp
-bash: ./hellov.tp: tpage: bad interpreter:
No such file or directory
where bash finds the
          Executable code to
#!tpage    load into memory


[% whereami = “Vienna” -%]
Hello [% wheream...
bash$ cat tpage
#!/usr/bin/perl -w
use strict;
use Template;
use AppConfig;
…
Two possible solutions
Method one:
Abuse source filters
• “Source filters are a way to change your
  source code before perl gets to see it”
#!/usr/bin/perl

use strict;
use warnings;

use EnableDebugging;

# DEBUG printing stuff out
print quot;hinquot;;
#!/usr/bin/perl

use strict;
use warnings;

use EnableDebugging;

;print STDERR “DEBUG: printing stuff outn”;
print quot;h...
package EnableDebugging;
use Filter::Simple;

FILTER {
  s{#s*DEBUGs+(.*)}
    {;print STDERR q<DEBUG: $1>, quot;nquot;;};...
package EnableDebugging;
use Filter::Simple;

FILTER {
  s{#s*DEBUGs+(.*)}
    {;print STDERR q<DEBUG: $1>, quot;nquot;;};...
package tpage;
use Filter::Simple;

FILTER {
  s{#s*DEBUGs+(.*)}
    {;print STDERR q<DEBUG: $1>, quot;nquot;;};
};

1;
package tpage;
use Filter::Simple;

FILTER {
  s{#s*DEBUGs+(.*)}
    {;print STDERR q<DEBUG: $1>, quot;nquot;;};
};

1;
package tpage;
use Filter::Simple;

FILTER {
   $template .= $_;
   $_ = “”;
};

1;
package tpage;
use Filter::Simple;

FILTER {
   $template .= $_;
   $_ = “”;
};

END {
  use Template;
  Template->new->pr...
#!/usr/bin/perl
use tpage;

[%- whereami = “Vienna” -%]
Hello [% whereami %]!
2. Build our own
   executable
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

int main(int argc, char **argv, char **env)
{
  c...
(    stolen from
“perldoc perlembed”)
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

int main(int argc, char **argv, char **env)
{
  c...
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

int main(int argc, char **argv, char **env)
{
  c...
cc -o hellow hellow.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
bash$ ./hellow
    o hai
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

int main(int argc, char **argv, char **env)
{
  c...
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

int main(int argc, char **argv, char **env)
{
  c...
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

int main(int argc, char **argv, char **env)
{
  c...
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

int main(int argc, char **argv, char **env)
{
  c...
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

int main(int argc, char **argv, char **env)
{
  c...
cc -o mytt mytt.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
now Executable code to
            load into memory
#!mytt

[% whereami = “Vienna” -%]
Hello [% whereami %]!
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

                                                 ...
#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

                                                 ...
A
                      LP
                           H
                            A




We’ve already seen
  source filters
B
                                                E
                                                   TA
                ...
A
       LP
            H
             A




MAD
A
                                        LP
                                             H
                              ...
A
                  LP
                       H
                        A




 my $a = 1;
 my $b = 2;
print $a + $b;
A
                                   LP
                                        H
                                        ...
</op_nextstate>
                                                                                                   A
     ...
B::Generate


• Can be used to create OP codes (i.e.
  compiled Perl code) directly from Perl
use B::Generate;
# Do nothing, slowly.
 CHECK {
  my $null = new B::OP(quot;nullquot;,0);
  my $enter = new B::OP(quot;ent...
optomize.pm

• Can be used to manipulate the OP codes
  after they’ve loaded
• Kinda like source filters for compiled
  byp...
Use?
• PPI is reliable, but limited in it’s ability
 • Easy to try to do too much with
• Other techniques are very unstabl...
A
                                                                                 LP
                                    ...
A
                                                                                 LP
                                    ...
A
                                                                                 LP
                                    ...
A
                                                                                 LP
                                    ...
Perl Sucks - and what to do about it
Perl Sucks - and what to do about it
Perl Sucks - and what to do about it
Perl Sucks - and what to do about it
Perl Sucks - and what to do about it
Perl Sucks - and what to do about it
Upcoming SlideShare
Loading in...5
×

Perl Sucks - and what to do about it

22,783

Published on

(originally presented at YAPC::Europe::2007)

No-one is as critical about something as those that love it dearly. Mark Fowler has been collecting complaints from professional Perl developers for years about what warts still remain with the language when strict and warnings are turned on.

Are these problems unsolvable? A veteran Perl programmer himself Mark attempted to try and solve these issues - and then turned to the experts, the people who write books on Perl, the people who maintain the perl interpreter itself, for help.

This is what he learned...

Published in: Technology, Business
7 Comments
15 Likes
Statistics
Notes
  • It looks like trying to bend Perl into being Lisp.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Error.pm indeed can be used for exceptions, and I did mention it in the talk (just not on the written slides.) You'll note most of my syntax is the same as Error.pm's too.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Error.pm can be used for exceptions.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 'But when it comes time to run one of the commands...'
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 'Normally I can just SCP the files from my home linux box to the new machine'
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
22,783
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
549
Comments
7
Likes
15
Embeds 0
No embeds

No notes for slide

Transcript of "Perl Sucks - and what to do about it"

  1. 1. Perl Sucks! (and what to do about it)
  2. 2. What this talk is not • “Wah, no one uses ‘use strict’” • “People’s perception of Perl is wrong” • “The CPAN/mailing list/a other website isn’t exactly how I like it” • “The garbage collection de-allocation routine isn’t very efficent”
  3. 3. What this talk is • What’s a few major annoyances with Perl • What we the humble programmer can do to work around them
  4. 4. ~/bin
  5. 5. scp ~/bin nethost:
  6. 6. ssh newhost
  7. 7. jabme -m ‘compile done’
  8. 8. Module “Jabber::Lite” not found
  9. 9. -bash: jabme: /usr/local/bin/ perl: bad interpreter: No such file or directory
  10. 10. My Scripts Need • A particular version of Perl • A set of Perl modules
  11. 11. PAR
  12. 12. #!/usr/bin/perl use strict; use warnings; use XML::LibXML; use Template; use DBD::SQLite; use CGI; use Parse::RecDescent; use List::MoreUtils; use Moose; print quot;Hello Worldnquot;;
  13. 13. Make an executable • perl -MCPAN -e ‘install PAR::Packer’ • pp -o hellow hellow.pl • ...copy “hellow” to new computer • ./hellow Hello World
  14. 14. #!/usr/bin/perl use strict; use warnings; print quot;Hello Worldnquot;;
  15. 15. Build our own Perl and ship the whole thing
  16. 16. Get Stable Perl • lwp-request $CPAN_URL > perl-5.8.8.tar.gz • gunzip -c perl-5.8.8.tar.gz | tar -xvf - • cd perl-5.8.8
  17. 17. Tell it where to go • mkdir -p /User/mark/bin/perl5.8.8 • ./configure.gnu --prefix=/User/mark/bin/ perl5.8.8
  18. 18. Install it • make • make test • make install
  19. 19. We now have our own perl in ~/bin
  20. 20. We can install it’s own modules
  21. 21. ~/bin/perl5.8.8/bin/perl -MCPAN -e ‘install Template’
  22. 22. Problem: different paths • /home/mark/bin/myperl • /home/mfowler/bin/myperl • /home/nisuser/bin/myperl
  23. 23. mv ~/bin/perl5.8.8 whatever
  24. 24. whatever/bin/perl -e ‘use Storable’
  25. 25. Can't locate Storable.pm in @INC (@INC contains: /User/mark/bin/perl5.8.8/lib/5.8.8/ darwin-2level /User/mark/bin/perl5.8.8/lib/ 5.8.8 /User/mark/bin/perl5.8.8/lib/site_perl/ 5.8.8/darwin-2level /User/mark/bin/perl5.8.8/lib/ site_perl/5.8.8 /User/mark/bin/perl5.8.8/lib/ site_perl .) at -e line 1.
  26. 26. Can't locate Storable.pm in @INC (@INC contains: /User/mark/bin/perl5.8.8/lib/5.8.8/ darwin-2level /User/mark/bin/perl5.8.8/lib/ 5.8.8 /User/mark/bin/perl5.8.8/lib/site_perl/ 5.8.8/darwin-2level /User/mark/bin/perl5.8.8/lib/ site_perl/5.8.8 /User/mark/bin/perl5.8.8/lib/ site_perl .) at -e line 1.
  27. 27. Can't locate Storable.pm in @INC (@INC contains: ../lib/5.8.8/darwin-2level ../lib/5.8.8 ../lib/site_perl/5.8.8/darwin-2level ../lib/site_perl/5.8.8 ../lib/site_perl .) at -e line 1.
  28. 28. bleed to the rescue
  29. 29. B E TA Get Bleed Perl • lwp-request $CPAN_URL > perl-5.9.5.tar.gz • gunzip -c perl-5.9.5.tar.gz | tar -xvf - • cd perl-5.9.5
  30. 30. B E TA Tell it where to go • mkdir -p /User/mark/bin/perl5.9.5 • ./Configure -Dusedevel -Dprefix=/User/ mark/bin/perl5.9.5 -Duserelocatableinc -d
  31. 31. B E TA Tell it where to go • mkdir -p /User/mark/bin/perl5.9.5 • ./Configure -Dusedevel -Dprefix=/User/ mark/bin/perl5.9.5 -Duserelocatableinc -d
  32. 32. B E TA Install it • make • make test • make install
  33. 33. B E TA mv ~/bin/perl5.9.5 whatever
  34. 34. B E TA whatever/bin/perl5.9.5 -e ‘use Storable’
  35. 35. Exception Handling
  36. 36. Java try { throw new NoCheeseException(“redo”); } catch (NoCheeseException e) { system.err.println(e.toString()); }
  37. 37. Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
  38. 38. Perl has SUCKY SYNTAX
  39. 39. Sins include:
  40. 40. Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
  41. 41. die “stop my program”;
  42. 42. die “some catchable exception”;
  43. 43. Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
  44. 44. eval “some code to be compiled”;
  45. 45. eval { # run some code to catch errors in };
  46. 46. Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
  47. 47. Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
  48. 48. We can fix it!
  49. 49. (still) Perl try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; };
  50. 50. try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; } catch AnotherError with { print STDERR “oopsn”; };
  51. 51. try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; } catch AnotherError with { print STDERR “oopsn”; };
  52. 52. try( sub { throw NoCheeseException “redo”; }, catch NoCheeseException with(sub { print STDERR $@; }, catch AnotherError with(sub { print STDERR “oopsn”; })));
  53. 53. try( sub { throw NoCheeseException “redo”; }, catch NoCheeseException with(sub { print STDERR $@; }, catch AnotherError with(sub { print STDERR “oopsn”; })));
  54. 54. try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( with(sub { print STDERR $@; }, AnotherError->catch( with(sub { print STDERR “oopsn”; })))));
  55. 55. sub with (&;@) { return @_ }
  56. 56. try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( with(sub { print STDERR $@; }, AnotherError->catch( with(sub { print STDERR “oopsn”; })))));
  57. 57. try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( sub { print STDERR $@; }, AnotherError->catch( sub { print STDERR “oopsn”; })));
  58. 58. package OurErrorSuperclass; sub catch { my $class = shift; my $action = shift; return +{ class => $class, action => $action }, @_; }
  59. 59. try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( sub { print STDERR $@; }, AnotherError->catch( sub { print STDERR “oopsn”; })));
  60. 60. try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( sub { print STDERR $@; }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } }));
  61. 61. try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } });
  62. 62. try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } });
  63. 63. try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } });
  64. 64. try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } });
  65. 65. (still) Perl try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; };
  66. 66. sub foo { try { return “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; }; }
  67. 67. sub foo { eval { return “This doesn’t return from foo”; }; if ($@) { .... } }
  68. 68. sub foo { try { return “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; }; }
  69. 69. sub foo { try { rreturn “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; } and return allowed; }
  70. 70. sub foo { try { rreturn “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; } and return allowed; }
  71. 71. MyException NoDairyException NoSpreadException NoMilkException NoButterException NoMargException NoCheeseException NoEdamException NoStiltonException NoBrieException
  72. 72. package NoDairyException; our @ISA = qw(MyError); package NoMilkException; our @ISA = qw(NoDairyException); package NoSpreadException; our @ISA = qw(NoDairyException); package NoButterException; our @ISA = qw(NoSpreadException); package NoMargException; our @ISA = qw(NoMargeException); package NoCheeseException; our @ISA = qw(NoDairyException); package NoEdamException; our @ISA = qw(NoCheeseException); package NoStiltonException; our @ISA = qw(NoCheeseException); package NoBrieException; our@ISA = qw(NoCheeseException);
  73. 73. Exceptions::define { exception NoDairyException; exception NoSpreadException extends NoDairyException; exception NoButterException extends NoSpreadException; exception NoMargException extends NoSpreadException; exception NoMilkException extends NoDairyException; exception NoCheeseException extends NoDairyException; exception NoEdamException extends NoCheeseException; exception NoStiltonException extends NoCheeseException; exception NoBrieException extends NoCheeseException; };
  74. 74. But it’s a scripting language!
  75. 75. Don’t you just love the Template Toolkit?
  76. 76. bash$ tpage [% FOR a = [1..5]; a; END %] ^D 12345 bash$
  77. 77. #!perl $whereami = “Vienna”; print “Hello $whereami!n”;
  78. 78. #!tpage [% whereami = “Vienna” -%] Hello [% whereami %]!
  79. 79. bash$ ./hellov.tp
  80. 80. bash$ ./hellov.tp -bash: ./hellov.tp: tpage: bad interpreter: No such file or directory
  81. 81. where bash finds the Executable code to #!tpage load into memory [% whereami = “Vienna” -%] Hello [% whereami %]!
  82. 82. bash$ cat tpage #!/usr/bin/perl -w use strict; use Template; use AppConfig; …
  83. 83. Two possible solutions
  84. 84. Method one: Abuse source filters
  85. 85. • “Source filters are a way to change your source code before perl gets to see it”
  86. 86. #!/usr/bin/perl use strict; use warnings; use EnableDebugging; # DEBUG printing stuff out print quot;hinquot;;
  87. 87. #!/usr/bin/perl use strict; use warnings; use EnableDebugging; ;print STDERR “DEBUG: printing stuff outn”; print quot;hinquot;;
  88. 88. package EnableDebugging; use Filter::Simple; FILTER { s{#s*DEBUGs+(.*)} {;print STDERR q<DEBUG: $1>, quot;nquot;;}; }; 1;
  89. 89. package EnableDebugging; use Filter::Simple; FILTER { s{#s*DEBUGs+(.*)} {;print STDERR q<DEBUG: $1>, quot;nquot;;}; }; 1;
  90. 90. package tpage; use Filter::Simple; FILTER { s{#s*DEBUGs+(.*)} {;print STDERR q<DEBUG: $1>, quot;nquot;;}; }; 1;
  91. 91. package tpage; use Filter::Simple; FILTER { s{#s*DEBUGs+(.*)} {;print STDERR q<DEBUG: $1>, quot;nquot;;}; }; 1;
  92. 92. package tpage; use Filter::Simple; FILTER { $template .= $_; $_ = “”; }; 1;
  93. 93. package tpage; use Filter::Simple; FILTER { $template .= $_; $_ = “”; }; END { use Template; Template->new->process($template); }
  94. 94. #!/usr/bin/perl use tpage; [%- whereami = “Vienna” -%] Hello [% whereami %]!
  95. 95. 2. Build our own executable
  96. 96. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(quot;print qq'oh hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  97. 97. ( stolen from “perldoc perlembed”)
  98. 98. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(quot;print qq'o hain';quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  99. 99. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(quot;print qq’o hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  100. 100. cc -o hellow hellow.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
  101. 101. bash$ ./hellow o hai
  102. 102. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(quot;print qq'o hain';quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  103. 103. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(quot;print qq’o hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  104. 104. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(quot;print qq’o hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  105. 105. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(quot;print qq’o hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  106. 106. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv( “use Template Template->new->process($ARGV[0])quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  107. 107. cc -o mytt mytt.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
  108. 108. now Executable code to load into memory #!mytt [% whereami = “Vienna” -%] Hello [% whereami %]!
  109. 109. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; “hellov.tp” int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv( “use Template Template->new->process($ARGV[0])quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  110. 110. #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; “hellov.tp” int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv( “use Template Template->new->process($ARGV[0])quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
  111. 111. A LP H A We’ve already seen source filters
  112. 112. B E TA PPI • Pure Perl parser • Only parses a subset of Perl • Can’t tell the difference between certain Perl constructs • This said - very very good at what it does
  113. 113. A LP H A MAD
  114. 114. A LP H A ./configure.gnu --prefix=~/bin/perl595 -Dusedevel -Dmad=y make && make test && make install
  115. 115. A LP H A my $a = 1; my $b = 2; print $a + $b;
  116. 116. A LP H A PERL_XMLDUMP=quot;foo.xmlquot; ./perl foo.pl
  117. 117. </op_nextstate> A LP <op_sassign seq=quot;9 -> 10quot; H flags=quot;VOID,KIDS,STACKEDquot;> A <op_leave seq=quot;0 -> DONEquot; targ=quot;1quot; flags=quot;VOID,KIDS,PARENSquot; private=quot;REFCOUNTEDquot; refcnt=quot;1quot;> <op_enter seq=quot;1 -> 2quot; /> <op_null seq=quot;0 -> (2)quot; flags=quot;VOIDquot;> <madprops> <mad_sv key=quot;;quot; val=quot;quot;/> </madprops> <madprops> </op_null> <op_nextstate seq=quot;2 -> 3quot; flags=quot;VOIDquot; line=quot;1quot; package=quot;mainquot;> <madprops> <mad_sv key=quot;;quot; val=quot;;quot;/> <mad_sv key=quot;#;quot; val=quot; quot;/> </madprops> <mad_sv key=quot;oquot; val=quot;=quot;/> </op_nextstate> <op_sassign seq=quot;5 -> 6quot; flags=quot;VOID,KIDS,STACKEDquot;> <madprops> <mad_sv key=quot;oquot; val=quot;=quot;/> <mad_sv key=quot;_oquot; val=quot; quot;/> </madprops> <op_const seq=quot;3 -> 4quot; flags=quot;SCALARquot; IV=quot;1quot;> <mad_sv key=quot;_oquot; val=quot; quot;/> <madprops> <mad_sv key=quot;Xquot; val=quot;1quot;/> <mad_sv key=quot;_Xquot; val=quot; quot;/> </madprops> </op_const> <op_padsv seq=quot;4 -> 5quot; targ=quot;1quot; flags=quot;SCALAR,REF,MOD,SPECIALquot; private=quot;INTROquot;> <madprops> </madprops> <mad_sv key=quot;$quot; val=quot;$aquot;/> <mad_sv key=quot;_$quot; val=quot; quot;/> <mad_sv key=quot;dquot; val=quot;myquot;/> <mad_sv key=quot;_dquot; val=quot;quot;/> </madprops> </op_padsv> </op_sassign> <op_nextstate seq=quot;6 -> 7quot; flags=quot;VOIDquot; <op_const seq=quot;7 -> 8quot; flags=quot;SCALARquot; line=quot;2quot; package=quot;mainquot;> <madprops> <mad_sv key=quot;;quot; val=quot;;quot;/> <mad_sv key=quot;#;quot; val=quot; quot;/> </madprops> </op_nextstate> <op_sassign seq=quot;9 -> 10quot; flags=quot;VOID,KIDS,STACKEDquot;> <madprops> IV=quot;2quot;> <mad_sv key=quot;oquot; val=quot;=quot;/> <mad_sv key=quot;_oquot; val=quot; quot;/> </madprops> <op_const seq=quot;7 -> 8quot; flags=quot;SCALARquot; IV=quot;2quot;> <madprops> <mad_sv key=quot;Xquot; val=quot;2quot;/> <mad_sv key=quot;_Xquot; val=quot; quot;/> <madprops> </madprops> </op_const> <op_padsv seq=quot;8 -> 9quot; targ=quot;2quot; flags=quot;SCALAR,REF,MOD,SPECIALquot; private=quot;INTROquot;> <madprops> <mad_sv key=quot;$quot; val=quot;$bquot;/> <mad_sv key=quot;_$quot; val=quot; quot;/> <mad_sv key=quot;dquot; val=quot;myquot;/> <mad_sv key=quot;Xquot; val=quot;2quot;/> </madprops> </op_padsv> </op_sassign> <op_nextstate seq=quot;10 -> 11quot; flags=quot;VOIDquot; line=quot;3quot; package=quot;mainquot;> <madprops> <mad_sv key=quot;;quot; val=quot;;quot;/> <mad_sv key=quot;_Xquot; val=quot; quot;/> <mad_sv key=quot;_;quot; val=quot;quot;/> <mad_sv key=quot;#;quot; val=quot; quot;/> </madprops> </op_nextstate> <op_print seq=quot;15 -> 16quot; flags=quot;SCALAR,KIDSquot;> <madprops> <mad_sv key=quot;oquot; val=quot;printquot;/> </madprops> </madprops> <op_pushmark seq=quot;11 -> 12quot; flags=quot;SCALARquot; /> <op_add seq=quot;14 -> 15quot; targ=quot;3quot; flags=quot;SCALAR,KIDSquot;> <madprops> <mad_sv key=quot;oquot; val=quot;+quot;/> <mad_sv key=quot;_oquot; val=quot; quot;/> </madprops> <op_padsv seq=quot;12 -> 13quot; targ=quot;1quot; flags=quot;SCALARquot;> <madprops> </op_const> <mad_sv key=quot;$quot; val=quot;$aquot;/> <mad_sv key=quot;_$quot; val=quot; quot;/> </madprops> </op_padsv> <op_padsv seq=quot;13 -> 14quot; targ=quot;2quot; flags=quot;SCALARquot;> <madprops> <mad_sv key=quot;$quot; val=quot;$bquot;/> <mad_sv key=quot;_$quot; val=quot; quot;/> </madprops> <op_padsv seq=quot;8 -> 9quot; targ=quot;2quot; </op_padsv> </op_add> </op_print> <op_null seq=quot;0 -> (16)quot; flags=quot;VOIDquot; /> </op_leave> flags=quot;SCALAR,REF,MOD,SPECIALquot;
  118. 118. B::Generate • Can be used to create OP codes (i.e. compiled Perl code) directly from Perl
  119. 119. use B::Generate; # Do nothing, slowly. CHECK { my $null = new B::OP(quot;nullquot;,0); my $enter = new B::OP(quot;enterquot;,0); my $cop = new B::COP(0, quot;hiyaquot;, 0); my $leave = new B::LISTOP(quot;leavequot;, 0, $enter, $null); $leave->children(3); $enter->sibling($cop); $enter->next($cop); $cop->sibling($null); $null->next($leave); $cop->next($leave); # Tell Perl where to find our tree. B::main_root($leave); B::main_start($enter); }
  120. 120. optomize.pm • Can be used to manipulate the OP codes after they’ve loaded • Kinda like source filters for compiled bypecode
  121. 121. Use? • PPI is reliable, but limited in it’s ability • Easy to try to do too much with • Other techniques are very unstable / new • B::Generate • optomize • MAD
  122. 122. A LP H A package main; use typesafety; # 'summary', 'debug'; my FooBar $foo; # establish type-checked variables my FooBar $bar; # FooBar is the base class of references $bar will hold my BazQux $baz; $foo = new FooBar; # this is okay, because $foo holds FooBars $bar = $foo; # this is okay, because $bar also holds FooBars # $foo = 10; # this would throw an error - 10 is not a FooBar # $baz = $foo; # not allowed - FooBar isn't a BazQux $foo = $baz; # is allowed - BazQux is a FooBar because of inheritance $bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also typesafety::check(); # perform type check static analysis
  123. 123. A LP H A package main; use typesafety; # 'summary', 'debug'; my FooBar $foo; # establish type-checked variables my FooBar $bar; # FooBar is the base class of references $bar will hold my BazQux $baz; $foo = new FooBar; # this is okay, because $foo holds FooBars $bar = $foo; # this is okay, because $bar also holds FooBars # $foo = 10; # this would throw an error - 10 is not a FooBar # $baz = $foo; # not allowed - FooBar isn't a BazQux $foo = $baz; # is allowed - BazQux is a FooBar because of inheritance $bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also typesafety::check(); # perform type check static analysis
  124. 124. A LP H A package main; use typesafety; # 'summary', 'debug'; my FooBar $foo; # establish type-checked variables my FooBar $bar; # FooBar is the base class of references $bar will hold my BazQux $baz; $foo = new FooBar; # this is okay, because $foo holds FooBars $bar = $foo; # this is okay, because $bar also holds FooBars # $foo = 10; # this would throw an error - 10 is not a FooBar # $baz = $foo; # not allowed - FooBar isn't a BazQux $foo = $baz; # is allowed - BazQux is a FooBar because of inheritance $bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also typesafety::check(); # perform type check static analysis
  125. 125. A LP H A package main; use typesafety; # 'summary', 'debug'; my FooBar $foo; # establish type-checked variables my FooBar $bar; # FooBar is the base class of references $bar will hold my BazQux $baz; $foo = new FooBar; # this is okay, because $foo holds FooBars $bar = $foo; # this is okay, because $bar also holds FooBars # $foo = 10; # this would throw an error - 10 is not a FooBar # $baz = $foo; # not allowed - FooBar isn't a BazQux $foo = $baz; # is allowed - BazQux is a FooBar because of inheritance $bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also typesafety::check(); # perform type check static analysis
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×