From: erg Date: Sat, 6 Sep 2008 23:45:18 +0000 (+0000) Subject: Add new function for iterating over defined attributes for a given X-Git-Tag: LAST_LIBGRAPH~32^2~3455 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5012fdf883de6d2a793bb2537554161a9cb10419;p=graphviz Add new function for iterating over defined attributes for a given object class. --- diff --git a/cmd/gvpr/actions.c b/cmd/gvpr/actions.c index bb704513b..fdf01e826 100644 --- a/cmd/gvpr/actions.c +++ b/cmd/gvpr/actions.c @@ -134,7 +134,7 @@ int copyAttr(Agobj_t * src, Agobj_t * tgt) while ((sym = agnxtattr(srcg, skind, sym))) { tsym = agattrsym(tgt, sym->name); if (!tsym) - tsym = agattr(tgtg, tkind, sym->name, ""); + tsym = agattr(tgtg, tkind, sym->name, sym->defval); val = agxget(src, sym); if (aghtmlstr (val)) { val = agstrdup_html (tgtg, val); diff --git a/cmd/gvpr/compile.c b/cmd/gvpr/compile.c index ff95d2693..47802ac9f 100644 --- a/cmd/gvpr/compile.c +++ b/cmd/gvpr/compile.c @@ -485,7 +485,7 @@ setDfltAttr (Agraph_t *gp, char* k, char* name, char* value) * Map string to object kind */ static int -toKind (char* k) +toKind (char* k, char* fn) { int kind; @@ -500,22 +500,46 @@ toKind (char* k) kind = AGNODE; break; default : - error(ERROR_FATAL, "Unknown kind \"%s\" passed to getDflt()", k); + error(ERROR_FATAL, "Unknown kind \"%s\" passed to %s()", k, fn); break; } return kind; } +/* nxtAttr: + */ +static char* +nxtAttr (Agraph_t *gp, char* k, char* name) +{ + char* fn = (name ? "nxtAttr" : "fstAttr"); + int kind = toKind (k, fn); + Agsym_t* sym; + + if (name) { + sym = agattr (gp, kind, name, 0); + if (!sym) { + error(ERROR_FATAL, "Third argument \"%s\" in nxtAttr() must be the name of an existing attribute", name); + } + + } + else sym = NULL; + + sym = agnxtattr (gp, kind, sym); + if (sym) return sym->name; + else return ""; +} + /* getDfltAttr: */ static char* getDfltAttr (Agraph_t *gp, char* k, char* name) { - int kind = toKind (k); + int kind = toKind (k, "getDflt"); Agsym_t* sym = agattr (gp, kind, name, 0); if (!sym) { sym = agattr(gp, kind, name, ""); - error(ERROR_WARNING, "Uninitialized %s attribute \"%s\" in getDflt", kindToStr (kind), name); + error(ERROR_WARNING, "Uninitialized %s attribute \"%s\" in %s", + kindToStr (kind), name, "getDflt"); } return sym->defval; } @@ -1202,6 +1226,21 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref, v.integer = 0; } break; + case F_fstattr: + gp = INT2PTR(Agraph_t *, args[0].integer); + if (gp) { + char* kind = args[1].string; + if (!kind) { + error(ERROR_FATAL,"NULL kind passed to fstAttr()"); + } + else { + v.string = nxtAttr (gp, kind, NULL); + } + } else { + error(ERROR_FATAL, "NULL graph passed to fstAttr()"); + } + break; + case F_nxtattr: case F_isattr: case F_dget: gp = INT2PTR(Agraph_t *, args[0].integer); @@ -1209,19 +1248,22 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref, char* kind = args[1].string; char* name = args[2].string; if (!name) { - error(ERROR_FATAL,"NULL name passed to getDflt()/isAttr()"); + error(ERROR_FATAL,"NULL name passed to %s", sym->name); } else if (!kind) { - error(ERROR_FATAL,"NULL kind passed to getDflt()/isAttr()"); + error(ERROR_FATAL,"NULL kind passed to %s", sym->name); } else if (sym->index == F_isattr) { - v.integer = (agattr(gp, toKind (kind), name, 0) != NULL); + v.integer = (agattr(gp, toKind (kind, sym->name), name, 0) != NULL); + } + else if (sym->index == F_nxtattr) { + v.string = nxtAttr (gp, kind, name); } else { v.string = getDfltAttr(gp, kind, name); } } else { - error(ERROR_FATAL, "NULL graph passed to getDflt()/isAttr()"); + error(ERROR_FATAL, "NULL graph passed to %s", sym->name); } break; case F_canon: diff --git a/cmd/gvpr/gprdata b/cmd/gvpr/gprdata index 1cf7c5f53..114b79404 100644 --- a/cmd/gvpr/gprdata +++ b/cmd/gvpr/gprdata @@ -100,6 +100,8 @@ F_dget "getDflt" FUNCTION S|A(1,G)|A(2,S)|A(3,S) F_dset "setDflt" FUNCTION I|A(1,G)|A(2,S)|A(3,S)|A(4,S) F_hasattr "hasAttr" FUNCTION I|A(1,O)|A(2,S) F_isattr "isAttr" FUNCTION I|A(1,G)|A(2,S)|A(3,S) +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) C_flat "TV_flat" CONSTANT T_tvtyp C_dfs "TV_dfs" CONSTANT T_tvtyp C_bfs "TV_bfs" CONSTANT T_tvtyp diff --git a/cmd/gvpr/gvpr.1 b/cmd/gvpr/gvpr.1 index ff68143d0..ad294a182 100644 --- a/cmd/gvpr/gvpr.1 +++ b/cmd/gvpr/gvpr.1 @@ -537,6 +537,22 @@ the given \fIkind\fP. For nodes, edges, and graphs, \fIkind\fP should be "N", "E", and "G", respectively. Returns 0 on success, non\(hyzero on failure. See \fBgetDflt\fP above. .TP +\fBfstAttr\fP(\fIg\fP : \fBgraph_t\fP, \fIkind\fP : \fBstring\fP) : \fBstring\fP +returns the name of the first attribute of objects in \fIg\fP of +the given \fIkind\fP. For nodes, edges, and graphs, \fIkind\fP +should be "N", "E", and "G", respectively. +If there are no attributes, the string "" is returned. +.TP +\fBnxtAttr\fP(\fIg\fP : \fBgraph_t\fP, \fIkind\fP : \fBstring\fP, \fIname\fP : \fBstring\fP) : \fBstring\fP +returns the name of the next attribute of objects in \fIg\fP of +the given \fIkind\fP after the attribute \fIname\fP. +The argument \fIname\fP must be the name of an existing attribute; it will +typically be the return value of an previous call to \fBfstAttr\fP or +\fBnxtAttr\fP. +For nodes, edges, and graphs, \fIkind\fP +should be "N", "E", and "G", respectively. +If there are no attributes left, the string "" is returned. +.TP \fBcompOf\fP(\fIg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBgraph_t\fP returns the connected component of the graph \fIg\fP containing node \fIn\fP, as a subgraph of \fIg\fP. The subgraph only contains the nodes. One can