]> granicus.if.org Git - graphviz/commitdiff
Update cgraph man page
authorEmden Gansner <erg@research.att.com>
Thu, 28 Feb 2013 22:12:11 +0000 (17:12 -0500)
committerEmden Gansner <erg@research.att.com>
Thu, 28 Feb 2013 22:12:11 +0000 (17:12 -0500)
lib/cgraph/cgraph.3

index c0ebd9d583f91b5b8e325863ab80dd2cacf87254..a05bc38aa56c6cc6db601f34804d6ef4e04f25c7 100644 (file)
@@ -11,7 +11,7 @@
 .ne 2
 .SS "\\$1"
 ..
-.TH LIBCGRAPH 3 "30 JULY 2007"
+.TH LIBCGRAPH 3 "28 FEBRUARY 2013"
 .SH "NAME"
 \fBlibcgraph\fR \- abstract graph library
 .SH "SYNOPSIS"
@@ -29,76 +29,89 @@ Agedge_t;
 Agdesc_t;
 Agdisc_t;
 Agsym_t;
+Agrec_t;
+Agcbdisc_t;
+.P1
+.SS "GLOBALS"
+.P0
+Agmemdisc_t AgMemDisc;
+Agiddisc_t  AgIdDisc;
+Agiodisc_t  AgIoDisc;
+Agdisc_t    AgDefaultDisc;
 .P1
 .SS "GRAPHS"
 .P0
-Agraph_t        *agopen(char *name, Agdesc_t kind, Agdisc_t *disc);
-int             agclose(Agraph_t *g);
-Agraph_t        *agread(void *channel, Agdisc_t *);
-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);
-int                            agisdirected(Agraph_t * g),agisundirected(Agraph_t * g),agisstrict(Agraph_t * g), agissimple(Agraph_t * g); 
+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            agcountuniqedges(Agraph_t * g, Agnode_t * n, int in, int out);
+int            agisdirected(Agraph_t * g),agisundirected(Agraph_t * g),agisstrict(Agraph_t * g), agissimple(Agraph_t * g); 
 .SS "SUBGRAPHS"
 .P0
-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() */
+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() */
 .P1
 .SS "NODES"
 .P0
-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(Agnode_t *n, int use_inedges, int use_outedges);
+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(Agnode_t *n, int use_inedges, int use_outedges);
 .P1
 .SS "EDGES"
 .P0
-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       *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 *g, Agedge_t *e);
 .SS "STRING ATTRIBUTES"
 .P0
-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);
+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 *);
 .P1
 .SS "RECORDS"
 .P0
 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);
-int                    agcopyattr(void *, void *);
+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);
 .P1
 .SS "CALLBACKS"
 .P0
-Agcbdisc_t    *agpopdisc(Agraph_t *g);
-void        agpushdisc(Agraph_t *g, Agcbdisc_t *disc);
-void        agmethod(Agraph_t *g, void *obj, Agcbdisc_t *disc, int initflag);
+Agcbdisc_t     *agpopdisc(Agraph_t *g);
+void           agpushdisc(Agraph_t *g, Agcbdisc_t *disc);
+void           agmethod(Agraph_t *g, void *obj, Agcbdisc_t *disc, int initflag);
 .P1
 .SS "MEMORY"
 .P0
@@ -115,31 +128,32 @@ char              *agstrbind(Agraph_t * g, char *);
 int            strfree(Agraph_t *, char *);
 char           *agcanonStr(char *);
 char           *agstrcanon(char *, char *);
+char           *agcanon(char *, int);
 .P1
 .SS "GENERIC OBJECTS"
 .P0
 Agraph_t       *agraphof(void*);
 Agraph_t       *agroot(void*);
-int                    agcontains(Agraph_t*, void*);
+int            agcontains(Agraph_t*, void*);
 char           *agnameof(void*);
 void           agdelete(Agraph_t *g, void *obj);
-int            agobjkind(void *obj);
+int            agobjkind(void *obj);
 Agrec_t                *AGDATA(void *obj);
 ulong          AGID(void *obj);
-int                    AGTYPE(void *obj);
+int            AGTYPE(void *obj);
 .P1
 .SS "ERROR REPORTING"
 .P0
 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);
+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);
 .P1
 .SH "DESCRIPTION"
 Libcgraph supports graph programming by maintaining graphs in memory
