This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
remove duplicate code and an extra branch in sv_setsv() and
[perl5.git] / sv.h
diff --git a/sv.h b/sv.h
index c888d8f..92e9207 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -1,6 +1,6 @@
 /*    sv.h
  *
- *    Copyright (c) 1991-1997, Larry Wall
+ *    Copyright (c) 1991-1999, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -70,19 +70,48 @@ struct io {
 
 #define SvANY(sv)      (sv)->sv_any
 #define SvFLAGS(sv)    (sv)->sv_flags
+#define SvREFCNT(sv)   (sv)->sv_refcnt
+
+#ifdef USE_THREADS
+
+#  ifdef EMULATE_ATOMIC_REFCOUNTS
+#    define ATOMIC_INC(count) STMT_START {     \
+       MUTEX_LOCK(&PL_svref_mutex);            \
+       ++count;                                \
+       MUTEX_UNLOCK(&PL_svref_mutex);          \
+     } STMT_END
+#    define ATOMIC_DEC_AND_TEST(res,count) STMT_START {        \
+       MUTEX_LOCK(&PL_svref_mutex);                    \
+       res = (--count == 0);                           \
+       MUTEX_UNLOCK(&PL_svref_mutex);                  \
+     } STMT_END
+#  else
+#    define ATOMIC_INC(count) atomic_inc(&count)
+#    define ATOMIC_DEC_AND_TEST(res,count) (res = atomic_dec_and_test(&count))
+#  endif /* EMULATE_ATOMIC_REFCOUNTS */
+#else
+#  define ATOMIC_INC(count) (++count)
+#  define ATOMIC_DEC_AND_TEST(res, count) (res = (--count == 0))
+#endif /* USE_THREADS */
 
 #ifdef __GNUC__
-#  define SvREFCNT_inc(sv) ({SV* nsv=(SV*)(sv); if(nsv) ++SvREFCNT(nsv); nsv;})
+#  define SvREFCNT_inc(sv)             \
+    ({                                 \
+       SV *nsv = (SV*)(sv);            \
+       if (nsv)                        \
+            ATOMIC_INC(SvREFCNT(nsv)); \
+       nsv;                            \
+    })
 #else
 #  if defined(CRIPPLED_CC) || defined(USE_THREADS)
 #    define SvREFCNT_inc(sv) sv_newref((SV*)sv)
 #  else
-#    define SvREFCNT_inc(sv) ((Sv=(SV*)(sv)), (Sv && ++SvREFCNT(Sv)), (SV*)Sv)
+#    define SvREFCNT_inc(sv)   \
+       ((PL_Sv=(SV*)(sv)), (PL_Sv && ATOMIC_INC(SvREFCNT(PL_Sv))), (SV*)PL_Sv)
 #  endif
 #endif
 
 #define SvREFCNT_dec(sv)       sv_free((SV*)sv)
-#endif
 
 #define SVTYPEMASK     0xff
 #define SvTYPE(sv)     ((sv)->sv_flags & SVTYPEMASK)
