Merge branch 'hook_op_check'
Florian Ragwitz [Wed, 22 Oct 2008 18:29:36 +0000 (18:29 +0000)]
* hook_op_check:
  Update for latest B::Hooks::OP::Check API.
  Use B::Hooks::OP::Check to register PL_check callbacks.
  Create branch hook_op_check

Changes
Declare.xs
MANIFEST.SKIP
lib/Devel/Declare.pm
stolen_chunk_of_toke.c
t/load_module.t [new file with mode: 0644]
t/method.t
t/multiline-proto.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index bdbd9d2..46f9268 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,8 +1,25 @@
 Changes for Devel-Declare
 
-  - eliminate PERL_5_9_PLUS macro in favour of ifdef PL_parser
+0.002002
+  - switch done_declare call from call_argv to call_pv.
+  - Make get_linestr{,_offset} return sensible values when called while the
+    parser isn't running.
+  - Remove several compile time warnings.
+  - Allow enabling of debug mode using $ENV{DD_DEBUG}.
+
+0.002001
   - clean up checks for whether we're lexing and whether lex_stuff exists
     to handle the PL_parser factor-out in 5.10
+  - check if reallocation of PL_linestr is necessary before doing it. this way
+    we can bail out properly instead of corrupting memory in some cases
+  - don't call strlen twice on the same sting
+  - try to be more portable
+    - stop using Nullsv
+    - don't use Perl_* functions directly.
+    - don't define PERL_CORE
+    - use NEWSV from handy.h instead of defining our own
+    - don't define PERL_NO_GET_CONTEXT
+    - don't support preprocessors (perl -P)
 
 0.002000
   - rewrite guts into perl, add tests for new declaration style
index 537ff80..af640e9 100644 (file)
@@ -1,5 +1,3 @@
-#define PERL_CORE
-#define PERL_NO_GET_CONTEXT
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
 # define Newx(v,n,t) New(0,v,n,t)
 #endif /* !Newx */
 
-#if 0
-#define DD_DEBUG
-#endif
-
-#ifdef DD_DEBUG
-#define DD_DEBUG_S printf("Buffer: %s\n", s);
-#else
-#define DD_DEBUG_S
-#endif
+static int dd_debug = 0;
 
 #define LEX_NORMAL    10
 #define LEX_INTERPNORMAL   9
@@ -36,7 +26,7 @@ static int in_declare = 0;
 
 #define DD_AM_LEXING_CHECK (PL_lex_state == LEX_NORMAL || PL_lex_state == LEX_INTERPNORMAL)
 
-#ifdef PL_parser
+#if defined(PL_parser) || defined(PERL_5_9_PLUS)
 #define DD_HAVE_PARSER PL_parser
 #define DD_HAVE_LEX_STUFF (PL_parser && PL_lex_stuff)
 #define DD_AM_LEXING (PL_parser && DD_AM_LEXING_CHECK)
