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

This is scinit.c 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 some basic global objects and initializes those parts
   of the SCHEME->C runtime system which are written in C.  For
   compatibility with other modules, the routines and Scheme globals provided
   by these routines appear as members of the module "sc".
*/

/* External Definitions */

#ifdef NeXT
#define sbrk my_sbrk
#endif
extern  char *sbrk();
extern  char *getenv();

extern  errno;			/* C-library Error flag */

extern  etext;
#ifdef MIPS
#define ETEXT	((int)&etext)	/* First address after text */
#include <mips/param.h>
#include <mips/vmparam.h>
#define STACKBASE (int*)USRSTACK
#endif
#ifdef TITAN
#define ETEXT	etext		/* First address after text */
#include <sys/mparam.h>
#define STACKBASE (int*)(MAXUSERADDR+1)
#endif
#ifdef VAX
#define ETEXT	((int)&etext)	/* First address after text */
#include <vax/param.h>
#include <vax/vmparam.h>
#define STACKBASE (int*)USRSTACK
#endif
#ifdef apollo
#define ETEXT	((int)&etext)	/* First address after text */
#include <sys/param.h>
/* the stack back moves depending on shared libraries */
#include <apollo/base.h>
#include <apollo/error.h>
#include <apollo/proc2.h>
static proc2_$info_t sc_apollo_proc2;
#define STACKBASE ((int*) sc_apollo_proc2.stack_base)
#endif
#ifdef SPARC
#define ETEXT	((int)&etext)	/* First address after text */
#include <sun4/vmparam.h>
#define STACKBASE (int*)USRSTACK
#endif
#ifdef SUN3
#define ETEXT	((int)&etext)	/* First address after text */
#include <sun3/param.h>
#include <sun3/vmparam.h>
#define STACKBASE (int*)USRSTACK
#endif
#ifdef NeXT
#define ETEXT	((int)get_etext())
#include <next/vmparam.h>
#define STACKBASE (int*)USRSTACK
#endif
#ifdef ISC386IX
#define ETEXT	((int)&etext)	/* First address after text */
#include <sys/types.h>
#include <sys/fcntl.h>		/* probably should be elsewhere */
#include <sys/immu.h>
#define STACKBASE (int*)UVSTACK
#endif

#include <sys/types.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <strings.h>
#include <varargs.h>

/* Definitions for objects within sc */

#include "objects.h"
#include "scinit.h"
#include "heap.h"
#include "apply.h"
#include "callcc.h"
#include "signal.h"
#ifdef GGC
#include "GGC.h"
#endif

/* Definitions for objects elsewhere in the Scheme system */

extern  TSCP  scrt1_reverse();
extern  TSCP  scrt6_error();

/* Global data structure for this module. */

/* this struct must look like an SCOBJ */
static struct
{
    F2(unsigned  tag:8,
    unsigned  length:24);
} emptyvector, emptystring[2];

FILE   *sc_stdin,	/* Standard I/O Subroutine FILE pointers */
       *sc_stdout,
       *sc_stderr;

/* Command line arguments and environment variables which control the heap are
   interpreted by the following functions.
*/

static  char *heapfilename = NULL;	/* Pointer to heap file name */

static  int  defaultheap = 4,		/* Default heap size in megabytes */
	     minheap = 1,		/* Minimum heap size in megabytes */
	     maxheap = 1000,		/* Maximum heap size in megabytes */
	     defaultlimit = 33,		/* Default collection limit */
	     minlimit = 10,		/* Minimum total collection limit */
	     maxlimit = 45,		/* Maximun total collection limit */
	     scheap,			/* Heap size in megabytes */
	     sclimit;			/* % at which to do total collection */

static char*  getargval( argc, argv, cl, env )
	int  argc;
	char  *argv[],
	      *cl,	/* Ptr to command line argument name */
	      *env;	/* Ptr to environment variable name */
{
	int  i;

	for  (i = 1; i < argc-1; i++)  {
	   if  (strcmp( argv[ i ], cl ) == 0)  return( argv[ i+1 ] );
	}
	return( getenv( env ) );
}
	
