3 Revision 1.5 2003/07/14 13:36:58 ivo
4 use space() instead of malloc
6 Revision 1.4 2000/10/10 08:53:52 ivo
7 include dmalloc.h header if DMALLOC defined
9 Revision 1.4 2000/10/10 08:04:34 ivo
10 include dmalloc header id DMALLOC defined
12 Revision 1.3 1998/03/30 14:24:51 ivo
13 use RNA package utils.h
15 Revision 1.2 1997/10/09 19:01:50 steve
16 *** empty log message ***
18 Revision 1.1 1997/08/04 21:05:32 walter
23 (C) 1991 Kendall Bennett.
32 static char rcsid[] = "$Id: list.c,v 1.5 2003/07/14 13:36:58 ivo Exp $";
36 lst_newnode (int size)
37 /****************************************************************************
39 * Function: lst_newnode
40 * Parameters: size - Amount of memory to allocate for node
41 * Returns: Pointer to the allocated node's user space.
43 * Description: Allocates the memory required for a node, adding a small
44 * header at the start of the node. We return a reference to
45 * the user space of the node, as if it had been allocated via
48 ****************************************************************************/
52 node = (LST_BUCKET *) space (size + sizeof (LST_BUCKET));
54 return LST_USERSPACE (node); /* Return pointer to user space */
58 lst_freenode (void *node)
59 /****************************************************************************
61 * Function: lst_freenode
62 * Parameters: node - Node to free.
64 * Description: Frees a node previously allocated with lst_newnode().
66 ****************************************************************************/
68 free (LST_HEADER (node));
73 /****************************************************************************
76 * Returns: Pointer to a newly created list.
78 * Description: Initialises a list and returns a pointer to it.
80 ****************************************************************************/
84 if ((l = (LIST *) space (sizeof (LIST))) != NULL)
87 l->head = &(l->hz[0]);
89 l->head->next = l->z->next = l->z;
96 lst_kill (LIST * l, void (*freeNode) (void *node))
97 /****************************************************************************
100 * Parameters: l - List to kill
101 * freeNode - Pointer to user routine to free a node
103 * Description: Kills the list l, by deleting all of the elements contained
104 * within the list one by one and then deleting the list
105 * itself. Note that we call the user supplied routine
106 * (*freeNode)() to free each list node. This allows the user
107 * program to perform any extra processing needed to kill each
108 * node (if each node contains pointers to other items on the
109 * heap for example). If no extra processing is required, just
110 * pass the address of lst_freenode(), ie:
112 * lst_kill(myList,lst_freenode);
114 ****************************************************************************/
120 { /* Free all nodes in list */
123 (*freeNode) (LST_USERSPACE (p));
125 free (l); /* Free the list itself */
129 lst_insertafter (LIST * l, void *node, void *after)
130 /****************************************************************************
132 * Function: lst_insertafter
133 * Parameters: l - List to insert node into
134 * node - Pointer to user space of node to insert
135 * after - Pointer to user space of node to insert node after
137 * Description: Inserts a new node into the list after the node 'after'. To
138 * insert a new node at the beginning of the list, user the
139 * macro LST_HEAD in place of 'after'. ie:
141 * lst_insertafter(mylist,node,LST_HEAD(mylist));
143 ****************************************************************************/
145 LST_BUCKET *n = LST_HEADER (node), *a = LST_HEADER (after);
153 lst_deletenext (LIST * l, void *node)
154 /****************************************************************************
156 * Function: lst_deletenext
157 * Parameters: l - List to delete node from.
158 * node - Node to delete the next node from
159 * Returns: Pointer to the deleted node's userspace.
161 * Description: Removes the node AFTER 'node' from the list l.
163 ****************************************************************************/
165 LST_BUCKET *n = LST_HEADER (node);
167 node = LST_USERSPACE (n->next);
168 n->next = n->next->next;
175 /****************************************************************************
177 * Function: lst_first
178 * Parameters: l - List to obtain first node from
179 * Returns: Pointer to first node in list, NULL if list is empty.
181 * Description: Returns a pointer to the user space of the first node in
182 * the list. If the list is empty, we return NULL.
184 ****************************************************************************/
189 return (n == l->z ? NULL : LST_USERSPACE (n));
193 lst_next (void *prev)
194 /****************************************************************************
197 * Parameters: prev - Previous node in list to obtain next node from
198 * Returns: Pointer to the next node in the list, NULL at end of list.
200 * Description: Returns a pointer to the user space of the next node in the
201 * list given a pointer to the user space of the previous node.
202 * If we have reached the end of the list, we return NULL. The
203 * end of the list is detected when the next pointer of a node
204 * points back to itself, as does the dummy last node's next
205 * pointer. This enables us to detect the end of the list
206 * without needed access to the list data structure itself.
208 * NOTE: We do no checking to ensure that 'prev' is NOT a
211 ****************************************************************************/
213 LST_BUCKET *n = LST_HEADER (prev);
216 return (n == n->next ? NULL : LST_USERSPACE (n));
219 /* Static globals required by merge() */
221 static LST_BUCKET *z;
222 static int (*cmp) (void *, void *);
225 merge (LST_BUCKET * a, LST_BUCKET * b, LST_BUCKET ** end)
226 /****************************************************************************
229 * Parameters: a,b - Sublist's to merge
230 * Returns: Pointer to the merged sublists.
232 * Description: Merges two sorted lists of nodes together into a single
235 ****************************************************************************/
239 /* Go through the lists, merging them together in sorted order */
242 while (a != z && b != z)
244 if ((*cmp) (LST_USERSPACE (a), LST_USERSPACE (b)) <= 0)
258 /* If one of the lists is not exhausted, then re-attach it to the end
259 * of the newly merged list
267 /* Set *end to point to the end of the newly merged list */
273 /* Determine the start of the merged lists, and reset z to point to
283 lst_mergesort (LIST * l, int (*cmp_func) (void *, void *))
284 /****************************************************************************
286 * Function: lst_mergesort
287 * Parameters: l - List to merge sort
288 * cmp_func - Function to compare two user spaces
290 * Description: Mergesort's all the nodes in the list. 'cmp' must point to
291 * a comparison function that can compare the user spaces of
292 * two different nodes. 'cmp' should work the same as
293 * strcmp(), in terms of the values it returns.
295 ****************************************************************************/
298 LST_BUCKET *a, *b; /* Pointers to sublists to merge */
299 LST_BUCKET *c; /* Pointer to end of sorted sublists */
300 LST_BUCKET *head; /* Pointer to dummy head node for list */
301 LST_BUCKET *todo; /* Pointer to sublists yet to be sorted */
302 LST_BUCKET *t; /* Temporary */
304 /* Set up globals required by merge() and pointer to head */
310 for (N = 1, a = z; a != head->next; N = N + N)
317 /* Build first sublist to be merged, and splice from main list
321 for (i = 1; i < N; i++)
327 /* Build second sublist to be merged and splice from main list
330 for (i = 1; i < N; i++)
335 /* Merge the two sublists created, and set 'c' to point to the
336 * end of the newly merged sublists.
339 c->next = merge (a, b, &t);
347 /*---------------------------------------------------------------*/
348 /*---------------------------------------------------------------*/
350 /* Simple program to test the list routines */
359 /*---------------------------------------------------------------*/
362 my_cmp (REC * r1, REC * r2)
364 return strcmp (r1->name, r2->name);
367 /*---------------------------------------------------------------*/
379 printf ("Type a list of names and ages. Empty line quits\n\n");
383 rec = lst_newnode (sizeof (REC));
385 if ((done = (line[0] == '\0')) != 1)
387 strcpy (rec->name, line);
389 rec->age = atoi (line);
390 lst_insertafter (list, rec, LST_HEAD (list));
394 printf ("\nThe list you typed in was:\n\n");
396 for (rec = lst_first (list); rec; rec = lst_next (rec))
397 printf ("Name: %s, Age: %d\n", rec->name, rec->age);
399 printf ("\nSorting the list...\n\n");
401 lst_mergesort (list, my_cmp);
403 for (rec = lst_first (list); rec; rec = lst_next (rec))
404 printf ("Name: %s, Age: %d\n", rec->name, rec->age);
406 lst_kill (list, lst_freenode);
409 /*---------------------------------------------------------------*/