Fix regexec.c so $^N and $+ are correctly updated so that they work properly inside...
[p5sagit/p5-mst-13.2.git] / sv.h
diff --git a/sv.h b/sv.h
index df42dcf..ea5e0ae 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -421,6 +421,7 @@ union _xivu {
     void *  xivu_p1;
     I32            xivu_i32;
     HEK *   xivu_namehek;      /* xpvlv, xpvgv: GvNAME */
+    HV *    xivu_hv;           /* regexp: paren_names */
 };
 
 union _xmgu {
@@ -653,10 +654,12 @@ Will also turn off the UTF-8 status.
 Returns a boolean indicating whether the SV contains a v-string.
 
 =for apidoc Am|U32|SvOOK|SV* sv
-Returns a U32 indicating whether the SvIVX is a valid offset value for
-the SvPVX.  This hack is used internally to speed up removal of characters
-from the beginning of a SvPV.  When SvOOK is true, then the start of the
-allocated string buffer is really (SvPVX - SvIVX).
+Returns a U32 indicating whether the pointer to the string buffer is offset.
+This hack is used internally to speed up removal of characters from the
+beginning of a SvPV.  When SvOOK is true, then the start of the
+allocated string buffer is actually C<SvOOK_offset()> bytes before SvPVX.
+This offset used to be stored in SvIVX, but is now stored within the spare
+part of the buffer.
 
 =for apidoc Am|U32|SvROK|SV* sv
 Tests if the SV is an RV.
@@ -761,7 +764,7 @@ Set the actual length of the string which is in the SV.  See C<SvIV_set>.
 
 #define SvOKp(sv)              (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK))
 #define SvIOKp(sv)             (SvFLAGS(sv) & SVp_IOK)
-#define SvIOKp_on(sv)          (assert_not_glob(sv) SvRELEASE_IVX(sv), \
+#define SvIOKp_on(sv)          (assert_not_glob(sv) SvRELEASE_IVX_(sv) \
                                    SvFLAGS(sv) |= SVp_IOK)
 #define SvNOKp(sv)             (SvFLAGS(sv) & SVp_NOK)
 #define SvNOKp_on(sv)          (assert_not_glob(sv) SvFLAGS(sv) |= SVp_NOK)
@@ -770,7 +773,7 @@ Set the actual length of the string which is in the SV.  See C<SvIV_set>.
                                 SvFLAGS(sv) |= SVp_POK)
 
 #define SvIOK(sv)              (SvFLAGS(sv) & SVf_IOK)
-#define SvIOK_on(sv)           (assert_not_glob(sv) SvRELEASE_IVX(sv), \
+#define SvIOK_on(sv)           (assert_not_glob(sv) SvRELEASE_IVX_(sv) \
                                    SvFLAGS(sv) |= (SVf_IOK|SVp_IOK))
 #define SvIOK_off(sv)          (SvFLAGS(sv) &= ~(SVf_IOK|SVp_IOK|SVf_IVisUV))
 #define SvIOK_only(sv)         (SvOK_off(sv), \
