Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[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  * $DragonFly: src/usr.bin/yacc/verbose.c,v 1.2 2003/06/17 04:29:34 dillon Exp $
38  *
39  * @(#)verbose.c        5.3 (Berkeley) 1/20/91
40  */
41
42 #include <stdlib.h>
43 #include "defs.h"
44
45 static void log_unused __P((void));
46 static void log_conflicts __P((void));
47 static void print_actions __P((int));
48 static void print_conflicts __P((int));
49 static void print_core __P((int));
50 static void print_gotos __P((int));
51 static void print_nulls __P((int));
52 static void print_reductions __P((register action *, register int));
53 static void print_shifts __P((register action *));
54 static void print_state __P((int));
55
56 static short *null_rules;
57
58 void
59 verbose()
60 {
61     register int i;
62
63     if (!vflag) return;
64
65     null_rules = (short *) MALLOC(nrules*sizeof(short));
66     if (null_rules == 0) no_space();
67     fprintf(verbose_file, "\f\n");
68     for (i = 0; i < nstates; i++)
69         print_state(i);
70     FREE(null_rules);
71
72     if (nunused)
73         log_unused();
74     if (SRtotal || RRtotal)
75         log_conflicts();
76
77     fprintf(verbose_file, "\n\n%d terminals, %d nonterminals\n", ntokens,
78             nvars);
79     fprintf(verbose_file, "%d grammar rules, %d states\n", nrules - 2, nstates);
80 }
81
82
83 static void
84 log_unused()
85 {
86     register int i;
87     register short *p;
88
89     fprintf(verbose_file, "\n\nRules never reduced:\n");
90     for (i = 3; i < nrules; ++i)
91     {
92         if (!rules_used[i])
93         {
94             fprintf(verbose_file, "\t%s :", symbol_name[rlhs[i]]);
95             for (p = ritem + rrhs[i]; *p >= 0; ++p)
96                 fprintf(verbose_file, " %s", symbol_name[*p]);
97             fprintf(verbose_file, "  (%d)\n", i - 2);
98         }
99     }
100 }
101
102
103 static void
104 log_conflicts()
105 {
106     register int i;
107
108     fprintf(verbose_file, "\n\n");
109     for (i = 0; i < nstates; i++)
110     {
111         if (SRconflicts[i] || RRconflicts[i])
112         {
113             fprintf(verbose_file, "State %d contains ", i);
114             if (SRconflicts[i] == 1)
115                 fprintf(verbose_file, "1 shift/reduce conflict");
116             else if (SRconflicts[i] > 1)
117                 fprintf(verbose_file, "%d shift/reduce conflicts",
118                         SRconflicts[i]);
119             if (SRconflicts[i] && RRconflicts[i])
120                 fprintf(verbose_file, ", ");
121             if (RRconflicts[i] == 1)
122                 fprintf(verbose_file, "1 reduce/reduce conflict");
123             else if (RRconflicts[i] > 1)
124                 fprintf(verbose_file, "%d reduce/reduce conflicts",
125                         RRconflicts[i]);
126             fprintf(verbose_file, ".\n");
127         }
128     }
129 }
130
131
132 static void
133 print_state(state)
134 int state;
135 {
136     if (state)
137         fprintf(verbose_file, "\n\n");
138     if (SRconflicts[state] || RRconflicts[state])
139         print_conflicts(state);
140     fprintf(verbose_file, "state %d\n", state);
141     print_core(state);
142     print_nulls(state);
143     print_actions(state);
144 }
145
146
147 static void
148 print_conflicts(state)
149 int state;
150 {
151     register int symbol, act = 0, number = 0;
152     register action *p;
153
154     symbol = -1;
155     for (p = parser[state]; p; p = p->next)
156     {
157         if (p->suppressed == 2)
158             continue;
159
160         if (p->symbol != symbol)
161         {
162             symbol = p->symbol;
163             number = p->number;
164             if (p->action_code == SHIFT)
165                 act = SHIFT;
166             else
167                 act = REDUCE;
168         }
169         else if (p->suppressed == 1)
170         {
171             if (state == final_state && symbol == 0)
172             {
173                 fprintf(verbose_file, "%d: shift/reduce conflict \
174 (accept, reduce %d) on $end\n", state, p->number - 2);
175             }
176             else
177             {
178                 if (act == SHIFT)
179                 {
180                     fprintf(verbose_file, "%d: shift/reduce conflict \
181 (shift %d, reduce %d) on %s\n", state, number, p->number - 2,
182                             symbol_name[symbol]);
183                 }
184                 else
185                 {
186                     fprintf(verbose_file, "%d: reduce/reduce conflict \
187 (reduce %d, reduce %d) on %s\n", state, number - 2, p->number - 2,
188                             symbol_name[symbol]);
189                 }
190             }
191         }
192     }
193 }
194
195
196 static void
197 print_core(state)
198 int state;
199 {
200     register int i;
201     register int k;
202     register int rule;
203     register core *statep;
204     register short *sp;
205     register short *sp1;
206
207     statep = state_table[state];
208     k = statep->nitems;
209
210     for (i = 0; i < k; i++)
211     {
212         sp1 = sp = ritem + statep->items[i];
213
214         while (*sp >= 0) ++sp;
215         rule = -(*sp);
216         fprintf(verbose_file, "\t%s : ", symbol_name[rlhs[rule]]);
217
218         for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
219             fprintf(verbose_file, "%s ", symbol_name[*sp]);
220
221         putc('.', verbose_file);
222
223         while (*sp >= 0)
224         {
225             fprintf(verbose_file, " %s", symbol_name[*sp]);
226             sp++;
227         }
228         fprintf(verbose_file, "  (%d)\n", -2 - *sp);
229     }
230 }
231
232
233 static void
234 print_nulls(state)
235 int state;
236 {
237     register action *p;
238     register int i, j, k, nnulls;
239
240     nnulls = 0;
241     for (p = parser[state]; p; p = p->next)
242     {
243         if (p->action_code == REDUCE &&
244                 (p->suppressed == 0 || p->suppressed == 1))
245         {
246             i = p->number;
247             if (rrhs[i] + 1 == rrhs[i+1])
248             {
249                 for (j = 0; j < nnulls && i > null_rules[j]; ++j)
250                     continue;
251
252                 if (j == nnulls)
253                 {
254                     ++nnulls;
255                     null_rules[j] = i;
256                 }
257                 else if (i != null_rules[j])
258                 {
259                     ++nnulls;
260                     for (k = nnulls - 1; k > j; --k)
261                         null_rules[k] = null_rules[k-1];
262                     null_rules[j] = i;
263                 }
264             }
265         }
266     }
267
268     for (i = 0; i < nnulls; ++i)
269     {
270         j = null_rules[i];
271         fprintf(verbose_file, "\t%s : .  (%d)\n", symbol_name[rlhs[j]],
272                 j - 2);
273     }
274     fprintf(verbose_file, "\n");
275 }
276
277
278 static void
279 print_actions(stateno)
280 int stateno;
281 {
282     register action *p;
283     register shifts *sp;
284     register int as;
285
286     if (stateno == final_state)
287         fprintf(verbose_file, "\t$end  accept\n");
288
289     p = parser[stateno];
290     if (p)
291     {
292         print_shifts(p);
293         print_reductions(p, defred[stateno]);
294     }
295
296     sp = shift_table[stateno];
297     if (sp && sp->nshifts > 0)
298     {
299         as = accessing_symbol[sp->shift[sp->nshifts - 1]];
300         if (ISVAR(as))
301             print_gotos(stateno);
302     }
303 }
304
305
306 static void
307 print_shifts(p)
308 register action *p;
309 {
310     register int count;
311     register action *q;
312
313     count = 0;
314     for (q = p; q; q = q->next)
315     {
316         if (q->suppressed < 2 && q->action_code == SHIFT)
317             ++count;
318     }
319
320     if (count > 0)
321     {
322         for (; p; p = p->next)
323         {
324             if (p->action_code == SHIFT && p->suppressed == 0)
325                 fprintf(verbose_file, "\t%s  shift %d\n",
326                             symbol_name[p->symbol], p->number);
327         }
328     }
329 }
330
331
332 static void
333 print_reductions(p, defred)
334 register action *p;
335 register int defred;
336 {
337     register int k, anyreds;
338     register action *q;
339
340     anyreds = 0;
341     for (q = p; q ; q = q->next)
342     {
343         if (q->action_code == REDUCE && q->suppressed < 2)
344         {
345             anyreds = 1;
346             break;
347         }
348     }
349
350     if (anyreds == 0)
351         fprintf(verbose_file, "\t.  error\n");
352     else
353     {
354         for (; p; p = p->next)
355         {
356             if (p->action_code == REDUCE && p->number != defred)
357             {
358                 k = p->number - 2;
359                 if (p->suppressed == 0)
360                     fprintf(verbose_file, "\t%s  reduce %d\n",
361                             symbol_name[p->symbol], k);
362             }
363         }
364
365         if (defred > 0)
366             fprintf(verbose_file, "\t.  reduce %d\n", defred - 2);
367     }
368 }
369
370
371 static void
372 print_gotos(stateno)
373 int stateno;
374 {
375     register int i, k;
376     register int as;
377     register short *to_state;
378     register shifts *sp;
379
380     putc('\n', verbose_file);
381     sp = shift_table[stateno];
382     to_state = sp->shift;
383     for (i = 0; i < sp->nshifts; ++i)
384     {
385         k = to_state[i];
386         as = accessing_symbol[k];
387         if (ISVAR(as))
388             fprintf(verbose_file, "\t%s  goto %d\n", symbol_name[as], k);
389     }
390 }