@@ -149,6 +163,10 @@ These graph objects may be attributed with string name-value pairs
 and programmer-defined records (see Attributes).
 .PP
 All of Libcgraph's global symbols have the prefix \fBag\fR (case varying).
+In the following, if a function has a parameter \fBint createflag\fP and the
+object does not exist, the function
+will create the specified object if \fBcreateflag\fP is non-zero; otherwise,
+it will return NULL.
 .SH "GRAPH AND SUBGRAPHS"
 .PP
 A ``main'' or ``root'' graph defines a namespace for a collection of
@@ -159,23 +177,37 @@ Objects may be named by unique strings or by integer IDs.
 (Graph kinds are \fBAgdirected\fP, \fBAgundirected\fP,
 \fBAgstrictdirected\fP, and \fBAgstrictundirected\fP.
 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 \fBAgDefaultDisc\fP.
 \fBagclose\fP deletes a graph, freeing its associated storage.
 \fBagread\fP, \fBagwrite\fP, and \fBagconcat\fP perform file I/O 
 using the graph file language described below. \fBagread\fP
 constructs a new graph while \fBagconcat\fP 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. \fBagsetfile\fP and \fBagreadline\fP
+a stdio FILE pointer. 
+\fBagmemread\fP attempts to read a graph from the input string.
+\fBagsetfile\fP and \fBagreadline\fP
 are helper functions that simply set the current file name
 and input line number for subsequent error reporting.
 .PP
+The functions \fBagisdirected\fP, \fBagisundirected\fP, \fBagisstrict\fP, and \fBagissimple\fP
+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,
+.PP
 \fBagsubg\fP finds or creates
-a subgraph by name.  A new subgraph is is initially empty and
+a subgraph by name.
+\fBagidsubg\fP 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 \fBagfstsubg\fP and \fRagnxtsubg\fP.  A subgraph is
 deleted with \fBagdelsubg\fP (or \fBagclose\fP).
+The \fBagparent\fP function returns the immediate parent graph of a subgraph, or itself if the
+graph is already a root graph.
 .PP
 By default, nodes are stored in ordered sets for efficient random
 access to insert, find, and delete nodes.
@@ -183,25 +215,15 @@ 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.
 .PP
-\fBagnnodes\fP, \fBagnedges\fP, and \fBagdegree\fP return the
-sizes of node and edge sets of a graph.  The \fBagdegree\fP returns
+\fBagnnodes\fP, \fBagnedges\fP, and \fBagnsubg\fP return the
+sizes of node, edge and subgraph sets of a graph.  
+The function \fBagdegree\fP returns
 the size of the edge set of a nodes, and takes flags
 to select in-edges, out-edges, or both.
-.PP
-An \fBAgdisc_t\fP defines callbacks to be invoked by libcgraph when
-initializing, modifying, or finalizing graph objects.  (Casual users can ignore 
-the following.) Disciplines are kept on a stack.  Libcgraph automatically
-calls the methods on the stack, top-down.  Callbacks are installed
-with \fBagpushdisc\fP, uninstalled with \fBagpopdisc\fP, and 
-can be held pending or released via \fBagcallbacks\fP.
-.PP
-(Casual users may ignore the following.
-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.
+The function \fBagcountuniqedges\fP returns
+the size of the edge set of a nodes, and takes flags
+to select in-edges, out-edges, or both. Unlike \fBagdegree\fP, each loop is only
+counted once.
 .SH "NODES"
 A node is created by giving a unique string name or
 programmer defined integer ID, and is represented by a
@@ -210,9 +232,6 @@ by pointer comparison.)
 .PP
 \fBagnode\fP searches in a graph or subgraph for a node
 with the given name, and returns it if found.
-If not found, if \fBcreateflag\fP is boolean true
-a new node is created and returned, otherwise a nil
-pointer is returned.
 \fBagidnode\fP allows a programmer to specify the node
 by a unique integer ID.
 \fBagsubnode\fP performs a similar operation on
@@ -225,33 +244,42 @@ The default sequence is order of creation (object timestamp.)
 .SH "EDGES"
 .PP
 An abstract edge has two endpoint nodes called tail and head
-where the all outedges of the same node have it as the tail
+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.
 .PP
-\fBagedge\fP searches in a graph of subgraph for an
+\fBagedge\fP 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.
-Otherwise, if \fBcreateflag\fP is boolean true,
-a new edge is created and returned: otherwise
-a nil pointer is returned.  If the \fBname\fP 
+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 \fBname\fP 
 is NULL, then an anonymous internal
 value is generated. \fBagidedge\fP allows a programmer
 to create an edge by giving its unique integer ID.
-\fBagfstin\fP, \fBagnxtint\fP, \fBagfstout\fP, and 
+\fBagsubedge\fP performs a similar operation on
+an existing edge and a subgraph.
+\fBagfstin\fP, \fBagnxtin\fP, \fBagfstout\fP, and 
 \fBagnxtout\fP visit directed in- and out- edge lists,
 and ordinarily apply only in directed graphs.
 \fBagfstedge\fP and \fBagnxtedge\fP visit all edges
 incident to a node.  \fBagtail\fP and \fBaghead\fP
 get the endpoint of an edge.
+\fBagdeledge\fP removes an edge from a graph or subgraph.
+.PP
+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 \fBageqedge\fP 
+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 \fBagopp\fP.
 .SH "INTERNAL ATTRIBUTES"
 Programmer-defined values may be dynamically
 attached to graphs, subgraphs, nodes, and edges.
-Such values are either uninterpreted binary records
-(for implementing efficient algorithms)
-or character string data (for I/O).
+Such values are either character string data (for I/O)
+or uninterpreted binary records
+(for implementing algorithms efficiently). 
 .SH "STRING ATTRIBUTES"
 String attributes are handled automatically in reading
 and writing graph files. 
@@ -259,18 +287,10 @@ A string attribute is identified by name and by
 an internal symbol table entry (\fBAgsym_t\fP) created by Libcgraph.
 Attributes of nodes, edges, and graphs (with their subgraphs)
 have separate namespaces.  The contents of an \fBAgsym_t\fP
-is listed below, followed by primitives to operate on string
-attributes.
-.P0
-typedef struct Agsym_s {        /* symbol in one of the above dictionaries */
-    Dtlink_t        link;
-    char            *name;      /* attribute's name */
-    char            *defval;    /* its default value for initialization */
-    int             id;         /* its index in attr[] */
-    unsigned char      kind;           /* referent object type */
-    unsigned char      fixed;          /* immutable value */
-} Agsym_t;
-.P1
+have a \fBchar* name\fP for the attribute's name, a \fBchar* defval\fP
+field for the attribute's default value, and an \fBint id\fP field containing
+the index of the attribute's specific value for an object in the object's array
+of attribute values. 
 .PP
 \fBagattr\fP creates or looks up attributes.
 \fBkind\fP may be \fBAGRAPH\fP, \fBAGNODE\fP, or \fBAGEDGE\fP.
@@ -280,22 +300,31 @@ 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 \fBg\fP is NIL, the default is
+objects of the given kind. If \fBg\fP is NULL, the default is
 set for all graphs created subsequently.
 \fBagattrsym\fP is a helper function
 that looks up an attribute for a graph object given as an argument.
 \fBagnxtattr\fP permits traversing the list of attributes of
-a given type.  If \fBNIL\fP is passed as an argument it gets
-the first attribute, otherwise it returns the next one in
-succession or returns \fBNIL\fP at the end of the list.
+a given type.  If \fBNULL\fP is passed as an argument it gets
+the first attribute; otherwise it returns the next one in
+succession or returns \fBNULL\fP at the end of the list.
 \fBagget\fP and \fPagset\fP allow fetching and updating a
 string attribute for an object taking the attribute name as
-an argument. \fBagxget\fP and \fBagxset\fP do this but with
+an argument. 
+\fBagxget\fP and \fBagxset\fP do this but with
 an attribute symbol table entry as an argument (to avoid
-the cost of the string lookup).  \fBagsafeset\fP is a
+the cost of the string lookup). 
+Note that \fPagset\fP will fail unless the attribute is
+first defined using \fBagattr\fP. 
+\fBagsafeset\fP is a
 convenience function that ensures the given attribute is
 declared before setting it locally on an object.
