This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl5.000 patch.0f: [enable metaconfig (PL48) users to regenerate Configure]
[perl5.git] / util.c
CommitLineData
a0d0e21e 1/* util.c
a687059c 2 *
a0d0e21e 3 * Copyright (c) 1991-1994, Larry Wall
a687059c 4 *
d48672a2
LW
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
8d063cd8 7 *
8d063cd8 8 */
a0d0e21e
LW
9
10/*
11 * "Very useful, no doubt, that was to Saruman; yet it seems that he was
12 * not content." --Gandalf
13 */
8d063cd8 14
8d063cd8 15#include "EXTERN.h"
8d063cd8 16#include "perl.h"
62b28dd9 17
6eb13c3b 18#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
a687059c 19#include <signal.h>
62b28dd9 20#endif
a687059c 21
85e6fe83 22#ifdef I_UNISTD
8990e307
LW
23# include <unistd.h>
24#endif
25
a687059c
LW
26#ifdef I_VFORK
27# include <vfork.h>
28#endif
29
fe14fcc3
LW
30#ifdef I_FCNTL
31# include <fcntl.h>
32#endif
33#ifdef I_SYS_FILE
34# include <sys/file.h>
35#endif
36
8d063cd8 37#define FLUSH
8d063cd8 38
a0d0e21e
LW
39#ifdef LEAKTEST
40static void xstat _((void));
41#endif
42
de3bb511
LW
43#ifndef safemalloc
44
8d063cd8
LW
45/* paranoid version of malloc */
46
a687059c
LW
47/* NOTE: Do not call the next three routines directly. Use the macros
48 * in handy.h, so that we can easily redefine everything to do tracking of
49 * allocated hunks back to the original New to track down any memory leaks.
50 */
51
8d063cd8
LW
52char *
53safemalloc(size)
62b28dd9
LW
54#ifdef MSDOS
55unsigned long size;
56#else
8d063cd8 57MEM_SIZE size;
62b28dd9 58#endif /* MSDOS */
8d063cd8 59{
2304df62 60 char *ptr;
62b28dd9
LW
61#ifdef MSDOS
62 if (size > 0xffff) {
63 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
79072805 64 my_exit(1);
62b28dd9
LW
65 }
66#endif /* MSDOS */
34de22dd
LW
67#ifdef DEBUGGING
68 if ((long)size < 0)
463ee0b2 69 croak("panic: malloc");
34de22dd 70#endif
8d063cd8 71 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
79072805
LW
72#if !(defined(I286) || defined(atarist))
73 DEBUG_m(fprintf(stderr,"0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size));
74#else
75 DEBUG_m(fprintf(stderr,"0x%lx: (%05d) malloc %ld bytes\n",ptr,an++,(long)size));
8d063cd8
LW
76#endif
77 if (ptr != Nullch)
78 return ptr;
7c0587c8
LW
79 else if (nomemok)
80 return Nullch;
8d063cd8 81 else {
79072805
LW
82 fputs(no_mem,stderr) FLUSH;
83 my_exit(1);
8d063cd8
LW
84 }
85 /*NOTREACHED*/
86}
87
88/* paranoid version of realloc */
89
90char *
91saferealloc(where,size)
92char *where;
62b28dd9 93#ifndef MSDOS
8d063cd8 94MEM_SIZE size;
62b28dd9
LW
95#else
96unsigned long size;
97#endif /* MSDOS */
8d063cd8
LW
98{
99 char *ptr;
d48672a2 100#ifndef STANDARD_C
8d063cd8 101 char *realloc();
d48672a2 102#endif /* ! STANDARD_C */
8d063cd8 103
62b28dd9
LW
104#ifdef MSDOS
105 if (size > 0xffff) {
106 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
79072805 107 my_exit(1);
62b28dd9
LW
108 }
109#endif /* MSDOS */
378cc40b 110 if (!where)
463ee0b2 111 croak("Null realloc");
34de22dd
LW
112#ifdef DEBUGGING
113 if ((long)size < 0)
463ee0b2 114 croak("panic: realloc");
34de22dd 115#endif
8d063cd8 116 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
79072805
LW
117
118#if !(defined(I286) || defined(atarist))
119 DEBUG_m( {
8d063cd8 120 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
7c0587c8 121 fprintf(stderr,"0x%x: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
79072805
LW
122 } )
123#else
124 DEBUG_m( {
a687059c 125 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
7c0587c8 126 fprintf(stderr,"0x%lx: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
79072805 127 } )
8d063cd8 128#endif
79072805 129
8d063cd8
LW
130 if (ptr != Nullch)
131 return ptr;
7c0587c8
LW
132 else if (nomemok)
133 return Nullch;
8d063cd8 134 else {
79072805
LW
135 fputs(no_mem,stderr) FLUSH;
136 my_exit(1);
8d063cd8
LW
137 }
138 /*NOTREACHED*/
139}
140
141/* safe version of free */
142
a687059c 143void
8d063cd8
LW
144safefree(where)
145char *where;
146{
79072805
LW
147#if !(defined(I286) || defined(atarist))
148 DEBUG_m( fprintf(stderr,"0x%x: (%05d) free\n",where,an++));
149#else
150 DEBUG_m( fprintf(stderr,"0x%lx: (%05d) free\n",where,an++));
8d063cd8 151#endif
378cc40b 152 if (where) {
de3bb511 153 /*SUPPRESS 701*/
378cc40b
LW
154 free(where);
155 }
8d063cd8
LW
156}
157
de3bb511
LW
158#endif /* !safemalloc */
159
a687059c
LW
160#ifdef LEAKTEST
161
162#define ALIGN sizeof(long)
8d063cd8
LW
163
164char *
a687059c 165safexmalloc(x,size)
79072805 166I32 x;
a687059c 167MEM_SIZE size;
8d063cd8 168{
a687059c 169 register char *where;
8d063cd8 170
a687059c
LW
171 where = safemalloc(size + ALIGN);
172 xcount[x]++;
173 where[0] = x % 100;
174 where[1] = x / 100;
175 return where + ALIGN;
8d063cd8 176}
8d063cd8
LW
177
178char *
a687059c
LW
179safexrealloc(where,size)
180char *where;
181MEM_SIZE size;
182{
a0d0e21e
LW
183 register char *new = saferealloc(where - ALIGN, size + ALIGN);
184 return new + ALIGN;
a687059c
LW
185}
186
187void
188safexfree(where)
189char *where;
190{
79072805 191 I32 x;
a687059c
LW
192
193 if (!where)
194 return;
195 where -= ALIGN;
196 x = where[0] + 100 * where[1];
197 xcount[x]--;
198 safefree(where);
199}
200
7c0587c8 201static void
a687059c 202xstat()
8d063cd8 203{
79072805 204 register I32 i;
8d063cd8 205
a687059c 206 for (i = 0; i < MAXXCOUNT; i++) {
de3bb511 207 if (xcount[i] > lastxcount[i]) {
a687059c
LW
208 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
209 lastxcount[i] = xcount[i];
8d063cd8
LW
210 }
211 }
8d063cd8 212}
a687059c
LW
213
214#endif /* LEAKTEST */
8d063cd8
LW
215
216/* copy a string up to some (non-backslashed) delimiter, if any */
217
218char *
a687059c 219cpytill(to,from,fromend,delim,retlen)
62b28dd9
LW
220register char *to;
221register char *from;
a687059c 222register char *fromend;
a0d0e21e 223register int delim;
79072805 224I32 *retlen;
8d063cd8 225{
a687059c
LW
226 char *origto = to;
227
228 for (; from < fromend; from++,to++) {
378cc40b
LW
229 if (*from == '\\') {
230 if (from[1] == delim)
231 from++;
232 else if (from[1] == '\\')
233 *to++ = *from++;
234 }
8d063cd8
LW
235 else if (*from == delim)
236 break;
237 *to = *from;
238 }
239 *to = '\0';
a687059c 240 *retlen = to - origto;
8d063cd8
LW
241 return from;
242}
243
244/* return ptr to little string in big string, NULL if not found */
378cc40b 245/* This routine was donated by Corey Satten. */
8d063cd8
LW
246
247char *
248instr(big, little)
378cc40b
LW
249register char *big;
250register char *little;
251{
252 register char *s, *x;
79072805 253 register I32 first;
378cc40b 254
a687059c
LW
255 if (!little)
256 return big;
257 first = *little++;
378cc40b
LW
258 if (!first)
259 return big;
260 while (*big) {
261 if (*big++ != first)
262 continue;
263 for (x=big,s=little; *s; /**/ ) {
264 if (!*x)
265 return Nullch;
266 if (*s++ != *x++) {
267 s--;
268 break;
269 }
270 }
271 if (!*s)
272 return big-1;
273 }
274 return Nullch;
275}
8d063cd8 276
a687059c
LW
277/* same as instr but allow embedded nulls */
278
279char *
280ninstr(big, bigend, little, lend)
281register char *big;
282register char *bigend;
283char *little;
284char *lend;
8d063cd8 285{
a687059c 286 register char *s, *x;
79072805 287 register I32 first = *little;
a687059c 288 register char *littleend = lend;
378cc40b 289
a0d0e21e 290 if (!first && little >= littleend)
a687059c 291 return big;
de3bb511
LW
292 if (bigend - big < littleend - little)
293 return Nullch;
a687059c
LW
294 bigend -= littleend - little++;
295 while (big <= bigend) {
296 if (*big++ != first)
297 continue;
298 for (x=big,s=little; s < littleend; /**/ ) {
299 if (*s++ != *x++) {
300 s--;
301 break;
302 }
303 }
304 if (s >= littleend)
305 return big-1;
378cc40b 306 }
a687059c
LW
307 return Nullch;
308}
309
310/* reverse of the above--find last substring */
311
312char *
313rninstr(big, bigend, little, lend)
314register char *big;
315char *bigend;
316char *little;
317char *lend;
318{
319 register char *bigbeg;
320 register char *s, *x;
79072805 321 register I32 first = *little;
a687059c
LW
322 register char *littleend = lend;
323
a0d0e21e 324 if (!first && little >= littleend)
a687059c
LW
325 return bigend;
326 bigbeg = big;
327 big = bigend - (littleend - little++);
328 while (big >= bigbeg) {
329 if (*big-- != first)
330 continue;
331 for (x=big+2,s=little; s < littleend; /**/ ) {
332 if (*s++ != *x++) {
333 s--;
334 break;
335 }
336 }
337 if (s >= littleend)
338 return big+1;
378cc40b 339 }
a687059c 340 return Nullch;
378cc40b 341}
a687059c 342
378cc40b 343void
79072805
LW
344fbm_compile(sv, iflag)
345SV *sv;
346I32 iflag;
378cc40b 347{
a687059c
LW
348 register unsigned char *s;
349 register unsigned char *table;
79072805
LW
350 register U32 i;
351 register U32 len = SvCUR(sv);
352 I32 rarest = 0;
353 U32 frequency = 256;
354
355 Sv_Grow(sv,len+258);
463ee0b2 356 table = (unsigned char*)(SvPVX(sv) + len + 1);
a687059c
LW
357 s = table - 2;
358 for (i = 0; i < 256; i++) {
378cc40b
LW
359 table[i] = len;
360 }
361 i = 0;
463ee0b2 362 while (s >= (unsigned char*)(SvPVX(sv)))
a687059c
LW
363 {
364 if (table[*s] == len) {
365#ifndef pdp11
366 if (iflag)
367 table[*s] = table[fold[*s]] = i;
368#else
369 if (iflag) {
79072805 370 I32 j;
a687059c
LW
371 j = fold[*s];
372 table[j] = i;
373 table[*s] = i;
374 }
375#endif /* pdp11 */
376 else
377 table[*s] = i;
378 }
378cc40b
LW
379 s--,i++;
380 }
79072805 381 sv_upgrade(sv, SVt_PVBM);
a0d0e21e 382 sv_magic(sv, Nullsv, 'B', Nullch, 0); /* deep magic */
79072805 383 SvVALID_on(sv);
378cc40b 384
463ee0b2 385 s = (unsigned char*)(SvPVX(sv)); /* deeper magic */
a687059c 386 if (iflag) {
79072805
LW
387 register U32 tmp, foldtmp;
388 SvCASEFOLD_on(sv);
a687059c
LW
389 for (i = 0; i < len; i++) {
390 tmp=freq[s[i]];
391 foldtmp=freq[fold[s[i]]];
392 if (tmp < frequency && foldtmp < frequency) {
393 rarest = i;
394 /* choose most frequent among the two */
395 frequency = (tmp > foldtmp) ? tmp : foldtmp;
396 }
397 }
398 }
399 else {
400 for (i = 0; i < len; i++) {
401 if (freq[s[i]] < frequency) {
402 rarest = i;
403 frequency = freq[s[i]];
404 }
378cc40b
LW
405 }
406 }
79072805
LW
407 BmRARE(sv) = s[rarest];
408 BmPREVIOUS(sv) = rarest;
409 DEBUG_r(fprintf(stderr,"rarest char %c at %d\n",BmRARE(sv),BmPREVIOUS(sv)));
378cc40b
LW
410}
411
378cc40b 412char *
79072805 413fbm_instr(big, bigend, littlestr)
a687059c
LW
414unsigned char *big;
415register unsigned char *bigend;
79072805 416SV *littlestr;
378cc40b 417{
a687059c 418 register unsigned char *s;
79072805
LW
419 register I32 tmp;
420 register I32 littlelen;
a687059c
LW
421 register unsigned char *little;
422 register unsigned char *table;
423 register unsigned char *olds;
424 register unsigned char *oldlittle;
378cc40b 425
79072805 426 if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) {
a0d0e21e
LW
427 STRLEN len;
428 char *l = SvPV(littlestr,len);
429 if (!len)
d48672a2 430 return (char*)big;
a0d0e21e 431 return ninstr((char*)big,(char*)bigend, l, l + len);
d48672a2 432 }
378cc40b 433
79072805
LW
434 littlelen = SvCUR(littlestr);
435 if (SvTAIL(littlestr) && !multiline) { /* tail anchored? */
0f85fab0
LW
436 if (littlelen > bigend - big)
437 return Nullch;
463ee0b2 438 little = (unsigned char*)SvPVX(littlestr);
79072805 439 if (SvCASEFOLD(littlestr)) { /* oops, fake it */
a687059c
LW
440 big = bigend - littlelen; /* just start near end */
441 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
442 big--;
378cc40b
LW
443 }
444 else {
a687059c
LW
445 s = bigend - littlelen;
446 if (*s == *little && bcmp(s,little,littlelen)==0)
447 return (char*)s; /* how sweet it is */
34de22dd
LW
448 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
449 && s > big) {
a687059c
LW
450 s--;
451 if (*s == *little && bcmp(s,little,littlelen)==0)
452 return (char*)s;
453 }
454 return Nullch;
455 }
456 }
463ee0b2 457 table = (unsigned char*)(SvPVX(littlestr) + littlelen + 1);
62b28dd9
LW
458 if (--littlelen >= bigend - big)
459 return Nullch;
460 s = big + littlelen;
a687059c 461 oldlittle = little = table - 2;
79072805 462 if (SvCASEFOLD(littlestr)) { /* case insensitive? */
20188a90 463 if (s < bigend) {
a687059c 464 top1:
de3bb511 465 /*SUPPRESS 560*/
a687059c 466 if (tmp = table[*s]) {
62b28dd9
LW
467#ifdef POINTERRIGOR
468 if (bigend - s > tmp) {
469 s += tmp;
470 goto top1;
471 }
472#else
473 if ((s += tmp) < bigend)
474 goto top1;
475#endif
476 return Nullch;
a687059c
LW
477 }
478 else {
479 tmp = littlelen; /* less expensive than calling strncmp() */
480 olds = s;
481 while (tmp--) {
482 if (*--s == *--little || fold[*s] == *little)
483 continue;
484 s = olds + 1; /* here we pay the price for failure */
485 little = oldlittle;
486 if (s < bigend) /* fake up continue to outer loop */
487 goto top1;
488 return Nullch;
489 }
a687059c 490 return (char *)s;
a687059c
LW
491 }
492 }
493 }
494 else {
20188a90 495 if (s < bigend) {
a687059c 496 top2:
de3bb511 497 /*SUPPRESS 560*/
a687059c 498 if (tmp = table[*s]) {
62b28dd9
LW
499#ifdef POINTERRIGOR
500 if (bigend - s > tmp) {
501 s += tmp;
502 goto top2;
503 }
504#else
505 if ((s += tmp) < bigend)
506 goto top2;
507#endif
508 return Nullch;
a687059c
LW
509 }
510 else {
511 tmp = littlelen; /* less expensive than calling strncmp() */
512 olds = s;
513 while (tmp--) {
514 if (*--s == *--little)
515 continue;
516 s = olds + 1; /* here we pay the price for failure */
517 little = oldlittle;
518 if (s < bigend) /* fake up continue to outer loop */
519 goto top2;
520 return Nullch;
521 }
a687059c 522 return (char *)s;
378cc40b 523 }
378cc40b
LW
524 }
525 }
526 return Nullch;
527}
528
529char *
530screaminstr(bigstr, littlestr)
79072805
LW
531SV *bigstr;
532SV *littlestr;
378cc40b 533{
a687059c
LW
534 register unsigned char *s, *x;
535 register unsigned char *big;
79072805
LW
536 register I32 pos;
537 register I32 previous;
538 register I32 first;
a687059c
LW
539 register unsigned char *little;
540 register unsigned char *bigend;
541 register unsigned char *littleend;
378cc40b 542
79072805 543 if ((pos = screamfirst[BmRARE(littlestr)]) < 0)
378cc40b 544 return Nullch;
463ee0b2 545 little = (unsigned char *)(SvPVX(littlestr));
79072805 546 littleend = little + SvCUR(littlestr);
378cc40b 547 first = *little++;
79072805 548 previous = BmPREVIOUS(littlestr);
463ee0b2 549 big = (unsigned char *)(SvPVX(bigstr));
79072805 550 bigend = big + SvCUR(bigstr);
378cc40b
LW
551 while (pos < previous) {
552 if (!(pos += screamnext[pos]))
553 return Nullch;
554 }
de3bb511 555#ifdef POINTERRIGOR
79072805 556 if (SvCASEFOLD(littlestr)) { /* case insignificant? */
a687059c 557 do {
988174c1
LW
558 if (big[pos-previous] != first && big[pos-previous] != fold[first])
559 continue;
de3bb511
LW
560 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
561 if (x >= bigend)
562 return Nullch;
563 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
564 s--;
565 break;
566 }
567 }
568 if (s == littleend)
de3bb511 569 return (char *)(big+pos-previous);
de3bb511 570 } while (
de3bb511 571 pos += screamnext[pos] /* does this goof up anywhere? */
de3bb511
LW
572 );
573 }
574 else {
575 do {
988174c1
LW
576 if (big[pos-previous] != first)
577 continue;
de3bb511
LW
578 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
579 if (x >= bigend)
580 return Nullch;
581 if (*s++ != *x++) {
582 s--;
583 break;
584 }
585 }
586 if (s == littleend)
de3bb511 587 return (char *)(big+pos-previous);
79072805 588 } while ( pos += screamnext[pos] );
de3bb511
LW
589 }
590#else /* !POINTERRIGOR */
591 big -= previous;
79072805 592 if (SvCASEFOLD(littlestr)) { /* case insignificant? */
de3bb511 593 do {
988174c1
LW
594 if (big[pos] != first && big[pos] != fold[first])
595 continue;
a687059c
LW
596 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
597 if (x >= bigend)
598 return Nullch;
599 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
600 s--;
601 break;
602 }
603 }
604 if (s == littleend)
a687059c 605 return (char *)(big+pos);
a687059c 606 } while (
a687059c 607 pos += screamnext[pos] /* does this goof up anywhere? */
a687059c
LW
608 );
609 }
610 else {
611 do {
988174c1
LW
612 if (big[pos] != first)
613 continue;
a687059c
LW
614 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
615 if (x >= bigend)
616 return Nullch;
617 if (*s++ != *x++) {
618 s--;
619 break;
620 }
378cc40b 621 }
a687059c 622 if (s == littleend)
a687059c 623 return (char *)(big+pos);
a687059c 624 } while (
a687059c 625 pos += screamnext[pos]
a687059c
LW
626 );
627 }
de3bb511 628#endif /* POINTERRIGOR */
8d063cd8
LW
629 return Nullch;
630}
631
79072805
LW
632I32
633ibcmp(a,b,len)
a0d0e21e
LW
634register U8 *a;
635register U8 *b;
79072805
LW
636register I32 len;
637{
638 while (len--) {
639 if (*a == *b) {
640 a++,b++;
641 continue;
642 }
643 if (fold[*a++] == *b++)
644 continue;
645 return 1;
646 }
647 return 0;
648}
649
8d063cd8
LW
650/* copy a string to a safe spot */
651
652char *
a0d0e21e 653savepv(sv)
79072805 654char *sv;
8d063cd8 655{
a687059c 656 register char *newaddr;
8d063cd8 657
79072805
LW
658 New(902,newaddr,strlen(sv)+1,char);
659 (void)strcpy(newaddr,sv);
8d063cd8
LW
660 return newaddr;
661}
662
a687059c
LW
663/* same thing but with a known length */
664
665char *
a0d0e21e 666savepvn(sv, len)
79072805
LW
667char *sv;
668register I32 len;
a687059c
LW
669{
670 register char *newaddr;
671
672 New(903,newaddr,len+1,char);
79072805 673 Copy(sv,newaddr,len,char); /* might not be null terminated */
a687059c
LW
674 newaddr[len] = '\0'; /* is now */
675 return newaddr;
676}
677
a0d0e21e 678#if !defined(I_STDARG) && !defined(I_VARARGS)
8d063cd8 679
8990e307
LW
680/*
681 * Fallback on the old hackers way of doing varargs
682 */
8d063cd8 683
378cc40b 684/*VARARGS1*/
7c0587c8 685char *
378cc40b
LW
686mess(pat,a1,a2,a3,a4)
687char *pat;
a687059c 688long a1, a2, a3, a4;
378cc40b
LW
689{
690 char *s;
79072805
LW
691 I32 usermess = strEQ(pat,"%s");
692 SV *tmpstr;
378cc40b 693
a687059c 694 s = buf;
de3bb511 695 if (usermess) {
8990e307 696 tmpstr = sv_newmortal();
79072805 697 sv_setpv(tmpstr, (char*)a1);
463ee0b2 698 *s++ = SvPVX(tmpstr)[SvCUR(tmpstr)-1];
de3bb511
LW
699 }
700 else {
701 (void)sprintf(s,pat,a1,a2,a3,a4);
702 s += strlen(s);
703 }
704
378cc40b 705 if (s[-1] != '\n') {
2304df62
AD
706 if (dirty)
707 strcpy(s, " during global destruction.\n");
708 else {
709 if (curcop->cop_line) {
710 (void)sprintf(s," at %s line %ld",
711 SvPVX(GvSV(curcop->cop_filegv)), (long)curcop->cop_line);
712 s += strlen(s);
713 }
a0d0e21e
LW
714 if (GvIO(last_in_gv) &&
715 IoLINES(GvIOp(last_in_gv)) ) {
2304df62
AD
716 (void)sprintf(s,", <%s> %s %ld",
717 last_in_gv == argvgv ? "" : GvENAME(last_in_gv),
718 strEQ(rs,"\n") ? "line" : "chunk",
a0d0e21e 719 (long)IoLINES(GvIOp(last_in_gv)));
2304df62
AD
720 s += strlen(s);
721 }
722 (void)strcpy(s,".\n");
378cc40b 723 }
de3bb511 724 if (usermess)
79072805 725 sv_catpv(tmpstr,buf+1);
378cc40b 726 }
de3bb511 727 if (usermess)
463ee0b2 728 return SvPVX(tmpstr);
de3bb511
LW
729 else
730 return buf;
378cc40b
LW
731}
732
8d063cd8 733/*VARARGS1*/
463ee0b2 734void croak(pat,a1,a2,a3,a4)
8d063cd8 735char *pat;
a687059c 736long a1, a2, a3, a4;
8d063cd8 737{
9f68db38 738 char *tmps;
de3bb511 739 char *message;
8d063cd8 740
de3bb511 741 message = mess(pat,a1,a2,a3,a4);
a0d0e21e
LW
742 if (in_eval) {
743 restartop = die_where(message);
744 longjmp(top_env, 3);
745 }
de3bb511 746 fputs(message,stderr);
a687059c 747 (void)fflush(stderr);
8d063cd8 748 if (e_fp)
a687059c 749 (void)UNLINK(e_tmpname);
378cc40b 750 statusvalue >>= 8;
79072805 751 my_exit((I32)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
378cc40b
LW
752}
753
754/*VARARGS1*/
7c0587c8 755void warn(pat,a1,a2,a3,a4)
378cc40b 756char *pat;
a687059c 757long a1, a2, a3, a4;
378cc40b 758{
de3bb511
LW
759 char *message;
760
761 message = mess(pat,a1,a2,a3,a4);
762 fputs(message,stderr);
a687059c 763#ifdef LEAKTEST
79072805 764 DEBUG_L(xstat());
a687059c
LW
765#endif
766 (void)fflush(stderr);
8d063cd8 767}
8990e307 768
a0d0e21e 769#else /* !defined(I_STDARG) && !defined(I_VARARGS) */
8990e307 770
a0d0e21e 771#ifdef I_STDARG
8990e307 772char *
2304df62 773mess(char *pat, va_list *args)
a687059c
LW
774#else
775/*VARARGS0*/
de3bb511 776char *
8990e307 777mess(pat, args)
a687059c 778 char *pat;
2304df62 779 va_list *args;
8990e307
LW
780#endif
781{
a687059c 782 char *s;
79072805
LW
783 SV *tmpstr;
784 I32 usermess;
d48672a2 785#ifndef HAS_VPRINTF
85e6fe83 786#ifdef USE_CHAR_VSPRINTF
a687059c
LW
787 char *vsprintf();
788#else
79072805 789 I32 vsprintf();
a687059c 790#endif
d48672a2 791#endif
a687059c 792
de3bb511
LW
793 s = buf;
794 usermess = strEQ(pat, "%s");
795 if (usermess) {
8990e307 796 tmpstr = sv_newmortal();
2304df62 797 sv_setpv(tmpstr, va_arg(*args, char *));
463ee0b2 798 *s++ = SvPVX(tmpstr)[SvCUR(tmpstr)-1];
de3bb511
LW
799 }
800 else {
2304df62 801 (void) vsprintf(s,pat,*args);
de3bb511
LW
802 s += strlen(s);
803 }
2304df62 804 va_end(*args);
a687059c 805
a687059c 806 if (s[-1] != '\n') {
2304df62
AD
807 if (dirty)
808 strcpy(s, " during global destruction.\n");
809 else {
810 if (curcop->cop_line) {
811 (void)sprintf(s," at %s line %ld",
812 SvPVX(GvSV(curcop->cop_filegv)), (long)curcop->cop_line);
813 s += strlen(s);
814 }
a0d0e21e
LW
815 if (GvIO(last_in_gv) &&
816 IoLINES(GvIOp(last_in_gv)) ) {
2304df62
AD
817 (void)sprintf(s,", <%s> %s %ld",
818 last_in_gv == argvgv ? "" : GvNAME(last_in_gv),
819 strEQ(rs,"\n") ? "line" : "chunk",
a0d0e21e 820 (long)IoLINES(GvIOp(last_in_gv)));
2304df62
AD
821 s += strlen(s);
822 }
823 (void)strcpy(s,".\n");
a687059c 824 }
de3bb511 825 if (usermess)
79072805 826 sv_catpv(tmpstr,buf+1);
a687059c 827 }
de3bb511
LW
828
829 if (usermess)
463ee0b2 830 return SvPVX(tmpstr);
de3bb511
LW
831 else
832 return buf;
a687059c
LW
833}
834
8990e307 835#ifdef STANDARD_C
79072805 836void
8990e307 837croak(char* pat, ...)
463ee0b2 838#else
8990e307
LW
839/*VARARGS0*/
840void
841croak(pat, va_alist)
842 char *pat;
843 va_dcl
463ee0b2 844#endif
a687059c
LW
845{
846 va_list args;
de3bb511 847 char *message;
a687059c 848
a0d0e21e 849#ifdef I_STDARG
8990e307
LW
850 va_start(args, pat);
851#else
a687059c 852 va_start(args);
8990e307 853#endif
2304df62 854 message = mess(pat, &args);
a687059c 855 va_end(args);
a0d0e21e
LW
856 if (in_eval) {
857 restartop = die_where(message);
79072805 858 longjmp(top_env, 3);
a0d0e21e 859 }
de3bb511 860 fputs(message,stderr);
a687059c
LW
861 (void)fflush(stderr);
862 if (e_fp)
863 (void)UNLINK(e_tmpname);
864 statusvalue >>= 8;
79072805 865 my_exit((I32)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
a687059c
LW
866}
867
8990e307
LW
868void
869#ifdef STANDARD_C
870warn(char* pat,...)
463ee0b2 871#else
8990e307
LW
872/*VARARGS0*/
873warn(pat,va_alist)
874 char *pat;
875 va_dcl
463ee0b2 876#endif
a687059c
LW
877{
878 va_list args;
de3bb511 879 char *message;
a687059c 880
a0d0e21e 881#ifdef I_STDARG
8990e307
LW
882 va_start(args, pat);
883#else
a687059c 884 va_start(args);
8990e307 885#endif
2304df62 886 message = mess(pat, &args);
a687059c
LW
887 va_end(args);
888
de3bb511 889 fputs(message,stderr);
a687059c 890#ifdef LEAKTEST
79072805 891 DEBUG_L(xstat());
a687059c
LW
892#endif
893 (void)fflush(stderr);
894}
a0d0e21e 895#endif /* !defined(I_STDARG) && !defined(I_VARARGS) */
8d063cd8 896
a0d0e21e 897#ifndef VMS /* VMS' my_setenv() is in VMS.c */
8d063cd8 898void
7c0587c8 899my_setenv(nam,val)
8d063cd8
LW
900char *nam, *val;
901{
79072805 902 register I32 i=setenv_getix(nam); /* where does it go? */
8d063cd8 903
fe14fcc3 904 if (environ == origenviron) { /* need we copy environment? */
79072805
LW
905 I32 j;
906 I32 max;
fe14fcc3
LW
907 char **tmpenv;
908
de3bb511 909 /*SUPPRESS 530*/
fe14fcc3
LW
910 for (max = i; environ[max]; max++) ;
911 New(901,tmpenv, max+2, char*);
912 for (j=0; j<max; j++) /* copy environment */
a0d0e21e 913 tmpenv[j] = savepv(environ[j]);
fe14fcc3
LW
914 tmpenv[max] = Nullch;
915 environ = tmpenv; /* tell exec where it is now */
916 }
a687059c
LW
917 if (!val) {
918 while (environ[i]) {
919 environ[i] = environ[i+1];
920 i++;
921 }
922 return;
923 }
8d063cd8 924 if (!environ[i]) { /* does not exist yet */
fe14fcc3 925 Renew(environ, i+2, char*); /* just expand it a bit */
8d063cd8
LW
926 environ[i+1] = Nullch; /* make sure it's null terminated */
927 }
fe14fcc3
LW
928 else
929 Safefree(environ[i]);
a687059c 930 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
62b28dd9 931#ifndef MSDOS
a687059c 932 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
62b28dd9
LW
933#else
934 /* MS-DOS requires environment variable names to be in uppercase */
fe14fcc3
LW
935 /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
936 * some utilities and applications may break because they only look
937 * for upper case strings. (Fixed strupr() bug here.)]
938 */
939 strcpy(environ[i],nam); strupr(environ[i]);
62b28dd9
LW
940 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
941#endif /* MSDOS */
8d063cd8
LW
942}
943
79072805
LW
944I32
945setenv_getix(nam)
8d063cd8
LW
946char *nam;
947{
79072805 948 register I32 i, len = strlen(nam);
8d063cd8
LW
949
950 for (i = 0; environ[i]; i++) {
951 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
952 break; /* strnEQ must come first to avoid */
953 } /* potential SEGV's */
954 return i;
955}
a0d0e21e 956#endif /* !VMS */
378cc40b
LW
957
958#ifdef EUNICE
79072805 959I32
378cc40b
LW
960unlnk(f) /* unlink all versions of a file */
961char *f;
962{
79072805 963 I32 i;
378cc40b
LW
964
965 for (i = 0; unlink(f) >= 0; i++) ;
966 return i ? 0 : -1;
967}
968#endif
969
85e6fe83 970#if !defined(HAS_BCOPY) || !defined(HAS_SAFE_BCOPY)
378cc40b 971char *
7c0587c8 972my_bcopy(from,to,len)
378cc40b
LW
973register char *from;
974register char *to;
79072805 975register I32 len;
378cc40b
LW
976{
977 char *retval = to;
978
7c0587c8
LW
979 if (from - to >= 0) {
980 while (len--)
981 *to++ = *from++;
982 }
983 else {
984 to += len;
985 from += len;
986 while (len--)
faf8582f 987 *(--to) = *(--from);
7c0587c8 988 }
378cc40b
LW
989 return retval;
990}
ffed7fef 991#endif
378cc40b 992
7c0587c8 993#if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
378cc40b 994char *
7c0587c8 995my_bzero(loc,len)
378cc40b 996register char *loc;
79072805 997register I32 len;
378cc40b
LW
998{
999 char *retval = loc;
1000
1001 while (len--)
1002 *loc++ = 0;
1003 return retval;
1004}
1005#endif
7c0587c8
LW
1006
1007#ifndef HAS_MEMCMP
79072805 1008I32
7c0587c8
LW
1009my_memcmp(s1,s2,len)
1010register unsigned char *s1;
1011register unsigned char *s2;
79072805 1012register I32 len;
7c0587c8 1013{
79072805 1014 register I32 tmp;
7c0587c8
LW
1015
1016 while (len--) {
1017 if (tmp = *s1++ - *s2++)
1018 return tmp;
1019 }
1020 return 0;
1021}
1022#endif /* HAS_MEMCMP */
a687059c 1023
35c8bce7 1024#ifdef I_VARARGS
fe14fcc3 1025#ifndef HAS_VPRINTF
a687059c 1026
85e6fe83 1027#ifdef USE_CHAR_VSPRINTF
a687059c
LW
1028char *
1029#else
1030int
1031#endif
1032vsprintf(dest, pat, args)
1033char *dest, *pat, *args;
1034{
1035 FILE fakebuf;
1036
1037 fakebuf._ptr = dest;
1038 fakebuf._cnt = 32767;
35c8bce7
LW
1039#ifndef _IOSTRG
1040#define _IOSTRG 0
1041#endif
a687059c
LW
1042 fakebuf._flag = _IOWRT|_IOSTRG;
1043 _doprnt(pat, args, &fakebuf); /* what a kludge */
1044 (void)putc('\0', &fakebuf);
85e6fe83 1045#ifdef USE_CHAR_VSPRINTF
a687059c
LW
1046 return(dest);
1047#else
1048 return 0; /* perl doesn't use return value */
1049#endif
1050}
1051
a687059c
LW
1052int
1053vfprintf(fd, pat, args)
1054FILE *fd;
1055char *pat, *args;
1056{
1057 _doprnt(pat, args, fd);
1058 return 0; /* wrong, but perl doesn't use the return value */
1059}
fe14fcc3 1060#endif /* HAS_VPRINTF */
35c8bce7 1061#endif /* I_VARARGS */
a687059c 1062
988174c1
LW
1063/*
1064 * I think my_swap(), htonl() and ntohl() have never been used.
1065 * perl.h contains last-chance references to my_swap(), my_htonl()
1066 * and my_ntohl(). I presume these are the intended functions;
1067 * but htonl() and ntohl() have the wrong names. There are no
1068 * functions my_htonl() and my_ntohl() defined anywhere.
1069 * -DWS
1070 */
a687059c 1071#ifdef MYSWAP
ffed7fef 1072#if BYTEORDER != 0x4321
a687059c
LW
1073short
1074my_swap(s)
1075short s;
1076{
1077#if (BYTEORDER & 1) == 0
1078 short result;
1079
1080 result = ((s & 255) << 8) + ((s >> 8) & 255);
1081 return result;
1082#else
1083 return s;
1084#endif
1085}
1086
1087long
1088htonl(l)
1089register long l;
1090{
1091 union {
1092 long result;
ffed7fef 1093 char c[sizeof(long)];
a687059c
LW
1094 } u;
1095
ffed7fef 1096#if BYTEORDER == 0x1234
a687059c
LW
1097 u.c[0] = (l >> 24) & 255;
1098 u.c[1] = (l >> 16) & 255;
1099 u.c[2] = (l >> 8) & 255;
1100 u.c[3] = l & 255;
1101 return u.result;
1102#else
ffed7fef 1103#if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
463ee0b2 1104 croak("Unknown BYTEORDER\n");
a687059c 1105#else
79072805
LW
1106 register I32 o;
1107 register I32 s;
a687059c 1108
ffed7fef
LW
1109 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1110 u.c[o & 0xf] = (l >> s) & 255;
a687059c
LW
1111 }
1112 return u.result;
1113#endif
1114#endif
1115}
1116
1117long
1118ntohl(l)
1119register long l;
1120{
1121 union {
1122 long l;
ffed7fef 1123 char c[sizeof(long)];
a687059c
LW
1124 } u;
1125
ffed7fef 1126#if BYTEORDER == 0x1234
a687059c
LW
1127 u.c[0] = (l >> 24) & 255;
1128 u.c[1] = (l >> 16) & 255;
1129 u.c[2] = (l >> 8) & 255;
1130 u.c[3] = l & 255;
1131 return u.l;
1132#else
ffed7fef 1133#if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
463ee0b2 1134 croak("Unknown BYTEORDER\n");
a687059c 1135#else
79072805
LW
1136 register I32 o;
1137 register I32 s;
a687059c
LW
1138
1139 u.l = l;
1140 l = 0;
ffed7fef
LW
1141 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1142 l |= (u.c[o & 0xf] & 255) << s;
a687059c
LW
1143 }
1144 return l;
1145#endif
1146#endif
1147}
1148
ffed7fef 1149#endif /* BYTEORDER != 0x4321 */
988174c1
LW
1150#endif /* MYSWAP */
1151
1152/*
1153 * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
1154 * If these functions are defined,
1155 * the BYTEORDER is neither 0x1234 nor 0x4321.
1156 * However, this is not assumed.
1157 * -DWS
1158 */
1159
1160#define HTOV(name,type) \
1161 type \
1162 name (n) \
1163 register type n; \
1164 { \
1165 union { \
1166 type value; \
1167 char c[sizeof(type)]; \
1168 } u; \
79072805
LW
1169 register I32 i; \
1170 register I32 s; \
988174c1
LW
1171 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1172 u.c[i] = (n >> s) & 0xFF; \
1173 } \
1174 return u.value; \
1175 }
1176
1177#define VTOH(name,type) \
1178 type \
1179 name (n) \
1180 register type n; \
1181 { \
1182 union { \
1183 type value; \
1184 char c[sizeof(type)]; \
1185 } u; \
79072805
LW
1186 register I32 i; \
1187 register I32 s; \
988174c1
LW
1188 u.value = n; \
1189 n = 0; \
1190 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1191 n += (u.c[i] & 0xFF) << s; \
1192 } \
1193 return n; \
1194 }
1195
1196#if defined(HAS_HTOVS) && !defined(htovs)
1197HTOV(htovs,short)
1198#endif
1199#if defined(HAS_HTOVL) && !defined(htovl)
1200HTOV(htovl,long)
1201#endif
1202#if defined(HAS_VTOHS) && !defined(vtohs)
1203VTOH(vtohs,short)
1204#endif
1205#if defined(HAS_VTOHL) && !defined(vtohl)
1206VTOH(vtohl,long)
1207#endif
a687059c 1208
a0d0e21e 1209#if !defined(DOSISH) && !defined(VMS) /* VMS' my_popen() is in VMS.c */
a687059c 1210FILE *
79072805 1211my_popen(cmd,mode)
a687059c
LW
1212char *cmd;
1213char *mode;
1214{
1215 int p[2];
79072805
LW
1216 register I32 this, that;
1217 register I32 pid;
1218 SV *sv;
1219 I32 doexec = strNE(cmd,"-");
a687059c
LW
1220
1221 if (pipe(p) < 0)
1222 return Nullfp;
1223 this = (*mode == 'w');
1224 that = !this;
463ee0b2
LW
1225 if (tainting) {
1226 if (doexec) {
1227 taint_env();
1228 taint_proper("Insecure %s%s", "EXEC");
1229 }
d48672a2 1230 }
a687059c
LW
1231 while ((pid = (doexec?vfork():fork())) < 0) {
1232 if (errno != EAGAIN) {
1233 close(p[this]);
1234 if (!doexec)
463ee0b2 1235 croak("Can't fork");
a687059c
LW
1236 return Nullfp;
1237 }
1238 sleep(5);
1239 }
1240 if (pid == 0) {
79072805
LW
1241 GV* tmpgv;
1242
a687059c
LW
1243#define THIS that
1244#define THAT this
1245 close(p[THAT]);
1246 if (p[THIS] != (*mode == 'r')) {
1247 dup2(p[THIS], *mode == 'r');
1248 close(p[THIS]);
1249 }
1250 if (doexec) {
a0d0e21e 1251#if !defined(HAS_FCNTL) || !defined(F_SETFD)
ae986130
LW
1252 int fd;
1253
1254#ifndef NOFILE
1255#define NOFILE 20
1256#endif
d48672a2 1257 for (fd = maxsysfd + 1; fd < NOFILE; fd++)
ae986130
LW
1258 close(fd);
1259#endif
a687059c
LW
1260 do_exec(cmd); /* may or may not use the shell */
1261 _exit(1);
1262 }
de3bb511 1263 /*SUPPRESS 560*/
85e6fe83 1264 if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV))
79072805 1265 sv_setiv(GvSV(tmpgv),(I32)getpid());
9f68db38 1266 forkprocess = 0;
463ee0b2 1267 hv_clear(pidstatus); /* we have no children */
a687059c
LW
1268 return Nullfp;
1269#undef THIS
1270#undef THAT
1271 }
62b28dd9 1272 do_execfree(); /* free any memory malloced by child on vfork */
a687059c 1273 close(p[that]);
62b28dd9
LW
1274 if (p[that] < p[this]) {
1275 dup2(p[this], p[that]);
1276 close(p[this]);
1277 p[this] = p[that];
1278 }
79072805 1279 sv = *av_fetch(fdpid,p[this],TRUE);
a0d0e21e 1280 (void)SvUPGRADE(sv,SVt_IV);
463ee0b2 1281 SvIVX(sv) = pid;
a687059c
LW
1282 forkprocess = pid;
1283 return fdopen(p[this], mode);
1284}
7c0587c8
LW
1285#else
1286#ifdef atarist
1287FILE *popen();
1288FILE *
79072805 1289my_popen(cmd,mode)
7c0587c8
LW
1290char *cmd;
1291char *mode;
1292{
1293 return popen(cmd, mode);
1294}
1295#endif
1296
1297#endif /* !DOSISH */
a687059c 1298
ae986130 1299#ifdef NOTDEF
79072805 1300dump_fds(s)
ae986130
LW
1301char *s;
1302{
1303 int fd;
1304 struct stat tmpstatbuf;
1305
1306 fprintf(stderr,"%s", s);
1307 for (fd = 0; fd < 32; fd++) {
a0d0e21e 1308 if (Fstat(fd,&tmpstatbuf) >= 0)
ae986130
LW
1309 fprintf(stderr," %d",fd);
1310 }
1311 fprintf(stderr,"\n");
1312}
1313#endif
1314
fe14fcc3 1315#ifndef HAS_DUP2
a687059c
LW
1316dup2(oldfd,newfd)
1317int oldfd;
1318int newfd;
1319{
a0d0e21e 1320#if defined(HAS_FCNTL) && defined(F_DUPFD)
62b28dd9 1321 close(newfd);
a0d0e21e 1322 fcntl(oldfd, F_DUPFD, newfd);
62b28dd9 1323#else
d48672a2 1324 int fdtmp[256];
79072805 1325 I32 fdx = 0;
ae986130
LW
1326 int fd;
1327
fe14fcc3
LW
1328 if (oldfd == newfd)
1329 return 0;
a687059c 1330 close(newfd);
ae986130
LW
1331 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1332 fdtmp[fdx++] = fd;
1333 while (fdx > 0)
1334 close(fdtmp[--fdx]);
62b28dd9 1335#endif
a687059c
LW
1336}
1337#endif
1338
7c0587c8 1339#ifndef DOSISH
a0d0e21e 1340#ifndef VMS /* VMS' my_pclose() is in VMS.c */
79072805
LW
1341I32
1342my_pclose(ptr)
a687059c
LW
1343FILE *ptr;
1344{
a687059c
LW
1345#ifdef VOIDSIG
1346 void (*hstat)(), (*istat)(), (*qstat)();
1347#else
1348 int (*hstat)(), (*istat)(), (*qstat)();
1349#endif
1350 int status;
a0d0e21e 1351 SV **svp;
20188a90 1352 int pid;
a687059c 1353
a0d0e21e
LW
1354 svp = av_fetch(fdpid,fileno(ptr),TRUE);
1355 pid = SvIVX(*svp);
1356 SvREFCNT_dec(*svp);
1357 *svp = &sv_undef;
a687059c 1358 fclose(ptr);
7c0587c8
LW
1359#ifdef UTS
1360 if(kill(pid, 0) < 0) { return(pid); } /* HOM 12/23/91 */
1361#endif
a687059c
LW
1362 hstat = signal(SIGHUP, SIG_IGN);
1363 istat = signal(SIGINT, SIG_IGN);
1364 qstat = signal(SIGQUIT, SIG_IGN);
20188a90
LW
1365 pid = wait4pid(pid, &status, 0);
1366 signal(SIGHUP, hstat);
1367 signal(SIGINT, istat);
1368 signal(SIGQUIT, qstat);
1369 return(pid < 0 ? pid : status);
1370}
a0d0e21e 1371#endif /* !VMS */
79072805 1372I32
20188a90
LW
1373wait4pid(pid,statusp,flags)
1374int pid;
1375int *statusp;
1376int flags;
1377{
79072805
LW
1378 SV *sv;
1379 SV** svp;
20188a90
LW
1380 char spid[16];
1381
1382 if (!pid)
1383 return -1;
20188a90
LW
1384 if (pid > 0) {
1385 sprintf(spid, "%d", pid);
79072805
LW
1386 svp = hv_fetch(pidstatus,spid,strlen(spid),FALSE);
1387 if (svp && *svp != &sv_undef) {
463ee0b2 1388 *statusp = SvIVX(*svp);
79072805 1389 hv_delete(pidstatus,spid,strlen(spid));
20188a90
LW
1390 return pid;
1391 }
1392 }
1393 else {
79072805 1394 HE *entry;
20188a90 1395
79072805
LW
1396 hv_iterinit(pidstatus);
1397 if (entry = hv_iternext(pidstatus)) {
a0d0e21e 1398 pid = atoi(hv_iterkey(entry,(I32*)statusp));
79072805 1399 sv = hv_iterval(pidstatus,entry);
463ee0b2 1400 *statusp = SvIVX(sv);
20188a90 1401 sprintf(spid, "%d", pid);
79072805 1402 hv_delete(pidstatus,spid,strlen(spid));
20188a90
LW
1403 return pid;
1404 }
1405 }
79072805
LW
1406#ifdef HAS_WAITPID
1407 return waitpid(pid,statusp,flags);
1408#else
a0d0e21e
LW
1409#ifdef HAS_WAIT4
1410 return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
1411#else
1412 {
1413 I32 result;
1414 if (flags)
1415 croak("Can't do waitpid with flags");
1416 else {
1417 while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
1418 pidgone(result,*statusp);
1419 if (result < 0)
1420 *statusp = -1;
1421 }
1422 return result;
a687059c
LW
1423 }
1424#endif
20188a90 1425#endif
a687059c 1426}
7c0587c8 1427#endif /* !DOSISH */
a687059c 1428
7c0587c8 1429void
de3bb511 1430/*SUPPRESS 590*/
a687059c
LW
1431pidgone(pid,status)
1432int pid;
1433int status;
1434{
79072805 1435 register SV *sv;
20188a90 1436 char spid[16];
a687059c 1437
20188a90 1438 sprintf(spid, "%d", pid);
79072805 1439 sv = *hv_fetch(pidstatus,spid,strlen(spid),TRUE);
a0d0e21e 1440 (void)SvUPGRADE(sv,SVt_IV);
463ee0b2 1441 SvIVX(sv) = status;
20188a90 1442 return;
a687059c
LW
1443}
1444
7c0587c8
LW
1445#ifdef atarist
1446int pclose();
79072805
LW
1447I32
1448my_pclose(ptr)
7c0587c8 1449FILE *ptr;
a687059c 1450{
7c0587c8 1451 return pclose(ptr);
a687059c 1452}
7c0587c8 1453#endif
9f68db38
LW
1454
1455void
1456repeatcpy(to,from,len,count)
1457register char *to;
1458register char *from;
79072805
LW
1459I32 len;
1460register I32 count;
9f68db38 1461{
79072805 1462 register I32 todo;
9f68db38
LW
1463 register char *frombase = from;
1464
1465 if (len == 1) {
1466 todo = *from;
1467 while (count-- > 0)
1468 *to++ = todo;
1469 return;
1470 }
1471 while (count-- > 0) {
1472 for (todo = len; todo > 0; todo--) {
1473 *to++ = *from++;
1474 }
1475 from = frombase;
1476 }
1477}
0f85fab0
LW
1478
1479#ifndef CASTNEGFLOAT
463ee0b2 1480U32
79072805 1481cast_ulong(f)
0f85fab0
LW
1482double f;
1483{
1484 long along;
1485
27e2fb84 1486#if CASTFLAGS & 2
34de22dd
LW
1487# define BIGDOUBLE 2147483648.0
1488 if (f >= BIGDOUBLE)
1489 return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
1490#endif
0f85fab0
LW
1491 if (f >= 0.0)
1492 return (unsigned long)f;
1493 along = (long)f;
1494 return (unsigned long)along;
1495}
ed6116ce
LW
1496# undef BIGDOUBLE
1497#endif
1498
1499#ifndef CASTI32
1500I32
1501cast_i32(f)
1502double f;
1503{
1504# define BIGDOUBLE 2147483648.0 /* Assume 32 bit int's ! */
1505# define BIGNEGDOUBLE (-2147483648.0)
1506 if (f >= BIGDOUBLE)
1507 return (I32)fmod(f, BIGDOUBLE);
1508 if (f <= BIGNEGDOUBLE)
1509 return (I32)fmod(f, BIGNEGDOUBLE);
1510 return (I32) f;
1511}
1512# undef BIGDOUBLE
1513# undef BIGNEGDOUBLE
a0d0e21e
LW
1514
1515IV
1516cast_iv(f)
1517double f;
1518{
1519 /* XXX This should be fixed. It assumes 32 bit IV's. */
1520# define BIGDOUBLE 2147483648.0 /* Assume 32 bit IV's ! */
1521# define BIGNEGDOUBLE (-2147483648.0)
1522 if (f >= BIGDOUBLE)
1523 return (IV)fmod(f, BIGDOUBLE);
1524 if (f <= BIGNEGDOUBLE)
1525 return (IV)fmod(f, BIGNEGDOUBLE);
1526 return (IV) f;
1527}
1528# undef BIGDOUBLE
1529# undef BIGNEGDOUBLE
0f85fab0 1530#endif
62b28dd9 1531
fe14fcc3 1532#ifndef HAS_RENAME
79072805 1533I32
62b28dd9
LW
1534same_dirent(a,b)
1535char *a;
1536char *b;
1537{
93a17b20
LW
1538 char *fa = strrchr(a,'/');
1539 char *fb = strrchr(b,'/');
62b28dd9
LW
1540 struct stat tmpstatbuf1;
1541 struct stat tmpstatbuf2;
1542#ifndef MAXPATHLEN
1543#define MAXPATHLEN 1024
1544#endif
1545 char tmpbuf[MAXPATHLEN+1];
1546
1547 if (fa)
1548 fa++;
1549 else
1550 fa = a;
1551 if (fb)
1552 fb++;
1553 else
1554 fb = b;
1555 if (strNE(a,b))
1556 return FALSE;
1557 if (fa == a)
6eb13c3b 1558 strcpy(tmpbuf,".");
62b28dd9
LW
1559 else
1560 strncpy(tmpbuf, a, fa - a);
a0d0e21e 1561 if (Stat(tmpbuf, &tmpstatbuf1) < 0)
62b28dd9
LW
1562 return FALSE;
1563 if (fb == b)
6eb13c3b 1564 strcpy(tmpbuf,".");
62b28dd9
LW
1565 else
1566 strncpy(tmpbuf, b, fb - b);
a0d0e21e 1567 if (Stat(tmpbuf, &tmpstatbuf2) < 0)
62b28dd9
LW
1568 return FALSE;
1569 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1570 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1571}
fe14fcc3
LW
1572#endif /* !HAS_RENAME */
1573
1574unsigned long
79072805 1575scan_oct(start, len, retlen)
fe14fcc3 1576char *start;
79072805
LW
1577I32 len;
1578I32 *retlen;
fe14fcc3
LW
1579{
1580 register char *s = start;
1581 register unsigned long retval = 0;
1582
1583 while (len-- && *s >= '0' && *s <= '7') {
1584 retval <<= 3;
1585 retval |= *s++ - '0';
1586 }
1587 *retlen = s - start;
1588 return retval;
1589}
1590
1591unsigned long
79072805 1592scan_hex(start, len, retlen)
fe14fcc3 1593char *start;
79072805
LW
1594I32 len;
1595I32 *retlen;
fe14fcc3
LW
1596{
1597 register char *s = start;
1598 register unsigned long retval = 0;
1599 char *tmp;
1600
93a17b20 1601 while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
fe14fcc3
LW
1602 retval <<= 4;
1603 retval |= (tmp - hexdigit) & 15;
1604 s++;
1605 }
1606 *retlen = s - start;
1607 return retval;
1608}