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