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