/*$Header: /a/rathlin/disk/src/master/edml/EDML4/fam.src/UPTODATE/RCS/system.h,v 5.1 91/09/05 18:25:07 edml Exp $*/

#define VERSION ((4 << 8) + 2)	/* 4.2 */
#define SUBVERSION ".00"    

/********************/
/*  EMAS	    */
/********************/
#ifdef EMAS
#   define apm
#   undef unix
#   undef sun
#endif

#include <stdio.h>
#include <stdarg.h>
extern void ml_printf(char *fmt, ...);
extern void ml_putchar(int c);
#define printf     ml_printf
#undef putchar
#define putchar(x) ml_putchar(x)
#ifdef CWIN
#include "cwin.h"
#undef  getchar
#define getchar()  cwin_getchar()
#define exit(n)    cwin_exit(n)
#define atexit(f)  cwin_atexit(f)
#define fflush(f)  ml_fflush(f)      /* Only called on stdout, I hope */
#endif

#ifdef transputer
#   define BIN_READ "rb"
#   define BIN_WRITE "wb"
#   define fopen my_fopen
#   define ALIGNED
#   define NEGPTRS
#   define NOSHORTS          /* ie. no signed 16-bit integers */
#   define NOSIGNEDCHARS
#endif

#ifdef __STDC__              /* ANSI draft May 86 */
#   define memcmp_supplied 1
#   define BIN_READ "rb"
#   define BIN_WRITE "wb"
#else		/* not __STDC__ */
#   define signed            /* opposite to unsigned */
#endif		/* __STDC__ */

#ifdef vax
#  ifdef vms
#     define system(s) \
         (fprintf(stderr, "\nNot implemented: 'system'\n"), exit(1))
#  else		/* not vms: assume unix otherwise */
#     define BSD 1
#  endif	/* vms */
#endif		/* vax */

/*
 * All of the stuff I can find in here relates to all 3Bs so far,
 * so I define u3b as a general switch.  If this is ever run on 3B20
 * or 3B4000, bets are off.  I can't quite come to terms with the
 * fact that `u3b' isn't defined already...
 *
 * Sam Nelson, Stirling Univ., 20.1.88.
 */
#if defined(u3b2) || defined(u3b5) || defined(u3b15)
#define u3b
#endif

#ifdef u3b
#   define oddsex
#   define ALIGNED
#   define NEGPTRS
#   define memcmp_supplied 1
#endif

#ifdef orion
#   define BSD 1
#   define WORDPTRS
#   define ALIGNED
#endif

#ifdef os370
#   define oddsex
#   define perror(x) perrorx(x)
#   define REALFMT "%0.14e"
#   define BIN_READ "r,binary"
#   define BIN_WRITE "w,binary"
#   define memcmp_supplied 1
#endif

#ifdef CWIN
#   define ALIGNED
/*
 * Win32s has NEGPTRS but Win32 (ie NT) does not - but otherwise they are
 * supposed to be pretty much identical. Ugh.
 */
#   define DYNAMICPTRS 1   /* Sign bit of memory addresses unknown! */
#endif

#ifdef DOS386
#  define ALIGNED
#  define ACN_PLOT
#endif

#ifdef ARM
#  define ALIGNED
#  ifdef RISC_OS
#    define BIN_READ "rb"
#    define BIN_WRITE "wb"
#  endif
#endif

#ifdef acorn32016
#   define system(s) \
       (fprintf(stderr, "\nNot implemented: 'system'\n"), exit(1))
#endif

#ifdef sun
#   define BSD 1
#ifndef i386
#   define oddsex
#endif
#   define ALIGNED
#endif

#ifdef selport
#   define BSD 1
#   define oddsex
#   define ALIGNED
#   define ALIGNREALS
#endif

#ifdef pyr
#   define BSD 1
#   define oddsex
#   define ALIGNED
#endif

#ifdef apm
#   define oddsex
#   define ALIGNED
#endif

#ifdef hpux
#   define oddsex
#   define ALIGNED
#endif

#ifdef sgi    /* Silicon Graphics Iris 4d */
#   define oddsex
#   define ALIGNED
#endif

#ifdef MIPSEL /*DECstation 3100 MIPSEL*/
#   define ALIGNED
#endif
#ifdef apollo
#   define BSD 1
#   define oddsex
#endif
#ifndef BSD
#   define valloc(x) malloc(x)   /* valloc is non-ANSI */
#endif

