wolffd@0
|
1 .de P0
|
wolffd@0
|
2 .nf
|
wolffd@0
|
3 \f5
|
wolffd@0
|
4 ..
|
wolffd@0
|
5 .de P1
|
wolffd@0
|
6 \fP
|
wolffd@0
|
7 .fi
|
wolffd@0
|
8 ..
|
wolffd@0
|
9 .de Ss
|
wolffd@0
|
10 .fl
|
wolffd@0
|
11 .ne 2
|
wolffd@0
|
12 .SS "\\$1"
|
wolffd@0
|
13 ..
|
wolffd@0
|
14 .TH LIBCGRAPH 3 "30 JULY 2007"
|
wolffd@0
|
15 .SH "NAME"
|
wolffd@0
|
16 \fBlibcgraph\fR \- abstract graph library
|
wolffd@0
|
17 .SH "SYNOPSIS"
|
wolffd@0
|
18 ."ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i
|
wolffd@0
|
19 .PP
|
wolffd@0
|
20 .nf
|
wolffd@0
|
21 .P0
|
wolffd@0
|
22 #include <graphviz/cgraph.h>
|
wolffd@0
|
23 .P1
|
wolffd@0
|
24 .SS "TYPES"
|
wolffd@0
|
25 .P0
|
wolffd@0
|
26 Agraph_t;
|
wolffd@0
|
27 Agnode_t;
|
wolffd@0
|
28 Agedge_t;
|
wolffd@0
|
29 Agdesc_t;
|
wolffd@0
|
30 Agdisc_t;
|
wolffd@0
|
31 Agsym_t;
|
wolffd@0
|
32 .P1
|
wolffd@0
|
33 .SS "GRAPHS"
|
wolffd@0
|
34 .P0
|
wolffd@0
|
35 Agraph_t *agopen(char *name, Agdesc_t kind, Agdisc_t *disc);
|
wolffd@0
|
36 int agclose(Agraph_t *g);
|
wolffd@0
|
37 Agraph_t *agread(void *channel, Agdisc_t *);
|
wolffd@0
|
38 void agreadline(int line_no);
|
wolffd@0
|
39 void agsetfile(char *file_name);
|
wolffd@0
|
40 Agraph_t *agconcat(Agraph_t *g, void *channel, Agdisc_t *disc)
|
wolffd@0
|
41 int agwrite(Agraph_t *g, void *channel);
|
wolffd@0
|
42 int agnnodes(Agraph_t *g),agnedges(Agraph_t *g);
|
wolffd@0
|
43 int agisdirected(Agraph_t * g),agisundirected(Agraph_t * g),agisstrict(Agraph_t * g), agissimple(Agraph_t * g);
|
wolffd@0
|
44 .SS "SUBGRAPHS"
|
wolffd@0
|
45 .P0
|
wolffd@0
|
46 Agraph_t *agsubg(Agraph_t *g, char *name, int createflag);
|
wolffd@0
|
47 Agraph_t *agidsubg(Agraph_t * g, unsigned long id, int cflag);
|
wolffd@0
|
48 Agraph_t *agfstsubg(Agraph_t *g), agnxtsubg(Agraph_t *);
|
wolffd@0
|
49 Agraph_t *agparent(Agraph_t *g);
|
wolffd@0
|
50 int agdelsubg(Agraph_t * g, Agraph_t * sub); /* same as agclose() */
|
wolffd@0
|
51 .P1
|
wolffd@0
|
52 .SS "NODES"
|
wolffd@0
|
53 .P0
|
wolffd@0
|
54 Agnode_t *agnode(Agraph_t *g, char *name, int createflag);
|
wolffd@0
|
55 Agnode_t *agidnode(Agraph_t *g, ulong id, int createflag);
|
wolffd@0
|
56 Agnode_t *agsubnode(Agraph_t *g, Agnode_t *n, int createflag);
|
wolffd@0
|
57 Agnode_t *agfstnode(Agraph_t *g);
|
wolffd@0
|
58 Agnode_t *agnxtnode(Agraph_t *g, Agnode_t *n);
|
wolffd@0
|
59 Agnode_t *agprvnode(Agraph_t *g, Agnode_t *n);
|
wolffd@0
|
60 Agnode_t *aglstnode(Agraph_t *g);
|
wolffd@0
|
61 int agdelnode(Agraph_t *g, Agnode_t *n);
|
wolffd@0
|
62 int agdegree(Agnode_t *n, int use_inedges, int use_outedges);
|
wolffd@0
|
63 .P1
|
wolffd@0
|
64 .SS "EDGES"
|
wolffd@0
|
65 .P0
|
wolffd@0
|
66 Agedge_t *agedge(Agraph_t* g, Agnode_t *t, Agnode_t *h, char *name, int createflag);
|
wolffd@0
|
67 Agedge_t *agidedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, unsigned long id, int createflag);
|
wolffd@0
|
68 Agedge_t *agsubedge(Agraph_t *g, Agedge_t *e, int createflag);
|
wolffd@0
|
69 Agnode_t *aghead(Agedge_t *e), *agtail(Agedge_t *e);
|
wolffd@0
|
70 Agedge_t *agfstedge(Agraph_t* g, Agnode_t *n);
|
wolffd@0
|
71 Agedge_t *agnxtedge(Agraph_t* g, Agedge_t *e, Agnode_t *n);
|
wolffd@0
|
72 Agedge_t *agfstin(Agraph_t* g, Agnode_t *n);
|
wolffd@0
|
73 Agedge_t *agnxtin(Agraph_t* g, Agedge_t *e);
|
wolffd@0
|
74 Agedge_t *agfstout(Agraph_t* g, Agnode_t *n);
|
wolffd@0
|
75 Agedge_t *agnxtout(Agraph_t* g, Agedge_t *e);
|
wolffd@0
|
76 int agdeledge(Agraph_t *g, Agedge_t *e);
|
wolffd@0
|
77 .SS "STRING ATTRIBUTES"
|
wolffd@0
|
78 .P0
|
wolffd@0
|
79 Agsym_t *agattr(Agraph_t *g, int kind, char *name, char *value);
|
wolffd@0
|
80 Agsym_t *agattrsym(void *obj, char *name);
|
wolffd@0
|
81 Agsym_t *agnxtattr(Agraph_t *g, int kind, Agsym_t *attr);
|
wolffd@0
|
82 char *agget(void *obj, char *name);
|
wolffd@0
|
83 char *agxget(void *obj, Agsym_t *sym);
|
wolffd@0
|
84 int agset(void *obj, char *name, char *value);
|
wolffd@0
|
85 int agxset(void *obj, Agsym_t *sym, char *value);
|
wolffd@0
|
86 int agsafeset(void *obj, char *name, char *value, char *def);
|
wolffd@0
|
87 .P1
|
wolffd@0
|
88 .SS "RECORDS"
|
wolffd@0
|
89 .P0
|
wolffd@0
|
90 void *agbindrec(void *obj, char *name, unsigned int size, move_to_front);
|
wolffd@0
|
91 Agrec_t *aggetrec(void *obj, char *name, int move_to_front);
|
wolffd@0
|
92 int agdelrec(Agraph_t *g, void *obj, char *name);
|
wolffd@0
|
93 int agcopyattr(void *, void *);
|
wolffd@0
|
94 void aginit(Agraph_t * g, int kind, char *rec_name, int rec_size, int move_to_front);
|
wolffd@0
|
95 void agclean(Agraph_t * g, int kind, char *rec_name);
|
wolffd@0
|
96 .P1
|
wolffd@0
|
97 .SS "CALLBACKS"
|
wolffd@0
|
98 .P0
|
wolffd@0
|
99 Agcbdisc_t *agpopdisc(Agraph_t *g);
|
wolffd@0
|
100 void agpushdisc(Agraph_t *g, Agcbdisc_t *disc);
|
wolffd@0
|
101 void agmethod(Agraph_t *g, void *obj, Agcbdisc_t *disc, int initflag);
|
wolffd@0
|
102 .P1
|
wolffd@0
|
103 .SS "MEMORY"
|
wolffd@0
|
104 .P0
|
wolffd@0
|
105 void *agalloc(Agraph_t *g, size_t request);
|
wolffd@0
|
106 void *agrealloc(Agraph_t *g, void *ptr, size_t oldsize, size_t newsize);
|
wolffd@0
|
107 void agfree(Agraph_t *g, void *ptr);
|
wolffd@0
|
108 .P1
|
wolffd@0
|
109 .SS "STRINGS"
|
wolffd@0
|
110 .P0
|
wolffd@0
|
111 char *agstrdup(Agraph_t *, char *);
|
wolffd@0
|
112 char *agstrdup_html(Agraph_t *, char *);
|
wolffd@0
|
113 int aghtmlstr(char *);
|
wolffd@0
|
114 char *agstrbind(Agraph_t * g, char *);
|
wolffd@0
|
115 int strfree(Agraph_t *, char *);
|
wolffd@0
|
116 char *agcanonStr(char *);
|
wolffd@0
|
117 char *agstrcanon(char *, char *);
|
wolffd@0
|
118 .P1
|
wolffd@0
|
119 .SS "GENERIC OBJECTS"
|
wolffd@0
|
120 .P0
|
wolffd@0
|
121 Agraph_t *agraphof(void*);
|
wolffd@0
|
122 Agraph_t *agroot(void*);
|
wolffd@0
|
123 int agcontains(Agraph_t*, void*);
|
wolffd@0
|
124 char *agnameof(void*);
|
wolffd@0
|
125 void agdelete(Agraph_t *g, void *obj);
|
wolffd@0
|
126 int agobjkind(void *obj);
|
wolffd@0
|
127 Agrec_t *AGDATA(void *obj);
|
wolffd@0
|
128 ulong AGID(void *obj);
|
wolffd@0
|
129 int AGTYPE(void *obj);
|
wolffd@0
|
130 .P1
|
wolffd@0
|
131 .SH "DESCRIPTION"
|
wolffd@0
|
132 Libcgraph supports graph programming by maintaining graphs in memory
|
wolffd@0
|
133 and reading and writing graph files.
|
wolffd@0
|
134 Graphs are composed of nodes, edges, and nested subgraphs.
|
wolffd@0
|
135 These graph objects may be attributed with string name-value pairs
|
wolffd@0
|
136 and programmer-defined records (see Attributes).
|
wolffd@0
|
137 .PP
|
wolffd@0
|
138 All of Libcgraph's global symbols have the prefix \fBag\fR (case varying).
|
wolffd@0
|
139 .SH "GRAPH AND SUBGRAPHS"
|
wolffd@0
|
140 .PP
|
wolffd@0
|
141 A ``main'' or ``root'' graph defines a namespace for a collection of
|
wolffd@0
|
142 graph objects (subgraphs, nodes, edges) and their attributes.
|
wolffd@0
|
143 Objects may be named by unique strings or by 32-bit IDs.
|
wolffd@0
|
144 .PP
|
wolffd@0
|
145 \fBagopen\fP creates a new graph with the given name and kind.
|
wolffd@0
|
146 (Graph kinds are \fBAgdirected\fP, \fBAgundirected\fP,
|
wolffd@0
|
147 \fBAgstrictdirected\fP, and \fBAgstrictundirected\fP.
|
wolffd@0
|
148 A strict graph cannot have multi-edges or self-arcs.)
|
wolffd@0
|
149 \fBagclose\fP deletes a graph, freeing its associated storage.
|
wolffd@0
|
150 \fBagread\fP, \fBagwrite\fP, and \fBagconcat\fP perform file I/O
|
wolffd@0
|
151 using the graph file language described below. \fBagread\fP
|
wolffd@0
|
152 constructs a new graph while \fBagconcat\fP merges the file
|
wolffd@0
|
153 contents with a pre-existing graph. Though I/O methods may
|
wolffd@0
|
154 be overridden, the default is that the channel argument is
|
wolffd@0
|
155 a stdio FILE pointer. \fBagsetfile\fP and \fBagreadline\fP
|
wolffd@0
|
156 are helper functions that simply set the current file name
|
wolffd@0
|
157 and input line number for subsequent error reporting.
|
wolffd@0
|
158 .PP
|
wolffd@0
|
159 \fBagsubg\fP finds or creates
|
wolffd@0
|
160 a subgraph by name. A new subgraph is is initially empty and
|
wolffd@0
|
161 is of the same kind as its parent. Nested subgraph trees may be created.
|
wolffd@0
|
162 A subgraph's name is only interpreted relative to its parent.
|
wolffd@0
|
163 A program can scan subgraphs under a given graph
|
wolffd@0
|
164 using \fBagfstsubg\fP and \fRagnxtsubg\fP. A subgraph is
|
wolffd@0
|
165 deleted with \fBagdelsubg\fP (or \fBagclose\fP).
|
wolffd@0
|
166 .PP
|
wolffd@0
|
167 By default, nodes are stored in ordered sets for efficient random
|
wolffd@0
|
168 access to insert, find, and delete nodes.
|
wolffd@0
|
169 The edges of a node are also stored in ordered sets.
|
wolffd@0
|
170 The sets are maintained internally as splay tree dictionaries
|
wolffd@0
|
171 using Phong Vo's cdt library.
|
wolffd@0
|
172 .PP
|
wolffd@0
|
173 \fBagnnodes\fP, \fBagnedges\fP, and \fBagdegree\fP return the
|
wolffd@0
|
174 sizes of node and edge sets of a graph. The \fBagdegree\fP returns
|
wolffd@0
|
175 the size of the edge set of a nodes, and takes flags
|
wolffd@0
|
176 to select in-edges, out-edges, or both.
|
wolffd@0
|
177 .PP
|
wolffd@0
|
178 An \fBAgdisc_t\fP defines callbacks to be invoked by libcgraph when
|
wolffd@0
|
179 initializing, modifying, or finalizing graph objects. (Casual users can ignore
|
wolffd@0
|
180 the following.) Disciplines are kept on a stack. Libcgraph automatically
|
wolffd@0
|
181 calls the methods on the stack, top-down. Callbacks are installed
|
wolffd@0
|
182 with \fBagpushdisc\fP, uninstalled with \fBagpopdisc\fP, and
|
wolffd@0
|
183 can be held pending or released via \fBagcallbacks\fP.
|
wolffd@0
|
184 .PP
|
wolffd@0
|
185 (Casual users may ignore the following.
|
wolffd@0
|
186 When Libcgraph is compiled with Vmalloc (which is not the default),
|
wolffd@0
|
187 each graph has its own heap.
|
wolffd@0
|
188 Programmers may allocate application-dependent data within the
|
wolffd@0
|
189 same heap as the rest of the graph. The advantage is that
|
wolffd@0
|
190 a graph can be deleted by atomically freeing its entire heap
|
wolffd@0
|
191 without scanning each individual node and edge.
|
wolffd@0
|
192 .SH "NODES"
|
wolffd@0
|
193 A node is created by giving a unique string name or
|
wolffd@0
|
194 programmer defined 32-bit ID, and is represented by a
|
wolffd@0
|
195 unique internal object. (Node equality can checked
|
wolffd@0
|
196 by pointer comparison.)
|
wolffd@0
|
197 .PP
|
wolffd@0
|
198 \fBagnode\fP searches in a graph or subgraph for a node
|
wolffd@0
|
199 with the given name, and returns it if found.
|
wolffd@0
|
200 If not found, if \fBcreateflag\fP is boolean true
|
wolffd@0
|
201 a new node is created and returned, otherwise a nil
|
wolffd@0
|
202 pointer is returned.
|
wolffd@0
|
203 \fBagidnode\fP allows a programmer to specify the node
|
wolffd@0
|
204 by a unique 32-bit ID.
|
wolffd@0
|
205 \fBagsubnode\fP performs a similar operation on
|
wolffd@0
|
206 an existing node and a subgraph.
|
wolffd@0
|
207 .Pp
|
wolffd@0
|
208 \fBagfstnode\fP and \fBagnxtnode\fP scan node lists.
|
wolffd@0
|
209 \fBagprvnode\fP and \fPaglstnode\fP are symmetric but scan backward.
|
wolffd@0
|
210 The default sequence is order of creation (object timestamp.)
|
wolffd@0
|
211 \fBagdelnode\fP removes a node from a graph or subgraph.
|
wolffd@0
|
212 .SH "EDGES"
|
wolffd@0
|
213 .PP
|
wolffd@0
|
214 An abstract edge has two endpoint nodes called tail and head
|
wolffd@0
|
215 where the all outedges of the same node have it as the tail
|
wolffd@0
|
216 value and similarly all inedges have it as the head.
|
wolffd@0
|
217 In an undirected graph, head and tail are interchangable.
|
wolffd@0
|
218 If a graph has multi-edges between the same pair of nodes,
|
wolffd@0
|
219 the edge's string name behaves as a secondary key.
|
wolffd@0
|
220 .Pp
|
wolffd@0
|
221 \fBagedge\fP searches in a graph of subgraph for an
|
wolffd@0
|
222 edge between the given endpoints (with an optional
|
wolffd@0
|
223 multi-edge selector name) and returns it if found.
|
wolffd@0
|
224 Otherwise, if \fBcreateflag\fP is boolean true,
|
wolffd@0
|
225 a new edge is created and returned: otherwise
|
wolffd@0
|
226 a nil pointer is returned. If the \fBname\fP
|
wolffd@0
|
227 is NULL, then an anonymous internal
|
wolffd@0
|
228 value is generated. \fBagidedge\fP allows a programmer
|
wolffd@0
|
229 to create an edge by giving its unique 32-bit ID.
|
wolffd@0
|
230 \fBagfstin\fP, \fBagnxtint\fP, \fBagfstout\fP, and
|
wolffd@0
|
231 \fBagnxtout\fP visit directed in- and out- edge lists,
|
wolffd@0
|
232 and ordinarily apply only in directed graphs.
|
wolffd@0
|
233 \fBagfstedge\fP and \fBagnxtedge\fP visit all edges
|
wolffd@0
|
234 incident to a node. \fBagtail\fP and \fBaghead\fP
|
wolffd@0
|
235 get the endpoint of an edge.
|
wolffd@0
|
236 .SH "INTERNAL ATTRIBUTES"
|
wolffd@0
|
237 Programmer-defined values may be dynamically
|
wolffd@0
|
238 attached to graphs, subgraphs, nodes, and edges.
|
wolffd@0
|
239 Such values are either uninterpreted binary records
|
wolffd@0
|
240 (for implementing efficient algorithms)
|
wolffd@0
|
241 or character string data (for I/O).
|
wolffd@0
|
242 .SH "STRING ATTRIBUTES"
|
wolffd@0
|
243 String attributes are handled automatically in reading
|
wolffd@0
|
244 and writing graph files.
|
wolffd@0
|
245 A string attribute is identified by name and by
|
wolffd@0
|
246 an internal symbol table entry (\fBAgsym_t\fP) created by Libcgraph.
|
wolffd@0
|
247 Attributes of nodes, edges, and graphs (with their subgraphs)
|
wolffd@0
|
248 have separate namespaces. The contents of an \fBAgsym_t\fP
|
wolffd@0
|
249 is listed below, followed by primitives to operate on string
|
wolffd@0
|
250 attributes.
|
wolffd@0
|
251 .P0
|
wolffd@0
|
252 typedef struct Agsym_s { /* symbol in one of the above dictionaries */
|
wolffd@0
|
253 Dtlink_t link;
|
wolffd@0
|
254 char *name; /* attribute's name */
|
wolffd@0
|
255 char *defval; /* its default value for initialization */
|
wolffd@0
|
256 int id; /* its index in attr[] */
|
wolffd@0
|
257 unsigned char kind; /* referent object type */
|
wolffd@0
|
258 unsigned char fixed; /* immutable value */
|
wolffd@0
|
259 } Agsym_t;
|
wolffd@0
|
260 .P1
|
wolffd@0
|
261 .PP
|
wolffd@0
|
262 \fBagattr\fP creates or looks up attributes.
|
wolffd@0
|
263 \fBkind\fP may be \fBAGRAPH\fP, \fBAGNODE\fP, or \fBAGEDGE\fP.
|
wolffd@0
|
264 If \fBvalue\fP is \fB(char*)0)\fP, the request is to search
|
wolffd@0
|
265 for an existing attribute of the given kind and name.
|
wolffd@0
|
266 Otherwise, if the attribute already exists, its default
|
wolffd@0
|
267 for creating new objects is set to the given value;
|
wolffd@0
|
268 if it does not exist, a new attribute is created with the
|
wolffd@0
|
269 given default, and the default is applied to all pre-existing
|
wolffd@0
|
270 objects of the given kind. If \fBg\fP is NIL, the default is
|
wolffd@0
|
271 set for all graphs created subsequently.
|
wolffd@0
|
272 \fBagattrsym\fP is a helper function
|
wolffd@0
|
273 that looks up an attribute for a graph object given as an argument.
|
wolffd@0
|
274 \fBagnxtattr\fP permits traversing the list of attributes of
|
wolffd@0
|
275 a given type. If \fBNIL\fP is passed as an argument it gets
|
wolffd@0
|
276 the first attribute, otherwise it returns the next one in
|
wolffd@0
|
277 succession or returns \fBNIL\fP at the end of the list.
|
wolffd@0
|
278 \fBagget\fP and \fPagset\fP allow fetching and updating a
|
wolffd@0
|
279 string attribute for an object taking the attribute name as
|
wolffd@0
|
280 an argument. \fBagxget\fP and \fBagxset\fP do this but with
|
wolffd@0
|
281 an attribute symbol table entry as an argument (to avoid
|
wolffd@0
|
282 the cost of the string lookup). \fBagsafeset\fP is a
|
wolffd@0
|
283 convenience function that ensures the given attribute is
|
wolffd@0
|
284 declared before setting it locally on an object.
|
wolffd@0
|
285
|
wolffd@0
|
286 .SH "STRINGS"
|
wolffd@0
|
287 Libcgraph performs its own storage management of strings as
|
wolffd@0
|
288 reference-counted strings.
|
wolffd@0
|
289 The caller does not need to dynamically allocate storage.
|
wolffd@0
|
290 .PP
|
wolffd@0
|
291 \fBagstrdup\fP returns a pointer to a reference-counted copy of
|
wolffd@0
|
292 the argument string, creating one if necessary. \fBagstrbind\fP
|
wolffd@0
|
293 returns a pointer to a reference-counted string if it exists, or NULL if not.
|
wolffd@0
|
294 All uses of cgraph strings need to be freed using \fBagstrfree\fP
|
wolffd@0
|
295 in order to correctly maintain the reference count.
|
wolffd@0
|
296 .PP
|
wolffd@0
|
297 \fBagcanonStr\fP returns a pointer to a version of the input string
|
wolffd@0
|
298 canonicalized for output for later re-parsing. This includes quoting
|
wolffd@0
|
299 special characters and keywords. It uses its own internal buffer, so
|
wolffd@0
|
300 the value will be lost on the next call to \fBagcanonStr\fP.
|
wolffd@0
|
301 \fBagstrcanon\fP is an unsafe version of \fBagcanonStr\fP, in which
|
wolffd@0
|
302 the application passes in a buffer as the second argument. Note that
|
wolffd@0
|
303 the buffer may not be used; if the input string is in canonical form,
|
wolffd@0
|
304 the function will just return a pointer to it.
|
wolffd@0
|
305 .PP
|
wolffd@0
|
306 The cgraph parser handles HTML-like strings. These should be
|
wolffd@0
|
307 indistinguishable from other strings for most purposes. To create
|
wolffd@0
|
308 an HTML-like string, use \fBagstrdup_html\fP. The \fBaghtmlstr\fP
|
wolffd@0
|
309 function can be used to query if a string is an ordinary string or
|
wolffd@0
|
310 an HTML-like string.
|
wolffd@0
|
311 .SH "RECORDS"
|
wolffd@0
|
312 Uninterpreted records may be attached to graphs, subgraphs, nodes,
|
wolffd@0
|
313 and edges for efficient operations on values such as marks, weights,
|
wolffd@0
|
314 counts, and pointers needed by algorithms. Application programmers
|
wolffd@0
|
315 define the fields of these records, but they must be declared with
|
wolffd@0
|
316 a common header as shown below.
|
wolffd@0
|
317 .P0
|
wolffd@0
|
318 typedef struct Agrec_s {
|
wolffd@0
|
319 Agrec_t header;
|
wolffd@0
|
320 /* programmer-defined fields follow */
|
wolffd@0
|
321 } Agrec_t;
|
wolffd@0
|
322 .P1
|
wolffd@0
|
323 Records are created and managed by Libcgraph. A programmer must
|
wolffd@0
|
324 explicitly attach them to the objects in a graph, either to
|
wolffd@0
|
325 individual objects one at a time via \fBagbindrec\fP, or to
|
wolffd@0
|
326 all the objects of the same class in a graph via \fBaginit\fP.
|
wolffd@0
|
327 The \fBname\fP argument a record distinguishes various types of records,
|
wolffd@0
|
328 and is programmer defined (Libcgraph reserves the prefix \fB_ag\fR).
|
wolffd@0
|
329 If size is 0, the call to \fBagbindrec\fP is simply a lookup.
|
wolffd@0
|
330 \fBagdelrec\fP is the deletes records one at a time.
|
wolffd@0
|
331 \fBagclean\fP does the same for all objects of the same
|
wolffd@0
|
332 class in an entire graph.
|
wolffd@0
|
333
|
wolffd@0
|
334 Internally, records are maintained in circular linked lists
|
wolffd@0
|
335 attached to graph objects.
|
wolffd@0
|
336 To allow referencing application-dependent data without function
|
wolffd@0
|
337 calls or search, Libcgraph allows setting and locking the list
|
wolffd@0
|
338 pointer of a graph, node, or edge on a particular record.
|
wolffd@0
|
339 This pointer can be obtained with the macro \fBAGDATA(obj)\fP.
|
wolffd@0
|
340 A cast, generally within a macro or inline function,
|
wolffd@0
|
341 is usually applied to convert the list pointer to
|
wolffd@0
|
342 an appropriate programmer-defined type.
|
wolffd@0
|
343
|
wolffd@0
|
344 To control the setting of this pointer,
|
wolffd@0
|
345 the \fBmove_to_front\fP flag may be \fBAG_MTF_FALSE\fP,
|
wolffd@0
|
346 \fBAG_MTF_SOFT\fP, or \fBAG_MTF_HARD\fP accordingly.
|
wolffd@0
|
347 The \fBAG_MTF_SOFT\fP field is only a hint that decreases
|
wolffd@0
|
348 overhead in subsequent calls of \fBaggetrec\fP;
|
wolffd@0
|
349 \fBAG_MTF_HARD\fP guarantees that a lock was obtained.
|
wolffd@0
|
350 To release locks, use \fBAG_MTF_SOFT\fP or \fBAG_MTF_FALSE\fP.
|
wolffd@0
|
351 Use of this feature implies cooperation or at least isolation
|
wolffd@0
|
352 from other functions also using the move-to-front convention.
|
wolffd@0
|
353
|
wolffd@0
|
354 .SH "DISCIPLINES"
|
wolffd@0
|
355 (The following is not intended for casual users.)
|
wolffd@0
|
356 Programmer-defined disciplines customize certain resources-
|
wolffd@0
|
357 ID namespace, memory, and I/O - needed by Libcgraph.
|
wolffd@0
|
358 A discipline struct (or NIL) is passed at graph creation time.
|
wolffd@0
|
359 .P0
|
wolffd@0
|
360 struct Agdisc_s { /* user's discipline */
|
wolffd@0
|
361 Agmemdisc_t *mem;
|
wolffd@0
|
362 Agiddisc_t *id;
|
wolffd@0
|
363 Agiodisc_t *io;
|
wolffd@0
|
364 } ;
|
wolffd@0
|
365 .P1
|
wolffd@0
|
366 A default discipline is supplied when NIL is given for
|
wolffd@0
|
367 any of these fields.
|
wolffd@0
|
368
|
wolffd@0
|
369 An ID allocator discipline allows a client to control assignment
|
wolffd@0
|
370 of IDs (uninterpreted 32-bit values) to objects, and possibly how
|
wolffd@0
|
371 they are mapped to and from strings.
|
wolffd@0
|
372
|
wolffd@0
|
373 .P0
|
wolffd@0
|
374 struct Agiddisc_s { /* object ID allocator */
|
wolffd@0
|
375 void *(*open)(Agraph_t *g); /* associated with a graph */
|
wolffd@0
|
376 int (*map)(void *state, int objtype, char *str, ulong *id, int createflag);
|
wolffd@0
|
377 int (*alloc)(void *state, int objtype, ulong id);
|
wolffd@0
|
378 void (*free)(void *state, int objtype, ulong id);
|
wolffd@0
|
379 char *(*print)(void *state, int objtype, ulong id);
|
wolffd@0
|
380 void (*close)(void *state);
|
wolffd@0
|
381 } ;
|
wolffd@0
|
382 .P1
|
wolffd@0
|
383
|
wolffd@0
|
384 \f5open\fP permits the ID discipline to initialize any data
|
wolffd@0
|
385 structures that maintains per individual graph.
|
wolffd@0
|
386 Its return value is then passed as the first argument to
|
wolffd@0
|
387 all subsequent ID manager calls.
|
wolffd@0
|
388
|
wolffd@0
|
389 \f5alloc\fP informs the ID manager that Libcgraph is attempting
|
wolffd@0
|
390 to create an object with a specific ID that was given by a client.
|
wolffd@0
|
391 The ID manager should return TRUE (nonzero) if the ID can be
|
wolffd@0
|
392 allocated, or FALSE (which aborts the operation).
|
wolffd@0
|
393
|
wolffd@0
|
394 \f5free\fP is called to inform the ID manager that the
|
wolffd@0
|
395 object labeled with the given ID is about to go out of existence.
|
wolffd@0
|
396
|
wolffd@0
|
397 \f5map\fP is called to create or look-up IDs by string name
|
wolffd@0
|
398 (if supported by the ID manager). Returning TRUE (nonzero)
|
wolffd@0
|
399 in all cases means that the request succeeded (with a valid
|
wolffd@0
|
400 ID stored through \f5result\fP. There are four cases:
|
wolffd@0
|
401 .PP
|
wolffd@0
|
402 \f5name != NULL\fP and \f5createflag == 1\fP:
|
wolffd@0
|
403 This requests mapping a string (e.g. a name in a graph file) into a new ID.
|
wolffd@0
|
404 If the ID manager can comply, then it stores the result and returns TRUE.
|
wolffd@0
|
405 It is then also responsible for being able to \f5print\fP the ID again
|
wolffd@0
|
406 as a string. Otherwise the ID manager may return FALSE but it must
|
wolffd@0
|
407 implement the following (at least for graph file reading and writing to work):
|
wolffd@0
|
408 .PP
|
wolffd@0
|
409 \f5name == NULL\fP and \f5createflag == 1\fP:
|
wolffd@0
|
410 The ID manager creates a unique new ID of its own choosing.
|
wolffd@0
|
411 Although it may return FALSE if it does not support anonymous objects,
|
wolffd@0
|
412 but this is strongly discouraged (to support "local names" in graph files.)
|
wolffd@0
|
413 .PP
|
wolffd@0
|
414 \f5name != NULL\fP and \f5createflag == 0\fP:
|
wolffd@0
|
415 This is a namespace probe. If the name was previously mapped into
|
wolffd@0
|
416 an allocated ID by the ID manager, then the manager must return this ID.
|
wolffd@0
|
417 Otherwise, the ID manager may either return FALSE, or may store
|
wolffd@0
|
418 any unallocated ID into result. (This is convenient, for example,
|
wolffd@0
|
419 if names are known to be digit strings that are directly converted into 32 bit values.)
|
wolffd@0
|
420 .PP
|
wolffd@0
|
421 \f5name == NULL\fP and \f5createflag == 0\fP: forbidden.
|
wolffd@0
|
422 .PP
|
wolffd@0
|
423 \f5print\fP is allowed to return a pointer to a static buffer;
|
wolffd@0
|
424 a caller must copy its value if needed past subsequent calls.
|
wolffd@0
|
425 \f5NULL\fP should be returned by ID managers that do not map names.
|
wolffd@0
|
426 .PP
|
wolffd@0
|
427 The \f5map\fP and \f5alloc\fP calls do not pass a pointer to the
|
wolffd@0
|
428 newly allocated object. If a client needs to install object
|
wolffd@0
|
429 pointers in a handle table, it can obtain them via
|
wolffd@0
|
430 new object callbacks.
|
wolffd@0
|
431 .P0
|
wolffd@0
|
432 struct Agiodisc_s {
|
wolffd@0
|
433 int (*fread)(void *chan, char *buf, int bufsize);
|
wolffd@0
|
434 int (*putstr)(void *chan, char *str);
|
wolffd@0
|
435 int (*flush)(void *chan); /* sync */
|
wolffd@0
|
436 /* error messages? */
|
wolffd@0
|
437 } ;
|
wolffd@0
|
438
|
wolffd@0
|
439 struct Agmemdisc_s { /* memory allocator */
|
wolffd@0
|
440 void *(*open)(void); /* independent of other resources */
|
wolffd@0
|
441 void *(*alloc)(void *state, size_t req);
|
wolffd@0
|
442 void *(*resize)(void *state, void *ptr, size_t old, size_t req);
|
wolffd@0
|
443 void (*free)(void *state, void *ptr);
|
wolffd@0
|
444 void (*close)(void *state);
|
wolffd@0
|
445 } ;
|
wolffd@0
|
446 .P1
|
wolffd@0
|
447
|
wolffd@0
|
448 .SH "EXAMPLE PROGRAM"
|
wolffd@0
|
449 .P0
|
wolffd@0
|
450 #include <graphviz/cgraph.h>
|
wolffd@0
|
451 typedef struct mydata_s {Agrec_t hdr; int x,y,z;} mydata;
|
wolffd@0
|
452
|
wolffd@0
|
453 main(int argc, char **argv)
|
wolffd@0
|
454 {
|
wolffd@0
|
455 Agraph_t *g;
|
wolffd@0
|
456 Agnode_t *v;
|
wolffd@0
|
457 Agedge_t *e;
|
wolffd@0
|
458 Agsym_t *attr;
|
wolffd@0
|
459 Dict_t *d
|
wolffd@0
|
460 int cnt;
|
wolffd@0
|
461 mydata *p;
|
wolffd@0
|
462
|
wolffd@0
|
463 if (g = agread(stdin,NIL(Agdisc_t*))) {
|
wolffd@0
|
464 cnt = 0; attr = 0;
|
wolffd@0
|
465 while (attr = agnxtattr(g, AGNODE, attr)) cnt++;
|
wolffd@0
|
466 printf("The graph %s has %d attributes\n",agnameof(g),cnt);
|
wolffd@0
|
467
|
wolffd@0
|
468 /* make the graph have a node color attribute, default is blue */
|
wolffd@0
|
469 attr = agattr(g,AGNODE,"color","blue");
|
wolffd@0
|
470
|
wolffd@0
|
471 /* create a new graph of the same kind as g */
|
wolffd@0
|
472 h = agopen("tmp",g->desc);
|
wolffd@0
|
473
|
wolffd@0
|
474 /* this is a way of counting all the edges of the graph */
|
wolffd@0
|
475 cnt = 0;
|
wolffd@0
|
476 for (v = agfstnode(g); v; v = agnxtnode(g,v))
|
wolffd@0
|
477 for (e = agfstout(g,v); e; e = agnxtout(g,e))
|
wolffd@0
|
478 cnt++;
|
wolffd@0
|
479
|
wolffd@0
|
480 /* attach records to edges */
|
wolffd@0
|
481 for (v = agfstnode(g); v; v = agnxtnode(g,v))
|
wolffd@0
|
482 for (e = agfstout(g,v); e; e; = agnxtout(g,e)) {
|
wolffd@0
|
483 p = (mydata*) agbindrec(g,e,"mydata",sizeof(mydata),TRUE);
|
wolffd@0
|
484 p->x = 27; /* meaningless data access example */
|
wolffd@0
|
485 ((mydata*)(AGDATA(e)))->y = 999; /* another example */
|
wolffd@0
|
486 }
|
wolffd@0
|
487 }
|
wolffd@0
|
488 }
|
wolffd@0
|
489 .P1
|
wolffd@0
|
490 .SH "EXAMPLE GRAPH FILES"
|
wolffd@0
|
491 .P0
|
wolffd@0
|
492 digraph G {
|
wolffd@0
|
493 a -> b;
|
wolffd@0
|
494 c [shape=box];
|
wolffd@0
|
495 a -> c [weight=29,label="some text];
|
wolffd@0
|
496 subgraph anything {
|
wolffd@0
|
497 /* the following affects only x,y,z */
|
wolffd@0
|
498 node [shape=circle];
|
wolffd@0
|
499 a; x; y -> z; y -> z; /* multiple edges */
|
wolffd@0
|
500 }
|
wolffd@0
|
501 }
|
wolffd@0
|
502
|
wolffd@0
|
503 strict graph H {
|
wolffd@0
|
504 n0 -- n1 -- n2 -- n0; /* a cycle */
|
wolffd@0
|
505 n0 -- {a b c d}; /* a star */
|
wolffd@0
|
506 n0 -- n3;
|
wolffd@0
|
507 n0 -- n3 [weight=1]; /* same edge because graph is strict */
|
wolffd@0
|
508 }
|
wolffd@0
|
509 .P1
|
wolffd@0
|
510 .SH "SEE ALSO"
|
wolffd@0
|
511 Libcdt(3)
|
wolffd@0
|
512
|
wolffd@0
|
513 .SH "BUGS"
|
wolffd@0
|
514 It is difficult to change endpoints of edges, delete string attributes or
|
wolffd@0
|
515 modify edge keys. The work-around is to create a new object and copy the
|
wolffd@0
|
516 contents of an old one (but new object obviously has a different ID,
|
wolffd@0
|
517 internal address, and object creation timestamp).
|
wolffd@0
|
518
|
wolffd@0
|
519 The API lacks convenient functions to substitute programmer-defined ordering of
|
wolffd@0
|
520 nodes and edges but in principle this can be supported.
|
wolffd@0
|
521 .SH "AUTHOR"
|
wolffd@0
|
522 Stephen North, north@research.att.com, AT&T Research.
|