home *** CD-ROM | disk | FTP | other *** search
- /* dldmem - xlisp dynamic memory management routines */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- /* Modified memory management scheme such that array/string space is
- managed here rather than using malloc/free. The advantage of this is
- the array/string space gets compacted allowing better operation when
- available memory is tight or virtual memory is used. XSCHEME does this,
- but probably needs it more since Xscheme functions are kept as compiled
- code in arrays rather than lists. */
-
- /* When this module is used rather than xldmem (and dlimage is used rather
- than xlimage) then ALLOC and EXPAND take an additional second argument
- for array segment allocation size and array segments to add, respectively.
- The ROOM report is changed to indicate array allocation statistics. */
-
-
- #include "xlisp.h"
-
- /* node flags */
- #define MARK 0x20
- #define LEFT 0x40
-
- /* macro to compute the size of a segment */
- #define segsize(n) (sizeof(SEGMENT)+((n)-1)*sizeof(struct node))
-
- /* external variables */
- extern LVAL obarray,s_gcflag,s_gchook,s_unbound,s_debugio,true;
- extern LVAL xlenv,xlfenv,xldenv;
-
- /* For vector memory management */
- #define vsegsize(n) (sizeof(VSEGMENT)+((n)-1)*sizeof(LVAL))
-
- #define btow_size(n) (((unsigned)(n)+(sizeof(LVAL)-1))/(unsigned)sizeof(LVAL))
-
- typedef struct vsegment {
- struct vsegment XFAR *vs_next; /* next vector segment */
- LVAL XFAR *vs_free; /* next free location in this segment */
- LVAL XFAR *vs_top; /* top of segment (plus one) */
- LVAL vs_data[1]; /* segment data */
- } VSEGMENT;
-
- VSEGMENT XFAR *vsegments; /* list of vector segments */
- VSEGMENT XFAR *vscurrent; /* current vector segment */
- int vscount; /* number of vector segments */
- LVAL XFAR *vfree; /* next free location in vector space */
- LVAL XFAR *vtop; /* top of vector space */
-
-
- /* variables local to xldmem.c and xlimage.c */
- SEGMENT XFAR *segs, XFAR *lastseg, XFAR *fixseg, XFAR *charseg;
- int anodes,vnodes,nsegs;
- long gccalls;
- long nnodes,nfree,total;
- long vsfree;
- LVAL fnodes;
-
- /* forward declarations */
- #ifdef ANSI
- void XNEAR compact_vector(VSEGMENT XFAR *vseg);
- void XNEAR compact(void);
- LVAL XNEAR allocvector(int type, unsigned int size);
- VSEGMENT XFAR* newvsegment(unsigned int n);
- #ifdef JMAC
- LVAL XNEAR Newnode(int type);
- #else
- LVAL XNEAR newnode(int type);
- #endif
- VOID XNEAR mark(LVAL ptr);
- VOID XNEAR sweep(void);
- VOID XNEAR findmem(void);
- int XNEAR addseg(void);
- int scanvmemory(unsigned int size);
- #else
- FORWARD VOID compact_vector();
- FORWARD VSEGMENT *newvsegment();
- FORWARD VOID compact();
- FORWARD LVAL allocvector();
- #ifdef JMAC
- FORWARD LVAL Newnode();
- #else
- FORWARD LVAL newnode();
- #endif
- FORWARD VOID mark();
- FORWARD VOID sweep();
- FORWARD VOID findmem();
- #endif
-
- #ifdef JMAC
- LVAL _nnode = NIL;
- FIXTYPE _tfixed = 0;
- int _tint = 0;
-
- #define newnode(type) (((_nnode = fnodes) != NIL) ? \
- ((fnodes = cdr(_nnode)), \
- nfree--, \
- (_nnode->n_type = type), \
- rplacd(_nnode,NIL), \
- _nnode) \
- : Newnode(type))
-
- #endif
-
-
- /* xlminit - initialize the dynamic memory module */
- VOID xlminit()
- {
- LVAL p;
- int i;
-
- /* initialize our internal variables */
- segs = lastseg = NULL;
- nnodes = nfree = total = gccalls = 0L;
- nsegs = 0;
- anodes = NNODES;
- vnodes = VSSIZE;
- fnodes = NIL;
-
- /* initialize vector space */
- vsegments = vscurrent = NULL;
- vscount = 0;
- vfree = vtop = NULL;
-
- /* allocate the fixnum segment */
- if ((fixseg = newsegment(SFIXSIZE)) == NULL)
- xlfatal("insufficient memory");
-
- /* initialize the fixnum segment */
- p = &fixseg->sg_nodes[0];
- for (i = SFIXMIN; i <= SFIXMAX; ++i) {
- p->n_type = FIXNUM;
- p->n_fixnum = i;
- ++p;
- }
-
- /* allocate the character segment */
- if ((charseg = newsegment(CHARSIZE)) == NULL)
- xlfatal("insufficient memory");
-
- /* initialize the character segment */
- p = &charseg->sg_nodes[0];
- for (i = CHARMIN; i <= CHARMAX; ++i) {
- p->n_type = CHAR;
- p->n_chcode = i;
- ++p;
- }
-
- /* initialize structures that are marked by the collector */
- obarray = NULL; /* will be set to LVAL later */
- xlenv = xlfenv = xldenv = NIL; /* list heads, initially NIL */
- s_gcflag = s_gchook = NULL; /* will be set to lval later */
-
- /* allocate the evaluation stack */
- xlstack = xlstktop;
-
- /* allocate the argument stack */
- xlfp = xlsp = xlargstkbase;
- *xlsp++ = NIL;
-
- /* we have to make a NIL symbol before continuing */
- {
- LVAL XFAR *vdata;
- p = xlmakesym("NIL");
- MEMCPY(NIL, p, sizeof(struct node)); /* we point to this! */
- defconstant(NIL, NIL);
- p->n_type = FREE; /* don't collect "garbage" */
- vdata = p->n_vdata; /* correct ptr for compress */
- *--vdata = NIL;
- }
-
- }
-
- /* cons - construct a new cons node */
- LVAL cons(x,y)
- LVAL x,y;
- {
- LVAL nnode;
-
- /* get a free node */
- if ((nnode = fnodes) == NIL) {
- xlstkcheck(2);
- xlprotect(x);
- xlprotect(y);
- findmem();
- if ((nnode = fnodes) == NIL)
- xlabort("insufficient node space");
- xlpopn(2);
- }
-
- /* unlink the node from the free list */
- fnodes = cdr(nnode);
- --nfree;
-
- /* initialize the new node */
- nnode->n_type = CONS;
- rplaca(nnode,x);
- rplacd(nnode,y);
-
- /* return the new node */
- return (nnode);
- }
-
- /* cvstring - convert a string to a string node */
- LVAL cvstring(str)
- char XFAR *str;
- {
- LVAL val;
- val = newstring(STRLEN(str));
- STRCPY(getstring(val),str);
- return (val);
- }
-
- /* newstring - allocate and initialize a new string */
- LVAL newstring(size)
- unsigned size;
- {
- LVAL val;
- val = allocvector(STRING,btow_size(size+1));
- val->n_strlen = size;
- return (val);
- }
-
- /* cvsymbol - convert a string to a symbol */
- LVAL cvsymbol(pname)
- char *pname;
- {
- LVAL val;
- xlsave1(val);
- val = allocvector(SYMBOL,SYMSIZE);
- setvalue(val,s_unbound);
- setfunction(val,s_unbound);
- setpname(val,cvstring(pname));
- xlpop();
- return (val);
- }
-
- /* cvsubr - convert a function to a subr or fsubr */
- #ifdef ANSI
- LVAL cvsubr(LVAL (*fcn)(void), int type, int offset)
- #else
- LVAL cvsubr(fcn,type,offset)
- LVAL (*fcn)(); int type,offset;
- #endif
- {
- LVAL val;
- val = newnode(type);
- val->n_subr = fcn;
- val->n_offset = offset;
- return (val);
- }
-
- /* cvfile - convert a file pointer to a stream */
- LVAL cvfile(fp, iomode)
- FILEP fp;
- int iomode;
- {
- LVAL val;
- val = newnode(STREAM);
- setfile(val,fp);
- setsavech(val,'\0');
- val->n_sflags = iomode;
- val->n_cpos = 0;
- return (val);
- }
-
- #ifdef JMAC
-
- /* cvfixnum - convert an integer to a fixnum node */
- LVAL Cvfixnum(n)
- FIXTYPE n;
- {
- LVAL val;
- val = newnode(FIXNUM);
- val->n_fixnum = n;
- return (val);
- }
- #else
- /* cvfixnum - convert an integer to a fixnum node */
- LVAL cvfixnum(n)
- FIXTYPE n;
- {
- LVAL val;
- if (n >= SFIXMIN && n <= SFIXMAX)
- return (&fixseg->sg_nodes[(int)n-SFIXMIN]);
- val = newnode(FIXNUM);
- val->n_fixnum = n;
- return (val);
- }
- #endif
-
- #ifdef RATIOS
- /* cvratio - convert an integer pair to a ratio node */
- LVAL cvratio(num, denom)
- FIXTYPE num, denom;
- {
- LVAL val;
- FIXTYPE n, m, r;
-
- if (num == 0) return cvfixnum((FIXTYPE) 0); /* zero is int zero */
- if (denom < 0) { /* denominator must be positive */
- denom = -denom;
- num = -num;
- }
- if ((n = num) < 0) n = -n;
- m = denom; /* reduce the ratio: compute GCD */
- for (;;) {
- if ((r = m % n) == 0) break;
- m = n;
- n = r;
- }
- if (n != 1) {
- denom /= n;
- num /= n;
- }
- if (denom == 1) return cvfixnum(num); /* reduced to integer */
- val = newnode(RATIO);
- val->n_denom = denom;
- val->n_numer = num;
- return (val);
- }
- #endif
-
- /* cvflonum - convert a floating point number to a flonum node */
- LVAL cvflonum(n)
- FLOTYPE n;
- {
- LVAL val;
- val = newnode(FLONUM);
- val->n_flonum = n;
- return (val);
- }
-
- /* cvchar - convert an integer to a character node */
- #ifdef JMAC
- LVAL Cvchar(n)
- int n;
- {
- xlerror("character code out of range",cvfixnum((FIXTYPE)n));
- return (NIL); /* never really returns */
- }
- #else
- LVAL cvchar(n)
- int n;
- {
- #if (CHARMIN == 0) /* TAA MOD eliminating a comparison */
- if (((unsigned)n) <= CHARMAX)
- #else
- if (n >= CHARMIN && n <= CHARMAX)
- #endif
- return (&charseg->sg_nodes[n-CHARMIN]);
- xlerror("character code out of range",cvfixnum((FIXTYPE)n));
- return (NIL); /* never really returns */
- }
- #endif
-
- /* newustream - create a new unnamed stream */
- LVAL newustream()
- {
- LVAL val;
- val = newnode(USTREAM);
- sethead(val,NIL);
- settail(val,NIL);
- return (val);
- }
-
- /* newobject - allocate and initialize a new object */
- LVAL newobject(cls,size)
- LVAL cls; int size;
- {
- LVAL val;
- val = allocvector(OBJECT,size+1);
- setelement(val,0,cls);
- return (val);
- }
-
- /* newclosure - allocate and initialize a new closure */
- LVAL newclosure(name,type,env,fenv)
- LVAL name,type,env,fenv;
- {
- LVAL val;
- val = allocvector(CLOSURE,CLOSIZE);
- setname(val,name);
- settype(val,type);
- setenvi(val,env);
- setfenv(val,fenv);
- return (val);
- }
-
- /* newstruct - allocate and initialize a new structure node */
- LVAL newstruct(type,size)
- LVAL type; int size;
- {
- LVAL val;
- val = allocvector(STRUCT,size+1);
- setelement(val,0,type);
- return (val);
- }
-
-
- /* newvector - allocate and initialize a new vector */
- LVAL newvector(size)
- unsigned size;
- {
- return (allocvector(VECTOR,size));
- }
-
-
- /* getvused - get used vector space */
- /* also sets vsfree to free space */
- #ifdef ANSI
- static long XNEAR getvused(void)
- #else
- LOCAL long getvused()
- #endif
- {
- long vnu=0L;
- VSEGMENT XFAR *vseg;
-
- vsfree = 0L;
-
- if (vscurrent != NULL)
- vscurrent->vs_free = vfree;
- for (vseg = vsegments; vseg != NULL; vseg = vseg->vs_next) {
- vnu += ((long)vseg->vs_free - (long)&vseg->vs_data[0])/sizeof(LVAL XFAR *);
- vsfree += ((long)vseg->vs_top - (long)vseg->vs_free)/sizeof(LVAL XFAR *);
- }
- return vnu;
- }
-
-
- /* allocvector - allocate and initialize a new vector node */
- LOCAL LVAL XNEAR allocvector(type,size)
- int type;
- unsigned size;
- {
- LVAL val, XFAR *p;
- unsigned int i;
-
- if (size+1 > MAXVLEN) xlfail("array too large");
-
- xlsave1(val);
- val = newnode(type);
-
- /* initialize the vector node */
- val->n_type = type;
- val->n_vsize = size;
- val->n_vdata = NULL;
-
- /* add space for the backpointer */
- ++size;
-
- /* make sure there's enough space */
- if (((unsigned)vtop-(unsigned)vfree < size*sizeof(LVAL XFAR *)) &&
- !scanvmemory(size)) {
- gc(); /* try cleaning up and scanning again */
- getvused(); /* calculate free and used space */
- if (!scanvmemory(size) || vsfree < vnodes)
- newvsegment(size); /* no memory -- allocate segment */
- if ((unsigned)vtop-(unsigned)vfree < size*sizeof(LVAL XFAR *))
- xlabort("insufficient vector space");
- }
-
- /* allocate the next available block */
- p = vfree;
- vfree += size;
-
- /* store the backpointer */
- *p++ = val;
- val->n_vdata = p;
-
- /* set all the elements to NIL, except for STRINGs */
- if (type != STRING) for (i = size; i > 1; --i) *p++ = NIL;
-
- /* return the new vector */
- xlpop();
- return (val);
- }
-
- /* scanvmemory - look for vector segment with enough space */
- /* return success */
- int scanvmemory(size)
- unsigned int size;
- {
- VSEGMENT XFAR *vseg;
- if (vscurrent != NULL)
- vscurrent->vs_free = vfree;
- for (vseg = vsegments; vseg != NULL; vseg = vseg->vs_next)
- if ((unsigned)vseg->vs_top - (unsigned)vseg->vs_free >
- size*sizeof(LVAL XFAR *)) {
- vfree = vseg->vs_free;
- vtop = vseg->vs_top;
- vscurrent = vseg;
- return TRUE;
- }
- return FALSE;
- }
-
- /* newvsegment - create a new vector segment */
- VSEGMENT XFAR *newvsegment(n)
- unsigned int n;
- {
- VSEGMENT XFAR *newseg;
- long reqsize;
-
- if (n < vnodes) n = vnodes; /* allocate vnodes if larger than request */
-
-
- reqsize = vsegsize((long)n);
-
- if ((unsigned int)reqsize != reqsize) return NULL; /* can't do it */
-
- /* allocate the new segment */
- if ((newseg = (VSEGMENT XFAR *)MALLOC((unsigned int)reqsize)) == NULL)
- return (NULL);
-
- if (vscurrent != NULL)
- vscurrent->vs_free = vfree;
-
- /* initialize the new segment */
- vfree = newseg->vs_free = &newseg->vs_data[0];
- vtop = newseg->vs_top = newseg->vs_free + n;
- newseg->vs_next = vsegments;
- vscurrent = vsegments = newseg;
-
- /* update the statistics */
- total += reqsize;
- ++vscount;
-
- /* return the new segment */
- return (newseg);
- }
-
- /* newnode - allocate a new node */
- #ifdef JMAC
- LOCAL LVAL XNEAR Newnode(type)
- int type;
- {
- LVAL nnode;
-
- /* get a free node */
- findmem();
- if ((nnode = fnodes) == NIL)
- xlabort("insufficient node space");
-
- /* unlink the node from the free list */
- fnodes = cdr(nnode);
- nfree -= 1L;
-
- /* initialize the new node */
- nnode->n_type = type;
- rplacd(nnode,NIL);
-
- /* return the new node */
- return (nnode);
- }
- #else
- LOCAL LVAL XNEAR newnode(type)
- int type;
- {
- LVAL nnode;
-
- /* get a free node */
- if ((nnode = fnodes) == NIL) {
- findmem();
- if ((nnode = fnodes) == NIL)
- xlabort("insufficient node space");
- }
-
- /* unlink the node from the free list */
- fnodes = cdr(nnode);
- nfree -= 1L;
-
- /* initialize the new node */
- nnode->n_type = type;
- rplacd(nnode,NIL);
-
- /* return the new node */
- return (nnode);
- }
- #endif
-
- /* findmem - find more memory by collecting then expanding */
- LOCAL VOID XNEAR findmem()
- {
- gc();
- if (nfree < (long)anodes)
- addseg();
- }
-
- /* gc - garbage collect (only called here and in xlimage.c) */
- VOID gc()
- {
- LVAL **p,*ap,tmp;
- FRAMEP newfp;
- LVAL fun;
-
- /* print the start of the gc message */
- if (s_gcflag!=NULL && getvalue(s_gcflag) != NIL) {
- /* print message on a fresh line */
- xlfreshline(getvalue(s_debugio));
- sprintf(buf,"[ gc: total %ld, ",nnodes);
- dbgputstr(buf); /* TAA MOD -- was std output */
- }
-
- /* mark the obarray, the argument list and the current environment */
- if (obarray != NULL)
- mark(obarray);
- if (xlenv != NIL)
- mark(xlenv);
- if (xlfenv != NIL)
- mark(xlfenv);
- if (xldenv != NIL)
- mark(xldenv);
-
- mark(NIL);
-
- /* mark the evaluation stack */
- for (p = xlstack; p < xlstktop; ++p)
- if ((tmp = **p) != NIL)
- mark(tmp);
-
- /* mark the argument stack */
- for (ap = xlargstkbase; ap < xlsp; ++ap)
- if ((tmp = *ap) != NIL)
- mark(tmp);
-
- /* compact vector space */
- compact();
-
- /* sweep memory collecting all unmarked nodes */
- sweep();
-
- NIL->n_type &= ~MARK;
-
-
- /* count the gc call */
- ++gccalls;
-
- /* call the *gc-hook* if necessary */
- if (s_gchook != NULL && ((fun = getvalue(s_gchook)) != NIL) ) {
- /* rebind hook function to NIL TAA MOD */
- tmp = xldenv;
- xldbind(s_gchook,NIL);
-
- newfp = xlsp;
- pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
- pusharg(fun);
- pusharg(cvfixnum((FIXTYPE)2));
- pusharg(cvfixnum((FIXTYPE)nnodes));
- pusharg(cvfixnum((FIXTYPE)nfree));
- xlfp = newfp;
- xlapply(2);
-
- /* unbind the symbol TAA MOD */
- xlunbind(tmp);
- }
-
- /* print the end of the gc message */
- if (s_gcflag != NULL && getvalue(s_gcflag) != NIL) {
- sprintf(buf,"%ld free ]\n",nfree);
- dbgputstr(buf); /* TAA MOD -- was std output */
- }
- }
-
- /* mark - mark all accessible nodes */
- LOCAL VOID XNEAR mark(ptr)
- LVAL ptr;
- {
- register LVAL this,prev,tmp;
- int i,n;
-
- /* initialize */
- prev = NIL;
- this = ptr;
-
- /* mark this list */
- for (;;) {
- /* descend as far as we can */
- while (!(this->n_type & MARK))
-
- /* check cons and unnamed stream nodes */
- if (((i = (this->n_type |= MARK) & TYPEFIELD) == CONS)||
- (i == USTREAM)) {
- if ((tmp = car(this)) != NIL) {
- this->n_type |= LEFT;
- rplaca(this,prev);
- }
- else if ((tmp = cdr(this)) != NIL)
- rplacd(this,prev);
- else /* both sides nil */
- break;
- prev = this; /* step down the branch */
- this = tmp;
- }
- else {
- if (((i & ARRAY) != 0) && (this->n_vdata != NULL))
- for (i = 0, n = getsize(this); i < n;)
- if ((tmp = getelement(this,i++)) != NIL)
- if ((tmp->n_type & (ARRAY|MARK)) == ARRAY ||
- tmp->n_type == CONS ||
- tmp->n_type == USTREAM)
- mark(tmp);
- else tmp->n_type |= MARK;
- break;
- }
-
- /* backup to a point where we can continue descending */
- for (;;)
-
- /* make sure there is a previous node */
- if (prev!=NIL) {
- if (prev->n_type & LEFT) { /* came from left side */
- prev->n_type &= ~LEFT;
- tmp = car(prev);
- rplaca(prev,this);
- if ((this = cdr(prev)) != NIL) {
- rplacd(prev,tmp);
- break;
- }
- }
- else { /* came from right side */
- tmp = cdr(prev);
- rplacd(prev,this);
- }
- this = prev; /* step back up the branch */
- prev = tmp;
- }
- /* no previous node, must be done */
- else
- return;
- }
- }
-
- /* compact - compact vector space */
- LOCAL VOID XNEAR compact()
- {
- VSEGMENT XFAR *vseg, XFAR *vsold;
-
- /* store the current segment information */
- if (vscurrent != NULL)
- vscurrent->vs_free = vfree;
-
- /* compact each vector segment */
- for (vseg = vsegments, vsold = (VSEGMENT XFAR *)&vsegments;
- vseg != NULL;
- vsold = vseg, vseg = vseg->vs_next) {
- compact_vector(vseg);
- #if 0
- if (vseg->vs_free == &vseg->vs_data[0]) { /* empty segment */
- vsold->vs_next = vseg->vs_next; /* unlink segment */
- vscount--; /* adjust tallies */
- total -= sizeof(VSEGMENT)-sizeof(LVAL XFAR *)+
- (unsigned)vseg->vs_top - (unsigned)vseg->vs_free;
- MFREE(vseg); /* free segment */
- vseg = vsold; /* last becomes current */
- }
- #endif
- }
-
- /* make the first vector segment current */
- if ((vscurrent = vsegments) != NULL) {
- vfree = vscurrent->vs_free;
- vtop = vscurrent->vs_top;
- }
-
-
- getvused(); /* calculate free and used space */
-
- /* and free any unused segments if lots of free space (TAA MOD) */
- if (vsfree > 2*(long)vnodes) {
- for (vseg = vsegments, vsold = (VSEGMENT XFAR *)&vsegments;
- vseg != NULL;
- vsold = vseg, vseg = vseg->vs_next)
- if (vseg->vs_free == &vseg->vs_data[0]) { /* empty segment */
- vsold->vs_next = vseg->vs_next; /* unlink segment */
- vscount--; /* adjust tallies */
- total -= sizeof(VSEGMENT)-sizeof(LVAL XFAR *)+
- (unsigned)vseg->vs_top - (unsigned)vseg->vs_free;
- MFREE(vseg); /* free segment */
- vseg = vsold; /* last becomes current */
- }
-
- /* make the first vector segment current */
- if ((vscurrent = vsegments) != NULL) {
- vfree = vscurrent->vs_free;
- vtop = vscurrent->vs_top;
- }
- }
- }
-
- /* compact_vector - compact a vector segment */
- LOCAL VOID XNEAR compact_vector(vseg)
- VSEGMENT XFAR *vseg;
- {
- LVAL XFAR *vdata, XFAR *vnext, XFAR *vfree,vector;
- unsigned vsize;
-
- vdata = vnext = &vseg->vs_data[0];
- vfree = vseg->vs_free;
- while (vdata < vfree) {
- vector = *vdata;
- if ((vector->n_type & TYPEFIELD) == STRING)
- vsize = btow_size(vector->n_strlen+1) + 1;
- else
- vsize = vector->n_vsize + 1;
- if (vector->n_type & MARK) {
- if (vdata != vnext) {
- vector->n_vdata = vnext + 1;
- MEMCPY(vnext, vdata, vsize * (unsigned)sizeof(LVAL));
- }
- vnext += vsize;
- }
- vdata += vsize;
- }
- vseg->vs_free = vnext;
- }
-
- /* sweep - sweep all unmarked nodes and add them to the free list */
- LOCAL VOID XNEAR sweep()
- {
- SEGMENT XFAR *seg;
- LVAL p;
- int n;
-
- /* empty the free list */
- fnodes = NIL;
- nfree = 0L;
-
- /* add all unmarked nodes */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- if (seg == fixseg || seg == charseg) {
- /* remove marks from segments */
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0;)
- (p++)->n_type &= ~MARK;
- continue;
- }
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0;)
- if (p->n_type & MARK)
- (p++)->n_type &= ~MARK;
- else {
- if (((ntype(p)&TYPEFIELD) == STREAM)
- && getfile(p) != CLOSED
- && getfile(p) != STDIN
- && getfile(p) != STDOUT
- && getfile(p) != CONSOLE)/* taa fix - dont close stdio */
- OSCLOSE(getfile(p));
- p->n_type = FREE;
- rplaca(p,NIL);
- rplacd(p,fnodes);
- fnodes = p++;
- nfree++;
- }
- }
- }
-
- /* addseg - add a segment to the available memory */
- LOCAL int XNEAR addseg()
- {
- SEGMENT XFAR *newseg;
- LVAL p;
- int n;
-
- /* allocate the new segment */
- if (anodes == 0 || (newseg = newsegment(anodes)) == NULL)
- return (FALSE);
-
- /* add each new node to the free list */
- p = &newseg->sg_nodes[0];
- for (n = anodes; --n >= 0; ++p) {
- rplacd(p,fnodes);
- fnodes = p;
- }
-
- /* return successfully */
- return (TRUE);
- }
-
- /* newsegment - create a new segment (only called here and in xlimage.c) */
- SEGMENT XFAR *newsegment(n)
- int n;
- {
- SEGMENT XFAR *newseg;
-
- /* allocate the new segment */
- if ((newseg = (SEGMENT XFAR *)CALLOC(1,segsize(n))) == NULL)
- return (NULL);
-
- /* initialize the new segment */
- newseg->sg_size = n;
- newseg->sg_next = NULL;
- if (segs != NULL)
- lastseg->sg_next = newseg;
- else
- segs = newseg;
- lastseg = newseg;
-
- /* update the statistics */
- total += (long)segsize(n);
- nnodes += (long)n;
- nfree += (long)n;
- ++nsegs;
-
- /* return the new segment */
- return (newseg);
- }
-
- /* stats - print memory statistics */
- #ifdef ANSI
- static void XNEAR stats(void)
- #else
- LOCAL VOID stats()
- #endif
- {
- sprintf(buf,"Nodes: %ld\n",nnodes); stdputstr(buf);
- sprintf(buf,"Free nodes: %ld\n",nfree); stdputstr(buf);
- sprintf(buf,"Segments: %d\n",nsegs); stdputstr(buf);
- sprintf(buf,"Vector nodes: %ld\n",getvused()); stdputstr(buf);
- sprintf(buf,"Vector free: %ld\n",vsfree); stdputstr(buf);
- sprintf(buf,"Vector segs: %d\n",vscount); stdputstr(buf);
- sprintf(buf,"Allocate: %d\n",anodes); stdputstr(buf);
- sprintf(buf,"Vec Allocate: %d\n",vnodes); stdputstr(buf);
- sprintf(buf,"Total: %ld\n",total); stdputstr(buf);
- sprintf(buf,"Collections: %ld\n",gccalls); stdputstr(buf);
- }
-
- /* xgc - xlisp function to force garbage collection */
- LVAL xgc()
- {
- /* make sure there aren't any arguments */
- xllastarg();
-
- /* garbage collect */
- gc();
-
- /* return nil */
- return (NIL);
- }
-
- /* xexpand - xlisp function to force memory expansion */
- LVAL xexpand()
- {
- LVAL num;
- FIXTYPE n,i;
-
- /* get the new number to allocate */
- if (moreargs()) {
- num = xlgafixnum();
- n = getfixnum(num);
- xllastarg();
- }
- else
- n = 1;
-
- /* allocate more segments */
- for (i = 0; i < n; i++)
- if (!addseg())
- break;
-
- /* return the number of segments added */
- return (cvfixnum((FIXTYPE)i));
- }
-
- /* xalloc - xlisp function to set the number of nodes to allocate */
- LVAL xalloc()
- {
- FIXTYPE n,vn; /* TAA MOD -- prevent overflow */
- int oldn;
-
- /* get the new number to allocate */
- n = getfixnum(xlgafixnum());
-
- if (moreargs()) { /* vector allocation */
- vn = getfixnum(xlgafixnum());
- xllastarg();
- /* clip to reasonable values*/
- if (vn > (long)MAXVLEN-sizeof(VSEGMENT)/sizeof(LVAL))
- vn = MAXVLEN-sizeof(VSEGMENT)/sizeof(LVAL);
- else if (vn < 1000) vn = 1000;
- vnodes = (int)vn;
- }
-
- /* Place limits on argument by clipping to reasonable values TAA MOD */
- if (n > ((long)MAXSLEN - sizeof(SEGMENT))/sizeof(struct node))
- n = ((long)MAXSLEN - sizeof(SEGMENT))/sizeof(struct node);
- else if (n < 1000)
- n = 1000; /* arbitrary */
-
- /* set the new number of nodes to allocate */
- oldn = anodes;
- anodes = (int)n;
-
- /* return the old number */
- return (cvfixnum((FIXTYPE)oldn));
- }
-
- /* xmem - xlisp function to print memory statistics */
- LVAL xmem()
- {
- /* allow one argument for compatiblity with common lisp */
- if (xlargc > 1) xltoomany(); /* TAA Mod */
-
- /* print the statistics */
- stats();
-
- /* return nil */
- return (NIL);
- }
-
- #ifdef SAVERESTORE
- /* xsave - save the memory image */
- LVAL xsave()
- {
- #ifdef MEDMEM
- char name[STRMAX];
- #else
- char *name;
- #endif
-
- /* get the file name */
- #ifdef MEDMEM
- _fstrncpy(name, getstring(xlgetfname()), STRMAX);
- name[STRMAX-1] = '\0';
- #else
- name = getstring(xlgetfname());
- #endif
- xllastarg();
-
- /* save the memory image */
- return (xlisave(name) ? true : NIL);
- }
-
- /* xrestore - restore a saved memory image */
- LVAL xrestore()
- {
- extern jmp_buf top_level;
- #ifdef MEDMEM
- char name[STRMAX];
- #else
- char *name;
- #endif
-
- /* get the file name */
- #ifdef MEDMEM
- _fstrncpy(name, getstring(xlgetfname()), STRMAX);
- name[STRMAX-1] = '\0';
- #else
- name = getstring(xlgetfname());
- #endif
- xllastarg();
-
- /* restore the saved memory image */
- if (!xlirestore(name))
- return (NIL);
-
- /* return directly to the top level */
- dbgputstr("[ returning to the top level ]\n"); /* TAA MOD --was std out*/
- longjmp(top_level,1);
- return (NIL); /* never executed, but avoids warning message */
- }
- #endif
-
- #ifdef COMPLX
- /* From XLISP-STAT, Copyright (c) 1988 Luke Tierney */
-
- LVAL newicomplex(real, imag)
- FIXTYPE real, imag;
- {
- LVAL val;
-
- if (imag == 0) val = cvfixnum(real);
- else {
- xlsave1(val);
- val = newvector(2);
- val->n_type = COMPLEX;
- setelement(val, 0, cvfixnum(real));
- setelement(val, 1, cvfixnum(imag));
- xlpop();
- }
- return(val);
- }
-
- LVAL newdcomplex(real, imag)
- double real, imag;
- {
- LVAL val;
-
- xlsave1(val);
- val = newvector(2);
- val->n_type = COMPLEX;
- setelement(val, 0, cvflonum((FLOTYPE) real));
- setelement(val, 1, cvflonum((FLOTYPE) imag));
- xlpop();
- return(val);
- }
-
- /* newcomplex - allocate and initialize a new object */
- LVAL newcomplex(real,imag)
- LVAL real,imag;
- {
- if (fixp(real) && fixp(imag))
- return(newicomplex(getfixnum(real), getfixnum(imag)));
- else
- return(newdcomplex(makefloat(real), makefloat(imag)));
- }
-
- #endif
-