#include "EXTERN.h"
#include "perl.h"
+#include "perlmem.h"
#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
#include <signal.h>
#define FLUSH
#ifdef LEAKTEST
-static void xstat _((void));
-#endif
-#ifdef USE_THREADS
-static U32 threadnum = 0;
-#endif /* USE_THREADS */
+static void xstat _((int));
+long xcount[MAXXCOUNT];
+long lastxcount[MAXXCOUNT];
+long xycount[MAXXCOUNT][MAXYCOUNT];
+long lastxycount[MAXXCOUNT][MAXYCOUNT];
+
+#endif
#ifndef MYMALLOC
*/
Malloc_t
-safemalloc(size)
-MEM_SIZE size;
+safemalloc(MEM_SIZE size)
{
Malloc_t ptr;
#ifdef HAS_64K_LIMIT
if ((long)size < 0)
croak("panic: malloc");
#endif
- ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
+ ptr = PerlMem_malloc(size?size:1); /* malloc(0) is NASTY on our system */
#if !(defined(I286) || defined(atarist))
DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size));
#else
else {
PerlIO_puts(PerlIO_stderr(),no_mem) FLUSH;
my_exit(1);
+ return Nullch;
}
/*NOTREACHED*/
}
/* paranoid version of realloc */
Malloc_t
-saferealloc(where,size)
-Malloc_t where;
-MEM_SIZE size;
+saferealloc(Malloc_t where,MEM_SIZE size)
{
Malloc_t ptr;
#if !defined(STANDARD_C) && !defined(HAS_REALLOC_PROTOTYPE)
- Malloc_t realloc();
+ Malloc_t PerlMem_realloc();
#endif /* !defined(STANDARD_C) && !defined(HAS_REALLOC_PROTOTYPE) */
#ifdef HAS_64K_LIMIT
if ((long)size < 0)
croak("panic: realloc");
#endif
- ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
+ ptr = PerlMem_realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
#if !(defined(I286) || defined(atarist))
DEBUG_m( {
else {
PerlIO_puts(PerlIO_stderr(),no_mem) FLUSH;
my_exit(1);
+ return Nullch;
}
/*NOTREACHED*/
}
/* safe version of free */
Free_t
-safefree(where)
-Malloc_t where;
+safefree(Malloc_t where)
{
#if !(defined(I286) || defined(atarist))
- DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%x: (%05d) free\n",where,an++));
+ DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%x: (%05d) free\n",(char *) where,an++));
#else
- DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) free\n",where,an++));
+ DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) free\n",(char *) where,an++));
#endif
if (where) {
/*SUPPRESS 701*/
- free(where);
+ PerlMem_free(where);
}
}
/* safe version of calloc */
Malloc_t
-safecalloc(count, size)
-MEM_SIZE count;
-MEM_SIZE size;
+safecalloc(MEM_SIZE count, MEM_SIZE size)
{
Malloc_t ptr;
croak("panic: calloc");
#endif
size *= count;
- ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
+ ptr = PerlMem_malloc(size?size:1); /* malloc(0) is NASTY on our system */
#if !(defined(I286) || defined(atarist))
DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%x: (%05d) calloc %ld x %ld bytes\n",ptr,an++,(long)count,(long)size));
#else
else {
PerlIO_puts(PerlIO_stderr(),no_mem) FLUSH;
my_exit(1);
+ return Nullch;
}
/*NOTREACHED*/
}
#ifdef LEAKTEST
-#define ALIGN sizeof(long)
+struct mem_test_strut {
+ union {
+ long type;
+ char c[2];
+ } u;
+ long size;
+};
+
+# define ALIGN sizeof(struct mem_test_strut)
+
+# define sizeof_chunk(ch) (((struct mem_test_strut*) (ch))->size)
+# define typeof_chunk(ch) \
+ (((struct mem_test_strut*) (ch))->u.c[0] + ((struct mem_test_strut*) (ch))->u.c[1]*100)
+# define set_typeof_chunk(ch,t) \
+ (((struct mem_test_strut*) (ch))->u.c[0] = t % 100, ((struct mem_test_strut*) (ch))->u.c[1] = t / 100)
+#define SIZE_TO_Y(size) ( (size) > MAXY_SIZE \
+ ? MAXYCOUNT - 1 \
+ : ( (size) > 40 \
+ ? ((size) - 1)/8 + 5 \
+ : ((size) - 1)/4))
Malloc_t
-safexmalloc(x,size)
-I32 x;
-MEM_SIZE size;
+safexmalloc(I32 x, MEM_SIZE size)
{
- register Malloc_t where;
+ register char* where = (char*)safemalloc(size + ALIGN);
- where = safemalloc(size + ALIGN);
- xcount[x]++;
- where[0] = x % 100;
- where[1] = x / 100;
- return where + ALIGN;
+ xcount[x] += size;
+ xycount[x][SIZE_TO_Y(size)]++;
+ set_typeof_chunk(where, x);
+ sizeof_chunk(where) = size;
+ return (Malloc_t)(where + ALIGN);
}
Malloc_t
-safexrealloc(where,size)
-Malloc_t where;
-MEM_SIZE size;
+safexrealloc(Malloc_t wh, MEM_SIZE size)
{
- register Malloc_t new = saferealloc(where - ALIGN, size + ALIGN);
- return new + ALIGN;
+ char *where = (char*)wh;
+
+ if (!wh)
+ return safexmalloc(0,size);
+
+ {
+ MEM_SIZE old = sizeof_chunk(where - ALIGN);
+ int t = typeof_chunk(where - ALIGN);
+ register char* new = (char*)saferealloc(where - ALIGN, size + ALIGN);
+
+ xycount[t][SIZE_TO_Y(old)]--;
+ xycount[t][SIZE_TO_Y(size)]++;
+ xcount[t] += size - old;
+ sizeof_chunk(new) = size;
+ return (Malloc_t)(new + ALIGN);
+ }
}
void
-safexfree(where)
-Malloc_t where;
+safexfree(Malloc_t wh)
{
I32 x;
-
+ char *where = (char*)wh;
+ MEM_SIZE size;
+
if (!where)
return;
where -= ALIGN;
+ size = sizeof_chunk(where);
x = where[0] + 100 * where[1];
- xcount[x]--;
+ xcount[x] -= size;
+ xycount[x][SIZE_TO_Y(size)]--;
safefree(where);
}
Malloc_t
-safexcalloc(x,count,size)
-I32 x;
-MEM_SIZE count;
-MEM_SIZE size;
+safexcalloc(I32 x,MEM_SIZE count, MEM_SIZE size)
{
- register Malloc_t where;
-
- where = safexmalloc(x, size * count + ALIGN);
- xcount[x]++;
- memset((void*)where + ALIGN, 0, size * count);
- where[0] = x % 100;
- where[1] = x / 100;
- return where + ALIGN;
+ register char * where = (char*)safexmalloc(x, size * count + ALIGN);
+ xcount[x] += size;
+ xycount[x][SIZE_TO_Y(size)]++;
+ memset((void*)(where + ALIGN), 0, size * count);
+ set_typeof_chunk(where, x);
+ sizeof_chunk(where) = size;
+ return (Malloc_t)(where + ALIGN);
}
static void
-xstat()
+xstat(int flag)
{
- register I32 i;
+ register I32 i, j, total = 0;
+ I32 subtot[MAXYCOUNT];
+ for (j = 0; j < MAXYCOUNT; j++) {
+ subtot[j] = 0;
+ }
+
+ PerlIO_printf(PerlIO_stderr(), " Id subtot 4 8 12 16 20 24 28 32 36 40 48 56 64 72 80 80+\n", total);
for (i = 0; i < MAXXCOUNT; i++) {
- if (xcount[i] > lastxcount[i]) {
- PerlIO_printf(PerlIO_stderr(),"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
+ total += xcount[i];
+ for (j = 0; j < MAXYCOUNT; j++) {
+ subtot[j] += xycount[i][j];
+ }
+ if (flag == 0
+ ? xcount[i] /* Have something */
+ : (flag == 2
+ ? xcount[i] != lastxcount[i] /* Changed */
+ : xcount[i] > lastxcount[i])) { /* Growed */
+ PerlIO_printf(PerlIO_stderr(),"%2d %02d %7ld ", i / 100, i % 100,
+ flag == 2 ? xcount[i] - lastxcount[i] : xcount[i]);
lastxcount[i] = xcount[i];
+ for (j = 0; j < MAXYCOUNT; j++) {
+ if ( flag == 0
+ ? xycount[i][j] /* Have something */
+ : (flag == 2
+ ? xycount[i][j] != lastxycount[i][j] /* Changed */
+ : xycount[i][j] > lastxycount[i][j])) { /* Growed */
+ PerlIO_printf(PerlIO_stderr(),"%3ld ",
+ flag == 2
+ ? xycount[i][j] - lastxycount[i][j]
+ : xycount[i][j]);
+ lastxycount[i][j] = xycount[i][j];
+ } else {
+ PerlIO_printf(PerlIO_stderr(), " . ", xycount[i][j]);
+ }
+ }
+ PerlIO_printf(PerlIO_stderr(), "\n");
}
}
+ if (flag != 2) {
+ PerlIO_printf(PerlIO_stderr(), "Total %7ld ", total);
+ for (j = 0; j < MAXYCOUNT; j++) {
+ if (subtot[j]) {
+ PerlIO_printf(PerlIO_stderr(), "%3ld ", subtot[j]);
+ } else {
+ PerlIO_printf(PerlIO_stderr(), " . ");
+ }
+ }
+ PerlIO_printf(PerlIO_stderr(), "\n");
+ }
}
#endif /* LEAKTEST */
/* copy a string up to some (non-backslashed) delimiter, if any */
char *
-delimcpy(to, toend, from, fromend, delim, retlen)
-register char *to;
-register char *toend;
-register char *from;
-register char *fromend;
-register int delim;
-I32 *retlen;
+delimcpy(register char *to, register char *toend, register char *from, register char *fromend, register int delim, I32 *retlen)
{
register I32 tolen;
for (tolen = 0; from < fromend; from++, tolen++) {
/* This routine was donated by Corey Satten. */
char *
-instr(big, little)
-register char *big;
-register char *little;
+instr(register char *big, register char *little)
{
register char *s, *x;
register I32 first;
/* same as instr but allow embedded nulls */
char *
-ninstr(big, bigend, little, lend)
-register char *big;
-register char *bigend;
-char *little;
-char *lend;
+ninstr(register char *big, register char *bigend, char *little, char *lend)
{
register char *s, *x;
register I32 first = *little;
/* reverse of the above--find last substring */
char *
-rninstr(big, bigend, little, lend)
-register char *big;
-char *bigend;
-char *little;
-char *lend;
+rninstr(register char *big, char *bigend, char *little, char *lend)
{
register char *bigbeg;
register char *s, *x;
* Set up for a new ctype locale.
*/
void
-perl_new_ctype(newctype)
- char *newctype;
+perl_new_ctype(char *newctype)
{
#ifdef USE_LOCALE_CTYPE
* Set up for a new collation locale.
*/
void
-perl_new_collate(newcoll)
- char *newcoll;
+perl_new_collate(char *newcoll)
{
#ifdef USE_LOCALE_COLLATE
* Set up for a new numeric locale.
*/
void
-perl_new_numeric(newnum)
- char *newnum;
+perl_new_numeric(char *newnum)
{
#ifdef USE_LOCALE_NUMERIC
}
void
-perl_set_numeric_standard()
+perl_set_numeric_standard(void)
{
#ifdef USE_LOCALE_NUMERIC
}
void
-perl_set_numeric_local()
+perl_set_numeric_local(void)
{
#ifdef USE_LOCALE_NUMERIC
* Initialize locale awareness.
*/
int
-perl_init_i18nl10n(printwarn)
- int printwarn;
+perl_init_i18nl10n(int printwarn)
{
int ok = 1;
/* returns
#ifdef USE_LOCALE_NUMERIC
char *curnum = NULL;
#endif /* USE_LOCALE_NUMERIC */
- char *lc_all = getenv("LC_ALL");
- char *lang = getenv("LANG");
+ char *lc_all = PerlEnv_getenv("LC_ALL");
+ char *lang = PerlEnv_getenv("LANG");
bool setlocale_failure = FALSE;
#ifdef LOCALE_ENVIRON_REQUIRED
{
#ifdef USE_LOCALE_CTYPE
if (! (curctype = setlocale(LC_CTYPE,
- (!done && (lang || getenv("LC_CTYPE")))
+ (!done && (lang || PerlEnv_getenv("LC_CTYPE")))
? "" : Nullch)))
setlocale_failure = TRUE;
#endif /* USE_LOCALE_CTYPE */
#ifdef USE_LOCALE_COLLATE
if (! (curcoll = setlocale(LC_COLLATE,
- (!done && (lang || getenv("LC_COLLATE")))
+ (!done && (lang || PerlEnv_getenv("LC_COLLATE")))
? "" : Nullch)))
setlocale_failure = TRUE;
#endif /* USE_LOCALE_COLLATE */
#ifdef USE_LOCALE_NUMERIC
if (! (curnum = setlocale(LC_NUMERIC,
- (!done && (lang || getenv("LC_NUMERIC")))
+ (!done && (lang || PerlEnv_getenv("LC_NUMERIC")))
? "" : Nullch)))
setlocale_failure = TRUE;
#endif /* USE_LOCALE_NUMERIC */
char *p;
bool locwarn = (printwarn > 1 ||
printwarn &&
- (!(p = getenv("PERL_BADLANG")) || atoi(p)));
+ (!(p = PerlEnv_getenv("PERL_BADLANG")) || atoi(p)));
if (locwarn) {
#ifdef LC_ALL
/* Backwards compatibility. */
int
-perl_init_i18nl14n(printwarn)
- int printwarn;
+perl_init_i18nl14n(int printwarn)
{
return perl_init_i18nl10n(printwarn);
}
* Please see sv_collxfrm() to see how this is used.
*/
char *
-mem_collxfrm(s, len, xlen)
- const char *s;
- STRLEN len;
- STRLEN *xlen;
+mem_collxfrm(const char *s, STRLEN len, STRLEN *xlen)
{
char *xbuf;
STRLEN xalloc, xin, xout;
#endif /* USE_LOCALE_COLLATE */
void
-fbm_compile(sv)
-SV *sv;
+fbm_compile(SV *sv, U32 flags /* not used yet */)
{
register unsigned char *s;
register unsigned char *table;
I32 rarest = 0;
U32 frequency = 256;
- if (len > 255)
+ sv_upgrade(sv, SVt_PVBM);
+ if (len > 255 || len == 0) /* TAIL might be on on a zero-length string. */
return; /* can't have offsets that big */
- Sv_Grow(sv,len+258);
- table = (unsigned char*)(SvPVX(sv) + len + 1);
- s = table - 2;
- for (i = 0; i < 256; i++) {
- table[i] = len;
- }
- i = 0;
- while (s >= (unsigned char*)(SvPVX(sv)))
- {
- if (table[*s] == len)
- table[*s] = i;
- s--,i++;
+ if (len > 2) {
+ Sv_Grow(sv,len + 258);
+ table = (unsigned char*)(SvPVX(sv) + len + 1);
+ s = table - 2;
+ for (i = 0; i < 256; i++) {
+ table[i] = len;
+ }
+ i = 0;
+ while (s >= (unsigned char*)(SvPVX(sv)))
+ {
+ if (table[*s] == len)
+ table[*s] = i;
+ s--,i++;
+ }
}
- sv_upgrade(sv, SVt_PVBM);
sv_magic(sv, Nullsv, 'B', Nullch, 0); /* deep magic */
SvVALID_on(sv);
}
char *
-fbm_instr(big, bigend, littlestr)
-unsigned char *big;
-register unsigned char *bigend;
-SV *littlestr;
+fbm_instr(unsigned char *big, register unsigned char *bigend, SV *littlestr)
{
register unsigned char *s;
register I32 tmp;
if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) {
STRLEN len;
char *l = SvPV(littlestr,len);
- if (!len)
+ if (!len) {
+ if (SvTAIL(littlestr)) { /* Can be only 0-len constant
+ substr => we can ignore SvVALID */
+ if (multiline) {
+ char *t = "\n";
+ if ((s = (unsigned char*)ninstr((char*)big, (char*)bigend,
+ t, t + len))) {
+ return (char*)s;
+ }
+ }
+ if (bigend > big && bigend[-1] == '\n')
+ return (char *)(bigend - 1);
+ else
+ return (char *) bigend;
+ }
return (char*)big;
+ }
return ninstr((char*)big,(char*)bigend, l, l + len);
}
return Nullch;
little = (unsigned char*)SvPVX(littlestr);
s = bigend - littlelen;
- if (*s == *little && memEQ((char*)s,(char*)little,littlelen))
+ 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))
return (char*)s; /* how sweet it is */
- else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
- && s > big) {
- s--;
- if (*s == *little && memEQ((char*)s,(char*)little,littlelen))
+ 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 */
+ {
return (char*)s;
+ }
+ s++;
}
return Nullch;
}
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;
return Nullch;
}
+ if (SvTAIL(littlestr) /* automatically multiline */
+ && olds + 1 != bigend
+ && olds[1] != '\n')
+ goto differ;
return (char *)s;
}
}
return Nullch;
}
+/* start_shift, end_shift are positive quantities which give offsets
+ of ends of some substring of bigstr.
+ If `last' we want the last occurence.
+ old_posp is the way of communication between consequent calls if
+ the next call needs to find the .
+ The 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.
+ */
+
char *
-screaminstr(bigstr, littlestr)
-SV *bigstr;
-SV *littlestr;
+screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_posp, I32 last)
{
register unsigned char *s, *x;
register unsigned char *big;
register I32 previous;
register I32 first;
register unsigned char *little;
- register unsigned char *bigend;
+ register I32 stop_pos;
register unsigned char *littleend;
+ I32 found = 0;
- if ((pos = screamfirst[BmRARE(littlestr)]) < 0)
+ if (*old_posp == -1
+ ? (pos = screamfirst[BmRARE(littlestr)]) < 0
+ : (((pos = *old_posp), pos += screamnext[pos]) == 0))
return Nullch;
little = (unsigned char *)(SvPVX(littlestr));
littleend = little + SvCUR(littlestr);
first = *little++;
+ /* The value of pos we can start at: */
previous = BmPREVIOUS(littlestr);
big = (unsigned char *)(SvPVX(bigstr));
- bigend = big + SvCUR(bigstr);
- while (pos < previous) {
+ /* 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;
+ while (pos < previous + start_shift) {
if (!(pos += screamnext[pos]))
return Nullch;
}
#ifdef POINTERRIGOR
do {
+ if (pos >= stop_pos) return Nullch;
if (big[pos-previous] != first)
continue;
for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
- if (x >= bigend)
- return Nullch;
if (*s++ != *x++) {
s--;
break;
}
}
- if (s == littleend)
- return (char *)(big+pos-previous);
+ if (s == littleend) {
+ *old_posp = pos;
+ if (!last) return (char *)(big+pos-previous);
+ found = 1;
+ }
} while ( pos += screamnext[pos] );
+ return (last && found) ? (char *)(big+(*old_posp)-previous) : Nullch;
#else /* !POINTERRIGOR */
big -= previous;
do {
+ if (pos >= stop_pos) return Nullch;
if (big[pos] != first)
continue;
for (x=big+pos+1,s=little; s < littleend; /**/ ) {
- if (x >= bigend)
- return Nullch;
if (*s++ != *x++) {
s--;
break;
}
}
- if (s == littleend)
- return (char *)(big+pos);
+ if (s == littleend) {
+ *old_posp = pos;
+ if (!last) return (char *)(big+pos);
+ found = 1;
+ }
} while ( pos += screamnext[pos] );
+ return (last && found) ? (char *)(big+(*old_posp)) : Nullch;
#endif /* POINTERRIGOR */
- return Nullch;
}
I32
-ibcmp(s1, s2, len)
-char *s1, *s2;
-register I32 len;
+ibcmp(char *s1, char *s2, register I32 len)
{
register U8 *a = (U8 *)s1;
register U8 *b = (U8 *)s2;
}
I32
-ibcmp_locale(s1, s2, len)
-char *s1, *s2;
-register I32 len;
+ibcmp_locale(char *s1, char *s2, register I32 len)
{
register U8 *a = (U8 *)s1;
register U8 *b = (U8 *)s2;
/* copy a string to a safe spot */
char *
-savepv(sv)
-char *sv;
+savepv(char *sv)
{
register char *newaddr;
/* same thing but with a known length */
char *
-savepvn(sv, len)
-char *sv;
-register I32 len;
+savepvn(char *sv, register I32 len)
{
register char *newaddr;
/* the SV for form() and mess() is not kept in an arena */
static SV *
-mess_alloc()
+mess_alloc(void)
{
SV *sv;
XPVMG *any;
}
char *
-mess(pat, args)
- const char *pat;
- va_list *args;
+mess(const char *pat, va_list *args)
{
SV *sv;
static char dgd[] = " during global destruction.\n";
dTHR;
va_list args;
char *message;
- I32 oldrunlevel = runlevel;
int was_in_eval = in_eval;
HV *stash;
GV *gv;
CV *cv;
- DEBUG_L(PerlIO_printf(PerlIO_stderr(), "die: curstack = %p, mainstack= %p\n",
- curstack, mainstack));/*debug*/
- /* We have to switch back to mainstack or die_where may try to pop
- * the eval block from the wrong stack if die is being called from a
- * signal handler. - dkindred@cs.cmu.edu */
- if (curstack != mainstack) {
- dSP;
- SWITCHSTACK(curstack, mainstack);
- }
+#ifdef USE_THREADS
+ DEBUG_L(PerlIO_printf(PerlIO_stderr(),
+ "%p: die: curstack = %p, mainstack = %p\n",
+ thr, curstack, mainstack));
+#endif /* USE_THREADS */
#ifdef I_STDARG
va_start(args, pat);
#else
va_start(args);
#endif
- message = mess(pat, &args);
+ message = pat ? mess(pat, &args) : Nullch;
va_end(args);
- DEBUG_L(PerlIO_printf(PerlIO_stderr(), "die: message = %s\ndiehook = %p\n",
- message, diehook));/*debug*/
+#ifdef USE_THREADS
+ DEBUG_L(PerlIO_printf(PerlIO_stderr(),
+ "%p: die: message = %s\ndiehook = %p\n",
+ thr, message, diehook));
+#endif /* USE_THREADS */
if (diehook) {
/* sv_2cv might call croak() */
SV *olddiehook = diehook;
SV *msg;
ENTER;
- msg = newSVpv(message, 0);
- SvREADONLY_on(msg);
- SAVEFREESV(msg);
+ if(message) {
+ msg = newSVpv(message, 0);
+ SvREADONLY_on(msg);
+ SAVEFREESV(msg);
+ }
+ else {
+ msg = ERRSV;
+ }
- PUSHMARK(sp);
+ PUSHSTACK(SI_DIEHOOK);
+ PUSHMARK(SP);
XPUSHs(msg);
PUTBACK;
perl_call_sv((SV*)cv, G_DISCARD);
-
+ POPSTACK();
LEAVE;
}
}
restartop = die_where(message);
+#ifdef USE_THREADS
DEBUG_L(PerlIO_printf(PerlIO_stderr(),
- "die: restartop = %p, was_in_eval = %d, oldrunlevel = %d\n",
- restartop, was_in_eval, oldrunlevel));/*debug*/
- if ((!restartop && was_in_eval) || oldrunlevel > 1)
+ "%p: die: restartop = %p, was_in_eval = %d, top_env = %p\n",
+ thr, restartop, was_in_eval, top_env));
+#endif /* USE_THREADS */
+ if ((!restartop && was_in_eval) || top_env->je_prev)
JMPENV_JUMP(3);
return restartop;
}
SvREADONLY_on(msg);
SAVEFREESV(msg);
- PUSHMARK(sp);
+ PUSHSTACK(SI_DIEHOOK);
+ PUSHMARK(SP);
XPUSHs(msg);
PUTBACK;
perl_call_sv((SV*)cv, G_DISCARD);
-
+ POPSTACK();
LEAVE;
}
}
SvREADONLY_on(msg);
SAVEFREESV(msg);
- PUSHMARK(sp);
+ PUSHSTACK(SI_WARNHOOK);
+ PUSHMARK(SP);
XPUSHs(msg);
PUTBACK;
perl_call_sv((SV*)cv, G_DISCARD);
-
+ POPSTACK();
LEAVE;
return;
}
}
PerlIO_puts(PerlIO_stderr(),message);
#ifdef LEAKTEST
- DEBUG_L(xstat());
+ DEBUG_L(*message == '!'
+ ? (xstat(message[1]=='!'
+ ? (message[2]=='!' ? 2 : 1)
+ : 0)
+ , 0)
+ : 0);
#endif
(void)PerlIO_flush(PerlIO_stderr());
}
#ifndef VMS /* VMS' my_setenv() is in VMS.c */
#ifndef WIN32
void
-my_setenv(nam,val)
-char *nam, *val;
+my_setenv(char *nam, char *val)
{
register I32 i=setenv_getix(nam); /* where does it go? */
#else /* if WIN32 */
void
-my_setenv(nam,val)
-char *nam, *val;
+my_setenv(char *nam,char *val)
{
#ifdef USE_WIN32_RTL_ENV
vallen = strlen(val);
New(904, envstr, namlen + vallen + 3, char);
(void)sprintf(envstr,"%s=%s",nam,val);
- (void)putenv(envstr);
+ (void)PerlEnv_putenv(envstr);
if (oldstr)
Safefree(oldstr);
#ifdef _MSC_VER
#endif /* WIN32 */
I32
-setenv_getix(nam)
-char *nam;
+setenv_getix(char *nam)
{
register I32 i, len = strlen(nam);
{
I32 i;
- for (i = 0; unlink(f) >= 0; i++) ;
+ for (i = 0; PerlLIO_unlink(f) >= 0; i++) ;
return i ? 0 : -1;
}
#endif
#if !defined(HAS_BCOPY) || !defined(HAS_SAFE_BCOPY)
char *
-my_bcopy(from,to,len)
-register char *from;
-register char *to;
-register I32 len;
+my_bcopy(register char *from,register char *to,register I32 len)
{
char *retval = to;
#ifdef MYSWAP
#if BYTEORDER != 0x4321
short
-#ifndef CAN_PROTOTYPE
-my_swap(s)
-short s;
-#else
my_swap(short s)
-#endif
{
#if (BYTEORDER & 1) == 0
short result;
}
long
-#ifndef CAN_PROTOTYPE
-my_htonl(l)
-register long l;
-#else
my_htonl(long l)
-#endif
{
union {
long result;
}
long
-#ifndef CAN_PROTOTYPE
-my_ntohl(l)
-register long l;
-#else
my_ntohl(long l)
-#endif
{
union {
long l;
/* VMS' my_popen() is in VMS.c, same with OS/2. */
#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS)
PerlIO *
-my_popen(cmd,mode)
-char *cmd;
-char *mode;
+my_popen(char *cmd, char *mode)
{
int p[2];
- register I32 this, that;
+ register I32 This, that;
register I32 pid;
SV *sv;
I32 doexec = strNE(cmd,"-");
return my_syspopen(cmd,mode);
}
#endif
- if (pipe(p) < 0)
- return Nullfp;
- this = (*mode == 'w');
- that = !this;
+ This = (*mode == 'w');
+ that = !This;
if (doexec && tainting) {
taint_env();
taint_proper("Insecure %s%s", "EXEC");
}
+ if (PerlProc_pipe(p) < 0)
+ return Nullfp;
while ((pid = (doexec?vfork():fork())) < 0) {
if (errno != EAGAIN) {
- close(p[this]);
+ PerlLIO_close(p[This]);
if (!doexec)
croak("Can't fork");
return Nullfp;
GV* tmpgv;
#define THIS that
-#define THAT this
- close(p[THAT]);
+#define THAT This
+ PerlLIO_close(p[THAT]);
if (p[THIS] != (*mode == 'r')) {
- dup2(p[THIS], *mode == 'r');
- close(p[THIS]);
+ PerlLIO_dup2(p[THIS], *mode == 'r');
+ PerlLIO_close(p[THIS]);
}
if (doexec) {
#if !defined(HAS_FCNTL) || !defined(F_SETFD)
#define NOFILE 20
#endif
for (fd = maxsysfd + 1; fd < NOFILE; fd++)
- close(fd);
+ PerlLIO_close(fd);
#endif
do_exec(cmd); /* may or may not use the shell */
- _exit(1);
+ PerlProc__exit(1);
}
/*SUPPRESS 560*/
if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV))
#undef THAT
}
do_execfree(); /* free any memory malloced by child on vfork */
- close(p[that]);
- if (p[that] < p[this]) {
- dup2(p[this], p[that]);
- close(p[this]);
- p[this] = p[that];
+ PerlLIO_close(p[that]);
+ if (p[that] < p[This]) {
+ PerlLIO_dup2(p[This], p[that]);
+ PerlLIO_close(p[This]);
+ p[This] = p[that];
}
- sv = *av_fetch(fdpid,p[this],TRUE);
+ sv = *av_fetch(fdpid,p[This],TRUE);
(void)SvUPGRADE(sv,SVt_IV);
SvIVX(sv) = pid;
forkprocess = pid;
- return PerlIO_fdopen(p[this], mode);
+ return PerlIO_fdopen(p[This], mode);
}
#else
#if defined(atarist) || defined(DJGPP)
PerlIO_printf(PerlIO_stderr(),"%s", s);
for (fd = 0; fd < 32; fd++) {
- if (Fstat(fd,&tmpstatbuf) >= 0)
+ if (PerlLIO_fstat(fd,&tmpstatbuf) >= 0)
PerlIO_printf(PerlIO_stderr()," %d",fd);
}
PerlIO_printf(PerlIO_stderr(),"\n");
#if defined(HAS_FCNTL) && defined(F_DUPFD)
if (oldfd == newfd)
return oldfd;
- close(newfd);
+ PerlLIO_close(newfd);
return fcntl(oldfd, F_DUPFD, newfd);
#else
#define DUP2_MAX_FDS 256
if (oldfd == newfd)
return oldfd;
- close(newfd);
+ PerlLIO_close(newfd);
/* good enough for low fd's... */
- while ((fd = dup(oldfd)) != newfd && fd >= 0) {
+ while ((fd = PerlLIO_dup(oldfd)) != newfd && fd >= 0) {
if (fdx >= DUP2_MAX_FDS) {
- close(fd);
+ PerlLIO_close(fd);
fd = -1;
break;
}
fdtmp[fdx++] = fd;
}
while (fdx > 0)
- close(fdtmp[--fdx]);
+ PerlLIO_close(fdtmp[--fdx]);
return fd;
#endif
}
#ifdef HAS_SIGACTION
Sighandler_t
-rsignal(signo, handler)
-int signo;
-Sighandler_t handler;
+rsignal(int signo, Sighandler_t handler)
{
struct sigaction act, oact;
}
Sighandler_t
-rsignal_state(signo)
-int signo;
+rsignal_state(int signo)
{
struct sigaction oact;
}
int
-rsignal_save(signo, handler, save)
-int signo;
-Sighandler_t handler;
-Sigsave_t *save;
+rsignal_save(int signo, Sighandler_t handler, Sigsave_t *save)
{
struct sigaction act;
}
int
-rsignal_restore(signo, save)
-int signo;
-Sigsave_t *save;
+rsignal_restore(int signo, Sigsave_t *save)
{
return sigaction(signo, save, (struct sigaction *)NULL);
}
#else /* !HAS_SIGACTION */
Sighandler_t
-rsignal(signo, handler)
-int signo;
-Sighandler_t handler;
+rsignal(int signo, Sighandler_t handler)
{
- return signal(signo, handler);
+ return PerlProc_signal(signo, handler);
}
static int sig_trapped;
static
Signal_t
-sig_trap(signo)
-int signo;
+sig_trap(int signo)
{
sig_trapped++;
}
Sighandler_t
-rsignal_state(signo)
-int signo;
+rsignal_state(int signo)
{
Sighandler_t oldsig;
sig_trapped = 0;
- oldsig = signal(signo, sig_trap);
- signal(signo, oldsig);
+ oldsig = PerlProc_signal(signo, sig_trap);
+ PerlProc_signal(signo, oldsig);
if (sig_trapped)
- kill(getpid(), signo);
+ PerlProc_kill(getpid(), signo);
return oldsig;
}
int
-rsignal_save(signo, handler, save)
-int signo;
-Sighandler_t handler;
-Sigsave_t *save;
+rsignal_save(int signo, Sighandler_t handler, Sigsave_t *save)
{
- *save = signal(signo, handler);
+ *save = PerlProc_signal(signo, handler);
return (*save == SIG_ERR) ? -1 : 0;
}
int
-rsignal_restore(signo, save)
-int signo;
-Sigsave_t *save;
+rsignal_restore(int signo, Sigsave_t *save)
{
- return (signal(signo, *save) == SIG_ERR) ? -1 : 0;
+ return (PerlProc_signal(signo, *save) == SIG_ERR) ? -1 : 0;
}
#endif /* !HAS_SIGACTION */
/* VMS' my_pclose() is in VMS.c; same with OS/2 */
#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS)
I32
-my_pclose(ptr)
-PerlIO *ptr;
+my_pclose(PerlIO *ptr)
{
Sigsave_t hstat, istat, qstat;
int status;
SV **svp;
int pid;
+ int pid2;
bool close_failed;
int saved_errno;
#ifdef VMS
int saved_vaxc_errno;
#endif
+#ifdef WIN32
+ int saved_win32_errno;
+#endif
svp = av_fetch(fdpid,PerlIO_fileno(ptr),TRUE);
pid = (int)SvIVX(*svp);
#ifdef VMS
saved_vaxc_errno = vaxc$errno;
#endif
+#ifdef WIN32
+ saved_win32_errno = GetLastError();
+#endif
}
#ifdef UTS
- if(kill(pid, 0) < 0) { return(pid); } /* HOM 12/23/91 */
+ if(PerlProc_kill(pid, 0) < 0) { return(pid); } /* HOM 12/23/91 */
#endif
rsignal_save(SIGHUP, SIG_IGN, &hstat);
rsignal_save(SIGINT, SIG_IGN, &istat);
rsignal_save(SIGQUIT, SIG_IGN, &qstat);
do {
- pid = wait4pid(pid, &status, 0);
- } while (pid == -1 && errno == EINTR);
+ pid2 = wait4pid(pid, &status, 0);
+ } while (pid2 == -1 && errno == EINTR);
rsignal_restore(SIGHUP, &hstat);
rsignal_restore(SIGINT, &istat);
rsignal_restore(SIGQUIT, &qstat);
SETERRNO(saved_errno, saved_vaxc_errno);
return -1;
}
- return(pid < 0 ? pid : status == 0 ? 0 : (errno = 0, status));
+ return(pid2 < 0 ? pid2 : status == 0 ? 0 : (errno = 0, status));
}
#endif /* !DOSISH */
-#if !defined(DOSISH) || defined(OS2)
+#if !defined(DOSISH) || defined(OS2) || defined(WIN32)
I32
-wait4pid(pid,statusp,flags)
-int pid;
-int *statusp;
-int flags;
+wait4pid(int pid, int *statusp, int flags)
{
SV *sv;
SV** svp;
}
#endif
}
-#endif /* !DOSISH */
+#endif /* !DOSISH || OS2 || WIN32 */
void
/*SUPPRESS 590*/
-pidgone(pid,status)
-int pid;
-int status;
+pidgone(int pid, int status)
{
register SV *sv;
char spid[TYPE_CHARS(int)];
#endif
void
-repeatcpy(to,from,len,count)
-register char *to;
-register char *from;
-I32 len;
-register I32 count;
+repeatcpy(register char *to, register char *from, I32 len, register I32 count)
{
register I32 todo;
register char *frombase = from;
sv_setpv(tmpsv, ".");
else
sv_setpvn(tmpsv, a, fa - a);
- if (Stat(SvPVX(tmpsv), &tmpstatbuf1) < 0)
+ if (PerlLIO_stat(SvPVX(tmpsv), &tmpstatbuf1) < 0)
return FALSE;
if (fb == b)
sv_setpv(tmpsv, ".");
else
sv_setpvn(tmpsv, b, fb - b);
- if (Stat(SvPVX(tmpsv), &tmpstatbuf2) < 0)
+ if (PerlLIO_stat(SvPVX(tmpsv), &tmpstatbuf2) < 0)
return FALSE;
return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
#endif /* !HAS_RENAME */
UV
-scan_oct(start, len, retlen)
-char *start;
-I32 len;
-I32 *retlen;
+scan_oct(char *start, I32 len, I32 *retlen)
{
register char *s = start;
register UV retval = 0;
}
UV
-scan_hex(start, len, retlen)
-char *start;
-I32 len;
-I32 *retlen;
+scan_hex(char *start, I32 len, I32 *retlen)
{
register char *s = start;
register UV retval = 0;
bool overflowed = FALSE;
- char *tmp;
+ char *tmp = s;
- while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
+ while (len-- && *s && (tmp = strchr((char *) hexdigit, *s))) {
register UV n = retval << 4;
if (!overflowed && (n >> 4) != retval) {
warn("Integer overflow in hex number");
overflowed = TRUE;
}
- retval = n | (tmp - hexdigit) & 15;
+ retval = n | ((tmp - hexdigit) & 15);
s++;
}
+ if (dowarn && !tmp) {
+ warn("Illegal hex digit ignored");
+ }
*retlen = s - start;
return retval;
}
+char*
+find_script(char *scriptname, bool dosearch, char **search_ext, I32 flags)
+{
+ dTHR;
+ char *xfound = Nullch;
+ char *xfailed = Nullch;
+ register char *s;
+ I32 len;
+ int retval;
+#if defined(DOSISH) && !defined(OS2) && !defined(atarist)
+# define SEARCH_EXTS ".bat", ".cmd", NULL
+# define MAX_EXT_LEN 4
+#endif
+#ifdef OS2
+# define SEARCH_EXTS ".cmd", ".btm", ".bat", ".pl", NULL
+# define MAX_EXT_LEN 4
+#endif
+#ifdef VMS
+# define SEARCH_EXTS ".pl", ".com", NULL
+# define MAX_EXT_LEN 4
+#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;
+ int extidx = 0, i = 0;
+ char *curext = Nullch;
+#else
+# define MAX_EXT_LEN 0
+#endif
+
+ /*
+ * If dosearch is true and if scriptname does not contain path
+ * delimiters, search the PATH for scriptname.
+ *
+ * If SEARCH_EXTS is also defined, will look for each
+ * scriptname{SEARCH_EXTS} whenever scriptname is not found
+ * while searching the PATH.
+ *
+ * Assuming SEARCH_EXTS is C<".foo",".bar",NULL>, PATH search
+ * proceeds as follows:
+ * If DOSISH or VMSISH:
+ * + look for ./scriptname{,.foo,.bar}
+ * + search the PATH for scriptname{,.foo,.bar}
+ *
+ * If !DOSISH:
+ * + look *only* in the PATH for scriptname{,.foo,.bar} (note
+ * this will not look in '.' if it's not in the PATH)
+ */
+
+#ifdef VMS
+# ifdef ALWAYS_DEFTYPES
+ len = strlen(scriptname);
+ if (!(len == 1 && *scriptname == '-') && scriptname[len-1] != ':') {
+ int hasdir, idx = 0, deftypes = 1;
+ bool seen_dot = 1;
+
+ hasdir = !dosearch || (strpbrk(scriptname,":[</") != Nullch) ;
+# else
+ if (dosearch) {
+ int hasdir, idx = 0, deftypes = 1;
+ bool seen_dot = 1;
+
+ hasdir = (strpbrk(scriptname,":[</") != Nullch) ;
+# endif
+ /* The first time through, just add SEARCH_EXTS to whatever we
+ * already have, so we can check for default file types. */
+ while (deftypes ||
+ (!hasdir && my_trnlnm("DCL$PATH",tokenbuf,idx++)) )
+ {
+ if (deftypes) {
+ deftypes = 0;
+ *tokenbuf = '\0';
+ }
+ if ((strlen(tokenbuf) + strlen(scriptname)
+ + MAX_EXT_LEN) >= sizeof tokenbuf)
+ continue; /* don't search dir with too-long name */
+ strcat(tokenbuf, scriptname);
+#else /* !VMS */
+
+#ifdef DOSISH
+ if (strEQ(scriptname, "-"))
+ dosearch = 0;
+ if (dosearch) { /* Look in '.' first. */
+ char *cur = scriptname;
+#ifdef SEARCH_EXTS
+ if ((curext = strrchr(scriptname,'.'))) /* possible current ext */
+ while (ext[i])
+ if (strEQ(ext[i++],curext)) {
+ extidx = -1; /* already has an ext */
+ break;
+ }
+ do {
+#endif
+ DEBUG_p(PerlIO_printf(Perl_debug_log,
+ "Looking for %s\n",cur));
+ if (PerlLIO_stat(cur,&statbuf) >= 0) {
+ dosearch = 0;
+ scriptname = cur;
+#ifdef SEARCH_EXTS
+ break;
+#endif
+ }
+#ifdef SEARCH_EXTS
+ if (cur == scriptname) {
+ len = strlen(scriptname);
+ if (len+MAX_EXT_LEN+1 >= sizeof(tokenbuf))
+ break;
+ cur = strcpy(tokenbuf, scriptname);
+ }
+ } while (extidx >= 0 && ext[extidx] /* try an extension? */
+ && strcpy(tokenbuf+len, ext[extidx++]));
+#endif
+ }
+#endif
+
+ if (dosearch && !strchr(scriptname, '/')
+#ifdef DOSISH
+ && !strchr(scriptname, '\\')
+#endif
+ && (s = PerlEnv_getenv("PATH"))) {
+ bool seen_dot = 0;
+
+ bufend = s + strlen(s);
+ while (s < bufend) {
+#if defined(atarist) || defined(DOSISH)
+ for (len = 0; *s
+# ifdef atarist
+ && *s != ','
+# endif
+ && *s != ';'; len++, s++) {
+ if (len < sizeof tokenbuf)
+ tokenbuf[len] = *s;
+ }
+ if (len < sizeof tokenbuf)
+ tokenbuf[len] = '\0';
+#else /* ! (atarist || DOSISH) */
+ s = delimcpy(tokenbuf, tokenbuf + sizeof tokenbuf, s, bufend,
+ ':',
+ &len);
+#endif /* ! (atarist || DOSISH) */
+ if (s < bufend)
+ s++;
+ if (len + 1 + strlen(scriptname) + MAX_EXT_LEN >= sizeof tokenbuf)
+ continue; /* don't search dir with too-long name */
+ if (len
+#if defined(atarist) || defined(DOSISH)
+ && tokenbuf[len - 1] != '/'
+ && tokenbuf[len - 1] != '\\'
+#endif
+ )
+ tokenbuf[len++] = '/';
+ if (len == 2 && tokenbuf[0] == '.')
+ seen_dot = 1;
+ (void)strcpy(tokenbuf + len, scriptname);
+#endif /* !VMS */
+
+#ifdef SEARCH_EXTS
+ len = strlen(tokenbuf);
+ if (extidx > 0) /* reset after previous loop */
+ extidx = 0;
+ do {
+#endif
+ DEBUG_p(PerlIO_printf(Perl_debug_log, "Looking for %s\n",tokenbuf));
+ retval = PerlLIO_stat(tokenbuf,&statbuf);
+#ifdef SEARCH_EXTS
+ } while ( retval < 0 /* not there */
+ && extidx>=0 && ext[extidx] /* try an extension? */
+ && strcpy(tokenbuf+len, ext[extidx++])
+ );
+#endif
+ if (retval < 0)
+ continue;
+ if (S_ISREG(statbuf.st_mode)
+ && cando(S_IRUSR,TRUE,&statbuf)
+#ifndef DOSISH
+ && cando(S_IXUSR,TRUE,&statbuf)
+#endif
+ )
+ {
+ xfound = tokenbuf; /* bingo! */
+ break;
+ }
+ if (!xfailed)
+ xfailed = savepv(tokenbuf);
+ }
+#ifndef DOSISH
+ if (!xfound && !seen_dot && !xfailed && (PerlLIO_stat(scriptname,&statbuf) < 0))
+#endif
+ seen_dot = 1; /* Disable message. */
+ if (!xfound)
+ scriptname = NULL;
+/* croak("Can't %s %s%s%s",
+ (xfailed ? "execute" : "find"),
+ (xfailed ? xfailed : scriptname),
+ (xfailed ? "" : " on PATH"),
+ (xfailed || seen_dot) ? "" : ", '.' not in PATH"); */
+ if (xfailed)
+ Safefree(xfailed);
+ scriptname = xfound;
+ }
+ return scriptname;
+}
+
+
#ifdef USE_THREADS
#ifdef FAKE_THREADS
/* Very simplistic scheduler for now */
perl_cond_signal(cp)
perl_cond *cp;
{
- perl_thread t;
+ perl_os_thread t;
perl_cond cond = *cp;
if (!cond)
perl_cond_broadcast(cp)
perl_cond *cp;
{
- perl_thread t;
+ perl_os_thread t;
perl_cond cond, cond_next;
for (cond = *cp; cond; cond = cond_next) {
#endif /* FAKE_THREADS */
#ifdef OLD_PTHREADS_API
-struct thread *
+struct perl_thread *
getTHR _((void))
{
pthread_addr_t t;
if (pthread_getspecific(thr_key, &t))
croak("panic: pthread_getspecific");
- return (struct thread *) t;
+ return (struct perl_thread *) t;
}
#endif /* OLD_PTHREADS_API */
MAGIC *
-condpair_magic(sv)
-SV *sv;
+condpair_magic(SV *sv)
{
MAGIC *mg;
COND_INIT(&cp->owner_cond);
COND_INIT(&cp->cond);
cp->owner = 0;
- MUTEX_LOCK(&sv_mutex);
+ LOCK_SV_MUTEX;
mg = mg_find(sv, 'm');
if (mg) {
/* someone else beat us to initialising it */
- MUTEX_UNLOCK(&sv_mutex);
+ UNLOCK_SV_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);
- MUTEX_UNLOCK(&sv_mutex);
+ UNLOCK_SV_MUTEX;
DEBUG_L(WITH_THR(PerlIO_printf(PerlIO_stderr(),
"%p: condpair_magic %p\n", thr, sv));)
}
}
/*
- * Make a new perl thread structure using t as a prototype. If t is NULL
- * then this is the initial main thread and we have to bootstrap carefully.
- * Some of the fields for the new thread are copied from the prototype
- * thread, t, so t should not be running in perl at the time this function
- * is called. The usual case, where t is the thread calling new_struct_thread,
- * clearly satisfies this constraint.
+ * Make a new perl thread structure using t as a prototype. Some of the
+ * fields for the new thread are copied from the prototype thread, t,
+ * so t should not be running in perl at the time this function is
+ * called. The use by ext/Thread/Thread.xs in core perl (where t is the
+ * thread calling new_struct_thread) clearly satisfies this constraint.
*/
-struct thread *
-new_struct_thread(t)
-struct thread *t;
+struct perl_thread *
+new_struct_thread(struct perl_thread *t)
{
- struct thread *thr;
- XPV *xpv;
+ struct perl_thread *thr;
SV *sv;
+ SV **svp;
+ I32 i;
+
+ sv = newSVpv("", 0);
+ SvGROW(sv, sizeof(struct perl_thread) + 1);
+ SvCUR_set(sv, sizeof(struct perl_thread));
+ thr = (Thread) SvPVX(sv);
+ /* debug */
+ memset(thr, 0xab, sizeof(struct perl_thread));
+ markstack = 0;
+ scopestack = 0;
+ savestack = 0;
+ retstack = 0;
+ dirty = 0;
+ localizing = 0;
+ /* end debug */
+
+ thr->oursv = sv;
+ init_stacks(ARGS);
- Newz(53, thr, 1, struct thread);
- cvcache = newHV();
curcop = &compiling;
- thr->magicals = newAV();
+ thr->cvcache = newHV();
+ thr->threadsv = newAV();
thr->specific = newAV();
+ thr->errsv = newSVpv("", 0);
+ thr->errhv = newHV();
thr->flags = THRf_R_JOINABLE;
MUTEX_INIT(&thr->mutex);
- if (t) {
- oursv = newSVpv("", 0);
- SvGROW(oursv, sizeof(struct thread) + 1);
- SvCUR_set(oursv, sizeof(struct thread));
- thr = (struct thread *) SvPVX(sv);
- } else {
- /* Handcraft thrsv similarly to mess_sv */
- New(53, thrsv, 1, SV);
- Newz(53, xpv, 1, XPV);
- SvFLAGS(thrsv) = SVt_PV;
- SvANY(thrsv) = (void*)xpv;
- SvREFCNT(thrsv) = 1 << 30; /* practically infinite */
- SvPVX(thrsv) = (char*)thr;
- SvCUR_set(thrsv, sizeof(thr));
- SvLEN_set(thrsv, sizeof(thr));
- *SvEND(thrsv) = '\0'; /* in the trailing_nul field */
- oursv = thrsv;
- }
- if (t) {
- curcop = t->Tcurcop; /* XXX As good a guess as any? */
- defstash = t->Tdefstash; /* XXX maybe these should */
- curstash = t->Tcurstash; /* always be set to main? */
- /* top_env? */
- /* runlevel */
- tainted = t->Ttainted;
- curpm = t->Tcurpm; /* XXX No PMOP ref count */
- nrs = newSVsv(t->Tnrs);
- rs = newSVsv(t->Trs);
- last_in_gv = (GV*)SvREFCNT_inc(t->Tlast_in_gv);
- ofslen = t->Tofslen;
- ofs = savepvn(t->Tofs, ofslen);
- defoutgv = (GV*)SvREFCNT_inc(t->Tdefoutgv);
- chopset = t->Tchopset;
- formtarget = newSVsv(t->Tformtarget);
- bodytarget = newSVsv(t->Tbodytarget);
- toptarget = newSVsv(t->Ttoptarget);
- } else {
- curcop = &compiling;
- chopset = " \n-";
- }
+
+ curcop = t->Tcurcop; /* XXX As good a guess as any? */
+ defstash = t->Tdefstash; /* XXX maybe these should */
+ curstash = t->Tcurstash; /* always be set to main? */
+
+
+ /* top_env needs to be non-zero. It points to an area
+ in which longjmp() stuff is stored, as C callstack
+ info there at least is thread specific this has to
+ be per-thread. Otherwise a 'die' in a thread gives
+ that thread the C stack of last thread to do an eval {}!
+ See comments in scope.h
+ Initialize top entry (as in perl.c for main thread)
+ */
+ start_env.je_prev = NULL;
+ start_env.je_ret = -1;
+ start_env.je_mustcatch = TRUE;
+ top_env = &start_env;
+
+ in_eval = FALSE;
+ restartop = 0;
+
+ tainted = t->Ttainted;
+ curpm = t->Tcurpm; /* XXX No PMOP ref count */
+ nrs = newSVsv(t->Tnrs);
+ rs = newSVsv(t->Trs);
+ last_in_gv = (GV*)SvREFCNT_inc(t->Tlast_in_gv);
+ ofslen = t->Tofslen;
+ ofs = savepvn(t->Tofs, ofslen);
+ defoutgv = (GV*)SvREFCNT_inc(t->Tdefoutgv);
+ chopset = t->Tchopset;
+ formtarget = newSVsv(t->Tformtarget);
+ bodytarget = newSVsv(t->Tbodytarget);
+ toptarget = newSVsv(t->Ttoptarget);
+
+ /* Initialise all per-thread SVs that the template thread used */
+ svp = AvARRAY(t->threadsv);
+ for (i = 0; i <= AvFILLp(t->threadsv); i++, svp++) {
+ if (*svp && *svp != &sv_undef) {
+ SV *sv = newSVsv(*svp);
+ av_store(thr->threadsv, i, sv);
+ sv_magic(sv, 0, 0, &threadsv_names[i], 1);
+ DEBUG_L(PerlIO_printf(PerlIO_stderr(),
+ "new_struct_thread: copied threadsv %d %p->%p\n",i, t, thr));
+ }
+ }
+ thr->threadsvp = AvARRAY(thr->threadsv);
+
MUTEX_LOCK(&threads_mutex);
nthreads++;
- thr->tid = threadnum++;
- if (t) {
- thr->next = t->next;
- thr->prev = t;
- t->next = thr;
- thr->next->prev = thr;
- } else {
- thr->next = thr;
- thr->prev = thr;
- }
+ thr->tid = ++threadnum;
+ thr->next = t->next;
+ thr->prev = t;
+ t->next = thr;
+ thr->next->prev = thr;
MUTEX_UNLOCK(&threads_mutex);
#ifdef HAVE_THREAD_INTERN
init_thread_intern(thr);
-#else
- thr->self = pthread_self();
#endif /* HAVE_THREAD_INTERN */
- SET_THR(thr);
- if (!t) {
- /*
- * These must come after the SET_THR because sv_setpvn does
- * SvTAINT and the taint fields require dTHR.
- */
- toptarget = NEWSV(0,0);
- sv_upgrade(toptarget, SVt_PVFM);
- sv_setpvn(toptarget, "", 0);
- bodytarget = NEWSV(0,0);
- sv_upgrade(bodytarget, SVt_PVFM);
- sv_setpvn(bodytarget, "", 0);
- formtarget = bodytarget;
- }
return thr;
}
#endif /* USE_THREADS */
* Needed for SunOS with Sun's 'acc' for example.
*/
double
-Perl_huge()
+Perl_huge(void)
{
return HUGE_VAL;
}
#endif
+
+#ifdef PERL_GLOBAL_STRUCT
+struct perl_vars *
+Perl_GetVars(void)
+{
+ return &Perl_Vars;
+}
+#endif
+
+char **
+get_op_names(void)
+{
+ return op_name;
+}
+
+char **
+get_op_descs(void)
+{
+ return op_desc;
+}