#ifndef REALFMT
#  define REALFMT "%0.16g"
#endif

#ifndef BIN_READ     /* compatibility with unices not accepting "rb" etc */
#  define BIN_READ "r"
#  define BIN_WRITE "w"
#endif

#ifdef unix
#   ifdef vax
#      define OrdAssign_(A,B) FAM_TEMPORARY = B; A = FAM_TEMPORARY
#   else	/* not vax */
#      define OrdAssign_(A,B) {LWord temp; temp = B; A = temp;}
#   endif	/* vax */
#else		/* not unix */
#   ifdef os370
#      define OrdAssign_(A,B) tmpreg = B; A = tmpreg;
#   else	/* not os370 */
#      define OrdAssign_(A,B) {LWord temp; temp = B; A = temp;}
#   endif	/* os370 */
#endif		/* unix */

/*
 * Added fcntl.h to replace archaic dup2() system call, and make memcmp()
 * available...
 *
 * Sam Nelson, Stirling Univ., 20.1.88.
 */
#ifdef u3b
#  include <fcntl.h>
#  define DUP2(ofd,cfd) {(void)close(cfd);(void)fcntl(ofd,F_DUPFD,cfd);}

#  include <memory.h>
#else
#   define DUP2 dup2
#endif

/* NICK: "execute" implemented via "vfork" if we've got it - forking an ML
         system's entire virtual address space is not my idea of fun.
 */

#ifdef BSD
#   define FORK vfork
#else
#   define FORK fork
#endif

#define Squeeze1_(S) OrdAssign_(*(S),*(S)++)

/* beware the following does not work on non-__STDC__ implementations
   with default char = unsigned char.
*/
#ifdef NOSIGNEDCHARS
static int PCSByteFn(i)
{
   if (i>127) i |= 0xFFFFFF00;
   return i;
}
#   define PCSByte_ (PCSByteFn(*(unsigned char *)PC++))
#else		/* not NOSIGNEDCHARS */
#   define PCSByte_ (*(signed char *)PC++)
#endif		/* NOSIGNEDCHARS */

#ifdef ALIGNED
# ifdef oddsex
#   define PCWord_ (PC += 2, PC[-2]<<8 | PC[-1] )
/* beware the next macro */
/* rjg inserted for emas compiler bug */
#   ifdef NOSHORTS
   static int PCSWordFn(i)
      int i;
   {
      if (i>=0x8000) i |= 0xFFFF0000;
      return i;
   }
#      define PCSWord_ (PCSWordFn((PC += 2, PC[-2]<<8 | PC[-1] )))
#   else	/* not NOSHORTS */
#      define PCSWord_ ((SWord)(PC += 2, PC[-2]<<8 | PC[-1] ))
#   endif	/* NOSHORTS */

#   define PCLWord_ (PC += 4, (PC[-4]<<24 | PC[-3]<<16 | PC[-2]<<8  | PC[-1]))
#   define StoreWord_(a,b) (((Byte *)(a))[0] = ((b) >> 8), \
                            ((Byte *)(a))[1] = (b))
#   define StoreLong_(a,b) (((Byte *)(a))[0] = ((b) >> 24), \
                            ((Byte *)(a))[1] = ((b) >> 16), \
                            ((Byte *)(a))[2] = ((b) >> 8),  \
                            ((Byte *)(a))[3] = (b))
#   define FetchWord_(a,b) ( a =  (((Byte *)(b))[0]), \
                             a = (a<<8) | (((Byte *)(b))[1]))
#   define FetchLong_(a,b) ( a = (((Byte *)(b))[0]), \
                             a = (a<<8) | (((Byte *)(b))[1]), \
                             a = (a<<8) | (((Byte *)(b))[2]), \
                             a = (a<<8) | (((Byte *)(b))[3]))
#   define PCSwTab_(n) (SWord)(PC[2*(n)]<<8 | PC[2*(n)+1])
# else		/* not oddsex */
#   define PCWord_ (PC += 2, PC[-1]<<8 | PC[-2] )
#   ifdef NOSHORTS
   static int PCSWordFn(i)
      int i;
   {
      if (i>=0x8000) i |= 0xFFFF0000;
      return i;
   }
