version 1.28, 2015/08/31 09:36:02 |
version 1.29, 2015/09/03 11:16:50 |
|
|
static struct node *find_predecessor(struct array *, struct node *); |
static struct node *find_predecessor(struct array *, struct node *); |
static unsigned int traverse_node(struct node *, unsigned int, struct array *); |
static unsigned int traverse_node(struct node *, unsigned int, struct array *); |
static struct node *find_longest_cycle(struct array *, struct array *); |
static struct node *find_longest_cycle(struct array *, struct array *); |
|
static struct node *find_normal_cycle(struct array *, struct array *); |
|
|
static void heap_down(struct array *, unsigned int); |
static void heap_down(struct array *, unsigned int); |
static void heapify(struct array *, int); |
static void heapify(struct array *, int); |
|
|
#define DEBUG_TRAVERSE 0 |
#define DEBUG_TRAVERSE 0 |
static struct ohash_info node_info = { |
static struct ohash_info node_info = { |
offsetof(struct node, k), NULL, hash_calloc, hash_free, entry_alloc }; |
offsetof(struct node, k), NULL, hash_calloc, hash_free, entry_alloc }; |
|
static void parse_args(int, char *[], struct ohash *); |
|
static int tsort(struct ohash *); |
|
|
|
static int quiet_flag, long_flag, |
|
warn_flag, hints_flag, verbose_flag; |
|
|
|
|
int main(int, char *[]); |
int main(int, char *[]); |
|
|
/*** |
/*** |
|
|
return n; |
return n; |
} |
} |
|
|
|
static struct node * |
|
find_normal_cycle(struct array *h, struct array *c) |
|
{ |
|
struct node *b, *n; |
|
|
|
if (hints_flag) |
|
n = find_smallest_node(h); |
|
else |
|
n = find_good_cycle_break(h); |
|
while ((b = find_cycle_from(n, c)) == NULL) |
|
n = find_predecessor(h, n); |
|
return b; |
|
} |
|
|
|
|
#define plural(n) ((n) > 1 ? "s" : "") |
#define plural(n) ((n) > 1 ? "s" : "") |
|
|
int |
static void |
main(int argc, char *argv[]) |
parse_args(int argc, char *argv[], struct ohash *pairs) |
{ |
{ |
struct ohash pairs; |
int c; |
int reverse_flag, quiet_flag, long_flag, |
|
warn_flag, hints_flag, verbose_flag; |
|
unsigned int order; |
unsigned int order; |
|
int reverse_flag; |
|
|
order = 0; |
order = 0; |
|
|
reverse_flag = quiet_flag = long_flag = |
reverse_flag = quiet_flag = long_flag = |
warn_flag = hints_flag = verbose_flag = 0; |
warn_flag = hints_flag = verbose_flag = 0; |
nodes_init(&pairs); |
nodes_init(pairs); |
|
while ((c = getopt(argc, argv, "h:flqrvw")) != -1) { |
|
switch(c) { |
|
case 'h': { |
|
FILE *f; |
|
|
{ |
f = fopen(optarg, "r"); |
int c; |
if (f == NULL) |
|
err(EX_NOINPUT, "Can't open hint file %s", |
while ((c = getopt(argc, argv, "h:flqrvw")) != -1) { |
optarg); |
switch(c) { |
order = read_hints(f, pairs, quiet_flag, |
case 'h': { |
optarg, order); |
FILE *f; |
fclose(f); |
|
} |
f = fopen(optarg, "r"); |
hints_flag = 1; |
if (f == NULL) |
break; |
err(EX_NOINPUT, "Can't open hint file %s", |
/*FALLTHRU*/ |
optarg); |
case 'f': |
order = read_hints(f, &pairs, quiet_flag, |
hints_flag = 2; |
optarg, order); |
break; |
fclose(f); |
case 'l': |
} |
long_flag = 1; |
hints_flag = 1; |
break; |
break; |
case 'q': |
/*FALLTHRU*/ |
quiet_flag = 1; |
case 'f': |
break; |
hints_flag = 2; |
case 'r': |
break; |
reverse_flag = 1; |
case 'l': |
break; |
long_flag = 1; |
case 'v': |
break; |
verbose_flag = 1; |
case 'q': |
break; |
quiet_flag = 1; |
case 'w': |
break; |
warn_flag = 1; |
case 'r': |
break; |
reverse_flag = 1; |
default: |
break; |
usage(); |
case 'v': |
} |
verbose_flag = 1; |
|
break; |
|
case 'w': |
|
warn_flag = 1; |
|
break; |
|
default: |
|
usage(); |
|
} |
|
} |
|
|
|
argc -= optind; |
|
argv += optind; |
|
} |
} |
|
|
|
argc -= optind; |
|
argv += optind; |
|
|
switch(argc) { |
switch(argc) { |
case 1: { |
case 1: { |
FILE *f; |
FILE *f; |
|
|
f = fopen(argv[0], "r"); |
f = fopen(argv[0], "r"); |
if (f == NULL) |
if (f == NULL) |
err(EX_NOINPUT, "Can't open file %s", argv[0]); |
err(EX_NOINPUT, "Can't open file %s", argv[0]); |
order = read_pairs(f, &pairs, reverse_flag, argv[0], order, |
order = read_pairs(f, pairs, reverse_flag, argv[0], order, |
hints_flag == 2); |
hints_flag == 2); |
fclose(f); |
fclose(f); |
break; |
break; |
} |
} |
case 0: |
case 0: |
order = read_pairs(stdin, &pairs, reverse_flag, "stdin", |
order = read_pairs(stdin, pairs, reverse_flag, "stdin", |
order, hints_flag == 2); |
order, hints_flag == 2); |
break; |
break; |
default: |
default: |
usage(); |
usage(); |
} |
} |
|
} |
|
|
{ |
static int |
|
tsort(struct ohash *pairs) |
|
{ |
struct array aux; /* Unrefed nodes/cycle reporting. */ |
struct array aux; /* Unrefed nodes/cycle reporting. */ |
struct array remaining; |
struct array remaining; |
unsigned int broken_arcs, broken_cycles; |
unsigned int broken_arcs, broken_cycles; |
|
|
broken_cycles = 0; |
broken_cycles = 0; |
|
|
if (hints_flag) |
if (hints_flag) |
make_transparent(&pairs); |
make_transparent(pairs); |
split_nodes(&pairs, &aux, &remaining); |
split_nodes(pairs, &aux, &remaining); |
ohash_delete(&pairs); |
ohash_delete(pairs); |
|
|
if (hints_flag) |
if (hints_flag) |
heapify(&aux, verbose_flag); |
heapify(&aux, verbose_flag); |
|
|
/* XXX Simple cycle detection and long cycle |
/* XXX Simple cycle detection and long cycle |
* detection are mutually exclusive. */ |
* detection are mutually exclusive. */ |
|
|
if (long_flag) { |
if (long_flag) |
n = find_longest_cycle(&remaining, &aux); |
n = find_longest_cycle(&remaining, &aux); |
} else { |
else |
struct node *b; |
n = find_normal_cycle(&remaining, &aux); |
|
|
if (hints_flag) |
|
n = find_smallest_node(&remaining); |
|
else |
|
n = find_good_cycle_break(&remaining); |
|
while ((b = find_cycle_from(n, &aux)) == NULL) |
|
n = find_predecessor(&remaining, n); |
|
n = b; |
|
} |
|
|
|
if (!quiet_flag) { |
if (!quiet_flag) { |
warnx("cycle in data"); |
warnx("cycle in data"); |
print_cycle(&aux); |
print_cycle(&aux); |
|
|
broken_cycles, plural(broken_cycles), |
broken_cycles, plural(broken_cycles), |
broken_arcs, plural(broken_arcs)); |
broken_arcs, plural(broken_arcs)); |
if (warn_flag) |
if (warn_flag) |
exit(broken_cycles < 256 ? broken_cycles : 255); |
return (broken_cycles < 256 ? broken_cycles : 255); |
else |
else |
exit(EX_OK); |
return (EX_OK); |
} |
} |
|
|
|
int |
|
main(int argc, char *argv[]) |
|
{ |
|
struct ohash pairs; |
|
|
|
parse_args(argc, argv, &pairs); |
|
return tsort(&pairs); |
} |
} |
|
|
|
|