Add strcmp() and cloneG for graph renaming.
authorerg <devnull@localhost>
Tue, 15 Jun 2010 03:16:11 +0000 (03:16 +0000)
committererg <devnull@localhost>
Tue, 15 Jun 2010 03:16:11 +0000 (03:16 +0000)
cmd/gvpr/gvpr.1
lib/gvpr/actions.c
lib/gvpr/actions.h
lib/gvpr/compile.c
lib/gvpr/gprdata

index eb9fb0603caa86060e6ed1601a79741c9a364d6a..a8e198906ecf74a434dadf3782caa4102370a6c1 100644 (file)
@@ -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
index 6bee10c4273d29f3052c747167aa3ef3f2409cc8..af0ed9155a902673b6852d7ce641e24630ee8228 100644 (file)
@@ -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:
index 5fc43fd9ae5131a4ef2ffb4dee9ec4f7ccab33db..f380511635dadf73f7ac86cb8553cf4f409d319f 100644 (file)
@@ -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);
index 425aa11d714ddae1ba2dab625d7096eca5afce3e..80c5dc60b1b2e38c4aaf8b7921c2c9f418404b0a 100644 (file)
@@ -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;
index ef2d20ced8280fe3d57a23a7d9429c4d44d03af0..230a6b73711a95d6ab8ab4ceaba060c0b9eef353 100644 (file)
@@ -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)