]> granicus.if.org Git - graphviz/commitdiff
Many new features, especially for string processing, array handling
authorerg <devnull@localhost>
Fri, 3 Jul 2009 14:35:17 +0000 (14:35 +0000)
committererg <devnull@localhost>
Fri, 3 Jul 2009 14:35:17 +0000 (14:35 +0000)
18 files changed:
cmd/gvpr/gvpr.1
lib/expr/Makefile.am
lib/expr/excc.c
lib/expr/exdata.c
lib/expr/exeval.c
lib/expr/exgram.h
lib/expr/exparse.y
lib/expr/extoken.c
lib/gvpr/Makefile.am
lib/gvpr/actions.c
lib/gvpr/actions.h
lib/gvpr/compile.c
lib/gvpr/compile.h
lib/gvpr/gprdata
lib/gvpr/gprstate.c
lib/gvpr/gprstate.h
lib/gvpr/gvpr.c
lib/gvpr/parse.c

index a198c07fcccb37094f507c658e58093db9dc1d61..fde4f61d149002198960c12246ace019154cada7 100644 (file)
@@ -3,7 +3,7 @@
 .  ns
 .  TP \\$1
 ..
-.TH GVPR 1 "24 April 2008"
+.TH GVPR 1 "3 July 2009"
 .SH NAME
 gvpr \- graph pattern scanning and processing language
 .br
@@ -236,6 +236,7 @@ Executable statements can be one of the following:
 \fBif(\fI expression \fP)\fI statement \fR[ \fBelse\fI statement \fR]
 \fBfor(\fI expression \fP;\fI expression \fP;\fI expression \fP)\fI statement\fP
 \fBfor(\fI array \fP[\fI var \fP])\fI statement\fP
+\fBforr(\fI array \fP[\fI var \fP])\fI statement\fP
 \fBwhile(\fI expression \fP)\fI statement\fP
 \fBswitch(\fI expression \fP)\fI case statements\fP
 \fBbreak [\fI expression \fP]
@@ -246,10 +247,13 @@ Executable statements can be one of the following:
 .ST
 Items in brackets are optional.
 .PP
-In the second form of the \fBfor\fP statement, the variable \fIvar\fP
+In the second form of the \fBfor\fP statement and the \fBforr\fP statement, the variable \fIvar\fP
 is set to each value used as an index in the specified array and then
-the associated \fIstatement\fP is evaluated. Function definitions can
-only appear in the \fBBEGIN\fP clause.
+the associated \fIstatement\fP is evaluated. For numeric and string indices, the indices are 
+returned in increasing (decreasing) numeric or lexicographic order for 
+\fBfor\fP (\fBforr\fP, respectively). This can be used for sorting.
+.PP
+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
@@ -679,6 +683,27 @@ The values are stored in the addresses following \fIfmt\fP,
 addresses having the form \fB&\fP\fIv\fP, where \fIv\fP is some declared
 variable of the correct type.
 Returns the number of items successfully scanned.
+.TP
+\fBsplit\fP(\fIs\fP : \fBstring\fP, \fIarr\fP : \fBarray\fP, \fIseps\fP : \fBstring\fP) : \fBint\fP
+.TP
+\fBsplit\fP(\fIs\fP : \fBstring\fP, \fIarr\fP : \fBarray\fP) : \fBint\fP
+.TP
+\fBtokens\fP(\fIs\fP : \fBstring\fP, \fIarr\fP : \fBarray\fP, \fIseps\fP : \fBstring\fP) : \fBint\fP
+.TP
+\fBtokens\fP(\fIs\fP : \fBstring\fP, \fIarr\fP : \fBarray\fP) : \fBint\fP
+The \fBsplit\fP function breaks the string \fIs\fP into fields, while the \fBtokens\fP function
+breaks the string into tokens. 
+A field consists of all non-separator characters between two separator characters or the beginning or
+end of the string. Thus, a field may be the empty string. A
+token is a maximal, non-empty substring not containing a separator character.
+The separator characters are those given in the \fIseps\fP argument.
+If \fIseps\fP is not provided, the default value is " \\t\\n". 
+The functions return the number of fields or tokens.
+.sp
+The fields and tokens are stored in the argument array. The array must be \fBstring\fP-valued and,
+if an index type is specified, it must be \fBint\fP. The entries are indexed by consecutive
+integers, starting at 0. Any values already stored in the array will be either overwritten, or
+still be present after the function returns.
 .SS "I/O"
 .TP
 \fBprint\fP(\fI...\fP) : \fBvoid\fP
