]> git.saurik.com Git - bison.git/blobdiff - src/conflicts.c
* src/LR0.c (new_itemsets): Use nshifts only, not shiftcount.
[bison.git] / src / conflicts.c
index 6b9cad07e7d504fd43201e82e61cbb74ed487ad8..f4b08ede34d83288a417e342f51c70d6c823305f 100644 (file)
@@ -1,5 +1,5 @@
 /* Find and resolve or report look-ahead conflicts for bison,
 /* Find and resolve or report look-ahead conflicts for bison,
-   Copyright (C) 1984, 1989, 1992, 2000 Free Software Foundation, Inc.
+   Copyright 1984, 1989, 1992, 2000, 2001 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
    02111-1307, USA.  */
 
 #include "system.h"
    02111-1307, USA.  */
 
 #include "system.h"
+#include "complain.h"
 #include "getargs.h"
 #include "getargs.h"
-#include "alloc.h"
 #include "files.h"
 #include "gram.h"
 #include "state.h"
 #include "files.h"
 #include "gram.h"
 #include "state.h"
+#include "lalr.h"
+#include "conflicts.h"
+#include "reader.h"
+#include "LR0.h"
 
 
+errs **err_table = NULL;
+/* -1 stands for not specified. */
+int expected_conflicts = -1;
+static char *conflicts = NULL;
 
 
-extern char **tags;
-extern int tokensetsize;
-extern char *consistent;
-extern short *accessing_symbol;
-extern shifts **shift_table;
-extern unsigned *LA;
-extern short *LAruleno;
-extern short *lookaheads;
-extern int fixed_outfiles;
-
-extern void initialize_conflicts PARAMS((void));
-extern void conflict_log PARAMS((void));
-extern void verbose_conflict_log PARAMS((void));
-extern void print_reductions PARAMS((int));
-extern void finalize_conflicts PARAMS((void));
-
-static void set_conflicts PARAMS((int));
-static void resolve_sr_conflict PARAMS((int, int));
-static void flush_shift PARAMS((int, int));
-static void log_resolution PARAMS((int, int, int, char *));
-static void total_conflicts PARAMS((void));
-static void count_sr_conflicts PARAMS((int));
-static void count_rr_conflicts PARAMS((int));
-
-char any_conflicts;
-errs **err_table;
-int expected_conflicts;
-static char *conflicts;
-
-
-static unsigned *shiftset;
-static unsigned *lookaheadset;
-static int src_total;
-static int rrc_total;
-static int src_count;
-static int rrc_count;
+static unsigned *shiftset = NULL;
+static unsigned *lookaheadset = NULL;
+\f
 
 
-
-void
-initialize_conflicts (void)
+static inline void
+log_resolution (int state, int LAno, int token, char *resolution)
 {
 {
-  register int i;
-/*  register errs *sp; JF unused */
-
-  conflicts = NEW2(nstates, char);
-  shiftset = NEW2(tokensetsize, unsigned);
-  lookaheadset = NEW2(tokensetsize, unsigned);
-
-  err_table = NEW2(nstates, errs *);
-
-  any_conflicts = 0;
-
-  for (i = 0; i < nstates; i++)
-    set_conflicts(i);
+  obstack_fgrow4 (&output_obstack,
+                 _("\
+Conflict in state %d between rule %d and token %s resolved as %s.\n"),
+                 state, LAruleno[LAno], tags[token], resolution);
 }
 
 
 }
 
 
+/*------------------------------------------------------------------.
+| Turn off the shift recorded for the specified token in the        |
+| specified state.  Used when we resolve a shift-reduce conflict in |
+| favor of the reduction.                                           |
+`------------------------------------------------------------------*/
+
 static void
 static void
