]> granicus.if.org Git - graphviz/commitdiff
Initial version of Cgraph created.
authornorth <devnull@localhost>
Thu, 25 Oct 2007 20:27:57 +0000 (20:27 +0000)
committernorth <devnull@localhost>
Thu, 25 Oct 2007 20:27:57 +0000 (20:27 +0000)
lib/cgraph/attr.c [new file with mode: 0644]
lib/cgraph/cghdr.h [new file with mode: 0644]
lib/cgraph/cgraph.h [new file with mode: 0644]

diff --git a/lib/cgraph/attr.c b/lib/cgraph/attr.c
new file mode 100644 (file)
index 0000000..3be23ca
--- /dev/null
@@ -0,0 +1,492 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+#include       <cghdr.h>
+
+/*
+ * dynamic attributes
+ */
+
+/* to create a graph's data dictionary */
+
+#define MINATTR        4               /* minimum allocation */
+
+static void freesym(Dict_t * d, Void_t * obj, Dtdisc_t * disc);
+
+Dtdisc_t AgDataDictDisc = {
+    (int) offsetof(Agsym_t, name),     /* use symbol name as key */
+    -1,
+    (int) offsetof(Agsym_t, link),
+    NIL(Dtmake_f),
+    freesym,
+    NIL(Dtcompar_f),
+    NIL(Dthash_f)
+};
+
+static char DataDictName[] = "_AG_datadict";
+static void init_all_attrs(Agraph_t * g);
+static Agdesc_t ProtoDesc = {1,0,1,0,1,1};
+static Agraph_t *ProtoGraph;
+
+Agdatadict_t *agdatadict(Agraph_t * g)
+{
+    Agdatadict_t *rv;
+    while ((rv = (Agdatadict_t *) aggetrec(g, DataDictName, FALSE))
+          == NIL(Agdatadict_t *))
+       init_all_attrs(g);
+    return rv;
+}
+
+Dict_t *agdictof(Agraph_t * g, int kind)
+{
+    Agdatadict_t *dd;
+    Dict_t *dict;
+
+    dd = agdatadict(g);
+    switch (kind) {
+    case AGRAPH:
+       dict = dd->dict.g;
+       break;
+    case AGNODE:
+       dict = dd->dict.n;
+       break;
+    case AGINEDGE:
+    case AGOUTEDGE:
+       dict = dd->dict.e;
+       break;
+    default:
+       abort();
+    }
+    return dict;
+}
+
+static Agdatadict_t *agmakedatadict(Agraph_t * g)
+{
+    Agraph_t *par;
+    Agdatadict_t *parent_dd, *dd;
+
+    dd = (Agdatadict_t *) agbindrec(g, DataDictName, sizeof(Agdatadict_t),
+                                   FALSE);
+    dd->dict.n = agdtopen(g, &AgDataDictDisc, Dttree);
+    dd->dict.e = agdtopen(g, &AgDataDictDisc, Dttree);
+    dd->dict.g = agdtopen(g, &AgDataDictDisc, Dttree);
+    if ((par = agparent(g))) {
+       parent_dd = agdatadict(par);
+       assert(dd != parent_dd);
+       dtview(dd->dict.n, parent_dd->dict.n);
+       dtview(dd->dict.e, parent_dd->dict.e);
+       dtview(dd->dict.g, parent_dd->dict.g);
+    }
+    return dd;
+}
+
+Agsym_t *agnewsym(Agraph_t * g, char *name, char *value, int id, int kind)
+{
+    Agsym_t *sym;
+    sym = agalloc(g, sizeof(Agsym_t));
+    sym->kind = kind;
+    sym->name = agstrdup(g, name);
+    sym->defval = agstrdup(g, value);
+    sym->id = id;
+    return sym;
+}
+
+       /* look up or update a value associated with an object. */
+Agsym_t *agdictsym(Dict_t * dict, char *name)
+{
+    Agsym_t key;
+    key.name = (char *) name;
+    return (Agsym_t *) dtsearch(dict, &key);
+}
+
+/* look up attribute in local dictionary with no view pathing */
+Agsym_t *aglocaldictsym(Dict_t * dict, char *name)
+{
+    Agsym_t *rv;
+    Dict_t *view;
+
+    view = dtview(dict, NIL(Dict_t *));
+    rv = agdictsym(dict, name);
+    dtview(dict, view);
+    return rv;
+}
+
+Agsym_t *agattrsym(void *obj, char *name)
+{
+    Agattr_t *data;
+
+    data = agattrrec((Agobj_t *) obj);
+    return (data ? agdictsym(data->dict, name) : NILsym);
+}
+
+/* to create a graph's, node's edge's string attributes */
+
+char *AgDataRecName = "_AG_strdata";
+
+static int topdictsize(Agobj_t * obj)
+{
+    return dtsize(agdictof(agroot(agraphof(obj)), AGTYPE(obj)));
+}
+
+static Agrec_t *agmakeattrs(void *obj)
+{
+    int sz;
+    Agattr_t *rec;
+    Agsym_t *sym;
+    Agraph_t *g;
+    Dict_t *datadict;
+
+    g = agraphof(obj);
+    rec = agbindrec(obj, AgDataRecName, sizeof(Agattr_t), FALSE);
+    datadict = agdictof(g, AGTYPE(obj));
+    if (rec->dict == NIL(Dict_t *)) {
+       rec->dict = datadict;
+       /* don't malloc(0) */
+       sz = topdictsize(obj);
+       if (sz < MINATTR)
+           sz = MINATTR;
+       rec->str = agalloc(g, sz * sizeof(char *));
+       /* doesn't call agxset() so no obj-modified callbacks occur */
+       for (sym = (Agsym_t *) dtfirst(datadict); sym;
+            sym = (Agsym_t *) dtnext(datadict, sym))
+           rec->str[sym->id] = agstrdup(g, sym->defval);
+    } else {
+       assert(rec->dict == datadict);
+    }
+    return (Agrec_t *) rec;
+}
+
+
+static void freeattr(Agobj_t * obj, Agattr_t * attr)
+{
+    int i, sz;
+    Agraph_t *g;
+
+    g = agraphof(obj);
+    sz = topdictsize(obj);
+    for (i = 0; i < sz; i++)
+       agstrfree(g, attr->str[i]);
+    agfree(g, attr->str);
+}
+
+static void freesym(Dict_t * d, Void_t * obj, Dtdisc_t * disc)
+{
+    Agsym_t *sym;
+
+    NOTUSED(d);
+    sym = (Agsym_t *) obj;
+    NOTUSED(disc);
+    agstrfree(Ag_G_global, sym->name);
+    agstrfree(Ag_G_global, sym->defval);
+    agfree(Ag_G_global, sym);
+}
+
+Agattr_t *agattrrec(void *obj)
+{
+    return (Agattr_t *) aggetrec(obj, AgDataRecName, FALSE);
+}
+
+
+static void addattr(Agraph_t * g, Agobj_t * obj, Agsym_t * sym)
+{
+    Agattr_t *attr;
+
+    attr = (Agattr_t *) agattrrec(obj);
+    assert(attr != NIL(Agattr_t *));
+    if (sym->id >= MINATTR)
+       attr->str = (char **) AGDISC(g, mem)->resize(AGCLOS(g, mem),
+                                                    attr->str,
+                                                    sym->id *
+                                                    sizeof(char *),
+                                                    (sym->id +
+                                                     1) * sizeof(char *));
+    attr->str[sym->id] = agstrdup(g, sym->defval);
+    /* agmethod_upd(g,obj,sym);  JCE and GN didn't like this. */
+}
+
+
+/*
+ * create or update an existing attribute and return its descriptor.
+ * if the new value is NIL(char*), this is only a search, no update.
+ * when a new attribute is created, existing graphs/nodes/edges
+ * receive its default value.
+ */
+Agsym_t *agattr(Agraph_t * g, int kind, char *name, char *value)
+{
+    Agraph_t *root;
+    Agsym_t *lsym, *rsym;
+    Dict_t *ldict, *rdict;
+    Agnode_t *n;
+    Agedge_t *e;
+
+    if (g == 0) {if (ProtoGraph == 0) ProtoGraph = agopen(0,ProtoDesc,0); g = ProtoGraph;}
+    ldict = agdictof(g, kind);
+    lsym = aglocaldictsym(ldict, name);
+    root = agroot(g);
+    if (lsym) {
+       /* this attr was previously defined in this graph */
+       if (value) {
+           agstrfree(g, lsym->defval);
+           lsym->defval = agstrdup(g, value);
+       }
+    } else {                   /* not previously defined here */
+       rsym = agdictsym(ldict, name);  /* viewpath up to root */
+       if (value) {            /* need to define */
+           if (rsym) {
+               lsym = agnewsym(g, name, value, rsym->id, kind);
+               dtinsert(ldict, lsym);
+           } else {            /* just define globally */
+               rdict = agdictof(root, kind);
+               lsym = rsym =
+                   agnewsym(g, name, value, dtsize(rdict), kind);
+               dtinsert(rdict, rsym);
+
+               switch (kind) {
+               case AGRAPH:
+                   agapply(root, (Agobj_t *) root, (agobjfn_t) addattr,
+                           lsym, TRUE);
+                   break;
+               case AGNODE:
+                   for (n = agfstnode(root); n; n = agnxtnode(root, n))
+                       addattr(g, (Agobj_t *) n, lsym);
+                   break;
+               case AGINEDGE:
+               case AGOUTEDGE:
+                   for (n = agfstnode(root); n; n = agnxtnode(root, n))
+                       for (e = agfstout(root, n); e;
+                            e = agnxtout(root, e))
+                           addattr(g, (Agobj_t *) e, lsym);
+                   break;
+               }
+           }
+           agmethod_upd(g, g, lsym);   /* JCE and GN wanted this instead */
+       } else
+           return rsym;
+    }
+    /* in graphs, defaults and actual values are always the same.
+     * see also agxset() where graph attrs are handled.  therefore
+     * agxset() must not call agattr() in its implementation 
+     */
+    if (lsym && (kind == AGRAPH))
+       agxset(g, lsym, value);
+    return lsym;
+}
+
+Agsym_t *agnxtattr(Agraph_t * g, int kind, Agsym_t * attr)
+{
+    Dict_t *d;
+    Agsym_t *rv;
+
+    d = agdictof(g, kind);
+    if (attr)
+       rv = (Agsym_t *) dtnext(d, attr);
+    else
+       rv = (Agsym_t *) dtfirst(d);
+    return rv;
+}
+
+/* Create or delete attributes associated with an object */
+
+void agraphattr_init(Agraph_t * g)
+{
+    /* Agdatadict_t *dd; */
+    /* Agrec_t                      *attr; */
+
+    g->desc.has_attrs = 1;
+    /* dd = */ agmakedatadict(g);
+    /* attr = */ agmakeattrs(g);
+}
+
+void agraphattr_delete(Agraph_t * g)
+{
+    Agdatadict_t *dd;
+    Agattr_t *attr;
+
+    Ag_G_global = g;
+    if ((attr = agattrrec(g))) {
+       freeattr((Agobj_t *) g, attr);
+       agdelrec(g, attr->h.name);
+    }
+
+    if ((dd = agdatadict(g))) {
+       agdtclose(g, dd->dict.n);
+       agdtclose(g, dd->dict.e);
+       agdtclose(g, dd->dict.g);
+       agdelrec(g, dd->h.name);
+    }
+}
+
+void agnodeattr_init(Agnode_t * n)
+{
+    Agattr_t *data;
+
+    data = agattrrec(n);
+    if ((!data) || (!data->dict))
+       (void) agmakeattrs(n);
+}
+
+void agnodeattr_delete(Agnode_t * n)
+{
+    Agattr_t *rec;
+
+    if ((rec = agattrrec(n))) {
+       freeattr((Agobj_t *) n, rec);
+       agdelrec(n, AgDataRecName);
+    }
+}
+
+void agedgeattr_init(Agedge_t * e)
+{
+    Agattr_t *data;
+
+    data = agattrrec(e);
+    if ((!data) || (!data->dict))
+       (void) agmakeattrs(e);
+}
+
+void agedgeattr_delete(Agedge_t * e)
+{
+    Agattr_t *rec;
+
+    if ((rec = agattrrec(e))) {
+       freeattr((Agobj_t *) e, rec);
+       agdelrec(e, AgDataRecName);
+    }
+}
+
+char *agget(void *obj, char *name)
+{
+    Agsym_t *sym;
+    Agattr_t *data;
+    char *rv;
+
+    sym = agattrsym(obj, name);
+    if (sym == NILsym)
+       rv = 0;         /* note was "", but this provides more info */
+    else {
+       data = agattrrec((Agobj_t *) obj);
+       rv = (char *) (data->str[sym->id]);
+    }
+    return rv;
+}
+
+char *agxget(void *obj, Agsym_t * sym)
+{
+    Agattr_t *data;
+    char *rv;
+
+    data = agattrrec((Agobj_t *) obj);
+    assert((sym->id >= 0) && (sym->id < topdictsize(obj)));
+    rv = (char *) (data->str[sym->id]);
+    return rv;
+}
+
+int agset(void *obj, char *name, char *value)
+{
+    Agsym_t *sym;
+    int rv;
+
+    sym = agattrsym(obj, name);
+    if (sym == NILsym)
+       rv = FAILURE;
+    else
+       rv = agxset(obj, sym, value);
+    return rv;
+}
+
+int agxset(void *obj, Agsym_t * sym, char *value)
+{
+    Agraph_t *g;
+    Agobj_t *hdr;
+    Agattr_t *data;
+    Agsym_t *lsym;
+
+    g = agraphof(obj);
+    hdr = (Agobj_t *) obj;
+    data = agattrrec(hdr);
+    assert((sym->id >= 0) && (sym->id < topdictsize(obj)));
+    agstrfree(g, data->str[sym->id]);
+    data->str[sym->id] = agstrdup(g, value);
+    if (hdr->tag.objtype == AGRAPH) {
+       /* also update dict default */
+       Dict_t *dict;
+       dict = agdatadict(g)->dict.g;
+       if ((lsym = aglocaldictsym(dict, sym->name))) {
+           agstrfree(g, lsym->defval);
+           lsym->defval = agstrdup(g, value);
+       } else {
+           lsym = agnewsym(g, sym->name, value, sym->id, AGTYPE(hdr));
+           dtinsert(dict, lsym);
+       }
+    }
+    agmethod_upd(g, obj, sym);
+    return SUCCESS;
+}
+
+int agsafeset(void* obj, char* name, char* value, char* def)
+{
+    Agsym_t* a;
+
+       a = agattr(agraphof(obj),AGTYPE(obj),value,0);
+       if (!a) a = agattr(agraphof(obj),AGTYPE(obj),value,def);
+    return agxset(obj, a, value);
+}
+
+
+/*
+ * here we are attaching attributes to the already created graph objs.
+ * presumably they were already initialized, so we don't invoke any
+ * of the old methods.
+ */
+static void init_all_attrs(Agraph_t * g)
+{
+    Agraph_t *root;
+    Agnode_t *n;
+    Agedge_t *e;
+
+    root = agroot(g);
+    agapply(root, (Agobj_t *) root, (agobjfn_t) agraphattr_init,
+           NIL(Agdisc_t *), TRUE);
+    for (n = agfstnode(root); n; n = agnxtnode(root, n)) {
+       agnodeattr_init(n);
+       for (e = agfstout(root, n); e; e = agnxtout(root, e)) {
+           agedgeattr_init(e);
+       }
+    }
+}
+
+/* agcopyattr:
+ * Assumes attributes have already been declared.
+ * Do not copy key attribute for edges, as this must be distinct.
+ * Returns non-zero on failure or if objects have different type.
+ */
+int agcopyattr(void *oldobj, void *newobj)
+{
+       Agraph_t *g;
+    Agsym_t *sym;
+    Agsym_t *newsym;
+       int             r = 1;
+
+       g = agraphof(oldobj);
+    if (AGTYPE(oldobj) != AGTYPE(newobj)) return 1;
+       sym = 0;
+       while ((sym = agnxtattr(g, AGTYPE(oldobj), sym))) {
+        newsym = agattrsym(newobj,sym->name);
+        if (!newsym) return 1;
+        r = agxset(newobj, newsym, agxget(oldobj, sym));
+    }
+    return r;
+}
diff --git a/lib/cgraph/cghdr.h b/lib/cgraph/cghdr.h
new file mode 100644 (file)
index 0000000..83a625f
--- /dev/null
@@ -0,0 +1,173 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+#ifndef ATT_GRAPHPVT_H
+#define ATT_GRAPHPVT_H 1
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+#include <cgraph.h>
+
+#include               <ctype.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_AST
+#include               <ast.h>
+#include               <vmalloc.h>
+#else
+#ifdef HAVE_VMALLOC
+#include               <vmalloc.h>
+#endif                         /* HAVE_VMALLOC */
+#include               <sys/types.h>
+#include               <stdarg.h>
+#include               <stdlib.h>
+#include               <string.h>
+#ifdef HAVE_UNISTD_H
+#include       <unistd.h>
+#endif                         /* HAVE_UNISTD_H */
+#endif                         /* HAVE_AST */
+#ifdef DEBUG
+#include <assert.h>
+#else
+#define assert(x)
+#endif
+
+#ifndef streq
+#define streq(s,t)             ((*s == *t) && !strcmp((s),(t)))
+#endif
+#ifdef offsetof
+#undef offsetof
+#endif
+#define offsetof(typ,fld)  ((int)(&(((typ*)0)->fld)))
+#define NOTUSED(var)   (void) var
+
+#define NILgraph                       NIL(Agraph_t*)
+#define NILnode                                NIL(Agnode_t*)
+#define NILedge                                NIL(Agedge_t*)
+#define NILsym                         NIL(Agsym_t*)
+#define NILstr                         NIL(char*)
+
+#define MAX_OUTPUTLINE         80
+#define        SUCCESS                         0
+#define FAILURE                                -1
+#define LOCALNAMEPREFIX                '%'
+
+#define AGDISC(g,d)                    ((g)->clos->disc.d)
+#define AGCLOS(g,d)                    ((g)->clos->state.d)
+#define AGNEW(g,t)                     ((t*)(agalloc(g,sizeof(t))))
+
+#define ISALNUM(c) ((isalnum(c)) || ((c) == '_') || (!isascii(c)))
+
+       /* functional definitions */
+typedef Agobj_t *(*agobjsearchfn_t) (Agraph_t * g, Agobj_t * obj);
+int agapply(Agraph_t * g, Agobj_t * obj, agobjfn_t fn, void *arg,
+           int preorder);
+
+       /* global variables */
+EXTERN Agraph_t *Ag_G_global;
+extern char *AgDataRecName;
+
+       /* set ordering disciplines */
+extern Dtdisc_t Ag_subnode_id_disc;
+extern Dtdisc_t Ag_subnode_seq_disc;
+extern Dtdisc_t Ag_mainedge_id_disc;
+extern Dtdisc_t Ag_subedge_id_disc;
+extern Dtdisc_t Ag_mainedge_seq_disc;
+extern Dtdisc_t Ag_subedge_seq_disc;
+extern Dtdisc_t Ag_subgraph_id_disc;
+extern Agcbdisc_t AgAttrdisc;
+
+       /* internal constructor of graphs and subgraphs */
+Agraph_t *agopen1(Agraph_t * g);
+void agstrclose(Agraph_t * g);
+
+       /* object set management */
+Agnode_t *agfindnode_by_id(Agraph_t * g, unsigned long id);
+Dtcompar_f agdictorder(Agraph_t *, Dict_t *, Dtcompar_f);
+int agedgecmpf(Dict_t * d, void *arg_e0, void *arg_e1, Dtdisc_t * disc);
+int agnamecmpf(Dict_t * d, void *, void *, Dtdisc_t * disc);
+void agset_node_disc(Agraph_t * g, Dtdisc_t * disc);
+unsigned long agnextseq(Agraph_t * g, int objtype);
+
+/* dict helper functions */
+Dict_t *agdtopen(Agraph_t * g, Dtdisc_t * disc, Dtmethod_t * method);
+void agdtdisc(Agraph_t * g, Dict_t * dict, Dtdisc_t * disc);
+long agdtdelete(Agraph_t * g, Dict_t * dict, void *obj);
+void agdtclose(Agraph_t * g, Dict_t * dict);
+void *agdictobjmem(Dict_t * dict, Void_t * p, size_t size,
+                  Dtdisc_t * disc);
+void agdictobjfree(Dict_t * dict, Void_t * p, Dtdisc_t * disc);
+
+       /* name-value pair operations */
+Agdatadict_t *agdatadict(Agraph_t * g);
+Agattr_t *agattrrec(void *obj);
+
+void agraphattr_init(Agraph_t * g);
+void agraphattr_delete(Agraph_t * g);
+void agnodeattr_init(Agnode_t * n);
+void agnodeattr_delete(Agnode_t * n);
+void agedgeattr_init(Agedge_t * e);
+void agedgeattr_delete(Agedge_t * e);
+
+       /* parsing and lexing graph files */
+int aagparse(void);
+void aglexinit(Agdisc_t * disc, void *ifile);
+int aaglex(void);
+void aglexeof(void);
+
+       /* ID management */
+int agmapnametoid(Agraph_t * g, int objtype, char *str,
+                 unsigned long *result, int allocflag);
+int agallocid(Agraph_t * g, int objtype, unsigned long request);
+void agfreeid(Agraph_t * g, int objtype, unsigned long id);
+char *agprintid(Agobj_t * obj);
+int aginternalmaplookup(Agraph_t * g, int objtype, char *str,
+                       unsigned long *result);
+void aginternalmapinsert(Agraph_t * g, int objtype, char *str,
+                        unsigned long result);
+char *aginternalmapprint(Agraph_t * g, int objtype, unsigned long id);
+int aginternalmapdelete(Agraph_t * g, int objtype, unsigned long id);
+void aginternalmapclose(Agraph_t * g);
+
+       /* internal set operations */
+void agedgesetop(Agraph_t * g, Agedge_t * e, int insertion);
+void agdelnodeimage(Agraph_t * g, Agnode_t * node, void *ignored);
+void agdeledgeimage(Agraph_t * g, Agedge_t * edge, void *ignored);
+void *agrebind0(Agraph_t * g, void *obj);      /* unsafe */
+int agrename(Agobj_t * obj, char *newname);
+void agrecclose(Agobj_t * obj);
+
+void agmethod_init(Agraph_t * g, void *obj);
+void agmethod_upd(Agraph_t * g, void *obj, Agsym_t * sym);
+void agmethod_delete(Agraph_t * g, void *obj);
+
+#define CB_INITIALIZE  100
+#define CB_UPDATE              101
+#define CB_DELETION            102
+void agsyspushdisc(Agraph_t * g, Agcbdisc_t * cb, void *state, int stack);
+int agsyspopdisc(Agraph_t * g, Agcbdisc_t * cb, int stack);
+void agrecord_callback(Agraph_t * g, Agobj_t * obj, int kind,
+                      Agsym_t * optsym);
+void aginitcb(Agraph_t * g, void *obj, Agcbstack_t * disc);
+void agupdcb(Agraph_t * g, void *obj, Agsym_t * sym, Agcbstack_t * disc);
+void agdelcb(Agraph_t * g, void *obj, Agcbstack_t * disc);
+
+#endif                         /* ATT_GRAPHPVT_H */
diff --git a/lib/cgraph/cgraph.h b/lib/cgraph/cgraph.h
new file mode 100644 (file)
index 0000000..b4cb359
--- /dev/null
@@ -0,0 +1,410 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+#ifndef ATT_GRAPH_H
+#define ATT_GRAPH_H
+
+#include               <cdt.h>
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+#ifndef NOT
+#define        NOT(x)                  (!(x))
+#endif
+#ifndef NIL
+#define NIL(type)              ((type)0)
+#endif
+#define NILgraph               NIL(Agraph_t*)
+#define NILnode                        NIL(Agnode_t*)
+#define NILedge                        NIL(Agedge_t*)
+#define NILsym                 NIL(Agsym_t*)
+
+/* forward struct type declarations */
+typedef struct Agtag_s Agtag_t;
+typedef struct Agobj_s Agobj_t;        /* generic object header */
+typedef struct Agraph_s Agraph_t;      /* graph, subgraph (or hyperedge) */
+typedef struct Agnode_s Agnode_t;      /* node (atom) */
+typedef struct Agedge_s Agedge_t;      /* node pair */
+typedef struct Agdesc_s Agdesc_t;      /* graph descriptor */
+typedef struct Agmemdisc_s Agmemdisc_t;        /* memory allocator */
+typedef struct Agiddisc_s Agiddisc_t;  /* object ID allocator */
+typedef struct Agiodisc_s Agiodisc_t;  /* IO services */
+typedef struct Agdisc_s Agdisc_t;      /* union of client discipline methods */
+typedef struct Agdstate_s Agdstate_t;  /* client state (closures) */
+typedef struct Agsym_s Agsym_t;        /* string attribute descriptors */
+typedef struct Agattr_s Agattr_t;      /* string attribute container */
+typedef struct Agcbdisc_s Agcbdisc_t;  /* client event callbacks */
+typedef struct Agcbstack_s Agcbstack_t;        /* enclosing state for cbdisc */
+typedef struct Agclos_s Agclos_t;      /* common fields for graph/subgs */
+typedef struct Agrec_s Agrec_t;        /* generic runtime record */
+typedef struct Agdatadict_s Agdatadict_t;      /* set of dictionaries per graph */
+typedef struct Agedgepair_s Agedgepair_t;      /* the edge object */
+typedef struct Agsubnode_s Agsubnode_t;
+
+/* Header of a user record.  These records are attached by client programs
+dynamically at runtime.  A unique string ID must be given to each record
+attached to the same object.  Cgraph has functions to create, search for,
+and delete these records.   The records are maintained in a circular list,
+with obj->data pointing somewhere in the list.  The search function has
+an option to lock this pointer on a given record.  The application must
+be written so only one such lock is outstanding at a time. */
+
+struct Agrec_s {
+    char *name;
+    Agrec_t *next;
+    /* following this would be any programmer-defined data */
+};
+
+/* Object tag for graphs, nodes, and edges.  While there may be several structs
+for a given node or edges, there is only one unique ID (per main graph).  */
+struct Agtag_s {
+    unsigned objtype:2;                /* see literal tags below */
+    unsigned mtflock:1;                /* move-to-front lock, see above */
+    unsigned attrwf:1;         /* attrs written (parity, write.c) */
+    unsigned seq:(sizeof(unsigned) * 8 - 4);   /* sequence no. */
+    unsigned long id;          /* client  ID */
+};
+
+       /* object tags */
+#define AGRAPH                         0       /* can't exceed 2 bits. see Agtag_t. */
+#define AGNODE                         1
+#define AGOUTEDGE                      2
+#define AGINEDGE                       3       /* (1 << 1) indicates an edge tag.   */
+#define AGEDGE                                 AGOUTEDGE       /* synonym in object kind args */
+
+       /* a generic graph/node/edge header */
+struct Agobj_s {
+    Agtag_t tag;
+    Agrec_t *data;
+};
+
+#define AGTAG(obj)             (((Agobj_t*)(obj))->tag)
+#define AGTYPE(obj)            (AGTAG(obj).objtype)
+#define AGID(obj)              (AGTAG(obj).id)
+#define AGSEQ(obj)             (AGTAG(obj).seq)
+#define AGATTRWF(obj)          (AGTAG(obj).attrwf)
+#define AGDATA(obj)            (((Agobj_t*)(obj))->data)
+
+/* This is the node struct allocated per graph (or subgraph).  It resides
+in the n_dict of the graph.  The node set is maintained by libdict, but
+transparently to libgraph callers.  Every node may be given an optional
+string name at its time of creation, or it is permissible to pass NIL(char*)
+for the name. */
+
+struct Agsubnode_s {           /* the node-per-graph-or-subgraph record */
+    Dtlink_t id_link;
+    Dtlink_t seq_link;
+    Agnode_t *node;            /* the object */
+    Dtlink_t *in_id, *out_id;  /* by node/ID for random access */
+    Dtlink_t *in_seq, *out_seq;        /* by node/sequence for serial access */
+};
+
+struct Agnode_s {
+    Agobj_t base;
+    Agraph_t *root;
+    Agsubnode_t mainsub;       /* embedded for main graph */
+};
+
+struct Agedge_s {
+    Agobj_t base;
+    Dtlink_t id_link;          /* main graph only */
+    Dtlink_t seq_link;
+    Agnode_t *node;            /* the endpoint node */
+};
+
+struct Agedgepair_s {
+    Agedge_t out, in;
+};
+
+struct Agdesc_s {              /* graph descriptor */
+    unsigned directed:1;       /* if edges are asymmetric */
+    unsigned strict:1;         /* if and self, multi-edges forbidden */
+    unsigned maingraph:1;      /* if this is the top level graph */
+    unsigned flatlock:1;       /* if sets are flattened into lists in cdt */
+    unsigned no_write:1;       /* if a temporary subgraph */
+    unsigned has_attrs:1;      /* if string attr tables should be initialized */
+    unsigned has_cmpnd:1;      /* if may contain collapsed nodes */
+};
+
+/* disciplines for external resources needed by libgraph */
+
+struct Agmemdisc_s {           /* memory allocator */
+    void *(*open) (void);      /* 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);
+};
+
+struct Agiddisc_s {            /* object ID allocator */
+    void *(*open) (Agraph_t * g);      /* 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);
+};
+
+struct Agiodisc_s {
+    int (*afread) (void *chan, char *buf, int bufsize);
+    int (*putstr) (void *chan, char *str);
+    int (*flush) (void *chan); /* sync */
+    /* error messages? */
+};
+
+struct Agdisc_s {              /* user's discipline */
+    Agmemdisc_t *mem;
+    Agiddisc_t *id;
+    Agiodisc_t *io;
+};
+
+       /* default resource disciplines */
+extern Agmemdisc_t AgMemDisc;
+extern Agiddisc_t AgIdDisc;
+extern Agiodisc_t AgIoDisc;
+
+extern Agdisc_t AgDefaultDisc;
+
+struct Agdstate_s {
+    void *mem;
+    void *id;
+    /* IO must be initialized and finalized outside Cgraph,
+     * and channels (FILES) are passed as void* arguments. */
+};
+
+typedef void (*agobjfn_t) (Agraph_t * g, Agobj_t * obj, void *arg);
+typedef void (*agobjupdfn_t) (Agraph_t * g, Agobj_t * obj, void *arg,
+                             Agsym_t * sym);
+
+struct Agcbdisc_s {
+    struct {
+       agobjfn_t ins;
+       agobjupdfn_t mod;
+       agobjfn_t del;
+    } graph, node, edge;
+};
+
+struct Agcbstack_s {           /* object event callbacks */
+    Agcbdisc_t *f;             /* methods */
+    void *state;               /* closure */
+    Agcbstack_t *prev;         /* kept in a stack, unlike other disciplines */
+};
+
+struct Agclos_s {
+    Agdisc_t disc;             /* resource discipline functions */
+    Agdstate_t state;          /* resource closures */
+    Dict_t *strdict;           /* shared string dict */
+    unsigned long seq[3];      /* local object sequence number counter */
+    Agcbstack_t *cb;           /* user and system callback function stacks */
+    unsigned char callbacks_enabled;   /* issue user callbacks or hold them? */
+    Dict_t *lookup_by_name[3];
+    Dict_t *lookup_by_id[3];
+};
+
+struct Agraph_s {
+    Agobj_t base;
+    Agdesc_t desc;
+    Dtlink_t link;
+    Dict_t *n_seq;             /* the node set in sequence */
+    Dict_t *n_id;              /* the node set indexed by ID */
+    Dict_t *e_seq, *e_id;      /* holders for edge sets */
+    Dict_t *g_dict;            /* subgraphs - descendants */
+    Agraph_t *parent, *root;   /* subgraphs - ancestors */
+    Agclos_t *clos;            /* shared resources */
+};
+
+
+#if _PACKAGE_ast
+/* fine control of object callbacks */
+#   if defined(_BLD_agraph) && defined(__EXPORT__)
+#      define extern  __EXPORT__
+#   endif
+#   if !defined(_BLD_agraph) && defined(__IMPORT__)
+#      define extern  __IMPORT__
+#   endif
+#endif
+
+extern void agpushdisc(Agraph_t * g, Agcbdisc_t * disc, void *state);
+extern int agpopdisc(Agraph_t * g, Agcbdisc_t * disc);
+extern int agcallbacks(Agraph_t * g, int flag);        /* return prev value */
+
+/* graphs */
+extern Agraph_t *agopen(char *name, Agdesc_t desc, Agdisc_t * disc);
+extern int agclose(Agraph_t * g);
+extern Agraph_t *agread(void *chan, Agdisc_t * disc);
+extern void agreadline(int);
+extern void agsetfile(char *);
+extern Agraph_t *agconcat(Agraph_t * g, void *chan, Agdisc_t * disc);
+extern int agwrite(Agraph_t * g, void *chan);
+extern int agisdirected(Agraph_t * g);
+extern int agisundirected(Agraph_t * g);
+extern int agisstrict(Agraph_t * g);
+
+/* nodes */
+extern Agnode_t *agnode(Agraph_t * g, char *name, int createflag);
+extern Agnode_t *agidnode(Agraph_t * g, unsigned long id, int createflag);
+extern Agnode_t *agsubnode(Agraph_t * g, Agnode_t * n, int createflag);
+extern Agnode_t *agfstnode(Agraph_t * g);
+extern Agnode_t *agnxtnode(Agraph_t * g, Agnode_t * n);
+extern Agnode_t *aglstnode(Agraph_t * g);
+extern Agnode_t *agprvnode(Agraph_t * g, Agnode_t * n);
+
+extern Agsubnode_t *agsubrep(Agraph_t * g, Agnode_t * n);
+
+/* edges */
+extern Agedge_t *agedge(Agraph_t * g, Agnode_t * t, Agnode_t * h,
+                       char *name, int createflag);
+extern Agedge_t *agidedge(Agraph_t * g, Agnode_t * t, Agnode_t * h,
+                         unsigned long id, int createflag);
+extern Agedge_t *agsubedge(Agraph_t * g, Agedge_t * e, int createflag);
+extern Agedge_t *agfstin(Agraph_t * g, Agnode_t * n);
+extern Agedge_t *agnxtin(Agraph_t * g, Agedge_t * e);
+extern Agedge_t *agfstout(Agraph_t * g, Agnode_t * n);
+extern Agedge_t *agnxtout(Agraph_t * g, Agedge_t * e);
+extern Agedge_t *agfstedge(Agraph_t * g, Agnode_t * n);
+extern Agedge_t *agnxtedge(Agraph_t * g, Agedge_t * e, Agnode_t * n);
+
+/* generic */
+extern Agraph_t *agraphof(void *);
+extern char *agnameof(void *);
+extern int agrelabel(void *obj, char *name);   /* scary */
+extern int agrelabel_node(Agnode_t * n, char *newname);
+extern int agdelete(Agraph_t * g, void *obj);
+extern long agdelsubg(Agraph_t * g, Agraph_t * sub);   /* could be agclose */
+extern int agdelnode(Agraph_t * g, Agnode_t * arg_n);
+extern int agdeledge(Agraph_t * g, Agedge_t * arg_e);
+extern Agobj_t *agrebind(Agraph_t * g, Agobj_t * obj);
+extern int agobjkind(void *);
+
+/* strings */
+extern char *agstrdup(Agraph_t *, char *);
+extern char *agstrdup_html(Agraph_t *, char *);
+extern int aghtmlstr(char *);
+extern char *agstrbind(Agraph_t * g, char *);
+extern int agstrfree(Agraph_t *, char *);
+extern char *agstrcanon(char *, char *);
+char *agcanonStr(char *str);  /* manages its own buf */
+
+/* definitions for dynamic string attributes */
+struct Agattr_s {              /* dynamic string attributes */
+    Agrec_t h;                 /* common data header */
+    Dict_t *dict;              /* shared dict to interpret attr field */
+    char **str;                        /* the attribute string values */
+};
+
+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 */
+};
+
+struct Agdatadict_s {          /* set of dictionaries per graph */
+    Agrec_t h;                 /* installed in list of graph recs */
+    struct {
+       Dict_t *n, *e, *g;
+    } dict;
+};
+
+extern Agsym_t *agattr(Agraph_t * g, int kind, char *name, char *value);
+extern Agsym_t *agattrsym(void *obj, char *name);
+extern Agsym_t *agnxtattr(Agraph_t * g, int kind, Agsym_t * attr);
+extern int      agcopyattr(void *, void *);
+
+extern void *agbindrec(void *obj, char *name, unsigned int size,
+                      int move_to_front);
+extern Agrec_t *aggetrec(void *obj, char *name, int move_to_front);
+extern int agdelrec(void *obj, char *name);
+extern void aginit(Agraph_t * g, int kind, char *rec_name, int rec_size,
+                  int move_to_front);
+extern void agclean(Agraph_t * g, int kind, char *rec_name);
+
+extern char *agget(void *obj, char *name);
+extern char *agxget(void *obj, Agsym_t * sym);
+extern int agset(void *obj, char *name, char *value);
+extern int agxset(void *obj, Agsym_t * sym, char *value);
+extern int agsafeset(void* obj, char* name, char* value, char* def);
+
+/* defintions for subgraphs */
+extern Agraph_t *agsubg(Agraph_t * g, char *name, int cflag);  /* constructor */
+extern Agraph_t *agidsubg(Agraph_t * g, unsigned long id, int cflag);  /* constructor */
+extern Agraph_t *agfstsubg(Agraph_t * g), *agnxtsubg(Agraph_t * subg);
+extern Agraph_t *agparent(Agraph_t * g), *agroot(Agraph_t * g);
+
+/* set cardinality */
+extern int agnnodes(Agraph_t * g), agnedges(Agraph_t * g);
+extern int agdegree(Agraph_t * g, Agnode_t * n, int in, int out);
+
+/* memory */
+extern void *agalloc(Agraph_t * g, size_t size);
+extern void *agrealloc(Agraph_t * g, void *ptr, size_t oldsize,
+                      size_t size);
+extern void agfree(Agraph_t * g, void *ptr);
+extern struct _vmalloc_s *agheap(Agraph_t * g);
+
+/* an engineering compromise is a joy forever */
+extern void aginternalmapclearlocalnames(Agraph_t * g);
+
+#define agnew(g,t)             ((t*)agalloc(g,sizeof(t)))
+#define agnnew(g,n,t)  ((t*)agalloc(g,(n)*sizeof(t)))
+
+/* error handling */
+typedef enum { AGWARN, AGERR, AGMAX, AGPREV } agerrlevel_t;
+extern agerrlevel_t agerrno;
+extern void agseterr(agerrlevel_t);
+extern char *aglasterr(void);
+extern int agerr(agerrlevel_t level, char *fmt, ...);
+extern void agerrorf(char *fmt, ...);
+extern void agwarningf(char *fmt, ...);
+extern int agerrors(void);
+
+/* data access macros */
+/* this assumes that e[0] is out and e[1] is inedge, see edgepair in edge.c  */
+#define AGIN2OUT(e)            ((e)-1)
+#define AGOUT2IN(e)            ((e)+1)
+#define AGOPP(e)               ((AGTYPE(e)==AGINEDGE)?AGIN2OUT(e):AGOUT2IN(e))
+#define AGMKOUT(e)             (AGTYPE(e) == AGOUTEDGE? (e): AGIN2OUT(e))
+#define AGMKIN(e)              (AGTYPE(e) == AGINEDGE?  (e): AGOUT2IN(e))
+#define AGTAIL(e)              (AGMKIN(e)->node)
+#define AGHEAD(e)              (AGMKOUT(e)->node)
+#define agtail(e)              AGTAIL(e)
+#define aghead(e)              AGHEAD(e)
+#define agopp(e)               AGOPP(e)
+
+#define TAILPORT_ID            "tailport"
+#define HEADPORT_ID            "headport"
+
+#if _PACKAGE_ast
+#   if !defined(_BLD_agraph) && defined(__IMPORT__)
+#      define extern  __IMPORT__
+#   endif
+#endif
+
+extern Agdesc_t Agdirected, Agstrictdirected, Agundirected,
+    Agstrictundirected;
+
+#undef extern
+#if _PACKAGE_ast
+_END_EXTERNS_
+#endif
+#endif