Provided by: libgraphviz-dev_2.40.1-2_amd64 bug

NAME

       libcgraph - abstract graph library

SYNOPSIS

       #include <graphviz/cgraph.h>

   TYPES
       Agraph_t;
       Agnode_t;
       Agedge_t;
       Agdesc_t;
       Agdisc_t;
       Agsym_t;
       Agrec_t;
       Agcbdisc_t;

   GLOBALS
       Agmemdisc_t AgMemDisc;
       Agiddisc_t  AgIdDisc;
       Agiodisc_t  AgIoDisc;
       Agdisc_t    AgDefaultDisc;

   GRAPHS
       Agraph_t  *agopen(char *name, Agdesc_t kind, Agdisc_t *disc);
       int       agclose(Agraph_t *g);
       Agraph_t  *agread(void *channel, Agdisc_t *);
       Agraph_t  *agmemread(char *);
       void      agreadline(int line_no);
       void      agsetfile(char *file_name);
       Agraph_t  *agconcat(Agraph_t *g, void *channel, Agdisc_t *disc)
       int       agwrite(Agraph_t *g, void *channel);
       int       agnnodes(Agraph_t *g),agnedges(Agraph_t *g), agnsubg(Agraph_t * g);
       int       agisdirected(Agraph_t * g),agisundirected(Agraph_t * g),agisstrict(Agraph_t * g), agissimple(Agraph_t * g);

   SUBGRAPHS
       Agraph_t  *agsubg(Agraph_t *g, char *name, int createflag);
       Agraph_t  *agidsubg(Agraph_t * g, unsigned long id, int cflag);
       Agraph_t  *agfstsubg(Agraph_t *g), agnxtsubg(Agraph_t *);
       Agraph_t  *agparent(Agraph_t *g);
       int       agdelsubg(Agraph_t * g, Agraph_t * sub);    /* same as agclose() */

   NODES
       Agnode_t  *agnode(Agraph_t *g, char *name, int createflag);
       Agnode_t  *agidnode(Agraph_t *g, ulong id, int createflag);
       Agnode_t  *agsubnode(Agraph_t *g, Agnode_t *n, int createflag);
       Agnode_t  *agfstnode(Agraph_t *g);
       Agnode_t  *agnxtnode(Agraph_t *g, Agnode_t *n);
       Agnode_t  *agprvnode(Agraph_t *g, Agnode_t *n);
       Agnode_t  *aglstnode(Agraph_t *g);
       int       agdelnode(Agraph_t *g, Agnode_t *n);
       int       agdegree(Agraph_t *g, Agnode_t *n, int use_inedges, int use_outedges);
       int       agcountuniqedges(Agraph_t * g, Agnode_t * n, int in, int out);

   EDGES
       Agedge_t  *agedge(Agraph_t* g, Agnode_t *t, Agnode_t *h, char *name, int createflag);
       Agedge_t  *agidedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, unsigned long id, int createflag);
       Agedge_t  *agsubedge(Agraph_t *g, Agedge_t *e, int createflag);
       Agnode_t  *aghead(Agedge_t *e), *agtail(Agedge_t *e);
       Agedge_t  *agfstedge(Agraph_t* g, Agnode_t *n);
       Agedge_t  *agnxtedge(Agraph_t* g, Agedge_t *e, Agnode_t *n);
       Agedge_t  *agfstin(Agraph_t* g, Agnode_t *n);
       Agedge_t  *agnxtin(Agraph_t* g, Agedge_t *e);
       Agedge_t  *agfstout(Agraph_t* g, Agnode_t *n);
       Agedge_t  *agnxtout(Agraph_t* g, Agedge_t *e);
       int       agdeledge(Agraph_t *g, Agedge_t *e);
       Agedge_t  *agopp(Agedge_t *e);
       int       ageqedge(Agedge_t *e0, Agedge_t *e1);

   STRING ATTRIBUTES
       Agsym_t   *agattr(Agraph_t *g, int kind, char *name, char *value);
       Agsym_t   *agattrsym(void *obj, char *name);
       Agsym_t   *agnxtattr(Agraph_t *g, int kind, Agsym_t *attr);
       char      *agget(void *obj, char *name);
       char      *agxget(void *obj, Agsym_t *sym);
       int       agset(void *obj, char *name, char *value);
       int       agxset(void *obj, Agsym_t *sym, char *value);
       int       agsafeset(void *obj, char *name, char *value, char *def);
       int       agcopyattr(void *, void *);

   RECORDS
       void      *agbindrec(void *obj, char *name, unsigned int size, move_to_front);
       Agrec_t        *aggetrec(void *obj, char *name, int move_to_front);
       int       agdelrec(Agraph_t *g, void *obj, char *name);
       void      aginit(Agraph_t * g, int kind, char *rec_name, int rec_size, int move_to_front);
       void      agclean(Agraph_t * g, int kind, char *rec_name);

   CALLBACKS
       int            *agpopdisc(Agraph_t *g);
       void      agpushdisc(Agraph_t *g, Agcbdisc_t *disc);
       int            agcallbacks(Agraph_t * g, int flag);

   MEMORY
       void      *agalloc(Agraph_t *g, size_t request);
       void      *agrealloc(Agraph_t *g, void *ptr, size_t oldsize, size_t newsize);
       void      agfree(Agraph_t *g, void *ptr);

   STRINGS
       char      *agstrdup(Agraph_t *, char *);
       char      *agstrdup_html(Agraph_t *, char *);
       int       aghtmlstr(char *);
       char      *agstrbind(Agraph_t * g, char *);
       int       strfree(Agraph_t *, char *);
       char      *agcanonStr(char *);
       char      *agstrcanon(char *, char *);
       char      *agcanon(char *, int);

   GENERIC OBJECTS
       Agraph_t  *agraphof(void*);
       Agraph_t  *agroot(void*);
       int       agcontains(Agraph_t*, void*);
       char      *agnameof(void*);
       void      agdelete(Agraph_t *g, void *obj);
       int       agobjkind(void *obj);
       Agrec_t        *AGDATA(void *obj);
       ulong          AGID(void *obj);
       int       AGTYPE(void *obj);

   ERROR REPORTING
       typedef enum { AGWARN, AGERR, AGMAX, AGPREV } agerrlevel_t;
       typedef int (*agusererrf) (char*);
       agerrlevel_t   agerrno;
       agerrlevel_t   agseterr(agerrlevel_t);
       char      *aglasterr(void);
       int       agerr(agerrlevel_t level, char *fmt, ...);
       void      agerrorf(char *fmt, ...);
       void      agwarningf(char *fmt, ...);
       int       agerrors(void);
       agusererrf     agseterrf(agusererrf);