-
+.PP
+It is sometimes convenient to copy all of the attributes from one
+object to another. This can be done using \fBagcopyattr\fP. 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.
 .SH "STRINGS"
 Libcgraph performs its own storage management of strings as 
 reference-counted strings.
@@ -307,6 +336,12 @@ 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 \fBagstrfree\fP
 in order to correctly maintain the reference count.
 .PP
+The cgraph parser handles HTML-like strings. These should be 
+indistinguishable from other strings for most purposes. To create
+an HTML-like string, use \fBagstrdup_html\fP. The \fBaghtmlstr\fP
+function can be used to query if a string is an ordinary string or
+an HTML-like string.
+.PP
 \fBagcanonStr\fP 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
@@ -315,12 +350,11 @@ the value will be lost on the next call to \fBagcanonStr\fP.
 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.
-.PP
-The cgraph parser handles HTML-like strings. These should be 
-indistinguishable from other strings for most purposes. To create
-an HTML-like string, use \fBagstrdup_html\fP. The \fBaghtmlstr\fP
-function can be used to query if a string is an ordinary string or
-an HTML-like string.
+For both of the functions, the input string must have been created using
+\fBagstrdup\fP or \fBagstrdup_html\fP.
+Finally, \fBagcanonStr\fP is identical with \fBagcanonStr\fP
+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.
 .SH "RECORDS"
 Uninterpreted records may be attached to graphs, subgraphs, nodes,
 and edges for efficient operations on values such as marks, weights,
