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