Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
acyclic.c
Go to the documentation of this file.
1
18#include <cgraph/cghdr.h>
19#include <stdbool.h>
20#include <stddef.h>
21
22typedef struct {
23 Agrec_t h;
24 int mark;
25 bool onstack : 1;
27
28#define ND_mark(n) (((Agnodeinfo_t *)((n)->base.data))->mark)
29#define ND_onstack(n) (((Agnodeinfo_t *)((n)->base.data))->onstack)
30#define graphName(g) (agnameof(g))
31
32/* Add a reversed version of e. The new edge has the same key.
33 * We also copy the attributes, reversing the roles of head and
34 * tail ports.
35 * This assumes we've already checked that such an edge does not exist.
36 */
37static void addRevEdge(Agraph_t *g, Agedge_t *e) {
38 Agsym_t *sym;
39 Agedge_t *f = agedge(g, aghead(e), agtail(e), agnameof(e), 1);
40
41 agcopyattr(e, f);
42
43 sym = agattr(g, AGEDGE, TAILPORT_ID, 0);
44 if (sym)
45 agsafeset(f, HEADPORT_ID, agxget(e, sym), "");
46 sym = agattr(g, AGEDGE, HEADPORT_ID, 0);
47 if (sym)
48 agsafeset(f, TAILPORT_ID, agxget(e, sym), "");
49}
50
52static bool dfs(Agraph_t *g, Agnode_t *t, bool hasCycle, size_t *num_rev) {
53 Agedge_t *e;
54 Agedge_t *f;
55 Agnode_t *h;
56
57 ND_mark(t) = 1;
58 ND_onstack(t) = true;
59 for (e = agfstout(g, t); e; e = f) {
60 f = agnxtout(g, e);
61 if (agtail(e) == aghead(e))
62 continue;
63 h = aghead(e);
64 if (ND_onstack(h)) {
65 if (agisstrict(g)) {
66 if (agedge(g, h, t, 0, 0) == 0) {
67 addRevEdge(g, e);
68 ++*num_rev;
69 }
70 } else {
71 char *key = agnameof(e);
72 if (!key || agedge(g, h, t, key, 0) == 0) {
73 addRevEdge(g, e);
74 ++*num_rev;
75 }
76 }
77 agdelete(g, e);
78 hasCycle = true;
79 } else if (ND_mark(h) == 0)
80 hasCycle |= dfs(g, h, hasCycle, num_rev);
81 }
82 ND_onstack(t) = false;
83 return hasCycle;
84}
85
87 size_t *num_rev) {
88 bool has_cycle = false;
89 aginit(g, AGNODE, "info", sizeof(Agnodeinfo_t), true);
90 for (Agnode_t *n = agfstnode(g); n; n = agnxtnode(g, n)) {
91 if (ND_mark(n) == 0) {
92 has_cycle |= dfs(g, n, false, num_rev);
93 }
94 }
95 if (opts->doWrite) {
96 agwrite(g, opts->outFile);
97 fflush(opts->outFile);
98 }
99 return has_cycle;
100}
cgraph.h additions
bool graphviz_acyclic(Agraph_t *g, const graphviz_acyclic_options_t *opts, size_t *num_rev)
Definition acyclic.c:86
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
Definition attr.c:338
int agsafeset(void *obj, char *name, const char *value, const char *def)
ensures the given attribute is declared before setting it locally on an object
Definition attr.c:507
char * agxget(void *obj, Agsym_t *sym)
Definition attr.c:455
int agcopyattr(void *oldobj, void *newobj)
copies all of the attributes from one object to another
Definition attr.c:549
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:260
#define TAILPORT_ID
Definition cgraph.h:887
#define HEADPORT_ID
Definition cgraph.h:888
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:24
#define agtail(e)
Definition cgraph.h:880
#define aghead(e)
Definition cgraph.h:881
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:39
int agisstrict(Agraph_t *g)
Definition graph.c:200
int agwrite(Agraph_t *g, void *chan)
Return 0 on success, EOF on failure.
Definition write.c:730
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:158
int agdelete(Agraph_t *g, void *obj)
deletes object. Equivalent to agclose, agdelnode, and agdeledge for obj being a graph,...
Definition obj.c:20
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
void aginit(Agraph_t *g, int kind, const char *rec_name, int rec_size, int move_to_front)
attach new records to objects of specified kind
Definition rec.c:170
static opts_t opts
Definition gvgen.c:394
#define ND_onstack(n)
Definition acyclic.c:29
static void addRevEdge(Agraph_t *g, Agedge_t *e)
Definition acyclic.c:37
#define ND_mark(n)
Definition acyclic.c:28
static bool dfs(Agraph_t *g, Agnode_t *t, bool hasCycle, size_t *num_rev)
Return true if the graph has a cycle.
Definition acyclic.c:52
bool onstack
Definition acyclic.c:25
graph or subgraph
Definition cgraph.h:425
implementation of Agrec_t
Definition cgraph.h:172
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:637
options for passing to graphviz_acyclic
Definition cgraph.h:919