DESCRIPTION

       Libcgraph supports graph programming by maintaining graphs in memory and reading and writing graph files.
       Graphs are composed of nodes, edges, and nested subgraphs.  These graph objects may  be  attributed  with
       string name-value pairs and programmer-defined records (see Attributes).

       All of Libcgraph's global symbols have the prefix ag (case varying).  In the following, if a function has
       a parameter int createflag and the object does not exist, the function will create the  specified  object
       if createflag is non-zero; otherwise, it will return NULL.

GRAPH AND SUBGRAPHS

       A  ``main''  or  ``root''  graph defines a namespace for a collection of graph objects (subgraphs, nodes,
       edges) and their attributes.  Objects may be named by unique strings or by integer IDs.

       agopen creates a new graph with the given name and kind.   (Graph  kinds  are  Agdirected,  Agundirected,
       Agstrictdirected,  and  Agstrictundirected.   A  strict graph cannot have multi-edges or self-arcs.)  The
       final argument points to a discpline structure which can be used to tailor I/O, memory allocation, and ID
       allocation.  Typically,  a  NULL  value  will  be  used to indicate the default discipline AgDefaultDisc.
       agclose deletes a graph, freeing its associated storage.  agread, agwrite, and agconcat perform file  I/O
       using  the  graph  file language described below. agread constructs a new graph while agconcat merges the
       file contents with a pre-existing graph.  Though I/O methods may be overridden, the default is  that  the
       channel  argument  is  a  stdio  FILE pointer.  agmemread attempts to read a graph from the input string.
       agsetfile and agreadline are helper functions that simply set the current file name and input line number
       for subsequent error reporting.

       The functions agisdirected, agisundirected, agisstrict, and agissimple can be used to query if a graph is
       directed, undirected, strict (at most one edge with a given tail and head), or  simple  (strict  with  no
       loops), respectively,

       agsubg  finds  or  creates a subgraph by name.  agidsubg allows a programmer to specify the subgraph by a
       unique integer ID.  A new subgraph is initially empty and is of the same  kind  as  its  parent.   Nested
       subgraph  trees may be created.  A subgraph's name is only interpreted relative to its parent.  A program
       can scan subgraphs under a given graph using  agfstsubg  and  agnxtsubg.   A  subgraph  is  deleted  with
       agdelsubg  (or  agclose).   The  agparent  function  returns the immediate parent graph of a subgraph, or
       itself if the graph is already a root graph.

       By default, nodes are stored in ordered sets for efficient random access  to  insert,  find,  and  delete
       nodes.  The edges of a node are also stored in ordered sets.  The sets are maintained internally as splay
       tree dictionaries using Phong Vo's cdt library.

       agnnodes, agnedges, and agnsubg return the sizes of node,  edge  and  subgraph  sets  of  a  graph.   The
       function  agdegree  returns the size of the edge set of a nodes, and takes flags to select in-edges, out-
       edges, or both.  The function agcountuniqedges returns the size of the edge set of  a  nodes,  and  takes
       flags to select in-edges, out-edges, or both. Unlike agdegree, each loop is only counted once.

