// Copyright (c) 1993-1999 Microsoft Corporation

#include "y1.h"

/*
 * yclsur.1c
 *
 * Modified to make debug code conditionally compile.
 * 28-Aug-81
 * Bob Denny
 */

void 
closure( int i)

   {
   /* generate the closure of state i */

   int work, k;
   SSIZE_T ch, c;
   register struct wset *u, *v;
   SSIZE_T *pi;
   SSIZE_T **s, **t;
   struct item *q;
   register struct item *p;

   ++zzclose;

   /* first, copy kernel of state i to wsets */

   cwp = wsets;
   ITMLOOP(i,p,q)

      {
      cwp->pitem = p->pitem;
      cwp->flag = 1;    /* this item must get closed */
      SETLOOP(k) cwp->ws.lset[k] = p->look->lset[k];
      WSBUMP(cwp);
      }

   /* now, go through the loop, closing each item */

   work = 1;
   while( work )

      {
      work = 0;
      WSLOOP(wsets,u)

         {

         if( u->flag == 0 ) continue;
         c = *(u->pitem);  /* dot is before c */

         if( c < NTBASE )

            {
            u->flag = 0;
            continue;  /* only interesting case is where . is before nonterminal */
            }

         /* compute the lookahead */
         aryfil( clset.lset, tbitset, 0 );

         /* find items involving c */

         WSLOOP(u,v)

            {
            if( v->flag == 1 && *(pi=v->pitem) == c )

               {
               v->flag = 0;
               if( nolook ) continue;
               while( (ch= *++pi)>0 )

                  {
                  if( ch < NTBASE )

                     {
                     /* terminal symbol */
                     SETBIT( clset.lset, ch );
                     break;
                     }
                  /* nonterminal symbol */
                  setunion( clset.lset, pfirst[ch-NTBASE]->lset );
                  if( !pempty[ch-NTBASE] ) break;
                  }
               if( ch<=0 ) setunion( clset.lset, v->ws.lset );
               }
            }

         /*  now loop over productions derived from c */

         c -= NTBASE; /* c is now nonterminal number */

         t = pres[c+1];
         for( s=pres[c]; s<t; ++s )

            {
            /* put these items into the closure */
            WSLOOP(wsets,v)

               {
               /* is the item there */
               if( v->pitem == *s )

                  {
                  /* yes, it is there */
                  if( nolook ) goto nexts;
                  if( setunion( v->ws.lset, clset.lset ) ) v->flag = work = 1;
                  goto nexts;
                  }
               }

            /*  not there; make a new entry */
            if( cwp-wsets+1 >= WSETSIZE ) error( "working set overflow" );
            cwp->pitem = *s;
            cwp->flag = 1;
            if( !nolook )

               {
               work = 1;
               SETLOOP(k) cwp->ws.lset[k] = clset.lset[k];
               }
            WSBUMP(cwp);
nexts: 
            ;
            }

         }
      }

   /* have computed closure; flags are reset; return */

   if( cwp > zzcwp ) zzcwp = cwp;

#ifdef debug
   if( foutput!=NULL )

      {
      fprintf( foutput, "\nState %d, nolook = %d\n", i, nolook );
      WSLOOP(wsets,u)

         {
         if( u->flag ) fprintf( foutput, "flag set!\n");
         u->flag = 0;
         fprintf( foutput, "\t%s", writem(u->pitem));
         prlook( &u->ws );
         fprintf( foutput,  "\n" );
         }
      }
#endif
   }