-set_conflicts (int state)
+flush_shift (int state, int token)
 {
 {
-  register int i;
-  register int k;
-  register shifts *shiftp;
-  register unsigned *fp2;
-  register unsigned *fp3;
-  register unsigned *fp4;
-  register unsigned *fp1;
-  register int symbol;
-
-  if (consistent[state]) return;
-
-  for (i = 0; i < tokensetsize; i++)
-    lookaheadset[i] = 0;
-
-  shiftp = shift_table[state];
-  if (shiftp)
-    {
-      k = shiftp->nshifts;
-      for (i = 0; i < k; i++)
-       {
-         symbol = accessing_symbol[shiftp->shifts[i]];
-         if (ISVAR(symbol)) break;
-         SETBIT(lookaheadset, symbol);
-       }
-    }
-
-  k = lookaheads[state + 1];
-  fp4 = lookaheadset + tokensetsize;
-
-  /* loop over all rules which require lookahead in this state */
-  /* first check for shift-reduce conflict, and try to resolve using precedence  */
-
-  for (i = lookaheads[state]; i < k; i++)
-    if (rprec[LAruleno[i]])
-      {
-       fp1 = LA + i * tokensetsize;
-       fp2 = fp1;
-       fp3 = lookaheadset;
+  shifts *shiftp = state_table[state].shift_table;
+  int i;
 
 
-       while (fp3 < fp4)
-         {
-           if (*fp2++ & *fp3++)
-             {
-               resolve_sr_conflict(state, i);
-               break;
-             }
-         }
-      }
-
-  /* loop over all rules which require lookahead in this state */
-  /* Check for conflicts not resolved above.  */
-
-  for (i = lookaheads[state]; i < k; i++)
-    {
-      fp1 = LA + i * tokensetsize;
-      fp2 = fp1;
-      fp3 = lookaheadset;
-
-      while (fp3 < fp4)
-       {
-         if (*fp2++ & *fp3++)
-           {
-             conflicts[state] = 1;
-             any_conflicts = 1;
-           }
-       }
-
-      fp2 = fp1;
-      fp3 = lookaheadset;
-
-      while (fp3 < fp4)
-       *fp3++ |= *fp2++;
-    }
+  for (i = 0; i < shiftp->nshifts; i++)
+    if (!SHIFT_IS_DISABLED (shiftp, i) && SHIFT_SYMBOL (shiftp, i) == token)
+      SHIFT_DISABLE (shiftp, i);
 }
 
 
 }
 
 
