/* $Id: list.c,v 10.2 92/10/09 13:00:55 ca Exp $ */ /* list.c: Rest of list routines */ /*LINTLIBRARY*/ /* General-purpose list manipulation routines. Contains the following * routines: * l_add{t,h} Add element to head or tail if list. * l_adda Add element after another in the list. * l_del Delete an element from a list. * l{e}_remh remove and return head of list. * l{e}_remt remove and return tail of list. * l_find determine whether an element is in a list. * l_create create a list. * lq_delete Free all storage in either a list or a queue. * l_obliterate Free all storage (including user data) in a list. * All other general-purpose list manipulation routines are macros * defined in "list.h". */ #include #include "list.h" extern char *sim_calloc(); #define TRUE 1 #define FALSE 0 #define NULL 0 l_elt * l_addh(l, elt) register list *l; register caddr_t elt; { register l_elt *new = (l_elt *)sim_calloc(1, sizeof(l_elt)); new->le_data = elt; le_addh(l, new); return(new); } l_elt * l_addt(l, elt) register list *l; register caddr_t elt; { register l_elt *new = (l_elt *)sim_calloc(1, sizeof(l_elt)); new->le_data = elt; le_addt(l, new); return(new); } /* Procedure to determine if an element is in a list. Returns NULL if not found, and the pointer to the *l_elt* if found. */ l_elt * l_find(l, elt) register list *l; register caddr_t elt; { register l_elt *tmp; for (tmp = l->l_head; !tmp || tmp->le_data != elt; tmp = tmp->le_next) if (!tmp) return(NULL); return(tmp); } l_elt * l_adda(l, prev, new) register list *l; register caddr_t prev, new; { register l_elt *newelt; register l_elt *found; found = l_find(l, prev); if (found) { newelt = (l_elt *)sim_calloc(1, sizeof (l_elt)); newelt->le_data = new; le_adda(l, found, newelt); } return(newelt); } l_del(l, elt) register list *l; register caddr_t elt; { register l_elt *found; found = l_find(l, elt); if (found) { le_del(l, found); free((char *)found); return(TRUE); } return(FALSE); } caddr_t l_remh(l) register list *l; { register l_elt *head = le_remh(l); register caddr_t data = NULL; if (head) { data = head->le_data; free((char *)head); } return(data); } caddr_t l_remt(l) register list *l; { register l_elt *tail = le_remh(l); register caddr_t data = NULL; if (tail) { data = tail->le_data; free((char *)tail); } return(data); } l_elt * le_remh(l) register list *l; { register l_elt *le; if (l->l_head) { le = l->l_head; l->l_head = le->le_next; if (le->le_next) le->le_next->le_prev = NULL; else l->l_tail = NULL; if (--l->l_len < l->l_min) l->l_min = l->l_len; return(le); } else return(NULL); } l_elt * le_remt(l) register list *l; { register l_elt *le; if (l->l_tail) { le = l->l_tail; l->l_tail = le->le_prev; if (le->le_prev) le->le_prev->le_next = NULL; else l->l_head = NULL; if (--l->l_len < l->l_min) l->l_min = l->l_len; return(le); } else return(NULL); } list * l_create() { return((list *)sim_calloc(1, sizeof(list))); } /* Free a list or queue entirely. This **DOES NOT** free any of the storage pointed to by the list or queue elements. */ void lq_delete(lq) register list *lq; { register l_elt *le, *next; for (le = lq->l_head; le; le = next) { next = le->le_next; free((char *)le); } free((char *)lq); } /* Remove all elements from a list or queue. Similar to lq_delete, but doesn't free the list itself. */ void lq_clear(lq) register list *lq; { register l_elt *le, *next; for (le = lq->l_head; le; le = next) { next = le->le_next; free((char *)le); } lq->l_len = 0; lq->l_max = lq->l_min = 0; /* eric added the following lines. */ lq->l_head = 0; lq->l_tail = 0; } /* Free everything associated with a list. *** NOTE *** This is __NOT__ the opposite of l_create. l_create only allocates memory for the list header, not for all the elements in the list. This function frees the elements *and* the data pointed to by the elements as well as the header, and is provided as a service to the user. Use at your own risk. */ void l_obliterate(l) register list *l; { register l_elt *le, *next; for (le = l->l_head; le; le = next) { next = le->le_next; free((char *)le->le_data); free((char *)le); } free((char *)l); } /********************************************************************************************************************************************/ /* eric */ list *l_duplicate(l) register list *l; { register list *new; register l_elt *le; if (!(new=l_create())) return(NULL); for(le=l->l_head;le!=NULL;le=le->le_next) l_addh(new,le->le_data); return(new); } /****************************************************************************************************************************************/ /* eric */ void l_traverse(l,func) register list *l; register void (*func)(); { register l_elt *le; for (le=l->l_head; le!=NULL; le=le->le_next) (*func)(le->le_data); }