ftp.nice.ch/pub/next/developer/languages/translator/schemetoc.s.tar.gz#/schemetoc/scrt/objects.h

This is objects.h in view mode; [Download] [Up]

/* SCHEME->C */

/*              Copyright 1989 Digital Equipment Corporation
 *                         All Rights Reserved
 *
 * Permission to use, copy, and modify this software and its documentation is
 * hereby granted only under the following terms and conditions.  Both the
 * above copyright notice and this permission notice must appear in all copies
 * of the software, derivative works or modified versions, and any portions
 * thereof, and both notices must appear in supporting documentation.
 *
 * Users of this software agree to the terms and conditions set forth herein,
 * and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
 * right and license under any changes, enhancements or extensions made to the
 * core functions of the software, including but not limited to those affording
 * compatibility with other hardware or software environments, but excluding
 * applications which incorporate this software.  Users further agree to use
 * their best efforts to return to Digital any such changes, enhancements or
 * extensions that they make and inform Digital of noteworthy uses of this
 * software.  Correspondence should be provided to Digital at:
 * 
 *                       Director of Licensing
 *                       Western Research Laboratory
 *                       Digital Equipment Corporation
 *                       100 Hamilton Avenue
 *                       Palo Alto, California  94301  
 * 
 * This software may be distributed (but not offered for sale or transferred
 * for compensation) to third parties, provided such third parties agree to
 * abide by the terms and conditions of this notice.  
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
*/

/* This module defines the basic data objects and their associated functions.
*/

/* Default the value of CPUTYPE if not currently defined. */
#ifndef MIPS
#ifndef TITAN
#ifndef VAX
#ifndef SPARC
#ifndef SUN3
#ifndef I386
#ifndef APOLLO
#ifndef PRISM

#ifdef mips
#define MIPS 1
#endif
#ifdef titan
#define TITAN 1
#endif
#ifdef vax
#define VAX 1
#endif
#ifdef sun
#  ifdef sparc
#    define SPARC 1
#  else
#    ifdef mc68000
#      define SUN3 1
#    endif
#  endif
#endif
#ifdef i386
#define I386 1
#endif
#ifdef apollo
#  ifdef _ISP_A88K
#    define PRISM 1
#  else
#    define APOLLO 1
#  endif
#endif

#endif /* PRISM */
#endif /* APOLLO */
#endif /* I386 */
#endif /* SUN3 */
#endif /* SPARC */
#endif /* VAX */
#endif /* TITAN */
#endif /* MIPS */

/* The Scheme->C installer may elect to have arithmetic overflow handled
   gracefully on either the MIPS or the VAX implementations.  The default
   is to handle it.
*/

#ifndef MATHTRAPS
#define MATHTRAPS 1
#endif

/* A machine dependent definition:  the setjmp/longjmp buffer.  */

#ifdef MIPS
#include <setjmp.h>
#define CPUTYPE MIPS
#define DOUBLE_ALIGN 1
#endif

#ifdef TITAN
#include <setjmp.h>
#define CPUTYPE TITAN
#undef MATHTRAPS
#endif

#ifdef VAX
typedef int jmp_buf[ 16 ];	/* The buffer contains the following items:
				   R2-R11	saved registers
				   SIGM		saved signal mask
				   SP		stack pointer on entry to
				   		setjmp
				   PSW		PSW word from stack frame
				   AP		saved argument ptr from frame
				   FP		saved frame ptr from frame
				   PC		saved program cntr from frame
				*/
#define CPUTYPE VAX
#endif

#ifdef APOLLO
#include <setjmp.h>
#define CPUTYPE APOLLO
#define BIG_ENDIAN
#endif

#ifdef PRISM
/* Use our own setjmp/longjmp so we can make sure all the registers
   are saved that need to be saved, namely, .10 through .23,
   plus the signal mask, return PC, and PSWs.

   The layout of these registers in the array is described in prism.asm.
*/
typedef int jmp_buf[18];
#define CPUTYPE PRISM
#define BIG_ENDIAN
#endif

#ifdef SPARC
typedef int jmp_buf[2+7+8+8+1];
#define DOUBLE_ALIGN 1
#define CPUTYPE SPARC
#define BIG_ENDIAN
#undef MATHTRAPS
#define MATHTRAPS 0
#endif

#ifdef SUN3
#include <setjmp.h>
#define CPUTYPE SUN3
#define BIG_ENDIAN
#undef MATHTRAPS
#define MATHTRAPS 0
#endif

#ifdef NeXT
#include <setjmp.h>
#define CPUTYPE NeXT
#define BIG_ENDIAN
#undef MATHTRAPS
#define MATHTRAPS 0
#endif

#ifdef I386
#include <setjmp.h>
#define CPUTYPE I386
#undef MATHTRAPS
#define MATHTRAPS 0
#endif

