Store the offset from the source buffer beginning in the op info object
authorVincent Pit <vince@profvince.com>
Thu, 19 Aug 2010 15:05:48 +0000 (17:05 +0200)
committerVincent Pit <vince@profvince.com>
Thu, 19 Aug 2010 15:05:51 +0000 (17:05 +0200)
This fixes potential errors where some indirect constructs are wrongly
reported (or failed to be) when the source buffer is grown between the
method and the object name.

Also, from now on, an op info object is never stored when the correct
position could not have been found in the source buffer. This is really
how it should have behaved from the beginning.

indirect.xs

index 8a4a192..ba9c503 100644 (file)
@@ -62,6 +62,9 @@
 #define I_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S))))))
 
 #if I_HAS_PERL(5, 10, 0) || defined(PL_parser)
+# ifndef PL_linestr
+#  define PL_linestr PL_parser->linestr
+# endif
 # ifndef PL_bufptr
 #  define PL_bufptr PL_parser->bufptr
 # endif
@@ -69,6 +72,9 @@
 #  define PL_oldbufptr PL_parser->oldbufptr
 # endif
 #else
+# ifndef PL_linestr
+#  define PL_linestr PL_Ilinestr
+# endif
 # ifndef PL_bufptr
 #  define PL_bufptr PL_Ibufptr
 # endif
@@ -176,10 +182,11 @@ typedef SV indirect_hint_t;
  * thread cleanup. */
 
 typedef struct {
- const char *pos;
- char       *buf;
- STRLEN      len, size;
- line_t      line;
+ STRLEN  pos;
+ STRLEN  size;
+ STRLEN  len;
+ char   *buf;
+ line_t  line;
 } indirect_op_info_t;
 
 #define PTABLE_NAME        ptable