-
-/* Attempt to resolve shift-reduce conflict for one rule
-by means of precedence declarations.
-It has already been checked that the rule has a precedence.
-A conflict is resolved by modifying the shift or reduce tables
-so that there is no longer a conflict.  */
+/*------------------------------------------------------------------.
+| Attempt to resolve shift-reduce conflict for one rule by means of |
+| precedence declarations.  It has already been checked that the    |
+| rule has a precedence.  A conflict is resolved by modifying the   |
+| shift or reduce tables so that there is no longer a conflict.     |
+`------------------------------------------------------------------*/
 
 static void
 resolve_sr_conflict (int state, int lookaheadnum)
 {
 
 static void
 resolve_sr_conflict (int state, int lookaheadnum)
 {
-  register int i;
-  register int mask;
-  register unsigned *fp1;
-  register unsigned *fp2;
-  register int redprec;
-  errs *errp = (errs *) xmalloc (sizeof(errs) + ntokens * sizeof(short));
-  short *errtokens = errp->errs;
-
+  int i;
   /* find the rule to reduce by to get precedence of reduction  */
   /* find the rule to reduce by to get precedence of reduction  */
-  redprec = rprec[LAruleno[lookaheadnum]];
+  int redprec = rule_table[LAruleno[lookaheadnum]].prec;
+  errs *errp = ERRS_ALLOC (ntokens + 1);
+  short *errtokens = errp->errs;
 
 
-  mask = 1;
-  fp1 = LA + lookaheadnum * tokensetsize;
-  fp2 = lookaheadset;
   for (i = 0; i < ntokens; i++)
     {
   for (i = 0; i < ntokens; i++)
     {
-      if ((mask & *fp2 & *fp1) && sprec[i])
+      if (BITISSET (LA (lookaheadnum), i)
+         && BITISSET (lookaheadset, i)
+         && sprec[i])
        /* Shift-reduce conflict occurs for token number i
           and it has a precedence.
           The precedence of shifting is that of token i.  */
        {
          if (sprec[i] < redprec)
            {
        /* Shift-reduce conflict occurs for token number i
           and it has a precedence.
           The precedence of shifting is that of token i.  */
        {
          if (sprec[i] < redprec)
            {
-             if (verboseflag) log_resolution(state, lookaheadnum, i, _("reduce"));
-             *fp2 &= ~mask;  /* flush the shift for this token */
-             flush_shift(state, i);
+             log_resolution (state, lookaheadnum, i, _("reduce"));
+             /* flush the shift for this token */
+             RESETBIT (lookaheadset, i);
+             flush_shift (state, i);
            }
          else if (sprec[i] > redprec)
            {
            }
          else if (sprec[i] > redprec)
            {
-             if (verboseflag) log_resolution(state, lookaheadnum, i, _("shift"));
-             *fp1 &= ~mask;  /* flush the reduce for this token */
+             log_resolution (state, lookaheadnum, i, _("shift"));
+             /* flush the reduce for this token */
+             RESETBIT (LA (lookaheadnum), i);
            }
          else
            {
              /* Matching precedence levels.
            }
          else
            {
              /* Matching precedence levels.
-                For left association, keep only the reduction.
-                For right association, keep only the shift.
-                For nonassociation, keep neither.  */
+                For left association, keep only the reduction.
+                For right association, keep only the shift.
+                For nonassociation, keep neither.  */
 
              switch (sassoc[i])
                {
 
              switch (sassoc[i])
                {
-
-               case RIGHT_ASSOC:
-                 if (verboseflag) log_resolution(state, lookaheadnum, i, _("shift"));
+               case right_assoc:
+                 log_resolution (state, lookaheadnum, i, _("shift"));
                  break;
 
                  break;
 
-               case LEFT_ASSOC:
-                 if (verboseflag) log_resolution(state, lookaheadnum, i, _("reduce"));
+               case left_assoc:
+                 log_resolution (state, lookaheadnum, i, _("reduce"));
                  break;
 
                  break;
 
-               case NON_ASSOC:
-                 if (verboseflag) log_resolution(state, lookaheadnum, i, _("an error"));
+               case non_assoc:
+                 log_resolution (state, lookaheadnum, i, _("an error"));
                  break;
                }
 
                  break;
                }
 
-             if (sassoc[i] != RIGHT_ASSOC)
+             if (sassoc[i] != right_assoc)
                {
                {
-                 *fp2 &= ~mask;  /* flush the shift for this token */
-                 flush_shift(state, i);
+                 /* flush the shift for this token */
+                 RESETBIT (lookaheadset, i);
+                 flush_shift (state, i);
                }
                }
-             if (sassoc[i] != LEFT_ASSOC)
-               {
-                 *fp1 &= ~mask;  /* flush the reduce for this token */
+             if (sassoc[i] != left_assoc)
+               {
+                 /* flush the reduce for this token */
+                 RESETBIT (LA (lookaheadnum), i);
                }
                }
-             if (sassoc[i] == NON_ASSOC)
+             if (sassoc[i] == non_assoc)
                {
                  /* Record an explicit error for this token.  */
                  *errtokens++ = i;
                }
            }
        }
                {
                  /* Record an explicit error for this token.  */
                  *errtokens++ = i;
                }
            }
        }
-
-      mask <<= 1;
-      if (mask == 0)
-       {
-         mask = 1;
-         fp2++;  fp1++;
-       }
     }
   errp->nerrs = errtokens - errp->errs;
   if (errp->nerrs)
     {
       /* Some tokens have been explicitly made errors.  Allocate
     }
   errp->nerrs = errtokens - errp->errs;
   if (errp->nerrs)
     {
       /* Some tokens have been explicitly made errors.  Allocate
-        a permanent errs structure for this state, to record them.  */
+         a permanent errs structure for this state, to record them.  */
       i = (char *) errtokens - (char *) errp;
       i = (char *) errtokens - (char *) errp;
-      err_table[state] = (errs *) xmalloc ((unsigned int)i);
+      err_table[state] = ERRS_ALLOC (i + 1);
       bcopy (errp, err_table[state], i);
     }
   else
     err_table[state] = 0;
       bcopy (errp, err_table[state], i);
     }
   else
     err_table[state] = 0;
-  free(errp);
+  free (errp);
 }
 
 
 }
 
 
-
-/* turn off the shift recorded for the specified token in the specified state.
-Used when we resolve a shift-reduce conflict in favor of the reduction.  */
-
 static void
 static void
