From: John Ellson Date: Tue, 14 Aug 2012 03:28:18 +0000 (-0400) Subject: add agregister() and idregister to id discipline X-Git-Tag: LAST_LIBGRAPH~32^2~355^2~6 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=895bdd619f51a0f46d79a290b0b487b4561ad183;p=graphviz add agregister() and idregister to id discipline --- diff --git a/lib/cgraph/cghdr.h b/lib/cgraph/cghdr.h index 611873e0d..a07ada07c 100644 --- a/lib/cgraph/cghdr.h +++ b/lib/cgraph/cghdr.h @@ -157,6 +157,7 @@ void aginternalmapinsert(Agraph_t * g, int objtype, char *str, 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); diff --git a/lib/cgraph/cgraph.h b/lib/cgraph/cgraph.h index c7f5db145..7e68126e1 100644 --- a/lib/cgraph/cgraph.h +++ b/lib/cgraph/cgraph.h @@ -163,6 +163,7 @@ struct Agiddisc_s { /* object ID allocator */ 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 { diff --git a/lib/cgraph/edge.c b/lib/cgraph/edge.c index 3828dd4f3..f8cae4fdb 100644 --- a/lib/cgraph/edge.c +++ b/lib/cgraph/edge.c @@ -313,8 +313,10 @@ Agedge_t *agedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, char *name, } 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; diff --git a/lib/cgraph/id.c b/lib/cgraph/id.c index c4b5d71c8..cde61ada7 100644 --- a/lib/cgraph/id.c +++ b/lib/cgraph/id.c @@ -74,13 +74,21 @@ static void idclose(void *state) 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 */ @@ -156,3 +164,9 @@ char *agnameof(void *obj) 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); +} diff --git a/lib/cgraph/node.c b/lib/cgraph/node.c index 168b067f2..3d9c483ba 100644 --- a/lib/cgraph/node.c +++ b/lib/cgraph/node.c @@ -162,6 +162,7 @@ Agnode_t *agnode(Agraph_t * g, char *name, int cflag) installnodetoroot(g, n); initnode(g, n); assert(agsubrep(g,n)); + agregister(g, AGNODE, n); /* register in external namespace */ return n; } @@ -244,6 +245,7 @@ int agrelabel_node(Agnode_t * n, char *newname) } else { agfreeid(g, AGNODE, new_id); /* couldn't use it after all */ } + /* obj* is unchanged, so no need to re agregister() */ } return FAILURE; } diff --git a/lib/cgraph/obj.c b/lib/cgraph/obj.c index ae0918b43..b5141aa04 100755 --- a/lib/cgraph/obj.c +++ b/lib/cgraph/obj.c @@ -52,6 +52,7 @@ int agrename(Agobj_t * obj, char *newname) 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); diff --git a/lib/cgraph/subg.c b/lib/cgraph/subg.c index da4ceb17d..6ef5d02d2 100644 --- a/lib/cgraph/subg.c +++ b/lib/cgraph/subg.c @@ -60,8 +60,11 @@ Agraph_t *agsubg(Agraph_t * g, char *name, int cflag) 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; } diff --git a/tclpkg/tcldot/tcldot-graphcmd.c b/tclpkg/tcldot/tcldot-graphcmd.c index a5d232840..bd9f1fae2 100644 --- a/tclpkg/tcldot/tcldot-graphcmd.c +++ b/tclpkg/tcldot/tcldot-graphcmd.c @@ -13,6 +13,54 @@ #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[] @@ -22,14 +70,25 @@ int graphcmd(ClientData clientData, Tcl_Interp * interp, ) { - 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; @@ -39,12 +98,17 @@ int graphcmd(ClientData clientData, Tcl_Interp * interp, 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]); @@ -56,28 +120,48 @@ int graphcmd(ClientData clientData, Tcl_Interp * interp, 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); @@ -89,6 +173,7 @@ int graphcmd(ClientData clientData, Tcl_Interp * interp, #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; @@ -103,6 +188,7 @@ int graphcmd(ClientData clientData, Tcl_Interp * interp, } 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; diff --git a/tclpkg/tcldot/tcldot.c b/tclpkg/tcldot/tcldot.c index ee8746efa..4f963b9ae 100644 --- a/tclpkg/tcldot/tcldot.c +++ b/tclpkg/tcldot/tcldot.c @@ -18,92 +18,88 @@ // 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 @@ -117,10 +113,11 @@ static int dotnew(ClientData clientData, Tcl_Interp * interp, ) { 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 @@ -196,12 +193,6 @@ static int dotnew(ClientData clientData, Tcl_Interp * interp, #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); @@ -434,6 +425,7 @@ int Tcldot_Init(Tcl_Interp * interp) 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 diff --git a/tclpkg/tcldot/tcldot.h b/tclpkg/tcldot/tcldot.h index 3719c8b41..007d9c38d 100644 --- a/tclpkg/tcldot/tcldot.h +++ b/tclpkg/tcldot/tcldot.h @@ -45,11 +45,11 @@ Tcl_GetString(Tcl_Obj *obj) { */ 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; @@ -61,7 +61,8 @@ typedef struct { */ 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