[pe.cust.sources] Little Smalltalk Source, *New* Part 16 of 20

earlw@pesnta.UUCP (Earl Wallace) (06/13/85)

#! /bin/sh 
#
# This is an another posting of the Little Smalltalk source, the last posting
# of this source went out in 5 parts and they were too big (>200k) for most
# sites so I redid the whole mess to keep the files around the 50k range.
#
# The complete set is now 20 parts.
#
# P.S. - If you don't receive all 20 parts within 5 days, drop me a line.
#	 Also, I have the Rand sources of May 1984, if someone has a more
#	 updated copy, I'll be happy to post them (or YOU can post them :-))
# 
# -earlw@pesnta
#
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	sources/main.c
#	sources/number.c
#	sources/number.h
#	sources/object.c
#	sources/object.h
# This archive created: Thu Jun 13 11:33:00 1985
# By:	Earl Wallace (Perkin-Elmer Data Systems Group / Customer Service)
export PATH; PATH=/bin:$PATH
if test -f 'sources/main.c'
then
	echo shar: will not over-write existing file "'sources/main.c'"
else
cat << \SHAR_EOF > 'sources/main.c'
/*
	Little Smalltalk -
		main driver

		timothy a. budd

1. 	initializes various smalltalk constants and classes with
	legitimate values.  these values, however, will for the most part
	be overridden when the standard prelude is read in.

2.	reads in the standard prelude, plus any additional files listed
	on the command line.

3.	places the driver reading stdin on the process queue and starts
	the process driver running.
*/
/*
	The source code for the Little Smalltalk System may be freely
	copied provided that the source of all files is acknowledged
	and that this condition is copied with each file.

	The Little Smalltalk System is distributed without responsibility
	for the performance of the program and without any guarantee of
	maintenance.

	All questions concerning Little Smalltalk should be addressed to:

		Professor Tim Budd
		Department of Computer Science
		The University of Arizona
		Tucson, Arizona
		85721
		USA
*/

int version = 2; /* a Kludge to get us the start of the data segment.
			used to save and restore contexts */


# include <stdio.h>
# include "object.h"
# include "string.h"
# include "symbol.h"
# include "interp.h"
# include "primitive.h"

static object *null_object;	/* a totally classless object */
static char filebase[80];	/* base for forming temp file names */

extern int n_incs, n_decs, n_mallocs;	/* counters */

extern int ca_block, ca_barray, ca_class, ca_terp, ca_int, ca_float;
extern int ca_obj, ca_str, ca_sym, ca_wal, ca_cdict;
extern int ca_cobj[];
extern int btabletop, wtop;	/* more counters */

# ifdef INLINE
object *_dx;		/* object pointer used for decrementing */
# endif

int silence = 0;    	/* 1 if silence is desired on output */
int noload = 0;     	/* 1 if no loading of standard prelude is desired */
int debug = 0;		/* debug flag, set by a primitive call */
int fastload = 0;	/* 1 if doing a fast load of saved image */
int lexprnt = 0;	/* 1 if printing during lex is desired (for debug) */
int prallocs = 0;	/* 1 if printing final allocation figures is wanted */
int started = 0;	/* 1 if we have started reading user commands */
int prntcmd = 1;	/* 1 or 2 and commands will be printed as evaled */

/* pseudo-variables */
object *o_acollection;		/* arrayed collection (used internally) */
object *o_drive;		/* driver interpreter */
object *o_empty;		/* the empty array (used during initial) */
object *o_false;		/* value for pseudo variable false */
object *o_magnitude;		/* instance of class Magnitude */
object *o_nil;			/* value for pseudo variable nil */
object *o_number;		/* instance of class Number */
object *o_object;		/* instance of class Object */
object *o_tab;			/* string with tab only */
object *o_true;			/* value of pseudo variable true */
object *o_smalltalk;		/* value of pseudo variable smalltalk */

/* classes to be initialized */
extern class *Array;
extern class *ArrayedCollection;

/* input stack */
extern FILE *fdstack[];
extern int fdtop;

