/* util.c
*
- * Copyright (c) 1991-2002, Larry Wall
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ * 2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
* not content." --Gandalf
*/
+/* This file contains assorted utility routines.
+ * Which is a polite way of saying any stuff that people couldn't think of
+ * a better place for. Amongst other things, it includes the warning and
+ * dieing stuff, plus wrappers for malloc code.
+ */
+
#include "EXTERN.h"
#define PERL_IN_UTIL_C
#include "perl.h"
#ifndef PERL_MICRO
-#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
#include <signal.h>
-#endif
-
#ifndef SIG_ERR
# define SIG_ERR ((Sighandler_t) -1)
#endif
#endif
+#ifdef __Lynx__
+/* Missing protos on LynxOS */
+int putenv(char *);
+#endif
+
#ifdef I_SYS_WAIT
# include <sys/wait.h>
#endif
else if (PL_nomemok)
return Nullch;
else {
- PerlIO_puts(Perl_error_log,PL_no_mem) FLUSH;
+ /* Can't use PerlIO to write as it allocates memory */
+ PerlLIO_write(PerlIO_fileno(Perl_error_log),
+ PL_no_mem, strlen(PL_no_mem));
my_exit(1);
return Nullch;
}
else if (PL_nomemok)
return Nullch;
else {
- PerlIO_puts(Perl_error_log,PL_no_mem) FLUSH;
+ /* Can't use PerlIO to write as it allocates memory */
+ PerlLIO_write(PerlIO_fileno(Perl_error_log),
+ PL_no_mem, strlen(PL_no_mem));
my_exit(1);
return Nullch;
}
Free_t
Perl_safesysfree(Malloc_t where)
{
+ dVAR;
#ifdef PERL_IMPLICIT_SYS
dTHX;
#endif
else if (PL_nomemok)
return Nullch;
else {
- PerlIO_puts(Perl_error_log,PL_no_mem) FLUSH;
+ /* Can't use PerlIO to write as it allocates memory */
+ PerlLIO_write(PerlIO_fileno(Perl_error_log),
+ PL_no_mem, strlen(PL_no_mem));
my_exit(1);
return Nullch;
}
/* copy a string up to some (non-backslashed) delimiter, if any */
char *
-Perl_delimcpy(pTHX_ register char *to, register char *toend, register char *from, register char *fromend, register int delim, I32 *retlen)
+Perl_delimcpy(pTHX_ register char *to, register const char *toend, register const char *from, register const char *fromend, register int delim, I32 *retlen)
{
register I32 tolen;
for (tolen = 0; from < fromend; from++, tolen++) {
if (to < toend)
*to = '\0';
*retlen = tolen;
- return from;
+ return (char *)from;
}
/* return ptr to little string in big string, NULL if not found */
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;
+ register const I32 first = *little;
register const char *littleend = lend;
if (!first && little >= littleend)
{
register const char *bigbeg;
register const char *s, *x;
- register I32 first = *little;
+ register const I32 first = *little;
register const char *littleend = lend;
if (!first && little >= littleend)
I32 rarest = 0;
U32 frequency = 256;
- if (flags & FBMcf_TAIL)
+ if (flags & FBMcf_TAIL) {
+ MAGIC *mg = SvUTF8(sv) && SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_utf8) : NULL;
sv_catpvn(sv, "\n", 1); /* Taken into account in fbm_instr() */
+ if (mg && mg->mg_len >= 0)
+ mg->mg_len++;
+ }
s = (U8*)SvPV_force(sv, len);
(void)SvUPGRADE(sv, SVt_PVBM);
if (len == 0) /* TAIL might be on a zero-length string. */
STRLEN l;
register unsigned char *little = (unsigned char *)SvPV(littlestr,l);
register STRLEN littlelen = l;
- register I32 multiline = flags & FBMrf_MULTILINE;
+ register const I32 multiline = flags & FBMrf_MULTILINE;
if ((STRLEN)(bigend - big) < littlelen) {
if ( SvTAIL(littlestr)
}
{ /* Do actual FBM. */
- register unsigned char *table = little + littlelen + FBM_TABLE_OFFSET;
+ register const unsigned char *table = little + littlelen + FBM_TABLE_OFFSET;
register unsigned char *oldlittle;
if (littlelen > (STRLEN)(bigend - big))
I32
Perl_ibcmp(pTHX_ const char *s1, const char *s2, register I32 len)
{
- register U8 *a = (U8 *)s1;
- register U8 *b = (U8 *)s2;
+ register const U8 *a = (const U8 *)s1;
+ register const U8 *b = (const U8 *)s2;
while (len--) {
if (*a != *b && *a != PL_fold[*b])
return 1;
I32
Perl_ibcmp_locale(pTHX_ const char *s1, const char *s2, register I32 len)
{
- register U8 *a = (U8 *)s1;
- register U8 *b = (U8 *)s2;
+ dVAR;
+ register const U8 *a = (const U8 *)s1;
+ register const U8 *b = (const U8 *)s2;
while (len--) {
if (*a != *b && *a != PL_fold_locale[*b])
return 1;
char *
Perl_savepv(pTHX_ const char *pv)
{
- register char *newaddr = Nullch;
- if (pv) {
- New(902,newaddr,strlen(pv)+1,char);
- (void)strcpy(newaddr,pv);
- }
- return newaddr;
+ register char *newaddr;
+#ifdef PERL_MALLOC_WRAP
+ STRLEN pvlen;
+#endif
+ if (!pv)
+ return Nullch;
+
+#ifdef PERL_MALLOC_WRAP
+ pvlen = strlen(pv)+1;
+ New(902,newaddr,pvlen,char);
+#else
+ New(902,newaddr,strlen(pv)+1,char);
+#endif
+ return strcpy(newaddr,pv);
}
/* same thing but with a known length */
New(903,newaddr,len+1,char);
/* Give a meaning to NULL pointer mainly for the use in sv_magic() */
if (pv) {
- Copy(pv,newaddr,len,char); /* might not be null terminated */
- newaddr[len] = '\0'; /* is now */
+ /* might not be null terminated */
+ newaddr[len] = '\0';
+ return (char *) CopyD(pv,newaddr,len,char);
}
else {
- Zero(newaddr,len+1,char);
+ return (char *) ZeroD(newaddr,len+1,char);
}
- return newaddr;
}
/*
char *
Perl_savesharedpv(pTHX_ const char *pv)
{
- register char *newaddr = Nullch;
- if (pv) {
- newaddr = (char*)PerlMemShared_malloc(strlen(pv)+1);
- (void)strcpy(newaddr,pv);
+ register char *newaddr;
+ if (!pv)
+ return Nullch;
+
+ newaddr = (char*)PerlMemShared_malloc(strlen(pv)+1);
+ if (!newaddr) {
+ PerlLIO_write(PerlIO_fileno(Perl_error_log),
+ PL_no_mem, strlen(PL_no_mem));
+ my_exit(1);
}
- return newaddr;
+ return strcpy(newaddr,pv);
}
+/*
+=for apidoc savesvpv
+
+A version of C<savepv()>/C<savepvn()> which gets the string to duplicate from
+the passed in SV using C<SvPV()>
+
+=cut
+*/
+
+char *
+Perl_savesvpv(pTHX_ SV *sv)
+{
+ STRLEN len;
+ const char *pv = SvPV(sv, len);
+ register char *newaddr;
+
+ ++len;
+ New(903,newaddr,len,char);
+ return (char *) CopyD(pv,newaddr,len,char);
+}
/* the SV for Perl_form() and mess() is not kept in an arena */
Perl_vmess(pTHX_ const char *pat, va_list *args)
{
SV *sv = mess_alloc();
- static char dgd[] = " during global destruction.\n";
- COP *cop;
+ static const 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') {
* from the sibling of PL_curcop.
*/
- cop = closest_cop(PL_curcop, PL_curcop->op_sibling);
+ const COP *cop = closest_cop(PL_curcop, PL_curcop->op_sibling);
if (!cop) cop = PL_curcop;
if (CopLINE(cop))
Perl_sv_catpvf(aTHX_ sv, " at %s line %"IVdf,
OutCopFILE(cop), (IV)CopLINE(cop));
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');
+ const bool line_mode = (RsSIMPLE(PL_rs) &&
+ SvCUR(PL_rs) == 1 && *SvPVX_const(PL_rs) == '\n');
Perl_sv_catpvf(aTHX_ sv, ", <%s> %s %"IVdf,
PL_last_in_gv == PL_argvgv ?
"" : GvNAME(PL_last_in_gv),
return sv;
}
-OP *
-Perl_vdie(pTHX_ const char* pat, va_list *args)
+void
+Perl_write_to_stderr(pTHX_ const char* message, int msglen)
{
- char *message;
- int was_in_eval = PL_in_eval;
- HV *stash;
- GV *gv;
- CV *cv;
- SV *msv;
- STRLEN msglen;
+ dVAR;
+ IO *io;
+ MAGIC *mg;
- DEBUG_S(PerlIO_printf(Perl_debug_log,
- "%p: die: curstack = %p, mainstack = %p\n",
- thr, PL_curstack, PL_mainstack));
+ if (PL_stderrgv && SvREFCNT(PL_stderrgv)
+ && (io = GvIO(PL_stderrgv))
+ && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
+ {
+ dSP;
+ ENTER;
+ SAVETMPS;
+
+ save_re_context();
+ SAVESPTR(PL_stderrgv);
+ PL_stderrgv = Nullgv;
+
+ PUSHSTACKi(PERLSI_MAGIC);
+
+ PUSHMARK(SP);
+ EXTEND(SP,2);
+ PUSHs(SvTIED_obj((SV*)io, mg));
+ PUSHs(sv_2mortal(newSVpvn(message, msglen)));
+ PUTBACK;
+ call_method("PRINT", G_SCALAR);
+
+ POPSTACK;
+ FREETMPS;
+ LEAVE;
+ }
+ else {
+#ifdef USE_SFIO
+ /* SFIO can really mess with your errno */
+ int e = errno;
+#endif
+ PerlIO *serr = Perl_error_log;
+
+ PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
+ (void)PerlIO_flush(serr);
+#ifdef USE_SFIO
+ errno = e;
+#endif
+ }
+}
+
+/* Common code used by vcroak, vdie and vwarner */
+
+void S_vdie_common(pTHX_ const char *message, STRLEN msglen, I32 utf8);
+
+STATIC char *
+S_vdie_croak_common(pTHX_ const char* pat, va_list* args, STRLEN* msglen,
+ I32* utf8)
+{
+ dVAR;
+ char *message;
if (pat) {
- msv = vmess(pat, args);
+ SV *msv = vmess(pat, args);
if (PL_errors && SvCUR(PL_errors)) {
sv_catsv(PL_errors, msv);
- message = SvPV(PL_errors, msglen);
+ message = SvPV(PL_errors, *msglen);
SvCUR_set(PL_errors, 0);
}
else
- message = SvPV(msv,msglen);
+ message = SvPV(msv,*msglen);
+ *utf8 = SvUTF8(msv);
}
else {
message = Nullch;
- msglen = 0;
}
DEBUG_S(PerlIO_printf(Perl_debug_log,
- "%p: die: message = %s\ndiehook = %p\n",
+ "%p: die/croak: message = %s\ndiehook = %p\n",
thr, message, PL_diehook));
if (PL_diehook) {
- /* sv_2cv might call Perl_croak() */
- SV *olddiehook = PL_diehook;
- ENTER;
- SAVESPTR(PL_diehook);
- PL_diehook = Nullsv;
- cv = sv_2cv(olddiehook, &stash, &gv, 0);
- LEAVE;
- if (cv && !CvDEPTH(cv) && (CvROOT(cv) || CvXSUB(cv))) {
- dSP;
- SV *msg;
+ S_vdie_common(aTHX_ message, *msglen, *utf8);
+ }
+ return message;
+}
- ENTER;
- save_re_context();
- if (message) {
- msg = newSVpvn(message, msglen);
- SvREADONLY_on(msg);
- SAVEFREESV(msg);
- }
- else {
- msg = ERRSV;
- }
+void
+S_vdie_common(pTHX_ const char *message, STRLEN msglen, I32 utf8)
+{
+ HV *stash;
+ GV *gv;
+ CV *cv;
+ /* sv_2cv might call Perl_croak() */
+ SV *olddiehook = PL_diehook;
+
+ assert(PL_diehook);
+ ENTER;
+ SAVESPTR(PL_diehook);
+ PL_diehook = Nullsv;
+ cv = sv_2cv(olddiehook, &stash, &gv, 0);
+ LEAVE;
+ if (cv && !CvDEPTH(cv) && (CvROOT(cv) || CvXSUB(cv))) {
+ dSP;
+ SV *msg;
- PUSHSTACKi(PERLSI_DIEHOOK);
- PUSHMARK(SP);
- XPUSHs(msg);
- PUTBACK;
- call_sv((SV*)cv, G_DISCARD);
- POPSTACK;
- LEAVE;
+ ENTER;
+ save_re_context();
+ if (message) {
+ msg = newSVpvn(message, msglen);
+ SvFLAGS(msg) |= utf8;
+ SvREADONLY_on(msg);
+ SAVEFREESV(msg);
+ }
+ else {
+ msg = ERRSV;
}
+
+ PUSHSTACKi(PERLSI_DIEHOOK);
+ PUSHMARK(SP);
+ XPUSHs(msg);
+ PUTBACK;
+ call_sv((SV*)cv, G_DISCARD);
+ POPSTACK;
+ LEAVE;
}
+}
+
+OP *
+Perl_vdie(pTHX_ const char* pat, va_list *args)
+{
+ const char *message;
+ const int was_in_eval = PL_in_eval;
+ STRLEN msglen;
+ I32 utf8 = 0;
+
+ DEBUG_S(PerlIO_printf(Perl_debug_log,
+ "%p: die: curstack = %p, mainstack = %p\n",
+ thr, PL_curstack, PL_mainstack));
+
+ message = S_vdie_croak_common(aTHX_ pat, args, &msglen, &utf8);
PL_restartop = die_where(message, msglen);
+ SvFLAGS(ERRSV) |= utf8;
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));
void
Perl_vcroak(pTHX_ const char* pat, va_list *args)
{
- char *message;
- HV *stash;
- GV *gv;
- CV *cv;
- SV *msv;
+ const char *message;
STRLEN msglen;
+ I32 utf8 = 0;
- 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 Perl_croak() */
- SV *olddiehook = PL_diehook;
- ENTER;
- SAVESPTR(PL_diehook);
- PL_diehook = Nullsv;
- cv = sv_2cv(olddiehook, &stash, &gv, 0);
- LEAVE;
- if (cv && !CvDEPTH(cv) && (CvROOT(cv) || CvXSUB(cv))) {
- dSP;
- SV *msg;
+ message = S_vdie_croak_common(aTHX_ pat, args, &msglen, &utf8);
- ENTER;
- 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;
- call_sv((SV*)cv, G_DISCARD);
- POPSTACK;
- LEAVE;
- }
- }
if (PL_in_eval) {
PL_restartop = die_where(message, msglen);
+ SvFLAGS(ERRSV) |= utf8;
JMPENV_JUMP(3);
}
else if (!message)
message = SvPVx(ERRSV, msglen);
- {
-#ifdef USE_SFIO
- /* SFIO can really mess with your errno */
- int e = errno;
-#endif
- PerlIO *serr = Perl_error_log;
-
- PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
- (void)PerlIO_flush(serr);
-#ifdef USE_SFIO
- errno = e;
-#endif
- }
+ write_to_stderr(message, msglen);
my_failure_exit();
}
=for apidoc croak
This is the XSUB-writer's interface to Perl's C<die> function.
-Normally use this function the same way you use the C C<printf>
-function. See C<warn>.
+Normally call this function the same way you call the C C<printf>
+function. Calling C<croak> returns control directly to Perl,
+sidestepping the normal C order of execution. See C<warn>.
If you want to throw an exception object, assign the object to
C<$@> and then pass C<Nullch> to croak():
void
Perl_vwarn(pTHX_ const char* pat, va_list *args)
{
+ dVAR;
char *message;
HV *stash;
GV *gv;
CV *cv;
SV *msv;
STRLEN msglen;
- IO *io;
- MAGIC *mg;
+ I32 utf8 = 0;
msv = vmess(pat, args);
+ utf8 = SvUTF8(msv);
message = SvPV(msv, msglen);
if (PL_warnhook) {
ENTER;
save_re_context();
msg = newSVpvn(message, msglen);
+ SvFLAGS(msg) |= utf8;
SvREADONLY_on(msg);
SAVEFREESV(msg);
}
}
- /* if STDERR is tied, use it instead */
- if (PL_stderrgv && (io = GvIOp(PL_stderrgv))
- && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) {
- dSP; ENTER;
- PUSHMARK(SP);
- XPUSHs(SvTIED_obj((SV*)io, mg));
- XPUSHs(sv_2mortal(newSVpvn(message, msglen)));
- PUTBACK;
- call_method("PRINT", G_SCALAR);
- LEAVE;
- return;
- }
-
- {
- PerlIO *serr = Perl_error_log;
-
- PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
- (void)PerlIO_flush(serr);
- }
+ write_to_stderr(message, msglen);
}
#if defined(PERL_IMPLICIT_CONTEXT)
/*
=for apidoc warn
-This is the XSUB-writer's interface to Perl's C<warn> function. Use this
-function the same way you use the C C<printf> function. See
-C<croak>.
+This is the XSUB-writer's interface to Perl's C<warn> function. Call this
+function the same way you call the C C<printf> function. See C<croak>.
=cut
*/
void
Perl_warner_nocontext(U32 err, const char *pat, ...)
{
- dTHX;
+ dTHX;
va_list args;
va_start(args, pat);
vwarner(err, pat, &args);
void
Perl_vwarner(pTHX_ U32 err, const char* pat, va_list* args)
{
- char *message;
- HV *stash;
- GV *gv;
- CV *cv;
- SV *msv;
- STRLEN msglen;
-
- msv = vmess(pat, args);
- message = SvPV(msv, msglen);
-
+ dVAR;
if (ckDEAD(err)) {
+ SV * const msv = vmess(pat, args);
+ STRLEN msglen;
+ const char *message = SvPV(msv, msglen);
+ const I32 utf8 = SvUTF8(msv);
+
if (PL_diehook) {
- /* sv_2cv might call Perl_croak() */
- SV *olddiehook = PL_diehook;
- ENTER;
- SAVESPTR(PL_diehook);
- PL_diehook = Nullsv;
- cv = sv_2cv(olddiehook, &stash, &gv, 0);
- 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_DIEHOOK);
- PUSHMARK(sp);
- XPUSHs(msg);
- PUTBACK;
- call_sv((SV*)cv, G_DISCARD);
- POPSTACK;
- LEAVE;
- }
+ assert(message);
+ S_vdie_common(aTHX_ message, msglen, utf8);
}
if (PL_in_eval) {
PL_restartop = die_where(message, msglen);
+ SvFLAGS(ERRSV) |= utf8;
JMPENV_JUMP(3);
}
- {
- PerlIO *serr = Perl_error_log;
- PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
- (void)PerlIO_flush(serr);
- }
+ write_to_stderr(message, msglen);
my_failure_exit();
}
else {
- if (PL_warnhook) {
- /* 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;
- 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;
- call_sv((SV*)cv, G_DISCARD);
- POPSTACK;
- LEAVE;
- return;
- }
- }
- {
- PerlIO *serr = Perl_error_log;
- PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
- (void)PerlIO_flush(serr);
- }
+ Perl_vwarn(aTHX_ pat, args);
}
}
/* VMS' my_setenv() is in vms.c */
#if !defined(WIN32) && !defined(NETWARE)
void
-Perl_my_setenv(pTHX_ char *nam, char *val)
+Perl_my_setenv(pTHX_ const char *nam, const char *val)
{
+ dVAR;
#ifdef USE_ITHREADS
/* only parent thread can modify process environment */
if (PL_curinterp == aTHX)
#endif
{
#ifndef PERL_USE_SAFE_PUTENV
+ if (!PL_use_safe_putenv) {
/* most putenv()s leak, so we manipulate environ directly */
register I32 i=setenv_getix(nam); /* where does it go? */
int nlen, vlen;
for (max = i; environ[max]; max++) ;
tmpenv = (char**)safesysmalloc((max+2) * sizeof(char*));
for (j=0; j<max; j++) { /* copy environment */
- int len = strlen(environ[j]);
+ const int len = strlen(environ[j]);
tmpenv[j] = (char*)safesysmalloc((len+1)*sizeof(char));
Copy(environ[j], tmpenv[j], len+1, char);
}
environ[i] = (char*)safesysmalloc((nlen+vlen+2) * sizeof(char));
/* all that work just for this */
my_setenv_format(environ[i], nam, nlen, val, vlen);
-
-#else /* PERL_USE_SAFE_PUTENV */
-# if defined(__CYGWIN__) || defined( EPOC)
+ } else {
+# endif
+# if defined(__CYGWIN__) || defined(EPOC) || defined(SYMBIAN)
setenv(nam, val, 1);
# else
char *new_env;
my_setenv_format(new_env, nam, nlen, val, vlen);
(void)putenv(new_env);
# endif /* __CYGWIN__ */
-#endif /* PERL_USE_SAFE_PUTENV */
+#ifndef PERL_USE_SAFE_PUTENV
+ }
+#endif
}
}
#else /* WIN32 || NETWARE */
void
-Perl_my_setenv(pTHX_ char *nam,char *val)
+Perl_my_setenv(pTHX_ const char *nam, const char *val)
{
+ dVAR;
register char *envstr;
- int nlen = strlen(nam), vlen;
+ const int nlen = strlen(nam);
+ int vlen;
if (!val) {
val = "";
#endif /* WIN32 || NETWARE */
+#ifndef PERL_MICRO
I32
-Perl_setenv_getix(pTHX_ char *nam)
+Perl_setenv_getix(pTHX_ const char *nam)
{
register I32 i, len = strlen(nam);
} /* potential SEGV's */
return i;
}
+#endif /* !PERL_MICRO */
#endif /* !VMS && !EPOC*/
I32
Perl_my_memcmp(const char *s1, const char *s2, register I32 len)
{
- register U8 *a = (U8 *)s1;
- register U8 *b = (U8 *)s2;
+ register const U8 *a = (const U8 *)s1;
+ register const U8 *b = (const U8 *)s2;
register I32 tmp;
while (len--) {
- if (tmp = *a++ - *b++)
+ if ((tmp = *a++ - *b++))
return tmp;
}
return 0;
* -DWS
*/
-#define HTOV(name,type) \
+#define HTOLE(name,type) \
+ type \
+ name (register type n) \
+ { \
+ union { \
+ type value; \
+ char c[sizeof(type)]; \
+ } u; \
+ register I32 i; \
+ register I32 s = 0; \
+ for (i = 0; i < sizeof(u.c); i++, s += 8) { \
+ u.c[i] = (n >> s) & 0xFF; \
+ } \
+ return u.value; \
+ }
+
+#define LETOH(name,type) \
+ type \
+ name (register type n) \
+ { \
+ union { \
+ type value; \
+ char c[sizeof(type)]; \
+ } u; \
+ register I32 i; \
+ register I32 s = 0; \
+ u.value = n; \
+ n = 0; \
+ for (i = 0; i < sizeof(u.c); i++, s += 8) { \
+ n |= ((type)(u.c[i] & 0xFF)) << s; \
+ } \
+ return n; \
+ }
+
+/*
+ * Big-endian byte order functions.
+ */
+
+#define HTOBE(name,type) \
type \
name (register type n) \
{ \
char c[sizeof(type)]; \
} u; \
register I32 i; \
- register I32 s; \
- for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
+ register I32 s = 8*(sizeof(u.c)-1); \
+ for (i = 0; i < sizeof(u.c); i++, s -= 8) { \
u.c[i] = (n >> s) & 0xFF; \
} \
return u.value; \
}
-#define VTOH(name,type) \
+#define BETOH(name,type) \
type \
name (register type n) \
{ \
char c[sizeof(type)]; \
} u; \
register I32 i; \
- register I32 s; \
+ register I32 s = 8*(sizeof(u.c)-1); \
u.value = n; \
n = 0; \
- for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
- n += (u.c[i] & 0xFF) << s; \
+ for (i = 0; i < sizeof(u.c); i++, s -= 8) { \
+ n |= ((type)(u.c[i] & 0xFF)) << s; \
} \
return n; \
}
+/*
+ * If we just can't do it...
+ */
+
+#define NOT_AVAIL(name,type) \
+ type \
+ name (register type n) \
+ { \
+ Perl_croak_nocontext(#name "() not available"); \
+ return n; /* not reached */ \
+ }
+
+
#if defined(HAS_HTOVS) && !defined(htovs)
-HTOV(htovs,short)
+HTOLE(htovs,short)
#endif
#if defined(HAS_HTOVL) && !defined(htovl)
-HTOV(htovl,long)
+HTOLE(htovl,long)
#endif
#if defined(HAS_VTOHS) && !defined(vtohs)
-VTOH(vtohs,short)
+LETOH(vtohs,short)
#endif
#if defined(HAS_VTOHL) && !defined(vtohl)
-VTOH(vtohl,long)
+LETOH(vtohl,long)
#endif
+#ifdef PERL_NEED_MY_HTOLE16
+# if U16SIZE == 2
+HTOLE(Perl_my_htole16,U16)
+# else
+NOT_AVAIL(Perl_my_htole16,U16)
+# endif
+#endif
+#ifdef PERL_NEED_MY_LETOH16
+# if U16SIZE == 2
+LETOH(Perl_my_letoh16,U16)
+# else
+NOT_AVAIL(Perl_my_letoh16,U16)
+# endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE16
+# if U16SIZE == 2
+HTOBE(Perl_my_htobe16,U16)
+# else
+NOT_AVAIL(Perl_my_htobe16,U16)
+# endif
+#endif
+#ifdef PERL_NEED_MY_BETOH16
+# if U16SIZE == 2
+BETOH(Perl_my_betoh16,U16)
+# else
+NOT_AVAIL(Perl_my_betoh16,U16)
+# endif
+#endif
+
+#ifdef PERL_NEED_MY_HTOLE32
+# if U32SIZE == 4
+HTOLE(Perl_my_htole32,U32)
+# else
+NOT_AVAIL(Perl_my_htole32,U32)
+# endif
+#endif
+#ifdef PERL_NEED_MY_LETOH32
+# if U32SIZE == 4
+LETOH(Perl_my_letoh32,U32)
+# else
+NOT_AVAIL(Perl_my_letoh32,U32)
+# endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE32
+# if U32SIZE == 4
+HTOBE(Perl_my_htobe32,U32)
+# else
+NOT_AVAIL(Perl_my_htobe32,U32)
+# endif
+#endif
+#ifdef PERL_NEED_MY_BETOH32
+# if U32SIZE == 4
+BETOH(Perl_my_betoh32,U32)
+# else
+NOT_AVAIL(Perl_my_betoh32,U32)
+# endif
+#endif
+
+#ifdef PERL_NEED_MY_HTOLE64
+# if U64SIZE == 8
+HTOLE(Perl_my_htole64,U64)
+# else
+NOT_AVAIL(Perl_my_htole64,U64)
+# endif
+#endif
+#ifdef PERL_NEED_MY_LETOH64
+# if U64SIZE == 8
+LETOH(Perl_my_letoh64,U64)
+# else
+NOT_AVAIL(Perl_my_letoh64,U64)
+# endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE64
+# if U64SIZE == 8
+HTOBE(Perl_my_htobe64,U64)
+# else
+NOT_AVAIL(Perl_my_htobe64,U64)
+# endif
+#endif
+#ifdef PERL_NEED_MY_BETOH64
+# if U64SIZE == 8
+BETOH(Perl_my_betoh64,U64)
+# else
+NOT_AVAIL(Perl_my_betoh64,U64)
+# endif
+#endif
+
+#ifdef PERL_NEED_MY_HTOLES
+HTOLE(Perl_my_htoles,short)
+#endif
+#ifdef PERL_NEED_MY_LETOHS
+LETOH(Perl_my_letohs,short)
+#endif
+#ifdef PERL_NEED_MY_HTOBES
+HTOBE(Perl_my_htobes,short)
+#endif
+#ifdef PERL_NEED_MY_BETOHS
+BETOH(Perl_my_betohs,short)
+#endif
+
+#ifdef PERL_NEED_MY_HTOLEI
+HTOLE(Perl_my_htolei,int)
+#endif
+#ifdef PERL_NEED_MY_LETOHI
+LETOH(Perl_my_letohi,int)
+#endif
+#ifdef PERL_NEED_MY_HTOBEI
+HTOBE(Perl_my_htobei,int)
+#endif
+#ifdef PERL_NEED_MY_BETOHI
+BETOH(Perl_my_betohi,int)
+#endif
+
+#ifdef PERL_NEED_MY_HTOLEL
+HTOLE(Perl_my_htolel,long)
+#endif
+#ifdef PERL_NEED_MY_LETOHL
+LETOH(Perl_my_letohl,long)
+#endif
+#ifdef PERL_NEED_MY_HTOBEL
+HTOBE(Perl_my_htobel,long)
+#endif
+#ifdef PERL_NEED_MY_BETOHL
+BETOH(Perl_my_betohl,long)
+#endif
+
+void
+Perl_my_swabn(void *ptr, int n)
+{
+ register char *s = (char *)ptr;
+ register char *e = s + (n-1);
+ register char tc;
+
+ for (n /= 2; n > 0; s++, e--, n--) {
+ tc = *s;
+ *s = *e;
+ *e = tc;
+ }
+}
+
PerlIO *
Perl_my_popen_list(pTHX_ char *mode, int n, SV **args)
{
sv = *av_fetch(PL_fdpid,p[This],TRUE);
UNLOCK_FDPID_MUTEX;
(void)SvUPGRADE(sv,SVt_IV);
- SvIVX(sv) = pid;
+ SvIV_set(sv, pid);
PL_forkprocess = pid;
/* If we managed to get status pipe check for exec fail */
if (did_pipes && pid > 0) {
register I32 This, that;
register Pid_t pid;
SV *sv;
- I32 doexec = strNE(cmd,"-");
+ I32 doexec = !(*cmd == '-' && cmd[1] == '\0');
I32 did_pipes = 0;
int pp[2];
#ifndef OS2
if (doexec) {
#if !defined(HAS_FCNTL) || !defined(F_SETFD)
- int fd;
-
#ifndef NOFILE
#define NOFILE 20
#endif
sv = *av_fetch(PL_fdpid,p[This],TRUE);
UNLOCK_FDPID_MUTEX;
(void)SvUPGRADE(sv,SVt_IV);
- SvIVX(sv) = pid;
+ SvIV_set(sv, pid);
PL_forkprocess = pid;
if (did_pipes && pid > 0) {
int errkid;
void
Perl_atfork_lock(void)
{
+ dVAR;
#if defined(USE_ITHREADS)
/* locks must be held in locking order (if any) */
# ifdef MYMALLOC
void
Perl_atfork_unlock(void)
{
+ dVAR;
#if defined(USE_ITHREADS)
/* locks must be released in same order as in atfork_lock() */
# ifdef MYMALLOC
PerlIO_printf(Perl_debug_log," %d",fd);
}
PerlIO_printf(Perl_debug_log,"\n");
+ return;
}
#endif /* DUMP_FDS */
Sighandler_t
Perl_rsignal(pTHX_ int signo, Sighandler_t handler)
{
+ dVAR;
struct sigaction act, oact;
#ifdef USE_ITHREADS
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_RESTART
-#if defined(PERL_OLD_SIGNALS)
- act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
+ if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG)
+ act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
#endif
-#endif
-#ifdef SA_NOCLDWAIT
+#if defined(SA_NOCLDWAIT) && !defined(BSDish) /* See [perl #18849] */
if (signo == SIGCHLD && handler == (Sighandler_t)SIG_IGN)
act.sa_flags |= SA_NOCLDWAIT;
#endif
int
Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save)
{
+ dVAR;
struct sigaction act;
#ifdef USE_ITHREADS
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_RESTART
-#if defined(PERL_OLD_SIGNALS)
- act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
-#endif
+ if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG)
+ act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
#endif
-#ifdef SA_NOCLDWAIT
+#if defined(SA_NOCLDWAIT) && !defined(BSDish) /* See [perl #18849] */
if (signo == SIGCHLD && handler == (Sighandler_t)SIG_IGN)
act.sa_flags |= SA_NOCLDWAIT;
#endif
int
Perl_rsignal_restore(pTHX_ int signo, Sigsave_t *save)
{
+ dVAR;
#ifdef USE_ITHREADS
/* only "parent" interpreter can diddle signals */
if (PL_curinterp != aTHX)
return PerlProc_signal(signo, handler);
}
-static int sig_trapped; /* XXX signals are process-wide anyway, so we
- ignore the implications of this for threading */
-
static
Signal_t
sig_trap(int signo)
{
- sig_trapped++;
+ dVAR;
+ PL_sig_trapped++;
}
Sighandler_t
Perl_rsignal_state(pTHX_ int signo)
{
+ dVAR;
Sighandler_t oldsig;
#if defined(USE_ITHREADS) && !defined(WIN32)
return SIG_ERR;
#endif
- sig_trapped = 0;
+ PL_sig_trapped = 0;
oldsig = PerlProc_signal(signo, sig_trap);
PerlProc_signal(signo, oldsig);
- if (sig_trapped)
+ if (PL_sig_trapped)
PerlProc_kill(PerlProc_getpid(), signo);
return oldsig;
}
I32
Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags)
{
- I32 result;
+ I32 result = 0;
if (!pid)
return -1;
#if !defined(HAS_WAITPID) && !defined(HAS_WAIT4) || defined(HAS_WAITPID_RUNTIME)
{
- SV *sv;
- SV** svp;
- char spid[TYPE_CHARS(int)];
+ char spid[TYPE_CHARS(IV)];
if (pid > 0) {
+ SV** svp;
sprintf(spid, "%"IVdf, (IV)pid);
svp = hv_fetch(PL_pidstatus,spid,strlen(spid),FALSE);
if (svp && *svp != &PL_sv_undef) {
hv_iterinit(PL_pidstatus);
if ((entry = hv_iternext(PL_pidstatus))) {
- SV *sv;
- char spid[TYPE_CHARS(int)];
+ SV *sv = hv_iterval(PL_pidstatus,entry);
pid = atoi(hv_iterkey(entry,(I32*)statusp));
- sv = hv_iterval(PL_pidstatus,entry);
*statusp = SvIVX(sv);
sprintf(spid, "%"IVdf, (IV)pid);
(void)hv_delete(PL_pidstatus,spid,strlen(spid),G_DISCARD);
goto finish;
#endif
#if !defined(HAS_WAITPID) && !defined(HAS_WAIT4) || defined(HAS_WAITPID_RUNTIME)
+#if defined(HAS_WAITPID) && defined(HAS_WAITPID_RUNTIME)
hard_way:
+#endif
{
if (flags)
Perl_croak(aTHX_ "Can't do waitpid with flags");
}
}
#endif
+#if defined(HAS_WAITPID) || defined(HAS_WAIT4)
finish:
+#endif
if (result < 0 && errno == EINTR) {
PERL_ASYNC_CHECK();
}
Perl_pidgone(pTHX_ Pid_t pid, int status)
{
register SV *sv;
- char spid[TYPE_CHARS(int)];
+ char spid[TYPE_CHARS(IV)];
sprintf(spid, "%"IVdf, (IV)pid);
sv = *hv_fetch(PL_pidstatus,spid,strlen(spid),TRUE);
(void)SvUPGRADE(sv,SVt_IV);
- SvIVX(sv) = status;
+ SvIV_set(sv, status);
return;
}
#ifndef HAS_RENAME
I32
-Perl_same_dirent(pTHX_ char *a, char *b)
+Perl_same_dirent(pTHX_ const char *a, const char *b)
{
char *fa = strrchr(a,'/');
char *fb = strrchr(b,'/');
sv_setpv(tmpsv, ".");
else
sv_setpvn(tmpsv, a, fa - a);
- if (PerlLIO_stat(SvPVX(tmpsv), &tmpstatbuf1) < 0)
+ if (PerlLIO_stat(SvPVX_const(tmpsv), &tmpstatbuf1) < 0)
return FALSE;
if (fb == b)
sv_setpv(tmpsv, ".");
else
sv_setpvn(tmpsv, b, fb - b);
- if (PerlLIO_stat(SvPVX(tmpsv), &tmpstatbuf2) < 0)
+ if (PerlLIO_stat(SvPVX_const(tmpsv), &tmpstatbuf2) < 0)
return FALSE;
return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
#endif /* !HAS_RENAME */
char*
-Perl_find_script(pTHX_ char *scriptname, bool dosearch, char **search_ext, I32 flags)
+Perl_find_script(pTHX_ const char *scriptname, bool dosearch, const char **search_ext, I32 flags)
{
- char *xfound = Nullch;
+ const char *xfound = Nullch;
char *xfailed = Nullch;
char tmpbuf[MAXPATHLEN];
register char *s;
#endif
/* additional extensions to try in each dir if scriptname not found */
#ifdef SEARCH_EXTS
- char *exts[] = { SEARCH_EXTS };
- char **ext = search_ext ? search_ext : exts;
+ const char *exts[] = { SEARCH_EXTS };
+ const char **ext = search_ext ? search_ext : exts;
int extidx = 0, i = 0;
- char *curext = Nullch;
+ const char *curext = Nullch;
#else
+ (void)search_ext;
# define MAX_EXT_LEN 0
#endif
if (strEQ(scriptname, "-"))
dosearch = 0;
if (dosearch) { /* Look in '.' first. */
- char *cur = scriptname;
+ const char *cur = scriptname;
#ifdef SEARCH_EXTS
if ((curext = strrchr(scriptname,'.'))) /* possible current ext */
while (ext[i])
void *
Perl_get_context(void)
{
+ dVAR;
#if defined(USE_ITHREADS)
# ifdef OLD_PTHREADS_API
pthread_addr_t t;
void
Perl_set_context(void *t)
{
+ dVAR;
#if defined(USE_ITHREADS)
# ifdef I_MACH_CTHREADS
cthread_set_data(cthread_self(), t);
#endif /* !PERL_GET_CONTEXT_DEFINED */
-#ifdef PERL_GLOBAL_STRUCT
+#if defined(PERL_GLOBAL_STRUCT) && !defined(PERL_GLOBAL_STRUCT_PRIVATE)
struct perl_vars *
Perl_GetVars(pTHX)
{
char **
Perl_get_op_names(pTHX)
{
- return PL_op_name;
+ return (char **)PL_op_name;
}
char **
Perl_get_op_descs(pTHX)
{
- return PL_op_desc;
+ return (char **)PL_op_desc;
}
-char *
+const char *
Perl_get_no_modify(pTHX)
{
- return (char*)PL_no_modify;
+ return PL_no_modify;
}
U32 *
Perl_get_opargs(pTHX)
{
- return PL_opargs;
+ return (U32 *)PL_opargs;
}
PPADDR_t*
Perl_get_ppaddr(pTHX)
{
+ dVAR;
return (PPADDR_t*)PL_ppaddr;
}
MGVTBL*
Perl_get_vtbl(pTHX_ int vtbl_id)
{
- MGVTBL* result = Null(MGVTBL*);
+ const MGVTBL* result = Null(MGVTBL*);
switch(vtbl_id) {
case want_vtbl_sv:
result = &PL_vtbl_utf8;
break;
}
- return result;
+ return (MGVTBL*)result;
}
I32
}
void
-Perl_report_evil_fh(pTHX_ GV *gv, IO *io, I32 op)
+Perl_report_evil_fh(pTHX_ const GV *gv, const IO *io, I32 op)
{
- char *func =
+ const char *func =
op == OP_READLINE ? "readline" : /* "<HANDLE>" 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)
+ const char *pars = OP_IS_FILETEST(op) ? "" : "()";
+ const char *type = OP_IS_SOCKET(op)
|| (gv && io && IoTYPE(io) == IoTYPE_SOCKET)
? "socket" : "filehandle";
- char *name = NULL;
+ const char *name = NULL;
if (gv && isGV(gv)) {
name = GvENAME(gv);
}
}
else {
- char *vile;
+ const char *vile;
I32 warn_type;
if (gv && io && IoTYPE(io) == IoTYPE_CLOSED) {
Perl_ebcdic_control(pTHX_ int ch)
{
if (ch > 'a') {
- char *ctlp;
+ const char *ctlp;
if (islower(ch))
ch = toupper(ch);
{
#ifdef HAS_TM_TM_ZONE
Time_t now;
+ struct tm* my_tm;
(void)time(&now);
- Copy(localtime(&now), ptm, 1, struct tm);
+ my_tm = localtime(&now);
+ if (my_tm)
+ Copy(my_tm, ptm, 1, struct tm);
#endif
}
}
char *
-Perl_my_strftime(pTHX_ char *fmt, int sec, int min, int hour, int mday, int mon, int year, int wday, int yday, int isdst)
+Perl_my_strftime(pTHX_ const char *fmt, int sec, int min, int hour, int mday, int mon, int year, int wday, int yday, int isdst)
{
#ifdef HAS_STRFTIME
char *buf;
return buf;
else {
/* Possibly buf overflowed - try again with a bigger buf */
- int fmtlen = strlen(fmt);
- int bufsize = fmtlen + buflen;
+ const int fmtlen = strlen(fmt);
+ const int bufsize = fmtlen + buflen;
New(0, buf, bufsize, char);
while (buf) {
buf = NULL;
break;
}
- bufsize *= 2;
- Renew(buf, bufsize, char);
+ Renew(buf, bufsize*2, char);
}
return buf;
}
#else
Perl_croak(aTHX_ "panic: no strftime");
+ return NULL;
#endif
}
* size from the heap if they are given a NULL buffer pointer.
* The problem is that this behaviour is not portable. */
if (getcwd(buf, sizeof(buf) - 1)) {
- STRLEN len = strlen(buf);
- sv_setpvn(sv, buf, len);
+ sv_setpvn(sv, buf, strlen(buf));
return TRUE;
}
else {
Stat_t statbuf;
int orig_cdev, orig_cino, cdev, cino, odev, oino, tdev, tino;
- int namelen, pathlen=0;
- DIR *dir;
+ int pathlen=0;
Direntry_t *dp;
(void)SvUPGRADE(sv, SVt_PV);
cino = orig_cino;
for (;;) {
+ DIR *dir;
odev = cdev;
oino = cino;
while ((dp = PerlDir_read(dir)) != NULL) {
#ifdef DIRNAMLEN
- namelen = dp->d_namlen;
+ const int namelen = dp->d_namlen;
#else
- namelen = strlen(dp->d_name);
+ const int namelen = strlen(dp->d_name);
#endif
/* skip . and .. */
if (SV_CWD_ISDOT(dp)) {
if (pathlen) {
/* shift down */
- Move(SvPVX(sv), SvPVX(sv) + namelen + 1, pathlen, char);
+ Move(SvPVX_const(sv), SvPVX(sv) + namelen + 1, pathlen, char);
}
/* prepend current directory to the front */
*SvEND(sv) = '\0';
SvPOK_only(sv);
- if (PerlDir_chdir(SvPVX(sv)) < 0) {
+ if (PerlDir_chdir(SvPVX_const(sv)) < 0) {
SV_CWD_RETURN_UNDEF;
}
}
}
/*
-=head1 SV Manipulation Functions
-
-=for apidoc scan_vstring
-
-Returns a pointer to the next character after the parsed
-vstring, as well as updating the passed in sv.
-
-Function must be called like
-
- sv = NEWSV(92,5);
- s = scan_vstring(s,sv);
-
-The sv should already be large enough to store the vstring
-passed in, for performance reasons.
-
-=cut
-*/
-
-char *
-Perl_scan_vstring(pTHX_ char *s, SV *sv)
-{
- char *pos = s;
- char *start = s;
- if (*pos == 'v') pos++; /* get past 'v' */
- while (isDIGIT(*pos) || *pos == '_')
- pos++;
- if (!isALPHA(*pos)) {
- UV rev;
- U8 tmpbuf[UTF8_MAXLEN+1];
- U8 *tmpend;
-
- if (*s == 'v') s++; /* get past 'v' */
-
- sv_setpvn(sv, "", 0);
-
- for (;;) {
- rev = 0;
- {
- /* this is atoi() that tolerates underscores */
- char *end = pos;
- UV mult = 1;
- while (--end >= s) {
- UV orev;
- if (*end == '_')
- continue;
- orev = rev;
- rev += (*end - '0') * mult;
- mult *= 10;
- if (orev > rev && ckWARN_d(WARN_OVERFLOW))
- Perl_warner(aTHX_ packWARN(WARN_OVERFLOW),
- "Integer overflow in decimal number");
- }
- }
-#ifdef EBCDIC
- if (rev > 0x7FFFFFFF)
- Perl_croak(aTHX "In EBCDIC the v-string components cannot exceed 2147483647");
-#endif
- /* Append native character for the rev point */
- tmpend = uvchr_to_utf8(tmpbuf, rev);
- sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
- if (!UNI_IS_INVARIANT(NATIVE_TO_UNI(rev)))
- SvUTF8_on(sv);
- if (*pos == '.' && isDIGIT(pos[1]))
- s = ++pos;
- else {
- s = pos;
- break;
- }
- while (isDIGIT(*pos) || *pos == '_')
- pos++;
- }
- SvPOK_on(sv);
- sv_magic(sv,NULL,PERL_MAGIC_vstring,(const char*)start, pos-start);
- SvRMAGICAL_on(sv);
- }
- return s;
-}
-
-/*
=for apidoc scan_version
Returns a pointer to the next character after the parsed
Function must be called with an already existing SV like
- sv = NEWSV(92,0);
- s = scan_version(s,sv);
+ sv = newSV(0);
+ s = scan_version(s,SV *sv, bool qv);
Performs some preprocessing to the string to ensure that
it has the correct characteristics of a version. Flags the
object if it contains an underscore (which denotes this
-is a beta version).
+is a alpha version). The boolean qv denotes that the version
+should be interpreted as if it had multiple decimals, even if
+it doesn't.
=cut
*/
char *
-Perl_scan_version(pTHX_ char *s, SV *rv)
+Perl_scan_version(pTHX_ const char *s, SV *rv, bool qv)
{
const char *start = s;
- char *pos = s;
+ const char *pos = s;
I32 saw_period = 0;
bool saw_under = 0;
SV* sv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */
(void)sv_upgrade(sv, SVt_PVAV); /* needs to be an AV type */
+ AvREAL_on((AV*)sv);
/* pre-scan the imput string to check for decimals */
while ( *pos == '.' || *pos == '_' || isDIGIT(*pos) )
}
pos = s;
- if (*pos == 'v') pos++; /* get past 'v' */
+ if (*pos == 'v') {
+ pos++; /* get past 'v' */
+ qv = 1; /* force quoted version processing */
+ }
while (isDIGIT(*pos))
pos++;
if (!isALPHA(*pos)) {
rev = 0;
{
/* this is atoi() that delimits on underscores */
- char *end = pos;
+ const char *end = pos;
I32 mult = 1;
I32 orev;
if ( s < pos && s > start && *(s-1) == '_' ) {
- mult *= -1; /* beta version */
+ mult *= -1; /* alpha version */
}
/* the following if() will only be true after the decimal
* point of a version originally created with a bare
* floating point number, i.e. not quoted in any way
*/
- if ( s > start+1 && saw_period == 1 && !saw_under ) {
- mult = 100;
+ if ( !qv && s > start+1 && saw_period == 1 ) {
+ mult *= 100;
while ( s < end ) {
orev = rev;
rev += (*s - '0') * mult;
mult /= 10;
- if ( abs(orev) > abs(rev) )
+ if ( PERL_ABS(orev) > PERL_ABS(rev) )
Perl_croak(aTHX_ "Integer overflow in version");
s++;
}
orev = rev;
rev += (*end - '0') * mult;
mult *= 10;
- if ( abs(orev) > abs(rev) )
+ if ( PERL_ABS(orev) > PERL_ABS(rev) )
Perl_croak(aTHX_ "Integer overflow in version");
}
}
break;
}
while ( isDIGIT(*pos) ) {
- if ( !saw_under && saw_period == 1 && pos-s == 3 )
+ if ( saw_period == 1 && pos-s == 3 )
break;
pos++;
}
}
}
- return s;
+ if ( qv ) { /* quoted versions always become full version objects */
+ I32 len = av_len((AV *)sv);
+ /* 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:
+ gcc version 3.3 20030304 (Apple Computer, Inc. build 1640)
+ for ( len = 2 - len; len > 0; len-- )
+ av_push((AV *)sv, newSViv(0));
+ */
+ len = 2 - len;
+ while (len-- > 0)
+ av_push((AV *)sv, newSViv(0));
+ }
+ return (char *)s;
}
/*
Perl_new_version(pTHX_ SV *ver)
{
SV *rv = newSV(0);
- char *version;
- if ( SvNOK(ver) ) /* may get too much accuracy */
+ if ( sv_derived_from(ver,"version") ) /* can just copy directly */
{
- char tbuf[64];
- sprintf(tbuf,"%.9"NVgf, SvNVX(ver));
- version = savepv(tbuf);
+ I32 key;
+ AV *av = (AV *)SvRV(ver);
+ SV* sv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */
+ (void)sv_upgrade(sv, SVt_PVAV); /* needs to be an AV type */
+ AvREAL_on((AV*)sv);
+ for ( key = 0; key <= av_len(av); key++ )
+ {
+ const I32 rev = SvIV(*av_fetch(av, key, FALSE));
+ av_push((AV *)sv, newSViv(rev));
+ }
+ return rv;
}
#ifdef SvVOK
- else if ( SvVOK(ver) ) { /* already a v-string */
+ if ( SvVOK(ver) ) { /* already a v-string */
+ char *version;
MAGIC* mg = mg_find(ver,PERL_MAGIC_vstring);
version = savepvn( (const char*)mg->mg_ptr,mg->mg_len );
+ sv_setpv(rv,version);
+ Safefree(version);
}
+ else {
#endif
- else /* must be a string or something like a string */
- {
- version = (char *)SvPV(ver,PL_na);
+ sv_setsv(rv,ver); /* make a duplicate */
+#ifdef SvVOK
}
- version = scan_version(version,rv);
+#endif
+ upg_version(rv);
return rv;
}
SV *
Perl_upg_version(pTHX_ SV *ver)
{
- char *version = savepvn(SvPVX(ver),SvCUR(ver));
+ char *version;
+ bool qv = 0;
+
+ if ( SvNOK(ver) ) /* may get too much accuracy */
+ {
+ char tbuf[64];
+ sprintf(tbuf,"%.9"NVgf, SvNVX(ver));
+ version = savepv(tbuf);
+ }
#ifdef SvVOK
- if ( SvVOK(ver) ) { /* already a v-string */
+ else if ( SvVOK(ver) ) { /* already a v-string */
MAGIC* mg = mg_find(ver,PERL_MAGIC_vstring);
version = savepvn( (const char*)mg->mg_ptr,mg->mg_len );
+ qv = 1;
}
#endif
- version = scan_version(version,ver);
+ else /* must be a string or something like a string */
+ {
+ version = savesvpv(ver);
+ }
+ (void)scan_version(version, ver, qv);
+ Safefree(version);
return ver;
}
Perl_vnumify(pTHX_ SV *vs)
{
I32 i, len, digit;
- SV *sv = NEWSV(92,0);
+ SV *sv = newSV(0);
if ( SvROK(vs) )
vs = SvRV(vs);
len = av_len((AV *)vs);
return sv;
}
digit = SvIVX(*av_fetch((AV *)vs, 0, 0));
- Perl_sv_setpvf(aTHX_ sv,"%d.",abs(digit));
- for ( i = 1 ; i <= len ; i++ )
+ Perl_sv_setpvf(aTHX_ sv,"%d.", (int)PERL_ABS(digit));
+ for ( i = 1 ; i < len ; i++ )
{
digit = SvIVX(*av_fetch((AV *)vs, i, 0));
- Perl_sv_catpvf(aTHX_ sv,"%03d",abs(digit));
+ Perl_sv_catpvf(aTHX_ sv,"%03d", (int)PERL_ABS(digit));
}
- if ( len == 0 )
+
+ if ( len > 0 )
+ {
+ digit = SvIVX(*av_fetch((AV *)vs, len, 0));
+ if ( (int)PERL_ABS(digit) != 0 || len == 1 )
+ {
+ if ( digit < 0 ) /* alpha version */
+ Perl_sv_catpv(aTHX_ sv,"_");
+ /* Don't display additional trailing zeros */
+ Perl_sv_catpvf(aTHX_ sv,"%03d", (int)PERL_ABS(digit));
+ }
+ }
+ else /* len == 0 */
+ {
Perl_sv_catpv(aTHX_ sv,"000");
- sv_setnv(sv, SvNV(sv));
+ }
return sv;
}
/*
-=for apidoc vstringify
+=for apidoc vnormal
Accepts a version object and returns the normalized string
representation. Call like:
- sv = vstringify(rv);
+ sv = vnormal(rv);
NOTE: you can pass either the object directly or the SV
contained within the RV.
*/
SV *
-Perl_vstringify(pTHX_ SV *vs)
+Perl_vnormal(pTHX_ SV *vs)
{
I32 i, len, digit;
- SV *sv = NEWSV(92,0);
+ SV *sv = newSV(0);
if ( SvROK(vs) )
vs = SvRV(vs);
len = av_len((AV *)vs);
else
Perl_sv_catpvf(aTHX_ sv,".%"IVdf,(IV)digit);
}
- if ( len == 0 )
- Perl_sv_catpv(aTHX_ sv,".0");
+
+ if ( len <= 2 ) { /* short version, must be at least three */
+ for ( len = 2 - len; len != 0; len-- )
+ Perl_sv_catpv(aTHX_ sv,".0");
+ }
+
return sv;
}
/*
+=for apidoc vstringify
+
+In order to maintain maximum compatibility with earlier versions
+of Perl, this function will return either the floating point
+notation or the multiple dotted notation, depending on whether
+the original version contained 1 or more dots, respectively
+
+=cut
+*/
+
+SV *
+Perl_vstringify(pTHX_ SV *vs)
+{
+ I32 len, digit;
+ if ( SvROK(vs) )
+ vs = SvRV(vs);
+ len = av_len((AV *)vs);
+ digit = SvIVX(*av_fetch((AV *)vs, len, 0));
+
+ if ( len < 2 || ( len == 2 && digit < 0 ) )
+ return vnumify(vs);
+ else
+ return vnormal(vs);
+}
+
+/*
=for apidoc vcmp
Version object aware cmp. Both operands must already have been
{
I32 left = SvIV(*av_fetch((AV *)lsv,i,0));
I32 right = SvIV(*av_fetch((AV *)rsv,i,0));
- bool lbeta = left < 0 ? 1 : 0;
- bool rbeta = right < 0 ? 1 : 0;
+ bool lalpha = left < 0 ? 1 : 0;
+ bool ralpha = right < 0 ? 1 : 0;
left = abs(left);
right = abs(right);
- if ( left < right || (left == right && lbeta && !rbeta) )
+ if ( left < right || (left == right && lalpha && !ralpha) )
retval = -1;
- if ( left > right || (left == right && rbeta && !lbeta) )
+ if ( left > right || (left == right && ralpha && !lalpha) )
retval = +1;
i++;
}
- if ( l != r && retval == 0 ) /* possible match except for trailing 0 */
+ if ( l != r && retval == 0 ) /* possible match except for trailing 0's */
{
- if ( !( l < r && r-l == 1 && SvIV(*av_fetch((AV *)rsv,r,0)) == 0 ) &&
- !( l-r == 1 && SvIV(*av_fetch((AV *)lsv,l,0)) == 0 ) )
+ if ( l < r )
{
- retval = l < r ? -1 : +1; /* not a match after all */
+ while ( i <= r && retval == 0 )
+ {
+ if ( SvIV(*av_fetch((AV *)rsv,i,0)) != 0 )
+ retval = -1; /* not a match after all */
+ i++;
+ }
+ }
+ else
+ {
+ while ( i <= l && retval == 0 )
+ {
+ if ( SvIV(*av_fetch((AV *)lsv,i,0)) != 0 )
+ retval = +1; /* not a match after all */
+ i++;
+ }
}
}
return retval;
errno = ECONNABORTED;
tidy_up_and_fail:
{
- int save_errno = errno;
+ const int save_errno = errno;
if (sockets[0] != -1)
PerlLIO_close(sockets[0]);
if (sockets[1] != -1)
return 0;
abort_tidy_up_and_fail:
- errno = ECONNABORTED; /* I hope this is portable and appropriate. */
+#ifdef ECONNABORTED
+ errno = ECONNABORTED; /* This would be the standard thing to do. */
+#else
+# ifdef ECONNREFUSED
+ errno = ECONNREFUSED; /* E.g. Symbian does not have ECONNABORTED. */
+# else
+ errno = ETIMEDOUT; /* Desperation time. */
+# endif
+#endif
tidy_up_and_fail:
{
int save_errno = errno;
void
Perl_sv_nosharing(pTHX_ SV *sv)
{
+ (void)sv;
}
/*
void
Perl_sv_nolocking(pTHX_ SV *sv)
{
+ (void)sv;
}
void
Perl_sv_nounlocking(pTHX_ SV *sv)
{
+ (void)sv;
}
U32
-Perl_parse_unicode_opts(pTHX_ char **popt)
+Perl_parse_unicode_opts(pTHX_ const char **popt)
{
- char *p = *popt;
+ const char *p = *popt;
U32 opt = 0;
if (*p) {
if (isDIGIT(*p)) {
opt = (U32) atoi(p);
while (isDIGIT(*p)) p++;
- if (*p)
+ if (*p && *p != '\n' && *p != '\r')
Perl_croak(aTHX_ "Unknown Unicode option letter '%c'", *p);
}
else {
case PERL_UNICODE_ARGV:
opt |= PERL_UNICODE_ARGV_FLAG; break;
default:
- Perl_croak(aTHX_
- "Unknown Unicode option letter '%c'", *p);
+ if (*p != '\n' && *p != '\r')
+ Perl_croak(aTHX_
+ "Unknown Unicode option letter '%c'", *p);
}
}
}
opt = PERL_UNICODE_DEFAULT_FLAGS;
if (opt & ~PERL_UNICODE_ALL_FLAGS)
- Perl_croak(aTHX_ "Unknown Unicode option value 0x%"IVdf,
+ Perl_croak(aTHX_ "Unknown Unicode option value %"UVuf,
(UV) (opt & ~PERL_UNICODE_ALL_FLAGS));
*popt = p;
return opt;
}
+U32
+Perl_seed(pTHX)
+{
+ /*
+ * This is really just a quick hack which grabs various garbage
+ * values. It really should be a real hash algorithm which
+ * spreads the effect of every input bit onto every output bit,
+ * if someone who knows about such things would bother to write it.
+ * Might be a good idea to add that function to CORE as well.
+ * No numbers below come from careful analysis or anything here,
+ * except they are primes and SEED_C1 > 1E6 to get a full-width
+ * value from (tv_sec * SEED_C1 + tv_usec). The multipliers should
+ * probably be bigger too.
+ */
+#if RANDBITS > 16
+# define SEED_C1 1000003
+#define SEED_C4 73819
+#else
+# define SEED_C1 25747
+#define SEED_C4 20639
+#endif
+#define SEED_C2 3
+#define SEED_C3 269
+#define SEED_C5 26107
+
+#ifndef PERL_NO_DEV_RANDOM
+ int fd;
+#endif
+ U32 u;
+#ifdef VMS
+# include <starlet.h>
+ /* when[] = (low 32 bits, high 32 bits) of time since epoch
+ * in 100-ns units, typically incremented ever 10 ms. */
+ unsigned int when[2];
+#else
+# ifdef HAS_GETTIMEOFDAY
+ struct timeval when;
+# else
+ Time_t when;
+# endif
+#endif
+
+/* This test is an escape hatch, this symbol isn't set by Configure. */
+#ifndef PERL_NO_DEV_RANDOM
+#ifndef PERL_RANDOM_DEVICE
+ /* /dev/random isn't used by default because reads from it will block
+ * if there isn't enough entropy available. You can compile with
+ * PERL_RANDOM_DEVICE to it if you'd prefer Perl to block until there
+ * is enough real entropy to fill the seed. */
+# define PERL_RANDOM_DEVICE "/dev/urandom"
+#endif
+ fd = PerlLIO_open(PERL_RANDOM_DEVICE, 0);
+ if (fd != -1) {
+ if (PerlLIO_read(fd, (void*)&u, sizeof u) != sizeof u)
+ u = 0;
+ PerlLIO_close(fd);
+ if (u)
+ return u;
+ }
+#endif
+
+#ifdef VMS
+ _ckvmssts(sys$gettim(when));
+ u = (U32)SEED_C1 * when[0] + (U32)SEED_C2 * when[1];
+#else
+# ifdef HAS_GETTIMEOFDAY
+ PerlProc_gettimeofday(&when,NULL);
+ u = (U32)SEED_C1 * when.tv_sec + (U32)SEED_C2 * when.tv_usec;
+# else
+ (void)time(&when);
+ u = (U32)SEED_C1 * when;
+# endif
+#endif
+ u += SEED_C3 * (U32)PerlProc_getpid();
+ u += SEED_C4 * (U32)PTR2UV(PL_stack_sp);
+#ifndef PLAN9 /* XXX Plan9 assembler chokes on this; fix needed */
+ u += SEED_C5 * (U32)PTR2UV(&when);
+#endif
+ return u;
+}
+
+UV
+Perl_get_hash_seed(pTHX)
+{
+ 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)((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;
+}
+
+#ifdef PERL_GLOBAL_STRUCT
+
+struct perl_vars *
+Perl_init_global_struct(pTHX)
+{
+ struct perl_vars *plvarsp = NULL;
+#ifdef PERL_GLOBAL_STRUCT
+# define PERL_GLOBAL_STRUCT_INIT
+# include "opcode.h" /* the ppaddr and check */
+ IV nppaddr = sizeof(Gppaddr)/sizeof(Perl_ppaddr_t);
+ IV ncheck = sizeof(Gcheck) /sizeof(Perl_check_t);
+# ifdef PERL_GLOBAL_STRUCT_PRIVATE
+ /* PerlMem_malloc() because can't use even safesysmalloc() this early. */
+ plvarsp = (struct perl_vars*)PerlMem_malloc(sizeof(struct perl_vars));
+ if (!plvarsp)
+ exit(1);
+# else
+ plvarsp = PL_VarsPtr;
+# endif /* PERL_GLOBAL_STRUCT_PRIVATE */
+# undef PERLVAR
+# undef PERLVARA
+# undef PERLVARI
+# undef PERLVARIC
+# undef PERLVARISC
+# define PERLVAR(var,type) /**/
+# define PERLVARA(var,n,type) /**/
+# define PERLVARI(var,type,init) plvarsp->var = init;
+# define PERLVARIC(var,type,init) plvarsp->var = init;
+# define PERLVARISC(var,init) Copy(init, plvarsp->var, sizeof(init), char);
+# include "perlvars.h"
+# undef PERLVAR
+# undef PERLVARA
+# undef PERLVARI
+# undef PERLVARIC
+# undef PERLVARISC
+# ifdef PERL_GLOBAL_STRUCT
+ plvarsp->Gppaddr = PerlMem_malloc(nppaddr * sizeof(Perl_ppaddr_t));
+ if (!plvarsp->Gppaddr)
+ exit(1);
+ plvarsp->Gcheck = PerlMem_malloc(ncheck * sizeof(Perl_check_t));
+ if (!plvarsp->Gcheck)
+ exit(1);
+ Copy(Gppaddr, plvarsp->Gppaddr, nppaddr, Perl_ppaddr_t);
+ Copy(Gcheck, plvarsp->Gcheck, ncheck, Perl_check_t);
+# endif
+# ifdef PERL_SET_VARS
+ PERL_SET_VARS(plvarsp);
+# endif
+# undef PERL_GLOBAL_STRUCT_INIT
+#endif
+ return plvarsp;
+}
+
+#endif /* PERL_GLOBAL_STRUCT */
+
+#ifdef PERL_GLOBAL_STRUCT
+
+void
+Perl_free_global_struct(pTHX_ struct perl_vars *plvarsp)
+{
+#ifdef PERL_GLOBAL_STRUCT
+# ifdef PERL_UNSET_VARS
+ PERL_UNSET_VARS(plvarsp);
+# endif
+ free(plvarsp->Gppaddr);
+ free(plvarsp->Gcheck);
+# ifdef PERL_GLOBAL_STRUCT_PRIVATE
+ free(plvarsp);
+# endif
+#endif
+}
+
+#endif /* PERL_GLOBAL_STRUCT */
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set ts=8 sts=4 sw=4 noet:
+ */