X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=util.c;h=1261b98331d030c82cf666d381f960491fb6ca94;hb=0e06870bf080a38cda51c06c6612359afc2334e1;hp=d48c1dd1a1857a02f5b54225f6d8b2c059207ac1;hpb=20ce7b12268a3d32b5b246928de5084322e709cf;p=p5sagit%2Fp5-mst-13.2.git diff --git a/util.c b/util.c index d48c1dd..1261b98 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,6 @@ /* util.c * - * Copyright (c) 1991-1999, Larry Wall + * Copyright (c) 1991-2001, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -13,8 +13,10 @@ */ #include "EXTERN.h" +#define PERL_IN_UTIL_C #include "perl.h" +#ifndef PERL_MICRO #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) #include #endif @@ -22,10 +24,6 @@ #ifndef SIG_ERR # define SIG_ERR ((Sighandler_t) -1) #endif - -/* XXX If this causes problems, set i_unistd=undef in the hint file. */ -#ifdef I_UNISTD -# include #endif #ifdef I_VFORK @@ -39,22 +37,18 @@ # define vfork fork #endif -#ifdef I_FCNTL -# include -#endif -#ifdef I_SYS_FILE -# include -#endif - #ifdef I_SYS_WAIT # 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]; @@ -62,6 +56,10 @@ long lastxycount[MAXXCOUNT][MAXYCOUNT]; #endif +#if defined(HAS_FCNTL) && defined(F_SETFD) && !defined(FD_CLOEXEC) +# define FD_CLOEXEC 1 /* NeXT needs this */ +#endif + /* paranoid version of system's malloc() */ /* NOTE: Do not call the next three routines directly. Use the macros @@ -71,31 +69,30 @@ long lastxycount[MAXXCOUNT][MAXYCOUNT]; */ Malloc_t -safesysmalloc(MEM_SIZE size) +Perl_safesysmalloc(MEM_SIZE size) { + dTHX; Malloc_t ptr; #ifdef HAS_64K_LIMIT if (size > 0xffff) { - PerlIO_printf(PerlIO_stderr(), "Allocation too large: %lx\n", size) FLUSH; - my_exit(1); + PerlIO_printf(Perl_error_log, + "Allocation too large: %lx\n", size) FLUSH; + my_exit(1); } #endif /* HAS_64K_LIMIT */ #ifdef DEBUGGING if ((long)size < 0) - croak("panic: malloc"); -#endif - ptr = PerlMem_malloc(size?size:1); /* malloc(0) is NASTY on our system */ -#if !(defined(I286) || defined(atarist)) - DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%x: (%05d) malloc %ld bytes\n",ptr,PL_an++,(long)size)); -#else - DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) malloc %ld bytes\n",ptr,PL_an++,(long)size)); + Perl_croak_nocontext("panic: malloc"); #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) malloc %ld bytes\n",PTR2UV(ptr),(long)PL_an++,(long)size)); if (ptr != Nullch) return ptr; else if (PL_nomemok) return Nullch; else { - PerlIO_puts(PerlIO_stderr(),PL_no_mem) FLUSH; + PerlIO_puts(Perl_error_log,PL_no_mem) FLUSH; my_exit(1); return Nullch; } @@ -105,16 +102,17 @@ 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) { + dTHX; Malloc_t ptr; -#if !defined(STANDARD_C) && !defined(HAS_REALLOC_PROTOTYPE) +#if !defined(STANDARD_C) && !defined(HAS_REALLOC_PROTOTYPE) && !defined(PERL_MICRO) Malloc_t PerlMem_realloc(); #endif /* !defined(STANDARD_C) && !defined(HAS_REALLOC_PROTOTYPE) */ -#ifdef HAS_64K_LIMIT +#ifdef HAS_64K_LIMIT if (size > 0xffff) { - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, "Reallocation too large: %lx\n", size) FLUSH; my_exit(1); } @@ -128,28 +126,20 @@ 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); + ptr = (Malloc_t)PerlMem_realloc(where,size); + PERL_ALLOC_CHECK(ptr); -#if !(defined(I286) || defined(atarist)) - DEBUG_m( { - PerlIO_printf(Perl_debug_log, "0x%x: (%05d) rfree\n",where,PL_an++); - PerlIO_printf(Perl_debug_log, "0x%x: (%05d) realloc %ld bytes\n",ptr,PL_an++,(long)size); - } ) -#else - DEBUG_m( { - PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) rfree\n",where,PL_an++); - PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) realloc %ld bytes\n",ptr,PL_an++,(long)size); - } ) -#endif + 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) return ptr; else if (PL_nomemok) return Nullch; else { - PerlIO_puts(PerlIO_stderr(),PL_no_mem) FLUSH; + PerlIO_puts(Perl_error_log,PL_no_mem) FLUSH; my_exit(1); return Nullch; } @@ -159,13 +149,12 @@ 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++)); -#else - DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) free\n",(char *) where,PL_an++)); +#ifdef PERL_IMPLICIT_SYS + dTHX; #endif + DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) free\n",PTR2UV(where),(long)PL_an++)); if (where) { /*SUPPRESS 701*/ PerlMem_free(where); @@ -175,28 +164,26 @@ 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) { + dTHX; Malloc_t ptr; #ifdef HAS_64K_LIMIT if (size * count > 0xffff) { - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, "Allocation too large: %lx\n", size * count) FLUSH; 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 */ -#if !(defined(I286) || defined(atarist)) - DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%x: (%05d) calloc %ld x %ld bytes\n",ptr,PL_an++,(long)count,(long)size)); -#else - DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) calloc %ld x %ld bytes\n",ptr,PL_an++,(long)count,(long)size)); -#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); return ptr; @@ -204,7 +191,7 @@ safesyscalloc(MEM_SIZE count, MEM_SIZE size) else if (PL_nomemok) return Nullch; else { - PerlIO_puts(PerlIO_stderr(),PL_no_mem) FLUSH; + PerlIO_puts(Perl_error_log,PL_no_mem) FLUSH; my_exit(1); return Nullch; } @@ -235,7 +222,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,18 +234,18 @@ 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; if (!wh) return safexmalloc(0,size); - + { MEM_SIZE old = sizeof_chunk(where - ALIGN); int t = typeof_chunk(where - ALIGN); register char* new = (char*)saferealloc(where - ALIGN, size + ALIGN); - + xycount[t][SIZE_TO_Y(old)]--; xycount[t][SIZE_TO_Y(size)]++; xcount[t] += size - old; @@ -268,12 +255,12 @@ safexrealloc(Malloc_t wh, MEM_SIZE size) } void -safexfree(Malloc_t wh) +Perl_safexfree(Malloc_t wh) { I32 x; char *where = (char*)wh; MEM_SIZE size; - + if (!where) return; where -= ALIGN; @@ -285,7 +272,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 +283,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]; @@ -305,8 +292,8 @@ xstat(int flag) for (j = 0; j < MAXYCOUNT; j++) { subtot[j] = 0; } - - PerlIO_printf(PerlIO_stderr(), " Id subtot 4 8 12 16 20 24 28 32 36 40 48 56 64 72 80 80+\n", total); + + PerlIO_printf(Perl_debug_log, " Id subtot 4 8 12 16 20 24 28 32 36 40 48 56 64 72 80 80+\n", total); for (i = 0; i < MAXXCOUNT; i++) { total += xcount[i]; for (j = 0; j < MAXYCOUNT; j++) { @@ -314,40 +301,40 @@ xstat(int flag) } if (flag == 0 ? xcount[i] /* Have something */ - : (flag == 2 + : (flag == 2 ? xcount[i] != lastxcount[i] /* Changed */ : xcount[i] > lastxcount[i])) { /* Growed */ - PerlIO_printf(PerlIO_stderr(),"%2d %02d %7ld ", i / 100, i % 100, + PerlIO_printf(Perl_debug_log,"%2d %02d %7ld ", i / 100, i % 100, flag == 2 ? xcount[i] - lastxcount[i] : xcount[i]); lastxcount[i] = xcount[i]; for (j = 0; j < MAXYCOUNT; j++) { - if ( flag == 0 + if ( flag == 0 ? xycount[i][j] /* Have something */ - : (flag == 2 + : (flag == 2 ? xycount[i][j] != lastxycount[i][j] /* Changed */ : xycount[i][j] > lastxycount[i][j])) { /* Growed */ - PerlIO_printf(PerlIO_stderr(),"%3ld ", - flag == 2 - ? xycount[i][j] - lastxycount[i][j] + PerlIO_printf(Perl_debug_log,"%3ld ", + flag == 2 + ? xycount[i][j] - lastxycount[i][j] : xycount[i][j]); lastxycount[i][j] = xycount[i][j]; } else { - PerlIO_printf(PerlIO_stderr(), " . ", xycount[i][j]); + PerlIO_printf(Perl_debug_log, " . ", xycount[i][j]); } } - PerlIO_printf(PerlIO_stderr(), "\n"); + PerlIO_printf(Perl_debug_log, "\n"); } } if (flag != 2) { - PerlIO_printf(PerlIO_stderr(), "Total %7ld ", total); + PerlIO_printf(Perl_debug_log, "Total %7ld ", total); for (j = 0; j < MAXYCOUNT; j++) { if (subtot[j]) { - PerlIO_printf(PerlIO_stderr(), "%3ld ", subtot[j]); + PerlIO_printf(Perl_debug_log, "%3ld ", subtot[j]); } else { - PerlIO_printf(PerlIO_stderr(), " . "); + PerlIO_printf(Perl_debug_log, " . "); } } - PerlIO_printf(PerlIO_stderr(), "\n"); + PerlIO_printf(Perl_debug_log, "\n"); } } @@ -356,7 +343,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 +372,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 +402,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 +431,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 +461,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_ char *newctype) { #ifdef USE_LOCALE_CTYPE @@ -493,10 +480,54 @@ perl_new_ctype(const char *newctype) } /* + * Standardize the locale name from a string returned by 'setlocale'. + * + * The standard return value of setlocale() is either + * (1) "xx_YY" if the first argument of setlocale() is not LC_ALL + * (2) "xa_YY xb_YY ..." if the first argument of setlocale() is LC_ALL + * (the space-separated values represent the various sublocales, + * in some unspecificed order) + * + * In some platforms it has a form like "LC_SOMETHING=Lang_Country.866\n", + * which is harmful for further use of the string in setlocale(). + * + */ +STATIC char * +S_stdize_locale(pTHX_ char *locs) +{ + char *s; + bool okay = TRUE; + + if ((s = strchr(locs, '='))) { + char *t; + + okay = FALSE; + if ((t = strchr(s, '.'))) { + char *u; + + if ((u = strchr(t, '\n'))) { + + if (u[1] == 0) { + STRLEN len = u - s; + Move(s + 1, locs, len, char); + locs[len] = 0; + okay = TRUE; + } + } + } + } + + if (!okay) + Perl_croak(aTHX_ "Can't fix broken locale name \"%s\"", locs); + + return locs; +} + +/* * Set up for a new collation locale. */ void -perl_new_collate(const char *newcoll) +Perl_new_collate(pTHX_ char *newcoll) { #ifdef USE_LOCALE_COLLATE @@ -505,17 +536,17 @@ perl_new_collate(const char *newcoll) ++PL_collation_ix; Safefree(PL_collation_name); PL_collation_name = NULL; - PL_collation_standard = TRUE; - PL_collxfrm_base = 0; - PL_collxfrm_mult = 2; } + PL_collation_standard = TRUE; + PL_collxfrm_base = 0; + PL_collxfrm_mult = 2; return; } if (! PL_collation_name || strNE(PL_collation_name, newcoll)) { ++PL_collation_ix; Safefree(PL_collation_name); - PL_collation_name = savepv(newcoll); + PL_collation_name = stdize_locale(savepv(newcoll)); PL_collation_standard = (strEQ(newcoll, "C") || strEQ(newcoll, "POSIX")); { @@ -527,7 +558,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 +567,30 @@ perl_new_collate(const char *newcoll) #endif /* USE_LOCALE_COLLATE */ } +void +Perl_set_numeric_radix(pTHX) +{ +#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 */ +#endif /* USE_LOCALE_NUMERIC */ +} + /* * Set up for a new numeric locale. */ void -perl_new_numeric(const char *newnum) +Perl_new_numeric(pTHX_ char *newnum) { #ifdef USE_LOCALE_NUMERIC @@ -548,24 +598,25 @@ perl_new_numeric(const char *newnum) if (PL_numeric_name) { Safefree(PL_numeric_name); PL_numeric_name = NULL; - PL_numeric_standard = TRUE; - PL_numeric_local = TRUE; } + PL_numeric_standard = TRUE; + PL_numeric_local = TRUE; return; } if (! PL_numeric_name || strNE(PL_numeric_name, newnum)) { Safefree(PL_numeric_name); - PL_numeric_name = savepv(newnum); + PL_numeric_name = stdize_locale(savepv(newnum)); PL_numeric_standard = (strEQ(newnum, "C") || strEQ(newnum, "POSIX")); PL_numeric_local = TRUE; + set_numeric_radix(); } #endif /* USE_LOCALE_NUMERIC */ } void -perl_set_numeric_standard(void) +Perl_set_numeric_standard(pTHX) { #ifdef USE_LOCALE_NUMERIC @@ -573,13 +624,14 @@ perl_set_numeric_standard(void) setlocale(LC_NUMERIC, "C"); PL_numeric_standard = TRUE; PL_numeric_local = FALSE; + set_numeric_radix(); } #endif /* USE_LOCALE_NUMERIC */ } void -perl_set_numeric_local(void) +Perl_set_numeric_local(pTHX) { #ifdef USE_LOCALE_NUMERIC @@ -587,17 +639,17 @@ perl_set_numeric_local(void) setlocale(LC_NUMERIC, PL_numeric_name); PL_numeric_standard = FALSE; PL_numeric_local = TRUE; + 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 @@ -647,6 +699,8 @@ perl_init_i18nl10n(int printwarn) (!done && (lang || PerlEnv_getenv("LC_CTYPE"))) ? "" : Nullch))) setlocale_failure = TRUE; + else + curctype = savepv(curctype); #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE if (! (curcoll = @@ -654,6 +708,8 @@ perl_init_i18nl10n(int printwarn) (!done && (lang || PerlEnv_getenv("LC_COLLATE"))) ? "" : Nullch))) setlocale_failure = TRUE; + else + curcoll = savepv(curcoll); #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC if (! (curnum = @@ -661,6 +717,8 @@ perl_init_i18nl10n(int printwarn) (!done && (lang || PerlEnv_getenv("LC_NUMERIC"))) ? "" : Nullch))) setlocale_failure = TRUE; + else + curnum = savepv(curnum); #endif /* USE_LOCALE_NUMERIC */ } @@ -677,61 +735,67 @@ perl_init_i18nl10n(int printwarn) #ifdef USE_LOCALE_CTYPE if (! (curctype = setlocale(LC_CTYPE, ""))) setlocale_failure = TRUE; + else + curctype = savepv(curctype); #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE if (! (curcoll = setlocale(LC_COLLATE, ""))) setlocale_failure = TRUE; + else + curcoll = savepv(curcoll); #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC if (! (curnum = setlocale(LC_NUMERIC, ""))) setlocale_failure = TRUE; + else + curnum = savepv(curnum); #endif /* USE_LOCALE_NUMERIC */ } if (setlocale_failure) { char *p; - bool locwarn = (printwarn > 1 || - printwarn && - (!(p = PerlEnv_getenv("PERL_BADLANG")) || atoi(p))); + bool locwarn = (printwarn > 1 || + (printwarn && + (!(p = PerlEnv_getenv("PERL_BADLANG")) || atoi(p)))); if (locwarn) { #ifdef LC_ALL - - PerlIO_printf(PerlIO_stderr(), + + PerlIO_printf(Perl_error_log, "perl: warning: Setting locale failed.\n"); #else /* !LC_ALL */ - - PerlIO_printf(PerlIO_stderr(), + + PerlIO_printf(Perl_error_log, "perl: warning: Setting locale failed for the categories:\n\t"); #ifdef USE_LOCALE_CTYPE if (! curctype) - PerlIO_printf(PerlIO_stderr(), "LC_CTYPE "); + PerlIO_printf(Perl_error_log, "LC_CTYPE "); #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE if (! curcoll) - PerlIO_printf(PerlIO_stderr(), "LC_COLLATE "); + PerlIO_printf(Perl_error_log, "LC_COLLATE "); #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC if (! curnum) - PerlIO_printf(PerlIO_stderr(), "LC_NUMERIC "); + PerlIO_printf(Perl_error_log, "LC_NUMERIC "); #endif /* USE_LOCALE_NUMERIC */ - PerlIO_printf(PerlIO_stderr(), "\n"); + PerlIO_printf(Perl_error_log, "\n"); #endif /* LC_ALL */ - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, "perl: warning: Please check that your locale settings:\n"); #ifdef __GLIBC__ - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, "\tLANGUAGE = %c%s%c,\n", language ? '"' : '(', language ? language : "unset", language ? '"' : ')'); #endif - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, "\tLC_ALL = %c%s%c,\n", lc_all ? '"' : '(', lc_all ? lc_all : "unset", @@ -743,18 +807,18 @@ perl_init_i18nl10n(int printwarn) if (strnEQ(*e, "LC_", 3) && strnNE(*e, "LC_ALL=", 7) && (p = strchr(*e, '='))) - PerlIO_printf(PerlIO_stderr(), "\t%.*s = \"%s\",\n", + PerlIO_printf(Perl_error_log, "\t%.*s = \"%s\",\n", (int)(p - *e), *e, p + 1); } } - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, "\tLANG = %c%s%c\n", lang ? '"' : '(', lang ? lang : "unset", lang ? '"' : ')'); - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, " are supported and installed on your system.\n"); } @@ -762,13 +826,13 @@ perl_init_i18nl10n(int printwarn) if (setlocale(LC_ALL, "C")) { if (locwarn) - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, "perl: warning: Falling back to the standard locale (\"C\").\n"); ok = 0; } else { if (locwarn) - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, "perl: warning: Failed to fall back to the standard locale (\"C\").\n"); ok = -1; } @@ -788,7 +852,7 @@ perl_init_i18nl10n(int printwarn) ) { if (locwarn) - PerlIO_printf(PerlIO_stderr(), + PerlIO_printf(Perl_error_log, "perl: warning: Cannot fall back to the standard locale (\"C\").\n"); ok = -1; } @@ -796,38 +860,52 @@ perl_init_i18nl10n(int printwarn) #endif /* ! LC_ALL */ #ifdef USE_LOCALE_CTYPE - curctype = setlocale(LC_CTYPE, Nullch); + curctype = savepv(setlocale(LC_CTYPE, Nullch)); #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE - curcoll = setlocale(LC_COLLATE, Nullch); + curcoll = savepv(setlocale(LC_COLLATE, Nullch)); #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC - curnum = setlocale(LC_NUMERIC, Nullch); + curnum = savepv(setlocale(LC_NUMERIC, Nullch)); #endif /* USE_LOCALE_NUMERIC */ } + else { #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 */ +#ifdef USE_LOCALE_CTYPE + if (curctype != NULL) + Safefree(curctype); +#endif /* USE_LOCALE_CTYPE */ +#ifdef USE_LOCALE_COLLATE + if (curcoll != NULL) + Safefree(curcoll); +#endif /* USE_LOCALE_COLLATE */ +#ifdef USE_LOCALE_NUMERIC + if (curnum != NULL) + Safefree(curnum); +#endif /* USE_LOCALE_NUMERIC */ return ok; } /* 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 +918,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 */ @@ -897,8 +975,17 @@ mem_collxfrm(const char *s, STRLEN len, STRLEN *xlen) If FBMcf_TAIL, the table is created as if the string has a trailing \n. */ +/* +=for apidoc fbm_compile + +Analyses the string in order to make fast searches on it using fbm_instr() +-- the Boyer-Moore algorithm. + +=cut +*/ + void -fbm_compile(SV *sv, U32 flags /* not used yet */) +Perl_fbm_compile(pTHX_ SV *sv, U32 flags) { register U8 *s; register U8 *table; @@ -914,23 +1001,23 @@ fbm_compile(SV *sv, U32 flags /* not used yet */) if (len == 0) /* TAIL might be on on a zero-length string. */ return; if (len > 2) { - I32 mlen = len; + U8 mlen; unsigned char *sb; - if (mlen > 255) + if (len > 255) mlen = 255; - Sv_Grow(sv,len + 256 + FBM_TABLE_OFFSET); + else + mlen = (U8)len; + 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] = mlen; - } - table[-1] = flags; /* Not used yet */ + s = table - 1 - FBM_TABLE_OFFSET; /* last char */ + memset((void*)table, mlen, 256); + table[-1] = (U8)flags; i = 0; - sb = s - mlen; + sb = s - mlen + 1; /* first char (maybe) */ while (s >= sb) { if (table[*s] == mlen) - table[*s] = i; + table[*s] = (U8)i; s--, i++; } } @@ -949,15 +1036,27 @@ fbm_compile(SV *sv, U32 flags /* not used yet */) 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))); + 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 */ +/* +=for apidoc fbm_instr + +Returns the location of the SV in the string delimited by C and +C. It returns C if the string can't be found. The C +does not have to be fbm_compiled, but the search will not be as fast +then. + +=cut +*/ + 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; STRLEN l; @@ -966,17 +1065,16 @@ fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 register I32 multiline = flags & FBMrf_MULTILINE; if (bigend - big < littlelen) { - check_tail: - if ( SvTAIL(littlestr) + if ( SvTAIL(littlestr) && (bigend - big == littlelen - 1) - && (littlelen == 1 - || *big == *little && memEQ(big, little, littlelen - 1))) + && (littlelen == 1 + || (*big == *little && + memEQ((char *)big, (char *)little, littlelen - 1)))) return (char*)big; return Nullch; } if (littlelen <= 2) { /* Special-cased */ - register char c; if (littlelen == 1) { if (SvTAIL(littlestr) && !multiline) { /* Anchor only! */ @@ -1061,15 +1159,17 @@ fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 } if (SvTAIL(littlestr) && !multiline) { /* tail anchored? */ s = bigend - littlelen; - if (s >= big - && bigend[-1] == '\n' - && *s == *little + if (s >= big && bigend[-1] == '\n' && *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)) + } + if (s[1] == *little + && memEQ((char*)s + 2, (char*)little + 1, littlelen - 2)) + { return (char*)s + 1; /* how sweet it is */ + } return Nullch; } if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) { @@ -1079,14 +1179,16 @@ fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 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)) + if (*s == *little + && memEQ((char*)s + 1, (char*)little + 1, littlelen - 2)) + { return (char*)s; + } return Nullch; } return b; } - + { /* Do actual FBM. */ register unsigned char *table = little + littlelen + FBM_TABLE_OFFSET; register unsigned char *oldlittle; @@ -1103,7 +1205,7 @@ fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 top2: /*SUPPRESS 560*/ - if (tmp = table[*s]) { + if ((tmp = table[*s])) { #ifdef POINTERRIGOR if (bigend - s > tmp) { s += tmp; @@ -1124,7 +1226,6 @@ fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 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 */ @@ -1136,7 +1237,8 @@ fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 } check_end: if ( s == bigend && (table[-1] & FBMcf_TAIL) - && memEQ(bigend - littlelen, oldlittle - littlelen, littlelen) ) + && memEQ((char *)(bigend - littlelen), + (char *)(oldlittle - littlelen), littlelen) ) return (char*)bigend - littlelen; return Nullch; } @@ -1146,7 +1248,7 @@ fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 of ends of some substring of bigstr. If `last' we want the last occurence. old_posp is the way of communication between consequent calls if - the next call needs to find the . + the next call needs to find the . The initial *old_posp should be -1. Note that we take into account SvTAIL, so one can get extra @@ -1158,9 +1260,8 @@ fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 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; register unsigned char *big; register I32 pos; @@ -1175,7 +1276,7 @@ screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_ ? (pos = PL_screamfirst[BmRARE(littlestr)]) < 0 : (((pos = *old_posp), pos += PL_screamnext[pos]) == 0)) { cant_find: - if ( BmRARE(littlestr) == '\n' + if ( BmRARE(littlestr) == '\n' && BmPREVIOUS(littlestr) == SvCUR(littlestr) - 1) { little = (unsigned char *)(SvPVX(littlestr)); littleend = little + SvCUR(littlestr); @@ -1238,7 +1339,7 @@ screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_ found = 1; } } while ( pos += PL_screamnext[pos] ); - if (last && found) + if (last && found) return (char *)(big+(*old_posp)); #endif /* POINTERRIGOR */ check_tail: @@ -1251,13 +1352,14 @@ screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_ return (char*)big; big -= stop_pos; if (*big == first - && ((stop_pos == 1) || memEQ(big + 1, little, stop_pos - 1))) + && ((stop_pos == 1) || + memEQ((char *)(big + 1), (char *)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; @@ -1270,7 +1372,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; @@ -1284,8 +1386,16 @@ ibcmp_locale(const char *s1, const char *s2, register I32 len) /* copy a string to a safe spot */ +/* +=for apidoc savepv + +Copy a string to a safe spot. This does not use an SV. + +=cut +*/ + char * -savepv(const char *sv) +Perl_savepv(pTHX_ const char *sv) { register char *newaddr; @@ -1296,8 +1406,17 @@ savepv(const char *sv) /* same thing but with a known length */ +/* +=for apidoc savepvn + +Copy a string to a safe spot. The C indicates number of bytes to +copy. This does not use an SV. + +=cut +*/ + char * -savepvn(const char *sv, register I32 len) +Perl_savepvn(pTHX_ const char *sv, register I32 len) { register char *newaddr; @@ -1307,12 +1426,11 @@ 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; XPVMG *any; @@ -1332,47 +1450,95 @@ mess_alloc(void) return sv; } +#if defined(PERL_IMPLICIT_CONTEXT) char * -form(const char* pat, ...) +Perl_form_nocontext(const char* pat, ...) { - SV *sv = mess_alloc(); + dTHX; + char *retval; va_list args; va_start(args, pat); - sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); + retval = vform(pat, &args); va_end(args); + return retval; +} +#endif /* PERL_IMPLICIT_CONTEXT */ + +char * +Perl_form(pTHX_ const char* pat, ...) +{ + char *retval; + va_list args; + va_start(args, pat); + retval = vform(pat, &args); + va_end(args); + return retval; +} + +char * +Perl_vform(pTHX_ const char *pat, va_list *args) +{ + SV *sv = mess_alloc(); + sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); return SvPVX(sv); } +#if defined(PERL_IMPLICIT_CONTEXT) SV * -mess(const char *pat, va_list *args) +Perl_mess_nocontext(const char *pat, ...) +{ + dTHX; + SV *retval; + va_list args; + va_start(args, pat); + retval = vmess(pat, &args); + va_end(args); + return retval; +} +#endif /* PERL_IMPLICIT_CONTEXT */ + +SV * +Perl_mess(pTHX_ const char *pat, ...) +{ + SV *retval; + va_list args; + va_start(args, pat); + retval = vmess(pat, &args); + va_end(args); + return retval; +} + +SV * +Perl_vmess(pTHX_ const char *pat, va_list *args) { SV *sv = mess_alloc(); static char dgd[] = " during global destruction.\n"; sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); if (!SvCUR(sv) || *(SvEND(sv) - 1) != '\n') { - dTHR; - if (PL_curcop->cop_line) - sv_catpvf(sv, " at %_ line %ld", - GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line); + if (CopLINE(PL_curcop)) + Perl_sv_catpvf(aTHX_ sv, " at %s line %"IVdf, + CopFILE(PL_curcop), (IV)CopLINE(PL_curcop)); 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'); - sv_catpvf(sv, ", <%s> %s %ld", + Perl_sv_catpvf(aTHX_ sv, ", <%s> %s %"IVdf, PL_last_in_gv == PL_argvgv ? "" : GvNAME(PL_last_in_gv), - line_mode ? "line" : "chunk", - (long)IoLINES(GvIOp(PL_last_in_gv))); + line_mode ? "line" : "chunk", + (IV)IoLINES(GvIOp(PL_last_in_gv))); } +#ifdef USE_THREADS + if (thr->tid) + Perl_sv_catpvf(aTHX_ sv, " thread %ld", thr->tid); +#endif sv_catpv(sv, PL_dirty ? dgd : ".\n"); } return sv; } OP * -die(const char* pat, ...) +Perl_vdie(pTHX_ const char* pat, va_list *args) { - dTHR; - va_list args; char *message; int was_in_eval = PL_in_eval; HV *stash; @@ -1381,25 +1547,30 @@ die(const char* pat, ...) SV *msv; STRLEN msglen; - DEBUG_S(PerlIO_printf(PerlIO_stderr(), + DEBUG_S(PerlIO_printf(Perl_debug_log, "%p: die: curstack = %p, mainstack = %p\n", thr, PL_curstack, PL_mainstack)); - va_start(args, pat); if (pat) { - msv = mess(pat, &args); - message = SvPV(msv,msglen); + msv = vmess(pat, args); + if (PL_errors && SvCUR(PL_errors)) { + sv_catsv(PL_errors, msv); + message = SvPV(PL_errors, msglen); + SvCUR_set(PL_errors, 0); + } + else + message = SvPV(msv,msglen); } else { message = Nullch; + msglen = 0; } - va_end(args); - DEBUG_S(PerlIO_printf(PerlIO_stderr(), + DEBUG_S(PerlIO_printf(Perl_debug_log, "%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); @@ -1411,6 +1582,7 @@ die(const char* pat, ...) SV *msg; ENTER; + save_re_context(); if (message) { msg = newSVpvn(message, msglen); SvREADONLY_on(msg); @@ -1424,14 +1596,14 @@ 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, msglen); - DEBUG_S(PerlIO_printf(PerlIO_stderr(), + DEBUG_S(PerlIO_printf(Perl_debug_log, "%p: die: restartop = %p, was_in_eval = %d, top_env = %p\n", thr, PL_restartop, was_in_eval, PL_top_env)); if ((!PL_restartop && was_in_eval) || PL_top_env->je_prev) @@ -1439,11 +1611,34 @@ die(const char* pat, ...) return PL_restartop; } -void -croak(const char* pat, ...) +#if defined(PERL_IMPLICIT_CONTEXT) +OP * +Perl_die_nocontext(const char* pat, ...) { - dTHR; + dTHX; + OP *o; va_list args; + va_start(args, pat); + o = vdie(pat, &args); + va_end(args); + return o; +} +#endif /* PERL_IMPLICIT_CONTEXT */ + +OP * +Perl_die(pTHX_ const char* pat, ...) +{ + OP *o; + va_list args; + va_start(args, pat); + o = vdie(pat, &args); + va_end(args); + return o; +} + +void +Perl_vcroak(pTHX_ const char* pat, va_list *args) +{ char *message; HV *stash; GV *gv; @@ -1451,13 +1646,26 @@ croak(const char* pat, ...) SV *msv; STRLEN msglen; - va_start(args, pat); - msv = mess(pat, &args); - message = SvPV(msv,msglen); - va_end(args); - DEBUG_S(PerlIO_printf(PerlIO_stderr(), "croak: 0x%lx %s", (unsigned long) thr, message)); + if (pat) { + msv = vmess(pat, args); + if (PL_errors && SvCUR(PL_errors)) { + sv_catsv(PL_errors, msv); + message = SvPV(PL_errors, msglen); + SvCUR_set(PL_errors, 0); + } + else + message = SvPV(msv,msglen); + } + else { + message = Nullch; + msglen = 0; + } + + DEBUG_S(PerlIO_printf(Perl_debug_log, "croak: 0x%"UVxf" %s", + PTR2UV(thr), message)); + if (PL_diehook) { - /* sv_2cv might call croak() */ + /* sv_2cv might call Perl_croak() */ SV *olddiehook = PL_diehook; ENTER; SAVESPTR(PL_diehook); @@ -1469,15 +1677,21 @@ croak(const char* pat, ...) SV *msg; ENTER; - msg = newSVpvn(message, msglen); - SvREADONLY_on(msg); - SAVEFREESV(msg); + save_re_context(); + if (message) { + msg = newSVpvn(message, msglen); + SvREADONLY_on(msg); + SAVEFREESV(msg); + } + else { + msg = ERRSV; + } PUSHSTACKi(PERLSI_DIEHOOK); PUSHMARK(SP); XPUSHs(msg); PUTBACK; - perl_call_sv((SV*)cv, G_DISCARD); + call_sv((SV*)cv, G_DISCARD); POPSTACK; LEAVE; } @@ -1491,8 +1705,10 @@ croak(const char* pat, ...) /* SFIO can really mess with your errno */ int e = errno; #endif - PerlIO_write(PerlIO_stderr(), message, msglen); - (void)PerlIO_flush(PerlIO_stderr()); + PerlIO *serr = Perl_error_log; + + PerlIO_write(serr, message, msglen); + (void)PerlIO_flush(serr); #ifdef USE_SFIO errno = e; #endif @@ -1500,10 +1716,49 @@ croak(const char* pat, ...) my_failure_exit(); } +#if defined(PERL_IMPLICIT_CONTEXT) +void +Perl_croak_nocontext(const char *pat, ...) +{ + dTHX; + va_list args; + va_start(args, pat); + vcroak(pat, &args); + /* NOTREACHED */ + va_end(args); +} +#endif /* PERL_IMPLICIT_CONTEXT */ + +/* +=for apidoc croak + +This is the XSUB-writer's interface to Perl's C function. +Normally use this function the same way you use the C C +function. See C. + +If you want to throw an exception object, assign the object to +C<$@> and then pass C to croak(): + + errsv = get_sv("@", TRUE); + sv_setsv(errsv, exception_object); + croak(Nullch); + +=cut +*/ + void -warn(const char* pat,...) +Perl_croak(pTHX_ const char *pat, ...) { va_list args; + va_start(args, pat); + vcroak(pat, &args); + /* NOTREACHED */ + va_end(args); +} + +void +Perl_vwarn(pTHX_ const char* pat, va_list *args) +{ char *message; HV *stash; GV *gv; @@ -1511,14 +1766,11 @@ warn(const char* pat,...) SV *msv; STRLEN msglen; - va_start(args, pat); - msv = mess(pat, &args); + msv = vmess(pat, args); message = SvPV(msv, msglen); - va_end(args); if (PL_warnhook) { - /* sv_2cv might call warn() */ - dTHR; + /* sv_2cv might call Perl_warn() */ SV *oldwarnhook = PL_warnhook; ENTER; SAVESPTR(PL_warnhook); @@ -1530,6 +1782,7 @@ warn(const char* pat,...) SV *msg; ENTER; + save_re_context(); msg = newSVpvn(message, msglen); SvREADONLY_on(msg); SAVEFREESV(msg); @@ -1538,29 +1791,83 @@ 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_write(PerlIO_stderr(), message, msglen); + { + PerlIO *serr = Perl_error_log; + + PerlIO_write(serr, message, msglen); #ifdef LEAKTEST - DEBUG_L(*message == '!' - ? (xstat(message[1]=='!' - ? (message[2]=='!' ? 2 : 1) - : 0) - , 0) - : 0); + DEBUG_L(*message == '!' + ? (xstat(message[1]=='!' + ? (message[2]=='!' ? 2 : 1) + : 0) + , 0) + : 0); #endif - (void)PerlIO_flush(PerlIO_stderr()); + (void)PerlIO_flush(serr); + } } +#if defined(PERL_IMPLICIT_CONTEXT) void -warner(U32 err, const char* pat,...) +Perl_warn_nocontext(const char *pat, ...) { - dTHR; + dTHX; va_list args; + va_start(args, pat); + vwarn(pat, &args); + va_end(args); +} +#endif /* PERL_IMPLICIT_CONTEXT */ + +/* +=for apidoc warn + +This is the XSUB-writer's interface to Perl's C function. Use this +function the same way you use the C C function. See +C. + +=cut +*/ + +void +Perl_warn(pTHX_ const char *pat, ...) +{ + va_list args; + va_start(args, pat); + vwarn(pat, &args); + va_end(args); +} + +#if defined(PERL_IMPLICIT_CONTEXT) +void +Perl_warner_nocontext(U32 err, const char *pat, ...) +{ + dTHX; + va_list args; + va_start(args, pat); + vwarner(err, pat, &args); + va_end(args); +} +#endif /* PERL_IMPLICIT_CONTEXT */ + +void +Perl_warner(pTHX_ U32 err, const char* pat,...) +{ + va_list args; + va_start(args, pat); + vwarner(err, pat, &args); + va_end(args); +} + +void +Perl_vwarner(pTHX_ U32 err, const char* pat, va_list* args) +{ char *message; HV *stash; GV *gv; @@ -1568,17 +1875,15 @@ warner(U32 err, const char* pat,...) SV *msv; STRLEN msglen; - va_start(args, pat); - msv = mess(pat, &args); + msv = vmess(pat, args); message = SvPV(msv, msglen); - va_end(args); if (ckDEAD(err)) { #ifdef USE_THREADS - DEBUG_S(PerlIO_printf(PerlIO_stderr(), "croak: 0x%lx %s", (unsigned long) thr, message)); + DEBUG_S(PerlIO_printf(Perl_debug_log, "croak: 0x%"UVxf" %s", PTR2UV(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); @@ -1588,17 +1893,19 @@ warner(U32 err, const char* pat,...) if (cv && !CvDEPTH(cv) && (CvROOT(cv) || CvXSUB(cv))) { dSP; SV *msg; - + ENTER; + save_re_context(); msg = newSVpvn(message, msglen); SvREADONLY_on(msg); SAVEFREESV(msg); - + + PUSHSTACKi(PERLSI_DIEHOOK); PUSHMARK(sp); XPUSHs(msg); PUTBACK; - perl_call_sv((SV*)cv, G_DISCARD); - + call_sv((SV*)cv, G_DISCARD); + POPSTACK; LEAVE; } } @@ -1606,51 +1913,64 @@ warner(U32 err, const char* pat,...) PL_restartop = die_where(message, msglen); JMPENV_JUMP(3); } - PerlIO_write(PerlIO_stderr(), message, msglen); - (void)PerlIO_flush(PerlIO_stderr()); + { + PerlIO *serr = Perl_error_log; + PerlIO_write(serr, message, msglen); + (void)PerlIO_flush(serr); + } my_failure_exit(); } else { if (PL_warnhook) { - /* sv_2cv might call warn() */ - dTHR; + /* sv_2cv might call Perl_warn() */ SV *oldwarnhook = PL_warnhook; ENTER; SAVESPTR(PL_warnhook); PL_warnhook = Nullsv; cv = sv_2cv(oldwarnhook, &stash, &gv, 0); - LEAVE; + LEAVE; if (cv && !CvDEPTH(cv) && (CvROOT(cv) || CvXSUB(cv))) { dSP; SV *msg; - + ENTER; + save_re_context(); msg = newSVpvn(message, msglen); SvREADONLY_on(msg); SAVEFREESV(msg); - + + PUSHSTACKi(PERLSI_WARNHOOK); PUSHMARK(sp); XPUSHs(msg); PUTBACK; - perl_call_sv((SV*)cv, G_DISCARD); - + call_sv((SV*)cv, G_DISCARD); + POPSTACK; LEAVE; return; } } - PerlIO_write(PerlIO_stderr(), message, msglen); + { + PerlIO *serr = Perl_error_log; + PerlIO_write(serr, message, msglen); #ifdef LEAKTEST - DEBUG_L(xstat()); -#endif - (void)PerlIO_flush(PerlIO_stderr()); + DEBUG_L(*message == '!' + ? (xstat(message[1]=='!' + ? (message[2]=='!' ? 2 : 1) + : 0) + , 0) + : 0); +#endif + (void)PerlIO_flush(serr); + } } } -#ifndef VMS /* VMS' my_setenv() is in VMS.c */ -#if !defined(WIN32) && !defined(CYGWIN32) +#ifdef USE_ENVIRON_ARRAY + /* VMS' and EPOC's my_setenv() is in vms.c and epoc.c */ +#if !defined(WIN32) 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 */ @@ -1687,36 +2007,25 @@ my_setenv(char *nam, char *val) safesysfree(environ[i]); environ[i] = (char*)safesysmalloc((strlen(nam)+strlen(val)+2) * sizeof(char)); -#ifndef MSDOS (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */ -#else - /* MS-DOS requires environment variable names to be in uppercase */ - /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but - * some utilities and applications may break because they only look - * for upper case strings. (Fixed strupr() bug here.)] - */ - strcpy(environ[i],nam); strupr(environ[i]); - (void)sprintf(environ[i] + strlen(nam),"=%s",val); -#endif /* MSDOS */ #else /* PERL_USE_SAFE_PUTENV */ +# if defined(__CYGWIN__) + setenv(nam, val, 1); +# else char *new_env; new_env = (char*)safesysmalloc((strlen(nam) + strlen(val) + 2) * sizeof(char)); -#ifndef MSDOS (void)sprintf(new_env,"%s=%s",nam,val);/* all that work just for this */ -#else - strcpy(new_env,nam); strupr(new_env); - (void)sprintf(new_env + strlen(nam),"=%s",val); -#endif (void)putenv(new_env); +# endif /* __CYGWIN__ */ #endif /* PERL_USE_SAFE_PUTENV */ } -#else /* if WIN32 */ +#else /* WIN32 */ void -my_setenv(char *nam,char *val) +Perl_my_setenv(pTHX_ char *nam,char *val) { #ifdef USE_WIN32_RTL_ENV @@ -1776,7 +2085,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); @@ -1793,11 +2102,11 @@ setenv_getix(char *nam) return i; } -#endif /* !VMS */ +#endif /* !VMS && !EPOC*/ #ifdef UNLINK_ALL_VERSIONS I32 -unlnk(char *f) /* unlink all versions of a file */ +Perl_unlnk(pTHX_ char *f) /* unlink all versions of a file */ { I32 i; @@ -1806,9 +2115,10 @@ unlnk(char *f) /* unlink all versions of a file */ } #endif +/* this is a drop-in replacement for bcopy() */ #if !defined(HAS_BCOPY) || !defined(HAS_SAFE_BCOPY) char * -my_bcopy(register const char *from,register char *to,register I32 len) +Perl_my_bcopy(register const char *from,register char *to,register I32 len) { char *retval = to; @@ -1826,9 +2136,10 @@ my_bcopy(register const char *from,register char *to,register I32 len) } #endif +/* this is a drop-in replacement for memset() */ #ifndef HAS_MEMSET void * -my_memset(register char *loc, register I32 ch, register I32 len) +Perl_my_memset(register char *loc, register I32 ch, register I32 len) { char *retval = loc; @@ -1838,9 +2149,10 @@ my_memset(register char *loc, register I32 ch, register I32 len) } #endif +/* this is a drop-in replacement for bzero() */ #if !defined(HAS_BZERO) && !defined(HAS_MEMSET) char * -my_bzero(register char *loc, register I32 len) +Perl_my_bzero(register char *loc, register I32 len) { char *retval = loc; @@ -1850,9 +2162,10 @@ my_bzero(register char *loc, register I32 len) } #endif +/* this is a drop-in replacement for memcmp() */ #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP) I32 -my_memcmp(const char *s1, const char *s2, register I32 len) +Perl_my_memcmp(const char *s1, const char *s2, register I32 len) { register U8 *a = (U8 *)s1; register U8 *b = (U8 *)s2; @@ -1897,7 +2210,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; @@ -1910,7 +2223,7 @@ my_swap(short s) } long -my_htonl(long l) +Perl_my_htonl(pTHX_ long l) { union { long result; @@ -1925,7 +2238,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; @@ -1939,7 +2252,7 @@ my_htonl(long l) } long -my_ntohl(long l) +Perl_my_ntohl(pTHX_ long l) { union { long l; @@ -1954,7 +2267,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; @@ -2028,13 +2341,13 @@ VTOH(vtohl,long) #endif /* VMS' my_popen() is in VMS.c, same with OS/2. */ -#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__OPEN_VM) +#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__OPEN_VM) && !defined(EPOC) && !defined(MACOS_TRADITIONAL) 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; + register Pid_t pid; SV *sv; I32 doexec = strNE(cmd,"-"); I32 did_pipes = 0; @@ -2043,9 +2356,9 @@ my_popen(char *cmd, char *mode) PERL_FLUSHALL_FOR_CHILD; #ifdef OS2 if (doexec) { - return my_syspopen(cmd,mode); + return my_syspopen(aTHX_ cmd,mode); } -#endif +#endif This = (*mode == 'w'); that = !This; if (doexec && PL_tainting) { @@ -2064,7 +2377,7 @@ my_popen(char *cmd, char *mode) PerlLIO_close(pp[1]); } if (!doexec) - croak("Can't fork"); + Perl_croak(aTHX_ "Can't fork"); return Nullfp; } sleep(5); @@ -2104,8 +2417,8 @@ my_popen(char *cmd, char *mode) } #endif /* defined OS2 */ /*SUPPRESS 560*/ - if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV)) - sv_setiv(GvSV(tmpgv), (IV)getpid()); + if ((tmpgv = gv_fetchpv("$",TRUE, SVt_PV))) + sv_setiv(GvSV(tmpgv), PerlProc_getpid()); PL_forkprocess = 0; hv_clear(PL_pidstatus); /* we have no children */ return Nullfp; @@ -2121,7 +2434,9 @@ my_popen(char *cmd, char *mode) PerlLIO_close(p[This]); p[This] = p[that]; } + LOCK_FDPID_MUTEX; sv = *av_fetch(PL_fdpid,p[This],TRUE); + UNLOCK_FDPID_MUTEX; (void)SvUPGRADE(sv,SVt_IV); SvIVX(sv) = pid; PL_forkprocess = pid; @@ -2137,10 +2452,15 @@ my_popen(char *cmd, char *mode) break; n += n1; } + PerlLIO_close(pp[0]); + did_pipes = 0; if (n) { /* Error */ + int pid2, status; if (n != sizeof(int)) - croak("panic: kid popen errno read"); - PerlLIO_close(pp[0]); + Perl_croak(aTHX_ "panic: kid popen errno read"); + do { + pid2 = wait4pid(pid, &status, 0); + } while (pid2 == -1 && errno == EINTR); errno = errkid; /* Propagate errno from kid */ return Nullfp; } @@ -2153,12 +2473,14 @@ my_popen(char *cmd, char *mode) #if defined(atarist) || defined(DJGPP) FILE *popen(); PerlIO * -my_popen(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); + /* Call system's popen() to get a FILE *, then import it. + used 0 for 2nd parameter to PerlIO_importFILE; + apparently not used + */ + return PerlIO_importFILE(popen(cmd, mode), 0); } #endif @@ -2166,17 +2488,17 @@ my_popen(char *cmd, char *mode) #ifdef DUMP_FDS void -dump_fds(char *s) +Perl_dump_fds(pTHX_ char *s) { int fd; struct stat tmpstatbuf; - PerlIO_printf(PerlIO_stderr(),"%s", s); + PerlIO_printf(Perl_debug_log,"%s", s); for (fd = 0; fd < 32; fd++) { if (PerlLIO_fstat(fd,&tmpstatbuf) >= 0) - PerlIO_printf(PerlIO_stderr()," %d",fd); + PerlIO_printf(Perl_debug_log," %d",fd); } - PerlIO_printf(PerlIO_stderr(),"\n"); + PerlIO_printf(Perl_debug_log,"\n"); } #endif /* DUMP_FDS */ @@ -2214,11 +2536,11 @@ dup2(int oldfd, int newfd) } #endif - +#ifndef PERL_MICRO #ifdef HAS_SIGACTION Sighandler_t -rsignal(int signo, Sighandler_t handler) +Perl_rsignal(pTHX_ int signo, Sighandler_t handler) { struct sigaction act, oact; @@ -2239,7 +2561,7 @@ rsignal(int signo, Sighandler_t handler) } Sighandler_t -rsignal_state(int signo) +Perl_rsignal_state(pTHX_ int signo) { struct sigaction oact; @@ -2250,7 +2572,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; @@ -2268,7 +2590,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); } @@ -2276,7 +2598,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); } @@ -2291,7 +2613,7 @@ sig_trap(int signo) } Sighandler_t -rsignal_state(int signo) +Perl_rsignal_state(pTHX_ int signo) { Sighandler_t oldsig; @@ -2299,35 +2621,36 @@ rsignal_state(int signo) oldsig = PerlProc_signal(signo, sig_trap); PerlProc_signal(signo, oldsig); if (sig_trapped) - PerlProc_kill(getpid(), signo); + PerlProc_kill(PerlProc_getpid(), signo); return oldsig; } 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; } #endif /* !HAS_SIGACTION */ +#endif /* !PERL_MICRO */ /* VMS' my_pclose() is in VMS.c; same with OS/2 */ -#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__OPEN_VM) +#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__OPEN_VM) && !defined(EPOC) && !defined(MACOS_TRADITIONAL) I32 -my_pclose(PerlIO *ptr) +Perl_my_pclose(pTHX_ PerlIO *ptr) { Sigsave_t hstat, istat, qstat; int status; SV **svp; - int pid; - int pid2; + Pid_t pid; + Pid_t pid2; bool close_failed; int saved_errno; #ifdef VMS @@ -2337,15 +2660,17 @@ my_pclose(PerlIO *ptr) int saved_win32_errno; #endif + LOCK_FDPID_MUTEX; svp = av_fetch(PL_fdpid,PerlIO_fileno(ptr),TRUE); - pid = (int)SvIVX(*svp); + UNLOCK_FDPID_MUTEX; + pid = SvIVX(*svp); SvREFCNT_dec(*svp); *svp = &PL_sv_undef; #ifdef OS2 if (pid == -1) { /* Opened by popen. */ return my_syspclose(ptr); } -#endif +#endif if ((close_failed = (PerlIO_close(ptr) == EOF))) { saved_errno = errno; #ifdef VMS @@ -2358,15 +2683,19 @@ my_pclose(PerlIO *ptr) #ifdef UTS 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); +#endif do { pid2 = wait4pid(pid, &status, 0); } while (pid2 == -1 && errno == EINTR); +#ifndef PERL_MICRO rsignal_restore(SIGHUP, &hstat); rsignal_restore(SIGINT, &istat); rsignal_restore(SIGQUIT, &qstat); +#endif if (close_failed) { SETERRNO(saved_errno, saved_vaxc_errno); return -1; @@ -2375,9 +2704,9 @@ my_pclose(PerlIO *ptr) } #endif /* !DOSISH */ -#if !defined(DOSISH) || defined(OS2) || defined(WIN32) || defined(CYGWIN32) +#if (!defined(DOSISH) || defined(OS2) || defined(WIN32)) && !defined(MACOS_TRADITIONAL) I32 -wait4pid(int pid, int *statusp, int flags) +Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags) { SV *sv; SV** svp; @@ -2385,8 +2714,9 @@ wait4pid(int pid, int *statusp, int flags) if (!pid) return -1; +#if !defined(HAS_WAITPID) && !defined(HAS_WAIT4) || defined(HAS_WAITPID_RUNTIME) if (pid > 0) { - sprintf(spid, "%d", pid); + sprintf(spid, "%"IVdf, (IV)pid); svp = hv_fetch(PL_pidstatus,spid,strlen(spid),FALSE); if (svp && *svp != &PL_sv_undef) { *statusp = SvIVX(*svp); @@ -2398,15 +2728,16 @@ wait4pid(int pid, int *statusp, int flags) HE *entry; hv_iterinit(PL_pidstatus); - if (entry = hv_iternext(PL_pidstatus)) { + if ((entry = hv_iternext(PL_pidstatus))) { pid = atoi(hv_iterkey(entry,(I32*)statusp)); sv = hv_iterval(PL_pidstatus,entry); *statusp = SvIVX(sv); - sprintf(spid, "%d", pid); + sprintf(spid, "%"IVdf, (IV)pid); (void)hv_delete(PL_pidstatus,spid,strlen(spid),G_DISCARD); return pid; } } +#endif #ifdef HAS_WAITPID # ifdef HAS_WAITPID_RUNTIME if (!HAS_WAITPID_RUNTIME) @@ -2422,7 +2753,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); @@ -2437,12 +2768,12 @@ wait4pid(int pid, int *statusp, int flags) void /*SUPPRESS 590*/ -pidgone(int pid, int status) +Perl_pidgone(pTHX_ Pid_t pid, int status) { register SV *sv; char spid[TYPE_CHARS(int)]; - sprintf(spid, "%d", pid); + sprintf(spid, "%"IVdf, (IV)pid); sv = *hv_fetch(PL_pidstatus,spid,strlen(spid),TRUE); (void)SvUPGRADE(sv,SVt_IV); SvIVX(sv) = status; @@ -2457,19 +2788,22 @@ int /* Cannot prototype with I32 my_syspclose(PerlIO *ptr) #else I32 -my_pclose(PerlIO *ptr) -#endif +Perl_my_pclose(pTHX_ PerlIO *ptr) +#endif { /* Needs work for PerlIO ! */ FILE *f = PerlIO_findFILE(ptr); I32 result = pclose(f); +#if defined(DJGPP) + result = (result << 8) & 0xff00; +#endif PerlIO_releaseFILE(ptr,f); return result; } #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; @@ -2489,7 +2823,7 @@ repeatcpy(register char *to, register const char *from, I32 len, register I32 co } U32 -cast_ulong(double f) +Perl_cast_ulong(pTHX_ NV f) { long along; @@ -2519,14 +2853,14 @@ cast_ulong(double f) /* Code modified to prefer proper named type ranges, I32, IV, or UV, instead of LONG_(MIN/MAX). -- Kenneth Albanowski -*/ +*/ #ifndef MY_UV_MAX # define MY_UV_MAX ((UV)IV_MAX * (UV)2 + (UV)1) #endif I32 -cast_i32(double f) +Perl_cast_i32(pTHX_ NV f) { if (f >= I32_MAX) return (I32) I32_MAX; @@ -2536,12 +2870,12 @@ cast_i32(double f) } IV -cast_iv(double f) +Perl_cast_iv(pTHX_ NV f) { if (f >= IV_MAX) { UV uv; - if (f >= (double)UV_MAX) + if (f >= (NV)UV_MAX) return (IV) UV_MAX; uv = (UV) f; return (IV)uv; @@ -2552,7 +2886,7 @@ cast_iv(double f) } UV -cast_uv(double f) +Perl_cast_uv(pTHX_ NV f) { if (f >= MY_UV_MAX) return (UV) MY_UV_MAX; @@ -2569,7 +2903,7 @@ cast_uv(double 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,'/'); @@ -2604,91 +2938,219 @@ same_dirent(char *a, char *b) } #endif /* !HAS_RENAME */ -UV -scan_bin(char *start, I32 len, I32 *retlen) +NV +Perl_scan_bin(pTHX_ char *start, STRLEN len, STRLEN *retlen) { register char *s = start; - register UV retval = 0; - bool overflowed = FALSE; - while (len && *s >= '0' && *s <= '1') { - register UV n = retval << 1; - if (!overflowed && (n >> 1) != retval) { - warn("Integer overflow in binary number"); - overflowed = TRUE; - } - retval = n | (*s++ - '0'); - len--; - } - if (len && (*s >= '2' && *s <= '9')) { - dTHR; - if (ckWARN(WARN_UNSAFE)) - warner(WARN_UNSAFE, "Illegal binary digit '%c' ignored", *s); + register NV rnv = 0.0; + register UV ruv = 0; + register bool seenb = FALSE; + register bool overflowed = FALSE; + + for (; len-- && *s; s++) { + if (!(*s == '0' || *s == '1')) { + if (*s == '_' && len && *retlen + && (s[1] == '0' || s[1] == '1')) + { + --len; + ++s; + } + else if (seenb == FALSE && *s == 'b' && ruv == 0) { + /* Disallow 0bbb0b0bbb... */ + seenb = TRUE; + continue; + } + else { + if (ckWARN(WARN_DIGIT)) + Perl_warner(aTHX_ WARN_DIGIT, + "Illegal binary digit '%c' ignored", *s); + break; + } + } + if (!overflowed) { + register UV xuv = ruv << 1; + + if ((xuv >> 1) != ruv) { + overflowed = TRUE; + rnv = (NV) ruv; + if (ckWARN_d(WARN_OVERFLOW)) + Perl_warner(aTHX_ WARN_OVERFLOW, + "Integer overflow in binary number"); + } + else + ruv = xuv | (*s - '0'); + } + if (overflowed) { + rnv *= 2; + /* If an NV has not enough bits in its mantissa to + * represent an UV this summing of small low-order numbers + * is a waste of time (because the NV cannot preserve + * the low-order bits anyway): we could just remember when + * did we overflow and in the end just multiply rnv by the + * right amount. */ + rnv += (*s - '0'); + } + } + if (!overflowed) + rnv = (NV) ruv; + if ( ( overflowed && rnv > 4294967295.0) +#if UVSIZE > 4 + || (!overflowed && ruv > 0xffffffff ) +#endif + ) { + if (ckWARN(WARN_PORTABLE)) + Perl_warner(aTHX_ WARN_PORTABLE, + "Binary number > 0b11111111111111111111111111111111 non-portable"); } *retlen = s - start; - return retval; + return rnv; } -UV -scan_oct(char *start, I32 len, I32 *retlen) + +NV +Perl_scan_oct(pTHX_ char *start, STRLEN len, STRLEN *retlen) { register char *s = start; - register UV retval = 0; - bool overflowed = FALSE; - - while (len && *s >= '0' && *s <= '7') { - register UV n = retval << 3; - if (!overflowed && (n >> 3) != retval) { - warn("Integer overflow in octal number"); - overflowed = TRUE; + register NV rnv = 0.0; + register UV ruv = 0; + register bool overflowed = FALSE; + + for (; len-- && *s; s++) { + if (!(*s >= '0' && *s <= '7')) { + if (*s == '_' && len && *retlen + && (s[1] >= '0' && s[1] <= '7')) + { + --len; + ++s; + } + else { + /* Allow \octal to work the DWIM way (that is, stop scanning + * as soon as non-octal characters are seen, complain only iff + * someone seems to want to use the digits eight and nine). */ + if (*s == '8' || *s == '9') { + if (ckWARN(WARN_DIGIT)) + Perl_warner(aTHX_ WARN_DIGIT, + "Illegal octal digit '%c' ignored", *s); + } + break; + } + } + if (!overflowed) { + register UV xuv = ruv << 3; + + if ((xuv >> 3) != ruv) { + overflowed = TRUE; + rnv = (NV) ruv; + if (ckWARN_d(WARN_OVERFLOW)) + Perl_warner(aTHX_ WARN_OVERFLOW, + "Integer overflow in octal number"); + } + else + ruv = xuv | (*s - '0'); + } + if (overflowed) { + rnv *= 8.0; + /* If an NV has not enough bits in its mantissa to + * represent an UV this summing of small low-order numbers + * is a waste of time (because the NV cannot preserve + * the low-order bits anyway): we could just remember when + * did we overflow and in the end just multiply rnv by the + * right amount of 8-tuples. */ + rnv += (NV)(*s - '0'); } - retval = n | (*s++ - '0'); - len--; } - if (len && (*s == '8' || *s == '9')) { - dTHR; - if (ckWARN(WARN_OCTAL)) - warner(WARN_OCTAL, "Illegal octal digit '%c' ignored", *s); + if (!overflowed) + rnv = (NV) ruv; + if ( ( overflowed && rnv > 4294967295.0) +#if UVSIZE > 4 + || (!overflowed && ruv > 0xffffffff ) +#endif + ) { + if (ckWARN(WARN_PORTABLE)) + Perl_warner(aTHX_ WARN_PORTABLE, + "Octal number > 037777777777 non-portable"); } *retlen = s - start; - return retval; + return rnv; } -UV -scan_hex(char *start, I32 len, I32 *retlen) +NV +Perl_scan_hex(pTHX_ char *start, STRLEN len, STRLEN *retlen) { register char *s = start; - register UV retval = 0; - bool overflowed = FALSE; - char *tmp = s; - register UV n; - - while (len-- && *s) { - tmp = strchr((char *) PL_hexdigit, *s++); - if (!tmp) { - if (*(s-1) == '_' || (*(s-1) == 'x' && retval == 0)) - continue; + register NV rnv = 0.0; + register UV ruv = 0; + register bool overflowed = FALSE; + char *hexdigit; + + if (len > 2) { + if (s[0] == 'x') { + s++; + len--; + } + else if (len > 3 && s[0] == '0' && s[1] == 'x') { + s+=2; + len-=2; + } + } + + for (; len-- && *s; s++) { + hexdigit = strchr((char *) PL_hexdigit, *s); + if (!hexdigit) { + if (*s == '_' && len && *retlen && s[1] + && (hexdigit = strchr((char *) PL_hexdigit, s[1]))) + { + --len; + ++s; + } else { - dTHR; - --s; - if (ckWARN(WARN_UNSAFE)) - warner(WARN_UNSAFE,"Illegal hex digit '%c' ignored", *s); + if (ckWARN(WARN_DIGIT)) + Perl_warner(aTHX_ WARN_DIGIT, + "Illegal hexadecimal digit '%c' ignored", *s); break; } } - n = retval << 4; - if (!overflowed && (n >> 4) != retval) { - warn("Integer overflow in hex number"); - overflowed = TRUE; + if (!overflowed) { + register UV xuv = ruv << 4; + + if ((xuv >> 4) != ruv) { + overflowed = TRUE; + rnv = (NV) ruv; + if (ckWARN_d(WARN_OVERFLOW)) + Perl_warner(aTHX_ WARN_OVERFLOW, + "Integer overflow in hexadecimal number"); + } + else + ruv = xuv | ((hexdigit - PL_hexdigit) & 15); + } + if (overflowed) { + rnv *= 16.0; + /* If an NV has not enough bits in its mantissa to + * represent an UV this summing of small low-order numbers + * is a waste of time (because the NV cannot preserve + * the low-order bits anyway): we could just remember when + * did we overflow and in the end just multiply rnv by the + * right amount of 16-tuples. */ + rnv += (NV)((hexdigit - PL_hexdigit) & 15); } - retval = n | ((tmp - PL_hexdigit) & 15); + } + if (!overflowed) + rnv = (NV) ruv; + if ( ( overflowed && rnv > 4294967295.0) +#if UVSIZE > 4 + || (!overflowed && ruv > 0xffffffff ) +#endif + ) { + if (ckWARN(WARN_PORTABLE)) + Perl_warner(aTHX_ WARN_PORTABLE, + "Hexadecimal number > 0xffffffff non-portable"); } *retlen = s - start; - return retval; + return rnv; } 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; char *xfailed = Nullch; char tmpbuf[MAXPATHLEN]; @@ -2804,15 +3266,26 @@ find_script(char *scriptname, bool dosearch, char **search_ext, I32 flags) } #endif +#ifdef MACOS_TRADITIONAL + if (dosearch && !strchr(scriptname, ':') && + (s = PerlEnv_getenv("Commands"))) +#else if (dosearch && !strchr(scriptname, '/') #ifdef DOSISH && !strchr(scriptname, '\\') #endif - && (s = PerlEnv_getenv("PATH"))) { + && (s = PerlEnv_getenv("PATH"))) +#endif + { bool seen_dot = 0; PL_bufend = s + strlen(s); while (s < PL_bufend) { +#ifdef MACOS_TRADITIONAL + s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf, s, PL_bufend, + ',', + &len); +#else #if defined(atarist) || defined(DOSISH) for (len = 0; *s # ifdef atarist @@ -2829,10 +3302,15 @@ find_script(char *scriptname, bool dosearch, char **search_ext, I32 flags) ':', &len); #endif /* ! (atarist || DOSISH) */ +#endif /* MACOS_TRADITIONAL */ if (s < PL_bufend) s++; if (len + 1 + strlen(scriptname) + MAX_EXT_LEN >= sizeof tmpbuf) continue; /* don't search dir with too-long name */ +#ifdef MACOS_TRADITIONAL + if (len && tmpbuf[len - 1] != ':') + tmpbuf[len++] = ':'; +#else if (len #if defined(atarist) || defined(__MINT__) || defined(DOSISH) && tmpbuf[len - 1] != '/' @@ -2842,6 +3320,7 @@ find_script(char *scriptname, bool dosearch, char **search_ext, I32 flags) tmpbuf[len++] = '/'; if (len == 2 && tmpbuf[0] == '.') seen_dot = 1; +#endif (void)strcpy(tmpbuf + len, scriptname); #endif /* !VMS */ @@ -2866,7 +3345,7 @@ find_script(char *scriptname, bool dosearch, char **search_ext, I32 flags) continue; if (S_ISREG(PL_statbuf.st_mode) && cando(S_IRUSR,TRUE,&PL_statbuf) -#ifndef DOSISH +#if !defined(DOSISH) && !defined(MACOS_TRADITIONAL) && cando(S_IXUSR,TRUE,&PL_statbuf) #endif ) @@ -2879,13 +3358,13 @@ find_script(char *scriptname, bool dosearch, char **search_ext, I32 flags) } #ifndef DOSISH if (!xfound && !seen_dot && !xfailed && - (PerlLIO_stat(scriptname,&PL_statbuf) < 0 + (PerlLIO_stat(scriptname,&PL_statbuf) < 0 || S_ISDIR(PL_statbuf.st_mode))) #endif 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"), @@ -2900,8 +3379,46 @@ find_script(char *scriptname, bool dosearch, char **search_ext, I32 flags) return (scriptname ? savepv(scriptname) : Nullch); } +#ifndef PERL_GET_CONTEXT_DEFINED + +void * +Perl_get_context(void) +{ +#if defined(USE_THREADS) || defined(USE_ITHREADS) +# ifdef OLD_PTHREADS_API + pthread_addr_t t; + if (pthread_getspecific(PL_thr_key, &t)) + Perl_croak_nocontext("panic: pthread_getspecific"); + return (void*)t; +# else +# ifdef I_MACH_CTHREADS + return (void*)cthread_data(cthread_self()); +# else + return (void*)pthread_getspecific(PL_thr_key); +# endif +# endif +#else + return (void*)NULL; +#endif +} + +void +Perl_set_context(void *t) +{ +#if defined(USE_THREADS) || defined(USE_ITHREADS) +# ifdef I_MACH_CTHREADS + cthread_set_data(cthread_self(), t); +# else + if (pthread_setspecific(PL_thr_key, t)) + Perl_croak_nocontext("panic: pthread_setspecific"); +# endif +#endif +} + +#endif /* !PERL_GET_CONTEXT_DEFINED */ #ifdef USE_THREADS + #ifdef FAKE_THREADS /* Very simplistic scheduler for now */ void @@ -2911,17 +3428,17 @@ 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; - + if (!cond) return; t = cond->thread; @@ -2937,11 +3454,11 @@ 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; - + for (cond = *cp; cond; cond = cond_next) { t = cond->thread; /* Insert t in the runnable queue just ahead of us */ @@ -2958,13 +3475,13 @@ 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; cond->next = *cp; @@ -2976,23 +3493,11 @@ perl_cond_wait(perl_cond *cp) } #endif /* FAKE_THREADS */ -#ifdef PTHREAD_GETSPECIFIC_INT -struct perl_thread * -getTHR(void) -{ - pthread_addr_t t; - - if (pthread_getspecific(PL_thr_key, &t)) - croak("panic: pthread_getspecific"); - return (struct perl_thread *) t; -} -#endif - MAGIC * -condpair_magic(SV *sv) +Perl_condpair_magic(pTHX_ SV *sv) { MAGIC *mg; - + SvUPGRADE(sv, SVt_PVMG); mg = mg_find(sv, 'm'); if (!mg) { @@ -3003,11 +3508,11 @@ condpair_magic(SV *sv) COND_INIT(&cp->owner_cond); COND_INIT(&cp->cond); cp->owner = 0; - MUTEX_LOCK(&PL_cred_mutex); /* XXX need separate mutex? */ + LOCK_CRED_MUTEX; /* XXX need separate mutex? */ mg = mg_find(sv, 'm'); if (mg) { /* someone else beat us to initialising it */ - MUTEX_UNLOCK(&PL_cred_mutex); /* XXX need separate mutex? */ + UNLOCK_CRED_MUTEX; /* XXX need separate mutex? */ MUTEX_DESTROY(&cp->mutex); COND_DESTROY(&cp->owner_cond); COND_DESTROY(&cp->cond); @@ -3018,14 +3523,43 @@ condpair_magic(SV *sv) mg = SvMAGIC(sv); mg->mg_ptr = (char *)cp; mg->mg_len = sizeof(cp); - MUTEX_UNLOCK(&PL_cred_mutex); /* XXX need separate mutex? */ - DEBUG_S(WITH_THR(PerlIO_printf(PerlIO_stderr(), + UNLOCK_CRED_MUTEX; /* XXX need separate mutex? */ + DEBUG_S(WITH_THR(PerlIO_printf(Perl_debug_log, "%p: condpair_magic %p\n", thr, sv));) } } return mg; } +SV * +Perl_sv_lock(pTHX_ SV *osv) +{ + MAGIC *mg; + SV *sv = osv; + + LOCK_SV_LOCK_MUTEX; + if (SvROK(sv)) { + sv = SvRV(sv); + } + + mg = condpair_magic(sv); + MUTEX_LOCK(MgMUTEXP(mg)); + if (MgOWNER(mg) == thr) + MUTEX_UNLOCK(MgMUTEXP(mg)); + else { + while (MgOWNER(mg)) + COND_WAIT(MgOWNERCONDP(mg), MgMUTEXP(mg)); + MgOWNER(mg) = thr; + DEBUG_S(PerlIO_printf(Perl_debug_log, + "0x%"UVxf": Perl_lock lock 0x%"UVxf"\n", + PTR2UV(thr), PTR2UV(sv));) + MUTEX_UNLOCK(MgMUTEXP(mg)); + SAVEDESTRUCTOR_X(Perl_unlock_condpair, sv); + } + UNLOCK_SV_LOCK_MUTEX; + return sv; +} + /* * Make a new perl thread structure using t as a prototype. Some of the * fields for the new thread are copied from the prototype thread, t, @@ -3034,9 +3568,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) { +#if !defined(PERL_IMPLICIT_CONTEXT) struct perl_thread *thr; +#endif SV *sv; SV **svp; I32 i; @@ -3054,44 +3590,38 @@ new_struct_thread(struct perl_thread *t) PL_dirty = 0; PL_localizing = 0; Zero(&PL_hv_fetch_ent_mh, 1, HE); + PL_efloatbuf = (char*)NULL; + PL_efloatsize = 0; #else Zero(thr, 1, struct perl_thread); #endif - PL_protect = FUNC_NAME_TO_PTR(default_protect); - thr->oursv = sv; - init_stacks(ARGS); + init_stacks(); PL_curcop = &PL_compiling; + thr->interp = t->interp; thr->cvcache = newHV(); thr->threadsv = newAV(); thr->specific = newAV(); thr->errsv = newSVpvn("", 0); - thr->errhv = newHV(); thr->flags = THRf_R_JOINABLE; + thr->thr_done = 0; MUTEX_INIT(&thr->mutex); - /* top_env needs to be non-zero. It points to an area - in which longjmp() stuff is stored, as C callstack - info there at least is thread specific this has to - be per-thread. Otherwise a 'die' in a thread gives - that thread the C stack of last thread to do an eval {}! - See comments in scope.h - Initialize top entry (as in perl.c for main thread) - */ - PL_start_env.je_prev = NULL; - PL_start_env.je_ret = -1; - PL_start_env.je_mustcatch = TRUE; - PL_top_env = &PL_start_env; + JMPENV_BOOTSTRAP; - PL_in_eval = EVAL_NULL; /* ~(EVAL_INEVAL|EVAL_WARNONLY|EVAL_KEEPERR) */ + PL_in_eval = EVAL_NULL; /* ~(EVAL_INEVAL|EVAL_WARNONLY|EVAL_KEEPERR|EVAL_INREQUIRE) */ PL_restartop = 0; PL_statname = NEWSV(66,0); + PL_errors = newSVpvn("", 0); PL_maxscream = -1; - PL_regcompp = FUNC_NAME_TO_PTR(pregcomp); - PL_regexecp = FUNC_NAME_TO_PTR(regexec_flags); + PL_regcompp = MEMBER_TO_FPTR(Perl_pregcomp); + PL_regexecp = MEMBER_TO_FPTR(Perl_regexec_flags); + PL_regint_start = MEMBER_TO_FPTR(Perl_re_intuit_start); + PL_regint_string = MEMBER_TO_FPTR(Perl_re_intuit_string); + PL_regfree = MEMBER_TO_FPTR(Perl_pregfree); PL_regindent = 0; PL_reginterp_cnt = 0; PL_lastscream = Nullsv; @@ -3099,11 +3629,14 @@ new_struct_thread(struct perl_thread *t) PL_screamnext = 0; PL_reg_start_tmp = 0; PL_reg_start_tmpl = 0; + PL_reg_poscache = Nullch; /* parent thread's data needs to be locked while we make copy */ MUTEX_LOCK(&t->mutex); +#ifdef PERL_FLEXIBLE_EXCEPTIONS PL_protect = t->Tprotect; +#endif PL_curcop = t->Tcurcop; /* XXX As good a guess as any? */ PL_defstash = t->Tdefstash; /* XXX maybe these should */ @@ -3114,13 +3647,15 @@ new_struct_thread(struct perl_thread *t) PL_nrs = newSVsv(t->Tnrs); PL_rs = SvREFCNT_inc(PL_nrs); PL_last_in_gv = Nullgv; - PL_ofslen = t->Tofslen; - PL_ofs = savepvn(t->Tofs, PL_ofslen); + PL_ofs_sv = SvREFCNT_inc(PL_ofs_sv); PL_defoutgv = (GV*)SvREFCNT_inc(t->Tdefoutgv); PL_chopset = t->Tchopset; - PL_formtarget = newSVsv(t->Tformtarget); PL_bodytarget = newSVsv(t->Tbodytarget); PL_toptarget = newSVsv(t->Ttoptarget); + if (t->Tformtarget == t->Ttoptarget) + PL_formtarget = PL_toptarget; + else + PL_formtarget = PL_bodytarget; /* Initialise all per-thread SVs that the template thread used */ svp = AvARRAY(t->threadsv); @@ -3129,10 +3664,11 @@ new_struct_thread(struct perl_thread *t) SV *sv = newSVsv(*svp); av_store(thr->threadsv, i, sv); sv_magic(sv, 0, 0, &PL_threadsv_names[i], 1); - DEBUG_S(PerlIO_printf(PerlIO_stderr(), - "new_struct_thread: copied threadsv %d %p->%p\n",i, t, thr)); + DEBUG_S(PerlIO_printf(Perl_debug_log, + "new_struct_thread: copied threadsv %"IVdf" %p->%p\n", + (IV)i, t, thr)); } - } + } thr->threadsvp = AvARRAY(thr->threadsv); MUTEX_LOCK(&PL_threads_mutex); @@ -3148,60 +3684,69 @@ 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; } #endif /* USE_THREADS */ -#ifdef HUGE_VAL +#if defined(HUGE_VAL) || (defined(USE_LONG_DOUBLE) && defined(HUGE_VALL)) /* * This hack is to force load of "huge" support from libm.a - * So it is in perl for (say) POSIX to use. + * So it is in perl for (say) POSIX to use. * Needed for SunOS with Sun's 'acc' for example. */ -double +NV Perl_huge(void) { - return HUGE_VAL; +# if defined(USE_LONG_DOUBLE) && defined(HUGE_VALL) + return HUGE_VALL; +# endif + return HUGE_VAL; } #endif #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; } +PPADDR_t* +Perl_get_ppaddr(pTHX) +{ + return (PPADDR_t*)PL_ppaddr; +} + #ifndef HAS_GETENV_LEN char * -getenv_len(char *env_elem, unsigned long *len) +Perl_getenv_len(pTHX_ const char *env_elem, unsigned long *len) { char *env_trans = PerlEnv_getenv(env_elem); if (env_trans) @@ -3212,7 +3757,7 @@ getenv_len(char *env_elem, unsigned long *len) MGVTBL* -get_vtbl(int vtbl_id) +Perl_get_vtbl(pTHX_ int vtbl_id) { MGVTBL* result = Null(MGVTBL*); @@ -3316,32 +3861,38 @@ get_vtbl(int vtbl_id) } I32 -my_fflush_all(void) +Perl_my_fflush_all(pTHX) { -#ifdef FFLUSH_NULL +#if defined(FFLUSH_NULL) return PerlIO_flush(NULL); #else +# if defined(HAS__FWALK) + /* undocumented, unprototyped, but very useful BSDism */ + extern void _fwalk(int (*)(FILE *)); + _fwalk(&fflush); + return 0; +# else long open_max = -1; -# if defined(FFLUSH_ALL) && defined(HAS_STDIO_STREAM_ARRAY) -# ifdef PERL_FFLUSH_ALL_FOPEN_MAX +# 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) +# 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; +# ifdef FOPEN_MAX + open_max = FOPEN_MAX; # else -# ifdef _NFILE +# ifdef OPEN_MAX + open_max = OPEN_MAX; +# else +# ifdef _NFILE open_max = _NFILE; +# endif # endif # endif # endif -# endif -# endif +# endif if (open_max > 0) { long i; for (i = 0; i < open_max; i++) @@ -3351,8 +3902,87 @@ my_fflush_all(void) PerlIO_flush(&STDIO_STREAM_ARRAY[i]); return 0; } -# endif +# endif SETERRNO(EBADF,RMS$_IFI); return EOF; +# endif #endif } + +NV +Perl_my_atof(pTHX_ const char* s) +{ + NV x = 0.0; +#ifdef USE_LOCALE_NUMERIC + if ((PL_hints & HINT_LOCALE) && PL_numeric_local) { + NV y; + + Perl_atof2(s, x); + SET_NUMERIC_STANDARD(); + Perl_atof2(s, y); + SET_NUMERIC_LOCAL(); + if ((y < 0.0 && y < x) || (y > 0.0 && y > x)) + return y; + } + else + Perl_atof2(s, x); +#else + Perl_atof2(s, x); +#endif + return x; +} + +void +Perl_report_evil_fh(pTHX_ GV *gv, IO *io, I32 op) +{ + char *vile; + I32 warn_type; + char *func = + op == OP_READLINE ? "readline" : /* "" not nice */ + op == OP_LEAVEWRITE ? "write" : /* "write exit" not nice */ + PL_op_desc[op]; + char *pars = OP_IS_FILETEST(op) ? "" : "()"; + char *type = OP_IS_SOCKET(op) || (io && IoTYPE(io) == IoTYPE_SOCKET) ? + "socket" : "filehandle"; + char *name = NULL; + + if (io && IoTYPE(io) == IoTYPE_CLOSED) { + vile = "closed"; + warn_type = WARN_CLOSED; + } + else { + vile = "unopened"; + warn_type = WARN_UNOPENED; + } + + if (gv && isGV(gv)) { + SV *sv = sv_newmortal(); + gv_efullname4(sv, gv, Nullch, FALSE); + name = SvPVX(sv); + } + + if (op == OP_phoney_OUTPUT_ONLY || op == OP_phoney_INPUT_ONLY) { + if (name && *name) + Perl_warner(aTHX_ WARN_IO, "Filehandle %s opened only for %sput", + name, + (op == OP_phoney_INPUT_ONLY ? "in" : "out")); + else + Perl_warner(aTHX_ WARN_IO, "Filehandle opened only for %sput", + (op == OP_phoney_INPUT_ONLY ? "in" : "out")); + } else if (name && *name) { + Perl_warner(aTHX_ warn_type, + "%s%s on %s %s %s", func, pars, vile, type, name); + if (io && IoDIRP(io) && !(IoFLAGS(io) & IOf_FAKE_DIRP)) + Perl_warner(aTHX_ warn_type, + "\t(Are you trying to call %s%s on dirhandle %s?)\n", + func, pars, name); + } + else { + Perl_warner(aTHX_ warn_type, + "%s%s on %s %s", func, pars, vile, type); + if (io && IoDIRP(io) && !(IoFLAGS(io) & IOf_FAKE_DIRP)) + Perl_warner(aTHX_ warn_type, + "\t(Are you trying to call %s%s on dirhandle?)\n", + func, pars); + } +}