/* main - main driver */
main(argc, argv)
int argc;
char **argv;
{	int i;
	class *null_class();
	object *tempobj;
	FILE *sfd;

# ifdef FASTDEFAULT
	fastload = 1;
# endif
# ifndef FASTDEFAULT
	fastload = 0;
# endif

	/* first check for flags */
	for (i = 1; i < argc; i++)
		if (argv[i][0] == '-')
			switch(argv[i][1]) {
				case 'f': fastload = 1; break;
				case 'l': 		/* fall through */
				case 'n': noload = 1; /* fall through */
				case 'm': fastload = 0; break;
				case 'z': lexprnt = 1; break;
			}

	if (fastload) {
		dofast();
		}
	else {			/* gotta do it the hard way */
		strcpy(filebase, TEMPFILE);
		mktemp(filebase);

		byte_init();
		class_init();
		cdic_init();
		int_init();
		str_init();
		sym_init();
		init_objs();

		null_object = new_obj((class *) 0, 0, 0);

		sassign(o_object, null_object);
		/* true is given a different object from others , so comparisons
					work correctly */
		sassign(o_true, new_obj((class *) 0, 0, 0));
		sassign(o_false, null_object);
		sassign(o_nil, null_object);
		sassign(o_number, null_object);
		sassign(o_magnitude, null_object);
		sassign(o_empty, null_object);
		sassign(o_smalltalk, null_object);
		sassign(o_acollection, null_object);

		sassign(Array, null_class("Array"));
		sassign(ArrayedCollection, null_class("ArrayedCollection"));

		drv_init();	/* initialize the driver */
		sassign(o_drive, (object *) cr_interpreter((interpreter *) 0,
			null_object, null_object, null_object, null_object));
		init_process((interpreter *) o_drive);

		/* now read in standard prelude */
		if (! noload) {
			sfd = fopen(PRELUDE, "r");
			if (sfd == NULL) cant_happen(20);
			set_file(sfd);
			start_execution();
			fclose(sfd);
			}

		/* then set lexer up to read stdin */
		set_file(stdin);
		sassign(o_tab, new_str("\t"));
		}

	/* announce that we're ready for action */
	sassign(tempobj, new_sym("Little Smalltalk"));
	primitive(SYMPRINT, 1, &tempobj);
	obj_dec(tempobj);
	started = 1;

	/* now read in the command line files */
	user_read(argc, argv);

	start_execution();

	/* print out one last newline - to move everything out of output
	queue */
	sassign(tempobj, new_sym("\n"));
	primitive(SYMPRINT, 1, &tempobj);
	obj_dec(tempobj);

	/* now free things up, hopefully keeping ref counts straight */

	drv_free();

	flush_processes();

	free_low_nums();

	obj_dec((object *) Array);
	obj_dec((object *) ArrayedCollection);

	free_all_classes();
	
	obj_dec(o_tab);
	obj_dec(o_drive);
	obj_dec(o_magnitude);
	obj_dec(o_number);
	obj_dec(o_nil);
	obj_dec(o_false);
	obj_dec(o_true);
	obj_dec(o_object);
	obj_dec(o_empty);
	obj_dec(o_smalltalk);
	obj_dec(o_acollection);

	if (! silence)
		fprintf(stderr,"incs %u decs %u difference %d allocs %d\n", 
			n_incs, n_decs, n_incs - n_decs, n_mallocs);
	if (prallocs) {
		fprintf(stderr,"blocks allocated %d\n", ca_block);
		fprintf(stderr,"bytearrays allocated %d\n", ca_barray);
		fprintf(stderr,"classes allocated %d\n", ca_class);
		fprintf(stderr,"interpreters allocated %d\n", ca_terp);
		fprintf(stderr,"ints allocated %d\n", ca_int);
		fprintf(stderr,"floats allocated %d\n", ca_float);
		fprintf(stderr,"strings allocated %d\n", ca_str);
		fprintf(stderr,"symbols allocated %d\n", ca_sym);
		fprintf(stderr,"class entryies %d\n", ca_cdict);
		fprintf(stderr,"wallocs %d\n", ca_wal);
		fprintf(stderr,"wtop %d\n", wtop);
		fprintf(stderr,"byte table top %d\n", btabletop);
		fprintf(stderr,"smalltalk objects allocated %d\n", ca_obj);
		for (i = 0; i < 5; i++)
			fprintf(stderr,"size %d objects %d\n", i, ca_cobj[i]);
	}
	clean_files();
	exit(0);	/* say good by gracie */
}

