Make parser_free() be called slightly later,
[p5sagit/p5-mst-13.2.git] / universal.c
index 69c31f1..182b5c9 100644 (file)
@@ -185,6 +185,7 @@ Perl_sv_does(pTHX_ SV *sv, const char *name)
 {
     const char *classname;
     bool does_it;
+    SV *methodname;
 
     dSP;
     ENTER;
@@ -199,7 +200,7 @@ Perl_sv_does(pTHX_ SV *sv, const char *name)
     if (sv_isobject(sv)) {
        classname = sv_reftype(SvRV(sv),TRUE);
     } else {
-       classname = SvPV(sv,PL_na);
+       classname = SvPV_nolen(sv);
     }
 
     if (strEQ(name,classname))
@@ -210,7 +211,12 @@ Perl_sv_does(pTHX_ SV *sv, const char *name)
     XPUSHs(sv_2mortal(newSVpv(name, 0)));
     PUTBACK;
 
-    call_method("isa", G_SCALAR);
+    methodname = sv_2mortal(newSVpv("isa", 0));
+    /* ugly hack: use the SvSCREAM flag so S_method_common
+     * can figure out we're calling DOES() and not isa(),
+     * and report eventual errors correctly. --rgs */
+    SvSCREAM_on(methodname);
+    call_sv(methodname, G_SCALAR | G_METHOD);
     SPAGAIN;
 
     does_it = SvTRUE( TOPs );
@@ -333,11 +339,11 @@ Perl_boot_core_UNIVERSAL(pTHX)
     newXSproto("Internals::inc_sub_generation",XS_Internals_inc_sub_generation,
               file, "");
     newXSproto("re::is_regexp", XS_re_is_regexp, file, "$");
-    newXSproto("re::regname", XS_re_regname, file, ";$$$");
-    newXSproto("re::regnames", XS_re_regnames, file, ";$$");
-    newXSproto("re::regnames_iterinit", XS_re_regnames_iterinit, file, ";$");
-    newXSproto("re::regnames_iternext", XS_re_regnames_iternext, file, ";$$");
-    newXSproto("re::regnames_count", XS_re_regnames_count, file, ";$");
+    newXSproto("re::regname", XS_re_regname, file, ";$$");
+    newXSproto("re::regnames", XS_re_regnames, file, ";$");
+    newXSproto("re::regnames_iterinit", XS_re_regnames_iterinit, file, "");
+    newXSproto("re::regnames_iternext", XS_re_regnames_iternext, file, ";$");
+    newXSproto("re::regnames_count", XS_re_regnames_count, file, "");
 }
 
 
@@ -457,7 +463,7 @@ XS(XS_UNIVERSAL_VERSION)
         sv_setsv(nsv, sv);
         sv = nsv;
        if ( !sv_derived_from(sv, "version"))