/* The data encoding scheme is similar to that used by Vax NIL and T, where
   all objects are represented by 32-bit pointers, with a "low tag" encoded
   in the two least significant bits encoding the type.  All objects are
   multiples of 32-bits and must be allocated on word boundaries.

   The basic data object is a "Scheme to C Object", or SCOBJ.  It is defined
   by the following UNION type.  In addition, the following types are also
   defined:

	SCP		pointer to a SCOBJ.
	TSCP		tagged pointer to a SCOBJ
	PATSCP		pointer to an array of TSCP's.
	TSCPP		function which returns a TSCP as its value.

   The most common type conversion is that which converts SCP's and TSCP's.
   It is done by the following:

	U_T( tsp, tag )	convert Untagged SCP to a Tagged TSCP.
	U_TX( tsp )	convert Untagged SCP to an Extended Tagged TSCP.
        U_TP( tsp )     convert Untagged SCP to an Pair Tagged TSCP.
	T_U( tscp )	convert Tagged TSCP to an Untagged SCP.
	TX_U( tscp )	convert Tagged eXtended pointer to an Untagged SCP.
        TP_U( tscp )    convert Tagged Pair pointer to an Untagged SCP.
*/

struct  STACKTRACE;

/*
  Ugly, but machine independent way to declare and use bit fields:
  Bit fields are declared using F?(...), where the least significant
  fields are listed first (in honor of the original implementations).
  Similarly, static objects are created with the U?(...) macros.
 */
#ifdef BIG_ENDIAN
#define	F2(a,b)		b;a
#define F3(a,b,c)	c;b;a
#define U2(a,b)		(b),(a)
#define	U3(a,b,c)	(c),(b),(a)
#else
#define F2(a,b)		a;b
#define F3(a,b,c)	a;b;c
#define U2(a,b)		(a),(b)
#define U3(a,b,c)	(a),(b),(c)
#endif

typedef char *TSCP;

typedef union SCOBJ {		/* SCHEME to C OBJECT */
	   struct {	/* as an unsigned value */
	      unsigned  gned;
	   }  unsi;
	   struct {	/* EXTENDEDOBJ */
	      F2(unsigned  tag:8,
	      unsigned  rest:24);
	   }  extendedobj;
	   struct {	/* SYMBOL */
	      F2(unsigned  tag:8,
	      unsigned  rest:24);
	      TSCP  name;
	      TSCP  *ptrtovalue;
	      TSCP  value;
	      TSCP  propertylist;
	   }  symbol;
	   struct {	/* STRING */
	      F2(unsigned  tag:8,
	      unsigned  length:24);
	      char  char0;
	   }  string;
	   struct {	/* VECTOR */
	      F2(unsigned  tag:8,
	      unsigned  length:24);
	      TSCP  element0;
	   }  vector;
	   struct {	/* PROCEDURE */
	      F3(unsigned  tag:8,
	      unsigned  required:8,
	      unsigned  optional:16);
	      TSCP  (*code)();
	      TSCP  closure;
	   }  procedure;
	   struct {	/* CLOSURE */
	      F2(unsigned  tag:8,
	      unsigned  length:24);
	      TSCP  closure;
	      TSCP  var0;
	   }  closure;
	   struct {	/* CONTINUATION */
	      F2(unsigned  tag:8,
	      unsigned  length:24);
	      TSCP  continuation;
	      jmp_buf  savedstate;
	      int  *address;
	      struct STACKTRACE*  stacktrace;
	      int  word0;
	   }  continuation;
	   struct {	/* FLOAT32 */
	      F2(unsigned  tag:8,
	      unsigned  rest:24);
	      float  value;
	   }  float32;
	   struct {	/* FLOAT64 */
	      F2(unsigned  tag:8,
	      unsigned  rest:24);
	      double  value;
	   }  float64;
	   struct {	/* FORWARD */
	      F2(unsigned  tag:8,
	      unsigned  length:24);
	      TSCP  forward;
	   } forward;
	   struct {	/* WORDALIGN */
	      F2(unsigned  tag:8,
	      unsigned  length:24);
	   }  wordalign;
	   struct {	/* PAIR */
	      TSCP  car;
	      TSCP  cdr;
	   } pair;
	}  *SCP;

typedef TSCP *PATSCP;	 /* POINTER to ARRAY of TAGGED SCHEME to C POINTERs */

typedef TSCP (*TSCPP)(); /* TAGGED SCHEME to C POINTER returning PROCEDURE */

#define	 TAGMASK 3
#define  TSCPTAG( x ) ((int)x & TAGMASK)
#define  U_T( scp, tag ) ((TSCP)((char*)(scp)+tag))
#define  U_TX( scp ) ((TSCP)((char*)(scp)+EXTENDEDTAG))
#define  U_TP( scp ) ((TSCP)((char*)(scp)+PAIRTAG))
#define  T_U( tscp ) ((SCP)((int)(tscp) & (~TAGMASK)))
#ifdef MIPS
#define  TX_U( tscp ) ((SCP)((char*)tscp-EXTENDEDTAG))
#define  TP_U( tscp ) ((SCP)((char*)tscp-PAIRTAG))
#endif
#ifdef TITAN
#define  TX_U( tscp ) ((SCP)tscp)
#define  TP_U( tscp ) ((SCP)tscp)
#endif
#ifdef VAX
#define  TX_U( tscp ) ((SCP)((char*)tscp-EXTENDEDTAG))
#define  TP_U( tscp ) ((SCP)((char*)tscp-PAIRTAG))
#endif
#ifdef apollo
#define  TX_U( tscp ) ((SCP)((char*)tscp-EXTENDEDTAG))
#define  TP_U( tscp ) ((SCP)((char*)tscp-PAIRTAG))
#endif
#ifdef SPARC
#define  TX_U( tscp ) ((SCP)((char*)tscp-EXTENDEDTAG))
#define  TP_U( tscp ) ((SCP)((char*)tscp-PAIRTAG))
#endif
#ifdef SUN3
#define  TX_U( tscp ) ((SCP)((char*)tscp-EXTENDEDTAG))
#define  TP_U( tscp ) ((SCP)((char*)tscp-PAIRTAG))
#endif
#ifdef NeXT
#define  TX_U( tscp ) ((SCP)((char*)tscp-EXTENDEDTAG))
#define  TP_U( tscp ) ((SCP)((char*)tscp-PAIRTAG))
#endif
#ifdef I386
#define  TX_U( tscp ) ((SCP)((char*)tscp-EXTENDEDTAG))
#define  TP_U( tscp ) ((SCP)((char*)tscp-PAIRTAG))
#endif