/* dofast - do a fast load of the standard prelude */
static dofast() {
	char buffer[100];

	sprintf(buffer,")l %s\n", FAST);
	dolexcommand(buffer);
}

/* null_class - create a null class for bootstrapping purposes */
static class *null_class(name)
char *name;
{	class *new, *new_class();

	new = new_class();
	assign(new->class_name, new_sym(name));
	enter_class(name, (object *) new);
	return(new);
}

/* user_read - read the user command line arguments */
static user_read(argc, argv)
int argc;
char **argv;
{	int i, count;
	char buffer[100];
	char name[100];
	FILE *fd = 0;

	gettemp(name);
	count = 0;
	fd = fopen(name, "w");
	if (fd == NULL)
		cant_happen(22);
	for (i = 1; i < argc; i++)
		if (argv[i][0] == '-') {
			switch(argv[i][1]) {
				case 'a':
					prallocs = 1; break;
				case 'l':
					sprintf(buffer,")l %s\n", argv[++i]);
					count++;
					fputs(buffer, fd);
					break;
				case 'd':
					prntcmd = argv[i][1] - '0';
					break;
				case 'r':
					sprintf(buffer,")r %s\n", argv[++i]);
					count++;
					fputs(buffer, fd);
					break;
				case 's':
					silence = 1;
					break;
				}
			}
		else {
			sprintf(buffer,")i %s\n", argv[i]);
			count++;
			fputs(buffer, fd);
			}
	fclose(fd);
	if (count) {
		fd = fopen(name, "r");
		if (fd == NULL)
			cant_happen(22);
		set_file(fd);
		}
}

/* gettemp makes a temp file name that can be deleted when finished */
static char c = 'a';
gettemp(buffer)
char *buffer;
{
	sprintf(buffer,"%s%c", filebase, c++);
	if (c > 'z') c = 'a';	/* wrap around forever */
}

/* clean_files - delete all temp files created */
static clean_files()
{
	char buffer[100];

# ifndef NOSYSTEM
	sprintf(buffer,"rm -f %s*", filebase);
	system(buffer);
# endif
}
SHAR_EOF
if test 8245 -ne "`wc -c < 'sources/main.c'`"
then
	echo shar: error transmitting "'sources/main.c'" '(should have been 8245 characters)'
fi
fi # end of overwriting check
if test -f 'sources/number.c'
then
	echo shar: will not over-write existing file "'sources/number.c'"
else
cat << \SHAR_EOF > 'sources/number.c'
/*
	Little Smalltalk

		number definitions
		timothy a. budd, 10/84
*/
/*
	The source code for the Little Smalltalk System may be freely
	copied provided that the source of all files is acknowledged
	and that this condition is copied with each file.

	The Little Smalltalk System is distributed without responsibility
	for the performance of the program and without any guarantee of
	maintenance.

	All questions concerning Little Smalltalk should be addressed to:

		Professor Tim Budd
		Department of Computer Science
		The University of Arizona
		Tucson, Arizona
		85721
		USA
*/
# include <stdio.h>
# include "object.h"
# include "number.h"

# define MAXLOW 100	/* maximum low numbers kept */

static integer *low_nums[MAXLOW];  /* better be initialized to zero ! */

static mstruct *fr_integer = 0;
static mstruct *fr_float = 0;

static integer init_itable[INTINITMAX];

int_init() {
	integer *p;
	mstruct *new;
	int i;

	for (p = init_itable, i = 0; i < INTINITMAX; i++, p++) {
		new = (mstruct *) p;
		new->mlink = fr_integer;
		/*fprintf(stderr,"init int %d %d\n", new, new->mlink);*/
		fr_integer = new;
		}
}

int ca_int = 0;	/* count the number of integer allocations */

extern object *o_magnitude;
extern object *o_number;

