+#define PERL_NO_GET_CONTEXT 1
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#define LEX_NORMAL 10
#define LEX_INTERPNORMAL 9
+/* please try not to have a line longer than this :) */
+
+#define DD_PREFERRED_LINESTR_SIZE 16384
+
/* flag to trigger removal of temporary declaree sub */
static int in_declare = 0;
HV* is_declarator_pack_hash;
SV** is_declarator_flag_ref;
int dd_flags;
+ char* curstash_name;
is_declarator = get_hv("Devel::Declare::declarators", FALSE);
/* $declarators{$current_package_name} */
- if (!HvNAME(PL_curstash))
+ curstash_name = HvNAME(PL_curstash);
+ if (!curstash_name)
return -1;
- is_declarator_pack_ref = hv_fetch(is_declarator, HvNAME(PL_curstash),
- strlen(HvNAME(PL_curstash)), FALSE);
+ is_declarator_pack_ref = hv_fetch(is_declarator, curstash_name,
+ strlen(curstash_name), FALSE);
if (!is_declarator_pack_ref || !SvROK(*is_declarator_pack_ref))
return -1; /* not a hashref */
PL_bufend = SvPVX(PL_linestr) + new_len;
if ( DD_DEBUG_UPDATED_LINESTR && PERLDB_LINE && PL_curstash != PL_debstash) {
- // Cribbed from toke.c
- SV * const sv = NEWSV(85,0);
-
- sv_upgrade(sv, SVt_PVMG);
- sv_setpvn(sv,PL_bufptr,PL_bufend-PL_bufptr);
- (void)SvIOK_on(sv);
- SvIV_set(sv, 0);
- av_store(CopFILEAV(&PL_compiling),(I32)CopLINE(&PL_compiling),sv);
+ /* Cribbed from toke.c */
+ AV *fileav = CopFILEAV(&PL_compiling);
+ if (fileav) {
+ SV * const sv = NEWSV(85,0);
+
+ sv_upgrade(sv, SVt_PVMG);
+ sv_setpvn(sv,PL_bufptr,PL_bufend-PL_bufptr);
+ (void)SvIOK_on(sv);
+ SvIV_set(sv, 0);
+ av_store(fileav,(I32)CopLINE(&PL_compiling),sv);
+ }
}
}
}
int dd_toke_scan_str(pTHX_ int offset) {
- STRLEN remaining = sv_len(PL_linestr) - offset;
- SV* line_copy = newSVsv(PL_linestr);
+ char* old_pvx = SvPVX(PL_linestr);
+ SV* line_copy = sv_2mortal(newSVsv(PL_linestr));
char* base_s = SvPVX(PL_linestr) + offset;
char* s = scan_str(base_s, FALSE, FALSE);
- if (s != base_s && sv_len(PL_lex_stuff) > remaining) {
- int ret = (s - SvPVX(PL_linestr)) + remaining;
+ if(SvPVX(PL_linestr) != old_pvx)
+ croak("PL_linestr reallocated during scan_str, "
+ "Devel::Declare can't continue");
+ if (!s)
+ return 0;
+ if (s <= base_s || memcmp(SvPVX(line_copy), SvPVX(PL_linestr), offset)) {
+ s += SvCUR(line_copy);
sv_catsv(line_copy, PL_linestr);
dd_set_linestr(aTHX_ SvPV_nolen(line_copy));
- SvREFCNT_dec(line_copy);
- return ret;
}
return s - base_s;
}
int dd_toke_skipspace(pTHX_ int offset) {
+ char* old_pvx = SvPVX(PL_linestr);
char* base_s = SvPVX(PL_linestr) + offset;
char* s = skipspace_force(base_s);
+ if(SvPVX(PL_linestr) != old_pvx)
+ croak("PL_linestr reallocated during skipspace, "
+ "Devel::Declare can't continue");
return s - base_s;
}
PERL_UNUSED_VAR(user_data);
+ if (!DD_AM_LEXING)
+ return o; /* not lexing? */
+
if (in_declare) {
call_done_declare(aTHX);
return o;
if (kid->op_type != OP_GV) /* not a GV so ignore */
return o;
- if (!DD_AM_LEXING)
- return o; /* not lexing? */
-
if (DD_DEBUG_TRACE) {
printf("Checking GV %s -> %s\n", HvNAME(GvSTASH(kGVOP_gv)), GvNAME(kGVOP_gv));
}
static void dd_block_start(pTHX_ int full)
{
PERL_UNUSED_VAR(full);
- if (SvLEN(PL_linestr) < 8192)
- (void) lex_grow_linestr(8192);
+ if (SvLEN(PL_linestr) < DD_PREFERRED_LINESTR_SIZE)
+ (void) lex_grow_linestr(DD_PREFERRED_LINESTR_SIZE);
}
#else /* !DD_GROW_VIA_BLOCKHOOK */
const char* s;
SV *sv;
#ifdef PERL_5_9_PLUS
- SV *saved_hh;
+ SV *saved_hh = NULL;
if (PL_op->op_private & OPpEVAL_HAS_HH) {
saved_hh = POPs;
}
sv = sv_2mortal(newSVsv(sv));
sv_catpvn(sv, "\n;", 2);
}
- SvGROW(sv, 8192);
+ SvGROW(sv, DD_PREFERRED_LINESTR_SIZE);
}
PUSHs(sv);
#ifdef PERL_5_9_PLUS
static I32 dd_filter_realloc(pTHX_ int idx, SV *sv, int maxlen)
{
+ SV *filter_datasv;
const I32 count = FILTER_READ(idx+1, sv, maxlen);
- SvGROW(sv, 8192); /* please try not to have a line longer than this :) */
- /* filter_del(dd_filter_realloc); */
+ SvGROW(sv, DD_PREFERRED_LINESTR_SIZE);
+ /* Filters can only be deleted in the correct order (reverse of the
+ order in which they were added). Insisting on deleting the filter
+ here would break if another filter were added after ours and is
+ still around. Not deleting the filter at all would break if another
+ filter were added earlier and attempts to delete itself later.
+ We can play nicely to the maximum possible extent by deleting our
+ filter iff it is currently deletable (i.e., it is on the top of
+ the filter stack). Can still run into trouble in more complex
+ situations, but can't avoid that. */
+ if (PL_rsfp_filters && AvFILLp(PL_rsfp_filters) >= 0 &&
+ (filter_datasv = FILTER_DATA(AvFILLp(PL_rsfp_filters))) &&
+ IoANY(filter_datasv) == FPTR2DPTR(void *, dd_filter_realloc)) {
+ filter_del(dd_filter_realloc);
+ }
return count;
}
#endif /* !DD_CONST_VIA_RV2CV */
-static int initialized = 0;
-
-MODULE = Devel::Declare PACKAGE = Devel::Declare
-
-PROTOTYPES: DISABLE
-
-void
-setup()
- CODE:
- if (!initialized++) {
+STATIC void dd_initialize(pTHX) {
+ static int initialized = 0;
+ if (!initialized) {
+ initialized = 1;
#if DD_GROW_VIA_BLOCKHOOK
- static BHK bhk;
+ {
+ static BHK bhk;
#if PERL_VERSION_GE(5,13,6)
- BhkENTRY_set(&bhk, bhk_start, dd_block_start);
+ BhkENTRY_set(&bhk, bhk_start, dd_block_start);
#else /* <5.13.6 */
- BhkENTRY_set(&bhk, start, dd_block_start);
+ BhkENTRY_set(&bhk, start, dd_block_start);
#endif /* <5.13.6 */
- Perl_blockhook_register(aTHX_ &bhk);
+ Perl_blockhook_register(aTHX_ &bhk);
+ }
#else /* !DD_GROW_VIA_BLOCKHOOK */
hook_op_check(OP_ENTEREVAL, dd_ck_entereval, NULL);
#endif /* !DD_GROW_VIA_BLOCKHOOK */
hook_op_check(OP_CONST, dd_ck_const, NULL);
#endif /* !DD_CONST_VIA_RV2CV */
}
- filter_add(dd_filter_realloc, NULL);
+}
+
+MODULE = Devel::Declare PACKAGE = Devel::Declare
+
+PROTOTYPES: DISABLE
+
+void
+initialize()
+ CODE:
+ dd_initialize(aTHX);
+
+void
+setup()
+ CODE:
+ dd_initialize(aTHX);
+ filter_add(dd_filter_realloc, NULL);
char*
get_linestr()
OUTPUT:
RETVAL
-int
+SV*
toke_scan_str(int offset);
+ PREINIT:
+ int len;
CODE:
- RETVAL = dd_toke_scan_str(aTHX_ offset);
+ len = dd_toke_scan_str(aTHX_ offset);
+ RETVAL = len ? newSViv(len) : &PL_sv_undef;
OUTPUT:
RETVAL