#include "perl.h"
#include "reentr.h"
-#ifdef USE_PERLIO
+#if defined(USE_PERLIO)
#include "perliol.h" /* For PerlIOUnix_refcnt */
#endif
#endif
#endif
+#include <math.h>
+#include <stdlib.h>
+
#ifdef __Lynx__
/* Missing protos on LynxOS */
int putenv(char *);
dTHX;
#endif
Malloc_t ptr;
-#ifdef HAS_64K_LIMIT
- if (size > 0xffff) {
- PerlIO_printf(Perl_error_log,
- "Allocation too large: %lx\n", size) FLUSH;
- my_exit(1);
- }
-#endif /* HAS_64K_LIMIT */
#ifdef PERL_TRACK_MEMPOOL
size += sTHX;
#endif
Malloc_t PerlMem_realloc();
#endif /* !defined(STANDARD_C) && !defined(HAS_REALLOC_PROTOTYPE) */
-#ifdef HAS_64K_LIMIT
- if (size > 0xffff) {
- PerlIO_printf(Perl_error_log,
- "Reallocation too large: %lx\n", size) FLUSH;
- my_exit(1);
- }
-#endif /* HAS_64K_LIMIT */
if (!size) {
safesysfree(where);
return NULL;
dTHX;
#endif
Malloc_t ptr;
-#if defined(PERL_TRACK_MEMPOOL) || defined(HAS_64K_LIMIT) || defined(DEBUGGING)
+#if defined(PERL_TRACK_MEMPOOL) || defined(DEBUGGING)
MEM_SIZE total_size = 0;
#endif
/* Even though calloc() for zero bytes is strange, be robust. */
if (size && (count <= MEM_SIZE_MAX / size)) {
-#if defined(PERL_TRACK_MEMPOOL) || defined(HAS_64K_LIMIT) || defined(DEBUGGING)
+#if defined(PERL_TRACK_MEMPOOL) || defined(DEBUGGING)
total_size = size * count;
#endif
}
else
- Perl_croak_memory_wrap();
+ croak_memory_wrap();
#ifdef PERL_TRACK_MEMPOOL
if (sTHX <= MEM_SIZE_MAX - (MEM_SIZE)total_size)
total_size += sTHX;
else
- Perl_croak_memory_wrap();
+ croak_memory_wrap();
#endif
-#ifdef HAS_64K_LIMIT
- if (total_size > 0xffff) {
- PerlIO_printf(Perl_error_log,
- "Allocation too large: %lx\n", total_size) FLUSH;
- my_exit(1);
- }
-#endif /* HAS_64K_LIMIT */
#ifdef DEBUGGING
if ((SSize_t)size < 0 || (SSize_t)count < 0)
Perl_croak_nocontext("panic: calloc, size=%"UVuf", count=%"UVuf,
const U8 *s;
STRLEN i;
STRLEN len;
- STRLEN rarest = 0;
U32 frequency = 256;
MAGIC *mg;
+ PERL_DEB( STRLEN rarest = 0 );
PERL_ARGS_ASSERT_FBM_COMPILE;
- if (isGV_with_GP(sv))
+ if (isGV_with_GP(sv) || SvROK(sv))
return;
if (SvVALID(sv))
if (mg && mg->mg_len >= 0)
mg->mg_len++;
}
- s = (U8*)SvPV_force_mutable(sv, len);
+ if (!SvPOK(sv) || SvNIOKp(sv))
+ s = (U8*)SvPV_force_mutable(sv, len);
+ else s = (U8 *)SvPV_mutable(sv, len);
if (len == 0) /* TAIL might be on a zero-length string. */
return;
SvUPGRADE(sv, SVt_PVMG);
s = (const unsigned char*)(SvPVX_const(sv)); /* deeper magic */
for (i = 0; i < len; i++) {
if (PL_freq[s[i]] < frequency) {
- rarest = i;
+ PERL_DEB( rarest = i );
frequency = PL_freq[s[i]];
}
}
- BmRARE(sv) = s[rarest];
- BmPREVIOUS(sv) = rarest;
BmUSEFUL(sv) = 100; /* Initial value */
if (flags & FBMcf_TAIL)
SvTAIL_on(sv);
DEBUG_r(PerlIO_printf(Perl_debug_log, "rarest char %c at %"UVuf"\n",
- BmRARE(sv), BmPREVIOUS(sv)));
+ s[rarest], (UV)rarest));
}
/* If SvTAIL(littlestr), it has a fake '\n' at end. */
determined by C<strlen()>. The memory allocated for the new string can
be freed with the C<Safefree()> function.
+On some platforms, Windows for example, all allocated memory owned by a thread
+is deallocated when that thread ends. So if you need that not to happen, you
+need to use the shared memory functions, such as C<L</savesharedpv>>.
+
=cut
*/
C<len> bytes from C<pv>, plus a trailing NUL byte. The memory allocated for
the new string can be freed with the C<Safefree()> function.
+On some platforms, Windows for example, all allocated memory owned by a thread
+is deallocated when that thread ends. So if you need that not to happen, you
+need to use the shared memory functions, such as C<L</savesharedpvn>>.
+
=cut
*/
A version of C<savepv()>/C<savepvn()> which gets the string to duplicate from
the passed in SV using C<SvPV()>
+On some platforms, Windows for example, all allocated memory owned by a thread
+is deallocated when that thread ends. So if you need that not to happen, you
+need to use the shared memory functions, such as C<L</savesharedsvpv>>.
+
=cut
*/
return retval;
}
-STATIC const COP*
-S_closest_cop(pTHX_ const COP *cop, const OP *o)
+const COP*
+Perl_closest_cop(pTHX_ const COP *cop, const OP *o, const OP *curop,
+ bool opnext)
{
dVAR;
- /* Look for PL_op starting from o. cop is the last COP we've seen. */
+ /* Look for curop starting from o. cop is the last COP we've seen. */
+ /* opnext means that curop is actually the ->op_next of the op we are
+ seeking. */
PERL_ARGS_ASSERT_CLOSEST_COP;
- if (!o || o == PL_op)
+ if (!o || !curop || (
+ opnext ? o->op_next == curop && o->op_type != OP_SCOPE : o == curop
+ ))
return cop;
if (o->op_flags & OPf_KIDS) {
/* Keep searching, and return when we've found something. */
- new_cop = closest_cop(cop, kid);
+ new_cop = closest_cop(cop, kid, curop, opnext);
if (new_cop)
return new_cop;
}
* from the sibling of PL_curcop.
*/
- const COP *cop = closest_cop(PL_curcop, PL_curcop->op_sibling);
+ const COP *cop =
+ closest_cop(PL_curcop, PL_curcop->op_sibling, PL_op, FALSE);
if (!cop)
cop = PL_curcop;
if (PL_stderrgv && SvREFCNT(PL_stderrgv)
&& (io = GvIO(PL_stderrgv))
&& (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar)))
- Perl_magic_methcall(aTHX_ MUTABLE_SV(io), mg, "PRINT",
+ Perl_magic_methcall(aTHX_ MUTABLE_SV(io), mg, SV_CONST(PRINT),
G_SCALAR | G_DISCARD | G_WRITING_TO_STDERR, 1, msv);
else {
-#ifdef USE_SFIO
- /* SFIO can really mess with your errno */
- dSAVED_ERRNO;
-#endif
PerlIO * const serr = Perl_error_log;
do_print(msv, serr);
(void)PerlIO_flush(serr);
-#ifdef USE_SFIO
- RESTORE_ERRNO;
-#endif
}
}
Perl_croak_no_mem()
{
dTHX;
+ int rc;
/* Can't use PerlIO to write as it allocates memory */
- PerlLIO_write(PerlIO_fileno(Perl_error_log),
+ rc = PerlLIO_write(PerlIO_fileno(Perl_error_log),
PL_no_mem, sizeof(PL_no_mem)-1);
+ /* silently ignore failures */
+ PERL_UNUSED_VAR(rc);
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)
#endif /* HAS_FORK */
}
-#ifdef DUMP_FDS
-void
-Perl_dump_fds(pTHX_ const char *const s)
-{
- int fd;
- Stat_t tmpstatbuf;
-
- PERL_ARGS_ASSERT_DUMP_FDS;
-
- PerlIO_printf(Perl_debug_log,"%s", s);
- for (fd = 0; fd < 32; fd++) {
- if (PerlLIO_fstat(fd,&tmpstatbuf) >= 0)
- PerlIO_printf(Perl_debug_log," %d",fd);
- }
- PerlIO_printf(Perl_debug_log,"\n");
- return;
-}
-#endif /* DUMP_FDS */
-
#ifndef HAS_DUP2
int
dup2(int oldfd, int newfd)
bool close_failed;
dSAVEDERRNO;
const int fd = PerlIO_fileno(ptr);
+ bool should_wait;
-#ifdef USE_PERLIO
+ svp = av_fetch(PL_fdpid,fd,TRUE);
+ pid = (SvTYPE(*svp) == SVt_IV) ? SvIVX(*svp) : -1;
+ SvREFCNT_dec(*svp);
+ *svp = NULL;
+
+#if defined(USE_PERLIO)
/* Find out whether the refcount is low enough for us to wait for the
child proc without blocking. */
- const bool should_wait = PerlIOUnix_refcnt(fd) == 1;
+ should_wait = PerlIOUnix_refcnt(fd) == 1 && pid > 0;
#else
- const bool should_wait = 1;
+ should_wait = pid > 0;
#endif
- svp = av_fetch(PL_fdpid,fd,TRUE);
- pid = (SvTYPE(*svp) == SVt_IV) ? SvIVX(*svp) : -1;
- SvREFCNT_dec(*svp);
- *svp = &PL_sv_undef;
#ifdef OS2
if (pid == -1) { /* Opened by popen. */
return my_syspclose(ptr);
dVAR;
I32 result = 0;
PERL_ARGS_ASSERT_WAIT4PID;
- if (!pid)
- return -1;
#ifdef PERL_USES_PL_PIDSTATUS
+ if (!pid) {
+ /* PERL_USES_PL_PIDSTATUS is only defined when neither
+ waitpid() nor wait4() is available, or on OS/2, which
+ doesn't appear to support waiting for a progress group
+ member, so we can only treat a 0 pid as an unknown child.
+ */
+ errno = ECHILD;
+ return -1;
+ }
{
if (pid > 0) {
/* The keys in PL_pidstatus are now the raw 4 (or 8) bytes of the
goto finish;
#endif
#if !defined(HAS_WAITPID) && defined(HAS_WAIT4)
- result = wait4((pid==-1)?0:pid,statusp,flags,NULL);
+ result = wait4(pid,statusp,flags,NULL);
goto finish;
#endif
#ifdef PERL_USES_PL_PIDSTATUS
assert(len >= 0);
if (count < 0)
- Perl_croak_memory_wrap();
+ croak_memory_wrap();
if (len == 1)
memset(to, *from, count);
I32
Perl_my_fflush_all(pTHX)
{
-#if defined(USE_PERLIO) || defined(FFLUSH_NULL) || defined(USE_SFIO)
+#if defined(USE_PERLIO) || defined(FFLUSH_NULL)
return PerlIO_flush(NULL);
#else
# if defined(HAS__FWALK)
*
*/
-#ifdef HAS_GNULIBC
+#ifdef __GLIBC__
# ifndef STRUCT_TM_HASZONE
# define STRUCT_TM_HASZONE
# endif
#endif
buflen = 64;
Newx(buf, buflen, char);
+
+ GCC_DIAG_IGNORE(-Wformat-nonliteral); /* fmt checked by caller */
len = strftime(buf, buflen, fmt, &mytm);
+ GCC_DIAG_RESTORE;
+
/*
** The following is needed to handle to the situation where
** tmpbuf overflows. Basically we want to allocate a buffer
Renew(buf, bufsize, char);
while (buf) {
+
+ GCC_DIAG_IGNORE(-Wformat-nonliteral); /* fmt checked by caller */
buflen = strftime(buf, bufsize, fmt, &mytm);
+ GCC_DIAG_RESTORE;
+
if (buflen > 0 && buflen < bufsize)
break;
/* heuristic to prevent out-of-memory errors */
{
#ifndef PERL_MICRO
dVAR;
-#ifndef INCOMPLETE_TAINTS
SvTAINTED_on(sv);
-#endif
PERL_ARGS_ASSERT_GETCWD_SV;
}
}
if ( qv ) { /* quoted versions always get at least three terms*/
- I32 len = av_len(av);
+ SSize_t len = av_len(av);
/* This for loop appears to trigger a compiler bug on OS X, as it
loops infinitely. Yes, len is negative. No, it makes no sense.
Compiler in question is:
if ( sv_isobject(ver) && sv_derived_from(ver, "version") )
/* can just copy directly */
{
- I32 key;
+ SSize_t key;
AV * const av = newAV();
AV *sav;
/* This will get reblessed later if a derived class*/
SV *sv = SvNVX(ver) > 10e50 ? newSV(64) : 0;
char *buf;
#ifdef USE_LOCALE_NUMERIC
- char *loc = savepv(setlocale(LC_NUMERIC, NULL));
- setlocale(LC_NUMERIC, "C");
+ char *loc = NULL;
+ if (! PL_numeric_standard) {
+ loc = savepv(setlocale(LC_NUMERIC, NULL));
+ setlocale(LC_NUMERIC, "C");
+ }
#endif
if (sv) {
Perl_sv_setpvf(aTHX_ sv, "%.9"NVff, SvNVX(ver));
buf = tbuf;
}
#ifdef USE_LOCALE_NUMERIC
- setlocale(LC_NUMERIC, loc);
- Safefree(loc);
+ if (loc) {
+ setlocale(LC_NUMERIC, loc);
+ Safefree(loc);
+ }
#endif
while (buf[len-1] == '0' && len > 0) len--;
if ( buf[len-1] == '.' ) len--; /* eat the trailing decimal */
SV *
Perl_vnumify(pTHX_ SV *vs)
{
- I32 i, len, digit;
+ SSize_t i, len;
+ I32 digit;
int width;
bool alpha = FALSE;
SV *sv;
int
Perl_vcmp(pTHX_ SV *lhv, SV *rhv)
{
- I32 i,l,m,r,retval;
+ SSize_t i,l,m,r;
+ I32 retval;
bool lalpha = FALSE;
bool ralpha = FALSE;
I32 left = 0;
# ifdef PERL_SET_VARS
PERL_SET_VARS(plvarsp);
# endif
+# ifdef PERL_GLOBAL_STRUCT_PRIVATE
+ plvarsp->Gsv_placeholder.sv_flags = 0;
+ memset(plvarsp->Ghash_seed, 0, sizeof(plvarsp->Ghash_seed));
+# endif
# undef PERL_GLOBAL_STRUCT_INIT
# endif
return plvarsp;
Perl_croak_sv(aTHX_ xpt);
}
+/*
+=for apidoc my_strlcat
+
+The C library C<strlcat> if available, or a Perl implementation of it.
+This operates on C NUL-terminated strings.
+
+C<my_strlcat()> appends string C<src> to the end of C<dst>. It will append at
+most S<C<size - strlen(dst) - 1>> characters. It will then NUL-terminate,
+unless C<size> is 0 or the original C<dst> string was longer than C<size> (in
+practice this should not happen as it means that either C<size> is incorrect or
+that C<dst> is not a proper NUL-terminated string).
+
+Note that C<size> is the full size of the destination buffer and
+the result is guaranteed to be NUL-terminated if there is room. Note that room
+for the NUL should be included in C<size>.
+
+=cut
+
+Description stolen from http://www.openbsd.org/cgi-bin/man.cgi?query=strlcat
+*/
#ifndef HAS_STRLCAT
Size_t
Perl_my_strlcat(char *dst, const char *src, Size_t size)
}
#endif
+
+/*
+=for apidoc my_strlcpy
+
+The C library C<strlcpy> if available, or a Perl implementation of it.
+This operates on C NUL-terminated strings.
+
+C<my_strlcpy()> copies up to S<C<size - 1>> characters from the string C<src>
+to C<dst>, NUL-terminating the result if C<size> is not 0.
+
+=cut
+
+Description stolen from http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy
+*/
#ifndef HAS_STRLCPY
Size_t
Perl_my_strlcpy(char *dst, const char *src, Size_t size)
}
/*
+ * This code is derived from drand48() implementation from FreeBSD,
+ * found in lib/libc/gen/_rand48.c.
+ *
+ * The U64 implementation is original, based on the POSIX
+ * specification for drand48().
+ */
+
+/*
+* Copyright (c) 1993 Martin Birgmeier
+* All rights reserved.
+*
+* You may redistribute unmodified or modified versions of this source
+* code provided that the above copyright notice and this and the
+* following conditions are retained.
+*
+* This software is provided ``as is'', and comes with no warranties
+* of any kind. I shall in no event be liable for anything that happens
+* to anyone/anything when using this software.
+*/
+
+#define FREEBSD_DRAND48_SEED_0 (0x330e)
+
+#ifdef PERL_DRAND48_QUAD
+
+#define DRAND48_MULT U64_CONST(0x5deece66d)
+#define DRAND48_ADD 0xb
+#define DRAND48_MASK U64_CONST(0xffffffffffff)
+
+#else
+
+#define FREEBSD_DRAND48_SEED_1 (0xabcd)
+#define FREEBSD_DRAND48_SEED_2 (0x1234)
+#define FREEBSD_DRAND48_MULT_0 (0xe66d)
+#define FREEBSD_DRAND48_MULT_1 (0xdeec)
+#define FREEBSD_DRAND48_MULT_2 (0x0005)
+#define FREEBSD_DRAND48_ADD (0x000b)
+
+const unsigned short _rand48_mult[3] = {
+ FREEBSD_DRAND48_MULT_0,
+ FREEBSD_DRAND48_MULT_1,
+ FREEBSD_DRAND48_MULT_2
+};
+const unsigned short _rand48_add = FREEBSD_DRAND48_ADD;
+
+#endif
+
+void
+Perl_drand48_init_r(perl_drand48_t *random_state, U32 seed)
+{
+ PERL_ARGS_ASSERT_DRAND48_INIT_R;
+
+#ifdef PERL_DRAND48_QUAD
+ *random_state = FREEBSD_DRAND48_SEED_0 + ((U64TYPE)seed << 16);
+#else
+ random_state->seed[0] = FREEBSD_DRAND48_SEED_0;
+ random_state->seed[1] = (U16) seed;
+ random_state->seed[2] = (U16) (seed >> 16);
+#endif
+}
+
+double
+Perl_drand48_r(perl_drand48_t *random_state)
+{
+ PERL_ARGS_ASSERT_DRAND48_R;
+
+#ifdef PERL_DRAND48_QUAD
+ *random_state = (*random_state * DRAND48_MULT + DRAND48_ADD)
+ & DRAND48_MASK;
+
+ return ldexp((double)*random_state, -48);
+#else
+ {
+ U32 accu;
+ U16 temp[2];
+
+ accu = (U32) _rand48_mult[0] * (U32) random_state->seed[0]
+ + (U32) _rand48_add;
+ temp[0] = (U16) accu; /* lower 16 bits */
+ accu >>= sizeof(U16) * 8;
+ accu += (U32) _rand48_mult[0] * (U32) random_state->seed[1]
+ + (U32) _rand48_mult[1] * (U32) random_state->seed[0];
+ temp[1] = (U16) accu; /* middle 16 bits */
+ accu >>= sizeof(U16) * 8;
+ accu += _rand48_mult[0] * random_state->seed[2]
+ + _rand48_mult[1] * random_state->seed[1]
+ + _rand48_mult[2] * random_state->seed[0];
+ random_state->seed[0] = temp[0];
+ random_state->seed[1] = temp[1];
+ random_state->seed[2] = (U16) accu;
+
+ return ldexp((double) random_state->seed[0], -48) +
+ ldexp((double) random_state->seed[1], -32) +
+ ldexp((double) random_state->seed[2], -16);
+ }
+#endif
+}
+
+
+/*
* Local variables:
* c-indentation-style: bsd
* c-basic-offset: 4