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