@@ -402,8 +409,8 @@ STATIC SV *indirect_hint(pTHX) {
 
 /* ... op -> source position ............................................... */
 
-STATIC void indirect_map_store(pTHX_ const OP *o, const char *src, SV *sv, line_t line) {
-#define indirect_map_store(O, S, N, L) indirect_map_store(aTHX_ (O), (S), (N), (L))
+STATIC void indirect_map_store(pTHX_ const OP *o, STRLEN pos, SV *sv, line_t line) {
+#define indirect_map_store(O, P, N, L) indirect_map_store(aTHX_ (O), (P), (N), (L))
  indirect_op_info_t *oi;
  const char *s;
  STRLEN len;
@@ -431,7 +438,7 @@ STATIC void indirect_map_store(pTHX_ const OP *o, const char *src, SV *sv, line_
  Copy(s, oi->buf, len, char);
 
  oi->len  = len;
- oi->pos  = src;
+ oi->pos  = pos;
  oi->line = line;
 }
 
@@ -451,8 +458,8 @@ STATIC void indirect_map_delete(pTHX_ const OP *o) {
 
 /* --- Check functions ----------------------------------------------------- */
 
-STATIC const char *indirect_find(pTHX_ SV *sv, const char *s) {
-#define indirect_find(N, S) indirect_find(aTHX_ (N), (S))
+STATIC int indirect_find(pTHX_ SV *sv, const char *s, STRLEN *pos) {
+#define indirect_find(N, S, P) indirect_find(aTHX_ (N), (S), (P))
  STRLEN len;
  const char *p = NULL, *r = SvPV_const(sv, len);
 
@@ -461,7 +468,7 @@ STATIC const char *indirect_find(pTHX_ SV *sv, const char *s) {
   --len;
   s = strchr(s, '$');
   if (!s)
-   return NULL;
+   return 0;
  }
 
  p = strstr(s, r);
@@ -471,8 +478,12 @@ STATIC const char *indirect_find(pTHX_ SV *sv, const char *s) {
    break;
   p = strstr(p + 1, r);
  }
+ if (!p)
+  return 0;
 
- return p;
+ *pos = p - SvPVX_const(PL_linestr);
+
+ return 1;
 }
 
 /* ... ck_const ............................................................ */
@@ -484,10 +495,14 @@ STATIC OP *indirect_ck_const(pTHX_ OP *o) {
 
  if (indirect_hint()) {
   SV *sv = cSVOPo_sv;
+
   if (SvPOK(sv) && (SvTYPE(sv) >= SVt_PV)) {
-   const char *s = indirect_find(sv, PL_oldbufptr);
-   indirect_map_store(o, s, sv, CopLINE(&PL_compiling));
-   return o;
+   STRLEN pos;
+
+   if (indirect_find(sv, PL_oldbufptr, &pos)) {
+    indirect_map_store(o, pos, sv, CopLINE(&PL_compiling));
+    return o;
+   }
   }
  }
 
@@ -503,8 +518,8 @@ STATIC OP *indirect_ck_rv2sv(pTHX_ OP *o) {
  if (indirect_hint()) {
   OP *op = cUNOPo->op_first;
   SV *sv;
-  const char *name = NULL, *s;
-  STRLEN len;
+  const char *name = NULL;
+  STRLEN pos, len;
   OPCODE type = (OPCODE) op->op_type;
 
   switch (type) {
@@ -527,8 +542,8 @@ STATIC OP *indirect_ck_rv2sv(pTHX_ OP *o) {
 
   sv = sv_2mortal(newSVpvn("$", 1));
   sv_catpvn_nomg(sv, name, len);
-  s = indirect_find(sv, PL_oldbufptr);
-  if (!s) { /* If it failed, retry without the current stash */
+  if (!indirect_find(sv, PL_oldbufptr, &pos)) {
+   /* If it failed, retry without the current stash */
    const char *stash = HvNAME_get(PL_curstash);
    STRLEN stashlen = HvNAMELEN_get(PL_curstash);
 
@@ -545,13 +560,13 @@ STATIC OP *indirect_ck_rv2sv(pTHX_ OP *o) {
    sv_setpvn(sv, "$", 1);
    stashlen += 2;
    sv_catpvn_nomg(sv, name + stashlen, len - stashlen);
-   s = indirect_find(sv, PL_oldbufptr);
-   if (!s)
+   if (!indirect_find(sv, PL_oldbufptr, &pos))
     goto done;
   }
 
   o = CALL_FPTR(indirect_old_ck_rv2sv)(aTHX_ o);
-  indirect_map_store(o, s, sv, CopLINE(&PL_compiling));
+
+  indirect_map_store(o, pos, sv, CopLINE(&PL_compiling));
   return o;
  }
 
@@ -579,7 +594,8 @@ STATIC OP *indirect_ck_padany(pTHX_ OP *o) {
    while (s < t && isSPACE(*t)) --t;
    sv = sv_2mortal(newSVpvn("$", 1));
    sv_catpvn_nomg(sv, s, t - s + 1);
-   indirect_map_store(o, s, sv, CopLINE(&PL_compiling));
+   indirect_map_store(o, s - SvPVX_const(PL_linestr),
+                         sv, CopLINE(&PL_compiling));
    return o;
   }
  }
@@ -603,7 +619,8 @@ STATIC OP *indirect_ck_scope(pTHX_ OP *o) {
  o = CALL_FPTR(old_ck)(aTHX_ o);
 
  if (indirect_hint()) {
-  indirect_map_store(o, PL_oldbufptr, NULL, CopLINE(&PL_compiling));
+  indirect_map_store(o, PL_oldbufptr - SvPVX_const(PL_linestr),
+                        NULL, CopLINE(&PL_compiling));
   return o;
  }
 
@@ -626,12 +643,13 @@ STATIC OP *indirect_ck_method(pTHX_ OP *o) {
    * don't trip up on $obj->$meth. */
   if (op && op->op_type == OP_CONST) {
    const indirect_op_info_t *oi = indirect_map_fetch(op);
-   const char *s = NULL;
+   STRLEN pos;
    line_t line;
    SV *sv;
 
-   if (oi && (s = oi->pos)) {
+   if (oi) {
     sv   = sv_2mortal(newSVpvn(oi->buf, oi->len));
+    pos  = oi->pos;
     /* Keep the old line so that we really point to the first line of the
      * expression. */
     line = oi->line;
@@ -639,15 +657,17 @@ STATIC OP *indirect_ck_method(pTHX_ OP *o) {
     sv = cSVOPx_sv(op);
     if (!SvPOK(sv) || (SvTYPE(sv) < SVt_PV))
      goto done;
-    sv   = sv_mortalcopy(sv);
-    s    = indirect_find(sv, PL_oldbufptr);
+    sv = sv_mortalcopy(sv);
+
+    if (!indirect_find(sv, PL_oldbufptr, &pos))
+     goto done;
     line = CopLINE(&PL_compiling);
    }
 
    o = CALL_FPTR(indirect_old_ck_method)(aTHX_ o);
    /* o may now be a method_named */
 
-   indirect_map_store(o, s, sv, line);
+   indirect_map_store(o, pos, sv, line);
    return o;
   }
  }
@@ -668,22 +688,22 @@ STATIC OP *(*indirect_old_ck_method_named)(pTHX_ OP *) = 0;
 
 STATIC OP *indirect_ck_method_named(pTHX_ OP *o) {
  if (indirect_hint()) {
-  const char *s;
+  STRLEN pos;
   line_t line;
   SV *sv;
 
-  sv   = cSVOPo_sv;
+  sv = cSVOPo_sv;
   if (!SvPOK(sv) || (SvTYPE(sv) < SVt_PV))
    goto done;
-  sv   = sv_mortalcopy(sv);
-  s    = indirect_find(sv, PL_oldbufptr);
-  if (!s)
+  sv = sv_mortalcopy(sv);
+
+  if (!indirect_find(sv, PL_oldbufptr, &pos))
    goto done;
   line = CopLINE(&PL_compiling);
 
   o = CALL_FPTR(indirect_old_ck_method_named)(aTHX_ o);
 
-  indirect_map_store(o, s, sv, line);
+  indirect_map_store(o, pos, sv, line);
   return o;
  }
 
@@ -748,11 +768,11 @@ STATIC OP *indirect_ck_entersub(pTHX_ OP *o) {
    goto done;
 
   moi = indirect_map_fetch(mop);
-  if (!(moi && moi->pos))
+  if (!moi)
    goto done;
 
   ooi = indirect_map_fetch(oop);
-  if (!(ooi && ooi->pos))
+  if (!ooi)
    goto done;
 
   if (indirect_is_indirect(moi, ooi)) {