-flush_shift (int state, int token)
+set_conflicts (int state)
 {
 {
-  register shifts *shiftp;
-  register int k, i;
-/*  register unsigned symbol; JF unused */
+  int i, j;
+  shifts *shiftp;
 
 
-  shiftp = shift_table[state];
+  if (state_table[state].consistent)
+    return;
 
 
-  if (shiftp)
-    {
-      k = shiftp->nshifts;
-      for (i = 0; i < k; i++)
-       {
-         if (shiftp->shifts[i] && token == accessing_symbol[shiftp->shifts[i]])
-           (shiftp->shifts[i]) = 0;
-       }
-    }
-}
+  for (i = 0; i < tokensetsize; i++)
+    lookaheadset[i] = 0;
 
 
+  shiftp = state_table[state].shift_table;
+  for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
+    if (!SHIFT_IS_DISABLED (shiftp, i))
+      SETBIT (lookaheadset, SHIFT_SYMBOL (shiftp, i));
+
+  /* Loop over all rules which require lookahead in this state.  First
+     check for shift-reduce conflict, and try to resolve using
+     precedence */
+  for (i = state_table[state].lookaheads;
+       i < state_table[state + 1].lookaheads;
+       ++i)
+    if (rule_table[LAruleno[i]].prec)
+      for (j = 0; j < tokensetsize; ++j)
+       if (LA (i)[j] & lookaheadset[j])
+         {
+           resolve_sr_conflict (state, i);
+           break;
+         }
 
 
-static void
-log_resolution (int state, int LAno, int token, char *resolution)
-{
-  fprintf(foutput,
-         _("Conflict in state %d between rule %d and token %s resolved as %s.\n"),
-         state, LAruleno[LAno], tags[token], resolution);
-}
 
 
+  /* Loop over all rules which require lookahead in this state.  Check
+     for conflicts not resolved above.  */
+  for (i = state_table[state].lookaheads;
+       i < state_table[state + 1].lookaheads;
+       ++i)
+    {
+      for (j = 0; j < tokensetsize; ++j)
+       if (LA (i)[j] & lookaheadset[j])
+         conflicts[state] = 1;
+
+      for (j = 0; j < tokensetsize; ++j)
+       lookaheadset[j] |= LA (i)[j];
+    }
+}
 
 void
 
 void
-conflict_log (void)
+solve_conflicts (void)
 {
 {
-  register int i;
+  int i;
 
 
-  src_total = 0;
-  rrc_total = 0;
+  conflicts = XCALLOC (char, nstates);
+  shiftset = XCALLOC (unsigned, tokensetsize);
+  lookaheadset = XCALLOC (unsigned, tokensetsize);
 
 
-  for (i = 0; i < nstates; i++)
-    {
-      if (conflicts[i])
-       {
-         count_sr_conflicts(i);
-         count_rr_conflicts(i);
-         src_total += src_count;
-         rrc_total += rrc_count;
-       }
-    }
+  err_table = XCALLOC (errs *, nstates);
 
 
-  total_conflicts();
+  for (i = 0; i < nstates; i++)
+    set_conflicts (i);
 }
 
 
 }
 
 
-void
-verbose_conflict_log (void)
+/*---------------------------------------------.
+| Count the number of shift/reduce conflicts.  |
+`---------------------------------------------*/
+
+static int
+count_sr_conflicts (int state)
 {
 {
-  register int i;
+  int i, k;
+  int src_count = 0;
+  shifts *shiftp = state_table[state].shift_table;
 
 
-  src_total = 0;
-  rrc_total = 0;
+  if (!shiftp)
+    return 0;
 
 
-  for (i = 0; i < nstates; i++)
+  for (i = 0; i < tokensetsize; i++)
     {
     {
-      if (conflicts[i])
-       {
-         count_sr_conflicts(i);
-         count_rr_conflicts(i);
-         src_total += src_count;
-         rrc_total += rrc_count;
-
-         fprintf(foutput, _("State %d contains"), i);
+      shiftset[i] = 0;
+      lookaheadset[i] = 0;
+    }
 
 
-         if (src_count == 1)
-           fprintf(foutput, _(" 1 shift/reduce conflict"));
-         else if (src_count > 1)
-           fprintf(foutput, _(" %d shift/reduce conflicts"), src_count);
+  for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
+    if (!SHIFT_IS_DISABLED (shiftp, i))
+      SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
 
 
-         if (src_count > 0 && rrc_count > 0)
-           fprintf(foutput, _(" and"));
+  for (i = state_table[state].lookaheads;
+       i < state_table[state + 1].lookaheads;
+       ++i)
+    for (k = 0; k < tokensetsize; ++k)
+      lookaheadset[k] |= LA (i)[k];
 
 
-         if (rrc_count == 1)
-           fprintf(foutput, _(" 1 reduce/reduce conflict"));
-         else if (rrc_count > 1)
-           fprintf(foutput, _(" %d reduce/reduce conflicts"), rrc_count);
+  for (k = 0; k < tokensetsize; ++k)
+    lookaheadset[k] &= shiftset[k];
 
 
-         putc('.', foutput);
-         putc('\n', foutput);
-       }
-    }
+  for (i = 0; i < ntokens; i++)
+    if (BITISSET (lookaheadset, i))
+      src_count++;
 
 
-  total_conflicts();
+  return src_count;
 }
 
 
 }
 
 