static void  decodearguments( argc, argv )
	int  argc;
	char  *argv[];
{
	char  *val;
	
	val = getargval( argc, argv, "-sch", "SCHEAP" );
	if  (val != NULL)  {
	   scheap = atoi( val );
	   if  (scheap < minheap)  scheap = minheap;
	   if  (scheap > maxheap)  scheap = maxheap;
	}
	else  scheap = defaultheap;
	heapfilename = getargval( argc, argv, "-schf", "SCHEAPFILE" );
	val = getargval( argc, argv, "-scgc", "SCGCINFO" );
	if  (val != NULL)  {
	   sc_gcinfo = atoi( val );
	   if  (sc_gcinfo < 0  ||  sc_gcinfo > 2)  sc_gcinfo = 0;
	}
	else  sc_gcinfo = 0;
	val = getargval( argc, argv, "-scl", "SCLIMIT" );
	if  (val != NULL)  {
	   sclimit = atoi( val );
	   if  (sclimit < minlimit)  sclimit = defaultlimit;
	   if  (sclimit > maxlimit)  sclimit = defaultlimit;
	}
	else  sclimit = defaultlimit;
}

/* The variables holding the values of the functions defined in this module
   are initialized by the following procedure.
*/

DEFSTRING( t1030, "MY-RUSAGE", 9 );
DEFSTRING( t1032, "COLLECT-RUSAGE", 14 );
DEFSTRING( t1034, "COLLECT", 7 );
DEFSTRING( t1035, "COLLECT-ALL", 11 );
DEFSTRING( t1036, "CONS", 4 );
DEFSTRING( t1038, "MAKE-STRING", 11 );
DEFSTRING( t1040, "STRING-COPY", 11 );
DEFSTRING( t1044, "MAKE-VECTOR", 11 );
DEFSTRING( t1046, "STRING->SYMBOL", 14 );
DEFSTRING( t1048, "STRING->UNINTERNED-SYMBOL", 25 );
DEFSTRING( t1050, "UNINTERNED-SYMBOL?", 18 );
DEFSTRING( t1052, "CALL-WITH-CURRENT-CONTINUATION", 30 );
DEFSTRING( t1056, "SAVE-HEAP", 9 );
DEFSTRING( t1058, "IMPLEMENTATION-INFORMATION", 26 );
DEFSTRING( t1060, "AFTER-COLLECT", 13 );

static  init_procs()
{
#ifndef SYSV
        INITIALIZEVAR( U_TX( ADR( t1030 ) ), 
                       ADR( sc_my_2drusage_v ), 
                       MAKEPROCEDURE( 0, 
                                      0, sc_my_2drusage, EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1032 ) ), 
                       ADR( sc_collect_2drusage_v ), 
                       MAKEPROCEDURE( 0, 
                                      0, 
                                      sc_collect_2drusage, EMPTYLIST ) );
#endif
        INITIALIZEVAR( U_TX( ADR( t1034 ) ), 
                       ADR( sc_collect_v ), 
                       MAKEPROCEDURE( 0, 
                                      0, sc_collect, EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1035 ) ), 
                       ADR( sc_collect_2dall_v ), 
                       MAKEPROCEDURE( 0, 
                                      0, sc_collect_2dall, EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1036 ) ), 
                       ADR( sc_cons_v ), 
                       MAKEPROCEDURE( 2, 0, sc_cons, EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1038 ) ), 
                       ADR( sc_make_2dstring_v ), 
                       MAKEPROCEDURE( 1, 
                                      1, 
                                      sc_make_2dstring, EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1040 ) ), 
                       ADR( sc_string_2dcopy_v ), 
                       MAKEPROCEDURE( 1, 
                                      0, 
                                      sc_string_2dcopy, EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1044 ) ), 
                       ADR( sc_make_2dvector_v ), 
                       MAKEPROCEDURE( 1, 
                                      1, 
                                      sc_make_2dvector, EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1046 ) ), 
                       ADR( sc_string_2d_3esymbol_v ), 
                       MAKEPROCEDURE( 1, 
                                      0, 
                                      sc_string_2d_3esymbol, EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1048 ) ), 
                       ADR( sc_d_2dsymbol_ab4b4447_v ), 
                       MAKEPROCEDURE( 1, 
                                      0, 
                                      sc_d_2dsymbol_ab4b4447, 
                                      EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1050 ) ), 
                       ADR( sc_uninterned_2dsymbol_3f_v ), 
                       MAKEPROCEDURE( 1, 
                                      0, 
                                      sc_uninterned_2dsymbol_3f, 
                                      EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1052 ) ), 
                       ADR( sc_ntinuation_1af38b9f_v ), 
                       MAKEPROCEDURE( 1, 
                                      0, 
                                      sc_ntinuation_1af38b9f, 
                                      EMPTYLIST ) );
        INITIALIZEVAR( U_TX( ADR( t1056 ) ), 
                       ADR( sc_save_2dheap_v ), 
                       MAKEPROCEDURE( 1, 
                                      1, sc_save_2dheap, EMPTYLIST ) );
	INITIALIZEVAR( U_TX( ADR( t1058 ) ),
		       ADR( sc_implementation_v ),
		       MAKEPROCEDURE( 0,
				      0, sc_implementation, EMPTYLIST ) );
	INITIALIZEVAR( U_TX( ADR( t1060 ) ),
		       ADR( sc_after_2dcollect_v ),
		       FALSEVALUE );
        MAXDISPLAY( 0 );
        return;
}