@@ -1240,7 +1243,9 @@ the scalar's value cannot change unless written to.
                     if (SvLEN(sv)) {                                   \
                         assert(!SvROK(sv));                            \
                         if(SvOOK(sv)) {                                \
-                            SvPV_set(sv, SvPVX_mutable(sv) - SvIVX(sv)); \
+                            STRLEN zok;                                \
+                            SvOOK_offset(sv, zok);                     \
+                            SvPV_set(sv, SvPVX_mutable(sv) - zok);     \
                             SvFLAGS(sv) &= ~SVf_OOK;                   \
                         }                                              \
                         Safefree(SvPVX(sv));                           \
@@ -1714,10 +1719,16 @@ Like C<sv_catsv> but doesn't process magic.
 
 #ifdef PERL_OLD_COPY_ON_WRITE
 #define SvRELEASE_IVX(sv)   \
-    ((SvIsCOW(sv) ? sv_force_normal_flags(sv, 0) : (void) 0), SvOOK_off(sv))
+    ((SvIsCOW(sv) ? sv_force_normal_flags(sv, 0) : (void) 0), 0)
 #  define SvIsCOW_normal(sv)   (SvIsCOW(sv) && SvLEN(sv))
+#  define SvRELEASE_IVX_(sv)   SvRELEASE_IVX(sv),
 #else
-#  define SvRELEASE_IVX(sv)   SvOOK_off(sv)
+#  define SvRELEASE_IVX(sv)   0
+/* This little game brought to you by the need to shut this warning up:
+mg.c: In function `Perl_magic_get':
+mg.c:1024: warning: left-hand operand of comma expression has no effect
+*/
+#  define SvRELEASE_IVX_(sv)  /**/
 #endif /* PERL_OLD_COPY_ON_WRITE */
 
 #define CAN_COW_MASK   (SVs_OBJECT|SVs_GMG|SVs_SMG|SVs_RMG|SVf_IOK|SVf_NOK| \
@@ -1761,7 +1772,7 @@ Like C<sv_catsv> but doesn't process magic.
 #define sv_catpvn_utf8_upgrade(dsv, sstr, slen, nsv)   \
        STMT_START {                                    \
            if (!(nsv))                                 \
-               nsv = sv_2mortal(newSVpvn(sstr, slen)); \
+               nsv = newSVpvn_flags(sstr, slen, SVs_TEMP);     \
            else                                        \
                sv_setpvn(nsv, sstr, slen);             \
            SvUTF8_off(nsv);                            \
@@ -1911,6 +1922,71 @@ struct clone_params {
 };
 
 /*
+=for apidoc Am|SV*|newSVpvn_utf8|NULLOK const char* s|STRLEN len|U32 utf8
+
+Creates a new SV and copies a string into it.  If utf8 is true, calls
+C<SvUTF8_on> on the new SV.  Implemented as a wrapper around C<newSVpvn_flags>.
+
+=cut
+*/
+
+#define newSVpvn_utf8(s, len, u) newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0)
+
+/*
+=for apidoc Am|void|SvOOK_offset|NN SV*sv|STRLEN len
+
+Reads into I<len> the offset from SvPVX back to the true start of the
+allocated buffer, which will be non-zero if C<sv_chop> has been used to
+efficiently remove characters from start of the buffer. Implemented as a
+macro, which takes the address of I<len>, which must be of type C<STRLEN>.
+Evaluates I<sv> more than once. Sets I<len> to 0 if C<SvOOK(sv)> is false.
+
+=cut
+*/
+
+#ifdef DEBUGGING
+/* Does the bot know something I don't?
+10:28 <@Nicholas> metabatman
+10:28 <+meta> Nicholas: crash
+*/
+#  define SvOOK_offset(sv, offset) STMT_START {                                \
+       assert(sizeof(offset) == sizeof(STRLEN));                       \
+       if (SvOOK(sv)) {                                                \
+           const U8 *crash = (U8*)SvPVX_const(sv);                     \
+           offset = *--crash;                                          \
+           if (!offset) {                                              \
+               crash -= sizeof(STRLEN);                                \
+               Copy(crash, (U8 *)&offset, sizeof(STRLEN), U8);         \
+           }                                                           \
+           {                                                           \
+               /* Validate the preceding buffer's sentinels to         \
+                  verify that no-one is using it.  */                  \
+               const U8 *const bonk = (U8 *) SvPVX_const(sv) - offset; \
+               while (crash > bonk) {                                  \
+                   --crash;                                            \
+                   assert (*crash == (U8)PTR2UV(crash));               \
+               }                                                       \
+           }                                                           \
+       } else {                                                        \
+           offset = 0;                                                 \
+       }                                                               \
+    } STMT_END
+#else
+    /* This is the same code, but avoids using any temporary variables:  */
+#  define SvOOK_offset(sv, offset) STMT_START {                                \
+       assert(sizeof(offset) == sizeof(STRLEN));                       \
+       if (SvOOK(sv)) {                                                \
+           offset = ((U8*)SvPVX_const(sv))[-1];                        \
+           if (!offset) {                                              \
+               Copy(SvPVX_const(sv) - 1 - sizeof(STRLEN),              \
+                    (U8 *)&offset, sizeof(STRLEN), U8);                \
+           }                                                           \
+       } else {                                                        \
+           offset = 0;                                                 \
+       }                                                               \
+    } STMT_END
+#endif
+/*
  * Local variables:
  * c-indentation-style: bsd
  * c-basic-offset: 4