@@ -763,6 +788,20 @@ returns the minimum of \fIy\fP and \fIx\fP.
 .TP
 \fBMAX\fP(\fIy\fP : \fBdouble\fP, \fIx\fP : \fBdouble\fP) : \fBdouble\fP
 returns the maximum of \fIy\fP and \fIx\fP.
+.SS "Associative Arrays"
+.TP
+\fB#\fP \fIarr\fP : \fBint\fP
+returns the number of elements in the array \fIarr\fP.
+.TP
+\fIidx\fP \fBin\fP \fIarr\fP : \fBint\fP
+returns 1 if a value has been set for index \fIidx\fP in the array \fIarr\fP.
+It returns 0 otherwise.
+.TP
+\fBunset\fP(\fIv\fP : \fBarray\fP, \Iidx\P) : \fBint\fP
+removes the item indexed by \fIidx\fP. It returns 1 if the item existed, 0 otherwise.
+.TP
+\fBunset\fP(\fIv\fP : \fBarray\fP) : \fBvoid\fP
+re-initializes the array.
 .SS "Miscellaneous"
 .TP
 \fBexit\fP(\fIv\fP : \fBint\fP) : \fBvoid\fP
@@ -787,6 +826,12 @@ sets a seed for the random number generator. The optional argument gives
 the seed; if it is omitted, the current time is used. The previous seed
 value is returned. \fBsrand\fP should be called before any calls to
 \fBrand\fP.
+.TP
+\fBcolorx\fP(\fIcolor\fP : \fBstring\fP, \fIfmt\fP : \fBstring\fP) : \fBstring\fP
+translates a color from one format to another. The \fIcolor\fP argument should be
+a color in one of the recognized string representations. The \fIfmt\fP value should
+be one of "RGB", "RGBA", "HSV", "HSVA", or "CMYK".
+An empty string is returned on error.
 .SH "BUILT\(hyIN VARIABLES"
 .PP
 .B gvpr
