.PP
Predicates and actions are sequences of statements in the C dialect
supported by the
-.IR libexpr (3)
+.IR expr (3)
library.
The only difference between predicates and actions is that the former
must have a type that may interpreted as either true or false.
.DT
.PP
Computes the degrees of nodes with edges.
+.PP
+.ta \w'\f(CWdelete array[expression]'u
+.RS
+.nf
+\fBBEGIN {
+ int i, indent;
+ int seen[string];
+ void prInd (int cnt) {
+ for (i = 0; i < cnt; i++) printf (" ");
+ }
+}
+BEG_G {
+
+ $tvtype = TV_prepostfwd;
+ $tvroot = node($,ARGV[0]);
+}
+N {
+ if (seen[$.name]) indent--;
+ else {
+ prInd(indent);
+ print ($.name);
+ seen[$.name] = 1;
+ indent++;
+ }
+}\fP
+.fi
+.RE
+.DT
+.PP
+Prints the depth-first traversal of the graph, starting
+with the node whose name is \fBARGV[0]\fP, as an indented list.
.SH ENVIRONMENT
.TP
.B GPRPATH
Emden R. Gansner <erg@research.att.com>
.SH "SEE ALSO"
.PP
-awk(1), gc(1), dot(1), nop(1), libexpr(3), libcgraph(3)
+awk(1), gc(1), dot(1), nop(1), expr(3), cgraph(3)
--- /dev/null
+/* computes the bounding box of a graph based on node positions */
+BEGIN {
+ double xmin, ymin, xmax, ymax;
+ xmin = ymin = 1.7976931348623157e+308;
+ xmax = ymax = -ymin;
+ double x, y;
+}
+N {
+ if (sscanf ($.pos, "%f,%f", &x, &y) == 2) {
+ if (x < xmin) xmin = x;
+ if (y < ymin) ymin = y;
+ if (x > xmax) xmax = x;
+ if (y > ymax) ymax = y;
+ }
+}
+
+END {
+ printf ("(%f,%f) (%f,%f)\n", xmin, ymin, xmax, ymax);
+ if (ARGC) printf ("area = %f aspect = %f\n", ((xmax-xmin)*(ymax-ymin))/1000000., (xmax-xmin)/(ymax-ymin));
+}
int degrees[];
int maxd = 0;
int i, d;
+ char* maxn;
}
N{
degrees[degree]++;
- if (degree > maxd) maxd = degree;
+ if (degree > maxd) {
+ maxn = $.name;
+ maxd = degree;
+ }
}
END {
+ printf ("max node %s (%d)\n", maxn, maxd);
for (i = 1; i <= maxd; i++) {
d = degrees[i];
if (d > 0) printf ("[%d] %d\n", i, d);
--- /dev/null
+/* Print the depth-first traversal of nodes
+ * as an indented list
+ */
+BEGIN {
+ int i, indent;
+ int seen[string];
+ void prInd () {
+ for (i = 0; i < indent; i++) printf (" ");
+ }
+}
+BEG_G {
+
+ $tvtype = TV_prepostfwd;
+ $tvroot = node($,ARGV[0]);
+}
+N {
+ if (seen[$.name]) indent--;
+ else {
+ prInd();
+ print ($.name);
+ seen[$.name] = 1;
+ indent++;
+ }
+}
--- /dev/null
+/* Given node name and angle, rotate a layout using the given
+ * node as origin.
+ */
+
+BEGIN {
+ double x,y;
+ double x0,y0;
+ double x1,y1;
+ double angle, cosa, sina;
+ int cnt, sz;
+
+ void rotate (double a, double b) {
+ a -= x0;
+ b -= y0;
+ x1 = a*cosa - b*sina;
+ y1 = a*sina + b*cosa;
+ }
+ char* rotateE (char* p) {
+ char* newpos = "";
+ cnt = sscanf (p, "e,%lf,%lf%n", &x, &y, &sz);
+ if (cnt == 2) {
+ rotate (x,y);
+ newpos = newpos + sprintf ("e%lf,%lf ", x1, y1);
+ p = substr(p, sz);
+ }
+ cnt = sscanf (p, "s,%lf,%lf%n", &x, &y, &sz);
+ if (cnt == 2) {
+ rotate (x,y);
+ newpos = newpos + sprintf ("s%lf,%lf ", x1, y1);
+ p = substr(p, sz);
+ }
+
+ while (sscanf (p, "%lf,%lf%n", &x, &y, &sz) == 2) {
+ rotate (x,y);
+ newpos = newpos + sprintf ("%lf,%lf ", x1, y1);
+ p = substr(p, sz);
+ }
+
+ return newpos;
+ }
+}
+
+BEG_G {
+ node_t ctr = node ($, ARGV[0]);
+
+ sscanf (ARGV[1], "%f", &angle);
+ cosa = cos(angle);
+ sina = sin(angle);
+
+ sscanf (ctr.pos, "%f,%f", &x0, &y0);
+ $.bb ="";
+}
+N {
+ sscanf ($.pos, "%f,%f", &x, &y);
+ rotate (x,y);
+ $.pos = sprintf ("%f,%f", x1, y1);
+}
+E {
+ $.pos = rotateE($.pos);
+}
/* derive simple spanning tree */
-BEG_G { $tvtype = TV_dfs}
+BEG_G { $tvtype = TV_dfs; $tvroot = node($,ARGV[0]);}
E [!isSubnode($T,$.head) || !isSubnode($T,$.tail)]