-static void
-total_conflicts (void)
-{
-  if (src_total == expected_conflicts && rrc_total == 0)
-    return;
+/*----------------------------------------------.
+| Count the number of reduce/reduce conflicts.  |
+`----------------------------------------------*/
 
 
-  if (fixed_outfiles)
-    {
-      /* If invoked under the name `yacc', use the output format
-        specified by POSIX.  */
-      fprintf(stderr, _("conflicts: "));
-      if (src_total > 0)
-       fprintf(stderr, _(" %d shift/reduce"), src_total);
-      if (src_total > 0 && rrc_total > 0)
-       fprintf(stderr, ",");
-      if (rrc_total > 0)
-       fprintf(stderr, _(" %d reduce/reduce"), rrc_total);
-      putc('\n', stderr);
-    }
-  else
-    {
-      fprintf(stderr, _("%s contains"), infile);
+static int
+count_rr_conflicts (int state)
+{
+  int i;
+  int rrc_count = 0;
 
 
-      if (src_total == 1)
-       fprintf(stderr, _(" 1 shift/reduce conflict"));
-      else if (src_total > 1)
-       fprintf(stderr, _(" %d shift/reduce conflicts"), src_total);
+  int m = state_table[state].lookaheads;
+  int n = state_table[state + 1].lookaheads;
 
 
-      if (src_total > 0 && rrc_total > 0)
-       fprintf(stderr, _(" and"));
+  if (n - m < 2)
+    return 0;
 
 
-      if (rrc_total == 1)
-       fprintf(stderr, _(" 1 reduce/reduce conflict"));
-      else if (rrc_total > 1)
-       fprintf(stderr, _(" %d reduce/reduce conflicts"), rrc_total);
+  for (i = 0; i < ntokens; i++)
+    {
+      int count = 0;
+      int j;
+      for (j = m; j < n; j++)
+       if (BITISSET (LA (m), j))
+         count++;
 
 
-      putc('.', stderr);
-      putc('\n', stderr);
+      if (count >= 2)
+       rrc_count++;
     }
     }
+
+  return rrc_count;
 }
 
 }
 
+/*--------------------------------------------------------------.
+| Return a human readable string which reports shift/reduce and |
+| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM).            |
+`--------------------------------------------------------------*/
 
 
-static void
-count_sr_conflicts (int state)
+static const char *
+conflict_report (int src_num, int rrc_num)
 {
 {
-  register int i;
-  register int k;
-  register int mask;
-  register shifts *shiftp;
-  register unsigned *fp1;
-  register unsigned *fp2;
-  register unsigned *fp3;
-  register int symbol;
-
-  src_count = 0;
-
-  shiftp = shift_table[state];
-  if (!shiftp) return;
+  static char res[4096];
+  char *cp = res;
 
 
-  for (i = 0; i < tokensetsize; i++)
+  if (src_num >= 1)
     {
     {
-      shiftset[i] = 0;
-      lookaheadset[i] = 0;
+      sprintf (cp, ngettext ("%d shift/reduce conflict",
+                            "%d shift/reduce conflicts", src_num), src_num);
+      cp += strlen (cp);
     }
 
     }
 
-  k = shiftp->nshifts;
-  for (i = 0; i < k; i++)
+  if (src_num > 0 && rrc_num > 0)
     {
     {
-      if (! shiftp->shifts[i]) continue;
-      symbol = accessing_symbol[shiftp->shifts[i]];
-      if (ISVAR(symbol)) break;
-      SETBIT(shiftset, symbol);
+      sprintf (cp, " %s ", _("and"));
+      cp += strlen (cp);
     }
 
     }
 
-  k = lookaheads[state + 1];
-  fp3 = lookaheadset + tokensetsize;
-
-  for (i = lookaheads[state]; i < k; i++)
+  if (rrc_num >= 1)
     {
     {
-      fp1 = LA + i * tokensetsize;
-      fp2 = lookaheadset;
-
-      while (fp2 < fp3)
-       *fp2++ |= *fp1++;
+      sprintf (cp, ngettext ("%d reduce/reduce conflict",
+                            "%d reduce/reduce conflicts", rrc_num), rrc_num);
+      cp += strlen (cp);
     }
 
     }
 
-  fp1 = shiftset;
-  fp2 = lookaheadset;
+  *cp++ = '.';
+  *cp++ = '\n';
+  *cp++ = '\0';
 
 
-  while (fp2 < fp3)
-    *fp2++ &= *fp1++;
+  return res;
+}
 
 
-  mask = 1;
-  fp2 = lookaheadset;
-  for (i = 0; i < ntokens; i++)
-    {
-      if (mask & *fp2)
-       src_count++;
 
 
-      mask <<= 1;
-      if (mask == 0)
-       {
-         mask = 1;
-         fp2++;
-       }
-    }
+/*-----------------------------------------------------------.
+| Output the detailed description of states with conflicts.  |
+`-----------------------------------------------------------*/
+
+void
+conflicts_output (FILE *out)
+{
+  bool printed_sth = FALSE;
+  int i;
+  for (i = 0; i < nstates; i++)
+    if (conflicts[i])
+      {
+       fprintf (out, _("State %d contains "), i);
+       fputs (conflict_report (count_sr_conflicts (i),
+                               count_rr_conflicts (i)), out);
+       printed_sth = TRUE;
+      }
+  if (printed_sth)
+    fputs ("\n\n", out);
 }
 
 
 }
 
 