@@ -62,6 +52,9 @@ int dd_is_declarator(pTHX_ char* name) {
 
   /* $declarators{$current_package_name} */
 
+  if (!HvNAME(PL_curstash))
+         return -1;
+
   is_declarator_pack_ref = hv_fetch(is_declarator, HvNAME(PL_curstash),
                              strlen(HvNAME(PL_curstash)), FALSE);
 
@@ -114,17 +107,20 @@ void dd_linestr_callback (pTHX_ char* type, char* name) {
 }
 
 char* dd_get_linestr(pTHX) {
+  if (!DD_HAVE_PARSER) {
+    return NULL;
+  }
   return SvPVX(PL_linestr);
 }
 
 void dd_set_linestr(pTHX_ char* new_value) {
   int new_len = strlen(new_value);
-  char* old_linestr = SvPVX(PL_linestr);
 
-  SvGROW(PL_linestr, strlen(new_value));
+  if (SvLEN(PL_linestr) < new_len) {
+    croak("forced to realloc PL_linestr for line %s, bailing out before we crash harder", SvPVX(PL_linestr));
+  }
 
-  if (SvPVX(PL_linestr) != old_linestr)
-    Perl_croak(aTHX_ "forced to realloc PL_linestr for line %s, bailing out before we crash harder", SvPVX(PL_linestr));
+  SvGROW(PL_linestr, new_len);
 
   memcpy(SvPVX(PL_linestr), new_value, new_len+1);
 
@@ -137,9 +133,9 @@ char* dd_get_lex_stuff(pTHX) {
   return (DD_HAVE_LEX_STUFF ? SvPVX(PL_lex_stuff) : "");
 }
 
-char* dd_clear_lex_stuff(pTHX) {
+void dd_clear_lex_stuff(pTHX) {
   if (DD_HAVE_PARSER)
-    PL_lex_stuff = Nullsv;
+    PL_lex_stuff = (SV*)NULL;
 }
 
 char* dd_get_curstash_name(pTHX) {
@@ -147,7 +143,11 @@ char* dd_get_curstash_name(pTHX) {
 }
 
 int dd_get_linestr_offset(pTHX) {
-  char* linestr = SvPVX(PL_linestr);
+  char* linestr;
+  if (!DD_HAVE_PARSER) {
+    return -1;
+  }
+  linestr = SvPVX(PL_linestr);
   return PL_bufptr - linestr;
 }
 
@@ -196,25 +196,35 @@ int dd_toke_skipspace(pTHX_ int offset) {
 STATIC OP *dd_ck_rv2cv(pTHX_ OP *o, void *user_data) {
   OP* kid;
   int dd_flags;
-  char* cb_args[6];
 
   if (in_declare) {
-    cb_args[0] = NULL;
-#ifdef DD_DEBUG
-    printf("Deconstructing declare\n");
-    printf("PL_bufptr: %s\n", PL_bufptr);
-    printf("bufend at: %i\n", PL_bufend - PL_bufptr);
-    printf("linestr: %s\n", SvPVX(PL_linestr));
-    printf("linestr len: %i\n", PL_bufend - SvPVX(PL_linestr));
-#endif
-    call_argv("Devel::Declare::done_declare", G_VOID|G_DISCARD, cb_args);
-#ifdef DD_DEBUG
-    printf("PL_bufptr: %s\n", PL_bufptr);
-    printf("bufend at: %i\n", PL_bufend - PL_bufptr);
-    printf("linestr: %s\n", SvPVX(PL_linestr));
-    printf("linestr len: %i\n", PL_bufend - SvPVX(PL_linestr));
-    printf("actual len: %i\n", strlen(PL_bufptr));
-#endif
+    if (dd_debug) {
+      printf("Deconstructing declare\n");
+      printf("PL_bufptr: %s\n", PL_bufptr);
+      printf("bufend at: %i\n", PL_bufend - PL_bufptr);
+      printf("linestr: %s\n", SvPVX(PL_linestr));
+      printf("linestr len: %i\n", PL_bufend - SvPVX(PL_linestr));
+    }
+
+    dSP;
+  
+    ENTER;
+    SAVETMPS;
+  
+    PUSHMARK(SP);
+  
+    call_pv("Devel::Declare::done_declare", G_VOID|G_DISCARD);
+
+    FREETMPS;
+    LEAVE;
+
+    if (dd_debug) {
+      printf("PL_bufptr: %s\n", PL_bufptr);
+      printf("bufend at: %i\n", PL_bufend - PL_bufptr);
+      printf("linestr: %s\n", SvPVX(PL_linestr));
+      printf("linestr len: %i\n", PL_bufend - SvPVX(PL_linestr));
+      printf("actual len: %i\n", strlen(PL_bufptr));
+    }
     return o;
   }
 
@@ -226,22 +236,19 @@ STATIC OP *dd_ck_rv2cv(pTHX_ OP *o, void *user_data) {
   if (!DD_AM_LEXING)
     return o; /* not lexing? */
 
-#ifdef DD_DEBUG
-  printf("Checking GV %s -> %s\n", HvNAME(GvSTASH(kGVOP_gv)), GvNAME(kGVOP_gv));
-#endif
+  if (dd_debug) {
+    printf("Checking GV %s -> %s\n", HvNAME(GvSTASH(kGVOP_gv)), GvNAME(kGVOP_gv));
+  }
 
   dd_flags = dd_is_declarator(aTHX_ GvNAME(kGVOP_gv));
 
   if (dd_flags == -1)
     return o;
 
-#ifdef DD_DEBUG
-  printf("dd_flags are: %i\n", dd_flags);
-#endif
-
-#ifdef DD_DEBUG
-  printf("PL_tokenbuf: %s\n", PL_tokenbuf);
-#endif
+  if (dd_debug) {
+    printf("dd_flags are: %i\n", dd_flags);
+    printf("PL_tokenbuf: %s\n", PL_tokenbuf);
+  }
 
   dd_linestr_callback(aTHX_ "rv2cv", GvNAME(kGVOP_gv));
 
@@ -254,9 +261,9 @@ OP* dd_pp_entereval(pTHX) {
   STRLEN len;
   const char* s;
   if (SvPOK(sv)) {
-#ifdef DD_DEBUG
-    printf("mangling eval sv\n");
-#endif
+    if (dd_debug) {
+      printf("mangling eval sv\n");
+    }
     if (SvREADONLY(sv))
       sv = sv_2mortal(newSVsv(sv));
     s = SvPVX(sv);
@@ -288,7 +295,6 @@ static I32 dd_filter_realloc(pTHX_ int idx, SV *sv, int maxlen)
 
 STATIC OP *dd_ck_const(pTHX_ OP *o, void *user_data) {
   int dd_flags;
-  char* s;
   char* name;
 
   /* if this is set, we just grabbed a delimited string or something,
@@ -406,3 +412,8 @@ void
 set_in_declare(int value)
   CODE:
     in_declare = value;
+
+BOOT:
+  if (getenv ("DD_DEBUG")) {
+    dd_debug = 1;
+  }
index df9b0fb..9d62519 100644 (file)
@@ -1 +1,2 @@
 ^(?!script/|lib/|inc/|t/|example/|Makefile.PL$|README$|MANIFEST$|Changes$|META.yml|.*?.xs$|stolen_chunk_of_toke.c$)
+t/multiline-proto.t
index 6280eec..7a710b2 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 use warnings;
 use 5.008001;
 
-our $VERSION = '0.002000';
+our $VERSION = '0.002002';
 
 use constant DECLARE_NAME => 1;
 use constant DECLARE_PROTO => 2;
@@ -486,13 +486,15 @@ Devel::Declare -
 
 Currently valid op types: 'check', 'rv2cv'
 
-=head1 AUTHOR
+=head1 AUTHORS
 
 Matt S Trout - <mst@shadowcat.co.uk>
 
 Company: http://www.shadowcat.co.uk/
 Blog: http://chainsawblues.vox.com/
 
+Florian Ragwitz E<lt>rafl@debian.orgE<gt>
+
 =head1 LICENSE
 
 This library is free software under the same terms as perl itself
index 3f0f896..f0498cb 100644 (file)
@@ -83,7 +83,11 @@ STATIC char*    S_scan_word(pTHX_ char *s, char *dest, STRLEN destlen, int allow
 #define PERL_5_8_8_PLUS
 #endif
 
-#ifdef PL_parser
+#if PERL_REVISION == 5 && PERL_VERSION > 8
+#define PERL_5_9_PLUS
+#endif
+
+#ifdef PERL_5_9_PLUS
 /* 5.9+ moves a bunch of things to a PL_parser struct so we need to
    declare the backcompat macros for things to still work (mst) */
 
@@ -136,11 +140,6 @@ STATIC char*    S_scan_word(pTHX_ char *s, char *dest, STRLEN destlen, int allow
 #  define PL_nextval            (PL_parser->nextval)
 /* end of backcompat macros form 5.9 toke.c (mst) */
 #endif
-/* we also need this because we define PERL_CORE so handy.h doesn't provide
-   it for us (mst) */
-#ifndef NEWSV
-#define NEWSV(x,len)    newSV(len)
-#endif
 
 /* when ccflags include -DDEBUGGING we need this for earlier 5.8 perls */
 #ifndef SvPV_nolen_const
@@ -307,16 +306,20 @@ S_skipspace(pTHX_ register char *s)
            PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
            PL_last_lop = PL_last_uni = Nullch;
 
-           /* Close the filehandle.  Could be from -P preprocessor,
+           /* In perl versions previous to p4-rawid: //depot/perl@32954 -P
+            * preprocessors were supported here. We don't support -P at all, even
+            * on perls that support it, and use the following chunk from blead
+            * perl. (rafl)
+            */
+
+           /* Close the filehandle.  Could be from
             * STDIN, or a regular file.  If we were reading code from
             * STDIN (because the commandline held no -e or filename)
             * then we don't close it, we reset it so the code can
             * read from STDIN too.
             */
 
-           if (PL_preprocess && !PL_in_eval)
-               (void)PerlProc_pclose(PL_rsfp);
-           else if ((PerlIO*)PL_rsfp == PerlIO_stdin())
+           if ((PerlIO*)PL_rsfp == PerlIO_stdin())
                PerlIO_clearerr(PL_rsfp);
            else
                (void)PerlIO_close(PL_rsfp);
diff --git a/t/load_module.t b/t/load_module.t
new file mode 100644 (file)
index 0000000..2b1ac62
--- /dev/null
@@ -0,0 +1,19 @@
+=pod
+
+This tests against a segfault when PL_parser becomes NULL temporarly, while
+another module is loaded.
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 1;                      # last test to print
+
+use Devel::Declare 'method' => sub{};
+
+sub lowercase {
+        lc $_[0];
+}
+
+is lowercase("FOO\x{263a}"), "foo\x{263a}";
index 9833e30..7335635 100644 (file)
@@ -91,16 +91,6 @@ use Devel::Declare ();
       shadow(sub (&) { shift });
     }
   }
-
-  sub inject_scope {
-    $^H |= 0x120000;
-    $^H{DD_METHODHANDLERS} = Scope::Guard->new(sub {
-      my $linestr = Devel::Declare::get_linestr;
-      my $offset = Devel::Declare::get_linestr_offset;
-      substr($linestr, $offset, 0) = ';';
-      Devel::Declare::set_linestr($linestr);
-    });
-  }
 }
 
 my ($test_method1, $test_method2, @test_list);
diff --git a/t/multiline-proto.t b/t/multiline-proto.t
new file mode 100644 (file)
index 0000000..b549313
--- /dev/null
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+use Test::More tests => 1;
+
+sub fun :lvalue { return my $sv; }
+
+sub handle_fun {
+  my ($usepack, $use, $inpack, $name, $proto) = @_;
+  my $XX = sub (&) {
+    my $cr = $_[0];
+    return sub {
+      return join(': ', $proto, $cr->());
+    };
+  };
+  return (undef, $XX);
+}
+
+use Devel::Declare;
+use Devel::Declare fun => [ DECLARE_PROTO, \&handle_fun ];
+
+my $foo = fun ($a,
+$b) { "woot" };
+
+is($foo->(), '$a, $b: woot', 'proto declarator ok');