wolffd@0: /* $Id: cgraph.h,v 1.16 2009/07/10 21:10:32 erg Exp $ $Revision: 1.16 $ */ wolffd@0: /* vim:set shiftwidth=4 ts=8: */ wolffd@0: wolffd@0: /********************************************************** wolffd@0: * This software is part of the graphviz package * wolffd@0: * http://www.graphviz.org/ * wolffd@0: * * wolffd@0: * Copyright (c) 1994-2004 AT&T Corp. * wolffd@0: * and is licensed under the * wolffd@0: * Common Public License, Version 1.0 * wolffd@0: * by AT&T Corp. * wolffd@0: * * wolffd@0: * Information and Software Systems Research * wolffd@0: * AT&T Research, Florham Park NJ * wolffd@0: **********************************************************/ wolffd@0: wolffd@0: #ifndef ATT_GRAPH_H wolffd@0: #define ATT_GRAPH_H wolffd@0: wolffd@0: #include "cdt.h" wolffd@0: wolffd@0: #ifdef __cplusplus wolffd@0: extern "C" { wolffd@0: #endif wolffd@0: wolffd@0: #ifndef FALSE wolffd@0: #define FALSE (0) wolffd@0: #endif wolffd@0: #ifndef TRUE wolffd@0: #define TRUE (!FALSE) wolffd@0: #endif wolffd@0: #ifndef NOT wolffd@0: #define NOT(x) (!(x)) wolffd@0: #endif wolffd@0: #ifndef NIL wolffd@0: #define NIL(type) ((type)0) wolffd@0: #endif wolffd@0: #define NILgraph NIL(Agraph_t*) wolffd@0: #define NILnode NIL(Agnode_t*) wolffd@0: #define NILedge NIL(Agedge_t*) wolffd@0: #define NILsym NIL(Agsym_t*) wolffd@0: wolffd@0: /* forward struct type declarations */ wolffd@0: typedef struct Agtag_s Agtag_t; wolffd@0: typedef struct Agobj_s Agobj_t; /* generic object header */ wolffd@0: typedef struct Agraph_s Agraph_t; /* graph, subgraph (or hyperedge) */ wolffd@0: typedef struct Agnode_s Agnode_t; /* node (atom) */ wolffd@0: typedef struct Agedge_s Agedge_t; /* node pair */ wolffd@0: typedef struct Agdesc_s Agdesc_t; /* graph descriptor */ wolffd@0: typedef struct Agmemdisc_s Agmemdisc_t; /* memory allocator */ wolffd@0: typedef struct Agiddisc_s Agiddisc_t; /* object ID allocator */ wolffd@0: typedef struct Agiodisc_s Agiodisc_t; /* IO services */ wolffd@0: typedef struct Agdisc_s Agdisc_t; /* union of client discipline methods */ wolffd@0: typedef struct Agdstate_s Agdstate_t; /* client state (closures) */ wolffd@0: typedef struct Agsym_s Agsym_t; /* string attribute descriptors */ wolffd@0: typedef struct Agattr_s Agattr_t; /* string attribute container */ wolffd@0: typedef struct Agcbdisc_s Agcbdisc_t; /* client event callbacks */ wolffd@0: typedef struct Agcbstack_s Agcbstack_t; /* enclosing state for cbdisc */ wolffd@0: typedef struct Agclos_s Agclos_t; /* common fields for graph/subgs */ wolffd@0: typedef struct Agrec_s Agrec_t; /* generic runtime record */ wolffd@0: typedef struct Agdatadict_s Agdatadict_t; /* set of dictionaries per graph */ wolffd@0: typedef struct Agedgepair_s Agedgepair_t; /* the edge object */ wolffd@0: typedef struct Agsubnode_s Agsubnode_t; wolffd@0: wolffd@0: /* Header of a user record. These records are attached by client programs wolffd@0: dynamically at runtime. A unique string ID must be given to each record wolffd@0: attached to the same object. Cgraph has functions to create, search for, wolffd@0: and delete these records. The records are maintained in a circular list, wolffd@0: with obj->data pointing somewhere in the list. The search function has wolffd@0: an option to lock this pointer on a given record. The application must wolffd@0: be written so only one such lock is outstanding at a time. */ wolffd@0: wolffd@0: struct Agrec_s { wolffd@0: char *name; wolffd@0: Agrec_t *next; wolffd@0: /* following this would be any programmer-defined data */ wolffd@0: }; wolffd@0: wolffd@0: /* Object tag for graphs, nodes, and edges. While there may be several structs wolffd@0: for a given node or edges, there is only one unique ID (per main graph). */ wolffd@0: struct Agtag_s { wolffd@0: unsigned objtype:2; /* see literal tags below */ wolffd@0: unsigned mtflock:1; /* move-to-front lock, see above */ wolffd@0: unsigned attrwf:1; /* attrs written (parity, write.c) */ wolffd@0: unsigned seq:(sizeof(unsigned) * 8 - 4); /* sequence no. */ wolffd@0: unsigned long id; /* client ID */ wolffd@0: }; wolffd@0: wolffd@0: /* object tags */ wolffd@0: #define AGRAPH 0 /* can't exceed 2 bits. see Agtag_t. */ wolffd@0: #define AGNODE 1 wolffd@0: #define AGOUTEDGE 2 wolffd@0: #define AGINEDGE 3 /* (1 << 1) indicates an edge tag. */ wolffd@0: #define AGEDGE AGOUTEDGE /* synonym in object kind args */ wolffd@0: wolffd@0: /* a generic graph/node/edge header */ wolffd@0: struct Agobj_s { wolffd@0: Agtag_t tag; wolffd@0: Agrec_t *data; wolffd@0: }; wolffd@0: wolffd@0: #define AGTAG(obj) (((Agobj_t*)(obj))->tag) wolffd@0: #define AGTYPE(obj) (AGTAG(obj).objtype) wolffd@0: #define AGID(obj) (AGTAG(obj).id) wolffd@0: #define AGSEQ(obj) (AGTAG(obj).seq) wolffd@0: #define AGATTRWF(obj) (AGTAG(obj).attrwf) wolffd@0: #define AGDATA(obj) (((Agobj_t*)(obj))->data) wolffd@0: wolffd@0: /* This is the node struct allocated per graph (or subgraph). It resides wolffd@0: in the n_dict of the graph. The node set is maintained by libdict, but wolffd@0: transparently to libgraph callers. Every node may be given an optional wolffd@0: string name at its time of creation, or it is permissible to pass NIL(char*) wolffd@0: for the name. */ wolffd@0: wolffd@0: struct Agsubnode_s { /* the node-per-graph-or-subgraph record */ wolffd@0: Dtlink_t seq_link; /* must be first */ wolffd@0: Dtlink_t id_link; wolffd@0: Agnode_t *node; /* the object */ wolffd@0: Dtlink_t *in_id, *out_id; /* by node/ID for random access */ wolffd@0: Dtlink_t *in_seq, *out_seq; /* by node/sequence for serial access */ wolffd@0: }; wolffd@0: wolffd@0: struct Agnode_s { wolffd@0: Agobj_t base; wolffd@0: Agraph_t *root; wolffd@0: Agsubnode_t mainsub; /* embedded for main graph */ wolffd@0: }; wolffd@0: wolffd@0: struct Agedge_s { wolffd@0: Agobj_t base; wolffd@0: Dtlink_t id_link; /* main graph only */ wolffd@0: Dtlink_t seq_link; wolffd@0: Agnode_t *node; /* the endpoint node */ wolffd@0: }; wolffd@0: wolffd@0: struct Agedgepair_s { wolffd@0: Agedge_t out, in; wolffd@0: }; wolffd@0: wolffd@0: struct Agdesc_s { /* graph descriptor */ wolffd@0: unsigned directed:1; /* if edges are asymmetric */ wolffd@0: unsigned strict:1; /* if multi-edges forbidden */ wolffd@0: unsigned no_loop:1; /* if no loops */ wolffd@0: unsigned maingraph:1; /* if this is the top level graph */ wolffd@0: unsigned flatlock:1; /* if sets are flattened into lists in cdt */ wolffd@0: unsigned no_write:1; /* if a temporary subgraph */ wolffd@0: unsigned has_attrs:1; /* if string attr tables should be initialized */ wolffd@0: unsigned has_cmpnd:1; /* if may contain collapsed nodes */ wolffd@0: }; wolffd@0: wolffd@0: /* disciplines for external resources needed by libgraph */ wolffd@0: wolffd@0: struct Agmemdisc_s { /* memory allocator */ wolffd@0: void *(*open) (void); /* independent of other resources */ wolffd@0: void *(*alloc) (void *state, size_t req); wolffd@0: void *(*resize) (void *state, void *ptr, size_t old, size_t req); wolffd@0: void (*free) (void *state, void *ptr); wolffd@0: void (*close) (void *state); wolffd@0: }; wolffd@0: wolffd@0: struct Agiddisc_s { /* object ID allocator */ wolffd@0: void *(*open) (Agraph_t * g); /* associated with a graph */ wolffd@0: long (*map) (void *state, int objtype, char *str, unsigned long *id, wolffd@0: int createflag); wolffd@0: long (*alloc) (void *state, int objtype, unsigned long id); wolffd@0: void (*free) (void *state, int objtype, unsigned long id); wolffd@0: char *(*print) (void *state, int objtype, unsigned long id); wolffd@0: void (*close) (void *state); wolffd@0: }; wolffd@0: wolffd@0: struct Agiodisc_s { wolffd@0: int (*afread) (void *chan, char *buf, int bufsize); wolffd@0: int (*putstr) (void *chan, const char *str); wolffd@0: int (*flush) (void *chan); /* sync */ wolffd@0: /* error messages? */ wolffd@0: }; wolffd@0: wolffd@0: struct Agdisc_s { /* user's discipline */ wolffd@0: Agmemdisc_t *mem; wolffd@0: Agiddisc_t *id; wolffd@0: Agiodisc_t *io; wolffd@0: }; wolffd@0: wolffd@0: /* default resource disciplines */ wolffd@0: #if !defined(_BLD_cgraph) && defined(GVDLL) wolffd@0: #define extern __declspec(dllimport) wolffd@0: #endif wolffd@0: wolffd@0: /*visual studio*/ wolffd@0: #ifdef WIN32_DLL wolffd@0: #ifndef CGRAPH_EXPORTS wolffd@0: #define extern __declspec(dllimport) wolffd@0: #endif wolffd@0: #endif wolffd@0: /*end visual studio*/ wolffd@0: wolffd@0: extern Agmemdisc_t AgMemDisc; wolffd@0: extern Agiddisc_t AgIdDisc; wolffd@0: extern Agiodisc_t AgIoDisc; wolffd@0: wolffd@0: extern Agdisc_t AgDefaultDisc; wolffd@0: #undef extern wolffd@0: wolffd@0: struct Agdstate_s { wolffd@0: void *mem; wolffd@0: void *id; wolffd@0: /* IO must be initialized and finalized outside Cgraph, wolffd@0: * and channels (FILES) are passed as void* arguments. */ wolffd@0: }; wolffd@0: wolffd@0: typedef void (*agobjfn_t) (Agraph_t * g, Agobj_t * obj, void *arg); wolffd@0: typedef void (*agobjupdfn_t) (Agraph_t * g, Agobj_t * obj, void *arg, wolffd@0: Agsym_t * sym); wolffd@0: wolffd@0: struct Agcbdisc_s { wolffd@0: struct { wolffd@0: agobjfn_t ins; wolffd@0: agobjupdfn_t mod; wolffd@0: agobjfn_t del; wolffd@0: } graph, node, edge; wolffd@0: }; wolffd@0: wolffd@0: struct Agcbstack_s { /* object event callbacks */ wolffd@0: Agcbdisc_t *f; /* methods */ wolffd@0: void *state; /* closure */ wolffd@0: Agcbstack_t *prev; /* kept in a stack, unlike other disciplines */ wolffd@0: }; wolffd@0: wolffd@0: struct Agclos_s { wolffd@0: Agdisc_t disc; /* resource discipline functions */ wolffd@0: Agdstate_t state; /* resource closures */ wolffd@0: Dict_t *strdict; /* shared string dict */ wolffd@0: unsigned long seq[3]; /* local object sequence number counter */ wolffd@0: Agcbstack_t *cb; /* user and system callback function stacks */ wolffd@0: unsigned char callbacks_enabled; /* issue user callbacks or hold them? */ wolffd@0: Dict_t *lookup_by_name[3]; wolffd@0: Dict_t *lookup_by_id[3]; wolffd@0: }; wolffd@0: wolffd@0: struct Agraph_s { wolffd@0: Agobj_t base; wolffd@0: Agdesc_t desc; wolffd@0: Dtlink_t link; wolffd@0: Dict_t *n_seq; /* the node set in sequence */ wolffd@0: Dict_t *n_id; /* the node set indexed by ID */ wolffd@0: Dict_t *e_seq, *e_id; /* holders for edge sets */ wolffd@0: Dict_t *g_dict; /* subgraphs - descendants */ wolffd@0: Agraph_t *parent, *root; /* subgraphs - ancestors */ wolffd@0: Agclos_t *clos; /* shared resources */ wolffd@0: }; wolffd@0: wolffd@0: wolffd@0: #if _PACKAGE_ast wolffd@0: /* fine control of object callbacks */ wolffd@0: # if defined(_BLD_cgraph) && defined(__EXPORT__) wolffd@0: # define extern __EXPORT__ wolffd@0: # endif wolffd@0: # if !defined(_BLD_cgraph) && defined(__IMPORT__) wolffd@0: # define extern __IMPORT__ wolffd@0: # endif wolffd@0: #endif wolffd@0: wolffd@0: extern void agpushdisc(Agraph_t * g, Agcbdisc_t * disc, void *state); wolffd@0: extern int agpopdisc(Agraph_t * g, Agcbdisc_t * disc); wolffd@0: extern int agcallbacks(Agraph_t * g, int flag); /* return prev value */ wolffd@0: wolffd@0: /* graphs */ wolffd@0: extern Agraph_t *agopen(char *name, Agdesc_t desc, Agdisc_t * disc); wolffd@0: extern int agclose(Agraph_t * g); wolffd@0: extern Agraph_t *agread(void *chan, Agdisc_t * disc); wolffd@0: extern void agreadline(int); wolffd@0: extern void agsetfile(char *); wolffd@0: extern Agraph_t *agconcat(Agraph_t * g, void *chan, Agdisc_t * disc); wolffd@0: extern int agwrite(Agraph_t * g, void *chan); wolffd@0: extern int agisdirected(Agraph_t * g); wolffd@0: extern int agisundirected(Agraph_t * g); wolffd@0: extern int agisstrict(Agraph_t * g); wolffd@0: extern int agissimple(Agraph_t * g); wolffd@0: wolffd@0: /* nodes */ wolffd@0: extern Agnode_t *agnode(Agraph_t * g, char *name, int createflag); wolffd@0: extern Agnode_t *agidnode(Agraph_t * g, unsigned long id, int createflag); wolffd@0: extern Agnode_t *agsubnode(Agraph_t * g, Agnode_t * n, int createflag); wolffd@0: extern Agnode_t *agfstnode(Agraph_t * g); wolffd@0: extern Agnode_t *agnxtnode(Agraph_t * g, Agnode_t * n); wolffd@0: extern Agnode_t *aglstnode(Agraph_t * g); wolffd@0: extern Agnode_t *agprvnode(Agraph_t * g, Agnode_t * n); wolffd@0: wolffd@0: extern Agsubnode_t *agsubrep(Agraph_t * g, Agnode_t * n); wolffd@0: wolffd@0: /* edges */ wolffd@0: extern Agedge_t *agedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, wolffd@0: char *name, int createflag); wolffd@0: extern Agedge_t *agidedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, wolffd@0: unsigned long id, int createflag); wolffd@0: extern Agedge_t *agsubedge(Agraph_t * g, Agedge_t * e, int createflag); wolffd@0: extern Agedge_t *agfstin(Agraph_t * g, Agnode_t * n); wolffd@0: extern Agedge_t *agnxtin(Agraph_t * g, Agedge_t * e); wolffd@0: extern Agedge_t *agfstout(Agraph_t * g, Agnode_t * n); wolffd@0: extern Agedge_t *agnxtout(Agraph_t * g, Agedge_t * e); wolffd@0: extern Agedge_t *agfstedge(Agraph_t * g, Agnode_t * n); wolffd@0: extern Agedge_t *agnxtedge(Agraph_t * g, Agedge_t * e, Agnode_t * n); wolffd@0: wolffd@0: /* generic */ wolffd@0: extern Agraph_t *agraphof(void* obj); wolffd@0: extern Agraph_t *agroot(void* obj); wolffd@0: extern int agcontains(Agraph_t *, void *); wolffd@0: extern char *agnameof(void *); wolffd@0: extern int agrelabel(void *obj, char *name); /* scary */ wolffd@0: extern int agrelabel_node(Agnode_t * n, char *newname); wolffd@0: extern int agdelete(Agraph_t * g, void *obj); wolffd@0: extern long agdelsubg(Agraph_t * g, Agraph_t * sub); /* could be agclose */ wolffd@0: extern int agdelnode(Agraph_t * g, Agnode_t * arg_n); wolffd@0: extern int agdeledge(Agraph_t * g, Agedge_t * arg_e); wolffd@0: extern int agobjkind(void *); wolffd@0: wolffd@0: /* strings */ wolffd@0: extern char *agstrdup(Agraph_t *, char *); wolffd@0: extern char *agstrdup_html(Agraph_t *, char *); wolffd@0: extern int aghtmlstr(char *); wolffd@0: extern char *agstrbind(Agraph_t * g, char *); wolffd@0: extern int agstrfree(Agraph_t *, char *); wolffd@0: extern char *agstrcanon(char *, char *); wolffd@0: char *agcanonStr(char *str); /* manages its own buf */ wolffd@0: wolffd@0: /* definitions for dynamic string attributes */ wolffd@0: struct Agattr_s { /* dynamic string attributes */ wolffd@0: Agrec_t h; /* common data header */ wolffd@0: Dict_t *dict; /* shared dict to interpret attr field */ wolffd@0: char **str; /* the attribute string values */ wolffd@0: }; wolffd@0: wolffd@0: struct Agsym_s { /* symbol in one of the above dictionaries */ wolffd@0: Dtlink_t link; wolffd@0: char *name; /* attribute's name */ wolffd@0: char *defval; /* its default value for initialization */ wolffd@0: int id; /* its index in attr[] */ wolffd@0: unsigned char kind; /* referent object type */ wolffd@0: unsigned char fixed; /* immutable value */ wolffd@0: }; wolffd@0: wolffd@0: struct Agdatadict_s { /* set of dictionaries per graph */ wolffd@0: Agrec_t h; /* installed in list of graph recs */ wolffd@0: struct { wolffd@0: Dict_t *n, *e, *g; wolffd@0: } dict; wolffd@0: }; wolffd@0: wolffd@0: extern Agsym_t *agattr(Agraph_t * g, int kind, char *name, char *value); wolffd@0: extern Agsym_t *agattrsym(void *obj, char *name); wolffd@0: extern Agsym_t *agnxtattr(Agraph_t * g, int kind, Agsym_t * attr); wolffd@0: extern int agcopyattr(void *oldobj, void *newobj); wolffd@0: wolffd@0: extern void *agbindrec(void *obj, char *name, unsigned int size, wolffd@0: int move_to_front); wolffd@0: extern Agrec_t *aggetrec(void *obj, char *name, int move_to_front); wolffd@0: extern int agdelrec(void *obj, char *name); wolffd@0: extern void aginit(Agraph_t * g, int kind, char *rec_name, int rec_size, wolffd@0: int move_to_front); wolffd@0: extern void agclean(Agraph_t * g, int kind, char *rec_name); wolffd@0: wolffd@0: extern char *agget(void *obj, char *name); wolffd@0: extern char *agxget(void *obj, Agsym_t * sym); wolffd@0: extern int agset(void *obj, char *name, char *value); wolffd@0: extern int agxset(void *obj, Agsym_t * sym, char *value); wolffd@0: extern int agsafeset(void* obj, char* name, char* value, char* def); wolffd@0: wolffd@0: /* defintions for subgraphs */ wolffd@0: extern Agraph_t *agsubg(Agraph_t * g, char *name, int cflag); /* constructor */ wolffd@0: extern Agraph_t *agidsubg(Agraph_t * g, unsigned long id, int cflag); /* constructor */ wolffd@0: extern Agraph_t *agfstsubg(Agraph_t * g), *agnxtsubg(Agraph_t * subg); wolffd@0: extern Agraph_t *agparent(Agraph_t * g); wolffd@0: wolffd@0: /* set cardinality */ wolffd@0: extern int agnnodes(Agraph_t * g), agnedges(Agraph_t * g); wolffd@0: extern int agdegree(Agraph_t * g, Agnode_t * n, int in, int out); wolffd@0: extern int agcountuniqedges(Agraph_t * g, Agnode_t * n, int in, int out); wolffd@0: wolffd@0: /* memory */ wolffd@0: extern void *agalloc(Agraph_t * g, size_t size); wolffd@0: extern void *agrealloc(Agraph_t * g, void *ptr, size_t oldsize, wolffd@0: size_t size); wolffd@0: extern void agfree(Agraph_t * g, void *ptr); wolffd@0: extern struct _vmalloc_s *agheap(Agraph_t * g); wolffd@0: wolffd@0: /* an engineering compromise is a joy forever */ wolffd@0: extern void aginternalmapclearlocalnames(Agraph_t * g); wolffd@0: wolffd@0: #define agnew(g,t) ((t*)agalloc(g,sizeof(t))) wolffd@0: #define agnnew(g,n,t) ((t*)agalloc(g,(n)*sizeof(t))) wolffd@0: wolffd@0: /* error handling */ wolffd@0: typedef enum { AGWARN, AGERR, AGMAX, AGPREV } agerrlevel_t; wolffd@0: extern agerrlevel_t agerrno; wolffd@0: extern void agseterr(agerrlevel_t); wolffd@0: extern char *aglasterr(void); wolffd@0: extern int agerr(agerrlevel_t level, char *fmt, ...); wolffd@0: extern void agerrorf(char *fmt, ...); wolffd@0: extern void agwarningf(char *fmt, ...); wolffd@0: extern int agerrors(void); wolffd@0: wolffd@0: /* data access macros */ wolffd@0: /* this assumes that e[0] is out and e[1] is inedge, see edgepair in edge.c */ wolffd@0: #define AGIN2OUT(e) ((e)-1) wolffd@0: #define AGOUT2IN(e) ((e)+1) wolffd@0: #define AGOPP(e) ((AGTYPE(e)==AGINEDGE)?AGIN2OUT(e):AGOUT2IN(e)) wolffd@0: #define AGMKOUT(e) (AGTYPE(e) == AGOUTEDGE? (e): AGIN2OUT(e)) wolffd@0: #define AGMKIN(e) (AGTYPE(e) == AGINEDGE? (e): AGOUT2IN(e)) wolffd@0: #define AGTAIL(e) (AGMKIN(e)->node) wolffd@0: #define AGHEAD(e) (AGMKOUT(e)->node) wolffd@0: #define agtail(e) AGTAIL(e) wolffd@0: #define aghead(e) AGHEAD(e) wolffd@0: #define agopp(e) AGOPP(e) wolffd@0: wolffd@0: #define TAILPORT_ID "tailport" wolffd@0: #define HEADPORT_ID "headport" wolffd@0: wolffd@0: #if _PACKAGE_ast wolffd@0: # if !defined(_BLD_cgraph) && defined(__IMPORT__) wolffd@0: # define extern __IMPORT__ wolffd@0: # endif wolffd@0: #endif wolffd@0: #if !defined(_BLD_cgraph) && defined(GVDLL) wolffd@0: #define extern __declspec(dllimport) wolffd@0: #endif wolffd@0: wolffd@0: extern Agdesc_t Agdirected, Agstrictdirected, Agundirected, wolffd@0: Agstrictundirected; wolffd@0: wolffd@0: #undef extern wolffd@0: wolffd@0: /* fast graphs */ wolffd@0: void agflatten(Agraph_t * g, int flag); wolffd@0: typedef Agsubnode_t Agnoderef_t; wolffd@0: typedef Dtlink_t Agedgeref_t; wolffd@0: wolffd@0: #define AGHEADPOINTER(g) ((Agnoderef_t*)(g->n_seq->data->hh._head)) wolffd@0: #define AGRIGHTPOINTER(rep) ((Agnoderef_t*)((rep)->seq_link.right?((void*)((rep)->seq_link.right) - offsetof(Agsubnode_t,seq_link)):0)) wolffd@0: #define AGLEFTPOINTER(rep) ((Agnoderef_t*)((rep)->seq_link.hl._left?((void*)((rep)->seq_link.hl._left) - offsetof(Agsubnode_t,seq_link)):0)) wolffd@0: wolffd@0: #define FIRSTNREF(g) (agflatten(g,1), AGHEADPOINTER(g)) wolffd@0: wolffd@0: #define NEXTNREF(g,rep) (AGRIGHTPOINTER(rep) == AGHEADPOINTER(g)?0:AGRIGHTPOINTER(rep)) wolffd@0: wolffd@0: #define PREVNREF(g,rep) (((rep)==AGHEADPOINTER(g))?0:(AGLEFTPOINTER(rep))) wolffd@0: wolffd@0: #define LASTNREF(g) (agflatten(g,1), AGHEADPOINTER(g)?AGLEFTPOINTER(AGHEADPOINTER(g)):0) wolffd@0: #define NODEOF(rep) ((rep)->node) wolffd@0: wolffd@0: #define FIRSTOUTREF(g,sn) (agflatten(g,1), (sn)->out_seq) wolffd@0: #define LASTOUTREF(g,sn) (agflatten(g,1), (Agedgeref_t*)dtlast(sn->out_seq)) wolffd@0: #define FIRSTINREF(g,sn) (agflatten(g,1), (sn)->in_seq) wolffd@0: #define NEXTEREF(g,rep) ((rep)->right) wolffd@0: #define PREVEREF(g,rep) ((rep)->hl._left) wolffd@0: /* this is expedient but a bit slimey because it "knows" that dict entries of both nodes wolffd@0: and edges are embedded in main graph objects but allocated separately in subgraphs */ wolffd@0: #define AGSNMAIN(sn) ((sn)==(&((sn)->node->mainsub))) wolffd@0: #define EDGEOF(sn,rep) (AGSNMAIN(sn)?((Agedge_t*)((unsigned char*)(rep) - offsetof(Agedge_t,seq_link))) : ((Dthold_t*)(rep))->obj) wolffd@0: wolffd@0: #undef extern wolffd@0: #if _PACKAGE_ast wolffd@0: _END_EXTERNS_ wolffd@0: #endif wolffd@0: #ifdef __cplusplus wolffd@0: } wolffd@0: #endif wolffd@0: #endif