X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=util.c;h=8fa774f189d810ee5892f8df383245fb638b34c4;hb=c067b4bea65bd7b97b0ae4f7b058dd94b44a4c48;hp=74f594426923de888bc877be056d93ce04bd5968;hpb=e352bcff231c07cf21f07ae801f374a3da3229ed;p=p5sagit%2Fp5-mst-13.2.git diff --git a/util.c b/util.c index 74f5944..8fa774f 100644 --- a/util.c +++ b/util.c @@ -921,7 +921,7 @@ Perl_form(pTHX_ const char* pat, ...) char * Perl_vform(pTHX_ const char *pat, va_list *args) { - SV *sv = mess_alloc(); + SV * const sv = mess_alloc(); sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); return SvPVX(sv); } @@ -1278,6 +1278,8 @@ Perl_vwarn(pTHX_ const char* pat, va_list *args) SV *msg; ENTER; + SAVESPTR(PL_warnhook); + PL_warnhook = Nullsv; save_re_context(); msg = newSVpvn(message, msglen); SvFLAGS(msg) |= utf8; @@ -1494,19 +1496,39 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val) } else { # endif # if defined(__CYGWIN__) || defined(EPOC) || defined(SYMBIAN) - setenv(nam, val, 1); +# if defined(HAS_UNSETENV) + if (val == NULL) { + (void)unsetenv(nam); + } else { + (void)setenv(nam, val, 1); + } +# else /* ! HAS_UNSETENV */ + (void)setenv(nam, val, 1); +# endif /* HAS_UNSETENV */ # else - char *new_env; - const int nlen = strlen(nam); - int vlen; - if (!val) { - val = ""; - } - vlen = strlen(val); - new_env = (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char)); - /* all that work just for this */ - my_setenv_format(new_env, nam, nlen, val, vlen); - (void)putenv(new_env); +# if defined(HAS_UNSETENV) + if (val == NULL) { + (void)unsetenv(nam); + } else { + int nlen = strlen(nam); + int vlen = strlen(val); + char *new_env = + (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char)); + my_setenv_format(new_env, nam, nlen, val, vlen); + (void)putenv(new_env); + } +# else /* ! HAS_UNSETENV */ + char *new_env; + int nlen = strlen(nam), vlen; + if (!val) { + val = ""; + } + vlen = strlen(val); + new_env = (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char)); + /* all that work just for this */ + my_setenv_format(new_env, nam, nlen, val, vlen); + (void)putenv(new_env); +# endif /* HAS_UNSETENV */ # endif /* __CYGWIN__ */ #ifndef PERL_USE_SAFE_PUTENV } @@ -1561,7 +1583,7 @@ Perl_setenv_getix(pTHX_ const char *nam) #ifdef UNLINK_ALL_VERSIONS I32 -Perl_unlnk(pTHX_ char *f) /* unlink all versions of a file */ +Perl_unlnk(pTHX_ const char *f) /* unlink all versions of a file */ { I32 i; @@ -1575,7 +1597,7 @@ Perl_unlnk(pTHX_ char *f) /* unlink all versions of a file */ char * Perl_my_bcopy(register const char *from,register char *to,register I32 len) { - char *retval = to; + char * const retval = to; if (from - to >= 0) { while (len--) @@ -1596,7 +1618,7 @@ Perl_my_bcopy(register const char *from,register char *to,register I32 len) void * Perl_my_memset(register char *loc, register I32 ch, register I32 len) { - char *retval = loc; + char * const retval = loc; while (len--) *loc++ = ch; @@ -1609,7 +1631,7 @@ Perl_my_memset(register char *loc, register I32 ch, register I32 len) char * Perl_my_bzero(register char *loc, register I32 len) { - char *retval = loc; + char * const retval = loc; while (len--) *loc++ = 0; @@ -2121,13 +2143,13 @@ Perl_my_popen_list(pTHX_ char *mode, int n, SV **args) /* VMS' my_popen() is in VMS.c, same with OS/2. */ #if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__OPEN_VM) && !defined(EPOC) && !defined(MACOS_TRADITIONAL) PerlIO * -Perl_my_popen(pTHX_ char *cmd, char *mode) +Perl_my_popen(pTHX_ const char *cmd, const char *mode) { int p[2]; register I32 This, that; register Pid_t pid; SV *sv; - I32 doexec = !(*cmd == '-' && cmd[1] == '\0'); + const I32 doexec = !(*cmd == '-' && cmd[1] == '\0'); I32 did_pipes = 0; int pp[2]; @@ -2411,10 +2433,10 @@ Perl_rsignal(pTHX_ int signo, Sighandler_t handler) #ifdef USE_ITHREADS /* only "parent" interpreter can diddle signals */ if (PL_curinterp != aTHX) - return SIG_ERR; + return (Sighandler_t) SIG_ERR; #endif - act.sa_handler = handler; + act.sa_handler = (void(*)(int))handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_RESTART @@ -2422,13 +2444,13 @@ Perl_rsignal(pTHX_ int signo, Sighandler_t handler) act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */ #endif #if defined(SA_NOCLDWAIT) && !defined(BSDish) /* See [perl #18849] */ - if (signo == SIGCHLD && handler == (Sighandler_t)SIG_IGN) + if (signo == SIGCHLD && handler == (Sighandler_t) SIG_IGN) act.sa_flags |= SA_NOCLDWAIT; #endif if (sigaction(signo, &act, &oact) == -1) - return SIG_ERR; + return (Sighandler_t) SIG_ERR; else - return oact.sa_handler; + return (Sighandler_t) oact.sa_handler; } Sighandler_t @@ -2437,9 +2459,9 @@ Perl_rsignal_state(pTHX_ int signo) struct sigaction oact; if (sigaction(signo, (struct sigaction *)NULL, &oact) == -1) - return SIG_ERR; + return (Sighandler_t) SIG_ERR; else - return oact.sa_handler; + return (Sighandler_t) oact.sa_handler; } int @@ -2454,7 +2476,7 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save) return -1; #endif - act.sa_handler = handler; + act.sa_handler = (void(*)(int))handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_RESTART @@ -2462,7 +2484,7 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save) act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */ #endif #if defined(SA_NOCLDWAIT) && !defined(BSDish) /* See [perl #18849] */ - if (signo == SIGCHLD && handler == (Sighandler_t)SIG_IGN) + if (signo == SIGCHLD && handler == (Sighandler_t) SIG_IGN) act.sa_flags |= SA_NOCLDWAIT; #endif return sigaction(signo, &act, save); @@ -2489,7 +2511,7 @@ 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; + return (Sighandler_t) SIG_ERR; #endif return PerlProc_signal(signo, handler); @@ -2512,7 +2534,7 @@ Perl_rsignal_state(pTHX_ int signo) #if defined(USE_ITHREADS) && !defined(WIN32) /* only "parent" interpreter can diddle signals */ if (PL_curinterp != aTHX) - return SIG_ERR; + return (Sighandler_t) SIG_ERR; #endif PL_sig_trapped = 0; @@ -2532,7 +2554,7 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save) return -1; #endif *save = PerlProc_signal(signo, handler); - return (*save == SIG_ERR) ? -1 : 0; + return (*save == (Sighandler_t) SIG_ERR) ? -1 : 0; } int @@ -2543,7 +2565,7 @@ Perl_rsignal_restore(pTHX_ int signo, Sigsave_t *save) if (PL_curinterp != aTHX) return -1; #endif - return (PerlProc_signal(signo, *save) == SIG_ERR) ? -1 : 0; + return (PerlProc_signal(signo, *save) == (Sighandler_t) SIG_ERR) ? -1 : 0; } #endif /* !HAS_SIGACTION */ @@ -2586,9 +2608,9 @@ Perl_my_pclose(pTHX_ PerlIO *ptr) if(PerlProc_kill(pid, 0) < 0) { return(pid); } /* HOM 12/23/91 */ #endif #ifndef PERL_MICRO - rsignal_save(SIGHUP, SIG_IGN, &hstat); - rsignal_save(SIGINT, SIG_IGN, &istat); - rsignal_save(SIGQUIT, SIG_IGN, &qstat); + rsignal_save(SIGHUP, (Sighandler_t) SIG_IGN, &hstat); + rsignal_save(SIGINT, (Sighandler_t) SIG_IGN, &istat); + rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qstat); #endif do { pid2 = wait4pid(pid, &status, 0); @@ -2784,7 +2806,8 @@ Perl_same_dirent(pTHX_ const char *a, const char *b) #endif /* !HAS_RENAME */ char* -Perl_find_script(pTHX_ const char *scriptname, bool dosearch, const char **search_ext, I32 flags) +Perl_find_script(pTHX_ const char *scriptname, bool dosearch, + const char *const *const search_ext, I32 flags) { const char *xfound = Nullch; char *xfailed = Nullch; @@ -2806,8 +2829,8 @@ Perl_find_script(pTHX_ const char *scriptname, bool dosearch, const char **searc #endif /* additional extensions to try in each dir if scriptname not found */ #ifdef SEARCH_EXTS - const char *exts[] = { SEARCH_EXTS }; - const char **ext = search_ext ? search_ext : exts; + const char *const exts[] = { SEARCH_EXTS }; + const char *const *const ext = search_ext ? search_ext : exts; int extidx = 0, i = 0; const char *curext = Nullch; #else @@ -3876,57 +3899,59 @@ it doesn't. const char * Perl_scan_version(pTHX_ const char *s, SV *rv, bool qv) { - const char *start = s; + const char *start; const char *pos; const char *last; int saw_period = 0; - int saw_under = 0; + int alpha = 0; int width = 3; AV *av = newAV(); - SV* hv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */ + SV *hv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */ (void)sv_upgrade(hv, SVt_PVHV); /* needs to be an HV type */ + #ifndef NODEFAULT_SHAREKEYS HvSHAREKEYS_on(hv); /* key-sharing on by default */ #endif + while (isSPACE(*s)) /* leading whitespace is OK */ + s++; + if (*s == 'v') { s++; /* get past 'v' */ qv = 1; /* force quoted version processing */ } - last = pos = s; + start = last = pos = s; /* pre-scan the input string to check for decimals/underbars */ while ( *pos == '.' || *pos == '_' || isDIGIT(*pos) ) { if ( *pos == '.' ) { - if ( saw_under ) + if ( alpha ) Perl_croak(aTHX_ "Invalid version format (underscores before decimal)"); saw_period++ ; last = pos; } else if ( *pos == '_' ) { - if ( saw_under ) + if ( alpha ) Perl_croak(aTHX_ "Invalid version format (multiple underscores)"); - saw_under = 1; + alpha = 1; width = pos - last - 1; /* natural width of sub-version */ } pos++; } - if ( saw_period > 1 ) { + if ( saw_period > 1 ) qv = 1; /* force quoted version processing */ - } pos = s; if ( qv ) - hv_store((HV *)hv, "qv", 2, &PL_sv_yes, 0); - if ( saw_under ) { - hv_store((HV *)hv, "alpha", 5, &PL_sv_yes, 0); - } + hv_store((HV *)hv, "qv", 2, newSViv(qv), 0); + if ( alpha ) + hv_store((HV *)hv, "alpha", 5, newSViv(alpha), 0); if ( !qv && width < 3 ) hv_store((HV *)hv, "width", 5, newSViv(width), 0); @@ -3947,7 +3972,7 @@ Perl_scan_version(pTHX_ const char *s, SV *rv, bool qv) * point of a version originally created with a bare * floating point number, i.e. not quoted in any way */ - if ( !qv && s > start+1 && saw_period == 1 ) { + if ( !qv && s > start && saw_period == 1 ) { mult *= 100; while ( s < end ) { orev = rev; @@ -4015,7 +4040,7 @@ Perl_scan_version(pTHX_ const char *s, SV *rv, bool qv) av_push(av, newSViv(0)); /* And finally, store the AV in the hash */ - hv_store((HV *)hv, "version", 7, (SV *)av, 0); + hv_store((HV *)hv, "version", 7, newRV_noinc((SV *)av), 0); return s; } @@ -4035,14 +4060,14 @@ want to upgrade the SV. SV * Perl_new_version(pTHX_ SV *ver) { - SV *rv = newSV(0); + SV * const rv = newSV(0); if ( sv_derived_from(ver,"version") ) /* can just copy directly */ { I32 key; AV * const av = newAV(); AV *sav; /* This will get reblessed later if a derived class*/ - SV* const hv = newSVrv(rv, "version"); + SV * const hv = newSVrv(rv, "version"); (void)sv_upgrade(hv, SVt_PVHV); /* needs to be an HV type */ #ifndef NODEFAULT_SHAREKEYS HvSHAREKEYS_on(hv); /* key-sharing on by default */ @@ -4064,7 +4089,7 @@ Perl_new_version(pTHX_ SV *ver) hv_store((HV *)hv, "width", 5, newSViv(width), 0); } - sav = (AV *)*hv_fetch((HV*)ver, "version", 7, FALSE); + sav = (AV *)SvRV(*hv_fetch((HV*)ver, "version", 7, FALSE)); /* This will get reblessed later if a derived class*/ for ( key = 0; key <= av_len(sav); key++ ) { @@ -4072,15 +4097,14 @@ Perl_new_version(pTHX_ SV *ver) av_push(av, newSViv(rev)); } - hv_store((HV *)hv, "version", 7, (SV *)av, 0); + hv_store((HV *)hv, "version", 7, newRV_noinc((SV *)av), 0); return rv; } #ifdef SvVOK if ( SvVOK(ver) ) { /* already a v-string */ - char *version; - MAGIC* mg = mg_find(ver,PERL_MAGIC_vstring); + const MAGIC* const mg = mg_find(ver,PERL_MAGIC_vstring); const STRLEN len = mg->mg_len; - version = savepvn( (const char*)mg->mg_ptr, len); + char * const version = savepvn( (const char*)mg->mg_ptr, len); sv_setpvn(rv,version,len); Safefree(version); } @@ -4120,7 +4144,7 @@ Perl_upg_version(pTHX_ SV *ver) } #ifdef SvVOK else if ( SvVOK(ver) ) { /* already a v-string */ - MAGIC* mg = mg_find(ver,PERL_MAGIC_vstring); + const MAGIC* const mg = mg_find(ver,PERL_MAGIC_vstring); version = savepvn( (const char*)mg->mg_ptr,mg->mg_len ); qv = 1; } @@ -4134,6 +4158,45 @@ Perl_upg_version(pTHX_ SV *ver) return ver; } +/* +=for apidoc vverify + +Validates that the SV contains a valid version object. + + bool vverify(SV *vobj); + +Note that it only confirms the bare minimum structure (so as not to get +confused by derived classes which may contain additional hash entries): + +=over 4 + +=item * The SV contains a [reference to a] hash + +=item * The hash contains a "version" key + +=item * The "version" key has [a reference to] an AV as its value + +=back + +=cut +*/ + +bool +Perl_vverify(pTHX_ SV *vs) +{ + SV *sv; + if ( SvROK(vs) ) + vs = SvRV(vs); + + /* see if the appropriate elements exist */ + if ( SvTYPE(vs) == SVt_PVHV + && hv_exists((HV*)vs, "version", 7) + && (sv = SvRV(*hv_fetch((HV*)vs, "version", 7, FALSE))) + && SvTYPE(sv) == SVt_PVAV ) + return TRUE; + else + return FALSE; +} /* =for apidoc vnumify @@ -4160,6 +4223,9 @@ Perl_vnumify(pTHX_ SV *vs) if ( SvROK(vs) ) vs = SvRV(vs); + if ( !vverify(vs) ) + Perl_croak(aTHX_ "Invalid version object"); + /* see if various flags exist */ if ( hv_exists((HV*)vs, "alpha", 5 ) ) alpha = TRUE; @@ -4170,7 +4236,7 @@ Perl_vnumify(pTHX_ SV *vs) /* attempt to retrieve the version array */ - if ( !(av = (AV *)*hv_fetch((HV*)vs, "version", 7, FALSE) ) ) { + if ( !(av = (AV *)SvRV(*hv_fetch((HV*)vs, "version", 7, FALSE)) ) ) { sv_catpvn(sv,"0",1); return sv; } @@ -4183,17 +4249,17 @@ Perl_vnumify(pTHX_ SV *vs) } digit = SvIV(*av_fetch(av, 0, 0)); - Perl_sv_setpvf(aTHX_ sv,"%d.", (int)PERL_ABS(digit)); + Perl_sv_setpvf(aTHX_ sv, "%d.", (int)PERL_ABS(digit)); for ( i = 1 ; i < len ; i++ ) { digit = SvIV(*av_fetch(av, i, 0)); if ( width < 3 ) { const int denom = (int)pow(10,(3-width)); const div_t term = div((int)PERL_ABS(digit),denom); - Perl_sv_catpvf(aTHX_ sv,"%0*d_%d", width, term.quot, term.rem); + Perl_sv_catpvf(aTHX_ sv, "%0*d_%d", width, term.quot, term.rem); } else { - Perl_sv_catpvf(aTHX_ sv,"%0*d", width, (int)digit); + Perl_sv_catpvf(aTHX_ sv, "%0*d", width, (int)digit); } } @@ -4201,14 +4267,12 @@ Perl_vnumify(pTHX_ SV *vs) { digit = SvIV(*av_fetch(av, len, 0)); if ( alpha && width == 3 ) /* alpha version */ - Perl_sv_catpv(aTHX_ sv,"_"); - /* Don't display additional trailing zeros */ - if ( digit > 0 ) - Perl_sv_catpvf(aTHX_ sv,"%0*d", width, (int)digit); + sv_catpvn(sv,"_",1); + Perl_sv_catpvf(aTHX_ sv, "%0*d", width, (int)digit); } - else /* len == 1 */ + else /* len == 0 */ { - sv_catpvn(sv,"000",3); + sv_catpvn(sv,"000",3); } return sv; } @@ -4232,28 +4296,33 @@ Perl_vnormal(pTHX_ SV *vs) { I32 i, len, digit; bool alpha = FALSE; - SV *sv = newSV(0); + SV * const sv = newSV(0); AV *av; if ( SvROK(vs) ) vs = SvRV(vs); + if ( !vverify(vs) ) + Perl_croak(aTHX_ "Invalid version object"); + if ( hv_exists((HV*)vs, "alpha", 5 ) ) alpha = TRUE; - av = (AV *)*hv_fetch((HV*)vs, "version", 7, FALSE); + av = (AV *)SvRV(*hv_fetch((HV*)vs, "version", 7, FALSE)); len = av_len(av); - if ( len == -1 ) { + if ( len == -1 ) + { sv_catpvn(sv,"",0); return sv; } digit = SvIV(*av_fetch(av, 0, 0)); - Perl_sv_setpvf(aTHX_ sv,"v%"IVdf,(IV)digit); - for ( i = 1 ; i <= len-1 ; i++ ) { + Perl_sv_setpvf(aTHX_ sv, "v%"IVdf, (IV)digit); + for ( i = 1 ; i < len ; i++ ) { digit = SvIV(*av_fetch(av, i, 0)); Perl_sv_catpvf(aTHX_ sv, ".%"IVdf, (IV)digit); } - if ( len > 0 ) { + if ( len > 0 ) + { /* handle last digit specially */ digit = SvIV(*av_fetch(av, len, 0)); if ( alpha ) @@ -4266,7 +4335,6 @@ Perl_vnormal(pTHX_ SV *vs) for ( len = 2 - len; len != 0; len-- ) sv_catpvn(sv,".0",2); } - return sv; } @@ -4284,14 +4352,13 @@ the original version contained 1 or more dots, respectively SV * Perl_vstringify(pTHX_ SV *vs) { - I32 qv = 0; if ( SvROK(vs) ) vs = SvRV(vs); + if ( !vverify(vs) ) + Perl_croak(aTHX_ "Invalid version object"); + if ( hv_exists((HV *)vs, "qv", 2) ) - qv = 1; - - if ( qv ) return vnormal(vs); else return vnumify(vs); @@ -4320,13 +4387,19 @@ Perl_vcmp(pTHX_ SV *lhv, SV *rhv) if ( SvROK(rhv) ) rhv = SvRV(rhv); + if ( !vverify(lhv) ) + Perl_croak(aTHX_ "Invalid version object"); + + if ( !vverify(rhv) ) + Perl_croak(aTHX_ "Invalid version object"); + /* get the left hand term */ - lav = (AV *)*hv_fetch((HV*)lhv, "version", 7, FALSE); + lav = (AV *)SvRV(*hv_fetch((HV*)lhv, "version", 7, FALSE)); if ( hv_exists((HV*)lhv, "alpha", 5 ) ) lalpha = TRUE; /* and the right hand term */ - rav = (AV *)*hv_fetch((HV*)rhv, "version", 7, FALSE); + rav = (AV *)SvRV(*hv_fetch((HV*)rhv, "version", 7, FALSE)); if ( hv_exists((HV*)rhv, "alpha", 5 ) ) ralpha = TRUE;