home *** CD-ROM | disk | FTP | other *** search
- /* xldmem - xlisp dynamic memory management routines */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- #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;
-
- /* variables local to xldmem.c and xlimage.c */
- SEGMENT *segs,*lastseg,*fixseg,*charseg;
- int anodes,nsegs;
- long gccalls;
- long nnodes,nfree,total;
- LVAL fnodes = NIL;
-
- /* forward declarations */
- #ifdef ANSI
- #ifdef JMAC
- FORWARD LVAL NEAR Newnode(int type);
- #else
- FORWARD LVAL NEAR newnode(int type);
- #endif
- FORWARD char * NEAR stralloc(unsigned int size);
- FORWARD VOID NEAR mark(LVAL ptr);
- FORWARD VOID NEAR sweep(void);
- FORWARD VOID NEAR findmem(void);
- FORWARD int NEAR addseg(void);
- #else
- #ifdef JMAC
- FORWARD LVAL Newnode();
- #else
- FORWARD LVAL newnode();
- #endif
- FORWARD char *stralloc();
- 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
-
- /* $putpatch.c$: "MODULE_XLDMEM_C_GLOBALS" */
-
- #ifdef VMEM
- LOCAL VOID gcq(size)
- long size;
- {
- if ((total+size)/VMEM > total/VMEM) gc();
- }
- #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;
- fnodes = NIL;
-
- /* 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;
- xlenv = xlfenv = xldenv = NIL;
- s_gcflag = s_gchook = NULL;
-
- /* $putpatch.c$: "MODULE_XLDMEM_C_XLMINIT" */
-
- /* allocate the evaluation stack */
- xlstack = xlstktop;
-
- /* allocate the argument stack */
- xlfp = xlsp = xlargstkbase;
- *xlsp++ = NIL;
-
- /* we have to make a NIL symbol before continuing */
-
- p = xlmakesym("NIL");
- memcpy(NIL, p, sizeof(struct node)); /* we point to this! */
- defconstant(NIL, NIL);
- p->n_type = FREE; /* don't collect "garbage" */
-
- }
-
- /* 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");
- xlpop();
- xlpop();
- }
-
- /* 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 *str;
- {
- LVAL val;
- xlsave1(val);
- val = newnode(STRING);
- val->n_strlen = strlen(str);
- val->n_string = stralloc(getslength(val)+1);
- strcpy((char *)getstring(val),str);
- xlpop();
- return (val);
- }
-
- /* newstring - allocate and initialize a new string */
- LVAL newstring(size)
- unsigned size;
- {
- LVAL val;
- xlsave1(val);
- val = newnode(STRING);
- val->n_strlen = size;
- val->n_string = stralloc(size+1);
- val->n_string[0] = 0;
- xlpop();
- return (val);
- }
-
- /* cvsymbol - convert a string to a symbol */
- LVAL cvsymbol(pname)
- char *pname;
- {
- LVAL val;
- xlsave1(val);
- val = newvector(SYMSIZE);
- val->n_type = SYMBOL;
- 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
-
- /* 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 executed */
- }
- #else
- LVAL cvchar(n)
- int n;
- {
- if (n >= CHARMIN && n <= CHARMAX)
- return (&charseg->sg_nodes[n-CHARMIN]);
- xlerror("character code out of range",cvfixnum((FIXTYPE)n));
- return 0; /* never executed but gets rid of warning message */
- }
- #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
-
- /* 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 = newvector(size+1);
- val->n_type = OBJECT;
- 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 = newvector(CLOSIZE);
- val->n_type = CLOSURE;
- 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 = newvector(size+1);
- val->n_type = STRUCT;
- setelement(val,0,type);
- return (val);
- }
-
-
- /* newvector - allocate and initialize a new vector node */
- LVAL newvector(size)
- unsigned size;
- {
- LVAL vect;
- int i;
- long bsize = size * sizeof(LVAL *);
-
- if (size > MAXVLEN) xlfail("array too large");
-
- xlsave1(vect);
-
- vect = newnode(VECTOR);
- vect->n_vsize = 0;
-
- if (size != 0) {
- /* We must clear to a nonzero value */
- #ifdef VMEM
- gcq(bsize);
- #endif
- if ((vect->n_vdata = (LVAL *)MALLOC((unsigned int)bsize)) == NULL) {
- gc(); /* TAA Mod -- was findmem(), but this would
- cause undesired memory expansion */
- if ((vect->n_vdata = (LVAL *)MALLOC((unsigned int)bsize)) == NULL)
- xlfail("insufficient vector space");
- }
- for (i = size; i-- > 0;) setelement(vect, i, NIL);
- vect->n_vsize = size;
- total += bsize;
- }
- xlpop();
- return (vect);
- }
-
- /* newnode - allocate a new node */
- #ifdef JMAC
- LOCAL LVAL NEAR 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 NEAR 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
-
- /* stralloc - allocate memory for a string */
- LOCAL char * NEAR stralloc(size)
- unsigned int size;
- {
- char *sptr;
-
- #ifdef VMEM
- gcq((long)size);
- #endif
-
- /* allocate memory for the string copy */
- if ((sptr = (char *)MALLOC(size)) == NULL) {
- gc();
- if ((sptr = (char *)MALLOC(size)) == NULL)
- xlfail("insufficient string space");
- }
- total += (long)size;
-
- /* return the new string memory */
- return (sptr);
- }
-
- /* findmem - find more memory by collecting then expanding */
- LOCAL VOID NEAR findmem()
- {
- gc();
- if (nfree < (long)anodes)
- addseg();
- }
-
- /* gc - garbage collect (only called here and in xlimage.c) */
- VOID gc()
- {
- register 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 */
- }
-
- /* $putpatch.c$: "MODULE_XLDMEM_C_GC" */
-
- /* 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);
-
- /* 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 NEAR 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;
- }
- /* $putpatch.c$: "MODULE_XLDMEM_C_MARK" */
- else {
- if ((i & ARRAY) != 0)
- 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;
- }
- }
-
- /* sweep - sweep all unmarked nodes and add them to the free list */
- LOCAL VOID NEAR sweep()
- {
- SEGMENT *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 {
- switch (ntype(p)&TYPEFIELD) {
- case STRING:
- if (getstring(p) != NULL) {
- total -= (long)getslength(p)+1;
- MFREE(getstring(p));
- }
- break;
- case STREAM:
- if (getfile(p) != CLOSED
- && getfile(p) != STDIN
- && getfile(p) != STDOUT
- && getfile(p) != CONSOLE)/* taa fix - dont close stdio */
- OSCLOSE(getfile(p));
- break;
- /* $putpatch.c$: "MODULE_XLDMEM_C_SWEEP" */
- case SYMBOL:
- case OBJECT:
- case VECTOR:
- case CLOSURE:
- case STRUCT:
- #ifdef COMPLX
- case COMPLEX:
- #endif
- if (p->n_vsize) {
- total -= (long)p->n_vsize * sizeof(LVAL);
- MFREE(p->n_vdata);
- }
- break;
- }
- p->n_type = FREE;
- rplaca(p,NIL);
- rplacd(p,fnodes);
- fnodes = p++;
- nfree++;
- }
- }
- }
-
- /* addseg - add a segment to the available memory */
- LOCAL int NEAR addseg()
- {
- SEGMENT *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 *newsegment(n)
- int n;
- {
- SEGMENT *newseg;
-
- /* allocate the new segment */
- if ((newseg = (SEGMENT *)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 NEAR 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,"Allocate: %d\n",anodes); 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);
- /* make sure there aren't any more arguments */
- 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; /* TAA MOD -- prevent overflow */
- int oldn;
-
- /* get the new number to allocate */
- n = getfixnum(xlgafixnum());
-
- /* make sure there aren't any more arguments */
- if (xlargc > 1) xltoomany(); /* but one more is OK, TAA MOD */
-
- /* 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()
- {
- char *name;
-
- /* get the file name, verbose flag and print flag */
- name = getstring(xlgetfname());
- xllastarg();
-
- /* save the memory image */
- return (xlisave(name) ? true : NIL);
- }
-
- /* xrestore - restore a saved memory image */
- LVAL xrestore()
- {
- extern jmp_buf top_level;
- char *name;
-
- /* get the file name, verbose flag and print flag */
- name = getstring(xlgetfname());
- 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
-