/* Fixed point numbers are encoded in the address portion of the pointer.  The
   value is obtained by arithmetically shifting the pointer value two bits to
   the right.  A tag value of 0 is used to allow fixed point numbers to be
   added and subtracted without any tag extraction and insertion.  Note that
   the define FIXED_C assumes that >> provides an arithmetic right shift.

	+--------+--------+--------+--------+
	|....signed fixed point value.....00|
	+--------+--------+--------+--------+
*/

#define	FIXNUMTAG 0

typedef int 	SCFIXED;	/* Scheme to C fixed point number */

#define FIXED_C( x ) (((int)(x))>>2)
#define C_FIXED( x ) ((TSCP)((x)<<2))


/* The second type of object is an "extended" object.  This is where the
   pointer points to the header of a multi-word object.

        +--------+--------+--------+--------+
        |........pointer to object........01|
        +--------+--------+--------+--------+
 
   This header in turn has an immediate tag (tag = 2) and the remaining 6 bits
   of the first byte define the type of the object as follows.

   A SYMBOL is represented by:

	+--------+--------+--------+--------+
	|    0   |    0   |    0   |10000010|		symbol (tag = 130)
	+--------+--------+--------+--------+
	|            symbol name	    |
	+--------+--------+--------+--------+
	| 	  pointer to value	    |
	+--------+--------+--------+--------+
	|               value    	    |
	+--------+--------+--------+--------+
	|           property list	    |
	+--------+--------+--------+--------+

   where the first word contains the tag.  Following the tag is the symbol
   name.  It is a string and is of the form "symbol-name" for top-level
   symbols and "module-name_symbol-name" for other symbols.

   Next comes a pointer to the top-level value of the symbol.  If the symbol
   is bound to a compiled global value, then the pointer will point to that
   value and the following field will not be used.  On the other hand, if
   the symbol is not bound to a compiled global, then the pointer will point
   to the following word which will hold its value.

   The final field points to the property list for the symbol.   

   All "interned" symbols are kept in a data structure called the OBARRAY.  It
   is a Scheme array which maintains bucket-hash lists of all allocated
   symbols.  Symbols are created and entered into the data structure by the
   function "sc_string_2d_3esymbol".

   A STRING is represented by:  

	+--------+--------+--------+--------+
	|     length of string     |10000110|		string (tag = 134)
        +--------+--------+--------+--------+
        |    i   |    r   |    t   |    s   |
        +--------+--------+--------+--------+
	|    -   |    0   |    g   |    n   |
	+--------+--------+--------+--------+

   where the first word contains the tag and the length (in bytes) of the
   string.  The string storage starts in the next word.  Following the last
   character of the string is a null byte. 

   A VECTOR is represented by:

	+--------+--------+--------+--------+
	|   number of elements     |10001010|           vector (tag = 138)
	+--------+--------+--------+--------+
	|            element 0              |
	+--------+--------+--------+--------+
	|            element 1              |
	+--------+--------+--------+--------+
	|	         ...		    |

  where the first word contains the tag and the length (in elements) of the
  vector.  The vector storage starts in the next word, where each element is a
  scheme pointer.

   A PROCEDURE is represented by:

        +--------+--------+--------+--------+
	|   0    |optional|required|10001110|           procedure (tag = 142)
	+--------+--------+--------+--------+
        |         code address              |
        +--------+--------+--------+--------+
	|  pointer to enclosing closure     |
	+--------+--------+--------+--------+

   where the first word contains the tag and the argument flags.  The optional
   flag is 0 when the function takes a fixed number of arguments and 1 when it
   takes a list of optional arguments as its final argument.  The required
   field is the number of required arguments that the function takes.  This is
   followed by the code address and a pointer to the enclosing closure (which
   may be () or a continuation).

   A CLOSURE is represented by:

	+--------+--------+--------+--------+
        |      # closed values     |10010010|           closure (tag = 146)
        +--------+--------+--------+--------+
        |    pointer to enclosing closure   |
        +--------+--------+--------+--------+
        |        1st closed variable        |
        +--------+--------+--------+--------+
        |        2nd closed variable        |
        +--------+--------+--------+--------+
        |                ...                |

   where the first word contains the tag and the number of closed variables.
   The next word contains a pointer to the enclosing closure (which may be ())
   and the closed variables then follow.

   A CONTINUATION is a formed by CALL-WITH-CURRENT-CONTINUATION.  It is
   represented by:

        +--------+--------+--------+--------+
        |      # saved words       |10010110|           continuation (tag=150)
        +--------+--------+--------+--------+
        | pointer to enclosing continuation |
        +--------+--------+--------+--------+
        .				    .
        .      state saved by setjmp	    .
        .        	 		    .
        +--------+--------+--------+--------+
        | address of word[0] of saved stack |
	+--------+--------+--------+--------+
	|   saved value of sc_stacktrace    |
	+--------+--------+--------+--------+
        .				    .
	.           saved display           .
	. 				    .
	+--------+--------+--------+--------+
	|      1st word of saved stack      |
	+--------+--------+--------+--------+
	|      2nd word of saved stack      |
	+--------+--------+--------+--------+
	|                ...                |

   where the first word contains the tag and the count of the number of words
   required to hold the continuation (does not include word for pointer to
   enclosing continuation).  The next word contains a pointer to the enclosing
   continuation (or () if there isn't one).  Following this is the state saved
   by setjmp.  The continuation is terminated by the stack address, the value
   of sc_stacktrace, the saved display, and the saved stack block.  Note the
   contents of any of these saved words may be pointers or derived from
   pointers.

   A 32-BIT FLOATING POINT number is represented by:

        +--------+--------+--------+--------+
        |    0   |    0   |    0   |10011010|           32-bit fp (tag = 154)
        +--------+--------+--------+--------+
        |   32-bit floating point value     |
        +--------+--------+--------+--------+

   A 64-BIT FLOATING POINT number is represented by:

        +--------+--------+--------+--------+
        |    0   |    0   |    0   |10011110|           64-bit fp (tag = 158)
        +--------+--------+--------+--------+
        |   				    |
        +--  64-bit floating point value  --+
	|				    |
	+--------+--------+--------+--------+

   A forwarded object (which may be a pair or an extended object) is
   represented by:

	+--------+--------+--------+--------+
	|        word count        |10100010|		forward (tag = 162)
	+--------+--------+--------+--------+
	|    tagged pointer to new copy     |
	+--------+--------+--------+--------+

   where the first word contains the tag and the size of the object (in words).
   The next word contains a Scheme pointer to the new copy of the object.

   When storage must be allocated to correctly align objects, a wordalign
   object is allocated:

	+--------+--------+--------+--------+
	|    0   |    0   |    0   |10100110|		word align (tag = 166)
	+--------+--------+--------+--------+
*/