/* new_cori - new character or integer */
object *new_cori(val, type)
int val, type;
{	register integer *new;

	if ((type == 1) && (val >= 0 && val < MAXLOW) && low_nums[val])
		return( (struct obj_struct *) low_nums[val]);

	if (fr_integer) {
		new = (integer *) fr_integer;
		/*fprintf(stderr,"int off list %d %d\n", fr_integer,
		fr_integer->mlink);*/
		fr_integer = fr_integer->mlink;
		}
	else {
		new = structalloc(integer);
		/*fprintf(stderr,"allocating new int %d\n", new);*/
		ca_int++;
		}

	new->i_ref_count = 0;
	new->i_value = val;
	switch(type) {
		case 0: /* chars */
			new->i_size = CHARSIZE;
		  	break;

		case 1: /* integers */
			new->i_size = INTEGERSIZE;
			if (val >= 0 && val < MAXLOW)
				sassign(low_nums[val], new);
		  	break;

		default: cant_happen(5);
		}
	return ((object *) new);
}

free_integer(i)
integer *i;
{
	if ((! is_integer(i)) && (! is_character(i)))
		cant_happen(8);
	((mstruct *) i)->mlink = fr_integer;
	fr_integer = (mstruct *) i;
	/*fprintf(stderr,"freeing integer %d %d\n", fr_integer,
	fr_integer->mlink);*/
}

free_low_nums()
{	int i;

	for (i = 0; i < MAXLOW; i++)
		if (low_nums[i]) {
			obj_dec((object *) low_nums[i]);
			low_nums[i] = (integer *) 0;
			}
}

int ca_float = 0;

/* new_float - produce a new floating point number */
object *new_float(val)
double val;
{	register sfloat *new;

	if (fr_float) {
		new = (sfloat *) fr_float;
		fr_float = fr_float->mlink;
		}
	else {
		new = structalloc(sfloat);
		ca_float++;
		}

	new->f_ref_count = 0;
	new->f_size = FLOATSIZE;
	new->f_value = val;
	return( (object *) new);
}

free_float(f)
sfloat *f;
{
	if (! is_float(f))
		cant_happen(8);
	((mstruct *) f)->mlink = fr_float;
	fr_float = (mstruct *) f;
}
SHAR_EOF
if test 2951 -ne "`wc -c < 'sources/number.c'`"
then
	echo shar: error transmitting "'sources/number.c'" '(should have been 2951 characters)'
fi
fi # end of overwriting check
if test -f 'sources/number.h'
then
	echo shar: will not over-write existing file "'sources/number.h'"
else
cat << \SHAR_EOF > 'sources/number.h'
/*
	Little Smalltalk number definitions

*/
/* 
	integer and character definitions
	for integers
		i_size = INTEGERSIZE

	for characters
		i_size = CHARSIZE

*/

struct int_struct {
        int     i_ref_count;
	int     i_size;
	int	i_value;
	};

typedef struct int_struct integer;

# define int_value(x) (((integer *)x)->i_value)
# define char_value(x) ((char) int_value(x))

extern object *new_cori();	/* new Character OR Integer */

# define new_int(x) new_cori(x, 1)
# define new_char(x) new_cori(x, 0)

# define INTINITMAX 50

/*
	floating point definitions
	size should always be FLOATSIZE
*/

struct float_struct {
	int	f_ref_count;
	int	f_size;
	double	f_value;
	};

typedef struct float_struct sfloat;

# define float_value(x) (((sfloat *)x)->f_value)

extern object *new_float();
SHAR_EOF
if test 790 -ne "`wc -c < 'sources/number.h'`"
then
	echo shar: error transmitting "'sources/number.h'" '(should have been 790 characters)'
fi
fi # end of overwriting check
if test -f 'sources/object.c'
then
	echo shar: will not over-write existing file "'sources/object.c'"
else
cat << \SHAR_EOF > 'sources/object.c'
/*
        Little Smalltalk

        	object memory management

		timothy a. budd, 10/84
*/
/*
	The source code for the Little Smalltalk System may be freely
	copied provided that the source of all files is acknowledged
	and that this condition is copied with each file.

	The Little Smalltalk System is distributed without responsibility
	for the performance of the program and without any guarantee of
	maintenance.

	All questions concerning Little Smalltalk should be addressed to:

		Professor Tim Budd
		Department of Computer Science
		The University of Arizona
		Tucson, Arizona
		85721
		USA
*/
# include <stdio.h>
# include "object.h"
# include "drive.h"
# include "string.h"
# include "symbol.h"
# include "byte.h"
# include "number.h"
# include "interp.h"
# include "process.h"
# include "block.h"
# include "file.h"
# include "primitive.h"