@@ -329,10 +363,10 @@ define the fields of these records, but they must be declared with
 a common header as shown below.
 .PP
 .P0
-typedef struct Agrec_s {
-    Agrec_t            header;
+typedef struct {
+    Agrec_t        header;
     /* programmer-defined fields follow */
-} Agrec_t;
+} user_data_t;
 .P1
 .PP
 Records are created and managed by Libcgraph. A programmer must
@@ -342,10 +376,11 @@ all the objects of the same class in a graph via \fBaginit\fP.
 (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 \fBname\fP argument a record distinguishes various types of records,
+The \fBname\fP argument of a record distinguishes various types of records,
 and is programmer defined (Libcgraph reserves the prefix \fB_ag\fR).
 If size is 0, the call to \fBagbindrec\fP is simply a lookup.
-\fBagdelrec\fP is the deletes records one at a time.
+The function \fBaggetrec\fP can also be used for lookup.
+\fBagdelrec\fP deletes a named record from one object.
 \fBagclean\fP does the same for all objects of the same
 class in an entire graph. 
 
@@ -370,34 +405,35 @@ Use of this feature implies cooperation or at least isolation
 from other functions also using the move-to-front convention.
 
 .SH "DISCIPLINES"
-(The following is not intended for casual users.)
+(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 NIL) is passed at graph creation time.
+A discipline struct (or NULL) is passed at graph creation time.
 .PP
 .P0
-struct Agdisc_s {                      /* user's discipline */
-       Agmemdisc_t                     *mem;
-       Agiddisc_t                      *id;
-       Agiodisc_t                      *io;
+struct Agdisc_s {            /* user's discipline */
+    Agmemdisc_t            *mem;
+    Agiddisc_t            *id;
+    Agiodisc_t            *io;
 } ;
 .P1
 .PP
-A default discipline is supplied when NIL is given for
+A default discipline is supplied when NULL is given for
 any of these fields.
 
+.SH "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.
 
 .P0
 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);
+    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);
 };
 .P1
 .PP
@@ -448,24 +484,59 @@ The \f5map\fP and \f5alloc\fP 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.
+.PP
+An \fBAgcbdisc_t\fP 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 \fBagpushdisc\fP, uninstalled with \fBagpopdisc\fP, and 
+can be held pending or released via \fBagcallbacks\fP.
+.PP
+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.
+.SH "IO DISCIPLINE"
+.PP
+The I/O discipline provides an abstraction for the reading and writing of graphs.
 .P0
 struct Agiodisc_s {
-       int             (*fread)(void *chan, char *buf, int bufsize);
-       int             (*putstr)(void *chan, char *str);
-       int             (*flush)(void *chan);   /* sync */
-       /* error messages? */
+    int        (*fread)(void *chan, char *buf, int bufsize);
+    int        (*putstr)(void *chan, char *str);
+    int        (*flush)(void *chan);    /* sync */
 } ;
