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