From: Emden Gansner Date: Thu, 5 Jul 2012 17:39:28 +0000 (-0400) Subject: Provide $tvnext to assist in setting up traversal roots. In particular, X-Git-Tag: LAST_LIBGRAPH~32^2~382^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c2f518b49f316aea6f778aeb6e8c8d0e25b8d407;p=graphviz Provide $tvnext to assist in setting up traversal roots. In particular, one can set $tvnext == NULL at the beginning to get a single traversal. --- diff --git a/cmd/gvpr/gvpr.1 b/cmd/gvpr/gvpr.1 index adf23c5f3..7833480a3 100644 --- a/cmd/gvpr/gvpr.1 +++ b/cmd/gvpr/gvpr.1 @@ -909,9 +909,19 @@ This variable may be set by the user. .TP \fB$tvroot\fP : \fBnode_t\fP indicates the starting node for a (directed or undirected) -depth\(hyfirst traversal of the +depth\(hyfirst or breadth\(hyfirst traversal of the graph (cf. \fB$tvtype\fP below). The default value is \fBNULL\fP for each input graph. +After the traversal at the given root, if the value of \fB$tvroot\fP has changed, +a new traversal will begin with the new value of \fB$tvroot\fP. Also, set \fB$tvnext\fP below. +.TP +\fB$tvnext\fP : \fBnode_t\fP +indicates the next starting node for a (directed or undirected) +depth\(hyfirst or breadth\(hyfirst traversal of the +graph (cf. \fB$tvtype\fP below). +If a traversal finishes and the \fB$tvroot\fP but the \fB$tvnext\fP has been +set but not used, this node will be used as the next choice for \fB$tvroot\fP. +The default value is \fBNULL\fP for each input graph. .TP \fB$tvedge\fP : \fBedge_t\fP For BFS and DFS traversals, this is set to the edge used to arrive at the diff --git a/lib/gvpr/compile.c b/lib/gvpr/compile.c index 9897b2f34..73041c839 100644 --- a/lib/gvpr/compile.c +++ b/lib/gvpr/compile.c @@ -289,6 +289,10 @@ static Agobj_t *deref(Expr_t * pgm, Exnode_t * x, Exref_t * ref, return deref(pgm, x, ref->next, (Agobj_t *) state->tvroot, state); break; + case V_travnext: + return deref(pgm, x, ref->next, (Agobj_t *) state->tvnext, + state); + break; case M_head: if (!objp && !(objp = state->curobj)) { exerror("Current object $ not defined"); @@ -1497,6 +1501,9 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref, case V_travroot: v.integer = PTR2INT(state->tvroot); break; + case V_travnext: + v.integer = PTR2INT(state->tvnext); + break; case V_travedge: v.integer = PTR2INT(state->tvedge); break; @@ -1574,6 +1581,16 @@ setval(Expr_t * pgm, Exnode_t * x, Exid_t * sym, Exref_t * ref, agnameof(np)); } break; + case V_travnext: + np = INT2PTR(Agnode_t *, v.integer); + if (!np || (agroot(np) == state->curgraph)) { + state->tvnext = np; + state->flags |= GV_NEXT_SET; + } else { + error(1, "cannot set $tvnext, node %s not in $G : ignored", + agnameof(np)); + } + break; case V_tgtname: if (!streq(state->tgtname, v.string)) { vmfree(pgm->vm, state->tgtname); diff --git a/lib/gvpr/gprdata b/lib/gvpr/gprdata index 6df9ee13f..595a7729e 100644 --- a/lib/gvpr/gprdata +++ b/lib/gvpr/gprdata @@ -6,6 +6,7 @@ V_outgraph "$O" ID T_graph 0 Y(G) V_tgtname "$tgtname" ID STRING 0 Y(S) V_infname "$F" ID STRING 0 Y(S) V_travroot "$tvroot" ID T_node 0 Y(V) +V_travnext "$tvnext" ID T_node 0 Y(V) V_travedge "$tvedge" ID T_edge 0 Y(E) V_travtype "$tvtype" ID T_tvtyp 0 Y(TV) V_ARGC "ARGC" ID INTEGER 0 Y(I) diff --git a/lib/gvpr/gprstate.c b/lib/gvpr/gprstate.c index 6d5c1a77e..fb695814c 100644 --- a/lib/gvpr/gprstate.c +++ b/lib/gvpr/gprstate.c @@ -56,6 +56,7 @@ Gpr_t *openGPRState(gpr_info* info) state->tvt = TV_flat; state->name_used = name_used; state->tvroot = 0; + state->tvnext = 0; state->tvedge = 0; state->outFile = info->outFile; state->argc = info->argc; diff --git a/lib/gvpr/gprstate.h b/lib/gvpr/gprstate.h index 82ed5707a..c7dcda158 100644 --- a/lib/gvpr/gprstate.h +++ b/lib/gvpr/gprstate.h @@ -32,6 +32,14 @@ extern "C" { TV_prepostdfs, TV_prepostfwd, TV_prepostrev, } trav_type; +/* Bits for flags variable. + */ + /* If set, gvpr calls exit() on errors */ +#define GV_USE_EXIT 1 + /* If set, gvpr stores output graphs in gvpropts */ +#define GV_USE_OUTGRAPH 2 +#define GV_USE_JUMP 4 + typedef struct { Agraph_t *curgraph; Agraph_t *nextgraph; @@ -48,6 +56,7 @@ extern "C" { Agiodisc_t* dfltIO; trav_type tvt; Agnode_t *tvroot; + Agnode_t *tvnext; Agedge_t *tvedge; int name_used; int argc; diff --git a/lib/gvpr/gvpr.c b/lib/gvpr/gvpr.c index f523dc89f..031c759cf 100644 --- a/lib/gvpr/gvpr.c +++ b/lib/gvpr/gvpr.c @@ -48,8 +48,6 @@ #define DFLT_GVPRPATH "." #endif -#define GV_USE_JUMP 4 - static char *Info[] = { "gvpr", /* Program */ VERSION, /* Version */ @@ -518,6 +516,9 @@ static Agnode_t *nextNode(Gpr_t * state, nodestream * nodes) if (state->tvroot != nodes->oldroot) { np = nodes->oldroot = state->tvroot; + } else if (state->flags & GV_NEXT_SET) { + np = nodes->oldroot = state->tvroot = state->tvnext; + state->flags &= ~GV_NEXT_SET; } else if (nodes->prev) { np = nodes->prev = agnxtnode(state->curgraph, nodes->prev); } else { diff --git a/lib/gvpr/gvpr.h b/lib/gvpr/gvpr.h index 94f7a1400..f89d87bca 100644 --- a/lib/gvpr/gvpr.h +++ b/lib/gvpr/gvpr.h @@ -21,10 +21,19 @@ extern "C" { #include "ast_common.h" #include "cgraph.h" +/* Bits for flags variable in gvprstate_t. + * Included here so that calling programs can use the first + * two in gvpropts.flags + */ /* If set, gvpr calls exit() on errors */ #define GV_USE_EXIT 1 /* If set, gvpr stores output graphs in gvpropts */ #define GV_USE_OUTGRAPH 2 + /* Use longjmp to return to top-level call in gvpr */ +#define GV_USE_JUMP 4 + /* $tvnext has been set but not used */ +#define GV_NEXT_SET 8 + typedef ssize_t (*gvprwr) (void*, const char *buf, size_t nbyte, void*); typedef int (*gvpruserfn) (char *);