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