/* Memory is allocated from the heap by calling the following function
   with a byte count.  It returns a pointer to the space.  Errors will
   cause the program to abort.
*/

static char  *getmem( bytes )
	int  bytes;
{
	char  *memp;

	memp = sbrk( 0 );
	if  ((int)memp & 7)
	   sbrk( 8-(int)memp & 7 );
	memp = sbrk( bytes );
	if  ((int)memp == -1)  {
	   fprintf( stderr, "***** Memory allocation failed: sbrk( %d )\n",
	   	    bytes );
	   exit( 1 );
	}
	return( memp );
}

/* The following function is called to initialize the heap from scratch. */

static int  module_initialized = 0;

sc_newheap()
{
	int  i;
	char  *freebase;
	TSCP  unknown;

#ifdef apollo
	/* on an apollo, we get the stack top at run time */
	uid_$t me;
	status_$t status;
	proc2_$who_am_i(&me);
	proc2_$get_info(me, &sc_apollo_proc2, sizeof(sc_apollo_proc2), &status);
	if (status.all != status_$ok && status.all != proc2_$is_current)
	{
	    error_$print(status);
	    exit(2);
	}
#endif

	if  (sc_gcinfo)
	   fprintf( stderr, "***** SCGCINFO = %d  SCHEAP = %d  SCLIMIT = %d\n",
	   	    sc_gcinfo, scheap, sclimit );
	sc_limit = sclimit;
	sc_heappages = scheap*(ONEMB/PAGEBYTES);
	sc_allocatedheappages = 0;
	freebase = getmem( scheap*ONEMB+PAGEBYTES-1 );
	if  ((int)freebase & (PAGEBYTES-1))
	   freebase = freebase+(PAGEBYTES-((int)freebase & (PAGEBYTES-1)));
	sc_firstheappage = ADDRESS_PAGE( freebase );
	sc_lastheappage = sc_firstheappage+sc_heappages-1;
	sc_freepage = sc_firstheappage;
	sc_firstheapp = (int*)freebase;
	sc_lastheapp = sc_firstheapp+PAGEWORDS*sc_heappages-1;
	sc_pagegeneration = ((int*)getmem( sc_heappages*4 ))-sc_firstheappage;
	sc_current_generation = 3;
	sc_next_generation = 3;
	sc_genlist = -1;
	sc_pagetype = ((int*)getmem( sc_heappages*4 ))-sc_firstheappage;
	sc_pagelock = ((int*)getmem( sc_heappages*4 ))-sc_firstheappage;
	sc_pagelink = ((int*)getmem( sc_heappages*4 ))-sc_firstheappage;
	for  (i = sc_firstheappage; i <= sc_lastheappage; i++ )  {
	   sc_pagegeneration[ i ] = 1;
	   sc_pagelock[ i ] = 0;
	}
	sc_initiallink = OKTOSET;
	sc_conscnt = 0;
	sc_extobjwords = 0;
	sc_mutex = 0;
	sc_pendingsignals = 0;
	sc_emptylist = EMPTYLIST;
	emptyvector.tag = VECTORTAG;
	emptystring[0].tag = STRINGTAG;
	sc_emptyvector = U_T( &emptyvector, EXTENDEDTAG );
	sc_emptystring = U_T( emptystring, EXTENDEDTAG );
	sc_falsevalue = FALSEVALUE;
	sc_truevalue = TRUEVALUE;
	sc_eofobject = EOFOBJECT;
	sc_undefined = UNDEFINED;
	sc_stdin = stdin;
	sc_stdout = stdout;
	sc_stderr = stderr;
	sc_constants = NULL;
	sc_globals = NULL;
	sc_stackbase = STACKBASE;
	sc_whenfreed = EMPTYLIST;
	sc_freed = EMPTYLIST;
	sc_clink = EMPTYLIST;
	sc_globals = addtoSCPTRS( sc_globals, &sc_clink );
	sc_stacktrace = NULL;
	sc_obarray = sc_make_2dvector( 1023*4, EMPTYLIST );
	sc_initializevar( sc_cstringtostring( "*OBARRAY*" ),
			  &sc_obarray,
			  sc_obarray );
	init_procs();
	unknown = sc_makeprocedure( 0, 0, sc_unknowncall, EMPTYLIST );
	TX_U( unknown )->procedure.required = 255;
	for  (i = 0;  i <= 3;  i++)  {
	   sc_unknownproc[ i ] = unknown;
	   sc_globals = addtoSCPTRS( sc_globals, &sc_unknownproc[ i ] );
	}
	module_initialized = 1;
}