#define	EXTENDEDTAG 	1
#define	SYMBOLTAG 	130
#define STRINGTAG	134
#define	VECTORTAG	138
#define	PROCEDURETAG	142
#define	CLOSURETAG	146
#define CONTINUATIONTAG 150
#define	FLOAT32TAG	154
#define FLOAT64TAG      158
#define FORWARDTAG	162
#define WORDALIGNTAG	166

/* The following definitions define the size in words of each extended object.
*/

#define SYMBOLSIZE	       5
#define STRINGSIZE( x )        ((((x)+4)/4)+1)
#define VECTORSIZE( x )        ((x)+1)
#define PROCEDURESIZE	       3
#define CLOSURESIZE( x )       ((x)+2)
#define CONTINUATIONSIZE( x )  ((x)+2)
#define FLOAT32SIZE	       2
#ifdef DOUBLE_ALIGN
#define FLOAT64SIZE	       4
#endif
#ifndef DOUBLE_ALIGN
#define FLOAT64SIZE	       3
#endif
#define FORWARDSIZE( x )       (x)
#define WORDALIGNSIZE	       1

/* While the data representation allows for two types of floating point
   numbers, only one type is actually used.  The default is 64-bits, but 32-bit
   numbers may be selected by defining the flag SHORTFLOAT.
*/

#ifdef SHORTFLOAT

#define FLOATTAG 	FLOAT32TAG
#define FLOATTYPE 	float
#define FLOATUTYPE 	float32
#define MAKEFLOAT	sc_makefloat32

#else

#define FLOATTAG 	FLOAT64TAG
#define FLOATTYPE 	double
#define FLOATUTYPE 	float64
#define MAKEFLOAT	sc_makefloat64

#endif

/* A pointer that points to an extended object must pass the following test.
   Note that some things which aren't pointers can pass this test too.  The
   pointer P must be untagged.
*/

#define EXTENDEDHEADER( p ) ((p->extendedobj.tag >= SYMBOLTAG) && \
			     (TSCPTAG( p->extendedobj.tag ) == IMMEDIATETAG))

/* The number of closed variables in a contination with 0 saved stack words is
   NULLCONTINUATIONSIZE.
*/

#define NULLCONTINUATIONSIZE (sizeof( jmp_buf )/4+2)

/* There is one string which is the empty string and one vector which is the
   empty vector.
*/

#define EMPTYSTRING	sc_emptystring
#define EMPTYVECTOR	sc_emptyvector

extern TSCP	sc_emptystring,
		sc_emptyvector;

