X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=util.c;h=0380085995a31357753a26556f9a185f031ff1f4;hb=377729033bd4c3e2f6c0ac6b0d2bde9a83c5da6d;hp=2ee9c0ef907d66a3fadf66760db72055eb6e1876;hpb=03136e130d992186c97de0acd23f4857b1a277da;p=p5sagit%2Fp5-mst-13.2.git diff --git a/util.c b/util.c index 2ee9c0e..0380085 100644 --- a/util.c +++ b/util.c @@ -56,6 +56,10 @@ static void xstat _((void)); #endif +#ifdef USE_THREADS +static U32 threadnum = 0; +#endif /* USE_THREADS */ + #ifndef MYMALLOC /* paranoid version of malloc */ @@ -67,8 +71,7 @@ static void xstat _((void)); */ Malloc_t -safemalloc(size) -MEM_SIZE size; +safemalloc(MEM_SIZE size) { Malloc_t ptr; #ifdef HAS_64K_LIMIT @@ -94,6 +97,7 @@ MEM_SIZE size; else { PerlIO_puts(PerlIO_stderr(),no_mem) FLUSH; my_exit(1); + return Nullch; } /*NOTREACHED*/ } @@ -101,9 +105,7 @@ MEM_SIZE size; /* 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) @@ -144,6 +146,7 @@ MEM_SIZE size; else { PerlIO_puts(PerlIO_stderr(),no_mem) FLUSH; my_exit(1); + return Nullch; } /*NOTREACHED*/ } @@ -151,13 +154,12 @@ MEM_SIZE size; /* 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*/ @@ -168,9 +170,7 @@ Malloc_t 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; @@ -188,9 +188,9 @@ MEM_SIZE size; size *= count; ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */ #if !(defined(I286) || defined(atarist)) - DEBUG_m(PerlIO_printf(PerlIO_stderr(), "0x%x: (%05d) calloc %ld x %ld bytes\n",ptr,an++,(long)count,(long)size)); + DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%x: (%05d) calloc %ld x %ld bytes\n",ptr,an++,(long)count,(long)size)); #else - DEBUG_m(PerlIO_printf(PerlIO_stderr(), "0x%lx: (%05d) calloc %ld x %ld bytes\n",ptr,an++,(long)count,(long)size)); + DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) calloc %ld x %ld bytes\n",ptr,an++,(long)count,(long)size)); #endif if (ptr != Nullch) { memset((void*)ptr, 0, size); @@ -201,6 +201,7 @@ MEM_SIZE size; else { PerlIO_puts(PerlIO_stderr(),no_mem) FLUSH; my_exit(1); + return Nullch; } /*NOTREACHED*/ } @@ -212,9 +213,7 @@ MEM_SIZE size; #define ALIGN sizeof(long) Malloc_t -safexmalloc(x,size) -I32 x; -MEM_SIZE size; +safexmalloc(I32 x, MEM_SIZE size) { register Malloc_t where; @@ -226,17 +225,14 @@ MEM_SIZE size; } Malloc_t -safexrealloc(where,size) -Malloc_t where; -MEM_SIZE size; +safexrealloc(Malloc_t where, MEM_SIZE size) { register Malloc_t new = saferealloc(where - ALIGN, size + ALIGN); return new + ALIGN; } void -safexfree(where) -Malloc_t where; +safexfree(Malloc_t where) { I32 x; @@ -249,10 +245,7 @@ Malloc_t 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; @@ -265,7 +258,7 @@ MEM_SIZE size; } static void -xstat() +xstat(void) { register I32 i; @@ -282,13 +275,7 @@ xstat() /* 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++) { @@ -302,14 +289,13 @@ I32 *retlen; from++; } } - else if (*from == delim) { - if (to < toend) - *to = '\0'; + else if (*from == delim) break; - } if (to < toend) *to++ = *from; } + if (to < toend) + *to = '\0'; *retlen = tolen; return from; } @@ -318,9 +304,7 @@ I32 *retlen; /* 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; @@ -350,11 +334,7 @@ register char *little; /* 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; @@ -383,11 +363,7 @@ char *lend; /* 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; @@ -417,8 +393,7 @@ char *lend; * Set up for a new ctype locale. */ void -perl_new_ctype(newctype) - char *newctype; +perl_new_ctype(char *newctype) { #ifdef USE_LOCALE_CTYPE @@ -440,8 +415,7 @@ perl_new_ctype(newctype) * Set up for a new collation locale. */ void -perl_new_collate(newcoll) - char *newcoll; +perl_new_collate(char *newcoll) { #ifdef USE_LOCALE_COLLATE @@ -485,8 +459,7 @@ perl_new_collate(newcoll) * Set up for a new numeric locale. */ void -perl_new_numeric(newnum) - char *newnum; +perl_new_numeric(char *newnum) { #ifdef USE_LOCALE_NUMERIC @@ -511,7 +484,7 @@ perl_new_numeric(newnum) } void -perl_set_numeric_standard() +perl_set_numeric_standard(void) { #ifdef USE_LOCALE_NUMERIC @@ -525,7 +498,7 @@ perl_set_numeric_standard() } void -perl_set_numeric_local() +perl_set_numeric_local(void) { #ifdef USE_LOCALE_NUMERIC @@ -543,8 +516,7 @@ perl_set_numeric_local() * Initialize locale awareness. */ int -perl_init_i18nl10n(printwarn) - int printwarn; +perl_init_i18nl10n(int printwarn) { int ok = 1; /* returns @@ -692,7 +664,7 @@ perl_init_i18nl10n(printwarn) && strnNE(*e, "LC_ALL=", 7) && (p = strchr(*e, '='))) PerlIO_printf(PerlIO_stderr(), "\t%.*s = \"%s\",\n", - (p - *e), *e, p + 1); + (int)(p - *e), *e, p + 1); } } @@ -773,8 +745,7 @@ perl_init_i18nl10n(printwarn) /* Backwards compatibility. */ int -perl_init_i18nl14n(printwarn) - int printwarn; +perl_init_i18nl14n(int printwarn) { return perl_init_i18nl10n(printwarn); } @@ -789,10 +760,7 @@ perl_init_i18nl14n(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; @@ -842,8 +810,7 @@ mem_collxfrm(s, len, xlen) #endif /* USE_LOCALE_COLLATE */ void -fbm_compile(sv) -SV *sv; +fbm_compile(SV *sv) { register unsigned char *s; register unsigned char *table; @@ -852,22 +819,24 @@ SV *sv; 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); @@ -884,10 +853,7 @@ SV *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; @@ -900,8 +866,23 @@ SV *littlestr; 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); } @@ -911,13 +892,32 @@ SV *littlestr; 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; } @@ -947,22 +947,35 @@ SV *littlestr; 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; @@ -970,60 +983,69 @@ SV *littlestr; 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; @@ -1036,9 +1058,7 @@ register I32 len; } 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; @@ -1053,8 +1073,7 @@ register I32 len; /* copy a string to a safe spot */ char * -savepv(sv) -char *sv; +savepv(char *sv) { register char *newaddr; @@ -1066,9 +1085,7 @@ char *sv; /* 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; @@ -1081,7 +1098,7 @@ register I32 len; /* the SV for form() and mess() is not kept in an arena */ static SV * -mess_alloc() +mess_alloc(void) { SV *sv; XPVMG *any; @@ -1120,9 +1137,7 @@ form(pat, va_alist) } 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"; @@ -1132,6 +1147,7 @@ mess(pat, args) sv = mess_sv; sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); if (!SvCUR(sv) || *(SvEND(sv) - 1) != '\n') { + dTHR; if (dirty) sv_catpv(sv, dgd); else { @@ -1163,14 +1179,19 @@ die(pat, va_alist) va_dcl #endif { + dTHR; va_list args; char *message; - I32 oldrunlevel = runlevel; int was_in_eval = in_eval; HV *stash; GV *gv; CV *cv; +#ifdef USE_THREADS + DEBUG_L(PerlIO_printf(PerlIO_stderr(), + "%p: die: curstack = %p, mainstack = %p\n", + thr, curstack, mainstack)); +#endif /* USE_THREADS */ /* 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 */ @@ -1187,6 +1208,11 @@ die(pat, va_alist) message = mess(pat, &args); va_end(args); +#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; @@ -1214,7 +1240,12 @@ die(pat, va_alist) } restartop = die_where(message); - if ((!restartop && was_in_eval) || oldrunlevel > 1) +#ifdef USE_THREADS + DEBUG_L(PerlIO_printf(PerlIO_stderr(), + "%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; } @@ -1230,6 +1261,7 @@ croak(pat, va_alist) va_dcl #endif { + dTHR; va_list args; char *message; HV *stash; @@ -1243,6 +1275,9 @@ croak(pat, va_alist) #endif message = mess(pat, &args); va_end(args); +#ifdef USE_THREADS + DEBUG_L(PerlIO_printf(PerlIO_stderr(), "croak: 0x%lx %s", (unsigned long) thr, message)); +#endif /* USE_THREADS */ if (diehook) { /* sv_2cv might call croak() */ SV *olddiehook = diehook; @@ -1303,6 +1338,7 @@ warn(pat,va_alist) if (warnhook) { /* sv_2cv might call warn() */ + dTHR; SV *oldwarnhook = warnhook; ENTER; SAVESPTR(warnhook); @@ -1335,10 +1371,9 @@ warn(pat,va_alist) } #ifndef VMS /* VMS' my_setenv() is in VMS.c */ -#ifndef _WIN32 +#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? */ @@ -1383,48 +1418,91 @@ char *nam, *val; #endif /* MSDOS */ } +#else /* if WIN32 */ + +void +my_setenv(char *nam,char *val) +{ + +#ifdef USE_WIN32_RTL_ENV + + register char *envstr; + STRLEN namlen = strlen(nam); + STRLEN vallen; + char *oldstr = environ[setenv_getix(nam)]; + + /* putenv() has totally broken semantics in both the Borland + * and Microsoft CRTLs. They either store the passed pointer in + * the environment without making a copy, or make a copy and don't + * free it. And on top of that, they dont free() old entries that + * are being replaced/deleted. This means the caller must + * free any old entries somehow, or we end up with a memory + * leak every time my_setenv() is called. One might think + * one could directly manipulate environ[], like the UNIX code + * above, but direct changes to environ are not allowed when + * calling putenv(), since the RTLs maintain an internal + * *copy* of environ[]. Bad, bad, *bad* stink. + * GSAR 97-06-07 + */ + + if (!val) { + if (!oldstr) + return; + val = ""; + vallen = 0; + } + else + vallen = strlen(val); + New(904, envstr, namlen + vallen + 3, char); + (void)sprintf(envstr,"%s=%s",nam,val); + (void)putenv(envstr); + if (oldstr) + Safefree(oldstr); +#ifdef _MSC_VER + Safefree(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); + +#endif +} + +#endif /* WIN32 */ + I32 -setenv_getix(nam) -char *nam; +setenv_getix(char *nam) { register I32 i, len = strlen(nam); for (i = 0; environ[i]; i++) { - if (strnEQ(environ[i],nam,len) && environ[i][len] == '=') + if ( +#ifdef WIN32 + strnicmp(environ[i],nam,len) == 0 +#else + strnEQ(environ[i],nam,len) +#endif + && environ[i][len] == '=') break; /* strnEQ must come first to avoid */ } /* potential SEGV's */ return i; } -#else /* if _WIN32 */ - -void -my_setenv(nam,val) -char *nam, *val; -{ - register char *envstr; - STRLEN namlen = strlen(nam); - STRLEN vallen = strlen(val ? val : ""); - - New(904, envstr, namlen + vallen + 3, char); - (void)sprintf(envstr,"%s=%s",nam,val); - if (!vallen) { - /* An attempt to delete the entry. - * We try to fix a Win32 process handling goof: Children - * of the current process will end up seeing the - * grandparent's entry if the current process has never - * modified the entry being deleted. So we call _putenv() - * twice: once to pretend to modify the entry, and the - * second time to actually delete it. GSAR 97-03-19 - */ - envstr[namlen+1] = 'X'; envstr[namlen+2] = '\0'; - (void)_putenv(envstr); - envstr[namlen+1] = '\0'; - } - (void)_putenv(envstr); -} - -#endif /* _WIN32 */ #endif /* !VMS */ #ifdef UNLINK_ALL_VERSIONS @@ -1441,10 +1519,7 @@ char *f; #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; @@ -1696,12 +1771,10 @@ VTOH(vtohl,long) /* 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,"-"); @@ -1713,15 +1786,15 @@ char *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"); } while ((pid = (doexec?vfork():fork())) < 0) { if (errno != EAGAIN) { - close(p[this]); + close(p[This]); if (!doexec) croak("Can't fork"); return Nullfp; @@ -1732,7 +1805,7 @@ char *mode; GV* tmpgv; #define THIS that -#define THAT this +#define THAT This close(p[THAT]); if (p[THIS] != (*mode == 'r')) { dup2(p[THIS], *mode == 'r'); @@ -1762,16 +1835,16 @@ char *mode; } 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]; + if (p[that] < p[This]) { + dup2(p[This], p[that]); + 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) @@ -1845,9 +1918,7 @@ int newfd; #ifdef HAS_SIGACTION Sighandler_t -rsignal(signo, handler) -int signo; -Sighandler_t handler; +rsignal(int signo, Sighandler_t handler) { struct sigaction act, oact; @@ -1864,8 +1935,7 @@ Sighandler_t handler; } Sighandler_t -rsignal_state(signo) -int signo; +rsignal_state(int signo) { struct sigaction oact; @@ -1876,10 +1946,7 @@ int signo; } 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; @@ -1893,9 +1960,7 @@ Sigsave_t *save; } int -rsignal_restore(signo, save) -int signo; -Sigsave_t *save; +rsignal_restore(int signo, Sigsave_t *save) { return sigaction(signo, save, (struct sigaction *)NULL); } @@ -1903,9 +1968,7 @@ Sigsave_t *save; #else /* !HAS_SIGACTION */ Sighandler_t -rsignal(signo, handler) -int signo; -Sighandler_t handler; +rsignal(int signo, Sighandler_t handler) { return signal(signo, handler); } @@ -1914,15 +1977,13 @@ 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; @@ -1935,19 +1996,14 @@ int signo; } 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); 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; } @@ -1957,8 +2013,7 @@ Sigsave_t *save; /* 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; @@ -1969,6 +2024,9 @@ PerlIO *ptr; #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); @@ -1984,6 +2042,9 @@ PerlIO *ptr; #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 */ @@ -2005,12 +2066,9 @@ PerlIO *ptr; } #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; @@ -2041,11 +2099,17 @@ int flags; } } #ifdef HAS_WAITPID +# ifdef HAS_WAITPID_RUNTIME + if (!HAS_WAITPID_RUNTIME) + goto hard_way; +# endif return waitpid(pid,statusp,flags); -#else -#ifdef HAS_WAIT4 +#endif +#if !defined(HAS_WAITPID) && defined(HAS_WAIT4) return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *)); -#else +#endif +#if !defined(HAS_WAITPID) && !defined(HAS_WAIT4) || defined(HAS_WAITPID_RUNTIME) + hard_way: { I32 result; if (flags) @@ -2059,15 +2123,12 @@ int flags; return result; } #endif -#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)]; @@ -2100,11 +2161,7 @@ PerlIO *ptr; #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; @@ -2238,10 +2295,7 @@ char *b; #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; @@ -2263,29 +2317,257 @@ I32 *retlen; } 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; - 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++; } *retlen = s - start; return retval; } +#ifdef USE_THREADS +#ifdef FAKE_THREADS +/* Very simplistic scheduler for now */ +void +schedule(void) +{ + thr = thr->i.next_run; +} + +void +perl_cond_init(cp) +perl_cond *cp; +{ + *cp = 0; +} + +void +perl_cond_signal(cp) +perl_cond *cp; +{ + perl_os_thread t; + perl_cond cond = *cp; + + if (!cond) + return; + t = cond->thread; + /* Insert t in the runnable queue just ahead of us */ + t->i.next_run = thr->i.next_run; + thr->i.next_run->i.prev_run = t; + t->i.prev_run = thr; + thr->i.next_run = t; + thr->i.wait_queue = 0; + /* Remove from the wait queue */ + *cp = cond->next; + Safefree(cond); +} + +void +perl_cond_broadcast(cp) +perl_cond *cp; +{ + perl_os_thread t; + perl_cond cond, cond_next; + + for (cond = *cp; cond; cond = cond_next) { + t = cond->thread; + /* Insert t in the runnable queue just ahead of us */ + t->i.next_run = thr->i.next_run; + thr->i.next_run->i.prev_run = t; + t->i.prev_run = thr; + thr->i.next_run = t; + thr->i.wait_queue = 0; + /* Remove from the wait queue */ + cond_next = cond->next; + Safefree(cond); + } + *cp = 0; +} + +void +perl_cond_wait(cp) +perl_cond *cp; +{ + perl_cond cond; + + if (thr->i.next_run == thr) + croak("panic: perl_cond_wait called by last runnable thread"); + + New(666, cond, 1, struct perl_wait_queue); + cond->thread = thr; + cond->next = *cp; + *cp = cond; + thr->i.wait_queue = cond; + /* Remove ourselves from runnable queue */ + thr->i.next_run->i.prev_run = thr->i.prev_run; + thr->i.prev_run->i.next_run = thr->i.next_run; +} +#endif /* FAKE_THREADS */ + +#ifdef OLD_PTHREADS_API +struct perl_thread * +getTHR _((void)) +{ + pthread_addr_t t; + + if (pthread_getspecific(thr_key, &t)) + croak("panic: pthread_getspecific"); + return (struct perl_thread *) t; +} +#endif /* OLD_PTHREADS_API */ + +MAGIC * +condpair_magic(SV *sv) +{ + MAGIC *mg; + + SvUPGRADE(sv, SVt_PVMG); + mg = mg_find(sv, 'm'); + if (!mg) { + condpair_t *cp; + + New(53, cp, 1, condpair_t); + MUTEX_INIT(&cp->mutex); + COND_INIT(&cp->owner_cond); + COND_INIT(&cp->cond); + cp->owner = 0; + MUTEX_LOCK(&sv_mutex); + mg = mg_find(sv, 'm'); + if (mg) { + /* someone else beat us to initialising it */ + MUTEX_UNLOCK(&sv_mutex); + MUTEX_DESTROY(&cp->mutex); + COND_DESTROY(&cp->owner_cond); + COND_DESTROY(&cp->cond); + Safefree(cp); + } + else { + sv_magic(sv, Nullsv, 'm', 0, 0); + mg = SvMAGIC(sv); + mg->mg_ptr = (char *)cp; + mg->mg_len = sizeof(cp); + MUTEX_UNLOCK(&sv_mutex); + DEBUG_L(WITH_THR(PerlIO_printf(PerlIO_stderr(), + "%p: condpair_magic %p\n", thr, sv));) + } + } + return mg; +} + +/* + * 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 perl_thread * +new_struct_thread(struct perl_thread *t) +{ + 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); + + curcop = &compiling; + 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); + + 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)); + } + } + + MUTEX_LOCK(&threads_mutex); + nthreads++; + 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); +#endif /* HAVE_THREAD_INTERN */ + return thr; +} +#endif /* USE_THREADS */ #ifdef HUGE_VAL /* @@ -2294,8 +2576,28 @@ I32 *retlen; * 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; +}