/* The routines which follow are responsible for saving the heap to disc
   and reloading it.  Saved heap images have the following header at the
   front of the file.  Following the header is the sc_constants array, the
   sc_globals array, thepagegeneration array, the pagetype array, and all
   valid pages of the heap.
*/

static struct  {
	char  id[4];		/* S->C */
	TSCP  procedure;	/* Restart procedure */
	TSCP  correct;		/* List of values for constants & globals */
	int  etext;
	int  locklist;			/* From heap.h */
	int  lockcnt;
	int  current_generation;
	int  next_generation;
	int  limit;
	int  heappages;
	int  firstheappage;
	int  freepage;
	int  allocatedheappages;
	int  *firstheapp;
	int  conscnt;
	SCP  consp;
	int  extobjwords;
	int  extwaste;
	SCP  extobjp;
	int  *sc_stackbase;
	TSCP  sc_whenfreed;
	int  sc_constants_limit;	/* From objects.h */
	int  sc_globals_limit;
	int  sc_maxdisplay;
       }  save;

/* I/O is done directly with system calls so as to not allocate any data
   from the heap when the heap must be restored.
*/

static  int  heapfile;		/* File descriptor for the heap file */

static void  heapin( address, count )
	char  *address;
	int  count;
{
	if  (read( heapfile, address, count ) != count)  {
	   fprintf( stderr, "***** SAVE-HEAP HEAP FILE read error: %d\n",
	   	    errno );
	   exit( 1 );
	}
}

static void  heapout( address, count )
	char  *address;
	int  count;
{
	int  error;

	if  (write( heapfile, address, count ) != count)  {
	   error = errno;
	   close( heapfile );
	   sc_error( "SAVE-HEAP", "HEAP FILE fwrite error: ~s", 1,
                     C_FIXED( error ) );
	}
}

/* A Scheme program may call (SAVE-HEAP filename . procedure) to save the
   heap in a file named "filename".  When the heap is reloaded into a
   newly created process, execution will start at the procedure "procedure"
   which will be called with the command line argument list.  If procedure is
   not supplied, then the normal start up procedure will be used.
*/

TSCP  sc_save_2dheap_v;