/* The third type of object is an "immediate" object where the actual
   object type is encoded in the rest of the pointer.  The objects of this
   type are:

	+--------+--------+--------+--------+
	|    0	 |    0   |    0   |00000010|		empty list
	+--------+--------+--------+--------+

	+--------+--------+--------+--------+
	|    0	 |    0   |    0   |00001010|		#F
	+--------+--------+--------+--------+

	+--------+--------+--------+--------+
	|    0	 |    0   |    0   |00001110|		#T
	+--------+--------+--------+--------+

	+--------+--------+--------+--------+
	|    0	 |    0   |  char  |00010010|		character
	+--------+--------+--------+--------+

	+--------+--------+--------+--------+
	|    0   |    0   |    0   |00010110|		eof object
	+--------+--------+--------+--------+

	+--------+--------+--------+--------+
	|    0   |    0   |    0   |00011010|		undefined
	+--------+--------+--------+--------+

   Tags are allocated with an eye toward null testing.  Note that the the
   boolean #F and the list () are separate objects, but both are treated as
   false to conform to the Scheme definition.
	
	()	==  2   ==  emptylist
	
	#F	==  10  ==  falsevalue
	
	#T	==  14  ==  truevalue

	(NOT P)	==  $1 := P and 247;		
		    $1 := $1 =i 2;
*/

#define	IMMEDIATETAG		2
#define	IMMEDIATETAGMASK	255
#define	EMPTYLIST		((TSCP)2)
#define	FALSEVALUE		((TSCP)10)
#define	TRUEVALUE		((TSCP)14)
#define	CHARACTERTAG		18
#define	EOFOBJECT		((TSCP)22)
#define UNDEFINED		((TSCP)26)

#define C_CHAR( i )	 ((TSCP)(((unsigned)( i )<< 8)+CHARACTERTAG))
#define CHAR_C( c )	 ((char)(((unsigned)( c )) >> 8))
#define CHAR_FIX( c )    ((TSCP)(((unsigned)( c )) >> 6))
#define FIX_CHAR( fix )  ((TSCP)(((unsigned)( fix ) << 6)+CHARACTERTAG))

#define TSCPIMMEDIATETAG( p ) ((int)(p) & IMMEDIATETAGMASK)

extern TSCP  sc_emptylist,	/* Immediate denoting empty list */
	     sc_falsevalue,	/* Immediate denoting false */
	     sc_truevalue,	/* Immediate denoting true  */
	     sc_eofobject,	/* Immediate denoting end-of-file */
	     sc_undefined;	/* Immediate denoting the undefined value */

/* The final type of object is a list cell.  The CAR of the cell is a word
   stored at (pointer), and the CDR of the cell is the next word.

	+--------+--------+--------+--------+
	|    	   CAR of the pair	    |		pair
	+--------+--------+--------+--------+
	|    	   CDR of the pair	    |
	+--------+--------+--------+--------+
*/

#define	PAIRTAG	  3
#define CONSSIZE  2
#define CONSBYTES 8


/* Symbols are kept in the "obarray" which is a data structure internal to
   this module.  It is used by SYMBOL->STRING to make symbols unique.
*/

extern TSCP  sc_obarray;

/* In order for garbage collection to work correctly, the addresses of all
   globals containing constants and top level variables must be known.  They
   are maintained in two extensible structures:  sc_constants and sc_globals.
   Entries are added by addtoSCPTRS.
*/

struct  SCPTRS  {
   int  count;		/* # of pointers in the structure */
   int  limit;		/* # of pointers it could hold */
   TSCP  *ptrs[ 1 ];	/* pointers */
};

#define sizeofSCPTRS( x ) (sizeof(struct SCPTRS)+sizeof(TSCP)*((x)-1))

extern struct  SCPTRS  *addtoSCPTRS();

extern struct  SCPTRS  *sc_constants;

extern struct  SCPTRS  *sc_globals;

/* Access to lexically nested variables is via a display maintained by the
   following data structure.  SC_DISPLAY is an array which maintains the
   display, and SC_MAXDISPLAY is the maximum number of cells in the display
   that are ever used.
*/

extern TSCP  sc_display[];

extern int  sc_maxdisplay;

/* Debugging information is kept on the stack in an implementation independent
   manner by using the following data structures and conventions.  When a
   procedure is entered, it will allocate a STACKTRACE structure on the stack
   and set SC_STACKTRACE to point to it.  The fields in the structure are
   set as follows:
			in sceval_exec:		in any other procedure:

   prevstacktrace:	previous value of	previous value of
			sc_stacktrace		sc_stacktrace

   procname:		current environment	string naming the procedure

   exp:			expression being	unused
		        interpreted	

   When the procedure is exited, sc_stacktrace is restored.  In order to assure
   that sc_stacktrace always points to a valid entry, the list is maintained
   by subroutines (compilers want to optimize it out!).

   In dobacktrace(), the stack is traced by calling C-UNSIGNED-REF
   to get the prevstacktrace pointer.  The problem with this is that
   C-UNSIGNED-REF (aka scrt4_c_2dunsigned_2dref) uses MUNSIGNED, which
   uses T_U, which masks out the least significant two bits of the pointer.
   The trick is to get an implementation independent method of aligning
   the stacktrace structure.  Most compilers at least align the structure
   with an even address, but only some will align it on a four-byte boundary.

   The macro ALIGN4(t,x) declares "x" to be a pointer to "t", aligned on
   a 4-byte boundary.  If nothing special needs to be done, then the default
   definition can be used.
*/

#ifdef APOLLO
/* On an Apollo, things are usually aligned properly on the stack,
   but after an interrupt, things can get screwy, and even doubles
   can end up non-longword aligned.  To be safe, we need to align
   everything on a longword boundary ourselves.
*/
#define IDENT(a)	a
#define CAT(a,b)	IDENT(a)b
#define ALIGN4(t,x)	char CAT(x,buf)[sizeof(t) + sizeof(long)];\
    t& x = * (t*) ((unsigned)CAT(x,buf) & ~(sizeof(long)-1))