@@ -108,7 +137,7 @@ struct io {
 #define SVf_BREAK      0x00400000      /* refcnt is artificially low */
 #define SVf_READONLY   0x00800000      /* may not be modified */
 
-#define SVf_THINKFIRST (SVf_READONLY|SVf_ROK)
+#define SVf_THINKFIRST (SVf_READONLY|SVf_ROK|SVf_FAKE)
 
 #define SVp_IOK                0x01000000      /* has valid non-public integer value */
 #define SVp_NOK                0x02000000      /* has valid non-public numeric value */
@@ -118,9 +147,7 @@ struct io {
 #define SVf_OK         (SVf_IOK|SVf_NOK|SVf_POK|SVf_ROK| \
                         SVp_IOK|SVp_NOK|SVp_POK)
 
-#ifdef OVERLOAD
-#define SVf_AMAGIC    0x10000000      /* has magical overloaded methods */
-#endif /* OVERLOAD */
+#define SVf_AMAGIC     0x10000000      /* has magical overloaded methods */
 
 #define PRIVSHIFT 8
 
@@ -166,6 +193,7 @@ struct xpvnv {
     double     xnv_nv;         /* numeric value, if any */
 };
 
+/* These structure must match the beginning of struct xpvhv in hv.h. */
 struct xpvmg {
     char *     xpv_pv;         /* pointer to malloced string */
     STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
@@ -237,7 +265,7 @@ struct xpvfm {
     HV *       xcv_stash;
     OP *       xcv_start;
     OP *       xcv_root;
-    void      (*xcv_xsub)_((CV*));
+    void      (*xcv_xsub)_((CV* _CPERLproto));
     ANY                xcv_xsubany;
     GV *       xcv_gv;
     GV *       xcv_filegv;
@@ -246,7 +274,7 @@ struct xpvfm {
     CV *       xcv_outside;
 #ifdef USE_THREADS
     perl_mutex *xcv_mutexp;    /* protects xcv_owner */
-    struct thread *xcv_owner;  /* current owner thread */
+    struct perl_thread *xcv_owner;     /* current owner thread */
 #endif /* USE_THREADS */
     cv_flags_t xcv_flags;
 
@@ -284,7 +312,8 @@ struct xpvio {
 #define IOf_START 2    /* check for null ARGV and substitute '-' */
 #define IOf_FLUSH 4    /* this fp wants a flush after write op */
 #define IOf_DIDTOP 8   /* just did top of form */
-#define IOf_UNTAINT 16  /* consider this fp (and it's data) "safe" */
+#define IOf_UNTAINT 16  /* consider this fp (and its data) "safe" */
+#define IOf_NOLINE  32 /* slurped a pseudo-line from empty file */
 
 /* The following macros define implementation-independent predicates on SVs. */
 
@@ -294,13 +323,8 @@ struct xpvio {
                                                  SVp_IOK|SVp_NOK))
 
 #define SvOK(sv)               (SvFLAGS(sv) & SVf_OK)
-
-#ifdef OVERLOAD
 #define SvOK_off(sv)           (SvFLAGS(sv) &= ~(SVf_OK|SVf_AMAGIC),   \
                                                        SvOOK_off(sv))
-#else
-#define SvOK_off(sv)           (SvFLAGS(sv) &= ~SVf_OK, SvOOK_off(sv))
-#endif /* OVERLOAD */
 
 #define SvOKp(sv)              (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK))
 #define SvIOKp(sv)             (SvFLAGS(sv) & SVp_IOK)
@@ -314,7 +338,7 @@ struct xpvio {
 #define SvIOK_on(sv)           (SvOOK_off(sv), \
                                    SvFLAGS(sv) |= (SVf_IOK|SVp_IOK))
 #define SvIOK_off(sv)          (SvFLAGS(sv) &= ~(SVf_IOK|SVp_IOK))
-#define SvIOK_only(sv)         (SvOOK_off(sv), SvOK_off(sv), \
+#define SvIOK_only(sv)         (SvOK_off(sv), \
                                    SvFLAGS(sv) |= (SVf_IOK|SVp_IOK))
 
 #define SvNOK(sv)              (SvFLAGS(sv) & SVf_NOK)
@@ -326,14 +350,8 @@ struct xpvio {
 #define SvPOK(sv)              (SvFLAGS(sv) & SVf_POK)
 #define SvPOK_on(sv)           (SvFLAGS(sv) |= (SVf_POK|SVp_POK))
 #define SvPOK_off(sv)          (SvFLAGS(sv) &= ~(SVf_POK|SVp_POK))
-
-#ifdef OVERLOAD
-#define SvPOK_only(sv)            (SvFLAGS(sv) &= ~(SVf_OK|SVf_AMAGIC),   \
-                                   SvFLAGS(sv) |= (SVf_POK|SVp_POK))
-#else
-#define SvPOK_only(sv)            (SvFLAGS(sv) &= ~SVf_OK, \
+#define SvPOK_only(sv)         (SvFLAGS(sv) &= ~(SVf_OK|SVf_AMAGIC),   \
                                    SvFLAGS(sv) |= (SVf_POK|SVp_POK))
-#endif /* OVERLOAD */
 
 #define SvOOK(sv)              (SvFLAGS(sv) & SVf_OOK)
 #define SvOOK_on(sv)           (SvIOK_off(sv), SvFLAGS(sv) |= SVf_OOK)
@@ -345,12 +363,7 @@ struct xpvio {
 
 #define SvROK(sv)              (SvFLAGS(sv) & SVf_ROK)
 #define SvROK_on(sv)           (SvFLAGS(sv) |= SVf_ROK)
-
-#ifdef OVERLOAD
 #define SvROK_off(sv)          (SvFLAGS(sv) &= ~(SVf_ROK|SVf_AMAGIC))
-#else
-#define SvROK_off(sv)          (SvFLAGS(sv) &= ~SVf_ROK)
-#endif /* OVERLOAD */
 
 #define SvMAGICAL(sv)          (SvFLAGS(sv) & (SVs_GMG|SVs_SMG|SVs_RMG))
 #define SvMAGICAL_on(sv)       (SvFLAGS(sv) |= (SVs_GMG|SVs_SMG|SVs_RMG))
@@ -368,18 +381,16 @@ struct xpvio {
 #define SvRMAGICAL_on(sv)      (SvFLAGS(sv) |= SVs_RMG)
 #define SvRMAGICAL_off(sv)     (SvFLAGS(sv) &= ~SVs_RMG)
 
-#ifdef OVERLOAD
-#define SvAMAGIC(sv)         (SvFLAGS(sv) & SVf_AMAGIC)
-#define SvAMAGIC_on(sv)      (SvFLAGS(sv) |= SVf_AMAGIC)
-#define SvAMAGIC_off(sv)     (SvFLAGS(sv) &= ~SVf_AMAGIC)
+#define SvAMAGIC(sv)           (SvFLAGS(sv) & SVf_AMAGIC)
+#define SvAMAGIC_on(sv)                (SvFLAGS(sv) |= SVf_AMAGIC)
+#define SvAMAGIC_off(sv)       (SvFLAGS(sv) &= ~SVf_AMAGIC)
 
 /*
 #define Gv_AMG(stash) \
         (HV_AMAGICmb(stash) && \
          ((!HV_AMAGICbad(stash) && HV_AMAGIC(stash)) || Gv_AMupdate(stash)))
 */
-#define Gv_AMG(stash)           (amagic_generation && Gv_AMupdate(stash))
-#endif /* OVERLOAD */
+#define Gv_AMG(stash)           (PL_amagic_generation && Gv_AMupdate(stash))
 
 #define SvTHINKFIRST(sv)       (SvFLAGS(sv) & SVf_THINKFIRST)
 
@@ -435,7 +446,7 @@ struct xpvio {
 #define SvLEN(sv) ((XPV*)  SvANY(sv))->xpv_len
 #define SvLENx(sv) SvLEN(sv)
 #define SvEND(sv)(((XPV*)  SvANY(sv))->xpv_pv + ((XPV*)SvANY(sv))->xpv_cur)
-#define SvENDx(sv) ((Sv = (sv)), SvEND(Sv))
+#define SvENDx(sv) ((PL_Sv = (sv)), SvEND(PL_Sv))
 #define SvMAGIC(sv)    ((XPVMG*)  SvANY(sv))->xmg_magic
 #define SvSTASH(sv)    ((XPVMG*)  SvANY(sv))->xmg_stash
 
@@ -487,15 +498,21 @@ struct xpvio {
 #define IoFLAGS(sv)    ((XPVIO*)  SvANY(sv))->xio_flags
 
 #define SvTAINTED(sv)    (SvMAGICAL(sv) && sv_tainted(sv))
-#define SvTAINTED_on(sv)  STMT_START{ if(tainting){sv_taint(sv);}   }STMT_END
-#define SvTAINTED_off(sv) STMT_START{ if(tainting){sv_untaint(sv);} }STMT_END
-
-#define SvTAINT(sv)      STMT_START{ if(tainted){SvTAINTED_on(sv);} }STMT_END
-
-#ifdef CRIPPLED_CC
+#define SvTAINTED_on(sv)  STMT_START{ if(PL_tainting){sv_taint(sv);}   }STMT_END
+#define SvTAINTED_off(sv) STMT_START{ if(PL_tainting){sv_untaint(sv);} }STMT_END
+
+#define SvTAINT(sv)                    \
+    STMT_START {                       \
+       if (PL_tainting) {              \
+           dTHR;                       \
+           if (PL_tainted)             \
+               SvTAINTED_on(sv);       \
+       }                               \
+    } STMT_END
 
 #define SvPV_force(sv, lp) sv_pvn_force(sv, &lp)
 #define SvPV(sv, lp) sv_pvn(sv, &lp)
+#define SvPV_nolen(sv) sv_pv(sv)
 #define SvIVx(sv) sv_iv(sv)
 #define SvUVx(sv) sv_uv(sv)
 #define SvNVx(sv) sv_nv(sv)
@@ -508,7 +525,8 @@ struct xpvio {
 #define SvUV(sv) SvIVx(sv)
 #define SvTRUE(sv) SvTRUEx(sv)
 
-#else /* !CRIPPLED_CC */
+#ifndef CRIPPLED_CC
+/* redefine some things to more efficient inlined versions */
 
 #undef SvIV
 #define SvIV(sv) (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv))
@@ -528,15 +546,30 @@ struct xpvio {
     ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \
      ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvn_force(sv, &lp))
 
-#undef SvTRUE
-#define SvTRUE(sv) (                                           \
+#undef SvPV_nolen
+#define SvPV_nolen(sv) \
+    (SvPOK(sv) ? SvPVX(sv) : sv_2pv_nolen(sv))
+
+#ifdef __GNUC__
+#  undef SvIVx
+#  undef SvUVx
+#  undef SvNVx
+#  undef SvPVx
+#  undef SvTRUE
+#  undef SvTRUEx
+#  define SvIVx(sv) ({SV *nsv = (SV*)(sv); SvIV(nsv); })
+#  define SvUVx(sv) ({SV *nsv = (SV*)(sv); SvUV(nsv); })
+#  define SvNVx(sv) ({SV *nsv = (SV*)(sv); SvNV(nsv); })
+#  define SvPVx(sv, lp) ({SV *nsv = (sv); SvPV(nsv, lp); })
+#  define SvTRUE(sv) (                                         \
     !sv                                                                \
     ? 0                                                                \
     :    SvPOK(sv)                                             \
-       ?   ((Xpv = (XPV*)SvANY(sv)) &&                         \
-            (*Xpv->xpv_pv > '0' ||                             \
-             Xpv->xpv_cur > 1 ||                               \
-             (Xpv->xpv_cur && *Xpv->xpv_pv != '0'))            \
+       ?   (({XPV *nxpv = (XPV*)SvANY(sv);                     \
+            nxpv &&                                            \
+            (*nxpv->xpv_pv > '0' ||                            \
+             nxpv->xpv_cur > 1 ||                              \
+             (nxpv->xpv_cur && *nxpv->xpv_pv != '0')); })      \
             ? 1                                                \
             : 0)                                               \
        :                                                       \
@@ -545,38 +578,67 @@ struct xpvio {
            :   SvNOK(sv)                                       \
                ? SvNVX(sv) != 0.0                              \
                : sv_2bool(sv) )
-
-#define SvIVx(sv) ((Sv = (sv)), SvIV(Sv))
-#define SvUVx(sv) ((Sv = (sv)), SvUV(Sv))
-#define SvNVx(sv) ((Sv = (sv)), SvNV(Sv))
-#define SvPVx(sv, lp) ((Sv = (sv)), SvPV(Sv, lp))
-#define SvTRUEx(sv) ((Sv = (sv)), SvTRUE(Sv))
-
-#endif /* CRIPPLED_CC */
+#  define SvTRUEx(sv) ({SV *nsv = (sv); SvTRUE(nsv); })
+#else /* __GNUC__ */
+#ifndef USE_THREADS
+/* These inlined macros use globals, which will require a thread
+ * declaration in user code, so we avoid them under threads */
+
+#  undef SvIVx
+#  undef SvUVx
+#  undef SvNVx
+#  undef SvPVx
+#  undef SvTRUE
+#  undef SvTRUEx
+#  define SvIVx(sv) ((PL_Sv = (sv)), SvIV(PL_Sv))
+#  define SvUVx(sv) ((PL_Sv = (sv)), SvUV(PL_Sv))
+#  define SvNVx(sv) ((PL_Sv = (sv)), SvNV(PL_Sv))
+#  define SvPVx(sv, lp) ((PL_Sv = (sv)), SvPV(PL_Sv, lp))
+#  define SvTRUE(sv) (                                         \
+    !sv                                                                \
+    ? 0                                                                \
+    :    SvPOK(sv)                                             \
+       ?   ((PL_Xpv = (XPV*)SvANY(sv)) &&                      \
+            (*PL_Xpv->xpv_pv > '0' ||                          \
+             PL_Xpv->xpv_cur > 1 ||                            \
+             (PL_Xpv->xpv_cur && *PL_Xpv->xpv_pv != '0'))      \
+            ? 1                                                \
+            : 0)                                               \
+       :                                                       \
+           SvIOK(sv)                                           \
+           ? SvIVX(sv) != 0                                    \
+           :   SvNOK(sv)                                       \
+               ? SvNVX(sv) != 0.0                              \
+               : sv_2bool(sv) )
+#  define SvTRUEx(sv) ((PL_Sv = (sv)), SvTRUE(PL_Sv))
+#endif /* !USE_THREADS */
+#endif /* !__GNU__ */
+#endif /* !CRIPPLED_CC */
 
 #define newRV_inc(sv)  newRV(sv)
-#ifndef CRIPPLED_CC
-#undef newRV_noinc
-#define newRV_noinc(sv)        ((Sv = newRV(sv)), --SvREFCNT(SvRV(Sv)), Sv)
-#endif
 
-/* the following macro updates any magic values this sv is associated with */
+/* the following macros update any magic values this sv is associated with */
 
-#define SvSETMAGIC(x) if (SvSMAGICAL(x)) mg_set(x)
+#define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
+#define SvSETMAGIC(x) STMT_START { if (SvSMAGICAL(x)) mg_set(x); } STMT_END
 
 #define SvSetSV_and(dst,src,finally) \
+       STMT_START {                                    \
            if ((dst) != (src)) {                       \
                sv_setsv(dst, src);                     \
                finally;                                \
-           }
+           }                                           \
+       } STMT_END
 #define SvSetSV_nosteal_and(dst,src,finally) \
+       STMT_START {                                    \
            if ((dst) != (src)) {                       \
                U32 tMpF = SvFLAGS(src) & SVs_TEMP;     \
                SvTEMP_off(src);                        \
                sv_setsv(dst, src);                     \
                SvFLAGS(src) |= tMpF;                   \
                finally;                                \
-           }
+           }                                           \
+       } STMT_END
 
 #define SvSetSV(dst,src) \
                SvSetSV_and(dst,src,/*nothing*/;)
@@ -588,11 +650,15 @@ struct xpvio {
 #define SvSetMagicSV_nosteal(dst,src) \
                SvSetSV_nosteal_and(dst,src,SvSETMAGIC(dst))
 
+#ifdef DEBUGGING
 #define SvPEEK(sv) sv_peek(sv)
+#else
+#define SvPEEK(sv) ""
+#endif
 
-#define SvIMMORTAL(sv) ((sv)==&sv_undef || (sv)==&sv_yes || (sv)==&sv_no)
+#define SvIMMORTAL(sv) ((sv)==&PL_sv_undef || (sv)==&PL_sv_yes || (sv)==&PL_sv_no)
 
-#define boolSV(b) ((b) ? &sv_yes : &sv_no)
+#define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no)
 
 #define isGV(sv) (SvTYPE(sv) == SVt_PVGV)