#      define PCSWord_ (PCSWordFn((PC += 2, PC[-1]<<8 | PC[-2] )))
#   else	/* not NOSHORTS */
#      define PCSWord_ ((SWord)(PC += 2, PC[-1]<<8 | PC[-2] ))
#   endif	/* NOSHORTS */
#   define PCLWord_ (PC += 4, (PC[-1]<<24 | PC[-2]<<16 | PC[-3]<<8  | PC[-4]))
#   define PCSwTab_(n) ((SWord)(PC[2*(n)+1]<<8 | PC[2*(n)]))
#   define StoreWord_(a,b) (((Byte *)(a))[0] = (b), \
                            ((Byte *)(a))[1] = ((b) >> 8))
#   define StoreLong_(a,b) (((Byte *)(a))[0] = (b), \
                            ((Byte *)(a))[1] = ((b) >> 8), \
                            ((Byte *)(a))[2] = ((b) >> 16), \
                            ((Byte *)(a))[3] = ((b) >> 24))
#   define FetchWord_(a,b) ( a =  (((Byte *)(b))[1]), \
                             a = (a<<8) | (((Byte *)(b))[0]))
#   define FetchLong_(a,b) ( a = (((Byte *)(b))[3]), \
                             a = (a<<8) | (((Byte *)(b))[2]), \
                             a = (a<<8) | (((Byte *)(b))[1]), \
                             a = (a<<8) | (((Byte *)(b))[0]))
# endif		/* oddsex */
#else		/* not ALIGNED */
#   define PCLWord_ (PC += 4, ((LWord *)PC)[-1] )
#   define PCWord_ (PC += 2, ((Word *)PC)[-1] )
#   define PCSWord_ (PC += 2, (*(SWord *)(PC-2)) )
#   define StoreWord_(a,b) *(Word *)(a) = b
#   define StoreLong_(a,b) *(LWord *)(a) = b
#   define FetchWord_(a) (*(Word *)(a))
#   define FetchLong_(a) (*(LWord *)(a))
#   define PCSwTab_(n) (*(SWord *)(PC + (n)*2))
#endif		/* ALIGNED */

#ifdef ebcdic
   extern char etoa[], atoe[];
#  define hostchar(x) atoe[x]
#  define asciichar(x) etoa[x]
#else
#  define hostchar(x) (x)
#  define asciichar(x) (x)
#endif

#define bopen_(fil)   (fopen(fil, BIN_READ))
#define bcreate_(fil) (fopen(fil, BIN_WRITE))

#ifdef BSD   /* hack because of miserable implementation of fread in terms */
             /* of about 1000 calls to read()!!!!                          */
#  define bread_(fp,buf,siz) read(fileno(fp),buf,siz)
#else		/* not BSD */
#  define bread_(fp,buf,siz) fread(buf,1,siz,fp)
#endif		/* BSD */

#define bwrite_(fp,buf,siz) fwrite(buf,1,siz,fp)

#ifdef CWIN
#    define isatty_(fp) ((fp) == stdin || (fp) == stdout || (fp) == stderr )
#else
#ifdef os370
#   define isatty_(fp) inquire(fp,_TTY)
#else		/* not os370 */
#ifdef ARM
#  ifdef RISC_OS
#    define isatty_(fp) ((fp) == stdin || (fp) == stdout || (fp) == stderr )
       /* Can be done proper but not within ANSI-C library */
#  else
#    define isatty_(fp) _fisatty(fp)
#  endif
#else		/* not ARM */
#ifdef __STDC__
#    define isatty_(fp) ((fp) == stdin || (fp) == stdout || (fp) == stderr )
       /* Can be done proper but not within ANSI-C library */
#else		/* not __STDC__ */
/*
 * If `-p' flag was given, we want SML to behave in a terminal fashion
 * whether or not it's actually running to one...
 *
 * Sam Nelson, Stirling Univ., 20.1.88.
 */
#   define isatty_(fp) (faketty?1:(isatty(fileno(fp))))
#endif		/* __STDC__ */
#endif		/* ARM */
#endif		/* os370 */
#endif      /* CWIN */

extern char *filecreationdate();
extern SetupIntHandler(), SetupFloatHandler();
extern int TimeInMS();

#ifdef EMAS
#   define perror(a) fprintf(stderr,"%s\n",a)
#   define isatty_(fp) ((fp) == stdin || (fp) == stdout || (fp) == stderr )
#endif

#define ASSIGNED 0x20000000   /* MK: Used to mark updated references */