TSCP  sc_save_2dheap( filename, argl )
	TSCP  filename, argl;
{
	int  i, firstpage, pagecount;
	TSCP  correct, cl, symbol, procedure;

	procedure = FALSEVALUE;
	if  (argl != EMPTYLIST)  {
	   procedure = PAIR_CAR( argl );
	   if  (TSCPTAG( procedure ) != EXTENDEDTAG  ||
	      T_U( procedure )->procedure.tag != PROCEDURETAG)
	      sc_error( "SAVE-HEAP",
	      		"Restart procedure is not a PROCEDURE: ~s",
	   	        1, procedure );
	   if  (PROCEDURE_REQUIRED( procedure ) > 1  ||
	        (PROCEDURE_REQUIRED( procedure ) == 0  &&
		 PROCEDURE_OPTIONAL( procedure ) == 0))
	      sc_error( "SAVE-HEAP",
	      		"Restart procedure must take 1 argument", 0 );
	   if  (PAIR_CDR( argl ) != EMPTYLIST)  {
	      sc_error( "SAVE-HEAP", "Too many arguments", 0 );
	   }
	}
	if  (TSCPTAG( filename ) != EXTENDEDTAG  ||
	     T_U( filename )->string.tag != STRINGTAG)
	   sc_error( "SAVE-HEAP", "File name is not a STRING: ~s", 1,
	   	     filename );
	heapfile = open( &(T_U( filename )->string.char0),
			 (O_WRONLY | O_CREAT | O_TRUNC), 0750 );
	if  (heapfile == -1)
	   sc_error( "SAVE-HEAP", "Can't open HEAP FILE: ~s", 1,
	             C_FIXED( errno ) );
	sc_collect_2dall();
	/* Build the save-heap file header */
	correct = EMPTYLIST;
	for  (i = 0; i < sc_constants->count; i++)
	   correct = sc_cons( *(sc_constants->ptrs[ i ]), correct );
        for  (i = 0; i < sc_globals->count; i++)
	   correct = sc_cons( *(sc_globals->ptrs[ i ]), correct );
	strncpy( save.id, "S->C", 4 );
	save.procedure = procedure;
	save.correct = correct;
	save.etext = ETEXT;
	save.locklist = sc_locklist;
	save.lockcnt = sc_lockcnt;
	save.current_generation = sc_current_generation;
	save.next_generation = sc_next_generation;
	save.limit = sc_limit;
	save.heappages = sc_heappages;
	save.firstheappage = sc_firstheappage;
	save.freepage = sc_freepage;
	save.allocatedheappages = sc_allocatedheappages;
	save.firstheapp = sc_firstheapp;
	save.conscnt = sc_conscnt;
	save.consp = sc_consp;
	save.extobjwords = sc_extobjwords;
	save.extwaste = sc_extwaste;
	save.extobjp = sc_extobjp;
	save.sc_stackbase = sc_stackbase;
	save.sc_whenfreed = sc_whenfreed;
	save.sc_constants_limit = sc_constants->limit;
	save.sc_globals_limit = sc_globals->limit;
	save.sc_maxdisplay = sc_maxdisplay;
	heapout( &save, sizeof( save ) );
	heapout( sc_constants, sizeofSCPTRS( sc_constants->limit ) );
	heapout( sc_globals, sizeofSCPTRS( sc_globals->limit ) );
	heapout( &sc_pagegeneration[ sc_firstheappage ], sc_heappages*4 );
	heapout( &sc_pagetype[ sc_firstheappage ], sc_heappages*4 );
	pagecount = 0;
	for  (i = sc_firstheappage; i <= sc_lastheappage; i++)  {
	   if  (sc_pagegeneration[ i ] == sc_current_generation  ||
		~sc_pagegeneration[ i ] & 1)  {
	      if  (pagecount++ == 0)  firstpage = i;
	   }
	   else  if  (pagecount)  {
	      heapout( PAGE_ADDRESS( firstpage ), pagecount*PAGEBYTES );
	      pagecount = 0;
	   }
	}
	if  (pagecount)
	   heapout( PAGE_ADDRESS( firstpage ), pagecount*PAGEBYTES );
	close( heapfile );
	return( TRUEVALUE );
}

/* The following routine is called from a Scheme main program to determine
   how the heap is to be constructed.  If the heap is being constructed from
   a saved file, then this function will not return.  If there is no saved
   heap, then sc__init will be called to initialize the heap.
*/

