]> git.saurik.com Git - bison.git/blame - src/print_graph.c
* tests/regression.at (AT_TEST_CPP_GUARD_H): Adjust the clean up
[bison.git] / src / print_graph.c
CommitLineData
22c2cbc0
AD
1/* Output a VCG description on generated parser, for Bison,
2 Copyright 2001 Free Software Foundation, Inc.
ce4d5ce0
AD
3
4 This file is part of Bison, the GNU Compiler Compiler.
5
6 Bison is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 Bison is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21#include "system.h"
ce4d5ce0
AD
22#include "files.h"
23#include "gram.h"
24#include "LR0.h"
25#include "lalr.h"
26#include "conflicts.h"
27#include "complain.h"
28#include "getargs.h"
29#include "state.h"
30#include "reader.h"
31#include "obstack.h"
32#include "print_graph.h"
33#include "vcg.h"
20e8e5ca 34#include "quotearg.h"
ce4d5ce0
AD
35
36static graph_t graph;
342b8b6e 37static FILE *fgraph = NULL;
ce4d5ce0 38
342b8b6e 39static size_t node_output_size = 0;
600cad3b 40
20e8e5ca
AD
41/* Return an unambiguous printable representated, allocated in slot 0,
42 for NAME, suitable for C strings. */
43static char const *
44quote (char const *name)
45{
46 return quotearg_n_style (0, escape_quoting_style, name);
47}
48
ce4d5ce0
AD
49/* This part will construct the label of nodes. */
50static void
600cad3b 51print_core (int state, struct obstack *node_obstack)
ce4d5ce0
AD
52{
53 int i;
54 int k;
55 int rule;
56 core *statep;
57 short *sp;
58 short *sp1;
22c2cbc0 59
ce4d5ce0
AD
60 statep = state_table[state];
61 k = statep->nitems;
62
63 if (k == 0)
64 return;
22c2cbc0 65
ce4d5ce0
AD
66 for (i = 0; i < k; i++)
67 {
c4b66126 68 if (i)
600cad3b 69 obstack_sgrow (node_obstack, "\\n");
c4b66126 70
ce4d5ce0
AD
71 sp1 = sp = ritem + statep->items[i];
72
73 while (*sp > 0)
74 sp++;
75
76 rule = -(*sp);
77
600cad3b
MA
78 obstack_fgrow1 (node_obstack, "%d: ", rule);
79 obstack_fgrow1 (node_obstack, " %s -> ", quote (tags[rlhs[rule]]));
ce4d5ce0
AD
80
81 for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
600cad3b 82 obstack_fgrow1 (node_obstack, "%s ", quote (tags[*sp]));
ce4d5ce0 83
600cad3b 84 obstack_1grow (node_obstack, '.');
22c2cbc0 85
ce4d5ce0 86 while (*sp > 0)
600cad3b 87 obstack_fgrow1 (node_obstack, " %s", quote (tags[*sp++]));
ce4d5ce0 88 }
ce4d5ce0
AD
89}
90
600cad3b
MA
91/* Output in graph_obstack edges specifications in incidence with current
92 node. */
ce4d5ce0 93static void
600cad3b 94print_actions (int state, const char *node_name, struct obstack *node_obstack)
ce4d5ce0
AD
95{
96 int i;
97 int k;
98 int state1;
99 int symbol;
100 shifts *shiftp;
101 errs *errp;
102 reductions *redp;
103 int rule;
104 static char buff[10];
105 edge_t edge;
22c2cbc0 106
ce4d5ce0
AD
107 shiftp = shift_table[state];
108 redp = reduction_table[state];
109 errp = err_table[state];
110
111 if (!shiftp && !redp)
112 {
113 if (final_state == state)
600cad3b 114 obstack_sgrow (node_obstack, "$default: accept");
ce4d5ce0 115 else
600cad3b 116 obstack_sgrow (node_obstack, "NO ACTIONS");
ce4d5ce0
AD
117 return;
118 }
119
120 if (shiftp)
121 {
122 k = shiftp->nshifts;
123
124 for (i = 0; i < k; i++)
125 {
126 if (!shiftp->shifts[i])
127 continue;
128 state1 = shiftp->shifts[i];
129 symbol = accessing_symbol[state1];
130
131 if (ISVAR (symbol))
132 break;
22c2cbc0 133
ce4d5ce0
AD
134 {
135 new_edge (&edge);
136
137 if (state > state1)
138 edge.type = back_edge;
342b8b6e 139 open_edge (&edge, fgraph);
600cad3b
MA
140 /* The edge source is the current node. */
141 edge.sourcename = node_name;
c4b66126 142 sprintf (buff, "%d", state1);
ce4d5ce0 143 edge.targetname = buff;
600cad3b 144 edge.color = (symbol == 0) ? red : blue;
c4b66126
AD
145 /* FIXME: Be aware that quote uses static memory. The string
146 must be output immediately (which is the case here). */
147 edge.label = tags[symbol] ? quote (tags[symbol]) : NULL;
342b8b6e
AD
148 output_edge (&edge, fgraph);
149 close_edge (fgraph);
22c2cbc0 150 }
ce4d5ce0
AD
151 }
152 }
153 else
154 {
155 i = 0;
156 k = 0;
157 }
158
159 if (errp)
160 {
161 int j, nerrs;
162
163 nerrs = errp->nerrs;
164
165 for (j = 0; j < nerrs; j++)
166 {
167 if (!errp->errs[j])
168 continue;
169 symbol = errp->errs[j];
600cad3b
MA
170 /* If something has been added in the NODE_OBSTACK after
171 the declaration of the label, then we need a `\n'. */
172 if (obstack_object_size (node_obstack) > node_output_size)
173 obstack_sgrow (node_obstack, "\\n");
174 obstack_fgrow1 (node_obstack, _("%-4s\terror (nonassociative)"),
175 tags[symbol]);
ce4d5ce0 176 }
600cad3b
MA
177 if (j > 0)
178 obstack_sgrow (node_obstack, "\\n");
ce4d5ce0 179 }
22c2cbc0 180
ce4d5ce0
AD
181 if (consistent[state] && redp)
182 {
183 rule = redp->rules[0];
184 symbol = rlhs[rule];
600cad3b
MA
185 if (obstack_object_size (node_obstack) > node_output_size)
186 obstack_sgrow (node_obstack, "\\n");
187 obstack_fgrow2 (node_obstack, _("$default\treduce using rule %d (%s)"),
188 rule, tags[symbol]);
ce4d5ce0 189 }
22c2cbc0 190
ce4d5ce0
AD
191 if (i < k)
192 {
193 for (; i < k; i++)
194 {
195 if (!shiftp->shifts[i])
196 continue;
197 state1 = shiftp->shifts[i];
198 symbol = accessing_symbol[state1];
199
200 new_edge (&edge);
342b8b6e 201 open_edge (&edge, fgraph);
600cad3b 202 edge.sourcename = node_name;
c4b66126 203 sprintf (buff, "%d", state1);
ce4d5ce0
AD
204 edge.targetname = buff;
205 edge.color = red;
c4b66126 206 edge.label = tags[symbol] ? quote (tags[symbol]) : NULL;
342b8b6e
AD
207 output_edge (&edge, fgraph);
208 close_edge (fgraph);
ce4d5ce0
AD
209 }
210 }
211}
212
600cad3b
MA
213/* Output in GRAPH_OBSTACK the current node specifications and edges
214 which go out from that node. */
ce4d5ce0
AD
215static void
216print_state (int state)
217{
218 static char name[10];
600cad3b 219 struct obstack node_obstack;
22c2cbc0 220 node_t node;
ce4d5ce0 221
600cad3b
MA
222 obstack_init (&node_obstack);
223 new_node (&node); /* Set node attributs default value. */
3e3da797 224 sprintf (name, "%d", state);
600cad3b 225 node.title = name; /* Give a name to the node. */
600cad3b
MA
226
227 {
228 /* Here we begin to compute the node label. */
229 obstack_sgrow (&node_obstack, "\t\tlabel:\t\""); /* Open Label */
230
231 /* Keep the size of NODE_OBSTACK before computing the label. It is
232 useful to format the label. */
233 node_output_size = obstack_object_size (&node_obstack);
234
235 /* Compute the labels of nodes on the fly. */
236 print_core (state, &node_obstack);
237 /* Compute edges and additionnal parts of node label. */
238 print_actions (state, node.title, &node_obstack);
239
240 obstack_sgrow (&node_obstack, "\"\n"); /* Close Label. */
342b8b6e
AD
241 }
242
243 open_node (fgraph);
244 /* Output a VCG formatted attributs list. */
245 output_node (&node, fgraph);
246 /* Save the node label. */
247 fwrite (obstack_base (&node_obstack),
248 obstack_object_size (&node_obstack), 1, fgraph);
249 close_node (fgraph);
250
251 obstack_free (&node_obstack, 0);
ce4d5ce0
AD
252}
253\f
254
255void
256print_graph (void)
257{
258 int i;
342b8b6e 259
ce4d5ce0 260 if (!graph_flag)
3e3da797 261 return;
342b8b6e
AD
262
263 /* Output file. */
264 fgraph = xfopen (spec_graph_file, "w");
265
ce4d5ce0 266 new_graph (&graph);
22c2cbc0 267
600cad3b
MA
268#if 0
269 graph.smanhattan_edges = yes;
270 graph.manhattan_edges = yes;
271#endif
22c2cbc0 272
ce4d5ce0 273 graph.display_edge_labels = yes;
342b8b6e 274 graph.layoutalgorithm = normal;
22c2cbc0 275
ce4d5ce0
AD
276 graph.port_sharing = no;
277 graph.finetuning = yes;
278 graph.straight_phase = yes;
279 graph.priority_phase = yes;
280 graph.splines = yes;
22c2cbc0 281
ce4d5ce0
AD
282 graph.crossing_weight = median;
283
284 /* Output graph options. */
342b8b6e
AD
285 open_graph (fgraph);
286 output_graph (&graph, fgraph);
ce4d5ce0
AD
287
288 for (i = 0; i < nstates; i++)
3e3da797
AD
289 /* Output nodes & edges. */
290 print_state (i);
ce4d5ce0
AD
291
292 /* Close graph. */
342b8b6e
AD
293 close_graph (&graph, fgraph);
294 xfclose (fgraph);
ce4d5ce0 295}