This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: [perl #41215] % on scalars sometimes throws away fractions
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index 58c495e..33cdb52 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1,7 +1,7 @@
 /*    sv.c
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -704,7 +704,7 @@ Perl_get_arena(pTHX_ int arena_size)
     Newxz(adesc->arena, arena_size, char);
     adesc->size = arena_size;
     DEBUG_m(PerlIO_printf(Perl_debug_log, "arena %d added: %p size %d\n", 
-                         curr, adesc->arena, arena_size));
+                         curr, (void*)adesc->arena, arena_size));
 
     return adesc->arena;
 }
@@ -1069,7 +1069,7 @@ S_more_bodies (pTHX_ svtype sv_type)
     /* computed count doesnt reflect the 1st slot reservation */
     DEBUG_m(PerlIO_printf(Perl_debug_log,
                          "arena %p end %p arena-size %d type %d size %d ct %d\n",
-                         start, end,
+                         (void*)start, (void*)end,
                          (int)bdp->arena_size, sv_type, (int)body_size,
                          (int)bdp->arena_size / (int)body_size));
 
@@ -1178,7 +1178,9 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
 
        (In fact, GP ends up pointing at a previous GP structure, because the
        principle cause of the padding in XPVMG getting garbage is a copy of
-       sizeof(XPVMG) bytes from a XPVGV structure in sv_unglob)
+       sizeof(XPVMG) bytes from a XPVGV structure in sv_unglob. Right now
+       this happens to be moot because XPVGV has been re-ordered, with GP
+       no longer after STASH)
 
        So we are careful and work out the size of used parts of all the
        structures.  */
@@ -3337,14 +3339,14 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
 
     if (SvIS_FREED(dstr)) {
        Perl_croak(aTHX_ "panic: attempt to copy value %" SVf
-                  " to a freed scalar %p", sstr, dstr);
+                  " to a freed scalar %p", SVfARG(sstr), (void *)dstr);
     }
     SV_CHECK_THINKFIRST_COW_DROP(dstr);
     if (!sstr)
        sstr = &PL_sv_undef;
     if (SvIS_FREED(sstr)) {
-       Perl_croak(aTHX_ "panic: attempt to copy freed scalar %p to %p", sstr,
-                  dstr);
+       Perl_croak(aTHX_ "panic: attempt to copy freed scalar %p to %p",
+                  (void*)sstr, (void*)dstr);
     }
     stype = SvTYPE(sstr);
     dtype = SvTYPE(dstr);
@@ -3487,7 +3489,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
     dtype = SvTYPE(dstr);
     sflags = SvFLAGS(sstr);
 
