1LIBCGRAPH(3) Library Functions Manual LIBCGRAPH(3)
2
3
4
6 libcgraph - abstract graph library
7
9 #include <graphviz/cgraph.h>
10
11 TYPES
12 Agraph_t;
13 Agnode_t;
14 Agedge_t;
15 Agdesc_t;
16 Agdisc_t;
17 Agsym_t;
18 Agrec_t;
19 Agcbdisc_t;
20
21 GLOBALS
22 Agmemdisc_t AgMemDisc;
23 Agiddisc_t AgIdDisc;
24 Agiodisc_t AgIoDisc;
25 Agdisc_t AgDefaultDisc;
26
27 GRAPHS
28 Agraph_t *agopen(char *name, Agdesc_t kind, Agdisc_t *disc);
29 int agclose(Agraph_t *g);
30 Agraph_t *agread(void *channel, Agdisc_t *);
31 Agraph_t *agmemread(char *);
32 void agreadline(int line_no);
33 void agsetfile(char *file_name);
34 Agraph_t *agconcat(Agraph_t *g, void *channel, Agdisc_t *disc)
35 int agwrite(Agraph_t *g, void *channel);
36 int agnnodes(Agraph_t *g),agnedges(Agraph_t *g), agnsubg(Agraph_t * g);
37 int agisdirected(Agraph_t * g),agisundirected(Agraph_t * g),agisstrict(Agraph_t * g), agissimple(Agraph_t * g);
38
39 SUBGRAPHS
40 Agraph_t *agsubg(Agraph_t *g, char *name, int createflag);
41 Agraph_t *agidsubg(Agraph_t * g, unsigned long id, int cflag);
42 Agraph_t *agfstsubg(Agraph_t *g), agnxtsubg(Agraph_t *);
43 Agraph_t *agparent(Agraph_t *g);
44 int agdelsubg(Agraph_t * g, Agraph_t * sub); /* same as agclose() */
45
46 NODES
47 Agnode_t *agnode(Agraph_t *g, char *name, int createflag);
48 Agnode_t *agidnode(Agraph_t *g, ulong id, int createflag);
49 Agnode_t *agsubnode(Agraph_t *g, Agnode_t *n, int createflag);
50 Agnode_t *agfstnode(Agraph_t *g);
51 Agnode_t *agnxtnode(Agraph_t *g, Agnode_t *n);
52 Agnode_t *agprvnode(Agraph_t *g, Agnode_t *n);
53 Agnode_t *aglstnode(Agraph_t *g);
54 int agdelnode(Agraph_t *g, Agnode_t *n);
55 int agdegree(Agraph_t *g, Agnode_t *n, int use_inedges, int use_outedges);
56 int agcountuniqedges(Agraph_t * g, Agnode_t * n, int in, int out);
57
58 EDGES
59 Agedge_t *agedge(Agraph_t* g, Agnode_t *t, Agnode_t *h, char *name, int createflag);
60 Agedge_t *agidedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, unsigned long id, int createflag);
61 Agedge_t *agsubedge(Agraph_t *g, Agedge_t *e, int createflag);
62 Agnode_t *aghead(Agedge_t *e), *agtail(Agedge_t *e);
63 Agedge_t *agfstedge(Agraph_t* g, Agnode_t *n);
64 Agedge_t *agnxtedge(Agraph_t* g, Agedge_t *e, Agnode_t *n);
65 Agedge_t *agfstin(Agraph_t* g, Agnode_t *n);
66 Agedge_t *agnxtin(Agraph_t* g, Agedge_t *e);
67 Agedge_t *agfstout(Agraph_t* g, Agnode_t *n);
68 Agedge_t *agnxtout(Agraph_t* g, Agedge_t *e);
69 int agdeledge(Agraph_t *g, Agedge_t *e);
70 Agedge_t *agopp(Agedge_t *e);
71 int ageqedge(Agedge_t *e0, Agedge_t *e1);
72
73 STRING ATTRIBUTES
74 Agsym_t *agattr(Agraph_t *g, int kind, char *name, const char *value);
75 Agsym_t *agattrsym(void *obj, char *name);
76 Agsym_t *agnxtattr(Agraph_t *g, int kind, Agsym_t *attr);
77 char *agget(void *obj, char *name);
78 char *agxget(void *obj, Agsym_t *sym);
79 int agset(void *obj, char *name, char *value);
80 int agxset(void *obj, Agsym_t *sym, char *value);
81 int agsafeset(void *obj, char *name, char *value, char *def);
82 int agcopyattr(void *, void *);
83
84 RECORDS
85 void *agbindrec(void *obj, char *name, unsigned int size, move_to_front);
86 Agrec_t *aggetrec(void *obj, char *name, int move_to_front);
87 int agdelrec(Agraph_t *g, void *obj, char *name);
88 void aginit(Agraph_t * g, int kind, char *rec_name, int rec_size, int move_to_front);
89 void agclean(Agraph_t * g, int kind, char *rec_name);
90
91 CALLBACKS
92 int *agpopdisc(Agraph_t *g);
93 void agpushdisc(Agraph_t *g, Agcbdisc_t *disc);
94 int agcallbacks(Agraph_t * g, int flag);
95
96 MEMORY
97 void *agalloc(Agraph_t *g, size_t request);
98 void *agrealloc(Agraph_t *g, void *ptr, size_t oldsize, size_t newsize);
99 void agfree(Agraph_t *g, void *ptr);
100
101 STRINGS
102 char *agstrdup(Agraph_t *, char *);
103 char *agstrdup_html(Agraph_t *, char *);
104 int aghtmlstr(char *);
105 char *agstrbind(Agraph_t * g, char *);
106 int strfree(Agraph_t *, char *);
107 char *agcanonStr(char *);
108 char *agstrcanon(char *, char *);
109 char *agcanon(char *, int);
110
111 GENERIC OBJECTS
112 Agraph_t *agraphof(void*);
113 Agraph_t *agroot(void*);
114 int agcontains(Agraph_t*, void*);
115 char *agnameof(void*);
116 void agdelete(Agraph_t *g, void *obj);
117 int agobjkind(void *obj);
118 Agrec_t *AGDATA(void *obj);
119 ulong AGID(void *obj);
120 int AGTYPE(void *obj);
121
122 ERROR REPORTING
123 typedef enum { AGWARN, AGERR, AGMAX, AGPREV } agerrlevel_t;
124 typedef int (*agusererrf) (char*);
125 agerrlevel_t agerrno;
126 agerrlevel_t agseterr(agerrlevel_t);
127 char *aglasterr(void);
128 int agerr(agerrlevel_t level, char *fmt, ...);
129 void agerrorf(char *fmt, ...);
130 void agwarningf(char *fmt, ...);
131 int agerrors(void);
132 agusererrf agseterrf(agusererrf);
133
135 Libcgraph supports graph programming by maintaining graphs in memory
136 and reading and writing graph files. Graphs are composed of nodes,
137 edges, and nested subgraphs. These graph objects may be attributed
138 with string name-value pairs and programmer-defined records (see At‐
139 tributes).
140
141 All of Libcgraph's global symbols have the prefix ag (case varying).
142 In the following, if a function has a parameter int createflag and the
143 object does not exist, the function will create the specified object if
144 createflag is non-zero; otherwise, it will return NULL.
145
147 A ``main'' or ``root'' graph defines a namespace for a collection of
148 graph objects (subgraphs, nodes, edges) and their attributes. Objects
149 may be named by unique strings or by integer IDs.
150
151 agopen creates a new graph with the given name and kind. (Graph kinds
152 are Agdirected, Agundirected, Agstrictdirected, and Agstrictundirected.
153 A strict graph cannot have multi-edges or self-arcs.) The final argu‐
154 ment points to a discpline structure which can be used to tailor I/O,
155 memory allocation, and ID allocation. Typically, a NULL value will be
156 used to indicate the default discipline AgDefaultDisc. agclose deletes
157 a graph, freeing its associated storage. agread, agwrite, and agconcat
158 perform file I/O using the graph file language described below. agread
159 constructs a new graph while agconcat merges the file contents with a
160 pre-existing graph. Though I/O methods may be overridden, the default
161 is that the channel argument is a stdio FILE pointer. In that case, if
162 any of the streams are wide-oriented, the behavior is undefined. ag‐
163 memread attempts to read a graph from the input string. agsetfile and
164 agreadline are helper functions that simply set the current file name
165 and input line number for subsequent error reporting.
166
167 The functions agisdirected, agisundirected, agisstrict, and agissimple
168 can be used to query if a graph is directed, undirected, strict (at
169 most one edge with a given tail and head), or simple (strict with no
170 loops), respectively,
171
172 agsubg finds or creates a subgraph by name. agidsubg allows a program‐
173 mer to specify the subgraph by a unique integer ID. A new subgraph is
174 initially empty and is of the same kind as its parent. Nested subgraph
175 trees may be created. A subgraph's name is only interpreted relative
176 to its parent. A program can scan subgraphs under a given graph using
177 agfstsubg and agnxtsubg. A subgraph is deleted with agdelsubg (or ag‐
178 close). The agparent function returns the immediate parent graph of a
179 subgraph, or itself if the graph is already a root graph.
180
181 By default, nodes are stored in ordered sets for efficient random ac‐
182 cess to insert, find, and delete nodes. The edges of a node are also
183 stored in ordered sets. The sets are maintained internally as splay
184 tree dictionaries using Phong Vo's cdt library.
185
186 agnnodes, agnedges, and agnsubg return the sizes of node, edge and sub‐
187 graph sets of a graph. The function agdegree returns the size of the
188 edge set of a nodes, and takes flags to select in-edges, out-edges, or
189 both. The function agcountuniqedges returns the size of the edge set
190 of a nodes, and takes flags to select in-edges, out-edges, or both. Un‐
191 like agdegree, each loop is only counted once.
192
194 A node is created by giving a unique string name or programmer defined
195 integer ID, and is represented by a unique internal object. (Node
196 equality can checked by pointer comparison.)
197
198 agnode searches in a graph or subgraph for a node with the given name,
199 and returns it if found. agidnode allows a programmer to specify the
200 node by a unique integer ID. agsubnode performs a similar operation on
201 an existing node and a subgraph.
202
203 agfstnode and agnxtnode scan node lists. agprvnode and aglstnode are
204 symmetric but scan backward. The default sequence is order of creation
205 (object timestamp.) agdelnode removes a node from a graph or subgraph.
206
208 An abstract edge has two endpoint nodes called tail and head where all
209 outedges of the same node have it as the tail value and similarly all
210 inedges have it as the head. In an undirected graph, head and tail are
211 interchangeable. If a graph has multi-edges between the same pair of
212 nodes, the edge's string name behaves as a secondary key.
213
214 agedge searches in a graph or subgraph for an edge between the given
215 endpoints (with an optional multi-edge selector name) and returns it if
216 found or created. Note that, in undirected graphs, a search tries both
217 orderings of the tail and head nodes. If the name is NULL, then an
218 anonymous internal value is generated. agidedge allows a programmer to
219 create an edge by giving its unique integer ID. agsubedge performs a
220 similar operation on an existing edge and a subgraph. agfstin, agnx‐
221 tin, agfstout, and agnxtout visit directed in- and out- edge lists, and
222 ordinarily apply only in directed graphs. agfstedge and agnxtedge
223 visit all edges incident to a node. agtail and aghead get the endpoint
224 of an edge. agdeledge removes an edge from a graph or subgraph.
225
226 Note that an abstract edge has two distinct concrete representations:
227 as an in-edge and as an out-edge. In particular, the pointer as an out-
228 edge is different from the pointer as an in-edge. The function ageqedge
229 canonicalizes the pointers before doing a comparison and so can be used
230 to test edge equality. The sense of an edge can be flipped using agopp.
231
233 Programmer-defined values may be dynamically attached to graphs, sub‐
234 graphs, nodes, and edges. Such values are either character string data
235 (for I/O) or uninterpreted binary records (for implementing algorithms
236 efficiently).
237
239 String attributes are handled automatically in reading and writing
240 graph files. A string attribute is identified by name and by an inter‐
241 nal symbol table entry (Agsym_t) created by Libcgraph. Attributes of
242 nodes, edges, and graphs (with their subgraphs) have separate name‐
243 spaces. The contents of an Agsym_t have a char* name for the attri‐
244 bute's name, a char* defval field for the attribute's default value,
245 and an int id field containing the index of the attribute's specific
246 value for an object in the object's array of attribute values.
247
248 agattr creates or looks up attributes. kind may be AGRAPH, AGNODE, or
249 AGEDGE. If value is (char*)0), the request is to search for an exist‐
250 ing attribute of the given kind and name. Otherwise, if the attribute
251 already exists, its default for creating new objects is set to the
252 given value; if it does not exist, a new attribute is created with the
253 given default, and the default is applied to all pre-existing objects
254 of the given kind. If g is NULL, the default is set for all graphs cre‐
255 ated subsequently. agattrsym is a helper function that looks up an at‐
256 tribute for a graph object given as an argument. agnxtattr permits
257 traversing the list of attributes of a given type. If NULL is passed
258 as an argument it gets the first attribute; otherwise it returns the
259 next one in succession or returns NULL at the end of the list. agget
260 and agset allow fetching and updating a string attribute for an object
261 taking the attribute name as an argument. agxget and agxset do this
262 but with an attribute symbol table entry as an argument (to avoid the
263 cost of the string lookup). Note that agset will fail unless the at‐
264 tribute is first defined using agattr. agsafeset is a convenience
265 function that ensures the given attribute is declared before setting it
266 locally on an object.
267
268 It is sometimes convenient to copy all of the attributes from one ob‐
269 ject to another. This can be done using agcopyattr. This fails and re‐
270 turns non-zero of argument objects are different kinds, or if all of
271 the attributes of the source object have not been declared for the tar‐
272 get object.
273
275 Libcgraph performs its own storage management of strings as reference-
276 counted strings. The caller does not need to dynamically allocate
277 storage.
278
279 agstrdup returns a pointer to a reference-counted copy of the argument
280 string, creating one if necessary. agstrbind returns a pointer to a
281 reference-counted string if it exists, or NULL if not. All uses of
282 cgraph strings need to be freed using agstrfree in order to correctly
283 maintain the reference count.
284
285 The cgraph parser handles HTML-like strings. These should be indistin‐
286 guishable from other strings for most purposes. To create an HTML-like
287 string, use agstrdup_html. The aghtmlstr function can be used to query
288 if a string is an ordinary string or an HTML-like string.
289
290 agcanonStr returns a pointer to a version of the input string canoni‐
291 calized for output for later re-parsing. This includes quoting special
292 characters and keywords. It uses its own internal buffer, so the value
293 will be lost on the next call to agcanonStr. agstrcanon is an unsafe
294 version of agcanonStr, in which the application passes in a buffer as
295 the second argument. Note that the buffer may not be used; if the input
296 string is in canonical form, the function will just return a pointer to
297 it. For both of the functions, the input string must have been created
298 using agstrdup or agstrdup_html. Finally, agcanonStr is identical with
299 agcanonStr except it can be used with any character string. The second
300 argument indicates whether or not the string should be canonicalized as
301 an HTML-like string.
302
304 Uninterpreted records may be attached to graphs, subgraphs, nodes, and
305 edges for efficient operations on values such as marks, weights,
306 counts, and pointers needed by algorithms. Application programmers de‐
307 fine the fields of these records, but they must be declared with a com‐
308 mon header as shown below.
309
310 typedef struct {
311 Agrec_t header;
312 /* programmer-defined fields follow */
313 } user_data_t;
314
315 Records are created and managed by Libcgraph. A programmer must explic‐
316 itly attach them to the objects in a graph, either to individual ob‐
317 jects one at a time via agbindrec, or to all the objects of the same
318 class in a graph via aginit. (Note that for graphs, aginit is applied
319 recursively to the graph and its subgraphs if rec_size is negative (of
320 the actual rec_size.)) The name argument of a record distinguishes
321 various types of records, and is programmer defined (Libcgraph reserves
322 the prefix _ag). If size is 0, the call to agbindrec is simply a
323 lookup. The function aggetrec can also be used for lookup. agdelrec
324 deletes a named record from one object. agclean does the same for all
325 objects of the same class in an entire graph.
326
327 Internally, records are maintained in circular linked lists attached to
328 graph objects. To allow referencing application-dependent data without
329 function calls or search, Libcgraph allows setting and locking the list
330 pointer of a graph, node, or edge on a particular record. This pointer
331 can be obtained with the macro AGDATA(obj). A cast, generally within a
332 macro or inline function, is usually applied to convert the list
333 pointer to an appropriate programmer-defined type.
334
335 To control the setting of this pointer, the move_to_front flag may be
336 TRUE or FALSE. If move_to_front is TRUE, the record will be locked at
337 the head of the list, so it can be accessed directly by AGDATA(obj).
338 The lock can be subsequently released or reset by a call to aggetrec.
339
340
342 (This section is not intended for casual users.) Programmer-defined
343 disciplines customize certain resources- ID namespace, memory, and I/O
344 - needed by Libcgraph. A discipline struct (or NULL) is passed at
345 graph creation time.
346
347 struct Agdisc_s { /* user's discipline */
348 Agmemdisc_t *mem;
349 Agiddisc_t *id;
350 Agiodisc_t *io;
351 } ;
352
353 A default discipline is supplied when NULL is given for any of these
354 fields.
355
356
358 An ID allocator discipline allows a client to control assignment of IDs
359 (uninterpreted integer values) to objects, and possibly how they are
360 mapped to and from strings.
361
362 struct Agiddisc_s { /* object ID allocator */
363 void *(*open) (Agraph_t * g, Agdisc_t*); /* associated with a graph */
364 long (*map) (void *state, int objtype, char *str, unsigned long *id, int createflag);
365 long (*alloc) (void *state, int objtype, unsigned long id);
366 void (*free) (void *state, int objtype, unsigned long id);
367 char *(*print) (void *state, int objtype, unsigned long id);
368 void (*close) (void *state);
369 };
370
371 open permits the ID discipline to initialize any data structures that
372 it maintains per individual graph. Its return value is then passed as
373 the first argument (void *state) to all subsequent ID manager calls.
374
375 alloc informs the ID manager that Libcgraph is attempting to create an
376 object with a specific ID that was given by a client. The ID manager
377 should return TRUE (nonzero) if the ID can be allocated, or FALSE
378 (which aborts the operation).
379
380 free is called to inform the ID manager that the object labeled with
381 the given ID is about to go out of existence.
382
383 map is called to create or look-up IDs by string name (if supported by
384 the ID manager). Returning TRUE (nonzero) in all cases means that the
385 request succeeded (with a valid ID stored through result. There are
386 four cases:
387
388 name != NULL and createflag == 1: This requests mapping a string (e.g.
389 a name in a graph file) into a new ID. If the ID manager can comply,
390 then it stores the result and returns TRUE. It is then also responsi‐
391 ble for being able to print the ID again as a string. Otherwise the ID
392 manager may return FALSE but it must implement the following (at least
393 for graph file reading and writing to work):
394
395 name == NULL and createflag == 1: The ID manager creates a unique new
396 ID of its own choosing. Although it may return FALSE if it does not
397 support anonymous objects, but this is strongly discouraged (to support
398 "local names" in graph files.)
399
400 name != NULL and createflag == 0: This is a namespace probe. If the
401 name was previously mapped into an allocated ID by the ID manager, then
402 the manager must return this ID. Otherwise, the ID manager may either
403 return FALSE, or may store any unallocated ID into result. (This is
404 convenient, for example, if names are known to be digit strings that
405 are directly converted into integer values.)
406
407 name == NULL and createflag == 0: forbidden.
408
409 print is allowed to return a pointer to a static buffer; a caller must
410 copy its value if needed past subsequent calls. NULL should be re‐
411 turned by ID managers that do not map names.
412
413 The map and alloc calls do not pass a pointer to the newly allocated
414 object. If a client needs to install object pointers in a handle ta‐
415 ble, it can obtain them via new object callbacks.
416
418 The I/O discipline provides an abstraction for the reading and writing
419 of graphs.
420 struct Agiodisc_s {
421 int (*fread)(void *chan, char *buf, int bufsize);
422 int (*putstr)(void *chan, char *str);
423 int (*flush)(void *chan); /* sync */
424 } ;
425 Normally, the FILE structure and its related functions are used for
426 I/O. At times, though, an application may need to use a totally differ‐
427 ent type of character source. The associated state or stream informa‐
428 tion is provided by the chan argument to agread or agwrite. The disci‐
429 pline function fread and putstr provide the corresponding functions for
430 read and writing.
431
432
434 Memory management in Libcgraph is handled on a per graph basis using
435 the memory discipline.
436 struct Agmemdisc_s { /* memory allocator */
437 void *(*open)(Agdisc_t*); /* independent of other resources */
438 void *(*alloc)(void *state, size_t req);
439 void *(*resize)(void *state, void *ptr, size_t old, size_t req);
440 void (*free)(void *state, void *ptr);
441 void (*close)(void *state);
442 } ;
443 The open function is used to initialize the memory subsystem, returning
444 state information that is passed to the calls to alloc, resize, and
445 free. The semantics of these should be comparable to the standard C
446 library functions malloc, realloc, and free, except that new space cre‐
447 ated by agalloc and agrealloc should be zeroed out. The close function
448 is used to terminate the memory subsystem, freeing any additional open
449 resources. For actual allocation, the library uses the functions agal‐
450 loc, agrealloc, and agfree, which provide simple wrappers for the un‐
451 derlying discipline functions alloc, resize, and free.
452
453 When Libcgraph is compiled with Vmalloc (which is not the default),
454 each graph has its own heap. Programmers may allocate application-de‐
455 pendent data within the same heap as the rest of the graph. The advan‐
456 tage is that a graph can be deleted by atomically freeing its entire
457 heap without scanning each individual node and edge.
458
459
461 An Agcbdisc_t defines callbacks to be invoked by Libcgraph when ini‐
462 tializing, modifying, or finalizing graph objects. Disciplines are
463 kept on a stack. Libcgraph automatically calls the methods on the
464 stack, top-down. Callbacks are installed with agpushdisc, uninstalled
465 with agpopdisc, and can be held pending or released via agcallbacks.
466
468 agroot takes any graph object (graph, subgraph, node, edge) and returns
469 the root graph in which it lives. agraphof does the same, except it is
470 the identity function on graphs and subgraphs. Note that there is no
471 function to return the least subgraph containing an object, in part be‐
472 cause this is not well-defined as nodes and edges may be in incompara‐
473 ble subgraphs.
474
475 agcontains(g,obj) returns non-zero if obj is a member of (sub)graph g.
476 agdelete(g,obj) is equivalent to agclose, agdelnode, and agdeledge for
477 obj being a graph, node or edge, respectively. It returns -1 if obj
478 does not belong to g.
479
480 AGDATA, AGID, and AGTYPE are macros returning the specified fields of
481 the argument object. The first is described in the RECORDS section
482 above. The second returns the unique integer ID associated with the ob‐
483 ject. The last returns AGRAPH, AGNODE, and AGEDGE depending on the type
484 of the object.
485
486 agnameof returns a string descriptor for the object. It returns the
487 name of the node or graph, and the key of an edge. agobjkind is a syn‐
488 onym for AGTYPE.
489
490
492 The library provides a variety of mechanisms to control the reporting
493 of errors and warnings. At present, there are basically two types of
494 messages: warnings and errors. A message is only written if its type
495 has higher priority than a programmer-controlled minimum, which is AG‐
496 WARN by default. The programmer can set this value using agseterr,
497 which returns the previous value. Calling agseterr(AGMAX) turns off the
498 writing of messages.
499
500 The function agerr if the main entry point for reporting an anomaly.
501 The first argument indicates the type of message. Usually, the first
502 argument in AGWARN or AGERR to indicate warnings and errors, respec‐
503 tively. Sometimes additional context information is only available in
504 functions calling the function where the error is actually caught. In
505 this case, the calling function can indicate that it is continuing the
506 current error by using AGPREV as the first argument. The remaining ar‐
507 guments to agerr are the same as the arguments to printf.
508
509 The functions agwarningf and agerrorf are shorthand for
510 agerr(AGERR,...) and agerr(AGWARN,...), respectively.
511
512 Some applications desire to directly control the writing of messages.
513 Such an application can use the function agseterrf to register the
514 function that the library should call to actually write the message.
515 The previous error function is returned. By default, the message is
516 written to stderr.
517
518 Errors not written are stored in a log file. The last recorded error
519 can be retreived by calling aglasterr. Unless the printing of error
520 messages has been completely disabled by a call to agseterr(AGMAX),
521 standard error must not be wide-oriented, even if a user-provided error
522 printing function is provided.
523
524 The function agerrors returns non-zero if errors have been reported.
525
527 #include <stdio.h>
528 #include <cgraph.h>
529
530 typedef struct {Agrec_t hdr; int x,y,z;} mydata;
531
532 void main(int argc, char **argv)
533 {
534 Agraph_t *g, *h;
535 Agnode_t *v;
536 Agedge_t *e;
537 Agsym_t *attr;
538 Dict_t *d;
539 int cnt;
540 mydata *p;
541
542 if (g = agread(stdin,NIL(Agdisc_t*))) {
543 cnt = 0; attr = 0;
544 while (attr = agnxtattr(g, AGNODE, attr)) cnt++;
545 printf("The graph %s has %d attributes\n",agnameof(g),cnt);
546
547 /* make the graph have a node color attribute, default is blue */
548 attr = agattr(g,AGNODE,"color","blue");
549
550 /* create a new graph of the same kind as g */
551 h = agopen("tmp",g->desc, NULL);
552
553 /* this is a way of counting all the edges of the graph */
554 cnt = 0;
555 for (v = agfstnode(g); v; v = agnxtnode(g,v))
556 for (e = agfstout(g,v); e; e = agnxtout(g,e))
557 cnt++;
558
559 /* attach records to edges */
560 for (v = agfstnode(g); v; v = agnxtnode(g,v))
561 for (e = agfstout(g,v); e; e = agnxtout(g,e)) {
562 p = (mydata*) agbindrec(e,"mydata",sizeof(mydata),TRUE);
563 p->x = 27; /* meaningless data access example */
564 ((mydata*)(AGDATA(e)))->y = 999; /* another example */
565 }
566 }
567 }
568
569
571 digraph G {
572 a -> b;
573 c [shape=box];
574 a -> c [weight=29,label="some text"];
575 subgraph anything {
576 /* the following affects only x,y,z */
577 node [shape=circle];
578 a; x; y -> z; y -> z; /* multiple edges */
579 }
580 }
581
582 strict graph H {
583 n0 -- n1 -- n2 -- n0; /* a cycle */
584 n0 -- {a b c d}; /* a star */
585 n0 -- n3;
586 n0 -- n3 [weight=1]; /* same edge because graph is strict */
587 }
588
590 Libcdt(3)
591
592
594 It is difficult to change endpoints of edges, delete string attributes
595 or modify edge keys. The work-around is to create a new object and
596 copy the contents of an old one (but new object obviously has a differ‐
597 ent ID, internal address, and object creation timestamp).
598
599 The API lacks convenient functions to substitute programmer-defined or‐
600 dering of nodes and edges but in principle this can be supported.
601
602 The library is not thread safe.
603
605 Stephen North, north@research.att.com, AT&T Research.
606
607
608
609 28 FEBRUARY 2013 LIBCGRAPH(3)