NODES

       A  node is created by giving a unique string name or programmer defined integer ID, and is represented by
       a unique internal object. (Node equality can checked by pointer comparison.)

       agnode searches in a graph or subgraph for a node with the given name, and returns it if found.  agidnode
       allows  a  programmer to specify the node by a unique integer ID.  agsubnode performs a similar operation
       on an existing node and a subgraph.

       agfstnode and agnxtnode scan node lists.  agprvnode and aglstnode are symmetric but scan  backward.   The
       default  sequence  is  order  of  creation  (object timestamp.)  agdelnode removes a node from a graph or
       subgraph.

EDGES

       An abstract edge has two endpoint nodes called tail and head where all outedges of the same node have  it
       as  the  tail value and similarly all inedges have it as the head.  In an undirected graph, head and tail
       are interchangeable.  If a graph has multi-edges between the same pair of nodes, the edge's  string  name
       behaves as a secondary key.

       agedge  searches  in a graph or subgraph for an edge between the given endpoints (with an optional multi-
       edge selector name) and returns it if found or created.  Note that, in undirected graphs, a search  tries
       both  orderings  of  the  tail  and head nodes.  If the name is NULL, then an anonymous internal value is
       generated. agidedge allows a programmer to create an edge by giving its  unique  integer  ID.   agsubedge
       performs  a  similar  operation  on  an  existing  edge  and a subgraph.  agfstin, agnxtin, agfstout, and
       agnxtout visit directed in- and out- edge lists, and ordinarily apply only in directed graphs.  agfstedge
       and  agnxtedge  visit  all  edges  incident  to  a  node.  agtail and aghead get the endpoint of an edge.
       agdeledge removes an edge from a graph or subgraph.

       Note that an abstract edge has two distinct concrete representations: as an in-edge and as  an  out-edge.
       In  particular,  the  pointer  as  an  out-edge is different from the pointer as an in-edge. The function
       ageqedge canonicalizes the pointers before doing a comparison and so can be used to test  edge  equality.
       The sense of an edge can be flipped using agopp.

