version 1.13, 2002/02/17 19:42:33 |
version 1.14, 2002/02/27 20:26:37 |
|
|
***/ |
***/ |
|
|
static void * |
static void * |
emem(p) |
emem(void *p) |
void *p; |
|
{ |
{ |
if (p) |
if (p) |
return p; |
return p; |
|
|
} |
} |
|
|
static void * |
static void * |
hash_alloc(s, u) |
hash_alloc(size_t s, void *u UNUSED) |
size_t s; |
|
void *u UNUSED; |
|
{ |
{ |
return emem(calloc(s, 1)); |
return emem(calloc(s, 1)); |
} |
} |
|
|
static void |
static void |
hash_free(p, s, u) |
hash_free(void *p, size_t s UNUSED, void *u UNUSED) |
void *p; |
|
size_t s UNUSED; |
|
void *u UNUSED; |
|
{ |
{ |
free(p); |
free(p); |
} |
} |
|
|
static void * |
static void * |
entry_alloc(s, u) |
entry_alloc(size_t s, void *u UNUSED) |
size_t s; |
|
void *u UNUSED; |
|
{ |
{ |
return emalloc(s); |
return emalloc(s); |
} |
} |
|
|
static void * |
static void * |
emalloc(s) |
emalloc(size_t s) |
size_t s; |
|
{ |
{ |
return emem(malloc(s)); |
return emem(malloc(s)); |
} |
} |
|
|
/* Inserting and finding nodes in the hash structure. |
/* Inserting and finding nodes in the hash structure. |
* We handle interval strings for efficiency wrt fgetln. */ |
* We handle interval strings for efficiency wrt fgetln. */ |
static struct node * |
static struct node * |
new_node(start, end) |
new_node(const char *start, const char *end) |
const char *start; |
|
const char *end; |
|
{ |
{ |
struct node *n; |
struct node *n; |
|
|
|
|
|
|
|
|
static void |
static void |
nodes_init(h) |
nodes_init(struct ohash *h) |
struct ohash *h; |
|
{ |
{ |
ohash_init(h, HASH_START, &node_info); |
ohash_init(h, HASH_START, &node_info); |
} |
} |
|
|
static struct node * |
static struct node * |
node_lookup(h, start, end) |
node_lookup(struct ohash *h, const char *start, const char *end) |
struct ohash *h; |
|
const char *start; |
|
const char *end; |
|
{ |
{ |
unsigned int i; |
unsigned int i; |
struct node * n; |
struct node * n; |
|
|
|
|
#ifdef DEBUG |
#ifdef DEBUG |
static void |
static void |
dump_node(n) |
dump_node(struct node *n) |
struct node *n; |
|
{ |
{ |
struct link *l; |
struct link *l; |
|
|
|
|
} |
} |
|
|
static void |
static void |
dump_array(a) |
dump_array(struct array *a) |
struct array *a; |
|
{ |
{ |
unsigned int i; |
unsigned int i; |
|
|
|
|
} |
} |
|
|
static void |
static void |
dump_hash(h) |
dump_hash(struct ohash *h) |
struct ohash *h; |
|
{ |
{ |
unsigned int i; |
unsigned int i; |
struct node *n; |
struct node *n; |
|
|
***/ |
***/ |
|
|
static void |
static void |
insert_arc(a, b) |
insert_arc(struct node *a, struct node *b) |
struct node *a, *b; |
|
{ |
{ |
struct link *l; |
struct link *l; |
|
|
|
|
} |
} |
|
|
static unsigned int |
static unsigned int |
read_pairs(f, h, reverse, name, order, hint) |
read_pairs(FILE *f, struct ohash *h, int reverse, const char *name, |
FILE *f; |
unsigned int order, int hint) |
struct ohash *h; |
|
int reverse; |
|
const char *name; |
|
unsigned int order; |
|
int hint; |
|
{ |
{ |
int toggle; |
int toggle; |
struct node *a; |
struct node *a; |
|
|
} |
} |
|
|
static unsigned int |
static unsigned int |
read_hints(f, h, quiet, name, order) |
read_hints(FILE *f, struct ohash *h, int quiet, const char *name, |
FILE *f; |
unsigned int order) |
struct ohash *h; |
|
int quiet; |
|
const char *name; |
|
unsigned int order; |
|
{ |
{ |
char *str; |
char *str; |
size_t size; |
size_t size; |
|
|
***/ |
***/ |
|
|
static void |
static void |
heap_down(h, i) |
heap_down(struct array *h, unsigned int i) |
struct array *h; |
|
unsigned int i; |
|
{ |
{ |
unsigned int j; |
unsigned int j; |
struct node *swap; |
struct node *swap; |
|
|
} |
} |
|
|
static void |
static void |
heapify(h, verbose) |
heapify(struct array *h, int verbose) |
struct array *h; |
|
int verbose; |
|
{ |
{ |
unsigned int i; |
unsigned int i; |
|
|
|
|
#define DEQUEUE(h) ( hints_flag ? dequeue(h) : (h)->t[--(h)->entries] ) |
#define DEQUEUE(h) ( hints_flag ? dequeue(h) : (h)->t[--(h)->entries] ) |
|
|
static struct node * |
static struct node * |
dequeue(h) |
dequeue(struct array *h) |
struct array *h; |
|
{ |
{ |
struct node *n; |
struct node *n; |
|
|
|
|
} while(0); |
} while(0); |
|
|
static void |
static void |
enqueue(h, n) |
enqueue(struct array *h, struct node *n) |
struct array *h; |
|
struct node *n; |
|
{ |
{ |
unsigned int i, j; |
unsigned int i, j; |
struct node *swap; |
struct node *swap; |
|
|
* Iterate until no nodes are left. |
* Iterate until no nodes are left. |
*/ |
*/ |
static void |
static void |
make_transparent(hash) |
make_transparent(struct ohash *hash) |
struct ohash *hash; |
|
{ |
{ |
struct node *n; |
struct node *n; |
unsigned int i; |
unsigned int i; |
|
|
|
|
/* Split nodes into unrefed nodes/live nodes. */ |
/* Split nodes into unrefed nodes/live nodes. */ |
static void |
static void |
split_nodes(hash, heap, remaining) |
split_nodes(struct ohash *hash, struct array *heap, struct array *remaining) |
struct ohash *hash; |
|
struct array *heap; |
|
struct array *remaining; |
|
{ |
{ |
|
|
struct node *n; |
struct node *n; |
|
|
|
|
/* Good point to break a cycle: live node with as few refs as possible. */ |
/* Good point to break a cycle: live node with as few refs as possible. */ |
static struct node * |
static struct node * |
find_good_cycle_break(h) |
find_good_cycle_break(struct array *h) |
struct array *h; |
|
{ |
{ |
unsigned int i; |
unsigned int i; |
unsigned int best; |
unsigned int best; |
|
|
|
|
/* Retrieve the node with the smallest order. */ |
/* Retrieve the node with the smallest order. */ |
static struct node * |
static struct node * |
find_smallest_node(h) |
find_smallest_node(struct array *h) |
struct array *h; |
|
{ |
{ |
unsigned int i; |
unsigned int i; |
unsigned int best; |
unsigned int best; |
|
|
/* Explore the nodes reachable from i to find a cycle, store it in c. |
/* Explore the nodes reachable from i to find a cycle, store it in c. |
* This may fail. */ |
* This may fail. */ |
static struct node * |
static struct node * |
find_cycle_from(i, c) |
find_cycle_from(struct node *i, struct array *c) |
struct node *i; |
|
struct array *c; |
|
{ |
{ |
struct node *n; |
struct node *n; |
|
|
|
|
* to go through the whole array, but it is not needed often. |
* to go through the whole array, but it is not needed often. |
*/ |
*/ |
static struct node * |
static struct node * |
find_predecessor(a, n) |
find_predecessor(struct array *a, struct node *n) |
struct array *a; |
|
struct node *n; |
|
{ |
{ |
unsigned int i; |
unsigned int i; |
|
|
|
|
Update the largest cycle found so far. |
Update the largest cycle found so far. |
*/ |
*/ |
static unsigned int |
static unsigned int |
traverse_node(n, o, c) |
traverse_node(struct node *n, unsigned int o, struct array *c) |
struct node *n; |
|
unsigned int o; |
|
struct array *c; |
|
{ |
{ |
unsigned int min, max; |
unsigned int min, max; |
|
|
|
|
} |
} |
|
|
static void |
static void |
print_cycle(c) |
print_cycle(struct array *c) |
struct array *c; |
|
{ |
{ |
unsigned int i; |
unsigned int i; |
|
|
|
|
} |
} |
|
|
static struct node * |
static struct node * |
find_longest_cycle(h, c) |
find_longest_cycle(struct array *h, struct array *c) |
struct array *h; |
|
struct array *c; |
|
{ |
{ |
unsigned int i; |
unsigned int i; |
unsigned int o; |
unsigned int o; |
|
|
#define plural(n) ((n) > 1 ? "s" : "") |
#define plural(n) ((n) > 1 ? "s" : "") |
|
|
int |
int |
main(argc, argv) |
main(int argc, char *argv[]) |
int argc; |
|
char *argv[]; |
|
{ |
{ |
struct ohash pairs; |
struct ohash pairs; |
int reverse_flag, quiet_flag, long_flag, |
int reverse_flag, quiet_flag, long_flag, |