-    if (dtype == SVt_PVCV) {
+    if (dtype == SVt_PVCV || dtype == SVt_PVFM) {
        /* Assigning to a subroutine sets the prototype.  */
        if (SvOK(sstr)) {
            STRLEN len;
@@ -3497,9 +3499,16 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
             Copy(ptr, SvPVX(dstr), len + 1, char);
             SvCUR_set(dstr, len);
            SvPOK_only(dstr);
+           SvFLAGS(dstr) |= sflags & SVf_UTF8;
        } else {
            SvOK_off(dstr);
        }
+    } else if (dtype == SVt_PVAV || dtype == SVt_PVHV) {
+       const char * const type = sv_reftype(dstr,0);
+       if (PL_op)
+           Perl_croak(aTHX_ "Cannot copy to %s in %s", type, OP_NAME(PL_op));
+       else
+           Perl_croak(aTHX_ "Cannot copy to %s", type);
     } else if (sflags & SVf_ROK) {
        if (isGV_with_GP(dstr) && dtype == SVt_PVGV
            && SvTYPE(SvRV(sstr)) == SVt_PVGV) {
@@ -3769,7 +3778,7 @@ Perl_sv_setsv_cow(pTHX_ SV *dstr, SV *sstr)
 
     if (DEBUG_C_TEST) {
        PerlIO_printf(Perl_debug_log, "Fast copy on write: %p -> %p\n",
-                     sstr, dstr);
+                     (void*)sstr, (void*)dstr);
        sv_dump(sstr);
        if (dstr)
                    sv_dump(dstr);
@@ -4358,7 +4367,7 @@ to contain an C<SV*> and is stored as-is with its REFCNT incremented.
 =cut
 */
 MAGIC *        
-Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, MGVTBL *vtable,
+Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, const MGVTBL *vtable,
                 const char* name, I32 namlen)
 {
     dVAR;
@@ -4420,7 +4429,7 @@ Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, MGVTBL *vtable,
        else
            mg->mg_ptr = (char *) name;
     }
-    mg->mg_virtual = vtable;
+    mg->mg_virtual = (MGVTBL *) vtable;
 
     mg_magical(sv);
     if (SvGMAGICAL(sv))
@@ -4447,7 +4456,7 @@ void
 Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 namlen)
 {
     dVAR;
-    MGVTBL *vtable;
+    const MGVTBL *vtable;
     MAGIC* mg;
 
 #ifdef PERL_OLD_COPY_ON_WRITE
@@ -4506,9 +4515,6 @@ Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 nam
     case PERL_MAGIC_regdata:
        vtable = &PL_vtbl_regdata;
        break;
-    case PERL_MAGIC_regdata_names:
-       vtable = &PL_vtbl_regdata_names;
-       break;
     case PERL_MAGIC_regdatum:
        vtable = &PL_vtbl_regdatum;
        break;
@@ -5111,7 +5117,7 @@ Perl_sv_clear(pTHX_ register SV *sv)
     }
     if (type >= SVt_PVMG) {
        if (type == SVt_PVMG && SvPAD_OUR(sv)) {
-           SvREFCNT_dec(OURSTASH(sv));
+           SvREFCNT_dec(SvOURSTASH(sv));
        } else if (SvMAGIC(sv))
            mg_free(sv);
        if (type == SVt_PVMG && SvPAD_TYPED(sv))
@@ -5380,7 +5386,7 @@ Perl_sv_len_utf8(pTHX_ register SV *sv)
                        PL_utf8cache = 0;
                        Perl_croak(aTHX_ "panic: sv_len_utf8 cache %"UVuf
                                   " real %"UVuf" for %"SVf,
-                                  (UV) ulen, (UV) real, (void*)sv);
+                                  (UV) ulen, (UV) real, SVfARG(sv));
                    }
                }
            }
@@ -5538,7 +5544,7 @@ S_sv_pos_u2b_cached(pTHX_ SV *sv, MAGIC **mgp, const U8 *const start,
                PL_utf8cache = 0;
                Perl_croak(aTHX_ "panic: sv_pos_u2b_cache cache %"UVuf
                           " real %"UVuf" for %"SVf,
-                          (UV) boffset, (UV) real_boffset, (void*)sv);
+                          (UV) boffset, (UV) real_boffset, SVfARG(sv));
            }
        }
        boffset = real_boffset;
@@ -5660,7 +5666,7 @@ S_utf8_mg_pos_cache_update(pTHX_ SV *sv, MAGIC **mgp, STRLEN byte, STRLEN utf8,
            SAVEI8(PL_utf8cache);
            PL_utf8cache = 0;
            Perl_croak(aTHX_ "panic: utf8_mg_pos_cache_update cache %"UVuf
-                      " real %"UVuf" for %"SVf, (UV) utf8, (UV) realutf8, (void*)sv);
+                      " real %"UVuf" for %"SVf, (UV) utf8, (UV) realutf8, SVfARG(sv));
        }
     }
 
@@ -5883,7 +5889,7 @@ Perl_sv_pos_b2u(pTHX_ register SV* sv, I32* offsetp)
                PL_utf8cache = 0;
                Perl_croak(aTHX_ "panic: sv_pos_b2u cache %"UVuf
                           " real %"UVuf" for %"SVf,
-                          (UV) len, (UV) real_len, (void*)sv);
+                          (UV) len, (UV) real_len, SVfARG(sv));
            }
        }
        len = real_len;
@@ -7377,7 +7383,7 @@ Perl_sv_2io(pTHX_ SV *sv)
        else
            io = 0;
        if (!io)