INTERNAL ATTRIBUTES

       Programmer-defined  values  may  be  dynamically  attached  to graphs, subgraphs, nodes, and edges.  Such
       values are either character string data (for I/O)  or  uninterpreted  binary  records  (for  implementing
       algorithms efficiently).

STRING ATTRIBUTES

       String  attributes  are  handled automatically in reading and writing graph files.  A string attribute is
       identified by name and by an internal symbol table entry (Agsym_t) created by Libcgraph.   Attributes  of
       nodes,  edges,  and  graphs  (with their subgraphs) have separate namespaces.  The contents of an Agsym_t
       have a char* name for the attribute's name, a char* defval field for the attribute's default  value,  and
       an  int  id  field  containing  the index of the attribute's specific value for an object in the object's
       array of attribute values.

       agattr creates or looks up attributes.  kind may be AGRAPH, AGNODE, or AGEDGE.  If  value  is  (char*)0),
       the  request  is  to  search  for  an  existing  attribute of the given kind and name.  Otherwise, if the
       attribute already exists, its default for creating new objects is set to the given value; if it does  not
       exist,  a new attribute is created with the given default, and the default is applied to all pre-existing
       objects of the given kind. If g is NULL,  the  default  is  set  for  all  graphs  created  subsequently.
       agattrsym  is  a  helper  function  that  looks  up an attribute for a graph object given as an argument.
       agnxtattr permits traversing the list of attributes of a given type.  If NULL is passed as an argument it
       gets  the  first attribute; otherwise it returns the next one in succession or returns NULL at the end of
       the list.  agget and agset allow fetching and updating a  string  attribute  for  an  object  taking  the
       attribute  name as an argument.  agxget and agxset do this but with an attribute symbol table entry as an
       argument (to avoid the cost of the string lookup).  Note that agset will fail  unless  the  attribute  is
       first  defined  using  agattr.   agsafeset  is a convenience function that ensures the given attribute is
       declared before setting it locally on an object.

       It is sometimes convenient to copy all of the attributes from one object to another.  This  can  be  done
       using  agcopyattr.  This fails and returns non-zero of argument objects are different kinds, or if all of
       the attributes of the source object have not been declared for the target object.

STRINGS

       Libcgraph performs its own storage management of strings as reference-counted strings.  The  caller  does
       not need to dynamically allocate storage.

       agstrdup returns a pointer to a reference-counted copy of the argument string, creating one if necessary.
       agstrbind returns a pointer to a reference-counted string if it exists, or NULL  if  not.   All  uses  of
       cgraph strings need to be freed using agstrfree in order to correctly maintain the reference count.

       The  cgraph  parser  handles  HTML-like strings. These should be indistinguishable from other strings for
       most purposes. To create an HTML-like string, use agstrdup_html. The aghtmlstr function can  be  used  to
       query if a string is an ordinary string or an HTML-like string.

       agcanonStr  returns  a  pointer  to  a version of the input string canonicalized for output for later re-
       parsing. This includes quoting special characters and keywords. It uses its own internal buffer,  so  the
       value  will  be  lost  on the next call to agcanonStr.  agstrcanon is an unsafe version of agcanonStr, in
       which the application passes in a buffer as the second argument. Note that the buffer may not be used; if
       the  input  string  is in canonical form, the function will just return a pointer to it.  For both of the
       functions, the input string must have been created using agstrdup or agstrdup_html.  Finally,  agcanonStr
       is  identical  with  agcanonStr  except  it  can  be  used with any character string. The second argument
       indicates whether or not the string should be canonicalized as an HTML-like string.

