text: // 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
     }
  