Boston, MA 02111-1307, USA. */
#include "system.h"
-#include "xalloc.h"
#include "files.h"
#include "gram.h"
#include "LR0.h"
#include "quotearg.h"
static graph_t graph;
+static FILE *fgraph = NULL;
+
+static size_t node_output_size = 0;
/* Return an unambiguous printable representated, allocated in slot 0,
for NAME, suitable for C strings. */
/* This part will construct the label of nodes. */
static void
-print_core (int state)
+print_core (int state, struct obstack *node_obstack)
{
int i;
int k;
if (k == 0)
return;
- obstack_sgrow (&graph_obstack, "\t\tlabel:\t\"");
-
for (i = 0; i < k; i++)
{
if (i)
- obstack_sgrow (&graph_obstack, "\\n");
+ obstack_sgrow (node_obstack, "\\n");
sp1 = sp = ritem + statep->items[i];
rule = -(*sp);
- obstack_fgrow1 (&graph_obstack, "%d: ", rule);
- obstack_fgrow1 (&graph_obstack, " %s -> ", quote (tags[rlhs[rule]]));
+ obstack_fgrow1 (node_obstack, "%d: ", rule);
+ obstack_fgrow1 (node_obstack, " %s -> ", quote (tags[rlhs[rule]]));
for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
- obstack_fgrow1 (&graph_obstack, "%s ", quote (tags[*sp]));
+ obstack_fgrow1 (node_obstack, "%s ", quote (tags[*sp]));
- obstack_1grow (&graph_obstack, '.');
+ obstack_1grow (node_obstack, '.');
while (*sp > 0)
- obstack_fgrow1 (&graph_obstack, " %s", quote (tags[*sp++]));
-
+ obstack_fgrow1 (node_obstack, " %s", quote (tags[*sp++]));
}
- obstack_sgrow (&graph_obstack, "\"\n");
}
+/* Output in graph_obstack edges specifications in incidence with current
+ node. */
static void
-print_actions (int state, node_t *node)
+print_actions (int state, const char *node_name, struct obstack *node_obstack)
{
int i;
int k;
if (!shiftp && !redp)
{
-#if 0
if (final_state == state)
- fprintf (f, " $default\taccept\n");
+ obstack_sgrow (node_obstack, "$default: accept");
else
- fprintf (f, " NO ACTIONS\n");
-#endif
+ obstack_sgrow (node_obstack, "NO ACTIONS");
return;
}
if (state > state1)
edge.type = back_edge;
- open_edge (&edge, &graph_obstack);
- edge.sourcename = node->title;
+ open_edge (&edge, fgraph);
+ /* The edge source is the current node. */
+ edge.sourcename = node_name;
sprintf (buff, "%d", state1);
edge.targetname = buff;
- edge.color = (symbol == 0) ? blue : red;
+ edge.color = (symbol == 0) ? red : blue;
/* FIXME: Be aware that quote uses static memory. The string
must be output immediately (which is the case here). */
edge.label = tags[symbol] ? quote (tags[symbol]) : NULL;
- output_edge (&edge, &graph_obstack);
- close_edge (&graph_obstack);
+ output_edge (&edge, fgraph);
+ close_edge (fgraph);
}
}
}
if (!errp->errs[j])
continue;
symbol = errp->errs[j];
+ /* If something has been added in the NODE_OBSTACK after
+ the declaration of the label, then we need a `\n'. */
+ if (obstack_object_size (node_obstack) > node_output_size)
+ obstack_sgrow (node_obstack, "\\n");
+ obstack_fgrow1 (node_obstack, _("%-4s\terror (nonassociative)"),
+ tags[symbol]);
}
+ if (j > 0)
+ obstack_sgrow (node_obstack, "\\n");
}
if (consistent[state] && redp)
{
rule = redp->rules[0];
symbol = rlhs[rule];
+ if (obstack_object_size (node_obstack) > node_output_size)
+ obstack_sgrow (node_obstack, "\\n");
+ obstack_fgrow2 (node_obstack, _("$default\treduce using rule %d (%s)"),
+ rule, tags[symbol]);
}
if (i < k)
symbol = accessing_symbol[state1];
new_edge (&edge);
- open_edge (&edge, &graph_obstack);
- edge.sourcename = node->title;
+ open_edge (&edge, fgraph);
+ edge.sourcename = node_name;
sprintf (buff, "%d", state1);
edge.targetname = buff;
edge.color = red;
edge.label = tags[symbol] ? quote (tags[symbol]) : NULL;
- output_edge (&edge, &graph_obstack);
- close_edge (&graph_obstack);
+ output_edge (&edge, fgraph);
+ close_edge (fgraph);
}
}
}
+/* Output in GRAPH_OBSTACK the current node specifications and edges
+ which go out from that node. */
static void
print_state (int state)
{
static char name[10];
+ struct obstack node_obstack;
node_t node;
- new_node (&node);
- open_node (&graph_obstack);
-
+ obstack_init (&node_obstack);
+ new_node (&node); /* Set node attributs default value. */
sprintf (name, "%d", state);
- node.title = name;
- output_node (&node, &graph_obstack);
-
- print_core (state); /* node label */
-
- close_node (&graph_obstack);
-
- print_actions (state, &node); /* edges */
+ node.title = name; /* Give a name to the node. */
+
+ {
+ /* Here we begin to compute the node label. */
+ obstack_sgrow (&node_obstack, "\t\tlabel:\t\""); /* Open Label */
+
+ /* Keep the size of NODE_OBSTACK before computing the label. It is
+ useful to format the label. */
+ node_output_size = obstack_object_size (&node_obstack);
+
+ /* Compute the labels of nodes on the fly. */
+ print_core (state, &node_obstack);
+ /* Compute edges and additionnal parts of node label. */
+ print_actions (state, node.title, &node_obstack);
+
+ obstack_sgrow (&node_obstack, "\"\n"); /* Close Label. */
+ }
+
+ open_node (fgraph);
+ /* Output a VCG formatted attributs list. */
+ output_node (&node, fgraph);
+ /* Save the node label. */
+ fwrite (obstack_base (&node_obstack),
+ obstack_object_size (&node_obstack), 1, fgraph);
+ close_node (fgraph);
+
+ obstack_free (&node_obstack, 0);
}
\f
print_graph (void)
{
int i;
-
+
if (!graph_flag)
return;
+
+ /* Output file. */
+ fgraph = xfopen (spec_graph_file, "w");
+
new_graph (&graph);
- /* graph.smanhattan_edges = yes;
- graph.manhattan_edges = yes; */
+#if 0
+ graph.smanhattan_edges = yes;
+ graph.manhattan_edges = yes;
+#endif
graph.display_edge_labels = yes;
- graph.layoutalgorithm = 0;
+ graph.layoutalgorithm = normal;
graph.port_sharing = no;
graph.finetuning = yes;
graph.crossing_weight = median;
/* Output graph options. */
- open_graph (&graph_obstack);
- output_graph (&graph, &graph_obstack);
+ open_graph (fgraph);
+ output_graph (&graph, fgraph);
for (i = 0; i < nstates; i++)
/* Output nodes & edges. */
print_state (i);
/* Close graph. */
- close_graph (&graph, &graph_obstack);
+ close_graph (&graph, fgraph);
+ xfclose (fgraph);
}