From: erg Date: Tue, 15 Jun 2010 03:16:11 +0000 (+0000) Subject: Add strcmp() and cloneG for graph renaming. X-Git-Tag: LAST_LIBGRAPH~32^2~1311 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e5807a89e0560fc31576f3c52f9a5dd948fd3abe;p=graphviz Add strcmp() and cloneG for graph renaming. --- diff --git a/cmd/gvpr/gvpr.1 b/cmd/gvpr/gvpr.1 index eb9fb0603..a8e198906 100644 --- a/cmd/gvpr/gvpr.1 +++ b/cmd/gvpr/gvpr.1 @@ -198,11 +198,7 @@ Besides these base types, the only other supported type expressions are (associative) arrays. .PP Constants follow C syntax, but strings may be quoted with either -\fB"..."\fP or \fB'...'\fP. In certain contexts, string values are -interpreted as patterns for the purpose of regular expression matching. -Patterns use -.IR ksh (1) -file match pattern syntax. +\fB"..."\fP or \fB'...'\fP. \fBgvpr\fP accepts C++ comments as well as cpp\(hytype comments. For the latter, if a line begins with a '#' character, the rest of the line is ignored. @@ -257,9 +253,16 @@ Function definitions can only appear in the \fBBEGIN\fP clause. .PP Expressions include the usual C expressions. String comparisons using \fB==\fP and \fB!=\fP -treat the right hand operand as a pattern. +treat the right hand operand as a pattern +for the purpose of regular expression matching. +Patterns use +.IR ksh (1) +file match pattern syntax. +(For simple string equality, use the \fBstrcmp\fP function. +.PP \fBgvpr\fP will attempt to use an expression as a string or numeric value -as appropriate. +as appropriate. Both C-like casts and function templates will cause +conversions to be performed, if possible. .PP Expressions of graphical type (i.e., \fBgraph_t, node_t, edge_t, obj_t\fP) may be followed by a field reference in the @@ -491,6 +494,10 @@ If \fIx\fP is a graph or subgraph, it is closed unless \fIx\fP is locked. \fBisIn\fP(\fIg\fP : \fBgraph_t\fP, \fIx\fP : \fBobj_t\fP) : \fBint\fP returns true if \fIx\fP is in subgraph \fIg\fP. .TP +\fBcloneG\fP(\fIg\fP : \fBgraph_t\fP, \fIs\fP : \fBstring\fP) : \fBgraph_t\fP +creates a clone of graph \fIg\fP with name of \fIs\fP. +If \fIs\fP is "", the created graph has the same name as \fIg\fP. +.TP \fBclone\fP(\fIg\fP : \fBgraph_t\fP, \fIx\fP : \fBobj_t\fP) : \fBobj_t\fP creates a clone of object \fIx\fP in graph \fIg\fP. In particular, the new object has the same name/value attributes @@ -501,7 +508,8 @@ If an edge is cloned, both endpoints are implicitly cloned. If a graph is cloned, all nodes, edges and subgraphs are implicitly cloned. If \fIx\fP is a graph, \fIg\fP may be \fBNULL\fP, in which case the cloned -object will be a new root graph. +object will be a new root graph. In this case, the call is equivalent +to \fBcloneG(\fP\fIx\fP\fB,"")\fP. .TP \fBcopy\fP(\fIg\fP : \fBgraph_t\fP, \fIx\fP : \fBobj_t\fP) : \fBobj_t\fP creates a copy of object \fIx\fP in graph \fIg\fP, @@ -629,8 +637,9 @@ the length of \fIstr\fP, a fatal error occurs. Similarly, in the second case, if \fIlen\fP is negative or \fIidx\fP + \fIlen\fP is greater than the length of \fIstr\fP, a fatal error occurs. .TP -\fBlength\fP(\fIs\fP : \fBstring\fP) : \fBint\fP -returns the length of the string \fIs\fP. +\fBstrcmp\fP(\fIs1\fP : \fBstring\fP, \fIs2\fP : \fBstring\fP) : \fBint\fP +provides the standard C function +.IR strcmp (3). .TP \fBindex\fP(\fIs\fP : \fBstring\fP, \fIt\fP : \fBstring\fP) : \fBint\fP .TP diff --git a/lib/gvpr/actions.c b/lib/gvpr/actions.c index 6bee10c42..af0ed9155 100644 --- a/lib/gvpr/actions.c +++ b/lib/gvpr/actions.c @@ -137,7 +137,7 @@ void nodeInduce(Agraph_t * selected) } } -/* copyAttr; +/* copyAttr: * Copy attributes from src to tgt. Overrides currently * defined values. * FIX: we should probably use the default value of the source @@ -359,6 +359,22 @@ static void cloneGraph(Agraph_t * tgt, Agraph_t * src) free (data); } +/* cloneG: + */ +Agraph_t *cloneG(Agraph_t * g, char* name) +{ + Agraph_t* ng; + + if (!name || (*name == '\0')) + name = agnameof (g); + ng = openG(name, g->desc); + if (ng) { + copyAttr((Agobj_t*)g, (Agobj_t*)ng); + cloneGraph(ng, g); + } + return ng; +} + /* clone: * Create new object of type AGTYPE(obj) with all of its * attributes and substructure. @@ -394,9 +410,10 @@ Agobj_t *clone(Agraph_t * g, Agobj_t * obj) nobj = (Agobj_t *) openSubg(g, name); else nobj = (Agobj_t *) openG(name, ((Agraph_t *) obj)->desc); - if (nobj) + if (nobj) { copyAttr(obj, nobj); - cloneGraph((Agraph_t *) nobj, (Agraph_t *) obj); + cloneGraph((Agraph_t *) nobj, (Agraph_t *) obj); + } break; case AGINEDGE: case AGOUTEDGE: diff --git a/lib/gvpr/actions.h b/lib/gvpr/actions.h index 5fc43fd9a..f38051163 100644 --- a/lib/gvpr/actions.h +++ b/lib/gvpr/actions.h @@ -26,6 +26,7 @@ extern "C" { extern void nodeInduce(Agraph_t * selected); extern Agobj_t *clone(Agraph_t * g, Agobj_t * obj); + extern Agraph_t *cloneG(Agraph_t * g, char* name); extern Agobj_t *copy(Agraph_t * g, Agobj_t * obj); extern int copyAttr(Agobj_t * obj, Agobj_t * obj1); extern int indexOf(char *s1, char *s2); diff --git a/lib/gvpr/compile.c b/lib/gvpr/compile.c index 425aa11d7..80c5dc60b 100644 --- a/lib/gvpr/compile.c +++ b/lib/gvpr/compile.c @@ -648,6 +648,9 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref, if (gp) { gp = openSubg(gp, args[1].string); v.integer = PTR2INT(gp); + } else { + error(ERROR_WARNING, "NULL graph passed to subg()"); + v.integer = 0; } break; case F_issubg: @@ -1089,6 +1092,16 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref, } else v.integer = PTR2INT(clone(gp, objp)); break; + case F_cloneG: + gp = INT2PTR(Agraph_t *, args[0].integer); + if (gp) { + gp = cloneG(gp, args[1].string); + v.integer = PTR2INT(gp); + } else { + error(ERROR_WARNING, "NULL graph passed to cloneG()"); + v.integer = 0; + } + break; case F_copya: objp = INT2PTR(Agobj_t *, args[0].integer); objp1 = INT2PTR(Agobj_t *, args[1].integer); @@ -1369,6 +1382,17 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref, case F_colorx: v.string = colorx(pgm, args[0].string, args[1].string, state->tmp); break; + case F_strcmp: + if (args[0].string) { + if (args[1].string) + v.integer = strcmp(args[0].string,args[1].string); + else + v.integer = -1; + } else if (args[1].string) + v.integer = 1; + else + v.integer = 0; + break; case F_toupper: v.string = toUpper(pgm, args[0].string, state->tmp); break; diff --git a/lib/gvpr/gprdata b/lib/gvpr/gprdata index ef2d20ced..230a6b737 100644 --- a/lib/gvpr/gprdata +++ b/lib/gvpr/gprdata @@ -79,6 +79,7 @@ F_isdirect "isDirect" FUNCTION I|A(1,G) F_isstrict "isStrict" FUNCTION I|A(1,G) F_delete "delete" FUNCTION I|A(1,G)|A(2,O) F_clone "clone" FUNCTION O|A(1,G)|A(2,O) +F_cloneG "cloneG" FUNCTION G|A(1,G)|A(2,S) F_copy "copy" FUNCTION O|A(1,G)|A(2,O) F_copya "copyA" FUNCTION I|A(1,O)|A(2,O) F_lock "lock" FUNCTION I|A(1,G)|A(2,I) @@ -109,6 +110,7 @@ F_fstattr "fstAttr" FUNCTION S|A(1,G)|A(2,S) F_nxtattr "nxtAttr" FUNCTION S|A(1,G)|A(2,S)|A(3,S) F_tolower "tolower" FUNCTION S|A(1,S) F_toupper "toupper" FUNCTION S|A(1,S) +F_strcmp "strcmp" FUNCTION I|A(1,S)|A(2,S) F_atoi "atoi" FUNCTION I|A(1,S) F_atof "atof" FUNCTION F|A(1,S) F_colorx "colorx" FUNCTION S|A(1,S)|A(2,S)