@@ -830,6 +875,11 @@ depth\(hyfirst traversal of the
 graph (cf. \fB$tvtype\fP below).
 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
+current node or edge. At the beginning of a traversal, or for other traversal
+types, the value is \fBNULL\fP.
+.TP
 \fB$tvtype\fP : \fBtvtype_t\fP
 indicates how \fBgvpr\fP traverses a graph. It can only take
 one of the constant values with the previx "TV_" described below.
index ba61ff2b0569edfc32fe34cfab789541c25382cb..0d90031e8684956fac0023f44f5ad320b011a016 100644 (file)
@@ -47,7 +47,7 @@ $(libexpr_C_la_OBJECTS) $(libexpr_la_OBJECTS): \
 exop.h: exparse.h
        echo "static const char* exop[] = {" > exop.h
        echo "  \"MINTOKEN\"," >> exop.h
-       $(SED) -e '1,/MINTOKEN/d' -e '/^[       ]*#[    ]*define[       ][      ]*[A-Z]/!d' -e 's/^[    ]*#[    ]*define[       ]*\([A-Z0-9_]*\).*/     "\1",/' < exparse.h >> exop.h
+       $(SED) -e '1,/^[   ]*#[    ]*define[   ][  ]*MINTOKEN/d' -e '/MAXTOKEN/,$$d' -e '/^[    ]*#[    ]*define[       ][      ]*[A-Z]/!d' -e 's/^[    ]*#[    ]*define[       ]*\([A-Z0-9_]*\).*/     "\1",/' < exparse.h >> exop.h
        echo "};" >> exop.h
 
 exparse.c: y.tab.c 
index 9a8fc6fd187752df9f681b8e83fd0e265616a0aa..409f3b193d6071aeab9d954ac8a48ad13654e539 100644 (file)
@@ -280,11 +280,7 @@ static void gen(Excc_t * cc, register Exnode_t * expr)
        sfprintf(cc->ccdisc->text, "}\n");
        return;
     case FOR:
-    case FORR:
-       if (expr->op == FOR)
-               sfprintf(cc->ccdisc->text, "for (;");
-       else
-               sfprintf(cc->ccdisc->text, "forr (;");
+       sfprintf(cc->ccdisc->text, "for (");
        gen(cc, x);
        sfprintf(cc->ccdisc->text, ");");
        if (expr->data.operand.left) {
@@ -310,6 +306,7 @@ static void gen(Excc_t * cc, register Exnode_t * expr)
        sfprintf(cc->ccdisc->text, "%s++", x->data.variable.symbol->name);
        return;
     case ITERATE:
+    case ITERATER:
        if (expr->op == DYNAMIC) {
            sfprintf(cc->ccdisc->text, "{ Exassoc_t* %stmp_%d;", cc->id,
                     ++cc->tmp);
@@ -344,7 +341,11 @@ static void gen(Excc_t * cc, register Exnode_t * expr)
        scan(cc, expr);
        return;
     case SPLIT:
-       sfprintf(cc->ccdisc->text, "split (");
+    case TOKENS:
+       if (expr->op == SPLIT)
+           sfprintf(cc->ccdisc->text, "split (");
+       else
+           sfprintf(cc->ccdisc->text, "tokens (");
         gen(cc, expr->data.split.string);
        sfprintf(cc->ccdisc->text, ", %s", expr->data.split.array->name);
         if (expr->data.split.seps) {
@@ -440,7 +441,6 @@ static void gen(Excc_t * cc, register Exnode_t * expr)
            if (!(x = expr->data.operand.right))
                switch (cc->lastop = expr->data.operand.left->op) {
                case FOR:
-               case FORR:
                case IF:
                case PRINTF:
                case PRINT:
@@ -459,7 +459,6 @@ static void gen(Excc_t * cc, register Exnode_t * expr)
            case ';':
                continue;
            case FOR:
-           case FORR:
            case IF:
            case PRINTF:
            case PRINT:
index 0a8f5634d886ec93848788d3f78ab39dcf463d6b..dbf1a4664cc9888ef9b5896702c3d38a5a1ceac8 100644 (file)
@@ -45,7 +45,7 @@ Exid_t exbuiltin[] = {
     EX_ID("else", ELSE, ELSE, 0, 0),
     EX_ID("exit", EXIT, EXIT, INTEGER, 0),
     EX_ID("for", FOR, FOR, 0, 0),
-    EX_ID("forr", FORR, FORR, 0, 0),
+    EX_ID("forr", ITERATER, ITERATER, 0, 0),
     EX_ID("float", DECLARE, FLOATING, FLOATING, 0),
     EX_ID("gsub", GSUB, GSUB, STRING, 0),
     EX_ID("if", IF, IF, 0, 0),
@@ -65,6 +65,7 @@ Exid_t exbuiltin[] = {
     EX_ID("sub", SUB, SUB, STRING, 0),
     EX_ID("substr", SUBSTR, SUBSTR, STRING, 0),
     EX_ID("switch", SWITCH, SWITCH, 0, 0),
+    EX_ID("tokens", TOKENS, TOKENS, INTEGER, 0),
     EX_ID("unsigned", DECLARE, UNSIGNED, UNSIGNED, 0),
     EX_ID("void", DECLARE, VOIDTYPE, 0, 0),
     EX_ID("unset", UNSET, UNSET, 0, 0),
index 0d9bef8e18d04a0f9ebe254624c2913d7dd84c58..6f18203e51fd912ae266389ffaa991c686fd4041 100644 (file)
@@ -652,26 +652,86 @@ replace(Sfio_t * s, char *base, register char *repl, int ng, int *sub)
 
 #define MCNT(s) (sizeof(s)/(2*sizeof(int)))
 
+static void
+addItem (Dt_t* arr, Extype_t v, char* tok)
+{
+    Exassoc_t* b;
+
+    if (!(b = (Exassoc_t *) dtmatch(arr, &v))) {
+       if (!(b = newof(0, Exassoc_t, 1, 0)))
+           exerror("out of space [assoc]");
+       b->key = v;
+       dtinsert(arr, b);
+    }
+    b->value.string = tok;
+}
+
 /* exsplit:
+ * break string into possibly empty fields and store in array
+ * return number of fields
+ */
+Extype_t
+exsplit(Expr_t * ex, register Exnode_t * expr, void *env)
+{
+    Extype_t v;
+    char *str;
+    char *seps;
+    char *tok;
+    size_t sz;
+    Sfio_t* fp = ex->tmp;
+    Dt_t* arr = (Dt_t*)expr->data.split.array->local.pointer;
+    int i;
+
+    str = (eval(ex, expr->data.split.string, env)).string;
+    if (expr->data.split.seps)
+       seps = (eval(ex, expr->data.split.seps, env)).string;
+    else
+       seps = " \t\n";
+
+    v.integer = 0;
+    while (*str) {
+       sz = strspn (str, seps);
+       for (i = 0; i < sz; i++) {
+           addItem (arr, v, "");
+           v.integer++;
+       }
+       str += sz;
+       if (*str == '\0') {
+           if (v.integer == sz) {  /* only separators */
+               addItem (arr, v, "");
+               v.integer++;
+           }
+           break;
+       }
+       sz = strcspn (str, seps);
+       sfwrite (fp, str, sz);
+       tok = exstrdup(ex, sfstruse(fp));
+       addItem (arr, v, tok);
+       v.integer++;
+       str += sz;
+    }
+
+    return v;
+}
+
+/* extoken:
  * tokenize string and store in array
  * return number of tokens
  */
 Extype_t
-exsplit(Expr_t * ex, register Exnode_t * expr, void *env)
+extokens(Expr_t * ex, register Exnode_t * expr, void *env)
 {
     Extype_t v;
     char *str;
     char *seps;
     char *tok;
-    Exassoc_t* b;
     size_t sz;
     Sfio_t* fp = ex->tmp;
-    int cnt = 0;
     Dt_t* arr = (Dt_t*)expr->data.split.array->local.pointer;
 
     str = (eval(ex, expr->data.split.string, env)).string;
     if (expr->data.split.seps)
-       seps = (eval(ex, expr->data.string.pat, env)).string;
+       seps = (eval(ex, expr->data.split.seps, env)).string;
     else
        seps = " \t\n";
 
@@ -681,26 +741,17 @@ exsplit(Expr_t * ex, register Exnode_t * expr, void *env)
        str += sz;
        if (*str == '\0')
            break;
+
        sz = strcspn (str, seps);
        assert (sz);
        sfwrite (fp, str, sz);
-       tok = vmstrdup(ex->vc, sfstruse(fp));
-
-       if (!(b = (Exassoc_t *) dtmatch(arr, &v))) {
-           if (!(b = newof(0, Exassoc_t, 1, 0)))
-               exerror("out of space [assoc]");
-           b->key = v;
-           dtinsert(arr, b);
-       }
-       b->value.string = tok;
-
+       tok = exstrdup(ex, sfstruse(fp));
+       addItem (arr, v, tok);
        v.integer++;
        str += sz;
     }
 
-    v.integer = cnt;
     return v;
-    
 }
 
 /* exsub:
@@ -953,6 +1004,8 @@ static Extype_t eval(Expr_t * ex, register Exnode_t * expr, void *env)
        return getdyn(ex, expr, env, &assoc);
     case SPLIT:
        return exsplit(ex, expr, env);
+    case TOKENS:
+       return extokens(ex, expr, env);
     case GSUB:
        return exsub(ex, expr, env, 1);
     case SUB:
index 3fd2f29ef25869c6d3e25f3ea7e3c983a64b9939..ea97eeeed1475cc452d31c84768176180d00921e 100644 (file)
@@ -140,6 +140,7 @@ extern "C" {
            if (x->data.string.repl)
                exfreenode(p, x->data.string.repl);
            break;
+       case TOKENS:
        case SPLIT:
            if (x->data.split.seps)
                exfreenode(p, x->data.split.seps);
@@ -196,27 +197,27 @@ extern "C" {
     }
 
 /* exnewsplit:
- * Generate split node.
- * Fourth argument is optional.
+ * Generate split/tokens node.
+ * Fifth argument is optional.
  */
-    static Exnode_t *exnewsplit(Expr_t * p, Exid_t* dyn, Exnode_t * s, Exnode_t* seps) {
+    static Exnode_t *exnewsplit(Expr_t * p, int op, Exid_t* dyn, Exnode_t * s, Exnode_t* seps) {
        Exnode_t *ss = 0;
 
        if (dyn->local.pointer == 0)
-               exerror("cannot use non-array %s in split", dyn->name);
+               exerror("cannot use non-array %s in %s", dyn->name, exopname(op));
        if ((dyn->index_type > 0) && (dyn->index_type != INTEGER))
-            exerror("in split, array %s must have integer index type, not %s", 
-               dyn->name, extypename(p, s->type));
+            exerror("in %s, array %s must have integer index type, not %s", 
+               exopname(op), dyn->name, extypename(p, s->type));
        if (dyn->type != STRING)
-            exerror("in split, array %s entries must have string type, not %s", 
-               dyn->name, extypename(p, s->type));
+            exerror("in %s, array %s entries must have string type, not %s", 
+               exopname(op), dyn->name, extypename(p, s->type));
        if (s->type != STRING)
-            exerror("first argument to split must have string type, not %s", 
-               extypename(p, s->type));
+            exerror("first argument to %s must have string type, not %s", 
+               exopname(op), extypename(p, s->type));
        if (seps && (seps->type != STRING))
-            exerror("third argument to split must have string type, not %s", 
-               extypename(p, seps->type));
-       ss = exnewnode(p, SPLIT, 0, INTEGER, NiL, NiL);
+            exerror("third argument to %s must have string type, not %s", 
+               exopname(op), extypename(p, seps->type));
+       ss = exnewnode(p, op, 0, INTEGER, NiL, NiL);
        ss->data.split.array = dyn;
        ss->data.split.string = s;
        ss->data.split.seps = seps;
index 54124e7052ead8854c6647b0e1d4195f972493a9..77ce460611284ad6f2e3697c359212ab096bd2e1 100644 (file)
@@ -78,7 +78,6 @@
 %token ELSE
 %token EXIT
 %token FOR
-%token FORR
 %token FUNCTION
 %token GSUB
 %token ITERATE
 %token SUB
 %token SUBSTR
 %token SWITCH
+%token TOKENS
 %token UNSET
 %token WHILE
 
 %type <id>             CONSTANT        ARRAY           FUNCTION        DECLARE
 %type <id>             EXIT            PRINT           PRINTF          QUERY
 %type <id>             RAND            SRAND
-%type <id>             SPRINTF         GSUB            SUB             SPLIT
+%type <id>             SPRINTF         GSUB            SUB
+%type <id>             SPLIT           TOKENS          splitop
 %type <id>             SUBSTR          PROCEDURE       name            dcl_name
-%type <id>             IF              WHILE           FOR             FORR
+%type <id>             IF              WHILE           FOR             ITERATER
 %type <id>             BREAK           CONTINUE        print           member
 %type <id>             RETURN          DYNAMIC         SWITCH          UNSET
 %type <id>             SCANF           SSCANF          scan
@@ -303,7 +304,7 @@ statement   :       '{' statement_list '}'
                        if ($3)
                                $$ = exnewnode(expr.program, ';', 1, INTEGER, $3, $$);
                }
-               |       FORR '(' variable ')' statement
+               |       ITERATER '(' variable ')' statement
                {
                        $$ = exnewnode(expr.program, ITERATER, 0, INTEGER, NiL, NiL);
                        $$->data.generate.array = $3;
@@ -802,13 +803,13 @@ expr              :       '(' expr ')'
                {
                        $$ = exnewsubstr (expr.program, $3);
                }
-               |       SPLIT '(' expr ',' DYNAMIC ')'
+               |       splitop '(' expr ',' DYNAMIC ')'
                {
-                       $$ = exnewsplit (expr.program, $5, $3, NiL);
+                       $$ = exnewsplit (expr.program, $1->index, $5, $3, NiL);
                }
-               |       SPLIT '(' expr ',' DYNAMIC ',' expr ')'
+               |       splitop '(' expr ',' DYNAMIC ',' expr ')'
                {
-                       $$ = exnewsplit (expr.program, $5, $3, $7);
+                       $$ = exnewsplit (expr.program, $1->index, $5, $3, $7);
                }
                |       EXIT '(' expr ')'
                {
@@ -960,6 +961,9 @@ expr                :       '(' expr ')'
                |       constant
                ;
 
+splitop                :       SPLIT
+               |       TOKENS
+               ;
 constant       :       CONSTANT
                {
                        $$ = exnewnode(expr.program, CONSTANT, 0, $1->type, NiL, NiL);
index b603ec92c28eab327f966f51798f585062cb5fcc..e115ec5b79243b10bde3ed3a68cea49af57f9535 100644 (file)
@@ -174,7 +174,7 @@ static void trace(Expr_t * ex, int lev, char *op, int c)
     case FOR:
        s = " for";
        break;
-    case FORR:
+    case ITERATER:
        s = " forr";
        break;
     case GSUB:
@@ -222,6 +222,9 @@ static void trace(Expr_t * ex, int lev, char *op, int c)
     case SWITCH:
        s = " switch";
        break;
+    case TOKENS:
+       s = " tokens";
+       break;
     case UNSET:
        s = " unset";
        break;
index eadab6b9b2e0203da9da13b7efa4e386cc955804..31da95a745df0cf64b3a70b4551a016142762b1c 100644 (file)
@@ -13,6 +13,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/lib/sfio \
        -I$(top_srcdir)/lib/ast \
        -I$(top_srcdir)/lib/ingraphs \
+       -I$(top_srcdir)/lib/common \
        -I$(top_srcdir)/lib/cgraph \
        -I$(top_srcdir)/lib/cdt
 
@@ -23,10 +24,11 @@ noinst_LTLIBRARIES = libgvpr_C.la
 lib_LTLIBRARIES = libgvpr.la
 pkgconfig_DATA = libgvpr.pc
 
-libgvpr_C_la_SOURCES = actions.c compile.c gvpr.c gprstate.c parse.c queue.c
+libgvpr_C_la_SOURCES = actions.c compile.c gvpr.c gprstate.c parse.c queue.c ../common/colxlate.c
 $(libgvpr_C_la_OBJECTS): gdefs.h
 libgvpr_C_la_DEPENDENCIES = \
        $(top_builddir)/lib/expr/libexpr_C.la \
+       $(top_builddir)/lib/common/libcommon_C.la \
        $(top_builddir)/lib/ingraphs/libingraphs_C.la
 
 
index 879e9cfc1fb39e2baa76cf2cd3977f1cfcccefa1..cf8132029506762cc6669f0c0f685c199043c473 100644 (file)
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <colorprocs.h>
 
 #define KINDS(p) ((AGTYPE(p) == AGRAPH) ? "graph" : (AGTYPE(p) == AGNODE) ? "node" : "edge")
 
@@ -663,7 +664,7 @@ char *readLine(Expr_t * ex, int fd)
 
     if (fd < 0 || fd >= elementsof(ex->file) || !((sp = ex->file[fd]))) {
        exerror("readL: %d: invalid descriptor", fd);
-       return exstring(ex, "");
+       return "";
     }
     tmps = sfstropen();
     while (((c = sfgetc(sp)) > 0) && (c != '\n'))
@@ -746,3 +747,74 @@ char *canon(Expr_t * pgm, char *arg)
 
     return p;
 }
+
+void *grealloc(void *ptr, size_t size)
+{
+    void *p = realloc(ptr, size);
+    if (p == NULL && size) {
+        fprintf(stderr, "out of memory\n");
+        abort();
+    }
+    return p;
+}
+
+/* colorx:
+ * RGB, RGBA, HSV, HSVA, CMYK
+ */
+char *colorx (Expr_t* ex, char* incolor, char* fmt, Sfio_t* fp)
+{
+    gvcolor_t color;
+    color_type_t type;
+    int rc;
+    int alpha;
+
+    if ((*fmt == '\0') || (*incolor == '\0'))
+       return "";
+    if (*fmt == 'R') {
+       type = RGBA_BYTE;
+       if (!strcmp (fmt, "RGBA")) 
+           alpha = 1;
+       else
+           alpha = 0;
+    }
+    else if (*fmt == 'H') {
+       type = HSVA_DOUBLE;
+       if (!strcmp (fmt, "HSVA")) 
+           alpha = 1;
+       else
+           alpha = 0;
+    }
+    else if (*fmt == 'C') {
+       type = CMYK_BYTE;
+    }
+    else
+       return "";
+
+    rc = colorxlate (incolor, &color, type);
+    if (rc != COLOR_OK)
+       return "";
+
+    switch (type) {
+    case HSVA_DOUBLE :
+       sfprintf (fp, ".03f .03f .03f", 
+           color.u.HSVA[0], color.u.HSVA[1], color.u.HSVA[2]);
+       if (alpha)
+           sfprintf (fp, " .03f", color.u.HSVA[3]);
+       break;
+    case RGBA_BYTE :
+       sfprintf (fp, "#%02x%02x%02x", 
+           color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]);
+       if (alpha)
+           sfprintf (fp, "%02x", color.u.rgba[3]);
+       break;
+    case CMYK_BYTE :
+       sfprintf (fp, "#%02x%02x%02x%02x", 
+           color.u.cmyk[0], color.u.cmyk[1], color.u.cmyk[2], color.u.cmyk[3]);
+       break;
+    default :
+       break;
+    }
+
+    return exstring(ex, sfstruse(fp));
+}
+
index 2ac1d7bbcb4da99d6f2e5d45d9e82eca388143b3..59190573f10047219635fc9f4a6dcd3b7cfb72c7 100644 (file)
@@ -49,6 +49,7 @@ extern "C" {
     extern char *toLower(Expr_t * pgm, char *, Sfio_t*);
     extern char *toUpper(Expr_t * pgm, char *, Sfio_t*);
     extern int deleteObj(Agraph_t * g, Agobj_t * obj);
+    extern char *colorx (Expr_t* ex, char* incolor, char* fmt, Sfio_t* fp);
 
 #endif
 
index 2b4d706f1c3d05b6da8a1326c5b4cedfeb119d71..2e9c13ebd8ef4ac4c966a6ca287b277f76d138fd 100644 (file)
@@ -257,6 +257,14 @@ static Agobj_t *deref(Expr_t * pgm, Exnode_t * x, Exref_t * ref,
            return deref(pgm, x, ref->next, (Agobj_t *) state->target,
                         state);
            break;
+       case V_travedge:
+           return deref(pgm, x, ref->next, (Agobj_t *) state->tvedge,
+                        state);
+           break;
+       case V_travroot:
+           return deref(pgm, x, ref->next, (Agobj_t *) state->tvroot,
+                        state);
+           break;
        case M_head:
            if (!objp && !(objp = state->curobj)) {
                exerror("Current object $ not defined");
@@ -1176,6 +1184,12 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref,
                v.integer = agnedges(gp);
            }
            break;
+       case F_atoi:
+           v.integer = atoi(args[0].string);
+           break;
+       case F_atof:
+           v.floating = atof(args[0].string);
+           break;
        case F_sqrt:
            v.floating = sqrt(args[0].floating);
            break;
@@ -1328,6 +1342,9 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref,
        case F_tolower:
            v.string = toLower(pgm, args[0].string, state->tmp);
            break;
+       case F_colorx:
+           v.string = colorx(pgm, args[0].string, args[1].string, state->tmp);
+           break;
        case F_toupper:
            v.string = toUpper(pgm, args[0].string, state->tmp);
            break;
@@ -1408,6 +1425,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_travedge:
+           v.integer = PTR2INT(state->tvedge);
+           break;
        }
        return v;
     } else {
index 5c2e7e3720af90fe1528ed1db0de00d51ff1a97d..7ad52eb1c0449cbcce9f729bea5d923a7516d015 100644 (file)
@@ -35,20 +35,21 @@ extern "C" {
 
     typedef struct {
        Agrec_t h;
-       Extype_t xu;
+       /* Extype_t xu; */
        Extype_t iu;
+       Agedge_t* ine;
     } nval_t;
 
     typedef struct {
        Agrec_t h;
-       Extype_t xu;
-       Extype_t iu;
+       /* Extype_t xu; */
+       /* Extype_t iu; */
        char lock;
     } gval_t;
 
     typedef struct {
        Agrec_t h;
-       Extype_t xu;
+       /* Extype_t xu; */
     } uval_t;
 
 #define OBJ(p) ((Agobj_t*)p)
index 0c96f4afe588ad22d86eb9cf9e9661ed833753e5..3c8831d8704fda1fb31b0670031cc5e0e6565070 100644 (file)
@@ -5,6 +5,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_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)
 M_degree    "degree"       ID       INTEGER            Y(V)        Y(I)
@@ -108,6 +109,9 @@ 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_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)
 C_flat      "TV_flat"      CONSTANT T_tvtyp
 C_ne        "TV_ne"        CONSTANT T_tvtyp
 C_en        "TV_en"        CONSTANT T_tvtyp
index ad237bff92b62c0463c5be33d8d5f2d13cfd5b91..796f648c2d4df86318c9c56a58d8600588c4b816 100644 (file)
@@ -56,6 +56,7 @@ Gpr_t *openGPRState(gpr_info* info)
 
     state->tvt = TV_flat;
     state->tvroot = 0;
+    state->tvedge = 0;
     state->outFile = info->outFile;
     state->argc = info->argc;
     state->argv = info->argv;
index e1433351108c75cb09b1a73675a0588cf227d83a..aa57fe3f3686ace53d3d4cbc97ff32d8a6571f5d 100644 (file)
@@ -48,6 +48,7 @@ extern "C" {
        Sfio_t *outFile;
        trav_type tvt;
        Agnode_t *tvroot;
+       Agedge_t *tvedge;
        int name_used;
        int argc;
        char **argv;
index 947aa4c435e45fbdec8a899375730e4d262ac93f..38cc017bf060eaafdb52439bdd532da1747af0b1 100644 (file)
@@ -487,7 +487,7 @@ static Agnode_t *nextNode(Gpr_t * state, nodestream * nodes)
 #define MARKED(x)  (((x)->iu.integer)&1)
 #define MARK(x)  (((x)->iu.integer) = 1)
 #define ONSTACK(x)  (((x)->iu.integer)&2)
-#define PUSH(x)  (((x)->iu.integer)|=2)
+#define PUSH(x,e)  (((x)->iu.integer)|=2,(x)->ine=(e))
 #define POP(x)  (((x)->iu.integer)&=(~2))
 
 typedef Agedge_t *(*fstedgefn_t) (Agraph_t *, Agnode_t *);
@@ -523,12 +523,13 @@ static void travBFS(Gpr_t * state, Expr_t* prog, comp_block * xprog)
        nd = nData(n);
        if (MARKED(nd))
            continue;
-       PUSH(nd);
+       PUSH(nd, 0);
        push(q, n);
        while ((n = pull(q))) {
            nd = nData(n);
            MARK(nd);
            POP(nd);
+           state->tvedge = nd->ine;
            evalNode(state, prog, xprog, n);
            for (cure = agfstedge(g, n); cure;
                 cure = agnxtedge(g, cure, n)) {
@@ -538,11 +539,12 @@ static void travBFS(Gpr_t * state, Expr_t* prog, comp_block * xprog)
                evalEdge(state, prog, xprog, cure);
                if (!ONSTACK(nd)) {
                    push(q, cure->node);
-                   PUSH(nd);
+                   PUSH(nd,cure);
                }
            }
        }
     }
+    state->tvedge = 0;
     freeQ(q);
 }
 
@@ -569,9 +571,9 @@ static void travDFS(Gpr_t * state, Expr_t* prog, comp_block * xprog, trav_fns *
        seed.in.node = 0;
        curn = n;
        entry = &(seed.out);
-       cure = 0;
+       state->tvedge = cure = 0;
        MARK(nd);
-       PUSH(nd);
+       PUSH(nd,0);
        if (fns->visit & PRE_VISIT)
            evalNode(state, prog, xprog, n);
        more = 1;
@@ -597,13 +599,13 @@ static void travDFS(Gpr_t * state, Expr_t* prog, comp_block * xprog, trav_fns *
                } else {
                    evalEdge(state, prog, xprog, cure);
                    push(stk, entry);
-                   entry = cure;
+                   state->tvedge = entry = cure;
                    curn = cure->node;
                    cure = 0;
                    if (fns->visit & PRE_VISIT)
                        evalNode(state, prog, xprog, curn);
                    MARK(nd);
-                   PUSH(nd);
+                   PUSH(nd, entry);
                }
            } else {
                if (fns->visit & POST_VISIT)
@@ -612,6 +614,10 @@ static void travDFS(Gpr_t * state, Expr_t* prog, comp_block * xprog, trav_fns *
                POP(nd);
                cure = entry;
                entry = (Agedge_t *) pull(stk);
+               if (entry == &seed)
+                   state->tvedge = 0;
+               else
+                   state->tvedge = entry;
                if (entry)
                    curn = entry->node;
                else
@@ -619,6 +625,7 @@ static void travDFS(Gpr_t * state, Expr_t* prog, comp_block * xprog, trav_fns *
            }
        }
     }
+    state->tvedge = 0;
     freeQ(stk);
 }
 
index 98a2a010deec1c7bc7bc4c5df85f4c139941e590..c7b8511e7186e5f1f610b0ccfb091975f4abbf09 100644 (file)
@@ -499,6 +499,7 @@ parse_prog *parseProg(char *input, int isFile)
     if (isFile) {
        mode = "r";
        prog->source = input;
+       
     } else {
        mode = "rs";
        prog->source = 0;       /* command line */