* Map string to object kind
*/
static int
-toKind (char* k)
+toKind (char* k, char* fn)
{
int kind;
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;
}
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);
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:
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
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