Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.bin / yacc / verbose.c
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Robert Paul Corbett.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * $FreeBSD: src/usr.bin/yacc/verbose.c,v 1.6 1999/08/28 01:08:03 peter Exp $
37  */
38
39 #ifndef lint
40 static char const sccsid[] = "@(#)verbose.c     5.3 (Berkeley) 1/20/91";
41 #endif /* not lint */
42
43 #include <stdlib.h>
44 #include "defs.h"
45
46 static void log_unused __P((void));
47 static void log_conflicts __P((void));
48 static void print_actions __P((int));
49 static void print_conflicts __P((int));
50 static void print_core __P((int));
51 static void print_gotos __P((int));
52 static void print_nulls __P((int));
53 static void print_reductions __P((register action *, register int));
54 static void print_shifts __P((register action *));
55 static void print_state __P((int));
56
57 static short *null_rules;
58
59 void
60 verbose()
61 {
62     register int i;
63
64     if (!vflag) return;
65
66     null_rules = (short *) MALLOC(nrules*sizeof(short));
67     if (null_rules == 0) no_space();
68     fprintf(verbose_file, "\f\n");
69     for (i = 0; i < nstates; i++)
70         print_state(i);
71     FREE(null_rules);
72
73     if (nunused)
74         log_unused();
75     if (SRtotal || RRtotal)
76         log_conflicts();
77
78     fprintf(verbose_file, "\n\n%d terminals, %d nonterminals\n", ntokens,
79             nvars);
80     fprintf(verbose_file, "%d grammar rules, %d states\n", nrules - 2, nstates);
81 }
82
83
84 static void
85 log_unused()
86 {
87     register int i;
88     register short *p;
89
90     fprintf(verbose_file, "\n\nRules never reduced:\n");
91     for (i = 3; i < nrules; ++i)
92     {
93         if (!rules_used[i])
94         {
95             fprintf(verbose_file, "\t%s :", symbol_name[rlhs[i]]);
96             for (p = ritem + rrhs[i]; *p >= 0; ++p)
97                 fprintf(verbose_file, " %s", symbol_name[*p]);
98             fprintf(verbose_file, "  (%d)\n", i - 2);
99         }
100     }
101 }
102
103
104 static void
105 log_conflicts()
106 {
107     register int i;
108
109     fprintf(verbose_file, "\n\n");
110     for (i = 0; i < nstates; i++)
111     {
112         if (SRconflicts[i] || RRconflicts[i])
113         {
114             fprintf(verbose_file, "State %d contains ", i);
115             if (SRconflicts[i] == 1)
116                 fprintf(verbose_file, "1 shift/reduce conflict");
117             else if (SRconflicts[i] > 1)
118                 fprintf(verbose_file, "%d shift/reduce conflicts",
119                         SRconflicts[i]);
120             if (SRconflicts[i] && RRconflicts[i])
121                 fprintf(verbose_file, ", ");
122             if (RRconflicts[i] == 1)
123                 fprintf(verbose_file, "1 reduce/reduce conflict");
124             else if (RRconflicts[i] > 1)
125                 fprintf(verbose_file, "%d reduce/reduce conflicts",
126                         RRconflicts[i]);
127             fprintf(verbose_file, ".\n");
128         }
129     }
130 }
131
132
133 static void
134 print_state(state)
135 int state;
136 {
137     if (state)
138         fprintf(verbose_file, "\n\n");
139     if (SRconflicts[state] || RRconflicts[state])
140         print_conflicts(state);
141     fprintf(verbose_file, "state %d\n", state);
142     print_core(state);
143     print_nulls(state);
144     print_actions(state);
145 }
146
147
148 static void
149 print_conflicts(state)
150 int state;
151 {
152     register int symbol, act = 0, number = 0;
153     register action *p;
154
155     symbol = -1;
156     for (p = parser[state]; p; p = p->next)
157     {
158         if (p->suppressed == 2)
159             continue;
160
161         if (p->symbol != symbol)
162         {
163             symbol = p->symbol;
164             number = p->number;
165             if (p->action_code == SHIFT)
166                 act = SHIFT;
167             else
168                 act = REDUCE;
169         }
170         else if (p->suppressed == 1)
171         {
172             if (state == final_state && symbol == 0)
173             {
174                 fprintf(verbose_file, "%d: shift/reduce conflict \
175 (accept, reduce %d) on $end\n", state, p->number - 2);
176             }
177             else
178             {
179                 if (act == SHIFT)
180                 {
181                     fprintf(verbose_file, "%d: shift/reduce conflict \
182 (shift %d, reduce %d) on %s\n", state, number, p->number - 2,
183                             symbol_name[symbol]);
184                 }
185                 else
186                 {
187                     fprintf(verbose_file, "%d: reduce/reduce conflict \
188 (reduce %d, reduce %d) on %s\n", state, number - 2, p->number - 2,
189                             symbol_name[symbol]);
190                 }
191             }
192         }
193     }
194 }
195
196
197 static void
198 print_core(state)
199 int state;
200 {
201     register int i;
202     register int k;
203     register int rule;
204     register core *statep;
205     register short *sp;
206     register short *sp1;
207
208     statep = state_table[state];
209     k = statep->nitems;
210
211     for (i = 0; i < k; i++)
212     {
213         sp1 = sp = ritem + statep->items[i];
214
215         while (*sp >= 0) ++sp;
216         rule = -(*sp);
217         fprintf(verbose_file, "\t%s : ", symbol_name[rlhs[rule]]);
218
219         for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
220             fprintf(verbose_file, "%s ", symbol_name[*sp]);
221
222         putc('.', verbose_file);
223
224         while (*sp >= 0)
225         {
226             fprintf(verbose_file, " %s", symbol_name[*sp]);
227             sp++;
228         }
229         fprintf(verbose_file, "  (%d)\n", -2 - *sp);
230     }
231 }
232
233
234 static void
235 print_nulls(state)
236 int state;
237 {
238     register action *p;
239     register int i, j, k, nnulls;
240
241     nnulls = 0;
242     for (p = parser[state]; p; p = p->next)
243     {
244         if (p->action_code == REDUCE &&
245                 (p->suppressed == 0 || p->suppressed == 1))
246         {
247             i = p->number;
248             if (rrhs[i] + 1 == rrhs[i+1])
249             {
250                 for (j = 0; j < nnulls && i > null_rules[j]; ++j)
251                     continue;
252
253                 if (j == nnulls)
254                 {
255                     ++nnulls;
256                     null_rules[j] = i;
257                 }
258                 else if (i != null_rules[j])
259                 {
260                     ++nnulls;
261                     for (k = nnulls - 1; k > j; --k)
262                         null_rules[k] = null_rules[k-1];
263                     null_rules[j] = i;
264                 }
265             }
266         }
267     }
268
269     for (i = 0; i < nnulls; ++i)
270     {
271         j = null_rules[i];
272         fprintf(verbose_file, "\t%s : .  (%d)\n", symbol_name[rlhs[j]],
273                 j - 2);
274     }
275     fprintf(verbose_file, "\n");
276 }
277
278
279 static void
280 print_actions(stateno)
281 int stateno;
282 {
283     register action *p;
284     register shifts *sp;
285     register int as;
286
287     if (stateno == final_state)
288         fprintf(verbose_file, "\t$end  accept\n");
289
290     p = parser[stateno];
291     if (p)
292     {
293         print_shifts(p);
294         print_reductions(p, defred[stateno]);
295     }
296
297     sp = shift_table[stateno];
298     if (sp && sp->nshifts > 0)
299     {
300         as = accessing_symbol[sp->shift[sp->nshifts - 1]];
301         if (ISVAR(as))
302             print_gotos(stateno);
303     }
304 }
305
306
307 static void
308 print_shifts(p)
309 register action *p;
310 {
311     register int count;
312     register action *q;
313
314     count = 0;
315     for (q = p; q; q = q->next)
316     {
317         if (q->suppressed < 2 && q->action_code == SHIFT)
318             ++count;
319     }
320
321     if (count > 0)
322     {
323         for (; p; p = p->next)
324         {
325             if (p->action_code == SHIFT && p->suppressed == 0)
326                 fprintf(verbose_file, "\t%s  shift %d\n",
327                             symbol_name[p->symbol], p->number);
328         }
329     }
330 }
331
332
333 static void
334 print_reductions(p, defred)
335 register action *p;
336 register int defred;
337 {
338     register int k, anyreds;
339     register action *q;
340
341     anyreds = 0;
342     for (q = p; q ; q = q->next)
343     {
344         if (q->action_code == REDUCE && q->suppressed < 2)
345         {
346             anyreds = 1;
347             break;
348         }
349     }
350
351     if (anyreds == 0)
352         fprintf(verbose_file, "\t.  error\n");
353     else
354     {
355         for (; p; p = p->next)
356         {
357             if (p->action_code == REDUCE && p->number != defred)
358             {
359                 k = p->number - 2;
360                 if (p->suppressed == 0)
361                     fprintf(verbose_file, "\t%s  reduce %d\n",
362                             symbol_name[p->symbol], k);
363             }
364         }
365
366         if (defred > 0)
367             fprintf(verbose_file, "\t.  reduce %d\n", defred - 2);
368     }
369 }
370
371
372 static void
373 print_gotos(stateno)
374 int stateno;
375 {
376     register int i, k;
377     register int as;
378     register short *to_state;
379     register shifts *sp;
380
381     putc('\n', verbose_file);
382     sp = shift_table[stateno];
383     to_state = sp->shift;
384     for (i = 0; i < sp->nshifts; ++i)
385     {
386         k = to_state[i];
387         as = accessing_symbol[k];
388         if (ISVAR(as))
389             fprintf(verbose_file, "\t%s  goto %d\n", symbol_name[as], k);
390     }
391 }