From: Emden R. Gansner Date: Tue, 6 Jan 2015 21:17:41 +0000 (-0500) Subject: Merge branch 'master' of ssh://github.com/ellson/graphviz X-Git-Tag: TRAVIS_CI_BUILD_EXPERIMENTAL~129^2~5^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4a7e0148ca2802fd85cde75236f62a5c2f9f887c;p=graphviz Merge branch 'master' of ssh://github.com/ellson/graphviz Conflicts: lib/gvc/gvusershape.c --- 4a7e0148ca2802fd85cde75236f62a5c2f9f887c diff --cc lib/dotgen/decomp.c index 3b1554ea5,3b1554ea5..01bae58c4 --- a/lib/dotgen/decomp.c +++ b/lib/dotgen/decomp.c @@@ -22,52 -22,52 +22,164 @@@ #include "dot.h" -- --static graph_t *G; static node_t *Last_node; static char Cmark; static void --begin_component(void) ++begin_component(graph_t* g) { -- Last_node = GD_nlist(G) = NULL; ++ Last_node = GD_nlist(g) = NULL; } static void --add_to_component(node_t * n) ++add_to_component(graph_t* g, node_t * n) { -- GD_n_nodes(G)++; ++ GD_n_nodes(g)++; ND_mark(n) = Cmark; if (Last_node) { ND_prev(n) = Last_node; ND_next(Last_node) = n; } else { ND_prev(n) = NULL; -- GD_nlist(G) = n; ++ GD_nlist(g) = n; } Last_node = n; ND_next(n) = NULL; } static void --end_component(void) ++end_component(graph_t* g) { int i; -- i = GD_comp(G).size++; -- GD_comp(G).list = ALLOC(GD_comp(G).size, GD_comp(G).list, node_t *); -- GD_comp(G).list[i] = GD_nlist(G); ++ i = GD_comp(g).size++; ++ GD_comp(g).list = ALLOC(GD_comp(g).size, GD_comp(g).list, node_t *); ++ GD_comp(g).list[i] = GD_nlist(g); ++} ++ ++typedef struct blk_t { ++ Agnode_t **data; ++ Agnode_t **endp; ++ struct blk_t *prev; ++ struct blk_t *next; ++} blk_t; ++ ++typedef struct { ++ blk_t *fstblk; ++ blk_t *curblk; ++ Agnode_t **curp; ++} stk_t; ++ ++#define BIGBUF 1000000 ++ ++static void initStk(stk_t* sp, blk_t* bp, node_t** base, int size) ++{ ++ bp->data = base; ++ bp->endp = bp->data + size; ++ bp->next = NULL; ++ bp->prev = NULL; ++ sp->curblk = sp->fstblk = bp; ++ sp->curp = sp->curblk->data; ++} ++ ++static void freeStk(stk_t* sp) ++{ ++ blk_t* bp = sp->fstblk->next; ++ blk_t* nbp; ++ while (bp) { ++ nbp = bp->next; ++ free (bp->data); ++ free (bp); ++ bp = nbp; ++ } ++} ++ ++static void push(stk_t* sp, node_t * np) ++{ ++ if (sp->curp == sp->curblk->endp) { ++ if (sp->curblk->next == NULL) { ++ blk_t *bp = NEW(blk_t); ++ if (bp == 0) { ++ agerr(AGERR, "gc: Out of memory\n"); ++ } ++ bp->prev = sp->curblk; ++ bp->next = NULL; ++ bp->data = N_NEW(BIGBUF, Agnode_t *); ++ if (bp->data == 0) { ++ agerr(AGERR, "dot: Out of memory\n"); ++ } ++ bp->endp = bp->data + BIGBUF; ++ sp->curblk->next = bp; ++ } ++ sp->curblk = sp->curblk->next; ++ sp->curp = sp->curblk->data; ++ } ++ ND_mark(np) = Cmark+1; ++ *sp->curp++ = np; ++} ++ ++static node_t *pop(stk_t* sp) ++{ ++ if (sp->curp == sp->curblk->data) { ++ if (sp->curblk == sp->fstblk) ++ return 0; ++ sp->curblk = sp->curblk->prev; ++ sp->curp = sp->curblk->endp; ++ } ++ sp->curp--; ++ return *sp->curp; ++} ++ ++/* search_component: ++ * iterative dfs for components. ++ * We process the edges in reverse order of the recursive version to maintain ++ * the processing order of the nodes. ++ * Since are using a stack, we need to indicate nodes on the stack. Nodes unprocessed ++ * in this call to decompose will have mark < Cmark; processed nodes will have mark=Cmark; ++ * so we use mark = Cmark+1 to indicate nodes on the stack. ++ */ ++static void ++search_component(stk_t* stk, graph_t * g, node_t * n) ++{ ++ int c, i; ++ elist vec[4]; ++ node_t *other; ++ edge_t *e; ++ edge_t **ep; ++ ++ push(stk, n); ++ while ((n = pop(stk))) { ++ if (ND_mark(n) == Cmark) continue; ++ add_to_component(g, n); ++ vec[0] = ND_out(n); ++ vec[1] = ND_in(n); ++ vec[2] = ND_flat_out(n); ++ vec[3] = ND_flat_in(n); ++ ++ for (c = 3; c >= 0; c--) { ++ if (vec[c].list) { ++ for (i = vec[c].size-1, ep = vec[c].list+i; i >= 0; i--, ep--) { ++ e = *ep; ++ if ((other = aghead(e)) == n) ++ other = agtail(e); ++ if ((ND_mark(other) != Cmark) && (other == UF_find(other))) ++ push(stk, other); ++ } ++ } ++ } ++ } } ++#if 0 static void --search_component(graph_t * g, node_t * n) ++osearch_component(graph_t * g, node_t * n) { int c, i; elist vec[4]; node_t *other; edge_t *e; -- add_to_component(n); ++ add_to_component(g, n); vec[0] = ND_out(n); vec[1] = ND_in(n); vec[2] = ND_flat_out(n); @@@ -79,17 -79,17 +191,21 @@@ if ((other = aghead(e)) == n) other = agtail(e); if ((ND_mark(other) != Cmark) && (other == UF_find(other))) -- search_component(g, other); ++ osearch_component(g, other); } } } ++#endif void decompose(graph_t * g, int pass) { graph_t *subg; node_t *n, *v; ++ stk_t stk; ++ blk_t blk; ++ Agnode_t *base[SMALLBUF]; -- G = g; ++ initStk (&stk, &blk, base, SMALLBUF); if (++Cmark == 0) Cmark = 1; GD_n_nodes(g) = GD_comp(g).size = 0; @@@ -100,9 -100,9 +216,10 @@@ else if (v != UF_find(v)) continue; if (ND_mark(v) != Cmark) { -- begin_component(); -- search_component(g, v); -- end_component(); ++ begin_component(g); ++ search_component(&stk, g, v); ++ end_component(g); } } ++ freeStk (&stk); } diff --cc lib/gvc/gvusershape.c index ebbac1989,3e6b18254..4203849db --- a/lib/gvc/gvusershape.c +++ b/lib/gvc/gvusershape.c @@@ -629,7 -629,7 +629,13 @@@ void gvusershape_file_release(usershape } } - static usershape_t *gvusershape_open (char *name) ++static void freeUsershape (usershape_t* us) ++{ ++ if (us->name) agstrfree(0, (char*)us->name); ++ free (us); ++} ++ + static usershape_t *gvusershape_open (const char *name) { usershape_t *us; @@@ -642,9 -642,9 +648,9 @@@ if (! (us = zmalloc(sizeof(usershape_t)))) return NULL; - us->name = agstrdup (0, name); - us->name = name; ++ us->name = agstrdup (0, (char*)name); if (!gvusershape_file_access(us)) { -- free(us); ++ freeUsershape (us); return NULL; } @@@ -652,11 -652,10 +658,11 @@@ switch(imagetype(us)) { case FT_NULL: - if (!(us->data = (void*)find_user_shape(us->name))) + if (!(us->data = (void*)find_user_shape(us->name))) { agerr(AGWARN, "\"%s\" was not found as a file or as a shape library member\n", us->name); -- free(us); ++ freeUsershape (us); return NULL; + } break; case FT_GIF: gif_size(us);