mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Moved taxonomy source code to a dependencies subdir for separation of
dependencies.
This commit is contained in:
@@ -1,890 +0,0 @@
|
||||
/* Produced by texiweb from libavl.w on 2002/08/24 at 13:21. */
|
||||
|
||||
/* libavl - library for manipulation of binary trees.
|
||||
Copyright (C) 1998-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The author may be contacted at <blp@gnu.org> on the Internet, or
|
||||
write to Ben Pfaff, Stanford University, Computer Science Dept., 353
|
||||
Serra Mall, Stanford CA 94305, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "avl.h"
|
||||
|
||||
/* Creates and returns a new table
|
||||
with comparison function |compare| using parameter |param|
|
||||
and memory allocator |allocator|.
|
||||
Returns |NULL| if memory allocation failed. */
|
||||
struct avl_table *
|
||||
avl_create (avl_comparison_func *compare, void *param,
|
||||
struct libavl_allocator *allocator)
|
||||
{
|
||||
struct avl_table *tree;
|
||||
|
||||
assert (compare != NULL);
|
||||
|
||||
if (allocator == NULL)
|
||||
allocator = &avl_allocator_default;
|
||||
|
||||
tree = allocator->libavl_malloc (allocator, sizeof *tree);
|
||||
if (tree == NULL)
|
||||
return NULL;
|
||||
|
||||
tree->avl_root = NULL;
|
||||
tree->avl_compare = compare;
|
||||
tree->avl_param = param;
|
||||
tree->avl_alloc = allocator;
|
||||
tree->avl_count = 0;
|
||||
tree->avl_generation = 0;
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* Search |tree| for an item matching |item|, and return it if found.
|
||||
Otherwise return |NULL|. */
|
||||
void *
|
||||
avl_find (const struct avl_table *tree, const void *item)
|
||||
{
|
||||
const struct avl_node *p;
|
||||
|
||||
assert (tree != NULL && item != NULL);
|
||||
for (p = tree->avl_root; p != NULL; )
|
||||
{
|
||||
int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
|
||||
|
||||
if (cmp < 0)
|
||||
p = p->avl_link[0];
|
||||
else if (cmp > 0)
|
||||
p = p->avl_link[1];
|
||||
else /* |cmp == 0| */
|
||||
return p->avl_data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Inserts |item| into |tree| and returns a pointer to |item|'s address.
|
||||
If a duplicate item is found in the tree,
|
||||
returns a pointer to the duplicate without inserting |item|.
|
||||
Returns |NULL| in case of memory allocation failure. */
|
||||
void **
|
||||
avl_probe (struct avl_table *tree, void *item)
|
||||
{
|
||||
struct avl_node *y, *z; /* Top node to update balance factor, and parent. */
|
||||
struct avl_node *p, *q; /* Iterator, and parent. */
|
||||
struct avl_node *n; /* Newly inserted node. */
|
||||
struct avl_node *w; /* New root of rebalanced subtree. */
|
||||
int dir; /* Direction to descend. */
|
||||
|
||||
unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */
|
||||
int k = 0; /* Number of cached results. */
|
||||
|
||||
assert (tree != NULL && item != NULL);
|
||||
|
||||
z = (struct avl_node *) &tree->avl_root;
|
||||
y = tree->avl_root;
|
||||
dir = 0;
|
||||
for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir])
|
||||
{
|
||||
int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
|
||||
if (cmp == 0)
|
||||
return &p->avl_data;
|
||||
|
||||
if (p->avl_balance != 0)
|
||||
z = q, y = p, k = 0;
|
||||
da[k++] = dir = cmp > 0;
|
||||
}
|
||||
|
||||
n = q->avl_link[dir] =
|
||||
tree->avl_alloc->libavl_malloc (tree->avl_alloc, sizeof *n);
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
|
||||
tree->avl_count++;
|
||||
n->avl_data = item;
|
||||
n->avl_link[0] = n->avl_link[1] = NULL;
|
||||
n->avl_balance = 0;
|
||||
if (y == NULL)
|
||||
return &n->avl_data;
|
||||
|
||||
for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++)
|
||||
if (da[k] == 0)
|
||||
p->avl_balance--;
|
||||
else
|
||||
p->avl_balance++;
|
||||
|
||||
if (y->avl_balance == -2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[0];
|
||||
if (x->avl_balance == -1)
|
||||
{
|
||||
w = x;
|
||||
y->avl_link[0] = x->avl_link[1];
|
||||
x->avl_link[1] = y;
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (x->avl_balance == +1);
|
||||
w = x->avl_link[1];
|
||||
x->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = x;
|
||||
y->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = y;
|
||||
if (w->avl_balance == -1)
|
||||
x->avl_balance = 0, y->avl_balance = +1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == +1| */
|
||||
x->avl_balance = -1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
else if (y->avl_balance == +2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[1];
|
||||
if (x->avl_balance == +1)
|
||||
{
|
||||
w = x;
|
||||
y->avl_link[1] = x->avl_link[0];
|
||||
x->avl_link[0] = y;
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (x->avl_balance == -1);
|
||||
w = x->avl_link[0];
|
||||
x->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = x;
|
||||
y->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = y;
|
||||
if (w->avl_balance == +1)
|
||||
x->avl_balance = 0, y->avl_balance = -1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == -1| */
|
||||
x->avl_balance = +1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return &n->avl_data;
|
||||
z->avl_link[y != z->avl_link[0]] = w;
|
||||
|
||||
tree->avl_generation++;
|
||||
return &n->avl_data;
|
||||
}
|
||||
|
||||
/* Inserts |item| into |table|.
|
||||
Returns |NULL| if |item| was successfully inserted
|
||||
or if a memory allocation error occurred.
|
||||
Otherwise, returns the duplicate item. */
|
||||
void *
|
||||
avl_insert (struct avl_table *table, void *item)
|
||||
{
|
||||
void **p = avl_probe (table, item);
|
||||
return p == NULL || *p == item ? NULL : *p;
|
||||
}
|
||||
|
||||
/* Inserts |item| into |table|, replacing any duplicate item.
|
||||
Returns |NULL| if |item| was inserted without replacing a duplicate,
|
||||
or if a memory allocation error occurred.
|
||||
Otherwise, returns the item that was replaced. */
|
||||
void *
|
||||
avl_replace (struct avl_table *table, void *item)
|
||||
{
|
||||
void **p = avl_probe (table, item);
|
||||
if (p == NULL || *p == item)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
void *r = *p;
|
||||
*p = item;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Deletes from |tree| and returns an item matching |item|.
|
||||
Returns a null pointer if no matching item found. */
|
||||
void *
|
||||
avl_delete (struct avl_table *tree, const void *item)
|
||||
{
|
||||
/* Stack of nodes. */
|
||||
struct avl_node *pa[AVL_MAX_HEIGHT]; /* Nodes. */
|
||||
unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
|
||||
int k; /* Stack pointer. */
|
||||
|
||||
struct avl_node *p; /* Traverses tree to find node to delete. */
|
||||
int cmp; /* Result of comparison between |item| and |p|. */
|
||||
|
||||
assert (tree != NULL && item != NULL);
|
||||
|
||||
k = 0;
|
||||
p = (struct avl_node *) &tree->avl_root;
|
||||
for (cmp = -1; cmp != 0;
|
||||
cmp = tree->avl_compare (item, p->avl_data, tree->avl_param))
|
||||
{
|
||||
int dir = cmp > 0;
|
||||
|
||||
pa[k] = p;
|
||||
da[k++] = dir;
|
||||
|
||||
p = p->avl_link[dir];
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
}
|
||||
item = p->avl_data;
|
||||
|
||||
if (p->avl_link[1] == NULL)
|
||||
pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
|
||||
else
|
||||
{
|
||||
struct avl_node *r = p->avl_link[1];
|
||||
if (r->avl_link[0] == NULL)
|
||||
{
|
||||
r->avl_link[0] = p->avl_link[0];
|
||||
r->avl_balance = p->avl_balance;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = r;
|
||||
da[k] = 1;
|
||||
pa[k++] = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avl_node *s;
|
||||
int j = k++;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
da[k] = 0;
|
||||
pa[k++] = r;
|
||||
s = r->avl_link[0];
|
||||
if (s->avl_link[0] == NULL)
|
||||
break;
|
||||
|
||||
r = s;
|
||||
}
|
||||
|
||||
s->avl_link[0] = p->avl_link[0];
|
||||
r->avl_link[0] = s->avl_link[1];
|
||||
s->avl_link[1] = p->avl_link[1];
|
||||
s->avl_balance = p->avl_balance;
|
||||
|
||||
pa[j - 1]->avl_link[da[j - 1]] = s;
|
||||
da[j] = 1;
|
||||
pa[j] = s;
|
||||
}
|
||||
}
|
||||
|
||||
tree->avl_alloc->libavl_free (tree->avl_alloc, p);
|
||||
|
||||
assert (k > 0);
|
||||
while (--k > 0)
|
||||
{
|
||||
struct avl_node *y = pa[k];
|
||||
|
||||
if (da[k] == 0)
|
||||
{
|
||||
y->avl_balance++;
|
||||
if (y->avl_balance == +1)
|
||||
break;
|
||||
else if (y->avl_balance == +2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[1];
|
||||
if (x->avl_balance == -1)
|
||||
{
|
||||
struct avl_node *w;
|
||||
assert (x->avl_balance == -1);
|
||||
w = x->avl_link[0];
|
||||
x->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = x;
|
||||
y->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = y;
|
||||
if (w->avl_balance == +1)
|
||||
x->avl_balance = 0, y->avl_balance = -1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == -1| */
|
||||
x->avl_balance = +1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
y->avl_link[1] = x->avl_link[0];
|
||||
x->avl_link[0] = y;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = x;
|
||||
if (x->avl_balance == 0)
|
||||
{
|
||||
x->avl_balance = -1;
|
||||
y->avl_balance = +1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
y->avl_balance--;
|
||||
if (y->avl_balance == -1)
|
||||
break;
|
||||
else if (y->avl_balance == -2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[0];
|
||||
if (x->avl_balance == +1)
|
||||
{
|
||||
struct avl_node *w;
|
||||
assert (x->avl_balance == +1);
|
||||
w = x->avl_link[1];
|
||||
x->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = x;
|
||||
y->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = y;
|
||||
if (w->avl_balance == -1)
|
||||
x->avl_balance = 0, y->avl_balance = +1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == +1| */
|
||||
x->avl_balance = -1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
y->avl_link[0] = x->avl_link[1];
|
||||
x->avl_link[1] = y;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = x;
|
||||
if (x->avl_balance == 0)
|
||||
{
|
||||
x->avl_balance = +1;
|
||||
y->avl_balance = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tree->avl_count--;
|
||||
tree->avl_generation++;
|
||||
return (void *) item;
|
||||
}
|
||||
|
||||
/* Refreshes the stack of parent pointers in |trav|
|
||||
and updates its generation number. */
|
||||
static void
|
||||
trav_refresh (struct avl_traverser *trav)
|
||||
{
|
||||
assert (trav != NULL);
|
||||
|
||||
trav->avl_generation = trav->avl_table->avl_generation;
|
||||
|
||||
if (trav->avl_node != NULL)
|
||||
{
|
||||
avl_comparison_func *cmp = trav->avl_table->avl_compare;
|
||||
void *param = trav->avl_table->avl_param;
|
||||
struct avl_node *node = trav->avl_node;
|
||||
struct avl_node *i;
|
||||
|
||||
trav->avl_height = 0;
|
||||
for (i = trav->avl_table->avl_root; i != node; )
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
assert (i != NULL);
|
||||
|
||||
trav->avl_stack[trav->avl_height++] = i;
|
||||
i = i->avl_link[cmp (node->avl_data, i->avl_data, param) > 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes |trav| for use with |tree|
|
||||
and selects the null node. */
|
||||
void
|
||||
avl_t_init (struct avl_traverser *trav, struct avl_table *tree)
|
||||
{
|
||||
trav->avl_table = tree;
|
||||
trav->avl_node = NULL;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
}
|
||||
|
||||
/* Initializes |trav| for |tree|
|
||||
and selects and returns a pointer to its least-valued item.
|
||||
Returns |NULL| if |tree| contains no nodes. */
|
||||
void *
|
||||
avl_t_first (struct avl_traverser *trav, struct avl_table *tree)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (tree != NULL && trav != NULL);
|
||||
|
||||
trav->avl_table = tree;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
|
||||
x = tree->avl_root;
|
||||
if (x != NULL)
|
||||
while (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[0];
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x != NULL ? x->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Initializes |trav| for |tree|
|
||||
and selects and returns a pointer to its greatest-valued item.
|
||||
Returns |NULL| if |tree| contains no nodes. */
|
||||
void *
|
||||
avl_t_last (struct avl_traverser *trav, struct avl_table *tree)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (tree != NULL && trav != NULL);
|
||||
|
||||
trav->avl_table = tree;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
|
||||
x = tree->avl_root;
|
||||
if (x != NULL)
|
||||
while (x->avl_link[1] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[1];
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x != NULL ? x->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Searches for |item| in |tree|.
|
||||
If found, initializes |trav| to the item found and returns the item
|
||||
as well.
|
||||
If there is no matching item, initializes |trav| to the null item
|
||||
and returns |NULL|. */
|
||||
void *
|
||||
avl_t_find (struct avl_traverser *trav, struct avl_table *tree, void *item)
|
||||
{
|
||||
struct avl_node *p, *q;
|
||||
|
||||
assert (trav != NULL && tree != NULL && item != NULL);
|
||||
trav->avl_table = tree;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
for (p = tree->avl_root; p != NULL; p = q)
|
||||
{
|
||||
int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
|
||||
|
||||
if (cmp < 0)
|
||||
q = p->avl_link[0];
|
||||
else if (cmp > 0)
|
||||
q = p->avl_link[1];
|
||||
else /* |cmp == 0| */
|
||||
{
|
||||
trav->avl_node = p;
|
||||
return p->avl_data;
|
||||
}
|
||||
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = p;
|
||||
}
|
||||
|
||||
trav->avl_height = 0;
|
||||
trav->avl_node = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Attempts to insert |item| into |tree|.
|
||||
If |item| is inserted successfully, it is returned and |trav| is
|
||||
initialized to its location.
|
||||
If a duplicate is found, it is returned and |trav| is initialized to
|
||||
its location. No replacement of the item occurs.
|
||||
If a memory allocation failure occurs, |NULL| is returned and |trav|
|
||||
is initialized to the null item. */
|
||||
void *
|
||||
avl_t_insert (struct avl_traverser *trav, struct avl_table *tree, void *item)
|
||||
{
|
||||
void **p;
|
||||
|
||||
assert (trav != NULL && tree != NULL && item != NULL);
|
||||
|
||||
p = avl_probe (tree, item);
|
||||
if (p != NULL)
|
||||
{
|
||||
trav->avl_table = tree;
|
||||
trav->avl_node =
|
||||
((struct avl_node *)
|
||||
((char *) p - offsetof (struct avl_node, avl_data)));
|
||||
trav->avl_generation = tree->avl_generation - 1;
|
||||
return *p;
|
||||
}
|
||||
else
|
||||
{
|
||||
avl_t_init (trav, tree);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes |trav| to have the same current node as |src|. */
|
||||
void *
|
||||
avl_t_copy (struct avl_traverser *trav, const struct avl_traverser *src)
|
||||
{
|
||||
assert (trav != NULL && src != NULL);
|
||||
|
||||
if (trav != src)
|
||||
{
|
||||
trav->avl_table = src->avl_table;
|
||||
trav->avl_node = src->avl_node;
|
||||
trav->avl_generation = src->avl_generation;
|
||||
if (trav->avl_generation == trav->avl_table->avl_generation)
|
||||
{
|
||||
trav->avl_height = src->avl_height;
|
||||
memcpy (trav->avl_stack, (const void *) src->avl_stack,
|
||||
sizeof *trav->avl_stack * trav->avl_height);
|
||||
}
|
||||
}
|
||||
|
||||
return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Returns the next data item in inorder
|
||||
within the tree being traversed with |trav|,
|
||||
or if there are no more data items returns |NULL|. */
|
||||
void *
|
||||
avl_t_next (struct avl_traverser *trav)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (trav != NULL);
|
||||
|
||||
if (trav->avl_generation != trav->avl_table->avl_generation)
|
||||
trav_refresh (trav);
|
||||
|
||||
x = trav->avl_node;
|
||||
if (x == NULL)
|
||||
{
|
||||
return avl_t_first (trav, trav->avl_table);
|
||||
}
|
||||
else if (x->avl_link[1] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[1];
|
||||
|
||||
while (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avl_node *y;
|
||||
|
||||
do
|
||||
{
|
||||
if (trav->avl_height == 0)
|
||||
{
|
||||
trav->avl_node = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
y = x;
|
||||
x = trav->avl_stack[--trav->avl_height];
|
||||
}
|
||||
while (y == x->avl_link[1]);
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x->avl_data;
|
||||
}
|
||||
|
||||
/* Returns the previous data item in inorder
|
||||
within the tree being traversed with |trav|,
|
||||
or if there are no more data items returns |NULL|. */
|
||||
void *
|
||||
avl_t_prev (struct avl_traverser *trav)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (trav != NULL);
|
||||
|
||||
if (trav->avl_generation != trav->avl_table->avl_generation)
|
||||
trav_refresh (trav);
|
||||
|
||||
x = trav->avl_node;
|
||||
if (x == NULL)
|
||||
{
|
||||
return avl_t_last (trav, trav->avl_table);
|
||||
}
|
||||
else if (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[0];
|
||||
|
||||
while (x->avl_link[1] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avl_node *y;
|
||||
|
||||
do
|
||||
{
|
||||
if (trav->avl_height == 0)
|
||||
{
|
||||
trav->avl_node = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
y = x;
|
||||
x = trav->avl_stack[--trav->avl_height];
|
||||
}
|
||||
while (y == x->avl_link[0]);
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x->avl_data;
|
||||
}
|
||||
|
||||
/* Returns |trav|'s current item. */
|
||||
void *
|
||||
avl_t_cur (struct avl_traverser *trav)
|
||||
{
|
||||
assert (trav != NULL);
|
||||
|
||||
return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Replaces the current item in |trav| by |new| and returns the item replaced.
|
||||
|trav| must not have the null item selected.
|
||||
The new item must not upset the ordering of the tree. */
|
||||
void *
|
||||
avl_t_replace (struct avl_traverser *trav, void *new)
|
||||
{
|
||||
void *old;
|
||||
|
||||
assert (trav != NULL && trav->avl_node != NULL && new != NULL);
|
||||
old = trav->avl_node->avl_data;
|
||||
trav->avl_node->avl_data = new;
|
||||
return old;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_error_recovery (struct avl_node **stack, int height,
|
||||
struct avl_table *new, avl_item_func *destroy)
|
||||
{
|
||||
assert (stack != NULL && height >= 0 && new != NULL);
|
||||
|
||||
for (; height > 2; height -= 2)
|
||||
stack[height - 1]->avl_link[1] = NULL;
|
||||
avl_destroy (new, destroy);
|
||||
}
|
||||
|
||||
/* Copies |org| to a newly created tree, which is returned.
|
||||
If |copy != NULL|, each data item in |org| is first passed to |copy|,
|
||||
and the return values are inserted into the tree,
|
||||
with |NULL| return values taken as indications of failure.
|
||||
On failure, destroys the partially created new tree,
|
||||
applying |destroy|, if non-null, to each item in the new tree so far,
|
||||
and returns |NULL|.
|
||||
If |allocator != NULL|, it is used for allocation in the new tree.
|
||||
Otherwise, the same allocator used for |org| is used. */
|
||||
struct avl_table *
|
||||
avl_copy (const struct avl_table *org, avl_copy_func *copy,
|
||||
avl_item_func *destroy, struct libavl_allocator *allocator)
|
||||
{
|
||||
struct avl_node *stack[2 * (AVL_MAX_HEIGHT + 1)];
|
||||
int height = 0;
|
||||
|
||||
struct avl_table *new;
|
||||
const struct avl_node *x;
|
||||
struct avl_node *y;
|
||||
|
||||
assert (org != NULL);
|
||||
new = avl_create (org->avl_compare, org->avl_param,
|
||||
allocator != NULL ? allocator : org->avl_alloc);
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
new->avl_count = org->avl_count;
|
||||
if (new->avl_count == 0)
|
||||
return new;
|
||||
|
||||
x = (const struct avl_node *) &org->avl_root;
|
||||
y = (struct avl_node *) &new->avl_root;
|
||||
for (;;)
|
||||
{
|
||||
while (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (height < 2 * (AVL_MAX_HEIGHT + 1));
|
||||
|
||||
y->avl_link[0] =
|
||||
new->avl_alloc->libavl_malloc (new->avl_alloc,
|
||||
sizeof *y->avl_link[0]);
|
||||
if (y->avl_link[0] == NULL)
|
||||
{
|
||||
if (y != (struct avl_node *) &new->avl_root)
|
||||
{
|
||||
y->avl_data = NULL;
|
||||
y->avl_link[1] = NULL;
|
||||
}
|
||||
|
||||
copy_error_recovery (stack, height, new, destroy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack[height++] = (struct avl_node *) x;
|
||||
stack[height++] = y;
|
||||
x = x->avl_link[0];
|
||||
y = y->avl_link[0];
|
||||
}
|
||||
y->avl_link[0] = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
y->avl_balance = x->avl_balance;
|
||||
if (copy == NULL)
|
||||
y->avl_data = x->avl_data;
|
||||
else
|
||||
{
|
||||
y->avl_data = copy (x->avl_data, org->avl_param);
|
||||
if (y->avl_data == NULL)
|
||||
{
|
||||
y->avl_link[1] = NULL;
|
||||
copy_error_recovery (stack, height, new, destroy);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (x->avl_link[1] != NULL)
|
||||
{
|
||||
y->avl_link[1] =
|
||||
new->avl_alloc->libavl_malloc (new->avl_alloc,
|
||||
sizeof *y->avl_link[1]);
|
||||
if (y->avl_link[1] == NULL)
|
||||
{
|
||||
copy_error_recovery (stack, height, new, destroy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
x = x->avl_link[1];
|
||||
y = y->avl_link[1];
|
||||
break;
|
||||
}
|
||||
else
|
||||
y->avl_link[1] = NULL;
|
||||
|
||||
if (height <= 2)
|
||||
return new;
|
||||
|
||||
y = stack[--height];
|
||||
x = stack[--height];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Frees storage allocated for |tree|.
|
||||
If |destroy != NULL|, applies it to each data item in inorder. */
|
||||
void
|
||||
avl_destroy (struct avl_table *tree, avl_item_func *destroy)
|
||||
{
|
||||
struct avl_node *p, *q;
|
||||
|
||||
assert (tree != NULL);
|
||||
|
||||
for (p = tree->avl_root; p != NULL; p = q)
|
||||
if (p->avl_link[0] == NULL)
|
||||
{
|
||||
q = p->avl_link[1];
|
||||
if (destroy != NULL && p->avl_data != NULL)
|
||||
destroy (p->avl_data, tree->avl_param);
|
||||
tree->avl_alloc->libavl_free (tree->avl_alloc, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
q = p->avl_link[0];
|
||||
p->avl_link[0] = q->avl_link[1];
|
||||
q->avl_link[1] = p;
|
||||
}
|
||||
|
||||
tree->avl_alloc->libavl_free (tree->avl_alloc, tree);
|
||||
}
|
||||
|
||||
/* Allocates |size| bytes of space using |malloc()|.
|
||||
Returns a null pointer if allocation fails. */
|
||||
void *
|
||||
avl_malloc (struct libavl_allocator *allocator, size_t size)
|
||||
{
|
||||
assert (allocator != NULL && size > 0);
|
||||
return malloc (size);
|
||||
}
|
||||
|
||||
/* Frees |block|. */
|
||||
void
|
||||
avl_free (struct libavl_allocator *allocator, void *block)
|
||||
{
|
||||
assert (allocator != NULL && block != NULL);
|
||||
free (block);
|
||||
}
|
||||
|
||||
/* Default memory allocator that uses |malloc()| and |free()|. */
|
||||
struct libavl_allocator avl_allocator_default =
|
||||
{
|
||||
avl_malloc,
|
||||
avl_free
|
||||
};
|
||||
|
||||
#undef NDEBUG
|
||||
#include <assert.h>
|
||||
|
||||
/* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */
|
||||
void
|
||||
(avl_assert_insert) (struct avl_table *table, void *item)
|
||||
{
|
||||
void **p = avl_probe (table, item);
|
||||
assert (p != NULL && *p == item);
|
||||
}
|
||||
|
||||
/* Asserts that |avl_delete()| really removes |item| from |table|,
|
||||
and returns the removed item. */
|
||||
void *
|
||||
(avl_assert_delete) (struct avl_table *table, void *item)
|
||||
{
|
||||
void *p = avl_delete (table, item);
|
||||
assert (p != NULL);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/* Produced by texiweb from libavl.w on 2002/08/24 at 13:21. */
|
||||
|
||||
/* libavl - library for manipulation of binary trees.
|
||||
Copyright (C) 1998-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The author may be contacted at <blp@gnu.org> on the Internet, or
|
||||
write to Ben Pfaff, Stanford University, Computer Science Dept., 353
|
||||
Serra Mall, Stanford CA 94305, USA.
|
||||
*/
|
||||
|
||||
#ifndef AVL_H
|
||||
#define AVL_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Function types. */
|
||||
typedef int avl_comparison_func (const void *avl_a, const void *avl_b,
|
||||
void *avl_param);
|
||||
typedef void avl_item_func (void *avl_item, void *avl_param);
|
||||
typedef void *avl_copy_func (void *avl_item, void *avl_param);
|
||||
|
||||
#ifndef LIBAVL_ALLOCATOR
|
||||
#define LIBAVL_ALLOCATOR
|
||||
/* Memory allocator. */
|
||||
struct libavl_allocator
|
||||
{
|
||||
void *(*libavl_malloc) (struct libavl_allocator *, size_t libavl_size);
|
||||
void (*libavl_free) (struct libavl_allocator *, void *libavl_block);
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Default memory allocator. */
|
||||
extern struct libavl_allocator avl_allocator_default;
|
||||
void *avl_malloc (struct libavl_allocator *, size_t);
|
||||
void avl_free (struct libavl_allocator *, void *);
|
||||
|
||||
/* Maximum AVL height. */
|
||||
#ifndef AVL_MAX_HEIGHT
|
||||
#define AVL_MAX_HEIGHT 32
|
||||
#endif
|
||||
|
||||
/* Tree data structure. */
|
||||
struct avl_table
|
||||
{
|
||||
struct avl_node *avl_root; /* Tree's root. */
|
||||
avl_comparison_func *avl_compare; /* Comparison function. */
|
||||
void *avl_param; /* Extra argument to |avl_compare|. */
|
||||
struct libavl_allocator *avl_alloc; /* Memory allocator. */
|
||||
size_t avl_count; /* Number of items in tree. */
|
||||
unsigned long avl_generation; /* Generation number. */
|
||||
};
|
||||
|
||||
/* An AVL tree node. */
|
||||
struct avl_node
|
||||
{
|
||||
struct avl_node *avl_link[2]; /* Subtrees. */
|
||||
void *avl_data; /* Pointer to data. */
|
||||
signed char avl_balance; /* Balance factor. */
|
||||
};
|
||||
|
||||
/* AVL traverser structure. */
|
||||
struct avl_traverser
|
||||
{
|
||||
struct avl_table *avl_table; /* Tree being traversed. */
|
||||
struct avl_node *avl_node; /* Current node in tree. */
|
||||
struct avl_node *avl_stack[AVL_MAX_HEIGHT];
|
||||
/* All the nodes above |avl_node|. */
|
||||
size_t avl_height; /* Number of nodes in |avl_parent|. */
|
||||
unsigned long avl_generation; /* Generation number. */
|
||||
};
|
||||
|
||||
/* Table functions. */
|
||||
struct avl_table *avl_create (avl_comparison_func *, void *,
|
||||
struct libavl_allocator *);
|
||||
struct avl_table *avl_copy (const struct avl_table *, avl_copy_func *,
|
||||
avl_item_func *, struct libavl_allocator *);
|
||||
void avl_destroy (struct avl_table *, avl_item_func *);
|
||||
void **avl_probe (struct avl_table *, void *);
|
||||
void *avl_insert (struct avl_table *, void *);
|
||||
void *avl_replace (struct avl_table *, void *);
|
||||
void *avl_delete (struct avl_table *, const void *);
|
||||
void *avl_find (const struct avl_table *, const void *);
|
||||
void avl_assert_insert (struct avl_table *, void *);
|
||||
void *avl_assert_delete (struct avl_table *, void *);
|
||||
|
||||
#define avl_count(table) ((size_t) (table)->avl_count)
|
||||
|
||||
/* Table traverser functions. */
|
||||
void avl_t_init (struct avl_traverser *, struct avl_table *);
|
||||
void *avl_t_first (struct avl_traverser *, struct avl_table *);
|
||||
void *avl_t_last (struct avl_traverser *, struct avl_table *);
|
||||
void *avl_t_find (struct avl_traverser *, struct avl_table *, void *);
|
||||
void *avl_t_insert (struct avl_traverser *, struct avl_table *, void *);
|
||||
void *avl_t_copy (struct avl_traverser *, const struct avl_traverser *);
|
||||
void *avl_t_next (struct avl_traverser *);
|
||||
void *avl_t_prev (struct avl_traverser *);
|
||||
void *avl_t_cur (struct avl_traverser *);
|
||||
void *avl_t_replace (struct avl_traverser *, void *);
|
||||
|
||||
#endif /* avl.h */
|
||||
@@ -1,22 +0,0 @@
|
||||
COMPILE
|
||||
=======
|
||||
|
||||
On Max OS X:
|
||||
$gcc -o tree2PS-fast -fast avl.c tree2ps.c
|
||||
|
||||
On Linux:
|
||||
|
||||
Insert the following near the top of tree2ps.c
|
||||
|
||||
#define isnumber (c) ( (c>='0') && (c<='9'))
|
||||
|
||||
Replace -fast with -O3 (the letter 'O'):
|
||||
|
||||
$gcc -o tree2PS-fast -O3 avl.c tree2ps.c
|
||||
|
||||
INSTALL
|
||||
=======
|
||||
|
||||
Place the binary into a directory that is listed in setup_paths.sh script located in the root of Galaxy installation
|
||||
|
||||
|
||||
@@ -1,961 +0,0 @@
|
||||
|
||||
#include "avl.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define DEFAULT_STRING_ALLOC 16L
|
||||
#define NUMBER_OF_TAX_FIELDS 22
|
||||
|
||||
char *rankLabels [NUMBER_OF_TAX_FIELDS] =
|
||||
{"root" ,
|
||||
"superkingdom",
|
||||
"kingdom" ,
|
||||
"subkingdom" ,
|
||||
"superphylum" ,
|
||||
"phylum" ,
|
||||
"subphylum" ,
|
||||
"superclass" ,
|
||||
"class" ,
|
||||
"subclass" ,
|
||||
"superorder" ,
|
||||
"order" ,
|
||||
"suborder" ,
|
||||
"superfamily" ,
|
||||
"family" ,
|
||||
"subfamily" ,
|
||||
"tribe" ,
|
||||
"subtribe" ,
|
||||
"genus" ,
|
||||
"subgenus" ,
|
||||
"species" ,
|
||||
"subspecies"
|
||||
};
|
||||
|
||||
static char *const Usage = "tree2ps newick_file ps_output_file max_tree_level (<=0 to show all levels) font_size (in 2-255, 8 is a good default) \nmax_leaves (<=0 to show all) count_duplicate_tax_id (0 or 1; with 0 multiple copies of the same taxid count as 1)\n";
|
||||
char validTaxonNameChar[256];
|
||||
|
||||
long fontSize = 8,
|
||||
showMaxNodes = 0;
|
||||
|
||||
double ySpacing,
|
||||
xPadding,
|
||||
globalXPad,
|
||||
globalYPad,
|
||||
lineWidth = 2.,
|
||||
countScaler;
|
||||
|
||||
char countDuplicateTaxID = 0;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
double _timesCharWidths[256]= // Hardcoded relative widths of all 255 characters in the Times font, for the use of PSTreeString
|
||||
{
|
||||
0,0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0,0.25098,0.721569,0.721569,0.721569,0,0.721569,0.721569,
|
||||
0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0.721569,0,0.721569,0.721569,
|
||||
0.25098,0.333333,0.407843,0.501961,0.501961,0.831373,0.776471,0.180392,0.333333,0.333333,0.501961,0.564706,0.25098,0.333333,0.25098,0.278431,
|
||||
0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,0.278431,0.278431,0.564706,0.564706,0.564706,0.443137,
|
||||
0.921569,0.721569,0.666667,0.666667,0.721569,0.611765,0.556863,0.721569,0.721569,0.333333,0.388235,0.721569,0.611765,0.890196,0.721569,0.721569,
|
||||
0.556863,0.721569,0.666667,0.556863,0.611765,0.721569,0.721569,0.945098,0.721569,0.721569,0.611765,0.333333,0.278431,0.333333,0.470588,0.501961,
|
||||
0.333333,0.443137,0.501961,0.443137,0.501961,0.443137,0.333333,0.501961,0.501961,0.278431,0.278431,0.501961,0.278431,0.776471,0.501961,0.501961,
|
||||
0.501961,0.501961,0.333333,0.388235,0.278431,0.501961,0.501961,0.721569,0.501961,0.501961,0.443137,0.478431,0.2,0.478431,0.541176,0.721569,
|
||||
0.721569,0.721569,0.666667,0.611765,0.721569,0.721569,0.721569,0.443137,0.443137,0.443137,0.443137,0.443137,0.443137,0.443137,0.443137,0.443137,
|
||||
0.443137,0.443137,0.278431,0.278431,0.278431,0.278431,0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,0.501961,
|
||||
0.501961,0.4,0.501961,0.501961,0.501961,0.34902,0.454902,0.501961,0.760784,0.760784,0.980392,0.333333,0.333333,0.54902,0.890196,0.721569,
|
||||
0.713725,0.54902,0.54902,0.54902,0.501961,0.576471,0.494118,0.713725,0.823529,0.54902,0.27451,0.27451,0.309804,0.768627,0.666667,0.501961,
|
||||
0.443137,0.333333,0.564706,0.54902,0.501961,0.54902,0.611765,0.501961,0.501961,1,0.25098,0.721569,0.721569,0.721569,0.890196,0.721569,
|
||||
0.501961,1,0.443137,0.443137,0.333333,0.333333,0.54902,0.494118,0.501961,0.721569,0.168627,0.745098,0.333333,0.333333,0.556863,0.556863,
|
||||
0.501961,0.25098,0.333333,0.443137,1,0.721569,0.611765,0.721569,0.611765,0.611765,0.333333,0.333333,0.333333,0.333333,0.721569,0.721569,
|
||||
0.788235,0.721569,0.721569,0.721569,0.721569,0.278431,0.333333,0.333333,0.333333,0.333333,0.333333,0.333333,0.333333,0.333333,0.333333,0.333333
|
||||
},
|
||||
_maxTimesCharWidth = 0.980392;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void check_pointer (void*);
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct avl_table * uniqueTags = NULL;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct bufferedString
|
||||
{
|
||||
char *sData;
|
||||
long sLength,
|
||||
saLength;
|
||||
}
|
||||
*globalNameBuffer;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct vector
|
||||
{
|
||||
long *vData;
|
||||
|
||||
long vLength,
|
||||
vaLength;
|
||||
} * treeLabelWidths,
|
||||
* nodeCountsByLevel,
|
||||
* leafCountsByLevel;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct bufferedString *allocateNewString (void)
|
||||
{
|
||||
struct bufferedString *newS = (struct bufferedString*)malloc (sizeof (struct bufferedString));
|
||||
check_pointer (newS);
|
||||
check_pointer (newS->sData = (char*)malloc (DEFAULT_STRING_ALLOC+1));
|
||||
newS->sLength = 0;
|
||||
newS->saLength = DEFAULT_STRING_ALLOC;
|
||||
newS->sData[0] = 0;
|
||||
return newS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct vector *allocateNewVector (void)
|
||||
{
|
||||
struct vector *newS = (struct vector*)malloc (sizeof (struct vector));
|
||||
check_pointer (newS);
|
||||
check_pointer (newS->vData = (long*)malloc (DEFAULT_STRING_ALLOC*sizeof(long)));
|
||||
newS->vLength = 0;
|
||||
newS->vaLength = DEFAULT_STRING_ALLOC;
|
||||
return newS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void clear_buffered_string (struct bufferedString* theString)
|
||||
{
|
||||
theString->sLength = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void clear_vector (struct vector* v)
|
||||
{
|
||||
v->vLength = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void reportError (FILE* f,const char * err, long cci)
|
||||
{
|
||||
char buffer[33];
|
||||
fprintf (stderr, "ERROR: %s. Tree string position %d\n", err, cci);
|
||||
fprintf (stderr, "?");
|
||||
buffer[fread (buffer,1,32,f)] = 0;
|
||||
fprintf (stderr, "%s\n", buffer);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void appendCharacterToString (struct bufferedString * s, const char c)
|
||||
{
|
||||
long addThis;
|
||||
if (s->saLength == s->sLength)
|
||||
{
|
||||
addThis = s->saLength / 8;
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
s->saLength += addThis;
|
||||
check_pointer (s->sData = realloc (s->sData,s->saLength+1));
|
||||
}
|
||||
s->sData[s->sLength] = c;
|
||||
s->sData[++s->sLength] = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void appendValueToVector (struct vector * v, long c)
|
||||
{
|
||||
long addThis;
|
||||
if (v->vaLength == v->vLength)
|
||||
{
|
||||
addThis = v->vaLength / 8;
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
v->vaLength += addThis;
|
||||
check_pointer (v->vData = realloc (v->vData,sizeof(long)*v->vaLength));
|
||||
}
|
||||
v->vData[v->vLength++] = c;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
long popValueFromVector (struct vector * v)
|
||||
{
|
||||
if (v->vLength)
|
||||
return v->vData[--v->vLength];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
long appendRangeToString (struct bufferedString * d, struct bufferedString *s, long from, long to)
|
||||
{
|
||||
long addThis,
|
||||
pl = to-from+1;
|
||||
|
||||
if (pl<=0)
|
||||
return -1;
|
||||
|
||||
if (d->saLength < d->sLength + pl)
|
||||
{
|
||||
addThis = d->saLength / 8;
|
||||
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
if (addThis < pl)
|
||||
addThis = pl;
|
||||
|
||||
d->saLength += addThis;
|
||||
check_pointer (d->sData = realloc (d->sData,d->saLength+1));
|
||||
}
|
||||
for (addThis = from; addThis <=to; addThis++)
|
||||
d->sData[d->sLength++] = s->sData[addThis];
|
||||
|
||||
d->sData[d->sLength] = 0;
|
||||
|
||||
return pl;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void appendCharRangeToString (struct bufferedString * d, char * buffer)
|
||||
{
|
||||
long addThis,
|
||||
pl = strlen(buffer);
|
||||
|
||||
if (pl<=0)
|
||||
return;
|
||||
|
||||
if (d->saLength < d->sLength + pl)
|
||||
{
|
||||
addThis = d->saLength / 8;
|
||||
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
if (addThis < pl)
|
||||
addThis = pl;
|
||||
|
||||
d->saLength += addThis;
|
||||
check_pointer (d->sData = realloc (d->sData,d->saLength+1));
|
||||
}
|
||||
for (addThis = 0; addThis <pl; addThis++)
|
||||
d->sData[d->sLength++] = buffer[addThis];
|
||||
|
||||
d->sData[d->sLength] = 0;
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
long appendCharBufferToString (struct bufferedString * d, const char * b)
|
||||
{
|
||||
long addThis,
|
||||
pl = strlen (b);
|
||||
|
||||
if (pl<=0)
|
||||
return -1;
|
||||
|
||||
if (d->saLength < d->sLength + pl)
|
||||
{
|
||||
addThis = d->saLength / 8;
|
||||
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
if (addThis < pl)
|
||||
addThis = pl;
|
||||
|
||||
d->saLength += addThis;
|
||||
check_pointer (d->sData = realloc (d->sData,d->saLength+1));
|
||||
}
|
||||
for (addThis = 0; addThis <pl; addThis++)
|
||||
d->sData[d->sLength++] = b[addThis];
|
||||
|
||||
d->sData[d->sLength] = 0;
|
||||
return pl;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct treeNode
|
||||
{
|
||||
struct treeNode * parent;
|
||||
long startIndex,
|
||||
hitCount,
|
||||
childrenCount,
|
||||
length;
|
||||
|
||||
struct vector * children;
|
||||
|
||||
} *globalTreeRoot;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct treeNode * allocateNewTreeNode (void)
|
||||
{
|
||||
struct treeNode *newN = (struct treeNode*)malloc (sizeof (struct treeNode));
|
||||
check_pointer (newN);
|
||||
newN->parent = NULL;
|
||||
newN->startIndex = 0;
|
||||
newN->length = 0;
|
||||
newN->hitCount = 0;
|
||||
newN->childrenCount = 0;
|
||||
newN->children = allocateNewVector();
|
||||
check_pointer (newN->children);
|
||||
return newN;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
void addAChild (struct treeNode* p, struct treeNode * c)
|
||||
{
|
||||
long i = 0;
|
||||
for (; i<p->children->vLength; i++)
|
||||
if (((struct treeNode**)p->children->vData)[i] == c)
|
||||
break;
|
||||
if (p->children->vLength == i)
|
||||
{
|
||||
appendValueToVector (p->children, (long)c);
|
||||
c->parent = p;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void destroyTreeNode (struct treeNode* n)
|
||||
{
|
||||
free (n->children);
|
||||
free (n);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
long traverseTree (struct treeNode* n, long maxDepth, long currentDepth, long* height, long *depth)
|
||||
{
|
||||
long i = 0;
|
||||
double w = 0.;
|
||||
char buffer[255];
|
||||
|
||||
if (currentDepth <= maxDepth)
|
||||
{
|
||||
if (currentDepth > *depth)
|
||||
*depth = currentDepth;
|
||||
|
||||
if (currentDepth >= treeLabelWidths->vLength)
|
||||
{
|
||||
appendValueToVector (treeLabelWidths, 0);
|
||||
appendValueToVector (nodeCountsByLevel,0);
|
||||
appendValueToVector (leafCountsByLevel,0);
|
||||
}
|
||||
|
||||
if (n->children->vLength)
|
||||
{
|
||||
nodeCountsByLevel->vData[currentDepth] ++;
|
||||
//fprintf (stdout, "%d %d %d\n", currentDepth, maxDepth, *height);
|
||||
|
||||
if (currentDepth == maxDepth)
|
||||
(*height) ++;
|
||||
for (i=0; i<n->children->vLength; i++)
|
||||
n->childrenCount += traverseTree (((struct treeNode**)n->children->vData)[i], maxDepth, currentDepth+1,height,depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
leafCountsByLevel->vData[currentDepth] ++;
|
||||
(*height) ++;
|
||||
n->childrenCount = countDuplicateTaxID?n->hitCount:1;
|
||||
}
|
||||
|
||||
sprintf (buffer,":%d", n->childrenCount);
|
||||
|
||||
for (i=0; i<n->length; i++)
|
||||
w += _timesCharWidths[*(globalNameBuffer->sData + n->startIndex + i)];
|
||||
for (i=0; buffer[i]; i++)
|
||||
w += _timesCharWidths[buffer[i]];
|
||||
|
||||
w *= fontSize;
|
||||
w += 0.5;
|
||||
|
||||
if (w > treeLabelWidths->vData[currentDepth])
|
||||
treeLabelWidths->vData[currentDepth] = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n->children->vLength)
|
||||
for (i=0; i<n->children->vLength; i++)
|
||||
n->childrenCount += traverseTree (((struct treeNode**)n->children->vData)[i], maxDepth, currentDepth+1,height,depth);
|
||||
else
|
||||
n->childrenCount = countDuplicateTaxID?n->hitCount:1;
|
||||
}
|
||||
return n->childrenCount;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
void drawGradient (FILE* f, double left, double top, double right, double bottom)
|
||||
{
|
||||
double color = 0.,
|
||||
step = 1./(right-left),
|
||||
i = left;
|
||||
|
||||
fprintf (f, "currentlinewidth 1 setlinewidth \n");
|
||||
for (i=left; i<right; i+=1.0)
|
||||
{
|
||||
color = step*(i-left);
|
||||
fprintf (f, "%g %g %g setrgbcolor \n", 1.-color*color*color, 0.5*color, color );
|
||||
fprintf (f, "newpath %g %g moveto %g %g lineto stroke\n",i,top,i,bottom);
|
||||
}
|
||||
|
||||
fprintf (f, "0 0 0 setrgbcolor %g %g %g %g rectstroke setlinewidth\n",left, top, right-left, bottom-top);
|
||||
fprintf (f, "%g %g (100\\%%) centertext\n", left, bottom - fontSize-2);
|
||||
fprintf (f, "%g %g (50\\%%) centertext\n", 0.5*(left+right), bottom - fontSize-2);
|
||||
fprintf (f, "%g %g (0\\%%) centertext\n", right, bottom - fontSize-2);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
void drawPSLine (FILE* f, double left, double top, double right, double bottom, double lineWidth, double color)
|
||||
{
|
||||
//color = sin(color*0.5*3.14);
|
||||
fprintf (f, "%g %g %g setrgbcolor \n", 1.-color*color*color, 0.5*color, color);
|
||||
if (lineWidth > 0.)
|
||||
fprintf (f, "%g setlinewidth ");
|
||||
fprintf (f, "newpath %g %g moveto %g %g lineto stroke\n",left,top,right,bottom);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
void drawTextInAbox (FILE* f, long from, long to, long childrenCount, double x, double y)
|
||||
{
|
||||
long i;
|
||||
|
||||
fprintf (f, "newpath %g %g moveto (", x,y);
|
||||
if (from>=0)
|
||||
for (i=from; i<to; i++)
|
||||
fputc (globalNameBuffer->sData[i],f);
|
||||
else
|
||||
fprintf (f,"N/A");
|
||||
fprintf (f, ":%d) drawletter\n", childrenCount);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
void drawTextInAbox2 (FILE* f, long splits, long childrenCount, long level, double x, double y)
|
||||
{
|
||||
long i;
|
||||
|
||||
fprintf (f, "newpath %g %g moveto (%d %s", x,y, splits, level<NUMBER_OF_TAX_FIELDS?rankLabels[level]:"n/a");
|
||||
fprintf (f, ":%d) drawletter2\n", childrenCount);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
double traverseTreePS (FILE* f, struct treeNode* n, long maxDepth, long currentDepth, double parentX, double* currentLeafY, double* childX)
|
||||
{
|
||||
double myX,
|
||||
myY,
|
||||
minChildY = 0.,
|
||||
maxChildY = 0.,
|
||||
t;
|
||||
|
||||
long i;
|
||||
|
||||
if (currentDepth <= maxDepth)
|
||||
{
|
||||
if (currentDepth)
|
||||
myX = parentX + treeLabelWidths->vData[currentDepth-1] + xPadding;
|
||||
else
|
||||
myX = parentX;
|
||||
|
||||
if (n->children->vLength && maxDepth > currentDepth)
|
||||
{
|
||||
minChildY = traverseTreePS (f,((struct treeNode**)n->children->vData)[0], maxDepth, currentDepth+1,myX,currentLeafY,&t);
|
||||
drawPSLine (f, myX, minChildY, t, minChildY,-1., 1. - ((struct treeNode**)n->children->vData)[0]->childrenCount * countScaler);
|
||||
for (i=1; i<n->children->vLength-1; i++)
|
||||
{
|
||||
maxChildY = traverseTreePS (f,((struct treeNode**)n->children->vData)[i], maxDepth, currentDepth+1,myX,currentLeafY,&t);
|
||||
drawPSLine (f, myX, maxChildY, t, maxChildY,-1.,1. - ((struct treeNode**)n->children->vData)[i]->childrenCount * countScaler);
|
||||
}
|
||||
if (i<n->children->vLength)
|
||||
{
|
||||
maxChildY = traverseTreePS(f,((struct treeNode**)n->children->vData)[i], maxDepth, currentDepth+1,myX,currentLeafY,&t);
|
||||
drawPSLine (f, myX, maxChildY, t, maxChildY,-1.,1. - ((struct treeNode**)n->children->vData)[i]->childrenCount * countScaler);
|
||||
}
|
||||
else
|
||||
maxChildY = minChildY;
|
||||
|
||||
if (maxChildY > minChildY)
|
||||
{
|
||||
drawPSLine (f, myX, minChildY, myX, maxChildY,-1.,1.-n->childrenCount * countScaler);
|
||||
}
|
||||
|
||||
myY = (minChildY+maxChildY)*0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
myY = *currentLeafY;
|
||||
*currentLeafY += ySpacing;
|
||||
}
|
||||
//fprintf (stdout, "%d %d\n", n->startIndex, n->length);
|
||||
if (!(n->length == 1 && globalNameBuffer->sData[n->startIndex] == 'n'))
|
||||
drawTextInAbox (f, n->startIndex, n->startIndex+n->length, n->childrenCount, myX, myY-fontSize/2);
|
||||
else
|
||||
{
|
||||
if (n->children->vLength)
|
||||
{
|
||||
if (currentDepth == maxDepth)
|
||||
{
|
||||
i = currentDepth;
|
||||
while (n->children->vLength == 1)
|
||||
{
|
||||
n = ((struct treeNode**)n->children->vData)[0];
|
||||
i++;
|
||||
}
|
||||
if (!(n->length == 1 && globalNameBuffer->sData[n->startIndex] == 'n'))
|
||||
drawTextInAbox (f, n->startIndex, n->startIndex+n->length, n->childrenCount, myX, myY-fontSize/2);
|
||||
else
|
||||
drawTextInAbox2 (f, n->children->vLength, n->childrenCount, i, myX, myY-fontSize/2);
|
||||
}
|
||||
}
|
||||
else
|
||||
drawTextInAbox (f, -1, 0, n->childrenCount, myX, myY-fontSize/2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*childX = myX;
|
||||
return myY;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct storedSequenceTag
|
||||
{
|
||||
long startIndex,
|
||||
length;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct storedSequenceTag *allocateStringTag (void)
|
||||
{
|
||||
struct storedSequenceTag *newS = (struct storedSequenceTag*)malloc (sizeof (struct storedSequenceTag));
|
||||
check_pointer (newS);
|
||||
newS->startIndex = -1;
|
||||
newS->length = 0;
|
||||
return newS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int compare_tags (const void *avl_a, const void *avl_b, void * xtra)
|
||||
{
|
||||
char* n1 = globalNameBuffer->sData+((struct storedSequenceTag*)avl_a)->startIndex,
|
||||
* n2 = globalNameBuffer->sData+((struct storedSequenceTag*)avl_b)->startIndex;
|
||||
|
||||
long l1 = ((struct storedSequenceTag*)avl_a)->length,
|
||||
l2 = ((struct storedSequenceTag*)avl_b)->length,
|
||||
i;
|
||||
|
||||
signed char c;
|
||||
|
||||
for (i = 0; i < l1 && i < l2; i++)
|
||||
{
|
||||
c = n1[i] - n2[i];
|
||||
if (c < 0)
|
||||
return -1;
|
||||
if (c>0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (l1 < l2)
|
||||
return -1;
|
||||
if (l1 > l2)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void check_pointer (void * p)
|
||||
{
|
||||
if (p == NULL)
|
||||
{
|
||||
fprintf (stderr,"Memory allocation error\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int compare_strings (const struct bufferedString * s1, const struct bufferedString * s2)
|
||||
{
|
||||
long upTo,
|
||||
i;
|
||||
|
||||
if (s1->sLength>s2->sLength)
|
||||
upTo = s2->sLength;
|
||||
else
|
||||
upTo = s1->sLength;
|
||||
|
||||
for (i=0; i<upTo; i++)
|
||||
{
|
||||
int res = (s1->sData[i]-s2->sData[i]);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
else
|
||||
if (res>0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (s1->sLength == s2->sLength)
|
||||
return 0;
|
||||
|
||||
return 1-2*(s1->sLength<s2->sLength);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void destroy_string (struct bufferedString* aStr)
|
||||
{
|
||||
free (aStr->sData);
|
||||
free (aStr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
struct storedSequenceTag *sTag = allocateStringTag(),
|
||||
*sTag2 = allocateStringTag(),
|
||||
*sTag3;
|
||||
|
||||
struct avl_traverser avlt;
|
||||
|
||||
struct treeNode *currentParent = NULL,
|
||||
*currentNode;
|
||||
|
||||
struct vector *nodeStack = allocateNewVector();
|
||||
|
||||
char automatonState = 0,
|
||||
currentChar = 0,
|
||||
buffa [255];
|
||||
|
||||
double Ycoord = 0.0,
|
||||
Xcoord = 0.0,
|
||||
t;
|
||||
|
||||
long currentCharID = 0,
|
||||
indexer,
|
||||
indexer2,
|
||||
indexer3,
|
||||
maxTreeLevel = 0,
|
||||
branchWeight = 0;
|
||||
|
||||
FILE * psFile = NULL,
|
||||
* inFile = NULL;
|
||||
|
||||
globalNameBuffer = allocateNewString();
|
||||
check_pointer (uniqueTags = avl_create (compare_tags, NULL, NULL));
|
||||
|
||||
for (indexer = 0; indexer < 256; indexer ++)
|
||||
validTaxonNameChar[indexer] = 1;
|
||||
|
||||
validTaxonNameChar[','] = 0;
|
||||
validTaxonNameChar[')'] = 0;
|
||||
validTaxonNameChar['('] = 0;
|
||||
validTaxonNameChar[':'] = 0;
|
||||
|
||||
if (argc != 7)
|
||||
{
|
||||
fprintf (stderr,"%s",Usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
maxTreeLevel = atoi (argv[3]);
|
||||
if (maxTreeLevel < 1)
|
||||
maxTreeLevel = 0xfffffffL;
|
||||
|
||||
inFile = fopen (argv[1], "rb");
|
||||
if (!inFile)
|
||||
{
|
||||
fprintf (stderr, "Failed to open the input file %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
psFile = fopen (argv[2], "wb");
|
||||
if (!psFile)
|
||||
{
|
||||
fprintf (stderr, "Failed to open the tree output file %s\n", argv[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fontSize = atoi (argv[4]);
|
||||
if (fontSize < 2)
|
||||
fontSize = 2;
|
||||
if (fontSize > 255)
|
||||
fontSize = 255;
|
||||
|
||||
showMaxNodes = atoi (argv[5]);
|
||||
if (showMaxNodes <= 0)
|
||||
showMaxNodes = 0x7FFFFFFFL;
|
||||
|
||||
countDuplicateTaxID = atoi (argv[6]);
|
||||
|
||||
ySpacing = fontSize+2*lineWidth + 5;
|
||||
xPadding = fontSize*2;
|
||||
globalXPad = fontSize;
|
||||
globalYPad = fontSize*3/2;
|
||||
|
||||
currentChar = fgetc(inFile);
|
||||
while (1)
|
||||
{
|
||||
currentCharID ++;
|
||||
//fprintf (stderr, "%d %c %d %d\n", currentCharID, currentChar, automatonState,nodeStack->vLength);
|
||||
switch (automatonState)
|
||||
{
|
||||
case 0: /* waiting for the opening '(' */
|
||||
if (currentChar == '(')
|
||||
{
|
||||
automatonState = 1; /* create new node*/
|
||||
globalTreeRoot = allocateNewTreeNode();
|
||||
appendValueToVector (nodeStack, (long)globalTreeRoot);
|
||||
currentChar = fgetc(inFile);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* starting node read; first pass */
|
||||
case 8: /* starting node read */
|
||||
{
|
||||
if (currentChar == ',')
|
||||
{
|
||||
if (automatonState == 1)
|
||||
reportError (inFile,"empty first clade node name", currentCharID);
|
||||
|
||||
currentNode = allocateNewTreeNode();
|
||||
appendValueToVector (nodeStack, (long)currentNode);
|
||||
automatonState = 8;
|
||||
currentChar = fgetc(inFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentChar == ')')
|
||||
{
|
||||
automatonState = 2;
|
||||
currentChar = fgetc(inFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentChar == '(')
|
||||
{
|
||||
currentNode = allocateNewTreeNode();
|
||||
appendValueToVector (nodeStack, (long)currentNode);
|
||||
currentChar = fgetc(inFile);
|
||||
//automatonState = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (automatonState == 1)
|
||||
{
|
||||
currentNode = allocateNewTreeNode();
|
||||
appendValueToVector (nodeStack, (long)currentNode);
|
||||
}
|
||||
currentCharID--;
|
||||
automatonState = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: /* reading first node character */
|
||||
{
|
||||
if (!validTaxonNameChar[currentChar])
|
||||
reportError (inFile,"empty node name", currentCharID);
|
||||
sTag->startIndex = globalNameBuffer->sLength;
|
||||
sTag->length = 1;
|
||||
appendCharacterToString (globalNameBuffer, currentChar);
|
||||
automatonState = 3;
|
||||
currentChar = fgetc(inFile);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* reading additional node characters */
|
||||
{
|
||||
if (validTaxonNameChar[currentChar])
|
||||
{
|
||||
sTag->length++;
|
||||
appendCharacterToString (globalNameBuffer, currentChar);
|
||||
currentChar = fgetc(inFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentChar == ':')
|
||||
{
|
||||
automatonState = 4; /* read branch length */
|
||||
currentChar = fgetc(inFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentCharID--;
|
||||
if (currentChar == ',' || currentChar == ')')
|
||||
automatonState = 6; /* finish up a node read */
|
||||
else
|
||||
reportError (inFile,"unexpected '(' character following a branch name", currentCharID);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4: /* initial read in branch length */
|
||||
{
|
||||
if (isnumber (currentChar))
|
||||
{
|
||||
automatonState = 5;
|
||||
sTag2->startIndex = globalNameBuffer->sLength;
|
||||
sTag2->length = 1;
|
||||
appendCharacterToString (globalNameBuffer,currentChar);
|
||||
currentChar = fgetc(inFile);
|
||||
}
|
||||
else
|
||||
reportError (inFile,"expected a digit following ':'", currentCharID);
|
||||
break;
|
||||
}
|
||||
case 5: /* continued read branch length */
|
||||
{
|
||||
if (isnumber (currentChar))
|
||||
{
|
||||
sTag2->length++;
|
||||
appendCharacterToString (globalNameBuffer,currentChar);
|
||||
currentChar = fgetc(inFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentCharID --;
|
||||
if (currentChar == ',' || currentChar == ')')
|
||||
automatonState = 6; /* finish up a node read */
|
||||
else
|
||||
reportError (inFile,"expected a ',' or a ')' following a branch length", currentCharID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6: /* create a new node with a name and a branch length */
|
||||
{
|
||||
currentNode = (struct treeNode*) popValueFromVector (nodeStack);
|
||||
if (!currentNode)
|
||||
reportError (inFile,"incorrect tree structure", currentCharID);
|
||||
|
||||
if (sTag2->length)
|
||||
{
|
||||
//fprintf (stderr, "%d %s\n", sTag2->length, globalNameBuffer->sData+sTag2->startIndex);
|
||||
currentNode->hitCount = atoi (globalNameBuffer->sData+sTag2->startIndex);
|
||||
globalNameBuffer->sLength -= sTag2->length;
|
||||
globalNameBuffer->sData[globalNameBuffer->sLength] = 0;
|
||||
}
|
||||
sTag3 = *(struct storedSequenceTag**)avl_probe (uniqueTags,sTag);
|
||||
if (sTag == sTag3) // new node
|
||||
sTag = allocateStringTag();
|
||||
else
|
||||
{
|
||||
//fprintf (stderr, "%d %s\n", sTag->length, globalNameBuffer->sData+sTag->startIndex);
|
||||
globalNameBuffer->sLength -= sTag->length;
|
||||
globalNameBuffer->sData[globalNameBuffer->sLength] = 0;
|
||||
//fprintf (stderr, "Duplicate %s %d %d %d\n", globalNameBuffer->sData,globalNameBuffer->sLength,
|
||||
// sTag3->startIndex, sTag3->length);
|
||||
}
|
||||
currentNode->startIndex = sTag3->startIndex;
|
||||
currentNode->length = sTag3->length;
|
||||
|
||||
if (nodeStack->vLength) // add current node to the parent
|
||||
addAChild ((struct treeNode*) nodeStack->vData[nodeStack->vLength-1],currentNode);
|
||||
else
|
||||
if (currentNode != globalTreeRoot)
|
||||
reportError (inFile,"imbalanced paretheses: too many closing ')'", currentCharID);
|
||||
else
|
||||
//if (feof (inFile))
|
||||
{
|
||||
automatonState = 1;
|
||||
break;
|
||||
}
|
||||
currentCharID--;
|
||||
//currentChar = fgetc(inFile);
|
||||
automatonState = 8; // go back to reading more nodes
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (feof (inFile))
|
||||
if (automatonState == 3 || automatonState == 5)
|
||||
automatonState = 6;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (automatonState != 1)
|
||||
reportError (inFile,"imbalanced paretheses in the tree", currentCharID);
|
||||
|
||||
indexer = 0; indexer2 = 0; indexer3 = 0;
|
||||
treeLabelWidths = allocateNewVector();
|
||||
nodeCountsByLevel = allocateNewVector();
|
||||
leafCountsByLevel = allocateNewVector();
|
||||
|
||||
traverseTree (globalTreeRoot, maxTreeLevel, 0, & indexer, & indexer2);
|
||||
//fprintf (stdout, "Height:%d Depth:%d\n", indexer, indexer2);
|
||||
|
||||
Xcoord = 0;
|
||||
for (indexer3 = 0; indexer3 < treeLabelWidths->vLength; indexer3++)
|
||||
if (Xcoord < treeLabelWidths->vData[indexer3])
|
||||
Xcoord = treeLabelWidths->vData[indexer3];
|
||||
|
||||
t = 16 * _maxTimesCharWidth * fontSize + 0.5;
|
||||
if (t>Xcoord)
|
||||
treeLabelWidths->vData[treeLabelWidths->vLength-1] = t;
|
||||
else
|
||||
treeLabelWidths->vData[treeLabelWidths->vLength-1] = Xcoord;
|
||||
|
||||
Xcoord = globalXPad;
|
||||
for (indexer3 = 1; indexer3 < leafCountsByLevel->vLength; indexer3++)
|
||||
leafCountsByLevel->vData[indexer3] += leafCountsByLevel->vData[indexer3-1];
|
||||
|
||||
for (indexer3 = 0; indexer3 < treeLabelWidths->vLength; indexer3++)
|
||||
{
|
||||
//fprintf (stdout, "Level %d, nodes %d\n", indexer3, nodeCountsByLevel->vData[indexer3] + leafCountsByLevel->vData[indexer3]);
|
||||
if (nodeCountsByLevel->vData[indexer3] + leafCountsByLevel->vData[indexer3] > showMaxNodes && indexer3 < maxTreeLevel)
|
||||
{
|
||||
maxTreeLevel = indexer3-1;
|
||||
indexer = nodeCountsByLevel->vData[maxTreeLevel] + leafCountsByLevel->vData[maxTreeLevel];
|
||||
break;
|
||||
}
|
||||
Xcoord += treeLabelWidths->vData[indexer3] + xPadding;
|
||||
}
|
||||
Ycoord = 3.*globalYPad + indexer * ySpacing;
|
||||
|
||||
countScaler = 1./(countDuplicateTaxID?globalTreeRoot->hitCount:globalTreeRoot->childrenCount);
|
||||
|
||||
fprintf (psFile,"%% PS file for the tree '%s'.\n%% Generated by tree2PS on %s\n<< /PageSize [%d %d] >> setpagedevice\n %g setlinewidth\n1 setlinecap\n",
|
||||
argv[1], argv[1],
|
||||
(long)(Xcoord+0.5), (long)(Ycoord+0.5), lineWidth);
|
||||
fprintf (psFile, "/Times-Roman findfont %d scalefont\nsetfont\n",fontSize);
|
||||
fprintf (psFile,"/drawletter {2 0 rmoveto 1 copy false charpath pathbbox 2 index 3 sub sub exch 3 index 3 sub sub exch 0.85 setgray 4 copy rectfill 0 setgray 3 index 3 index currentlinewidth 0.5 setlinewidth 7 3 roll rectstroke setlinewidth exch 1.5 add exch 1.5 add moveto show} def\n/centertext {dup newpath 0 0 moveto false charpath closepath pathbbox pop exch pop exch sub 2 div 4 -1 roll exch sub 3 -1 roll newpath moveto show} def\n");
|
||||
fprintf (psFile,"/drawletter2 {2 0 rmoveto 1 copy false charpath pathbbox 2 index 3 sub sub exch 3 index 3 sub sub exch 1 0.5 0 setrgbcolor 4 copy rectfill 0 setgray 3 index 3 index currentlinewidth 0.5 setlinewidth 7 3 roll rectstroke setlinewidth exch 1.5 add exch 1.5 add moveto show} def\n/centertext {dup newpath 0 0 moveto false charpath closepath pathbbox pop exch pop exch sub 2 div 4 -1 roll exch sub 3 -1 roll newpath moveto show} def\n");
|
||||
|
||||
t = globalXPad*2. + 100. + 2*fontSize;
|
||||
drawGradient (psFile, globalXPad*2., Ycoord - 0.5*globalYPad, t<Xcoord ? t : Xcoord, Ycoord - globalYPad*1.5);
|
||||
|
||||
Ycoord = globalYPad;
|
||||
traverseTreePS (psFile, globalTreeRoot, maxTreeLevel, 0, globalXPad, &Ycoord, &Ycoord);
|
||||
|
||||
fclose (inFile);
|
||||
fclose (psFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,890 +0,0 @@
|
||||
/* Produced by texiweb from libavl.w on 2002/08/24 at 13:21. */
|
||||
|
||||
/* libavl - library for manipulation of binary trees.
|
||||
Copyright (C) 1998-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The author may be contacted at <blp@gnu.org> on the Internet, or
|
||||
write to Ben Pfaff, Stanford University, Computer Science Dept., 353
|
||||
Serra Mall, Stanford CA 94305, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "avl.h"
|
||||
|
||||
/* Creates and returns a new table
|
||||
with comparison function |compare| using parameter |param|
|
||||
and memory allocator |allocator|.
|
||||
Returns |NULL| if memory allocation failed. */
|
||||
struct avl_table *
|
||||
avl_create (avl_comparison_func *compare, void *param,
|
||||
struct libavl_allocator *allocator)
|
||||
{
|
||||
struct avl_table *tree;
|
||||
|
||||
assert (compare != NULL);
|
||||
|
||||
if (allocator == NULL)
|
||||
allocator = &avl_allocator_default;
|
||||
|
||||
tree = allocator->libavl_malloc (allocator, sizeof *tree);
|
||||
if (tree == NULL)
|
||||
return NULL;
|
||||
|
||||
tree->avl_root = NULL;
|
||||
tree->avl_compare = compare;
|
||||
tree->avl_param = param;
|
||||
tree->avl_alloc = allocator;
|
||||
tree->avl_count = 0;
|
||||
tree->avl_generation = 0;
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* Search |tree| for an item matching |item|, and return it if found.
|
||||
Otherwise return |NULL|. */
|
||||
void *
|
||||
avl_find (const struct avl_table *tree, const void *item)
|
||||
{
|
||||
const struct avl_node *p;
|
||||
|
||||
assert (tree != NULL && item != NULL);
|
||||
for (p = tree->avl_root; p != NULL; )
|
||||
{
|
||||
int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
|
||||
|
||||
if (cmp < 0)
|
||||
p = p->avl_link[0];
|
||||
else if (cmp > 0)
|
||||
p = p->avl_link[1];
|
||||
else /* |cmp == 0| */
|
||||
return p->avl_data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Inserts |item| into |tree| and returns a pointer to |item|'s address.
|
||||
If a duplicate item is found in the tree,
|
||||
returns a pointer to the duplicate without inserting |item|.
|
||||
Returns |NULL| in case of memory allocation failure. */
|
||||
void **
|
||||
avl_probe (struct avl_table *tree, void *item)
|
||||
{
|
||||
struct avl_node *y, *z; /* Top node to update balance factor, and parent. */
|
||||
struct avl_node *p, *q; /* Iterator, and parent. */
|
||||
struct avl_node *n; /* Newly inserted node. */
|
||||
struct avl_node *w; /* New root of rebalanced subtree. */
|
||||
int dir; /* Direction to descend. */
|
||||
|
||||
unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */
|
||||
int k = 0; /* Number of cached results. */
|
||||
|
||||
assert (tree != NULL && item != NULL);
|
||||
|
||||
z = (struct avl_node *) &tree->avl_root;
|
||||
y = tree->avl_root;
|
||||
dir = 0;
|
||||
for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir])
|
||||
{
|
||||
int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
|
||||
if (cmp == 0)
|
||||
return &p->avl_data;
|
||||
|
||||
if (p->avl_balance != 0)
|
||||
z = q, y = p, k = 0;
|
||||
da[k++] = dir = cmp > 0;
|
||||
}
|
||||
|
||||
n = q->avl_link[dir] =
|
||||
tree->avl_alloc->libavl_malloc (tree->avl_alloc, sizeof *n);
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
|
||||
tree->avl_count++;
|
||||
n->avl_data = item;
|
||||
n->avl_link[0] = n->avl_link[1] = NULL;
|
||||
n->avl_balance = 0;
|
||||
if (y == NULL)
|
||||
return &n->avl_data;
|
||||
|
||||
for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++)
|
||||
if (da[k] == 0)
|
||||
p->avl_balance--;
|
||||
else
|
||||
p->avl_balance++;
|
||||
|
||||
if (y->avl_balance == -2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[0];
|
||||
if (x->avl_balance == -1)
|
||||
{
|
||||
w = x;
|
||||
y->avl_link[0] = x->avl_link[1];
|
||||
x->avl_link[1] = y;
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (x->avl_balance == +1);
|
||||
w = x->avl_link[1];
|
||||
x->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = x;
|
||||
y->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = y;
|
||||
if (w->avl_balance == -1)
|
||||
x->avl_balance = 0, y->avl_balance = +1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == +1| */
|
||||
x->avl_balance = -1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
else if (y->avl_balance == +2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[1];
|
||||
if (x->avl_balance == +1)
|
||||
{
|
||||
w = x;
|
||||
y->avl_link[1] = x->avl_link[0];
|
||||
x->avl_link[0] = y;
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (x->avl_balance == -1);
|
||||
w = x->avl_link[0];
|
||||
x->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = x;
|
||||
y->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = y;
|
||||
if (w->avl_balance == +1)
|
||||
x->avl_balance = 0, y->avl_balance = -1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == -1| */
|
||||
x->avl_balance = +1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return &n->avl_data;
|
||||
z->avl_link[y != z->avl_link[0]] = w;
|
||||
|
||||
tree->avl_generation++;
|
||||
return &n->avl_data;
|
||||
}
|
||||
|
||||
/* Inserts |item| into |table|.
|
||||
Returns |NULL| if |item| was successfully inserted
|
||||
or if a memory allocation error occurred.
|
||||
Otherwise, returns the duplicate item. */
|
||||
void *
|
||||
avl_insert (struct avl_table *table, void *item)
|
||||
{
|
||||
void **p = avl_probe (table, item);
|
||||
return p == NULL || *p == item ? NULL : *p;
|
||||
}
|
||||
|
||||
/* Inserts |item| into |table|, replacing any duplicate item.
|
||||
Returns |NULL| if |item| was inserted without replacing a duplicate,
|
||||
or if a memory allocation error occurred.
|
||||
Otherwise, returns the item that was replaced. */
|
||||
void *
|
||||
avl_replace (struct avl_table *table, void *item)
|
||||
{
|
||||
void **p = avl_probe (table, item);
|
||||
if (p == NULL || *p == item)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
void *r = *p;
|
||||
*p = item;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Deletes from |tree| and returns an item matching |item|.
|
||||
Returns a null pointer if no matching item found. */
|
||||
void *
|
||||
avl_delete (struct avl_table *tree, const void *item)
|
||||
{
|
||||
/* Stack of nodes. */
|
||||
struct avl_node *pa[AVL_MAX_HEIGHT]; /* Nodes. */
|
||||
unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
|
||||
int k; /* Stack pointer. */
|
||||
|
||||
struct avl_node *p; /* Traverses tree to find node to delete. */
|
||||
int cmp; /* Result of comparison between |item| and |p|. */
|
||||
|
||||
assert (tree != NULL && item != NULL);
|
||||
|
||||
k = 0;
|
||||
p = (struct avl_node *) &tree->avl_root;
|
||||
for (cmp = -1; cmp != 0;
|
||||
cmp = tree->avl_compare (item, p->avl_data, tree->avl_param))
|
||||
{
|
||||
int dir = cmp > 0;
|
||||
|
||||
pa[k] = p;
|
||||
da[k++] = dir;
|
||||
|
||||
p = p->avl_link[dir];
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
}
|
||||
item = p->avl_data;
|
||||
|
||||
if (p->avl_link[1] == NULL)
|
||||
pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
|
||||
else
|
||||
{
|
||||
struct avl_node *r = p->avl_link[1];
|
||||
if (r->avl_link[0] == NULL)
|
||||
{
|
||||
r->avl_link[0] = p->avl_link[0];
|
||||
r->avl_balance = p->avl_balance;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = r;
|
||||
da[k] = 1;
|
||||
pa[k++] = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avl_node *s;
|
||||
int j = k++;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
da[k] = 0;
|
||||
pa[k++] = r;
|
||||
s = r->avl_link[0];
|
||||
if (s->avl_link[0] == NULL)
|
||||
break;
|
||||
|
||||
r = s;
|
||||
}
|
||||
|
||||
s->avl_link[0] = p->avl_link[0];
|
||||
r->avl_link[0] = s->avl_link[1];
|
||||
s->avl_link[1] = p->avl_link[1];
|
||||
s->avl_balance = p->avl_balance;
|
||||
|
||||
pa[j - 1]->avl_link[da[j - 1]] = s;
|
||||
da[j] = 1;
|
||||
pa[j] = s;
|
||||
}
|
||||
}
|
||||
|
||||
tree->avl_alloc->libavl_free (tree->avl_alloc, p);
|
||||
|
||||
assert (k > 0);
|
||||
while (--k > 0)
|
||||
{
|
||||
struct avl_node *y = pa[k];
|
||||
|
||||
if (da[k] == 0)
|
||||
{
|
||||
y->avl_balance++;
|
||||
if (y->avl_balance == +1)
|
||||
break;
|
||||
else if (y->avl_balance == +2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[1];
|
||||
if (x->avl_balance == -1)
|
||||
{
|
||||
struct avl_node *w;
|
||||
assert (x->avl_balance == -1);
|
||||
w = x->avl_link[0];
|
||||
x->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = x;
|
||||
y->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = y;
|
||||
if (w->avl_balance == +1)
|
||||
x->avl_balance = 0, y->avl_balance = -1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == -1| */
|
||||
x->avl_balance = +1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
y->avl_link[1] = x->avl_link[0];
|
||||
x->avl_link[0] = y;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = x;
|
||||
if (x->avl_balance == 0)
|
||||
{
|
||||
x->avl_balance = -1;
|
||||
y->avl_balance = +1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
y->avl_balance--;
|
||||
if (y->avl_balance == -1)
|
||||
break;
|
||||
else if (y->avl_balance == -2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[0];
|
||||
if (x->avl_balance == +1)
|
||||
{
|
||||
struct avl_node *w;
|
||||
assert (x->avl_balance == +1);
|
||||
w = x->avl_link[1];
|
||||
x->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = x;
|
||||
y->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = y;
|
||||
if (w->avl_balance == -1)
|
||||
x->avl_balance = 0, y->avl_balance = +1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == +1| */
|
||||
x->avl_balance = -1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
y->avl_link[0] = x->avl_link[1];
|
||||
x->avl_link[1] = y;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = x;
|
||||
if (x->avl_balance == 0)
|
||||
{
|
||||
x->avl_balance = +1;
|
||||
y->avl_balance = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tree->avl_count--;
|
||||
tree->avl_generation++;
|
||||
return (void *) item;
|
||||
}
|
||||
|
||||
/* Refreshes the stack of parent pointers in |trav|
|
||||
and updates its generation number. */
|
||||
static void
|
||||
trav_refresh (struct avl_traverser *trav)
|
||||
{
|
||||
assert (trav != NULL);
|
||||
|
||||
trav->avl_generation = trav->avl_table->avl_generation;
|
||||
|
||||
if (trav->avl_node != NULL)
|
||||
{
|
||||
avl_comparison_func *cmp = trav->avl_table->avl_compare;
|
||||
void *param = trav->avl_table->avl_param;
|
||||
struct avl_node *node = trav->avl_node;
|
||||
struct avl_node *i;
|
||||
|
||||
trav->avl_height = 0;
|
||||
for (i = trav->avl_table->avl_root; i != node; )
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
assert (i != NULL);
|
||||
|
||||
trav->avl_stack[trav->avl_height++] = i;
|
||||
i = i->avl_link[cmp (node->avl_data, i->avl_data, param) > 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes |trav| for use with |tree|
|
||||
and selects the null node. */
|
||||
void
|
||||
avl_t_init (struct avl_traverser *trav, struct avl_table *tree)
|
||||
{
|
||||
trav->avl_table = tree;
|
||||
trav->avl_node = NULL;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
}
|
||||
|
||||
/* Initializes |trav| for |tree|
|
||||
and selects and returns a pointer to its least-valued item.
|
||||
Returns |NULL| if |tree| contains no nodes. */
|
||||
void *
|
||||
avl_t_first (struct avl_traverser *trav, struct avl_table *tree)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (tree != NULL && trav != NULL);
|
||||
|
||||
trav->avl_table = tree;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
|
||||
x = tree->avl_root;
|
||||
if (x != NULL)
|
||||
while (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[0];
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x != NULL ? x->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Initializes |trav| for |tree|
|
||||
and selects and returns a pointer to its greatest-valued item.
|
||||
Returns |NULL| if |tree| contains no nodes. */
|
||||
void *
|
||||
avl_t_last (struct avl_traverser *trav, struct avl_table *tree)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (tree != NULL && trav != NULL);
|
||||
|
||||
trav->avl_table = tree;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
|
||||
x = tree->avl_root;
|
||||
if (x != NULL)
|
||||
while (x->avl_link[1] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[1];
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x != NULL ? x->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Searches for |item| in |tree|.
|
||||
If found, initializes |trav| to the item found and returns the item
|
||||
as well.
|
||||
If there is no matching item, initializes |trav| to the null item
|
||||
and returns |NULL|. */
|
||||
void *
|
||||
avl_t_find (struct avl_traverser *trav, struct avl_table *tree, void *item)
|
||||
{
|
||||
struct avl_node *p, *q;
|
||||
|
||||
assert (trav != NULL && tree != NULL && item != NULL);
|
||||
trav->avl_table = tree;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
for (p = tree->avl_root; p != NULL; p = q)
|
||||
{
|
||||
int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
|
||||
|
||||
if (cmp < 0)
|
||||
q = p->avl_link[0];
|
||||
else if (cmp > 0)
|
||||
q = p->avl_link[1];
|
||||
else /* |cmp == 0| */
|
||||
{
|
||||
trav->avl_node = p;
|
||||
return p->avl_data;
|
||||
}
|
||||
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = p;
|
||||
}
|
||||
|
||||
trav->avl_height = 0;
|
||||
trav->avl_node = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Attempts to insert |item| into |tree|.
|
||||
If |item| is inserted successfully, it is returned and |trav| is
|
||||
initialized to its location.
|
||||
If a duplicate is found, it is returned and |trav| is initialized to
|
||||
its location. No replacement of the item occurs.
|
||||
If a memory allocation failure occurs, |NULL| is returned and |trav|
|
||||
is initialized to the null item. */
|
||||
void *
|
||||
avl_t_insert (struct avl_traverser *trav, struct avl_table *tree, void *item)
|
||||
{
|
||||
void **p;
|
||||
|
||||
assert (trav != NULL && tree != NULL && item != NULL);
|
||||
|
||||
p = avl_probe (tree, item);
|
||||
if (p != NULL)
|
||||
{
|
||||
trav->avl_table = tree;
|
||||
trav->avl_node =
|
||||
((struct avl_node *)
|
||||
((char *) p - offsetof (struct avl_node, avl_data)));
|
||||
trav->avl_generation = tree->avl_generation - 1;
|
||||
return *p;
|
||||
}
|
||||
else
|
||||
{
|
||||
avl_t_init (trav, tree);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes |trav| to have the same current node as |src|. */
|
||||
void *
|
||||
avl_t_copy (struct avl_traverser *trav, const struct avl_traverser *src)
|
||||
{
|
||||
assert (trav != NULL && src != NULL);
|
||||
|
||||
if (trav != src)
|
||||
{
|
||||
trav->avl_table = src->avl_table;
|
||||
trav->avl_node = src->avl_node;
|
||||
trav->avl_generation = src->avl_generation;
|
||||
if (trav->avl_generation == trav->avl_table->avl_generation)
|
||||
{
|
||||
trav->avl_height = src->avl_height;
|
||||
memcpy (trav->avl_stack, (const void *) src->avl_stack,
|
||||
sizeof *trav->avl_stack * trav->avl_height);
|
||||
}
|
||||
}
|
||||
|
||||
return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Returns the next data item in inorder
|
||||
within the tree being traversed with |trav|,
|
||||
or if there are no more data items returns |NULL|. */
|
||||
void *
|
||||
avl_t_next (struct avl_traverser *trav)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (trav != NULL);
|
||||
|
||||
if (trav->avl_generation != trav->avl_table->avl_generation)
|
||||
trav_refresh (trav);
|
||||
|
||||
x = trav->avl_node;
|
||||
if (x == NULL)
|
||||
{
|
||||
return avl_t_first (trav, trav->avl_table);
|
||||
}
|
||||
else if (x->avl_link[1] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[1];
|
||||
|
||||
while (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avl_node *y;
|
||||
|
||||
do
|
||||
{
|
||||
if (trav->avl_height == 0)
|
||||
{
|
||||
trav->avl_node = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
y = x;
|
||||
x = trav->avl_stack[--trav->avl_height];
|
||||
}
|
||||
while (y == x->avl_link[1]);
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x->avl_data;
|
||||
}
|
||||
|
||||
/* Returns the previous data item in inorder
|
||||
within the tree being traversed with |trav|,
|
||||
or if there are no more data items returns |NULL|. */
|
||||
void *
|
||||
avl_t_prev (struct avl_traverser *trav)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (trav != NULL);
|
||||
|
||||
if (trav->avl_generation != trav->avl_table->avl_generation)
|
||||
trav_refresh (trav);
|
||||
|
||||
x = trav->avl_node;
|
||||
if (x == NULL)
|
||||
{
|
||||
return avl_t_last (trav, trav->avl_table);
|
||||
}
|
||||
else if (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[0];
|
||||
|
||||
while (x->avl_link[1] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avl_node *y;
|
||||
|
||||
do
|
||||
{
|
||||
if (trav->avl_height == 0)
|
||||
{
|
||||
trav->avl_node = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
y = x;
|
||||
x = trav->avl_stack[--trav->avl_height];
|
||||
}
|
||||
while (y == x->avl_link[0]);
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x->avl_data;
|
||||
}
|
||||
|
||||
/* Returns |trav|'s current item. */
|
||||
void *
|
||||
avl_t_cur (struct avl_traverser *trav)
|
||||
{
|
||||
assert (trav != NULL);
|
||||
|
||||
return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Replaces the current item in |trav| by |new| and returns the item replaced.
|
||||
|trav| must not have the null item selected.
|
||||
The new item must not upset the ordering of the tree. */
|
||||
void *
|
||||
avl_t_replace (struct avl_traverser *trav, void *new)
|
||||
{
|
||||
void *old;
|
||||
|
||||
assert (trav != NULL && trav->avl_node != NULL && new != NULL);
|
||||
old = trav->avl_node->avl_data;
|
||||
trav->avl_node->avl_data = new;
|
||||
return old;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_error_recovery (struct avl_node **stack, int height,
|
||||
struct avl_table *new, avl_item_func *destroy)
|
||||
{
|
||||
assert (stack != NULL && height >= 0 && new != NULL);
|
||||
|
||||
for (; height > 2; height -= 2)
|
||||
stack[height - 1]->avl_link[1] = NULL;
|
||||
avl_destroy (new, destroy);
|
||||
}
|
||||
|
||||
/* Copies |org| to a newly created tree, which is returned.
|
||||
If |copy != NULL|, each data item in |org| is first passed to |copy|,
|
||||
and the return values are inserted into the tree,
|
||||
with |NULL| return values taken as indications of failure.
|
||||
On failure, destroys the partially created new tree,
|
||||
applying |destroy|, if non-null, to each item in the new tree so far,
|
||||
and returns |NULL|.
|
||||
If |allocator != NULL|, it is used for allocation in the new tree.
|
||||
Otherwise, the same allocator used for |org| is used. */
|
||||
struct avl_table *
|
||||
avl_copy (const struct avl_table *org, avl_copy_func *copy,
|
||||
avl_item_func *destroy, struct libavl_allocator *allocator)
|
||||
{
|
||||
struct avl_node *stack[2 * (AVL_MAX_HEIGHT + 1)];
|
||||
int height = 0;
|
||||
|
||||
struct avl_table *new;
|
||||
const struct avl_node *x;
|
||||
struct avl_node *y;
|
||||
|
||||
assert (org != NULL);
|
||||
new = avl_create (org->avl_compare, org->avl_param,
|
||||
allocator != NULL ? allocator : org->avl_alloc);
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
new->avl_count = org->avl_count;
|
||||
if (new->avl_count == 0)
|
||||
return new;
|
||||
|
||||
x = (const struct avl_node *) &org->avl_root;
|
||||
y = (struct avl_node *) &new->avl_root;
|
||||
for (;;)
|
||||
{
|
||||
while (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (height < 2 * (AVL_MAX_HEIGHT + 1));
|
||||
|
||||
y->avl_link[0] =
|
||||
new->avl_alloc->libavl_malloc (new->avl_alloc,
|
||||
sizeof *y->avl_link[0]);
|
||||
if (y->avl_link[0] == NULL)
|
||||
{
|
||||
if (y != (struct avl_node *) &new->avl_root)
|
||||
{
|
||||
y->avl_data = NULL;
|
||||
y->avl_link[1] = NULL;
|
||||
}
|
||||
|
||||
copy_error_recovery (stack, height, new, destroy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack[height++] = (struct avl_node *) x;
|
||||
stack[height++] = y;
|
||||
x = x->avl_link[0];
|
||||
y = y->avl_link[0];
|
||||
}
|
||||
y->avl_link[0] = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
y->avl_balance = x->avl_balance;
|
||||
if (copy == NULL)
|
||||
y->avl_data = x->avl_data;
|
||||
else
|
||||
{
|
||||
y->avl_data = copy (x->avl_data, org->avl_param);
|
||||
if (y->avl_data == NULL)
|
||||
{
|
||||
y->avl_link[1] = NULL;
|
||||
copy_error_recovery (stack, height, new, destroy);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (x->avl_link[1] != NULL)
|
||||
{
|
||||
y->avl_link[1] =
|
||||
new->avl_alloc->libavl_malloc (new->avl_alloc,
|
||||
sizeof *y->avl_link[1]);
|
||||
if (y->avl_link[1] == NULL)
|
||||
{
|
||||
copy_error_recovery (stack, height, new, destroy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
x = x->avl_link[1];
|
||||
y = y->avl_link[1];
|
||||
break;
|
||||
}
|
||||
else
|
||||
y->avl_link[1] = NULL;
|
||||
|
||||
if (height <= 2)
|
||||
return new;
|
||||
|
||||
y = stack[--height];
|
||||
x = stack[--height];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Frees storage allocated for |tree|.
|
||||
If |destroy != NULL|, applies it to each data item in inorder. */
|
||||
void
|
||||
avl_destroy (struct avl_table *tree, avl_item_func *destroy)
|
||||
{
|
||||
struct avl_node *p, *q;
|
||||
|
||||
assert (tree != NULL);
|
||||
|
||||
for (p = tree->avl_root; p != NULL; p = q)
|
||||
if (p->avl_link[0] == NULL)
|
||||
{
|
||||
q = p->avl_link[1];
|
||||
if (destroy != NULL && p->avl_data != NULL)
|
||||
destroy (p->avl_data, tree->avl_param);
|
||||
tree->avl_alloc->libavl_free (tree->avl_alloc, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
q = p->avl_link[0];
|
||||
p->avl_link[0] = q->avl_link[1];
|
||||
q->avl_link[1] = p;
|
||||
}
|
||||
|
||||
tree->avl_alloc->libavl_free (tree->avl_alloc, tree);
|
||||
}
|
||||
|
||||
/* Allocates |size| bytes of space using |malloc()|.
|
||||
Returns a null pointer if allocation fails. */
|
||||
void *
|
||||
avl_malloc (struct libavl_allocator *allocator, size_t size)
|
||||
{
|
||||
assert (allocator != NULL && size > 0);
|
||||
return malloc (size);
|
||||
}
|
||||
|
||||
/* Frees |block|. */
|
||||
void
|
||||
avl_free (struct libavl_allocator *allocator, void *block)
|
||||
{
|
||||
assert (allocator != NULL && block != NULL);
|
||||
free (block);
|
||||
}
|
||||
|
||||
/* Default memory allocator that uses |malloc()| and |free()|. */
|
||||
struct libavl_allocator avl_allocator_default =
|
||||
{
|
||||
avl_malloc,
|
||||
avl_free
|
||||
};
|
||||
|
||||
#undef NDEBUG
|
||||
#include <assert.h>
|
||||
|
||||
/* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */
|
||||
void
|
||||
(avl_assert_insert) (struct avl_table *table, void *item)
|
||||
{
|
||||
void **p = avl_probe (table, item);
|
||||
assert (p != NULL && *p == item);
|
||||
}
|
||||
|
||||
/* Asserts that |avl_delete()| really removes |item| from |table|,
|
||||
and returns the removed item. */
|
||||
void *
|
||||
(avl_assert_delete) (struct avl_table *table, void *item)
|
||||
{
|
||||
void *p = avl_delete (table, item);
|
||||
assert (p != NULL);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/* Produced by texiweb from libavl.w on 2002/08/24 at 13:21. */
|
||||
|
||||
/* libavl - library for manipulation of binary trees.
|
||||
Copyright (C) 1998-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The author may be contacted at <blp@gnu.org> on the Internet, or
|
||||
write to Ben Pfaff, Stanford University, Computer Science Dept., 353
|
||||
Serra Mall, Stanford CA 94305, USA.
|
||||
*/
|
||||
|
||||
#ifndef AVL_H
|
||||
#define AVL_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Function types. */
|
||||
typedef int avl_comparison_func (const void *avl_a, const void *avl_b,
|
||||
void *avl_param);
|
||||
typedef void avl_item_func (void *avl_item, void *avl_param);
|
||||
typedef void *avl_copy_func (void *avl_item, void *avl_param);
|
||||
|
||||
#ifndef LIBAVL_ALLOCATOR
|
||||
#define LIBAVL_ALLOCATOR
|
||||
/* Memory allocator. */
|
||||
struct libavl_allocator
|
||||
{
|
||||
void *(*libavl_malloc) (struct libavl_allocator *, size_t libavl_size);
|
||||
void (*libavl_free) (struct libavl_allocator *, void *libavl_block);
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Default memory allocator. */
|
||||
extern struct libavl_allocator avl_allocator_default;
|
||||
void *avl_malloc (struct libavl_allocator *, size_t);
|
||||
void avl_free (struct libavl_allocator *, void *);
|
||||
|
||||
/* Maximum AVL height. */
|
||||
#ifndef AVL_MAX_HEIGHT
|
||||
#define AVL_MAX_HEIGHT 32
|
||||
#endif
|
||||
|
||||
/* Tree data structure. */
|
||||
struct avl_table
|
||||
{
|
||||
struct avl_node *avl_root; /* Tree's root. */
|
||||
avl_comparison_func *avl_compare; /* Comparison function. */
|
||||
void *avl_param; /* Extra argument to |avl_compare|. */
|
||||
struct libavl_allocator *avl_alloc; /* Memory allocator. */
|
||||
size_t avl_count; /* Number of items in tree. */
|
||||
unsigned long avl_generation; /* Generation number. */
|
||||
};
|
||||
|
||||
/* An AVL tree node. */
|
||||
struct avl_node
|
||||
{
|
||||
struct avl_node *avl_link[2]; /* Subtrees. */
|
||||
void *avl_data; /* Pointer to data. */
|
||||
signed char avl_balance; /* Balance factor. */
|
||||
};
|
||||
|
||||
/* AVL traverser structure. */
|
||||
struct avl_traverser
|
||||
{
|
||||
struct avl_table *avl_table; /* Tree being traversed. */
|
||||
struct avl_node *avl_node; /* Current node in tree. */
|
||||
struct avl_node *avl_stack[AVL_MAX_HEIGHT];
|
||||
/* All the nodes above |avl_node|. */
|
||||
size_t avl_height; /* Number of nodes in |avl_parent|. */
|
||||
unsigned long avl_generation; /* Generation number. */
|
||||
};
|
||||
|
||||
/* Table functions. */
|
||||
struct avl_table *avl_create (avl_comparison_func *, void *,
|
||||
struct libavl_allocator *);
|
||||
struct avl_table *avl_copy (const struct avl_table *, avl_copy_func *,
|
||||
avl_item_func *, struct libavl_allocator *);
|
||||
void avl_destroy (struct avl_table *, avl_item_func *);
|
||||
void **avl_probe (struct avl_table *, void *);
|
||||
void *avl_insert (struct avl_table *, void *);
|
||||
void *avl_replace (struct avl_table *, void *);
|
||||
void *avl_delete (struct avl_table *, const void *);
|
||||
void *avl_find (const struct avl_table *, const void *);
|
||||
void avl_assert_insert (struct avl_table *, void *);
|
||||
void *avl_assert_delete (struct avl_table *, void *);
|
||||
|
||||
#define avl_count(table) ((size_t) (table)->avl_count)
|
||||
|
||||
/* Table traverser functions. */
|
||||
void avl_t_init (struct avl_traverser *, struct avl_table *);
|
||||
void *avl_t_first (struct avl_traverser *, struct avl_table *);
|
||||
void *avl_t_last (struct avl_traverser *, struct avl_table *);
|
||||
void *avl_t_find (struct avl_traverser *, struct avl_table *, void *);
|
||||
void *avl_t_insert (struct avl_traverser *, struct avl_table *, void *);
|
||||
void *avl_t_copy (struct avl_traverser *, const struct avl_traverser *);
|
||||
void *avl_t_next (struct avl_traverser *);
|
||||
void *avl_t_prev (struct avl_traverser *);
|
||||
void *avl_t_cur (struct avl_traverser *);
|
||||
void *avl_t_replace (struct avl_traverser *, void *);
|
||||
|
||||
#endif /* avl.h */
|
||||
@@ -1,22 +0,0 @@
|
||||
COMPILE
|
||||
=======
|
||||
|
||||
On Max OS X:
|
||||
$gcc -o taxonomy2tree -fast avl.c taxonomy2tree.c
|
||||
|
||||
On Linux:
|
||||
|
||||
Insert the following near the top of taxonomy2tree.c
|
||||
|
||||
#define isnumber (c) ( (c>='0') && (c<='9'))
|
||||
|
||||
Replace -fast with -O3 (the letter 'O'):
|
||||
|
||||
$gcc -o taxonomy2tree -O3 avl.c taxonomy2tree.c
|
||||
|
||||
INSTALL
|
||||
=======
|
||||
|
||||
Place the binary into a directory that is listed in setup_paths.sh script located in the root of Galaxy installation
|
||||
|
||||
|
||||
@@ -1,961 +0,0 @@
|
||||
|
||||
#include "avl.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define DEFAULT_STRING_ALLOC 16L
|
||||
#define NUMBER_OF_FIELDS 24
|
||||
#define NUMBER_OF_TAX_FIELDS 22
|
||||
#define AVL_THRESHOLD 64
|
||||
|
||||
char *rankLabels [NUMBER_OF_TAX_FIELDS] =
|
||||
{"root" ,
|
||||
"superkingdom",
|
||||
"kingdom" ,
|
||||
"subkingdom" ,
|
||||
"superphylum" ,
|
||||
"phylum" ,
|
||||
"subphylum" ,
|
||||
"superclass" ,
|
||||
"class" ,
|
||||
"subclass" ,
|
||||
"superorder" ,
|
||||
"order" ,
|
||||
"suborder" ,
|
||||
"superfamily" ,
|
||||
"family" ,
|
||||
"subfamily" ,
|
||||
"tribe" ,
|
||||
"subtribe" ,
|
||||
"genus" ,
|
||||
"subgenus" ,
|
||||
"species" ,
|
||||
"subspecies"
|
||||
};
|
||||
|
||||
static char *const Usage = "taxonomy2tree tax_dump_file(tab separated taxonomy dump) max_tree_level (<=0 to show all levels) file_for_the_tree file_for_tab_sep_summary include-empty-nodes(optional; 0 or 1; default 0)\n";
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void check_pointer (void*);
|
||||
|
||||
char validTaxonNameChar[256];
|
||||
|
||||
long currentLineID = 1;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct avl_table * idTagAVL = NULL,
|
||||
* uniqueTags = NULL,
|
||||
** byLevel = NULL;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct bufferedString
|
||||
{
|
||||
char *sData;
|
||||
long sLength,
|
||||
saLength;
|
||||
}
|
||||
*globalNameBuffer;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct vector
|
||||
{
|
||||
long *vData;
|
||||
|
||||
long vLength,
|
||||
vaLength;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void reportError (char * theMessage)
|
||||
{
|
||||
fprintf (stderr, "\nERROR: %s\n", theMessage);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void reportErrorLine (char * theMessage, long lineID)
|
||||
{
|
||||
fprintf (stderr, "SKIPPED line %d: %s\n", lineID, theMessage);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct bufferedString *allocateNewString (void)
|
||||
{
|
||||
struct bufferedString *newS = (struct bufferedString*)malloc (sizeof (struct bufferedString));
|
||||
check_pointer (newS);
|
||||
check_pointer (newS->sData = (char*)malloc (DEFAULT_STRING_ALLOC+1));
|
||||
newS->sLength = 0;
|
||||
newS->saLength = DEFAULT_STRING_ALLOC;
|
||||
newS->sData[0] = 0;
|
||||
return newS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct vector *allocateNewVector (void)
|
||||
{
|
||||
struct vector *newS = (struct vector*)malloc (sizeof (struct vector));
|
||||
check_pointer (newS);
|
||||
check_pointer (newS->vData = (long*)malloc (DEFAULT_STRING_ALLOC*sizeof(long)));
|
||||
newS->vLength = 0;
|
||||
newS->vaLength = DEFAULT_STRING_ALLOC;
|
||||
return newS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void clear_buffered_string (struct bufferedString* theString)
|
||||
{
|
||||
theString->sLength = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void clear_vector (struct vector* v)
|
||||
{
|
||||
v->vLength = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void appendCharacterToString (struct bufferedString * s, const char c)
|
||||
{
|
||||
long addThis;
|
||||
if (s->saLength == s->sLength)
|
||||
{
|
||||
addThis = s->saLength / 8;
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
s->saLength += addThis;
|
||||
check_pointer (s->sData = realloc (s->sData,s->saLength+1));
|
||||
}
|
||||
s->sData[s->sLength] = c;
|
||||
s->sData[++s->sLength] = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void appendValueToVector (struct vector * v, long c)
|
||||
{
|
||||
long addThis;
|
||||
if (v->vaLength == v->vLength)
|
||||
{
|
||||
addThis = v->vaLength / 8;
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
v->vaLength += addThis;
|
||||
check_pointer (v->vData = realloc (v->vData,sizeof(long)*v->vaLength));
|
||||
}
|
||||
v->vData[v->vLength++] = c;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
long appendRangeToString (struct bufferedString * d, struct bufferedString *s, long from, long to)
|
||||
{
|
||||
long addThis,
|
||||
pl = to-from+1;
|
||||
|
||||
if (pl<=0)
|
||||
return -1;
|
||||
|
||||
if (d->saLength < d->sLength + pl)
|
||||
{
|
||||
addThis = d->saLength / 8;
|
||||
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
if (addThis < pl)
|
||||
addThis = pl;
|
||||
|
||||
d->saLength += addThis;
|
||||
check_pointer (d->sData = realloc (d->sData,d->saLength+1));
|
||||
}
|
||||
for (addThis = from; addThis <=to; addThis++)
|
||||
d->sData[d->sLength++] = s->sData[addThis];
|
||||
|
||||
d->sData[d->sLength] = 0;
|
||||
|
||||
return pl;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void appendCharRangeToString (struct bufferedString * d, char * buffer)
|
||||
{
|
||||
long addThis,
|
||||
pl = strlen(buffer);
|
||||
|
||||
if (pl<=0)
|
||||
return;
|
||||
|
||||
if (d->saLength < d->sLength + pl)
|
||||
{
|
||||
addThis = d->saLength / 8;
|
||||
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
if (addThis < pl)
|
||||
addThis = pl;
|
||||
|
||||
d->saLength += addThis;
|
||||
check_pointer (d->sData = realloc (d->sData,d->saLength+1));
|
||||
}
|
||||
for (addThis = 0; addThis <pl; addThis++)
|
||||
d->sData[d->sLength++] = buffer[addThis];
|
||||
|
||||
d->sData[d->sLength] = 0;
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
long appendCharBufferToString (struct bufferedString * d, const char * b)
|
||||
{
|
||||
long addThis,
|
||||
pl = strlen (b);
|
||||
|
||||
if (pl<=0)
|
||||
return -1;
|
||||
|
||||
if (d->saLength < d->sLength + pl)
|
||||
{
|
||||
addThis = d->saLength / 8;
|
||||
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
if (addThis < pl)
|
||||
addThis = pl;
|
||||
|
||||
d->saLength += addThis;
|
||||
check_pointer (d->sData = realloc (d->sData,d->saLength+1));
|
||||
}
|
||||
for (addThis = 0; addThis <pl; addThis++)
|
||||
d->sData[d->sLength++] = b[addThis];
|
||||
|
||||
d->sData[d->sLength] = 0;
|
||||
return pl;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct treeNode
|
||||
{
|
||||
struct treeNode * parent;
|
||||
long startIndex,
|
||||
hitCount,
|
||||
length
|
||||
,beenhere;
|
||||
|
||||
struct vector * children;
|
||||
struct avl_table* cachedChildren;
|
||||
|
||||
} *globalTreeRoot;
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct treeNode * allocateNewTreeNode (void)
|
||||
{
|
||||
struct treeNode *newN = (struct treeNode*)malloc (sizeof (struct treeNode));
|
||||
check_pointer (newN);
|
||||
newN->parent = NULL;
|
||||
newN->startIndex = 0;
|
||||
newN->length = 0;
|
||||
newN->hitCount = 0;
|
||||
newN->beenhere = 0;
|
||||
newN->cachedChildren = NULL;
|
||||
newN->children = allocateNewVector();
|
||||
check_pointer (newN->children);
|
||||
return newN;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int compare_tree_nodes (const void *avl_a, const void *avl_b, void * xtra)
|
||||
{
|
||||
long t1 = ((struct treeNode*)avl_a)->startIndex,
|
||||
t2 = ((struct treeNode*)avl_b)->startIndex;
|
||||
|
||||
if (t1 < t2)
|
||||
return -1;
|
||||
if (t1 > t2)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void destroyTreeNode (struct treeNode* n)
|
||||
{
|
||||
if (n->cachedChildren)
|
||||
avl_destroy (n->cachedChildren, NULL);
|
||||
free (n->children);
|
||||
free (n);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void printTreeNode (FILE* f, struct treeNode* n)
|
||||
{
|
||||
long i = 0;
|
||||
fprintf (f, "Node name: ");
|
||||
if (n->startIndex>=0)
|
||||
{
|
||||
for (;i < n->length; i++)
|
||||
fputc (globalNameBuffer->sData[n->startIndex + i], f);
|
||||
}
|
||||
else
|
||||
fprintf (f, " empty node");
|
||||
fprintf (f, "\nHit count %d (backup %d)\n", n->hitCount, n->beenhere);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void traverseCheck (struct treeNode* n, char first)
|
||||
{
|
||||
long i = 0;
|
||||
|
||||
if (!first && n->startIndex >= 0 && n->beenhere != n->hitCount)
|
||||
{
|
||||
printTreeNode (stderr, n);
|
||||
//reportError ("DEATH AND DECAY, BIZNATCH!\n");
|
||||
}
|
||||
|
||||
for (i = 0; i<n->children->vLength; i++)
|
||||
traverseCheck (((struct treeNode**)n->children->vData)[i], first);
|
||||
|
||||
if (first)
|
||||
{
|
||||
if (n->children->vLength == 0)
|
||||
n->beenhere = n->hitCount;
|
||||
|
||||
if (n->parent)
|
||||
n->parent->beenhere += n->beenhere;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void traverseTree (FILE *summaryFile, struct treeNode* n, long maxDepth, long currentDepth)
|
||||
{
|
||||
long i = 0;
|
||||
char c;
|
||||
|
||||
if (currentDepth <= maxDepth)
|
||||
{
|
||||
if (n->children->vLength && maxDepth > currentDepth)
|
||||
{
|
||||
if (n->startIndex < 0)
|
||||
{
|
||||
for (i=0; i>n->startIndex && currentDepth - i < maxDepth; i--)
|
||||
fputc ('(', summaryFile);
|
||||
if (i == n->startIndex)
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
fputc ('(',summaryFile);
|
||||
|
||||
if (i==0)
|
||||
for (; i<n->children->vLength; i++)
|
||||
{
|
||||
traverseTree (summaryFile, ((struct treeNode**)n->children->vData)[i], maxDepth, currentDepth+1);
|
||||
if (i<n->children->vLength-1)
|
||||
fputc (',',summaryFile);
|
||||
}
|
||||
|
||||
if (n->startIndex < 0)
|
||||
for (i=0; i>n->startIndex+1 && currentDepth - i < maxDepth; i--)
|
||||
fprintf (summaryFile,")n:%d", n->hitCount);
|
||||
fputc (')',summaryFile);
|
||||
}
|
||||
|
||||
if (n->startIndex>= 0)
|
||||
{
|
||||
for (i=n->startIndex; i<n->startIndex+n->length;i++)
|
||||
{
|
||||
c = globalNameBuffer->sData[i];
|
||||
if (validTaxonNameChar [c])
|
||||
fputc (c,summaryFile);
|
||||
else
|
||||
fputc ('_',summaryFile);
|
||||
}
|
||||
fprintf (summaryFile,":%d", n->hitCount);
|
||||
}
|
||||
else
|
||||
fprintf (summaryFile, "n:%d", n->hitCount);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
struct treeNode * addAChild (struct treeNode* p, struct treeNode * c, char killIfD)
|
||||
{
|
||||
struct treeNode * c2 = NULL;
|
||||
long i = 0;
|
||||
char addNode = 0;
|
||||
|
||||
if (p->cachedChildren)
|
||||
{
|
||||
if ((c2 = ((struct treeNode*)avl_find (p->cachedChildren, c))) == NULL)
|
||||
addNode = 1;
|
||||
/*else
|
||||
{
|
||||
if (c2->startIndex > globalNameBuffer->sLength || c2->startIndex < 0)
|
||||
printf ("Reject node add %x %d %d\n", c2, c2->startIndex, c->startIndex);
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; i<p->children->vLength; i++)
|
||||
if (((struct treeNode**)p->children->vData)[i]->startIndex == c->startIndex)
|
||||
break;
|
||||
addNode = (p->children->vLength == i);
|
||||
}
|
||||
|
||||
if (addNode)
|
||||
{
|
||||
if (c->parent && c->parent != p)
|
||||
{
|
||||
c2 = allocateNewTreeNode();
|
||||
c2->startIndex = c->startIndex;
|
||||
c2->length = c->length;
|
||||
c2->hitCount = 1;
|
||||
//if (p->cachedChildren)
|
||||
// fprintf (stdout, "%x %x\n", p, c->parent);
|
||||
c = c2;
|
||||
|
||||
}
|
||||
c->parent = p;
|
||||
appendValueToVector (p->children, (long)c);
|
||||
if (p->children->vLength > AVL_THRESHOLD)
|
||||
if (p->cachedChildren == NULL)
|
||||
{
|
||||
//fprintf (stdout, "Switch %d\n", currentLineID);
|
||||
// switch over the the avl representation of nodes
|
||||
p->cachedChildren = avl_create (compare_tree_nodes, NULL, NULL);
|
||||
for (i=0; i<p->children->vLength; i++)
|
||||
avl_probe(p->cachedChildren, ((struct node**)p->children->vData)[i]);
|
||||
}
|
||||
else
|
||||
avl_probe (p->cachedChildren, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (killIfD)
|
||||
destroyTreeNode (c);
|
||||
if (c2)
|
||||
return c2;
|
||||
else
|
||||
c = ((struct treeNode**)p->children->vData)[i];
|
||||
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct storedIDTag
|
||||
{
|
||||
long taxID,
|
||||
hit_count;
|
||||
struct treeNode * tNode;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct storedIDTag *allocateIDTag (void)
|
||||
{
|
||||
struct storedIDTag *newS = (struct storedIDTag*)malloc (sizeof (struct storedIDTag));
|
||||
check_pointer (newS);
|
||||
newS->taxID = -1;
|
||||
newS->hit_count = 0;
|
||||
newS->tNode = NULL;
|
||||
return newS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int compare_id_tags (const void *avl_a, const void *avl_b, void * xtra)
|
||||
{
|
||||
long t1 = ((struct storedIDTag*)avl_a)->taxID,
|
||||
t2 = ((struct storedIDTag*)avl_b)->taxID;
|
||||
|
||||
if (t1 < t2)
|
||||
return -1;
|
||||
if (t1 > t2)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct storedSequenceTag
|
||||
{
|
||||
long startIndex,
|
||||
length;
|
||||
|
||||
struct treeNode * refNode;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct storedSequenceTag *allocateStringTag (void)
|
||||
{
|
||||
struct storedSequenceTag *newS = (struct storedSequenceTag*)malloc (sizeof (struct storedSequenceTag));
|
||||
check_pointer (newS);
|
||||
newS->startIndex = -1;
|
||||
newS->length = 0;
|
||||
newS->refNode = NULL;
|
||||
return newS;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
struct storedSequenceTag * storedSequenceTag (void)
|
||||
{
|
||||
struct storedSequenceTag *newS = (struct storedSequenceTag*)malloc (sizeof (struct storedSequenceTag));
|
||||
check_pointer (newS);
|
||||
newS->startIndex = 0;
|
||||
newS->length = 0;
|
||||
return newS;
|
||||
}*/
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int compare_tags (const void *avl_a, const void *avl_b, void * xtra)
|
||||
{
|
||||
char* n1 = globalNameBuffer->sData+((struct storedSequenceTag*)avl_a)->startIndex,
|
||||
* n2 = globalNameBuffer->sData+((struct storedSequenceTag*)avl_b)->startIndex;
|
||||
|
||||
long l1 = ((struct storedSequenceTag*)avl_a)->length,
|
||||
l2 = ((struct storedSequenceTag*)avl_b)->length,
|
||||
i;
|
||||
|
||||
signed char c;
|
||||
|
||||
for (i = 0; i < l1 && i < l2; i++)
|
||||
{
|
||||
c = n1[i] - n2[i];
|
||||
if (c < 0)
|
||||
return -1;
|
||||
if (c>0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (l1 < l2)
|
||||
return -1;
|
||||
if (l1 > l2)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void check_pointer (void * p)
|
||||
{
|
||||
if (p == NULL)
|
||||
{
|
||||
fprintf (stderr,"Memory allocation error\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int compare_strings (const struct bufferedString * s1, const struct bufferedString * s2)
|
||||
{
|
||||
long upTo,
|
||||
i;
|
||||
|
||||
if (s1->sLength>s2->sLength)
|
||||
upTo = s2->sLength;
|
||||
else
|
||||
upTo = s1->sLength;
|
||||
|
||||
for (i=0; i<upTo; i++)
|
||||
{
|
||||
int res = (s1->sData[i]-s2->sData[i]);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
else
|
||||
if (res>0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (s1->sLength == s2->sLength)
|
||||
return 0;
|
||||
|
||||
return 1-2*(s1->sLength<s2->sLength);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void destroy_string (struct bufferedString* aStr)
|
||||
{
|
||||
free (aStr->sData);
|
||||
free (aStr);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
|
||||
struct bufferedString **currentBuffers;
|
||||
|
||||
struct storedIDTag *aTag = allocateIDTag(),
|
||||
*aTag2;
|
||||
|
||||
struct storedSequenceTag *sTag = allocateStringTag(),
|
||||
*sTag2,
|
||||
*sTag3;
|
||||
|
||||
struct avl_traverser avlt;
|
||||
|
||||
struct treeNode *currentParent = NULL,
|
||||
*currentNode;
|
||||
|
||||
char automatonState = 0,
|
||||
currentField = 0,
|
||||
currentChar = 0,
|
||||
showEmptyNodes = 0;
|
||||
|
||||
long expectedFields = NUMBER_OF_FIELDS,
|
||||
indexer,
|
||||
indexer2,
|
||||
indexer3,
|
||||
maxTreeLevel = 0,
|
||||
setEOF = 0,
|
||||
nRunCounter = 0;
|
||||
|
||||
FILE * treeFile = NULL,
|
||||
* summaryFile = NULL,
|
||||
* inFile = NULL;
|
||||
|
||||
globalNameBuffer = allocateNewString();
|
||||
globalTreeRoot = allocateNewTreeNode();
|
||||
currentBuffers = (struct bufferedString**)malloc (expectedFields*sizeof (struct bufferedString*));
|
||||
byLevel = (struct avl_table**)malloc (sizeof (struct avl_table*) * NUMBER_OF_TAX_FIELDS);
|
||||
check_pointer (uniqueTags = avl_create (compare_tags, NULL, NULL));
|
||||
check_pointer (idTagAVL = avl_create (compare_id_tags, NULL, NULL));
|
||||
|
||||
for (indexer = 0; indexer < NUMBER_OF_TAX_FIELDS; indexer++)
|
||||
check_pointer (byLevel[indexer] = avl_create (compare_tags, NULL, NULL));
|
||||
|
||||
for (indexer = 0; indexer < expectedFields; indexer++)
|
||||
currentBuffers[indexer] = allocateNewString();
|
||||
|
||||
if (argc != 6 && argc != 5)
|
||||
{
|
||||
fprintf (stderr,"%s",Usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
maxTreeLevel = atoi (argv[2]);
|
||||
|
||||
inFile = fopen (argv[1], "rb");
|
||||
if (!inFile)
|
||||
{
|
||||
fprintf (stderr, "Failed to open the input file %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
treeFile = fopen (argv[3], "wb");
|
||||
if (!treeFile)
|
||||
{
|
||||
fprintf (stderr, "Failed to open the tree output file %s\n", argv[3]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
summaryFile = fopen (argv[4], "wb");
|
||||
if (!summaryFile)
|
||||
{
|
||||
fprintf (stderr, "Failed to open the summary output file %s\n", argv[4]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc == 6)
|
||||
showEmptyNodes = atoi (argv[5]);
|
||||
|
||||
currentChar = fgetc(inFile);
|
||||
currentField = 0;
|
||||
while (setEOF < 2)
|
||||
{
|
||||
switch (automatonState)
|
||||
{
|
||||
case 0: /* start of the line; expecting numbers or charcters */
|
||||
if (isalnum(currentChar))
|
||||
{
|
||||
automatonState = 1; /* reading sequence ID */
|
||||
appendCharacterToString(currentBuffers[currentField],toupper(currentChar));
|
||||
}
|
||||
else
|
||||
if (!(currentChar == '\n' || currentChar == '\r'))
|
||||
{
|
||||
reportErrorLine ("Could not find a valid gid number to start the line",currentLineID);
|
||||
automatonState = 6;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* reading sequence ID */
|
||||
if (currentChar == '\t')
|
||||
{
|
||||
automatonState = 2;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
{
|
||||
reportErrorLine ("Expected a tab following the gid",currentLineID);
|
||||
automatonState = 6;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
appendCharacterToString(currentBuffers[currentField],toupper(currentChar));
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* looking for a \t or a \n|\r*/
|
||||
if (currentChar == '\t')
|
||||
{
|
||||
currentField ++;
|
||||
if (currentField < expectedFields)
|
||||
automatonState = 3;
|
||||
|
||||
//reportErrorLine ("Too many fields",currentLineID);
|
||||
//automatonState = 6;
|
||||
//continue;
|
||||
}
|
||||
else
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
// finish the read
|
||||
{
|
||||
if (currentField < expectedFields-1)
|
||||
reportErrorLine ("Too few fields",currentLineID);
|
||||
aTag->taxID = atoi (currentBuffers[1]->sData);
|
||||
aTag->hit_count = 1;
|
||||
aTag2 = *(struct storedIDTag**)avl_probe(idTagAVL, aTag);
|
||||
//fprintf (stdout, "%d %d %x %x\n", currentLineID,aTag->taxID,aTag,aTag2);
|
||||
if (aTag == aTag2) // new taxID
|
||||
{
|
||||
// process fields
|
||||
currentParent = globalTreeRoot;
|
||||
nRunCounter = 0;
|
||||
for (indexer = NUMBER_OF_FIELDS-NUMBER_OF_TAX_FIELDS; indexer < NUMBER_OF_FIELDS; indexer++)
|
||||
{
|
||||
indexer2 = strlen(currentBuffers[indexer]->sData);
|
||||
//fprintf (stdout, "%d %d\n", indexer, nRunCounter,indexer2);
|
||||
if ((currentBuffers[indexer])->sData[0] == 'n' && indexer2 == 1)
|
||||
nRunCounter++;
|
||||
else
|
||||
{
|
||||
indexer3 = globalNameBuffer->sLength;
|
||||
appendRangeToString (globalNameBuffer,currentBuffers[indexer],0,indexer2-1);
|
||||
sTag->startIndex = indexer3;
|
||||
sTag->length = indexer2;
|
||||
sTag2 = *(struct storedSequenceTag**)avl_probe (uniqueTags,sTag);
|
||||
if (sTag == sTag2) // added
|
||||
sTag = allocateStringTag();
|
||||
else
|
||||
globalNameBuffer->sLength = indexer3;
|
||||
|
||||
sTag->startIndex = sTag2->startIndex;
|
||||
sTag->length = sTag2->length;
|
||||
|
||||
sTag3 = *(struct storedSequenceTag**)avl_probe (byLevel[indexer-(NUMBER_OF_FIELDS-NUMBER_OF_TAX_FIELDS)],sTag);
|
||||
if (sTag == sTag3) // new node
|
||||
{
|
||||
//fprintf (stderr, "Add node level %d %d\n",indexer-(NUMBER_OF_FIELDS-NUMBER_OF_TAX_FIELDS), sTag2->startIndex);
|
||||
sTag3 = sTag;
|
||||
sTag3->refNode = allocateNewTreeNode();
|
||||
sTag3->refNode->length = sTag2->length;
|
||||
sTag3->refNode->startIndex = sTag2->startIndex;
|
||||
sTag3->refNode->parent = NULL;
|
||||
sTag = allocateStringTag();
|
||||
}
|
||||
//else
|
||||
//fprintf (stderr, "Have node %x %x %c%c %d\n",sTag3->refNode, (currentBuffers[indexer])->sData[0],(currentBuffers[indexer])->sData[1], currentParent->children->vLength);
|
||||
|
||||
sTag3->refNode->hitCount++;
|
||||
|
||||
if (showEmptyNodes && nRunCounter>0)
|
||||
{
|
||||
currentNode = allocateNewTreeNode();
|
||||
currentNode->startIndex = -nRunCounter;
|
||||
currentNode->hitCount = 1;
|
||||
if (currentParent)
|
||||
currentParent = addAChild (currentParent,currentNode,1);
|
||||
else
|
||||
reportError ("Attempting to attach an empty node a null parent.");
|
||||
}
|
||||
|
||||
if (currentParent)
|
||||
currentParent = addAChild (currentParent,sTag3->refNode,0);
|
||||
else
|
||||
currentParent = sTag3->refNode;
|
||||
|
||||
nRunCounter = 0;
|
||||
}
|
||||
}
|
||||
if (nRunCounter>0)
|
||||
{
|
||||
currentNode = allocateNewTreeNode();
|
||||
currentNode->startIndex = -nRunCounter;
|
||||
currentNode->hitCount = 1;
|
||||
if (currentParent)
|
||||
currentParent = addAChild (currentParent,currentNode,1);
|
||||
else
|
||||
reportError ("Attempting to attach an empty node a null parent.");
|
||||
}
|
||||
aTag->tNode = currentParent;
|
||||
aTag = allocateIDTag();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
aTag2->hit_count++;
|
||||
currentParent = aTag2->tNode;
|
||||
while (currentParent)
|
||||
{
|
||||
currentParent->hitCount++;
|
||||
currentParent = currentParent->parent;
|
||||
}
|
||||
//printf ("Duplicate tag %d %d\n", aTag2->hit_count, aTag2->taxID);
|
||||
}
|
||||
//traverseCheck (globalTreeRoot);
|
||||
automatonState = 5;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentField < expectedFields)
|
||||
{
|
||||
reportErrorLine ("Expected a tab following a field",currentLineID);
|
||||
automatonState = 6;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* read a field */
|
||||
if (currentChar == '\t')
|
||||
{
|
||||
automatonState = 2;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
{
|
||||
currentField++;
|
||||
automatonState = 2;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentChar == '\'')
|
||||
automatonState = 4;
|
||||
else
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* inside ' ' */
|
||||
if (currentChar == '\'')
|
||||
automatonState = 3;
|
||||
else
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
{
|
||||
reportErrorLine ("Premature line end while reading a literal",currentLineID);
|
||||
automatonState = 5;
|
||||
}
|
||||
else
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
automatonState = 0;
|
||||
currentLineID ++;
|
||||
currentField = 0;
|
||||
for (indexer = 0; indexer < expectedFields; indexer++)
|
||||
clear_buffered_string(currentBuffers[indexer]);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
automatonState = 5;
|
||||
break;
|
||||
}
|
||||
currentChar = fgetc(inFile);
|
||||
if (feof (inFile))
|
||||
{
|
||||
setEOF ++;
|
||||
currentChar = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (stderr, "Read %d unique taxIDs\n", avl_count (idTagAVL));
|
||||
|
||||
fclose (inFile);
|
||||
|
||||
indexer3 = ((maxTreeLevel>0)?(maxTreeLevel+1):0xfffffL);
|
||||
if (indexer3 > NUMBER_OF_TAX_FIELDS)
|
||||
indexer3 = NUMBER_OF_TAX_FIELDS;
|
||||
for (indexer = 0; indexer < indexer3; indexer++)
|
||||
{
|
||||
avl_t_init (&avlt, byLevel[indexer]);
|
||||
sTag = (struct storedSequenceTag*)avl_t_first (&avlt, byLevel[indexer]);
|
||||
while (sTag)
|
||||
{
|
||||
fprintf (summaryFile, "%s\t", rankLabels[indexer]);
|
||||
for (indexer2 = 0; indexer2 < sTag->length; indexer2++)
|
||||
fputc(*(globalNameBuffer->sData+sTag->startIndex+indexer2),summaryFile);
|
||||
fprintf (summaryFile, "\t%d\n", sTag->refNode->hitCount);
|
||||
sTag = (struct storedSequenceTag*)avl_t_next (&avlt);
|
||||
}
|
||||
//fprintf (stderr, "Level %d unique IDs = %d\n", indexer, avl_count (byLevel[indexer]));
|
||||
}
|
||||
|
||||
for (indexer = 0; indexer < 256; indexer ++)
|
||||
validTaxonNameChar[indexer] = 1;
|
||||
|
||||
validTaxonNameChar[','] = 0;
|
||||
validTaxonNameChar[')'] = 0;
|
||||
validTaxonNameChar['('] = 0;
|
||||
validTaxonNameChar[':'] = 0;
|
||||
|
||||
|
||||
traverseTree (treeFile,((struct treeNode**)globalTreeRoot->children->vData)[0],(maxTreeLevel>0)?(maxTreeLevel+1):0xfffffL,0);
|
||||
fclose (treeFile);
|
||||
traverseCheck (((struct treeNode**)globalTreeRoot->children->vData)[0], 1);
|
||||
traverseCheck (((struct treeNode**)globalTreeRoot->children->vData)[0], 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
137 9913 root Eukaryota Metazoa n n Chordata Craniata Gnathostomata Mammalia n Laurasiatheria n Ruminantia n Bovidae Bovinae n n Bos n Bos taurus n
|
||||
565 9913 root Eukaryota Metazoa n n Chordata Craniata Gnathostomata Mammalia n Laurasiatheria n Ruminantia n Bovidae Bovinae n n Bos n Bos taurus n
|
||||
723 9913 root Eukaryota Metazoa n n Chordata Craniata Gnathostomata Mammalia n Laurasiatheria n Ruminantia n Bovidae Bovinae n n Bos n Bos taurus n
|
||||
724 9913 root Eukaryota Metazoa n n Chordata Craniata Gnathostomata Mammalia n Laurasiatheria n Ruminantia n Bovidae Bovinae n n Bos n Bos taurus n
|
||||
725 9913 root Eukaryota Metazoa n n Chordata Craniata Gnathostomata Mammalia n Laurasiatheria n Ruminantia n Bovidae Bovinae n n Bos n Bos taurus n
|
||||
1707 9986 root Eukaryota Metazoa n n Chordata Craniata Gnathostomata Mammalia n Euarchontoglires Lagomorpha n n Leporidae n n n Oryctolagus n Oryctolagus cuniculus n
|
||||
1708 9986 root Eukaryota Metazoa n n Chordata Craniata Gnathostomata Mammalia n Euarchontoglires Lagomorpha n n Leporidae n n n Oryctolagus n Oryctolagus cuniculus n
|
||||
2474 27373 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Diversisporales n n Acaulosporaceae n n n Acaulospora n Acaulospora rugosa n
|
||||
2480 27374 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Diversisporales n n Acaulosporaceae n n n Acaulospora n Acaulospora spinosa n
|
||||
2484 4971 root Eukaryota Fungi Dikarya n Basidiomycota n n Tremellomycetes n n Tremellales n n Tremellaceae n n n Bulleromyces n Bulleromyces albus n
|
||||
2485 5007 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n Saccharomycetaceae n n n Dekkera n Dekkera bruxellensis n
|
||||
2486 4808 root Eukaryota Fungi n n Blastocladiomycota n n Blastocladiomycetes n n Blastocladiales n n Blastocladiaceae n n n Blastocladiella n Blastocladiella emersonii n
|
||||
2507 5476 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n n n n n Candida n Candida albicans n
|
||||
2575 5478 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n n n n n Candida n Candida glabrata n
|
||||
2588 5501 root Eukaryota Fungi Dikarya n Ascomycota Pezizomycotina n Eurotiomycetes Eurotiomycetidae n Onygenales n n n n n n Coccidioides n Coccidioides immitis n
|
||||
2616 5207 root Eukaryota Fungi Dikarya n Basidiomycota n n Tremellomycetes n n Tremellales n n Tremellaceae n n n Filobasidiella n Filobasidiella neoformans n
|
||||
2685 58641 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n Saccharomycetaceae n n n Debaryomyces n Debaryomyces hansenii Debaryomyces hansenii var. hansenii
|
||||
2686 4959 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n Saccharomycetaceae n n n Debaryomyces n Debaryomyces hansenii n
|
||||
2687 5793 root Eukaryota n n n n n n n Myxogastromycetidae n Physariida n n n n n n Didymium n Didymium iridis n
|
||||
2694 27376 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Diversisporales n n Acaulosporaceae n n n Entrophospora n Entrophospora colombiana n
|
||||
2709 4872 root Eukaryota Fungi n n n Mucoromycotina n n n n Endogonales n n Endogonaceae n n n Endogone n Endogone pisiformis n
|
||||
2711 27377 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Diversisporales n n Acaulosporaceae n n n Entrophospora n Entrophospora sp. WV 796 n
|
||||
2737 27378 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Diversisporales n n Gigasporaceae n n n Gigaspora n Gigaspora albida n
|
||||
2738 27380 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Glomerales n n Glomeraceae n n n Glomus n Glomus etunicatum n
|
||||
2742 27379 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Diversisporales n n Gigasporaceae n n n Gigaspora n Gigaspora gigantea n
|
||||
2743 4876 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Glomerales n n Glomeraceae n n n Glomus n Glomus intraradices n
|
||||
2744 44941 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Diversisporales n n Gigasporaceae n n n Gigaspora n Gigaspora rosea n
|
||||
2745 27381 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Glomerales n n Glomeraceae n n n Glomus n Glomus mosseae n
|
||||
2759 5037 root Eukaryota Fungi Dikarya n Ascomycota Pezizomycotina n Eurotiomycetes Eurotiomycetidae n Onygenales n n Ajellomycetaceae n n n Ajellomyces n Ajellomyces capsulatus n
|
||||
2806 28985 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n Saccharomycetaceae n n n Kluyveromyces n Kluyveromyces lactis n
|
||||
2922 4803 root Eukaryota n n n n n n n n n Lagenidiales n n Lagenidiaceae n n n Lagenidium n Lagenidium giganteum n
|
||||
2924 5278 root Eukaryota Fungi Dikarya n Basidiomycota Pucciniomycotina n n Microbotryomycetes n Leucosporidiales n n n n n n Leucosporidium n Leucosporidium scottii n
|
||||
2961 4841 root Eukaryota Fungi n n n Mucoromycotina n n n n Mucorales n n Mucoraceae n n n Mucor n Mucor racemosus n
|
||||
3080 5141 root Eukaryota Fungi Dikarya n Ascomycota Pezizomycotina n Sordariomycetes Sordariomycetidae n Sordariales n n Sordariaceae n n n Neurospora n Neurospora crassa n
|
||||
3093 4927 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n Saccharomycetaceae n n n Pichia n Pichia anomala n
|
||||
3105 5145 root Eukaryota Fungi Dikarya n Ascomycota Pezizomycotina n Sordariomycetes Sordariomycetidae n Sordariales n n Lasiosphaeriaceae n n n Podospora n Podospora anserina n
|
||||
3179 4926 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n Saccharomycetaceae n n n Pichia n Pichia membranifaciens n
|
||||
3182 4788 root Eukaryota n n n n n n n n n Peronosporales n n n n n n Phytophthora n Phytophthora megasperma n
|
||||
3185 5791 root Eukaryota n n n n n n n Myxogastromycetidae n Physariida n n n n n n Physarum n Physarum polycephalum n
|
||||
3221 5791 root Eukaryota n n n n n n n Myxogastromycetidae n Physariida n n n n n n Physarum n Physarum polycephalum n
|
||||
3225 5791 root Eukaryota n n n n n n n Myxogastromycetidae n Physariida n n n n n n Physarum n Physarum polycephalum n
|
||||
3273 5286 root Eukaryota Fungi Dikarya n Basidiomycota Pucciniomycotina n n Microbotryomycetes n Sporidiobolales n n n n n n Rhodosporidium n Rhodosporidium toruloides n
|
||||
4347 4932 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n Saccharomycetaceae n n n Saccharomyces n Saccharomyces cerevisiae n
|
||||
4844 27383 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Diversisporales n n Gigasporaceae n n n Scutellospora n Scutellospora dipapillosa n
|
||||
4893 4896 root Eukaryota Fungi Dikarya n Ascomycota Taphrinomycotina n Schizosaccharomycetes n n Schizosaccharomycetales n n Schizosaccharomycetaceae n n n Schizosaccharomyces n Schizosaccharomyces pombe n
|
||||
5039 27384 root Eukaryota Fungi n n Glomeromycota n n Glomeromycetes n n Diversisporales n n Gigasporaceae n n n Scutellospora n Scutellospora pellucida n
|
||||
5075 4896 root Eukaryota Fungi Dikarya n Ascomycota Taphrinomycotina n Schizosaccharomycetes n n Schizosaccharomycetales n n Schizosaccharomycetaceae n n n Schizosaccharomyces n Schizosaccharomyces pombe n
|
||||
5153 40563 root Eukaryota Fungi Dikarya n Basidiomycota Pucciniomycotina n n Microbotryomycetes n Sporidiobolales n n n n n n Sporobolomyces n Sporobolomyces roseus n
|
||||
5174 5554 root Eukaryota Fungi Dikarya n Basidiomycota n n Tremellomycetes n n Tremellales n n n n n n Trichosporon n Trichosporon cutaneum n
|
||||
5175 4950 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n Saccharomycetaceae n n n Torulaspora n Torulaspora delbrueckii n
|
||||
5186 5551 root Eukaryota Fungi Dikarya n Ascomycota Pezizomycotina n Eurotiomycetes Eurotiomycetidae n Onygenales n n Arthrodermataceae n n n Trichophyton n Trichophyton rubrum n
|
||||
5232 5270 root Eukaryota Fungi Dikarya n Basidiomycota Ustilaginomycotina n Ustilaginomycetes n n Ustilaginales n n Ustilaginaceae n n n Ustilago n Ustilago maydis n
|
||||
5257 4956 root Eukaryota Fungi Dikarya n Ascomycota Saccharomycotina n Saccharomycetes n n Saccharomycetales n n Saccharomycetaceae n n n Zygosaccharomyces n Zygosaccharomyces rouxii n
|
||||
5552 7160 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Nematocera Culicoidea Culicidae Culicinae Culicini n Aedes Stegomyia Aedes albopictus n
|
||||
5654 7119 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera Amphiesmenoptera Lepidoptera Glossata Bombycoidea Saturniidae Saturniinae Saturniini n Antheraea n Antheraea pernyi n
|
||||
5691 7642 root Eukaryota Metazoa n n Echinodermata n Echinozoa Echinoidea Euechinoidea Echinacea Arbacoida n n Arbaciidae n n n Arbacia n Arbacia sp. n
|
||||
5702 85549 root Eukaryota Metazoa n n Arthropoda Crustacea n Branchiopoda Sarsostraca n Anostraca n n Artemiidae n n n Artemia n Artemia salina n
|
||||
5704 6108 root Eukaryota Metazoa n n Cnidaria n n Anthozoa Hexacorallia n Actiniaria Nynantheae n Actiniidae n n n Anemonia n Anemonia sulcata n
|
||||
5713 5866 root Eukaryota n n n Apicomplexa n n Aconoidasida n n n n n Babesiidae n n n Babesia n Babesia bigemina n
|
||||
5714 5866 root Eukaryota n n n Apicomplexa n n Aconoidasida n n n n n Babesiidae n n n Babesia n Babesia bigemina n
|
||||
5715 5866 root Eukaryota n n n Apicomplexa n n Aconoidasida n n n n n Babesiidae n n n Babesia n Babesia bigemina n
|
||||
5716 5871 root Eukaryota n n n Apicomplexa n n Aconoidasida n n n n n Babesiidae n n n Babesia n Babesia caballi n
|
||||
5718 5872 root Eukaryota n n n Apicomplexa n n Aconoidasida n n n n n Babesiidae n n n Babesia n Babesia equi n
|
||||
5907 7091 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera Amphiesmenoptera Lepidoptera Glossata Bombycoidea Bombycidae Bombycinae n n Bombyx n Bombyx mori n
|
||||
5909 7091 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera Amphiesmenoptera Lepidoptera Glossata Bombycoidea Bombycidae Bombycinae n n Bombyx n Bombyx mori n
|
||||
5914 7091 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera Amphiesmenoptera Lepidoptera Glossata Bombycoidea Bombycidae Bombycinae n n Bombyx n Bombyx mori n
|
||||
5919 7091 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera Amphiesmenoptera Lepidoptera Glossata Bombycoidea Bombycidae Bombycinae n n Bombyx n Bombyx mori n
|
||||
5954 7038 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Hemiptera n Aleyrodoidea Aleyrodidae Aleyrodinae n n Bemisia n Bemisia tabaci n
|
||||
5955 7038 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Hemiptera n Aleyrodoidea Aleyrodidae Aleyrodinae n n Bemisia n Bemisia tabaci n
|
||||
6830 6239 root Eukaryota Metazoa n n Nematoda n n Chromadorea n n Rhabditida n Rhabditoidea Rhabditidae Peloderinae n n Caenorhabditis n Caenorhabditis elegans n
|
||||
6831 7373 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Brachycera Oestroidea Calliphoridae Calliphorinae n n Calliphora n Calliphora vicina n
|
||||
6997 5808 root Eukaryota n n n Apicomplexa n n Coccidia n n Eucoccidiorida Eimeriorina n Cryptosporidiidae n n n Cryptosporidium n Cryptosporidium muris n
|
||||
6998 5808 root Eukaryota n n n Apicomplexa n n Coccidia n n Eucoccidiorida Eimeriorina n Cryptosporidiidae n n n Cryptosporidium n Cryptosporidium muris n
|
||||
7001 5807 root Eukaryota n n n Apicomplexa n n Coccidia n n Eucoccidiorida Eimeriorina n Cryptosporidiidae n n n Cryptosporidium n Cryptosporidium parvum n
|
||||
7002 5807 root Eukaryota n n n Apicomplexa n n Coccidia n n Eucoccidiorida Eimeriorina n Cryptosporidiidae n n n Cryptosporidium n Cryptosporidium parvum n
|
||||
7082 7154 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Nematocera Chironomoidea Chironomidae Chironominae Chironomini n Chironomus Chironomus Chironomus thummi n
|
||||
7131 6565 root Eukaryota Metazoa n n Mollusca n n Bivalvia Pteriomorphia n Ostreoida n Ostreoidea Ostreidae n n n Crassostrea n Crassostrea virginica n
|
||||
7349 44689 root Eukaryota n n n n n n n n n Dictyosteliida n n n n n n Dictyostelium n Dictyostelium discoideum n
|
||||
7431 7224 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Brachycera Ephydroidea Drosophilidae Drosophilinae Drosophilini Drosophilina Drosophila Drosophila Drosophila hydei n
|
||||
7493 7227 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Brachycera Ephydroidea Drosophilidae Drosophilinae Drosophilini Drosophilina Drosophila Sophophora Drosophila melanogaster n
|
||||
7692 7227 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Brachycera Ephydroidea Drosophilidae Drosophilinae Drosophilini Drosophilina Drosophila Sophophora Drosophila melanogaster n
|
||||
7956 7227 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Brachycera Ephydroidea Drosophilidae Drosophilinae Drosophilini Drosophilina Drosophila Sophophora Drosophila melanogaster n
|
||||
8419 7227 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Brachycera Ephydroidea Drosophilidae Drosophilinae Drosophilini Drosophilina Drosophila Sophophora Drosophila melanogaster n
|
||||
8456 7227 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Brachycera Ephydroidea Drosophilidae Drosophilinae Drosophilini Drosophilina Drosophila Sophophora Drosophila melanogaster n
|
||||
9202 7244 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Brachycera Ephydroidea Drosophilidae Drosophilinae Drosophilini Drosophilina Drosophila Drosophila Drosophila virilis n
|
||||
9270 29932 root Eukaryota Metazoa n n Arthropoda Chelicerata n Arachnida n n Araneae Mygalomorphae n Theraphosidae n n n Aphonopelma n Aphonopelma sp. n
|
||||
9330 27887 root Eukaryota Metazoa n n Platyhelminthes n n Trematoda Digenea n Strigeidida n Strigeoidea Fellodistomidae n n n Fellodistomum n Fellodistomum fellis n
|
||||
9349 6174 root Eukaryota Metazoa n n Platyhelminthes n n Turbellaria n n Lecithoepitheliata n n Prorhynchidae n n n Geocentrophora n Geocentrophora intersticialis n
|
||||
9377 7394 root Eukaryota Metazoa n n Arthropoda n Hexapoda Insecta Neoptera n Diptera Brachycera Hippoboscoidea Glossinidae n n n Glossina Glossina Glossina morsitans n
|
||||
9380 6175 root Eukaryota Metazoa n n Platyhelminthes n n Turbellaria n n Lecithoepitheliata n n Prorhynchidae n n n Geocentrophora n Geocentrophora porfirievae n
|
||||
9383 6176 root Eukaryota Metazoa n n Platyhelminthes n n Turbellaria n n Lecithoepitheliata n n Prorhynchidae n n n Geocentrophora n Geocentrophora sphyrocephala n
|
||||
9430 7733 root Eukaryota Metazoa n n Chordata Urochordata n Ascidiacea n n Stolidobranchia n n Pyuridae n n n Herdmania n Herdmania momus n
|
||||
9505 27877 root Eukaryota Metazoa n n Platyhelminthes n n Trematoda Digenea n Plagiorchiida Allocreadiata Lepocreadioidea Lepocreadiidae n n n Lepidapedon n Lepidapedon elongatum n
|
||||
@@ -1,890 +0,0 @@
|
||||
/* Produced by texiweb from libavl.w on 2002/08/24 at 13:21. */
|
||||
|
||||
/* libavl - library for manipulation of binary trees.
|
||||
Copyright (C) 1998-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The author may be contacted at <blp@gnu.org> on the Internet, or
|
||||
write to Ben Pfaff, Stanford University, Computer Science Dept., 353
|
||||
Serra Mall, Stanford CA 94305, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "avl.h"
|
||||
|
||||
/* Creates and returns a new table
|
||||
with comparison function |compare| using parameter |param|
|
||||
and memory allocator |allocator|.
|
||||
Returns |NULL| if memory allocation failed. */
|
||||
struct avl_table *
|
||||
avl_create (avl_comparison_func *compare, void *param,
|
||||
struct libavl_allocator *allocator)
|
||||
{
|
||||
struct avl_table *tree;
|
||||
|
||||
assert (compare != NULL);
|
||||
|
||||
if (allocator == NULL)
|
||||
allocator = &avl_allocator_default;
|
||||
|
||||
tree = allocator->libavl_malloc (allocator, sizeof *tree);
|
||||
if (tree == NULL)
|
||||
return NULL;
|
||||
|
||||
tree->avl_root = NULL;
|
||||
tree->avl_compare = compare;
|
||||
tree->avl_param = param;
|
||||
tree->avl_alloc = allocator;
|
||||
tree->avl_count = 0;
|
||||
tree->avl_generation = 0;
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* Search |tree| for an item matching |item|, and return it if found.
|
||||
Otherwise return |NULL|. */
|
||||
void *
|
||||
avl_find (const struct avl_table *tree, const void *item)
|
||||
{
|
||||
const struct avl_node *p;
|
||||
|
||||
assert (tree != NULL && item != NULL);
|
||||
for (p = tree->avl_root; p != NULL; )
|
||||
{
|
||||
int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
|
||||
|
||||
if (cmp < 0)
|
||||
p = p->avl_link[0];
|
||||
else if (cmp > 0)
|
||||
p = p->avl_link[1];
|
||||
else /* |cmp == 0| */
|
||||
return p->avl_data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Inserts |item| into |tree| and returns a pointer to |item|'s address.
|
||||
If a duplicate item is found in the tree,
|
||||
returns a pointer to the duplicate without inserting |item|.
|
||||
Returns |NULL| in case of memory allocation failure. */
|
||||
void **
|
||||
avl_probe (struct avl_table *tree, void *item)
|
||||
{
|
||||
struct avl_node *y, *z; /* Top node to update balance factor, and parent. */
|
||||
struct avl_node *p, *q; /* Iterator, and parent. */
|
||||
struct avl_node *n; /* Newly inserted node. */
|
||||
struct avl_node *w; /* New root of rebalanced subtree. */
|
||||
int dir; /* Direction to descend. */
|
||||
|
||||
unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */
|
||||
int k = 0; /* Number of cached results. */
|
||||
|
||||
assert (tree != NULL && item != NULL);
|
||||
|
||||
z = (struct avl_node *) &tree->avl_root;
|
||||
y = tree->avl_root;
|
||||
dir = 0;
|
||||
for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir])
|
||||
{
|
||||
int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
|
||||
if (cmp == 0)
|
||||
return &p->avl_data;
|
||||
|
||||
if (p->avl_balance != 0)
|
||||
z = q, y = p, k = 0;
|
||||
da[k++] = dir = cmp > 0;
|
||||
}
|
||||
|
||||
n = q->avl_link[dir] =
|
||||
tree->avl_alloc->libavl_malloc (tree->avl_alloc, sizeof *n);
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
|
||||
tree->avl_count++;
|
||||
n->avl_data = item;
|
||||
n->avl_link[0] = n->avl_link[1] = NULL;
|
||||
n->avl_balance = 0;
|
||||
if (y == NULL)
|
||||
return &n->avl_data;
|
||||
|
||||
for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++)
|
||||
if (da[k] == 0)
|
||||
p->avl_balance--;
|
||||
else
|
||||
p->avl_balance++;
|
||||
|
||||
if (y->avl_balance == -2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[0];
|
||||
if (x->avl_balance == -1)
|
||||
{
|
||||
w = x;
|
||||
y->avl_link[0] = x->avl_link[1];
|
||||
x->avl_link[1] = y;
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (x->avl_balance == +1);
|
||||
w = x->avl_link[1];
|
||||
x->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = x;
|
||||
y->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = y;
|
||||
if (w->avl_balance == -1)
|
||||
x->avl_balance = 0, y->avl_balance = +1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == +1| */
|
||||
x->avl_balance = -1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
else if (y->avl_balance == +2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[1];
|
||||
if (x->avl_balance == +1)
|
||||
{
|
||||
w = x;
|
||||
y->avl_link[1] = x->avl_link[0];
|
||||
x->avl_link[0] = y;
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (x->avl_balance == -1);
|
||||
w = x->avl_link[0];
|
||||
x->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = x;
|
||||
y->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = y;
|
||||
if (w->avl_balance == +1)
|
||||
x->avl_balance = 0, y->avl_balance = -1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == -1| */
|
||||
x->avl_balance = +1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return &n->avl_data;
|
||||
z->avl_link[y != z->avl_link[0]] = w;
|
||||
|
||||
tree->avl_generation++;
|
||||
return &n->avl_data;
|
||||
}
|
||||
|
||||
/* Inserts |item| into |table|.
|
||||
Returns |NULL| if |item| was successfully inserted
|
||||
or if a memory allocation error occurred.
|
||||
Otherwise, returns the duplicate item. */
|
||||
void *
|
||||
avl_insert (struct avl_table *table, void *item)
|
||||
{
|
||||
void **p = avl_probe (table, item);
|
||||
return p == NULL || *p == item ? NULL : *p;
|
||||
}
|
||||
|
||||
/* Inserts |item| into |table|, replacing any duplicate item.
|
||||
Returns |NULL| if |item| was inserted without replacing a duplicate,
|
||||
or if a memory allocation error occurred.
|
||||
Otherwise, returns the item that was replaced. */
|
||||
void *
|
||||
avl_replace (struct avl_table *table, void *item)
|
||||
{
|
||||
void **p = avl_probe (table, item);
|
||||
if (p == NULL || *p == item)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
void *r = *p;
|
||||
*p = item;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Deletes from |tree| and returns an item matching |item|.
|
||||
Returns a null pointer if no matching item found. */
|
||||
void *
|
||||
avl_delete (struct avl_table *tree, const void *item)
|
||||
{
|
||||
/* Stack of nodes. */
|
||||
struct avl_node *pa[AVL_MAX_HEIGHT]; /* Nodes. */
|
||||
unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
|
||||
int k; /* Stack pointer. */
|
||||
|
||||
struct avl_node *p; /* Traverses tree to find node to delete. */
|
||||
int cmp; /* Result of comparison between |item| and |p|. */
|
||||
|
||||
assert (tree != NULL && item != NULL);
|
||||
|
||||
k = 0;
|
||||
p = (struct avl_node *) &tree->avl_root;
|
||||
for (cmp = -1; cmp != 0;
|
||||
cmp = tree->avl_compare (item, p->avl_data, tree->avl_param))
|
||||
{
|
||||
int dir = cmp > 0;
|
||||
|
||||
pa[k] = p;
|
||||
da[k++] = dir;
|
||||
|
||||
p = p->avl_link[dir];
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
}
|
||||
item = p->avl_data;
|
||||
|
||||
if (p->avl_link[1] == NULL)
|
||||
pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
|
||||
else
|
||||
{
|
||||
struct avl_node *r = p->avl_link[1];
|
||||
if (r->avl_link[0] == NULL)
|
||||
{
|
||||
r->avl_link[0] = p->avl_link[0];
|
||||
r->avl_balance = p->avl_balance;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = r;
|
||||
da[k] = 1;
|
||||
pa[k++] = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avl_node *s;
|
||||
int j = k++;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
da[k] = 0;
|
||||
pa[k++] = r;
|
||||
s = r->avl_link[0];
|
||||
if (s->avl_link[0] == NULL)
|
||||
break;
|
||||
|
||||
r = s;
|
||||
}
|
||||
|
||||
s->avl_link[0] = p->avl_link[0];
|
||||
r->avl_link[0] = s->avl_link[1];
|
||||
s->avl_link[1] = p->avl_link[1];
|
||||
s->avl_balance = p->avl_balance;
|
||||
|
||||
pa[j - 1]->avl_link[da[j - 1]] = s;
|
||||
da[j] = 1;
|
||||
pa[j] = s;
|
||||
}
|
||||
}
|
||||
|
||||
tree->avl_alloc->libavl_free (tree->avl_alloc, p);
|
||||
|
||||
assert (k > 0);
|
||||
while (--k > 0)
|
||||
{
|
||||
struct avl_node *y = pa[k];
|
||||
|
||||
if (da[k] == 0)
|
||||
{
|
||||
y->avl_balance++;
|
||||
if (y->avl_balance == +1)
|
||||
break;
|
||||
else if (y->avl_balance == +2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[1];
|
||||
if (x->avl_balance == -1)
|
||||
{
|
||||
struct avl_node *w;
|
||||
assert (x->avl_balance == -1);
|
||||
w = x->avl_link[0];
|
||||
x->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = x;
|
||||
y->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = y;
|
||||
if (w->avl_balance == +1)
|
||||
x->avl_balance = 0, y->avl_balance = -1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == -1| */
|
||||
x->avl_balance = +1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
y->avl_link[1] = x->avl_link[0];
|
||||
x->avl_link[0] = y;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = x;
|
||||
if (x->avl_balance == 0)
|
||||
{
|
||||
x->avl_balance = -1;
|
||||
y->avl_balance = +1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
y->avl_balance--;
|
||||
if (y->avl_balance == -1)
|
||||
break;
|
||||
else if (y->avl_balance == -2)
|
||||
{
|
||||
struct avl_node *x = y->avl_link[0];
|
||||
if (x->avl_balance == +1)
|
||||
{
|
||||
struct avl_node *w;
|
||||
assert (x->avl_balance == +1);
|
||||
w = x->avl_link[1];
|
||||
x->avl_link[1] = w->avl_link[0];
|
||||
w->avl_link[0] = x;
|
||||
y->avl_link[0] = w->avl_link[1];
|
||||
w->avl_link[1] = y;
|
||||
if (w->avl_balance == -1)
|
||||
x->avl_balance = 0, y->avl_balance = +1;
|
||||
else if (w->avl_balance == 0)
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
else /* |w->avl_balance == +1| */
|
||||
x->avl_balance = -1, y->avl_balance = 0;
|
||||
w->avl_balance = 0;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
y->avl_link[0] = x->avl_link[1];
|
||||
x->avl_link[1] = y;
|
||||
pa[k - 1]->avl_link[da[k - 1]] = x;
|
||||
if (x->avl_balance == 0)
|
||||
{
|
||||
x->avl_balance = +1;
|
||||
y->avl_balance = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
x->avl_balance = y->avl_balance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tree->avl_count--;
|
||||
tree->avl_generation++;
|
||||
return (void *) item;
|
||||
}
|
||||
|
||||
/* Refreshes the stack of parent pointers in |trav|
|
||||
and updates its generation number. */
|
||||
static void
|
||||
trav_refresh (struct avl_traverser *trav)
|
||||
{
|
||||
assert (trav != NULL);
|
||||
|
||||
trav->avl_generation = trav->avl_table->avl_generation;
|
||||
|
||||
if (trav->avl_node != NULL)
|
||||
{
|
||||
avl_comparison_func *cmp = trav->avl_table->avl_compare;
|
||||
void *param = trav->avl_table->avl_param;
|
||||
struct avl_node *node = trav->avl_node;
|
||||
struct avl_node *i;
|
||||
|
||||
trav->avl_height = 0;
|
||||
for (i = trav->avl_table->avl_root; i != node; )
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
assert (i != NULL);
|
||||
|
||||
trav->avl_stack[trav->avl_height++] = i;
|
||||
i = i->avl_link[cmp (node->avl_data, i->avl_data, param) > 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes |trav| for use with |tree|
|
||||
and selects the null node. */
|
||||
void
|
||||
avl_t_init (struct avl_traverser *trav, struct avl_table *tree)
|
||||
{
|
||||
trav->avl_table = tree;
|
||||
trav->avl_node = NULL;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
}
|
||||
|
||||
/* Initializes |trav| for |tree|
|
||||
and selects and returns a pointer to its least-valued item.
|
||||
Returns |NULL| if |tree| contains no nodes. */
|
||||
void *
|
||||
avl_t_first (struct avl_traverser *trav, struct avl_table *tree)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (tree != NULL && trav != NULL);
|
||||
|
||||
trav->avl_table = tree;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
|
||||
x = tree->avl_root;
|
||||
if (x != NULL)
|
||||
while (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[0];
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x != NULL ? x->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Initializes |trav| for |tree|
|
||||
and selects and returns a pointer to its greatest-valued item.
|
||||
Returns |NULL| if |tree| contains no nodes. */
|
||||
void *
|
||||
avl_t_last (struct avl_traverser *trav, struct avl_table *tree)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (tree != NULL && trav != NULL);
|
||||
|
||||
trav->avl_table = tree;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
|
||||
x = tree->avl_root;
|
||||
if (x != NULL)
|
||||
while (x->avl_link[1] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[1];
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x != NULL ? x->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Searches for |item| in |tree|.
|
||||
If found, initializes |trav| to the item found and returns the item
|
||||
as well.
|
||||
If there is no matching item, initializes |trav| to the null item
|
||||
and returns |NULL|. */
|
||||
void *
|
||||
avl_t_find (struct avl_traverser *trav, struct avl_table *tree, void *item)
|
||||
{
|
||||
struct avl_node *p, *q;
|
||||
|
||||
assert (trav != NULL && tree != NULL && item != NULL);
|
||||
trav->avl_table = tree;
|
||||
trav->avl_height = 0;
|
||||
trav->avl_generation = tree->avl_generation;
|
||||
for (p = tree->avl_root; p != NULL; p = q)
|
||||
{
|
||||
int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
|
||||
|
||||
if (cmp < 0)
|
||||
q = p->avl_link[0];
|
||||
else if (cmp > 0)
|
||||
q = p->avl_link[1];
|
||||
else /* |cmp == 0| */
|
||||
{
|
||||
trav->avl_node = p;
|
||||
return p->avl_data;
|
||||
}
|
||||
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = p;
|
||||
}
|
||||
|
||||
trav->avl_height = 0;
|
||||
trav->avl_node = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Attempts to insert |item| into |tree|.
|
||||
If |item| is inserted successfully, it is returned and |trav| is
|
||||
initialized to its location.
|
||||
If a duplicate is found, it is returned and |trav| is initialized to
|
||||
its location. No replacement of the item occurs.
|
||||
If a memory allocation failure occurs, |NULL| is returned and |trav|
|
||||
is initialized to the null item. */
|
||||
void *
|
||||
avl_t_insert (struct avl_traverser *trav, struct avl_table *tree, void *item)
|
||||
{
|
||||
void **p;
|
||||
|
||||
assert (trav != NULL && tree != NULL && item != NULL);
|
||||
|
||||
p = avl_probe (tree, item);
|
||||
if (p != NULL)
|
||||
{
|
||||
trav->avl_table = tree;
|
||||
trav->avl_node =
|
||||
((struct avl_node *)
|
||||
((char *) p - offsetof (struct avl_node, avl_data)));
|
||||
trav->avl_generation = tree->avl_generation - 1;
|
||||
return *p;
|
||||
}
|
||||
else
|
||||
{
|
||||
avl_t_init (trav, tree);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes |trav| to have the same current node as |src|. */
|
||||
void *
|
||||
avl_t_copy (struct avl_traverser *trav, const struct avl_traverser *src)
|
||||
{
|
||||
assert (trav != NULL && src != NULL);
|
||||
|
||||
if (trav != src)
|
||||
{
|
||||
trav->avl_table = src->avl_table;
|
||||
trav->avl_node = src->avl_node;
|
||||
trav->avl_generation = src->avl_generation;
|
||||
if (trav->avl_generation == trav->avl_table->avl_generation)
|
||||
{
|
||||
trav->avl_height = src->avl_height;
|
||||
memcpy (trav->avl_stack, (const void *) src->avl_stack,
|
||||
sizeof *trav->avl_stack * trav->avl_height);
|
||||
}
|
||||
}
|
||||
|
||||
return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Returns the next data item in inorder
|
||||
within the tree being traversed with |trav|,
|
||||
or if there are no more data items returns |NULL|. */
|
||||
void *
|
||||
avl_t_next (struct avl_traverser *trav)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (trav != NULL);
|
||||
|
||||
if (trav->avl_generation != trav->avl_table->avl_generation)
|
||||
trav_refresh (trav);
|
||||
|
||||
x = trav->avl_node;
|
||||
if (x == NULL)
|
||||
{
|
||||
return avl_t_first (trav, trav->avl_table);
|
||||
}
|
||||
else if (x->avl_link[1] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[1];
|
||||
|
||||
while (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avl_node *y;
|
||||
|
||||
do
|
||||
{
|
||||
if (trav->avl_height == 0)
|
||||
{
|
||||
trav->avl_node = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
y = x;
|
||||
x = trav->avl_stack[--trav->avl_height];
|
||||
}
|
||||
while (y == x->avl_link[1]);
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x->avl_data;
|
||||
}
|
||||
|
||||
/* Returns the previous data item in inorder
|
||||
within the tree being traversed with |trav|,
|
||||
or if there are no more data items returns |NULL|. */
|
||||
void *
|
||||
avl_t_prev (struct avl_traverser *trav)
|
||||
{
|
||||
struct avl_node *x;
|
||||
|
||||
assert (trav != NULL);
|
||||
|
||||
if (trav->avl_generation != trav->avl_table->avl_generation)
|
||||
trav_refresh (trav);
|
||||
|
||||
x = trav->avl_node;
|
||||
if (x == NULL)
|
||||
{
|
||||
return avl_t_last (trav, trav->avl_table);
|
||||
}
|
||||
else if (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[0];
|
||||
|
||||
while (x->avl_link[1] != NULL)
|
||||
{
|
||||
assert (trav->avl_height < AVL_MAX_HEIGHT);
|
||||
trav->avl_stack[trav->avl_height++] = x;
|
||||
x = x->avl_link[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avl_node *y;
|
||||
|
||||
do
|
||||
{
|
||||
if (trav->avl_height == 0)
|
||||
{
|
||||
trav->avl_node = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
y = x;
|
||||
x = trav->avl_stack[--trav->avl_height];
|
||||
}
|
||||
while (y == x->avl_link[0]);
|
||||
}
|
||||
trav->avl_node = x;
|
||||
|
||||
return x->avl_data;
|
||||
}
|
||||
|
||||
/* Returns |trav|'s current item. */
|
||||
void *
|
||||
avl_t_cur (struct avl_traverser *trav)
|
||||
{
|
||||
assert (trav != NULL);
|
||||
|
||||
return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
|
||||
}
|
||||
|
||||
/* Replaces the current item in |trav| by |new| and returns the item replaced.
|
||||
|trav| must not have the null item selected.
|
||||
The new item must not upset the ordering of the tree. */
|
||||
void *
|
||||
avl_t_replace (struct avl_traverser *trav, void *new)
|
||||
{
|
||||
void *old;
|
||||
|
||||
assert (trav != NULL && trav->avl_node != NULL && new != NULL);
|
||||
old = trav->avl_node->avl_data;
|
||||
trav->avl_node->avl_data = new;
|
||||
return old;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_error_recovery (struct avl_node **stack, int height,
|
||||
struct avl_table *new, avl_item_func *destroy)
|
||||
{
|
||||
assert (stack != NULL && height >= 0 && new != NULL);
|
||||
|
||||
for (; height > 2; height -= 2)
|
||||
stack[height - 1]->avl_link[1] = NULL;
|
||||
avl_destroy (new, destroy);
|
||||
}
|
||||
|
||||
/* Copies |org| to a newly created tree, which is returned.
|
||||
If |copy != NULL|, each data item in |org| is first passed to |copy|,
|
||||
and the return values are inserted into the tree,
|
||||
with |NULL| return values taken as indications of failure.
|
||||
On failure, destroys the partially created new tree,
|
||||
applying |destroy|, if non-null, to each item in the new tree so far,
|
||||
and returns |NULL|.
|
||||
If |allocator != NULL|, it is used for allocation in the new tree.
|
||||
Otherwise, the same allocator used for |org| is used. */
|
||||
struct avl_table *
|
||||
avl_copy (const struct avl_table *org, avl_copy_func *copy,
|
||||
avl_item_func *destroy, struct libavl_allocator *allocator)
|
||||
{
|
||||
struct avl_node *stack[2 * (AVL_MAX_HEIGHT + 1)];
|
||||
int height = 0;
|
||||
|
||||
struct avl_table *new;
|
||||
const struct avl_node *x;
|
||||
struct avl_node *y;
|
||||
|
||||
assert (org != NULL);
|
||||
new = avl_create (org->avl_compare, org->avl_param,
|
||||
allocator != NULL ? allocator : org->avl_alloc);
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
new->avl_count = org->avl_count;
|
||||
if (new->avl_count == 0)
|
||||
return new;
|
||||
|
||||
x = (const struct avl_node *) &org->avl_root;
|
||||
y = (struct avl_node *) &new->avl_root;
|
||||
for (;;)
|
||||
{
|
||||
while (x->avl_link[0] != NULL)
|
||||
{
|
||||
assert (height < 2 * (AVL_MAX_HEIGHT + 1));
|
||||
|
||||
y->avl_link[0] =
|
||||
new->avl_alloc->libavl_malloc (new->avl_alloc,
|
||||
sizeof *y->avl_link[0]);
|
||||
if (y->avl_link[0] == NULL)
|
||||
{
|
||||
if (y != (struct avl_node *) &new->avl_root)
|
||||
{
|
||||
y->avl_data = NULL;
|
||||
y->avl_link[1] = NULL;
|
||||
}
|
||||
|
||||
copy_error_recovery (stack, height, new, destroy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack[height++] = (struct avl_node *) x;
|
||||
stack[height++] = y;
|
||||
x = x->avl_link[0];
|
||||
y = y->avl_link[0];
|
||||
}
|
||||
y->avl_link[0] = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
y->avl_balance = x->avl_balance;
|
||||
if (copy == NULL)
|
||||
y->avl_data = x->avl_data;
|
||||
else
|
||||
{
|
||||
y->avl_data = copy (x->avl_data, org->avl_param);
|
||||
if (y->avl_data == NULL)
|
||||
{
|
||||
y->avl_link[1] = NULL;
|
||||
copy_error_recovery (stack, height, new, destroy);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (x->avl_link[1] != NULL)
|
||||
{
|
||||
y->avl_link[1] =
|
||||
new->avl_alloc->libavl_malloc (new->avl_alloc,
|
||||
sizeof *y->avl_link[1]);
|
||||
if (y->avl_link[1] == NULL)
|
||||
{
|
||||
copy_error_recovery (stack, height, new, destroy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
x = x->avl_link[1];
|
||||
y = y->avl_link[1];
|
||||
break;
|
||||
}
|
||||
else
|
||||
y->avl_link[1] = NULL;
|
||||
|
||||
if (height <= 2)
|
||||
return new;
|
||||
|
||||
y = stack[--height];
|
||||
x = stack[--height];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Frees storage allocated for |tree|.
|
||||
If |destroy != NULL|, applies it to each data item in inorder. */
|
||||
void
|
||||
avl_destroy (struct avl_table *tree, avl_item_func *destroy)
|
||||
{
|
||||
struct avl_node *p, *q;
|
||||
|
||||
assert (tree != NULL);
|
||||
|
||||
for (p = tree->avl_root; p != NULL; p = q)
|
||||
if (p->avl_link[0] == NULL)
|
||||
{
|
||||
q = p->avl_link[1];
|
||||
if (destroy != NULL && p->avl_data != NULL)
|
||||
destroy (p->avl_data, tree->avl_param);
|
||||
tree->avl_alloc->libavl_free (tree->avl_alloc, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
q = p->avl_link[0];
|
||||
p->avl_link[0] = q->avl_link[1];
|
||||
q->avl_link[1] = p;
|
||||
}
|
||||
|
||||
tree->avl_alloc->libavl_free (tree->avl_alloc, tree);
|
||||
}
|
||||
|
||||
/* Allocates |size| bytes of space using |malloc()|.
|
||||
Returns a null pointer if allocation fails. */
|
||||
void *
|
||||
avl_malloc (struct libavl_allocator *allocator, size_t size)
|
||||
{
|
||||
assert (allocator != NULL && size > 0);
|
||||
return malloc (size);
|
||||
}
|
||||
|
||||
/* Frees |block|. */
|
||||
void
|
||||
avl_free (struct libavl_allocator *allocator, void *block)
|
||||
{
|
||||
assert (allocator != NULL && block != NULL);
|
||||
free (block);
|
||||
}
|
||||
|
||||
/* Default memory allocator that uses |malloc()| and |free()|. */
|
||||
struct libavl_allocator avl_allocator_default =
|
||||
{
|
||||
avl_malloc,
|
||||
avl_free
|
||||
};
|
||||
|
||||
#undef NDEBUG
|
||||
#include <assert.h>
|
||||
|
||||
/* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */
|
||||
void
|
||||
(avl_assert_insert) (struct avl_table *table, void *item)
|
||||
{
|
||||
void **p = avl_probe (table, item);
|
||||
assert (p != NULL && *p == item);
|
||||
}
|
||||
|
||||
/* Asserts that |avl_delete()| really removes |item| from |table|,
|
||||
and returns the removed item. */
|
||||
void *
|
||||
(avl_assert_delete) (struct avl_table *table, void *item)
|
||||
{
|
||||
void *p = avl_delete (table, item);
|
||||
assert (p != NULL);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/* Produced by texiweb from libavl.w on 2002/08/24 at 13:21. */
|
||||
|
||||
/* libavl - library for manipulation of binary trees.
|
||||
Copyright (C) 1998-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The author may be contacted at <blp@gnu.org> on the Internet, or
|
||||
write to Ben Pfaff, Stanford University, Computer Science Dept., 353
|
||||
Serra Mall, Stanford CA 94305, USA.
|
||||
*/
|
||||
|
||||
#ifndef AVL_H
|
||||
#define AVL_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Function types. */
|
||||
typedef int avl_comparison_func (const void *avl_a, const void *avl_b,
|
||||
void *avl_param);
|
||||
typedef void avl_item_func (void *avl_item, void *avl_param);
|
||||
typedef void *avl_copy_func (void *avl_item, void *avl_param);
|
||||
|
||||
#ifndef LIBAVL_ALLOCATOR
|
||||
#define LIBAVL_ALLOCATOR
|
||||
/* Memory allocator. */
|
||||
struct libavl_allocator
|
||||
{
|
||||
void *(*libavl_malloc) (struct libavl_allocator *, size_t libavl_size);
|
||||
void (*libavl_free) (struct libavl_allocator *, void *libavl_block);
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Default memory allocator. */
|
||||
extern struct libavl_allocator avl_allocator_default;
|
||||
void *avl_malloc (struct libavl_allocator *, size_t);
|
||||
void avl_free (struct libavl_allocator *, void *);
|
||||
|
||||
/* Maximum AVL height. */
|
||||
#ifndef AVL_MAX_HEIGHT
|
||||
#define AVL_MAX_HEIGHT 32
|
||||
#endif
|
||||
|
||||
/* Tree data structure. */
|
||||
struct avl_table
|
||||
{
|
||||
struct avl_node *avl_root; /* Tree's root. */
|
||||
avl_comparison_func *avl_compare; /* Comparison function. */
|
||||
void *avl_param; /* Extra argument to |avl_compare|. */
|
||||
struct libavl_allocator *avl_alloc; /* Memory allocator. */
|
||||
size_t avl_count; /* Number of items in tree. */
|
||||
unsigned long avl_generation; /* Generation number. */
|
||||
};
|
||||
|
||||
/* An AVL tree node. */
|
||||
struct avl_node
|
||||
{
|
||||
struct avl_node *avl_link[2]; /* Subtrees. */
|
||||
void *avl_data; /* Pointer to data. */
|
||||
signed char avl_balance; /* Balance factor. */
|
||||
};
|
||||
|
||||
/* AVL traverser structure. */
|
||||
struct avl_traverser
|
||||
{
|
||||
struct avl_table *avl_table; /* Tree being traversed. */
|
||||
struct avl_node *avl_node; /* Current node in tree. */
|
||||
struct avl_node *avl_stack[AVL_MAX_HEIGHT];
|
||||
/* All the nodes above |avl_node|. */
|
||||
size_t avl_height; /* Number of nodes in |avl_parent|. */
|
||||
unsigned long avl_generation; /* Generation number. */
|
||||
};
|
||||
|
||||
/* Table functions. */
|
||||
struct avl_table *avl_create (avl_comparison_func *, void *,
|
||||
struct libavl_allocator *);
|
||||
struct avl_table *avl_copy (const struct avl_table *, avl_copy_func *,
|
||||
avl_item_func *, struct libavl_allocator *);
|
||||
void avl_destroy (struct avl_table *, avl_item_func *);
|
||||
void **avl_probe (struct avl_table *, void *);
|
||||
void *avl_insert (struct avl_table *, void *);
|
||||
void *avl_replace (struct avl_table *, void *);
|
||||
void *avl_delete (struct avl_table *, const void *);
|
||||
void *avl_find (const struct avl_table *, const void *);
|
||||
void avl_assert_insert (struct avl_table *, void *);
|
||||
void *avl_assert_delete (struct avl_table *, void *);
|
||||
|
||||
#define avl_count(table) ((size_t) (table)->avl_count)
|
||||
|
||||
/* Table traverser functions. */
|
||||
void avl_t_init (struct avl_traverser *, struct avl_table *);
|
||||
void *avl_t_first (struct avl_traverser *, struct avl_table *);
|
||||
void *avl_t_last (struct avl_traverser *, struct avl_table *);
|
||||
void *avl_t_find (struct avl_traverser *, struct avl_table *, void *);
|
||||
void *avl_t_insert (struct avl_traverser *, struct avl_table *, void *);
|
||||
void *avl_t_copy (struct avl_traverser *, const struct avl_traverser *);
|
||||
void *avl_t_next (struct avl_traverser *);
|
||||
void *avl_t_prev (struct avl_traverser *);
|
||||
void *avl_t_cur (struct avl_traverser *);
|
||||
void *avl_t_replace (struct avl_traverser *, void *);
|
||||
|
||||
#endif /* avl.h */
|
||||
@@ -1,787 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "avl.h"
|
||||
|
||||
#define NUMBER_OF_TAX_FIELDS 22
|
||||
|
||||
char *rankLabels [NUMBER_OF_TAX_FIELDS] =
|
||||
{"root" ,
|
||||
"superkingdom",
|
||||
"kingdom" ,
|
||||
"subkingdom" ,
|
||||
"superphylum" ,
|
||||
"phylum" ,
|
||||
"subphylum" ,
|
||||
"superclass" ,
|
||||
"class" ,
|
||||
"subclass" ,
|
||||
"superorder" ,
|
||||
"order" ,
|
||||
"suborder" ,
|
||||
"superfamily" ,
|
||||
"family" ,
|
||||
"subfamily" ,
|
||||
"tribe" ,
|
||||
"subtribe" ,
|
||||
"genus" ,
|
||||
"subgenus" ,
|
||||
"species" ,
|
||||
"subspecies"
|
||||
};
|
||||
|
||||
char noValue[] = "n\t",
|
||||
rootValue[] = "toor\t",
|
||||
usage[] = "Incorrect number of arguments.\nExpected arguments: tax_id->label file, tax_id->hierarchy file, input file (gid taxid pairs), output file (24 columns)";
|
||||
|
||||
/*#define DEBUG_ME*/
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void check_pointer (void*);
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct avl_table * nameTagAVL = NULL,
|
||||
* rankLabelAVL = NULL;
|
||||
|
||||
#define DEFAULT_STRING_ALLOC 16L
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct bufferedString
|
||||
{
|
||||
char *sData;
|
||||
long sLength,
|
||||
saLength;
|
||||
}
|
||||
*globalNameBuffer;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct bufferedString *allocateNewString (void)
|
||||
{
|
||||
struct bufferedString *newS = (struct bufferedString*)malloc (sizeof (struct bufferedString));
|
||||
check_pointer (newS);
|
||||
check_pointer (newS->sData = (char*)malloc (DEFAULT_STRING_ALLOC+1));
|
||||
newS->sLength = 0;
|
||||
newS->saLength = DEFAULT_STRING_ALLOC;
|
||||
newS->sData[0] = 0;
|
||||
return newS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void clear_buffered_string (struct bufferedString* theString)
|
||||
{
|
||||
theString->sLength = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void appendCharacterToString (struct bufferedString * s, const char c)
|
||||
{
|
||||
long addThis;
|
||||
if (s->saLength == s->sLength)
|
||||
{
|
||||
addThis = s->saLength / 8;
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
s->saLength += addThis;
|
||||
check_pointer (s->sData = realloc (s->sData,s->saLength+1));
|
||||
}
|
||||
s->sData[s->sLength] = c;
|
||||
s->sData[++s->sLength] = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
long appendRangeToString (struct bufferedString * d, struct bufferedString *s, long from, long to)
|
||||
{
|
||||
long addThis,
|
||||
pl = to-from+1;
|
||||
|
||||
if (pl<=0)
|
||||
return -1;
|
||||
|
||||
if (d->saLength < d->sLength + pl)
|
||||
{
|
||||
addThis = d->saLength / 8;
|
||||
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
if (addThis < pl)
|
||||
addThis = pl;
|
||||
|
||||
d->saLength += addThis;
|
||||
check_pointer (d->sData = realloc (d->sData,d->saLength+1));
|
||||
}
|
||||
for (addThis = from; addThis <=to; addThis++)
|
||||
d->sData[d->sLength++] = s->sData[addThis];
|
||||
|
||||
d->sData[d->sLength] = 0;
|
||||
|
||||
return pl;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void appendCharRangeToString (struct bufferedString * d, char * buffer)
|
||||
{
|
||||
long addThis,
|
||||
pl = strlen(buffer);
|
||||
|
||||
if (pl<=0)
|
||||
return;
|
||||
|
||||
if (d->saLength < d->sLength + pl)
|
||||
{
|
||||
addThis = d->saLength / 8;
|
||||
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
if (addThis < pl)
|
||||
addThis = pl;
|
||||
|
||||
d->saLength += addThis;
|
||||
check_pointer (d->sData = realloc (d->sData,d->saLength+1));
|
||||
}
|
||||
for (addThis = 0; addThis <pl; addThis++)
|
||||
d->sData[d->sLength++] = buffer[addThis];
|
||||
|
||||
d->sData[d->sLength] = 0;
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
long appendCharBufferToString (struct bufferedString * d, const char * b)
|
||||
{
|
||||
long addThis,
|
||||
pl = strlen (b);
|
||||
|
||||
if (pl<=0)
|
||||
return -1;
|
||||
|
||||
if (d->saLength < d->sLength + pl)
|
||||
{
|
||||
addThis = d->saLength / 8;
|
||||
|
||||
if (DEFAULT_STRING_ALLOC > addThis)
|
||||
addThis = DEFAULT_STRING_ALLOC;
|
||||
if (addThis < pl)
|
||||
addThis = pl;
|
||||
|
||||
d->saLength += addThis;
|
||||
check_pointer (d->sData = realloc (d->sData,d->saLength+1));
|
||||
}
|
||||
for (addThis = 0; addThis <pl; addThis++)
|
||||
d->sData[d->sLength++] = b[addThis];
|
||||
|
||||
d->sData[d->sLength] = 0;
|
||||
return pl;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct storedNameTag
|
||||
{
|
||||
long taxID,
|
||||
startIndex,
|
||||
length;
|
||||
|
||||
char taxonomy_level;
|
||||
|
||||
struct storedNameTag * parent;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct storedNameTag * allocateNameTag (void)
|
||||
{
|
||||
struct storedNameTag *newS = (struct storedNameTag*)malloc (sizeof (struct storedNameTag));
|
||||
check_pointer (newS);
|
||||
newS->taxID = 0;
|
||||
newS->startIndex = 0;
|
||||
newS->length = 0;
|
||||
newS->parent = NULL;
|
||||
newS->taxonomy_level = -1;
|
||||
return newS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int compare_tags (const void *avl_a, const void *avl_b, void * xtra)
|
||||
{
|
||||
long n1 = ((struct storedNameTag*)avl_a)->taxID;
|
||||
long n2 = ((struct storedNameTag*)avl_b)->taxID;
|
||||
|
||||
if (n1 > n2) return 1;
|
||||
if (n1 < n2) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct bufferedString * nameByID (long taxID)
|
||||
{
|
||||
static struct storedNameTag queryTag;
|
||||
struct storedNameTag * res;
|
||||
struct bufferedString * resStr = NULL;
|
||||
|
||||
queryTag.taxID = taxID;
|
||||
res = (struct storedNameTag *)avl_find(nameTagAVL, &queryTag);
|
||||
if (res)
|
||||
{
|
||||
resStr = allocateNewString();
|
||||
appendRangeToString(resStr,globalNameBuffer,res->startIndex,res->startIndex+res->length-1);
|
||||
}
|
||||
return resStr;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct storedNameTag * tagByID (long taxID)
|
||||
{
|
||||
static struct storedNameTag queryTag;
|
||||
queryTag.taxID = taxID;
|
||||
return (struct storedNameTag *)avl_find(nameTagAVL, &queryTag);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct bufferedString * walkPath (long taxID)
|
||||
{
|
||||
struct storedNameTag * currentTag = tagByID(taxID);
|
||||
if (!currentTag)
|
||||
return NULL;
|
||||
|
||||
struct bufferedString * resStr = allocateNewString();
|
||||
long k,
|
||||
level = NUMBER_OF_TAX_FIELDS-1;
|
||||
|
||||
char // buffer [32],
|
||||
first_record = 1;
|
||||
|
||||
while (currentTag) {
|
||||
|
||||
if (currentTag->taxonomy_level >= 0)
|
||||
{
|
||||
if (first_record)
|
||||
{
|
||||
for (k = currentTag->taxonomy_level+1; k < NUMBER_OF_TAX_FIELDS; k++)
|
||||
appendCharBufferToString(resStr,noValue);
|
||||
first_record = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (k=currentTag->taxonomy_level+1; k<level; k++)
|
||||
appendCharBufferToString(resStr,noValue);
|
||||
}
|
||||
//appendCharacterToString(resStr,')');
|
||||
//sprintf (buffer, "%d", currentTag->taxonomy_level);
|
||||
//for (k=strlen(buffer)-1; k>=0; k--)
|
||||
// appendCharacterToString(resStr,buffer[k]);
|
||||
//appendCharacterToString(resStr,'(');
|
||||
for (k=currentTag->startIndex+currentTag->length-1; k>=currentTag->startIndex; k--)
|
||||
appendCharacterToString(resStr,globalNameBuffer->sData[k]);
|
||||
|
||||
appendCharacterToString(resStr,'\t');
|
||||
level = currentTag->taxonomy_level;
|
||||
}
|
||||
currentTag = currentTag->parent;
|
||||
}
|
||||
|
||||
for (k = level-1; k ; k--)
|
||||
appendCharBufferToString(resStr,noValue);
|
||||
|
||||
appendCharBufferToString(resStr,rootValue);
|
||||
|
||||
return resStr;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void check_pointer (void * p)
|
||||
{
|
||||
if (p == NULL)
|
||||
{
|
||||
fprintf (stderr,"Memory allocation error\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int compare_strings (struct bufferedString * s1, struct bufferedString * s2)
|
||||
{
|
||||
long upTo,
|
||||
i;
|
||||
|
||||
if (s1->sLength>s2->sLength)
|
||||
upTo = s2->sLength;
|
||||
else
|
||||
upTo = s1->sLength;
|
||||
|
||||
for (i=0; i<upTo; i++)
|
||||
{
|
||||
int res = (s1->sData[i]-s2->sData[i]);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
else
|
||||
if (res>0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (s1->sLength == s2->sLength)
|
||||
return 0;
|
||||
|
||||
return 1-2*(s1->sLength<s2->sLength);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int compare_tag_strings (const void *avl_a, const void *avl_b, void * xtra)
|
||||
{
|
||||
struct storedNameTag* s1 = (struct storedNameTag*)avl_a;
|
||||
struct storedNameTag* s2 = (struct storedNameTag*)avl_b;
|
||||
char *buffa = ((struct bufferedString*)xtra)->sData;
|
||||
|
||||
long upTo,
|
||||
i;
|
||||
|
||||
if (s1->length>s2->length)
|
||||
upTo = s2->length;
|
||||
else
|
||||
upTo = s1->length;
|
||||
|
||||
for (i=0; i<upTo; i++)
|
||||
{
|
||||
int res = (int)buffa[s1->startIndex+i]-buffa[s2->startIndex+i];
|
||||
if (res < 0)
|
||||
return -1;
|
||||
else
|
||||
if (res>0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (s1->length == s2->length)
|
||||
return 0;
|
||||
|
||||
return 1-2*(s1->length<s2->length);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void destroy_string (struct bufferedString* aStr)
|
||||
{
|
||||
free (aStr->sData);
|
||||
free (aStr);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void reportError (char * theMessage)
|
||||
{
|
||||
fprintf (stderr, "\nERROR: %s\n", theMessage);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
void reportErrorLine (char * theMessage, long lineID)
|
||||
{
|
||||
fprintf (stderr, "\nERROR in line %d: %s\n", lineID, theMessage);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
FILE *inFile,
|
||||
*structFile,
|
||||
*queryFile,
|
||||
*outFile;
|
||||
|
||||
struct bufferedString *scientificName = allocateNewString(),
|
||||
**currentBuffers,
|
||||
*qry;
|
||||
|
||||
struct storedNameTag *aTag,
|
||||
*aTag2,
|
||||
*aTag3 = allocateNameTag();
|
||||
|
||||
char automatonState = 0,
|
||||
currentField = 0,
|
||||
currentChar = 0,
|
||||
taxonBuffer [1024],
|
||||
firstLine;
|
||||
|
||||
long currentLineID = 1,
|
||||
expectedFields = 4,
|
||||
indexer,
|
||||
indexer2;
|
||||
|
||||
|
||||
|
||||
if (argc != 5)
|
||||
{
|
||||
fprintf (stderr,"%s\n", usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
appendCharBufferToString(scientificName, "scientific name");
|
||||
globalNameBuffer = allocateNewString();
|
||||
currentBuffers = (struct bufferedString**)malloc (expectedFields*sizeof (struct bufferedString*));
|
||||
nameTagAVL = avl_create (compare_tags, NULL, NULL);
|
||||
rankLabelAVL = avl_create (compare_tag_strings, globalNameBuffer, NULL);
|
||||
|
||||
for (indexer = 0; indexer < expectedFields; indexer++)
|
||||
currentBuffers[indexer] = allocateNewString();
|
||||
|
||||
for (indexer = 0; indexer < NUMBER_OF_TAX_FIELDS; indexer++)
|
||||
{
|
||||
aTag = allocateNameTag ();
|
||||
aTag->startIndex = globalNameBuffer->sLength;
|
||||
appendCharBufferToString (globalNameBuffer,rankLabels[indexer]);
|
||||
aTag->taxonomy_level = indexer;
|
||||
aTag->length = strlen(rankLabels[indexer]);
|
||||
if ((aTag2 = *avl_probe(rankLabelAVL, aTag)) != aTag)
|
||||
reportErrorLine ("Duplicate taxonomic rank name", aTag2->taxonomy_level);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inFile = fopen (argv[1], "rb");
|
||||
|
||||
if (!inFile)
|
||||
{
|
||||
fprintf (stderr,"Failed to open input file: %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
structFile = fopen (argv[2], "rb");
|
||||
|
||||
if (!structFile)
|
||||
{
|
||||
fprintf (stderr,"Failed to open input file: %s\n", argv[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
queryFile = fopen (argv[3], "rb");
|
||||
|
||||
if (!queryFile)
|
||||
{
|
||||
fprintf (stderr,"Failed to open input file: %s\n", argv[3]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
outFile = fopen (argv[4], "w");
|
||||
|
||||
if (!outFile)
|
||||
{
|
||||
fprintf (stderr,"Failed to open output file: %s\n", argv[3]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
currentChar = fgetc(inFile);
|
||||
while (!feof(inFile))
|
||||
{
|
||||
switch (automatonState)
|
||||
{
|
||||
case 0: /* start of the line; expecting numbers */
|
||||
if (currentChar >= '0' && currentChar <='9')
|
||||
{
|
||||
automatonState = 1; /* reading sequence ID */
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
}
|
||||
else
|
||||
if (!(currentChar == '\n' || currentChar == '\r'))
|
||||
reportErrorLine ("Could not find a valid sequence ID to start the line",currentLineID);
|
||||
break;
|
||||
|
||||
case 1: /* reading sequence ID */
|
||||
if (currentChar >= '0' && currentChar <='9')
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
else
|
||||
if (currentChar == '\t')
|
||||
automatonState = 2;
|
||||
else
|
||||
reportErrorLine ("Expected a tab following the tax ID",currentLineID);
|
||||
break;
|
||||
|
||||
case 2: /* looking for a | */
|
||||
if (currentChar != '|')
|
||||
reportErrorLine ("Expected a '|' following the tab",currentLineID);
|
||||
else
|
||||
automatonState = 3;
|
||||
break;
|
||||
|
||||
case 3: /* looking for a \t or a \n|\r*/
|
||||
if (currentChar == '\t')
|
||||
{
|
||||
automatonState = 4;
|
||||
currentField ++;
|
||||
if (currentField == expectedFields)
|
||||
reportErrorLine ("Too many fields",currentLineID);
|
||||
}
|
||||
else
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
{
|
||||
if (currentField < expectedFields-1)
|
||||
reportErrorLine ("Too few fields",currentLineID);
|
||||
automatonState = 0;
|
||||
currentLineID ++;
|
||||
currentField = 0;
|
||||
if (compare_strings(currentBuffers[3],scientificName)==0)
|
||||
{
|
||||
aTag = allocateNameTag();
|
||||
aTag->taxID = atoi(currentBuffers[0]->sData);
|
||||
aTag->startIndex = globalNameBuffer->sLength;
|
||||
aTag->length = appendRangeToString(globalNameBuffer,currentBuffers[1],0,currentBuffers[1]->sLength-1);
|
||||
if (aTag->length <= 0)
|
||||
reportErrorLine ("Empty name tag",currentLineID);
|
||||
if (*avl_probe(nameTagAVL,aTag) != aTag)
|
||||
reportErrorLine ("Duplicate name tag",currentLineID);
|
||||
|
||||
}
|
||||
for (indexer = 0; indexer < expectedFields; indexer++)
|
||||
clear_buffered_string(currentBuffers[indexer]);
|
||||
}
|
||||
else
|
||||
reportErrorLine ("Expected a tab following the '|'",currentLineID);
|
||||
break;
|
||||
|
||||
case 4: /* read a field */
|
||||
if (currentChar == '\t')
|
||||
automatonState = 2;
|
||||
else
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
reportErrorLine ("Unexpected end-of-line",currentLineID);
|
||||
else
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
break;
|
||||
|
||||
}
|
||||
currentChar = fgetc(inFile);
|
||||
}
|
||||
|
||||
fclose (inFile);
|
||||
|
||||
for (indexer = 0; indexer < expectedFields; indexer++)
|
||||
destroy_string(currentBuffers[indexer]);
|
||||
|
||||
free(currentBuffers);
|
||||
expectedFields = 13;
|
||||
currentBuffers = (struct bufferedString**)malloc (expectedFields*sizeof (struct bufferedString*));
|
||||
|
||||
for (indexer = 0; indexer < expectedFields; indexer++)
|
||||
currentBuffers[indexer] = allocateNewString();
|
||||
|
||||
automatonState = 0;
|
||||
currentLineID = 1;
|
||||
currentField = 0;
|
||||
|
||||
currentChar = fgetc(structFile);
|
||||
|
||||
while (!feof(structFile))
|
||||
{
|
||||
switch (automatonState)
|
||||
{
|
||||
case 0: /* start of the line; expecting numbers */
|
||||
if (currentChar >= '0' && currentChar <='9')
|
||||
{
|
||||
automatonState = 1; /* reading sequence ID */
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
}
|
||||
else
|
||||
if (!(currentChar == '\n' || currentChar == '\r'))
|
||||
reportErrorLine ("Could not find a valid sequence ID to start the line",currentLineID);
|
||||
break;
|
||||
|
||||
case 1: /* reading sequence ID */
|
||||
if (currentChar >= '0' && currentChar <='9')
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
else
|
||||
if (currentChar == '\t')
|
||||
automatonState = 2;
|
||||
else
|
||||
reportErrorLine ("Expected a tab following the tax ID",currentLineID);
|
||||
break;
|
||||
|
||||
case 2: /* looking for a | */
|
||||
if (currentChar != '|')
|
||||
reportErrorLine ("Expected a '|' following the tab",currentLineID);
|
||||
else
|
||||
automatonState = 3;
|
||||
break;
|
||||
|
||||
case 3: /* looking for a \t or a \n|\r*/
|
||||
if (currentChar == '\t')
|
||||
{
|
||||
automatonState = 4;
|
||||
currentField ++;
|
||||
if (currentField == expectedFields)
|
||||
reportErrorLine ("Too many fields",currentLineID);
|
||||
}
|
||||
else
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
{
|
||||
if (currentField < expectedFields-1)
|
||||
reportErrorLine ("Too few fields",currentLineID);
|
||||
|
||||
aTag = tagByID(atoi(currentBuffers[0]->sData));
|
||||
aTag2 = tagByID(atoi(currentBuffers[1]->sData));
|
||||
|
||||
if (! (aTag && aTag2))
|
||||
reportErrorLine ("Invalid ID tag",currentLineID);
|
||||
|
||||
if (aTag2 != aTag)
|
||||
{
|
||||
aTag->parent = aTag2;
|
||||
aTag3->startIndex = globalNameBuffer->sLength;
|
||||
aTag3->length = currentBuffers[2]->sLength;
|
||||
appendRangeToString (globalNameBuffer, currentBuffers[2], 0, currentBuffers[2]->sLength-1);
|
||||
aTag2 = avl_find (rankLabelAVL, aTag3);
|
||||
if (aTag2)
|
||||
aTag->taxonomy_level = aTag2->taxonomy_level;
|
||||
globalNameBuffer->sLength = aTag3->startIndex;
|
||||
}
|
||||
|
||||
currentField = 0;
|
||||
automatonState = 0;
|
||||
currentLineID ++;
|
||||
|
||||
for (indexer = 0; indexer < expectedFields; indexer++)
|
||||
clear_buffered_string(currentBuffers[indexer]);
|
||||
}
|
||||
else
|
||||
reportErrorLine ("Expected a tab following the '|'",currentLineID);
|
||||
break;
|
||||
|
||||
case 4: /* read a field */
|
||||
if (currentChar == '\t')
|
||||
automatonState = 2;
|
||||
else
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
reportErrorLine ("Unexpected end-of-line",currentLineID);
|
||||
else
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
break;
|
||||
|
||||
}
|
||||
currentChar = fgetc(structFile);
|
||||
}
|
||||
|
||||
fclose (structFile);
|
||||
|
||||
for (indexer = 0; indexer < expectedFields; indexer++)
|
||||
destroy_string(currentBuffers[indexer]);
|
||||
free(currentBuffers);
|
||||
expectedFields = 2;
|
||||
currentBuffers = (struct bufferedString**)malloc (expectedFields*sizeof (struct bufferedString*));
|
||||
|
||||
for (indexer = 0; indexer <= expectedFields; indexer++)
|
||||
currentBuffers[indexer] = allocateNewString();
|
||||
|
||||
automatonState = 0;
|
||||
currentLineID = 1;
|
||||
currentField = 0;
|
||||
firstLine = 1;
|
||||
|
||||
currentChar = fgetc(queryFile);
|
||||
|
||||
while (!feof(queryFile))
|
||||
{
|
||||
switch (automatonState)
|
||||
{
|
||||
case 0: /* start of the line; expecting numbers */
|
||||
if (!isspace(currentChar))
|
||||
{
|
||||
automatonState = 1; /* reading sequence ID */
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
}
|
||||
else
|
||||
if (!(currentChar == '\n' || currentChar == '\r'))
|
||||
reportErrorLine ("Could not find a valid sequence ID to start the line",currentLineID);
|
||||
break;
|
||||
|
||||
case 1: /* reading sequence ID */
|
||||
if ((currentField == 1 && currentChar >= '0' && currentChar <='9')||(currentField == 0 && currentChar != '\n' && currentChar != '\r' && currentChar != '\t'))
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
else
|
||||
if (currentChar == '\t')
|
||||
{
|
||||
automatonState = 1;
|
||||
currentField ++;
|
||||
if (currentField == expectedFields)
|
||||
automatonState = 2;
|
||||
}
|
||||
else
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
{
|
||||
currentField++;
|
||||
automatonState = 2;
|
||||
ungetc (currentChar,queryFile);
|
||||
}
|
||||
else
|
||||
reportErrorLine ("Expected a tab following a Tax/GID",currentLineID);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (currentChar == '\n' || currentChar == '\r')
|
||||
{
|
||||
if (currentField == expectedFields)
|
||||
{
|
||||
|
||||
indexer2 = atoi (currentBuffers[1]->sData); // TaxID
|
||||
qry = walkPath (indexer2);
|
||||
if (firstLine)
|
||||
firstLine = 0;
|
||||
else
|
||||
fputc ('\n',outFile);
|
||||
|
||||
fprintf (outFile,"%s\t%d", currentBuffers[0]->sData, indexer2);
|
||||
if (qry)
|
||||
{
|
||||
for (indexer = qry->sLength-1; indexer >= 0; indexer--)
|
||||
fputc (qry->sData[indexer], outFile);
|
||||
destroy_string(qry);
|
||||
}
|
||||
else
|
||||
fprintf (outFile, "\tNULL");
|
||||
if (currentBuffers[expectedFields]->sLength)
|
||||
fprintf (outFile, "\t%s", currentBuffers[expectedFields]->sData);
|
||||
|
||||
}
|
||||
currentLineID ++;
|
||||
currentField = 0;
|
||||
for (indexer = 0; indexer <= expectedFields; indexer++)
|
||||
clear_buffered_string(currentBuffers[indexer]);
|
||||
automatonState = 0;
|
||||
}
|
||||
else
|
||||
appendCharacterToString(currentBuffers[currentField],currentChar);
|
||||
|
||||
|
||||
}
|
||||
currentChar = fgetc(queryFile);
|
||||
}
|
||||
|
||||
fclose (queryFile);
|
||||
fclose (outFile);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
COMPILE
|
||||
=======
|
||||
|
||||
On Max OS X:
|
||||
$gcc -o taxBuilder -fast avl.c main.c
|
||||
|
||||
On Linux:
|
||||
|
||||
Insert the following near the top of main.c
|
||||
|
||||
#define isnumber (c) ( (c>='0') && (c<='9'))
|
||||
|
||||
Replace -fast with -O3 (the letter 'O'):
|
||||
|
||||
$gcc -o taxBuilder -O3 avl.c main.c
|
||||
|
||||
INSTALL
|
||||
=======
|
||||
|
||||
Place the binary into a directory that is listed in setup_paths.sh script located in the root of Galaxy installation
|
||||
|
||||
Reference in New Issue
Block a user