# define DEBUG 0

extern object *o_acollection;

int n_incs = 0;		/* number of increments counter */
int n_decs = 0;		/* number of decrements counter (should be equal)*/
int n_mallocs = 0;	/* number of mallocs counter */

/* o_alloc - allocate a block of memory, checking for end of memory */
char *o_alloc(n)
unsigned n;
{  char *p, *malloc();

   p = malloc(n);
   if (p == (char *) 0) cant_happen(1);	/* out of memory */
   n_mallocs++;
   return(p);
}

#ifndef INLINE

/* obj_inc - increment an object (usually expanded in-line) */
obj_inc(x) 
register object *x;
{
	x->ref_count++;
	n_incs++;
}

/* obj_dec - decrement an object (usually half expanded in-line) */
obj_dec(x) 
object *x;
{
	n_decs++;
	if (--(x->ref_count) > 0) return;
# endif
# ifdef INLINE
ob_dec(x)
object *x;
{
# endif
	if (x->ref_count < 0) {
		fprintf(stderr,"ref count %d %d\n", x->ref_count, x);
		x->ref_count /= 0;
		primitive(REFCOUNTERROR, 1, &x);
		return;
		}
	if (is_bltin(x)) {	/* free a built-in object */
		switch(x->size) {
			case BLOCKSIZE:
				free_block(x); break;
			case BYTEARRAYSIZE:
				free_bytearray((bytearray *) x); break;
			case CLASSSIZE : 
				free_class((class *) x); break;
			case FILESIZE:
				free_file((struct file_struct *) x);
				break;
			case FLOATSIZE:
				free_float((sfloat *) x); break;
			case INTEGERSIZE: case CHARSIZE:
				free_integer((integer *) x); break;
			case INTERPSIZE:
				free_terpreter((interpreter *) x); break;
			case PROCSIZE:
				free_process((process *) x); break;
			case SYMBOLSIZE: 
				cant_happen(16);
			case STRINGSIZE:
				free_string((string *) x); break;
			default: cant_happen(6);
			}
		}
	else {		/* free a normal (non-special) object */
		if (x->super_obj)
			obj_dec(x->super_obj);
		free_obj(x, 1);
		}
}

# define MAXOBJLIST 100
# define sizeobj(x) (sizeof(object) + ((x) - 1) * sizeof(object *) )

/* obj_free_list is a free list for memory blocks */

static object *obj_free_list[MAXOBJLIST]; /* better be initialized to zero! */

int ca_obj = 0;			/* count the number of allocations made */
int ca_cobj[5] = {0,0,0,0,0};	/* count how many allocations for small vals*/

/* make sure the following list is null terminated! */
int size_obj_init[] = {15, 75, 420, 10, 10, 5, 0};

/* init_objs - initialize the memory management module */
init_objs() {
	int i, j, max, size;
	char *p;
	object *new;

	for (i = 0; (max = size_obj_init[i]); i++) {
		size = sizeobj(i);
		p = o_alloc((unsigned int) (max * size));
		for (j = 0; j < max; j++) {
			new = (object *) p;
			new->super_obj = obj_free_list[i];
			obj_free_list[i] = new;
			p += size;
			}
		}
}

/* new_obj - create a new non-special object */
object *new_obj(nclass, nsize, alloc)
class *nclass;
int nsize, alloc;
{	register object *new;
	int i;
	
	if (nsize < 0)
		cant_happen(2);
	if (nsize < MAXOBJLIST && obj_free_list[nsize])
		obj_free_list[nsize] = (new = obj_free_list[nsize])->super_obj;
	else {
		new = (object *) o_alloc(sizeobj(nsize));
		ca_obj++;
		if (nsize < 5)
			ca_cobj[nsize]++;
	}
	new->super_obj = (object *) 0;
	new->class = nclass;
	if (nclass)
		obj_inc((object *) new->class );
	new->ref_count = 0;
	new->size = nsize;
	if (alloc)
		for (i = 0; i < nsize; i++) {
			sassign(new->inst_var[ i ], o_nil);
		 }	
	return(new);
}
	
/* free_obj - free a non-special object */
free_obj(obj, dofree)
register object *obj;
int    dofree;
{	int size, i;

	size = obj->size;
	if (dofree)
		for (i = 0; i < size; i++)
			obj_dec(obj->inst_var[i]);
	if (obj->class)
		obj_dec((object *) obj->class);
	if (size < MAXOBJLIST) {
		obj->super_obj = obj_free_list[size];
		obj_free_list[size] = obj;
		}
	else {
		free(obj);
      		}
}

/* fnd_class - find the class of a special object */
object *fnd_class(anObject)
object *anObject;
{	object *result, *lookup_class();
	char *name;