-static void
-count_rr_conflicts (int state)
-{
-  register int i;
-  register int j;
-  register int count;
-  register unsigned mask;
-  register unsigned *baseword;
-  register unsigned *wordp;
-  register int m;
-  register int n;
+/*------------------------------------------.
+| Reporting the total number of conflicts.  |
+`------------------------------------------*/
 
 
-  rrc_count = 0;
+void
+conflicts_print (void)
+{
+  int i;
 
 
-  m = lookaheads[state];
-  n = lookaheads[state + 1];
+  /* Is the number of SR conflicts OK?  Either EXPECTED_CONFLICTS is
+     not set, and then we want 0 SR, or else it is specified, in which
+     case we want equality.  */
+  int src_ok = 0;
 
 
-  if (n - m < 2) return;
+  int src_total = 0;
+  int rrc_total = 0;
 
 
-  mask = 1;
-  baseword = LA + m * tokensetsize;
-  for (i = 0; i < ntokens; i++)
-    {
-      wordp = baseword;
+  /* Conflicts by state.  */
+  for (i = 0; i < nstates; i++)
+    if (conflicts[i])
+      {
+       src_total += count_sr_conflicts (i);
+       rrc_total += count_rr_conflicts (i);
+      }
 
 
-      count = 0;
-      for (j = m; j < n; j++)
-       {
-         if (mask & *wordp)
-           count++;
+  src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
 
 
-         wordp += tokensetsize;
-       }
+  /* If there are no RR conflicts, and as many SR conflicts as
+     expected, then there is nothing to report.  */
+  if (!rrc_total && src_ok)
+    return;
 
 
-      if (count >= 2) rrc_count++;
+  /* Report the total number of conflicts on STDERR.  */
+  if (yacc_flag)
+    {
+      /* If invoked with `--yacc', use the output format specified by
+        POSIX.  */
+      fprintf (stderr, _("conflicts: "));
+      if (src_total > 0)
+       fprintf (stderr, _(" %d shift/reduce"), src_total);
+      if (src_total > 0 && rrc_total > 0)
+       fprintf (stderr, ",");
+      if (rrc_total > 0)
+       fprintf (stderr, _(" %d reduce/reduce"), rrc_total);
+      putc ('\n', stderr);
+    }
+  else
+    {
+      fprintf (stderr, _("%s contains "), infile);
+      fputs (conflict_report (src_total, rrc_total), stderr);
+    }
 
 
-      mask <<= 1;
-      if (mask == 0)
-       {
-         mask = 1;
-         baseword++;
-       }
+  if (expected_conflicts != -1 && !src_ok)
+    {
+      complain_message_count++;
+      fprintf (stderr, ngettext ("expected %d shift/reduce conflict\n",
+                                "expected %d shift/reduce conflicts\n",
+                                expected_conflicts),
+              expected_conflicts);
     }
 }
 
 
 void
     }
 }
 
 
 void
