/* util.c
*
- * Copyright (c) 1991-1997, Larry Wall
+ * Copyright (c) 1991-1999, 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.
#endif
-#ifndef MYMALLOC
-
-/* paranoid version of malloc */
+/* paranoid version of system's malloc() */
/* NOTE: Do not call the next three routines directly. Use the macros
* in handy.h, so that we can easily redefine everything to do tracking of
*/
Malloc_t
-safemalloc(MEM_SIZE size)
+safesysmalloc(MEM_SIZE size)
{
Malloc_t ptr;
#ifdef HAS_64K_LIMIT
/*NOTREACHED*/
}
-/* paranoid version of realloc */
+/* paranoid version of system's realloc() */
Malloc_t
-saferealloc(Malloc_t where,MEM_SIZE size)
+safesysrealloc(Malloc_t where,MEM_SIZE size)
{
Malloc_t ptr;
#if !defined(STANDARD_C) && !defined(HAS_REALLOC_PROTOTYPE)
}
#endif /* HAS_64K_LIMIT */
if (!size) {
- safefree(where);
+ safesysfree(where);
return NULL;
}
if (!where)
- return safemalloc(size);
+ return safesysmalloc(size);
#ifdef DEBUGGING
if ((long)size < 0)
croak("panic: realloc");
/*NOTREACHED*/
}
-/* safe version of free */
+/* safe version of system's free() */
Free_t
-safefree(Malloc_t where)
+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++));
}
}
-/* safe version of calloc */
+/* safe version of system's calloc() */
Malloc_t
-safecalloc(MEM_SIZE count, MEM_SIZE size)
+safesyscalloc(MEM_SIZE count, MEM_SIZE size)
{
Malloc_t ptr;
/*NOTREACHED*/
}
-#endif /* !MYMALLOC */
-
#ifdef LEAKTEST
struct mem_test_strut {
/* This routine was donated by Corey Satten. */
char *
-instr(register char *big, register char *little)
+instr(register const char *big, register const char *little)
{
- register char *s, *x;
+ register const char *s, *x;
register I32 first;
if (!little)
- return big;
+ return (char*)big;
first = *little++;
if (!first)
- return big;
+ return (char*)big;
while (*big) {
if (*big++ != first)
continue;
}
}
if (!*s)
- return big-1;
+ return (char*)(big-1);
}
return Nullch;
}
/* same as instr but allow embedded nulls */
char *
-ninstr(register char *big, register char *bigend, char *little, char *lend)
+ninstr(register const char *big, register const char *bigend, const char *little, const char *lend)
{
- register char *s, *x;
+ register const char *s, *x;
register I32 first = *little;
- register char *littleend = lend;
+ register const char *littleend = lend;
if (!first && little >= littleend)
- return big;
+ return (char*)big;
if (bigend - big < littleend - little)
return Nullch;
bigend -= littleend - little++;
}
}
if (s >= littleend)
- return big-1;
+ return (char*)(big-1);
}
return Nullch;
}
/* reverse of the above--find last substring */
char *
-rninstr(register char *big, char *bigend, char *little, char *lend)
+rninstr(register const char *big, const char *bigend, const char *little, const char *lend)
{
- register char *bigbeg;
- register char *s, *x;
+ register const char *bigbeg;
+ register const char *s, *x;
register I32 first = *little;
- register char *littleend = lend;
+ register const char *littleend = lend;
if (!first && little >= littleend)
- return bigend;
+ return (char*)bigend;
bigbeg = big;
big = bigend - (littleend - little++);
while (big >= bigbeg) {
}
}
if (s >= littleend)
- return big+1;
+ return (char*)(big+1);
}
return Nullch;
}
* Set up for a new ctype locale.
*/
void
-perl_new_ctype(char *newctype)
+perl_new_ctype(const char *newctype)
{
#ifdef USE_LOCALE_CTYPE
* Set up for a new collation locale.
*/
void
-perl_new_collate(char *newcoll)
+perl_new_collate(const char *newcoll)
{
#ifdef USE_LOCALE_COLLATE
* Set up for a new numeric locale.
*/
void
-perl_new_numeric(char *newnum)
+perl_new_numeric(const char *newnum)
{
#ifdef USE_LOCALE_NUMERIC
#ifdef USE_LOCALE_NUMERIC
char *curnum = NULL;
#endif /* USE_LOCALE_NUMERIC */
+#ifdef __GLIBC__
+ char *language = PerlEnv_getenv("LANGUAGE");
+#endif
char *lc_all = PerlEnv_getenv("LC_ALL");
char *lang = PerlEnv_getenv("LANG");
bool setlocale_failure = FALSE;
PerlIO_printf(PerlIO_stderr(),
"perl: warning: Please check that your locale settings:\n");
+#ifdef __GLIBC__
+ PerlIO_printf(PerlIO_stderr(),
+ "\tLANGUAGE = %c%s%c,\n",
+ language ? '"' : '(',
+ language ? language : "unset",
+ language ? '"' : ')');
+#endif
+
PerlIO_printf(PerlIO_stderr(),
"\tLC_ALL = %c%s%c,\n",
lc_all ? '"' : '(',
#endif /* USE_LOCALE_COLLATE */
+#define FBM_TABLE_OFFSET 2 /* Number of bytes between EOS and table*/
+
+/* As a space optimization, we do not compile tables for strings of length
+ 0 and 1, and for strings of length 2 unless FBMcf_TAIL. These are
+ special-cased in fbm_instr().
+
+ If FBMcf_TAIL, the table is created as if the string has a trailing \n. */
+
void
fbm_compile(SV *sv, U32 flags /* not used yet */)
{
I32 rarest = 0;
U32 frequency = 256;
+ if (flags & FBMcf_TAIL)
+ sv_catpvn(sv, "\n", 1); /* Taken into account in fbm_instr() */
s = (U8*)SvPV_force(sv, len);
(void)SvUPGRADE(sv, SVt_PVBM);
- if (len > 255 || len == 0) /* TAIL might be on on a zero-length string. */
- return; /* can't have offsets that big */
+ if (len == 0) /* TAIL might be on on a zero-length string. */
+ return;
if (len > 2) {
- Sv_Grow(sv,len + 258);
- table = (unsigned char*)(SvPVX(sv) + len + 1);
- s = table - 2;
+ I32 mlen = len;
+ unsigned char *sb;
+
+ if (mlen > 255)
+ mlen = 255;
+ Sv_Grow(sv,len + 256 + FBM_TABLE_OFFSET);
+ table = (unsigned char*)(SvPVX(sv) + len + FBM_TABLE_OFFSET);
+ s = table - 1 - FBM_TABLE_OFFSET; /* Last char */
for (i = 0; i < 256; i++) {
- table[i] = len;
+ table[i] = mlen;
}
+ table[-1] = flags; /* Not used yet */
i = 0;
- while (s >= (unsigned char*)(SvPVX(sv)))
- {
- if (table[*s] == len)
- table[*s] = i;
- s--,i++;
- }
+ sb = s - mlen;
+ while (s >= sb) {
+ if (table[*s] == mlen)
+ table[*s] = i;
+ s--, i++;
+ }
}
sv_magic(sv, Nullsv, 'B', Nullch, 0); /* deep magic */
SvVALID_on(sv);
}
BmRARE(sv) = s[rarest];
BmPREVIOUS(sv) = rarest;
+ BmUSEFUL(sv) = 100; /* Initial value */
+ if (flags & FBMcf_TAIL)
+ SvTAIL_on(sv);
DEBUG_r(PerlIO_printf(Perl_debug_log, "rarest char %c at %d\n",BmRARE(sv),BmPREVIOUS(sv)));
}
+/* If SvTAIL(littlestr), it has a fake '\n' at end. */
+/* If SvTAIL is actually due to \Z or \z, this gives false positives
+ if multiline */
+
char *
fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr, U32 flags)
{
register unsigned char *s;
- register I32 tmp;
- register I32 littlelen;
- register unsigned char *little;
- register unsigned char *table;
- register unsigned char *olds;
- register unsigned char *oldlittle;
+ STRLEN l;
+ register unsigned char *little = (unsigned char *)SvPV(littlestr,l);
+ register STRLEN littlelen = l;
+ register I32 multiline = flags & FBMrf_MULTILINE;
+
+ if (bigend - big < littlelen) {
+ check_tail:
+ if ( SvTAIL(littlestr)
+ && (bigend - big == littlelen - 1)
+ && (littlelen == 1
+ || *big == *little && memEQ(big, little, littlelen - 1)))
+ return (char*)big;
+ return Nullch;
+ }
- if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) {
- STRLEN len;
- char *l = SvPV(littlestr,len);
- if (!len) {
- if (SvTAIL(littlestr)) { /* Can be only 0-len constant
- substr => we can ignore SvVALID */
- if (PL_multiline) {
- char *t = "\n";
- if ((s = (unsigned char*)ninstr((char*)big, (char*)bigend,
- t, t + len))) {
- return (char*)s;
+ if (littlelen <= 2) { /* Special-cased */
+ register char c;
+
+ if (littlelen == 1) {
+ if (SvTAIL(littlestr) && !multiline) { /* Anchor only! */
+ /* Know that bigend != big. */
+ if (bigend[-1] == '\n')
+ return (char *)(bigend - 1);
+ return (char *) bigend;
+ }
+ s = big;
+ while (s < bigend) {
+ if (*s == *little)
+ return (char *)s;
+ s++;
+ }
+ if (SvTAIL(littlestr))
+ return (char *) bigend;
+ return Nullch;
+ }
+ if (!littlelen)
+ return (char*)big; /* Cannot be SvTAIL! */
+
+ /* littlelen is 2 */
+ if (SvTAIL(littlestr) && !multiline) {
+ if (bigend[-1] == '\n' && bigend[-2] == *little)
+ return (char*)bigend - 2;
+ if (bigend[-1] == *little)
+ return (char*)bigend - 1;
+ return Nullch;
+ }
+ {
+ /* This should be better than FBM if c1 == c2, and almost
+ as good otherwise: maybe better since we do less indirection.
+ And we save a lot of memory by caching no table. */
+ register unsigned char c1 = little[0];
+ register unsigned char c2 = little[1];
+
+ s = big + 1;
+ bigend--;
+ if (c1 != c2) {
+ while (s <= bigend) {
+ if (s[0] == c2) {
+ if (s[-1] == c1)
+ return (char*)s - 1;
+ s += 2;
+ continue;
}
+ next_chars:
+ if (s[0] == c1) {
+ if (s == bigend)
+ goto check_1char_anchor;
+ if (s[1] == c2)
+ return (char*)s;
+ else {
+ s++;
+ goto next_chars;
+ }
+ }
+ else
+ s += 2;
+ }
+ goto check_1char_anchor;
+ }
+ /* Now c1 == c2 */
+ while (s <= bigend) {
+ if (s[0] == c1) {
+ if (s[-1] == c1)
+ return (char*)s - 1;
+ if (s == bigend)
+ goto check_1char_anchor;
+ if (s[1] == c1)
+ return (char*)s;
+ s += 3;
}
- if (bigend > big && bigend[-1] == '\n')
- return (char *)(bigend - 1);
else
- return (char *) bigend;
+ s += 2;
}
- return (char*)big;
}
- return ninstr((char*)big,(char*)bigend, l, l + len);
+ check_1char_anchor: /* One char and anchor! */
+ if (SvTAIL(littlestr) && (*bigend == *little))
+ return (char *)bigend; /* bigend is already decremented. */
+ return Nullch;
}
-
- littlelen = SvCUR(littlestr);
- if (SvTAIL(littlestr) && !PL_multiline) { /* tail anchored? */
- if (littlelen > bigend - big)
- return Nullch;
- little = (unsigned char*)SvPVX(littlestr);
+ if (SvTAIL(littlestr) && !multiline) { /* tail anchored? */
s = bigend - littlelen;
- if (s > big
+ if (s >= big
&& bigend[-1] == '\n'
- && s[-1] == *little && memEQ((char*)s - 1,(char*)little,littlelen))
- return (char*)s - 1; /* how sweet it is */
- else if (*s == *little && memEQ((char*)s,(char*)little,littlelen))
+ && *s == *little
+ /* Automatically of length > 2 */
+ && memEQ((char*)s + 1, (char*)little + 1, littlelen - 2))
return (char*)s; /* how sweet it is */
+ if (s[1] == *little && memEQ((char*)s + 2,(char*)little + 1,
+ littlelen - 2))
+ return (char*)s + 1; /* how sweet it is */
return Nullch;
}
- if (littlelen <= 2) {
- unsigned char c1 = (unsigned char)SvPVX(littlestr)[0];
- unsigned char c2 = (unsigned char)SvPVX(littlestr)[1];
- /* This may do extra comparisons if littlelen == 2, but this
- should be hidden in the noise since we do less indirection. */
-
- s = big;
- bigend -= littlelen;
- while (s <= bigend) {
- if (s[0] == c1
- && (littlelen == 1 || s[1] == c2)
- && (!SvTAIL(littlestr)
- || s == bigend
- || s[littlelen] == '\n')) /* Automatically multiline */
- {
+ if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) {
+ char *b = ninstr((char*)big,(char*)bigend,
+ (char*)little, (char*)little + littlelen);
+
+ if (!b && SvTAIL(littlestr)) { /* Automatically multiline! */
+ /* Chop \n from littlestr: */
+ s = bigend - littlelen + 1;
+ if (*s == *little && memEQ((char*)s + 1, (char*)little + 1,
+ littlelen - 2))
return (char*)s;
- }
- s++;
+ return Nullch;
}
- return Nullch;
+ return b;
}
- table = (unsigned char*)(SvPVX(littlestr) + littlelen + 1);
- if (--littlelen >= bigend - big)
- return Nullch;
- s = big + littlelen;
- oldlittle = little = table - 2;
- if (s < bigend) {
- top2:
- /*SUPPRESS 560*/
- if (tmp = table[*s]) {
+
+ { /* Do actual FBM. */
+ register unsigned char *table = little + littlelen + FBM_TABLE_OFFSET;
+ register unsigned char *oldlittle;
+
+ if (littlelen > bigend - big)
+ return Nullch;
+ --littlelen; /* Last char found by table lookup */
+
+ s = big + littlelen;
+ little += littlelen; /* last char */
+ oldlittle = little;
+ if (s < bigend) {
+ register I32 tmp;
+
+ top2:
+ /*SUPPRESS 560*/
+ if (tmp = table[*s]) {
#ifdef POINTERRIGOR
- if (bigend - s > tmp) {
+ if (bigend - s > tmp) {
+ s += tmp;
+ goto top2;
+ }
s += tmp;
- goto top2;
- }
#else
- if ((s += tmp) < bigend)
- goto top2;
-#endif
- return Nullch;
- }
- else {
- tmp = littlelen; /* less expensive than calling strncmp() */
- olds = s;
- while (tmp--) {
- if (*--s == *--little)
- continue;
- differ:
- s = olds + 1; /* here we pay the price for failure */
- little = oldlittle;
- if (s < bigend) /* fake up continue to outer loop */
+ if ((s += tmp) < bigend)
goto top2;
- return Nullch;
+#endif
+ goto check_end;
+ }
+ else { /* less expensive than calling strncmp() */
+ register unsigned char *olds = s;
+
+ tmp = littlelen;
+
+ while (tmp--) {
+ if (*--s == *--little)
+ continue;
+ differ:
+ s = olds + 1; /* here we pay the price for failure */
+ little = oldlittle;
+ if (s < bigend) /* fake up continue to outer loop */
+ goto top2;
+ goto check_end;
+ }
+ return (char *)s;
}
- if (SvTAIL(littlestr) /* automatically multiline */
- && olds + 1 != bigend
- && olds[1] != '\n')
- goto differ;
- return (char *)s;
}
+ check_end:
+ if ( s == bigend && (table[-1] & FBMcf_TAIL)
+ && memEQ(bigend - littlelen, oldlittle - littlelen, littlelen) )
+ return (char*)bigend - littlelen;
+ return Nullch;
}
- return Nullch;
}
/* start_shift, end_shift are positive quantities which give offsets
old_posp is the way of communication between consequent calls if
the next call needs to find the .
The initial *old_posp should be -1.
- Note that we do not take into account SvTAIL, so it may give wrong
- positives if _ALL flag is set.
+
+ Note that we take into account SvTAIL, so one can get extra
+ optimizations if _ALL flag is set.
*/
+/* If SvTAIL is actually due to \Z or \z, this gives false positives
+ if PL_multiline. In fact if !PL_multiline the autoritative answer
+ is not supported yet. */
+
char *
screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_posp, I32 last)
{
if (*old_posp == -1
? (pos = PL_screamfirst[BmRARE(littlestr)]) < 0
- : (((pos = *old_posp), pos += PL_screamnext[pos]) == 0))
+ : (((pos = *old_posp), pos += PL_screamnext[pos]) == 0)) {
+ cant_find:
+ if ( BmRARE(littlestr) == '\n'
+ && BmPREVIOUS(littlestr) == SvCUR(littlestr) - 1) {
+ little = (unsigned char *)(SvPVX(littlestr));
+ littleend = little + SvCUR(littlestr);
+ first = *little++;
+ goto check_tail;
+ }
return Nullch;
+ }
+
little = (unsigned char *)(SvPVX(littlestr));
littleend = little + SvCUR(littlestr);
first = *little++;
big = (unsigned char *)(SvPVX(bigstr));
/* The value of pos we can stop at: */
stop_pos = SvCUR(bigstr) - end_shift - (SvCUR(littlestr) - 1 - previous);
- if (previous + start_shift > stop_pos) return Nullch;
+ if (previous + start_shift > stop_pos) {
+ if (previous + start_shift == stop_pos + 1) /* A fake '\n'? */
+ goto check_tail;
+ return Nullch;
+ }
while (pos < previous + start_shift) {
if (!(pos += PL_screamnext[pos]))
- return Nullch;
+ goto cant_find;
}
#ifdef POINTERRIGOR
do {
found = 1;
}
} while ( pos += PL_screamnext[pos] );
- return (last && found) ? (char *)(big+(*old_posp)) : Nullch;
+ if (last && found)
+ return (char *)(big+(*old_posp));
#endif /* POINTERRIGOR */
+ check_tail:
+ if (!SvTAIL(littlestr) || (end_shift > 0))
+ return Nullch;
+ /* Ignore the trailing "\n". This code is not microoptimized */
+ big = (unsigned char *)(SvPVX(bigstr) + SvCUR(bigstr));
+ stop_pos = littleend - little; /* Actual littlestr len */
+ if (stop_pos == 0)
+ return (char*)big;
+ big -= stop_pos;
+ if (*big == first
+ && ((stop_pos == 1) || memEQ(big + 1, little, stop_pos - 1)))
+ return (char*)big;
+ return Nullch;
}
I32
-ibcmp(char *s1, char *s2, register I32 len)
+ibcmp(const char *s1, const char *s2, register I32 len)
{
register U8 *a = (U8 *)s1;
register U8 *b = (U8 *)s2;
}
I32
-ibcmp_locale(char *s1, char *s2, register I32 len)
+ibcmp_locale(const char *s1, const char *s2, register I32 len)
{
register U8 *a = (U8 *)s1;
register U8 *b = (U8 *)s2;
/* copy a string to a safe spot */
char *
-savepv(char *sv)
+savepv(const char *sv)
{
register char *newaddr;
/* same thing but with a known length */
char *
-savepvn(char *sv, register I32 len)
+savepvn(const char *sv, register I32 len)
{
register char *newaddr;
return SvPVX(sv);
}
-char *
+SV *
mess(const char *pat, va_list *args)
{
SV *sv = mess_alloc();
sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
if (!SvCUR(sv) || *(SvEND(sv) - 1) != '\n') {
dTHR;
- if (PL_dirty)
- sv_catpv(sv, dgd);
- else {
- if (PL_curcop->cop_line)
- sv_catpvf(sv, " at %_ line %ld",
- GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line);
- if (GvIO(PL_last_in_gv) && IoLINES(GvIOp(PL_last_in_gv))) {
- bool line_mode = (RsSIMPLE(PL_rs) &&
- SvLEN(PL_rs) == 1 && *SvPVX(PL_rs) == '\n');
- sv_catpvf(sv, ", <%s> %s %ld",
- PL_last_in_gv == PL_argvgv ? "" : GvNAME(PL_last_in_gv),
- line_mode ? "line" : "chunk",
- (long)IoLINES(GvIOp(PL_last_in_gv)));
- }
- sv_catpv(sv, ".\n");
+ if (PL_curcop->cop_line)
+ sv_catpvf(sv, " at %_ line %ld",
+ GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line);
+ if (GvIO(PL_last_in_gv) && IoLINES(GvIOp(PL_last_in_gv))) {
+ bool line_mode = (RsSIMPLE(PL_rs) &&
+ SvCUR(PL_rs) == 1 && *SvPVX(PL_rs) == '\n');
+ sv_catpvf(sv, ", <%s> %s %ld",
+ PL_last_in_gv == PL_argvgv ? "" : GvNAME(PL_last_in_gv),
+ line_mode ? "line" : "chunk",
+ (long)IoLINES(GvIOp(PL_last_in_gv)));
}
+ sv_catpv(sv, PL_dirty ? dgd : ".\n");
}
- return SvPVX(sv);
+ return sv;
}
OP *
HV *stash;
GV *gv;
CV *cv;
+ SV *msv;
+ STRLEN msglen;
DEBUG_S(PerlIO_printf(PerlIO_stderr(),
"%p: die: curstack = %p, mainstack = %p\n",
thr, PL_curstack, PL_mainstack));
va_start(args, pat);
- message = pat ? mess(pat, &args) : Nullch;
+ if (pat) {
+ msv = mess(pat, &args);
+ message = SvPV(msv,msglen);
+ }
+ else {
+ message = Nullch;
+ }
va_end(args);
DEBUG_S(PerlIO_printf(PerlIO_stderr(),
SV *msg;
ENTER;
- if(message) {
- msg = newSVpv(message, 0);
+ if (message) {
+ msg = newSVpvn(message, msglen);
SvREADONLY_on(msg);
SAVEFREESV(msg);
}
}
}
- PL_restartop = die_where(message);
+ PL_restartop = die_where(message, msglen);
DEBUG_S(PerlIO_printf(PerlIO_stderr(),
"%p: die: restartop = %p, was_in_eval = %d, top_env = %p\n",
thr, PL_restartop, was_in_eval, PL_top_env));
HV *stash;
GV *gv;
CV *cv;
+ SV *msv;
+ STRLEN msglen;
va_start(args, pat);
- message = mess(pat, &args);
+ msv = mess(pat, &args);
+ message = SvPV(msv,msglen);
va_end(args);
DEBUG_S(PerlIO_printf(PerlIO_stderr(), "croak: 0x%lx %s", (unsigned long) thr, message));
if (PL_diehook) {
SV *msg;
ENTER;
- msg = newSVpv(message, 0);
+ msg = newSVpvn(message, msglen);
SvREADONLY_on(msg);
SAVEFREESV(msg);
}
}
if (PL_in_eval) {
- PL_restartop = die_where(message);
+ PL_restartop = die_where(message, msglen);
JMPENV_JUMP(3);
}
- PerlIO_puts(PerlIO_stderr(),message);
- (void)PerlIO_flush(PerlIO_stderr());
+ {
+#ifdef USE_SFIO
+ /* SFIO can really mess with your errno */
+ int e = errno;
+#endif
+ PerlIO_write(PerlIO_stderr(), message, msglen);
+ (void)PerlIO_flush(PerlIO_stderr());
+#ifdef USE_SFIO
+ errno = e;
+#endif
+ }
my_failure_exit();
}
HV *stash;
GV *gv;
CV *cv;
+ SV *msv;
+ STRLEN msglen;
va_start(args, pat);
- message = mess(pat, &args);
+ msv = mess(pat, &args);
+ message = SvPV(msv, msglen);
va_end(args);
if (PL_warnhook) {
SV *msg;
ENTER;
- msg = newSVpv(message, 0);
+ msg = newSVpvn(message, msglen);
SvREADONLY_on(msg);
SAVEFREESV(msg);
return;
}
}
- PerlIO_puts(PerlIO_stderr(),message);
+ PerlIO_write(PerlIO_stderr(), message, msglen);
#ifdef LEAKTEST
DEBUG_L(*message == '!'
? (xstat(message[1]=='!'
HV *stash;
GV *gv;
CV *cv;
+ SV *msv;
+ STRLEN msglen;
va_start(args, pat);
- message = mess(pat, &args);
+ msv = mess(pat, &args);
+ message = SvPV(msv, msglen);
va_end(args);
if (ckDEAD(err)) {
SV *msg;
ENTER;
- msg = newSVpv(message, 0);
+ msg = newSVpvn(message, msglen);
SvREADONLY_on(msg);
SAVEFREESV(msg);
}
}
if (PL_in_eval) {
- PL_restartop = die_where(message);
+ PL_restartop = die_where(message, msglen);
JMPENV_JUMP(3);
}
- PerlIO_puts(PerlIO_stderr(),message);
+ PerlIO_write(PerlIO_stderr(), message, msglen);
(void)PerlIO_flush(PerlIO_stderr());
my_failure_exit();
SV *msg;
ENTER;
- msg = newSVpv(message, 0);
+ msg = newSVpvn(message, msglen);
SvREADONLY_on(msg);
SAVEFREESV(msg);
return;
}
}
- PerlIO_puts(PerlIO_stderr(),message);
+ PerlIO_write(PerlIO_stderr(), message, msglen);
#ifdef LEAKTEST
DEBUG_L(xstat());
#endif
}
#ifndef VMS /* VMS' my_setenv() is in VMS.c */
-#ifndef WIN32
+#if !defined(WIN32) && !defined(CYGWIN32)
void
my_setenv(char *nam, char *val)
{
+#ifndef PERL_USE_SAFE_PUTENV
+ /* most putenv()s leak, so we manipulate environ directly */
register I32 i=setenv_getix(nam); /* where does it go? */
if (environ == PL_origenviron) { /* need we copy environment? */
/*SUPPRESS 530*/
for (max = i; environ[max]; max++) ;
- New(901,tmpenv, max+2, char*);
- for (j=0; j<max; j++) /* copy environment */
- tmpenv[j] = savepv(environ[j]);
+ tmpenv = (char**)safesysmalloc((max+2) * sizeof(char*));
+ for (j=0; j<max; j++) { /* copy environment */
+ tmpenv[j] = (char*)safesysmalloc((strlen(environ[j])+1)*sizeof(char));
+ strcpy(tmpenv[j], environ[j]);
+ }
tmpenv[max] = Nullch;
environ = tmpenv; /* tell exec where it is now */
}
if (!val) {
- Safefree(environ[i]);
+ safesysfree(environ[i]);
while (environ[i]) {
environ[i] = environ[i+1];
i++;
return;
}
if (!environ[i]) { /* does not exist yet */
- Renew(environ, i+2, char*); /* just expand it a bit */
+ environ = (char**)safesysrealloc(environ, (i+2) * sizeof(char*));
environ[i+1] = Nullch; /* make sure it's null terminated */
}
else
- Safefree(environ[i]);
- New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
+ 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
strcpy(environ[i],nam); strupr(environ[i]);
(void)sprintf(environ[i] + strlen(nam),"=%s",val);
#endif /* MSDOS */
+
+#else /* PERL_USE_SAFE_PUTENV */
+ 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 /* PERL_USE_SAFE_PUTENV */
}
#else /* if WIN32 */
}
else
vallen = strlen(val);
- New(904, envstr, namlen + vallen + 3, char);
+ envstr = (char*)safesysmalloc((namlen + vallen + 3) * sizeof(char));
(void)sprintf(envstr,"%s=%s",nam,val);
(void)PerlEnv_putenv(envstr);
if (oldstr)
- Safefree(oldstr);
+ safesysfree(oldstr);
#ifdef _MSC_VER
- Safefree(envstr); /* MSVCRT leaks without this */
+ safesysfree(envstr); /* MSVCRT leaks without this */
#endif
#else /* !USE_WIN32_RTL_ENV */
- /* The sane way to deal with the environment.
- * Has these advantages over putenv() & co.:
- * * enables us to store a truly empty value in the
- * environment (like in UNIX).
- * * we don't have to deal with RTL globals, bugs and leaks.
- * * Much faster.
- * Why you may want to enable USE_WIN32_RTL_ENV:
- * * environ[] and RTL functions will not reflect changes,
- * which might be an issue if extensions want to access
- * the env. via RTL. This cuts both ways, since RTL will
- * not see changes made by extensions that call the Win32
- * functions directly, either.
- * GSAR 97-06-07
- */
- SetEnvironmentVariable(nam,val);
+ register char *envstr;
+ STRLEN len = strlen(nam) + 3;
+ if (!val) {
+ val = "";
+ }
+ len += strlen(val);
+ New(904, envstr, len, char);
+ (void)sprintf(envstr,"%s=%s",nam,val);
+ (void)PerlEnv_putenv(envstr);
+ Safefree(envstr);
#endif
}
#ifdef UNLINK_ALL_VERSIONS
I32
-unlnk(f) /* unlink all versions of a file */
-char *f;
+unlnk(char *f) /* unlink all versions of a file */
{
I32 i;
#if !defined(HAS_BCOPY) || !defined(HAS_SAFE_BCOPY)
char *
-my_bcopy(register char *from,register char *to,register I32 len)
+my_bcopy(register const char *from,register char *to,register I32 len)
{
char *retval = to;
#ifndef HAS_MEMSET
void *
-my_memset(loc,ch,len)
-register char *loc;
-register I32 ch;
-register I32 len;
+my_memset(register char *loc, register I32 ch, register I32 len)
{
char *retval = loc;
#if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
char *
-my_bzero(loc,len)
-register char *loc;
-register I32 len;
+my_bzero(register char *loc, register I32 len)
{
char *retval = loc;
#if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
I32
-my_memcmp(s1,s2,len)
-char *s1;
-char *s2;
-register I32 len;
+my_memcmp(const char *s1, const char *s2, register I32 len)
{
register U8 *a = (U8 *)s1;
register U8 *b = (U8 *)s2;
#else
int
#endif
-vsprintf(dest, pat, args)
-char *dest;
-const char *pat;
-char *args;
+vsprintf(char *dest, const char *pat, char *args)
{
FILE fakebuf;
#define HTOV(name,type) \
type \
- name (n) \
- register type n; \
+ name (register type n) \
{ \
union { \
type value; \
#define VTOH(name,type) \
type \
- name (n) \
- register type n; \
+ name (register type n) \
{ \
union { \
type value; \
register I32 pid;
SV *sv;
I32 doexec = strNE(cmd,"-");
+ I32 did_pipes = 0;
+ int pp[2];
+ PERL_FLUSHALL_FOR_CHILD;
#ifdef OS2
if (doexec) {
return my_syspopen(cmd,mode);
}
if (PerlProc_pipe(p) < 0)
return Nullfp;
+ if (doexec && PerlProc_pipe(pp) >= 0)
+ did_pipes = 1;
while ((pid = (doexec?vfork():fork())) < 0) {
if (errno != EAGAIN) {
PerlLIO_close(p[This]);
+ if (did_pipes) {
+ PerlLIO_close(pp[0]);
+ PerlLIO_close(pp[1]);
+ }
if (!doexec)
croak("Can't fork");
return Nullfp;
#define THIS that
#define THAT This
PerlLIO_close(p[THAT]);
+ if (did_pipes) {
+ PerlLIO_close(pp[0]);
+#if defined(HAS_FCNTL) && defined(F_SETFD)
+ fcntl(pp[1], F_SETFD, FD_CLOEXEC);
+#endif
+ }
if (p[THIS] != (*mode == 'r')) {
PerlLIO_dup2(p[THIS], *mode == 'r');
PerlLIO_close(p[THIS]);
#define NOFILE 20
#endif
for (fd = PL_maxsysfd + 1; fd < NOFILE; fd++)
- PerlLIO_close(fd);
+ if (fd != pp[1])
+ PerlLIO_close(fd);
#endif
- do_exec(cmd); /* may or may not use the shell */
+ do_exec3(cmd,pp[1],did_pipes); /* may or may not use the shell */
PerlProc__exit(1);
}
/*SUPPRESS 560*/
}
do_execfree(); /* free any memory malloced by child on vfork */
PerlLIO_close(p[that]);
+ if (did_pipes)
+ PerlLIO_close(pp[1]);
if (p[that] < p[This]) {
PerlLIO_dup2(p[This], p[that]);
PerlLIO_close(p[This]);
(void)SvUPGRADE(sv,SVt_IV);
SvIVX(sv) = pid;
PL_forkprocess = pid;
+ if (did_pipes && pid > 0) {
+ int errkid;
+ int n = 0, n1;
+
+ while (n < sizeof(int)) {
+ n1 = PerlLIO_read(pp[0],
+ (void*)(((char*)&errkid)+n),
+ (sizeof(int)) - n);
+ if (n1 <= 0)
+ break;
+ n += n1;
+ }
+ if (n) { /* Error */
+ if (n != sizeof(int))
+ croak("panic: kid popen errno read");
+ PerlLIO_close(pp[0]);
+ errno = errkid; /* Propagate errno from kid */
+ return Nullfp;
+ }
+ }
+ if (did_pipes)
+ PerlLIO_close(pp[0]);
return PerlIO_fdopen(p[This], mode);
}
#else
#if defined(atarist) || defined(DJGPP)
FILE *popen();
PerlIO *
-my_popen(cmd,mode)
-char *cmd;
-char *mode;
+my_popen(char *cmd, char *mode)
{
/* Needs work for PerlIO ! */
/* used 0 for 2nd parameter to PerlIO-exportFILE; apparently not used */
+ PERL_FLUSHALL_FOR_CHILD;
return popen(PerlIO_exportFILE(cmd, 0), mode);
}
#endif
#ifndef HAS_DUP2
int
-dup2(oldfd,newfd)
-int oldfd;
-int newfd;
+dup2(int oldfd, int newfd)
{
#if defined(HAS_FCNTL) && defined(F_DUPFD)
if (oldfd == newfd)
}
#endif /* !DOSISH */
-#if !defined(DOSISH) || defined(OS2) || defined(WIN32)
+#if !defined(DOSISH) || defined(OS2) || defined(WIN32) || defined(CYGWIN32)
I32
wait4pid(int pid, int *statusp, int flags)
{
#ifdef HAS_FORK
int /* Cannot prototype with I32
in os2ish.h. */
-my_syspclose(ptr)
+my_syspclose(PerlIO *ptr)
#else
I32
-my_pclose(ptr)
+my_pclose(PerlIO *ptr)
#endif
-PerlIO *ptr;
{
/* Needs work for PerlIO ! */
FILE *f = PerlIO_findFILE(ptr);
#endif
void
-repeatcpy(register char *to, register char *from, I32 len, register I32 count)
+repeatcpy(register char *to, register const char *from, I32 len, register I32 count)
{
register I32 todo;
- register char *frombase = from;
+ register const char *frombase = from;
if (len == 1) {
- register char c = *from;
+ register const char c = *from;
while (count-- > 0)
*to++ = c;
return;
IV
cast_iv(double f)
{
- if (f >= IV_MAX)
- return (IV) IV_MAX;
+ if (f >= IV_MAX) {
+ UV uv;
+
+ if (f >= (double)UV_MAX)
+ return (IV) UV_MAX;
+ uv = (UV) f;
+ return (IV)uv;
+ }
if (f <= IV_MIN)
return (IV) IV_MIN;
return (IV) f;
{
if (f >= MY_UV_MAX)
return (UV) MY_UV_MAX;
+ if (f < 0) {
+ IV iv;
+
+ if (f < IV_MIN)
+ return (UV)IV_MIN;
+ iv = (IV) f;
+ return (UV) iv;
+ }
return (UV) f;
}
#endif /* !HAS_RENAME */
UV
+scan_bin(char *start, I32 len, I32 *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);
+ }
+ *retlen = s - start;
+ return retval;
+}
+UV
scan_oct(char *start, I32 len, I32 *retlen)
{
register char *s = start;
if (len && (*s == '8' || *s == '9')) {
dTHR;
if (ckWARN(WARN_OCTAL))
- warner(WARN_OCTAL, "Illegal octal digit ignored");
+ warner(WARN_OCTAL, "Illegal octal digit '%c' ignored", *s);
}
*retlen = s - start;
return retval;
dTHR;
--s;
if (ckWARN(WARN_UNSAFE))
- warner(WARN_UNSAFE,"Illegal hex digit ignored");
+ warner(WARN_UNSAFE,"Illegal hex digit '%c' ignored", *s);
break;
}
}
if (len + 1 + strlen(scriptname) + MAX_EXT_LEN >= sizeof tmpbuf)
continue; /* don't search dir with too-long name */
if (len
-#if defined(atarist) || defined(DOSISH)
+#if defined(atarist) || defined(__MINT__) || defined(DOSISH)
&& tmpbuf[len - 1] != '/'
&& tmpbuf[len - 1] != '\\'
#endif
COND_INIT(&cp->owner_cond);
COND_INIT(&cp->cond);
cp->owner = 0;
- LOCK_SV_MUTEX;
+ MUTEX_LOCK(&PL_cred_mutex); /* XXX need separate mutex? */
mg = mg_find(sv, 'm');
if (mg) {
/* someone else beat us to initialising it */
- UNLOCK_SV_MUTEX;
+ MUTEX_UNLOCK(&PL_cred_mutex); /* XXX need separate mutex? */
MUTEX_DESTROY(&cp->mutex);
COND_DESTROY(&cp->owner_cond);
COND_DESTROY(&cp->cond);
mg = SvMAGIC(sv);
mg->mg_ptr = (char *)cp;
mg->mg_len = sizeof(cp);
- UNLOCK_SV_MUTEX;
+ MUTEX_UNLOCK(&PL_cred_mutex); /* XXX need separate mutex? */
DEBUG_S(WITH_THR(PerlIO_printf(PerlIO_stderr(),
"%p: condpair_magic %p\n", thr, sv));)
}
SV **svp;
I32 i;
- sv = newSVpv("", 0);
+ sv = newSVpvn("", 0);
SvGROW(sv, sizeof(struct perl_thread) + 1);
SvCUR_set(sv, sizeof(struct perl_thread));
thr = (Thread) SvPVX(sv);
Zero(thr, 1, struct perl_thread);
#endif
+ PL_protect = FUNC_NAME_TO_PTR(default_protect);
+
thr->oursv = sv;
init_stacks(ARGS);
thr->cvcache = newHV();
thr->threadsv = newAV();
thr->specific = newAV();
- thr->errsv = newSVpv("", 0);
+ thr->errsv = newSVpvn("", 0);
thr->errhv = newHV();
thr->flags = THRf_R_JOINABLE;
MUTEX_INIT(&thr->mutex);
PL_start_env.je_mustcatch = TRUE;
PL_top_env = &PL_start_env;
- PL_in_eval = FALSE;
+ PL_in_eval = EVAL_NULL; /* ~(EVAL_INEVAL|EVAL_WARNONLY|EVAL_KEEPERR) */
PL_restartop = 0;
PL_statname = NEWSV(66,0);
/* parent thread's data needs to be locked while we make copy */
MUTEX_LOCK(&t->mutex);
+ PL_protect = t->Tprotect;
+
PL_curcop = t->Tcurcop; /* XXX As good a guess as any? */
PL_defstash = t->Tdefstash; /* XXX maybe these should */
PL_curstash = t->Tcurstash; /* always be set to main? */
return PL_specialsv_list;
}
+#ifndef HAS_GETENV_LEN
+char *
+getenv_len(char *env_elem, unsigned long *len)
+{
+ char *env_trans = PerlEnv_getenv(env_elem);
+ if (env_trans)
+ *len = strlen(env_trans);
+ return env_trans;
+}
+#endif
+
MGVTBL*
get_vtbl(int vtbl_id)
case want_vtbl_amagicelem:
result = &PL_vtbl_amagicelem;
break;
+ case want_vtbl_backref:
+ result = &PL_vtbl_backref;
+ break;
}
return result;
}
+I32
+my_fflush_all(void)
+{
+#ifdef FFLUSH_NULL
+ return fflush(NULL);
+#else
+ long open_max = -1;
+# if defined(FFLUSH_ALL) && defined(HAS_STDIO_STREAM_ARRAY)
+# if defined(HAS_SYSCONF) && defined(_SC_OPEN_MAX)
+ open_max = sysconf(_SC_OPEN_MAX);
+# else
+# ifdef FOPEN_MAX
+# open_max = FOPEN_MAX;
+# else
+# ifdef OPEN_MAX
+# open_max = OPEN_MAX;
+# else
+# ifdef _NFILE
+# open_max = _NFILE;
+# endif
+# endif
+# endif
+# endif
+ if (open_max > 0) {
+ long i;
+ for (i = 0; i < open_max; i++)
+ fflush(&STDIO_STREAM_ARRAY[i]);
+ return 0;
+ }
+# endif
+ SETERRNO(EBADF,RMS$_IFI);
+ return EOF;
+#endif
+}