+.P1
+Normally, the \fBFILE\fP 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 \fIchan\fP argument to \fBagread\fP or \fBagwrite\fP.
+The discipline function \fIfread\fP and \fIputstr\fP provide the corresponding functions for
+read and writing.
 
-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);
+.SH "MEMORY DISCIPLINE"
+Memory management in Libcgraph is handled on a per graph basis using the memory discipline.
+.P0
+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);
 } ;
 .P1
+The \fBopen\fP function is used to initialize the memory subsystem,
+returning state information that is passed to the calls to  
+\fBalloc\fP, \fBresize\fP, and \fBfree\fP.
+The semantics of these should be comparable to the standard C library functions
+\fBmalloc\fP, \fBrealloc\fP, and \fBfree\fP, except that new space created by \fBagalloc\fP 
+and \fBagrealloc\fP should be zeroed out.
+The \fBclose\fP function is used to terminate the memory subsystem, freeing any additional
+open resources.
+For actual allocation, the library uses the functions
+\fBagalloc\fP, \fBagrealloc\fP, and \fBagfree\fP, which provide simple wrappers for
+the underlying discipline functions \fBalloc\fP, \fBresize\fP, and \fBfree\fP..
 
-.P0
 .SH "GENERIC OBJECTS"
 \fBagroot\fP takes any graph object (graph, subgraph, node, edge) and returns
 the root graph in which it lives. \fBagraphof\fP does the same, except it 
@@ -473,24 +544,22 @@ 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.
 .PP
-\fBagcontains(\fIg\fP,\fIobj\fP)\fP returns non-zero if \fIobj\fP is a member 
-of (sub)graph \fIg\fP. \fBagdelete(\fIg\fP,\fIobj\fP)\fP is equivalent 
-to \fBagclose\fP, \fBagdelnode\fP, and \fBagclose\fP for \fIobj\fP being a 
+\fBagcontains\fP(\fIg\fP,\fIobj\fP) returns non-zero if \fIobj\fP is a member 
+of (sub)graph \fIg\fP. \fBagdelete\fP(\fIg\fP,\fIobj\fP) is equivalent 
+to \fBagclose\fP, \fBagdelnode\fP, and \fBagdeledge\fP for \fIobj\fP being a 
 graph, node or edge, respectively. It returns -1 if \fIobj\fP does not 
 belong to \fIg\fP.
 .PP
-\fBagnameof\fP returns a string descriptor for the object. It returns the name
-of the node or graph, and the key of an edge. 
-\fBagobjkind\fP is a synonym for \fBAGTYPE\fP.
-.PP
 \fBAGDATA\fP, \fBAGID\fP, and \fBAGTYPE\fP are macros returning the specified
 fields of the argument object. The first is described in the \fBRECORDS\fP
 section above. The second returns the unique integer ID associated with
 the object. The last returns \fBAGRAPH\fP, \fBAGNODE\fP, and \fBAGEDGE\fP
 depending on the type of the object.
+.PP
+\fBagnameof\fP returns a string descriptor for the object. It returns the name
+of the node or graph, and the key of an edge. 
+\fBagobjkind\fP is a synonym for \fBAGTYPE\fP.
 
-typedef int (*agusererrf) (char*);
-agusererrf agseterrf(agusererrf);
 .SH "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
@@ -525,8 +594,8 @@ can be retreived by calling \fBaglasterr\fP.
 The function \fBagerrors\fP returns non-zero if errors have been reported. 
 .SH "EXAMPLE PROGRAM"
 .P0
-#include <graphviz/cgraph.h>
-typedef struct mydata_s {Agrec_t hdr; int x,y,z;} mydata;
+#include <cgraph.h>
+typedef struct {Agrec_t hdr; int x,y,z;} mydata;
 
 main(int argc, char **argv)
 {
@@ -539,11 +608,11 @@ main(int argc, char **argv)
     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);
+        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 */
+        /* 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 */
@@ -560,7 +629,7 @@ main(int argc, char **argv)
             for (e = agfstout(g,v); e; e; = agnxtout(g,e)) {
                 p = (mydata*) agbindrec(g,e,"mydata",sizeof(mydata),TRUE);
                 p->x = 27;  /* meaningless data access example */
-                               ((mydata*)(AGDATA(e)))->y = 999; /* another example */
+                ((mydata*)(AGDATA(e)))->y = 999; /* another example */
         }
     }
 }