#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/resource.h>
#include <sys/utsname.h>
#include <xr/sMisc.h>
#include <xr/Threads.h>
#include <xr/ThreadsMsg.h>
#include <xr/UIO.h>
#include <xr/GC.h>
#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);
}