Go to main content

man pages section 3: Library Interfaces and Headers

Exit Print View

Updated: Wednesday, July 27, 2022
 
 

cgraph (3)

Name

cgraph - 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(3)               Library Functions Manual               LIBCGRAPH(3)



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  argu-
       ment  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 agread-
       line 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 program-
       mer  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 sub-
       graph  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,  agnx-
       tin, 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,  sub-
       graphs, 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 inter-
       nal  symbol  table entry (Agsym_t) created by Libcgraph.  Attributes of
       nodes, edges, and graphs (with their subgraphs)  have  separate  names-
       paces.   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 spe-
       cific 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 exist-
       ing 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 cre-
       ated  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 tar-
       get 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  indistin-
       guishable  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 canoni-
       calized 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 explic-
       itly  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  responsi-
       ble 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  ta-
       ble, 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 differ-
       ent type of character source. The associated state or  stream  informa-
       tion is provided by the chan argument to agread or agwrite.  The disci-
       pline 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 cre-
       ated 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 agal-
       loc,  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  ini-
       tializing,  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  incompa-
       rable 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 syn-
       onym 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,  respec-
       tively.  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 */
       }


ATTRIBUTES
       See attributes(7) for descriptions of the following attributes:


       +---------------+------------------+
       |ATTRIBUTE TYPE | ATTRIBUTE VALUE  |
       +---------------+------------------+
       |Availability   | image/graphviz   |
       +---------------+------------------+
       |Stability      | Volatile         |
       +---------------+------------------+

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 differ-
       ent 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.



NOTES
       Source  code  for open source software components in Oracle Solaris can
       be found at https://www.oracle.com/downloads/opensource/solaris-source-
       code-downloads.html.

       This     software     was    built    from    source    available    at
       https://github.com/oracle/solaris-userland.   The  original   community
       source  was  downloaded from  http://gitlab.com/graphviz/graphviz/-/ar-
       chive/2.47.1/graphviz-2.47.1.tar.gz.

       Further information about this software can be found on the open source
       community website at http://www.graphviz.org/.



                               28 FEBRUARY 2013                   LIBCGRAPH(3)