RECORDS

       Uninterpreted records may be attached to graphs, subgraphs, nodes, and edges for efficient operations  on
       values such as marks, weights, counts, and pointers needed by algorithms.  Application programmers define
       the fields of these records, but they must be declared with a common header as shown below.

       typedef struct {
           Agrec_t        header;
           /* programmer-defined fields follow */
       } user_data_t;

       Records are created and managed by Libcgraph. A programmer must explicitly attach them to the objects  in
       a  graph,  either  to  individual  objects one at a time via agbindrec, or to all the objects of the same
       class in a graph via aginit.  (Note that for graphs, aginit is applied recursively to the graph  and  its
       subgraphs if rec_size is negative (of the actual rec_size.))  The name argument of a record distinguishes
       various types of records, and is programmer defined (Libcgraph reserves the prefix _ag).  If size  is  0,
       the  call  to agbindrec is simply a lookup.  The function aggetrec can also be used for lookup.  agdelrec
       deletes a named record from one object.  agclean does the same for all objects of the same  class  in  an
       entire graph.

       Internally,  records  are  maintained  in  circular  linked  lists  attached  to graph objects.  To allow
       referencing application-dependent data without function calls or search,  Libcgraph  allows  setting  and
       locking  the list pointer of a graph, node, or edge on a particular record.  This pointer can be obtained
       with the macro AGDATA(obj).  A cast, generally within a macro or inline function, is usually  applied  to
       convert the list pointer to an appropriate programmer-defined type.

       To control the setting of this pointer, the move_to_front flag may be TRUE or FALSE.  If move_to_front is
       TRUE, the record will be locked at the head of the list, so it can be accessed directly  by  AGDATA(obj).
       The lock can be subsequently released or reset by a call to aggetrec.

DISCIPLINES

       (This  section  is  not  intended  for  casual  users.)  Programmer-defined disciplines customize certain
       resources- ID namespace, memory, and I/O - needed by Libcgraph.  A discipline struct (or NULL) is  passed
       at graph creation time.

       struct Agdisc_s {            /* user's discipline */
           Agmemdisc_t            *mem;
           Agiddisc_t            *id;
           Agiodisc_t            *io;
       } ;

       A default discipline is supplied when NULL is given for any of these fields.

