This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 3.0 patch #17 patch #16, continued
[perl5.git] / util.c
CommitLineData
9f68db38 1/* $Header: util.c,v 3.0.1.4 90/03/01 10:26:48 lwall Locked $
a687059c
LW
2 *
3 * Copyright (c) 1989, Larry Wall
4 *
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
8d063cd8
LW
7 *
8 * $Log: util.c,v $
9f68db38
LW
9 * Revision 3.0.1.4 90/03/01 10:26:48 lwall
10 * patch9: fbminstr() called instr() rather than ninstr()
11 * patch9: nested evals clobbered their longjmp environment
12 * patch9: piped opens returned undefined rather than 0 in child
13 * patch9: the x operator is now up to 10 times faster
14 *
663a0e37
LW
15 * Revision 3.0.1.3 89/12/21 20:27:41 lwall
16 * patch7: errno may now be a macro with an lvalue
17 *
ffed7fef
LW
18 * Revision 3.0.1.2 89/11/17 15:46:35 lwall
19 * patch5: BZERO separate from BCOPY now
20 * patch5: byteorder now is a hex value
21 *
ae986130
LW
22 * Revision 3.0.1.1 89/11/11 05:06:13 lwall
23 * patch2: made dup2 a little better
24 *
a687059c
LW
25 * Revision 3.0 89/10/18 15:32:43 lwall
26 * 3.0 baseline
8d063cd8
LW
27 *
28 */
29
8d063cd8 30#include "EXTERN.h"
8d063cd8 31#include "perl.h"
a687059c
LW
32#include <signal.h>
33
34#ifdef I_VFORK
35# include <vfork.h>
36#endif
37
38#ifdef I_VARARGS
39# include <varargs.h>
40#endif
8d063cd8
LW
41
42#define FLUSH
8d063cd8
LW
43
44static char nomem[] = "Out of memory!\n";
45
46/* paranoid version of malloc */
47
378cc40b 48#ifdef DEBUGGING
8d063cd8 49static int an = 0;
378cc40b 50#endif
8d063cd8 51
a687059c
LW
52/* NOTE: Do not call the next three routines directly. Use the macros
53 * in handy.h, so that we can easily redefine everything to do tracking of
54 * allocated hunks back to the original New to track down any memory leaks.
55 */
56
8d063cd8
LW
57char *
58safemalloc(size)
59MEM_SIZE size;
60{
61 char *ptr;
62 char *malloc();
63
64 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
65#ifdef DEBUGGING
a687059c 66# ifndef I286
8d063cd8
LW
67 if (debug & 128)
68 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
a687059c
LW
69# else
70 if (debug & 128)
71 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
72# endif
8d063cd8
LW
73#endif
74 if (ptr != Nullch)
75 return ptr;
76 else {
77 fputs(nomem,stdout) FLUSH;
78 exit(1);
79 }
80 /*NOTREACHED*/
a687059c
LW
81#ifdef lint
82 return ptr;
83#endif
8d063cd8
LW
84}
85
86/* paranoid version of realloc */
87
88char *
89saferealloc(where,size)
90char *where;
91MEM_SIZE size;
92{
93 char *ptr;
94 char *realloc();
95
378cc40b
LW
96 if (!where)
97 fatal("Null realloc");
8d063cd8
LW
98 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
99#ifdef DEBUGGING
a687059c 100# ifndef I286
8d063cd8
LW
101 if (debug & 128) {
102 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
103 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
104 }
a687059c
LW
105# else
106 if (debug & 128) {
107 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
108 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
109 }
110# endif
8d063cd8
LW
111#endif
112 if (ptr != Nullch)
113 return ptr;
114 else {
115 fputs(nomem,stdout) FLUSH;
116 exit(1);
117 }
118 /*NOTREACHED*/
a687059c
LW
119#ifdef lint
120 return ptr;
121#endif
8d063cd8
LW
122}
123
124/* safe version of free */
125
a687059c 126void
8d063cd8
LW
127safefree(where)
128char *where;
129{
130#ifdef DEBUGGING
a687059c 131# ifndef I286
8d063cd8
LW
132 if (debug & 128)
133 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
a687059c
LW
134# else
135 if (debug & 128)
136 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
137# endif
8d063cd8 138#endif
378cc40b
LW
139 if (where) {
140 free(where);
141 }
8d063cd8
LW
142}
143
a687059c
LW
144#ifdef LEAKTEST
145
146#define ALIGN sizeof(long)
8d063cd8
LW
147
148char *
a687059c
LW
149safexmalloc(x,size)
150int x;
151MEM_SIZE size;
8d063cd8 152{
a687059c 153 register char *where;
8d063cd8 154
a687059c
LW
155 where = safemalloc(size + ALIGN);
156 xcount[x]++;
157 where[0] = x % 100;
158 where[1] = x / 100;
159 return where + ALIGN;
8d063cd8 160}
8d063cd8
LW
161
162char *
a687059c
LW
163safexrealloc(where,size)
164char *where;
165MEM_SIZE size;
166{
167 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
168}
169
170void
171safexfree(where)
172char *where;
173{
174 int x;
175
176 if (!where)
177 return;
178 where -= ALIGN;
179 x = where[0] + 100 * where[1];
180 xcount[x]--;
181 safefree(where);
182}
183
184xstat()
8d063cd8 185{
a687059c 186 register int i;
8d063cd8 187
a687059c
LW
188 for (i = 0; i < MAXXCOUNT; i++) {
189 if (xcount[i] != lastxcount[i]) {
190 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
191 lastxcount[i] = xcount[i];
8d063cd8
LW
192 }
193 }
8d063cd8 194}
a687059c
LW
195
196#endif /* LEAKTEST */
8d063cd8
LW
197
198/* copy a string up to some (non-backslashed) delimiter, if any */
199
200char *
a687059c 201cpytill(to,from,fromend,delim,retlen)
8d063cd8 202register char *to, *from;
a687059c 203register char *fromend;
8d063cd8 204register int delim;
a687059c 205int *retlen;
8d063cd8 206{
a687059c
LW
207 char *origto = to;
208
209 for (; from < fromend; from++,to++) {
378cc40b
LW
210 if (*from == '\\') {
211 if (from[1] == delim)
212 from++;
213 else if (from[1] == '\\')
214 *to++ = *from++;
215 }
8d063cd8
LW
216 else if (*from == delim)
217 break;
218 *to = *from;
219 }
220 *to = '\0';
a687059c 221 *retlen = to - origto;
8d063cd8
LW
222 return from;
223}
224
225/* return ptr to little string in big string, NULL if not found */
378cc40b 226/* This routine was donated by Corey Satten. */
8d063cd8
LW
227
228char *
229instr(big, little)
378cc40b
LW
230register char *big;
231register char *little;
232{
233 register char *s, *x;
a687059c 234 register int first;
378cc40b 235
a687059c
LW
236 if (!little)
237 return big;
238 first = *little++;
378cc40b
LW
239 if (!first)
240 return big;
241 while (*big) {
242 if (*big++ != first)
243 continue;
244 for (x=big,s=little; *s; /**/ ) {
245 if (!*x)
246 return Nullch;
247 if (*s++ != *x++) {
248 s--;
249 break;
250 }
251 }
252 if (!*s)
253 return big-1;
254 }
255 return Nullch;
256}
8d063cd8 257
a687059c
LW
258/* same as instr but allow embedded nulls */
259
260char *
261ninstr(big, bigend, little, lend)
262register char *big;
263register char *bigend;
264char *little;
265char *lend;
8d063cd8 266{
a687059c
LW
267 register char *s, *x;
268 register int first = *little;
269 register char *littleend = lend;
378cc40b 270
a687059c
LW
271 if (!first && little > littleend)
272 return big;
273 bigend -= littleend - little++;
274 while (big <= bigend) {
275 if (*big++ != first)
276 continue;
277 for (x=big,s=little; s < littleend; /**/ ) {
278 if (*s++ != *x++) {
279 s--;
280 break;
281 }
282 }
283 if (s >= littleend)
284 return big-1;
378cc40b 285 }
a687059c
LW
286 return Nullch;
287}
288
289/* reverse of the above--find last substring */
290
291char *
292rninstr(big, bigend, little, lend)
293register char *big;
294char *bigend;
295char *little;
296char *lend;
297{
298 register char *bigbeg;
299 register char *s, *x;
300 register int first = *little;
301 register char *littleend = lend;
302
303 if (!first && little > littleend)
304 return bigend;
305 bigbeg = big;
306 big = bigend - (littleend - little++);
307 while (big >= bigbeg) {
308 if (*big-- != first)
309 continue;
310 for (x=big+2,s=little; s < littleend; /**/ ) {
311 if (*s++ != *x++) {
312 s--;
313 break;
314 }
315 }
316 if (s >= littleend)
317 return big+1;
378cc40b 318 }
a687059c 319 return Nullch;
378cc40b 320}
a687059c
LW
321
322unsigned char fold[] = {
323 0, 1, 2, 3, 4, 5, 6, 7,
324 8, 9, 10, 11, 12, 13, 14, 15,
325 16, 17, 18, 19, 20, 21, 22, 23,
326 24, 25, 26, 27, 28, 29, 30, 31,
327 32, 33, 34, 35, 36, 37, 38, 39,
328 40, 41, 42, 43, 44, 45, 46, 47,
329 48, 49, 50, 51, 52, 53, 54, 55,
330 56, 57, 58, 59, 60, 61, 62, 63,
331 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
332 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
333 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
334 'x', 'y', 'z', 91, 92, 93, 94, 95,
335 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
336 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
337 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
338 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
339 128, 129, 130, 131, 132, 133, 134, 135,
340 136, 137, 138, 139, 140, 141, 142, 143,
341 144, 145, 146, 147, 148, 149, 150, 151,
342 152, 153, 154, 155, 156, 157, 158, 159,
343 160, 161, 162, 163, 164, 165, 166, 167,
344 168, 169, 170, 171, 172, 173, 174, 175,
345 176, 177, 178, 179, 180, 181, 182, 183,
346 184, 185, 186, 187, 188, 189, 190, 191,
347 192, 193, 194, 195, 196, 197, 198, 199,
348 200, 201, 202, 203, 204, 205, 206, 207,
349 208, 209, 210, 211, 212, 213, 214, 215,
350 216, 217, 218, 219, 220, 221, 222, 223,
351 224, 225, 226, 227, 228, 229, 230, 231,
352 232, 233, 234, 235, 236, 237, 238, 239,
353 240, 241, 242, 243, 244, 245, 246, 247,
354 248, 249, 250, 251, 252, 253, 254, 255
355};
378cc40b
LW
356
357static unsigned char freq[] = {
358 1, 2, 84, 151, 154, 155, 156, 157,
359 165, 246, 250, 3, 158, 7, 18, 29,
360 40, 51, 62, 73, 85, 96, 107, 118,
361 129, 140, 147, 148, 149, 150, 152, 153,
362 255, 182, 224, 205, 174, 176, 180, 217,
363 233, 232, 236, 187, 235, 228, 234, 226,
364 222, 219, 211, 195, 188, 193, 185, 184,
365 191, 183, 201, 229, 181, 220, 194, 162,
366 163, 208, 186, 202, 200, 218, 198, 179,
367 178, 214, 166, 170, 207, 199, 209, 206,
368 204, 160, 212, 216, 215, 192, 175, 173,
369 243, 172, 161, 190, 203, 189, 164, 230,
370 167, 248, 227, 244, 242, 255, 241, 231,
371 240, 253, 169, 210, 245, 237, 249, 247,
372 239, 168, 252, 251, 254, 238, 223, 221,
373 213, 225, 177, 197, 171, 196, 159, 4,
374 5, 6, 8, 9, 10, 11, 12, 13,
375 14, 15, 16, 17, 19, 20, 21, 22,
376 23, 24, 25, 26, 27, 28, 30, 31,
377 32, 33, 34, 35, 36, 37, 38, 39,
378 41, 42, 43, 44, 45, 46, 47, 48,
379 49, 50, 52, 53, 54, 55, 56, 57,
380 58, 59, 60, 61, 63, 64, 65, 66,
381 67, 68, 69, 70, 71, 72, 74, 75,
382 76, 77, 78, 79, 80, 81, 82, 83,
383 86, 87, 88, 89, 90, 91, 92, 93,
384 94, 95, 97, 98, 99, 100, 101, 102,
385 103, 104, 105, 106, 108, 109, 110, 111,
386 112, 113, 114, 115, 116, 117, 119, 120,
387 121, 122, 123, 124, 125, 126, 127, 128,
388 130, 131, 132, 133, 134, 135, 136, 137,
389 138, 139, 141, 142, 143, 144, 145, 146
390};
8d063cd8 391
378cc40b 392void
a687059c 393fbmcompile(str, iflag)
378cc40b 394STR *str;
a687059c 395int iflag;
378cc40b 396{
a687059c
LW
397 register unsigned char *s;
398 register unsigned char *table;
378cc40b
LW
399 register int i;
400 register int len = str->str_cur;
401 int rarest = 0;
402 int frequency = 256;
403
a687059c
LW
404 str_grow(str,len+258);
405#ifndef lint
406 table = (unsigned char*)(str->str_ptr + len + 1);
407#else
408 table = Null(unsigned char*);
409#endif
410 s = table - 2;
411 for (i = 0; i < 256; i++) {
378cc40b
LW
412 table[i] = len;
413 }
414 i = 0;
a687059c
LW
415#ifndef lint
416 while (s >= (unsigned char*)(str->str_ptr))
417#endif
418 {
419 if (table[*s] == len) {
420#ifndef pdp11
421 if (iflag)
422 table[*s] = table[fold[*s]] = i;
423#else
424 if (iflag) {
425 int j;
426 j = fold[*s];
427 table[j] = i;
428 table[*s] = i;
429 }
430#endif /* pdp11 */
431 else
432 table[*s] = i;
433 }
378cc40b
LW
434 s--,i++;
435 }
a687059c 436 str->str_pok |= SP_FBM; /* deep magic */
378cc40b 437
a687059c
LW
438#ifndef lint
439 s = (unsigned char*)(str->str_ptr); /* deeper magic */
440#else
441 s = Null(unsigned char*);
442#endif
443 if (iflag) {
444 register int tmp, foldtmp;
445 str->str_pok |= SP_CASEFOLD;
446 for (i = 0; i < len; i++) {
447 tmp=freq[s[i]];
448 foldtmp=freq[fold[s[i]]];
449 if (tmp < frequency && foldtmp < frequency) {
450 rarest = i;
451 /* choose most frequent among the two */
452 frequency = (tmp > foldtmp) ? tmp : foldtmp;
453 }
454 }
455 }
456 else {
457 for (i = 0; i < len; i++) {
458 if (freq[s[i]] < frequency) {
459 rarest = i;
460 frequency = freq[s[i]];
461 }
378cc40b
LW
462 }
463 }
464 str->str_rare = s[rarest];
a687059c 465 str->str_state = rarest;
378cc40b
LW
466#ifdef DEBUGGING
467 if (debug & 512)
a687059c 468 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
378cc40b
LW
469#endif
470}
471
378cc40b
LW
472char *
473fbminstr(big, bigend, littlestr)
a687059c
LW
474unsigned char *big;
475register unsigned char *bigend;
378cc40b
LW
476STR *littlestr;
477{
a687059c 478 register unsigned char *s;
378cc40b
LW
479 register int tmp;
480 register int littlelen;
a687059c
LW
481 register unsigned char *little;
482 register unsigned char *table;
483 register unsigned char *olds;
484 register unsigned char *oldlittle;
378cc40b 485
a687059c
LW
486#ifndef lint
487 if (!(littlestr->str_pok & SP_FBM))
9f68db38
LW
488 return ninstr((char*)big,(char*)bigend,
489 littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
a687059c 490#endif
378cc40b
LW
491
492 littlelen = littlestr->str_cur;
a687059c
LW
493#ifndef lint
494 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
495 little = (unsigned char*)littlestr->str_ptr;
496 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
497 big = bigend - littlelen; /* just start near end */
498 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
499 big--;
378cc40b
LW
500 }
501 else {
a687059c
LW
502 s = bigend - littlelen;
503 if (*s == *little && bcmp(s,little,littlelen)==0)
504 return (char*)s; /* how sweet it is */
505 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n') {
506 s--;
507 if (*s == *little && bcmp(s,little,littlelen)==0)
508 return (char*)s;
509 }
510 return Nullch;
511 }
512 }
513 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
514#else
515 table = Null(unsigned char*);
516#endif
517 s = big + --littlelen;
518 oldlittle = little = table - 2;
519 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
520 while (s < bigend) {
521 top1:
522 if (tmp = table[*s]) {
523 s += tmp;
524 }
525 else {
526 tmp = littlelen; /* less expensive than calling strncmp() */
527 olds = s;
528 while (tmp--) {
529 if (*--s == *--little || fold[*s] == *little)
530 continue;
531 s = olds + 1; /* here we pay the price for failure */
532 little = oldlittle;
533 if (s < bigend) /* fake up continue to outer loop */
534 goto top1;
535 return Nullch;
536 }
537#ifndef lint
538 return (char *)s;
539#endif
540 }
541 }
542 }
543 else {
544 while (s < bigend) {
545 top2:
546 if (tmp = table[*s]) {
547 s += tmp;
548 }
549 else {
550 tmp = littlelen; /* less expensive than calling strncmp() */
551 olds = s;
552 while (tmp--) {
553 if (*--s == *--little)
554 continue;
555 s = olds + 1; /* here we pay the price for failure */
556 little = oldlittle;
557 if (s < bigend) /* fake up continue to outer loop */
558 goto top2;
559 return Nullch;
560 }
561#ifndef lint
562 return (char *)s;
563#endif
378cc40b 564 }
378cc40b
LW
565 }
566 }
567 return Nullch;
568}
569
570char *
571screaminstr(bigstr, littlestr)
572STR *bigstr;
573STR *littlestr;
574{
a687059c
LW
575 register unsigned char *s, *x;
576 register unsigned char *big;
378cc40b
LW
577 register int pos;
578 register int previous;
579 register int first;
a687059c
LW
580 register unsigned char *little;
581 register unsigned char *bigend;
582 register unsigned char *littleend;
378cc40b
LW
583
584 if ((pos = screamfirst[littlestr->str_rare]) < 0)
585 return Nullch;
a687059c
LW
586#ifndef lint
587 little = (unsigned char *)(littlestr->str_ptr);
588#else
589 little = Null(unsigned char *);
590#endif
591 littleend = little + littlestr->str_cur;
378cc40b 592 first = *little++;
a687059c
LW
593 previous = littlestr->str_state;
594#ifndef lint
595 big = (unsigned char *)(bigstr->str_ptr);
596#else
597 big = Null(unsigned char*);
598#endif
599 bigend = big + bigstr->str_cur;
378cc40b
LW
600 big -= previous;
601 while (pos < previous) {
a687059c 602#ifndef lint
378cc40b 603 if (!(pos += screamnext[pos]))
a687059c 604#endif
378cc40b
LW
605 return Nullch;
606 }
a687059c
LW
607 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
608 do {
609 if (big[pos] != first && big[pos] != fold[first])
610 continue;
611 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
612 if (x >= bigend)
613 return Nullch;
614 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
615 s--;
616 break;
617 }
618 }
619 if (s == littleend)
620#ifndef lint
621 return (char *)(big+pos);
622#else
8d063cd8 623 return Nullch;
a687059c
LW
624#endif
625 } while (
626#ifndef lint
627 pos += screamnext[pos] /* does this goof up anywhere? */
628#else
629 pos += screamnext[0]
630#endif
631 );
632 }
633 else {
634 do {
635 if (big[pos] != first)
636 continue;
637 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
638 if (x >= bigend)
639 return Nullch;
640 if (*s++ != *x++) {
641 s--;
642 break;
643 }
378cc40b 644 }
a687059c
LW
645 if (s == littleend)
646#ifndef lint
647 return (char *)(big+pos);
648#else
649 return Nullch;
650#endif
651 } while (
652#ifndef lint
653 pos += screamnext[pos]
654#else
655 pos += screamnext[0]
656#endif
657 );
658 }
8d063cd8
LW
659 return Nullch;
660}
661
662/* copy a string to a safe spot */
663
664char *
665savestr(str)
666char *str;
667{
a687059c 668 register char *newaddr;
8d063cd8 669
a687059c 670 New(902,newaddr,strlen(str)+1,char);
8d063cd8
LW
671 (void)strcpy(newaddr,str);
672 return newaddr;
673}
674
a687059c
LW
675/* same thing but with a known length */
676
677char *
678nsavestr(str, len)
679char *str;
680register int len;
681{
682 register char *newaddr;
683
684 New(903,newaddr,len+1,char);
685 (void)bcopy(str,newaddr,len); /* might not be null terminated */
686 newaddr[len] = '\0'; /* is now */
687 return newaddr;
688}
689
8d063cd8
LW
690/* grow a static string to at least a certain length */
691
692void
693growstr(strptr,curlen,newlen)
694char **strptr;
695int *curlen;
696int newlen;
697{
698 if (newlen > *curlen) { /* need more room? */
699 if (*curlen)
a687059c 700 Renew(*strptr,newlen,char);
8d063cd8 701 else
a687059c 702 New(905,*strptr,newlen,char);
8d063cd8
LW
703 *curlen = newlen;
704 }
705}
706
a687059c 707#ifndef VARARGS
378cc40b
LW
708/*VARARGS1*/
709mess(pat,a1,a2,a3,a4)
710char *pat;
a687059c 711long a1, a2, a3, a4;
378cc40b
LW
712{
713 char *s;
714
a687059c
LW
715 s = buf;
716 (void)sprintf(s,pat,a1,a2,a3,a4);
378cc40b
LW
717 s += strlen(s);
718 if (s[-1] != '\n') {
719 if (line) {
a687059c 720 (void)sprintf(s," at %s line %ld",
378cc40b
LW
721 in_eval?filename:origfilename, (long)line);
722 s += strlen(s);
723 }
724 if (last_in_stab &&
a687059c
LW
725 stab_io(last_in_stab) &&
726 stab_io(last_in_stab)->lines ) {
727 (void)sprintf(s,", <%s> line %ld",
728 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
729 (long)stab_io(last_in_stab)->lines);
378cc40b
LW
730 s += strlen(s);
731 }
a687059c 732 (void)strcpy(s,".\n");
378cc40b
LW
733 }
734}
735
8d063cd8
LW
736/*VARARGS1*/
737fatal(pat,a1,a2,a3,a4)
738char *pat;
a687059c 739long a1, a2, a3, a4;
8d063cd8
LW
740{
741 extern FILE *e_fp;
742 extern char *e_tmpname;
9f68db38 743 char *tmps;
8d063cd8 744
378cc40b 745 mess(pat,a1,a2,a3,a4);
a559c259 746 if (in_eval) {
a687059c 747 str_set(stab_val(stabent("@",TRUE)),buf);
9f68db38
LW
748 tmps = "_EVAL_";
749 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
750 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
751#ifdef DEBUGGING
752 if (debug & 4) {
753 deb("(Skipping label #%d %s)\n",loop_ptr,
754 loop_stack[loop_ptr].loop_label);
755 }
756#endif
757 loop_ptr--;
758 }
759#ifdef DEBUGGING
760 if (debug & 4) {
761 deb("(Found label #%d %s)\n",loop_ptr,
762 loop_stack[loop_ptr].loop_label);
763 }
764#endif
765 if (loop_ptr < 0) {
766 in_eval = 0;
767 fatal("Bad label: %s", tmps);
768 }
769 longjmp(loop_stack[loop_ptr].loop_env, 1);
a559c259 770 }
a687059c
LW
771 fputs(buf,stderr);
772 (void)fflush(stderr);
8d063cd8 773 if (e_fp)
a687059c 774 (void)UNLINK(e_tmpname);
378cc40b
LW
775 statusvalue >>= 8;
776 exit(errno?errno:(statusvalue?statusvalue:255));
777}
778
779/*VARARGS1*/
780warn(pat,a1,a2,a3,a4)
781char *pat;
a687059c 782long a1, a2, a3, a4;
378cc40b
LW
783{
784 mess(pat,a1,a2,a3,a4);
a687059c
LW
785 fputs(buf,stderr);
786#ifdef LEAKTEST
787#ifdef DEBUGGING
788 if (debug & 4096)
789 xstat();
790#endif
791#endif
792 (void)fflush(stderr);
8d063cd8 793}
a687059c
LW
794#else
795/*VARARGS0*/
796mess(args)
797va_list args;
798{
799 char *pat;
800 char *s;
801#ifdef CHARVSPRINTF
802 char *vsprintf();
803#else
804 int vsprintf();
805#endif
806
807 s = buf;
808#ifdef lint
809 pat = Nullch;
810#else
811 pat = va_arg(args, char *);
812#endif
813 (void) vsprintf(s,pat,args);
814
815 s += strlen(s);
816 if (s[-1] != '\n') {
817 if (line) {
818 (void)sprintf(s," at %s line %ld",
819 in_eval?filename:origfilename, (long)line);
820 s += strlen(s);
821 }
822 if (last_in_stab &&
823 stab_io(last_in_stab) &&
824 stab_io(last_in_stab)->lines ) {
825 (void)sprintf(s,", <%s> line %ld",
826 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
827 (long)stab_io(last_in_stab)->lines);
828 s += strlen(s);
829 }
830 (void)strcpy(s,".\n");
831 }
832}
833
834/*VARARGS0*/
835fatal(va_alist)
836va_dcl
837{
838 va_list args;
839 extern FILE *e_fp;
840 extern char *e_tmpname;
9f68db38 841 char *tmps;
a687059c
LW
842
843#ifndef lint
844 va_start(args);
845#else
846 args = 0;
847#endif
848 mess(args);
849 va_end(args);
850 if (in_eval) {
851 str_set(stab_val(stabent("@",TRUE)),buf);
9f68db38
LW
852 tmps = "_EVAL_";
853 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
854 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
855#ifdef DEBUGGING
856 if (debug & 4) {
857 deb("(Skipping label #%d %s)\n",loop_ptr,
858 loop_stack[loop_ptr].loop_label);
859 }
860#endif
861 loop_ptr--;
862 }
863#ifdef DEBUGGING
864 if (debug & 4) {
865 deb("(Found label #%d %s)\n",loop_ptr,
866 loop_stack[loop_ptr].loop_label);
867 }
868#endif
869 if (loop_ptr < 0) {
870 in_eval = 0;
871 fatal("Bad label: %s", tmps);
872 }
873 longjmp(loop_stack[loop_ptr].loop_env, 1);
a687059c
LW
874 }
875 fputs(buf,stderr);
876 (void)fflush(stderr);
877 if (e_fp)
878 (void)UNLINK(e_tmpname);
879 statusvalue >>= 8;
880 exit((int)(errno?errno:(statusvalue?statusvalue:255)));
881}
882
883/*VARARGS0*/
884warn(va_alist)
885va_dcl
886{
887 va_list args;
888
889#ifndef lint
890 va_start(args);
891#else
892 args = 0;
893#endif
894 mess(args);
895 va_end(args);
896
897 fputs(buf,stderr);
898#ifdef LEAKTEST
899#ifdef DEBUGGING
900 if (debug & 4096)
901 xstat();
902#endif
903#endif
904 (void)fflush(stderr);
905}
906#endif
8d063cd8
LW
907
908static bool firstsetenv = TRUE;
909extern char **environ;
910
911void
912setenv(nam,val)
913char *nam, *val;
914{
915 register int i=envix(nam); /* where does it go? */
916
a687059c
LW
917 if (!val) {
918 while (environ[i]) {
919 environ[i] = environ[i+1];
920 i++;
921 }
922 return;
923 }
8d063cd8
LW
924 if (!environ[i]) { /* does not exist yet */
925 if (firstsetenv) { /* need we copy environment? */
926 int j;
a687059c
LW
927 char **tmpenv;
928
929 New(901,tmpenv, i+2, char*);
8d063cd8
LW
930 firstsetenv = FALSE;
931 for (j=0; j<i; j++) /* copy environment */
932 tmpenv[j] = environ[j];
933 environ = tmpenv; /* tell exec where it is now */
934 }
8d063cd8 935 else
a687059c 936 Renew(environ, i+2, char*); /* just expand it a bit */
8d063cd8
LW
937 environ[i+1] = Nullch; /* make sure it's null terminated */
938 }
a687059c 939 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
8d063cd8
LW
940 /* this may or may not be in */
941 /* the old environ structure */
a687059c 942 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
8d063cd8
LW
943}
944
945int
946envix(nam)
947char *nam;
948{
949 register int i, len = strlen(nam);
950
951 for (i = 0; environ[i]; i++) {
952 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
953 break; /* strnEQ must come first to avoid */
954 } /* potential SEGV's */
955 return i;
956}
378cc40b
LW
957
958#ifdef EUNICE
959unlnk(f) /* unlink all versions of a file */
960char *f;
961{
962 int i;
963
964 for (i = 0; unlink(f) >= 0; i++) ;
965 return i ? 0 : -1;
966}
967#endif
968
378cc40b 969#ifndef MEMCPY
ffed7fef 970#ifndef BCOPY
378cc40b
LW
971char *
972bcopy(from,to,len)
973register char *from;
974register char *to;
975register int len;
976{
977 char *retval = to;
978
979 while (len--)
980 *to++ = *from++;
981 return retval;
982}
ffed7fef 983#endif
378cc40b 984
ffed7fef 985#ifndef BZERO
378cc40b
LW
986char *
987bzero(loc,len)
988register char *loc;
989register int len;
990{
991 char *retval = loc;
992
993 while (len--)
994 *loc++ = 0;
995 return retval;
996}
997#endif
998#endif
a687059c
LW
999
1000#ifdef VARARGS
1001#ifndef VPRINTF
1002
1003#ifdef CHARVSPRINTF
1004char *
1005#else
1006int
1007#endif
1008vsprintf(dest, pat, args)
1009char *dest, *pat, *args;
1010{
1011 FILE fakebuf;
1012
1013 fakebuf._ptr = dest;
1014 fakebuf._cnt = 32767;
1015 fakebuf._flag = _IOWRT|_IOSTRG;
1016 _doprnt(pat, args, &fakebuf); /* what a kludge */
1017 (void)putc('\0', &fakebuf);
1018#ifdef CHARVSPRINTF
1019 return(dest);
1020#else
1021 return 0; /* perl doesn't use return value */
1022#endif
1023}
1024
1025#ifdef DEBUGGING
1026int
1027vfprintf(fd, pat, args)
1028FILE *fd;
1029char *pat, *args;
1030{
1031 _doprnt(pat, args, fd);
1032 return 0; /* wrong, but perl doesn't use the return value */
1033}
1034#endif
1035#endif /* VPRINTF */
1036#endif /* VARARGS */
1037
1038#ifdef MYSWAP
ffed7fef 1039#if BYTEORDER != 0x4321
a687059c
LW
1040short
1041my_swap(s)
1042short s;
1043{
1044#if (BYTEORDER & 1) == 0
1045 short result;
1046
1047 result = ((s & 255) << 8) + ((s >> 8) & 255);
1048 return result;
1049#else
1050 return s;
1051#endif
1052}
1053
1054long
1055htonl(l)
1056register long l;
1057{
1058 union {
1059 long result;
ffed7fef 1060 char c[sizeof(long)];
a687059c
LW
1061 } u;
1062
ffed7fef 1063#if BYTEORDER == 0x1234
a687059c
LW
1064 u.c[0] = (l >> 24) & 255;
1065 u.c[1] = (l >> 16) & 255;
1066 u.c[2] = (l >> 8) & 255;
1067 u.c[3] = l & 255;
1068 return u.result;
1069#else
ffed7fef 1070#if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
a687059c
LW
1071 fatal("Unknown BYTEORDER\n");
1072#else
1073 register int o;
1074 register int s;
1075
ffed7fef
LW
1076 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1077 u.c[o & 0xf] = (l >> s) & 255;
a687059c
LW
1078 }
1079 return u.result;
1080#endif
1081#endif
1082}
1083
1084long
1085ntohl(l)
1086register long l;
1087{
1088 union {
1089 long l;
ffed7fef 1090 char c[sizeof(long)];
a687059c
LW
1091 } u;
1092
ffed7fef 1093#if BYTEORDER == 0x1234
a687059c
LW
1094 u.c[0] = (l >> 24) & 255;
1095 u.c[1] = (l >> 16) & 255;
1096 u.c[2] = (l >> 8) & 255;
1097 u.c[3] = l & 255;
1098 return u.l;
1099#else
ffed7fef 1100#if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
a687059c
LW
1101 fatal("Unknown BYTEORDER\n");
1102#else
1103 register int o;
1104 register int s;
1105
1106 u.l = l;
1107 l = 0;
ffed7fef
LW
1108 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1109 l |= (u.c[o & 0xf] & 255) << s;
a687059c
LW
1110 }
1111 return l;
1112#endif
1113#endif
1114}
1115
ffed7fef 1116#endif /* BYTEORDER != 0x4321 */
a687059c
LW
1117#endif /* HTONS */
1118
1119FILE *
1120mypopen(cmd,mode)
1121char *cmd;
1122char *mode;
1123{
1124 int p[2];
1125 register int this, that;
1126 register int pid;
1127 STR *str;
1128 int doexec = strNE(cmd,"-");
1129
1130 if (pipe(p) < 0)
1131 return Nullfp;
1132 this = (*mode == 'w');
1133 that = !this;
1134 while ((pid = (doexec?vfork():fork())) < 0) {
1135 if (errno != EAGAIN) {
1136 close(p[this]);
1137 if (!doexec)
1138 fatal("Can't fork");
1139 return Nullfp;
1140 }
1141 sleep(5);
1142 }
1143 if (pid == 0) {
1144#define THIS that
1145#define THAT this
1146 close(p[THAT]);
1147 if (p[THIS] != (*mode == 'r')) {
1148 dup2(p[THIS], *mode == 'r');
1149 close(p[THIS]);
1150 }
1151 if (doexec) {
ae986130
LW
1152#if !defined(FCNTL) || !defined(F_SETFD)
1153 int fd;
1154
1155#ifndef NOFILE
1156#define NOFILE 20
1157#endif
1158 for (fd = 3; fd < NOFILE; fd++)
1159 close(fd);
1160#endif
a687059c
LW
1161 do_exec(cmd); /* may or may not use the shell */
1162 _exit(1);
1163 }
1164 if (tmpstab = stabent("$",allstabs))
1165 str_numset(STAB_STR(tmpstab),(double)getpid());
9f68db38 1166 forkprocess = 0;
a687059c
LW
1167 return Nullfp;
1168#undef THIS
1169#undef THAT
1170 }
1171 close(p[that]);
1172 str = afetch(pidstatary,p[this],TRUE);
1173 str_numset(str,(double)pid);
1174 str->str_cur = 0;
1175 forkprocess = pid;
1176 return fdopen(p[this], mode);
1177}
1178
ae986130
LW
1179#ifdef NOTDEF
1180dumpfds(s)
1181char *s;
1182{
1183 int fd;
1184 struct stat tmpstatbuf;
1185
1186 fprintf(stderr,"%s", s);
1187 for (fd = 0; fd < 32; fd++) {
1188 if (fstat(fd,&tmpstatbuf) >= 0)
1189 fprintf(stderr," %d",fd);
1190 }
1191 fprintf(stderr,"\n");
1192}
1193#endif
1194
a687059c
LW
1195#ifndef DUP2
1196dup2(oldfd,newfd)
1197int oldfd;
1198int newfd;
1199{
ae986130
LW
1200 int fdtmp[10];
1201 int fdx = 0;
1202 int fd;
1203
a687059c 1204 close(newfd);
ae986130
LW
1205 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1206 fdtmp[fdx++] = fd;
1207 while (fdx > 0)
1208 close(fdtmp[--fdx]);
a687059c
LW
1209}
1210#endif
1211
1212int
1213mypclose(ptr)
1214FILE *ptr;
1215{
1216 register int result;
1217#ifdef VOIDSIG
1218 void (*hstat)(), (*istat)(), (*qstat)();
1219#else
1220 int (*hstat)(), (*istat)(), (*qstat)();
1221#endif
1222 int status;
1223 STR *str;
1224 register int pid;
1225
1226 str = afetch(pidstatary,fileno(ptr),TRUE);
1227 fclose(ptr);
1228 pid = (int)str_gnum(str);
1229 if (!pid)
1230 return -1;
1231 hstat = signal(SIGHUP, SIG_IGN);
1232 istat = signal(SIGINT, SIG_IGN);
1233 qstat = signal(SIGQUIT, SIG_IGN);
1234#ifdef WAIT4
1235 if (wait4(pid,&status,0,Null(struct rusage *)) < 0)
1236 status = -1;
1237#else
1238 if (pid < 0) /* already exited? */
1239 status = str->str_cur;
1240 else {
1241 while ((result = wait(&status)) != pid && result >= 0)
1242 pidgone(result,status);
1243 if (result < 0)
1244 status = -1;
1245 }
1246#endif
1247 signal(SIGHUP, hstat);
1248 signal(SIGINT, istat);
1249 signal(SIGQUIT, qstat);
1250 str_numset(str,0.0);
1251 return(status);
1252}
1253
1254pidgone(pid,status)
1255int pid;
1256int status;
1257{
1258#ifdef WAIT4
1259 return;
1260#else
1261 register int count;
1262 register STR *str;
1263
1264 for (count = pidstatary->ary_fill; count >= 0; --count) {
1265 if ((str = afetch(pidstatary,count,FALSE)) &&
1266 ((int)str->str_u.str_nval) == pid) {
1267 str_numset(str, -str->str_u.str_nval);
1268 str->str_cur = status;
1269 return;
1270 }
1271 }
1272#endif
1273}
1274
1275#ifndef MEMCMP
1276memcmp(s1,s2,len)
1277register unsigned char *s1;
1278register unsigned char *s2;
1279register int len;
1280{
1281 register int tmp;
1282
1283 while (len--) {
1284 if (tmp = *s1++ - *s2++)
1285 return tmp;
1286 }
1287 return 0;
1288}
1289#endif /* MEMCMP */
9f68db38
LW
1290
1291void
1292repeatcpy(to,from,len,count)
1293register char *to;
1294register char *from;
1295int len;
1296register int count;
1297{
1298 register int todo;
1299 register char *frombase = from;
1300
1301 if (len == 1) {
1302 todo = *from;
1303 while (count-- > 0)
1304 *to++ = todo;
1305 return;
1306 }
1307 while (count-- > 0) {
1308 for (todo = len; todo > 0; todo--) {
1309 *to++ = *from++;
1310 }
1311 from = frombase;
1312 }
1313}