ESUCCESS = 0 is not true, but exists.
[p5sagit/p5-mst-13.2.git] / ext / Storable / Storable.xs
index b7ddc73..1bf09c1 100644 (file)
 
 #include <EXTERN.h>
 #include <perl.h>
-#include <patchlevel.h>                /* Perl's one, needed since 5.6 */
 #include <XSUB.h>
 
+#ifndef PATCHLEVEL
+#    include <patchlevel.h>            /* Perl's one, needed since 5.6 */
+#    if !(defined(PERL_VERSION) || (SUBVERSION > 0 && defined(PATCHLEVEL)))
+#        include <could_not_find_Perl_patchlevel.h>
+#    endif
+#endif
+
 #ifndef NETWARE
 #if 0
 #define DEBUGME /* Debug mode, turns assertions on as well */
@@ -464,7 +470,7 @@ static stcxt_t *Context_ptr = NULL;
        if (!mbase) {                                           \
                TRACEME(("** allocating mbase of %d bytes", MGROW)); \
                New(10003, mbase, MGROW, char); \
-               msiz = MGROW;                                   \
+               msiz = (STRLEN)MGROW;                                   \
        }                                                                       \
        mptr = mbase;                                           \
        if (x)                                                          \
@@ -844,12 +850,12 @@ static const char byteorderstr_56[] = {BYTEORDER_BYTES_56, 0};
 #define STORE_SCALAR(pv, len)  STORE_PV_LEN(pv, len, SX_SCALAR, SX_LSCALAR)
 
 /*
- * Store undef in arrays and hashes without recursing through store().
+ * Store &PL_sv_undef in arrays without recursing through store().
  */
-#define STORE_UNDEF()                                  \
+#define STORE_SV_UNDEF()                                       \
   STMT_START {                                                 \
        cxt->tagnum++;                                          \
-       PUTMARK(SX_UNDEF);                                      \
+       PUTMARK(SX_SV_UNDEF);                                   \
   } STMT_END
 
 /*
@@ -1231,13 +1237,13 @@ static void clean_store_context(stcxt_t *cxt)
        if (cxt->hseen) {
                hv_iterinit(cxt->hseen);
                while ((he = hv_iternext(cxt->hseen)))  /* Extra () for -Wall, grr.. */
-                       HeVAL(he) = &PL_sv_undef;
+                       HeVAL(he) = &PL_sv_placeholder;
        }
 
        if (cxt->hclass) {
                hv_iterinit(cxt->hclass);
                while ((he = hv_iternext(cxt->hclass))) /* Extra () for -Wall, grr.. */
-                       HeVAL(he) = &PL_sv_undef;
+                       HeVAL(he) = &PL_sv_placeholder;
        }
 
        /*
@@ -1316,7 +1322,8 @@ static void init_retrieve_context(stcxt_t *cxt, int optype, int is_tainted)
         * new retrieve routines.
         */
 
-       cxt->hseen = ((cxt->retrieve_vtbl == sv_old_retrieve) ? newHV() : 0);
+       cxt->hseen = (((void*)cxt->retrieve_vtbl == (void*)sv_old_retrieve)
+                     ? newHV() : 0);
 
        cxt->aseen = newAV();                   /* Where retrieved objects are kept */
        cxt->aclass = newAV();                  /* Where seen classnames are kept */
@@ -1954,7 +1961,7 @@ static int store_scalar(stcxt_t *cxt, SV *sv)
 #else
 
             SvIV_please(sv);
