/************************************************************************/
/*                                                                      */
/* Copyright (c) 1988 -                                                 */
/*     The Rector and Visitors of the University of Virginia            */
/*                                                                      */
/* This code may not be distributed further without permission          */
/*      from the University of Virginia.                                */
/* This code is distributed WITHOUT ANY WARRANTY.  No claims are        */
/*      made as to whether it serves any particular purpose or even     */
/*      works at all.                                                   */
/*                                                                      */
/************************************************************************/

/*
 * This file contains the functions for implementing "stop sets" in
 * the parser.  A stop set is a set of input symbols that are
 * expected to follow the current symbol.  Whenever a symbol is
 * accepted, the next symbol must be in the current stop set.
 * If not, the parser recovers from the error by inputting symbols
 * until the current symbol is in the stop set.
 * 
 * Pascal has 62 input symbols so a stop set is a bit map consisting
 * of two unsigned longs.
 */

#include <varargs.h>
#include "types.h"
#include "stopset.h"

/*
 * set_cons() takes a variable number of arguments terminated
 * by zero.  These arguments are symbol values.  Set_cons returns
 * a pointer to a stop set that is the union of all the arguments.
 */

/* VARARGS */

STOPSET
set_cons(va_alist)
	va_dcl
{
	va_list ap;
	register int member;
	static STOPBUF resbuf;
	register STOPSET result = resbuf;
	
	result[0] = result[1] = 0;
	va_start(ap);
	while((member = va_arg(ap, int)) != 0) {
		result[member >> SS_SHIFT] |= (1L << (member & SS_MASK));
	}
	va_end(ap);
	return(result);
}

/*
 * set_or() takes a variable number of arguments terminated by S0,
 * ((unsigned*)0).  The arguments are pointers to stop sets.
 * The union of all these sets is placed in the result.
 */

/* VARARGS */

set_or(result, va_alist)
	STOPSET result;
	va_dcl
{
	va_list ap;
	register STOPSET set;
	register unsigned long r0, r1;

	r0 = r1 = 0;
	va_start(ap);
	while((set = va_arg(ap, STOPSET)) != S0) {
		r0 |= *set;
		r1 |= *++set;
	}
	va_end(ap);
	*result   = r0;
	*++result = r1;
}

/*

set_in() -- see macro in stopset.h

*/
