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