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