wolffd@0: .de TQ wolffd@0: . br wolffd@0: . ns wolffd@0: . TP \\$1 wolffd@0: .. wolffd@0: .TH GVPR 1 "24 April 2008" wolffd@0: .SH NAME wolffd@0: gvpr \- graph pattern scanning and processing language wolffd@0: .br wolffd@0: ( previously known as wolffd@0: .B gpr wolffd@0: ) wolffd@0: .SH SYNOPSIS wolffd@0: .B gvpr wolffd@0: [\fB\-icqV?\fP] wolffd@0: [ wolffd@0: .BI \-o wolffd@0: .I outfile wolffd@0: ] wolffd@0: [ wolffd@0: .BI \-a wolffd@0: .I args wolffd@0: ] wolffd@0: [ wolffd@0: .I 'prog' wolffd@0: | wolffd@0: .BI \-f wolffd@0: .I progfile wolffd@0: ] wolffd@0: [ wolffd@0: .I files wolffd@0: ] wolffd@0: .SH DESCRIPTION wolffd@0: .B gvpr wolffd@0: is a graph stream editor inspired by \fBawk\fP. wolffd@0: It copies input graphs to its wolffd@0: output, possibly transforming their structure and attributes, wolffd@0: creating new graphs, or printing arbitrary information. wolffd@0: The graph model is that provided by wolffd@0: .IR libcgraph (3). wolffd@0: In particular, \fBgvpr\fP reads and writes graphs using the wolffd@0: dot language. wolffd@0: .PP wolffd@0: Basically, wolffd@0: .B gvpr wolffd@0: traverses each input graph, denoted by \fB$G\fP, visiting each node and edge, wolffd@0: matching it with the predicate\(hyaction rules supplied in the input program. wolffd@0: The rules are evaluated in order. wolffd@0: For each predicate evaluating to true, the corresponding wolffd@0: action is performed. wolffd@0: During the traversal, the current node or edge being visited wolffd@0: is denoted by \fB$\fP. wolffd@0: .PP wolffd@0: For each input graph, there is a target subgraph, denoted by wolffd@0: \fB$T\fP, initially empty and used to accumulate wolffd@0: chosen entities, and an output graph, \fB$O\fP, used for final processing wolffd@0: and then written to output. wolffd@0: By default, the output graph is the target graph. wolffd@0: The output graph can be set in the program or, in a limited sense, wolffd@0: on the command line. wolffd@0: .SH OPTIONS wolffd@0: The following options are supported: wolffd@0: .TP wolffd@0: .BI \-a " args" wolffd@0: The string \fIargs\fP is split into whitespace\(hyseparated tokens, wolffd@0: with the individual tokens wolffd@0: available as strings in the \fBgvpr\fP program wolffd@0: as \fBARGV[\fI0\fP],...,ARGV[ARGC\-1]\fR. wolffd@0: Whitespace characters within single or double quoted substrings, or wolffd@0: preceded by a backslash, are ignored as separators. wolffd@0: In general, a backslash character turns off any special meaning of the wolffd@0: following character. wolffd@0: Note that the tokens derived from multiple \fB\-a\fP flags are concatenated. wolffd@0: .TP wolffd@0: .B \-c wolffd@0: Use the source graph as the output graph. wolffd@0: .TP wolffd@0: .B \-i wolffd@0: Derive the node\(hyinduced subgraph extension of the output graph in the context wolffd@0: of its root graph. wolffd@0: .TP wolffd@0: .BI \-o " outfile" wolffd@0: Causes the output stream to be written to the specified file; by default, wolffd@0: output is written to \fBstdout\fP. wolffd@0: .TP wolffd@0: .BI \-f " progfile" wolffd@0: Use the contents of the specified file as the program to execute wolffd@0: on the input. If \fIprogfile\fP contains a slash character, the name is taken wolffd@0: as the pathname of the file. Otherwise, \fBgvpr\fP will use the wolffd@0: directories specified in the environment variable \fBGPRPATH\fP to look wolffd@0: for the file. If wolffd@0: .B \-f wolffd@0: is not given, wolffd@0: .B gvpr wolffd@0: will use the first non\(hyoption argument as the program. wolffd@0: .TP wolffd@0: .B \-q wolffd@0: Turns off warning messages. wolffd@0: .TP wolffd@0: .B \-V wolffd@0: Causes the program to print version information and exit. wolffd@0: .TP wolffd@0: .B \-? wolffd@0: Causes the program to print usage information and exit. wolffd@0: .SH OPERANDS wolffd@0: The following operand is supported: wolffd@0: .TP 8 wolffd@0: .I files wolffd@0: Names of files containing 1 or more graphs in the dot language. wolffd@0: If no wolffd@0: .B \-f wolffd@0: option is given, the first name is removed from the list and used wolffd@0: as the input program. If the list of files is empty, \fBstdin\fP will be used. wolffd@0: .SH PROGRAMS wolffd@0: A wolffd@0: .B gvpr wolffd@0: program consists of a list of predicate\(hyaction clauses, having one wolffd@0: of the forms: wolffd@0: .IP wolffd@0: .BI "BEGIN { " action " }" wolffd@0: .IP wolffd@0: .BI "BEG_G { " action " }" wolffd@0: .IP wolffd@0: .BI "N [ " predicate " ] { " action " } wolffd@0: .IP wolffd@0: .BI "E [ " predicate " ] { " action " } wolffd@0: .IP wolffd@0: .BI "END_G { " action " }" wolffd@0: .IP wolffd@0: .BI "END { " action " }" wolffd@0: .PP wolffd@0: A program can contain at most one of each of the \fBBEGIN\fP, \fBBEG_G\fP, wolffd@0: \fBEND_G\fP and \fBEND\fP clauses. wolffd@0: There can be any number of \fBN\fP and \fBE\fP statements, wolffd@0: the first applied to nodes, the second to edges. wolffd@0: The top\(hylevel semantics of a \fBgvpr\fP program are: wolffd@0: .PP wolffd@0: .ta \w'\f(CWdelete array[expression]'u wolffd@0: .RS wolffd@0: .nf wolffd@0: Evaluate the \fBBEGIN\fP clause, if any. wolffd@0: For each input graph \fIG\fP { wolffd@0: Set \fIG\fP as the current graph and current object. wolffd@0: Evaluate the \fBBEG_G\fP clause, if any. wolffd@0: For each node and edge in \fIG\fP { wolffd@0: Set the node or edge as the current object. wolffd@0: Evaluate the \fBN\fP or \fBE\fP clauses, as appropriate. wolffd@0: } wolffd@0: Set \fIG\fP as the current object. wolffd@0: Evaluate the \fBEND_G\fP clause, if any. wolffd@0: } wolffd@0: Evaluate the \fBEND\fP clause, if any. wolffd@0: .fi wolffd@0: .RE wolffd@0: .DT wolffd@0: .PP wolffd@0: The actions of the \fBBEGIN\fP, \fBBEG_G\fP, \fBEND_G\fP and \fBEND\fP clauses wolffd@0: are performed when the clauses are evaluated. wolffd@0: For \fBN\fP or \fBE\fP clauses, wolffd@0: either the predicate or action may be omitted. wolffd@0: If there is no predicate with an action, the action is wolffd@0: performed on every node or edge, as appropriate. wolffd@0: If there is no action and the predicate evaluates to true, wolffd@0: the associated node or edge is added to the target graph. wolffd@0: .PP wolffd@0: Predicates and actions are sequences of statements in the C dialect wolffd@0: supported by the wolffd@0: .IR libexpr (3) wolffd@0: library. wolffd@0: The only difference between predicates and actions is that the former wolffd@0: must have a type that may interpreted as either true or false. wolffd@0: Here the usual C convention is followed, in which a non\(hyzero value is wolffd@0: considered true. This would include non\(hyempty strings and non\(hyempty wolffd@0: references to nodes, edges, etc. However, if a string can be wolffd@0: converted to an integer, this value is used. wolffd@0: .PP wolffd@0: In addition to the usual C base types wolffd@0: (\fBvoid\fP, \fBint\fP, \fBchar\fP, \fBfloat\fP, \fBlong\fP, wolffd@0: \fBunsigned\fP and \fBdouble\fP), wolffd@0: \fBgvpr\fP \fRprovides \fBstring\fP as a synonym for \fBchar*\fP, and wolffd@0: the graph\(hybased types \fBnode_t\fP, wolffd@0: \fBedge_t\fP, \fBgraph_t\fP and \fBobj_t\fP. wolffd@0: The \fBobj_t\fP type can be viewed as a supertype of the other 3 concrete types; wolffd@0: the correct base type is maintained dynamically. wolffd@0: Besides these base types, the only other supported type expressions wolffd@0: are (associative) arrays. wolffd@0: .PP wolffd@0: Constants follow C syntax, but strings may be quoted with either wolffd@0: \fB"..."\fP or \fB'...'\fP. In certain contexts, string values are wolffd@0: interpreted as patterns for the purpose of regular expression matching. wolffd@0: Patterns use wolffd@0: .IR ksh (1) wolffd@0: file match pattern syntax. wolffd@0: \fBgvpr\fP accepts C++ comments as well as cpp\(hytype comments. wolffd@0: For the latter, if a line begins with a '#' character, the rest of wolffd@0: the line is ignored. wolffd@0: .PP wolffd@0: A statement can be a declaration of a function, a variable wolffd@0: or an array, or an executable statement. For declarations, there wolffd@0: is a single scope. Array declarations have the form: wolffd@0: .PP wolffd@0: .ta \w'\f(CWdelete array[expression]'u wolffd@0: .RS wolffd@0: .nf wolffd@0: \fI type array \fB[\fP type0 \fB]\fR wolffd@0: .fi wolffd@0: .RE wolffd@0: .DT wolffd@0: .PP wolffd@0: where \fI type0 \fP is optional. If it is supplied, the parser will wolffd@0: enforce that all array subscripts have the specified type. If it is wolffd@0: not supplied, objects of all types can be used as subscripts. wolffd@0: As in C, variables and arrays must wolffd@0: be declared. In particular, an undeclared variable will be interpreted wolffd@0: as the name of an attribute of a node, edge or graph, depending on the wolffd@0: context. wolffd@0: .PP wolffd@0: Executable statements can be one of the following: wolffd@0: .ta \w'\f(CWdelete array[expression]'u wolffd@0: .RS wolffd@0: .nf wolffd@0: \fB{\fR [\fI statement ... \fR] \fB}\fR wolffd@0: \fIexpression\fP \fR// commonly\fP\fI var \fB=\fP expression\fR wolffd@0: \fBif(\fI expression \fP)\fI statement \fR[ \fBelse\fI statement \fR] wolffd@0: \fBfor(\fI expression \fP;\fI expression \fP;\fI expression \fP)\fI statement\fP wolffd@0: \fBfor(\fI array \fP[\fI var \fP])\fI statement\fP wolffd@0: \fBwhile(\fI expression \fP)\fI statement\fP wolffd@0: \fBswitch(\fI expression \fP)\fI case statements\fP wolffd@0: \fBbreak [\fI expression \fP] wolffd@0: \fBcontinue [\fI expression \fP] wolffd@0: \fBreturn [\fI expression \fP]\fR wolffd@0: .fi wolffd@0: .RE wolffd@0: .ST wolffd@0: Items in brackets are optional. wolffd@0: .PP wolffd@0: In the second form of the \fBfor\fP statement, the variable \fIvar\fP wolffd@0: is set to each value used as an index in the specified array and then wolffd@0: the associated \fIstatement\fP is evaluated. Function definitions can wolffd@0: only appear in the \fBBEGIN\fP clause. wolffd@0: .PP wolffd@0: Expressions include the usual C expressions. wolffd@0: String comparisons using \fB==\fP and \fB!=\fP wolffd@0: treat the right hand operand as a pattern. wolffd@0: \fBgvpr\fP will attempt to use an expression as a string or numeric value wolffd@0: as appropriate. wolffd@0: .PP wolffd@0: Expressions of graphical type (i.e., \fBgraph_t, node_t, wolffd@0: edge_t, obj_t\fP) may be followed by a field reference in the wolffd@0: form of \fB.\fP\fIname\fP. The resulting value is the value wolffd@0: of the attribute named \fIname\fP of the given object. wolffd@0: In addition, in certain contexts an undeclared, unmodified wolffd@0: identifier is taken to be an wolffd@0: attribute name. Specifically, such identifiers denote attributes wolffd@0: of the current node or edge, respectively, in \fBN\fP wolffd@0: and \fBE\fP clauses, and the current graph in \fBBEG_G\fP and \fBEND_G\fP wolffd@0: clauses. wolffd@0: .PP wolffd@0: As usual in the wolffd@0: .IR libcgraph (3) wolffd@0: model, attributes are string\(hyvalued. wolffd@0: In addition, wolffd@0: .B gvpr wolffd@0: supports certain pseudo\(hyattributes of graph objects, not necessarily wolffd@0: string\(hyvalued. These reflect intrinsic properties of the graph objects wolffd@0: and cannot be set by the user. wolffd@0: .TP wolffd@0: \fBhead\fR : \fBnode_t\fR wolffd@0: the head of an edge. wolffd@0: .TP wolffd@0: \fBtail\fR : \fBnode_t\fR wolffd@0: the tail of an edge. wolffd@0: .TP wolffd@0: \fBname\fR : \fBstring\fR wolffd@0: the name of an edge, node or graph. The name of an edge has the wolffd@0: form "\fI\fB[\fI\fB]\fR", wolffd@0: where \fI\fP is "\fB\->\fP" or "\fB\-\-\fP" depending on wolffd@0: whether the graph is directed or not. The bracket part \fB[\fI\fB]\fR wolffd@0: only appears if the edge has a non\(hytrivial key. wolffd@0: .TP wolffd@0: \fBindegree\fR : \fBint\fR wolffd@0: the indegree of a node. wolffd@0: .TP wolffd@0: \fBoutdegree\fR : \fBint\fR wolffd@0: the outdegree of a node. wolffd@0: .TP wolffd@0: \fBdegree\fR : \fBint\fR wolffd@0: the degree of a node. wolffd@0: .TP wolffd@0: \fBroot\fR : \fBgraph_t\fR wolffd@0: the root graph of an object. The root of a root graph wolffd@0: is itself. wolffd@0: .TP wolffd@0: \fBparent\fR : \fBgraph_t\fR wolffd@0: the parent graph of a subgraph. The parent of a root graph wolffd@0: is \fBNULL\fP wolffd@0: .TP wolffd@0: \fBn_edges\fR : \fBint\fR wolffd@0: the number of edges in the graph wolffd@0: .TP wolffd@0: \fBn_nodes\fR : \fBint\fR wolffd@0: the number of nodes in the graph wolffd@0: .TP wolffd@0: \fBdirected\fR : \fBint\fR wolffd@0: true (non\(hyzero) if the graph is directed wolffd@0: .TP wolffd@0: \fBstrict\fR : \fBint\fR wolffd@0: true (non\(hyzero) if the graph is strict wolffd@0: .SH "BUILT\(hyIN FUNCTIONS" wolffd@0: .PP wolffd@0: The following functions are built into \fBgvpr\fP. Those functions wolffd@0: returning references to graph objects return \fBNULL\fP in case of failure. wolffd@0: .SS "Graphs and subgraph" wolffd@0: .TP wolffd@0: \fBgraph\fP(\fIs\fP : \fBstring\fP, \fIt\fP : \fBstring\fP) : \fBgraph_t\fP wolffd@0: creates a graph whose name is \fIs\fP and whose type is wolffd@0: specified by the string \fIt\fP. Ignoring case, the characters wolffd@0: \fBU, D, S, N\fR have the interpretation undirected, directed, wolffd@0: strict, and non\(hystrict, respectively. If \fIt\fP is empty, wolffd@0: a directed, non\(hystrict graph is generated. wolffd@0: .TP wolffd@0: \fBsubg\fP(\fIg\fP : \fBgraph_t\fP, \fIs\fP : \fBstring\fP) : \fBgraph_t\fP wolffd@0: creates a subgraph in graph \fIg\fP with name \fIs\fP. If the subgraph wolffd@0: already exists, it is returned. wolffd@0: .TP wolffd@0: \fBisSubg\fP(\fIg\fP : \fBgraph_t\fP, \fIs\fP : \fBstring\fP) : \fBgraph_t\fP wolffd@0: returns the subgraph in graph \fIg\fP with name \fIs\fP, if it exists, wolffd@0: or \fBNULL\fP otherwise. wolffd@0: .TP wolffd@0: \fBfstsubg\fP(\fIg\fP : \fBgraph_t\fP) : \fBgraph_t\fP wolffd@0: returns the first subgraph in graph \fIg\fP, or \fBNULL\fP if none exists. wolffd@0: .TP wolffd@0: \fBnxtsubg\fP(\fIsg\fP : \fBgraph_t\fP) : \fBgraph_t\fP wolffd@0: returns the next subgraph after \fIsg\fP, or \fBNULL\fP. wolffd@0: .TP wolffd@0: \fBisDirect\fP(\fIg\fP : \fBgraph_t\fP) : \fBint\fP wolffd@0: returns true if and only if \fIg\fP is directed. wolffd@0: .TP wolffd@0: \fBisStrict\fP(\fIg\fP : \fBgraph_t\fP) : \fBint\fP wolffd@0: returns true if and only if \fIg\fP is strict. wolffd@0: .TP wolffd@0: \fBnNodes\fP(\fIg\fP : \fBgraph_t\fP) : \fBint\fP wolffd@0: returns the number of nodes in \fIg\fP. wolffd@0: .TP wolffd@0: \fBnEdges\fP(\fIg\fP : \fBgraph_t\fP) : \fBint\fP wolffd@0: returns the number of edges in \fIg\fP. wolffd@0: .SS "Nodes" wolffd@0: .TP wolffd@0: \fBnode\fP(\fIsg\fP : \fBgraph_t\fP, \fIs\fP : \fBstring\fP) : \fBnode_t\fP wolffd@0: creates a node in graph \fIg\fP of name \fIs\fP. If such a node wolffd@0: already exists, it is returned. wolffd@0: .TP wolffd@0: \fBsubnode\fP(\fIsg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBnode_t\fP wolffd@0: inserts the node \fIn\fP into the subgraph \fIg\fP. Returns the node. wolffd@0: .TP wolffd@0: \fBfstnode\fP(\fIg\fP : \fBgraph_t\fP) : \fBnode_t\fP wolffd@0: returns the first node in graph \fIg\fP, or \fBNULL\fP if none exists. wolffd@0: .TP wolffd@0: \fBnxtnode\fP(\fIn\fP : \fBnode_t\fP) : \fBnode_t\fP wolffd@0: returns the next node after \fIn\fP in the root graph, or \fBNULL\fP. wolffd@0: .TP wolffd@0: \fBnxtnode_sg\fP(\fIsg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBnode_t\fP wolffd@0: returns the next node after \fIn\fP in \fIsg\fP, or \fBNULL\fP. wolffd@0: .TP wolffd@0: \fBisNode\fP(\fIsg\fP : \fBgraph_t\fP, \fIs\fP : \fBstring\fP) : \fBnode_t\fP wolffd@0: looks for a node in (sub)graph \fIsg\fP of name \fIs\fP. If such a node wolffd@0: exists, it is returned. Otherwise, \fBNULL\fP is returned. wolffd@0: .TP wolffd@0: \fBisSubnode\fP(\fIsg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBint\fP wolffd@0: returns non-zero if node \fIn\fP is in (sub)graph \fIsg\fP, or zero wolffd@0: otherwise. wolffd@0: .TP wolffd@0: \fBindegreeOf\fP(\fIsg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBint\fP wolffd@0: returns the indegree of node \fIn\fP in (sub)graph \fIsg\fP. wolffd@0: .TP wolffd@0: \fBoutdegreeOf\fP(\fIsg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBint\fP wolffd@0: returns the outdegree of node \fIn\fP in (sub)graph \fIsg\fP. wolffd@0: .TP wolffd@0: \fBdegreeOf\fP(\fIsg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBint\fP wolffd@0: returns the degree of node \fIn\fP in (sub)graph \fIsg\fP. wolffd@0: .SS "Edges" wolffd@0: .TP wolffd@0: \fBedge\fP(\fIt\fP : \fBnode_t\fP, \fIh\fP : \fBnode_t\fP, \fIs\fP : \fBstring\fP) : \fBedge_t\fP wolffd@0: creates an edge with tail node \fIt\fP, head node \fIh\fP and wolffd@0: name \fIs\fP in the root graph. If the graph is undirected, the wolffd@0: distinction between head and tail nodes is unimportant. wolffd@0: If such an edge already exists, it is returned. wolffd@0: .TP wolffd@0: \fBedge_sg\fP(\fIsg\fP : \fBgraph_t\fP, \fIt\fP : \fBnode_t\fP, \fIh\fP : \fBnode_t\fP, \fIs\fP : \fBstring\fP) : \fBedge_t\fP wolffd@0: creates an edge with tail node \fIt\fP, head node \fIh\fP and name \fIs\fP wolffd@0: in (sub)graph \fIsg\fP (and all parent graphs). If the graph is undirected, the distinction between wolffd@0: head and tail nodes is unimportant. wolffd@0: If such an edge already exists, it is returned. wolffd@0: .TP wolffd@0: \fBsubedge\fP(\fIg\fP : \fBgraph_t\fP, \fIe\fP : \fBedge_t\fP) : \fBedge_t\fP wolffd@0: inserts the edge \fIe\fP into the subgraph \fIg\fP. Returns the edge. wolffd@0: .TP wolffd@0: \fBisEdge\fP(\fIt\fP : \fBnode_t\fP, \fIh\fP : \fBnode_t\fP, \fIs\fP : \fBstring\fP) : \fBedge_t\fP wolffd@0: looks for an edge with tail node \fIt\fP, head node \fIh\fP and wolffd@0: name \fIs\fP. If the graph is undirected, the distinction between wolffd@0: head and tail nodes is unimportant. wolffd@0: If such an edge exists, it is returned. Otherwise, \fBNULL\fP is returned. wolffd@0: .TP wolffd@0: \fBisEdge_sg\fP(\fIsg\fP : \fBgraph_t\fP, \fIt\fP : \fBnode_t\fP, \fIh\fP : \fBnode_t\fP, \fIs\fP : \fBstring\fP) : \fBedge_t\fP wolffd@0: looks for an edge with tail node \fIt\fP, head node \fIh\fP and wolffd@0: name \fIs\fP in (sub)graph \fIsg\fP. If the graph is undirected, the distinction between wolffd@0: head and tail nodes is unimportant. wolffd@0: If such an edge exists, it is returned. Otherwise, \fBNULL\fP is returned. wolffd@0: .TP wolffd@0: \fBisSubedge\fP(\fIg\fP : \fBgraph_t\fP, \fIe\fP : \fBedge_t\fP) : \fBint\fP wolffd@0: returns non-zero if edge \fIe\fP is in (sub)graph \fIsg\fP, or zero wolffd@0: otherwise. wolffd@0: .TP wolffd@0: \fBfstout\fP(\fIn\fP : \fBnode_t\fP) : \fBedge_t\fP wolffd@0: returns the first outedge of node \fIn\fP in the root graph. wolffd@0: .TP wolffd@0: \fBfstout_sg\fP(\fIsg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBedge_t\fP wolffd@0: returns the first outedge of node \fIn\fP in (sub)graph \fIsg\fP. wolffd@0: .TP wolffd@0: \fBnxtout\fP(\fIe\fP : \fBedge_t\fP) : \fBedge_t\fP wolffd@0: returns the next outedge after \fIe\fP in the root graph. wolffd@0: .TP wolffd@0: \fBnxtout_sg\fP(\fIsg\fP : \fBgraph_t\fP, \fIe\fP : \fBedge_t\fP) : \fBedge_t\fP wolffd@0: returns the next outedge after \fIe\fP in graph \fIsg\fP. wolffd@0: .TP wolffd@0: \fBfstin\fP(\fIn\fP : \fBnode_t\fP) : \fBedge_t\fP wolffd@0: returns the first inedge of node \fIn\fP in the root graph. wolffd@0: .TP wolffd@0: \fBfstin_sg\fP(\fIsg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBedge_t\fP wolffd@0: returns the first inedge of node \fIn\fP in graph \fIsg\fP. wolffd@0: .TP wolffd@0: \fBnxtin\fP(\fIe\fP : \fBedge_t\fP) : \fBedge_t\fP wolffd@0: returns the next inedge after \fIe\fP in the root graph. wolffd@0: .TP wolffd@0: \fBnxtin_sg\fP(\fIsg\fP : \fBgraph_t\fP, \fIe\fP : \fBedge_t\fP) : \fBedge_t\fP wolffd@0: returns the next inedge after \fIe\fP in graph \fIsg\fP. wolffd@0: .TP wolffd@0: \fBfstedge\fP(\fIn\fP : \fBnode_t\fP) : \fBedge_t\fP wolffd@0: returns the first edge of node \fIn\fP in the root graph. wolffd@0: .TP wolffd@0: \fBfstedge_sg\fP(\fIsg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBedge_t\fP wolffd@0: returns the first edge of node \fIn\fP in graph \fIsg\fP. wolffd@0: .TP wolffd@0: \fBnxtedge\fP(\fIe\fP : \fBedge_t\fP, \fBnode_t\fP) : \fBedge_t\fP wolffd@0: returns the next edge after \fIe\fP in the root graph. wolffd@0: .TP wolffd@0: \fBnxtedge_sg\fP(\fIsg\fP : \fBgraph_t\fP, \fIe\fP : \fBedge_t\fP, \fBnode_t\fP) : \fBedge_t\fP wolffd@0: returns the next edge after \fIe\fP in the graph \fIsg\fP. wolffd@0: .SS "Graph I/O" wolffd@0: .TP wolffd@0: \fBwrite\fP(\fIg\fP : \fBgraph_t\fP) : \fBvoid\fP wolffd@0: prints \fIg\fP in dot format onto the output stream. wolffd@0: .TP wolffd@0: \fBwriteG\fP(\fIg\fP : \fBgraph_t\fP, \fIfname\fP : \fBstring\fP) : \fBvoid\fP wolffd@0: prints \fIg\fP in dot format into the file \fIfname\fP. wolffd@0: .TP wolffd@0: \fBfwriteG\fP(\fIg\fP : \fBgraph_t\fP, \fIfd\fP : \fBint\fP) : \fBvoid\fP wolffd@0: prints \fIg\fP in dot format onto the open stream denoted wolffd@0: by the integer \fIfd\fP. wolffd@0: .TP wolffd@0: \fBreadG\fP(\fIfname\fP : \fBstring\fP) : \fBgraph_t\fP wolffd@0: returns a graph read from the file \fIfname\fP. The graph should be wolffd@0: in dot format. If no graph can be read, \fBNULL\fP is returned. wolffd@0: .TP wolffd@0: \fBfreadG\fP(\fIfd\fP : \fBint\fP) : \fBgraph_t\fP wolffd@0: returns the next graph read from the open stream \fIfd\fP. wolffd@0: Returns \fBNULL\fP at end of file. wolffd@0: .SS "Graph miscellany" wolffd@0: .TP wolffd@0: \fBdelete\fP(\fIg\fP : \fBgraph_t\fP, \fIx\fP : \fBobj_t\fP) : \fBvoid\fP wolffd@0: deletes object \fIx\fP from graph \fIg\fP. wolffd@0: If \fIg\fP is \fBNULL\fP, the function uses the root graph of \fIx\fP. wolffd@0: If \fIx\fP is a graph or subgraph, it is closed unless \fIx\fP is locked. wolffd@0: .TP wolffd@0: \fBisIn\fP(\fIg\fP : \fBgraph_t\fP, \fIx\fP : \fBobj_t\fP) : \fBint\fP wolffd@0: returns true if \fIx\fP is in subgraph \fIg\fP. wolffd@0: .TP wolffd@0: \fBclone\fP(\fIg\fP : \fBgraph_t\fP, \fIx\fP : \fBobj_t\fP) : \fBobj_t\fP wolffd@0: creates a clone of object \fIx\fP in graph \fIg\fP. wolffd@0: In particular, the new object has the same name/value attributes wolffd@0: and structure as the original object. wolffd@0: If an object with the same key as \fIx\fP already exists, its attributes wolffd@0: are overlaid by those of \fIx\fP and the object is returned. wolffd@0: If an edge is cloned, both endpoints are implicitly cloned. wolffd@0: If a graph is cloned, all nodes, edges and subgraphs are implicitly wolffd@0: cloned. wolffd@0: If \fIx\fP is a graph, \fIg\fP may be \fBNULL\fP, in which case the cloned wolffd@0: object will be a new root graph. wolffd@0: .TP wolffd@0: \fBcopy\fP(\fIg\fP : \fBgraph_t\fP, \fIx\fP : \fBobj_t\fP) : \fBobj_t\fP wolffd@0: creates a copy of object \fIx\fP in graph \fIg\fP, wolffd@0: where the new object has the same name/value attributes wolffd@0: as the original object. wolffd@0: If an object with the same key as \fIx\fP already exists, its attributes wolffd@0: are overlaid by those of \fIx\fP and the object is returned. wolffd@0: Note that this is a shallow copy. If \fIx\fP is a graph, none of its nodes, wolffd@0: edges or subgraphs are copied into the new graph. If \fIx\fP is an edge, wolffd@0: the endpoints are created if necessary, but they are not cloned. wolffd@0: If \fIx\fP is a graph, \fIg\fP may be \fBNULL\fP, in which case the cloned wolffd@0: object will be a new root graph. wolffd@0: .TP wolffd@0: \fBcopyA\fP(\fIsrc\fP : \fBobj_t\fP, \fItgt\fP : \fBobj_t\fP) : \fBint\fP wolffd@0: copies the attributes of object \fIsrc\fP to object \fItgt\fP, overwriting wolffd@0: any attribute values \fItgt\fP may initially have. wolffd@0: .TP wolffd@0: \fBinduce\fP(\fIg\fP : \fBgraph_t\fP) : \fBvoid\fP wolffd@0: extends \fIg\fP to its node\(hyinduced subgraph extension in its root graph. wolffd@0: .TP wolffd@0: \fBhasAttr\fP(\fIsrc\fP : \fBobj_t\fP, \fIname\fP : \fBstring\fP) : \fBint\fP wolffd@0: returns non-zero if object \fIsrc\fP has an attribute whose name is wolffd@0: \fIname\fP. It returns 0 otherwise. wolffd@0: .TP wolffd@0: \fBisAttr\fP(\fIg\fP : \fBgraph_t\fP, \fIkind\fP : \fBstring\fP, \fIname\fP : \fBstring\fP) : \fBint\fP wolffd@0: returns non-zero if an attribute \fIname\fP has been defined in \fIg\fP wolffd@0: for objects of the given \fIkind\fP. For nodes, edges, and graphs, \fIkind\fP wolffd@0: should be "N", "E", and "G", respectively. wolffd@0: It returns 0 otherwise. wolffd@0: .TP wolffd@0: \fBaget\fP(\fIsrc\fP : \fBobj_t\fP, \fIname\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns the value of attribute \fIname\fP in object \fIsrc\fP. This is wolffd@0: useful for those cases when \fIname\fP conflicts with one of the keywords wolffd@0: such as "head" or "root". wolffd@0: If the attribute has not been declared in the graph, the function will wolffd@0: initialize it with a default value of "". To avoid this, one should use wolffd@0: the \fBhasAttr\fP or \fBisAttr\fP function to check that the attribute exists. wolffd@0: .TP wolffd@0: \fBaset\fP(\fIsrc\fP : \fBobj_t\fP, \fIname\fP : \fBstring\fP, \fIvalue\fP : \fBstring\fP) : \fBint\fP wolffd@0: sets the value of attribute \fIname\fP in object \fIsrc\fP to \fIvalue\fP. wolffd@0: Returns 0 on success, non\(hyzero on failure. See \fBaget\fP above. wolffd@0: .TP wolffd@0: \fBgetDflt\fP(\fIg\fP : \fBgraph_t\fP, \fIkind\fP : \fBstring\fP, \fIname\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns the default value of attribute \fIname\fP in objects in \fIg\fP of wolffd@0: the given \fIkind\fP. For nodes, edges, and graphs, \fIkind\fP wolffd@0: should be "N", "E", and "G", respectively. wolffd@0: If the attribute has not been declared in the graph, the function will wolffd@0: initialize it with a default value of "". To avoid this, one should use wolffd@0: the \fBisAttr\fP function to check that the attribute exists. wolffd@0: .TP wolffd@0: \fBsetDflt\fP(\fIg\fP : \fBgraph_t\fP, \fIkind\fP : \fBstring\fP, \fIname\fP : \fBstring\fP, \fIvalue\fP : \fBstring\fP) : \fBint\fP wolffd@0: sets the default value of attribute \fIname\fP to \fIvalue\fP in wolffd@0: objects in \fIg\fP of wolffd@0: the given \fIkind\fP. For nodes, edges, and graphs, \fIkind\fP wolffd@0: should be "N", "E", and "G", respectively. wolffd@0: Returns 0 on success, non\(hyzero on failure. See \fBgetDflt\fP above. wolffd@0: .TP wolffd@0: \fBfstAttr\fP(\fIg\fP : \fBgraph_t\fP, \fIkind\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns the name of the first attribute of objects in \fIg\fP of wolffd@0: the given \fIkind\fP. For nodes, edges, and graphs, \fIkind\fP wolffd@0: should be "N", "E", and "G", respectively. wolffd@0: If there are no attributes, the string "" is returned. wolffd@0: .TP wolffd@0: \fBnxtAttr\fP(\fIg\fP : \fBgraph_t\fP, \fIkind\fP : \fBstring\fP, \fIname\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns the name of the next attribute of objects in \fIg\fP of wolffd@0: the given \fIkind\fP after the attribute \fIname\fP. wolffd@0: The argument \fIname\fP must be the name of an existing attribute; it will wolffd@0: typically be the return value of an previous call to \fBfstAttr\fP or wolffd@0: \fBnxtAttr\fP. wolffd@0: For nodes, edges, and graphs, \fIkind\fP wolffd@0: should be "N", "E", and "G", respectively. wolffd@0: If there are no attributes left, the string "" is returned. wolffd@0: .TP wolffd@0: \fBcompOf\fP(\fIg\fP : \fBgraph_t\fP, \fIn\fP : \fBnode_t\fP) : \fBgraph_t\fP wolffd@0: returns the connected component of the graph \fIg\fP containing node \fIn\fP, wolffd@0: as a subgraph of \fIg\fP. The subgraph only contains the nodes. One can wolffd@0: use \fIinduce\fP to add the edges. The function fails and returns \fBNULL\fP wolffd@0: if \fIn\fP is not in \fIg\fP. Connectivity is based on the underlying wolffd@0: undirected graph of \fIg\fP. wolffd@0: .TP wolffd@0: \fBkindOf\fP(\fIobj\fP : \fBobj_t\fP) : \fBstring\fP wolffd@0: returns an indication of what kind of graph object is the argument. wolffd@0: For nodes, edges, and graphs, it returns wolffd@0: should be "N", "E", and "G", respectively. wolffd@0: .TP wolffd@0: \fBlock\fP(\fIg\fP : \fBgraph_t\fP, \fIv\fP : \fBint\fP) : \fBint\fP wolffd@0: implements graph locking on root graphs. If the integer \fIv\fP is positive, the wolffd@0: graph is set so that future calls to \fBdelete\fP have no immediate effect. wolffd@0: If \fIv\fP is zero, the graph is unlocked. If there has been a call wolffd@0: to delete the graph while it was locked, the graph is closed. wolffd@0: If \fIv\fP is negative, nothing is done. wolffd@0: In all cases, the previous lock value is returned. wolffd@0: .SS "Strings" wolffd@0: .TP wolffd@0: \fBsprintf\fP(\fIfmt\fP : \fBstring\fP, \fI...\fP) : \fBstring\fP wolffd@0: returns the string resulting from formatting wolffd@0: the values of the expressions occurring after \fIfmt\fP wolffd@0: according to the wolffd@0: .IR printf (3) wolffd@0: format wolffd@0: .I fmt wolffd@0: .TP wolffd@0: \fBgsub\fP(\fIstr\fP : \fBstring\fP, \fIpat\fP : \fBstring\fP) : \fBstring\fP wolffd@0: .TP wolffd@0: \fBgsub\fP(\fIstr\fP : \fBstring\fP, \fIpat\fP : \fBstring\fP, \fIrepl\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns \fIstr\fP with all substrings matching \fIpat\fP wolffd@0: deleted or replaced by \fIrepl\fP, respectively. wolffd@0: .TP wolffd@0: \fBsub\fP(\fIstr\fP : \fBstring\fP, \fIpat\fP : \fBstring\fP) : \fBstring\fP wolffd@0: .TP wolffd@0: \fBsub\fP(\fIstr\fP : \fBstring\fP, \fIpat\fP : \fBstring\fP, \fIrepl\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns \fIstr\fP with the leftmost substring matching \fIpat\fP wolffd@0: deleted or replaced by \fIrepl\fP, respectively. The wolffd@0: characters '^' and '$' wolffd@0: may be used at the beginning and end, respectively, wolffd@0: of \fIpat\fP to anchor the pattern to the beginning or end of \fIstr\fP. wolffd@0: .TP wolffd@0: \fBsubstr\fP(\fIstr\fP : \fBstring\fP, \fIidx\fP : \fBint\fP) : \fBstring\fP wolffd@0: .TP wolffd@0: \fBsubstr\fP(\fIstr\fP : \fBstring\fP, \fIidx\fP : \fBint\fP, \fIlen\fP : \fBint\fP) : \fBstring\fP wolffd@0: returns the substring of \fIstr\fP starting at position \fIidx\fP to wolffd@0: the end of the string or of length \fIlen\fP, respectively. wolffd@0: Indexing starts at 0. If \fIidx\fP is negative or \fIidx\fP is greater than wolffd@0: the length of \fIstr\fP, a fatal error occurs. Similarly, in the second wolffd@0: case, if \fIlen\fP is negative or \fIidx\fP + \fIlen\fP is greater than the wolffd@0: length of \fIstr\fP, a fatal error occurs. wolffd@0: .TP wolffd@0: \fBlength\fP(\fIs\fP : \fBstring\fP) : \fBint\fP wolffd@0: returns the length of the string \fIs\fP. wolffd@0: .TP wolffd@0: \fBindex\fP(\fIs\fP : \fBstring\fP, \fIt\fP : \fBstring\fP) : \fBint\fP wolffd@0: .TP wolffd@0: \fBrindex\fP(\fIs\fP : \fBstring\fP, \fIt\fP : \fBstring\fP) : \fBint\fP wolffd@0: returns the index of the character in string \fIs\fP where the leftmost wolffd@0: (rightmost) copy of string \fIt\fP can be found, or \-1 if \fIt\fP is not a wolffd@0: substring of \fIs\fP. wolffd@0: .TP wolffd@0: \fBmatch\fP(\fIs\fP : \fBstring\fP, \fIp\fP : \fBstring\fP) : \fBint\fP wolffd@0: returns the index of the character in string \fIs\fP where the leftmost wolffd@0: match of pattern \fIp\fP can be found, or \-1 if no substring of \fIs\fP wolffd@0: matches \fIp\fP. wolffd@0: .TP wolffd@0: \fBcanon\fP(\fIs\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns a version of \fIs\fP appropriate to be used as an identifier wolffd@0: in a dot file. wolffd@0: .TP wolffd@0: \fBxOf\fP(\fIs\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns the string "\fIx\fP" if \fIs\fP has the form "\fIx\fP,\fIy\fP", wolffd@0: where both \fIx\fP and \fIy\fP are numeric. wolffd@0: .TP wolffd@0: \fByOf\fP(\fIs\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns the string "\fIy\fP" if \fIs\fP has the form "\fIx\fP,\fIy\fP", wolffd@0: where both \fIx\fP and \fIy\fP are numeric. wolffd@0: .TP wolffd@0: \fBllOf\fP(\fIs\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns the string "\fIllx\fP,\fIlly\fP" if \fIs\fP has the form wolffd@0: "\fIllx\fP,\fIlly\fP,\fIurx\fP,\fIury\fP", wolffd@0: where all of \fIllx\fP, \fIlly\fP, \fIurx\fP, and \fIury\fP are numeric. wolffd@0: .TP wolffd@0: .BI urOf( s ) wolffd@0: \fBurOf\fP(\fIs\fP : \fBstring\fP) : \fBstring\fP wolffd@0: returns the string "\fIurx\fP,\fIury\fP" if \fIs\fP has the form wolffd@0: "\fIllx\fP,\fIlly\fP,\fIurx\fP,\fIury\fP", wolffd@0: where all of \fIllx\fP, \fIlly\fP, \fIurx\fP, and \fIury\fP are numeric. wolffd@0: .TP wolffd@0: \fBsscanf\fP(\fIs\fP : \fBstring\fP, \fIfmt\fP : \fBstring\fP, \fI...\fP) : \fBint\fP wolffd@0: scans the string \fIs\fP, extracting values wolffd@0: according to the wolffd@0: .IR sscanf (3) wolffd@0: format wolffd@0: .IR fmt . wolffd@0: The values are stored in the addresses following \fIfmt\fP, wolffd@0: addresses having the form \fB&\fP\fIv\fP, where \fIv\fP is some declared wolffd@0: variable of the correct type. wolffd@0: Returns the number of items successfully scanned. wolffd@0: .SS "I/O" wolffd@0: .TP wolffd@0: \fBprint\fP(\fI...\fP) : \fBvoid\fP wolffd@0: .BI print( " expr" , " ...\fB ) wolffd@0: prints a string representation of each argument in turn onto wolffd@0: \fBstdout\fP, followed by a newline. wolffd@0: .TP wolffd@0: \fBprintf\fP(\fIfmt\fP : \fBstring\fP, \fI...\fP) : \fBint\fP wolffd@0: .TP wolffd@0: \fBprintf\fP(\fIfd\fP : \fBint\fP, \fIfmt\fP : \fBstring\fP, \fI...\fP) : \fBint\fP wolffd@0: prints the string resulting from formatting wolffd@0: the values of the expressions following \fIfmt\fP wolffd@0: according to the wolffd@0: .IR printf (3) wolffd@0: format wolffd@0: .IR fmt . wolffd@0: Returns 0 on success. wolffd@0: By default, it prints on \fBstdout\fP. wolffd@0: If the optional integer \fIfd\fP is given, output is written on the open wolffd@0: stream associated with \fIfd\fP. wolffd@0: .TP wolffd@0: \fBscanf\fP(\fIfmt\fP : \fBstring\fP, \fI...\fP) : \fBint\fP wolffd@0: .TP wolffd@0: \fBscanf\fP(\fIfd\fP : \fBint\fP, \fIfmt\fP : \fBstring\fP, \fI...\fP) : \fBint\fP wolffd@0: scans in values from an input stream according to the wolffd@0: .IR scanf (3) wolffd@0: format wolffd@0: .IR fmt . wolffd@0: The values are stored in the addresses following \fIfmt\fP, wolffd@0: addresses having the form \fB&\fP\fIv\fP, where \fIv\fP is some declared wolffd@0: variable of the correct type. wolffd@0: By default, it reads from \fBstdin\fP. wolffd@0: If the optional integer \fIfd\fP is given, input is read from the open wolffd@0: stream associated with \fIfd\fP. wolffd@0: Returns the number of items successfully scanned. wolffd@0: .TP wolffd@0: \fBopenF\fP(\fIs\fP : \fBstring\fP, \fIt\fP : \fBstring\fP) : \fBint\fP wolffd@0: opens the file \fIs\fP as an I/O stream. The string argument \fIt\fP wolffd@0: specifies how the file is opened. The arguments are the same as for wolffd@0: the C function wolffd@0: .IR fopen (3). wolffd@0: It returns an integer denoting the stream, or \-1 on error. wolffd@0: .sp wolffd@0: As usual, streams 0, 1 and 2 are already open as \fBstdin\fP, \fBstdout\fP, wolffd@0: and \fBstderr\fP, respectively. Since \fBgvpr\fP may use \fBstdin\fP to wolffd@0: read the input graphs, the user should avoid using this stream. wolffd@0: .TP wolffd@0: \fBcloseF\fP(\fIfd\fP : \fBint\fP) : \fBint\fP wolffd@0: closes the open stream denoted by the integer \fIfd\fP. wolffd@0: Streams 0, 1 and 2 cannot be closed. wolffd@0: Returns 0 on success. wolffd@0: .TP wolffd@0: \fBreadL\fP(\fIfd\fP : \fBint\fP) : \fBstring\fP wolffd@0: returns the next line read from the input stream \fIfd\fP. It returns wolffd@0: the empty string "" on end of file. Note that the newline character is wolffd@0: left in the returned string. wolffd@0: .SS "Math" wolffd@0: .TP wolffd@0: \fBexp\fP(\fId\fP : \fBdouble\fP) : \fBdouble\fP wolffd@0: returns e to the \fId\fPth power. wolffd@0: .TP wolffd@0: \fBlog\fP(\fId\fP : \fBdouble\fP) : \fBdouble\fP wolffd@0: returns the natural log of \fId\fP. wolffd@0: .TP wolffd@0: \fBsqrt\fP(\fId\fP : \fBdouble\fP) : \fBdouble\fP wolffd@0: returns the square root of the double \fId\fP. wolffd@0: .TP wolffd@0: \fBpow\fP(\fId\fP : \fBdouble\fP, \fIx\fP : \fBdouble\fP) : \fBdouble\fP wolffd@0: returns \fId\fP raised to the \fIx\fPth power. wolffd@0: .TP wolffd@0: \fBcos\fP(\fId\fP : \fBdouble\fP) : \fBdouble\fP wolffd@0: returns the cosine of \fId\fP. wolffd@0: .TP wolffd@0: \fBsin\fP(\fId\fP : \fBdouble\fP) : \fBdouble\fP wolffd@0: returns the sine of \fId\fP. wolffd@0: .TP wolffd@0: \fBatan2\fP(\fIy\fP : \fBdouble\fP, \fIx\fP : \fBdouble\fP) : \fBdouble\fP wolffd@0: returns the arctangent of \fIy/x\fP in the range \-pi to pi. wolffd@0: .TP wolffd@0: \fBMIN\fP(\fIy\fP : \fBdouble\fP, \fIx\fP : \fBdouble\fP) : \fBdouble\fP wolffd@0: returns the minimum of \fIy\fP and \fIx\fP. wolffd@0: .TP wolffd@0: \fBMAX\fP(\fIy\fP : \fBdouble\fP, \fIx\fP : \fBdouble\fP) : \fBdouble\fP wolffd@0: returns the maximum of \fIy\fP and \fIx\fP. wolffd@0: .SS "Miscellaneous" wolffd@0: .TP wolffd@0: \fBexit\fP(\fIv\fP : \fBint\fP) : \fBvoid\fP wolffd@0: causes wolffd@0: .B gvpr wolffd@0: to exit with the exit code wolffd@0: .IR v . wolffd@0: .TP wolffd@0: \fBsystem\fP(\fIcmd\fP : \fBstring\fP) : \fBint\fP wolffd@0: provides the standard C function wolffd@0: .IR system (3). wolffd@0: It executes \fIcmd\fP if the user's shell environment, and wolffd@0: returns the exit status of the shell. wolffd@0: .TP wolffd@0: \fBrand\fP() : \fBdouble\fP wolffd@0: returns a pseudo\(hyrandom double between 0 and 1. wolffd@0: .TP wolffd@0: \fBsrand\fP() : \fBint\fP wolffd@0: .TP wolffd@0: \fBsrand\fP(\fIv\fP : \fBint\fP) : \fBint\fP wolffd@0: sets a seed for the random number generator. The optional argument gives wolffd@0: the seed; if it is omitted, the current time is used. The previous seed wolffd@0: value is returned. \fBsrand\fP should be called before any calls to wolffd@0: \fBrand\fP. wolffd@0: .SH "BUILT\(hyIN VARIABLES" wolffd@0: .PP wolffd@0: .B gvpr wolffd@0: provides certain special, built\(hyin variables, whose values are set wolffd@0: automatically by \fBgvpr\fP depending on the context. Except as noted, wolffd@0: the user cannot modify their values. wolffd@0: .TP wolffd@0: \fB$\fP : \fBobj_t\fP wolffd@0: denotes the current object (node, edge, graph) depending on the wolffd@0: context. It is not available in \fBBEGIN\fP or \fBEND\fP clauses. wolffd@0: .TP wolffd@0: \fB$F\fP : \fBstring\fP wolffd@0: is the name of the current input file. wolffd@0: .TP wolffd@0: \fB$G\fP : \fBgraph_t\fP wolffd@0: denotes the current graph being processed. It is not available wolffd@0: in \fBBEGIN\fP or \fBEND\fP clauses. wolffd@0: .TP wolffd@0: \fB$O\fP : \fBgraph_t\fP wolffd@0: denotes the output graph. Before graph traversal, it is initialized wolffd@0: to the target graph. After traversal and any \fBEND_G\fP actions, wolffd@0: if it refers to a non\(hyempty graph, that graph is printed onto the output stream. wolffd@0: It is only valid in \fBN\fP, \fBE\fP and \fBEND_G\fP clauses. wolffd@0: The output graph may be set by the user. wolffd@0: .TP wolffd@0: \fB$T\fP : \fBgraph_t\fP wolffd@0: denotes the current target graph. It is a subgraph of \fB$G\fP wolffd@0: and is available only in \fBN\fP, \fBE\fP and \fBEND_G\fP clauses. wolffd@0: .TP wolffd@0: \fB$tgtname\fP : \fBstring\fP wolffd@0: denotes the name of the target graph. wolffd@0: By default, it is set to \fB"gvpr_result"\fP. wolffd@0: If used multiple times during the execution of wolffd@0: .BR gvpr , wolffd@0: the name will be appended with an integer. wolffd@0: This variable may be set by the user. wolffd@0: .TP wolffd@0: \fB$tvroot\fP : \fBnode_t\fP wolffd@0: indicates the starting node for a (directed or undirected) wolffd@0: depth\(hyfirst traversal of the wolffd@0: graph (cf. \fB$tvtype\fP below). wolffd@0: The default value is \fBNULL\fP for each input graph. wolffd@0: .TP wolffd@0: \fB$tvtype\fP : \fBtvtype_t\fP wolffd@0: indicates how \fBgvpr\fP traverses a graph. It can only take wolffd@0: one of the constant values with the previx "TV_" described below. wolffd@0: \fBTV_flat\fP is the default. wolffd@0: .IP wolffd@0: In the underlying graph library wolffd@0: .IR cgraph (3), wolffd@0: edges in undirected graphs are given an arbitrary direction. This is wolffd@0: used for traversals, such as \fBTV_fwd\fR, requiring directed edges. wolffd@0: . wolffd@0: .TP wolffd@0: \fBARGC\fP : \fBint\fP wolffd@0: denotes the number of arguments specified by the wolffd@0: \fB\-a\fP \fIargs\fP command\(hyline argument. wolffd@0: .TP wolffd@0: \fBARGV\fP : \fBstring array\fP wolffd@0: denotes the array of arguments specified by the wolffd@0: \fB\-a\fP \fIargs\fP wolffd@0: command\(hyline argument. The \fIi\fPth argument is given wolffd@0: by \fBARGV[\fIi\fP]\fR. wolffd@0: .SH "BUILT\(hyIN CONSTANTS" wolffd@0: .PP wolffd@0: There are several symbolic constants defined by \fBgvpr\fP. wolffd@0: .TP wolffd@0: \fBNULL\fR : \fIobj_t\fR wolffd@0: a null object reference, equivalent to 0. wolffd@0: .TP wolffd@0: \fBTV_flat\fR : \fItvtype_t\fR wolffd@0: a simple, flat traversal, with graph objects visited in wolffd@0: seemingly arbitrary order. wolffd@0: .TP wolffd@0: \fBTV_ne\fR : \fItvtype_t\fR wolffd@0: a traversal which first visits all of the nodes, then all wolffd@0: of the edges. wolffd@0: .TP wolffd@0: \fBTV_en\fR : \fItvtype_t\fR wolffd@0: a traversal which first visits all of the edges, then all wolffd@0: of the nodes. wolffd@0: .TP wolffd@0: \fBTV_dfs\fR : \fItvtype_t\fR wolffd@0: .TQ wolffd@0: \fBTV_postdfs\fR : \fItvtype_t\fR wolffd@0: .TQ wolffd@0: \fBTV_prepostdfs\fR : \fItvtype_t\fR wolffd@0: a traversal of the graph using a depth\(hyfirst search on the wolffd@0: underlying undirected graph. wolffd@0: To do the traversal, \fBgvpr\fP will check the value of wolffd@0: \fB$tvroot\fP. If this has the same value that it had previously wolffd@0: (at the start, the previous value is initialized to \fBNULL\fP.), \fBgvpr\fP wolffd@0: will simply look for some unvisited node and traverse its connected wolffd@0: component. On the other hand, if \fB$tvroot\fP has changed, its connected wolffd@0: component will be toured, assuming it has not been previously visited or, wolffd@0: if \fB$tvroot\fP is \fBNULL\fP, the traversal will stop. Note that using wolffd@0: \fBTV_dfs\fP and \fB$tvroot\fP, it is possible to create an infinite loop. wolffd@0: . wolffd@0: .IP wolffd@0: By default, the traversal is done in pre-order. That is, a node is wolffd@0: visited before all of its unvisited edges. For \fBTV_postdfs\fR, wolffd@0: all of a node's unvisited edges are visited before the node. For wolffd@0: \fBTV_prepostdfs\fR, a node is visited twice, before and after all of wolffd@0: its unvisited edges. wolffd@0: . wolffd@0: .TP wolffd@0: \fBTV_fwd\fR : \fItvtype_t\fR wolffd@0: .TQ wolffd@0: \fBTV_postfwd\fR : \fItvtype_t\fR wolffd@0: .TQ wolffd@0: \fBTV_prepostfwd\fR : \fItvtype_t\fR wolffd@0: A traversal of the graph using a depth\(hyfirst search on the wolffd@0: graph following only forward arcs. wolffd@0: The choice of roots for the traversal is the wolffd@0: same as described for \fBTV_dfs\fR above. wolffd@0: The different order of visitation specified by \fBTV_fwd\fR, wolffd@0: \fBTV_postfwd\fR and \fBTV_prepostfwd\fR are the same as those wolffd@0: specified by the analogous traversals \fBTV_dfs\fR, wolffd@0: \fBTV_postdfs\fR and \fBTV_prepostdfs\fR. wolffd@0: .TP wolffd@0: \fBTV_rev\fR : \fItvtype_t\fR wolffd@0: .TQ wolffd@0: \fBTV_postrev\fR : \fItvtype_t\fR wolffd@0: .TQ wolffd@0: \fBTV_prepostrev\fR : \fItvtype_t\fR wolffd@0: A traversal of the graph using a depth\(hyfirst search on the wolffd@0: graph following only reverse arcs. wolffd@0: The choice of roots for the traversal is the wolffd@0: same as described for \fBTV_dfs\fR above. wolffd@0: The different order of visitation specified by \fBTV_rev\fR, wolffd@0: \fBTV_postrev\fR and \fBTV_prepostrev\fR are the same as those wolffd@0: specified by the analogous traversals \fBTV_dfs\fR, wolffd@0: \fBTV_postdfs\fR and \fBTV_prepostdfs\fR. wolffd@0: .TP wolffd@0: \fBTV_bfs\fR : \fItvtype_t\fR wolffd@0: A traversal of the graph using a bread\(hyfirst search on the wolffd@0: graph ignoring edge directions. See the item on \fBTV_dfs\fR above wolffd@0: for the role of \fB$tvroot\fP. wolffd@0: .SH EXAMPLES wolffd@0: .PP wolffd@0: .ta \w'\f(CWdelete array[expression]'u wolffd@0: .RS wolffd@0: .nf wolffd@0: \fBgvpr \-i 'N[color=="blue"]' file.dot\fP wolffd@0: .fi wolffd@0: .RE wolffd@0: .DT wolffd@0: .PP wolffd@0: Generate the node\(hyinduced subgraph of all nodes with color blue. wolffd@0: .PP wolffd@0: .ta \w'\f(CWdelete array[expression]'u wolffd@0: .RS wolffd@0: .nf wolffd@0: \fBgvpr \-c 'N[color=="blue"]{color = "red"}' file.dot\fP wolffd@0: .fi wolffd@0: .RE wolffd@0: .DT wolffd@0: .PP wolffd@0: Make all blue nodes red. wolffd@0: .PP wolffd@0: .ta \w'\f(CWdelete array[expression]'u wolffd@0: .RS wolffd@0: .nf wolffd@0: \fBBEGIN { int n, e; int tot_n = 0; int tot_e = 0; } wolffd@0: BEG_G { wolffd@0: n = nNodes($G); wolffd@0: e = nEdges($G); wolffd@0: printf ("%d nodes %d edges %s\n", n, e, $G.name); wolffd@0: tot_n += n; wolffd@0: tot_e += e; wolffd@0: } wolffd@0: END { printf ("%d nodes %d edges total\n", tot_n, tot_e) }\fP wolffd@0: .fi wolffd@0: .RE wolffd@0: .DT wolffd@0: .PP wolffd@0: Version of the program \fBgc\fP. wolffd@0: .PP wolffd@0: .ta \w'\f(CWdelete array[expression]'u wolffd@0: .RS wolffd@0: .nf wolffd@0: \fBgvpr \-c ""\fP wolffd@0: .fi wolffd@0: .RE wolffd@0: .DT wolffd@0: .PP wolffd@0: Equivalent to \fBnop\fP. wolffd@0: .PP wolffd@0: .ta \w'\f(CWdelete array[expression]'u wolffd@0: .RS wolffd@0: .nf wolffd@0: \fBBEG_G { graph_t g = graph ("merge", "S"); } wolffd@0: E { wolffd@0: node_t h = clone(g,$.head); wolffd@0: node_t t = clone(g,$.tail); wolffd@0: edge_t e = edge(t,h,""); wolffd@0: e.weight = e.weight + 1; wolffd@0: } wolffd@0: END_G { $O = g; }\fP wolffd@0: .fi wolffd@0: .RE wolffd@0: .DT wolffd@0: .PP wolffd@0: Produces a strict version of the input graph, where the weight attribute wolffd@0: of an edge indicates how many edges from the input graph the edge represents. wolffd@0: .PP wolffd@0: .ta \w'\f(CWdelete array[expression]'u wolffd@0: .RS wolffd@0: .nf wolffd@0: \fBBEGIN {node_t n; int deg[]} wolffd@0: E{deg[head]++; deg[tail]++; } wolffd@0: END_G { wolffd@0: for (deg[n]) { wolffd@0: printf ("deg[%s] = %d\n", n.name, deg[n]); wolffd@0: } wolffd@0: }\fP wolffd@0: .fi wolffd@0: .RE wolffd@0: .DT wolffd@0: .PP wolffd@0: Computes the degrees of nodes with edges. wolffd@0: .SH ENVIRONMENT wolffd@0: .TP wolffd@0: .B GPRPATH wolffd@0: Colon\(hyseparated list of directories to be searched to find wolffd@0: the file specified by the \-f option. wolffd@0: .SH BUGS AND WARNINGS wolffd@0: When the program is given as a command line argument, the usual wolffd@0: shell interpretation takes place, which may affect some of the wolffd@0: special names in \fBgvpr\fP. To avoid this, it is best to wrap the wolffd@0: program in single quotes. wolffd@0: .PP wolffd@0: As of 24 April 2008, \fBgvpr\fP switched to using a new, underlying wolffd@0: graph library, which uses the simpler model that there is only one wolffd@0: copy of a node, not one copy for each subgraph logically containing wolffd@0: it. This means that iterators such as \Inxtnode\P cannot traverse wolffd@0: a subgraph using just a node argument. For this reason, subgraph wolffd@0: traversal requires new functions ending in "_sg", which also take wolffd@0: a subgraph argument. The versions without that suffix will always wolffd@0: traverse the root graph. wolffd@0: .PP wolffd@0: There is a single global scope, except for formal function parameters, wolffd@0: and even these can interfere with the type system. Also, the wolffd@0: extent of all variables is the entire life of the program. wolffd@0: It might be preferable for scope wolffd@0: to reflect the natural nesting of the clauses, or for the program wolffd@0: to at least reset locally declared variables. wolffd@0: For now, it is advisable to use distinct names for all variables. wolffd@0: .PP wolffd@0: If a function ends with a complex statement, such as an wolffd@0: IF statement, with each branch doing a return, type checking may fail. wolffd@0: Functions should use a return at the end. wolffd@0: .PP wolffd@0: The expr library does not support string values of (char*)0. wolffd@0: This means we can't distinguish between "" and (char*)0 edge keys. wolffd@0: For the purposes of looking up and creating edges, we translate "" wolffd@0: to be (char*)0, since this latter value is wolffd@0: necessary in order to look up any edge with a matching head and tail. wolffd@0: .PP wolffd@0: Related to this, strings converted to integers act like char pointers, wolffd@0: getting the value 0 or 1 depending on whether the string consists wolffd@0: solely of zeroes or not. Thus, the ((int)"2") evaluates to 1. wolffd@0: .PP wolffd@0: The language inherits the usual C problems such as dangling references wolffd@0: and the confusion between '=' and '=='. wolffd@0: .SH AUTHOR wolffd@0: Emden R. Gansner wolffd@0: .SH "SEE ALSO" wolffd@0: .PP wolffd@0: awk(1), gc(1), dot(1), nop(1), libexpr(3), libcgraph(3)