--- /dev/null
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ * This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ * Dr. Andrew S. Tanenbaum
+ * Wiskundig Seminarium
+ * Vrije Universiteit
+ * Postbox 7161
+ * 1007 MC Amsterdam
+ * The Netherlands
+ *
+ */
+
+/*
+ * L L G E N
+ *
+ * An Extended LL(1) Parser Generator
+ *
+ * Author : Ceriel J.H. Jacobs
+ */
+
+/*
+ * sets.c
+ * Some general setmanipulation routines are defined,
+ * and also two set allocating routines are defined
+ */
+
+# include "types.h"
+# include "extern.h"
+# include "sets.h"
+# include "assert.h"
+
+# ifndef NORCSID
+static string rcsid9 = "$Header$";
+# endif
+
+/* In this file the following routines are defined: */
+extern setinit();
+extern p_set setalloc();
+extern int setunion();
+extern int setintersect();
+extern setminus();
+extern int setempty();
+extern int findindex();
+extern int setcount();
+
+int tbitset;
+int setsize,tsetsize;
+p_set *setptr, *maxptr, *topptr;
+
+static unsigned size,nbytes;
+
+setinit(ntneeded) {
+ /*
+ * Initialises some variables needed for setcomputations
+ */
+ register int bitset;
+
+ nbytes = NBYTES(nterminals);
+ tbitset = ALIGN(nbytes);
+ tsetsize = NINTS(tbitset);
+ bitset = tbitset;
+ if (ntneeded) {
+ /* nonterminals must be included in the sets */
+ bitset += NBYTES(nnonterms);
+ }
+ setsize = NINTS(bitset);
+ tbitset *= 8;
+}
+
+p_set
+setalloc(size) int size; {
+ /*
+ * Allocate a set of size "size" ints
+ */
+ register p_set t;
+ register int i;
+ p_mem alloc();
+
+ assert(size == tsetsize || size == setsize);
+ t = (p_set) alloc((unsigned) (size * sizeof(int)));
+ i = size;
+ t += i;
+ for (; i; i--) {
+ *--t = 0;
+ }
+ return t;
+}
+
+int
+setunion(a,b,size) register p_set a,b; int size; {
+ /*
+ * a = a union b.
+ * Return 1 if the set a changed
+ */
+ register i;
+ register j;
+ int nsub = 0;
+
+ assert(size == tsetsize || size == setsize);
+ for (i = size; i; i--) {
+ *a = (j = *a) | *b++;
+ if (*a++ != j) {
+ nsub = 1;
+ }
+ }
+ return nsub;
+}
+
+int
+setintersect(a,b,size) register p_set a,b; int size; {
+ /*
+ * a = a intersect b.
+ * return 1 if the resut is empty
+ */
+ register i;
+ register nempty;
+
+ assert(size == tsetsize || size == setsize);
+ nempty = 1;
+ for (i = size; i; i--) {
+ if (*a++ &= *b++) nempty = 0;
+ }
+ return nempty;
+}
+
+setminus(a,b,size) register p_set a,b; int size; {
+ /*
+ * a = a setminus b
+ */
+ register i;
+
+ assert(size == tsetsize || size == setsize);
+ for (i = size; i; i--) {
+ *a++ &= ~(*b++);
+ }
+}
+
+int
+setempty(p) register p_set p; {
+ /*
+ * Return 1 if the set p is empty
+ */
+ register i;
+
+ for (i = tsetsize; i; i--) {
+ if (*p++) return 0;
+ }
+ return 1;
+}
+
+int
+findindex(set) p_set *set; {
+ /*
+ * The set "set" will serve as a recovery set.
+ * Search for it in the table. If not present, enter it
+ */
+ register p_set *t;
+ p_mem alloc(),ralloc();
+ register p_set a;
+ register p_set b;
+ register i;
+ register j;
+ int saved;
+
+ /*
+ * First search for the set in the table
+ */
+ for (t = setptr; t < maxptr; t++) {
+ a = *t;
+ b = *set;
+ for (i = tsetsize; i; i--) {
+ if (*a++ != *b++) break;
+ }
+ if (i) continue;
+ /*
+ * Here, the sets are equal.
+ */
+ return nbytes * (t - setptr);
+ }
+ /*
+ * Now check if the set consists of only one element.
+ * It would be a waste to use a set for that
+ */
+ if (setcount(*set, &saved) == 1) return -h_entry[saved].h_num;
+ /*
+ * If it does, return its number as a negative number.
+ */
+ if (maxptr >= topptr) {
+ /*
+ * Need new space for the list, in chunks of 50 pointers
+ */
+ if (setptr == 0) {
+ setptr = (p_set *) alloc(50 * sizeof(p_set));
+ size = 50;
+ maxptr = setptr;
+ } else {
+ setptr = (p_set *) ralloc((p_mem) setptr,
+ (50+size)*sizeof(p_set));
+ maxptr = &setptr[size-1];
+ size += 50;
+ }
+ topptr = &setptr[size-1];
+ }
+ *maxptr = setalloc(tsetsize);
+ setunion(*maxptr, *set, tsetsize);
+ return nbytes * (maxptr++ - setptr);
+}
+
+int
+setcount(set, saved) register p_set set; int *saved; {
+ register int i, j;
+
+ for (j = 0, i = 0; i < nterminals; i++) {
+ if (IN(set,i)) {
+ j++;
+ *saved = i;
+ }
+ }
+ return j;
+}