1 /* $RCSfile: util.c,v $$Revision: 4.1 $$Date: 92/08/07 18:29:00 $
3 * Copyright (c) 1991, Larry Wall
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.
9 * Revision 4.1 92/08/07 18:29:00 lwall
11 * Revision 4.0.1.6 92/06/11 21:18:47 lwall
12 * patch34: boneheaded typo in my_bcopy()
14 * Revision 4.0.1.5 92/06/08 16:08:37 lwall
15 * patch20: removed implicit int declarations on functions
16 * patch20: Perl now distinguishes overlapped copies from non-overlapped
17 * patch20: fixed confusion between a *var's real name and its effective name
18 * patch20: bcopy() and memcpy() now tested for overlap safety
19 * patch20: added Atari ST portability
21 * Revision 4.0.1.4 91/11/11 16:48:54 lwall
22 * patch19: study was busted by 4.018
23 * patch19: added little-endian pack/unpack options
25 * Revision 4.0.1.3 91/11/05 19:18:26 lwall
26 * patch11: safe malloc code now integrated into Perl's malloc when possible
27 * patch11: strchr("little", "longer string") could visit faraway places
28 * patch11: warn '-' x 10000 dumped core
29 * patch11: forked exec on non-existent program now issues a warning
31 * Revision 4.0.1.2 91/06/07 12:10:42 lwall
32 * patch4: new copyright notice
33 * patch4: made some allowances for "semi-standard" C
34 * patch4: strchr() could blow up searching for null string
35 * patch4: taintchecks could improperly modify parent in vfork()
36 * patch4: exec would close files even if you cleared close-on-exec flag
38 * Revision 4.0.1.1 91/04/12 09:19:25 lwall
39 * patch1: random cleanup in cpp namespace
41 * Revision 4.0 91/03/20 01:56:39 lwall
50 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
66 # include <sys/file.h>
73 /* paranoid version of malloc */
75 /* NOTE: Do not call the next three routines directly. Use the macros
76 * in handy.h, so that we can easily redefine everything to do tracking of
77 * allocated hunks back to the original New to track down any memory leaks.
91 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
97 croak("panic: malloc");
99 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
100 #if !(defined(I286) || defined(atarist))
101 DEBUG_m(fprintf(stderr,"0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size));
103 DEBUG_m(fprintf(stderr,"0x%lx: (%05d) malloc %ld bytes\n",ptr,an++,(long)size));
110 fputs(no_mem,stderr) FLUSH;
116 /* paranoid version of realloc */
119 saferealloc(where,size)
130 #endif /* ! STANDARD_C */
134 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
139 croak("Null realloc");
142 croak("panic: realloc");
144 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
146 #if !(defined(I286) || defined(atarist))
148 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
149 fprintf(stderr,"0x%x: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
153 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
154 fprintf(stderr,"0x%lx: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
163 fputs(no_mem,stderr) FLUSH;
169 /* safe version of free */
175 #if !(defined(I286) || defined(atarist))
176 DEBUG_m( fprintf(stderr,"0x%x: (%05d) free\n",where,an++));
178 DEBUG_m( fprintf(stderr,"0x%lx: (%05d) free\n",where,an++));
186 #endif /* !safemalloc */
190 #define ALIGN sizeof(long)
197 register char *where;
199 where = safemalloc(size + ALIGN);
203 return where + ALIGN;
207 safexrealloc(where,size)
211 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
223 x = where[0] + 100 * where[1];
233 for (i = 0; i < MAXXCOUNT; i++) {
234 if (xcount[i] > lastxcount[i]) {
235 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
236 lastxcount[i] = xcount[i];
241 #endif /* LEAKTEST */
243 /* copy a string up to some (non-backslashed) delimiter, if any */
246 cpytill(to,from,fromend,delim,retlen)
249 register char *fromend;
255 for (; from < fromend; from++,to++) {
257 if (from[1] == delim)
259 else if (from[1] == '\\')
262 else if (*from == delim)
267 *retlen = to - origto;
271 /* return ptr to little string in big string, NULL if not found */
272 /* This routine was donated by Corey Satten. */
277 register char *little;
279 register char *s, *x;
290 for (x=big,s=little; *s; /**/ ) {
304 /* same as instr but allow embedded nulls */
307 ninstr(big, bigend, little, lend)
309 register char *bigend;
313 register char *s, *x;
314 register I32 first = *little;
315 register char *littleend = lend;
317 if (!first && little > littleend)
319 if (bigend - big < littleend - little)
321 bigend -= littleend - little++;
322 while (big <= bigend) {
325 for (x=big,s=little; s < littleend; /**/ ) {
337 /* reverse of the above--find last substring */
340 rninstr(big, bigend, little, lend)
346 register char *bigbeg;
347 register char *s, *x;
348 register I32 first = *little;
349 register char *littleend = lend;
351 if (!first && little > littleend)
354 big = bigend - (littleend - little++);
355 while (big >= bigbeg) {
358 for (x=big+2,s=little; s < littleend; /**/ ) {
371 fbm_compile(sv, iflag)
375 register unsigned char *s;
376 register unsigned char *table;
378 register U32 len = SvCUR(sv);
383 table = (unsigned char*)(SvPVX(sv) + len + 1);
385 for (i = 0; i < 256; i++) {
389 while (s >= (unsigned char*)(SvPVX(sv)))
391 if (table[*s] == len) {
394 table[*s] = table[fold[*s]] = i;
408 sv_upgrade(sv, SVt_PVBM);
409 sv_magic(sv, 0, 'B', 0, 0); /* deep magic */
412 s = (unsigned char*)(SvPVX(sv)); /* deeper magic */
414 register U32 tmp, foldtmp;
416 for (i = 0; i < len; i++) {
418 foldtmp=freq[fold[s[i]]];
419 if (tmp < frequency && foldtmp < frequency) {
421 /* choose most frequent among the two */
422 frequency = (tmp > foldtmp) ? tmp : foldtmp;
427 for (i = 0; i < len; i++) {
428 if (freq[s[i]] < frequency) {
430 frequency = freq[s[i]];
434 BmRARE(sv) = s[rarest];
435 BmPREVIOUS(sv) = rarest;
436 DEBUG_r(fprintf(stderr,"rarest char %c at %d\n",BmRARE(sv),BmPREVIOUS(sv)));
440 fbm_instr(big, bigend, littlestr)
442 register unsigned char *bigend;
445 register unsigned char *s;
447 register I32 littlelen;
448 register unsigned char *little;
449 register unsigned char *table;
450 register unsigned char *olds;
451 register unsigned char *oldlittle;
453 if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) {
454 if (!SvPOK(littlestr) || !SvPVX(littlestr))
456 return ninstr((char*)big,(char*)bigend,
457 SvPVX(littlestr), SvPVX(littlestr) + SvCUR(littlestr));
460 littlelen = SvCUR(littlestr);
461 if (SvTAIL(littlestr) && !multiline) { /* tail anchored? */
462 if (littlelen > bigend - big)
464 little = (unsigned char*)SvPVX(littlestr);
465 if (SvCASEFOLD(littlestr)) { /* oops, fake it */
466 big = bigend - littlelen; /* just start near end */
467 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
471 s = bigend - littlelen;
472 if (*s == *little && bcmp(s,little,littlelen)==0)
473 return (char*)s; /* how sweet it is */
474 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
477 if (*s == *little && bcmp(s,little,littlelen)==0)
483 table = (unsigned char*)(SvPVX(littlestr) + littlelen + 1);
484 if (--littlelen >= bigend - big)
487 oldlittle = little = table - 2;
488 if (SvCASEFOLD(littlestr)) { /* case insensitive? */
492 if (tmp = table[*s]) {
494 if (bigend - s > tmp) {
499 if ((s += tmp) < bigend)
505 tmp = littlelen; /* less expensive than calling strncmp() */
508 if (*--s == *--little || fold[*s] == *little)
510 s = olds + 1; /* here we pay the price for failure */
512 if (s < bigend) /* fake up continue to outer loop */
524 if (tmp = table[*s]) {
526 if (bigend - s > tmp) {
531 if ((s += tmp) < bigend)
537 tmp = littlelen; /* less expensive than calling strncmp() */
540 if (*--s == *--little)
542 s = olds + 1; /* here we pay the price for failure */
544 if (s < bigend) /* fake up continue to outer loop */
556 screaminstr(bigstr, littlestr)
560 register unsigned char *s, *x;
561 register unsigned char *big;
563 register I32 previous;
565 register unsigned char *little;
566 register unsigned char *bigend;
567 register unsigned char *littleend;
569 if ((pos = screamfirst[BmRARE(littlestr)]) < 0)
571 little = (unsigned char *)(SvPVX(littlestr));
572 littleend = little + SvCUR(littlestr);
574 previous = BmPREVIOUS(littlestr);
575 big = (unsigned char *)(SvPVX(bigstr));
576 bigend = big + SvCUR(bigstr);
577 while (pos < previous) {
578 if (!(pos += screamnext[pos]))
582 if (SvCASEFOLD(littlestr)) { /* case insignificant? */
584 if (big[pos-previous] != first && big[pos-previous] != fold[first])
586 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
589 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
595 return (char *)(big+pos-previous);
597 pos += screamnext[pos] /* does this goof up anywhere? */
602 if (big[pos-previous] != first)
604 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
613 return (char *)(big+pos-previous);
614 } while ( pos += screamnext[pos] );
616 #else /* !POINTERRIGOR */
618 if (SvCASEFOLD(littlestr)) { /* case insignificant? */
620 if (big[pos] != first && big[pos] != fold[first])
622 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
625 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
631 return (char *)(big+pos);
633 pos += screamnext[pos] /* does this goof up anywhere? */
638 if (big[pos] != first)
640 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
649 return (char *)(big+pos);
651 pos += screamnext[pos]
654 #endif /* POINTERRIGOR */
669 if (fold[*a++] == *b++)
676 /* copy a string to a safe spot */
682 register char *newaddr;
684 New(902,newaddr,strlen(sv)+1,char);
685 (void)strcpy(newaddr,sv);
689 /* same thing but with a known length */
696 register char *newaddr;
698 New(903,newaddr,len+1,char);
699 Copy(sv,newaddr,len,char); /* might not be null terminated */
700 newaddr[len] = '\0'; /* is now */
704 #if !defined(STANDARD_C) && !defined(I_VARARGS)
707 * Fallback on the old hackers way of doing varargs
712 mess(pat,a1,a2,a3,a4)
717 I32 usermess = strEQ(pat,"%s");
722 tmpstr = sv_newmortal();
723 sv_setpv(tmpstr, (char*)a1);
724 *s++ = SvPVX(tmpstr)[SvCUR(tmpstr)-1];
727 (void)sprintf(s,pat,a1,a2,a3,a4);
733 strcpy(s, " during global destruction.\n");
735 if (curcop->cop_line) {
736 (void)sprintf(s," at %s line %ld",
737 SvPVX(GvSV(curcop->cop_filegv)), (long)curcop->cop_line);
742 IoLINES(GvIO(last_in_gv)) ) {
743 (void)sprintf(s,", <%s> %s %ld",
744 last_in_gv == argvgv ? "" : GvENAME(last_in_gv),
745 strEQ(rs,"\n") ? "line" : "chunk",
746 (long)IoLINES(GvIO(last_in_gv)));
749 (void)strcpy(s,".\n");
752 sv_catpv(tmpstr,buf+1);
755 return SvPVX(tmpstr);
761 void croak(pat,a1,a2,a3,a4)
768 message = mess(pat,a1,a2,a3,a4);
769 fputs(message,stderr);
770 (void)fflush(stderr);
772 (void)UNLINK(e_tmpname);
774 my_exit((I32)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
778 void warn(pat,a1,a2,a3,a4)
784 message = mess(pat,a1,a2,a3,a4);
785 fputs(message,stderr);
789 (void)fflush(stderr);
792 #else /* !defined(STANDARD_C) && !defined(I_VARARGS) */
796 mess(char *pat, va_list *args)
809 #ifdef USE_CHAR_VSPRINTF
817 usermess = strEQ(pat, "%s");
819 tmpstr = sv_newmortal();
820 sv_setpv(tmpstr, va_arg(*args, char *));
821 *s++ = SvPVX(tmpstr)[SvCUR(tmpstr)-1];
824 (void) vsprintf(s,pat,*args);
831 strcpy(s, " during global destruction.\n");
833 if (curcop->cop_line) {
834 (void)sprintf(s," at %s line %ld",
835 SvPVX(GvSV(curcop->cop_filegv)), (long)curcop->cop_line);
840 IoLINES(GvIO(last_in_gv)) ) {
841 (void)sprintf(s,", <%s> %s %ld",
842 last_in_gv == argvgv ? "" : GvNAME(last_in_gv),
843 strEQ(rs,"\n") ? "line" : "chunk",
844 (long)IoLINES(GvIO(last_in_gv)));
847 (void)strcpy(s,".\n");
850 sv_catpv(tmpstr,buf+1);
854 return SvPVX(tmpstr);
861 croak(char* pat, ...)
879 message = mess(pat, &args);
881 if (restartop = die_where(message))
883 fputs(message,stderr);
884 (void)fflush(stderr);
886 (void)UNLINK(e_tmpname);
888 my_exit((I32)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
909 message = mess(pat, &args);
912 fputs(message,stderr);
916 (void)fflush(stderr);
918 #endif /* !defined(STANDARD_C) && !defined(I_VARARGS) */
924 register I32 i=setenv_getix(nam); /* where does it go? */
926 if (environ == origenviron) { /* need we copy environment? */
932 for (max = i; environ[max]; max++) ;
933 New(901,tmpenv, max+2, char*);
934 for (j=0; j<max; j++) /* copy environment */
935 tmpenv[j] = savestr(environ[j]);
936 tmpenv[max] = Nullch;
937 environ = tmpenv; /* tell exec where it is now */
941 environ[i] = environ[i+1];
946 if (!environ[i]) { /* does not exist yet */
947 Renew(environ, i+2, char*); /* just expand it a bit */
948 environ[i+1] = Nullch; /* make sure it's null terminated */
951 Safefree(environ[i]);
952 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
954 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
956 /* MS-DOS requires environment variable names to be in uppercase */
957 /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
958 * some utilities and applications may break because they only look
959 * for upper case strings. (Fixed strupr() bug here.)]
961 strcpy(environ[i],nam); strupr(environ[i]);
962 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
970 register I32 i, len = strlen(nam);
972 for (i = 0; environ[i]; i++) {
973 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
974 break; /* strnEQ must come first to avoid */
975 } /* potential SEGV's */
981 unlnk(f) /* unlink all versions of a file */
986 for (i = 0; unlink(f) >= 0; i++) ;
991 #if !defined(HAS_BCOPY) || !defined(HAS_SAFE_BCOPY)
993 my_bcopy(from,to,len)
1000 if (from - to >= 0) {
1008 *(--to) = *(--from);
1014 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
1030 my_memcmp(s1,s2,len)
1031 register unsigned char *s1;
1032 register unsigned char *s2;
1038 if (tmp = *s1++ - *s2++)
1043 #endif /* HAS_MEMCMP */
1048 #ifdef USE_CHAR_VSPRINTF
1053 vsprintf(dest, pat, args)
1054 char *dest, *pat, *args;
1058 fakebuf._ptr = dest;
1059 fakebuf._cnt = 32767;
1063 fakebuf._flag = _IOWRT|_IOSTRG;
1064 _doprnt(pat, args, &fakebuf); /* what a kludge */
1065 (void)putc('\0', &fakebuf);
1066 #ifdef USE_CHAR_VSPRINTF
1069 return 0; /* perl doesn't use return value */
1074 vfprintf(fd, pat, args)
1078 _doprnt(pat, args, fd);
1079 return 0; /* wrong, but perl doesn't use the return value */
1081 #endif /* HAS_VPRINTF */
1082 #endif /* I_VARARGS */
1085 * I think my_swap(), htonl() and ntohl() have never been used.
1086 * perl.h contains last-chance references to my_swap(), my_htonl()
1087 * and my_ntohl(). I presume these are the intended functions;
1088 * but htonl() and ntohl() have the wrong names. There are no
1089 * functions my_htonl() and my_ntohl() defined anywhere.
1093 #if BYTEORDER != 0x4321
1098 #if (BYTEORDER & 1) == 0
1101 result = ((s & 255) << 8) + ((s >> 8) & 255);
1114 char c[sizeof(long)];
1117 #if BYTEORDER == 0x1234
1118 u.c[0] = (l >> 24) & 255;
1119 u.c[1] = (l >> 16) & 255;
1120 u.c[2] = (l >> 8) & 255;
1124 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1125 croak("Unknown BYTEORDER\n");
1130 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1131 u.c[o & 0xf] = (l >> s) & 255;
1144 char c[sizeof(long)];
1147 #if BYTEORDER == 0x1234
1148 u.c[0] = (l >> 24) & 255;
1149 u.c[1] = (l >> 16) & 255;
1150 u.c[2] = (l >> 8) & 255;
1154 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1155 croak("Unknown BYTEORDER\n");
1162 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1163 l |= (u.c[o & 0xf] & 255) << s;
1170 #endif /* BYTEORDER != 0x4321 */
1174 * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
1175 * If these functions are defined,
1176 * the BYTEORDER is neither 0x1234 nor 0x4321.
1177 * However, this is not assumed.
1181 #define HTOV(name,type) \
1188 char c[sizeof(type)]; \
1192 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1193 u.c[i] = (n >> s) & 0xFF; \
1198 #define VTOH(name,type) \
1205 char c[sizeof(type)]; \
1211 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1212 n += (u.c[i] & 0xFF) << s; \
1217 #if defined(HAS_HTOVS) && !defined(htovs)
1220 #if defined(HAS_HTOVL) && !defined(htovl)
1223 #if defined(HAS_VTOHS) && !defined(vtohs)
1226 #if defined(HAS_VTOHL) && !defined(vtohl)
1237 register I32 this, that;
1240 I32 doexec = strNE(cmd,"-");
1244 this = (*mode == 'w');
1249 taint_proper("Insecure %s%s", "EXEC");
1252 while ((pid = (doexec?vfork():fork())) < 0) {
1253 if (errno != EAGAIN) {
1256 croak("Can't fork");
1267 if (p[THIS] != (*mode == 'r')) {
1268 dup2(p[THIS], *mode == 'r');
1272 #if !defined(HAS_FCNTL) || !defined(FFt_SETFD)
1278 for (fd = maxsysfd + 1; fd < NOFILE; fd++)
1281 do_exec(cmd); /* may or may not use the shell */
1282 warn("Can't exec \"%s\": %s", cmd, Strerror(errno));
1286 if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV))
1287 sv_setiv(GvSV(tmpgv),(I32)getpid());
1289 hv_clear(pidstatus); /* we have no children */
1294 do_execfree(); /* free any memory malloced by child on vfork */
1296 if (p[that] < p[this]) {
1297 dup2(p[this], p[that]);
1301 sv = *av_fetch(fdpid,p[this],TRUE);
1302 SvUPGRADE(sv,SVt_IV);
1305 return fdopen(p[this], mode);
1315 return popen(cmd, mode);
1319 #endif /* !DOSISH */
1326 struct stat tmpstatbuf;
1328 fprintf(stderr,"%s", s);
1329 for (fd = 0; fd < 32; fd++) {
1330 if (fstat(fd,&tmpstatbuf) >= 0)
1331 fprintf(stderr," %d",fd);
1333 fprintf(stderr,"\n");
1342 #if defined(HAS_FCNTL) && defined(FFt_DUPFD)
1344 fcntl(oldfd, FFt_DUPFD, newfd);
1353 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1356 close(fdtmp[--fdx]);
1367 void (*hstat)(), (*istat)(), (*qstat)();
1369 int (*hstat)(), (*istat)(), (*qstat)();
1375 sv = *av_fetch(fdpid,fileno(ptr),TRUE);
1377 av_store(fdpid,fileno(ptr),Nullsv);
1380 if(kill(pid, 0) < 0) { return(pid); } /* HOM 12/23/91 */
1382 hstat = signal(SIGHUP, SIG_IGN);
1383 istat = signal(SIGINT, SIG_IGN);
1384 qstat = signal(SIGQUIT, SIG_IGN);
1385 pid = wait4pid(pid, &status, 0);
1386 signal(SIGHUP, hstat);
1387 signal(SIGINT, istat);
1388 signal(SIGQUIT, qstat);
1389 return(pid < 0 ? pid : status);
1393 wait4pid(pid,statusp,flags)
1406 sprintf(spid, "%d", pid);
1407 svp = hv_fetch(pidstatus,spid,strlen(spid),FALSE);
1408 if (svp && *svp != &sv_undef) {
1409 *statusp = SvIVX(*svp);
1410 hv_delete(pidstatus,spid,strlen(spid));
1417 hv_iterinit(pidstatus);
1418 if (entry = hv_iternext(pidstatus)) {
1419 pid = atoi(hv_iterkey(entry,statusp));
1420 sv = hv_iterval(pidstatus,entry);
1421 *statusp = SvIVX(sv);
1422 sprintf(spid, "%d", pid);
1423 hv_delete(pidstatus,spid,strlen(spid));
1428 return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
1431 return waitpid(pid,statusp,flags);
1434 croak("Can't do waitpid with flags");
1436 while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
1437 pidgone(result,*statusp);
1445 #endif /* !DOSISH */
1456 sprintf(spid, "%d", pid);
1457 sv = *hv_fetch(pidstatus,spid,strlen(spid),TRUE);
1458 SvUPGRADE(sv,SVt_IV);
1474 repeatcpy(to,from,len,count)
1476 register char *from;
1481 register char *frombase = from;
1489 while (count-- > 0) {
1490 for (todo = len; todo > 0; todo--) {
1497 #ifndef CASTNEGFLOAT
1505 # define BIGDOUBLE 2147483648.0
1507 return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
1510 return (unsigned long)f;
1512 return (unsigned long)along;
1522 # define BIGDOUBLE 2147483648.0 /* Assume 32 bit int's ! */
1523 # define BIGNEGDOUBLE (-2147483648.0)
1525 return (I32)fmod(f, BIGDOUBLE);
1526 if (f <= BIGNEGDOUBLE)
1527 return (I32)fmod(f, BIGNEGDOUBLE);
1531 # undef BIGNEGDOUBLE
1540 char *fa = strrchr(a,'/');
1541 char *fb = strrchr(b,'/');
1542 struct stat tmpstatbuf1;
1543 struct stat tmpstatbuf2;
1545 #define MAXPATHLEN 1024
1547 char tmpbuf[MAXPATHLEN+1];
1562 strncpy(tmpbuf, a, fa - a);
1563 if (stat(tmpbuf, &tmpstatbuf1) < 0)
1568 strncpy(tmpbuf, b, fb - b);
1569 if (stat(tmpbuf, &tmpstatbuf2) < 0)
1571 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1572 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1574 #endif /* !HAS_RENAME */
1577 scan_oct(start, len, retlen)
1582 register char *s = start;
1583 register unsigned long retval = 0;
1585 while (len-- && *s >= '0' && *s <= '7') {
1587 retval |= *s++ - '0';
1589 *retlen = s - start;
1594 scan_hex(start, len, retlen)
1599 register char *s = start;
1600 register unsigned long retval = 0;
1603 while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
1605 retval |= (tmp - hexdigit) & 15;
1608 *retlen = s - start;