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