#endif

/* the rest of the world does not need to worry about such matters */
#ifndef ALIGN4
#define ALIGN4(t,x)	t x
#endif
struct  STACKTRACE {			/* Stack trace back record */
	struct STACKTRACE*  prevstacktrace;	
	TSCP  procname;
	TSCP  exp;
	};

extern  struct STACKTRACE  *sc_stacktrace;

#define  PUSHSTACKTRACE( procedure )	ALIGN4(struct  STACKTRACE,  st); \
					sc_pushtrace( &st, (procedure) )

#define  POPSTACKTRACE( exp )		return( sc_poptrace( &st, (exp) ) )

#define  LOOPSTACKTRACE( exp, env )	sc_looptrace( &st, (exp), (env) )

/* The procedural interfaces to this module are: */

extern TSCP   sc_make_2dstring_v;

extern TSCP   sc_make_2dstring();

extern TSCP   sc_string_2dcopy_v;

extern TSCP   sc_string_2dcopy();

extern TSCP   sc_cstringtostring();

extern TSCP   sc_make_2dvector_v;

extern TSCP   sc_make_2dvector();

extern TSCP   sc_makeclosure();

extern TSCP   sc_makeprocedure();

extern void   sc_initializevar();

extern void   sc_global_TSCP();

extern void   sc_constantexp();

extern TSCP   sc_string_2d_3esymbol_v;

extern TSCP   sc_string_2d_3esymbol();

extern TSCP   sc_d_2dsymbol_ab4b4447_v;

extern TSCP   sc_d_2dsymbol_ab4b4447();

extern TSCP   sc_uninterned_2dsymbol_3f_v;

extern TSCP   sc_uninterned_2dsymbol_3f();

extern TSCP   sc_clarguments();

extern char   sc_tscp_char();

extern int    sc_tscp_int();

extern unsigned  sc_tscp_unsigned();

extern unsigned  sc_tscp_pointer();

extern double sc_tscp_double();

extern TSCP   sc_int_tscp();

extern TSCP   sc_unsigned_tscp();

extern unsigned  sc_procedureaddress();

extern void   sc_pushtrace();

extern void   sc_looptrace();

extern TSCP   sc_poptrace();

/* The definitions which follow are used by the code generated by the Scheme->C
   compiler.  They are included in this file so that only one #include file
   will be required.
*/

/* Alternative C access to SCOBJ's */

#define UNSI_GNED( tscp )  (TX_U( tscp )->unsi.gned)

#define TSCP_EXTENDEDTAG( tscp )  (TX_U( tscp )->extendedobj.tag)

#define SYMBOL_NAME( tscp )          (TX_U( tscp )->symbol.name)
#define SYMBOL_VALUEADDR( tscp )     (TX_U( tscp )->symbol.ptrtovalue)
#define SYMBOL_VALUE( tscp )         (*TX_U( tscp )->symbol.ptrtovalue)
#define SYMBOL_PROPERTYLIST( tscp )  (TX_U( tscp )->symbol.propertylist)

#define STRING_LENGTH( tscp )   (TX_U( tscp )->string.length)
#define STRING_CHAR( tscp, n )  (*(((unsigned char*)tscp)+FIXED_C( n )+3))

#define VECTOR_LENGTH( tscp )     (TX_U( tscp )->vector.length)
#ifdef MIPS
#define VECTOR_ELEMENT( tscp, n ) (*((PATSCP)(((char*)( tscp ))+3+((int)n))))
#endif
#ifdef TITAN
#define VECTOR_ELEMENT( tscp, n ) (*(&TX_U( tscp )->vector.element0+ \
						    FIXED_C( n )))
#endif
#ifdef VAX
#define VECTOR_ELEMENT( tscp, n ) (*((PATSCP)(((char*)( tscp ))+3+((int)n))))
#endif
#ifdef apollo
#define VECTOR_ELEMENT( tscp, n ) (*((PATSCP)(((char*)( tscp ))+3+((int)n))))
#endif
#ifdef SPARC
#define VECTOR_ELEMENT( tscp, n ) (*((PATSCP)(((char*)( tscp ))+3+((int)n))))
#endif
#ifdef I386
#define VECTOR_ELEMENT( tscp, n ) (*((PATSCP)(((char*)( tscp ))+3+((int)n))))
#endif
#ifdef SUN3
#define VECTOR_ELEMENT( tscp, n ) (*((PATSCP)(((char*)( tscp ))+3+((int)n))))
#endif
#ifdef NeXT
#define VECTOR_ELEMENT( tscp, n ) (*((PATSCP)(((char*)( tscp ))+3+((int)n))))
#endif

#define PROCEDURE_REQUIRED( tscp )  (TX_U( tscp )->procedure.required)
#define PROCEDURE_OPTIONAL( tscp )  (TX_U( tscp )->procedure.optional)
#define PROCEDURE_CLOSURE( tscp )   (TX_U( tscp )->procedure.closure)
#define PROCEDURE_CODE( tscp )	    (TX_U( tscp )->procedure.code)

