X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/1e422769b80038b1bfc4f5af33438b87cc1c7a22..324aa91a3e6fd44523a86df7c5575563c5adf45c:/util.c diff --git a/util.c b/util.c index 94aeccf..e78ad82 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,6 @@ /* util.c * - * Copyright (c) 1991-1994, Larry Wall + * Copyright (c) 1991-1997, 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. @@ -150,7 +150,7 @@ MEM_SIZE size; /* safe version of free */ -void +Free_t safefree(where) Malloc_t where; { @@ -185,13 +185,13 @@ MEM_SIZE size; if ((long)size < 0 || (long)count < 0) croak("panic: calloc"); #endif + 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)); #else DEBUG_m(PerlIO_printf(PerlIO_stderr(), "0x%lx: (%05d) calloc %ld x %ld bytes\n",ptr,an++,(long)count,(long)size)); #endif - size *= count; - ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */ if (ptr != Nullch) { memset((void*)ptr, 0, size); return ptr; @@ -282,28 +282,35 @@ xstat() /* copy a string up to some (non-backslashed) delimiter, if any */ char * -cpytill(to,from,fromend,delim,retlen) +delimcpy(to, toend, from, fromend, delim, retlen) register char *to; +register char *toend; register char *from; register char *fromend; register int delim; I32 *retlen; { - char *origto = to; - - for (; from < fromend; from++,to++) { + register I32 tolen; + for (tolen = 0; from < fromend; from++, tolen++) { if (*from == '\\') { if (from[1] == delim) from++; - else if (from[1] == '\\') - *to++ = *from++; + else { + if (to < toend) + *to++ = *from; + tolen++; + from++; + } } - else if (*from == delim) + else if (*from == delim) { + if (to < toend) + *to = '\0'; break; - *to = *from; + } + if (to < toend) + *to++ = *from; } - *to = '\0'; - *retlen = to - origto; + *retlen = tolen; return from; } @@ -1071,79 +1078,78 @@ register I32 len; return newaddr; } +/* the SV for form() and mess() is not kept in an arena */ + +static SV * +mess_alloc() +{ + SV *sv; + XPVMG *any; + + /* Create as PVMG now, to avoid any upgrading later */ + New(905, sv, 1, SV); + Newz(905, any, 1, XPVMG); + SvFLAGS(sv) = SVt_PVMG; + SvANY(sv) = (void*)any; + SvREFCNT(sv) = 1 << 30; /* practically infinite */ + return sv; +} + #ifdef I_STDARG char * -mess(const char *pat, va_list *args) +form(const char* pat, ...) #else /*VARARGS0*/ char * -mess(pat, args) +form(pat, va_alist) const char *pat; - va_list *args; + va_dcl #endif { - char *s; - char *s_start; - SV *tmpstr; - I32 usermess; -#ifndef HAS_VPRINTF -#ifdef USE_CHAR_VSPRINTF - char *vsprintf(); + va_list args; +#ifdef I_STDARG + va_start(args, pat); #else - I32 vsprintf(); -#endif + va_start(args); #endif + if (!mess_sv) + mess_sv = mess_alloc(); + sv_vsetpvfn(mess_sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); + va_end(args); + return SvPVX(mess_sv); +} - s = s_start = buf; - usermess = strEQ(pat, "%s"); - if (usermess) { - tmpstr = sv_newmortal(); - sv_setpv(tmpstr, va_arg(*args, char *)); - *s++ = SvCUR(tmpstr) ? SvPVX(tmpstr)[SvCUR(tmpstr)-1] : ' '; - } - else { - (void) vsprintf(s,pat,*args); - s += strlen(s); - } - va_end(*args); +char * +mess(pat, args) + const char *pat; + va_list *args; +{ + SV *sv; + static char dgd[] = " during global destruction.\n"; - if (!(s > s_start && s[-1] == '\n')) { + if (!mess_sv) + mess_sv = mess_alloc(); + sv = mess_sv; + sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); + if (!SvCUR(sv) || *(SvEND(sv) - 1) != '\n') { if (dirty) - strcpy(s, " during global destruction.\n"); + sv_catpv(sv, dgd); else { - if (curcop->cop_line) { - (void)sprintf(s," at %s line %ld", - SvPVX(GvSV(curcop->cop_filegv)), (long)curcop->cop_line); - s += strlen(s); - } + if (curcop->cop_line) + sv_catpvf(sv, " at %_ line %ld", + GvSV(curcop->cop_filegv), (long)curcop->cop_line); if (GvIO(last_in_gv) && IoLINES(GvIOp(last_in_gv))) { bool line_mode = (RsSIMPLE(rs) && SvLEN(rs) == 1 && *SvPVX(rs) == '\n'); - (void)sprintf(s,", <%s> %s %ld", - last_in_gv == argvgv ? "" : GvNAME(last_in_gv), - line_mode ? "line" : "chunk", - (long)IoLINES(GvIOp(last_in_gv))); - s += strlen(s); + sv_catpvf(sv, ", <%s> %s %ld", + last_in_gv == argvgv ? "" : GvNAME(last_in_gv), + line_mode ? "line" : "chunk", + (long)IoLINES(GvIOp(last_in_gv))); } - (void)strcpy(s,".\n"); - s += 2; + sv_catpv(sv, ".\n"); } - if (usermess) - sv_catpv(tmpstr,buf+1); - } - - if (s - s_start >= sizeof(buf)) { /* Ooops! */ - if (usermess) - PerlIO_puts(PerlIO_stderr(), SvPVX(tmpstr)); - else - PerlIO_puts(PerlIO_stderr(), buf); - PerlIO_puts(PerlIO_stderr(), "panic: message overflow - memory corrupted!\n"); - my_exit(1); } - if (usermess) - return SvPVX(tmpstr); - else - return buf; + return SvPVX(sv); } #ifdef I_STDARG @@ -1159,7 +1165,7 @@ die(pat, va_alist) { va_list args; char *message; - int oldrunlevel = runlevel; + I32 oldrunlevel = runlevel; int was_in_eval = in_eval; HV *stash; GV *gv; @@ -1209,7 +1215,7 @@ die(pat, va_alist) restartop = die_where(message); if ((!restartop && was_in_eval) || oldrunlevel > 1) - Siglongjmp(top_env, 3); + JMPENV_JUMP(3); return restartop; } @@ -1264,7 +1270,7 @@ croak(pat, va_alist) } if (in_eval) { restartop = die_where(message); - Siglongjmp(top_env, 3); + JMPENV_JUMP(3); } PerlIO_puts(PerlIO_stderr(),message); (void)PerlIO_flush(PerlIO_stderr()); @@ -1329,6 +1335,7 @@ warn(pat,va_alist) } #ifndef VMS /* VMS' my_setenv() is in VMS.c */ +#ifndef _WIN32 void my_setenv(nam,val) char *nam, *val; @@ -1349,6 +1356,7 @@ char *nam, *val; environ = tmpenv; /* tell exec where it is now */ } if (!val) { + Safefree(environ[i]); while (environ[i]) { environ[i] = environ[i+1]; i++; @@ -1387,6 +1395,36 @@ char *nam; } /* 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 @@ -1424,6 +1462,21 @@ register I32 len; } #endif +#ifndef HAS_MEMSET +void * +my_memset(loc,ch,len) +register char *loc; +register I32 ch; +register I32 len; +{ + char *retval = loc; + + while (len--) + *loc++ = ch; + return retval; +} +#endif + #if !defined(HAS_BZERO) && !defined(HAS_MEMSET) char * my_bzero(loc,len) @@ -1764,15 +1817,23 @@ int newfd; close(newfd); return fcntl(oldfd, F_DUPFD, newfd); #else - int fdtmp[256]; +#define DUP2_MAX_FDS 256 + int fdtmp[DUP2_MAX_FDS]; I32 fdx = 0; int fd; if (oldfd == newfd) return oldfd; close(newfd); - while ((fd = dup(oldfd)) != newfd && fd >= 0) /* good enough for low fd's */ + /* good enough for low fd's... */ + while ((fd = dup(oldfd)) != newfd && fd >= 0) { + if (fdx >= DUP2_MAX_FDS) { + close(fd); + fd = -1; + break; + } fdtmp[fdx++] = fd; + } while (fdx > 0) close(fdtmp[--fdx]); return fd; @@ -1939,7 +2000,7 @@ int flags; { SV *sv; SV** svp; - char spid[16]; + char spid[TYPE_CHARS(int)]; if (!pid) return -1; @@ -1995,7 +2056,7 @@ int pid; int status; { register SV *sv; - char spid[16]; + char spid[TYPE_CHARS(int)]; sprintf(spid, "%d", pid); sv = *hv_fetch(pidstatus,spid,strlen(spid),TRUE); @@ -2133,10 +2194,7 @@ char *b; char *fb = strrchr(b,'/'); struct stat tmpstatbuf1; struct stat tmpstatbuf2; -#ifndef MAXPATHLEN -#define MAXPATHLEN 1024 -#endif - char tmpbuf[MAXPATHLEN+1]; + SV *tmpsv = sv_newmortal(); if (fa) fa++; @@ -2149,16 +2207,16 @@ char *b; if (strNE(a,b)) return FALSE; if (fa == a) - strcpy(tmpbuf,"."); + sv_setpv(tmpsv, "."); else - strncpy(tmpbuf, a, fa - a); - if (Stat(tmpbuf, &tmpstatbuf1) < 0) + sv_setpvn(tmpsv, a, fa - a); + if (Stat(SvPVX(tmpsv), &tmpstatbuf1) < 0) return FALSE; if (fb == b) - strcpy(tmpbuf,"."); + sv_setpv(tmpsv, "."); else - strncpy(tmpbuf, b, fb - b); - if (Stat(tmpbuf, &tmpstatbuf2) < 0) + sv_setpvn(tmpsv, b, fb - b); + if (Stat(SvPVX(tmpsv), &tmpstatbuf2) < 0) return FALSE; return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev && tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;