X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=util.c;h=582a7977b89d0b83ad4a7212677413a83d1176ed;hb=054b02d6604bb3beeebed2d8a040d025b131c9a6;hp=0b3673e049d28f1bdb2faff6a2ee083b6bbbd6df;hpb=79cb57f6e01f91d8fff40d69caa187aaa669671b;p=p5sagit%2Fp5-mst-13.2.git diff --git a/util.c b/util.c index 0b3673e..582a797 100644 --- a/util.c +++ b/util.c @@ -13,6 +13,7 @@ */ #include "EXTERN.h" +#define PERL_IN_UTIL_C #include "perl.h" #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) @@ -50,11 +51,14 @@ # include #endif +#ifdef I_LOCALE +# include +#endif + #define FLUSH #ifdef LEAKTEST -static void xstat _((int)); long xcount[MAXXCOUNT]; long lastxcount[MAXXCOUNT]; long xycount[MAXXCOUNT][MAXYCOUNT]; @@ -71,18 +75,18 @@ long lastxycount[MAXXCOUNT][MAXYCOUNT]; */ Malloc_t -safesysmalloc(MEM_SIZE size) +Perl_safesysmalloc(MEM_SIZE size) { Malloc_t ptr; #ifdef HAS_64K_LIMIT if (size > 0xffff) { PerlIO_printf(PerlIO_stderr(), "Allocation too large: %lx\n", size) FLUSH; - my_exit(1); + WITH_THX(my_exit(1)); } #endif /* HAS_64K_LIMIT */ #ifdef DEBUGGING if ((long)size < 0) - croak("panic: malloc"); + Perl_croak_nocontext("panic: malloc"); #endif ptr = PerlMem_malloc(size?size:1); /* malloc(0) is NASTY on our system */ #if !(defined(I286) || defined(atarist)) @@ -96,7 +100,7 @@ safesysmalloc(MEM_SIZE size) return Nullch; else { PerlIO_puts(PerlIO_stderr(),PL_no_mem) FLUSH; - my_exit(1); + WITH_THX(my_exit(1)); return Nullch; } /*NOTREACHED*/ @@ -105,7 +109,7 @@ safesysmalloc(MEM_SIZE size) /* paranoid version of system's realloc() */ Malloc_t -safesysrealloc(Malloc_t where,MEM_SIZE size) +Perl_safesysrealloc(Malloc_t where,MEM_SIZE size) { Malloc_t ptr; #if !defined(STANDARD_C) && !defined(HAS_REALLOC_PROTOTYPE) @@ -116,7 +120,7 @@ safesysrealloc(Malloc_t where,MEM_SIZE size) if (size > 0xffff) { PerlIO_printf(PerlIO_stderr(), "Reallocation too large: %lx\n", size) FLUSH; - my_exit(1); + WITH_THX(my_exit(1)); } #endif /* HAS_64K_LIMIT */ if (!size) { @@ -128,7 +132,7 @@ safesysrealloc(Malloc_t where,MEM_SIZE size) return safesysmalloc(size); #ifdef DEBUGGING if ((long)size < 0) - croak("panic: realloc"); + Perl_croak_nocontext("panic: realloc"); #endif ptr = PerlMem_realloc(where,size); @@ -150,7 +154,7 @@ safesysrealloc(Malloc_t where,MEM_SIZE size) return Nullch; else { PerlIO_puts(PerlIO_stderr(),PL_no_mem) FLUSH; - my_exit(1); + WITH_THX(my_exit(1)); return Nullch; } /*NOTREACHED*/ @@ -159,7 +163,7 @@ safesysrealloc(Malloc_t where,MEM_SIZE size) /* safe version of system's free() */ Free_t -safesysfree(Malloc_t where) +Perl_safesysfree(Malloc_t where) { #if !(defined(I286) || defined(atarist)) DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%x: (%05d) free\n",(char *) where,PL_an++)); @@ -175,7 +179,7 @@ safesysfree(Malloc_t where) /* safe version of system's calloc() */ Malloc_t -safesyscalloc(MEM_SIZE count, MEM_SIZE size) +Perl_safesyscalloc(MEM_SIZE count, MEM_SIZE size) { Malloc_t ptr; @@ -183,12 +187,12 @@ safesyscalloc(MEM_SIZE count, MEM_SIZE size) if (size * count > 0xffff) { PerlIO_printf(PerlIO_stderr(), "Allocation too large: %lx\n", size * count) FLUSH; - my_exit(1); + WITH_THX(my_exit(1)); } #endif /* HAS_64K_LIMIT */ #ifdef DEBUGGING if ((long)size < 0 || (long)count < 0) - croak("panic: calloc"); + Perl_croak_nocontext("panic: calloc"); #endif size *= count; ptr = PerlMem_malloc(size?size:1); /* malloc(0) is NASTY on our system */ @@ -205,7 +209,7 @@ safesyscalloc(MEM_SIZE count, MEM_SIZE size) return Nullch; else { PerlIO_puts(PerlIO_stderr(),PL_no_mem) FLUSH; - my_exit(1); + WITH_THX(my_exit(1)); return Nullch; } /*NOTREACHED*/ @@ -235,7 +239,7 @@ struct mem_test_strut { : ((size) - 1)/4)) Malloc_t -safexmalloc(I32 x, MEM_SIZE size) +Perl_safexmalloc(I32 x, MEM_SIZE size) { register char* where = (char*)safemalloc(size + ALIGN); @@ -247,7 +251,7 @@ safexmalloc(I32 x, MEM_SIZE size) } Malloc_t -safexrealloc(Malloc_t wh, MEM_SIZE size) +Perl_safexrealloc(Malloc_t wh, MEM_SIZE size) { char *where = (char*)wh; @@ -268,7 +272,7 @@ safexrealloc(Malloc_t wh, MEM_SIZE size) } void -safexfree(Malloc_t wh) +Perl_safexfree(Malloc_t wh) { I32 x; char *where = (char*)wh; @@ -285,7 +289,7 @@ safexfree(Malloc_t wh) } Malloc_t -safexcalloc(I32 x,MEM_SIZE count, MEM_SIZE size) +Perl_safexcalloc(I32 x,MEM_SIZE count, MEM_SIZE size) { register char * where = (char*)safexmalloc(x, size * count + ALIGN); xcount[x] += size; @@ -296,8 +300,8 @@ safexcalloc(I32 x,MEM_SIZE count, MEM_SIZE size) return (Malloc_t)(where + ALIGN); } -static void -xstat(int flag) +STATIC void +S_xstat(pTHX_ int flag) { register I32 i, j, total = 0; I32 subtot[MAXYCOUNT]; @@ -356,7 +360,7 @@ xstat(int flag) /* copy a string up to some (non-backslashed) delimiter, if any */ char * -delimcpy(register char *to, register char *toend, register char *from, register char *fromend, register int delim, I32 *retlen) +Perl_delimcpy(pTHX_ register char *to, register char *toend, register char *from, register char *fromend, register int delim, I32 *retlen) { register I32 tolen; for (tolen = 0; from < fromend; from++, tolen++) { @@ -385,7 +389,7 @@ delimcpy(register char *to, register char *toend, register char *from, register /* This routine was donated by Corey Satten. */ char * -instr(register const char *big, register const char *little) +Perl_instr(pTHX_ register const char *big, register const char *little) { register const char *s, *x; register I32 first; @@ -415,7 +419,7 @@ instr(register const char *big, register const char *little) /* same as instr but allow embedded nulls */ char * -ninstr(register const char *big, register const char *bigend, const char *little, const char *lend) +Perl_ninstr(pTHX_ register const char *big, register const char *bigend, const char *little, const char *lend) { register const char *s, *x; register I32 first = *little; @@ -444,7 +448,7 @@ ninstr(register const char *big, register const char *bigend, const char *little /* reverse of the above--find last substring */ char * -rninstr(register const char *big, const char *bigend, const char *little, const char *lend) +Perl_rninstr(pTHX_ register const char *big, const char *bigend, const char *little, const char *lend) { register const char *bigbeg; register const char *s, *x; @@ -474,7 +478,7 @@ rninstr(register const char *big, const char *bigend, const char *little, const * Set up for a new ctype locale. */ void -perl_new_ctype(const char *newctype) +Perl_new_ctype(pTHX_ const char *newctype) { #ifdef USE_LOCALE_CTYPE @@ -496,7 +500,7 @@ perl_new_ctype(const char *newctype) * Set up for a new collation locale. */ void -perl_new_collate(const char *newcoll) +Perl_new_collate(pTHX_ const char *newcoll) { #ifdef USE_LOCALE_COLLATE @@ -527,7 +531,7 @@ perl_new_collate(const char *newcoll) Size_t fb = strxfrm(xbuf, "ab", XFRMBUFSIZE); SSize_t mult = fb - fa; if (mult < 1) - croak("strxfrm() gets absurd"); + Perl_croak(aTHX_ "strxfrm() gets absurd"); PL_collxfrm_base = (fa > mult) ? (fa - mult) : 0; PL_collxfrm_mult = mult; } @@ -536,11 +540,32 @@ perl_new_collate(const char *newcoll) #endif /* USE_LOCALE_COLLATE */ } +void +perl_set_numeric_radix(void) +{ +#ifdef USE_LOCALE_NUMERIC +# ifdef HAS_LOCALECONV + struct lconv* lc; + + lc = localeconv(); + if (lc && lc->decimal_point) + /* We assume that decimal separator aka the radix + * character is always a single character. If it + * ever is a string, this needs to be rethunk. */ + PL_numeric_radix = *lc->decimal_point; + else + PL_numeric_radix = 0; +# endif /* HAS_LOCALECONV */ +#else + PL_numeric_radix = 0; +#endif /* USE_LOCALE_NUMERIC */ +} + /* * Set up for a new numeric locale. */ void -perl_new_numeric(const char *newnum) +Perl_new_numeric(pTHX_ const char *newnum) { #ifdef USE_LOCALE_NUMERIC @@ -559,13 +584,14 @@ perl_new_numeric(const char *newnum) PL_numeric_name = savepv(newnum); PL_numeric_standard = (strEQ(newnum, "C") || strEQ(newnum, "POSIX")); PL_numeric_local = TRUE; + perl_set_numeric_radix(); } #endif /* USE_LOCALE_NUMERIC */ } void -perl_set_numeric_standard(void) +Perl_set_numeric_standard(pTHX) { #ifdef USE_LOCALE_NUMERIC @@ -579,7 +605,7 @@ perl_set_numeric_standard(void) } void -perl_set_numeric_local(void) +Perl_set_numeric_local(pTHX) { #ifdef USE_LOCALE_NUMERIC @@ -587,17 +613,17 @@ perl_set_numeric_local(void) setlocale(LC_NUMERIC, PL_numeric_name); PL_numeric_standard = FALSE; PL_numeric_local = TRUE; + perl_set_numeric_radix(); } #endif /* USE_LOCALE_NUMERIC */ } - /* * Initialize locale awareness. */ int -perl_init_i18nl10n(int printwarn) +Perl_init_i18nl10n(pTHX_ int printwarn) { int ok = 1; /* returns @@ -807,15 +833,15 @@ perl_init_i18nl10n(int printwarn) } #ifdef USE_LOCALE_CTYPE - perl_new_ctype(curctype); + new_ctype(curctype); #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE - perl_new_collate(curcoll); + new_collate(curcoll); #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC - perl_new_numeric(curnum); + new_numeric(curnum); #endif /* USE_LOCALE_NUMERIC */ #endif /* USE_LOCALE */ @@ -825,9 +851,9 @@ perl_init_i18nl10n(int printwarn) /* Backwards compatibility. */ int -perl_init_i18nl14n(int printwarn) +Perl_init_i18nl14n(pTHX_ int printwarn) { - return perl_init_i18nl10n(printwarn); + return init_i18nl10n(printwarn); } #ifdef USE_LOCALE_COLLATE @@ -840,7 +866,7 @@ perl_init_i18nl14n(int printwarn) * Please see sv_collxfrm() to see how this is used. */ char * -mem_collxfrm(const char *s, STRLEN len, STRLEN *xlen) +Perl_mem_collxfrm(pTHX_ const char *s, STRLEN len, STRLEN *xlen) { char *xbuf; STRLEN xAlloc, xin, xout; /* xalloc is a reserved word in VC */ @@ -889,8 +915,16 @@ mem_collxfrm(const char *s, STRLEN len, STRLEN *xlen) #endif /* USE_LOCALE_COLLATE */ +#define FBM_TABLE_OFFSET 2 /* Number of bytes between EOS and table*/ + +/* As a space optimization, we do not compile tables for strings of length + 0 and 1, and for strings of length 2 unless FBMcf_TAIL. These are + special-cased in fbm_instr(). + + If FBMcf_TAIL, the table is created as if the string has a trailing \n. */ + void -fbm_compile(SV *sv, U32 flags /* not used yet */) +Perl_fbm_compile(pTHX_ SV *sv, U32 flags /* not used yet */) { register U8 *s; register U8 *table; @@ -899,24 +933,32 @@ fbm_compile(SV *sv, U32 flags /* not used yet */) I32 rarest = 0; U32 frequency = 256; + if (flags & FBMcf_TAIL) + sv_catpvn(sv, "\n", 1); /* Taken into account in fbm_instr() */ s = (U8*)SvPV_force(sv, len); (void)SvUPGRADE(sv, SVt_PVBM); - if (len > 255 || len == 0) /* TAIL might be on on a zero-length string. */ - return; /* can't have offsets that big */ + if (len == 0) /* TAIL might be on on a zero-length string. */ + return; if (len > 2) { - Sv_Grow(sv,len + 258); - table = (unsigned char*)(SvPVX(sv) + len + 1); - s = table - 2; + I32 mlen = len; + unsigned char *sb; + + if (mlen > 255) + mlen = 255; + Sv_Grow(sv,len + 256 + FBM_TABLE_OFFSET); + table = (unsigned char*)(SvPVX(sv) + len + FBM_TABLE_OFFSET); + s = table - 1 - FBM_TABLE_OFFSET; /* Last char */ for (i = 0; i < 256; i++) { - table[i] = len; + table[i] = mlen; } + table[-1] = flags; /* Not used yet */ i = 0; - while (s >= (unsigned char*)(SvPVX(sv))) - { - if (table[*s] == len) - table[*s] = i; - s--,i++; - } + sb = s - mlen; + while (s >= sb) { + if (table[*s] == mlen) + table[*s] = i; + s--, i++; + } } sv_magic(sv, Nullsv, 'B', Nullch, 0); /* deep magic */ SvVALID_on(sv); @@ -930,119 +972,200 @@ fbm_compile(SV *sv, U32 flags /* not used yet */) } BmRARE(sv) = s[rarest]; BmPREVIOUS(sv) = rarest; + BmUSEFUL(sv) = 100; /* Initial value */ + if (flags & FBMcf_TAIL) + SvTAIL_on(sv); DEBUG_r(PerlIO_printf(Perl_debug_log, "rarest char %c at %d\n",BmRARE(sv),BmPREVIOUS(sv))); } +/* If SvTAIL(littlestr), it has a fake '\n' at end. */ +/* If SvTAIL is actually due to \Z or \z, this gives false positives + if multiline */ + char * -fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 flags) +Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 flags) { register unsigned char *s; - register I32 tmp; - register I32 littlelen; - register unsigned char *little; - register unsigned char *table; - register unsigned char *olds; - register unsigned char *oldlittle; + STRLEN l; + register unsigned char *little = (unsigned char *)SvPV(littlestr,l); + register STRLEN littlelen = l; + register I32 multiline = flags & FBMrf_MULTILINE; + + if (bigend - big < littlelen) { + check_tail: + if ( SvTAIL(littlestr) + && (bigend - big == littlelen - 1) + && (littlelen == 1 + || *big == *little && memEQ(big, little, littlelen - 1))) + return (char*)big; + return Nullch; + } - if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) { - STRLEN len; - char *l = SvPV(littlestr,len); - if (!len) { - if (SvTAIL(littlestr)) { /* Can be only 0-len constant - substr => we can ignore SvVALID */ - if (PL_multiline) { - char *t = "\n"; - if ((s = (unsigned char*)ninstr((char*)big, (char*)bigend, - t, t + len))) { - return (char*)s; + if (littlelen <= 2) { /* Special-cased */ + register char c; + + if (littlelen == 1) { + if (SvTAIL(littlestr) && !multiline) { /* Anchor only! */ + /* Know that bigend != big. */ + if (bigend[-1] == '\n') + return (char *)(bigend - 1); + return (char *) bigend; + } + s = big; + while (s < bigend) { + if (*s == *little) + return (char *)s; + s++; + } + if (SvTAIL(littlestr)) + return (char *) bigend; + return Nullch; + } + if (!littlelen) + return (char*)big; /* Cannot be SvTAIL! */ + + /* littlelen is 2 */ + if (SvTAIL(littlestr) && !multiline) { + if (bigend[-1] == '\n' && bigend[-2] == *little) + return (char*)bigend - 2; + if (bigend[-1] == *little) + return (char*)bigend - 1; + return Nullch; + } + { + /* This should be better than FBM if c1 == c2, and almost + as good otherwise: maybe better since we do less indirection. + And we save a lot of memory by caching no table. */ + register unsigned char c1 = little[0]; + register unsigned char c2 = little[1]; + + s = big + 1; + bigend--; + if (c1 != c2) { + while (s <= bigend) { + if (s[0] == c2) { + if (s[-1] == c1) + return (char*)s - 1; + s += 2; + continue; + } + next_chars: + if (s[0] == c1) { + if (s == bigend) + goto check_1char_anchor; + if (s[1] == c2) + return (char*)s; + else { + s++; + goto next_chars; + } } + else + s += 2; + } + goto check_1char_anchor; + } + /* Now c1 == c2 */ + while (s <= bigend) { + if (s[0] == c1) { + if (s[-1] == c1) + return (char*)s - 1; + if (s == bigend) + goto check_1char_anchor; + if (s[1] == c1) + return (char*)s; + s += 3; } - if (bigend > big && bigend[-1] == '\n') - return (char *)(bigend - 1); else - return (char *) bigend; + s += 2; } - return (char*)big; } - return ninstr((char*)big,(char*)bigend, l, l + len); + check_1char_anchor: /* One char and anchor! */ + if (SvTAIL(littlestr) && (*bigend == *little)) + return (char *)bigend; /* bigend is already decremented. */ + return Nullch; } - - littlelen = SvCUR(littlestr); - if (SvTAIL(littlestr) && !PL_multiline) { /* tail anchored? */ - if (littlelen > bigend - big) - return Nullch; - little = (unsigned char*)SvPVX(littlestr); + if (SvTAIL(littlestr) && !multiline) { /* tail anchored? */ s = bigend - littlelen; - if (s > big + if (s >= big && bigend[-1] == '\n' - && s[-1] == *little && memEQ((char*)s - 1,(char*)little,littlelen)) - return (char*)s - 1; /* how sweet it is */ - else if (*s == *little && memEQ((char*)s,(char*)little,littlelen)) + && *s == *little + /* Automatically of length > 2 */ + && memEQ((char*)s + 1, (char*)little + 1, littlelen - 2)) return (char*)s; /* how sweet it is */ + if (s[1] == *little && memEQ((char*)s + 2,(char*)little + 1, + littlelen - 2)) + return (char*)s + 1; /* how sweet it is */ return Nullch; } - if (littlelen <= 2) { - unsigned char c1 = (unsigned char)SvPVX(littlestr)[0]; - unsigned char c2 = (unsigned char)SvPVX(littlestr)[1]; - /* This may do extra comparisons if littlelen == 2, but this - should be hidden in the noise since we do less indirection. */ - - s = big; - bigend -= littlelen; - while (s <= bigend) { - if (s[0] == c1 - && (littlelen == 1 || s[1] == c2) - && (!SvTAIL(littlestr) - || s == bigend - || s[littlelen] == '\n')) /* Automatically multiline */ - { + if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) { + char *b = ninstr((char*)big,(char*)bigend, + (char*)little, (char*)little + littlelen); + + if (!b && SvTAIL(littlestr)) { /* Automatically multiline! */ + /* Chop \n from littlestr: */ + s = bigend - littlelen + 1; + if (*s == *little && memEQ((char*)s + 1, (char*)little + 1, + littlelen - 2)) return (char*)s; - } - s++; + return Nullch; } - return Nullch; + return b; } - table = (unsigned char*)(SvPVX(littlestr) + littlelen + 1); - if (--littlelen >= bigend - big) - return Nullch; - s = big + littlelen; - oldlittle = little = table - 2; - if (s < bigend) { - top2: - /*SUPPRESS 560*/ - if (tmp = table[*s]) { + + { /* Do actual FBM. */ + register unsigned char *table = little + littlelen + FBM_TABLE_OFFSET; + register unsigned char *oldlittle; + + if (littlelen > bigend - big) + return Nullch; + --littlelen; /* Last char found by table lookup */ + + s = big + littlelen; + little += littlelen; /* last char */ + oldlittle = little; + if (s < bigend) { + register I32 tmp; + + top2: + /*SUPPRESS 560*/ + if (tmp = table[*s]) { #ifdef POINTERRIGOR - if (bigend - s > tmp) { + if (bigend - s > tmp) { + s += tmp; + goto top2; + } s += tmp; - goto top2; - } #else - if ((s += tmp) < bigend) - goto top2; -#endif - return Nullch; - } - else { - tmp = littlelen; /* less expensive than calling strncmp() */ - olds = s; - while (tmp--) { - if (*--s == *--little) - continue; - differ: - s = olds + 1; /* here we pay the price for failure */ - little = oldlittle; - if (s < bigend) /* fake up continue to outer loop */ + if ((s += tmp) < bigend) goto top2; - return Nullch; +#endif + goto check_end; + } + else { /* less expensive than calling strncmp() */ + register unsigned char *olds = s; + + tmp = littlelen; + + while (tmp--) { + if (*--s == *--little) + continue; + differ: + s = olds + 1; /* here we pay the price for failure */ + little = oldlittle; + if (s < bigend) /* fake up continue to outer loop */ + goto top2; + goto check_end; + } + return (char *)s; } - if (SvTAIL(littlestr) /* automatically multiline */ - && olds + 1 != bigend - && olds[1] != '\n') - goto differ; - return (char *)s; } + check_end: + if ( s == bigend && (table[-1] & FBMcf_TAIL) + && memEQ(bigend - littlelen, oldlittle - littlelen, littlelen) ) + return (char*)bigend - littlelen; + return Nullch; } - return Nullch; } /* start_shift, end_shift are positive quantities which give offsets @@ -1051,12 +1174,17 @@ fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 old_posp is the way of communication between consequent calls if the next call needs to find the . The initial *old_posp should be -1. - Note that we do not take into account SvTAIL, so it may give wrong - positives if _ALL flag is set. + + Note that we take into account SvTAIL, so one can get extra + optimizations if _ALL flag is set. */ +/* If SvTAIL is actually due to \Z or \z, this gives false positives + if PL_multiline. In fact if !PL_multiline the autoritative answer + is not supported yet. */ + char * -screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_posp, I32 last) +Perl_screaminstr(pTHX_ SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_posp, I32 last) { dTHR; register unsigned char *s, *x; @@ -1071,8 +1199,18 @@ screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_ if (*old_posp == -1 ? (pos = PL_screamfirst[BmRARE(littlestr)]) < 0 - : (((pos = *old_posp), pos += PL_screamnext[pos]) == 0)) + : (((pos = *old_posp), pos += PL_screamnext[pos]) == 0)) { + cant_find: + if ( BmRARE(littlestr) == '\n' + && BmPREVIOUS(littlestr) == SvCUR(littlestr) - 1) { + little = (unsigned char *)(SvPVX(littlestr)); + littleend = little + SvCUR(littlestr); + first = *little++; + goto check_tail; + } return Nullch; + } + little = (unsigned char *)(SvPVX(littlestr)); littleend = little + SvCUR(littlestr); first = *little++; @@ -1081,10 +1219,14 @@ screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_ big = (unsigned char *)(SvPVX(bigstr)); /* The value of pos we can stop at: */ stop_pos = SvCUR(bigstr) - end_shift - (SvCUR(littlestr) - 1 - previous); - if (previous + start_shift > stop_pos) return Nullch; + if (previous + start_shift > stop_pos) { + if (previous + start_shift == stop_pos + 1) /* A fake '\n'? */ + goto check_tail; + return Nullch; + } while (pos < previous + start_shift) { if (!(pos += PL_screamnext[pos])) - return Nullch; + goto cant_find; } #ifdef POINTERRIGOR do { @@ -1122,12 +1264,26 @@ screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_ found = 1; } } while ( pos += PL_screamnext[pos] ); - return (last && found) ? (char *)(big+(*old_posp)) : Nullch; + if (last && found) + return (char *)(big+(*old_posp)); #endif /* POINTERRIGOR */ + check_tail: + if (!SvTAIL(littlestr) || (end_shift > 0)) + return Nullch; + /* Ignore the trailing "\n". This code is not microoptimized */ + big = (unsigned char *)(SvPVX(bigstr) + SvCUR(bigstr)); + stop_pos = littleend - little; /* Actual littlestr len */ + if (stop_pos == 0) + return (char*)big; + big -= stop_pos; + if (*big == first + && ((stop_pos == 1) || memEQ(big + 1, little, stop_pos - 1))) + return (char*)big; + return Nullch; } I32 -ibcmp(const char *s1, const char *s2, register I32 len) +Perl_ibcmp(pTHX_ const char *s1, const char *s2, register I32 len) { register U8 *a = (U8 *)s1; register U8 *b = (U8 *)s2; @@ -1140,7 +1296,7 @@ ibcmp(const char *s1, const char *s2, register I32 len) } I32 -ibcmp_locale(const char *s1, const char *s2, register I32 len) +Perl_ibcmp_locale(pTHX_ const char *s1, const char *s2, register I32 len) { register U8 *a = (U8 *)s1; register U8 *b = (U8 *)s2; @@ -1155,7 +1311,7 @@ ibcmp_locale(const char *s1, const char *s2, register I32 len) /* copy a string to a safe spot */ char * -savepv(const char *sv) +Perl_savepv(pTHX_ const char *sv) { register char *newaddr; @@ -1167,7 +1323,7 @@ savepv(const char *sv) /* same thing but with a known length */ char * -savepvn(const char *sv, register I32 len) +Perl_savepvn(pTHX_ const char *sv, register I32 len) { register char *newaddr; @@ -1177,10 +1333,10 @@ savepvn(const char *sv, register I32 len) return newaddr; } -/* the SV for form() and mess() is not kept in an arena */ +/* the SV for Perl_form() and mess() is not kept in an arena */ STATIC SV * -mess_alloc(void) +S_mess_alloc(pTHX) { dTHR; SV *sv; @@ -1202,9 +1358,11 @@ mess_alloc(void) return sv; } +#ifdef PERL_IMPLICIT_CONTEXT char * -form(const char* pat, ...) +Perl_form_nocontext(const char* pat, ...) { + dTHX; SV *sv = mess_alloc(); va_list args; va_start(args, pat); @@ -1212,9 +1370,21 @@ form(const char* pat, ...) va_end(args); return SvPVX(sv); } +#endif char * -mess(const char *pat, va_list *args) +Perl_form(pTHX_ const char* pat, ...) +{ + SV *sv = mess_alloc(); + va_list args; + va_start(args, pat); + sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); + va_end(args); + return SvPVX(sv); +} + +SV * +Perl_mess(pTHX_ const char *pat, va_list *args) { SV *sv = mess_alloc(); static char dgd[] = " during global destruction.\n"; @@ -1222,50 +1392,51 @@ mess(const char *pat, va_list *args) sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); if (!SvCUR(sv) || *(SvEND(sv) - 1) != '\n') { dTHR; - if (PL_dirty) - sv_catpv(sv, dgd); - else { - if (PL_curcop->cop_line) - sv_catpvf(sv, " at %_ line %ld", - GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line); - if (GvIO(PL_last_in_gv) && IoLINES(GvIOp(PL_last_in_gv))) { - bool line_mode = (RsSIMPLE(PL_rs) && - SvLEN(PL_rs) == 1 && *SvPVX(PL_rs) == '\n'); - sv_catpvf(sv, ", <%s> %s %ld", - PL_last_in_gv == PL_argvgv ? "" : GvNAME(PL_last_in_gv), - line_mode ? "line" : "chunk", - (long)IoLINES(GvIOp(PL_last_in_gv))); - } - sv_catpv(sv, ".\n"); + if (PL_curcop->cop_line) + Perl_sv_catpvf(aTHX_ sv, " at %_ line %ld", + GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line); + if (GvIO(PL_last_in_gv) && IoLINES(GvIOp(PL_last_in_gv))) { + bool line_mode = (RsSIMPLE(PL_rs) && + SvCUR(PL_rs) == 1 && *SvPVX(PL_rs) == '\n'); + Perl_sv_catpvf(aTHX_ sv, ", <%s> %s %ld", + PL_last_in_gv == PL_argvgv ? "" : GvNAME(PL_last_in_gv), + line_mode ? "line" : "chunk", + (long)IoLINES(GvIOp(PL_last_in_gv))); } + sv_catpv(sv, PL_dirty ? dgd : ".\n"); } - return SvPVX(sv); + return sv; } -OP * -die(const char* pat, ...) +STATIC OP * +S_do_die(pTHX_ const char* pat, va_list *args) { dTHR; - va_list args; char *message; int was_in_eval = PL_in_eval; HV *stash; GV *gv; CV *cv; + SV *msv; + STRLEN msglen; DEBUG_S(PerlIO_printf(PerlIO_stderr(), "%p: die: curstack = %p, mainstack = %p\n", thr, PL_curstack, PL_mainstack)); - va_start(args, pat); - message = pat ? mess(pat, &args) : Nullch; - va_end(args); + if (pat) { + msv = mess(pat, args); + message = SvPV(msv,msglen); + } + else { + message = Nullch; + } DEBUG_S(PerlIO_printf(PerlIO_stderr(), "%p: die: message = %s\ndiehook = %p\n", thr, message, PL_diehook)); if (PL_diehook) { - /* sv_2cv might call croak() */ + /* sv_2cv might call Perl_croak() */ SV *olddiehook = PL_diehook; ENTER; SAVESPTR(PL_diehook); @@ -1278,7 +1449,7 @@ die(const char* pat, ...) ENTER; if (message) { - msg = newSVpv(message, 0); + msg = newSVpvn(message, msglen); SvREADONLY_on(msg); SAVEFREESV(msg); } @@ -1290,13 +1461,13 @@ die(const char* pat, ...) PUSHMARK(SP); XPUSHs(msg); PUTBACK; - perl_call_sv((SV*)cv, G_DISCARD); + call_sv((SV*)cv, G_DISCARD); POPSTACK; LEAVE; } } - PL_restartop = die_where(message); + PL_restartop = die_where(message, msglen); DEBUG_S(PerlIO_printf(PerlIO_stderr(), "%p: die: restartop = %p, was_in_eval = %d, top_env = %p\n", thr, PL_restartop, was_in_eval, PL_top_env)); @@ -1305,22 +1476,47 @@ die(const char* pat, ...) return PL_restartop; } -void -croak(const char* pat, ...) +#ifdef PERL_IMPLICIT_CONTEXT +OP * +Perl_die_nocontext(const char* pat, ...) { - dTHR; + dTHX; + OP *o; va_list args; + va_start(args, pat); + o = do_die(aTHX_ pat, &args); + va_end(args); + return o; +} +#endif + +OP * +Perl_die(pTHX_ const char* pat, ...) +{ + OP *o; + va_list args; + va_start(args, pat); + o = do_die(aTHX_ pat, &args); + va_end(args); + return o; +} + +STATIC void +S_do_croak(pTHX_ const char* pat, va_list *args) +{ + dTHR; char *message; HV *stash; GV *gv; CV *cv; + SV *msv; + STRLEN msglen; - va_start(args, pat); - message = mess(pat, &args); - va_end(args); + msv = mess(pat, args); + message = SvPV(msv,msglen); DEBUG_S(PerlIO_printf(PerlIO_stderr(), "croak: 0x%lx %s", (unsigned long) thr, message)); if (PL_diehook) { - /* sv_2cv might call croak() */ + /* sv_2cv might call Perl_croak() */ SV *olddiehook = PL_diehook; ENTER; SAVESPTR(PL_diehook); @@ -1332,7 +1528,7 @@ croak(const char* pat, ...) SV *msg; ENTER; - msg = newSVpv(message, 0); + msg = newSVpvn(message, msglen); SvREADONLY_on(msg); SAVEFREESV(msg); @@ -1340,35 +1536,67 @@ croak(const char* pat, ...) PUSHMARK(SP); XPUSHs(msg); PUTBACK; - perl_call_sv((SV*)cv, G_DISCARD); + call_sv((SV*)cv, G_DISCARD); POPSTACK; LEAVE; } } if (PL_in_eval) { - PL_restartop = die_where(message); + PL_restartop = die_where(message, msglen); JMPENV_JUMP(3); } - PerlIO_puts(PerlIO_stderr(),message); - (void)PerlIO_flush(PerlIO_stderr()); + { +#ifdef USE_SFIO + /* SFIO can really mess with your errno */ + int e = errno; +#endif + PerlIO_write(PerlIO_stderr(), message, msglen); + (void)PerlIO_flush(PerlIO_stderr()); +#ifdef USE_SFIO + errno = e; +#endif + } my_failure_exit(); } +#ifdef PERL_IMPLICIT_CONTEXT +void +Perl_croak_nocontext(const char *pat, ...) +{ + dTHX; + va_list args; + va_start(args, pat); + do_croak(pat, &args); + /* NOTREACHED */ + va_end(args); +} +#endif /* PERL_IMPLICIT_CONTEXT */ + void -warn(const char* pat,...) +Perl_croak(pTHX_ const char *pat, ...) { va_list args; + va_start(args, pat); + do_croak(pat, &args); + /* NOTREACHED */ + va_end(args); +} + +STATIC void +S_do_warn(pTHX_ const char* pat, va_list *args) +{ char *message; HV *stash; GV *gv; CV *cv; + SV *msv; + STRLEN msglen; - va_start(args, pat); - message = mess(pat, &args); - va_end(args); + msv = mess(pat, args); + message = SvPV(msv, msglen); if (PL_warnhook) { - /* sv_2cv might call warn() */ + /* sv_2cv might call Perl_warn() */ dTHR; SV *oldwarnhook = PL_warnhook; ENTER; @@ -1381,7 +1609,7 @@ warn(const char* pat,...) SV *msg; ENTER; - msg = newSVpv(message, 0); + msg = newSVpvn(message, msglen); SvREADONLY_on(msg); SAVEFREESV(msg); @@ -1389,13 +1617,13 @@ warn(const char* pat,...) PUSHMARK(SP); XPUSHs(msg); PUTBACK; - perl_call_sv((SV*)cv, G_DISCARD); + call_sv((SV*)cv, G_DISCARD); POPSTACK; LEAVE; return; } } - PerlIO_puts(PerlIO_stderr(),message); + PerlIO_write(PerlIO_stderr(), message, msglen); #ifdef LEAKTEST DEBUG_L(*message == '!' ? (xstat(message[1]=='!' @@ -1407,8 +1635,29 @@ warn(const char* pat,...) (void)PerlIO_flush(PerlIO_stderr()); } +#ifdef PERL_IMPLICIT_CONTEXT void -warner(U32 err, const char* pat,...) +Perl_warn_nocontext(const char *pat, ...) +{ + dTHX; + va_list args; + va_start(args, pat); + do_warn(pat, &args); + va_end(args); +} +#endif /* PERL_IMPLICIT_CONTEXT */ + +void +Perl_warn(pTHX_ const char *pat, ...) +{ + va_list args; + va_start(args, pat); + do_warn(pat, &args); + va_end(args); +} + +void +Perl_warner(pTHX_ U32 err, const char* pat,...) { dTHR; va_list args; @@ -1416,9 +1665,12 @@ warner(U32 err, const char* pat,...) HV *stash; GV *gv; CV *cv; + SV *msv; + STRLEN msglen; va_start(args, pat); - message = mess(pat, &args); + msv = mess(pat, &args); + message = SvPV(msv, msglen); va_end(args); if (ckDEAD(err)) { @@ -1426,7 +1678,7 @@ warner(U32 err, const char* pat,...) DEBUG_S(PerlIO_printf(PerlIO_stderr(), "croak: 0x%lx %s", (unsigned long) thr, message)); #endif /* USE_THREADS */ if (PL_diehook) { - /* sv_2cv might call croak() */ + /* sv_2cv might call Perl_croak() */ SV *olddiehook = PL_diehook; ENTER; SAVESPTR(PL_diehook); @@ -1438,30 +1690,30 @@ warner(U32 err, const char* pat,...) SV *msg; ENTER; - msg = newSVpv(message, 0); + msg = newSVpvn(message, msglen); SvREADONLY_on(msg); SAVEFREESV(msg); PUSHMARK(sp); XPUSHs(msg); PUTBACK; - perl_call_sv((SV*)cv, G_DISCARD); + call_sv((SV*)cv, G_DISCARD); LEAVE; } } if (PL_in_eval) { - PL_restartop = die_where(message); + PL_restartop = die_where(message, msglen); JMPENV_JUMP(3); } - PerlIO_puts(PerlIO_stderr(),message); + PerlIO_write(PerlIO_stderr(), message, msglen); (void)PerlIO_flush(PerlIO_stderr()); my_failure_exit(); } else { if (PL_warnhook) { - /* sv_2cv might call warn() */ + /* sv_2cv might call Perl_warn() */ dTHR; SV *oldwarnhook = PL_warnhook; ENTER; @@ -1474,20 +1726,20 @@ warner(U32 err, const char* pat,...) SV *msg; ENTER; - msg = newSVpv(message, 0); + msg = newSVpvn(message, msglen); SvREADONLY_on(msg); SAVEFREESV(msg); PUSHMARK(sp); XPUSHs(msg); PUTBACK; - perl_call_sv((SV*)cv, G_DISCARD); + call_sv((SV*)cv, G_DISCARD); LEAVE; return; } } - PerlIO_puts(PerlIO_stderr(),message); + PerlIO_write(PerlIO_stderr(), message, msglen); #ifdef LEAKTEST DEBUG_L(xstat()); #endif @@ -1496,9 +1748,9 @@ warner(U32 err, const char* pat,...) } #ifndef VMS /* VMS' my_setenv() is in VMS.c */ -#ifndef WIN32 +#if !defined(WIN32) && !defined(CYGWIN32) void -my_setenv(char *nam, char *val) +Perl_my_setenv(pTHX_ char *nam, char *val) { #ifndef PERL_USE_SAFE_PUTENV /* most putenv()s leak, so we manipulate environ directly */ @@ -1564,7 +1816,7 @@ my_setenv(char *nam, char *val) #else /* if WIN32 */ void -my_setenv(char *nam,char *val) +Perl_my_setenv(pTHX_ char *nam,char *val) { #ifdef USE_WIN32_RTL_ENV @@ -1624,7 +1876,7 @@ my_setenv(char *nam,char *val) #endif /* WIN32 */ I32 -setenv_getix(char *nam) +Perl_setenv_getix(pTHX_ char *nam) { register I32 i, len = strlen(nam); @@ -1645,8 +1897,7 @@ setenv_getix(char *nam) #ifdef UNLINK_ALL_VERSIONS I32 -unlnk(f) /* unlink all versions of a file */ -char *f; +Perl_unlnk(pTHX_ char *f) /* unlink all versions of a file */ { I32 i; @@ -1657,7 +1908,7 @@ char *f; #if !defined(HAS_BCOPY) || !defined(HAS_SAFE_BCOPY) char * -my_bcopy(register const char *from,register char *to,register I32 len) +Perl_my_bcopy(pTHX_ register const char *from,register char *to,register I32 len) { char *retval = to; @@ -1677,7 +1928,7 @@ my_bcopy(register const char *from,register char *to,register I32 len) #ifndef HAS_MEMSET void * -my_memset(register char *loc, register I32 ch, register I32 len) +Perl_my_memset(pTHX_ register char *loc, register I32 ch, register I32 len) { char *retval = loc; @@ -1689,7 +1940,7 @@ my_memset(register char *loc, register I32 ch, register I32 len) #if !defined(HAS_BZERO) && !defined(HAS_MEMSET) char * -my_bzero(register char *loc, register I32 len) +Perl_my_bzero(pTHX_ register char *loc, register I32 len) { char *retval = loc; @@ -1701,7 +1952,7 @@ my_bzero(register char *loc, register I32 len) #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP) I32 -my_memcmp(const char *s1, const char *s2, register I32 len) +Perl_my_memcmp(pTHX_ const char *s1, const char *s2, register I32 len) { register U8 *a = (U8 *)s1; register U8 *b = (U8 *)s2; @@ -1746,7 +1997,7 @@ vsprintf(char *dest, const char *pat, char *args) #ifdef MYSWAP #if BYTEORDER != 0x4321 short -my_swap(short s) +Perl_my_swap(pTHX_ short s) { #if (BYTEORDER & 1) == 0 short result; @@ -1759,7 +2010,7 @@ my_swap(short s) } long -my_htonl(long l) +Perl_my_htonl(pTHX_ long l) { union { long result; @@ -1774,7 +2025,7 @@ my_htonl(long l) return u.result; #else #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf) - croak("Unknown BYTEORDER\n"); + Perl_croak(aTHX_ "Unknown BYTEORDER\n"); #else register I32 o; register I32 s; @@ -1788,7 +2039,7 @@ my_htonl(long l) } long -my_ntohl(long l) +Perl_my_ntohl(pTHX_ long l) { union { long l; @@ -1803,7 +2054,7 @@ my_ntohl(long l) return u.l; #else #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf) - croak("Unknown BYTEORDER\n"); + Perl_croak(aTHX_ "Unknown BYTEORDER\n"); #else register I32 o; register I32 s; @@ -1831,8 +2082,7 @@ my_ntohl(long l) #define HTOV(name,type) \ type \ - name (n) \ - register type n; \ + name (register type n) \ { \ union { \ type value; \ @@ -1848,8 +2098,7 @@ my_ntohl(long l) #define VTOH(name,type) \ type \ - name (n) \ - register type n; \ + name (register type n) \ { \ union { \ type value; \ @@ -1881,14 +2130,17 @@ VTOH(vtohl,long) /* VMS' my_popen() is in VMS.c, same with OS/2. */ #if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__OPEN_VM) PerlIO * -my_popen(char *cmd, char *mode) +Perl_my_popen(pTHX_ char *cmd, char *mode) { int p[2]; register I32 This, that; register I32 pid; SV *sv; I32 doexec = strNE(cmd,"-"); + I32 did_pipes = 0; + int pp[2]; + PERL_FLUSHALL_FOR_CHILD; #ifdef OS2 if (doexec) { return my_syspopen(cmd,mode); @@ -1902,11 +2154,17 @@ my_popen(char *cmd, char *mode) } if (PerlProc_pipe(p) < 0) return Nullfp; + if (doexec && PerlProc_pipe(pp) >= 0) + did_pipes = 1; while ((pid = (doexec?vfork():fork())) < 0) { if (errno != EAGAIN) { PerlLIO_close(p[This]); + if (did_pipes) { + PerlLIO_close(pp[0]); + PerlLIO_close(pp[1]); + } if (!doexec) - croak("Can't fork"); + Perl_croak(aTHX_ "Can't fork"); return Nullfp; } sleep(5); @@ -1919,10 +2177,17 @@ my_popen(char *cmd, char *mode) #define THIS that #define THAT This PerlLIO_close(p[THAT]); + if (did_pipes) { + PerlLIO_close(pp[0]); +#if defined(HAS_FCNTL) && defined(F_SETFD) + fcntl(pp[1], F_SETFD, FD_CLOEXEC); +#endif + } if (p[THIS] != (*mode == 'r')) { PerlLIO_dup2(p[THIS], *mode == 'r'); PerlLIO_close(p[THIS]); } +#ifndef OS2 if (doexec) { #if !defined(HAS_FCNTL) || !defined(F_SETFD) int fd; @@ -1931,11 +2196,13 @@ my_popen(char *cmd, char *mode) #define NOFILE 20 #endif for (fd = PL_maxsysfd + 1; fd < NOFILE; fd++) - PerlLIO_close(fd); + if (fd != pp[1]) + PerlLIO_close(fd); #endif - do_exec(cmd); /* may or may not use the shell */ + do_exec3(cmd,pp[1],did_pipes); /* may or may not use the shell */ PerlProc__exit(1); } +#endif /* defined OS2 */ /*SUPPRESS 560*/ if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV)) sv_setiv(GvSV(tmpgv), (IV)getpid()); @@ -1947,6 +2214,8 @@ my_popen(char *cmd, char *mode) } do_execfree(); /* free any memory malloced by child on vfork */ PerlLIO_close(p[that]); + if (did_pipes) + PerlLIO_close(pp[1]); if (p[that] < p[This]) { PerlLIO_dup2(p[This], p[that]); PerlLIO_close(p[This]); @@ -1956,18 +2225,39 @@ my_popen(char *cmd, char *mode) (void)SvUPGRADE(sv,SVt_IV); SvIVX(sv) = pid; PL_forkprocess = pid; + if (did_pipes && pid > 0) { + int errkid; + int n = 0, n1; + + while (n < sizeof(int)) { + n1 = PerlLIO_read(pp[0], + (void*)(((char*)&errkid)+n), + (sizeof(int)) - n); + if (n1 <= 0) + break; + n += n1; + } + if (n) { /* Error */ + if (n != sizeof(int)) + Perl_croak(aTHX_ "panic: kid popen errno read"); + PerlLIO_close(pp[0]); + errno = errkid; /* Propagate errno from kid */ + return Nullfp; + } + } + if (did_pipes) + PerlLIO_close(pp[0]); return PerlIO_fdopen(p[This], mode); } #else #if defined(atarist) || defined(DJGPP) FILE *popen(); PerlIO * -my_popen(cmd,mode) -char *cmd; -char *mode; +Perl_my_popen(pTHX_ char *cmd, char *mode) { /* Needs work for PerlIO ! */ /* used 0 for 2nd parameter to PerlIO-exportFILE; apparently not used */ + PERL_FLUSHALL_FOR_CHILD; return popen(PerlIO_exportFILE(cmd, 0), mode); } #endif @@ -1976,7 +2266,7 @@ char *mode; #ifdef DUMP_FDS void -dump_fds(char *s) +Perl_dump_fds(pTHX_ char *s) { int fd; struct stat tmpstatbuf; @@ -1992,9 +2282,7 @@ dump_fds(char *s) #ifndef HAS_DUP2 int -dup2(oldfd,newfd) -int oldfd; -int newfd; +dup2(int oldfd, int newfd) { #if defined(HAS_FCNTL) && defined(F_DUPFD) if (oldfd == newfd) @@ -2030,7 +2318,7 @@ int newfd; #ifdef HAS_SIGACTION Sighandler_t -rsignal(int signo, Sighandler_t handler) +Perl_rsignal(pTHX_ int signo, Sighandler_t handler) { struct sigaction act, oact; @@ -2051,7 +2339,7 @@ rsignal(int signo, Sighandler_t handler) } Sighandler_t -rsignal_state(int signo) +Perl_rsignal_state(pTHX_ int signo) { struct sigaction oact; @@ -2062,7 +2350,7 @@ rsignal_state(int signo) } int -rsignal_save(int signo, Sighandler_t handler, Sigsave_t *save) +Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save) { struct sigaction act; @@ -2080,7 +2368,7 @@ rsignal_save(int signo, Sighandler_t handler, Sigsave_t *save) } int -rsignal_restore(int signo, Sigsave_t *save) +Perl_rsignal_restore(pTHX_ int signo, Sigsave_t *save) { return sigaction(signo, save, (struct sigaction *)NULL); } @@ -2088,7 +2376,7 @@ rsignal_restore(int signo, Sigsave_t *save) #else /* !HAS_SIGACTION */ Sighandler_t -rsignal(int signo, Sighandler_t handler) +Perl_rsignal(pTHX_ int signo, Sighandler_t handler) { return PerlProc_signal(signo, handler); } @@ -2103,7 +2391,7 @@ sig_trap(int signo) } Sighandler_t -rsignal_state(int signo) +Perl_rsignal_state(pTHX_ int signo) { Sighandler_t oldsig; @@ -2116,14 +2404,14 @@ rsignal_state(int signo) } int -rsignal_save(int signo, Sighandler_t handler, Sigsave_t *save) +Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save) { *save = PerlProc_signal(signo, handler); return (*save == SIG_ERR) ? -1 : 0; } int -rsignal_restore(int signo, Sigsave_t *save) +Perl_rsignal_restore(pTHX_ int signo, Sigsave_t *save) { return (PerlProc_signal(signo, *save) == SIG_ERR) ? -1 : 0; } @@ -2133,7 +2421,7 @@ rsignal_restore(int signo, Sigsave_t *save) /* VMS' my_pclose() is in VMS.c; same with OS/2 */ #if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__OPEN_VM) I32 -my_pclose(PerlIO *ptr) +Perl_my_pclose(pTHX_ PerlIO *ptr) { Sigsave_t hstat, istat, qstat; int status; @@ -2187,9 +2475,9 @@ my_pclose(PerlIO *ptr) } #endif /* !DOSISH */ -#if !defined(DOSISH) || defined(OS2) || defined(WIN32) +#if !defined(DOSISH) || defined(OS2) || defined(WIN32) || defined(CYGWIN32) I32 -wait4pid(int pid, int *statusp, int flags) +Perl_wait4pid(pTHX_ int pid, int *statusp, int flags) { SV *sv; SV** svp; @@ -2234,7 +2522,7 @@ wait4pid(int pid, int *statusp, int flags) { I32 result; if (flags) - croak("Can't do waitpid with flags"); + Perl_croak(aTHX_ "Can't do waitpid with flags"); else { while ((result = PerlProc_wait(statusp)) != pid && pid > 0 && result >= 0) pidgone(result,*statusp); @@ -2249,7 +2537,7 @@ wait4pid(int pid, int *statusp, int flags) void /*SUPPRESS 590*/ -pidgone(int pid, int status) +Perl_pidgone(pTHX_ int pid, int status) { register SV *sv; char spid[TYPE_CHARS(int)]; @@ -2266,12 +2554,11 @@ int pclose(); #ifdef HAS_FORK int /* Cannot prototype with I32 in os2ish.h. */ -my_syspclose(ptr) +my_syspclose(PerlIO *ptr) #else I32 -my_pclose(ptr) +Perl_my_pclose(pTHX_ PerlIO *ptr) #endif -PerlIO *ptr; { /* Needs work for PerlIO ! */ FILE *f = PerlIO_findFILE(ptr); @@ -2282,7 +2569,7 @@ PerlIO *ptr; #endif void -repeatcpy(register char *to, register const char *from, I32 len, register I32 count) +Perl_repeatcpy(pTHX_ register char *to, register const char *from, I32 len, register I32 count) { register I32 todo; register const char *frombase = from; @@ -2302,7 +2589,7 @@ repeatcpy(register char *to, register const char *from, I32 len, register I32 co } U32 -cast_ulong(double f) +Perl_cast_ulong(pTHX_ double f) { long along; @@ -2339,7 +2626,7 @@ cast_ulong(double f) #endif I32 -cast_i32(double f) +Perl_cast_i32(pTHX_ double f) { if (f >= I32_MAX) return (I32) I32_MAX; @@ -2349,26 +2636,40 @@ cast_i32(double f) } IV -cast_iv(double f) +Perl_cast_iv(pTHX_ double f) { - if (f >= IV_MAX) - return (IV) IV_MAX; + if (f >= IV_MAX) { + UV uv; + + if (f >= (double)UV_MAX) + return (IV) UV_MAX; + uv = (UV) f; + return (IV)uv; + } if (f <= IV_MIN) return (IV) IV_MIN; return (IV) f; } UV -cast_uv(double f) +Perl_cast_uv(pTHX_ double f) { if (f >= MY_UV_MAX) return (UV) MY_UV_MAX; + if (f < 0) { + IV iv; + + if (f < IV_MIN) + return (UV)IV_MIN; + iv = (IV) f; + return (UV) iv; + } return (UV) f; } #ifndef HAS_RENAME I32 -same_dirent(char *a, char *b) +Perl_same_dirent(pTHX_ char *a, char *b) { char *fa = strrchr(a,'/'); char *fb = strrchr(b,'/'); @@ -2404,7 +2705,7 @@ same_dirent(char *a, char *b) #endif /* !HAS_RENAME */ UV -scan_bin(char *start, I32 len, I32 *retlen) +Perl_scan_bin(pTHX_ char *start, I32 len, I32 *retlen) { register char *s = start; register UV retval = 0; @@ -2412,22 +2713,22 @@ scan_bin(char *start, I32 len, I32 *retlen) while (len && *s >= '0' && *s <= '1') { register UV n = retval << 1; if (!overflowed && (n >> 1) != retval) { - warn("Integer overflow in binary number"); + Perl_warn(aTHX_ "Integer overflow in binary number"); overflowed = TRUE; } retval = n | (*s++ - '0'); len--; } - if (len && (*s >= '2' || *s <= '9')) { + if (len && (*s >= '2' && *s <= '9')) { dTHR; if (ckWARN(WARN_UNSAFE)) - warner(WARN_UNSAFE, "Illegal binary digit '%c' ignored", *s); + Perl_warner(aTHX_ WARN_UNSAFE, "Illegal binary digit '%c' ignored", *s); } *retlen = s - start; return retval; } UV -scan_oct(char *start, I32 len, I32 *retlen) +Perl_scan_oct(pTHX_ char *start, I32 len, I32 *retlen) { register char *s = start; register UV retval = 0; @@ -2436,7 +2737,7 @@ scan_oct(char *start, I32 len, I32 *retlen) while (len && *s >= '0' && *s <= '7') { register UV n = retval << 3; if (!overflowed && (n >> 3) != retval) { - warn("Integer overflow in octal number"); + Perl_warn(aTHX_ "Integer overflow in octal number"); overflowed = TRUE; } retval = n | (*s++ - '0'); @@ -2445,14 +2746,14 @@ scan_oct(char *start, I32 len, I32 *retlen) if (len && (*s == '8' || *s == '9')) { dTHR; if (ckWARN(WARN_OCTAL)) - warner(WARN_OCTAL, "Illegal octal digit '%c' ignored", *s); + Perl_warner(aTHX_ WARN_OCTAL, "Illegal octal digit '%c' ignored", *s); } *retlen = s - start; return retval; } UV -scan_hex(char *start, I32 len, I32 *retlen) +Perl_scan_hex(pTHX_ char *start, I32 len, I32 *retlen) { register char *s = start; register UV retval = 0; @@ -2469,13 +2770,13 @@ scan_hex(char *start, I32 len, I32 *retlen) dTHR; --s; if (ckWARN(WARN_UNSAFE)) - warner(WARN_UNSAFE,"Illegal hex digit '%c' ignored", *s); + Perl_warner(aTHX_ WARN_UNSAFE,"Illegal hex digit '%c' ignored", *s); break; } } n = retval << 4; if (!overflowed && (n >> 4) != retval) { - warn("Integer overflow in hex number"); + Perl_warn(aTHX_ "Integer overflow in hex number"); overflowed = TRUE; } retval = n | ((tmp - PL_hexdigit) & 15); @@ -2485,7 +2786,7 @@ scan_hex(char *start, I32 len, I32 *retlen) } char* -find_script(char *scriptname, bool dosearch, char **search_ext, I32 flags) +Perl_find_script(pTHX_ char *scriptname, bool dosearch, char **search_ext, I32 flags) { dTHR; char *xfound = Nullch; @@ -2684,7 +2985,7 @@ find_script(char *scriptname, bool dosearch, char **search_ext, I32 flags) seen_dot = 1; /* Disable message. */ if (!xfound) { if (flags & 1) { /* do or die? */ - croak("Can't %s %s%s%s", + Perl_croak(aTHX_ "Can't %s %s%s%s", (xfailed ? "execute" : "find"), (xfailed ? xfailed : scriptname), (xfailed ? "" : " on PATH"), @@ -2710,13 +3011,13 @@ schedule(void) } void -perl_cond_init(perl_cond *cp) +Perl_cond_init(pTHX_ perl_cond *cp) { *cp = 0; } void -perl_cond_signal(perl_cond *cp) +Perl_cond_signal(pTHX_ perl_cond *cp) { perl_os_thread t; perl_cond cond = *cp; @@ -2736,7 +3037,7 @@ perl_cond_signal(perl_cond *cp) } void -perl_cond_broadcast(perl_cond *cp) +Perl_cond_broadcast(pTHX_ perl_cond *cp) { perl_os_thread t; perl_cond cond, cond_next; @@ -2757,12 +3058,12 @@ perl_cond_broadcast(perl_cond *cp) } void -perl_cond_wait(perl_cond *cp) +Perl_cond_wait(pTHX_ perl_cond *cp) { perl_cond cond; if (thr->i.next_run == thr) - croak("panic: perl_cond_wait called by last runnable thread"); + Perl_croak(aTHX_ "panic: perl_cond_wait called by last runnable thread"); New(666, cond, 1, struct perl_wait_queue); cond->thread = thr; @@ -2777,18 +3078,18 @@ perl_cond_wait(perl_cond *cp) #ifdef PTHREAD_GETSPECIFIC_INT struct perl_thread * -getTHR _((void)) +Perl_getTHR(pTHX) { pthread_addr_t t; if (pthread_getspecific(PL_thr_key, &t)) - croak("panic: pthread_getspecific"); + Perl_croak(aTHX_ "panic: pthread_getspecific"); return (struct perl_thread *) t; } #endif MAGIC * -condpair_magic(SV *sv) +Perl_condpair_magic(pTHX_ SV *sv) { MAGIC *mg; @@ -2802,11 +3103,11 @@ condpair_magic(SV *sv) COND_INIT(&cp->owner_cond); COND_INIT(&cp->cond); cp->owner = 0; - LOCK_SV_MUTEX; + MUTEX_LOCK(&PL_cred_mutex); /* XXX need separate mutex? */ mg = mg_find(sv, 'm'); if (mg) { /* someone else beat us to initialising it */ - UNLOCK_SV_MUTEX; + MUTEX_UNLOCK(&PL_cred_mutex); /* XXX need separate mutex? */ MUTEX_DESTROY(&cp->mutex); COND_DESTROY(&cp->owner_cond); COND_DESTROY(&cp->cond); @@ -2817,7 +3118,7 @@ condpair_magic(SV *sv) mg = SvMAGIC(sv); mg->mg_ptr = (char *)cp; mg->mg_len = sizeof(cp); - UNLOCK_SV_MUTEX; + MUTEX_UNLOCK(&PL_cred_mutex); /* XXX need separate mutex? */ DEBUG_S(WITH_THR(PerlIO_printf(PerlIO_stderr(), "%p: condpair_magic %p\n", thr, sv));) } @@ -2833,9 +3134,11 @@ condpair_magic(SV *sv) * thread calling new_struct_thread) clearly satisfies this constraint. */ struct perl_thread * -new_struct_thread(struct perl_thread *t) +Perl_new_struct_thread(pTHX_ struct perl_thread *t) { +#ifndef PERL_IMPLICIT_CONTEXT struct perl_thread *thr; +#endif SV *sv; SV **svp; I32 i; @@ -2857,8 +3160,10 @@ new_struct_thread(struct perl_thread *t) Zero(thr, 1, struct perl_thread); #endif + PL_protect = FUNC_NAME_TO_PTR(Perl_default_protect); + thr->oursv = sv; - init_stacks(ARGS); + init_stacks(); PL_curcop = &PL_compiling; thr->cvcache = newHV(); @@ -2882,13 +3187,13 @@ new_struct_thread(struct perl_thread *t) PL_start_env.je_mustcatch = TRUE; PL_top_env = &PL_start_env; - PL_in_eval = FALSE; + PL_in_eval = EVAL_NULL; /* ~(EVAL_INEVAL|EVAL_WARNONLY|EVAL_KEEPERR) */ PL_restartop = 0; PL_statname = NEWSV(66,0); PL_maxscream = -1; - PL_regcompp = FUNC_NAME_TO_PTR(pregcomp); - PL_regexecp = FUNC_NAME_TO_PTR(regexec_flags); + PL_regcompp = FUNC_NAME_TO_PTR(Perl_pregcomp); + PL_regexecp = FUNC_NAME_TO_PTR(Perl_regexec_flags); PL_regindent = 0; PL_reginterp_cnt = 0; PL_lastscream = Nullsv; @@ -2900,6 +3205,8 @@ new_struct_thread(struct perl_thread *t) /* parent thread's data needs to be locked while we make copy */ MUTEX_LOCK(&t->mutex); + PL_protect = t->Tprotect; + PL_curcop = t->Tcurcop; /* XXX As good a guess as any? */ PL_defstash = t->Tdefstash; /* XXX maybe these should */ PL_curstash = t->Tcurstash; /* always be set to main? */ @@ -2943,7 +3250,7 @@ new_struct_thread(struct perl_thread *t) MUTEX_UNLOCK(&t->mutex); #ifdef HAVE_THREAD_INTERN - init_thread_intern(thr); + Perl_init_thread_intern(thr); #endif /* HAVE_THREAD_INTERN */ return thr; } @@ -2964,45 +3271,56 @@ Perl_huge(void) #ifdef PERL_GLOBAL_STRUCT struct perl_vars * -Perl_GetVars(void) +Perl_GetVars(pTHX) { return &PL_Vars; } #endif char ** -get_op_names(void) +Perl_get_op_names(pTHX) { return PL_op_name; } char ** -get_op_descs(void) +Perl_get_op_descs(pTHX) { return PL_op_desc; } char * -get_no_modify(void) +Perl_get_no_modify(pTHX) { return (char*)PL_no_modify; } U32 * -get_opargs(void) +Perl_get_opargs(pTHX) { return PL_opargs; } -SV ** -get_specialsv_list(void) +PPADDR_t* +Perl_get_ppaddr(pTHX) +{ + return &PL_ppaddr; +} + +#ifndef HAS_GETENV_LEN +char * +Perl_getenv_len(pTHX_ char *env_elem, unsigned long *len) { - return PL_specialsv_list; + char *env_trans = PerlEnv_getenv(env_elem); + if (env_trans) + *len = strlen(env_trans); + return env_trans; } +#endif MGVTBL* -get_vtbl(int vtbl_id) +Perl_get_vtbl(pTHX_ int vtbl_id) { MGVTBL* result = Null(MGVTBL*); @@ -3098,7 +3416,71 @@ get_vtbl(int vtbl_id) case want_vtbl_amagicelem: result = &PL_vtbl_amagicelem; break; + case want_vtbl_backref: + result = &PL_vtbl_backref; + break; } return result; } +I32 +Perl_my_fflush_all(pTHX) +{ +#ifdef FFLUSH_NULL + return PerlIO_flush(NULL); +#else + long open_max = -1; +# if defined(FFLUSH_ALL) && defined(HAS_STDIO_STREAM_ARRAY) +# ifdef PERL_FFLUSH_ALL_FOPEN_MAX + open_max = PERL_FFLUSH_ALL_FOPEN_MAX; +# else +# if defined(HAS_SYSCONF) && defined(_SC_OPEN_MAX) + open_max = sysconf(_SC_OPEN_MAX); +# else +# ifdef FOPEN_MAX + open_max = FOPEN_MAX; +# else +# ifdef OPEN_MAX + open_max = OPEN_MAX; +# else +# ifdef _NFILE + open_max = _NFILE; +# endif +# endif +# endif +# endif +# endif + if (open_max > 0) { + long i; + for (i = 0; i < open_max; i++) + if (STDIO_STREAM_ARRAY[i]._file >= 0 && + STDIO_STREAM_ARRAY[i]._file < open_max && + STDIO_STREAM_ARRAY[i]._flag) + PerlIO_flush(&STDIO_STREAM_ARRAY[i]); + return 0; + } +# endif + SETERRNO(EBADF,RMS$_IFI); + return EOF; +#endif +} + +double +Perl_my_atof(const char* s) { +#ifdef USE_LOCALE_NUMERIC + if ((PL_hints & HINT_LOCALE) && PL_numeric_local) { + double x, y; + + x = atof(s); + SET_NUMERIC_STANDARD(); + y = atof(s); + SET_NUMERIC_LOCAL(); + if ((y < 0.0 && y < x) || (y > 0.0 && y > x)) + return y; + return x; + } else + return atof(s); +#else + return atof(s); +#endif +}