This is my patch patch.0a for perl5.000.
[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
85e6fe83 22#ifdef I_UNISTD
8990e307 23# include <unistd.h>
24#endif
25
a687059c 26#ifdef I_VFORK
27# include <vfork.h>
28#endif
29
fe14fcc3 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 39#ifdef LEAKTEST
40static void xstat _((void));
41#endif
42
de3bb511 43#ifndef safemalloc
44
8d063cd8 45/* paranoid version of malloc */
46
a687059c 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 52char *
53safemalloc(size)
62b28dd9 54#ifdef MSDOS
55unsigned long size;
56#else
8d063cd8 57MEM_SIZE size;
62b28dd9 58#endif /* MSDOS */
8d063cd8 59{
2304df62 60 char *ptr;
62b28dd9 61#ifdef MSDOS
62 if (size > 0xffff) {
63 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
79072805 64 my_exit(1);
62b28dd9 65 }
66#endif /* MSDOS */
34de22dd 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 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 76#endif
77 if (ptr != Nullch)
78 return ptr;
7c0587c8 79 else if (nomemok)
80 return Nullch;
8d063cd8 81 else {
79072805 82 fputs(no_mem,stderr) FLUSH;
83 my_exit(1);
8d063cd8 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 95#else
96unsigned long size;
97#endif /* MSDOS */
8d063cd8 98{
99 char *ptr;
d48672a2 100#ifndef STANDARD_C
8d063cd8 101 char *realloc();
d48672a2 102#endif /* ! STANDARD_C */
8d063cd8 103
62b28dd9 104#ifdef MSDOS
105 if (size > 0xffff) {
106 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
79072805 107 my_exit(1);
62b28dd9 108 }
109#endif /* MSDOS */
378cc40b 110 if (!where)
463ee0b2 111 croak("Null realloc");
34de22dd 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 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 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 130 if (ptr != Nullch)
131 return ptr;
7c0587c8 132 else if (nomemok)
133 return Nullch;
8d063cd8 134 else {
79072805 135 fputs(no_mem,stderr) FLUSH;
136 my_exit(1);
8d063cd8 137 }
138 /*NOTREACHED*/
139}
140
141/* safe version of free */
142
a687059c 143void
8d063cd8 144safefree(where)
145char *where;
146{
79072805 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 154 free(where);
155 }
8d063cd8 156}
157
de3bb511 158#endif /* !safemalloc */
159
a687059c 160#ifdef LEAKTEST
161
162#define ALIGN sizeof(long)
8d063cd8 163
164char *
a687059c 165safexmalloc(x,size)
79072805 166I32 x;
a687059c 167MEM_SIZE size;
8d063cd8 168{
a687059c 169 register char *where;
8d063cd8 170
a687059c 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 177
178char *
a687059c 179safexrealloc(where,size)
180char *where;
181MEM_SIZE size;
182{
a0d0e21e 183 register char *new = saferealloc(where - ALIGN, size + ALIGN);
184 return new + ALIGN;
a687059c 185}
186
187void
188safexfree(where)
189char *where;
190{
79072805 191 I32 x;
a687059c 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 208 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
209 lastxcount[i] = xcount[i];
8d063cd8 210 }
211 }
8d063cd8 212}
a687059c 213
214#endif /* LEAKTEST */
8d063cd8 215
216/* copy a string up to some (non-backslashed) delimiter, if any */
217
218char *
a687059c 219cpytill(to,from,fromend,delim,retlen)
62b28dd9 220register char *to;
221register char *from;
a687059c 222register char *fromend;
a0d0e21e 223register int delim;
79072805 224I32 *retlen;
8d063cd8 225{
a687059c 226 char *origto = to;
227
228 for (; from < fromend; from++,to++) {
378cc40b 229 if (*from == '\\') {
230 if (from[1] == delim)
231 from++;
232 else if (from[1] == '\\')
233 *to++ = *from++;
234 }
8d063cd8 235 else if (*from == delim)
236 break;
237 *to = *from;
238 }
239 *to = '\0';
a687059c 240 *retlen = to - origto;
8d063cd8 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 246
247char *
248instr(big, little)
378cc40b 249register char *big;
250register char *little;
251{
252 register char *s, *x;
79072805 253 register I32 first;
378cc40b 254
a687059c 255 if (!little)
256 return big;
257 first = *little++;
378cc40b 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 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 292 if (bigend - big < littleend - little)
293 return Nullch;
a687059c 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 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 322 register char *littleend = lend;
323
a0d0e21e 324 if (!first && little >= littleend)
a687059c 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 344fbm_compile(sv, iflag)
345SV *sv;
346I32 iflag;
378cc40b 347{
a687059c 348 register unsigned char *s;
349 register unsigned char *table;
79072805 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 357 s = table - 2;
358 for (i = 0; i < 256; i++) {
378cc40b 359 table[i] = len;
360 }
361 i = 0;
463ee0b2 362 while (s >= (unsigned char*)(SvPVX(sv)))
a687059c 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 371 j = fold[*s];
372 table[j] = i;
373 table[*s] = i;
374 }
375#endif /* pdp11 */
376 else
377 table[*s] = i;
378 }
378cc40b 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 387 register U32 tmp, foldtmp;
388 SvCASEFOLD_on(sv);
a687059c 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 405 }
406 }
79072805 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 410}
411
378cc40b 412char *
79072805 413fbm_instr(big, bigend, littlestr)
a687059c 414unsigned char *big;
415register unsigned char *bigend;
79072805 416SV *littlestr;
378cc40b 417{
a687059c 418 register unsigned char *s;
79072805 419 register I32 tmp;
420 register I32 littlelen;
a687059c 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 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 434 littlelen = SvCUR(littlestr);
435 if (SvTAIL(littlestr) && !multiline) { /* tail anchored? */
0f85fab0 436 if (littlelen > bigend - big)
437 return Nullch;
463ee0b2 438 little = (unsigned char*)SvPVX(littlestr);
79072805 439 if (SvCASEFOLD(littlestr)) { /* oops, fake it */
a687059c 440 big = bigend - littlelen; /* just start near end */
441 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
442 big--;
378cc40b 443 }
444 else {
a687059c 445 s = bigend - littlelen;
446 if (*s == *little && bcmp(s,little,littlelen)==0)
447 return (char*)s; /* how sweet it is */
34de22dd 448 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
449 && s > big) {
a687059c 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 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 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 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 491 }
492 }
493 }
494 else {
20188a90 495 if (s < bigend) {
a687059c 496 top2:
de3bb511 497 /*SUPPRESS 560*/
a687059c 498 if (tmp = table[*s]) {
62b28dd9 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 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 524 }
525 }
526 return Nullch;
527}
528
529char *
530screaminstr(bigstr, littlestr)
79072805 531SV *bigstr;
532SV *littlestr;
378cc40b 533{
a687059c 534 register unsigned char *s, *x;
535 register unsigned char *big;
79072805 536 register I32 pos;
537 register I32 previous;
538 register I32 first;
a687059c 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 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 558 if (big[pos-previous] != first && big[pos-previous] != fold[first])
559 continue;
de3bb511 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 572 );
573 }
574 else {
575 do {
988174c1 576 if (big[pos-previous] != first)
577 continue;
de3bb511 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 589 }
590#else /* !POINTERRIGOR */
591 big -= previous;
79072805 592 if (SvCASEFOLD(littlestr)) { /* case insignificant? */
de3bb511 593 do {
988174c1 594 if (big[pos] != first && big[pos] != fold[first])
595 continue;
a687059c 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 608 );
609 }
610 else {
611 do {
988174c1 612 if (big[pos] != first)
613 continue;
a687059c 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 626 );
627 }
de3bb511 628#endif /* POINTERRIGOR */
8d063cd8 629 return Nullch;
630}
631
79072805 632I32
633ibcmp(a,b,len)
a0d0e21e 634register U8 *a;
635register U8 *b;
79072805 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 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 658 New(902,newaddr,strlen(sv)+1,char);
659 (void)strcpy(newaddr,sv);
8d063cd8 660 return newaddr;
661}
662
a687059c 663/* same thing but with a known length */
664
665char *
a0d0e21e 666savepvn(sv, len)
79072805 667char *sv;
668register I32 len;
a687059c 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 674 newaddr[len] = '\0'; /* is now */
675 return newaddr;
676}
677
a0d0e21e 678#if !defined(I_STDARG) && !defined(I_VARARGS)
8d063cd8 679
8990e307 680/*
681 * Fallback on the old hackers way of doing varargs
682 */
8d063cd8 683
378cc40b 684/*VARARGS1*/
7c0587c8 685char *
378cc40b 686mess(pat,a1,a2,a3,a4)
687char *pat;
a687059c 688long a1, a2, a3, a4;
378cc40b 689{
690 char *s;
79072805 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 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 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 714 if (GvIO(last_in_gv) &&
715 IoLINES(GvIOp(last_in_gv)) ) {
2304df62 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 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 729 else
730 return buf;
378cc40b 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 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 752}
753
754/*VARARGS1*/
7c0587c8 755void warn(pat,a1,a2,a3,a4)
378cc40b 756char *pat;
a687059c 757long a1, a2, a3, a4;
378cc40b 758{
de3bb511 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 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 774#else
775/*VARARGS0*/
de3bb511 776char *
8990e307 777mess(pat, args)
a687059c 778 char *pat;
2304df62 779 va_list *args;
8990e307 780#endif
781{
a687059c 782 char *s;
79072805 783 SV *tmpstr;
784 I32 usermess;
d48672a2 785#ifndef HAS_VPRINTF
85e6fe83 786#ifdef USE_CHAR_VSPRINTF
a687059c 787 char *vsprintf();
788#else
79072805 789 I32 vsprintf();
a687059c 790#endif
d48672a2 791#endif
a687059c 792
de3bb511 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 799 }
800 else {
2304df62 801 (void) vsprintf(s,pat,*args);
de3bb511 802 s += strlen(s);
803 }
2304df62 804 va_end(*args);
a687059c 805
a687059c 806 if (s[-1] != '\n') {
2304df62 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 815 if (GvIO(last_in_gv) &&
816 IoLINES(GvIOp(last_in_gv)) ) {
2304df62 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 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 828
829 if (usermess)
463ee0b2 830 return SvPVX(tmpstr);
de3bb511 831 else
832 return buf;
a687059c 833}
834
8990e307 835#ifdef STANDARD_C
79072805 836void
8990e307 837croak(char* pat, ...)
463ee0b2 838#else
8990e307 839/*VARARGS0*/
840void
841croak(pat, va_alist)
842 char *pat;
843 va_dcl
463ee0b2 844#endif
a687059c 845{
846 va_list args;
de3bb511 847 char *message;
a687059c 848
a0d0e21e 849#ifdef I_STDARG
8990e307 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 856 if (in_eval) {
857 restartop = die_where(message);
79072805 858 longjmp(top_env, 3);
a0d0e21e 859 }
de3bb511 860 fputs(message,stderr);
a687059c 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 866}
867
8990e307 868void
869#ifdef STANDARD_C
870warn(char* pat,...)
463ee0b2 871#else
8990e307 872/*VARARGS0*/
873warn(pat,va_alist)
874 char *pat;
875 va_dcl
463ee0b2 876#endif
a687059c 877{
878 va_list args;
de3bb511 879 char *message;
a687059c 880
a0d0e21e 881#ifdef I_STDARG
8990e307 882 va_start(args, pat);
883#else
a687059c 884 va_start(args);
8990e307 885#endif
2304df62 886 message = mess(pat, &args);
a687059c 887 va_end(args);
888
de3bb511 889 fputs(message,stderr);
a687059c 890#ifdef LEAKTEST
79072805 891 DEBUG_L(xstat());
a687059c 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 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 905 I32 j;
906 I32 max;
fe14fcc3 907 char **tmpenv;
908
de3bb511 909 /*SUPPRESS 530*/
fe14fcc3 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 914 tmpenv[max] = Nullch;
915 environ = tmpenv; /* tell exec where it is now */
916 }
a687059c 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 926 environ[i+1] = Nullch; /* make sure it's null terminated */
927 }
fe14fcc3 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 933#else
934 /* MS-DOS requires environment variable names to be in uppercase */
fe14fcc3 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 940 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
941#endif /* MSDOS */
8d063cd8 942}
943
79072805 944I32
945setenv_getix(nam)
8d063cd8 946char *nam;
947{
79072805 948 register I32 i, len = strlen(nam);
8d063cd8 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 957
958#ifdef EUNICE
79072805 959I32
378cc40b 960unlnk(f) /* unlink all versions of a file */
961char *f;
962{
79072805 963 I32 i;
378cc40b 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 973register char *from;
974register char *to;
79072805 975register I32 len;
378cc40b 976{
977 char *retval = to;
978
7c0587c8 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 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 998{
999 char *retval = loc;
1000
1001 while (len--)
1002 *loc++ = 0;
1003 return retval;
1004}
1005#endif
7c0587c8 1006
1007#ifndef HAS_MEMCMP
79072805 1008I32
7c0587c8 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 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 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 1039#ifndef _IOSTRG
1040#define _IOSTRG 0
1041#endif
a687059c 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 1046 return(dest);
1047#else
1048 return 0; /* perl doesn't use return value */
1049#endif
1050}
1051
a687059c 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 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 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 1094 } u;
1095
ffed7fef 1096#if BYTEORDER == 0x1234
a687059c 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 1106 register I32 o;
1107 register I32 s;
a687059c 1108
ffed7fef 1109 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1110 u.c[o & 0xf] = (l >> s) & 255;
a687059c 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 1124 } u;
1125
ffed7fef 1126#if BYTEORDER == 0x1234
a687059c 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 1136 register I32 o;
1137 register I32 s;
a687059c 1138
1139 u.l = l;
1140 l = 0;
ffed7fef 1141 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1142 l |= (u.c[o & 0xf] & 255) << s;
a687059c 1143 }
1144 return l;
1145#endif
1146#endif
1147}
1148
ffed7fef 1149#endif /* BYTEORDER != 0x4321 */
988174c1 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 1169 register I32 i; \
1170 register I32 s; \
988174c1 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 1186 register I32 i; \
1187 register I32 s; \
988174c1 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 1212char *cmd;
1213char *mode;
1214{
1215 int p[2];
79072805 1216 register I32 this, that;
1217 register I32 pid;
1218 SV *sv;
1219 I32 doexec = strNE(cmd,"-");
a687059c 1220
1221 if (pipe(p) < 0)
1222 return Nullfp;
1223 this = (*mode == 'w');
1224 that = !this;
463ee0b2 1225 if (tainting) {
1226 if (doexec) {
1227 taint_env();
1228 taint_proper("Insecure %s%s", "EXEC");
1229 }
d48672a2 1230 }
a687059c 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 1236 return Nullfp;
1237 }
1238 sleep(5);
1239 }
1240 if (pid == 0) {
79072805 1241 GV* tmpgv;
1242
a687059c 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 1252 int fd;
1253
1254#ifndef NOFILE
1255#define NOFILE 20
1256#endif
d48672a2 1257 for (fd = maxsysfd + 1; fd < NOFILE; fd++)
ae986130 1258 close(fd);
1259#endif
a687059c 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 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 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 1282 forkprocess = pid;
1283 return fdopen(p[this], mode);
1284}
7c0587c8 1285#else
1286#ifdef atarist
1287FILE *popen();
1288FILE *
79072805 1289my_popen(cmd,mode)
7c0587c8 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 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 1309 fprintf(stderr," %d",fd);
1310 }
1311 fprintf(stderr,"\n");
1312}
1313#endif
1314
fe14fcc3 1315#ifndef HAS_DUP2
a687059c 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 1326 int fd;
1327
fe14fcc3 1328 if (oldfd == newfd)
1329 return 0;
a687059c 1330 close(newfd);
ae986130 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 1336}
1337#endif
1338
7c0587c8 1339#ifndef DOSISH
a0d0e21e 1340#ifndef VMS /* VMS' my_pclose() is in VMS.c */
79072805 1341I32
1342my_pclose(ptr)
a687059c 1343FILE *ptr;
1344{
a687059c 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 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 1359#ifdef UTS
1360 if(kill(pid, 0) < 0) { return(pid); } /* HOM 12/23/91 */
1361#endif
a687059c 1362 hstat = signal(SIGHUP, SIG_IGN);
1363 istat = signal(SIGINT, SIG_IGN);
1364 qstat = signal(SIGQUIT, SIG_IGN);
20188a90 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 1373wait4pid(pid,statusp,flags)
1374int pid;
1375int *statusp;
1376int flags;
1377{
79072805 1378 SV *sv;
1379 SV** svp;
20188a90 1380 char spid[16];
1381
1382 if (!pid)
1383 return -1;
20188a90 1384 if (pid > 0) {
1385 sprintf(spid, "%d", pid);
79072805 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 1390 return pid;
1391 }
1392 }
1393 else {
79072805 1394 HE *entry;
20188a90 1395
79072805 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 1403 return pid;
1404 }
1405 }
79072805 1406#ifdef HAS_WAITPID
1407 return waitpid(pid,statusp,flags);
1408#else
a0d0e21e 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 1423 }
1424#endif
20188a90 1425#endif
a687059c 1426}
7c0587c8 1427#endif /* !DOSISH */
a687059c 1428
7c0587c8 1429void
de3bb511 1430/*SUPPRESS 590*/
a687059c 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 1443}
1444
7c0587c8 1445#ifdef atarist
1446int pclose();
79072805 1447I32
1448my_pclose(ptr)
7c0587c8 1449FILE *ptr;
a687059c 1450{
7c0587c8 1451 return pclose(ptr);
a687059c 1452}
7c0587c8 1453#endif
9f68db38 1454
1455void
1456repeatcpy(to,from,len,count)
1457register char *to;
1458register char *from;
79072805 1459I32 len;
1460register I32 count;
9f68db38 1461{
79072805 1462 register I32 todo;
9f68db38 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 1478
1479#ifndef CASTNEGFLOAT
463ee0b2 1480U32
79072805 1481cast_ulong(f)
0f85fab0 1482double f;
1483{
1484 long along;
1485
27e2fb84 1486#if CASTFLAGS & 2
34de22dd 1487# define BIGDOUBLE 2147483648.0
1488 if (f >= BIGDOUBLE)
1489 return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
1490#endif
0f85fab0 1491 if (f >= 0.0)
1492 return (unsigned long)f;
1493 along = (long)f;
1494 return (unsigned long)along;
1495}
ed6116ce 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 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 1534same_dirent(a,b)
1535char *a;
1536char *b;
1537{
93a17b20 1538 char *fa = strrchr(a,'/');
1539 char *fb = strrchr(b,'/');
62b28dd9 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 1559 else
1560 strncpy(tmpbuf, a, fa - a);
a0d0e21e 1561 if (Stat(tmpbuf, &tmpstatbuf1) < 0)
62b28dd9 1562 return FALSE;
1563 if (fb == b)
6eb13c3b 1564 strcpy(tmpbuf,".");
62b28dd9 1565 else
1566 strncpy(tmpbuf, b, fb - b);
a0d0e21e 1567 if (Stat(tmpbuf, &tmpstatbuf2) < 0)
62b28dd9 1568 return FALSE;
1569 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1570 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1571}
fe14fcc3 1572#endif /* !HAS_RENAME */
1573
1574unsigned long
79072805 1575scan_oct(start, len, retlen)
fe14fcc3 1576char *start;
79072805 1577I32 len;
1578I32 *retlen;
fe14fcc3 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 1594I32 len;
1595I32 *retlen;
fe14fcc3 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 1602 retval <<= 4;
1603 retval |= (tmp - hexdigit) & 15;
1604 s++;
1605 }
1606 *retlen = s - start;
1607 return retval;
1608}