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