-           upg_version(sv);
+           upg_version(sv, FALSE);
         undef = NULL;
     }
     else {
@@ -483,19 +489,23 @@ XS(XS_UNIVERSAL_VERSION)
 
        if ( !sv_derived_from(req, "version")) {
            /* req may very well be R/O, so create a new object */
-           SV * const nsv = sv_newmortal();
-           sv_setsv(nsv, req);
-           req = nsv;
-           upg_version(req);
+           req = sv_2mortal( new_version(req) );
        }
 
-       if ( vcmp( req, sv ) > 0 )
-           Perl_croak(aTHX_ "%s version %"SVf" (%"SVf") required--"
-                      "this is only version %"SVf" (%"SVf")", HvNAME_get(pkg),
-                      SVfARG(vnumify(req)),
+       if ( vcmp( req, sv ) > 0 ) {
+           if ( hv_exists((HV*)SvRV(req), "qv", 2 ) ) {
+               Perl_croak(aTHX_ "%s version %"SVf" required--"
+                      "this is only version %"SVf"", HvNAME_get(pkg),
                       SVfARG(vnormal(req)),
-                      SVfARG(vnumify(sv)),
                       SVfARG(vnormal(sv)));
+           } else {
+               Perl_croak(aTHX_ "%s version %"SVf" required--"
+                      "this is only version %"SVf"", HvNAME_get(pkg),
+                      SVfARG(vnumify(req)),
+                      SVfARG(vnumify(sv)));
+           }
+       }
+
     }
 
     if ( SvOK(sv) && sv_derived_from(sv, "version") ) {
@@ -728,29 +738,10 @@ XS(XS_version_qv)
     {
        SV *    ver = ST(0);
        if ( !SvVOK(ver) ) { /* only need to do with if not already v-string */
-           SV * const vs = sv_newmortal();
-           char *version;
-           if ( SvNOK(ver) ) /* may get too much accuracy */
-           {
-               char tbuf[64];
-#ifdef USE_LOCALE_NUMERIC
-               char *loc = setlocale(LC_NUMERIC, "C");
-#endif
-               STRLEN len = my_snprintf(tbuf, sizeof(tbuf), "%.9"NVgf, SvNVX(ver));
-#ifdef USE_LOCALE_NUMERIC
-               setlocale(LC_NUMERIC, loc);
-#endif
-               while (tbuf[len-1] == '0' && len > 0) len--;
-               version = savepvn(tbuf, len);
-           }
-           else
-           {
-               version = savesvpv(ver);
-           }
-           (void)scan_version(version,vs,TRUE);
-           Safefree(version);
-
-           PUSHs(vs);
+           SV * const rv = sv_newmortal();
+           sv_setsv(rv,ver); /* make a duplicate */
+           upg_version(rv, TRUE);
+           PUSHs(rv);
        }
        else
        {
@@ -1158,31 +1149,23 @@ XS(XS_re_regname)
 
     dVAR; 
     dXSARGS;
-    if (items < 1 || items > 3)
-       Perl_croak(aTHX_ "Usage: %s(%s)", "re::regname", "sv, qr = NULL, all = NULL");
+    if (items < 1 || items > 2)
+       Perl_croak(aTHX_ "Usage: %s(%s)", "re::regname", "name[, all ]");
     PERL_UNUSED_VAR(cv); /* -W */
     PERL_UNUSED_VAR(ax); /* -Wall */
     SP -= items;
     {
        SV *    sv = ST(0);
-       SV *    qr;
        SV *    all;
-        regexp *re = NULL;
+        regexp *re = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
         SV *bufs = NULL;
 
        if (items < 2)
-           qr = NULL;
-       else {
-           qr = ST(1);
-       }
-
-       if (items < 3)
            all = NULL;
        else {
-           all = ST(2);
+           all = ST(1);
        }
         {
-            re = Perl_get_re_arg( aTHX_ qr, 1, NULL);
             if (SvPOK(sv) && re && re->paren_names) {
                 bufs = CALLREG_NAMEDBUF(re,sv,all && SvTRUE(all));
                 if (bufs) {
@@ -1204,30 +1187,22 @@ XS(XS_re_regnames)
 {
     dVAR; 
     dXSARGS;
-    if (items < 0 || items > 2)
-       Perl_croak(aTHX_ "Usage: %s(%s)", "re::regnames", "sv = NULL, all = NULL");
+    if (items < 0 || items > 1)
+       Perl_croak(aTHX_ "Usage: %s(%s)", "re::regnames", "[all]");
     PERL_UNUSED_VAR(cv); /* -W */
     PERL_UNUSED_VAR(ax); /* -Wall */
     SP -= items;
     {
-       SV *    sv;
        SV *    all;
-        regexp *re = NULL;
+        regexp *re = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
         IV count = 0;
 
        if (items < 1)
-           sv = NULL;
-       else {
-           sv = ST(0);
-       }
-
-       if (items < 2)
            all = NULL;
        else {
-           all = ST(1);
+           all = ST(0);
        }
         {
-            re = Perl_get_re_arg( aTHX_  sv, 1, NULL );
             if (re && re->paren_names) {
                 HV *hv= re->paren_names;
                 (void)hv_iterinit(hv);
@@ -1240,8 +1215,8 @@ XS(XS_re_regnames)
                         I32 *nums = (I32*)SvPVX(sv_dat);
                         for ( i = 0; i < SvIVX(sv_dat); i++ ) {
                             if ((I32)(re->lastcloseparen) >= nums[i] &&
-                                re->startp[nums[i]] != -1 &&
-                                re->endp[nums[i]] != -1)
+                                re->offs[nums[i]].start != -1 &&
+                                re->offs[nums[i]].end != -1)
                             {
                                 parno = nums[i];
                                 break;
@@ -1274,29 +1249,19 @@ XS(XS_re_regnames_iterinit)
 {
     dVAR; 
     dXSARGS;
-    if (items < 0 || items > 1)
-       Perl_croak(aTHX_ "Usage: %s(%s)", "re::regnames_iterinit", "sv = NULL");
+    if (items != 0)
+       Perl_croak(aTHX_ "Usage: re::regnames_iterinit()");
     PERL_UNUSED_VAR(cv); /* -W */
     PERL_UNUSED_VAR(ax); /* -Wall */
     SP -= items;
     {
-       SV *    sv;
-        regexp *re = NULL;
-
-       if (items < 1)
-           sv = NULL;
-       else {
-           sv = ST(0);
-       }
-        {
-            re = Perl_get_re_arg( aTHX_  sv, 1, NULL );
-            if (re && re->paren_names) {
-                (void)hv_iterinit(re->paren_names);
-                XPUSHs(newSViv(HvTOTALKEYS(re->paren_names)));
-            } else {
-                XSRETURN_UNDEF;
-            }  
-        }
+        regexp *re = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
+        if (re && re->paren_names) {
+            (void)hv_iterinit(re->paren_names);
+            XPUSHs(newSViv(HvTOTALKEYS(re->paren_names)));
+        } else {
+            XSRETURN_UNDEF;
+        }  
        PUTBACK;
        return;
     }
@@ -1307,60 +1272,50 @@ XS(XS_re_regnames_iternext)
 {
     dVAR; 
     dXSARGS;
-    if (items < 0 || items > 2)
-       Perl_croak(aTHX_ "Usage: %s(%s)", "re::regnames_iternext", "sv = NULL, all = NULL");
+    if (items < 0 || items > 1)
+       Perl_croak(aTHX_ "Usage: %s(%s)", "re::regnames_iternext", "[all]");
     PERL_UNUSED_VAR(cv); /* -W */
     PERL_UNUSED_VAR(ax); /* -Wall */
     SP -= items;
     {
-       SV *    sv;
        SV *    all;
-        regexp *re;
+        regexp *re = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
 
        if (items < 1)
-           sv = NULL;
-       else {
-           sv = ST(0);
-       }
-
-       if (items < 2)
            all = NULL;
        else {
-           all = ST(1);
+           all = ST(0);
        }
-        {
-            re = Perl_get_re_arg( aTHX_  sv, 1, NULL ); 
-            if (re && re->paren_names) {
-                HV *hv= re->paren_names;
-                while (1) {
-                    HE *temphe = hv_iternext_flags(hv,0);
-                    if (temphe) {
-                        IV i;
-                        IV parno = 0;
-                        SV* sv_dat = HeVAL(temphe);
-                        I32 *nums = (I32*)SvPVX(sv_dat);
-                        for ( i = 0; i < SvIVX(sv_dat); i++ ) {
-                            if ((I32)(re->lastcloseparen) >= nums[i] &&
-                                re->startp[nums[i]] != -1 &&
-                                re->endp[nums[i]] != -1)
-                            {
-                                parno = nums[i];
-                                break;
-                            }
+        if (re && re->paren_names) {
+            HV *hv= re->paren_names;
+            while (1) {
+                HE *temphe = hv_iternext_flags(hv,0);
+                if (temphe) {
+                    IV i;
+                    IV parno = 0;
+                    SV* sv_dat = HeVAL(temphe);
+                    I32 *nums = (I32*)SvPVX(sv_dat);
+                    for ( i = 0; i < SvIVX(sv_dat); i++ ) {
+                        if ((I32)(re->lastcloseparen) >= nums[i] &&
+                            re->offs[nums[i]].start != -1 &&
+                            re->offs[nums[i]].end != -1)
+                        {
+                            parno = nums[i];
+                            break;
                         }
-                        if (parno || (all && SvTRUE(all))) {
-                            STRLEN len;
-                            char *pv = HePV(temphe, len);
-                            XPUSHs(newSVpvn(pv,len));
-                            XSRETURN(1);    
-                        }
-                    } else {
-                        break;
                     }
+                    if (parno || (all && SvTRUE(all))) {
+                        STRLEN len;
+                        char *pv = HePV(temphe, len);
+                        XPUSHs(newSVpvn(pv,len));
+                        XSRETURN(1);    
+                    }
+                } else {
+                    break;
                 }
             }
-            XSRETURN_UNDEF;
-        }    
+        }
+        XSRETURN_UNDEF;
        PUTBACK;
        return;
     }
@@ -1369,22 +1324,16 @@ XS(XS_re_regnames_iternext)
 
 XS(XS_re_regnames_count)
 {
-    SV *       sv;
-    regexp *re = NULL;
+    regexp *re = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
     dVAR; 
     dXSARGS;
 
-    if (items < 0 || items > 1)
-       Perl_croak(aTHX_ "Usage: %s(%s)", "re::regnames_count", "sv = NULL");
+    if (items != 0)
+       Perl_croak(aTHX_ "Usage: %s(%s)", "re::regnames_count", "");
     PERL_UNUSED_VAR(cv); /* -W */
     PERL_UNUSED_VAR(ax); /* -Wall */
     SP -= items;
-    if (items < 1)
-        sv = NULL;
-    else {
-        sv = ST(0);
-    }
-    re = Perl_get_re_arg( aTHX_  sv, 1, NULL );
+    
     if (re && re->paren_names) {
         XPUSHs(newSViv(HvTOTALKEYS(re->paren_names)));
     } else {