X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=Declare.xs;h=3a4ff9516929b449c7733e9ec084f6b97c13366f;hb=mxd_parameterized_bug;hp=7e968350d4b4969976f580dec0aca07225c045d7;hpb=8d96afb78ab58b0cd511077d97286175ff52692f;p=p5sagit%2FDevel-Declare.git diff --git a/Declare.xs b/Declare.xs index 7e96835..3a4ff95 100644 --- a/Declare.xs +++ b/Declare.xs @@ -11,6 +11,11 @@ # define Newx(v,n,t) New(0,v,n,t) #endif /* !Newx */ +#define DD_DEBUGf_UPDATED_LINESTR 1 +#define DD_DEBUGf_TRACE 2 + +#define DD_DEBUG_UPDATED_LINESTR (dd_debug & DD_DEBUGf_UPDATED_LINESTR) +#define DD_DEBUG_TRACE (dd_debug & DD_DEBUGf_TRACE) static int dd_debug = 0; #define LEX_NORMAL 10 @@ -36,8 +41,6 @@ static int in_declare = 0; #define DD_AM_LEXING DD_AM_LEXING_CHECK #endif -static OP *previous_op = NULL; - /* thing that decides whether we're dealing with a declarator */ int dd_is_declarator(pTHX_ char* name) { @@ -55,7 +58,7 @@ int dd_is_declarator(pTHX_ char* name) { /* $declarators{$current_package_name} */ if (!HvNAME(PL_curstash)) - return -1; + return -1; is_declarator_pack_ref = hv_fetch(is_declarator, HvNAME(PL_curstash), strlen(HvNAME(PL_curstash)), FALSE); @@ -75,7 +78,7 @@ int dd_is_declarator(pTHX_ char* name) { /* requires SvIOK as well as TRUE since flags not being an int is useless */ if (!is_declarator_flag_ref - || !SvIOK(*is_declarator_flag_ref) + || !SvIOK(*is_declarator_flag_ref) || !SvTRUE(*is_declarator_flag_ref)) return -1; @@ -119,16 +122,28 @@ void dd_set_linestr(pTHX_ char* new_value) { unsigned int new_len = 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)); + croak("PL_linestr not long enough, was Devel::Declare loaded soon enough in %s", + CopFILE(&PL_compiling) + ); } - SvGROW(PL_linestr, new_len); memcpy(SvPVX(PL_linestr), new_value, new_len+1); SvCUR_set(PL_linestr, new_len); 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); + } } char* dd_get_lex_stuff(pTHX) { @@ -189,14 +204,23 @@ int dd_toke_scan_ident(pTHX_ int offset) { } int dd_toke_scan_str(pTHX_ int offset) { + STRLEN remaining = sv_len(PL_linestr) - offset; + SV* line_copy = 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; + 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* base_s = SvPVX(PL_linestr) + offset; - char* s = skipspace(base_s); + char* s = skipspace_force(base_s); return s - base_s; } @@ -210,7 +234,7 @@ STATIC OP *dd_ck_rv2cv(pTHX_ OP *o, void *user_data) { PERL_UNUSED_VAR(user_data); if (in_declare) { - if (dd_debug) { + if (DD_DEBUG_TRACE) { printf("Deconstructing declare\n"); printf("PL_bufptr: %s\n", PL_bufptr); printf("bufend at: %i\n", PL_bufend - PL_bufptr); @@ -228,7 +252,7 @@ STATIC OP *dd_ck_rv2cv(pTHX_ OP *o, void *user_data) { FREETMPS; LEAVE; - if (dd_debug) { + if (DD_DEBUG_TRACE) { printf("PL_bufptr: %s\n", PL_bufptr); printf("bufend at: %i\n", PL_bufend - PL_bufptr); printf("linestr: %s\n", SvPVX(PL_linestr)); @@ -246,7 +270,7 @@ STATIC OP *dd_ck_rv2cv(pTHX_ OP *o, void *user_data) { if (!DD_AM_LEXING) return o; /* not lexing? */ - if (dd_debug) { + if (DD_DEBUG_TRACE) { printf("Checking GV %s -> %s\n", HvNAME(GvSTASH(kGVOP_gv)), GvNAME(kGVOP_gv)); } @@ -255,7 +279,7 @@ STATIC OP *dd_ck_rv2cv(pTHX_ OP *o, void *user_data) { if (dd_flags == -1) return o; - if (dd_debug) { + if (DD_DEBUG_TRACE) { printf("dd_flags are: %i\n", dd_flags); printf("PL_tokenbuf: %s\n", PL_tokenbuf); } @@ -278,7 +302,7 @@ OP* dd_pp_entereval(pTHX) { #endif sv = POPs; if (SvPOK(sv)) { - if (dd_debug) { + if (DD_DEBUG_TRACE) { printf("mangling eval sv\n"); } if (SvREADONLY(sv)) @@ -323,6 +347,10 @@ STATIC OP *dd_ck_const(pTHX_ OP *o, void *user_data) { PERL_UNUSED_VAR(user_data); + if (DD_HAVE_PARSER && PL_expect == XOPERATOR) { + return o; + } + /* if this is set, we just grabbed a delimited string or something, not a bareword, so NO TOUCHY */ @@ -340,28 +368,51 @@ STATIC OP *dd_ck_const(pTHX_ OP *o, void *user_data) { if (dd_flags == -1) return o; - if (previous_op != NULL) { - switch (previous_op->op_type) { - case OP_QR: - case OP_MATCH: - case OP_SUBST: - case OP_TRANS: + switch (PL_lex_inwhat) { + case OP_QR: + case OP_MATCH: + case OP_SUBST: + case OP_TRANS: + case OP_BACKTICK: + case OP_STRINGIFY: + return o; + break; + default: + break; + } + + if (strnEQ(PL_bufptr, "->", 2)) { + return o; + } + + { + char buf[256]; + STRLEN len; + char *s = PL_bufptr; + STRLEN old_offset = PL_bufptr - SvPVX(PL_linestr); + + s = scan_word(s, buf, sizeof buf, FALSE, &len); + if (strnEQ(buf, name, len)) { + char *d; + SV *inject = newSVpvn(SvPVX(PL_linestr), PL_bufptr - SvPVX(PL_linestr)); + sv_catpvn(inject, buf, len); + + d = peekspace(s); + sv_catpvn(inject, s, d - s); + + if ((PL_bufend - d) >= 2 && strnEQ(d, "=>", 2)) { return o; - break; - default: - break; + } + + sv_catpv(inject, d); + dd_set_linestr(aTHX_ SvPV_nolen(inject)); + PL_bufptr = SvPVX(PL_linestr) + old_offset; + SvREFCNT_dec (inject); } } - dd_linestr_callback(aTHX_ "const", name); - return o; -} + dd_linestr_callback(aTHX_ "const", name); -STATIC OP * -remember_previous_op (pTHX_ OP *o, void *user_data) -{ - PERL_UNUSED_VAR (user_data); - previous_op = o; return o; } @@ -373,17 +424,12 @@ PROTOTYPES: DISABLE void setup() - PREINIT: - I32 i; CODE: if (!initialized++) { hook_op_check(OP_RV2CV, dd_ck_rv2cv, NULL); hook_op_check(OP_ENTEREVAL, dd_ck_entereval, NULL); hook_op_check(OP_CONST, dd_ck_const, NULL); } - for (i = 0; i < OP_max; i++) { - (void)hook_op_check(i, remember_previous_op, NULL); - } filter_add(dd_filter_realloc, NULL); char* @@ -472,6 +518,13 @@ set_in_declare(int value) in_declare = value; BOOT: - if (getenv ("DD_DEBUG")) { - dd_debug = 1; +{ + char *endptr; + char *debug_str = getenv ("DD_DEBUG"); + if (debug_str) { + dd_debug = strtol (debug_str, &endptr, 10); + if (*endptr != '\0') { + dd_debug = 0; + } } +}