#define CLOSURE_LENGTH( tscp )   (TX_U( tscp )->closure.length)
#define CLOSURE_CLOSURE( tscp )  (TX_U( tscp )->closure.closure)
#define CLOSURE_VAR( tscp, n )   (*(&TX_U( tscp )->closure.var0+(n)))

#define FLOAT_VALUE( tscp )  (TX_U( tscp )->FLOATUTYPE.value)
 
#define PAIR_CAR( tscp )  (TP_U( tscp )->pair.car)
#define PAIR_CDR( tscp )  (TP_U( tscp )->pair.cdr)

/* C declarations */

#define DEFSTRING( name, chars, len ) \
	static struct { F2(unsigned tag:8, \
		        unsigned length:24); \
		        char char0[len+(4-(len % 4))]; } \
	name = { U2(STRINGTAG, len), chars }

#define DEFFLOAT( name, value ) \
	static struct { F2(unsigned tag:8, \
		        unsigned length: 24); \
		        FLOATTYPE f; } \
	name = { U2(FLOATTAG, 0), value }

#define DEFTSCP( name ) TSCP  name

#define DEFSTATICTSCP( name )  static TSCP  name

#define DEFSTATICTSCP2( name, obj )  static TSCP  name = U_TX( &obj )

#define EXTERNTSCP( a ) extern TSCP  a

#define EXTERNTSCPP( a )  extern TSCP  a()

#define EXTERNINT( a )  extern int a

#define EXTERNINTP( a ) extern int a()

#define EXTERNPOINTER( a )  extern unsigned a

#define EXTERNPOINTERP( a ) extern unsigned a()

#define EXTERNCHAR( a ) extern char a

#define EXTERNCHARP( a ) extern char a()

#define EXTERNSHORTINT( a ) extern short int a

#define EXTERNSHORTINTP( a ) extern short int a()

#define EXTERNLONGINT( a ) extern long int a

#define EXTERNLONGINTP( a ) extern long int a()

#define EXTERNUNSIGNED( a ) extern unsigned a

#define EXTERNUNSIGNEDP( a ) extern unsigned a()

#define EXTERNSHORTUNSIGNED( a ) extern short unsigned a

#define EXTERNSHORTUNSIGNEDP( a ) extern short unsigned a()

#define EXTERNLONGUNSIGNED( a ) extern long unsigned a

#define EXTERNLONGUNSIGNEDP( a ) extern long unsigned a()

#define EXTERNFLOAT( a ) extern float a

#define EXTERNFLOATP( a ) extern float a()

#define EXTERNDOUBLE( a ) extern double a

#define EXTERNDOUBLEP( a ) extern double a()

#define EXTERNVOIDP( a ) extern void a()

#define MAXDISPLAY( a ) if (a > sc_maxdisplay) sc_maxdisplay = a

/* C operators */

#define EQ( a, b )		(a == b)
#define NEQ( a, b )		(a != b)
#define NOT( a )		(a == 0)
#define GT( a, b )		(a > b)
#define LT( a, b )		(a < b)
#define GTE( a, b )		(a >= b)
#define LTE( a, b )		(a <= b)
#define OR( a, b )		(a || b)
#define AND( a, b )		(a && b)
#define SET( a, b )		(a = b)
#define BITAND( a, b )		(a & b)
#define BITOR( a, b )		(a | b)
#define BITXOR( a, b )		(a ^ b)
#define BITLSH( a, b )		(a << b)
#define BITRSH( a, b )		(a >> b)
#define PLUS( a, b )		(a + b)
#define DIFFERENCE( a, b )	(a - b)
#define NEGATE( a )		(- a)
#define TIMES( a, b )		(a * b)
#define QUOTIENT( a, b )	(a / b)
#define REMAINDER( a, b )	(a % b)
#define SHORTINT( a )		((short int) a)
#define INT( a )		((int) a)
#define LONGINT( a )		((long int) a)
#define SHORTUNSIGNED( a )	((short unsigned) a)
#define UNSIGNED( a )		((unsigned) a)
#define LONGUNSIGNED( a )	((long unsigned) a)
#define FLOAT( a )		((FLOATTYPE) a)
#define CFLOAT( a )		((float) a)
#define CDOUBLE( a )		((double) a)
#define _TSCP( a )		((TSCP) a)
#define VIA( a )		(*a)
#define ADR( a )		(&a)
#define DISPLAY( a )		(sc_display[ a ])

/* C operators that detect integer overflow in some implementations */

#if (MATHTRAPS == 0 || CPUTYPE == TITAN)
#define IPLUS( a, b )		(a + b)
#define IDIFFERENCE( a, b )	(a - b)
#define INEGATE( a )		(- a)
#define ITIMES( a, b )		(a * b)

#else

#define IPLUS( a, b )		sc_iplus( a, b )
#define IDIFFERENCE( a, b )	sc_idifference( a, b )
#define ITIMES( a, b )		sc_itimes( a, b )
#define INEGATE( a )		sc_inegate( a )
#endif

/* Generational garbage collection requires that stores of pointers to new
   objects in old objects be detected.  This is done by requiring the use
   of the macro SETGEN to set cells in SET-CAR!, SET-CDR!, VECTOR-SET!,
   PUTPROP, SCHEME-TSCP-SET!, and SET! of lexically bound variables.  The
   macro SETGENTL must be used to set the values of top level variables.

   N.B.  These macros assume a page size of 512 bytes.
*/