-            if (SvIOK(sv)) {
+           if (SvIOK_notUV(sv)) {
                 iv = SvIV(sv);
                 goto integer;          /* Share code above */
             }
@@ -2030,7 +2037,7 @@ static int store_array(stcxt_t *cxt, AV *av)
                sav = av_fetch(av, i, 0);
                if (!sav) {
                        TRACEME(("(#%d) undef item", i));
-                       STORE_UNDEF();
+                       STORE_SV_UNDEF();
                        continue;
                }
                TRACEME(("(#%d) item", i));
@@ -2201,7 +2208,7 @@ static int store_hash(stcxt_t *cxt, HV *hv)
                             = (((hash_flags & SHV_RESTRICTED)
                                 && SvREADONLY(val))
                                ? SHV_K_LOCKED : 0);
-                        if (val == &PL_sv_undef)
+                        if (val == &PL_sv_placeholder)
                             flags |= SHV_K_PLACEHOLDER;
 
                        keyval = SvPV(key, keylen_tmp);
@@ -2263,7 +2270,7 @@ static int store_hash(stcxt_t *cxt, HV *hv)
 
                /*
                 * Storing in "random" order (in the order the keys are stored
-                * within the the hash).  This is the default and will be faster!
+                * within the hash).  This is the default and will be faster!
                 */
   
                for (i = 0; i < len; i++) {
@@ -2297,7 +2304,7 @@ static int store_hash(stcxt_t *cxt, HV *hv)
                             = (((hash_flags & SHV_RESTRICTED)
                                 && SvREADONLY(val))
                                              ? SHV_K_LOCKED : 0);
-                        if (val == &PL_sv_undef)
+                        if (val == &PL_sv_placeholder)
                             flags |= SHV_K_PLACEHOLDER;
 
                         hek = HeKEY_hek(he);
@@ -2373,7 +2380,7 @@ static int store_code(stcxt_t *cxt, CV *cv)
 #else
        dSP;
        I32 len;
-       int ret, count, reallen;
+       int count, reallen;
        SV *text, *bdeparse;
 
        TRACEME(("store_code (0x%"UVxf")", PTR2UV(cv)));
@@ -2424,14 +2431,14 @@ static int store_code(stcxt_t *cxt, CV *cv)
 
        text = POPs;
        len = SvLEN(text);
-       reallen = strlen(SvPV(text,PL_na));
+       reallen = strlen(SvPV_nolen(text));
 
        /*
         * Empty code references or XS functions are deparsed as
         * "(prototype) ;" or ";".
         */
 
-       if (len == 0 || *(SvPV(text,PL_na)+reallen-1) == ';') {
+       if (len == 0 || *(SvPV_nolen(text)+reallen-1) == ';') {
            CROAK(("The result of B::Deparse::coderef2text was empty - maybe you're trying to serialize an XS function?\n"));
        }
 
@@ -2441,13 +2448,13 @@ static int store_code(stcxt_t *cxt, CV *cv)
 
        PUTMARK(SX_CODE);
        TRACEME(("size = %d", len));
-       TRACEME(("code = %s", SvPV(text,PL_na)));
+       TRACEME(("code = %s", SvPV_nolen(text)));
 
        /*
         * Now store the source code.
         */
 
-       STORE_SCALAR(SvPV(text,PL_na), len);
+       STORE_SCALAR(SvPV_nolen(text), len);
 
        FREETMPS;
        LEAVE;
@@ -2469,6 +2476,7 @@ static int store_code(stcxt_t *cxt, CV *cv)
 static int store_tied(stcxt_t *cxt, SV *sv)
 {
        MAGIC *mg;
+       SV *obj = NULL;
        int ret = 0;
        int svt = SvTYPE(sv);
        char mtype = 'P';
@@ -2514,7 +2522,9 @@ static int store_tied(stcxt_t *cxt, SV *sv)
         * accesses on the retrieved object will indeed call the magic methods...
         */
 
-       if ((ret = store(cxt, mg->mg_obj)))             /* Extra () for -Wall, grr... */
+       /* [#17040] mg_obj is NULL for scalar self-ties. AMS 20030416 */
+       obj = mg->mg_obj ? mg->mg_obj : newSV(0);
+       if ((ret = store(cxt, obj)))
                return ret;
 
        TRACEME(("ok (tied)"));
@@ -3366,7 +3376,7 @@ static int magic_write(stcxt_t *cxt)
         length -= sizeof (magicstr) - 1;
     }        
 
-    WRITE(header, length);
+    WRITE( (unsigned char*) header, length);
 
     if (!cxt->netorder) {
        TRACEME(("ok (magic_write byteorder = 0x%lx [%d], I%d L%d P%d D%d)",
@@ -4125,7 +4135,14 @@ static SV *retrieve_ref(stcxt_t *cxt, char *cname)
         * an SX_OBJECT indication, a ref count increment was done.
         */
 
-       sv_upgrade(rv, SVt_RV);
+       if (cname) {
+               /* Do not use sv_upgrade to preserve STASH */
+               SvFLAGS(rv) &= ~SVTYPEMASK;
+               SvFLAGS(rv) |= SVt_RV;
+       } else {
+               sv_upgrade(rv, SVt_RV);
+       }
+
        SvRV(rv) = sv;                          /* $rv = \$sv */
        SvROK_on(rv);
 
@@ -4250,19 +4267,27 @@ static SV *retrieve_tied_hash(stcxt_t *cxt, char *cname)
 static SV *retrieve_tied_scalar(stcxt_t *cxt, char *cname)
 {
        SV *tv;
-       SV *sv;
+       SV *sv, *obj = NULL;
 
        TRACEME(("retrieve_tied_scalar (#%d)", cxt->tagnum));
 
        tv = NEWSV(10002, 0);
        SEEN(tv, cname);                        /* Will return if rv is null */
        sv = retrieve(cxt, 0);          /* Retrieve <object> */
-       if (!sv)
+       if (!sv) {
                return (SV *) 0;                /* Failed */
+       }
+       else if (SvTYPE(sv) != SVt_NULL) {
+               obj = sv;
+       }
 
        sv_upgrade(tv, SVt_PVMG);
-       sv_magic(tv, sv, 'q', Nullch, 0);
-       SvREFCNT_dec(sv);                       /* Undo refcnt inc from sv_magic() */
+       sv_magic(tv, obj, 'q', Nullch, 0);
+
+       if (obj) {
+               /* Undo refcnt inc from sv_magic() */
+               SvREFCNT_dec(obj);
+       }
 
        TRACEME(("ok (retrieve_tied_scalar at 0x%"UVxf")", PTR2UV(tv)));
 
@@ -4871,7 +4896,7 @@ static SV *retrieve_flag_hash(stcxt_t *cxt, char *cname)
 
             if (flags & SHV_K_PLACEHOLDER) {
                 SvREFCNT_dec (sv);
-                sv = &PL_sv_undef;
+                sv = &PL_sv_placeholder;
                store_flags |= HVhek_PLACEHOLD;
            }
             if (flags & SHV_K_UTF8) {
@@ -4936,7 +4961,7 @@ static SV *retrieve_code(stcxt_t *cxt, char *cname)
        dSP;
        int type, count;
        SV *cv;
-       SV *sv, *text, *sub, *errsv;
+       SV *sv, *text, *sub;
 
        TRACEME(("retrieve_code (#%d)", cxt->tagnum));
 
@@ -4962,7 +4987,7 @@ static SV *retrieve_code(stcxt_t *cxt, char *cname)
         */
 
        sub = newSVpvn("sub ", 4);
-       sv_catpv(sub, SvPV(text, PL_na)); /* XXX no sv_catsv! */
+       sv_catpv(sub, SvPV_nolen(text)); /* XXX no sv_catsv! */
        SvREFCNT_dec(text);
 
        /*
@@ -5001,16 +5026,17 @@ static SV *retrieve_code(stcxt_t *cxt, char *cname)
                        CROAK(("Unexpected return value from $Storable::Eval callback\n"));
                cv = POPs;
                if (SvTRUE(errsv)) {
-                       CROAK(("code %s caused an error: %s", SvPV(sub, PL_na), SvPV(errsv, PL_na)));
+                       CROAK(("code %s caused an error: %s",
+                               SvPV_nolen(sub), SvPV_nolen(errsv)));
                }
                PUTBACK;
        } else {
-               cv = eval_pv(SvPV(sub, PL_na), TRUE);
+               cv = eval_pv(SvPV_nolen(sub), TRUE);
        }
        if (cv && SvROK(cv) && SvTYPE(SvRV(cv)) == SVt_PVCV) {
            sv = SvRV(cv);
        } else {
-           CROAK(("code %s did not evaluate to a subroutine reference\n", SvPV(sub, PL_na)));
+           CROAK(("code %s did not evaluate to a subroutine reference\n", SvPV_nolen(sub)));
        }
 
        SvREFCNT_inc(sv); /* XXX seems to be necessary */
@@ -5348,7 +5374,7 @@ static SV *magic_check(stcxt_t *cxt)
 
     /* sizeof(char *) */
     if ((int) *current != sizeof(char *))
-        CROAK(("Pointer integer size is not compatible"));
+        CROAK(("Pointer size is not compatible"));
 
     if (use_NV_size) {
         /* sizeof(NV) */
@@ -5642,7 +5668,22 @@ static SV *do_retrieve(
 
        if (!sv) {
                TRACEME(("retrieve ERROR"));
+#if (PATCHLEVEL <= 4) 
+               /* perl 5.00405 seems to screw up at this point with an
+                  'attempt to modify a read only value' error reported in the
+                  eval { $self = pretrieve(*FILE) } in _retrieve.
+                  I can't see what the cause of this error is, but I suspect a
+                  bug in 5.004, as it seems to be capable of issuing spurious
+                  errors or core dumping with matches on $@. I'm not going to
+                  spend time on what could be a fruitless search for the cause,
+                  so here's a bodge. If you're running 5.004 and don't like
+                  this inefficiency, either upgrade to a newer perl, or you are
+                  welcome to find the problem and send in a patch.
+                */
+               return newSV(0);
+#else
                return &PL_sv_undef;            /* Something went wrong, return undef */
+#endif
        }
 
        TRACEME(("retrieve got %s(0x%"UVxf")",