WSTester updated to work plus hopefully all the other changes that need to go into...
[jabaws.git] / binaries / src / ViennaRNA / lib / list.c
diff --git a/binaries/src/ViennaRNA/lib/list.c b/binaries/src/ViennaRNA/lib/list.c
new file mode 100644 (file)
index 0000000..da0ae5b
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+  $Log: list.c,v $
+  Revision 1.5  2003/07/14 13:36:58  ivo
+  use space() instead of malloc
+
+  Revision 1.4  2000/10/10 08:53:52  ivo
+  include dmalloc.h header if DMALLOC defined
+
+  Revision 1.4  2000/10/10 08:04:34  ivo
+  include dmalloc header id DMALLOC defined
+
+  Revision 1.3  1998/03/30 14:24:51  ivo
+  use RNA package utils.h
+
+  Revision 1.2  1997/10/09  19:01:50  steve
+  *** empty log message ***
+
+  Revision 1.1  1997/08/04 21:05:32  walter
+  Initial revision
+
+*/
+/*
+   (C) 1991 Kendall Bennett.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "utils.h"
+#include "list.h"
+
+/*@unused@*/
+static char rcsid[] = "$Id: list.c,v 1.5 2003/07/14 13:36:58 ivo Exp $";
+
+#define PUBLIC
+PUBLIC void *
+lst_newnode (int size)
+/****************************************************************************
+*
+* Function:    lst_newnode
+* Parameters:  size - Amount of memory to allocate for node
+* Returns:      Pointer to the allocated node's user space.
+*
+* Description: Allocates the memory required for a node, adding a small
+*              header at the start of the node. We return a reference to
+*              the user space of the node, as if it had been allocated via
+*              malloc().
+*
+****************************************************************************/
+{
+  LST_BUCKET *node;
+
+  node = (LST_BUCKET *) space (size + sizeof (LST_BUCKET));
+
+  return LST_USERSPACE (node); /* Return pointer to user space */
+}
+
+PUBLIC void
+lst_freenode (void *node)
+/****************************************************************************
+*
+* Function:    lst_freenode
+* Parameters:  node - Node to free.
+*
+* Description:  Frees a node previously allocated with lst_newnode().
+*
+****************************************************************************/
+{
+  free (LST_HEADER (node));
+}
+
+PUBLIC LIST *
+lst_init (void)
+/****************************************************************************
+*
+* Function:    lst_init
+* Returns:      Pointer to a newly created list.
+*
+* Description: Initialises a list and returns a pointer to it.
+*
+****************************************************************************/
+{
+  LIST *l;
+
+  if ((l = (LIST *) space (sizeof (LIST))) != NULL)
+    {
+      l->count = 0;
+      l->head = &(l->hz[0]);
+      l->z = &(l->hz[1]);
+      l->head->next = l->z->next = l->z;
+    }
+
+  return l;
+}
+
+PUBLIC void
+lst_kill (LIST * l, void (*freeNode) (void *node))
+/****************************************************************************
+*
+* Function:    lst_kill
+* Parameters:  l - List to kill
+*              freeNode - Pointer to user routine to free a node
+*
+* Description: Kills the list l, by deleting all of the elements contained
+*              within the list one by one and then deleting the list
+*              itself. Note that we call the user supplied routine
+*              (*freeNode)() to free each list node. This allows the user
+*              program to perform any extra processing needed to kill each
+*              node (if each node contains pointers to other items on the
+*              heap for example). If no extra processing is required, just
+*              pass the address of lst_freenode(), ie:
+*
+*              lst_kill(myList,lst_freenode);
+*
+****************************************************************************/
+{
+  LST_BUCKET *n, *p;
+
+  n = l->head->next;
+  while (n != l->z)
+    {                          /* Free all nodes in list  */
+      p = n;
+      n = n->next;
+      (*freeNode) (LST_USERSPACE (p));
+    }
+  free (l);                    /* Free the list itself    */
+}
+
+PUBLIC void
+lst_insertafter (LIST * l, void *node, void *after)
+/****************************************************************************
+*
+* Function:    lst_insertafter
+* Parameters:  l - List to insert node into
+*              node - Pointer to user space of node to insert
+*              after - Pointer to user space of node to insert node after
+*
+* Description: Inserts a new node into the list after the node 'after'. To
+*              insert a new node at the beginning of the list, user the
+*              macro LST_HEAD in place of 'after'. ie:
+*
+*              lst_insertafter(mylist,node,LST_HEAD(mylist));
+*
+****************************************************************************/
+{
+  LST_BUCKET *n = LST_HEADER (node), *a = LST_HEADER (after);
+
+  n->next = a->next;
+  a->next = n;
+  l->count++;
+}
+
+PUBLIC void *
+lst_deletenext (LIST * l, void *node)
+/****************************************************************************
+*
+* Function:    lst_deletenext
+* Parameters:  l - List to delete node from.
+*              node - Node to delete the next node from
+* Returns:     Pointer to the deleted node's userspace.
+*
+* Description: Removes the node AFTER 'node' from the list l.
+*
+****************************************************************************/
+{
+  LST_BUCKET *n = LST_HEADER (node);
+
+  node = LST_USERSPACE (n->next);
+  n->next = n->next->next;
+  l->count--;
+  return node;
+}
+
+PUBLIC void *
+lst_first (LIST * l)
+/****************************************************************************
+*
+* Function:    lst_first
+* Parameters:  l - List to obtain first node from
+* Returns:     Pointer to first node in list, NULL if list is empty.
+*
+* Description: Returns a pointer to the user space of the first node in
+*              the list. If the list is empty, we return NULL.
+*
+****************************************************************************/
+{
+  LST_BUCKET *n;
+
+  n = l->head->next;
+  return (n == l->z ? NULL : LST_USERSPACE (n));
+}
+
+PUBLIC void *
+lst_next (void *prev)
+/****************************************************************************
+*
+* Function:    lst_next
+* Parameters:  prev - Previous node in list to obtain next node from
+* Returns:     Pointer to the next node in the list, NULL at end of list.
+*
+* Description: Returns a pointer to the user space of the next node in the
+*              list given a pointer to the user space of the previous node.
+*              If we have reached the end of the list, we return NULL. The
+*              end of the list is detected when the next pointer of a node
+*              points back to itself, as does the dummy last node's next
+*              pointer. This enables us to detect the end of the list
+*              without needed access to the list data structure itself.
+*
+*              NOTE:   We do no checking to ensure that 'prev' is NOT a
+*                      NULL pointer.
+*
+****************************************************************************/
+{
+  LST_BUCKET *n = LST_HEADER (prev);
+
+  n = n->next;
+  return (n == n->next ? NULL : LST_USERSPACE (n));
+}
+
+/* Static globals required by merge()   */
+
+static LST_BUCKET *z;
+static int (*cmp) (void *, void *);
+
+static LST_BUCKET *
+merge (LST_BUCKET * a, LST_BUCKET * b, LST_BUCKET ** end)
+/****************************************************************************
+*
+* Function:    merge
+* Parameters:  a,b - Sublist's to merge
+* Returns:     Pointer to the merged sublists.
+*
+* Description: Merges two sorted lists of nodes together into a single
+*              sorted list.
+*
+****************************************************************************/
+{
+  LST_BUCKET *c;
+
+  /* Go through the lists, merging them together in sorted order  */
+
+  c = z;
+  while (a != z && b != z)
+    {
+      if ((*cmp) (LST_USERSPACE (a), LST_USERSPACE (b)) <= 0)
+       {
+         c->next = a;
+         c = a;
+         a = a->next;
+       }
+      else
+       {
+         c->next = b;
+         c = b;
+         b = b->next;
+       }
+    };
+
+  /* If one of the lists is not exhausted, then re-attach it to the end
+   * of the newly merged list
+   */
+
+  if (a != z)
+    c->next = a;
+  if (b != z)
+    c->next = b;
+
+  /* Set *end to point to the end of the newly merged list        */
+
+  while (c->next != z)
+    c = c->next;
+  *end = c;
+
+  /* Determine the start of the merged lists, and reset z to point to
+   * itself
+   */
+
+  c = z->next;
+  z->next = z;
+  return c;
+}
+
+PUBLIC void
+lst_mergesort (LIST * l, int (*cmp_func) (void *, void *))
+/****************************************************************************
+*
+* Function:    lst_mergesort
+* Parameters:  l - List to merge sort
+*              cmp_func - Function to compare two user spaces
+*
+* Description: Mergesort's all the nodes in the list. 'cmp' must point to
+*              a comparison function that can compare the user spaces of
+*              two different nodes. 'cmp' should work the same as
+*              strcmp(), in terms of the values it returns.
+*
+****************************************************************************/
+{
+  int i, N;
+  LST_BUCKET *a, *b;           /* Pointers to sublists to merge                */
+  LST_BUCKET *c;               /* Pointer to end of sorted sublists            */
+  LST_BUCKET *head;            /* Pointer to dummy head node for list          */
+  LST_BUCKET *todo;            /* Pointer to sublists yet to be sorted         */
+  LST_BUCKET *t;               /* Temporary                                                            */
+
+  /* Set up globals required by merge() and pointer to head       */
+
+  z = l->z;
+  cmp = cmp_func;
+  head = l->head;
+
+  for (N = 1, a = z; a != head->next; N = N + N)
+    {
+      todo = head->next;
+      c = head;
+      while (todo != z)
+       {
+
+         /* Build first sublist to be merged, and splice from main list
+          */
+
+         a = t = todo;
+         for (i = 1; i < N; i++)
+           t = t->next;
+         b = t->next;
+         t->next = z;
+         t = b;
+
+         /* Build second sublist to be merged and splice from main list
+          */
+
+         for (i = 1; i < N; i++)
+           t = t->next;
+         todo = t->next;
+         t->next = z;
+
+         /* Merge the two sublists created, and set 'c' to point to the
+          * end of the newly merged sublists.
+          */
+
+         c->next = merge (a, b, &t);
+         c = t;
+       }
+    }
+}
+
+#ifdef LIST_TEST
+
+/*---------------------------------------------------------------*/
+/*---------------------------------------------------------------*/
+
+/* Simple program to test the list routines */
+
+typedef struct
+{
+  char name[40];
+  int age;
+}
+REC;
+
+/*---------------------------------------------------------------*/
+
+int
+my_cmp (REC * r1, REC * r2)
+{
+  return strcmp (r1->name, r2->name);
+}
+
+/*---------------------------------------------------------------*/
+
+void
+main (void)
+{
+  LIST *list;
+  int done = 0;
+  REC *rec;
+  char line[80];
+
+  list = lst_init ();
+
+  printf ("Type a list of names and ages. Empty line quits\n\n");
+
+  while (!done)
+    {
+      rec = lst_newnode (sizeof (REC));
+      gets (line);
+      if ((done = (line[0] == '\0')) != 1)
+       {
+         strcpy (rec->name, line);
+         gets (line);
+         rec->age = atoi (line);
+         lst_insertafter (list, rec, LST_HEAD (list));
+       }
+    };
+
+  printf ("\nThe list you typed in was:\n\n");
+
+  for (rec = lst_first (list); rec; rec = lst_next (rec))
+    printf ("Name: %s, Age: %d\n", rec->name, rec->age);
+
+  printf ("\nSorting the list...\n\n");
+
+  lst_mergesort (list, my_cmp);
+
+  for (rec = lst_first (list); rec; rec = lst_next (rec))
+    printf ("Name: %s, Age: %d\n", rec->name, rec->age);
+
+  lst_kill (list, lst_freenode);
+}
+
+/*---------------------------------------------------------------*/
+
+#endif