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