Re: [PATCH] A variety of README nitpicks.
[p5sagit/p5-mst-13.2.git] / util.c
diff --git a/util.c b/util.c
index e42efe3..cf793bd 100644 (file)
--- a/util.c
+++ b/util.c
@@ -325,7 +325,7 @@ S_xstat(pTHX_ int flag)
                PerlIO_printf(Perl_debug_log, "  . ");
            }
        }
-       PerlIO_printf(Perl_debug_log, "\n");    
+       PerlIO_printf(Perl_debug_log, "\n");
     }
 }
 
@@ -2155,10 +2155,13 @@ Perl_my_popen(pTHX_ char *cmd, char *mode)
 #endif /* defined OS2 */
        /*SUPPRESS 560*/
        if ((tmpgv = gv_fetchpv("$",TRUE, SVt_PV))) {
-        SvREADONLY_off(GvSV(tmpgv));
+           SvREADONLY_off(GvSV(tmpgv));
            sv_setiv(GvSV(tmpgv), PerlProc_getpid());
-        SvREADONLY_on(GvSV(tmpgv));
-    }
+           SvREADONLY_on(GvSV(tmpgv));
+       }
+#ifdef THREADS_HAVE_PIDS
+       PL_ppid = (IV)getppid();
+#endif
        PL_forkprocess = 0;
        hv_clear(PL_pidstatus); /* we have no children */
        return Nullfp;
@@ -2349,6 +2352,12 @@ Perl_rsignal(pTHX_ int signo, Sighandler_t handler)
 {
     struct sigaction act, oact;
 
+#ifdef USE_ITHREADS
+    /* only "parent" interpreter can diddle signals */
+    if (PL_curinterp != aTHX)
+       return SIG_ERR;
+#endif
+
     act.sa_handler = handler;
     sigemptyset(&act.sa_mask);
     act.sa_flags = 0;
@@ -2383,6 +2392,12 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save)
 {
     struct sigaction act;
 
+#ifdef USE_ITHREADS
+    /* only "parent" interpreter can diddle signals */
+    if (PL_curinterp != aTHX)
+       return -1;
+#endif
+
     act.sa_handler = handler;
     sigemptyset(&act.sa_mask);
     act.sa_flags = 0;
@@ -2401,6 +2416,12 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save)
 int
 Perl_rsignal_restore(pTHX_ int signo, Sigsave_t *save)
 {
+#ifdef USE_ITHREADS
+    /* only "parent" interpreter can diddle signals */
+    if (PL_curinterp != aTHX)
+       return -1;
+#endif
+
     return sigaction(signo, save, (struct sigaction *)NULL);
 }
 
@@ -2409,6 +2430,12 @@ Perl_rsignal_restore(pTHX_ int signo, Sigsave_t *save)
 Sighandler_t
 Perl_rsignal(pTHX_ int signo, Sighandler_t handler)
 {
+#if defined(USE_ITHREADS) && !defined(WIN32)
+    /* only "parent" interpreter can diddle signals */
+    if (PL_curinterp != aTHX)
+       return SIG_ERR;
+#endif
+
     return PerlProc_signal(signo, handler);
 }
 
@@ -2427,6 +2454,12 @@ Perl_rsignal_state(pTHX_ int signo)
 {
     Sighandler_t oldsig;
 
+#if defined(USE_ITHREADS) && !defined(WIN32)
+    /* only "parent" interpreter can diddle signals */
+    if (PL_curinterp != aTHX)
+       return SIG_ERR;
+#endif
+
     sig_trapped = 0;
     oldsig = PerlProc_signal(signo, sig_trap);
     PerlProc_signal(signo, oldsig);
@@ -2438,6 +2471,11 @@ Perl_rsignal_state(pTHX_ int signo)
 int
 Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save)
 {
+#if defined(USE_ITHREADS) && !defined(WIN32)
+    /* only "parent" interpreter can diddle signals */
+    if (PL_curinterp != aTHX)
+       return -1;
+#endif
     *save = PerlProc_signal(signo, handler);
     return (*save == SIG_ERR) ? -1 : 0;
 }
@@ -2445,6 +2483,11 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save)
 int
 Perl_rsignal_restore(pTHX_ int signo, Sigsave_t *save)
 {
+#if defined(USE_ITHREADS) && !defined(WIN32)
+    /* only "parent" interpreter can diddle signals */
+    if (PL_curinterp != aTHX)
+       return -1;
+#endif
     return (PerlProc_signal(signo, *save) == SIG_ERR) ? -1 : 0;
 }
 