void  sc_restoreheap( desiredheap, argc, argv, mainproc )
	int  desiredheap;
	int  argc;
	char  *argv[];
	void  (*mainproc)();
{
	int  i,
	     pagecount,
	     firstpage;
	char  *freebase;
	TSCP  cl,
	      *address,
	      address_value;

	if  (module_initialized)  return;
	if  (desiredheap)  {
	   defaultheap = desiredheap;
	   minheap = desiredheap;
	}
	decodearguments( argc, argv );
#ifdef GGC
        GGCcreateMemoryBoard();
#endif
	if  (heapfilename == NULL)  {
	   sc_newheap();
	   return;
	}
	/* Saved heap exists, open it and validate the header */
	heapfile = open( heapfilename, O_RDONLY );
	if  (heapfile == -1)  {
	   fprintf( stderr, "***** Can't open heap file: %d\n", errno );
	   exit( 1 );
	}
	heapin( &save, sizeof( save ) );
	if  (strncmp( save.id, "S->C", 4)  ||  save.etext != ETEXT)  {
	   fprintf( stderr, "***** Incompatible heap file image\n" );
	   exit( 1 );
	}
	/* Initialize similar to sc__init */
	if  (scheap < save.heappages/(ONEMB/PAGEBYTES))
	   scheap = save.heappages/(ONEMB/PAGEBYTES);
	if  (sclimit < save.limit)  sclimit = save.limit;
#ifdef sun
	/* in SunOS, stderr is line buffered, which causes some unwanted */
	/* malloc..  */
	if (sc_gcinfo)
	    setbuf(stderr, (char*)0);
#endif
	if  (sc_gcinfo)
	   fprintf( stderr, "***** SCGCINFO = %d  SCHEAP = %d  SCLIMIT = %d\n",
		    sc_gcinfo, scheap, sclimit );
	sc_limit = sclimit;
	sc_heappages = scheap*(ONEMB/PAGEBYTES);
	sc_allocatedheappages = save.allocatedheappages;
	freebase = getmem( scheap*ONEMB+PAGEBYTES-1 );
	if  ((int)freebase & (PAGEBYTES-1))
	   freebase = freebase+(PAGEBYTES-((int)freebase & (PAGEBYTES-1)));
	sc_firstheappage = ADDRESS_PAGE( freebase );
	sc_lastheappage = sc_firstheappage+sc_heappages-1;
	sc_firstheapp = (int*)freebase;
	sc_lastheapp = sc_firstheapp+PAGEWORDS*sc_heappages-1;
	sc_freepage = save.freepage;
	sc_pagegeneration = ((int*)getmem( sc_heappages*4 ))-sc_firstheappage;
	sc_current_generation = save.current_generation;
	sc_next_generation = save.next_generation;
	sc_constants =
	     (struct SCPTRS*)malloc( sizeofSCPTRS( save.sc_constants_limit ) );
	heapin( sc_constants, sizeofSCPTRS( save.sc_constants_limit ) );
	sc_globals =
	     (struct SCPTRS*)malloc( sizeofSCPTRS( save.sc_globals_limit ) );
	heapin( sc_globals, sizeofSCPTRS( save.sc_globals_limit ) );
	heapin( &sc_pagegeneration[ sc_firstheappage ], save.heappages*4 );
	for  (i = save.firstheappage+save.heappages; i <= sc_lastheappage;
	      i++ )
	   sc_pagegeneration[ i ] = 1;
	sc_pagetype = ((int*)getmem( sc_heappages*4 ))-sc_firstheappage;
	heapin( &sc_pagetype[ sc_firstheappage ], save.heappages*4 );
	sc_pagelock = ((int*)getmem( sc_heappages*4 ))-sc_firstheappage;
	sc_genlist = -1;
	sc_pagelink = ((int*)getmem( sc_heappages*4 ))-sc_firstheappage;
	for  (i = sc_firstheappage; i <= sc_lastheappage; i++)  {
	   sc_pagelink[ i ] = 0;
	   sc_pagelock[ i ] = 0;
	}
	sc_initiallink = OKTOSET;
	sc_conscnt = save.conscnt;
	sc_consp = save.consp;
	sc_extobjwords = save.extobjwords;
	sc_extobjp = save.extobjp;
	sc_extwaste = save.extwaste;
	sc_mutex = 0;
	sc_pendingsignals = 0;
	sc_emptylist = EMPTYLIST;
	emptyvector.tag = VECTORTAG;
	emptystring[0].tag = STRINGTAG;
	sc_emptyvector = U_T( &emptyvector, EXTENDEDTAG );
	sc_emptystring = U_T( emptystring, EXTENDEDTAG );
	sc_falsevalue = FALSEVALUE;
	sc_truevalue = TRUEVALUE;
	sc_eofobject = EOFOBJECT;
	sc_undefined = UNDEFINED;
	sc_stdin = stdin;
	sc_stdout = stdout;
	sc_stderr = stderr;
	sc_maxdisplay = save.sc_maxdisplay;
	sc_stackbase = save.sc_stackbase;
	sc_whenfreed = save.sc_whenfreed;
	sc_freed = EMPTYLIST;
	sc_stacktrace = NULL;
	/* Reload the heap and correct globals which point into it */
	pagecount = 0;
	for  (i = sc_firstheappage; i < sc_firstheappage+save.heappages;
	      i++)  {
	   if  (sc_pagegeneration[ i ] == sc_current_generation  ||
		~sc_pagegeneration[ i ] & 1)  {
	      if  (pagecount++ == 0)  firstpage = i;
	   }
	   else  if  (pagecount)  {
	      heapin( PAGE_ADDRESS( firstpage ), pagecount*PAGEBYTES );
	      pagecount = 0;
	   }
	}
	if  (pagecount)
	   heapin( PAGE_ADDRESS( firstpage ), pagecount*PAGEBYTES );
	cl = save.correct;
        for  (i = sc_globals->count-1; i >= 0 ; i--)  {
	   *(sc_globals->ptrs[ i ]) = PAIR_CAR( cl );
	   cl = PAIR_CDR( cl );
	}
	for  (i = sc_constants->count-1; i >= 0; i--)  {
	   *(sc_constants->ptrs[ i ]) = PAIR_CAR( cl );
	   cl = PAIR_CDR( cl );
	}
	sc_clink = EMPTYLIST;
	close( heapfile );
#ifdef GGC
	for  (i = sc_firstheappage;  i <= sc_lastheappage;  i++)  {
	   if  (sc_pagegeneration[ i ] == sc_current_generation)
	      switch  (sc_pagetype[ i ])  {
	         case  PAIRTAG:
		    GGCmarkPair( i );
		    break;
	         case  EXTENDEDTAG:
		    GGCmarkExtended( i );
		    break;
	         case  BIGEXTENDEDTAG:
		    GGCmarkContinuations( i, 1 );
		    break;
	      }
	}
#endif
	module_initialized = 1;
	/* Start execution at the appropriate procedure */
	if  (save.procedure != FALSEVALUE)
	   sc_apply_2dtwo( save.procedure,
	   	          sc_cons( sc_clarguments( argc, argv ), EMPTYLIST ) );
	else  if  (mainproc != NULL)  
	   (*mainproc)( sc_clarguments( argc, argv ) );
	else
	   return;
	SCHEMEEXIT();
}