	if (is_bltin(anObject)) {
		switch(anObject->size) {
			case BLOCKSIZE:   name = "Block"; break; 
			case CLASSSIZE:   name = "Class"; break;
			case FILESIZE:    name = "File"; break;
			case FLOATSIZE:   name = "Float"; break;
			case INTEGERSIZE: name = "Integer"; break;
			case CHARSIZE:    name = "Char"; break;
			case INTERPSIZE:  name = "Interp"; break;
			case PROCSIZE:    name = "Process"; break;
			case SYMBOLSIZE:  name = "Symbol"; break;
			case STRINGSIZE:  name = "String"; break;
			case BYTEARRAYSIZE: name = "ByteArray"; break;
			default: cant_happen(6);
			}
		result = lookup_class(name);
		}
	else
		result = (object *) anObject->class;
	return(result);
}

extern object *o_object, *o_magnitude, *o_number;

/* fnd_super - produce a super-object for a special object */
object *fnd_super(anObject)
object *anObject;
{	object *result;

	if (is_bltin(anObject)) {
		switch(anObject->size) {
			case BLOCKSIZE:   result = o_object; break;
			case CLASSSIZE:   result = o_object; break;
			case FILESIZE:    result = o_object; break;
			case FLOATSIZE:   result = o_number; break;
			case INTEGERSIZE: result = o_number; break;
			case CHARSIZE:    result = o_magnitude; break;
			case INTERPSIZE:  result = o_object; break;
			case PROCSIZE:    result = o_object; break;
			case SYMBOLSIZE:  result = o_object; break;
			case STRINGSIZE:   /* strings DO have superobjs*/
				result = ((string *) anObject)->s_super_obj; 
				break;
			case BYTEARRAYSIZE: result = o_acollection; break;
			default: cant_happen(6);
			}
		}
	else
		result = anObject->super_obj;
	return(result);
}
SHAR_EOF
if test 6270 -ne "`wc -c < 'sources/object.c'`"
then
	echo shar: error transmitting "'sources/object.c'" '(should have been 6270 characters)'
fi
fi # end of overwriting check
if test -f 'sources/object.h'
then
	echo shar: will not over-write existing file "'sources/object.h'"
else
cat << \SHAR_EOF > 'sources/object.h'
/*
        Little Smalltalk object definitions
*/
# include "env.h"
/*
	for objects the inst_var array is actually made as large as
	necessary (as large as the size field).  since C does not do
	subscript bounds checking array indexing can be used
*/

struct obj_struct {
        int                   ref_count;
	int                   size;
        struct class_struct   *class;
        struct obj_struct     *super_obj;
        struct obj_struct     *inst_var[1];
        };

/*
	for classes
		c_size = CLASSSIZE

		class_name and super_class should be SYMBOLs
		containing the names of the class and superclass,
		respectively.

		c_inst_vars should be an array of symbols, containing the
		names of the instance variables

		context size is the size of the context that should be
		created each time a message is sent to objects of this
		class.

		message_names should be an array of symbols, corresponding
		to the messages accepted by objects of this class.

		methods should be an array of arrays, each element being a
		two element array of bytecodes and literals.
*/

struct class_struct {
	int			c_ref_count;
	int			c_size;
	struct obj_struct	*class_name;
	struct obj_struct	*super_class;
	struct obj_struct	*file_name;
	struct obj_struct	*c_inst_vars;
	int			context_size;
	struct obj_struct	*message_names;
	struct obj_struct	*methods;
	int			stack_max;
	};

typedef struct class_struct class;
typedef struct obj_struct object;

/*
	objects with non-object value (classes, integers, etc) have a
	negative size field, the particular value being used to indicate
	the type of object (the class field cannot be used for this purpose
	since all classes, even those for built in objects, can be redefined)

	check_bltin is a macro that tests the size field for a particular
	value.  it is used to define other macros, such as is_class, that
	test each particular type of object.

	The following classes are builtin

		Block
		ByteArray
		Char 
		Class
		Float
		Integer
		Interpreter
		String
		Symbol
*/

# define BLOCKSIZE 	-83
# define BYTEARRAYSIZE 	-567
# define CHARSIZE 	-33
# define CLASSSIZE 	-3
# define FILESIZE 	-5
# define FLOATSIZE 	-31415
# define INTEGERSIZE 	-17
# define INTERPSIZE 	-15
# define PROCSIZE  	-100
# define STRINGSIZE 	-258
# define SYMBOLSIZE 	-14

# define is_bltin(x) (x && (((object *) x)->size < 0))
# define check_bltin(obj, type) (obj && (((object *) obj)->size == type))

# define is_block(x)		check_bltin(x, BLOCKSIZE)
# define is_bytearray(x)	check_bltin(x, BYTEARRAYSIZE)
# define is_character(x)	check_bltin(x, CHARSIZE)
# define is_class(x)		check_bltin(x, CLASSSIZE)
# define is_file(x)		check_bltin(x, FILESIZE)
# define is_float(x)		check_bltin(x, FLOATSIZE)
# define is_integer(x)		check_bltin(x, INTEGERSIZE)
# define is_interpreter(x)	check_bltin(x, INTERPSIZE)
# define is_process(p)	 	check_bltin(p, PROCSIZE)
# define is_string(x)		check_bltin(x, STRINGSIZE)
# define is_symbol(x)		check_bltin(x, SYMBOLSIZE)

/*
	mstruct is used (via casts) to store linked lists of structures of
	various types for memory saving and recovering
*/

struct mem_struct {
	struct mem_struct *mlink;
	};

typedef struct mem_struct mstruct;

/*
	sassign assigns val to obj, which should not have a valid
	value in it already.
	assign decrements an existing val field first, then assigns.
	note this will not work for assign(x,x) if x ref count is 1.
	safeassign, although producing less efficient code, will work even
	in this case
*/
# define sassign(obj, val) obj_inc((object *) (obj = val))
# define assign(obj, val)  {obj_dec((object *) obj); sassign(obj, val);}
# define safeassign(obj, val) {obj_inc((object *) val); \
	obj_dec((object *) obj); obj = val; }

