| 1 | /* $Id$ $Revision$ */ | 
|---|
| 2 | /* vim:set shiftwidth=4 ts=8: */ | 
|---|
| 3 |  | 
|---|
| 4 | /************************************************************************* | 
|---|
| 5 | * Copyright (c) 2011 AT&T Intellectual Property | 
|---|
| 6 | * All rights reserved. This program and the accompanying materials | 
|---|
| 7 | * are made available under the terms of the Eclipse Public License v1.0 | 
|---|
| 8 | * which accompanies this distribution, and is available at | 
|---|
| 9 | * http://www.eclipse.org/legal/epl-v10.html | 
|---|
| 10 | * | 
|---|
| 11 | * Contributors: See CVS logs. Details at http://www.graphviz.org/ | 
|---|
| 12 | *************************************************************************/ | 
|---|
| 13 |  | 
|---|
| 14 | #ifndef ATT_GRAPH_H | 
|---|
| 15 | #define ATT_GRAPH_H | 
|---|
| 16 |  | 
|---|
| 17 | #include <inttypes.h> | 
|---|
| 18 | #include "cdt.h" | 
|---|
| 19 |  | 
|---|
| 20 | #ifdef __cplusplus | 
|---|
| 21 | extern "C"{ | 
|---|
| 22 | #endif | 
|---|
| 23 |  | 
|---|
| 24 | #ifdef _WIN32 | 
|---|
| 25 | #   ifdef EXPORT_CGRAPH | 
|---|
| 26 | #       define CGRAPH_API __declspec(dllexport) | 
|---|
| 27 | #   else | 
|---|
| 28 | #       define CGRAPH_API __declspec(dllimport) | 
|---|
| 29 | #   endif | 
|---|
| 30 | #else | 
|---|
| 31 | #   define CGRAPH_API extern | 
|---|
| 32 | #endif | 
|---|
| 33 |  | 
|---|
| 34 | #ifndef FALSE | 
|---|
| 35 | #define FALSE (0) | 
|---|
| 36 | #endif | 
|---|
| 37 | #ifndef TRUE | 
|---|
| 38 | #define TRUE (!FALSE) | 
|---|
| 39 | #endif | 
|---|
| 40 | #ifndef NOT | 
|---|
| 41 | #define	NOT(x)			(!(x)) | 
|---|
| 42 | #endif | 
|---|
| 43 | #ifndef NIL | 
|---|
| 44 | #define NIL(type)		((type)0) | 
|---|
| 45 | #endif | 
|---|
| 46 | #define NILgraph		NIL(Agraph_t*) | 
|---|
| 47 | #define NILnode			NIL(Agnode_t*) | 
|---|
| 48 | #define NILedge			NIL(Agedge_t*) | 
|---|
| 49 | #define NILsym			NIL(Agsym_t*) | 
|---|
| 50 |  | 
|---|
| 51 | typedef uint64_t IDTYPE; | 
|---|
| 52 |  | 
|---|
| 53 | /* forward struct type declarations */ | 
|---|
| 54 | typedef struct Agtag_s Agtag_t; | 
|---|
| 55 | typedef struct Agobj_s Agobj_t;	/* generic object header */ | 
|---|
| 56 | typedef struct Agraph_s Agraph_t;	/* graph, subgraph (or hyperedge) */ | 
|---|
| 57 | typedef struct Agnode_s Agnode_t;	/* node (atom) */ | 
|---|
| 58 | typedef struct Agedge_s Agedge_t;	/* node pair */ | 
|---|
| 59 | typedef struct Agdesc_s Agdesc_t;	/* graph descriptor */ | 
|---|
| 60 | typedef struct Agmemdisc_s Agmemdisc_t;	/* memory allocator */ | 
|---|
| 61 | typedef struct Agiddisc_s Agiddisc_t;	/* object ID allocator */ | 
|---|
| 62 | typedef struct Agiodisc_s Agiodisc_t;	/* IO services */ | 
|---|
| 63 | typedef struct Agdisc_s Agdisc_t;	/* union of client discipline methods */ | 
|---|
| 64 | typedef struct Agdstate_s Agdstate_t;	/* client state (closures) */ | 
|---|
| 65 | typedef struct Agsym_s Agsym_t;	/* string attribute descriptors */ | 
|---|
| 66 | typedef struct Agattr_s Agattr_t;	/* string attribute container */ | 
|---|
| 67 | typedef struct Agcbdisc_s Agcbdisc_t;	/* client event callbacks */ | 
|---|
| 68 | typedef struct Agcbstack_s Agcbstack_t;	/* enclosing state for cbdisc */ | 
|---|
| 69 | typedef struct Agclos_s Agclos_t;	/* common fields for graph/subgs */ | 
|---|
| 70 | typedef struct Agrec_s Agrec_t;	/* generic runtime record */ | 
|---|
| 71 | typedef struct Agdatadict_s Agdatadict_t;	/* set of dictionaries per graph */ | 
|---|
| 72 | typedef struct Agedgepair_s Agedgepair_t;	/* the edge object */ | 
|---|
| 73 | typedef struct Agsubnode_s Agsubnode_t; | 
|---|
| 74 |  | 
|---|
| 75 | /* Header of a user record.  These records are attached by client programs | 
|---|
| 76 | dynamically at runtime.  A unique string ID must be given to each record | 
|---|
| 77 | attached to the same object.  Cgraph has functions to create, search for, | 
|---|
| 78 | and delete these records.   The records are maintained in a circular list, | 
|---|
| 79 | with obj->data pointing somewhere in the list.  The search function has | 
|---|
| 80 | an option to lock this pointer on a given record.  The application must | 
|---|
| 81 | be written so only one such lock is outstanding at a time. */ | 
|---|
| 82 |  | 
|---|
| 83 | struct Agrec_s { | 
|---|
| 84 | char *name; | 
|---|
| 85 | Agrec_t *next; | 
|---|
| 86 | /* following this would be any programmer-defined data */ | 
|---|
| 87 | }; | 
|---|
| 88 |  | 
|---|
| 89 | /* Object tag for graphs, nodes, and edges.  While there may be several structs | 
|---|
| 90 | for a given node or edges, there is only one unique ID (per main graph).  */ | 
|---|
| 91 | struct Agtag_s { | 
|---|
| 92 | unsigned objtype:2;		/* see literal tags below */ | 
|---|
| 93 | unsigned mtflock:1;		/* move-to-front lock, see above */ | 
|---|
| 94 | unsigned attrwf:1;		/* attrs written (parity, write.c) */ | 
|---|
| 95 | unsigned seq:(sizeof(unsigned) * 8 - 4);	/* sequence no. */ | 
|---|
| 96 | IDTYPE id;		        /* client  ID */ | 
|---|
| 97 | }; | 
|---|
| 98 |  | 
|---|
| 99 | /* object tags */ | 
|---|
| 100 | #define AGRAPH				0	/* can't exceed 2 bits. see Agtag_t. */ | 
|---|
| 101 | #define AGNODE				1 | 
|---|
| 102 | #define AGOUTEDGE			2 | 
|---|
| 103 | #define AGINEDGE			3	/* (1 << 1) indicates an edge tag.   */ | 
|---|
| 104 | #define AGEDGE 				AGOUTEDGE	/* synonym in object kind args */ | 
|---|
| 105 |  | 
|---|
| 106 | /* a generic graph/node/edge header */ | 
|---|
| 107 | struct Agobj_s { | 
|---|
| 108 | Agtag_t tag; | 
|---|
| 109 | Agrec_t *data; | 
|---|
| 110 | }; | 
|---|
| 111 |  | 
|---|
| 112 | #define AGTAG(obj)		(((Agobj_t*)(obj))->tag) | 
|---|
| 113 | #define AGTYPE(obj)		(AGTAG(obj).objtype) | 
|---|
| 114 | #define AGID(obj)		(AGTAG(obj).id) | 
|---|
| 115 | #define AGSEQ(obj)		(AGTAG(obj).seq) | 
|---|
| 116 | #define AGATTRWF(obj)		(AGTAG(obj).attrwf) | 
|---|
| 117 | #define AGDATA(obj)		(((Agobj_t*)(obj))->data) | 
|---|
| 118 |  | 
|---|
| 119 | /* This is the node struct allocated per graph (or subgraph).  It resides | 
|---|
| 120 | in the n_dict of the graph.  The node set is maintained by libdict, but | 
|---|
| 121 | transparently to libgraph callers.  Every node may be given an optional | 
|---|
| 122 | string name at its time of creation, or it is permissible to pass NIL(char*) | 
|---|
| 123 | for the name. */ | 
|---|
| 124 |  | 
|---|
| 125 | struct Agsubnode_s {		/* the node-per-graph-or-subgraph record */ | 
|---|
| 126 | Dtlink_t seq_link;		/* must be first */ | 
|---|
| 127 | Dtlink_t id_link; | 
|---|
| 128 | Agnode_t *node;		/* the object */ | 
|---|
| 129 | Dtlink_t *in_id, *out_id;	/* by node/ID for random access */ | 
|---|
| 130 | Dtlink_t *in_seq, *out_seq;	/* by node/sequence for serial access */ | 
|---|
| 131 | }; | 
|---|
| 132 |  | 
|---|
| 133 | struct Agnode_s { | 
|---|
| 134 | Agobj_t base; | 
|---|
| 135 | Agraph_t *root; | 
|---|
| 136 | Agsubnode_t mainsub;	/* embedded for main graph */ | 
|---|
| 137 | }; | 
|---|
| 138 |  | 
|---|
| 139 | struct Agedge_s { | 
|---|
| 140 | Agobj_t base; | 
|---|
| 141 | Dtlink_t id_link;		/* main graph only */ | 
|---|
| 142 | Dtlink_t seq_link; | 
|---|
| 143 | Agnode_t *node;		/* the endpoint node */ | 
|---|
| 144 | }; | 
|---|
| 145 |  | 
|---|
| 146 | struct Agedgepair_s { | 
|---|
| 147 | Agedge_t out, in; | 
|---|
| 148 | }; | 
|---|
| 149 |  | 
|---|
| 150 | struct Agdesc_s {		/* graph descriptor */ | 
|---|
| 151 | unsigned directed:1;	/* if edges are asymmetric */ | 
|---|
| 152 | unsigned strict:1;		/* if multi-edges forbidden */ | 
|---|
| 153 | unsigned no_loop:1;		/* if no loops */ | 
|---|
| 154 | unsigned maingraph:1;	/* if this is the top level graph */ | 
|---|
| 155 | unsigned flatlock:1;	/* if sets are flattened into lists in cdt */ | 
|---|
| 156 | unsigned no_write:1;	/* if a temporary subgraph */ | 
|---|
| 157 | unsigned has_attrs:1;	/* if string attr tables should be initialized */ | 
|---|
| 158 | unsigned has_cmpnd:1;	/* if may contain collapsed nodes */ | 
|---|
| 159 | }; | 
|---|
| 160 |  | 
|---|
| 161 | /* disciplines for external resources needed by libgraph */ | 
|---|
| 162 |  | 
|---|
| 163 | struct Agmemdisc_s {		/* memory allocator */ | 
|---|
| 164 | void *(*open) (Agdisc_t*);	/* independent of other resources */ | 
|---|
| 165 | void *(*alloc) (void *state, size_t req); | 
|---|
| 166 | void *(*resize) (void *state, void *ptr, size_t old, size_t req); | 
|---|
| 167 | void (*free) (void *state, void *ptr); | 
|---|
| 168 | void (*close) (void *state); | 
|---|
| 169 | }; | 
|---|
| 170 |  | 
|---|
| 171 | struct Agiddisc_s {		/* object ID allocator */ | 
|---|
| 172 | void *(*open) (Agraph_t * g, Agdisc_t*);	/* associated with a graph */ | 
|---|
| 173 | long (*map) (void *state, int objtype, char *str, IDTYPE *id, | 
|---|
| 174 | int createflag); | 
|---|
| 175 | long (*alloc) (void *state, int objtype, IDTYPE id); | 
|---|
| 176 | void (*free) (void *state, int objtype, IDTYPE id); | 
|---|
| 177 | char *(*print) (void *state, int objtype, IDTYPE id); | 
|---|
| 178 | void (*close) (void *state); | 
|---|
| 179 | void (*idregister) (void *state, int objtype, void *obj); | 
|---|
| 180 | }; | 
|---|
| 181 |  | 
|---|
| 182 | struct Agiodisc_s { | 
|---|
| 183 | int (*afread) (void *chan, char *buf, int bufsize); | 
|---|
| 184 | int (*putstr) (void *chan, const char *str); | 
|---|
| 185 | int (*flush) (void *chan);	/* sync */ | 
|---|
| 186 | /* error messages? */ | 
|---|
| 187 | }; | 
|---|
| 188 |  | 
|---|
| 189 | struct Agdisc_s {		/* user's discipline */ | 
|---|
| 190 | Agmemdisc_t *mem; | 
|---|
| 191 | Agiddisc_t *id; | 
|---|
| 192 | Agiodisc_t *io; | 
|---|
| 193 | }; | 
|---|
| 194 |  | 
|---|
| 195 | /* default resource disciplines */ | 
|---|
| 196 |  | 
|---|
| 197 | CGRAPH_API Agmemdisc_t AgMemDisc; | 
|---|
| 198 | CGRAPH_API Agiddisc_t AgIdDisc; | 
|---|
| 199 | CGRAPH_API Agiodisc_t AgIoDisc; | 
|---|
| 200 |  | 
|---|
| 201 | CGRAPH_API Agdisc_t AgDefaultDisc; | 
|---|
| 202 |  | 
|---|
| 203 | struct Agdstate_s { | 
|---|
| 204 | void *mem; | 
|---|
| 205 | void *id; | 
|---|
| 206 | /* IO must be initialized and finalized outside Cgraph, | 
|---|
| 207 | * and channels (FILES) are passed as void* arguments. */ | 
|---|
| 208 | }; | 
|---|
| 209 |  | 
|---|
| 210 | typedef void (*agobjfn_t) (Agraph_t * g, Agobj_t * obj, void *arg); | 
|---|
| 211 | typedef void (*agobjupdfn_t) (Agraph_t * g, Agobj_t * obj, void *arg, | 
|---|
| 212 | Agsym_t * sym); | 
|---|
| 213 |  | 
|---|
| 214 | struct Agcbdisc_s { | 
|---|
| 215 | struct { | 
|---|
| 216 | agobjfn_t ins; | 
|---|
| 217 | agobjupdfn_t mod; | 
|---|
| 218 | agobjfn_t del; | 
|---|
| 219 | } graph, node, edge; | 
|---|
| 220 | }; | 
|---|
| 221 |  | 
|---|
| 222 | struct Agcbstack_s {		/* object event callbacks */ | 
|---|
| 223 | Agcbdisc_t *f;		/* methods */ | 
|---|
| 224 | void *state;		/* closure */ | 
|---|
| 225 | Agcbstack_t *prev;		/* kept in a stack, unlike other disciplines */ | 
|---|
| 226 | }; | 
|---|
| 227 |  | 
|---|
| 228 | struct Agclos_s { | 
|---|
| 229 | Agdisc_t disc;		/* resource discipline functions */ | 
|---|
| 230 | Agdstate_t state;		/* resource closures */ | 
|---|
| 231 | Dict_t *strdict;		/* shared string dict */ | 
|---|
| 232 | uint64_t seq[3];	/* local object sequence number counter */ | 
|---|
| 233 | Agcbstack_t *cb;		/* user and system callback function stacks */ | 
|---|
| 234 | unsigned char callbacks_enabled;	/* issue user callbacks or hold them? */ | 
|---|
| 235 | Dict_t *lookup_by_name[3]; | 
|---|
| 236 | Dict_t *lookup_by_id[3]; | 
|---|
| 237 | }; | 
|---|
| 238 |  | 
|---|
| 239 | struct Agraph_s { | 
|---|
| 240 | Agobj_t base; | 
|---|
| 241 | Agdesc_t desc; | 
|---|
| 242 | Dtlink_t link; | 
|---|
| 243 | Dict_t *n_seq;		/* the node set in sequence */ | 
|---|
| 244 | Dict_t *n_id;		/* the node set indexed by ID */ | 
|---|
| 245 | Dict_t *e_seq, *e_id;	/* holders for edge sets */ | 
|---|
| 246 | Dict_t *g_dict;		/* subgraphs - descendants */ | 
|---|
| 247 | Agraph_t *parent, *root;	/* subgraphs - ancestors */ | 
|---|
| 248 | Agclos_t *clos;		/* shared resources */ | 
|---|
| 249 | }; | 
|---|
| 250 |  | 
|---|
| 251 | CGRAPH_API void agpushdisc(Agraph_t * g, Agcbdisc_t * disc, void *state); | 
|---|
| 252 | CGRAPH_API int agpopdisc(Agraph_t * g, Agcbdisc_t * disc); | 
|---|
| 253 | CGRAPH_API int agcallbacks(Agraph_t * g, int flag);	/* return prev value */ | 
|---|
| 254 |  | 
|---|
| 255 | /* graphs */ | 
|---|
| 256 | CGRAPH_API Agraph_t *agopen(char *name, Agdesc_t desc, Agdisc_t * disc); | 
|---|
| 257 | CGRAPH_API int agclose(Agraph_t * g); | 
|---|
| 258 | CGRAPH_API Agraph_t *agread(void *chan, Agdisc_t * disc); | 
|---|
| 259 | CGRAPH_API Agraph_t *agmemread(const char *cp); | 
|---|
| 260 | CGRAPH_API void agreadline(int); | 
|---|
| 261 | CGRAPH_API void agsetfile(char *); | 
|---|
| 262 | CGRAPH_API Agraph_t *agconcat(Agraph_t * g, void *chan, Agdisc_t * disc); | 
|---|
| 263 | CGRAPH_API int agwrite(Agraph_t * g, void *chan); | 
|---|
| 264 | CGRAPH_API int agisdirected(Agraph_t * g); | 
|---|
| 265 | CGRAPH_API int agisundirected(Agraph_t * g); | 
|---|
| 266 | CGRAPH_API int agisstrict(Agraph_t * g); | 
|---|
| 267 | CGRAPH_API int agissimple(Agraph_t * g); | 
|---|
| 268 |  | 
|---|
| 269 | /* nodes */ | 
|---|
| 270 | CGRAPH_API Agnode_t *agnode(Agraph_t * g, char *name, int createflag); | 
|---|
| 271 | CGRAPH_API Agnode_t *agidnode(Agraph_t * g, IDTYPE id, int createflag); | 
|---|
| 272 | CGRAPH_API Agnode_t *agsubnode(Agraph_t * g, Agnode_t * n, int createflag); | 
|---|
| 273 | CGRAPH_API Agnode_t *agfstnode(Agraph_t * g); | 
|---|
| 274 | CGRAPH_API Agnode_t *agnxtnode(Agraph_t * g, Agnode_t * n); | 
|---|
| 275 | CGRAPH_API Agnode_t *aglstnode(Agraph_t * g); | 
|---|
| 276 | CGRAPH_API Agnode_t *agprvnode(Agraph_t * g, Agnode_t * n); | 
|---|
| 277 |  | 
|---|
| 278 | CGRAPH_API Agsubnode_t *agsubrep(Agraph_t * g, Agnode_t * n); | 
|---|
| 279 | CGRAPH_API int agnodebefore(Agnode_t *u, Agnode_t *v); /* we have no shame */ | 
|---|
| 280 |  | 
|---|
| 281 | /* edges */ | 
|---|
| 282 | CGRAPH_API Agedge_t *agedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, | 
|---|
| 283 | char *name, int createflag); | 
|---|
| 284 | CGRAPH_API Agedge_t *agidedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, | 
|---|
| 285 | IDTYPE id, int createflag); | 
|---|
| 286 | CGRAPH_API Agedge_t *agsubedge(Agraph_t * g, Agedge_t * e, int createflag); | 
|---|
| 287 | CGRAPH_API Agedge_t *agfstin(Agraph_t * g, Agnode_t * n); | 
|---|
| 288 | CGRAPH_API Agedge_t *agnxtin(Agraph_t * g, Agedge_t * e); | 
|---|
| 289 | CGRAPH_API Agedge_t *agfstout(Agraph_t * g, Agnode_t * n); | 
|---|
| 290 | CGRAPH_API Agedge_t *agnxtout(Agraph_t * g, Agedge_t * e); | 
|---|
| 291 | CGRAPH_API Agedge_t *agfstedge(Agraph_t * g, Agnode_t * n); | 
|---|
| 292 | CGRAPH_API Agedge_t *agnxtedge(Agraph_t * g, Agedge_t * e, Agnode_t * n); | 
|---|
| 293 |  | 
|---|
| 294 | /* generic */ | 
|---|
| 295 | CGRAPH_API Agraph_t *agraphof(void* obj); | 
|---|
| 296 | CGRAPH_API Agraph_t *agroot(void* obj); | 
|---|
| 297 | CGRAPH_API int agcontains(Agraph_t *, void *); | 
|---|
| 298 | CGRAPH_API char *agnameof(void *); | 
|---|
| 299 | CGRAPH_API int agrelabel(void *obj, char *name);	/* scary */ | 
|---|
| 300 | CGRAPH_API int agrelabel_node(Agnode_t * n, char *newname); | 
|---|
| 301 | CGRAPH_API int agdelete(Agraph_t * g, void *obj); | 
|---|
| 302 | CGRAPH_API long agdelsubg(Agraph_t * g, Agraph_t * sub);	/* could be agclose */ | 
|---|
| 303 | CGRAPH_API int agdelnode(Agraph_t * g, Agnode_t * arg_n); | 
|---|
| 304 | CGRAPH_API int agdeledge(Agraph_t * g, Agedge_t * arg_e); | 
|---|
| 305 | CGRAPH_API int agobjkind(void *); | 
|---|
| 306 |  | 
|---|
| 307 | /* strings */ | 
|---|
| 308 | CGRAPH_API char *agstrdup(Agraph_t *, char *); | 
|---|
| 309 | CGRAPH_API char *agstrdup_html(Agraph_t *, char *); | 
|---|
| 310 | CGRAPH_API int aghtmlstr(char *); | 
|---|
| 311 | CGRAPH_API char *agstrbind(Agraph_t * g, char *); | 
|---|
| 312 | CGRAPH_API int agstrfree(Agraph_t *, char *); | 
|---|
| 313 | CGRAPH_API char *agcanon(char *, int); | 
|---|
| 314 | CGRAPH_API char *agstrcanon(char *, char *); | 
|---|
| 315 | CGRAPH_API char *agcanonStr(char *str);  /* manages its own buf */ | 
|---|
| 316 |  | 
|---|
| 317 | /* definitions for dynamic string attributes */ | 
|---|
| 318 | struct Agattr_s {		/* dynamic string attributes */ | 
|---|
| 319 | Agrec_t h;			/* common data header */ | 
|---|
| 320 | Dict_t *dict;		/* shared dict to interpret attr field */ | 
|---|
| 321 | char **str;			/* the attribute string values */ | 
|---|
| 322 | }; | 
|---|
| 323 |  | 
|---|
| 324 | struct Agsym_s {		/* symbol in one of the above dictionaries */ | 
|---|
| 325 | Dtlink_t link; | 
|---|
| 326 | char *name;			/* attribute's name */ | 
|---|
| 327 | char *defval;		/* its default value for initialization */ | 
|---|
| 328 | int id;			/* its index in attr[] */ | 
|---|
| 329 | unsigned char kind;		/* referent object type */ | 
|---|
| 330 | unsigned char fixed;	/* immutable value */ | 
|---|
| 331 | unsigned char print;	/* always print */ | 
|---|
| 332 | }; | 
|---|
| 333 |  | 
|---|
| 334 | struct Agdatadict_s {		/* set of dictionaries per graph */ | 
|---|
| 335 | Agrec_t h;			/* installed in list of graph recs */ | 
|---|
| 336 | struct { | 
|---|
| 337 | Dict_t *n, *e, *g; | 
|---|
| 338 | } dict; | 
|---|
| 339 | }; | 
|---|
| 340 |  | 
|---|
| 341 | CGRAPH_API Agsym_t *agattr(Agraph_t * g, int kind, char *name, char *value); | 
|---|
| 342 | CGRAPH_API Agsym_t *agattrsym(void *obj, char *name); | 
|---|
| 343 | CGRAPH_API Agsym_t *agnxtattr(Agraph_t * g, int kind, Agsym_t * attr); | 
|---|
| 344 | CGRAPH_API int      agcopyattr(void *oldobj, void *newobj); | 
|---|
| 345 |  | 
|---|
| 346 | CGRAPH_API void *agbindrec(void *obj, char *name, unsigned int size, | 
|---|
| 347 | int move_to_front); | 
|---|
| 348 | CGRAPH_API Agrec_t *aggetrec(void *obj, char *name, int move_to_front); | 
|---|
| 349 | CGRAPH_API int agdelrec(void *obj, char *name); | 
|---|
| 350 | CGRAPH_API void aginit(Agraph_t * g, int kind, char *rec_name, int rec_size, | 
|---|
| 351 | int move_to_front); | 
|---|
| 352 | CGRAPH_API void agclean(Agraph_t * g, int kind, char *rec_name); | 
|---|
| 353 |  | 
|---|
| 354 | CGRAPH_API char *agget(void *obj, char *name); | 
|---|
| 355 | CGRAPH_API char *agxget(void *obj, Agsym_t * sym); | 
|---|
| 356 | CGRAPH_API int agset(void *obj, char *name, char *value); | 
|---|
| 357 | CGRAPH_API int agxset(void *obj, Agsym_t * sym, char *value); | 
|---|
| 358 | CGRAPH_API int agsafeset(void* obj, char* name, char* value, char* def); | 
|---|
| 359 |  | 
|---|
| 360 | /* defintions for subgraphs */ | 
|---|
| 361 | CGRAPH_API Agraph_t *agsubg(Agraph_t * g, char *name, int cflag);	/* constructor */ | 
|---|
| 362 | CGRAPH_API Agraph_t *agidsubg(Agraph_t * g, IDTYPE id, int cflag);	/* constructor */ | 
|---|
| 363 | CGRAPH_API Agraph_t *agfstsubg(Agraph_t * g); | 
|---|
| 364 | CGRAPH_API Agraph_t *agnxtsubg(Agraph_t * subg); | 
|---|
| 365 | CGRAPH_API Agraph_t *agparent(Agraph_t * g); | 
|---|
| 366 |  | 
|---|
| 367 | /* set cardinality */ | 
|---|
| 368 | CGRAPH_API int agnnodes(Agraph_t * g); | 
|---|
| 369 | CGRAPH_API int agnedges(Agraph_t * g); | 
|---|
| 370 | CGRAPH_API int agnsubg(Agraph_t * g); | 
|---|
| 371 | CGRAPH_API int agdegree(Agraph_t * g, Agnode_t * n, int in, int out); | 
|---|
| 372 | CGRAPH_API int agcountuniqedges(Agraph_t * g, Agnode_t * n, int in, int out); | 
|---|
| 373 |  | 
|---|
| 374 | /* memory */ | 
|---|
| 375 | CGRAPH_API void *agalloc(Agraph_t * g, size_t size); | 
|---|
| 376 | CGRAPH_API void *agrealloc(Agraph_t * g, void *ptr, size_t oldsize, | 
|---|
| 377 | size_t size); | 
|---|
| 378 | CGRAPH_API void agfree(Agraph_t * g, void *ptr); | 
|---|
| 379 | CGRAPH_API struct _vmalloc_s *agheap(Agraph_t * g); | 
|---|
| 380 |  | 
|---|
| 381 | /* an engineering compromise is a joy forever */ | 
|---|
| 382 | CGRAPH_API void aginternalmapclearlocalnames(Agraph_t * g); | 
|---|
| 383 |  | 
|---|
| 384 | #define agnew(g,t)		((t*)agalloc(g,sizeof(t))) | 
|---|
| 385 | #define agnnew(g,n,t)	((t*)agalloc(g,(n)*sizeof(t))) | 
|---|
| 386 |  | 
|---|
| 387 | /* error handling */ | 
|---|
| 388 | typedef enum { AGWARN, AGERR, AGMAX, AGPREV } agerrlevel_t; | 
|---|
| 389 | typedef int (*agusererrf) (char*); | 
|---|
| 390 | CGRAPH_API agerrlevel_t agseterr(agerrlevel_t); | 
|---|
| 391 | CGRAPH_API char *aglasterr(void); | 
|---|
| 392 | CGRAPH_API int agerr(agerrlevel_t level, const char *fmt, ...); | 
|---|
| 393 | CGRAPH_API void agerrorf(const char *fmt, ...); | 
|---|
| 394 | CGRAPH_API void agwarningf(const char *fmt, ...); | 
|---|
| 395 | CGRAPH_API int agerrors(void); | 
|---|
| 396 | CGRAPH_API int agreseterrors(void); | 
|---|
| 397 | CGRAPH_API agusererrf agseterrf(agusererrf); | 
|---|
| 398 |  | 
|---|
| 399 | /* data access macros */ | 
|---|
| 400 | /* this assumes that e[0] is out and e[1] is inedge, see edgepair in edge.c  */ | 
|---|
| 401 | #define AGIN2OUT(e)		((e)-1) | 
|---|
| 402 | #define AGOUT2IN(e)		((e)+1) | 
|---|
| 403 | #define AGOPP(e)		((AGTYPE(e)==AGINEDGE)?AGIN2OUT(e):AGOUT2IN(e)) | 
|---|
| 404 | #define AGMKOUT(e)		(AGTYPE(e) == AGOUTEDGE? (e): AGIN2OUT(e)) | 
|---|
| 405 | #define AGMKIN(e)		(AGTYPE(e) == AGINEDGE?  (e): AGOUT2IN(e)) | 
|---|
| 406 | #define AGTAIL(e)		(AGMKIN(e)->node) | 
|---|
| 407 | #define AGHEAD(e)		(AGMKOUT(e)->node) | 
|---|
| 408 | #define AGEQEDGE(e,f)		(AGMKOUT(e) == AGMKOUT(f)) | 
|---|
| 409 | /* These macros are also exposed as functions, so they can be linked against. */ | 
|---|
| 410 | #define agtail(e)		AGTAIL(e) | 
|---|
| 411 | #define aghead(e)		AGHEAD(e) | 
|---|
| 412 | #define agopp(e)		AGOPP(e) | 
|---|
| 413 | #define ageqedge(e,f)		AGEQEDGE(e,f) | 
|---|
| 414 |  | 
|---|
| 415 | #define TAILPORT_ID		"tailport" | 
|---|
| 416 | #define HEADPORT_ID		"headport" | 
|---|
| 417 |  | 
|---|
| 418 | CGRAPH_API Agdesc_t Agdirected; | 
|---|
| 419 | CGRAPH_API Agdesc_t Agstrictdirected; | 
|---|
| 420 | CGRAPH_API Agdesc_t Agundirected; | 
|---|
| 421 | CGRAPH_API Agdesc_t Agstrictundirected; | 
|---|
| 422 |  | 
|---|
| 423 | /* fast graphs */ | 
|---|
| 424 | void agflatten(Agraph_t * g, int flag); | 
|---|
| 425 | typedef Agsubnode_t	Agnoderef_t; | 
|---|
| 426 | typedef Dtlink_t	Agedgeref_t; | 
|---|
| 427 |  | 
|---|
| 428 | #define AGHEADPOINTER(g)	((Agnoderef_t*)(g->n_seq->data->hh._head)) | 
|---|
| 429 | #define AGRIGHTPOINTER(rep)  	((Agnoderef_t*)((rep)->seq_link.right?((void*)((rep)->seq_link.right) - offsetof(Agsubnode_t,seq_link)):0)) | 
|---|
| 430 | #define AGLEFTPOINTER(rep)  	((Agnoderef_t*)((rep)->seq_link.hl._left?((void*)((rep)->seq_link.hl._left) - offsetof(Agsubnode_t,seq_link)):0)) | 
|---|
| 431 |  | 
|---|
| 432 | #define FIRSTNREF(g)	(agflatten(g,1), AGHEADPOINTER(g)) | 
|---|
| 433 |  | 
|---|
| 434 | #define NEXTNREF(g,rep)  	(AGRIGHTPOINTER(rep) == AGHEADPOINTER(g)?0:AGRIGHTPOINTER(rep)) | 
|---|
| 435 |  | 
|---|
| 436 | #define PREVNREF(g,rep)  	(((rep)==AGHEADPOINTER(g))?0:(AGLEFTPOINTER(rep))) | 
|---|
| 437 |  | 
|---|
| 438 | #define LASTNREF(g)		(agflatten(g,1), AGHEADPOINTER(g)?AGLEFTPOINTER(AGHEADPOINTER(g)):0) | 
|---|
| 439 | #define NODEOF(rep)		((rep)->node) | 
|---|
| 440 |  | 
|---|
| 441 | #define FIRSTOUTREF(g,sn)	(agflatten(g,1), (sn)->out_seq) | 
|---|
| 442 | #define LASTOUTREF(g,sn)	(agflatten(g,1), (Agedgeref_t*)dtlast(sn->out_seq)) | 
|---|
| 443 | #define FIRSTINREF(g,sn)	(agflatten(g,1), (sn)->in_seq) | 
|---|
| 444 | #define NEXTEREF(g,rep)  	((rep)->right) | 
|---|
| 445 | #define PREVEREF(g,rep)  	((rep)->hl._left) | 
|---|
| 446 | /* this is expedient but a bit slimey because it "knows" that dict entries of both nodes | 
|---|
| 447 | and edges are embedded in main graph objects but allocated separately in subgraphs */ | 
|---|
| 448 | #define AGSNMAIN(sn)        ((sn)==(&((sn)->node->mainsub))) | 
|---|
| 449 | #define EDGEOF(sn,rep)		(AGSNMAIN(sn)?((Agedge_t*)((unsigned char*)(rep) - offsetof(Agedge_t,seq_link))) : ((Dthold_t*)(rep))->obj) | 
|---|
| 450 |  | 
|---|
| 451 | #ifdef __cplusplus | 
|---|
| 452 | } | 
|---|
| 453 | #endif | 
|---|
| 454 | #endif | 
|---|
| 455 |  | 
|---|