/* This initialization function is provided to allow automatic initialization
   from a Modula-2 program.
*/

sc__init()
{
	sc_restoreheap( 0, 0, NULL, NULL );
}

/* Routines coded in C call the following function to access the Scheme ERROR
   function.  SYMBOL is a string representing the function name.  FORMAT is a
   string which is a format descriptor.  ARGC is the argument count which is
   followed by the arguments.
*/

sc_error( va_alist )
	va_dcl
{
	char  *symbol, *format;
	int  argc;
	TSCP  argl;
	va_list  argp;

	va_start( argp );
	symbol = va_arg( argp, char* );
	format = va_arg( argp, char* );
	argc = va_arg( argp, int );
	argl = sc_emptylist;
	while  (argc--)  argl = sc_cons( va_arg( argp, TSCP ), argl );
	scrt6_error( sc_string_2d_3esymbol( sc_cstringtostring( symbol ) ),
		     sc_cstringtostring( format ),
		     scrt1_reverse( argl ) );
	va_end( argp );
}

/* The following function returns informations about the implementation.  The
   form of the function follows a recent proposal on rrrs-authors.  The result
   is a list of strings or #F's of the form:

	  (<name> <version> <MACHINE> <CPU> <OS> <FS> . <supports>)
*/

TSCP  sc_implementation_v;

