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