1
/* $Id: blocktree.c,v 1.9 2009/08/17 21:04:11 erg Exp $ $Revision: 1.9 $ */
2
/* vim:set shiftwidth=4 ts=8: */
4
/**********************************************************
5
* This software is part of the graphviz package *
6
* http://www.graphviz.org/ *
8
* Copyright (c) 1994-2004 AT&T Corp. *
9
* and is licensed under the *
10
* Common Public License, Version 1.0 *
13
* Information and Software Systems Research *
14
* AT&T Research, Florham Park NJ *
15
**********************************************************/
18
#include "blocktree.h"
20
static void addNode(block_t * bp, Agnode_t * n)
23
aginsert(bp->sub_graph, n);
24
#else /* WITH_CGRAPH */
25
agsubnode(bp->sub_graph, n,1);
26
#endif /* WITH_CGRAPH */
30
static Agraph_t *makeBlockGraph(Agraph_t * g, circ_state * state)
35
sprintf(name, "_block_%d", state->blockCount++);
37
subg = agsubg(g, name);
38
#else /* WITH_CGRAPH */
39
subg = agsubg(g, name,1);
40
agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); //node custom data
41
#endif /* WITH_CGRAPH */
45
static block_t *makeBlock(Agraph_t * g, circ_state * state)
47
Agraph_t *subg = makeBlockGraph(g, state);
48
block_t *bp = mkBlock(subg);
59
push (estack* s, Agedge_t* e)
69
Agedge_t *top = s->top;
83
static void dfs(Agraph_t * g, Agnode_t * u, circ_state * state, int isRoot, estack* stk)
88
LOWVAL(u) = VAL(u) = state->orderCount++;
89
for (e = agfstedge(g, u); e; e = agnxtedge(g, e, u)) {
93
if (!EDGEORDER(e)) EDGEORDER(e) = -1;
96
if (!EDGEORDER(e)) EDGEORDER(e) = 1;
102
dfs(g, v, state, 0, stk);
103
LOWVAL(u) = MIN(LOWVAL(u), LOWVAL(v));
104
if (LOWVAL(v) >= VAL(u)) { /* u is an articulation point */
105
block_t *block = NULL;
110
if (EDGEORDER(ep) == 1)
116
block = makeBlock(g, state);
120
if (block) { /* If block != NULL, it's not empty */
121
if (blockSize (block) > 1)
123
if (isRoot && (BLOCK(u) == block))
124
insertBlock(&state->bl, block);
126
appendBlock(&state->bl, block);
129
} else if (PARENT(u) != v) {
130
LOWVAL(u) = MIN(LOWVAL(u), VAL(v));
133
if (isRoot && !BLOCK(u)) {
134
block_t *block = makeBlock(g, state);
136
insertBlock(&state->bl, block);
143
static void find_blocks(Agraph_t * g, circ_state * state)
146
Agnode_t *root = NULL;
149
/* check to see if there is a node which is set to be the root
151
if (state->rootname) {
152
root = agfindnode(g, state->rootname);
154
if (!root && state->N_root) {
155
for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
156
if (late_bool(ORIGN(n), state->N_root, 0)) {
166
fprintf (stderr, "root = %s\n", agnameof(root));
169
dfs(g, root, state, 1, &stk);
173
/* create_block_tree:
174
* Construct block tree by peeling nodes from block list in state.
175
* When done, return root. The block list is empty
176
* FIX: use largest block as root
178
block_t *createBlocktree(Agraph_t * g, circ_state * state)
186
find_blocks(g, state);
188
bp = state->bl.first; /* if root chosen, will be first */
189
/* Otherwise, just pick first as root */
192
/* Find node with minimum VAL value to find parent block */
193
/* FIX: Should be some way to avoid search below. */
194
/* ordercnt = state->orderCount; */
195
for (bp = bp->next; bp; bp = next) {
199
Agraph_t *subg = bp->sub_graph;
201
child = n = agfstnode(subg);
205
for (n = agnxtnode(subg, n); n; n = agnxtnode(subg, n)) {
214
next = bp->next; /* save next since list insertion destroys it */
215
appendBlock(&(BLOCK(parent)->children), bp);
217
initBlocklist(&state->bl); /* zero out list */
221
void freeBlocktree(block_t * bp)
226
for (child = bp->children.first; child; child = next) {
228
freeBlocktree(child);
235
static void indent(int i)
241
void print_blocktree(block_t * sn, int depth)
249
fprintf(stderr, "%s:", g->name);
250
for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
251
fprintf(stderr, " %s", n->name);
256
for (child = sn->children.first; child; child = child->next) {
257
print_blocktree(child, depth);