-           Perl_croak(aTHX_ "Bad filehandle: %"SVf, (void*)sv);
+           Perl_croak(aTHX_ "Bad filehandle: %"SVf, SVfARG(sv));
        break;
     }
     return io;
@@ -7469,7 +7475,7 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref)
            LEAVE;
            if (!GvCVu(gv))
                Perl_croak(aTHX_ "Unable to create sub named \"%"SVf"\"",
-                          (void*)sv);
+                          SVfARG(sv));
        }
        return GvCVu(gv);
     }
@@ -8405,7 +8411,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     }
     if (args && patlen == 3 && pat[0] == '%' &&
                pat[1] == '-' && pat[2] == 'p') {
-       argsv = va_arg(*args, SV*);
+       argsv = (SV*)va_arg(*args, void*);
        sv_catsv(sv, argsv);
        return;
     }
@@ -8561,7 +8567,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                        precis = n;
                        has_precis = TRUE;
                    }
-                   argsv = va_arg(*args, SV*);
+                   argsv = (SV*)va_arg(*args, void*);
                    eptr = SvPVx_const(argsv, elen);
                    if (DO_UTF8(argsv))
                        is_utf8 = TRUE;
@@ -9338,7 +9344,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                                       (UV)c & 0xFF);
                } else
                    sv_catpvs(msg, "end of string");
-               Perl_warner(aTHX_ packWARN(WARN_PRINTF), "%"SVf, (void*)msg); /* yes, this is reentrant */
+               Perl_warner(aTHX_ packWARN(WARN_PRINTF), "%"SVf, SVfARG(msg)); /* yes, this is reentrant */
            }
 
            /* output mangled stuff ... */
@@ -9479,6 +9485,77 @@ ptr_table_* functions.
 #define SAVEPV(p)      ((p) ? savepv(p) : NULL)
 #define SAVEPVN(p,n)   ((p) ? savepvn(p,n) : NULL)
 
+/* clone a parser */
+
+yy_parser *
+Perl_parser_dup(pTHX_ const yy_parser *proto, CLONE_PARAMS* param)
+{
+    yy_parser *parser;
+
+    if (!proto)
+       return NULL;
+
+    /* look for it in the table first */
+    parser = (yy_parser *)ptr_table_fetch(PL_ptr_table, proto);
+    if (parser)
+       return parser;
+
+    /* create anew and remember what it is */
+    Newxz(parser, 1, yy_parser);
+    ptr_table_store(PL_ptr_table, proto, parser);
+
+    parser->yyerrstatus = 0;
+    parser->yychar = YYEMPTY;          /* Cause a token to be read.  */
+
+    /* XXX these not yet duped */
+    parser->old_parser = NULL;
+    parser->stack = NULL;
+    parser->ps = NULL;
+    parser->stack_size = 0;
+    /* XXX parser->stack->state = 0; */
+
+    /* XXX eventually, just Copy() most of the parser struct ? */
+
+    parser->lex_brackets = proto->lex_brackets;
+    parser->lex_casemods = proto->lex_casemods;
+    parser->lex_brackstack = savepvn(proto->lex_brackstack,
+                   (proto->lex_brackets < 120 ? 120 : proto->lex_brackets));
+    parser->lex_casestack = savepvn(proto->lex_casestack,
+                   (proto->lex_casemods < 12 ? 12 : proto->lex_casemods));
+    parser->lex_defer  = proto->lex_defer;
+    parser->lex_dojoin = proto->lex_dojoin;
+    parser->lex_expect = proto->lex_expect;
+    parser->lex_formbrack = proto->lex_formbrack;
+    parser->lex_inpat  = proto->lex_inpat;
+    parser->lex_inwhat = proto->lex_inwhat;
+    parser->lex_op     = proto->lex_op;
+    parser->lex_repl   = sv_dup_inc(proto->lex_repl, param);
+    parser->lex_starts = proto->lex_starts;
+    parser->lex_stuff  = sv_dup_inc(proto->lex_stuff, param);
+    parser->multi_close        = proto->multi_close;
+    parser->multi_open = proto->multi_open;
+    parser->multi_start        = proto->multi_start;
+    parser->pending_ident = proto->pending_ident;
+    parser->preambled  = proto->preambled;
+    parser->sublex_info        = proto->sublex_info; /* XXX not quite right */
+
+#ifdef PERL_MAD
+    parser->endwhite   = proto->endwhite;
+    parser->faketokens = proto->faketokens;
+    parser->lasttoke   = proto->lasttoke;
+    parser->nextwhite  = proto->nextwhite;
+    parser->realtokenstart = proto->realtokenstart;
+    parser->skipwhite  = proto->skipwhite;
+    parser->thisclose  = proto->thisclose;
+    parser->thismad    = proto->thismad;
+    parser->thisopen   = proto->thisopen;
+    parser->thisstuff  = proto->thisstuff;
+    parser->thistoken  = proto->thistoken;
+    parser->thiswhite  = proto->thiswhite;
+#endif
+    return parser;
+}
+
 
 /* duplicate a file handle */
 
