#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gc/gc_private.h" int SPCR_debugMessages = 1; int SPCR_ignoreErrors = 0; void SPCR_error(s) char *s; { if (SPCR_debugMessages) fprintf(stderr, "%s\n", s); if (!SPCR_ignoreErrors) abort(s); } void XR_Panic(s) char *s; { SPCR_error(s); } void SPCR_NotImplemented(s) char *s; { if (SPCR_debugMessages) fprintf(stderr, "%s not implemented in stubbed pcr\n", s); SPCR_error("unimplemented primitive\n"); } /* * Unix error return code */ int * XR_GetErrnoAddress() { extern int errno; return( &errno ); } /* Nobody actually looks at these. We save them just in case ... */ XR_HandlerProc SPCR_handler_proc; XR_Pointer SPCR_handler_data; void XR_RegisterHandler (proc, data) XR_HandlerProc proc; XR_Pointer data; { if( (proc != NIL) || (data == NIL) ) { SPCR_handler_proc = proc; } else { SPCR_handler_proc = (XR_HandlerProc) (((XR_MesaProc)(data))->mp_proc); } SPCR_handler_data = data; } XR_Fildes SPCR_map_descr(d) XR_Fildes d; { switch(d) { case -3: /* XR_MSG_STDOUT in standard PCR */ return(XR_MSG_STDOUT); case -2: /* XR_MSG_STDIN in standard PCR */ return(XR_MSG_STDIN); default: return(d); } } /* A slight change to the default behavior, to allow for standard PCR */ /* XR_MSG_STDOUT def. */ int XR_Write(fd, buf, nbyte) int fd; char * buf; int nbyte; { return(write(SPCR_map_descr(fd), buf, nbyte)); } int XR_WriteV(fd, iov, iovcnt) int fd; struct iovec *iov; int iovcnt; { return(writev(SPCR_map_descr(fd), iov, iovcnt)); } /* Ditto for XR_MSG_STDIN. */ int XR_Read(fd, buf, nbyte) int fd; char * buf; int nbyte; { return(read(SPCR_map_descr(fd), buf, nbyte)); } int XR_ReadV(fd, iov, iovcnt) int fd; struct iovec *iov; int iovcnt; { return(readv(SPCR_map_descr(fd), iov, iovcnt)); } # define BUFSZ 1024 void XR_Msg( descriptor, fmt, a0, a1, a2, a3, a4, a5, a6, a7 ) int descriptor; char *fmt; int a0, a1, a2, a3, a4, a5, a6, a7; { char buf[BUFSZ+1]; buf[BUFSZ] = 1; sprintf(buf, fmt, a0, a1, a2, a3, a4, a5, a6, a7); if (buf[BUFSZ] != 1) { SPCR_error("XR_Msg wrote past end of buffer"); } XR_Write(descriptor, buf, strlen(buf)); } void XR_FPrintF( descriptor, fmt, a0, a1, a2, a3, a4, a5, a6, a7 ) int descriptor; char *fmt; int a0, a1, a2, a3, a4, a5, a6, a7; { XR_Msg(descriptor, fmt, a0, a1, a2, a3, a4, a5, a6, a7); } char * XR_SPrintF( buf, fmt, a0, a1, a2, a3, a4, a5, a6, a7 ) char * buf; char *fmt; int a0, a1, a2, a3, a4, a5, a6, a7; { sprintf(buf, fmt, a0, a1, a2, a3, a4, a5, a6, a7); return(buf + strlen(buf)); } int XR_MsgWrite (buf, nbytes) char *buf; int nbytes; { return(XR_Write(XR_MSG_STDOUT, buf, nbytes) ); } #define DevNullOrFile(filename) ((filename) != 0 \ ? (filename) \ : "/dev/null") #define maxStrlenOfStrAndDevNull(s) ((s) != 0 \ ? strlen((s)) \ : (sizeof("/dev/null") - 1)) int XR_Spawn(cmd, in, out, err) char *cmd; char *in; /* NIL, "" => /dev/null */ char *out; char *err; { int len = strlen(cmd) + maxStrlenOfStrAndDevNull(in) + maxStrlenOfStrAndDevNull(out) + maxStrlenOfStrAndDevNull(err) + 11; /* 11 == strlen(" < ")+strlen(" > ")+strlen(" 2> ")+'\0' */ char *p = (char *)GC_malloc(len); sprintf(p, "%s < %s > %s 2> %s", cmd, DevNullOrFile(in), DevNullOrFile(out), DevNullOrFile(err)); return system(p); } void XR_GCollect() { GC_gcollect(); } unsigned XR_GCHeapSize() { return(GC_heapsize); } unsigned XR_GCTotalByteCount() { return(WORDS_TO_BYTES(GC_words_allocd_before_gc + GC_words_allocd)); } # define I_DONT_KNOW 17 unsigned XR_GCTotalObjectCount() { return(I_DONT_KNOW); } unsigned XR_GCCurrentByteCount() { return(I_DONT_KNOW); } unsigned XR_GCCurrentObjectCount() { return(I_DONT_KNOW); } static unsigned bytesAfterWhichToCollect; /* Not really, but we try to lie consistently ... */ unsigned XR_SetBytesAfterWhichToCollect(n) unsigned n; { unsigned old = bytesAfterWhichToCollect; bytesAfterWhichToCollect = n; return(old); } /* If p is a valid pointer to an object, return a pointer to the */ /* beginning of that object. Otherwise return NIL. */ /* If szp is nonNIL, save the objects size in bytes in *szp. */ /* If ptrfreep is nonNIL, set *ptrfreep to 0 or 1 depending on */ /* whether or not the object is pointer free. */ /* An object may be considered valid even though it is about to */ /* be garbage collected because it was inaccessible during the */ /* last mark phase. A nonNIL result does guarantee that the */ /* object can be read without generating a fault. */ XR_Pointer XR_PtrTest(p, szp, ptrfreep) void * p; /* May be any 32 bit integer */ long * szp; int * ptrfreep; { char * base = (char *)GC_base(p); struct hblk * h = HBLKPTR(base); hdr * hhdr = HDR(h); if (base == 0) return(0); if (szp != 0) *szp = (long)GC_size(base); if (ptrfreep != 0) { struct hblk * h = HBLKPTR(base); hdr * hhdr = HDR(h); if (hhdr -> hb_obj_kind == PTRFREE) { *ptrfreep = 1; } else { *ptrfreep = 0; } } return((XR_Pointer)base); } #undef XR_GetErrno #undef XR_SetErrno int XR_GetErrno() { return(errno); } int XR_SetErrno(x) int x; { errno = x; } XR_Pointer SPCR_freeMemPtr = (XR_Pointer)0x20000000; XR_Pointer XR_VMReserve (bytes) unsigned bytes; { XR_Pointer result = SPCR_freeMemPtr; unsigned ps = 4096; /* check if this is ok */ SPCR_freeMemPtr += (bytes + ps - 1) & ~(ps - 1); return(result); } /* Force the right GC routines to be inncluded in .o */ void SPCR_require() { GC_malloc(0); GC_realloc(0, 0); GC_free(0); GC_malloc_atomic(0); } bool XR_StackPushTest(nbytes) int nbytes; { char dummy; # define SLOP 10000 struct rlimit rl; if (getrlimit(RLIMIT_STACK, &rl) < 0) { SPCR_error("XR_StackPushTest"); } if ((char *)GC_stackbottom - &dummy + SLOP + nbytes >= rl.rlim_cur) { return(FALSE); } else { return(TRUE); } } /* the following are not (readily) available in solaris, so we stub them */ /* most of the code is taken from (or patterned after) ppcr's XR_UIOImpl.c */ int XR_GetRUsage() { return -ENOSYS; } /* this is a guess -- we'll see how it works */ int XR_GetDTableSize1(XR_FDKind kind) { switch( kind ) { case XR_FD_KIND_STD: return 32; default: return -EINVAL; } } int XR_GetDTableSize(void) { return XR_GetDTableSize1(XR_FD_KIND_STD); } int XR_GetHostID(void) { return -ENOSYS; } int XR_GetDomainName(char *name, int nameLen) { return -ENOMEM; } int XR_KillPG(int pgrp, int sig) { return -1; } int XR_GetPageSize(void) { return 4096; } int XR_GetHostName(char *name, int nameLen) { struct utsname utsn; uname(&utsn); strncpy( name, utsn.nodename, nameLen ); return 0; } struct XR_timeval { long tv_sec; /* seconds */ long tv_usec; /* and microseconds */ }; struct XR_timezone { int tz_minuteswest; /* minutes west of Greenwich */ int tz_dsttime; /* type of dst correction */ }; int XR_GetTimeOfDay(struct XR_timeval *xtp, struct XR_timezone *xtzp) { int ans = 0; int saverr = 0; struct timeval t; if ( xtp != NIL ) { ans = gettimeofday(&t); if ( ans != (-1) ) { xtp->tv_sec = t.tv_sec; xtp->tv_usec = t.tv_usec; } else { saverr = - errno; } } if( xtzp != NIL ) { xtzp->tz_minuteswest = timezone / 60; /* is in seconds */ xtzp->tz_dsttime = daylight; } return saverr; } typedef unsigned short XR_mode_t; typedef long XR_time_t; typedef int XR_size_t; typedef short XR_dev_t; typedef long XR_off_t; typedef unsigned long XR_ino_t; typedef unsigned short XR_uid_t; typedef unsigned short XR_gid_t; struct XR_stat { XR_dev_t xrst_dev; XR_ino_t xrst_ino; XR_mode_t xrst_mode; short xrst_nlink; XR_uid_t xrst_uid; XR_gid_t xrst_gid; XR_dev_t xrst_rdev; XR_off_t xrst_size; XR_time_t xrst_atime; int xrst_spare1; XR_time_t xrst_mtime; int xrst_spare2; XR_time_t xrst_ctime; int xrst_spare3; long xrst_blksize; long xrst_blocks; long xrst_spare4[2]; }; int XR_FStat(XR_Fildes fildes, struct XR_stat *buf) { struct stat sysstat; int ans; if( buf == NIL ) return -EFAULT; ans = fstat(fildes, &sysstat); if (ans == -1) return -errno; (void)ConvertStat( buf, &sysstat); return 0; } int XR_Stat(char *path, struct XR_stat *buf) { int ans; struct stat sysstat; if( buf == NIL ) return -EFAULT; ans = stat( path, &sysstat ); if (ans == -1) return -errno; (void)ConvertStat( buf, &sysstat); return 0; } int ConvertStat( struct XR_stat *xs, struct stat *ps) { if( (xs == NIL) || (ps == NIL) ) return; xs->xrst_mode = ps->st_mode; xs->xrst_ino = ps->st_ino; xs->xrst_dev = ps->st_dev; xs->xrst_nlink = ps->st_nlink; xs->xrst_uid = ps->st_uid; xs->xrst_gid = ps->st_gid; xs->xrst_size = ps->st_size; xs->xrst_atime = ps->st_atime; xs->xrst_mtime = ps->st_mtime; xs->xrst_ctime = ps->st_ctime; xs->xrst_blksize = 4096; /* hack, hack */ xs->xrst_blocks = xs->xrst_size / xs->xrst_blksize; /* hack, hack */ return 0; } /* having trouble with lseek - seems to return fildes as result */ /* when defined as XR_SYSCALL3(LSeek,lseek) */ int XR_LSeek(int fildes, int offset, int whence) { int res; res = lseek(fildes, offset, whence); return (res); }