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);
+void agregister(Agraph_t * g, int objtype, void *obj);
/* internal set operations */
void agedgesetop(Agraph_t * g, Agedge_t * e, int insertion);
void (*free) (void *state, int objtype, unsigned long id);
char *(*print) (void *state, int objtype, unsigned long id);
void (*close) (void *state);
+ void (*idregister) (void *state, int objtype, void *obj);
};
struct Agiodisc_s {
}
if (cflag && ok_to_make_edge(g, t, h)
- && agmapnametoid(g, AGEDGE, name, &id, TRUE)) /* reserve id */
+ && agmapnametoid(g, AGEDGE, name, &id, TRUE)) { /* reserve id */
e = newedge(g, t, h, id);
+ agregister(g, AGEDGE, e); /* register new object in external namespace */
+ }
else
e = NILedge;
return e;
NOTUSED(state);
}
+static void idregister(void *state, int objtype, void *obj)
+{
+ NOTUSED(state);
+ NOTUSED(objtype);
+ NOTUSED(obj);
+}
+
Agiddisc_t AgIdDisc = {
idopen,
idmap,
idalloc,
idfree,
idprint,
- idclose
+ idclose,
+ idregister
};
/* aux functions incl. support for disciplines with anonymous IDs */
rv = 0;
return rv;
}
+
+/* register a graph object in an external namespace */
+void agregister(Agraph_t * g, int objtype, void *obj)
+{
+ AGDISC(g, id)->idregister(AGCLOS(g, id), objtype, obj);
+}
installnodetoroot(g, n);
initnode(g, n);
assert(agsubrep(g,n));
+ agregister(g, AGNODE, n); /* register in external namespace */
return n;
}
} else {
agfreeid(g, AGNODE, new_id); /* couldn't use it after all */
}
+ /* obj* is unchanged, so no need to re agregister() */
}
return FAILURE;
}
if (agmapnametoid(agroot(g), AGTYPE(obj), newname,
&new_id, TRUE) == 0)
return FAILURE;
+ /* obj* is unchanged, so no need to re agregister() */
if (agparent(g) && agidsubg(agparent(g), new_id, 0))
return FAILURE;
agfreeid(g, AGRAPH, old_id);
return subg;
}
- if (cflag && agmapnametoid(g, AGRAPH, name, &id, TRUE)) /* reserve id */
- return localsubg(g, id);
+ if (cflag && agmapnametoid(g, AGRAPH, name, &id, TRUE)) { /* reserve id */
+ subg = localsubg(g, id);
+ agregister(g, AGRAPH, subg);
+ return subg;
+ }
return NILgraph;
}
#include "tcldot.h"
+Agraph_t *cmd2g(gctx_t *gctx, char *cmd) {
+ unsigned long int id;
+ Agraph_t *g;
+
+ if (sscanf(cmd, "graph%lu", &id) != 1) {
+ Tcl_AppendResult(gctx->ictx->interp, " \"", cmd, "\" doesn't sscanf for graph object", NULL);
+ return NULL;
+ }
+ g = agidsubg(gctx->g, id, FALSE);
+ if (!g) {
+ Tcl_AppendResult(gctx->ictx->interp, " \"", cmd, "\" not found", NULL);
+ return NULL;
+ }
+ return g;
+}
+Agnode_t *cmd2n(gctx_t *gctx, char *cmd) {
+ unsigned long int id;
+ Agnode_t *n;
+
+ if (sscanf(cmd, "node%lu", &id) != 1) {
+ Tcl_AppendResult(gctx->ictx->interp, " \"", cmd, "\" doesn't sscanf for node object", NULL);
+ return NULL;
+ }
+ n = agidnode(gctx->g, id, FALSE);
+ if (!n) {
+ Tcl_AppendResult(gctx->ictx->interp, " \"", cmd, "\" not found", NULL);
+ return NULL;
+ }
+ return n;
+}
+Agedge_t *cmd2e(gctx_t *gctx, char *cmd) {
+ unsigned long int id;
+ Agedge_t *e;
+// FIXME
+ Agnode_t *t=NULL, *h=NULL;
+
+ if (sscanf(cmd, "edge%lu", &id) != 1) {
+ Tcl_AppendResult(gctx->ictx->interp, " \"", cmd, "\" doesn't sscanf for edge object", NULL);
+ return NULL;
+ }
+ e = agidedge(gctx->g, t, h, id, FALSE);
+ if (!e) {
+ Tcl_AppendResult(gctx->ictx->interp, " \"", cmd, "\" not found", NULL);
+ return NULL;
+ }
+ return e;
+}
+
int graphcmd(ClientData clientData, Tcl_Interp * interp,
#ifndef TCLOBJ
int argc, char *argv[]
)
{
- Agraph_t *g, **gp, *sg, **sgp;
- Agnode_t **np, *n, *tail, *head;
- Agedge_t **ep, *e;
+ Agraph_t *g, *sg;
+ Agnode_t *n, *tail, *head;
+ Agedge_t *e;
+// FIXME #ifndef WITH_CGRAPH
+ Agraph_t **sgp;
+ Agnode_t **np;
+// #endif
+#ifndef WITH_CGRAPH
+ Agraph_t **gp;
+ Agedge_t **ep;
+ ictx_t *ictx = (ictx_t *)clientData;
+ unsigned long id;
+#else
+ gctx_t *gctx = (gctx_t *)clientData;
+ ictx_t *ictx = gctx->ictx;
+#endif
Agsym_t *a;
char c, buf[256], **argv2;
int i, j, length, argc2, rc;
- unsigned long id;
- ictx_t *ictx = (ictx_t *)clientData;
GVC_t *gvc = ictx->gvc;
GVJ_t *job = gvc->job;
NULL);
return TCL_ERROR;
}
+#ifndef WITH_CGRAPH
if (!(gp = (Agraph_t **) tclhandleXlate(ictx->graphTblPtr, argv[0]))) {
Tcl_AppendResult(interp, " \"", argv[0], "\"", NULL);
return TCL_ERROR;
}
-
g = *gp;
+#else
+ g = cmd2g(gctx,argv[0]);
+ if (!g)
+ return TCL_ERROR;
+#endif
c = argv[1][0];
length = strlen(argv[1]);
NULL);
return TCL_ERROR;
}
+#ifndef WITH_CGRAPH
if (!(np = (Agnode_t **) tclhandleXlate(ictx->nodeTblPtr, argv[2]))) {
if (!(tail = agfindnode(g, argv[2]))) {
Tcl_AppendResult(interp, "Tail node \"", argv[2],
"\" not found.", NULL);
return TCL_ERROR;
}
- } else {
+ }
+#else
+ tail = cmd2n(gctx,argv[2]);
+ if (!tail) {
+ return TCL_ERROR;
+ }
+#endif
+ else {
+#ifndef WITH_CGRAPH
tail = *np;
+#endif
if (agroot(g) != agroot(agraphof(tail))) {
Tcl_AppendResult(interp, "Node ", argv[2],
" is not in the graph.", NULL);
return TCL_ERROR;
}
}
+#ifndef WITH_CGRAPH
if (!(np = (Agnode_t **) tclhandleXlate(ictx->nodeTblPtr, argv[3]))) {
if (!(head = agfindnode(g, argv[3]))) {
Tcl_AppendResult(interp, "Head node \"", argv[3],
"\" not found.", NULL);
return TCL_ERROR;
}
- } else {
+ }
+#else
+ head = cmd2n(gctx,argv[2]);
+ if (!head) {
+ return TCL_ERROR;
+ }
+#endif
+ else {
+#ifndef WITH_CGRAPH
head = *np;
+#endif
if (agroot(g) != agroot(agraphof(head))) {
Tcl_AppendResult(interp, "Node ", argv[3],
" is not in the graph.", NULL);
#else
e = agedge(g, tail, head);
#endif
+#ifndef WITH_CGRAPH
if (!(ep = (Agedge_t **) tclhandleXlateIndex(ictx->edgeTblPtr, AGID(e))) || *ep != e) {
ep = (Agedge_t **) tclhandleAlloc(ictx->edgeTblPtr, Tcl_GetStringResult(interp), &id);
*ep = e;
} else {
tclhandleString(ictx->edgeTblPtr, Tcl_GetStringResult(interp), AGID(e));
}
+#endif
setedgeattributes(agroot(g), e, &argv[4], argc - 4);
reset_layout(gvc, g);
return TCL_OK;
// Agiddisc functions
static void *myiddisc_open(Agraph_t *g, Agdisc_t *disc) {
- fprintf(stderr,"myiddisc_open:\n");
- return (void *)disc;
+ ictx_t *ictx = (ictx_t *)disc;
+ gctx_t *gctx;
+
+ gctx = (gctx_t *)malloc(sizeof(gctx_t));
+ gctx->g = g;
+ gctx->ictx = ictx;
+ return (void *)gctx;
}
static long myiddisc_map(void *state, int objtype, char *str, unsigned long *id, int createflag) {
- ictx_t *ictx = (ictx_t *)state;
- Tcl_Interp *interp = ictx->interp;
- Tcl_CmdProc *proc = NULL;
- void *tclhandleTblPtr = NULL;
- int rc = 1; // init to success
-
- switch (objtype) {
- case AGRAPH: tclhandleTblPtr = ictx->graphTblPtr; proc = graphcmd; break;
- case AGNODE: tclhandleTblPtr = ictx->nodeTblPtr; proc = nodecmd; break;
- case AGINEDGE:
- case AGOUTEDGE: tclhandleTblPtr = ictx->edgeTblPtr; proc=edgecmd; break;
- }
- if (createflag) {
- tclhandleAlloc(tclhandleTblPtr, Tcl_GetStringResult(interp), id);
+ gctx_t *gctx = (gctx_t *)state;
+ ictx_t *ictx = gctx->ictx;
+ Tcl_Interp *interp = ictx->interp;
+ Tcl_CmdProc *proc = NULL;
+ Agraph_t *g = NULL;
+ char *s, buf[30] = "";
+
+ if (str) {
+ if (createflag)
+ s = agstrdup(g, str);
+ else
+ s = agstrbind(g, str);
+ *id = (unsigned long) s;
+ } else {
+ *id = ictx->ctr;
+ ictx->ctr += 2;
+ }
+ switch (objtype) {
+ case AGRAPH: sprintf(buf,"graph%lu",*id); proc=graphcmd; break;
+ case AGNODE: sprintf(buf,"node%lu",*id); proc=nodecmd; break;
+ case AGINEDGE:
+ case AGOUTEDGE: sprintf(buf,"edge%lu",*id); proc=edgecmd; break;
+ }
+ Tcl_AppendResult(interp, buf, NULL);
+ if (createflag) {
#ifndef TCLOBJ
- Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), proc, (ClientData) ictx, (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), proc, (ClientData) gctx, (Tcl_CmdDeleteProc *) NULL);
#else
- Tcl_CreateObjCommand(interp, Tcl_GetStringResult(interp), proc, (ClientData) ictx, (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateObjCommand(interp, Tcl_GetStringResult(interp), proc, (ClientData) gctx, (Tcl_CmdDeleteProc *) NULL);
#endif
- }
- else {
- rc = 0; // FIXME - not sure about this
- }
- fprintf(stderr,"myiddisc_map: objtype %d, str \"%s\", id %lu, createflag %d, rc = %d\n", objtype, str, *id, createflag, rc);
- return rc;
+ }
+ return TRUE;
}
-static long myiddisc_alloc(void *state, int objtype, unsigned long id) {
-// ictx_t *ictx = (ictx_t *)state;
-
- switch (objtype) {
- case AGRAPH: break;
- case AGNODE: break;
- case AGINEDGE:
- case AGOUTEDGE: break;
- }
- fprintf(stderr,"myiddisc_alloc: objtype %d, id %lu\n", objtype, id);
- return 0;
+/* we don't allow users to explicitly set IDs, either */
+static long myiddisc_alloc(void *state, int objtype, unsigned long request_id) {
+ NOTUSED(state);
+ NOTUSED(objtype);
+ NOTUSED(request_id);
+ return FALSE;
}
static void myiddisc_free(void *state, int objtype, unsigned long id) {
- ictx_t *ictx = (ictx_t *)state;
- Tcl_Interp *interp = ictx->interp;
- char buf[32];
- void *tclhandleTblePtr = NULL;
-
- switch (objtype) {
- case AGRAPH: tclhandleTblePtr = ictx->graphTblPtr; break;
- case AGNODE: tclhandleTblePtr = ictx->nodeTblPtr; break;
- case AGINEDGE:
- case AGOUTEDGE: tclhandleTblePtr = ictx->edgeTblPtr; break;
- }
- tclhandleString(tclhandleTblePtr, buf, id);
- Tcl_DeleteCommand(interp, buf);
- tclhandleFreeIndex(tclhandleTblePtr, id);
- fprintf(stderr,"myiddisc_free: objtype %d, id %lu\n", objtype, id);
+ gctx_t *gctx = (gctx_t *)state;
+ ictx_t *ictx = gctx->ictx;
+ char buf[30] = "";
+
+ switch (objtype) {
+ case AGRAPH: sprintf(buf,"graph%lu",id); break;
+ case AGNODE: sprintf(buf,"node%lu",id); break;
+ case AGINEDGE:
+ case AGOUTEDGE: sprintf(buf,"edge%lu",id); break;
+ }
+ Tcl_DeleteCommand(ictx->interp, buf);
+ if (id % 2 == 0)
+ agstrfree((Agraph_t *) state, (char *) id);
}
static char *myiddisc_print(void *state, int objtype, unsigned long id) {
-// ictx_t *ictx = (ictx_t *)state;
-#if 0
- static char buf[64];
- switch (objtype) {
- case AGRAPH: sprintf(buf, "graph%lu", id); break;
- case AGNODE: sprintf(buf, "node%lu", id); break;
- case AGINEDGE:
- case AGOUTEDGE: sprintf(buf, "edge%lu", id); break;
- }
- fprintf(stderr,"myiddisc_print: objtype %d, id %lu\n", objtype, id);
- return buf;
-#else
- return NIL(char*);
-#endif
+ NOTUSED(state);
+ NOTUSED(objtype);
+ if (id % 2 == 0)
+ return (char *) id;
+ else
+ return "";
}
static void myiddisc_close(void *state) {
-// ictx_t *ictx = (ictx_t *)state;
- fprintf(stderr,"myiddisc_close:\n");
+ free(state);
}
static Agiddisc_t myiddisc = {
- myiddisc_open,
- myiddisc_map,
- myiddisc_alloc,
- myiddisc_free,
- myiddisc_print,
- myiddisc_close
+ myiddisc_open,
+ myiddisc_map,
+ myiddisc_alloc,
+ myiddisc_free,
+ myiddisc_print,
+ myiddisc_close
};
#endif // WITH_CGRAPH
)
{
ictx_t *ictx = (ictx_t *)clientData;
- Agraph_t *g, **gp;
+ Agraph_t *g;
char c;
int i, length;
#ifndef WITH_CGRAPH
+ Agraph_t **gp;
int kind;
unsigned long id;
#else
#ifndef WITH_CGRAPH
*gp = g;
AGID(g) = id;
-#else
- gp = (Agraph_t **)tclhandleXlateIndex(ictx->graphTblPtr, AGID(g));
- *gp = g;
-#endif
-
-#ifndef WITH_CGRAPH
#ifndef TCLOBJ
Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), graphcmd,
(ClientData) ictx, (Tcl_CmdDeleteProc *) NULL);
ictx->interp = interp;
#ifdef WITH_CGRAPH
ictx->mydisc.id = &myiddisc;
+ ictx->ctr = 1; /* init to first odd number, increment by 2 */
#endif
#ifdef USE_TCL_STUBS
*/
typedef struct {
#ifdef WITH_CGRAPH
- Agdisc_t mydisc; // must be first to allow casting mydisc to ictx
+ Agdisc_t mydisc; /* must be first to allow casting mydisc to ictx */
+ unsigned long int ctr; /* odd number counter for anon objects over all g's in interp */
#endif
- void *graphTblPtr;
/* **FIXME** #ifndef WITH_CGRAPH */
- void *nodeTblPtr, *edgeTblPtr;
+ void *graphTblPtr, *nodeTblPtr, *edgeTblPtr;
/* #endif */
Tcl_Interp *interp;
GVC_t *gvc;
*/
typedef struct {
Agraph_t *g; /* the graph */
- ictx_t *ictx; /* refer back to top context */
+ ictx_t *ictx;
+ unsigned long int idx;
} gctx_t;
#endif