ID DISCIPLINE

       An ID allocator discipline allows a client to control assignment of IDs (uninterpreted integer values) to
       objects, and possibly how they are mapped to and from strings.

       struct Agiddisc_s {             /* object ID allocator */
           void *(*open) (Agraph_t * g, Agdisc_t*);       /* associated with a graph */
           long (*map) (void *state, int objtype, char *str, unsigned long *id, int createflag);
           long (*alloc) (void *state, int objtype, unsigned long id);
           void (*free) (void *state, int objtype, unsigned long id);
           char *(*print) (void *state, int objtype, unsigned long id);
           void (*close) (void *state);
       };

       open permits the ID discipline to initialize any data structures that it maintains per individual  graph.
       Its return value is then passed as the first argument (void *state) to all subsequent ID manager calls.

       alloc informs the ID manager that Libcgraph is attempting to create an object with a specific ID that was
       given by a client.  The ID manager should return TRUE (nonzero) if the ID  can  be  allocated,  or  FALSE
       (which aborts the operation).

       free  is  called to inform the ID manager that the object labeled with the given ID is about to go out of
       existence.

       map is called to create or look-up IDs by string name (if supported by the ID manager).   Returning  TRUE
       (nonzero)  in  all  cases means that the request succeeded (with a valid ID stored through result.  There
       are four cases:

       name != NULL and createflag == 1: This requests mapping a string (e.g. a name in a graph file) into a new
       ID.   If  the  ID  manager  can  comply,  then  it  stores  the result and returns TRUE.  It is then also
       responsible for being able to print the ID again as a string.  Otherwise the ID manager may return  FALSE
       but it must implement the following (at least for graph file reading and writing to work):

       name  ==  NULL and createflag == 1: The ID manager creates a unique new ID of its own choosing.  Although
       it may return FALSE if it does not support anonymous  objects,  but  this  is  strongly  discouraged  (to
       support "local names" in graph files.)

       name  !=  NULL and createflag == 0: This is a namespace probe.  If the name was previously mapped into an
       allocated ID by the ID manager, then the manager must return this ID.   Otherwise,  the  ID  manager  may
       either  return  FALSE,  or may store any unallocated ID into result. (This is convenient, for example, if
       names are known to be digit strings that are directly converted into integer values.)

       name == NULL and createflag == 0: forbidden.

       print is allowed to return a pointer to a static buffer; a caller must copy  its  value  if  needed  past
       subsequent calls.  NULL should be returned by ID managers that do not map names.

       The  map  and  alloc  calls  do  not  pass a pointer to the newly allocated object.  If a client needs to
       install object pointers in a handle table, it can obtain them via new object callbacks.

IO DISCIPLINE

       The I/O discipline provides an abstraction for the reading and writing of graphs.
       struct Agiodisc_s {
           int        (*fread)(void *chan, char *buf, int bufsize);
           int        (*putstr)(void *chan, char *str);
           int        (*flush)(void *chan);    /* sync */
       } ;
       Normally, the FILE structure and its related functions are used for I/O. At times, though, an application
       may  need to use a totally different type of character source. The associated state or stream information
       is provided by the chan argument to agread or agwrite.  The discipline function fread and putstr  provide
       the corresponding functions for read and writing.

MEMORY DISCIPLINE

       Memory management in Libcgraph is handled on a per graph basis using the memory discipline.
       struct Agmemdisc_s {    /* memory allocator */
           void    *(*open)(Agdisc_t*);        /* independent of other resources */
           void    *(*alloc)(void *state, size_t req);
           void    *(*resize)(void *state, void *ptr, size_t old, size_t req);
           void    (*free)(void *state, void *ptr);
           void    (*close)(void *state);
       } ;
       The  open function is used to initialize the memory subsystem, returning state information that is passed
       to the calls to alloc, resize, and free.  The semantics of these should be comparable to the  standard  C
       library  functions  malloc,  realloc,  and  free,  except that new space created by agalloc and agrealloc
       should be zeroed out.  The close function  is  used  to  terminate  the  memory  subsystem,  freeing  any
       additional open resources.  For actual allocation, the library uses the functions agalloc, agrealloc, and
       agfree, which provide simple wrappers for the underlying discipline functions alloc, resize, and free.

       When Libcgraph is compiled with Vmalloc (which is  not  the  default),  each  graph  has  its  own  heap.
       Programmers  may  allocate application-dependent data within the same heap as the rest of the graph.  The
       advantage is that a graph can be deleted by atomically freeing its  entire  heap  without  scanning  each
       individual node and edge.

CALLBACKS

       An  Agcbdisc_t  defines  callbacks to be invoked by Libcgraph when initializing, modifying, or finalizing
       graph objects.  Disciplines are kept on a stack.  Libcgraph automatically calls the methods on the stack,
       top-down.   Callbacks  are installed with agpushdisc, uninstalled with agpopdisc, and can be held pending
       or released via agcallbacks.

GENERIC OBJECTS

       agroot takes any graph object (graph, subgraph, node, edge) and returns the root graph in which it lives.
       agraphof does the same, except it is the identity function on graphs and subgraphs. Note that there is no
       function to return the least subgraph containing an object, in part because this is not  well-defined  as
       nodes and edges may be in incomparable subgraphs.

       agcontains(g,obj)  returns  non-zero if obj is a member of (sub)graph g. agdelete(g,obj) is equivalent to
       agclose, agdelnode, and agdeledge for obj being a graph, node or edge, respectively. It returns -1 if obj
       does not belong to g.

       AGDATA,  AGID,  and AGTYPE are macros returning the specified fields of the argument object. The first is
       described in the RECORDS section above. The second returns the unique  integer  ID  associated  with  the
       object. The last returns AGRAPH, AGNODE, and AGEDGE depending on the type of the object.

       agnameof  returns  a  string descriptor for the object. It returns the name of the node or graph, and the
       key of an edge.  agobjkind is a synonym for AGTYPE.

ERROR REPORTING

       The library provides a variety of mechanisms to control the reporting of errors and warnings. At present,
       there are basically two types of messages: warnings and errors. A message is only written if its type has
       higher priority than a programmer-controlled minimum, which is AGWARN by default. The programmer can  set
       this  value  using  agseterr,  which  returns  the  previous value. Calling agseterr(AGMAX) turns off the
       writing of messages.

       The function agerr if the main entry point for reporting an anomaly. The  first  argument  indicates  the
       type  of  message.  Usually,  the  first  argument  in  AGWARN  or AGERR to indicate warnings and errors,
       respectively. Sometimes additional context  information  is  only  available  in  functions  calling  the
       function  where  the error is actually caught. In this case, the calling function can indicate that it is
       continuing the current error by using AGPREV as the first argument. The remaining arguments to agerr  are
       the same as the arguments to printf.

       The  functions  agwarningf  and  agerrorf  are  shorthand  for  agerr(AGERR,...)  and  agerr(AGWARN,...),
       respectively.

       Some applications desire to directly control the writing of messages.  Such an application  can  use  the
       function  agseterrf  to register the function that the library should call to actually write the message.
       The previous error function is returned. By default, the message is written to stderr.

       Errors not written are stored in a log file.  The  last  recorded  error  can  be  retreived  by  calling
       aglasterr.

       The function agerrors returns non-zero if errors have been reported.

EXAMPLE PROGRAM

       #include <stdio.h>
       #include <cgraph.h>

       typedef struct {Agrec_t hdr; int x,y,z;} mydata;

       void main(int argc, char **argv)
       {
           Agraph_t    *g, *h;
           Agnode_t    *v;
           Agedge_t    *e;
           Agsym_t     *attr;
           Dict_t      *d;
           int         cnt;
           mydata      *p;

           if (g = agread(stdin,NIL(Agdisc_t*))) {
               cnt = 0; attr = 0;
               while (attr = agnxtattr(g, AGNODE, attr)) cnt++;
               printf("The graph %s has %d attributes\n",agnameof(g),cnt);

               /* make the graph have a node color attribute, default is blue */
               attr = agattr(g,AGNODE,"color","blue");

               /* create a new graph of the same kind as g */
               h = agopen("tmp",g->desc, NULL);

               /* this is a way of counting all the edges of the graph */
               cnt = 0;
               for (v = agfstnode(g); v; v = agnxtnode(g,v))
                   for (e = agfstout(g,v); e; e = agnxtout(g,e))
                       cnt++;

               /* attach records to edges */
               for (v = agfstnode(g); v; v = agnxtnode(g,v))
                   for (e = agfstout(g,v); e; e = agnxtout(g,e)) {
                       p = (mydata*) agbindrec(e,"mydata",sizeof(mydata),TRUE);
                       p->x = 27;  /* meaningless data access example */
                       ((mydata*)(AGDATA(e)))->y = 999; /* another example */
               }
           }
       }

EXAMPLE GRAPH FILES

       digraph G {
           a -> b;
           c [shape=box];
           a -> c [weight=29,label="some text"];
           subgraph anything {
               /* the following affects only x,y,z */
               node [shape=circle];
               a; x; y -> z; y -> z;  /* multiple edges */
           }
       }

       strict graph H {
           n0 -- n1 -- n2 -- n0;  /* a cycle */
           n0 -- {a b c d};       /* a star */
           n0 -- n3;
           n0 -- n3 [weight=1];   /* same edge because graph is strict */
       }

SEE ALSO

       Libcdt(3)

BUGS

       It  is  difficult  to change endpoints of edges, delete string attributes or modify edge keys.  The work-
       around is to create a new object and copy the contents of an old one (but  new  object  obviously  has  a
       different ID, internal address, and object creation timestamp).

       The  API  lacks  convenient functions to substitute programmer-defined ordering of nodes and edges but in
       principle this can be supported.

       The library is not thread safe.

AUTHOR

       Stephen North, north@research.att.com, AT&T Research.

                                                28 FEBRUARY 2013                                    LIBCGRAPH(3)