/* 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.
/* safe version of free */
-void
+Free_t
safefree(where)
Malloc_t where;
{
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;
/* 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;
}
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
{
va_list args;
char *message;
- int oldrunlevel = runlevel;
+ I32 oldrunlevel = runlevel;
int was_in_eval = in_eval;
HV *stash;
GV *gv;
restartop = die_where(message);
if ((!restartop && was_in_eval) || oldrunlevel > 1)
- Siglongjmp(top_env, 3);
+ JMPENV_JUMP(3);
return restartop;
}
}
if (in_eval) {
restartop = die_where(message);
- Siglongjmp(top_env, 3);
+ JMPENV_JUMP(3);
}
PerlIO_puts(PerlIO_stderr(),message);
(void)PerlIO_flush(PerlIO_stderr());
}
#ifndef VMS /* VMS' my_setenv() is in VMS.c */
+#ifndef _WIN32
void
my_setenv(nam,val)
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++;
} /* 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
}
#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)
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;
{
SV *sv;
SV** svp;
- char spid[16];
+ char spid[TYPE_CHARS(int)];
if (!pid)
return -1;
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);
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++;
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;