#define SETGEN( a, b )		((sc_pagelink[ (int)(((unsigned)(&a))>>9) ])?\
				 (a = b):sc_setgeneration( &a, b ))

#define SETGENTL( a, b )	(sc_setgeneration( &a, b ))

/* Scheme boolean tests */

#define TRUE( x )   ((((int)(x)) & 247) != 2)
#define FALSE( x )  ((((int)(x)) & 247) == 2)

/* Short circuiting for procedure application.  In order for this code
   to work correctly, it requires that the tag field be in the least
   significant 8 bits of the extended object header.
*/

#define UNKNOWNCALL( proc, argc ) \
    (sc_unknownargc = argc, sc_unknownproc[ 1 ] = proc, \
    sc_unknownproc[(PROCEDURE_REQUIRED(sc_unknownproc[ TSCPTAG(proc) ]) == argc\
		    && ! PROCEDURE_OPTIONAL(sc_unknownproc[ TSCPTAG( proc )]))])
/* UNSI_GNED(sc_unknownproc[ TSCPTAG( proc ) ] ) \
		    == (argc*256+PROCEDURETAG)) ])
*/

/* Inline type conversions */

/* round a floating point number to the nearest integer */
#ifdef apollo
#include <math.h>
/* Apollo SR10.2, with cc 6.7: rint() returns a bogus value (e.g., 0.9
   is "rounded" to 0.899902).
   If Apollo does not fix rint() soon, then we should write our own.
*/
#define rint(x)		floor((x) + 0.5)
#define ROUND(x)	((int) rint(x))
#endif

#ifndef ROUND
#define ROUND(x)	((int) (x))
#endif

#define FLT_FIX( flt )   C_FIXED( ROUND(FLOAT_VALUE( flt )) )
#define FIX_FLT( fix )   MAKEFLOAT( (FLOATTYPE)(FIXED_C( fix )) )
#define FIX_FLTV( fix )  ((FLOATTYPE)(FIXED_C( fix )))
#define FLTV_FLT( flt )	 MAKEFLOAT( flt )
#define FLTP_FLT( fltp ) MAKEFLOAT( *((FLOATTYPE*)( fltp )) )

#define STRING_C( s ) (&T_U( s )->string.char0)

#define BOOLEAN( c )	 ((c) ? TRUEVALUE : FALSEVALUE)

/* Memory Access */

#define MBYTE( base, bx )   (*( ((unsigned char*)T_U( base ))+bx ))
#define MSINT( base, bx )   (*((short int*)( ((char*)T_U( base )) + bx )))
#define MINT( base, bx )    (*((int*)( ((char*)T_U( base )) + bx )))
#define MUNSIGNED(base, bx) (*((unsigned*)( ((char*)T_U( base )) + bx )))
#define MSUNSIGNED(base,bx) (*((short unsigned*)( ((char*)T_U( base )) + bx )))
#define MTSCP( base, bx )   (*((TSCP*)( ((char*)T_U( base )) + bx )))
#define MFLOAT( base, bx ) (*((float*)( ((char*)T_U( base )) + bx )))
#define MDOUBLE( base, bx ) (*((double*)( ((char*)T_U( base )) + bx )))

/* Low-level builtins */

#define CONS 		sc_cons
#define STRINGTOSYMBOL 	sc_string_2d_3esymbol
#define CONSTANTEXP 	sc_constantexp
#define CLARGUMENTS 	sc_clarguments
#define MAKEPROCEDURE 	sc_makeprocedure
#define MAKECLOSURE 	sc_makeclosure
#define INITIALIZEVAR 	sc_initializevar
#define TSCP_CHAR	sc_tscp_char
#define TSCP_UNSIGNED	sc_tscp_unsigned
#define TSCP_INT	sc_tscp_int
#define TSCP_POINTER	sc_tscp_pointer
#define TSCP_DOUBLE	sc_tscp_double
#define CHAR_TSCP	C_CHAR
#define INT_TSCP	sc_int_tscp
#define UNSIGNED_TSCP   sc_unsigned_tscp
#define POINTER_TSCP	sc_unsigned_tscp
#define DOUBLE_TSCP	FLTV_FLT
#define INITHEAP	sc_restoreheap
#define SCHEMEEXIT()	scrt6_default_2dexit()
#define LISTTOVECTOR	scrt4_list_2d_3evector

/* External Functions and SCHEME->C globals which are defined in other
   modules.  They are duplicated here so that this file contains all external
   definitions needed by a SCHEME->C program.
*/

#ifdef PRISM
/* As explained in heap.c, it is important to declare the function prototype,
   so the compiler passes the floating point argument in a register, rather
   than on the stack.
*/
extern  TSCP  sc_makefloat32(float);
extern  TSCP  sc_makefloat64(double);
#else
extern  TSCP  sc_makefloat32();
extern  TSCP  sc_makefloat64();
#endif
extern  TSCP  sc_cons();
extern  int  sc_unknownargc;
extern  TSCP  sc_unknownproc[ 4 ];
extern  void  sc_restoreheap();
extern  TSCP  scrt4_list_2d_3evector();
extern  int   sc_iplus();
extern  int   sc_idifference();
extern  int   sc_itimes();
extern  int   sc_inegate();
extern  int*  sc_pagelink;
extern  TSCP  sc_setgeneration();

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.