X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=util.c;h=48cc63a2535d2a48a2aa1c12fcf640c9f80fd41a;hb=d933dc9eee7771e117a050289ed31b0286699d55;hp=2f5e2c3eca25ecd1e3eb3802aa8cc8358c2f0aa6;hpb=bfce84ec9fb7d74c41a80b7823d3e3c5a1e43f7a;p=p5sagit%2Fp5-mst-13.2.git diff --git a/util.c b/util.c index 2f5e2c3..48cc63a 100644 --- a/util.c +++ b/util.c @@ -1,7 +1,7 @@ /* util.c * * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others + * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 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. @@ -57,6 +57,17 @@ int putenv(char *); * XXX This advice seems to be widely ignored :-( --AD August 1996. */ +static char * +S_write_no_mem(pTHX) +{ + dVAR; + /* Can't use PerlIO to write as it allocates memory */ + PerlLIO_write(PerlIO_fileno(Perl_error_log), + PL_no_mem, strlen(PL_no_mem)); + my_exit(1); + NORETURN_FUNCTION_END; +} + /* paranoid version of system's malloc() */ Malloc_t @@ -71,6 +82,9 @@ Perl_safesysmalloc(MEM_SIZE size) my_exit(1); } #endif /* HAS_64K_LIMIT */ +#ifdef PERL_TRACK_MEMPOOL + size += sTHX; +#endif #ifdef DEBUGGING if ((long)size < 0) Perl_croak_nocontext("panic: malloc"); @@ -78,16 +92,21 @@ Perl_safesysmalloc(MEM_SIZE size) ptr = (Malloc_t)PerlMem_malloc(size?size:1); /* malloc(0) is NASTY on our system */ PERL_ALLOC_CHECK(ptr); DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) malloc %ld bytes\n",PTR2UV(ptr),(long)PL_an++,(long)size)); - if (ptr != Nullch) + if (ptr != Nullch) { +#ifdef PERL_TRACK_MEMPOOL + ((struct perl_memory_debug_header *)ptr)->interpreter = aTHX; +# ifdef PERL_POISON + ((struct perl_memory_debug_header *)ptr)->size = size; + ((struct perl_memory_debug_header *)ptr)->in_use = PERL_POISON_INUSE; +# endif + ptr = (Malloc_t)((char*)ptr+sTHX); +#endif return ptr; +} else if (PL_nomemok) return Nullch; else { - /* Can't use PerlIO to write as it allocates memory */ - PerlLIO_write(PerlIO_fileno(Perl_error_log), - PL_no_mem, strlen(PL_no_mem)); - my_exit(1); - return Nullch; + return write_no_mem(); } /*NOTREACHED*/ } @@ -117,6 +136,22 @@ Perl_safesysrealloc(Malloc_t where,MEM_SIZE size) if (!where) return safesysmalloc(size); +#ifdef PERL_TRACK_MEMPOOL + where = (Malloc_t)((char*)where-sTHX); + size += sTHX; + if (((struct perl_memory_debug_header *)where)->interpreter != aTHX) { + Perl_croak_nocontext("panic: realloc from wrong pool"); + } +# ifdef PERL_POISON + if (((struct perl_memory_debug_header *)where)->size > size) { + const MEM_SIZE freed_up = + ((struct perl_memory_debug_header *)where)->size - size; + char *start_of_freed = ((char *)where) + size; + Poison(start_of_freed, freed_up, char); + } + ((struct perl_memory_debug_header *)where)->size = size; +# endif +#endif #ifdef DEBUGGING if ((long)size < 0) Perl_croak_nocontext("panic: realloc"); @@ -127,16 +162,16 @@ Perl_safesysrealloc(Malloc_t where,MEM_SIZE size) DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) rfree\n",PTR2UV(where),(long)PL_an++)); DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) realloc %ld bytes\n",PTR2UV(ptr),(long)PL_an++,(long)size)); - if (ptr != Nullch) + if (ptr != Nullch) { +#ifdef PERL_TRACK_MEMPOOL + ptr = (Malloc_t)((char*)ptr+sTHX); +#endif return ptr; + } else if (PL_nomemok) return Nullch; else { - /* Can't use PerlIO to write as it allocates memory */ - PerlLIO_write(PerlIO_fileno(Perl_error_log), - PL_no_mem, strlen(PL_no_mem)); - my_exit(1); - return Nullch; + return write_no_mem(); } /*NOTREACHED*/ } @@ -146,12 +181,34 @@ Perl_safesysrealloc(Malloc_t where,MEM_SIZE size) Free_t Perl_safesysfree(Malloc_t where) { - dVAR; -#ifdef PERL_IMPLICIT_SYS +#if defined(PERL_IMPLICIT_SYS) || defined(PERL_TRACK_MEMPOOL) dTHX; +#else + dVAR; #endif DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) free\n",PTR2UV(where),(long)PL_an++)); if (where) { +#ifdef PERL_TRACK_MEMPOOL + where = (Malloc_t)((char*)where-sTHX); + if (((struct perl_memory_debug_header *)where)->interpreter != aTHX) { + Perl_croak_nocontext("panic: free from wrong pool"); + } +# ifdef PERL_POISON + { + if (((struct perl_memory_debug_header *)where)->in_use + == PERL_POISON_FREE) { + Perl_croak_nocontext("panic: duplicate free"); + } + if (((struct perl_memory_debug_header *)where)->in_use + != PERL_POISON_INUSE) { + Perl_croak_nocontext("panic: bad free "); + } + ((struct perl_memory_debug_header *)where)->in_use + = PERL_POISON_FREE; + } + Poison(where, ((struct perl_memory_debug_header *)where)->size, char); +# endif +#endif PerlMem_free(where); } } @@ -176,23 +233,27 @@ Perl_safesyscalloc(MEM_SIZE count, MEM_SIZE size) Perl_croak_nocontext("panic: calloc"); #endif size *= count; +#ifdef PERL_TRACK_MEMPOOL + size += sTHX; +#endif ptr = (Malloc_t)PerlMem_malloc(size?size:1); /* malloc(0) is NASTY on our system */ PERL_ALLOC_CHECK(ptr); DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) calloc %ld x %ld bytes\n",PTR2UV(ptr),(long)PL_an++,(long)count,(long)size)); if (ptr != Nullch) { memset((void*)ptr, 0, size); +#ifdef PERL_TRACK_MEMPOOL + ((struct perl_memory_debug_header *)ptr)->interpreter = aTHX; +# ifdef PERL_POISON + ((struct perl_memory_debug_header *)ptr)->size = size; + ((struct perl_memory_debug_header *)ptr)->in_use = PERL_POISON_INUSE; +# endif + ptr = (Malloc_t)((char*)ptr+sTHX); +#endif return ptr; } else if (PL_nomemok) return Nullch; - else { - /* Can't use PerlIO to write as it allocates memory */ - PerlLIO_write(PerlIO_fileno(Perl_error_log), - PL_no_mem, strlen(PL_no_mem)); - my_exit(1); - return Nullch; - } - /*NOTREACHED*/ + return write_no_mem(); } /* These must be defined when not using Perl's malloc for binary @@ -274,9 +335,11 @@ Perl_instr(pTHX_ register const char *big, register const char *little) for (x=big,s=little; *s; /**/ ) { if (!*x) return Nullch; - if (*s++ != *x++) { - s--; + if (*s != *x) break; + else { + s++; + x++; } } if (!*s) @@ -288,28 +351,24 @@ Perl_instr(pTHX_ register const char *big, register const char *little) /* same as instr but allow embedded nulls */ char * -Perl_ninstr(pTHX_ register const char *big, register const char *bigend, const char *little, const char *lend) +Perl_ninstr(pTHX_ const char *big, const char *bigend, const char *little, const char *lend) { - register const I32 first = *little; - register const char *littleend = lend; - - if (!first && little >= littleend) - return (char*)big; - if (bigend - big < littleend - little) - return Nullch; - bigend -= littleend - little++; - while (big <= bigend) { - register const char *s, *x; - if (*big++ != first) - continue; - for (x=big,s=little; s < littleend; /**/ ) { - if (*s++ != *x++) { - s--; - break; - } - } - if (s >= littleend) - return (char*)(big-1); + if (little >= lend) + return (char*)big; + { + char first = *little++; + const char *s, *x; + bigend -= lend - little; + OUTER: + while (big <= bigend) { + if (*big++ != first) + goto OUTER; + for (x=big,s=little; s < lend; x++,s++) { + if (*s != *x) + goto OUTER; + } + return (char*)(big-1); + } } return Nullch; } @@ -321,9 +380,9 @@ Perl_rninstr(pTHX_ register const char *big, const char *bigend, const char *lit { register const char *bigbeg; register const I32 first = *little; - register const char *littleend = lend; + register const char * const littleend = lend; - if (!first && little >= littleend) + if (little >= littleend) return (char*)bigend; bigbeg = big; big = bigend - (littleend - little++); @@ -332,9 +391,11 @@ Perl_rninstr(pTHX_ register const char *big, const char *bigend, const char *lit if (*big-- != first) continue; for (x=big+2,s=little; s < littleend; /**/ ) { - if (*s++ != *x++) { - s--; + if (*s != *x) break; + else { + x++; + s++; } } if (s >= littleend) @@ -365,7 +426,8 @@ Analyses the string in order to make fast searches on it using fbm_instr() void Perl_fbm_compile(pTHX_ SV *sv, U32 flags) { - const register U8 *s; + dVAR; + register const U8 *s; register U32 i; STRLEN len; I32 rarest = 0; @@ -373,7 +435,7 @@ Perl_fbm_compile(pTHX_ SV *sv, U32 flags) if (flags & FBMcf_TAIL) { MAGIC * const mg = SvUTF8(sv) && SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_utf8) : NULL; - sv_catpvn(sv, "\n", 1); /* Taken into account in fbm_instr() */ + sv_catpvs(sv, "\n"); /* Taken into account in fbm_instr() */ if (mg && mg->mg_len >= 0) mg->mg_len++; } @@ -552,7 +614,7 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit return Nullch; } if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) { - char *b = ninstr((char*)big,(char*)bigend, + char * const b = ninstr((char*)big,(char*)bigend, (char*)little, (char*)little + littlelen); if (!b && SvTAIL(littlestr)) { /* Automatically multiline! */ @@ -569,8 +631,8 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit } { /* Do actual FBM. */ - register const unsigned char *table = little + littlelen + FBM_TABLE_OFFSET; - const register unsigned char *oldlittle; + register const unsigned char * const table = little + littlelen + FBM_TABLE_OFFSET; + register const unsigned char *oldlittle; if (littlelen > (STRLEN)(bigend - big)) return Nullch; @@ -632,13 +694,14 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit char * Perl_screaminstr(pTHX_ SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_posp, I32 last) { - const register unsigned char *big; + dVAR; + register const unsigned char *big; register I32 pos; register I32 previous; register I32 first; - const register unsigned char *little; + register const unsigned char *little; register I32 stop_pos; - const register unsigned char *littleend; + register const unsigned char *littleend; I32 found = 0; if (*old_posp == -1 @@ -680,7 +743,7 @@ Perl_screaminstr(pTHX_ SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift } big -= previous; do { - const register unsigned char *s, *x; + register const unsigned char *s, *x; if (pos >= stop_pos) break; if (big[pos] != first) continue; @@ -819,9 +882,7 @@ Perl_savesharedpv(pTHX_ const char *pv) pvlen = strlen(pv)+1; newaddr = (char*)PerlMemShared_malloc(pvlen); if (!newaddr) { - PerlLIO_write(PerlIO_fileno(Perl_error_log), - PL_no_mem, strlen(PL_no_mem)); - my_exit(1); + return write_no_mem(); } return memcpy(newaddr,pv,pvlen); } @@ -839,7 +900,7 @@ char * Perl_savesvpv(pTHX_ SV *sv) { STRLEN len; - const char *pv = SvPV_const(sv, len); + const char * const pv = SvPV_const(sv, len); register char *newaddr; ++len; @@ -853,11 +914,12 @@ Perl_savesvpv(pTHX_ SV *sv) STATIC SV * S_mess_alloc(pTHX) { + dVAR; SV *sv; XPVMG *any; if (!PL_dirty) - return sv_2mortal(newSVpvn("",0)); + return sv_2mortal(newSVpvs("")); if (PL_mess_sv) return PL_mess_sv; @@ -954,14 +1016,15 @@ Perl_mess(pTHX_ const char *pat, ...) STATIC COP* S_closest_cop(pTHX_ COP *cop, const OP *o) { + dVAR; /* Look for PL_op starting from o. cop is the last COP we've seen. */ - if (!o || o == PL_op) return cop; + if (!o || o == PL_op) + return cop; if (o->op_flags & OPf_KIDS) { OP *kid; - for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) - { + for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) { COP *new_cop; /* If the OP_NEXTSTATE has been optimised away we can still use it @@ -973,7 +1036,8 @@ S_closest_cop(pTHX_ COP *cop, const OP *o) /* Keep searching, and return when we've found something. */ new_cop = closest_cop(cop, kid); - if (new_cop) return new_cop; + if (new_cop) + return new_cop; } } @@ -985,7 +1049,8 @@ S_closest_cop(pTHX_ COP *cop, const OP *o) SV * Perl_vmess(pTHX_ const char *pat, va_list *args) { - SV *sv = mess_alloc(); + dVAR; + SV * const sv = mess_alloc(); static const char dgd[] = " during global destruction.\n"; sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); @@ -1070,6 +1135,7 @@ Perl_write_to_stderr(pTHX_ const char* message, int msglen) STATIC void S_vdie_common(pTHX_ const char *message, STRLEN msglen, I32 utf8) { + dVAR; HV *stash; GV *gv; CV *cv; @@ -1142,6 +1208,7 @@ S_vdie_croak_common(pTHX_ const char* pat, va_list* args, STRLEN* msglen, OP * Perl_vdie(pTHX_ const char* pat, va_list *args) { + dVAR; const char *message; const int was_in_eval = PL_in_eval; STRLEN msglen; @@ -1191,6 +1258,7 @@ Perl_die(pTHX_ const char* pat, ...) void Perl_vcroak(pTHX_ const char* pat, va_list *args) { + dVAR; const char *message; STRLEN msglen; I32 utf8 = 0; @@ -1358,7 +1426,7 @@ Perl_vwarner(pTHX_ U32 err, const char* pat, va_list* args) if (ckDEAD(err)) { SV * const msv = vmess(pat, args); STRLEN msglen; - const char *message = SvPV_const(msv, msglen); + const char * const message = SvPV_const(msv, msglen); const I32 utf8 = SvUTF8(msv); if (PL_diehook) { @@ -1383,6 +1451,7 @@ Perl_vwarner(pTHX_ U32 err, const char* pat, va_list* args) bool Perl_ckwarn(pTHX_ U32 w) { + dVAR; return ( isLEXWARN_on @@ -1410,6 +1479,7 @@ Perl_ckwarn(pTHX_ U32 w) bool Perl_ckwarn_d(pTHX_ U32 w) { + dVAR; return isLEXWARN_off || PL_curcop->cop_warnings == pWARN_ALL @@ -1495,20 +1565,41 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val) my_setenv_format(environ[i], nam, nlen, val, vlen); } else { # endif -# if defined(__CYGWIN__) || defined(EPOC) || defined(SYMBIAN) - setenv(nam, val, 1); +# if defined(__CYGWIN__) || defined(EPOC) || defined(__SYMBIAN32__) +# 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 { + const int nlen = strlen(nam); + const int vlen = strlen(val); + char * const 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; + 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); +# endif /* HAS_UNSETENV */ # endif /* __CYGWIN__ */ #ifndef PERL_USE_SAFE_PUTENV } @@ -1543,7 +1634,7 @@ I32 Perl_setenv_getix(pTHX_ const char *nam) { register I32 i; - const register I32 len = strlen(nam); + register const I32 len = strlen(nam); for (i = 0; environ[i]; i++) { if ( @@ -1992,6 +2083,7 @@ PerlIO * Perl_my_popen_list(pTHX_ char *mode, int n, SV **args) { #if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(OS2) && !defined(VMS) && !defined(__OPEN_VM) && !defined(EPOC) && !defined(MACOS_TRADITIONAL) && !defined(NETWARE) + dVAR; int p[2]; register I32 This, that; register Pid_t pid; @@ -2125,6 +2217,7 @@ Perl_my_popen_list(pTHX_ char *mode, int n, SV **args) PerlIO * Perl_my_popen(pTHX_ const char *cmd, const char *mode) { + dVAR; int p[2]; register I32 This, that; register Pid_t pid; @@ -2212,7 +2305,9 @@ Perl_my_popen(pTHX_ const char *cmd, const char *mode) PL_ppid = (IV)getppid(); #endif PL_forkprocess = 0; +#ifdef PERL_USES_PL_PIDSTATUS hv_clear(PL_pidstatus); /* we have no children */ +#endif return Nullfp; #undef THIS #undef THAT @@ -2497,8 +2592,7 @@ Perl_rsignal(pTHX_ int signo, Sighandler_t handler) return PerlProc_signal(signo, handler); } -static -Signal_t +static Signal_t sig_trap(int signo) { dVAR; @@ -2556,6 +2650,7 @@ Perl_rsignal_restore(pTHX_ int signo, Sigsave_t *save) I32 Perl_my_pclose(pTHX_ PerlIO *ptr) { + dVAR; Sigsave_t hstat, istat, qstat; int status; SV **svp; @@ -2612,20 +2707,20 @@ Perl_my_pclose(pTHX_ PerlIO *ptr) I32 Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags) { + dVAR; I32 result = 0; if (!pid) return -1; -#if !defined(HAS_WAITPID) && !defined(HAS_WAIT4) || defined(HAS_WAITPID_RUNTIME) +#ifdef PERL_USES_PL_PIDSTATUS { - char spid[TYPE_CHARS(IV)]; - if (pid > 0) { - SV** svp; - sprintf(spid, "%"IVdf, (IV)pid); - svp = hv_fetch(PL_pidstatus,spid,strlen(spid),FALSE); + /* The keys in PL_pidstatus are now the raw 4 (or 8) bytes of the + pid, rather than a string form. */ + SV * const * const svp = hv_fetch(PL_pidstatus,(const char*) &pid,sizeof(Pid_t),FALSE); if (svp && *svp != &PL_sv_undef) { *statusp = SvIVX(*svp); - (void)hv_delete(PL_pidstatus,spid,strlen(spid),G_DISCARD); + (void)hv_delete(PL_pidstatus,(const char*) &pid,sizeof(Pid_t), + G_DISCARD); return pid; } } @@ -2634,12 +2729,21 @@ Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags) hv_iterinit(PL_pidstatus); if ((entry = hv_iternext(PL_pidstatus))) { - SV *sv = hv_iterval(PL_pidstatus,entry); + SV * const sv = hv_iterval(PL_pidstatus,entry); + I32 len; + const char * const spid = hv_iterkey(entry,&len); - pid = atoi(hv_iterkey(entry,(I32*)statusp)); + assert (len == sizeof(Pid_t)); + memcpy((char *)&pid, spid, len); *statusp = SvIVX(sv); - sprintf(spid, "%"IVdf, (IV)pid); - (void)hv_delete(PL_pidstatus,spid,strlen(spid),G_DISCARD); + /* The hash iterator is currently on this entry, so simply + calling hv_delete would trigger the lazy delete, which on + aggregate does more work, beacuse next call to hv_iterinit() + would spot the flag, and have to call the delete routine, + while in the meantime any new entries can't re-use that + memory. */ + hv_iterinit(PL_pidstatus); + (void)hv_delete(PL_pidstatus,spid,len,G_DISCARD); return pid; } } @@ -2657,7 +2761,7 @@ Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags) result = wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *)); goto finish; #endif -#if !defined(HAS_WAITPID) && !defined(HAS_WAIT4) || defined(HAS_WAITPID_RUNTIME) +#ifdef PERL_USES_PL_PIDSTATUS #if defined(HAS_WAITPID) && defined(HAS_WAITPID_RUNTIME) hard_way: #endif @@ -2682,18 +2786,18 @@ Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags) } #endif /* !DOSISH || OS2 || WIN32 || NETWARE */ +#ifdef PERL_USES_PL_PIDSTATUS void Perl_pidgone(pTHX_ Pid_t pid, int status) { register SV *sv; - char spid[TYPE_CHARS(IV)]; - sprintf(spid, "%"IVdf, (IV)pid); - sv = *hv_fetch(PL_pidstatus,spid,strlen(spid),TRUE); + sv = *hv_fetch(PL_pidstatus,(const char*)&pid,sizeof(Pid_t),TRUE); SvUPGRADE(sv,SVt_IV); SvIV_set(sv, status); return; } +#endif #if defined(atarist) || defined(OS2) || defined(EPOC) int pclose(); @@ -2707,8 +2811,8 @@ Perl_my_pclose(pTHX_ PerlIO *ptr) #endif { /* Needs work for PerlIO ! */ - FILE *f = PerlIO_findFILE(ptr); - I32 result = pclose(f); + FILE * const f = PerlIO_findFILE(ptr); + const I32 result = pclose(f); PerlIO_releaseFILE(ptr,f); return result; } @@ -2720,7 +2824,7 @@ I32 Perl_my_pclose(pTHX_ PerlIO *ptr) { /* Needs work for PerlIO ! */ - FILE *f = PerlIO_findFILE(ptr); + FILE * const f = PerlIO_findFILE(ptr); I32 result = djgpp_pclose(f); result = (result << 8) & 0xff00; PerlIO_releaseFILE(ptr,f); @@ -2732,7 +2836,7 @@ void Perl_repeatcpy(pTHX_ register char *to, register const char *from, I32 len, register I32 count) { register I32 todo; - register const char *frombase = from; + register const char * const frombase = from; if (len == 1) { register const char c = *from; @@ -2756,7 +2860,7 @@ Perl_same_dirent(pTHX_ const char *a, const char *b) char *fb = strrchr(b,'/'); Stat_t tmpstatbuf1; Stat_t tmpstatbuf2; - SV *tmpsv = sv_newmortal(); + SV * const tmpsv = sv_newmortal(); if (fa) fa++; @@ -2786,8 +2890,10 @@ 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) { + dVAR; const char *xfound = Nullch; char *xfailed = Nullch; char tmpbuf[MAXPATHLEN]; @@ -2808,8 +2914,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; + static 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 @@ -2841,16 +2947,16 @@ Perl_find_script(pTHX_ const char *scriptname, bool dosearch, const char **searc # ifdef ALWAYS_DEFTYPES len = strlen(scriptname); if (!(len == 1 && *scriptname == '-') && scriptname[len-1] != ':') { - int hasdir, idx = 0, deftypes = 1; + int idx = 0, deftypes = 1; bool seen_dot = 1; - hasdir = !dosearch || (strpbrk(scriptname,":[ 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); @@ -4018,7 +4131,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; } @@ -4038,6 +4151,7 @@ want to upgrade the SV. SV * Perl_new_version(pTHX_ SV *ver) { + dVAR; SV * const rv = newSV(0); if ( sv_derived_from(ver,"version") ) /* can just copy directly */ { @@ -4067,7 +4181,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++ ) { @@ -4075,7 +4189,7 @@ 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 @@ -4117,8 +4231,8 @@ Perl_upg_version(pTHX_ SV *ver) if ( SvNOK(ver) ) /* may get too much accuracy */ { char tbuf[64]; - sprintf(tbuf,"%.9"NVgf, SvNVX(ver)); - version = savepv(tbuf); + const STRLEN len = my_sprintf(tbuf,"%.9"NVgf, SvNVX(ver)); + version = savepvn(tbuf, len); } #ifdef SvVOK else if ( SvVOK(ver) ) { /* already a v-string */ @@ -4148,11 +4262,11 @@ confused by derived classes which may contain additional hash entries): =over 4 -=item * The SV contains a hash (or a reference to one) +=item * The SV contains a [reference to a] hash =item * The hash contains a "version" key -=item * The "version" key has an AV as its value +=item * The "version" key has [a reference to] an AV as its value =back @@ -4169,7 +4283,7 @@ Perl_vverify(pTHX_ SV *vs) /* see if the appropriate elements exist */ if ( SvTYPE(vs) == SVt_PVHV && hv_exists((HV*)vs, "version", 7) - && (sv = *hv_fetch((HV*)vs, "version", 7, FALSE)) + && (sv = SvRV(*hv_fetch((HV*)vs, "version", 7, FALSE))) && SvTYPE(sv) == SVt_PVAV ) return TRUE; else @@ -4214,15 +4328,15 @@ Perl_vnumify(pTHX_ SV *vs) /* attempt to retrieve the version array */ - if ( !(av = (AV *)*hv_fetch((HV*)vs, "version", 7, FALSE) ) ) { - sv_catpvn(sv,"0",1); + if ( !(av = (AV *)SvRV(*hv_fetch((HV*)vs, "version", 7, FALSE)) ) ) { + sv_catpvs(sv,"0"); return sv; } len = av_len(av); if ( len == -1 ) { - sv_catpvn(sv,"0",1); + sv_catpvs(sv,"0"); return sv; } @@ -4232,7 +4346,7 @@ Perl_vnumify(pTHX_ SV *vs) { digit = SvIV(*av_fetch(av, i, 0)); if ( width < 3 ) { - const int denom = (int)pow(10,(3-width)); + const int denom = (width == 2 ? 10 : 100); const div_t term = div((int)PERL_ABS(digit),denom); Perl_sv_catpvf(aTHX_ sv, "%0*d_%d", width, term.quot, term.rem); } @@ -4245,12 +4359,12 @@ Perl_vnumify(pTHX_ SV *vs) { digit = SvIV(*av_fetch(av, len, 0)); if ( alpha && width == 3 ) /* alpha version */ - sv_catpvn(sv,"_",1); + sv_catpvs(sv,"_"); Perl_sv_catpvf(aTHX_ sv, "%0*d", width, (int)digit); } else /* len == 0 */ { - sv_catpvn(sv,"000",3); + sv_catpvs(sv, "000"); } return sv; } @@ -4284,17 +4398,17 @@ Perl_vnormal(pTHX_ SV *vs) 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 ) { - sv_catpvn(sv,"",0); + sv_catpvs(sv,""); 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++ ) { + for ( i = 1 ; i < len ; i++ ) { digit = SvIV(*av_fetch(av, i, 0)); Perl_sv_catpvf(aTHX_ sv, ".%"IVdf, (IV)digit); } @@ -4311,7 +4425,7 @@ Perl_vnormal(pTHX_ SV *vs) if ( len <= 2 ) { /* short version, must be at least three */ for ( len = 2 - len; len != 0; len-- ) - sv_catpvn(sv,".0",2); + sv_catpvs(sv,".0"); } return sv; } @@ -4330,7 +4444,6 @@ the original version contained 1 or more dots, respectively SV * Perl_vstringify(pTHX_ SV *vs) { - I32 qv = 0; if ( SvROK(vs) ) vs = SvRV(vs); @@ -4338,12 +4451,9 @@ Perl_vstringify(pTHX_ SV *vs) Perl_croak(aTHX_ "Invalid version object"); if ( hv_exists((HV *)vs, "qv", 2) ) - qv = 1; - - if ( qv ) - return Perl_vnormal(aTHX_ vs); + return vnormal(vs); else - return Perl_vnumify(aTHX_ vs); + return vnumify(vs); } /* @@ -4376,12 +4486,12 @@ Perl_vcmp(pTHX_ SV *lhv, SV *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; @@ -4676,7 +4786,7 @@ Perl_my_socketpair (int family, int type, int protocol, int fd[2]) { #endif tidy_up_and_fail: { - int save_errno = errno; + const int save_errno = errno; if (listener != -1) PerlLIO_close(listener); if (connector != -1) @@ -4705,8 +4815,9 @@ Perl_my_socketpair (int family, int type, int protocol, int fd[2]) { =for apidoc sv_nosharing Dummy routine which "shares" an SV when there is no sharing module present. -Exists to avoid test for a NULL function pointer and because it could potentially warn under -some level of strict-ness. +Or "locks" it. Or "unlocks" it. In other words, ignores its single SV argument. +Exists to avoid test for a NULL function pointer and because it could +potentially warn under some level of strict-ness. =cut */ @@ -4717,39 +4828,6 @@ Perl_sv_nosharing(pTHX_ SV *sv) PERL_UNUSED_ARG(sv); } -/* -=for apidoc sv_nolocking - -Dummy routine which "locks" an SV when there is no locking module present. -Exists to avoid test for a NULL function pointer and because it could potentially warn under -some level of strict-ness. - -=cut -*/ - -void -Perl_sv_nolocking(pTHX_ SV *sv) -{ - PERL_UNUSED_ARG(sv); -} - - -/* -=for apidoc sv_nounlocking - -Dummy routine which "unlocks" an SV when there is no locking module present. -Exists to avoid test for a NULL function pointer and because it could potentially warn under -some level of strict-ness. - -=cut -*/ - -void -Perl_sv_nounlocking(pTHX_ SV *sv) -{ - PERL_UNUSED_ARG(sv); -} - U32 Perl_parse_unicode_opts(pTHX_ const char **popt) { @@ -4807,6 +4885,7 @@ Perl_parse_unicode_opts(pTHX_ const char **popt) U32 Perl_seed(pTHX) { + dVAR; /* * This is really just a quick hack which grabs various garbage * values. It really should be a real hash algorithm which @@ -4888,6 +4967,7 @@ Perl_seed(pTHX) UV Perl_get_hash_seed(pTHX) { + dVAR; const char *s = PerlEnv_getenv("PERL_HASH_SEED"); UV myseed = 0; @@ -4948,8 +5028,8 @@ Perl_init_global_struct(pTHX) #ifdef PERL_GLOBAL_STRUCT # define PERL_GLOBAL_STRUCT_INIT # include "opcode.h" /* the ppaddr and check */ - IV nppaddr = sizeof(Gppaddr)/sizeof(Perl_ppaddr_t); - IV ncheck = sizeof(Gcheck) /sizeof(Perl_check_t); + const IV nppaddr = sizeof(Gppaddr)/sizeof(Perl_ppaddr_t); + const IV ncheck = sizeof(Gcheck) /sizeof(Perl_check_t); # ifdef PERL_GLOBAL_STRUCT_PRIVATE /* PerlMem_malloc() because can't use even safesysmalloc() this early. */ plvarsp = (struct perl_vars*)PerlMem_malloc(sizeof(struct perl_vars)); @@ -5023,11 +5103,12 @@ Perl_mem_log_alloc(const UV n, const UV typesize, const char *typename, Malloc_t #ifdef PERL_MEM_LOG_STDERR /* We can't use PerlIO for obvious reasons. */ char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE]; - sprintf(buf, - "alloc: %s:%d:%s: %"IVdf" %"UVuf" %s = %"IVdf": %"UVxf"\n", - filename, linenumber, funcname, - n, typesize, typename, n * typesize, PTR2UV(newalloc)); - PerlLIO_write(2, buf, strlen(buf)); + const STRLEN len = my_sprintf(buf, + "alloc: %s:%d:%s: %"IVdf" %"UVuf + " %s = %"IVdf": %"UVxf"\n", + filename, linenumber, funcname, n, typesize, + typename, n * typesize, PTR2UV(newalloc)); + PerlLIO_write(2, buf, len); #endif return newalloc; } @@ -5038,11 +5119,12 @@ Perl_mem_log_realloc(const UV n, const UV typesize, const char *typename, Malloc #ifdef PERL_MEM_LOG_STDERR /* We can't use PerlIO for obvious reasons. */ char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE]; - sprintf(buf, - "realloc: %s:%d:%s: %"IVdf" %"UVuf" %s = %"IVdf": %"UVxf" -> %"UVxf"\n", - filename, linenumber, funcname, - n, typesize, typename, n * typesize, PTR2UV(oldalloc), PTR2UV(newalloc)); - PerlLIO_write(2, buf, strlen(buf)); + const STRLEN len = my_sprintf(buf, "realloc: %s:%d:%s: %"IVdf" %"UVuf + " %s = %"IVdf": %"UVxf" -> %"UVxf"\n", + filename, linenumber, funcname, n, typesize, + typename, n * typesize, PTR2UV(oldalloc), + PTR2UV(newalloc)); + PerlLIO_write(2, buf, len); #endif return newalloc; } @@ -5053,9 +5135,10 @@ Perl_mem_log_free(Malloc_t oldalloc, const char *filename, const int linenumber, #ifdef PERL_MEM_LOG_STDERR /* We can't use PerlIO for obvious reasons. */ char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE]; - sprintf(buf, "free: %s:%d:%s: %"UVxf"\n", - filename, linenumber, funcname, PTR2UV(oldalloc)); - PerlLIO_write(2, buf, strlen(buf)); + const STRLEN len = my_sprintf(buf, "free: %s:%d:%s: %"UVxf"\n", + filename, linenumber, funcname, + PTR2UV(oldalloc)); + PerlLIO_write(2, buf, len); #endif return oldalloc; } @@ -5063,6 +5146,122 @@ Perl_mem_log_free(Malloc_t oldalloc, const char *filename, const int linenumber, #endif /* PERL_MEM_LOG */ /* +=for apidoc my_sprintf + +The C library C, wrapped if necessary, to ensure that it will return +the length of the string written to the buffer. Only rare pre-ANSI systems +need the wrapper function - usually this is a direct call to C. + +=cut +*/ +#ifndef SPRINTF_RETURNS_STRLEN +int +Perl_my_sprintf(char *buffer, const char* pat, ...) +{ + va_list args; + va_start(args, pat); + vsprintf(buffer, pat, args); + va_end(args); + return strlen(buffer); +} +#endif + +void +Perl_my_clearenv(pTHX) +{ + dVAR; +#if ! defined(PERL_MICRO) +# if defined(PERL_IMPLICIT_SYS) || defined(WIN32) + PerlEnv_clearenv(); +# else /* ! (PERL_IMPLICIT_SYS || WIN32) */ +# if defined(USE_ENVIRON_ARRAY) +# if defined(USE_ITHREADS) + /* only the parent thread can clobber the process environment */ + if (PL_curinterp == aTHX) +# endif /* USE_ITHREADS */ + { +# if ! defined(PERL_USE_SAFE_PUTENV) + if ( !PL_use_safe_putenv) { + I32 i; + if (environ == PL_origenviron) + environ = (char**)safesysmalloc(sizeof(char*)); + else + for (i = 0; environ[i]; i++) + (void)safesysfree(environ[i]); + } + environ[0] = NULL; +# else /* PERL_USE_SAFE_PUTENV */ +# if defined(HAS_CLEARENV) + (void)clearenv(); +# elif defined(HAS_UNSETENV) + int bsiz = 80; /* Most envvar names will be shorter than this. */ + char *buf = (char*)safesysmalloc(bsiz * sizeof(char)); + while (*environ != NULL) { + char *e = strchr(*environ, '='); + int l = e ? e - *environ : strlen(*environ); + if (bsiz < l + 1) { + (void)safesysfree(buf); + bsiz = l + 1; + buf = (char*)safesysmalloc(bsiz * sizeof(char)); + } + strncpy(buf, *environ, l); + *(buf + l) = '\0'; + (void)unsetenv(buf); + } + (void)safesysfree(buf); +# else /* ! HAS_CLEARENV && ! HAS_UNSETENV */ + /* Just null environ and accept the leakage. */ + *environ = NULL; +# endif /* HAS_CLEARENV || HAS_UNSETENV */ +# endif /* ! PERL_USE_SAFE_PUTENV */ + } +# endif /* USE_ENVIRON_ARRAY */ +# endif /* PERL_IMPLICIT_SYS || WIN32 */ +#endif /* PERL_MICRO */ +} + +#ifdef PERL_IMPLICIT_CONTEXT + +/* implements the MY_CXT_INIT macro. The first time a module is loaded, +the global PL_my_cxt_index is incremented, and that value is assigned to +that module's static my_cxt_index (who's address is passed as an arg). +Then, for each interpreter this function is called for, it makes sure a +void* slot is available to hang the static data off, by allocating or +extending the interpreter's PL_my_cxt_list array */ + +void * +Perl_my_cxt_init(pTHX_ int *index, size_t size) +{ + dVAR; + void *p; + if (*index == -1) { + /* this module hasn't been allocated an index yet */ + MUTEX_LOCK(&PL_my_ctx_mutex); + *index = PL_my_cxt_index++; + MUTEX_UNLOCK(&PL_my_ctx_mutex); + } + + /* make sure the array is big enough */ + if (PL_my_cxt_size <= *index) { + if (PL_my_cxt_size) { + while (PL_my_cxt_size <= *index) + PL_my_cxt_size *= 2; + Renew(PL_my_cxt_list, PL_my_cxt_size, void *); + } + else { + PL_my_cxt_size = 16; + Newx(PL_my_cxt_list, PL_my_cxt_size, void *); + } + } + /* newSV() allocates one more than needed */ + p = (void*)SvPVX(newSV(size-1)); + PL_my_cxt_list[*index] = p; + Zero(p, size, char); + return p; +} +#endif + +/* * Local variables: * c-indentation-style: bsd * c-basic-offset: 4