perl 5.0 alpha 8
[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 I_FCNTL
63 #  include <fcntl.h>
64 #endif
65 #ifdef I_SYS_FILE
66 #  include <sys/file.h>
67 #endif
68
69 #define FLUSH
70
71 #ifndef safemalloc
72
73 /* paranoid version of malloc */
74
75 /* NOTE:  Do not call the next three routines directly.  Use the macros
76  * in handy.h, so that we can easily redefine everything to do tracking of
77  * allocated hunks back to the original New to track down any memory leaks.
78  */
79
80 char *
81 safemalloc(size)
82 #ifdef MSDOS
83 unsigned long size;
84 #else
85 MEM_SIZE size;
86 #endif /* MSDOS */
87 {
88     char  *ptr;
89 #ifndef STANDARD_C
90     char *malloc();
91 #endif /* ! STANDARD_C */
92
93 #ifdef MSDOS
94         if (size > 0xffff) {
95                 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
96                 my_exit(1);
97         }
98 #endif /* MSDOS */
99 #ifdef DEBUGGING
100     if ((long)size < 0)
101         croak("panic: malloc");
102 #endif
103     ptr = malloc(size?size:1);  /* malloc(0) is NASTY on our system */
104 #if !(defined(I286) || defined(atarist))
105     DEBUG_m(fprintf(stderr,"0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size));
106 #else
107     DEBUG_m(fprintf(stderr,"0x%lx: (%05d) malloc %ld bytes\n",ptr,an++,(long)size));
108 #endif
109     if (ptr != Nullch)
110         return ptr;
111     else if (nomemok)
112         return Nullch;
113     else {
114         fputs(no_mem,stderr) FLUSH;
115         my_exit(1);
116     }
117     /*NOTREACHED*/
118 }
119
120 /* paranoid version of realloc */
121
122 char *
123 saferealloc(where,size)
124 char *where;
125 #ifndef MSDOS
126 MEM_SIZE size;
127 #else
128 unsigned long size;
129 #endif /* MSDOS */
130 {
131     char *ptr;
132 #ifndef STANDARD_C
133     char *realloc();
134 #endif /* ! STANDARD_C */
135
136 #ifdef MSDOS
137         if (size > 0xffff) {
138                 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
139                 my_exit(1);
140         }
141 #endif /* MSDOS */
142     if (!where)
143         croak("Null realloc");
144 #ifdef DEBUGGING
145     if ((long)size < 0)
146         croak("panic: realloc");
147 #endif
148     ptr = realloc(where,size?size:1);   /* realloc(0) is NASTY on our system */
149
150 #if !(defined(I286) || defined(atarist))
151     DEBUG_m( {
152         fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
153         fprintf(stderr,"0x%x: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
154     } )
155 #else
156     DEBUG_m( {
157         fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
158         fprintf(stderr,"0x%lx: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
159     } )
160 #endif
161
162     if (ptr != Nullch)
163         return ptr;
164     else if (nomemok)
165         return Nullch;
166     else {
167         fputs(no_mem,stderr) FLUSH;
168         my_exit(1);
169     }
170     /*NOTREACHED*/
171 }
172
173 /* safe version of free */
174
175 void
176 safefree(where)
177 char *where;
178 {
179 #if !(defined(I286) || defined(atarist))
180     DEBUG_m( fprintf(stderr,"0x%x: (%05d) free\n",where,an++));
181 #else
182     DEBUG_m( fprintf(stderr,"0x%lx: (%05d) free\n",where,an++));
183 #endif
184     if (where) {
185         /*SUPPRESS 701*/
186         free(where);
187     }
188 }
189
190 #endif /* !safemalloc */
191
192 #ifdef LEAKTEST
193
194 #define ALIGN sizeof(long)
195
196 char *
197 safexmalloc(x,size)
198 I32 x;
199 MEM_SIZE size;
200 {
201     register char *where;
202
203     where = safemalloc(size + ALIGN);
204     xcount[x]++;
205     where[0] = x % 100;
206     where[1] = x / 100;
207     return where + ALIGN;
208 }
209
210 char *
211 safexrealloc(where,size)
212 char *where;
213 MEM_SIZE size;
214 {
215     return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
216 }
217
218 void
219 safexfree(where)
220 char *where;
221 {
222     I32 x;
223
224     if (!where)
225         return;
226     where -= ALIGN;
227     x = where[0] + 100 * where[1];
228     xcount[x]--;
229     safefree(where);
230 }
231
232 static void
233 xstat()
234 {
235     register I32 i;
236
237     for (i = 0; i < MAXXCOUNT; i++) {
238         if (xcount[i] > lastxcount[i]) {
239             fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
240             lastxcount[i] = xcount[i];
241         }
242     }
243 }
244
245 #endif /* LEAKTEST */
246
247 /* copy a string up to some (non-backslashed) delimiter, if any */
248
249 char *
250 cpytill(to,from,fromend,delim,retlen)
251 register char *to;
252 register char *from;
253 register char *fromend;
254 register I32 delim;
255 I32 *retlen;
256 {
257     char *origto = to;
258
259     for (; from < fromend; from++,to++) {
260         if (*from == '\\') {
261             if (from[1] == delim)
262                 from++;
263             else if (from[1] == '\\')
264                 *to++ = *from++;
265         }
266         else if (*from == delim)
267             break;
268         *to = *from;
269     }
270     *to = '\0';
271     *retlen = to - origto;
272     return from;
273 }
274
275 /* return ptr to little string in big string, NULL if not found */
276 /* This routine was donated by Corey Satten. */
277
278 char *
279 instr(big, little)
280 register char *big;
281 register char *little;
282 {
283     register char *s, *x;
284     register I32 first;
285
286     if (!little)
287         return big;
288     first = *little++;
289     if (!first)
290         return big;
291     while (*big) {
292         if (*big++ != first)
293             continue;
294         for (x=big,s=little; *s; /**/ ) {
295             if (!*x)
296                 return Nullch;
297             if (*s++ != *x++) {
298                 s--;
299                 break;
300             }
301         }
302         if (!*s)
303             return big-1;
304     }
305     return Nullch;
306 }
307
308 /* same as instr but allow embedded nulls */
309
310 char *
311 ninstr(big, bigend, little, lend)
312 register char *big;
313 register char *bigend;
314 char *little;
315 char *lend;
316 {
317     register char *s, *x;
318     register I32 first = *little;
319     register char *littleend = lend;
320
321     if (!first && little > littleend)
322         return big;
323     if (bigend - big < littleend - little)
324         return Nullch;
325     bigend -= littleend - little++;
326     while (big <= bigend) {
327         if (*big++ != first)
328             continue;
329         for (x=big,s=little; s < littleend; /**/ ) {
330             if (*s++ != *x++) {
331                 s--;
332                 break;
333             }
334         }
335         if (s >= littleend)
336             return big-1;
337     }
338     return Nullch;
339 }
340
341 /* reverse of the above--find last substring */
342
343 char *
344 rninstr(big, bigend, little, lend)
345 register char *big;
346 char *bigend;
347 char *little;
348 char *lend;
349 {
350     register char *bigbeg;
351     register char *s, *x;
352     register I32 first = *little;
353     register char *littleend = lend;
354
355     if (!first && little > littleend)
356         return bigend;
357     bigbeg = big;
358     big = bigend - (littleend - little++);
359     while (big >= bigbeg) {
360         if (*big-- != first)
361             continue;
362         for (x=big+2,s=little; s < littleend; /**/ ) {
363             if (*s++ != *x++) {
364                 s--;
365                 break;
366             }
367         }
368         if (s >= littleend)
369             return big+1;
370     }
371     return Nullch;
372 }
373
374 void
375 fbm_compile(sv, iflag)
376 SV *sv;
377 I32 iflag;
378 {
379     register unsigned char *s;
380     register unsigned char *table;
381     register U32 i;
382     register U32 len = SvCUR(sv);
383     I32 rarest = 0;
384     U32 frequency = 256;
385
386     Sv_Grow(sv,len+258);
387     table = (unsigned char*)(SvPVX(sv) + len + 1);
388     s = table - 2;
389     for (i = 0; i < 256; i++) {
390         table[i] = len;
391     }
392     i = 0;
393     while (s >= (unsigned char*)(SvPVX(sv)))
394     {
395         if (table[*s] == len) {
396 #ifndef pdp11
397             if (iflag)
398                 table[*s] = table[fold[*s]] = i;
399 #else
400             if (iflag) {
401                 I32 j;
402                 j = fold[*s];
403                 table[j] = i;
404                 table[*s] = i;
405             }
406 #endif /* pdp11 */
407             else
408                 table[*s] = i;
409         }
410         s--,i++;
411     }
412     sv_upgrade(sv, SVt_PVBM);
413     sv_magic(sv, 0, 'B', 0, 0);                 /* deep magic */
414     SvVALID_on(sv);
415
416     s = (unsigned char*)(SvPVX(sv));            /* deeper magic */
417     if (iflag) {
418         register U32 tmp, foldtmp;
419         SvCASEFOLD_on(sv);
420         for (i = 0; i < len; i++) {
421             tmp=freq[s[i]];
422             foldtmp=freq[fold[s[i]]];
423             if (tmp < frequency && foldtmp < frequency) {
424                 rarest = i;
425                 /* choose most frequent among the two */
426                 frequency = (tmp > foldtmp) ? tmp : foldtmp;
427             }
428         }
429     }
430     else {
431         for (i = 0; i < len; i++) {
432             if (freq[s[i]] < frequency) {
433                 rarest = i;
434                 frequency = freq[s[i]];
435             }
436         }
437     }
438     BmRARE(sv) = s[rarest];
439     BmPREVIOUS(sv) = rarest;
440     DEBUG_r(fprintf(stderr,"rarest char %c at %d\n",BmRARE(sv),BmPREVIOUS(sv)));
441 }
442
443 char *
444 fbm_instr(big, bigend, littlestr)
445 unsigned char *big;
446 register unsigned char *bigend;
447 SV *littlestr;
448 {
449     register unsigned char *s;
450     register I32 tmp;
451     register I32 littlelen;
452     register unsigned char *little;
453     register unsigned char *table;
454     register unsigned char *olds;
455     register unsigned char *oldlittle;
456
457     if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) {
458         if (!SvPOK(littlestr) || !SvPVX(littlestr))
459             return (char*)big;
460         return ninstr((char*)big,(char*)bigend,
461                 SvPVX(littlestr), SvPVX(littlestr) + SvCUR(littlestr));
462     }
463
464     littlelen = SvCUR(littlestr);
465     if (SvTAIL(littlestr) && !multiline) {      /* tail anchored? */
466         if (littlelen > bigend - big)
467             return Nullch;
468         little = (unsigned char*)SvPVX(littlestr);
469         if (SvCASEFOLD(littlestr)) {    /* oops, fake it */
470             big = bigend - littlelen;           /* just start near end */
471             if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
472                 big--;
473         }
474         else {
475             s = bigend - littlelen;
476             if (*s == *little && bcmp(s,little,littlelen)==0)
477                 return (char*)s;                /* how sweet it is */
478             else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
479               && s > big) {
480                     s--;
481                 if (*s == *little && bcmp(s,little,littlelen)==0)
482                     return (char*)s;
483             }
484             return Nullch;
485         }
486     }
487     table = (unsigned char*)(SvPVX(littlestr) + littlelen + 1);
488     if (--littlelen >= bigend - big)
489         return Nullch;
490     s = big + littlelen;
491     oldlittle = little = table - 2;
492     if (SvCASEFOLD(littlestr)) {        /* case insensitive? */
493         if (s < bigend) {
494           top1:
495             /*SUPPRESS 560*/
496             if (tmp = table[*s]) {
497 #ifdef POINTERRIGOR
498                 if (bigend - s > tmp) {
499                     s += tmp;
500                     goto top1;
501                 }
502 #else
503                 if ((s += tmp) < bigend)
504                     goto top1;
505 #endif
506                 return Nullch;
507             }
508             else {
509                 tmp = littlelen;        /* less expensive than calling strncmp() */
510                 olds = s;
511                 while (tmp--) {
512                     if (*--s == *--little || fold[*s] == *little)
513                         continue;
514                     s = olds + 1;       /* here we pay the price for failure */
515                     little = oldlittle;
516                     if (s < bigend)     /* fake up continue to outer loop */
517                         goto top1;
518                     return Nullch;
519                 }
520                 return (char *)s;
521             }
522         }
523     }
524     else {
525         if (s < bigend) {
526           top2:
527             /*SUPPRESS 560*/
528             if (tmp = table[*s]) {
529 #ifdef POINTERRIGOR
530                 if (bigend - s > tmp) {
531                     s += tmp;
532                     goto top2;
533                 }
534 #else
535                 if ((s += tmp) < bigend)
536                     goto top2;
537 #endif
538                 return Nullch;
539             }
540             else {
541                 tmp = littlelen;        /* less expensive than calling strncmp() */
542                 olds = s;
543                 while (tmp--) {
544                     if (*--s == *--little)
545                         continue;
546                     s = olds + 1;       /* here we pay the price for failure */
547                     little = oldlittle;
548                     if (s < bigend)     /* fake up continue to outer loop */
549                         goto top2;
550                     return Nullch;
551                 }
552                 return (char *)s;
553             }
554         }
555     }
556     return Nullch;
557 }
558
559 char *
560 screaminstr(bigstr, littlestr)
561 SV *bigstr;
562 SV *littlestr;
563 {
564     register unsigned char *s, *x;
565     register unsigned char *big;
566     register I32 pos;
567     register I32 previous;
568     register I32 first;
569     register unsigned char *little;
570     register unsigned char *bigend;
571     register unsigned char *littleend;
572
573     if ((pos = screamfirst[BmRARE(littlestr)]) < 0) 
574         return Nullch;
575     little = (unsigned char *)(SvPVX(littlestr));
576     littleend = little + SvCUR(littlestr);
577     first = *little++;
578     previous = BmPREVIOUS(littlestr);
579     big = (unsigned char *)(SvPVX(bigstr));
580     bigend = big + SvCUR(bigstr);
581     while (pos < previous) {
582         if (!(pos += screamnext[pos]))
583             return Nullch;
584     }
585 #ifdef POINTERRIGOR
586     if (SvCASEFOLD(littlestr)) {        /* case insignificant? */
587         do {
588             if (big[pos-previous] != first && big[pos-previous] != fold[first])
589                 continue;
590             for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
591                 if (x >= bigend)
592                     return Nullch;
593                 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
594                     s--;
595                     break;
596                 }
597             }
598             if (s == littleend)
599                 return (char *)(big+pos-previous);
600         } while (
601                 pos += screamnext[pos]  /* does this goof up anywhere? */
602             );
603     }
604     else {
605         do {
606             if (big[pos-previous] != first)
607                 continue;
608             for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
609                 if (x >= bigend)
610                     return Nullch;
611                 if (*s++ != *x++) {
612                     s--;
613                     break;
614                 }
615             }
616             if (s == littleend)
617                 return (char *)(big+pos-previous);
618         } while ( pos += screamnext[pos] );
619     }
620 #else /* !POINTERRIGOR */
621     big -= previous;
622     if (SvCASEFOLD(littlestr)) {        /* case insignificant? */
623         do {
624             if (big[pos] != first && big[pos] != fold[first])
625                 continue;
626             for (x=big+pos+1,s=little; s < littleend; /**/ ) {
627                 if (x >= bigend)
628                     return Nullch;
629                 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
630                     s--;
631                     break;
632                 }
633             }
634             if (s == littleend)
635                 return (char *)(big+pos);
636         } while (
637                 pos += screamnext[pos]  /* does this goof up anywhere? */
638             );
639     }
640     else {
641         do {
642             if (big[pos] != first)
643                 continue;
644             for (x=big+pos+1,s=little; s < littleend; /**/ ) {
645                 if (x >= bigend)
646                     return Nullch;
647                 if (*s++ != *x++) {
648                     s--;
649                     break;
650                 }
651             }
652             if (s == littleend)
653                 return (char *)(big+pos);
654         } while (
655                 pos += screamnext[pos]
656             );
657     }
658 #endif /* POINTERRIGOR */
659     return Nullch;
660 }
661
662 I32
663 ibcmp(a,b,len)
664 register char *a;
665 register char *b;
666 register I32 len;
667 {
668     while (len--) {
669         if (*a == *b) {
670             a++,b++;
671             continue;
672         }
673         if (fold[*a++] == *b++)
674             continue;
675         return 1;
676     }
677     return 0;
678 }
679
680 /* copy a string to a safe spot */
681
682 char *
683 savestr(sv)
684 char *sv;
685 {
686     register char *newaddr;
687
688     New(902,newaddr,strlen(sv)+1,char);
689     (void)strcpy(newaddr,sv);
690     return newaddr;
691 }
692
693 /* same thing but with a known length */
694
695 char *
696 nsavestr(sv, len)
697 char *sv;
698 register I32 len;
699 {
700     register char *newaddr;
701
702     New(903,newaddr,len+1,char);
703     Copy(sv,newaddr,len,char);          /* might not be null terminated */
704     newaddr[len] = '\0';                /* is now */
705     return newaddr;
706 }
707
708 #if !defined(STANDARD_C) && !defined(I_VARARGS)
709
710 /*
711  * Fallback on the old hackers way of doing varargs
712  */
713
714 /*VARARGS1*/
715 char *
716 mess(pat,a1,a2,a3,a4)
717 char *pat;
718 long a1, a2, a3, a4;
719 {
720     char *s;
721     I32 usermess = strEQ(pat,"%s");
722     SV *tmpstr;
723
724     s = buf;
725     if (usermess) {
726         tmpstr = sv_newmortal();
727         sv_setpv(tmpstr, (char*)a1);
728         *s++ = SvPVX(tmpstr)[SvCUR(tmpstr)-1];
729     }
730     else {
731         (void)sprintf(s,pat,a1,a2,a3,a4);
732         s += strlen(s);
733     }
734
735     if (s[-1] != '\n') {
736         if (dirty)
737             strcpy(s, " during global destruction.\n");
738         else {
739             if (curcop->cop_line) {
740                 (void)sprintf(s," at %s line %ld",
741                   SvPVX(GvSV(curcop->cop_filegv)), (long)curcop->cop_line);
742                 s += strlen(s);
743             }
744             if (last_in_gv &&
745                 GvIO(last_in_gv) &&
746                 IoLINES(GvIO(last_in_gv)) ) {
747                 (void)sprintf(s,", <%s> %s %ld",
748                   last_in_gv == argvgv ? "" : GvENAME(last_in_gv),
749                   strEQ(rs,"\n") ? "line" : "chunk", 
750                   (long)IoLINES(GvIO(last_in_gv)));
751                 s += strlen(s);
752             }
753             (void)strcpy(s,".\n");
754         }
755         if (usermess)
756             sv_catpv(tmpstr,buf+1);
757     }
758     if (usermess)
759         return SvPVX(tmpstr);
760     else
761         return buf;
762 }
763
764 /*VARARGS1*/
765 void croak(pat,a1,a2,a3,a4)
766 char *pat;
767 long a1, a2, a3, a4;
768 {
769     char *tmps;
770     char *message;
771
772     message = mess(pat,a1,a2,a3,a4);
773     fputs(message,stderr);
774     (void)fflush(stderr);
775     if (e_fp)
776         (void)UNLINK(e_tmpname);
777     statusvalue >>= 8;
778     my_exit((I32)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
779 }
780
781 /*VARARGS1*/
782 void warn(pat,a1,a2,a3,a4)
783 char *pat;
784 long a1, a2, a3, a4;
785 {
786     char *message;
787
788     message = mess(pat,a1,a2,a3,a4);
789     fputs(message,stderr);
790 #ifdef LEAKTEST
791     DEBUG_L(xstat());
792 #endif
793     (void)fflush(stderr);
794 }
795
796 #else /* !defined(STANDARD_C) && !defined(I_VARARGS) */
797
798 #ifdef STANDARD_C
799 char *
800 mess(char *pat, va_list *args)
801 #else
802 /*VARARGS0*/
803 char *
804 mess(pat, args)
805     char *pat;
806     va_list *args;
807 #endif
808 {
809     char *s;
810     SV *tmpstr;
811     I32 usermess;
812 #ifndef HAS_VPRINTF
813 #ifdef CHARVSPRINTF
814     char *vsprintf();
815 #else
816     I32 vsprintf();
817 #endif
818 #endif
819
820     s = buf;
821     usermess = strEQ(pat, "%s");
822     if (usermess) {
823         tmpstr = sv_newmortal();
824         sv_setpv(tmpstr, va_arg(*args, char *));
825         *s++ = SvPVX(tmpstr)[SvCUR(tmpstr)-1];
826     }
827     else {
828         (void) vsprintf(s,pat,*args);
829         s += strlen(s);
830     }
831     va_end(*args);
832
833     if (s[-1] != '\n') {
834         if (dirty)
835             strcpy(s, " during global destruction.\n");
836         else {
837             if (curcop->cop_line) {
838                 (void)sprintf(s," at %s line %ld",
839                   SvPVX(GvSV(curcop->cop_filegv)), (long)curcop->cop_line);
840                 s += strlen(s);
841             }
842             if (last_in_gv &&
843                 GvIO(last_in_gv) &&
844                 IoLINES(GvIO(last_in_gv)) ) {
845                 (void)sprintf(s,", <%s> %s %ld",
846                   last_in_gv == argvgv ? "" : GvNAME(last_in_gv),
847                   strEQ(rs,"\n") ? "line" : "chunk", 
848                   (long)IoLINES(GvIO(last_in_gv)));
849                 s += strlen(s);
850             }
851             (void)strcpy(s,".\n");
852         }
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 }