/* structalloc calls alloc to allocate a block of memory 
   for a structure and casts the returned
   pointer to the appropriate type */
# define structalloc(type) (type *) o_alloc(sizeof(type))

/*
	if INLINE is defined ( see env.h ) , inline code will be generated 
	for object increments.  inline code is generally faster, but
	larger than using subroutine calls for incs and decs
*/

extern int  n_incs, n_decs;

# ifdef INLINE

# define obj_inc(x) n_incs++, (x)->ref_count++
extern object *_dx;
# define obj_dec(x) {n_decs++; if (--((_dx=x)->ref_count) <= 0) ob_dec(_dx);}

# endif

extern char   *o_alloc();	/* allocate a block of memory */
extern object *new_inst();	/* make a new instance of a class */
extern object *new_sinst();	/* an internal (system) version of new_inst*/
extern object *new_obj();	/* allocate a new object */
extern object *new_array();	/* make a new array */
extern object *primitive();	/* perform a primitive operation */
 
extern object *o_nil;		/* current value of pseudo variable nil */
extern object *o_true;		/* current value of pseudo variable true */
extern object *o_false;		/* current value of pseudo variable false */
extern object *o_smalltalk;	/* current value of pseudo var smalltalk */

extern int debug;		/* debugging toggle */

/* reference count macro, used during debugging */
# define rc(x) ((object *)x)->ref_count
SHAR_EOF
if test 5074 -ne "`wc -c < 'sources/object.h'`"
then
	echo shar: error transmitting "'sources/object.h'" '(should have been 5074 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0