#include "EXTERN.h"
#define PERL_IN_UTIL_C
#include "perl.h"
+#include "reentr.h"
#ifdef USE_PERLIO
#include "perliol.h" /* For PerlIOUnix_refcnt */
* XXX This advice seems to be widely ignored :-( --AD August 1996.
*/
-static char *
-S_write_no_mem(pTHX)
-{
- dVAR;
- /* Can't use PerlIO to write as it allocates memory */
- PerlLIO_write(PerlIO_fileno(Perl_error_log),
- PL_no_mem, strlen(PL_no_mem));
- my_exit(1);
- NORETURN_FUNCTION_END;
-}
-
#if defined (DEBUGGING) || defined(PERL_IMPLICIT_SYS) || defined (PERL_TRACK_MEMPOOL)
# define ALWAYS_NEED_THX
#endif
if (PL_nomemok)
return NULL;
else {
- return write_no_mem();
+ croak_no_mem();
}
}
/*NOTREACHED*/
if (PL_nomemok)
return NULL;
else {
- return write_no_mem();
+ croak_no_mem();
}
}
/*NOTREACHED*/
#endif
}
else
- croak_memory_wrap();
+ Perl_croak_memory_wrap();
#ifdef PERL_TRACK_MEMPOOL
if (sTHX <= MEM_SIZE_MAX - (MEM_SIZE)total_size)
total_size += sTHX;
else
- croak_memory_wrap();
+ Perl_croak_memory_wrap();
#endif
#ifdef HAS_64K_LIMIT
if (total_size > 0xffff) {
#endif
if (PL_nomemok)
return NULL;
- return write_no_mem();
+ croak_no_mem();
}
}
/* copy a string up to some (non-backslashed) delimiter, if any */
char *
-Perl_delimcpy(register char *to, register const char *toend, register const char *from, register const char *fromend, register int delim, I32 *retlen)
+Perl_delimcpy(char *to, const char *toend, const char *from, const char *fromend, int delim, I32 *retlen)
{
I32 tolen;
/* This routine was donated by Corey Satten. */
char *
-Perl_instr(register const char *big, register const char *little)
+Perl_instr(const char *big, const char *little)
{
- I32 first;
PERL_ARGS_ASSERT_INSTR;
+ /* libc prior to 4.6.27 did not work properly on a NULL 'little' */
if (!little)
return (char*)big;
- first = *little++;
- if (!first)
- return (char*)big;
- while (*big) {
- const char *s, *x;
- if (*big++ != first)
- continue;
- for (x=big,s=little; *s; /**/ ) {
- if (!*x)
- return NULL;
- if (*s != *x)
- break;
- else {
- s++;
- x++;
- }
- }
- if (!*s)
- return (char*)(big-1);
- }
- return NULL;
+ return strstr((char*)big, (char*)little);
}
/* same as instr but allow embedded nulls. The end pointers point to 1 beyond
/* reverse of the above--find last substring */
char *
-Perl_rninstr(register const char *big, const char *bigend, const char *little, const char *lend)
+Perl_rninstr(const char *big, const char *bigend, const char *little, const char *lend)
{
const char *bigbeg;
const I32 first = *little;
*/
char *
-Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 flags)
+Perl_fbm_instr(pTHX_ unsigned char *big, unsigned char *bigend, SV *littlestr, U32 flags)
{
unsigned char *s;
STRLEN l;
I32
-Perl_foldEQ(const char *s1, const char *s2, register I32 len)
+Perl_foldEQ(const char *s1, const char *s2, I32 len)
{
const U8 *a = (const U8 *)s1;
const U8 *b = (const U8 *)s2;
PERL_ARGS_ASSERT_FOLDEQ;
+ assert(len >= 0);
+
while (len--) {
if (*a != *b && *a != PL_fold[*b])
return 0;
return 1;
}
I32
-Perl_foldEQ_latin1(const char *s1, const char *s2, register I32 len)
+Perl_foldEQ_latin1(const char *s1, const char *s2, I32 len)
{
/* Compare non-utf8 using Unicode (Latin1) semantics. Does not work on
* MICRO_SIGN, LATIN_SMALL_LETTER_SHARP_S, nor
PERL_ARGS_ASSERT_FOLDEQ_LATIN1;
+ assert(len >= 0);
+
while (len--) {
if (*a != *b && *a != PL_fold_latin1[*b]) {
return 0;
*/
I32
-Perl_foldEQ_locale(const char *s1, const char *s2, register I32 len)
+Perl_foldEQ_locale(const char *s1, const char *s2, I32 len)
{
dVAR;
const U8 *a = (const U8 *)s1;
PERL_ARGS_ASSERT_FOLDEQ_LOCALE;
+ assert(len >= 0);
+
while (len--) {
if (*a != *b && *a != PL_fold_locale[*b])
return 0;
*/
char *
-Perl_savepvn(pTHX_ const char *pv, register I32 len)
+Perl_savepvn(pTHX_ const char *pv, I32 len)
{
char *newaddr;
PERL_UNUSED_CONTEXT;
+ assert(len >= 0);
+
Newx(newaddr,len+1,char);
/* Give a meaning to NULL pointer mainly for the use in sv_magic() */
if (pv) {
pvlen = strlen(pv)+1;
newaddr = (char*)PerlMemShared_malloc(pvlen);
if (!newaddr) {
- return write_no_mem();
+ croak_no_mem();
}
return (char*)memcpy(newaddr, pv, pvlen);
}
/* PERL_ARGS_ASSERT_SAVESHAREDPVN; */
if (!newaddr) {
- return write_no_mem();
+ croak_no_mem();
}
newaddr[len] = '\0';
return (char*)memcpy(newaddr, pv, len);
*/
void
-Perl_croak_no_modify(pTHX)
+Perl_croak_no_modify()
{
- Perl_croak(aTHX_ "%s", PL_no_modify);
+ Perl_croak_nocontext( "%s", PL_no_modify);
+}
+
+/* does not return, used in util.c perlio.c and win32.c
+ This is typically called when malloc returns NULL.
+*/
+void
+Perl_croak_no_mem()
+{
+ dTHX;
+
+ /* Can't use PerlIO to write as it allocates memory */
+ PerlLIO_write(PerlIO_fileno(Perl_error_log),
+ PL_no_mem, sizeof(PL_no_mem)-1);
+ my_exit(1);
+}
+
+/* saves machine code for a common noreturn idiom typically used in Newx*() */
+void
+Perl_croak_memory_wrap(void)
+{
+ Perl_croak_nocontext("%s",PL_memory_wrap);
+}
+
+
+/* does not return, used only in POPSTACK */
+void
+Perl_croak_popstack(void)
+{
+ dTHX;
+ PerlIO_printf(Perl_error_log, "panic: POPSTACK\n");
+ my_exit(1);
}
/*
my_setenv_format(environ[i], nam, nlen, val, vlen);
} else {
# endif
-# if defined(__CYGWIN__) || defined(EPOC) || defined(__SYMBIAN32__) || defined(__riscos__)
+# if defined(__CYGWIN__)|| defined(__SYMBIAN32__) || defined(__riscos__)
# if defined(HAS_UNSETENV)
if (val == NULL) {
(void)unsetenv(nam);
# else
# if defined(HAS_UNSETENV)
if (val == NULL) {
- (void)unsetenv(nam);
+ if (environ) /* old glibc can crash with null environ */
+ (void)unsetenv(nam);
} else {
const int nlen = strlen(nam);
const int vlen = strlen(val);
#endif /* WIN32 || NETWARE */
-#endif /* !VMS && !EPOC*/
+#endif /* !VMS */
#ifdef UNLINK_ALL_VERSIONS
I32
/* this is a drop-in replacement for bcopy() */
#if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
char *
-Perl_my_bcopy(register const char *from,register char *to,register I32 len)
+Perl_my_bcopy(const char *from, char *to, I32 len)
{
char * const retval = to;
PERL_ARGS_ASSERT_MY_BCOPY;
+ assert(len >= 0);
+
if (from - to >= 0) {
while (len--)
*to++ = *from++;
/* this is a drop-in replacement for memset() */
#ifndef HAS_MEMSET
void *
-Perl_my_memset(register char *loc, register I32 ch, register I32 len)
+Perl_my_memset(char *loc, I32 ch, I32 len)
{
char * const retval = loc;
PERL_ARGS_ASSERT_MY_MEMSET;
+ assert(len >= 0);
+
while (len--)
*loc++ = ch;
return retval;
/* this is a drop-in replacement for bzero() */
#if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
char *
-Perl_my_bzero(register char *loc, register I32 len)
+Perl_my_bzero(char *loc, I32 len)
{
char * const retval = loc;
PERL_ARGS_ASSERT_MY_BZERO;
+ assert(len >= 0);
+
while (len--)
*loc++ = 0;
return retval;
/* this is a drop-in replacement for memcmp() */
#if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
I32
-Perl_my_memcmp(const char *s1, const char *s2, register I32 len)
+Perl_my_memcmp(const char *s1, const char *s2, I32 len)
{
const U8 *a = (const U8 *)s1;
const U8 *b = (const U8 *)s2;
PERL_ARGS_ASSERT_MY_MEMCMP;
+ assert(len >= 0);
+
while (len--) {
if ((tmp = *a++ - *b++))
return tmp;
#define HTOLE(name,type) \
type \
- name (register type n) \
+ name (type n) \
{ \
union { \
type value; \
char c[sizeof(type)]; \
} u; \
- U32 i; \
- U32 s = 0; \
+ U32 i; \
+ U32 s = 0; \
for (i = 0; i < sizeof(u.c); i++, s += 8) { \
u.c[i] = (n >> s) & 0xFF; \
} \
#define LETOH(name,type) \
type \
- name (register type n) \
+ name (type n) \
{ \
union { \
type value; \
char c[sizeof(type)]; \
} u; \
- U32 i; \
- U32 s = 0; \
+ U32 i; \
+ U32 s = 0; \
u.value = n; \
n = 0; \
for (i = 0; i < sizeof(u.c); i++, s += 8) { \
#define HTOBE(name,type) \
type \
- name (register type n) \
+ name (type n) \
{ \
union { \
type value; \
char c[sizeof(type)]; \
} u; \
- U32 i; \
- U32 s = 8*(sizeof(u.c)-1); \
+ U32 i; \
+ U32 s = 8*(sizeof(u.c)-1); \
for (i = 0; i < sizeof(u.c); i++, s -= 8) { \
u.c[i] = (n >> s) & 0xFF; \
} \
#define BETOH(name,type) \
type \
- name (register type n) \
+ name (type n) \
{ \
union { \
type value; \
char c[sizeof(type)]; \
} u; \
- U32 i; \
- U32 s = 8*(sizeof(u.c)-1); \
+ U32 i; \
+ U32 s = 8*(sizeof(u.c)-1); \
u.value = n; \
n = 0; \
for (i = 0; i < sizeof(u.c); i++, s -= 8) { \
#define NOT_AVAIL(name,type) \
type \
- name (register type n) \
+ name (type n) \
{ \
Perl_croak_nocontext(#name "() not available"); \
return n; /* not reached */ \
PerlIO *
Perl_my_popen_list(pTHX_ const char *mode, int n, SV **args)
{
-#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(OS2) && !defined(VMS) && !defined(EPOC) && !defined(NETWARE) && !defined(__LIBCATAMOUNT__)
+#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(OS2) && !defined(VMS) && !defined(NETWARE) && !defined(__LIBCATAMOUNT__)
dVAR;
int p[2];
I32 This, that;
}
/* VMS' my_popen() is in VMS.c, same with OS/2. */
-#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(EPOC) && !defined(__LIBCATAMOUNT__)
+#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__LIBCATAMOUNT__)
PerlIO *
Perl_my_popen(pTHX_ const char *cmd, const char *mode)
{
return PerlIO_fdopen(p[This], mode);
}
#else
-#if defined(EPOC)
-FILE *popen();
-PerlIO *
-Perl_my_popen(pTHX_ const char *cmd, const char *mode)
-{
- PERL_ARGS_ASSERT_MY_POPEN;
- PERL_FLUSHALL_FOR_CHILD;
- /* 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);
-}
-#else
#if defined(DJGPP)
FILE *djgpp_popen();
PerlIO *
}
#endif
#endif
-#endif
#endif /* !DOSISH */
dVAR;
#if defined(USE_ITHREADS)
/* locks must be held in locking order (if any) */
+# ifdef USE_PERLIO
+ MUTEX_LOCK(&PL_perlio_mutex);
+# endif
# ifdef MYMALLOC
MUTEX_LOCK(&PL_malloc_mutex);
# endif
dVAR;
#if defined(USE_ITHREADS)
/* locks must be released in same order as in atfork_lock() */
+# ifdef USE_PERLIO
+ MUTEX_UNLOCK(&PL_perlio_mutex);
+# endif
# ifdef MYMALLOC
MUTEX_UNLOCK(&PL_malloc_mutex);
# endif
#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(EPOC) && !defined(__LIBCATAMOUNT__)
+#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__LIBCATAMOUNT__)
I32
Perl_my_pclose(pTHX_ PerlIO *ptr)
{
}
#endif
-#if defined(OS2) || defined(EPOC)
+#if defined(OS2)
int pclose();
#ifdef HAS_FORK
int /* Cannot prototype with I32
#define PERL_REPEATCPY_LINEAR 4
void
-Perl_repeatcpy(register char *to, register const char *from, I32 len, register IV count)
+Perl_repeatcpy(char *to, const char *from, I32 len, IV count)
{
PERL_ARGS_ASSERT_REPEATCPY;
+ assert(len >= 0);
+
if (count < 0)
- croak_memory_wrap();
+ Perl_croak_memory_wrap();
if (len == 1)
memset(to, *from, count);
* back into. */
int
-Perl_getcwd_sv(pTHX_ register SV *sv)
+Perl_getcwd_sv(pTHX_ SV *sv)
{
#ifndef PERL_MICRO
dVAR;
const char *
Perl_scan_version(pTHX_ const char *s, SV *rv, bool qv)
{
- const char *start;
+ const char *start = s;
const char *pos;
const char *last;
const char *errstr = NULL;
int width = 3;
bool alpha = FALSE;
bool vinf = FALSE;
- AV * const av = newAV();
- SV * const hv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */
+ AV * av;
+ SV * hv;
PERL_ARGS_ASSERT_SCAN_VERSION;
- (void)sv_upgrade(hv, SVt_PVHV); /* needs to be an HV type */
-
-#ifndef NODEFAULT_SHAREKEYS
- HvSHAREKEYS_on(hv); /* key-sharing on by default */
-#endif
-
while (isSPACE(*s)) /* leading whitespace is OK */
s++;
if (errstr) {
/* "undef" is a special case and not an error */
if ( ! ( *s == 'u' && strEQ(s,"undef")) ) {
+ Safefree(start);
Perl_croak(aTHX_ "%s", errstr);
}
}
s++;
pos = s;
+ /* Now that we are through the prescan, start creating the object */
+ av = newAV();
+ hv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */
+ (void)sv_upgrade(hv, SVt_PVHV); /* needs to be an HV type */
+
+#ifndef NODEFAULT_SHAREKEYS
+ HvSHAREKEYS_on(hv); /* key-sharing on by default */
+#endif
+
if ( qv )
(void)hv_stores(MUTABLE_HV(hv), "qv", newSViv(qv));
if ( alpha )
(void)hv_stores(MUTABLE_HV(hv), "alpha", newSViv(alpha));
if ( !qv && width < 3 )
(void)hv_stores(MUTABLE_HV(hv), "width", newSViv(width));
-
+
while (isDIGIT(*pos))
pos++;
if (!isALPHA(*pos)) {
if ( hv_exists(MUTABLE_HV(ver), "alpha", 5) )
(void)hv_stores(MUTABLE_HV(hv), "alpha", newSViv(1));
-
+
if ( hv_exists(MUTABLE_HV(ver), "width", 5 ) )
{
const I32 width = SvIV(*hv_fetchs(MUTABLE_HV(ver), "width", FALSE));
}
/* is definitely a v-string */
- if ( saw_decimal >= 2 ) {
+ if ( saw_decimal >= 2 ) {
Safefree(version);
version = nver;
}
Perl_my_socketpair (int family, int type, int protocol, int fd[2]) {
/* Stevens says that family must be AF_LOCAL, protocol 0.
I'm going to enforce that, then ignore it, and use TCP (or UDP). */
- dTHX;
+ dTHXa(NULL);
int listener = -1;
int connector = -1;
int acceptor = -1;
return S_socketpair_udp(fd);
#endif
+ aTHXa(PERL_GET_THX);
listener = PerlSock_socket(AF_INET, type, 0);
if (listener == -1)
return -1;
return u;
}
-UV
-Perl_get_hash_seed(pTHX)
+void
+Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
{
dVAR;
- const char *s = PerlEnv_getenv("PERL_HASH_SEED");
- UV myseed = 0;
-
- if (s)
- while (isSPACE(*s))
- s++;
- if (s && isDIGIT(*s))
- myseed = (UV)Atoul(s);
- else
-#ifdef USE_HASH_SEED_EXPLICIT
- if (s)
-#endif
- {
- /* Compute a random seed */
- (void)seedDrand01((Rand_seed_t)seed());
- myseed = (UV)(Drand01() * (NV)UV_MAX);
-#if RANDBITS < (UVSIZE * 8)
- /* Since there are not enough randbits to to reach all
- * the bits of a UV, the low bits might need extra
- * help. Sum in another random number that will
- * fill in the low bits. */
- myseed +=
- (UV)(Drand01() * (NV)((((UV)1) << ((UVSIZE * 8 - RANDBITS))) - 1));
-#endif /* RANDBITS < (UVSIZE * 8) */
- if (myseed == 0) { /* Superparanoia. */
- myseed = (UV)(Drand01() * (NV)UV_MAX); /* One more chance. */
- if (myseed == 0)
- Perl_croak(aTHX_ "Your random numbers are not that random");
- }
- }
- PL_rehash_seed_set = TRUE;
-
- return myseed;
+ const char *env_pv;
+ unsigned long i;
+
+ PERL_ARGS_ASSERT_GET_HASH_SEED;
+
+ env_pv= PerlEnv_getenv("PERL_HASH_SEED");
+
+ if ( env_pv )
+#ifndef USE_HASH_SEED_EXPLICIT
+ {
+ /* ignore leading spaces */
+ while (isSPACE(*env_pv))
+ env_pv++;
+#ifdef USE_PERL_PERTURB_KEYS
+ /* if they set it to "0" we disable key traversal randomization completely */
+ if (strEQ(env_pv,"0")) {
+ PL_hash_rand_bits_enabled= 0;
+ } else {
+ /* otherwise switch to deterministic mode */
+ PL_hash_rand_bits_enabled= 2;
+ }
+#endif
+ /* ignore a leading 0x... if it is there */
+ if (env_pv[0] == '0' && env_pv[1] == 'x')
+ env_pv += 2;
+
+ for( i = 0; isXDIGIT(*env_pv) && i < PERL_HASH_SEED_BYTES; i++ ) {
+ seed_buffer[i] = READ_XDIGIT(env_pv) << 4;
+ if ( isXDIGIT(*env_pv)) {
+ seed_buffer[i] |= READ_XDIGIT(env_pv);
+ }
+ }
+ while (isSPACE(*env_pv))
+ env_pv++;
+
+ if (*env_pv && !isXDIGIT(*env_pv)) {
+ Perl_warn(aTHX_ "perl: warning: Non hex character in '$ENV{PERL_HASH_SEED}', seed only partially set\n");
+ }
+ /* should we check for unparsed crap? */
+ /* should we warn about unused hex? */
+ /* should we warn about insufficient hex? */
+ }
+ else
+#endif
+ {
+ (void)seedDrand01((Rand_seed_t)seed());
+
+ for( i = 0; i < PERL_HASH_SEED_BYTES; i++ ) {
+ seed_buffer[i] = (unsigned char)(Drand01() * (U8_MAX+1));
+ }
+ }
+#ifdef USE_PERL_PERTURB_KEYS
+ { /* initialize PL_hash_rand_bits from the hash seed.
+ * This value is highly volatile, it is updated every
+ * hash insert, and is used as part of hash bucket chain
+ * randomization and hash iterator randomization. */
+ PL_hash_rand_bits= 0xbe49d17f; /* I just picked a number */
+ for( i = 0; i < sizeof(UV) ; i++ ) {
+ PL_hash_rand_bits += seed_buffer[i % PERL_HASH_SEED_BYTES];
+ PL_hash_rand_bits = ROTL_UV(PL_hash_rand_bits,8);
+ }
+ }
+ env_pv= PerlEnv_getenv("PERL_PERTURB_KEYS");
+ if (env_pv) {
+ if (strEQ(env_pv,"0") || strEQ(env_pv,"NO")) {
+ PL_hash_rand_bits_enabled= 0;
+ } else if (strEQ(env_pv,"1") || strEQ(env_pv,"RANDOM")) {
+ PL_hash_rand_bits_enabled= 1;
+ } else if (strEQ(env_pv,"2") || strEQ(env_pv,"DETERMINISTIC")) {
+ PL_hash_rand_bits_enabled= 2;
+ } else {
+ Perl_warn(aTHX_ "perl: warning: strange setting in '$ENV{PERL_PERTURB_KEYS}': '%s'\n", env_pv);
+ }
+ }
+#endif
}
#ifdef PERL_GLOBAL_STRUCT
int
Perl_my_snprintf(char *buffer, const Size_t len, const char *format, ...)
{
- dTHX;
int retval;
va_list ap;
PERL_ARGS_ASSERT_MY_SNPRINTF;
(len > 0 && (Size_t)retval >= len)
#endif
)
- Perl_croak(aTHX_ "panic: my_snprintf buffer overflow");
+ Perl_croak_nocontext("panic: my_snprintf buffer overflow");
return retval;
}
int
Perl_my_vsnprintf(char *buffer, const Size_t len, const char *format, va_list ap)
{
- dTHX;
int retval;
#ifdef NEED_VA_COPY
va_list apc;
(len > 0 && (Size_t)retval >= len)
#endif
)
- Perl_croak(aTHX_ "panic: my_vsnprintf buffer overflow");
+ Perl_croak_nocontext("panic: my_vsnprintf buffer overflow");
return retval;
}
if (bsiz < l + 1) {
(void)safesysfree(buf);
bsiz = l + 1; /* + 1 for the \0. */
+ bufsiz = bsiz * sizeof(char); /* keep bsiz and bufsiz in sync */
buf = (char*)safesysmalloc(bufsiz);
}
memcpy(buf, *environ, l);
{
dVAR;
SV * const dbsv = GvSVn(PL_DBsub);
- const bool save_taint = TAINT_get; /* Accepted unused var warning under NO_TAINT_SUPPORT */
+ const bool save_taint = TAINT_get;
/* When we are called from pp_goto (svp is null),
* we do not care about using dbsv to call CV;
SvIV_set(dbsv, PTR2IV(cv)); /* Do it the quickest way */
}
TAINT_IF(save_taint);
+#ifdef NO_TAINT_SUPPORT
+ PERL_UNUSED_VAR(save_taint);
+#endif
}
int