/* This software may only be used by you under license from AT&T Corp. ("AT&T"). A copy of AT&T's Source Code Agreement is available at AT&T's Internet website having the URL: If you received this software without first entering into a license with AT&T, you have an infringing copy of this software and cannot use it without violating AT&T's intellectual property rights. */ #include "dthdr.h" #ifdef DMALLOC #include "dmalloc.h" #endif /* List, Stack, Queue. ** ** Written by Kiem-Phong Vo (05/25/96) */ #if __STD_C static Void_t* dtlist(reg Dt_t* dt, reg Void_t* obj, reg int type) #else static Void_t* dtlist(dt, obj, type) reg Dt_t* dt; reg Void_t* obj; reg int type; #endif { reg int lk, sz, ky; reg Dtcompar_f cmpf; reg Dtdisc_t* disc; reg Dtlink_t *r, *t; reg Void_t *key, *k; INITDISC(dt,disc,ky,sz,lk,cmpf); if(!obj) { if(type&(DT_LAST|DT_FIRST) ) { if((r = dt->data->head) ) { if(type&DT_LAST) r = r->left; dt->data->here = r; } return r ? OBJ(r,lk) : NIL(Void_t*); } else if(type&(DT_DELETE|DT_DETACH)) { if((dt->data->type&DT_LIST) || !(r = dt->data->head)) return NIL(Void_t*); else goto dt_delete; } else if(type&DT_CLEAR) { if(disc->freef || disc->link < 0) { for(r = dt->data->head; r; r = t) { t = r->right; if(disc->freef) (*disc->freef)(dt,OBJ(r,lk),disc); if(disc->link < 0) (*dt->memoryf)(dt,(Void_t*)r,0,disc); } } dt->data->head = dt->data->here = NIL(Dtlink_t*); dt->data->size = 0; return NIL(Void_t*); } else return NIL(Void_t*); } if(type&(DT_INSERT|DT_ATTACH)) { if(disc->makef && (type&DT_INSERT) && !(obj = (*disc->makef)(dt,obj,disc)) ) return NIL(Void_t*); if(lk >= 0) r = ELT(obj,lk); else { r = (Dtlink_t*)(*dt->memoryf) (dt,NIL(Void_t*),sizeof(Dthold_t),disc); if(r) ((Dthold_t*)r)->obj = obj; else { if(disc->makef && disc->freef && (type&DT_INSERT)) (*disc->freef)(dt,obj,disc); return NIL(Void_t*); } } if(dt->data->type&DT_LIST) { if((t = dt->data->here) && t != dt->data->head) { r->left = t->left; t->left->right = r; r->right = t; t->left = r; } else goto dt_stack; } else if(dt->data->type&DT_STACK) { dt_stack: r->right = t = dt->data->head; if(t) { r->left = t->left; t->left = r; } else r->left = r; dt->data->head = r; } else /* if(dt->data->type&DT_QUEUE) */ { if((t = dt->data->head) ) { t->left->right = r; r->left = t->left; t->left = r; } else { dt->data->head = r; r->left = r; } r->right = NIL(Dtlink_t*); } if(dt->data->size >= 0) dt->data->size += 1; dt->data->here = r; return OBJ(r,lk); } if((type&DT_MATCH) || !(r = dt->data->here) || OBJ(r,lk) != obj) { key = (type&DT_MATCH) ? obj : KEY(obj,ky,sz); for(r = dt->data->head; r; r = r->right) { k = OBJ(r,lk); k = KEY(k,ky,sz); if(CMP(dt,key,k,disc,cmpf,sz) == 0) break; } } if(!r) return NIL(Void_t*); if(type&(DT_DELETE|DT_DETACH)) { dt_delete: if(r->right) r->right->left = r->left; if(r == (t = dt->data->head) ) { dt->data->head = r->right; if(dt->data->head) dt->data->head->left = t->left; } else { r->left->right = r->right; if(r == t->left) t->left = r->left; } dt->data->here = r == dt->data->here ? r->right : NIL(Dtlink_t*); dt->data->size -= 1; obj = OBJ(r,lk); if(disc->freef && (type&DT_DELETE)) (*disc->freef)(dt,obj,disc); if(disc->link < 0) (*dt->memoryf)(dt,(Void_t*)r,0,disc); return obj; } else if(type&DT_NEXT) r = r->right; else if(type&DT_PREV) r = r == dt->data->head ? NIL(Dtlink_t*) : r->left; dt->data->here = r; return r ? OBJ(r,lk) : NIL(Void_t*); } #ifndef KPVDEL /* to be remove next round */ #define static #endif static Dtmethod_t _Dtlist = { dtlist, DT_LIST }; static Dtmethod_t _Dtstack = { dtlist, DT_STACK }; static Dtmethod_t _Dtqueue = { dtlist, DT_QUEUE }; __DEFINE__(Dtmethod_t*,Dtlist,&_Dtlist); __DEFINE__(Dtmethod_t*,Dtstack,&_Dtstack); __DEFINE__(Dtmethod_t*,Dtqueue,&_Dtqueue);