-print_reductions (int state)
+print_reductions (FILE *out, int state)
 {
 {
-  register int i;
-  register int j;
-  register int k;
-  register unsigned *fp1;
-  register unsigned *fp2;
-  register unsigned *fp3;
-  register unsigned *fp4;
-  register int rule;
-  register int symbol;
-  register unsigned mask;
-  register int m;
-  register int n;
-  register int default_LA;
-  register int default_rule = 0;
-  register int cmax;
-  register int count;
-  register shifts *shiftp;
-  register errs *errp;
+  int i;
+  int j;
+  int m;
+  int n;
+  shifts *shiftp;
+  errs *errp;
   int nodefault = 0;
 
   for (i = 0; i < tokensetsize; i++)
     shiftset[i] = 0;
 
   int nodefault = 0;
 
   for (i = 0; i < tokensetsize; i++)
     shiftset[i] = 0;
 
-  shiftp = shift_table[state];
-  if (shiftp)
-    {
-      k = shiftp->nshifts;
-      for (i = 0; i < k; i++)
-       {
-         if (! shiftp->shifts[i]) continue;
-         symbol = accessing_symbol[shiftp->shifts[i]];
-         if (ISVAR(symbol)) break;
-         /* if this state has a shift for the error token,
-            don't use a default rule.  */
-         if (symbol == error_token_number) nodefault = 1;
-         SETBIT(shiftset, symbol);
-       }
-    }
+  shiftp = state_table[state].shift_table;
+  for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
+    if (!SHIFT_IS_DISABLED (shiftp, i))
+      {
+       /* if this state has a shift for the error token, don't use a
+          default rule.  */
+       if (SHIFT_IS_ERROR (shiftp, i))
+         nodefault = 1;
+       SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
+      }
 
   errp = err_table[state];
   if (errp)
 
   errp = err_table[state];
   if (errp)
-    {
-      k = errp->nerrs;
-      for (i = 0; i < k; i++)
-       {
-         if (! errp->errs[i]) continue;
-         symbol = errp->errs[i];
-         SETBIT(shiftset, symbol);
-       }
-    }
+    for (i = 0; i < errp->nerrs; i++)
+      if (errp->errs[i])
+       SETBIT (shiftset, errp->errs[i]);
 
 
-  m = lookaheads[state];
-  n = lookaheads[state + 1];
+  m = state_table[state].lookaheads;
+  n = state_table[state + 1].lookaheads;
 
 
-  if (n - m == 1 && ! nodefault)
+  if (n - m == 1 && !nodefault)
     {
     {
-      default_rule = LAruleno[m];
-
-      fp1 = LA + m * tokensetsize;
-      fp2 = shiftset;
-      fp3 = lookaheadset;
-      fp4 = lookaheadset + tokensetsize;
-
-      while (fp3 < fp4)
-       *fp3++ = *fp1++ & *fp2++;
+      int k;
+      int default_rule = LAruleno[m];
 
 
-      mask = 1;
-      fp3 = lookaheadset;
+      for (k = 0; k < tokensetsize; ++k)
+       lookaheadset[k] = LA (m)[k] & shiftset[k];
 
       for (i = 0; i < ntokens; i++)
 
       for (i = 0; i < ntokens; i++)
-       {
-         if (mask & *fp3)
-           fprintf(foutput, _("    %-4s\t[reduce using rule %d (%s)]\n"),
-                   tags[i], default_rule, tags[rlhs[default_rule]]);
-
-         mask <<= 1;
-         if (mask == 0)
-           {
-             mask = 1;
-             fp3++;
-           }
-       }
+       if (BITISSET (lookaheadset, i))
+         fprintf (out, _("    %-4s\t[reduce using rule %d (%s)]\n"),
+                  tags[i], default_rule,
+                  tags[rule_table[default_rule].lhs]);
 
 
-      fprintf(foutput, _("    $default\treduce using rule %d (%s)\n\n"),
-             default_rule, tags[rlhs[default_rule]]);
+      fprintf (out, _("    $default\treduce using rule %d (%s)\n\n"),
+              default_rule, tags[rule_table[default_rule].lhs]);
     }
   else if (n - m >= 1)
     {
     }
   else if (n - m >= 1)
     {
-      cmax = 0;
-      default_LA = -1;
-      fp4 = lookaheadset + tokensetsize;
+      int k;
+
+      int cmax = 0;
+      int default_LA = -1;
+      int default_rule = 0;
 
 
-      if (! nodefault)
+      if (!nodefault)
        for (i = m; i < n; i++)
          {
        for (i = m; i < n; i++)
          {
-           fp1 = LA + i * tokensetsize;
-           fp2 = shiftset;
-           fp3 = lookaheadset;
+           int count = 0;
 
 
-           while (fp3 < fp4)
-             *fp3++ = *fp1++ & (~(*fp2++));
+           for (k = 0; k < tokensetsize; ++k)
+             lookaheadset[k] = LA (i)[k] & ~shiftset[k];
 
 
-           count = 0;
-           mask = 1;
-           fp3 = lookaheadset;
            for (j = 0; j < ntokens; j++)
            for (j = 0; j < ntokens; j++)
-             {
-               if (mask & *fp3)
-                 count++;
-
-               mask <<= 1;
-               if (mask == 0)
-                 {
-                   mask = 1;
-                   fp3++;
-                 }
-             }
+             if (BITISSET (lookaheadset, j))
+               count++;
 
            if (count > cmax)
              {
 
            if (count > cmax)
              {
@@ -647,101 +497,69 @@ print_reductions (int state)
                default_rule = LAruleno[i];
              }
 
                default_rule = LAruleno[i];
              }
 
-           fp2 = shiftset;
-           fp3 = lookaheadset;
-
-           while (fp3 < fp4)
-             *fp2++ |= *fp3++;
+           for (k = 0; k < tokensetsize; ++k)
+             shiftset[k] |= lookaheadset[k];
          }
 
       for (i = 0; i < tokensetsize; i++)
          }
 
       for (i = 0; i < tokensetsize; i++)
-        shiftset[i] = 0;
+       shiftset[i] = 0;
 
 
-      if (shiftp)
-        {
-          k = shiftp->nshifts;
-          for (i = 0; i < k; i++)
-           {
-             if (! shiftp->shifts[i]) continue;
-             symbol = accessing_symbol[shiftp->shifts[i]];
-             if (ISVAR(symbol)) break;
-             SETBIT(shiftset, symbol);
-           }
-        }
+      for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
+       if (!SHIFT_IS_DISABLED (shiftp, i))
+         SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
 
 
-      mask = 1;
-      fp1 = LA + m * tokensetsize;
-      fp2 = shiftset;
       for (i = 0; i < ntokens; i++)
        {
          int defaulted = 0;
       for (i = 0; i < ntokens; i++)
        {
          int defaulted = 0;
+         int count = BITISSET (shiftset, i);
 
 
-         if (mask & *fp2)
-           count = 1;
-         else
-           count = 0;
-
-         fp3 = fp1;
          for (j = m; j < n; j++)
            {
          for (j = m; j < n; j++)
            {
-             if (mask & *fp3)
+             if (BITISSET (LA (m), j))
                {
                  if (count == 0)
                    {
                      if (j != default_LA)
                {
                  if (count == 0)
                    {
                      if (j != default_LA)
-                       {
-                         rule = LAruleno[j];
-                         fprintf(foutput, _("    %-4s\treduce using rule %d (%s)\n"),
-                                 tags[i], rule, tags[rlhs[rule]]);
-                       }
-                     else defaulted = 1;
+                       fprintf (out,
+                                _("    %-4s\treduce using rule %d (%s)\n"),
+                                tags[i],
+                                LAruleno[j],
+                                tags[rule_table[LAruleno[j]].lhs]);
+                     else
+                       defaulted = 1;
 
                      count++;
                    }
                  else
                    {
                      if (defaulted)
 
                      count++;
                    }
                  else
                    {
                      if (defaulted)
-                       {
-                         rule = LAruleno[default_LA];
-                         fprintf(foutput, _("    %-4s\treduce using rule %d (%s)\n"),
-                                 tags[i], rule, tags[rlhs[rule]]);
-                         defaulted = 0;
-                       }
-                     rule = LAruleno[j];
-                     fprintf(foutput, _("    %-4s\t[reduce using rule %d (%s)]\n"),
-                             tags[i], rule, tags[rlhs[rule]]);
+                       fprintf (out,
+                                _("    %-4s\treduce using rule %d (%s)\n"),
+                                tags[i],
+                                LAruleno[default_LA],
+                                tags[rule_table[LAruleno[default_LA]].lhs]);
+                     defaulted = 0;
+                     fprintf (out,
+                              _("    %-4s\t[reduce using rule %d (%s)]\n"),
+                              tags[i],
+                              LAruleno[j],
+                              tags[rule_table[LAruleno[j]].lhs]);
                    }
                }
                    }
                }
-
-             fp3 += tokensetsize;
-           }
-
-         mask <<= 1;
-         if (mask == 0)
-           {
-             mask = 1;
-             /* We tried incrementing just fp1, and just fp2; both seem wrong.
-                It seems necessary to increment both in sync.  */
-             fp1++;
-             fp2++;
            }
        }
 
       if (default_LA >= 0)
            }
        }
 
       if (default_LA >= 0)
-       {
-         fprintf(foutput, _("    $default\treduce using rule %d (%s)\n"),
-                 default_rule, tags[rlhs[default_rule]]);
-       }
-
-      putc('\n', foutput);
+       fprintf (out, _("    $default\treduce using rule %d (%s)\n"),
+                default_rule, tags[rule_table[default_rule].lhs]);
     }
 }
 
 
 void
     }
 }
 
 
 void
-finalize_conflicts (void)
+free_conflicts (void)
 {
 {
-  FREE(conflicts);
-  FREE(shiftset);
-  FREE(lookaheadset);
+  XFREE (conflicts);
+  XFREE (shiftset);
+  XFREE (lookaheadset);
 }
 }