TSCP  sc_implementation()
{
	return(
	   sc_cons(
	      sc_cstringtostring( "Scheme->C" ),
	      sc_cons(
	         sc_cstringtostring( "28sep90jfb" ),
	         sc_cons(
#ifdef MIPS
		    sc_cstringtostring( "DECstation3100" ),
#endif
#ifdef TITAN
		    sc_cstringtostring( "WRL-TITAN" ),
#endif
#ifdef VAX
		    sc_cstringtostring( "VAX" ),
#endif
#ifdef apollo
		    sc_cstringtostring( "Apollo" ),
#endif
#ifdef SPARC
		    sc_cstringtostring( "Sun4/SPARC" ),
#endif
#ifdef SUN3
		    sc_cstringtostring( "Sun3" ),
#endif
#ifdef NeXT
		    sc_cstringtostring( "NeXT" ),
#endif
#ifdef I386
		    sc_cstringtostring( "AT/386" ),
#endif

		    sc_cons(
#ifdef MIPS
		       sc_cstringtostring( "R2000" ),
#endif
#ifdef TITAN
		       sc_cstringtostring( "BYTE-ADDRESSED" ),
#endif
#ifdef VAX
		       sc_cstringtostring( "VAX" ),
#endif
#ifdef APOLLO
		       sc_cstringtostring( "68K" ),
#endif
#ifdef PRISM
		       sc_cstringtostring( "PRISM" ),
#endif
#ifdef SPARC
		       sc_cstringtostring( "SPARC" ),
#endif
#ifdef SUN3
		       sc_cstringtostring( "68K" ),
#endif
#ifdef NeXT
		       sc_cstringtostring( "68K" ),
#endif
#ifdef I386
		       sc_cstringtostring( "Intel 386" ),
#endif
		       sc_cons(
#ifdef NeXT
		          sc_cstringtostring( "NeXT OS 2.0" ),
#else
#ifdef apollo
		          sc_cstringtostring( "Domain/OS" ),
#else /* ! apollo */
#ifdef SPARC
#ifdef sun
			  sc_cstringtostring( "SunOS" ),
#else
			  sc_cstringtostring( "SparcOS" ),
#endif /* sun */
#else /* ! SPARC */
#ifdef SUN3
			  sc_cstringtostring( "SunOS" ),
#else
#ifdef SYSV
			  sc_cstringtostring( "System V.3.2" ),
#else
		          sc_cstringtostring( "ULTRIX" ),
#endif /* SYSV */
#endif /* SUN3 */
#endif /* SPARC */
#endif /* apollo */
#endif /* NeXT */
		          sc_cons(
			      FALSEVALUE,
			      EMPTYLIST
			         )
			      )
			   )
		        )
		     )
	          )
	      );
}

#ifdef NeXT
#include <mach.h>
#include <stdio.h>

char               *my_current_brk = 0;
char               *my_end_brk = 0;

char *
my_sbrk(int incr)
{
  char               *temp, *ptr;
  kern_return_t       rtn;

  if (my_current_brk == 0) {
    if ((rtn = vm_allocate(task_self(), (vm_address_t *) & my_current_brk,
			   vm_page_size, 1)) != KERN_SUCCESS) {
      mach_error("my_sbrk: vm_allocate failed", rtn);
      return ((char *)-1);
    }
    my_end_brk = my_current_brk + vm_page_size;
  }
  if (incr == 0) return (my_current_brk);
 more:
  ptr = my_current_brk + incr;
  if (ptr <= my_end_brk) {
    temp = my_current_brk;
    my_current_brk = ptr;
    return (temp);
  } else {
    if ((rtn = vm_allocate(task_self(), (vm_address_t *) &ptr,
			   vm_page_size, 1)) != KERN_SUCCESS) {
      mach_error("my_sbrk: vm_allocate failed", rtn);
      return ((char *)-1);
    }
    if (ptr != my_end_brk) {
      fprintf(stderr, "my_sbrk: internal error\n");
      fflush(stderr);
      return ((char *)-1);
    }
    my_end_brk = ptr + vm_page_size;
    goto more;
  }
}
#endif /* NeXT */

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