/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* $Header: b1val.c,v 1.4 85/08/22 16:53:49 timo Exp $ */ /* General operations for objects */ #include "b.h" #include "b0con.h" #include "b1obj.h" #include "b1mem.h" #ifndef INTEGRATION #include "b1btr.h" #include "b1val.h" #endif #include "b1tlt.h" #include "b2nod.h" /* for _Nbranches */ #include "b3scr.h" /* TEMPORARY for at_nwl */ #include "b1num.h" /* for ccopy, rrelease, grab, grab_num, grab_rat, grab_approx */ #ifdef INTEGRATION #include "node.h" #endif INTEGRATION #ifdef vax /* 4.2 BSD malloc already takes care of using a small number of sizes */ #define Len len #else #define Len (len < 200 ? len : ((len-1)/8+1)*8) #endif #define Hdrsize (sizeof(struct value)-sizeof(string)) #define Tsize (sizeof(a_telita)) #define Adj(s) (unsigned) (Hdrsize+(s)) #define Unadj(s) (unsigned) ((s)-Hdrsize) #define NodOffset (sizeof(int) + 2*sizeof(intlet)) #define Grabber() {if(len>Maxintlet)syserr(MESS(1800, "big grabber"));} #define Regrabber() {if(len>Maxintlet)syserr(MESS(1801, "big regrabber"));} /*************************** Grabbing ***********************************/ #ifdef NOT_USED long gr= 0; Visible Procedure prgr() {at_nwl=No;printf(" gr:%ld",gr);gr=0;} #endif Hidden unsigned getsyze(type, len, pnptrs) literal type; intlet len; int *pnptrs; { register unsigned syze= 0; register int nptrs= 0; switch (type) { case Num: if (len >= 0) syze= Len*sizeof(digit); /* Integral */ else if (len == -1) { #ifdef EXT_RANGE syze= 2*sizeof(double); /* Approximate */ #else syze= sizeof(double); /* Approximate */ #endif } else { syze= 2*sizeof(value); nptrs= 2; } /* Rational */ break; case Ptn: len= _Nbranches(len); syze= (len+2)*sizeof(value); nptrs= len; break; case Com: syze= len*sizeof(value); nptrs= len; break; case Sim: syze= sizeof(simploc); nptrs= 1; break; case Tri: syze= sizeof(trimloc); nptrs= 3; break; case Tse: syze= sizeof(tbseloc); nptrs= 2; break; case How: syze= sizeof(how); nptrs= 1; break; case For: syze= sizeof(formal); nptrs= 1; /*uname!*/ break; case Per: syze= sizeof(per); nptrs= 1; break; case Fun: case Prd: syze= sizeof(funprd); nptrs= 1; break; case Ref: syze= sizeof(ref); nptrs= 1; break; #ifndef INTEGRATION case Tex: case ELT: case Lis: case Tab: syze= sizeof(value); nptrs= 1; break; #else case Tex: syze= (len+1)*sizeof(char); break; case ELT: case Lis: case Tab: syze = Len*sizeof(value); nptrs= len; break; case Pat: syze= sizeof(struct path) - Hdrsize; nptrs= 2; break; case Nod: syze= sizeof(struct node) - Hdrsize - sizeof(node) + len*sizeof(node); nptrs= len; break; #endif default: printf("\ngetsyze{%c}\n", type); syserr(MESS(1803, "getsyze called with unknown type")); } if (pnptrs != NULL) *pnptrs= nptrs; return syze; } Hidden value grab(type, len) literal type; intlet len; { unsigned syze= getsyze(type, len, (int*)NULL); value v; Grabber(); v= (value) getmem(Adj(syze)); v->type= type; v->len= len; v->refcnt= 1; #ifdef NOT_USED gr+=1; #endif return v; } #ifndef INTEGRATION Visible value grab_tlt(type, it) literal type, it; { return grab(type, it); } #else Visible value grab_tex(len) intlet len; { return grab(Tex, len); } Visible value grab_elt() { return grab(ELT, 0); } Visible value grab_lis(len) intlet len; { return grab(Lis, len); } Visible value grab_tab(len) intlet len; { return grab(Tab, len); } #endif Visible value grab_num(len) register int len; { integer v; register int i; if (len > Maxintlet) { error(MESS(1804, "exceptionally large number")); return Vnil; } if (len < -Maxintlet) len = -2; v = (integer) grab(Num, len); for (i = Length(v)-1; i >= 0; --i) Digit(v, i) = 0; return (value) v; } Visible value grab_rat() { return grab(Num, -2); } Visible value regrab_num(v, len) value v; register int len; { register unsigned syze; syze = Len * sizeof(digit); uniql(&v); regetmem((ptr*)&v, Adj(syze)); Length(v) = len; return v; } Visible value grab_com(len) intlet len; { return grab(Com, len); } Visible value grab_ptn(len) intlet len; { return grab(Ptn, len); } Visible value grab_sim() { return grab(Sim, 0); } Visible value grab_tri() { return grab(Tri, 0); } Visible value grab_tse() { return grab(Tse, 0); } Visible value grab_how() { return grab(How, 0); } Visible value grab_for() { return grab(For, 0); } Visible value grab_per() { return grab(Per, 0); } Visible value grab_fun() { return grab(Fun, 0); } Visible value grab_prd() { return grab(Prd, 0); } Visible value grab_ref() { return grab(Ref, 0); } #ifdef INTEGRATION /* * Allocate a node with nch children. */ Visible node grab_node(nch) register int nch; { register node n = (node) grab(Nod, nch); register int i; n->n_marks = 0; n->n_width = 0; n->n_symbol = 0; for (i = nch-1; i >= 0; --i) n->n_child[i] = Nnil; return n; } /* * Allocate a path. */ Visible path grab_path() { register path p = (path) grab(Pat, 0); p->p_parent = PATHnil; p->p_tree = Nnil; p->p_ichild = 0; p->p_ycoord = 0; p->p_xcoord = 0; p->p_level = 0; p->p_addmarks = 0; p->p_delmarks = 0; return p; } #endif INTEGRATION /******************************* Copying and releasing *********************/ Visible value copy(v) value v; { if (IsSmallInt(v)) return v; if (v != Vnil && v->refcnt < Maxrefcnt) (v->refcnt)++; #ifdef NOT_USED gr+=1; #endif return v; } Visible Procedure release(v) value v; { #ifdef IBMPC literal *r; #else intlet *r; #endif if (IsSmallInt(v)) return; if (v == Vnil) return; r= &(v->refcnt); if (*r == 0) syserr(MESS(1805, "releasing unreferenced value")); if (bugs) { printf("releasing: "); if (Type(v) == Num) bugs= No; wri(v,No,No,No); newline(); bugs= Yes; } if (*r < Maxrefcnt && --(*r) == 0) rrelease(v); #ifdef NOT_USED gr-=1; #endif } Hidden value ccopy(v) value v; { literal type= v->type; intlet len; value w; int nptrs; unsigned syze; register string from, to, end; register value p, *pp, *pend; len= Length(v); syze= getsyze(type, len, &nptrs); Grabber(); w= (value) getmem(Adj(syze)); w->type= type; w->len= len; w->refcnt= 1; from= Str(v); to= Str(w); end= to+syze; while (to < end) *to++ = *from++; pp= Ats(w); #ifdef INTEGRATION if (type == Nod) pp= (value*) ((char*)pp + NodOffset); #endif pend= pp+nptrs; while (pp < pend) { p= *pp++; if (p != Vnil && !IsSmallInt(p) && Refcnt(p) < Maxrefcnt) ++Refcnt(p); } return w; } Visible Procedure uniql(ll) value *ll; { if (*ll != Vnil && !IsSmallInt(*ll) && (*ll)->refcnt > 1) { value c= ccopy(*ll); release(*ll); *ll= c; } } Hidden Procedure rrelease(v) value v; { literal type= v->type; intlet len; int nptrs; register value *pp, *pend; len= Length(v); #ifndef INTEGRATION switch (type) { case Tex: case Tab: case Lis: case ELT: relbtree(Root(v), Itemtype(v)); break; default: #endif VOID getsyze(type, len, &nptrs); pp= Ats(v); #ifdef INTEGRATION if (type == Nod) pp= (value*) ((char*)pp + NodOffset); #endif pend= pp+nptrs; while (pp < pend) release(*pp++); #ifndef INTEGRATION } #endif v->type= '\0'; freemem((ptr) v); } #ifdef INTEGRATION Visible Procedure xtndtex(a, d) value *a; intlet d; { intlet len= Length(*a)+d; Regrabber(); regetmem((ptr *) a, Adj((len+1)*sizeof(char))); (*a)->len= len; } Visible Procedure xtndlt(a, d) value *a; intlet d; { intlet len= Length(*a); intlet l1= Len, l2; len+= d; l2= Len; if (l1 != l2) { Regrabber(); regetmem((ptr *) a, Adj(l2*sizeof(value))); } (*a)->len= len; } /* * Set an object's refcnt to infinity, so it will never be released. */ Visible Procedure fix_refcnt(v) register value v; { register int i; register node n; register path p; Assert(v->refcnt > 0); v->refcnt = Maxrefcnt; switch (v->type) { case Tex: break; case Nod: n = (node)v; for (i = v->len - 1; i >= 0; --i) if (n->n_child[i]) fix_refcnt((value)(n->n_child[i])); break; case Pat: p = (path)v; if (p->p_parent) fix_refcnt((value)(p->p_parent)); if (p->p_tree) fix_refcnt((value)(p->p_tree)); break; default: Abort(); } } #endif INTEGRATION #ifndef INTEGRATION /*********************************************************************/ /* grab, copy, release of btree(node)s /*********************************************************************/ Visible btreeptr grabbtreenode(flag, it) literal flag; literal it; { btreeptr pnode; unsigned syz; static intlet isize[]= { sizeof(itexnode), sizeof(ilisnode), sizeof(itabnode), sizeof(itabnode)}; static intlet bsize[]= { sizeof(btexnode), sizeof(blisnode), sizeof(btabnode), sizeof(btabnode)}; switch (flag) { case Inner: syz= isize[it]; break; case Bottom: syz= bsize[it]; break; case Irange: case Crange: syz = sizeof(rangenode); break; } pnode = (btreeptr) getmem((unsigned) syz); Refcnt(pnode) = 1; Flag(pnode) = flag; return(pnode); } /* ----------------------------------------------------------------- */ Visible btreeptr copybtree(pnode) btreeptr pnode; { if (pnode != Bnil && Refcnt(pnode) < Maxrefcnt) ++Refcnt(pnode); return(pnode); } Visible Procedure uniqlbtreenode(pptr, it) btreeptr *pptr; literal it; { if (*pptr NE Bnil && Refcnt(*pptr) > 1) { btreeptr qnode = *pptr; *pptr = ccopybtreenode(*pptr, it); relbtree(qnode, it); } } Visible btreeptr ccopybtreenode(pnode, it) btreeptr pnode; literal it; { intlet limp; btreeptr qnode; intlet iw; iw = Itemwidth(it); qnode = grabbtreenode(Flag(pnode), it); Lim(qnode) = limp = Lim(pnode); Size(qnode) = Size(pnode); switch (Flag(qnode)) { case Inner: cpynitms(Piitm(qnode, 0, iw), Piitm(pnode, 0, iw), limp, it); cpynptrs(&Ptr(qnode, 0), &Ptr(pnode, 0), limp+1); break; case Bottom: cpynitms(Pbitm(qnode, 0, iw), Pbitm(pnode, 0, iw), limp, it); break; case Irange: case Crange: Lwbval(qnode) = copy(Lwbval(pnode)); Upbval(qnode) = copy(Upbval(pnode)); break; default: syserr(MESS(1808, "unknown flag in ccopybtreenode")); } return(qnode); } /* make a new root (after the old ptr0 split) */ Visible btreeptr mknewroot(ptr0, pitm0, ptr1, it) btreeptr ptr0, ptr1; itemptr pitm0; literal it; { int r; intlet iw = Itemwidth(it); btreeptr qnode = grabbtreenode(Inner, it); Ptr(qnode, 0) = ptr0; movnitms(Piitm(qnode, 0, iw), pitm0, 1, iw); Ptr(qnode, 1) = ptr1; Lim(qnode) = 1; r= Sincr(Size(ptr0)); Size(qnode) = Ssum(r, Size(ptr1)); return(qnode); } /* ----------------------------------------------------------------- */ /* release btree */ Visible Procedure relbtree(pnode, it) btreeptr pnode; literal it; { width iw; iw = Itemwidth(it); if (pnode EQ Bnil) return; if (Refcnt(pnode) EQ 0) { syserr(MESS(1809, "releasing unreferenced btreenode")); return; } if (Refcnt(pnode) < Maxrefcnt && --Refcnt(pnode) EQ 0) { intlet l; switch (Flag(pnode)) { case Inner: for (l = 0; l < Lim(pnode); l++) { relbtree(Ptr(pnode, l), it); switch (it) { case Tt: case Kt: release(Ascval(Piitm(pnode, l, iw))); case Lt: release(Keyval(Piitm(pnode, l, iw))); } } relbtree(Ptr(pnode, l), it); break; case Bottom: for (l = 0; l < Lim(pnode); l++) { switch (it) { case Tt: case Kt: release(Ascval(Pbitm(pnode, l, iw))); case Lt: release(Keyval(Pbitm(pnode, l, iw))); } } break; case Irange: case Crange: release(Lwbval(pnode)); release(Upbval(pnode)); break; default: syserr(MESS(1810, "wrong flag in relbtree()")); } freemem((ptr) pnode); } } #endif !INTEGRATION