@@ -2821,7 +2864,7 @@ Perl_find_script(pTHX_ char *scriptname, bool dosearch, char **search_ext, I32 f
 #endif
     {
        bool seen_dot = 0;
-       
+
        PL_bufend = s + strlen(s);
        while (s < PL_bufend) {
 #ifdef MACOS_TRADITIONAL
@@ -3441,8 +3484,6 @@ Perl_my_fflush_all(pTHX)
 void
 Perl_report_evil_fh(pTHX_ GV *gv, IO *io, I32 op)
 {
-    char *vile;
-    I32   warn_type;
     char *func =
        op == OP_READLINE   ? "readline"  :     /* "<HANDLE>" not nice */
        op == OP_LEAVEWRITE ? "write" :         /* "write exit" not nice */
@@ -3453,42 +3494,53 @@ Perl_report_evil_fh(pTHX_ GV *gv, IO *io, I32 op)
                      "socket" : "filehandle";
     char *name = NULL;
 
-    if (gv && io && IoTYPE(io) == IoTYPE_CLOSED) {
-       vile = "closed";
-       warn_type = WARN_CLOSED;
-    }
-    else {
-       vile = "unopened";
-       warn_type = WARN_UNOPENED;
-    }
-
     if (gv && isGV(gv)) {
        name = GvENAME(gv);
     }
 
     if (op == OP_phoney_OUTPUT_ONLY || op == OP_phoney_INPUT_ONLY) {
-       if (name && *name)
-           Perl_warner(aTHX_ packWARN(WARN_IO), "Filehandle %s opened only for %sput",
-                       name,
-                       (op == OP_phoney_INPUT_ONLY ? "in" : "out"));
-       else
-           Perl_warner(aTHX_ packWARN(WARN_IO), "Filehandle opened only for %sput",
-                       (op == OP_phoney_INPUT_ONLY ? "in" : "out"));
-    } else if (name && *name) {
-       Perl_warner(aTHX_ packWARN(warn_type),
-                   "%s%s on %s %s %s", func, pars, vile, type, name);
-       if (io && IoDIRP(io) && !(IoFLAGS(io) & IOf_FAKE_DIRP))
-           Perl_warner(aTHX_ packWARN(warn_type),
-                       "\t(Are you trying to call %s%s on dirhandle %s?)\n",
-                       func, pars, name);
+        if (ckWARN(WARN_IO)) {
+            if (name && *name)
+                Perl_warner(aTHX_ packWARN(WARN_IO),
+                            "Filehandle %s opened only for %sput",
+                            name, (op == OP_phoney_INPUT_ONLY ? "in" : "out"));
+            else
+                Perl_warner(aTHX_ packWARN(WARN_IO),
+                            "Filehandle opened only for %sput",
+                            (op == OP_phoney_INPUT_ONLY ? "in" : "out"));
+        }
     }
     else {
-       Perl_warner(aTHX_ packWARN(warn_type),
-                   "%s%s on %s %s", func, pars, vile, type);
-       if (gv && io && IoDIRP(io) && !(IoFLAGS(io) & IOf_FAKE_DIRP))
-           Perl_warner(aTHX_ packWARN(warn_type),
-                       "\t(Are you trying to call %s%s on dirhandle?)\n",
-                       func, pars);
+        char *vile;
+        I32   warn_type;
+
+        if (gv && io && IoTYPE(io) == IoTYPE_CLOSED) {
+            vile = "closed";
+            warn_type = WARN_CLOSED;
+        }
+        else {
+            vile = "unopened";
+            warn_type = WARN_UNOPENED;
+        }
+
+        if (ckWARN(warn_type)) {
+            if (name && *name) {
+                Perl_warner(aTHX_ packWARN(warn_type),
+                            "%s%s on %s %s %s", func, pars, vile, type, name);
+                if (io && IoDIRP(io) && !(IoFLAGS(io) & IOf_FAKE_DIRP))
+                    Perl_warner(aTHX_ packWARN(warn_type),
+                                "\t(Are you trying to call %s%s on dirhandle %s?)\n",
+                                func, pars, name);
+            }
+            else {
+                Perl_warner(aTHX_ packWARN(warn_type),
+                            "%s%s on %s %s", func, pars, vile, type);
+                if (gv && io && IoDIRP(io) && !(IoFLAGS(io) & IOf_FAKE_DIRP))
+                    Perl_warner(aTHX_ packWARN(warn_type),
+                                "\t(Are you trying to call %s%s on dirhandle?)\n",
+                                func, pars);
+            }
+        }
     }
 }
 
@@ -4003,26 +4055,27 @@ Perl_getcwd_sv(pTHX_ register SV *sv)
 /*
 =head1 SV Manipulation Functions
 
-=for apidoc new_vstring
+=for apidoc scan_vstring
 
 Returns a pointer to the next character after the parsed
 vstring, as well as updating the passed in sv.
 
 Function must be called like
 
-        sv = NEWSV(92,5);
-       s = new_vstring(s,sv);
+       sv = NEWSV(92,5);
+       s = scan_vstring(s,sv);
 
-The sv must already be large enough to store the vstring
-passed in.
+The sv should already be large enough to store the vstring
+passed in, for performance reasons.
 
 =cut
 */
 
 char *
-Perl_new_vstring(pTHX_ char *s, SV *sv)
+Perl_scan_vstring(pTHX_ char *s, SV *sv)
 {
     char *pos = s;
+    char *start = s;
     if (*pos == 'v') pos++;  /* get past 'v' */
     while (isDIGIT(*pos) || *pos == '_')
     pos++;
@@ -4038,21 +4091,20 @@ Perl_new_vstring(pTHX_ char *s, SV *sv)
        for (;;) {
            rev = 0;
            {
-                /* this is atoi() that tolerates underscores */
-                char *end = pos;
-                UV mult = 1;
-                if ( s > pos && *(s-1) == '_') {
-                     mult = 10;
-                }
-                while (--end >= s) {
-                     UV orev;
-                     orev = rev;
-                     rev += (*end - '0') * mult;
-                     mult *= 10;
-                     if (orev > rev && ckWARN_d(WARN_OVERFLOW))
-                          Perl_warner(aTHX_ packWARN(WARN_OVERFLOW),
-                                      "Integer overflow in decimal number");
-                }
+               /* this is atoi() that tolerates underscores */
+               char *end = pos;
+               UV mult = 1;
+               while (--end >= s) {
+                   UV orev;
+                   if (*end == '_')
+                       continue;
+                   orev = rev;
+                   rev += (*end - '0') * mult;
+                   mult *= 10;
+                   if (orev > rev && ckWARN_d(WARN_OVERFLOW))
+                       Perl_warner(aTHX_ packWARN(WARN_OVERFLOW),
+                                   "Integer overflow in decimal number");
+               }
            }
 #ifdef EBCDIC
            if (rev > 0x7FFFFFFF)
@@ -4063,21 +4115,208 @@ Perl_new_vstring(pTHX_ char *s, SV *sv)
            sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
            if (!UNI_IS_INVARIANT(NATIVE_TO_UNI(rev)))
                 SvUTF8_on(sv);
-           if ( (*pos == '.' || *pos == '_') && isDIGIT(pos[1]))
+           if (*pos == '.' && isDIGIT(pos[1]))
                 s = ++pos;
            else {
                 s = pos;
                 break;
            }
-           while (isDIGIT(*pos) )
+           while (isDIGIT(*pos) || *pos == '_')
                 pos++;
        }
        SvPOK_on(sv);
-       SvREADONLY_on(sv);
+       sv_magicext(sv,NULL,PERL_MAGIC_vstring,NULL,(const char*)start, pos-start);
+       SvRMAGICAL_on(sv);
     }
     return s;
 }
 
+
+/*
+=for apidoc scan_version
+
+Returns a pointer to the next character after the parsed
+version string, as well as upgrading the passed in SV to
+an RV.
+
+Function must be called with an already existing SV like
+
+    sv = NEWSV(92,0);
+    s = scan_version(s,sv);
+
+Performs some preprocessing to the string to ensure that
+it has the correct characteristics of a version.  Flags the
+object if it contains an underscore (which denotes this
+is a beta version).
+
+=cut
+*/
+
+char *
+Perl_scan_version(pTHX_ char *version, SV *rv)
+{
+    char* d;
+    int beta = 0;
+    SV* sv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */
+    d = version;
+    if (*d == 'v')
+       d++;
+    if (isDIGIT(*d)) {
+       while (isDIGIT(*d) || *d == '.' || *d == '\0')
+           d++;
+       if (*d == '_') {
+           *d = '.';
+           if (*(d+1) == '0' && *(d+2) != '0') { /* perl-style version */
+               *(d+1) = *(d+2);
+               *(d+2) = '0';
+               if (ckWARN(WARN_PORTABLE))
+                   Perl_warner(aTHX_ packWARN(WARN_PORTABLE),
+                               "perl-style version not portable");
+           }
+           else {
+               beta = -1;
+           }
+       }
+       while (isDIGIT(*d) || *d == '.' || *d == '\0')
+           d++;
+       if (*d == '_')
+           Perl_croak(aTHX_ "Invalid version format (multiple underscores)");
+    }
+    version = scan_vstring(version, sv); /* store the v-string in the object */
+    SvIVX(sv) = beta;
+    return version;
+}
+
+/*
+=for apidoc new_version
+
+Returns a new version object based on the passed in SV:
+
+    SV *sv = new_version(SV *ver);
+
+Does not alter the passed in ver SV.  See "upg_version" if you
+want to upgrade the SV.
+
+=cut
+*/
+
+SV *
+Perl_new_version(pTHX_ SV *ver)
+{
+    SV *rv = NEWSV(92,5);
+    char *version;
+
+    if ( SvMAGICAL(ver) ) { /* already a v-string */
+       MAGIC* mg = mg_find(ver,PERL_MAGIC_vstring);
+       version = savepvn( (const char*)mg->mg_ptr,mg->mg_len );
+    }
+    else {
+       version = (char *)SvPV_nolen(ver);
+    }
+    version = scan_version(version,rv);
+    return rv;
+}
+
+/*
+=for apidoc upg_version
+
+In-place upgrade of the supplied SV to a version object.
+
+    SV *sv = upg_version(SV *sv);
+
+Returns a pointer to the upgraded SV.
+
+=cut
+*/
+
+SV *
+Perl_upg_version(pTHX_ SV *sv)
+{
+    char *version = (char *)SvPV_nolen(sv_mortalcopy(sv));
+    bool utf8 = SvUTF8(sv);
+    if ( SvVOK(sv) ) { /* already a v-string */
+       SV * ver = newSVrv(sv, "version");
+       sv_setpv(ver,version);
+       if ( utf8 )
+           SvUTF8_on(ver);
+    }
+    else {
+       version = scan_version(version,sv);
+    }
+    return sv;
+}
+
+
+/*
+=for apidoc vnumify
+
+Accepts a version (or vstring) object and returns the
+normalized floating point representation.  Call like:
+
+    sv = vnumify(sv,SvRV(rv));
+
+NOTE: no checking is done to see if the object is of the
+correct type (for speed).
+
+=cut
+*/
+
+SV *
+Perl_vnumify(pTHX_ SV *sv, SV *vs)
+{
+    U8* pv = (U8*)SvPVX(vs);
+    STRLEN len = SvCUR(vs);
+    STRLEN retlen;
+    UV digit = utf8_to_uvchr(pv,&retlen);
+    Perl_sv_setpvf(aTHX_ sv,"%"UVf".",digit);
+    for (pv += retlen, len -= retlen;
+       len > 0;
+       pv += retlen, len -= retlen)
+    {
+       digit = utf8_to_uvchr(pv,&retlen);
+       Perl_sv_catpvf(aTHX_ sv,"%03"UVf,digit);
+    }
+    return sv;
+}
+
+/*
+=for apidoc vstringify
+
+Accepts a version (or vstring) object and returns the
+normalized representation.  Call like:
+
+    sv = vstringify(sv,SvRV(rv));
+
+NOTE: no checking is done to see if the object is of the
+correct type (for speed).
+
+=cut
+*/
+
+SV *
+Perl_vstringify(pTHX_ SV *sv, SV *vs)
+{
+    U8* pv = (U8*)SvPVX(vs);
+    STRLEN len = SvCUR(vs);
+    STRLEN retlen;
+    UV digit = utf8_to_uvchr(pv,&retlen);
+    Perl_sv_setpvf(aTHX_ sv,"%"UVf,digit);
+    for (pv += retlen, len -= retlen;
+       len > 0;
+       pv += retlen, len -= retlen)
+    {
+       digit = utf8_to_uvchr(pv,&retlen);
+       Perl_sv_catpvf(aTHX_ sv,".%"UVf,digit);
+    }
+    if (SvIVX(vs) < 0) {
+       char* pv = SvPVX(sv); 
+       for (pv += SvCUR(sv); *pv != '.'; pv--)
+           ;
+       *pv = '_';
+    }
+    return sv;
+}
+
 #if !defined(HAS_SOCKETPAIR) && defined(HAS_SOCKET) && defined(AF_INET) && defined(PF_INET) && defined(SOCK_DGRAM) && defined(HAS_SELECT)
 #   define EMULATE_SOCKETPAIR_UDP
 #endif