@@ -9616,6 +9693,8 @@ Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS* param)
     return mgret;
 }
 
+#endif /* USE_ITHREADS */
+
 /* create a new pointer-mapping table */
 
 PTR_TBL_t *
@@ -9759,6 +9838,7 @@ Perl_ptr_table_free(pTHX_ PTR_TBL_t *tbl)
     Safefree(tbl);
 }
 
+#if defined(USE_ITHREADS)
 
 void
 Perl_rvpv_dup(pTHX_ SV *dstr, const SV *sstr, CLONE_PARAMS* param)
@@ -9854,7 +9934,7 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
 #ifdef DEBUGGING
     if (SvANY(sstr) && PL_watch_pvx && SvPVX_const(sstr) == PL_watch_pvx)
        PerlIO_printf(Perl_debug_log, "watch at %p hit, found string \"%s\"\n",
-                     PL_watch_pvx, SvPVX_const(sstr));
+                     (void*)PL_watch_pvx, SvPVX_const(sstr));
 #endif
 
     /* don't clone objects whose class has asked us not to */
@@ -9941,7 +10021,7 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
               FIXME - instrument and check that assumption  */
            if (sv_type >= SVt_PVMG) {
                if ((sv_type == SVt_PVMG) && SvPAD_OUR(dstr)) {
-                   OURSTASH_set(dstr, hv_dup_inc(OURSTASH(dstr), param));
+                   SvOURSTASH_set(dstr, hv_dup_inc(SvOURSTASH(dstr), param));
                } else if (SvMAGIC(dstr))
                    SvMAGIC_set(dstr, mg_dup(SvMAGIC(dstr), param));
                if (SvSTASH(dstr))
@@ -10298,6 +10378,7 @@ Perl_any_dup(pTHX_ void *v, const PerlInterpreter *proto_perl)
 ANY *
 Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
 {
+    dVAR;
     ANY * const ss     = proto_perl->Tsavestack;
     const I32 max      = proto_perl->Tsavestack_max;
     I32 ix             = proto_perl->Tsavestack_ix;
@@ -10593,6 +10674,10 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = DUP_WARNINGS((STRLEN*)ptr);
            break;
+       case SAVEt_PARSER:
+           ptr = POPPTR(ss,ix);
+           TOPPTR(nss,ix) = parser_dup(ptr, param);
+           break;
        default:
            Perl_croak(aTHX_
                       "panic: ss_dup inconsistency (%"IVdf")", (IV) type);
@@ -11021,7 +11106,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_Argv            = NULL;
     PL_Cmd             = NULL;
     PL_gensym          = proto_perl->Igensym;
-    PL_preambled       = proto_perl->Ipreambled;
     PL_preambleav      = av_dup_inc(proto_perl->Ipreambleav, param);
     PL_laststatval     = proto_perl->Ilaststatval;
     PL_laststype       = proto_perl->Ilaststype;
@@ -11042,9 +11126,17 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     if (PL_my_cxt_size) {
        Newx(PL_my_cxt_list, PL_my_cxt_size, void *);
        Copy(proto_perl->Imy_cxt_list, PL_my_cxt_list, PL_my_cxt_size, void *);
+#ifdef PERL_GLOBAL_STRUCT_PRIVATE
+       Newx(PL_my_cxt_keys, PL_my_cxt_size, char *);
+       Copy(proto_perl->Imy_cxt_keys, PL_my_cxt_keys, PL_my_cxt_size, char *);
+#endif
     }
-    else
+    else {
        PL_my_cxt_list  = (void**)NULL;
+#ifdef PERL_GLOBAL_STRUCT_PRIVATE
+       PL_my_cxt_keys  = (void**)NULL;
+#endif
+    }
     PL_modglobal       = hv_dup_inc(proto_perl->Imodglobal, param);
     PL_custom_op_names  = hv_dup_inc(proto_perl->Icustom_op_names,param);
     PL_custom_op_descs  = hv_dup_inc(proto_perl->Icustom_op_descs,param);
@@ -11093,38 +11185,12 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_cshname         = proto_perl->Icshname; /* XXX never deallocated */
 #endif
 
+    PL_parser          = parser_dup(proto_perl->Iparser, param);
+
     PL_lex_state       = proto_perl->Ilex_state;
-    PL_lex_defer       = proto_perl->Ilex_defer;
-    PL_lex_expect      = proto_perl->Ilex_expect;
-    PL_lex_formbrack   = proto_perl->Ilex_formbrack;
-    PL_lex_dojoin      = proto_perl->Ilex_dojoin;
-    PL_lex_starts      = proto_perl->Ilex_starts;
-    PL_lex_stuff       = sv_dup_inc(proto_perl->Ilex_stuff, param);
-    PL_lex_repl                = sv_dup_inc(proto_perl->Ilex_repl, param);
-    PL_lex_op          = proto_perl->Ilex_op;
-    PL_lex_inpat       = proto_perl->Ilex_inpat;
-    PL_lex_inwhat      = proto_perl->Ilex_inwhat;
-    PL_lex_brackets    = proto_perl->Ilex_brackets;
-    i = (PL_lex_brackets < 120 ? 120 : PL_lex_brackets);
-    PL_lex_brackstack  = SAVEPVN(proto_perl->Ilex_brackstack,i);
-    PL_lex_casemods    = proto_perl->Ilex_casemods;
-    i = (PL_lex_casemods < 12 ? 12 : PL_lex_casemods);
-    PL_lex_casestack   = SAVEPVN(proto_perl->Ilex_casestack,i);
 
 #ifdef PERL_MAD
     Copy(proto_perl->Inexttoke, PL_nexttoke, 5, NEXTTOKE);
-    PL_lasttoke                = proto_perl->Ilasttoke;
-    PL_realtokenstart  = proto_perl->Irealtokenstart;
-    PL_faketokens      = proto_perl->Ifaketokens;
-    PL_thismad         = proto_perl->Ithismad;
-    PL_thistoken       = proto_perl->Ithistoken;
-    PL_thisopen                = proto_perl->Ithisopen;
-    PL_thisstuff       = proto_perl->Ithisstuff;
-    PL_thisclose       = proto_perl->Ithisclose;
-    PL_thiswhite       = proto_perl->Ithiswhite;
-    PL_nextwhite       = proto_perl->Inextwhite;
-    PL_skipwhite       = proto_perl->Iskipwhite;
-    PL_endwhite                = proto_perl->Iendwhite;
     PL_curforce                = proto_perl->Icurforce;
 #else
     Copy(proto_perl->Inextval, PL_nextval, 5, YYSTYPE);
@@ -11142,15 +11208,10 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     i = proto_perl->Ilinestart - SvPVX_const(proto_perl->Ilinestr);
     PL_linestart       = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
     PL_bufend          = SvPVX(PL_linestr) + SvCUR(PL_linestr);
-    PL_pending_ident   = proto_perl->Ipending_ident;
-    PL_sublex_info     = proto_perl->Isublex_info;     /* XXX not quite right */
 
     PL_expect          = proto_perl->Iexpect;
 
-    PL_multi_start     = proto_perl->Imulti_start;
     PL_multi_end       = proto_perl->Imulti_end;
-    PL_multi_open      = proto_perl->Imulti_open;
-    PL_multi_close     = proto_perl->Imulti_close;
 
     PL_error_count     = proto_perl->Ierror_count;
     PL_subline         = proto_perl->Isubline;