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