shithub: riscv

Download patch

ref: 28e9566dc539244b3b429c21c556d656733839c2
parent: 077e719dfbf9bf2582bed80026251cc0d108c16e
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Nov 22 16:09:31 EST 2017

spin: Update to most recent version. (thanks Ori_B)

from Ori_B:

There were a small number of changes needed from the tarball
on spinroot.org:

  - The mkfile needed to be updated
  - Memory.h needed to not be included
  - It needed to invoke /bin/cpp instead of gcc -E
  - It depended on `yychar`, which our yacc doesn't
    provide.

I'm still figuring out how to use spin, but it seems to do
the right thing when testing a few of the examples:

	% cd $home/src/Spin/Examples/
	% spin -a peterson.pml
	% pcc pan.c -D_POSIX_SOURCE
	% ./6.out

	(Spin Version 6.4.7 -- 19 August 2017)
		+ Partial Order Reduction

	Full statespace search for:
		never claim         	- (none specified)
		assertion violations	+
		acceptance   cycles 	- (not selected)
		invalid end states	+

	State-vector 32 byte, depth reached 24, errors: 0
	40 states, stored
	27 states, matched
	67 transitions (= stored+matched)
		0 atomic steps
	hash conflicts:         0 (resolved)

	Stats on memory usage (in Megabytes):
	0.002	equivalent memory usage for states (stored*(State-vector + overhead))
	0.292	actual memory usage for states
	128.000	memory used for hash table (-w24)
	0.534	memory used for DFS stack (-m10000)
	128.730	total actual memory usage


	unreached in proctype user
		/tmp/Spin/Examples/peterson.pml:20, state 10, "-end-"
		(1 of 10 states)

	pan: elapsed time 1.25 seconds
	pan: rate        32 states/second

--- a/sys/src/cmd/spin/dstep.c
+++ b/sys/src/cmd/spin/dstep.c
@@ -1,20 +1,18 @@
 /***** spin: dstep.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
+#include <assert.h>
 #include "spin.h"
 #include "y.tab.h"
 
-#define MAXDSTEP	1024	/* was 512 */
+#define MAXDSTEP	2048	/* was 512 */
 
-char	*NextLab[64];
+char	*NextLab[64];	/* must match value in pangen2.c:41 */
 int	Level=0, GenCode=0, IsGuard=0, TestOnly=0;
 
 static int	Tj=0, Jt=0, LastGoto=0;
@@ -21,7 +19,7 @@
 static int	Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP];
 static void	putCode(FILE *, Element *, Element *, Element *, int);
 
-extern int	Pid, claimnr, separate, OkBreak;
+extern int	Pid, separate, OkBreak;
 
 static void
 Sourced(int n, int special)
@@ -59,7 +57,7 @@
 			if (Tojump[j] == Jumpto[i])
 				break;
 		if (j == Tj)
-		{	char buf[12];
+		{	char buf[16];
 			if (Jumpto[i] == OkBreak)
 			{	if (!LastGoto)
 				fprintf(fd, "S_%.3d_0:	/* break-dest */\n",
@@ -80,10 +78,11 @@
 	}
 	for (j = i = 0; j < Tj; j++)
 		if (Special[j])
-		{	Tojump[i] = Tojump[j];
+		{	if (i >= MAXDSTEP)
+			{	fatal("cannot happen (dstep.c)", (char *)0);
+			}
+			Tojump[i] = Tojump[j];
 			Special[i] = 2;
-			if (i >= MAXDSTEP)
-			fatal("cannot happen (dstep.c)", (char *)0);
 			i++;
 		}
 	Tj = i;	/* keep only the global exit-labels */
@@ -164,7 +163,7 @@
 			break;
 		case ELSE:
 			if (inh++ > 0) fprintf(fd, " || ");
-/* 4.2.5 */		if (Pid != claimnr)
+/* 4.2.5 */		if (!pid_is_claim(Pid))
 				fprintf(fd, "(boq == -1 /* else */)");
 			else
 				fprintf(fd, "(1 /* else */)");
@@ -184,7 +183,7 @@
 		case 's':
 			if (inh++ > 0) fprintf(fd, " || ");
 			fprintf(fd, "("); TestOnly=1;
-/* 4.2.1 */		if (Pid != claimnr) fprintf(fd, "(boq == -1) && ");
+/* 4.2.1 */		if (!pid_is_claim(Pid)) fprintf(fd, "(boq == -1) && ");
 			putstmnt(fd, ee->n, ee->seqno);
 			fprintf(fd, ")"); TestOnly=0;
 			break;
@@ -191,10 +190,10 @@
 		case 'c':
 			if (inh++ > 0) fprintf(fd, " || ");
 			fprintf(fd, "("); TestOnly=1;
-			if (Pid != claimnr)
+			if (!pid_is_claim(Pid))
 				fprintf(fd, "(boq == -1 && ");
 			putstmnt(fd, ee->n->lft, e->seqno);
-			if (Pid != claimnr)
+			if (!pid_is_claim(Pid))
 				fprintf(fd, ")");
 			fprintf(fd, ")"); TestOnly=0;
 			break;
@@ -204,7 +203,8 @@
 
 int
 putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln, int seqno)
-{	int isg=0; char buf[64];
+{	int isg=0;
+	static char buf[64];
 
 	NextLab[0] = "continue";
 	filterbad(s->frst);
@@ -215,6 +215,7 @@
 		return putcode(fd, s->frst->n->sl->this, nxt, 0, ln, seqno);
 	case NON_ATOMIC:
 		(void) putcode(fd, s->frst->n->sl->this, ZE, 1, ln, seqno);
+		if (justguards) return 0;	/* 6.2.5 */
 		break;
 	case IF:
 		fprintf(fd, "if (!(");
@@ -245,7 +246,7 @@
 	case 's':
 		fprintf(fd, "if (");
 #if 1
-/* 4.2.1 */	if (Pid != claimnr) fprintf(fd, "(boq != -1) || ");
+/* 4.2.1 */	if (!pid_is_claim(Pid)) fprintf(fd, "(boq != -1) || ");
 #endif
 		fprintf(fd, "!("); TestOnly=1;
 		putstmnt(fd, s->frst->n, s->frst->seqno);
@@ -253,7 +254,7 @@
 		break;
 	case 'c':
 		fprintf(fd, "if (!(");
-		if (Pid != claimnr) fprintf(fd, "boq == -1 && ");
+		if (!pid_is_claim(Pid)) fprintf(fd, "boq == -1 && ");
 		TestOnly=1;
 		putstmnt(fd, s->frst->n->lft, s->frst->seqno);
 		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
@@ -262,19 +263,31 @@
 		fprintf(fd, "if (boq != -1 || (");
 		if (separate != 2) fprintf(fd, "trpt->");
 		fprintf(fd, "o_pm&1))\n\t\t\tcontinue;");
+		{	extern FILE *th;
+			fprintf(th, "#ifndef ELSE_IN_GUARD\n");
+			fprintf(th, "	#define ELSE_IN_GUARD\n");
+			fprintf(th, "#endif\n");
+		}
 		break;
 	case ASGN:	/* new 3.0.8 */
 		fprintf(fd, "IfNotBlocked");
 		break;
+	default:
+		fprintf(fd, "/* default %d */\n\t\t", s->frst->n->ntyp);
 	}
+
+	/* 6.2.5 : before TstOnly */
+	fprintf(fd, "\n\n\t\treached[%d][%d] = 1;\n\t\t", Pid, seqno);
+	fprintf(fd, "reached[%d][t->st] = 1;\n\t\t", Pid); /* next state */
+	fprintf(fd, "reached[%d][tt] = 1;\n", Pid);	/* current state */
+
+	/* 6.2.5 : before sv_save() */
+	if (s->frst->n->ntyp != NON_ATOMIC)
+	fprintf(fd, "\n\t\tif (TstOnly) return 1;\n"); /* if called from enabled() */
+
 	if (justguards) return 0;
 
 	fprintf(fd, "\n\t\tsv_save();\n\t\t");
-#if 1
-	fprintf(fd, "reached[%d][%d] = 1;\n\t\t", Pid, seqno);
-	fprintf(fd, "reached[%d][t->st] = 1;\n\t\t", Pid);	/* true next state */
-	fprintf(fd, "reached[%d][tt] = 1;\n", Pid);		/* true current state */
-#endif
 	sprintf(buf, "Uerror(\"block in d_step seq, line %d\")", ln);
 	NextLab[0] = buf;
 	putCode(fd, s->frst, s->extent, nxt, isg);
@@ -359,7 +372,7 @@
 			case '.':
 				if (LastGoto) break;
 				if (e->nxt && (e->nxt->status & DONE2))
-				{	i = e->nxt?e->nxt->Seqno:0;
+				{	i = e->nxt->Seqno;
 					fprintf(fd, "\t\tgoto S_%.3d_0;", i);
 					fprintf(fd, " /* '.' */\n");
 					Dested(i);
@@ -375,7 +388,7 @@
 				break;
 			}
 			i = e->nxt?e->nxt->Seqno:0;
-			if (e->nxt && e->nxt->status & DONE2 && !LastGoto)
+			if (e->nxt && (e->nxt->status & DONE2) && !LastGoto)
 			{	fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
 				fprintf(fd, "/* ';' */\n");
 				Dested(i);
--- a/sys/src/cmd/spin/flow.c
+++ b/sys/src/cmd/spin/flow.c
@@ -1,24 +1,24 @@
 /***** spin: flow.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include "y.tab.h"
 
 extern Symbol	*Fname;
-extern int	nr_errs, lineno, verbose;
-extern short	has_unless, has_badelse;
+extern int	nr_errs, lineno, verbose, in_for, old_scope_rules, s_trail;
+extern short	has_unless, has_badelse, has_xu;
+extern char CurScope[MAXSCOPESZ];
 
 Element *Al_El = ZE;
 Label	*labtab = (Label *) 0;
-int	Unique=0, Elcnt=0, DstepStart = -1;
+int	Unique = 0, Elcnt = 0, DstepStart = -1;
+int	initialization_ok = 1;
+short	has_accept;
 
 static Lbreak	*breakstack = (Lbreak *) 0;
 static Lextok	*innermost;
@@ -37,10 +37,16 @@
 open_seq(int top)
 {	SeqList *t;
 	Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
+	s->minel = -1;
 
 	t = seqlist(s, cur_s);
 	cur_s = t;
-	if (top) Elcnt = 1;
+	if (top)
+	{	Elcnt = 1;
+		initialization_ok = 1;
+	} else
+	{	initialization_ok = 0;
+	}
 }
 
 void
@@ -84,6 +90,7 @@
 	&&  a->indstep != b->indstep)
 	{	lineno = a->ln;
 		Fname  = a->fn;
+		if (!s_trail)
 		fatal("jump into d_step sequence", (char *) 0);
 	}
 }
@@ -113,8 +120,8 @@
 			&&  n->ntyp != PRINT
 			&&  n->ntyp != PRINTM)
 			{	if (verbose&32)
-					printf("spin: line %d %s, redundant skip\n",
-						n->ln, n->fn->name);
+					printf("spin: %s:%d, redundant skip\n",
+						n->fn->name, n->ln);
 				if (e != s->frst
 				&&  e != s->last
 				&&  e != s->extent)
@@ -147,7 +154,11 @@
 {	Sequence *s = cur_s->this;
 	Symbol *z;
 
-	if (nottop > 0 && (z = has_lab(s->frst, 0)))
+	if (nottop == 0)	/* end of proctype body */
+	{	initialization_ok = 1;
+	}
+
+	if (nottop > 0 && s->frst && (z = has_lab(s->frst, 0)))
 	{	printf("error: (%s:%d) label %s placed incorrectly\n",
 			(s->frst->n)?s->frst->n->fn->name:"-",
 			(s->frst->n)?s->frst->n->ln:0,
@@ -183,12 +194,12 @@
 			printf("\"Label: { statement ... }\"\n");
 			break;
 		case 6:
-			printf("=====>instead of\n");
+			printf("=====> instead of\n");
 			printf("	do (or if)\n");
 			printf("	:: ...\n");
 			printf("	:: Label: statement\n");
 			printf("	od (of fi)\n");
-			printf("=====>always use\n");
+			printf("=====> use\n");
 			printf("Label:	do (or if)\n");
 			printf("	:: ...\n");
 			printf("	:: statement\n");
@@ -198,8 +209,9 @@
 			printf("cannot happen - labels\n");
 			break;
 		}
-		alldone(1);
-	}
+		if (nottop != 6)
+		{	alldone(1);
+	}	}
 
 	if (nottop == 4
 	&& !Rjumpslocal(s->frst, s->last))
@@ -217,13 +229,14 @@
 do_unless(Lextok *No, Lextok *Es)
 {	SeqList *Sl;
 	Lextok *Re = nn(ZN, UNLESS, ZN, ZN);
+
 	Re->ln = No->ln;
 	Re->fn = No->fn;
-
 	has_unless++;
+
 	if (Es->ntyp == NON_ATOMIC)
-		Sl = Es->sl;
-	else
+	{	Sl = Es->sl;
+	} else
 	{	open_seq(0); add_seq(Es);
 		Sl = seqlist(close_seq(1), 0);
 	}
@@ -348,6 +361,31 @@
 	}	}
 }
 
+void
+popbreak(void)
+{
+	if (!breakstack)
+		fatal("cannot happen, breakstack", (char *) 0);
+
+	breakstack = breakstack->nxt;	/* pop stack */
+}
+
+static Lbreak *ob = (Lbreak *) 0;
+
+void
+safe_break(void)
+{
+	ob = breakstack;
+	popbreak();
+}
+
+void
+restore_break(void)
+{
+	breakstack = ob;
+	ob = (Lbreak *) 0;
+}
+
 static Element *
 if_seq(Lextok *n)
 {	int	tok = n->ntyp;
@@ -388,8 +426,13 @@
 	&&  prev_z->this->frst->n->ntyp == ELSE)
 	{	prev_z->this->frst->n->val = 1;
 		has_badelse++;
-		non_fatal("dubious use of 'else' combined with i/o,",
-			(char *)0);
+		if (has_xu)
+		{	fatal("invalid use of 'else' combined with i/o and xr/xs assertions,",
+				(char *)0);
+		} else
+		{	non_fatal("dubious use of 'else' combined with i/o,",
+				(char *)0);
+		}
 		nr_errs--;
 	}
 
@@ -396,13 +439,13 @@
 	e->n = nn(n, tok, ZN, ZN);
 	e->n->sl = s;			/* preserve as info only */
 	e->sub = s;
-	for (z = s; z; prev_z = z, z = z->nxt)
+	for (z = s; z; z = z->nxt)
 		add_el(t, z->this);	/* append target */
 	if (tok == DO)
 	{	add_el(t, cur_s->this); /* target upfront */
 		t = new_el(nn(n, BREAK, ZN, ZN)); /* break target */
 		set_lab(break_dest(), t);	/* new exit  */
-		breakstack = breakstack->nxt;	/* pop stack */
+		popbreak();
 	}
 	add_el(e, cur_s->this);
 	add_el(t, cur_s->this);
@@ -563,33 +606,86 @@
 void
 set_lab(Symbol *s, Element *e)
 {	Label *l; extern Symbol *context;
+	int cur_uiid = is_inline();
 
 	if (!s) return;
+
 	for (l = labtab; l; l = l->nxt)
-		if (l->s == s && l->c == context)
+	{	if (strcmp(l->s->name, s->name) == 0
+		&&  l->c == context
+		&&  (old_scope_rules || strcmp((const char *) s->bscp, (const char *) l->s->bscp) == 0)
+		&&  l->uiid == cur_uiid)
 		{	non_fatal("label %s redeclared", s->name);
 			break;
-		}
+	}	}
+
+	if (strncmp(s->name, "accept", 6) == 0
+	&&  strncmp(s->name, "accept_all", 10) != 0)
+	{	has_accept = 1;
+	}
+
 	l = (Label *) emalloc(sizeof(Label));
 	l->s = s;
 	l->c = context;
 	l->e = e;
+	l->uiid = cur_uiid;
 	l->nxt = labtab;
 	labtab = l;
 }
 
+static Label *
+get_labspec(Lextok *n)
+{	Symbol *s = n->sym;
+	Label  *l, *anymatch = (Label *) 0;
+	int ln;
+	/*
+	 * try to find a label with the same inline id (uiid)
+	 * but if it doesn't exist, return any other match
+	 * within the same scope
+	 */
+	for (l = labtab; l; l = l->nxt)
+	{	if (strcmp(l->s->name, s->name) == 0	/* labelname matches */
+		&&  s->context == l->s->context)	/* same scope */
+		{
+#if 0
+			if (anymatch && n->uiid == anymatch->uiid)
+			{	if (0) non_fatal("label %s re-declared", s->name);
+			}
+			if (0)
+			{	printf("Label %s uiid now::then %d :: %d bcsp %s :: %s\n",
+					s->name, n->uiid, l->uiid, s->bscp, l->s->bscp);
+				printf("get_labspec match on %s %s (bscp goto %s - label %s)\n",
+					s->name, s->context->name,  s->bscp, l->s->bscp);
+			}
+#endif
+			/* same block scope */
+			if (strcmp((const char *) s->bscp, (const char *) l->s->bscp) == 0)
+			{	return l;	/* definite match */
+			}
+			/* higher block scope */
+			ln = strlen((const char *) l->s->bscp);
+			if (strncmp((const char *) s->bscp, (const char *) l->s->bscp, ln) == 0)
+			{	anymatch = l;	/* possible match */
+			} else if (!anymatch)
+			{	anymatch = l;	/* somewhere else in same context */
+	}	}	}
+
+	return anymatch; /* return best match */
+}
+
 Element *
 get_lab(Lextok *n, int md)
-{	Label *l;
-	Symbol *s = n->sym;
+{	Label *l = get_labspec(n);
 
-	for (l = labtab; l; l = l->nxt)
-		if (s == l->s)
-			return (l->e);
+	if (l != (Label *) 0)
+	{	return (l->e);
+	}
 
-	lineno = n->ln;
-	Fname = n->fn;
-	if (md) fatal("undefined label %s", s->name);
+	if (md)
+	{	lineno = n->ln;
+		Fname  = n->fn;
+		fatal("undefined label %s", n->sym->name);
+	}
 	return ZE;
 }
 
@@ -670,21 +766,46 @@
 	}
 	l->e->status |= CHECK2;	/* treat as if global */
 	if (l->e->status & (ATOM | L_ATOM | D_ATOM))
-	{	non_fatal("cannot reference label inside atomic or d_step (%s)",
-			c->name);
+	{	printf("spin: %s:%d, warning, reference to label ",
+			Fname->name, lineno);
+		printf("from inside atomic or d_step (%s)\n", c->name);
 	}
 }
 
 int
 find_lab(Symbol *s, Symbol *c, int markit)
-{	Label *l;
+{	Label *l, *pm = (Label *) 0, *apm = (Label *) 0;
+	int ln;
 
+	/* generally called for remote references in never claims */
 	for (l = labtab; l; l = l->nxt)
-	{	if (strcmp(s->name, l->s->name) == 0
+	{
+		if (strcmp(s->name, l->s->name) == 0
 		&&  strcmp(c->name, l->c->name) == 0)
-		{	l->visible |= markit;
-			return (l->e->seqno);
-	}	}
+		{	ln = strlen((const char *) l->s->bscp);
+			if (0)
+			{	printf("want '%s' in context '%s', scope ref '%s' - label '%s'\n",
+					s->name, c->name, s->bscp, l->s->bscp);
+			}
+			/* same or higher block scope */
+			if (strcmp((const char *)  s->bscp, (const char *) l->s->bscp) == 0)
+			{	pm = l;	/* definite match */
+				break;
+			}
+			if (strncmp((const char *) s->bscp, (const char *) l->s->bscp, ln) == 0)
+			{	pm = l;	/* possible match */
+			} else
+			{	apm = l;	/* remote */
+	}	}	}
+
+	if (pm)
+	{	pm->visible |= markit;
+		return pm->e->seqno;
+	}
+	if (apm)
+	{	apm->visible |= markit;
+		return apm->e->seqno;
+	} /* else printf("Not Found\n"); */
 	return 0;
 }
 
@@ -735,6 +856,226 @@
 	}
 }
 
+#if 0
+static int depth = 0;
+void dump_sym(Symbol *, char *);
+
+void
+dump_lex(Lextok *t, char *s)
+{	int i;
+
+	depth++;
+	printf(s);
+	for (i = 0; i < depth; i++)
+		printf("\t");
+	explain(t->ntyp);
+	if (t->ntyp == NAME) printf(" %s ", t->sym->name);
+	if (t->ntyp == CONST) printf(" %d ", t->val);
+	if (t->ntyp == STRUCT)
+	{	dump_sym(t->sym, "\n:Z:");
+	}
+	if (t->lft)
+	{	dump_lex(t->lft, "\nL");
+	}
+	if (t->rgt)
+	{	dump_lex(t->rgt, "\nR");
+	}	
+	depth--;
+}
+void
+dump_sym(Symbol *z, char *s)
+{	int i;
+	char txt[64];
+	depth++;
+	printf(s);
+	for (i = 0; i < depth; i++)
+		printf("\t");
+
+	if (z->type == CHAN)
+	{	if (z->ini && z->ini->rgt && z->ini->rgt->sym)
+		{	/* dump_sym(z->ini->rgt->sym, "\n:I:"); -- could also be longer list */
+			if (z->ini->rgt->rgt
+			|| !z->ini->rgt->sym)
+			fatal("chan %s in for should have only one field (a typedef)", z->name);
+			printf(" -- %s %p -- ", z->ini->rgt->sym->name, z->ini->rgt->sym);
+		}
+	} else if (z->type == STRUCT)
+	{	if (z->Snm)
+			printf(" == %s %p == ", z->Snm->name, z->Snm);
+		else
+		{	if (z->Slst)
+				dump_lex(z->Slst, "\n:X:");
+			if (z->ini)
+				dump_lex(z->ini, "\n:I:");
+		}
+	}
+	depth--;
+
+}
+#endif
+
+int
+match_struct(Symbol *s, Symbol *t)
+{
+	if (!t
+	||  !t->ini
+	||  !t->ini->rgt
+	||  !t->ini->rgt->sym
+	||   t->ini->rgt->rgt)
+	{	fatal("chan %s in for should have only one field (a typedef)", t?t->name:"--");
+	}
+	/* we already know that s is a STRUCT */
+	if (0)
+	{	printf("index type %s %p ==\n", s->Snm->name, s->Snm);
+		printf("chan type  %s %p --\n\n", t->ini->rgt->sym->name, t->ini->rgt->sym);
+	}
+
+	return (s->Snm == t->ini->rgt->sym);
+}
+
+void
+valid_name(Lextok *a3, Lextok *a5, Lextok *a8, char *tp)
+{
+	if (a3->ntyp != NAME)
+	{	fatal("%s ( .name : from .. to ) { ... }", tp);
+	}
+	if (a3->sym->type == CHAN
+	||  a3->sym->type == STRUCT
+	||  a3->sym->isarray != 0)
+	{	fatal("bad index in for-construct %s", a3->sym->name);
+	}
+	if (a5->ntyp == CONST && a8->ntyp == CONST && a5->val > a8->val)
+	{	non_fatal("start value for %s exceeds end-value", a3->sym->name);
+	}
+}
+
+void
+for_setup(Lextok *a3, Lextok *a5, Lextok *a8)
+{	/* for ( a3 : a5 .. a8 ) */
+
+	valid_name(a3, a5, a8, "for");
+	/* a5->ntyp = a8->ntyp = CONST; */
+	add_seq(nn(a3, ASGN, a3, a5));	/* start value */
+	open_seq(0);
+	add_seq(nn(ZN, 'c', nn(a3, LE, a3, a8), ZN));	/* condition */
+}
+
+Lextok *
+for_index(Lextok *a3, Lextok *a5)
+{	Lextok *z0, *z1, *z2, *z3;
+	Symbol *tmp_cnt;
+	char tmp_nm[MAXSCOPESZ+16];
+	/* for ( a3 in a5 ) { ... } */
+
+	if (a3->ntyp != NAME)
+	{	fatal("for ( .name in name ) { ... }", (char *) 0);
+	}
+
+	if (a5->ntyp != NAME)
+	{	fatal("for ( %s in .name ) { ... }", a3->sym->name);
+	}
+
+	if (a3->sym->type == STRUCT)
+	{	if (a5->sym->type != CHAN)
+		{	fatal("for ( %s in .channel_name ) { ... }",
+				a3->sym->name);
+		}
+		z0 = a5->sym->ini;
+		if (!z0
+		|| z0->val <= 0
+		|| z0->rgt->ntyp != STRUCT
+		|| z0->rgt->rgt != NULL)
+		{	fatal("bad channel type %s in for", a5->sym->name);
+		}
+
+		if (!match_struct(a3->sym, a5->sym))
+		{	fatal("type of %s does not match chan", a3->sym->name);
+		}
+
+		z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0;
+		z2 = nn(a5, LEN, a5, ZN);
+
+		sprintf(tmp_nm, "_f0r_t3mp%s", CurScope); /* make sure it's unique */
+		tmp_cnt = lookup(tmp_nm);
+		if (z0->val > 255)			/* check nr of slots, i.e. max length */
+		{	tmp_cnt->type = SHORT;	/* should be rare */
+		} else
+		{	tmp_cnt->type = BYTE;
+		}
+		z3 = nn(ZN, NAME, ZN, ZN);
+		z3->sym = tmp_cnt;
+
+		add_seq(nn(z3, ASGN, z3, z1));	/* start value 0 */
+
+		open_seq(0);
+
+		add_seq(nn(ZN, 'c', nn(z3, LT, z3, z2), ZN));	/* condition */
+
+		/* retrieve  message from the right slot -- for now: rotate contents */
+		in_for = 0;
+		add_seq(nn(a5, 'r', a5, expand(a3, 1)));	/* receive */
+		add_seq(nn(a5, 's', a5, expand(a3, 1)));	/* put back in to rotate */
+		in_for = 1;
+		return z3;
+	} else
+	{	if (a5->sym->isarray == 0
+		||  a5->sym->nel <= 0)
+		{	fatal("bad arrayname %s", a5->sym->name);
+		}
+		z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0;
+		z2 = nn(ZN, CONST, ZN, ZN); z2->val = a5->sym->nel - 1;
+		for_setup(a3, z1, z2);
+		return a3;
+	}
+}
+
+Lextok *
+for_body(Lextok *a3, int with_else)
+{	Lextok *t1, *t2, *t0, *rv;
+
+	rv = nn(ZN, CONST, ZN, ZN); rv->val = 1;
+	rv = nn(ZN,  '+', a3, rv);
+	rv = nn(a3, ASGN, a3, rv);
+	add_seq(rv);	/* initial increment */
+
+	/* completed loop body, main sequence */
+	t1 = nn(ZN, 0, ZN, ZN);
+	t1->sq = close_seq(8);
+
+	open_seq(0);		/* add else -> break sequence */
+	if (with_else)
+	{	add_seq(nn(ZN, ELSE, ZN, ZN));
+	}
+	t2 = nn(ZN, GOTO, ZN, ZN);
+	t2->sym = break_dest();
+	add_seq(t2);
+	t2 = nn(ZN, 0, ZN, ZN);
+	t2->sq = close_seq(9);
+
+	t0 = nn(ZN, 0, ZN, ZN);
+	t0->sl = seqlist(t2->sq, seqlist(t1->sq, 0));
+
+	rv = nn(ZN, DO, ZN, ZN);
+	rv->sl = t0->sl;
+
+	return rv;
+}
+
+Lextok *
+sel_index(Lextok *a3, Lextok *a5, Lextok *a7)
+{	/* select ( a3 : a5 .. a7 ) */
+
+	valid_name(a3, a5, a7, "select");
+	/* a5->ntyp = a7->ntyp = CONST; */
+
+	add_seq(nn(a3, ASGN, a3, a5));	/* start value */
+	open_seq(0);
+	add_seq(nn(ZN, 'c', nn(a3, LT, a3, a7), ZN));	/* condition */
+
+	pushbreak(); /* new 6.2.1 */
+	return for_body(a3, 0);	/* no else, just a non-deterministic break */
+}
+
 static void
 walk_atomic(Element *a, Element *b, int added)
 {	Element *f; Symbol *ofn; int oln;
@@ -747,8 +1088,8 @@
 		switch (f->n->ntyp) {
 		case ATOMIC:
 			if (verbose&32)
-			  printf("spin: warning, line %3d %s, atomic inside %s (ignored)\n",
-			  f->n->ln, f->n->fn->name, (added)?"d_step":"atomic");
+			  printf("spin: %s:%d, warning, atomic inside %s (ignored)\n",
+			  f->n->fn->name, f->n->ln, (added)?"d_step":"atomic");
 			goto mknonat;
 		case D_STEP:
 			if (!(verbose&32))
@@ -755,8 +1096,8 @@
 			{	if (added) goto mknonat;
 				break;
 			}
-			printf("spin: warning, line %3d %s, d_step inside ",
-			 f->n->ln, f->n->fn->name);
+			printf("spin: %s:%d, warning, d_step inside ",
+			 f->n->fn->name, f->n->ln);
 			if (added)
 			{	printf("d_step (ignored)\n");
 				goto mknonat;
@@ -770,8 +1111,8 @@
 			break;
 		case UNLESS:
 			if (added)
-			{ printf("spin: error, line %3d %s, unless in d_step (ignored)\n",
-			 	 f->n->ln, f->n->fn->name);
+			{ printf("spin: error, %s:%d, unless in d_step (ignored)\n",
+			 	 f->n->fn->name, f->n->ln);
 			}
 		}
 		for (h = f->sub; h; h = h->nxt)
@@ -789,6 +1130,15 @@
 
 	for (l = labtab; l; l = l->nxt)
 		if (l->c != 0 && l->s->name[0] != ':')
-		printf("label	%s	%d	<%s>\n",
-		l->s->name, l->e->seqno, l->c->name);
+		{	printf("label	%s	%d	",
+				l->s->name, l->e->seqno);
+			if (l->uiid == 0)
+				printf("<%s>", l->c->name);
+			else
+				printf("<%s i%d>", l->c->name, l->uiid);
+			if (!old_scope_rules)
+			{	printf("\t{scope %s}", l->s->bscp);
+			}
+			printf("\n");
+		}
 }
--- a/sys/src/cmd/spin/guided.c
+++ b/sys/src/cmd/spin/guided.c
@@ -1,17 +1,15 @@
 /***** spin: guided.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <limits.h>
 #include "y.tab.h"
 
 extern RunList	*run, *X;
@@ -19,8 +17,9 @@
 extern Symbol	*Fname, *oFname;
 extern int	verbose, lineno, xspin, jumpsteps, depth, merger, cutoff;
 extern int	nproc, nstop, Tval, ntrail, columns;
-extern short	Have_claim, Skip_claim;
+extern short	Have_claim, Skip_claim, has_code;
 extern void ana_src(int, int);
+extern char	**trailfilename;
 
 int	TstOnly = 0, pno;
 
@@ -73,6 +72,53 @@
 	return (!Have_claim || !X || X->pid != 0);
 }
 
+int globmin = INT_MAX;
+int globmax = 0;
+
+int
+find_min(Sequence *s)
+{	SeqList *l;
+	Element *e;
+
+	if (s->minel < 0)
+	{	s->minel = INT_MAX;
+		for (e = s->frst; e; e = e->nxt)
+		{	if (e->status & 512)
+			{	continue;
+			}
+			e->status |= 512;
+
+			if (e->n->ntyp == ATOMIC
+			||  e->n->ntyp == NON_ATOMIC
+			||  e->n->ntyp == D_STEP)
+			{	int n = find_min(e->n->sl->this);
+				if (n < s->minel)
+				{	s->minel = n;
+				}
+			} else if (e->Seqno < s->minel)
+			{	s->minel = e->Seqno;
+			}
+			for (l = e->sub; l; l = l->nxt)
+			{	int n = find_min(l->this);
+				if (n < s->minel)
+				{	s->minel = n;
+		}	}	}
+	}
+	if (s->minel < globmin)
+	{	globmin = s->minel;
+	}
+	return s->minel;
+}
+
+int
+find_max(Sequence *s)
+{
+	if (s->last->Seqno > globmax)
+	{	globmax = s->last->Seqno;
+	}
+	return s->last->Seqno;
+}
+
 void
 match_trail(void)
 {	int i, a, nst;
@@ -79,6 +125,17 @@
 	Element *dothis;
 	char snap[512], *q;
 
+	if (has_code)
+	{	printf("spin: important:\n");
+		printf("  =======================================warning====\n");
+		printf("  this model contains embedded c code statements\n");
+		printf("  these statements will not be executed when the trail\n");
+		printf("  is replayed in this way -- they are just printed,\n");
+		printf("  which will likely lead to inaccurate variable values.\n");
+		printf("  for an accurate replay use: ./pan -r\n");
+		printf("  =======================================warning====\n\n");
+	}
+
 	/*
 	 * if source model name is leader.pml
 	 * look for the trail file under these names:
@@ -88,10 +145,18 @@
 	 *	leader.tra
 	 */
 
-	if (ntrail)
-		sprintf(snap, "%s%d.trail", oFname->name, ntrail);
-	else
-		sprintf(snap, "%s.trail", oFname->name);
+	if (trailfilename)
+	{	if (strlen(*trailfilename) < sizeof(snap))
+		{	strcpy(snap, (const char *) *trailfilename);
+		} else
+		{	fatal("filename %s too long", *trailfilename);
+		}
+	} else
+	{	if (ntrail)
+			sprintf(snap, "%s%d.trail", oFname->name, ntrail);
+		else
+			sprintf(snap, "%s.trail", oFname->name);
+	}
 
 	if ((fd = fopen(snap, "r")) == NULL)
 	{	snap[strlen(snap)-2] = '\0';	/* .tra */
@@ -118,9 +183,9 @@
 	}	}
 okay:		
 	if (xspin == 0 && newer(oFname->name, snap))
-	printf("spin: warning, \"%s\" is newer than %s\n",
-		oFname->name, snap);
-
+	{	printf("spin: warning, \"%s\" is newer than %s\n",
+			oFname->name, snap);
+	}
 	Tval = 1;
 
 	/*
@@ -132,10 +197,23 @@
 	hookup();
 
 	while (fscanf(fd, "%d:%d:%d\n", &depth, &pno, &nst) == 3)
-	{	if (depth == -2) { start_claim(pno); continue; }
-		if (depth == -4) { merger = 1; ana_src(0, 1); continue; }
-		if (depth == -1)
+	{	if (depth == -2)
 		{	if (verbose)
+			{	printf("starting claim %d\n", pno);
+			}
+			start_claim(pno);
+			continue;
+		}
+		if (depth == -4)
+		{	if (verbose)
+			{	printf("using statement merging\n");
+			}
+			merger = 1;
+			ana_src(0, 1);
+			continue;
+		}
+		if (depth == -1)
+		{	if (1 || verbose)
 			{	if (columns == 2)
 				dotag(stdout, " CYCLE>\n");
 				else
@@ -188,16 +266,50 @@
 				pno - Have_claim, i, nst, dothis->n->ntyp);
 			lost_trail();
 		}
+
+		if (0 && !xspin && (verbose&32))
+		{	printf("step %d i=%d pno %d stmnt %d\n", depth, i, pno, nst);
+		}
+
 		for (X = run; X; X = X->nxt)
 		{	if (--i == pno)
 				break;
 		}
+
 		if (!X)
-		{	printf("%3d: no process %d ", depth, pno - Have_claim);
-			printf("(state %d)\n", nst);
-			lost_trail();
+		{	if (verbose&32)
+			{	printf("%3d: no process %d (stmnt %d)\n", depth, pno - Have_claim, nst);
+				printf(" max %d (%d - %d + %d) claim %d ",
+					nproc - nstop + Skip_claim,
+					nproc, nstop, Skip_claim, Have_claim);
+				printf("active processes:\n");
+				for (X = run; X; X = X->nxt)
+				{	printf("\tpid %d\tproctype %s\n", X->pid, X->n->name);
+				}
+				printf("\n");
+				continue;	
+			} else
+			{	printf("%3d:\tproc  %d (?) ", depth, pno);
+				lost_trail();
+			}
+		} else
+		{	int min_seq = find_min(X->ps);
+			int max_seq = find_max(X->ps);
+
+
+			if (nst < min_seq || nst > max_seq)
+			{	printf("%3d: error: invalid statement", depth);
+				if (verbose&32)
+				{	printf(": pid %d:%d (%s:%d:%d) stmnt %d (valid range %d .. %d)",
+					pno, X->pid, X->n->name, X->tn, X->b, nst, min_seq, max_seq);
+				}
+				printf("\n");
+				continue;
+				/* lost_trail(); */
+			}
+			X->pc  = dothis;
 		}
-		X->pc  = dothis;
+
 		lineno = dothis->n->ln;
 		Fname  = dothis->n->fn;
 
@@ -271,7 +383,7 @@
 		}	}
 
 		if (Have_claim && X && X->pid == 0
-		&&  dothis && dothis->n
+		&&  dothis->n
 		&&  lastclaim != dothis->n->ln)
 		{	lastclaim = dothis->n->ln;
 			if (columns == 2)
--- a/sys/src/cmd/spin/main.c
+++ b/sys/src/cmd/spin/main.c
@@ -1,25 +1,23 @@
 /***** spin: main.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include <stdlib.h>
+#include <assert.h>
 #include "spin.h"
 #include "version.h"
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <signal.h>
-/* #include <malloc.h> */
 #include <time.h>
 #ifdef PC
-#include <io.h>
-extern int unlink(const char *);
+ #include <io.h>
 #else
-#include <unistd.h>
+ #include <unistd.h>
 #endif
 #include "y.tab.h"
 
@@ -29,7 +27,13 @@
 extern char	*claimproc;
 extern void	repro_src(void);
 extern void	qhide(int);
+extern char	CurScope[MAXSCOPESZ];
+extern short	has_provided, has_code, has_ltl, has_accept;
+extern int	realread, buzzed;
 
+static void	add_comptime(char *);
+static void	add_runtime(char *);
+
 Symbol	*Fname, *oFname;
 
 int	Etimeouts;	/* nr timeouts in program */
@@ -40,12 +44,19 @@
 int	no_print, no_wrapup, Caccess, limited_vis, like_java;
 int	separate;	/* separate compilation */
 int	export_ast;	/* pangen5.c */
-int	inlineonly;	/* show inlined code */
-int	seedy;		/* be verbose about chosen seed */
+int	norecompile;	/* main.c */
+int	old_scope_rules;	/* use pre 5.3.0 rules */
+int	old_priority_rules;	/* use pre 6.2.0 rules */
+int	product, Strict;
+short	replay;
 
-int	dataflow = 1, merger = 1, deadvar = 1, ccache = 1;
+int	merger = 1, deadvar = 1, implied_semis = 1;
+int	ccache = 0; /* oyvind teig: 5.2.0 case caching off by default */
 
-static int preprocessonly, SeedUsed;
+static int preprocessonly, SeedUsed, itsr, itsr_n;
+static int seedy;	/* be verbose about chosen seed */
+static int inlineonly;	/* show inlined code */
+static int dataflow = 1;
 
 #if 0
 meaning of flags on verbose:
@@ -61,99 +72,515 @@
 static char	Operator[] = "operator: ";
 static char	Keyword[]  = "keyword: ";
 static char	Function[] = "function-name: ";
-static char	**add_ltl  = (char **)0;
-static char	**ltl_file = (char **)0;
-static char	**nvr_file = (char **)0;
+static char	**add_ltl  = (char **) 0;
+static char	**ltl_file = (char **) 0;
+static char	**nvr_file = (char **) 0;
+static char	*ltl_claims = (char *) 0;
+static char	*pan_runtime = "";
+static char	*pan_comptime = "";
+static char	formula[4096];
+static FILE	*fd_ltl = (FILE *) 0;
 static char	*PreArg[64];
 static int	PreCnt = 0;
 static char	out1[64];
-static void	explain(int);
 
-#ifndef CPP
-		/* OS2:		"spin -Picc -E/Pd+ -E/Q+"    */
-		/* Visual C++:	"spin -PCL  -E/E             */
-#ifdef PC
-#define CPP	"gcc -E -x c"	/* most systems have gcc anyway */
-				/* else use "cpp" */
-#else
-#ifdef SOLARIS
-#define CPP	"/usr/ccs/lib/cpp"
-#else
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
-#define CPP	"cpp"
-#else
-#define CPP	"/bin/cpp"	/* classic Unix systems */
-#endif
-#endif
-#endif
+char	**trailfilename;	/* new option 'k' */
 
-#endif
-static char	*PreProc = CPP;
+void	explain(int);
+
+#define CPP	"/bin/cpp"	/* sometimes: "/lib/cpp" */
+
+static char	PreProc[512];
 extern int	depth; /* at least some steps were made */
 
+int
+WhatSeed(void)
+{
+	return SeedUsed;
+}
+
 void
+final_fiddle(void)
+{	char *has_a, *has_l, *has_f;
+
+	/* no -a or -l but has_accept: add -a */
+	/* no -a or -l in pan_runtime: add -DSAFETY to pan_comptime */
+	/* -a or -l but no -f then add -DNOFAIR */
+
+	has_a = strstr(pan_runtime, "-a");
+	has_l = strstr(pan_runtime, "-l");
+	has_f = strstr(pan_runtime, "-f");
+
+	if (!has_l && !has_a && strstr(pan_comptime, "-DNP"))
+	{	add_runtime("-l");
+		has_l = strstr(pan_runtime, "-l");
+	}
+
+	if (!has_a && !has_l
+	&&  !strstr(pan_comptime, "-DSAFETY"))
+	{	if (has_accept
+		&& !strstr(pan_comptime, "-DBFS")
+		&& !strstr(pan_comptime, "-DNOCLAIM"))
+		{	add_runtime("-a");
+			has_a = pan_runtime;
+		} else
+		{	add_comptime("-DSAFETY");
+	}	}
+
+	if ((has_a || has_l) && !has_f
+	&&  !strstr(pan_comptime, "-DNOFAIR"))
+	{	add_comptime("-DNOFAIR");
+	}
+}
+
+static int
+change_param(char *t, char *what, int range, int bottom)
+{	char *ptr;
+	int v;
+
+	assert(range < 1000 && range > 0);
+	if ((ptr = strstr(t, what)) != NULL)
+	{	ptr += strlen(what);
+		if (!isdigit((int) *ptr))
+		{	return 0;
+		}
+		v = atoi(ptr) + 1;	/* was: v = (atoi(ptr)+1)%range */
+		if (v >= range)
+		{	v = bottom;
+		}
+		if (v >= 100)
+		{	*ptr++ = '0' + (v/100); v %= 100;
+			*ptr++ = '0' + (v/10);
+			*ptr   = '0' + (v%10);
+		} else if (v >= 10)
+		{	*ptr++ = '0' + (v/10);
+			*ptr++ = '0' + (v%10);
+			*ptr   = ' ';
+		} else
+		{	*ptr++ = '0' + v;
+			*ptr++ = ' ';
+			*ptr   = ' ';
+	}	}
+	return 1;
+}
+
+static void
+change_rs(char *t)
+{	char *ptr;
+	int cnt = 0;
+	long v;
+
+	if ((ptr = strstr(t, "-RS")) != NULL)
+	{	ptr += 3;
+		/* room for at least 10 digits */
+		v = Rand()%1000000000L;
+		while (v/10 > 0)
+		{	*ptr++ = '0' + v%10;
+			v /= 10;
+			cnt++;
+		}
+		*ptr++ = '0' + v;
+		cnt++;
+		while (cnt++ < 10)
+		{	*ptr++ = ' ';
+	}	}
+}
+
+int
+omit_str(char *in, char *s)
+{	char *ptr = strstr(in, s);
+	int i, nr = -1;
+
+	if (ptr)
+	{	for (i = 0; i < (int) strlen(s); i++)
+		{	*ptr++ = ' ';
+		}
+		if (isdigit((int) *ptr))
+		{	nr = atoi(ptr);
+			while (isdigit((int) *ptr))
+			{	*ptr++ = ' ';
+	}	}	}
+	return nr;
+}
+
+void
+string_trim(char *t)
+{	int n = strlen(t) - 1;
+
+	while (n > 0 && t[n] == ' ')
+	{	t[n--] = '\0';
+	}
+}
+
+int
+e_system(int v, const char *s)
+{	static int count = 1;
+	/* v == 0 : checks to find non-linked version of gcc */
+	/* v == 1 : all other commands */
+	/* v == 2 : preprocessing the promela input */
+
+	if (v == 1)
+	{	if (verbose&(32|64))	/* -v or -w */
+		{	printf("cmd%02d: %s\n", count++, s);
+			fflush(stdout);
+		}
+		if (verbose&64)		/* only -w */
+		{	return 0;	/* suppress the call to system(s) */
+	}	}
+	return system(s);
+}
+
+void
 alldone(int estatus)
-{
-	if (preprocessonly == 0
-	&&  strlen(out1) > 0)
-		(void) unlink((const char *)out1);
+{	char *ptr;
+#if defined(WIN32) || defined(WIN64)
+	struct _stat x;
+#else
+	struct stat x;
+#endif
+	if (preprocessonly == 0 &&  strlen(out1) > 0)
+	{	(void) unlink((const char *) out1);
+	}
 
-	if (seedy && !analyze && !export_ast
+	(void) unlink(TMP_FILE1);
+	(void) unlink(TMP_FILE2);
+
+	if (!buzzed && seedy && !analyze && !export_ast
 	&& !s_trail && !preprocessonly && depth > 0)
-		printf("seed used: %d\n", SeedUsed);
+	{	printf("seed used: %d\n", SeedUsed);
+	}
 
-	if (xspin && (analyze || s_trail))
+	if (!buzzed && xspin && (analyze || s_trail))
 	{	if (estatus)
-			printf("spin: %d error(s) - aborting\n",
-			estatus);
-		else
-			printf("Exit-Status 0\n");
+		{	printf("spin: %d error(s) - aborting\n",
+				estatus);
+		} else
+		{	printf("Exit-Status 0\n");
+	}	}
+
+	if (buzzed && replay && !has_code && !estatus)
+	{	extern QH *qh;
+		QH *j;
+		int i;
+		char *tmp = (char *) emalloc(strlen("spin -t") +
+				strlen(pan_runtime) + strlen(Fname->name) + 8);
+		pan_runtime = (char *) emalloc(2048);	/* more than enough */
+		sprintf(pan_runtime, "-n%d ", SeedUsed);
+		if (jumpsteps)
+		{	sprintf(&pan_runtime[strlen(pan_runtime)], "-j%d ", jumpsteps);
+		}
+		if (trailfilename)
+		{	sprintf(&pan_runtime[strlen(pan_runtime)], "-k%s ", *trailfilename);
+		}
+		if (cutoff)
+		{	sprintf(&pan_runtime[strlen(pan_runtime)], "-u%d ", cutoff);
+		}
+		for (i = 1; i <= PreCnt; i++)
+		{	strcat(pan_runtime, PreArg[i]);
+			strcat(pan_runtime, " ");
+		}
+		for (j = qh; j; j = j->nxt)
+		{	sprintf(&pan_runtime[strlen(pan_runtime)], "-q%d ", j->n);
+		}
+		if (strcmp(PreProc, CPP) != 0)
+		{	sprintf(&pan_runtime[strlen(pan_runtime)], "\"-P%s\" ", PreProc);
+		}
+		/* -oN options 1..5 are ignored in simulations */
+		if (old_priority_rules) strcat(pan_runtime, "-o6 ");
+		if (!implied_semis)  strcat(pan_runtime, "-o7 ");
+		if (no_print)        strcat(pan_runtime, "-b ");
+		if (no_wrapup)       strcat(pan_runtime, "-B ");
+		if (columns == 1)    strcat(pan_runtime, "-c ");
+		if (columns == 2)    strcat(pan_runtime, "-M ");
+		if (seedy == 1)      strcat(pan_runtime, "-h ");
+		if (like_java == 1)  strcat(pan_runtime, "-J ");
+		if (old_scope_rules) strcat(pan_runtime, "-O ");
+		if (notabs)          strcat(pan_runtime, "-T ");
+		if (verbose&1)       strcat(pan_runtime, "-g ");
+		if (verbose&2)       strcat(pan_runtime, "-l ");
+		if (verbose&4)       strcat(pan_runtime, "-p ");
+		if (verbose&8)       strcat(pan_runtime, "-r ");
+		if (verbose&16)      strcat(pan_runtime, "-s ");
+		if (verbose&32)      strcat(pan_runtime, "-v ");
+		if (verbose&64)      strcat(pan_runtime, "-w ");
+		if (m_loss)          strcat(pan_runtime, "-m ");
+		sprintf(tmp, "spin -t %s %s", pan_runtime, Fname->name);
+		estatus = e_system(1, tmp);	/* replay */
+		exit(estatus);	/* replay without c_code */
 	}
+
+	if (buzzed && (!replay || has_code) && !estatus)
+	{	char *tmp, *tmp2 = NULL, *P_X;
+		char *C_X = (buzzed == 2) ? "-O" : "";
+
+		if (replay && strlen(pan_comptime) == 0)
+		{
+#if defined(WIN32) || defined(WIN64)
+			P_X = "pan";
+#else
+			P_X = "./pan";
+#endif
+			if (stat(P_X, (struct stat *)&x) < 0)
+			{	goto recompile;	/* no executable pan for replay */
+			}
+			tmp = (char *) emalloc(8 + strlen(P_X) + strlen(pan_runtime) +4);
+			/* the final +4 is too allow adding " &" in some cases */
+			sprintf(tmp, "%s %s", P_X, pan_runtime);
+			goto runit;
+		}
+#if defined(WIN32) || defined(WIN64)
+		P_X = "-o pan pan.c && pan";
+#else
+		P_X = "-o pan pan.c && ./pan";
+#endif
+		/* swarm and biterate randomization additions */
+		if (!replay && itsr)	/* iterative search refinement */
+		{	if (!strstr(pan_comptime, "-DBITSTATE"))
+			{	add_comptime("-DBITSTATE");
+			}
+			if (!strstr(pan_comptime, "-DPUTPID"))
+			{	add_comptime("-DPUTPID");
+			}
+			if (!strstr(pan_comptime, "-DT_RAND")
+			&&  !strstr(pan_comptime, "-DT_REVERSE"))
+			{	add_runtime("-T0  ");	/* controls t_reverse */
+			}
+			if (!strstr(pan_runtime, "-P")	/* runtime flag */
+			||   pan_runtime[2] < '0'
+			||   pan_runtime[2] > '1') /* no -P0 or -P1 */
+			{	add_runtime("-P0  ");	/* controls p_reverse */
+			}
+			if (!strstr(pan_runtime, "-w"))
+			{	add_runtime("-w18 ");	/* -w18 = 256K */
+			} else
+			{	char nv[32];
+				int x;
+				x = omit_str(pan_runtime, "-w");
+				if (x >= 0)
+				{	sprintf(nv, "-w%d  ", x);
+					add_runtime(nv); /* added spaces */
+			}	}
+			if (!strstr(pan_runtime, "-h"))
+			{	add_runtime("-h0  ");	/* 0..499 */
+				/* leave 2 spaces for increments up to -h499 */
+			} else if (!strstr(pan_runtime, "-hash"))
+			{	char nv[32];
+				int x;
+				x = omit_str(pan_runtime, "-h");
+				if (x >= 0)
+				{	sprintf(nv, "-h%d  ", x%500);
+					add_runtime(nv); /* added spaces */
+			}	}
+			if (!strstr(pan_runtime, "-k"))
+			{	add_runtime("-k1  ");	/* 1..3 */
+			} else
+			{	char nv[32];
+				int x;
+				x = omit_str(pan_runtime, "-k");
+				if (x >= 0)
+				{	sprintf(nv, "-k%d  ", x%4);
+					add_runtime(nv); /* added spaces */
+			}	}
+			if (strstr(pan_runtime, "-p_rotate"))
+			{	char nv[32];
+				int x;
+				x = omit_str(pan_runtime, "-p_rotate");
+				if (x < 0)
+				{	x = 0;
+				}
+				sprintf(nv, "-p_rotate%d  ", x%256);
+				add_runtime(nv); /* added spaces */
+			} else if (strstr(pan_runtime, "-p_permute") == 0)
+			{	add_runtime("-p_rotate0  ");
+			}
+			if (strstr(pan_runtime, "-RS"))
+			{	(void) omit_str(pan_runtime, "-RS");
+			}
+			/* need room for at least 10 digits */
+			add_runtime("-RS1234567890 ");
+			change_rs(pan_runtime);
+		}
+recompile:
+		if (strstr(PreProc, "cpp"))	/* unix/linux */
+		{	strcpy(PreProc, "gcc");	/* need compiler */
+		} else if ((tmp = strstr(PreProc, "-E")) != NULL)
+		{	*tmp = '\0'; /* strip preprocessing flags */
+		}
+
+		final_fiddle();
+		tmp = (char *) emalloc(8 +	/* account for alignment */
+				strlen(PreProc) +
+				strlen(C_X) +
+				strlen(pan_comptime) +
+				strlen(P_X) +
+				strlen(pan_runtime) +
+				strlen(" -p_reverse & "));
+		tmp2 = tmp;
+
+		/* P_X ends with " && ./pan " */
+		sprintf(tmp, "%s %s %s %s %s",
+			PreProc, C_X, pan_comptime, P_X, pan_runtime);
+
+		if (!replay)
+		{	if (itsr < 0)		/* swarm only */
+			{	strcat(tmp, " &"); /* after ./pan */
+				itsr = -itsr;	/* now same as biterate */
+			}
+			/* do compilation first
+			 * split cc command from run command
+			 * leave cc in tmp, and set tmp2 to run
+			 */
+			if ((ptr = strstr(tmp, " && ")) != NULL)
+			{	tmp2 = ptr + 4;	/* first run */
+				*ptr = '\0';
+		}	}
+
+		if (has_ltl)
+		{	(void) unlink("_spin_nvr.tmp");
+		}
+		if (!norecompile)
+		{
+#ifdef PC
+		/* make sure that if compilation fails we do not continue */
+		(void) unlink("./pan.exe");
+#else
+		(void) unlink("./pan");
+#endif
+		}
+runit:
+		if (norecompile && tmp != tmp2)
+		{	estatus = 0;
+		} else
+		{	if (itsr > 0)	/* else it happens below */
+			{	estatus = e_system(1, tmp);	/* compile or run */
+		}	}
+		if (replay || estatus < 0)
+		{	goto skipahead;
+		}
+		/* !replay */
+		if (itsr == 0)			/* single run */
+		{	estatus = e_system(1, tmp2);
+		} else if (itsr > 0)	/* iterative search refinement */
+		{	int is_swarm = 0;
+			if (tmp2 != tmp)	/* swarm: did only compilation so far */
+			{	tmp = tmp2;	/* now we point to the run command */
+				estatus = e_system(1, tmp);	/* first run */
+			}
+			itsr--;			/* count down */
+
+			/* the following are added back randomly later */
+			(void) omit_str(tmp, "-p_reverse");	/* replaced by spaces */
+			(void) omit_str(tmp, "-p_normal");
+
+			if (strstr(tmp, " &") != NULL)
+			{	(void) omit_str(tmp, " &");
+				is_swarm = 1;
+			}
+
+			/* increase -w every itsr_n-th run */
+			if ((itsr_n > 0 && (itsr == 0 || (itsr%itsr_n) != 0))
+			||  (change_param(tmp, "-w", 36, 18) >= 0))	/* max 4G bit statespace */
+			{	(void) change_param(tmp, "-h", 500, 0);	/* hash function 0.499 */
+				(void) change_param(tmp, "-p_rotate", 256, 0); /* if defined */
+				(void) change_param(tmp, "-k", 4, 1);	/* nr bits per state 0->1,2,3 */
+				(void) change_param(tmp, "-T", 2, 0);	/* with or without t_reverse*/
+				(void) change_param(tmp, "-P", 2, 0);	/* -P 0..1 != p_reverse */
+				change_rs(tmp);			/* change random seed */
+				string_trim(tmp);
+				if (rand()%5 == 0)		/* 20% of all runs */
+				{	strcat(tmp, " -p_reverse ");
+					/* at end, so this overrides -p_rotateN, if there */
+					/* but -P0..1 disable this in 50% of the cases */
+					/* so its really activated in 10% of all runs */
+				} else if (rand()%6 == 0) /* override p_rotate and p_reverse */
+				{	strcat(tmp, " -p_normal ");
+				}
+				if (is_swarm)
+				{	strcat(tmp, " &");
+				}
+				goto runit;
+		}	}
+skipahead:
+		(void) unlink("pan.b");
+		(void) unlink("pan.c");
+		(void) unlink("pan.h");
+		(void) unlink("pan.m");
+		(void) unlink("pan.p");
+		(void) unlink("pan.t");
+	}
 	exit(estatus);
 }
+#if 0
+	-P0	normal active process creation
+	-P1	reversed order for *active* process creation != p_reverse
 
+	-T0	normal transition exploration
+	-T1	reversed order of transition exploration
+
+	-DP_RAND	(random starting point +- -DP_REVERSE)
+	-DPERMUTED	(also enables -p_rotateN and -p_reverse)
+	-DP_REVERSE	(same as -DPERMUTED with -p_reverse, but 7% faster)
+
+	-DT_RAND	(random starting point -- optionally with -T0..1)
+	-DT_REVERSE	(superseded by -T0..1 options)
+
+	 -hash generates new hash polynomial for -h0
+
+	permutation modes:
+	 -permuted (adds -DPERMUTED) -- this is also the default with -swarm
+	 -t_reverse (same as -T1)
+	 -p_reverse (similar to -P1)
+	 -p_rotateN
+	 -p_normal
+
+	less useful would be (since there is less non-determinism in transitions):
+		-t_rotateN -- a controlled version of -DT_RAND
+
+	compiling with -DPERMUTED enables a number of new runtime options,
+	that -swarmN,M will also exploit:
+		-p_permute (default)
+		-p_rotateN
+		-p_reverse
+#endif
+
 void
 preprocess(char *a, char *b, int a_tmp)
-{	char precmd[512], cmd[1024]; int i;
+{	char precmd[1024], cmd[2048];
+	int i;
 #ifdef PC
-	extern int try_zpp(char *, char *);
-	if (PreCnt == 0 && try_zpp(a, b)) goto out;
+	/* gcc is sometimes a symbolic link to gcc-4
+	   that does not work well in cygwin, so we try
+	   to use the actual executable that is used.
+	   the code below assumes we are on a cygwin-like system
+	 */
+	if (strncmp(PreProc, "gcc ", strlen("gcc ")) == 0)
+	{	if (e_system(0, "gcc-4 --version > pan.pre") == 0)
+		{	strcpy(PreProc, "gcc-4 -std=gnu99 -E -x c");
+		} else if (e_system(0, "gcc-3 --version > pan.pre") == 0)
+		{	strcpy(PreProc, "gcc-3 -std=gnu99 -E -x c");
+	}	}
 #endif
+
+	assert(strlen(PreProc) < sizeof(precmd));
 	strcpy(precmd, PreProc);
 	for (i = 1; i <= PreCnt; i++)
 	{	strcat(precmd, " ");
 		strcat(precmd, PreArg[i]);
 	}
+	if (strlen(precmd) > sizeof(precmd))
+	{	fprintf(stdout, "spin: too many -D args, aborting\n");
+		alldone(1);
+	}
 	sprintf(cmd, "%s %s > %s", precmd, a, b);
-	if (system((const char *)cmd))
+	if (e_system(2, (const char *)cmd))		/* preprocessing */
 	{	(void) unlink((const char *) b);
 		if (a_tmp) (void) unlink((const char *) a);
 		fprintf(stdout, "spin: preprocessing failed\n");	/* 4.1.2 was stderr */
 		alldone(1); /* no return, error exit */
 	}
-#ifdef PC
-out:
-#endif
 	if (a_tmp) (void) unlink((const char *) a);
 }
 
-FILE *
-cpyfile(char *src, char *tgt)
-{	FILE *inp, *out;
-	char buf[1024];
-
-	inp = fopen(src, "r");
-	out = fopen(tgt, "w");
-	if (!inp || !out)
-	{	printf("spin: cannot cp %s to %s\n", src, tgt);
-		alldone(1);
-	}
-	while (fgets(buf, 1024, inp))
-		fprintf(out, "%s", buf);
-	fclose(inp);
-	return out;
-}
-
 void
 usage(void)
 {
@@ -168,33 +595,73 @@
 	printf("\t-d produce symbol-table information\n");
 	printf("\t-Dyyy pass -Dyyy to the preprocessor\n");
 	printf("\t-Eyyy pass yyy to the preprocessor\n");
+	printf("\t-e compute synchronous product of multiple never claims (modified by -L)\n");
 	printf("\t-f \"..formula..\"  translate LTL ");
 	printf("into never claim\n");
-	printf("\t-F file  like -f, but with the LTL ");
-	printf("formula stored in a 1-line file\n");
+	printf("\t-F file  like -f, but with the LTL formula stored in a 1-line file\n");
 	printf("\t-g print all global variables\n");
-	printf("\t-h  at end of run, print value of seed for random nr generator used\n");
+	printf("\t-h at end of run, print value of seed for random nr generator used\n");
 	printf("\t-i interactive (random simulation)\n");
 	printf("\t-I show result of inlining and preprocessing\n");
 	printf("\t-J reverse eval order of nested unlesses\n");
 	printf("\t-jN skip the first N steps ");
 	printf("in simulation trail\n");
+	printf("\t-k fname use the trailfile stored in file fname, see also -t\n");
+	printf("\t-L when using -e, use strict language intersection\n");
 	printf("\t-l print all local variables\n");
-	printf("\t-M print msc-flow in Postscript\n");
+	printf("\t-M generate msc-flow in tcl/tk format\n");
 	printf("\t-m lose msgs sent to full queues\n");
-	printf("\t-N file use never claim stored in file\n");
+	printf("\t-N fname use never claim stored in file fname\n");
 	printf("\t-nN seed for random nr generator\n");
+	printf("\t-O use old scope rules (pre 5.3.0)\n");
 	printf("\t-o1 turn off dataflow-optimizations in verifier\n");
 	printf("\t-o2 don't hide write-only variables in verifier\n");
 	printf("\t-o3 turn off statement merging in verifier\n");
+	printf("\t-o4 turn on rendezvous optiomizations in verifier\n");
+	printf("\t-o5 turn on case caching (reduces size of pan.m, but affects reachability reports)\n");
+	printf("\t-o6 revert to the old rules for interpreting priority tags (pre version 6.2)\n");
+	printf("\t-o7 revert to the old rules for semi-colon usage (pre version 6.3)\n");
 	printf("\t-Pxxx use xxx for preprocessing\n");
 	printf("\t-p print all statements\n");
+	printf("\t-pp pretty-print (reformat) stdin, write stdout\n");
 	printf("\t-qN suppress io for queue N in printouts\n");
 	printf("\t-r print receive events\n");
+	printf("\t-replay  replay an error trail-file found earlier\n");
+	printf("\t	if the model contains embedded c-code, the ./pan executable is used\n");
+	printf("\t	otherwise spin itself is used to replay the trailfile\n");
+	printf("\t	note that pan recognizes different runtime options than spin itself\n");
+	printf("\t-search  (or -run) generate a verifier, and compile and run it\n");
+	printf("\t      options before -search are interpreted by spin to parse the input\n");
+	printf("\t      options following a -search are used to compile and run the verifier pan\n");
+	printf("\t	    valid options that can follow a -search argument include:\n");
+	printf("\t	    -bfs	perform a breadth-first search\n");
+	printf("\t	    -bfspar	perform a parallel breadth-first search\n");
+	printf("\t	    -bcs	use the bounded-context-switching algorithm\n");
+	printf("\t	    -bitstate	or -bit, use bitstate storage\n");
+	printf("\t	    -biterate	use bitstate with iterative search refinement (-w18..-w35)\n");
+	printf("\t	    -swarmN,M like -biterate, but running all iterations in parallel\n");
+	printf("\t			perform N parallel runs and increment -w every M runs\n");
+	printf("\t			default value for N is 10, default for M is 1\n");
+	printf("\t			(add -w to see which commands will be executed)\n");
+	printf("\t			(add -W if ./pan exists and need not be recompiled)\n");
+	printf("\t	    -link file.c  link executable pan to file.c\n");
+	printf("\t	    -collapse	use collapse state compression\n");
+	printf("\t	    -hc  	use hash-compact storage\n");
+	printf("\t	    -noclaim	ignore all ltl and never claims\n");
+	printf("\t	    -p_permute	use process scheduling order random permutation\n");
+	printf("\t	    -p_rotateN	use process scheduling order rotation by N\n");
+	printf("\t	    -p_reverse	use process scheduling order reversal\n");
+	printf("\t	    -ltl p	verify the ltl property named p\n");
+	printf("\t	    -safety	compile for safety properties only\n");
+	printf("\t	    -i	    	use the dfs iterative shortening algorithm\n");
+	printf("\t	    -a	    	search for acceptance cycles\n");
+	printf("\t	    -l	    	search for non-progress cycles\n");
+	printf("\t	similarly, a -D... parameter can be specified to modify the compilation\n");
+	printf("\t	and any valid runtime pan argument can be specified for the verification\n");
 	printf("\t-S1 and -S2 separate pan source for claim and model\n");
 	printf("\t-s print send events\n");
 	printf("\t-T do not indent printf output\n");
-	printf("\t-t[N] follow [Nth] simulation trail\n");
+	printf("\t-t[N] follow [Nth] simulation trail, see also -k\n");
 	printf("\t-Uyyy pass -Uyyy to the preprocessor\n");
 	printf("\t-uN stop a simulation run after N steps\n");
 	printf("\t-v verbose, more warnings\n");
@@ -204,8 +671,8 @@
 	alldone(1);
 }
 
-void
-optimizations(char nr)
+int
+optimizations(int nr)
 {
 	switch (nr) {
 	case '1':
@@ -243,37 +710,114 @@
 		printf("spin: case caching turned %s\n",
 			ccache?"on":"off");
 		break;
+	case '6':
+		old_priority_rules = 1;
+		if (verbose&32)
+		printf("spin: using old priority rules (pre version 6.2)\n");
+		return 0; /* no break */
+	case '7':
+		implied_semis = 0;
+		if (verbose&32)
+		printf("spin: no implied semi-colons (pre version 6.3)\n");
+		return 0; /* no break */
 	default:
 		printf("spin: bad or missing parameter on -o\n");
 		usage();
 		break;
 	}
+	return 1;
 }
 
-#if 0
-static int
-Rename(const char *old, char *new)
-{	FILE *fo, *fn;
-	char buf[1024];
+static void
+add_comptime(char *s)
+{	char *tmp;
 
-	if ((fo = fopen(old, "r")) == NULL)
-	{	printf("spin: cannot open %s\n", old);
-		return 1;
+	if (!s || strstr(pan_comptime, s))
+	{	return;
 	}
-	if ((fn = fopen(new, "w")) == NULL)
-	{	printf("spin: cannot create %s\n", new);
-		fclose(fo);
-		return 2;
+
+	tmp = (char *) emalloc(strlen(pan_comptime)+strlen(s)+2);
+	sprintf(tmp, "%s %s", pan_comptime, s);
+	pan_comptime = tmp;
+}
+
+static struct {
+	char *ifsee, *thendo;
+	int keeparg;
+} pats[] = {
+	{ "-bfspar",	"-DBFS_PAR",	0 },
+	{ "-bfs",	"-DBFS",	0 },
+	{ "-bcs",	"-DBCS",	0 },
+	{ "-bitstate",	"-DBITSTATE",	0 },
+	{ "-bit",	"-DBITSTATE",	0 },
+	{ "-hc",	"-DHC4",	0 },
+	{ "-collapse",	"-DCOLLAPSE",	0 },
+	{ "-noclaim",	"-DNOCLAIM",	0 },
+	{ "-permuted",	"-DPERMUTED",	0 },
+	{ "-p_permute", "-DPERMUTED",	1 },
+	{ "-p_rotate",	"-DPERMUTED",	1 },
+	{ "-p_reverse",	"-DPERMUTED",	1 },
+	{ "-safety",	"-DSAFETY",	0 },
+	{ "-i",		"-DREACH",	1 },
+	{ "-l",		"-DNP",		1 },
+	{ 0, 0 }
+};
+
+static void
+set_itsr_n(char *s)	/* e.g., -swarm12,3 */
+{	char *tmp;
+
+	if ((tmp = strchr(s, ',')) != NULL)
+	{	tmp++;
+		if (*tmp != '\0' && isdigit((int) *tmp))
+		{	itsr_n = atoi(tmp);
+			if (itsr_n < 2)
+			{	itsr_n = 0;
+	}	}	}
+}
+
+static void
+add_runtime(char *s)
+{	char *tmp;
+	int i;
+
+	if (strncmp(s, "-biterate", strlen("-biterate")) == 0)
+	{	itsr = 10;	/* default nr of sequential iterations */
+		if (isdigit((int) s[9]))
+		{	itsr = atoi(&s[9]);
+			if (itsr < 1)
+			{	itsr = 1;
+			}
+			set_itsr_n(s);
+		}
+		return;
 	}
-	while (fgets(buf, 1024, fo))
-		fputs(buf, fn);
+	if (strncmp(s, "-swarm", strlen("-swarm")) == 0)
+	{	itsr = -10;	/* parallel iterations */
+		if (isdigit((int) s[6]))
+		{	itsr = atoi(&s[6]);
+			if (itsr < 1)
+			{	itsr = 1;
+			}
+			itsr = -itsr;
+			set_itsr_n(s);
+		}
+		return;
+	}
 
-	fclose(fo);
-	fclose(fn);
+	for (i = 0; pats[i].ifsee; i++)
+	{	if (strncmp(s, pats[i].ifsee, strlen(pats[i].ifsee)) == 0)
+		{	add_comptime(pats[i].thendo);
+			if (pats[i].keeparg)
+			{	break;
+			}
+			return;
+	}	}
 
-	return 0;	/* success */
+	tmp = (char *) emalloc(strlen(pan_runtime)+strlen(s)+2);
+	sprintf(tmp, "%s %s", pan_runtime, s);
+	pan_runtime = tmp;
 }
-#endif
 
 int
 main(int argc, char *argv[])
@@ -285,17 +829,16 @@
 	yyin  = stdin;
 	yyout = stdout;
 	tl_out = stdout;
+	strcpy(CurScope, "_");
 
-	/* unused flags: e, w, x, y, z, A, G, I, L, O, Q, R, S, T, W */
+	assert(strlen(CPP) < sizeof(PreProc));
+	strcpy(PreProc, CPP);
+
+	/* unused flags: y, z, G, L, Q, R, W */
 	while (argc > 1 && argv[1][0] == '-')
 	{	switch (argv[1][1]) {
-
-		/* generate code for separate compilation: S1 or S2 */
-		case 'S': separate = atoi(&argv[1][2]);
-			  /* fall through */
-		case 'a': analyze  = 1; break;
-
 		case 'A': export_ast = 1; break;
+		case 'a': analyze = 1; break;
 		case 'B': no_wrapup = 1; break;
 		case 'b': no_print = 1; break;
 		case 'C': Caccess = 1; break;
@@ -305,6 +848,7 @@
 		case 'd': dumptab =  1; break;
 		case 'E': PreArg[++PreCnt] = (char *) &argv[1][2];
 			  break;
+		case 'e': product++; break; /* see also 'L' */
 		case 'F': ltl_file = (char **) (argv+2);
 			  argc--; argv++; break;
 		case 'f': add_ltl = (char **) argv;
@@ -315,6 +859,10 @@
 		case 'I': inlineonly = 1; break;
 		case 'J': like_java = 1; break;
 		case 'j': jumpsteps = atoi(&argv[1][2]); break;
+		case 'k': s_trail = 1;
+			  trailfilename = (char **) (argv+2);
+			  argc--; argv++; break;
+		case 'L': Strict++; break; /* modified -e */
 		case 'l': verbose +=  2; break;
 		case 'M': columns = 2; break;
 		case 'm': m_loss   =  1; break;
@@ -321,28 +869,100 @@
 		case 'N': nvr_file = (char **) (argv+2);
 			  argc--; argv++; break;
 		case 'n': T = atoi(&argv[1][2]); tl_terse = 1; break;
-		case 'o': optimizations(argv[1][2]);
-			  usedopts = 1; break;
-		case 'P': PreProc = (char *) &argv[1][2]; break;
-		case 'p': verbose +=  4; break;
-		case 'q': if (isdigit(argv[1][2]))
+		case 'O': old_scope_rules = 1; break;
+		case 'o': usedopts += optimizations(argv[1][2]); break;
+		case 'P': assert(strlen((const char *) &argv[1][2]) < sizeof(PreProc));
+			  strcpy(PreProc, (const char *) &argv[1][2]);
+			  break;
+		case 'p': if (argv[1][2] == 'p')
+			  {	pretty_print();
+				alldone(0);
+			  }
+			  verbose +=  4; break;
+		case 'q': if (isdigit((int) argv[1][2]))
 				qhide(atoi(&argv[1][2]));
 			  break;
-		case 'r': verbose +=  8; break;
-		case 's': verbose += 16; break;
+		case 'r':
+			  if (strcmp(&argv[1][1], "run") == 0)
+			  {	Srand((unsigned int) T);
+samecase:			if (buzzed != 0)
+				{ fatal("cannot combine -x with -run -replay or -search", (char *)0);
+				}
+				buzzed  = 2;
+				analyze = 1;
+				argc--; argv++;
+				/* process all remaining arguments as relating to pan: */
+				while (argc > 1 && argv[1][0] == '-')
+				{ switch (argv[1][1]) {
+				  case 'D': /* eg -DNP */
+			/*	  case 'E': conflicts with runtime arg */
+				  case 'O': /* eg -O2 */
+				  case 'U': /* to undefine a macro */
+					add_comptime(argv[1]);
+					break;
+				  case 'l':
+					if (strcmp(&argv[1][1], "ltl") == 0)
+					{	add_runtime("-N");
+						argc--; argv++;
+						add_runtime(argv[1]); /* prop name */
+						break;
+					}
+					if (strcmp(&argv[1][1], "link") == 0)
+					{	argc--; argv++;
+						add_comptime(argv[1]);
+						break;
+					}
+					/* else fall through */
+				  default:
+					add_runtime(argv[1]); /* -bfs etc. */
+					break;
+				  }
+				  argc--; argv++;
+				}
+				argc++; argv--;
+			  } else if (strcmp(&argv[1][1], "replay") == 0)
+			  {	replay = 1;
+				add_runtime("-r");
+				goto samecase;
+			  } else
+			  {	verbose +=  8;
+			  }
+			  break;
+		case 'S': separate = atoi(&argv[1][2]); /* S1 or S2 */
+			  /* generate code for separate compilation */
+			  analyze = 1; break;
+		case 's': 
+			  if (strcmp(&argv[1][1], "simulate") == 0)
+			  {	break; /* ignore */
+			  }
+			  if (strcmp(&argv[1][1], "search") == 0)
+			  {	goto samecase;
+			  }
+			  verbose += 16; break;
 		case 'T': notabs = 1; break;
 		case 't': s_trail  =  1;
-			  if (isdigit(argv[1][2]))
-				ntrail = atoi(&argv[1][2]);
+			  if (isdigit((int)argv[1][2]))
+			  {	ntrail = atoi(&argv[1][2]);
+			  }
 			  break;
 		case 'U': PreArg[++PreCnt] = (char *) &argv[1][0];
 			  break;	/* undefine */
-		case 'u': cutoff = atoi(&argv[1][2]); break;	/* new 3.4.14 */
+		case 'u': cutoff = atoi(&argv[1][2]); break;
 		case 'v': verbose += 32; break;
-		case 'V': printf("%s\n", Version);
+		case 'V': printf("%s\n", SpinVersion);
 			  alldone(0);
 			  break;
 		case 'w': verbose += 64; break;
+		case 'W': norecompile = 1; break;	/* 6.4.7: for swarm/biterate */
+		case 'x': /* internal - reserved use */
+			  if (buzzed != 0)
+			  {	fatal("cannot combine -x with -run -search or -replay", (char *)0);
+			  }
+			  buzzed = 1;	/* implies also -a -o3 */
+			  pan_runtime = "-d";
+			  analyze = 1; 
+			  usedopts += optimizations('3');
+			  break;
 		case 'X': xspin = notabs = 1;
 #ifndef PC
 			  signal(SIGPIPE, alldone); /* not posix... */
@@ -355,54 +975,61 @@
 		}
 		argc--; argv++;
 	}
+
+	if (columns == 2 && !cutoff)
+	{	cutoff = 1024;
+	}
+
 	if (usedopts && !analyze)
-		printf("spin: warning -o[123] option ignored in simulations\n");
-	
+		printf("spin: warning -o[1..5] option ignored in simulations\n");
+
 	if (ltl_file)
-	{	char formula[4096];
-		add_ltl = ltl_file-2; add_ltl[1][1] = 'f';
+	{	add_ltl = ltl_file-2; add_ltl[1][1] = 'f';
 		if (!(tl_out = fopen(*ltl_file, "r")))
 		{	printf("spin: cannot open %s\n", *ltl_file);
 			alldone(1);
 		}
-		fgets(formula, 4096, tl_out);
+		if (!fgets(formula, 4096, tl_out))
+		{	printf("spin: cannot read %s\n", *ltl_file);
+		}
 		fclose(tl_out);
 		tl_out = stdout;
 		*ltl_file = (char *) formula;
 	}
 	if (argc > 1)
-	{	char cmd[128], out2[64];
+	{	FILE *fd = stdout;
+		char cmd[512], out2[512];
 
 		/* must remain in current dir */
 		strcpy(out1, "pan.pre");
 
 		if (add_ltl || nvr_file)
-			strcpy(out2, "pan.___");
+		{	assert(strlen(argv[1]) < sizeof(out2));
+			sprintf(out2, "%s.nvr", argv[1]);
+			if ((fd = fopen(out2, MFLAGS)) == NULL)
+			{	printf("spin: cannot create tmp file %s\n",
+					out2);
+				alldone(1);
+			}
+			fprintf(fd, "#include \"%s\"\n", argv[1]);
+		}
 
 		if (add_ltl)
-		{	tl_out = cpyfile(argv[1], out2);
-			nr_errs = tl_main(2, add_ltl);	/* in tl_main.c */
-			fclose(tl_out);
+		{	tl_out = fd;
+			nr_errs = tl_main(2, add_ltl);
+			fclose(fd);
 			preprocess(out2, out1, 1);
 		} else if (nvr_file)
-		{	FILE *fd; char buf[1024];
-			
-			if ((fd = fopen(*nvr_file, "r")) == NULL)
-			{	printf("spin: cannot open %s\n",
-					*nvr_file);
-				alldone(1);
-			}
-			tl_out = cpyfile(argv[1], out2);
-			while (fgets(buf, 1024, fd))
-				fprintf(tl_out, "%s", buf);
-			fclose(tl_out);
+		{	fprintf(fd, "#include \"%s\"\n", *nvr_file);
 			fclose(fd);
 			preprocess(out2, out1, 1);
 		} else
-			preprocess(argv[1], out1, 0);
+		{	preprocess(argv[1], out1, 0);
+		}
 
 		if (preprocessonly)
-			alldone(0);
+		{	alldone(0);
+		}
 
 		if (!(yyin = fopen(out1, "r")))
 		{	printf("spin: cannot open %s\n", out1);
@@ -409,11 +1036,14 @@
 			alldone(1);
 		}
 
-		if (strncmp(argv[1], "progress", 8) == 0
-		||  strncmp(argv[1], "accept", 6) == 0)
-			sprintf(cmd, "_%s", argv[1]);
-		else
-			strcpy(cmd, argv[1]);
+		assert(strlen(argv[1])+1 < sizeof(cmd));
+
+		if (strncmp(argv[1], "progress", (size_t) 8) == 0
+		||  strncmp(argv[1], "accept", (size_t) 6) == 0)
+		{	sprintf(cmd, "_%s", argv[1]);
+		} else
+		{	strcpy(cmd, argv[1]);
+		}
 		oFname = Fname = lookup(cmd);
 		if (oFname->name[0] == '\"')
 		{	int i = (int) strlen(oFname->name);
@@ -428,13 +1058,14 @@
 			printf("spin: missing argument to -f\n");
 			alldone(1);
 		}
-		printf("%s\n", Version);
-		printf("reading input from stdin:\n");
+		printf("%s\n", SpinVersion);
+		fprintf(stderr, "spin: error, no filename specified\n");
 		fflush(stdout);
+		alldone(1);
 	}
 	if (columns == 2)
 	{	extern void putprelude(void);
-		if (xspin || verbose&(1|4|8|16|32))
+		if (xspin || (verbose & (1|4|8|16|32)))
 		{	printf("spin: -c precludes all flags except -t\n");
 			alldone(1);
 		}
@@ -441,10 +1072,13 @@
 		putprelude();
 	}
 	if (columns && !(verbose&8) && !(verbose&16))
-		verbose += (8+16);
+	{	verbose += (8+16);
+	}
 	if (columns == 2 && limited_vis)
-		verbose += (1+4);
-	Srand(T);	/* defined in run.c */
+	{	verbose += (1+4);
+	}
+
+	Srand((unsigned int) T);	/* defined in run.c */
 	SeedUsed = T;
 	s = lookup("_");	s->type = PREDEF; /* write-only global var */
 	s = lookup("_p");	s->type = PREDEF;
@@ -451,9 +1085,27 @@
 	s = lookup("_pid");	s->type = PREDEF;
 	s = lookup("_last");	s->type = PREDEF;
 	s = lookup("_nr_pr");	s->type = PREDEF; /* new 3.3.10 */
+	s = lookup("_priority"); s->type = PREDEF; /* new 6.2.0 */
 
 	yyparse();
 	fclose(yyin);
+
+	if (ltl_claims)
+	{	Symbol *r;
+		fclose(fd_ltl);
+		if (!(yyin = fopen(ltl_claims, "r")))
+		{	fatal("cannot open %s", ltl_claims);
+		}
+		r = oFname;
+		oFname = Fname = lookup(ltl_claims);
+		lineno = 0;
+		yyparse();
+		fclose(yyin);
+		oFname = Fname = r;
+		if (0)
+		{	(void) unlink(ltl_claims);
+	}	}
+
 	loose_ends();
 
 	if (inlineonly)
@@ -463,31 +1115,73 @@
 
 	chanaccess();
 	if (!Caccess)
-	{	if (!s_trail && (dataflow || merger))
-			ana_src(dataflow, merger);
+	{	if (has_provided && merger)
+		{	merger = 0;	/* cannot use statement merging in this case */
+		}
+		if (!s_trail && (dataflow || merger) && (!replay || has_code))
+		{	ana_src(dataflow, merger);
+		}
 		sched();
 		alldone(nr_errs);
 	}
+
 	return 0;
 }
 
-int
-yywrap(void)	/* dummy routine */
+void
+ltl_list(char *nm, char *fm)
 {
-	return 1;
+	if (s_trail
+	||  analyze
+	||  dumptab)	/* when generating pan.c or replaying a trace */
+	{	if (!ltl_claims)
+		{	ltl_claims = "_spin_nvr.tmp";
+			if ((fd_ltl = fopen(ltl_claims, MFLAGS)) == NULL)
+			{	fatal("cannot open tmp file %s", ltl_claims);
+			}
+			tl_out = fd_ltl;
+		}
+
+		add_ltl = (char **) emalloc(5 * sizeof(char *));
+		add_ltl[1] = "-c";
+		add_ltl[2] = nm;
+		add_ltl[3] = "-f";
+		add_ltl[4] = (char *) emalloc(strlen(fm)+4);
+		strcpy(add_ltl[4], "!(");
+		strcat(add_ltl[4], fm);
+		strcat(add_ltl[4], ")");
+		/* add_ltl[4] = fm; */
+		nr_errs += tl_main(4, add_ltl);
+
+		fflush(tl_out);
+		/* should read this file after the main file is read */
+	}
 }
 
 void
 non_fatal(char *s1, char *s2)
-{	extern char yytext[];
+{	extern int yychar; extern char yytext[];
 
-	printf("spin: line %3d %s, Error: ",
-		lineno, Fname?Fname->name:"nofilename");
+	printf("spin: %s:%d, Error: ",
+		Fname?Fname->name:(oFname?oFname->name:"nofilename"), lineno);
+#if 1
+	printf(s1, s2); /* avoids a gcc warning */
+#else
 	if (s2)
 		printf(s1, s2);
 	else
 		printf(s1);
-	if (yytext && strlen(yytext)>1)
+	if (yychar > 0)
+	{	if (yychar == SEMI)
+		{	printf(" statement separator");
+		} else
+		{	printf("	saw '");
+			explain(yychar);
+			printf("'");
+	}	}
+#endif
+
+	if (strlen(yytext)>1)
 		printf(" near '%s'", yytext);
 	printf("\n");
 	nr_errs++;
@@ -497,37 +1191,52 @@
 fatal(char *s1, char *s2)
 {
 	non_fatal(s1, s2);
+	(void) unlink("pan.b");
+	(void) unlink("pan.c");
+	(void) unlink("pan.h");
+	(void) unlink("pan.m");
+	(void) unlink("pan.t");
+	(void) unlink("pan.p");
+	(void) unlink("pan.pre");
+	if (!(verbose&32))
+	{	(void) unlink("_spin_nvr.tmp");
+	}
 	alldone(1);
 }
 
 char *
-emalloc(int n)
+emalloc(size_t n)
 {	char *tmp;
+	static unsigned long cnt = 0;
 
 	if (n == 0)
 		return NULL;	/* robert shelton 10/20/06 */
 
 	if (!(tmp = (char *) malloc(n)))
+	{	printf("spin: allocated %ld Gb, wanted %d bytes more\n",
+			cnt/(1024*1024*1024), (int) n);
 		fatal("not enough memory", (char *)0);
+	}
+	cnt += (unsigned long) n;
 	memset(tmp, 0, n);
 	return tmp;
 }
 
 void
-trapwonly(Lextok *n, char *unused)
-{	extern int realread;
-	short i = (n->sym)?n->sym->type:0;
+trapwonly(Lextok *n /* , char *unused */)
+{	short i = (n->sym)?n->sym->type:0;
 
-	if (i != MTYPE
-	&&  i != BIT
-	&&  i != BYTE
-	&&  i != SHORT
-	&&  i != INT
-	&&  i != UNSIGNED)
-		return;
+	/* printf("%s	realread %d type %d\n", n->sym?n->sym->name:"--", realread, i); */
 
-	if (realread)
-	n->sym->hidden |= 128;	/* var is read at least once */
+	if (realread
+	&& (i == MTYPE
+	||  i == BIT
+	||  i == BYTE
+	||  i == SHORT
+	||  i == INT
+	||  i == UNSIGNED))
+	{	n->sym->hidden |= 128;	/* var is read at least once */
+	}
 }
 
 void
@@ -555,7 +1264,8 @@
 {	Lextok *n = (Lextok *) emalloc(sizeof(Lextok));
 	static int warn_nn = 0;
 
-	n->ntyp = (short) t;
+	n->uiid = is_inline();	/* record origin of the statement */
+	n->ntyp = (unsigned short) t;
 	if (s && s->fn)
 	{	n->ln = s->ln;
 		n->fn = s->fn;
@@ -679,13 +1389,13 @@
 #endif
 }
 
-static void
+void
 explain(int n)
 {	FILE *fd = stdout;
 	switch (n) {
 	default:	if (n > 0 && n < 256)
-				fprintf(fd, "'%c' = '", n);
-			fprintf(fd, "%d'", n);
+				fprintf(fd, "'%c' = ", n);
+			fprintf(fd, "%d", n);
 			break;
 	case '\b':	fprintf(fd, "\\b"); break;
 	case '\t':	fprintf(fd, "\\t"); break;
@@ -698,6 +1408,16 @@
 	case 'R':	fprintf(fd, "recv poll %s", Operator); break;
 	case '@':	fprintf(fd, "@"); break;
 	case '?':	fprintf(fd, "(x->y:z)"); break;
+#if 1
+	case NEXT:	fprintf(fd, "X"); break;
+	case ALWAYS:	fprintf(fd, "[]"); break;
+	case EVENTUALLY: fprintf(fd, "<>"); break;
+	case IMPLIES:	fprintf(fd, "->"); break;
+	case EQUIV:	fprintf(fd, "<->"); break;
+	case UNTIL:	fprintf(fd, "U"); break;
+	case WEAK_UNTIL: fprintf(fd, "W"); break;
+	case IN: fprintf(fd, "%sin", Keyword); break;
+#endif
 	case ACTIVE:	fprintf(fd, "%sactive",	Keyword); break;
 	case AND:	fprintf(fd, "%s&&",	Operator); break;
 	case ASGN:	fprintf(fd, "%s=",	Operator); break;
@@ -724,6 +1444,7 @@
 	case FI:	fprintf(fd, "%sfi",	Keyword); break;
 	case FULL:	fprintf(fd, "%sfull",	Function); break;
 	case GE:	fprintf(fd, "%s>=",	Operator); break;
+	case GET_P:	fprintf(fd, "%sget_priority",Function); break;
 	case GOTO:	fprintf(fd, "%sgoto",	Keyword); break;
 	case GT:	fprintf(fd, "%s>",	Operator); break;
 	case HIDDEN:	fprintf(fd, "%shidden",	Keyword); break;
@@ -763,6 +1484,8 @@
 	case RUN:	fprintf(fd, "%srun",	Operator); break;
 	case SEP:	fprintf(fd, "token: ::"); break;
 	case SEMI:	fprintf(fd, ";"); break;
+	case ARROW:	fprintf(fd, "->"); break;
+	case SET_P:	fprintf(fd, "%sset_priority",Function); break;
 	case SHOW:	fprintf(fd, "%sshow", Keyword); break;
 	case SND:	fprintf(fd, "%s!",	Operator); break;
 	case STRING:	fprintf(fd, "a string"); break;
@@ -776,3 +1499,5 @@
 	case UNLESS:	fprintf(fd, "%sunless",	Keyword); break;
 	}
 }
+
+
--- a/sys/src/cmd/spin/mesg.c
+++ b/sys/src/cmd/spin/mesg.c
@@ -1,14 +1,12 @@
 /***** spin: mesg.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
+#include <stdlib.h>
 #include "spin.h"
 #include "y.tab.h"
 
@@ -24,9 +22,10 @@
 extern int	nproc, nstop;
 extern short	Have_claim;
 
+QH	*qh;
 Queue	*qtab = (Queue *) 0;	/* linked list of queues */
 Queue	*ltab[MAXQ];		/* linear list of queues */
-int	nqs = 0, firstrow = 1;
+int	nqs = 0, firstrow = 1, has_stdin = 0;
 char	Buf[4096];
 
 static Lextok	*n_rem = (Lextok *) 0;
@@ -73,7 +72,7 @@
 		return eval(s->ini);
 
 	q = (Queue *) emalloc(sizeof(Queue));
-	q->qid    = ++nqs;
+	q->qid    = (short) ++nqs;
 	q->nslots = s->ini->val;
 	q->nflds  = cnt_mpars(s->ini->rgt);
 	q->setat  = depth;
@@ -130,7 +129,7 @@
 
 	if (whichq == -1)
 	{	printf("Error: sending to an uninitialized chan\n");
-		whichq = 0;
+		/* whichq = 0; */
 		return 0;
 	}
 	if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
@@ -143,6 +142,37 @@
 	return 0;
 }
 
+#ifndef PC
+ #include <termios.h>
+ static struct termios initial_settings, new_settings;
+
+ void
+ peek_ch_init(void)
+ {
+	tcgetattr(0,&initial_settings);
+ 
+	new_settings = initial_settings;
+	new_settings.c_lflag &= ~ICANON;
+	new_settings.c_lflag &= ~ECHO;
+	new_settings.c_lflag &= ~ISIG;
+	new_settings.c_cc[VMIN] = 0;
+	new_settings.c_cc[VTIME] = 0;
+ }
+
+ int
+ peek_ch(void)
+ {	int n;
+
+	has_stdin = 1;
+
+	tcsetattr(0, TCSANOW, &new_settings);
+	n = getchar();
+	tcsetattr(0, TCSANOW, &initial_settings);
+
+	return n;
+ }
+#endif
+
 int
 qrecv(Lextok *n, int full)
 {	int whichq = eval(n->lft)-1;
@@ -150,22 +180,37 @@
 	if (whichq == -1)
 	{	if (n->sym && !strcmp(n->sym->name, "STDIN"))
 		{	Lextok *m;
-
+#ifndef PC
+			static int did_once = 0;
+			if (!did_once) /* 6.2.4 */
+			{	peek_ch_init();
+				did_once = 1;
+			}
+#endif
 			if (TstOnly) return 1;
 
 			for (m = n->rgt; m; m = m->rgt)
 			if (m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
-			{	int c = getchar();
+			{
+#ifdef PC
+				int c = getchar();
+#else
+				int c = peek_ch();	/* 6.2.4, was getchar(); */
+#endif
+				if (c == 27 || c == 3)	/* escape or control-c */
+				{	printf("quit\n");
+					exit(0);
+				} /* else: non-blocking */
+				if (c == EOF) return 0;	/* no char available */
 				(void) setval(m->lft, c);
 			} else
-				fatal("invalid use of STDIN", (char *)0);
-
-			whichq = 0;
+			{	fatal("invalid use of STDIN", (char *)0);
+			}
 			return 1;
 		}
 		printf("Error: receiving from an uninitialized chan %s\n",
 			n->sym?n->sym->name:"");
-		whichq = 0;
+		/* whichq = 0; */
 		return 0;
 	}
 	if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
@@ -185,9 +230,11 @@
 	for (j = 0, m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
 	{	New = cast_val(q->fld_width[j], eval(m->lft), 0);
 		Old = q->contents[i*q->nflds+j];
-		if (New == Old) continue;
-		if (New >  Old) break;			/* inner loop */
-		if (New <  Old) goto found;
+		if (New == Old)
+			continue;
+		if (New >  Old)
+			break;	/* inner loop */
+		goto found;	/* New < Old */
 	}
 found:
 	for (j = q->qlen-1; j >= i; j--)
@@ -204,7 +251,8 @@
 typ_ck(int ft, int at, char *s)
 {
 	if ((verbose&32) && ft != at
-	&& (ft == CHAN || at == CHAN))
+	&& (ft == CHAN || at == CHAN)
+	&& (at != PREDEF || strcmp(s, "recv") != 0))
 	{	char buf[128], tag1[64], tag2[64];
 		(void) sputtype(tag1, ft);
 		(void) sputtype(tag2, at);
@@ -383,7 +431,7 @@
 	return 1;
 }
 
-void
+static void
 channm(Lextok *n)
 {	char lbuf[512];
 
@@ -394,7 +442,11 @@
 	else if (n->sym->type == STRUCT)
 	{	Symbol *r = n->sym;
 		if (r->context)
-			r = findloc(r);
+		{	r = findloc(r);
+			if (!r)
+			{	strcat(Buf, "*?*");
+				return;
+		}	}
 		ini_struct(r);
 		printf("%s", r->name);
 		strcpy(lbuf, "");
@@ -422,7 +474,11 @@
 	sr_buf(v, q->fld_width[j] == MTYPE);
 	if (j == q->nflds - 1)
 	{	int cnr;
-		if (s_trail) cnr = pno; else cnr = X?X->pid - Have_claim:0;
+		if (s_trail)
+		{	cnr = pno;
+		} else
+		{	cnr = X?X->pid - Have_claim:0;
+		}
 		if (tr[0] == '[') strcat(Buf, "]");
 		pstext(cnr, Buf);
 	}
@@ -458,12 +514,6 @@
 	}
 }
 
-typedef struct QH {
-	int	n;
-	struct	QH *nxt;
-} QH;
-QH *qh;
-
 void
 qhide(int q)
 {	QH *p = (QH *) emalloc(sizeof(QH));
@@ -483,7 +533,7 @@
 
 static void
 sr_talk(Lextok *n, int v, char *tr, char *a, int j, Queue *q)
-{	char s[64];
+{	char s[128];
 
 	if (qishidden(eval(n->lft)))
 		return;
@@ -510,9 +560,20 @@
 	}
 
 	if (j == 0)
-	{	whoruns(1);
-		printf("line %3d %s %s",
-			n->ln, n->fn->name, s);
+	{	char snm[128];
+		whoruns(1);
+		{	char *ptr = n->fn->name;
+			char *qtr = snm;
+			while (*ptr != '\0')
+			{	if (*ptr != '\"')
+				{	*qtr++ = *ptr;
+				}
+				ptr++;
+			}
+			*qtr = '\0';
+			printf("%s:%d %s",
+				snm, n->ln, s);
+		}
 	} else
 		printf(",");
 	sr_mesg(stdout, v, q->fld_width[j] == MTYPE);
@@ -554,7 +615,11 @@
 sr_mesg(FILE *fd, int v, int j)
 {	Buf[0] ='\0';
 	sr_buf(v, j);
+#if 1
+	fprintf(fd, Buf, (char *) 0); /* prevent compiler warning */
+#else
 	fprintf(fd, Buf);
+#endif
 }
 
 void
@@ -572,10 +637,15 @@
 			continue;
 		if (q->nslots == 0)
 			continue; /* rv q always empty */
+#if 0
+		if (q->qlen == 0)	/* new 7/10 -- dont show if queue is empty */
+		{	continue;
+		}
+#endif
 		printf("\t\tqueue %d (", q->qid);
 		if (r)
 		printf("%s(%d):", r->n->name, r->pid - Have_claim);
-		if (s->nel != 1)
+		if (s->nel > 1 || s->isarray)
 		  printf("%s[%d]): ", s->name, n);
 		else
 		  printf("%s): ", s->name);
@@ -609,7 +679,11 @@
 		}	
 	}
 
-	if (!n || n->ntyp == LEN || n->ntyp == RUN)
+	/* ok on the rhs of an assignment: */
+	if (!n || n->ntyp == LEN || n->ntyp == RUN
+	||  n->ntyp == FULL  || n->ntyp == NFULL
+	||  n->ntyp == EMPTY || n->ntyp == NEMPTY
+	||  n->ntyp == 'R')
 		return;
 
 	if (n->sym && n->sym->type == CHAN)
@@ -627,7 +701,122 @@
 	nochan_manip(p, n->rgt, 1);
 }
 
+typedef struct BaseName {
+	char *str;
+	int cnt;
+	struct BaseName *nxt;
+} BaseName;
+
+static BaseName *bsn;
+
 void
+newbasename(char *s)
+{	BaseName *b;
+
+/*	printf("+++++++++%s\n", s);	*/
+	for (b = bsn; b; b = b->nxt)
+		if (strcmp(b->str, s) == 0)
+		{	b->cnt++;
+			return;
+		}
+	b = (BaseName *) emalloc(sizeof(BaseName));
+	b->str = emalloc(strlen(s)+1);
+	b->cnt = 1;
+	strcpy(b->str, s);
+	b->nxt = bsn;
+	bsn = b;
+}
+
+void
+delbasename(char *s)
+{	BaseName *b, *prv = (BaseName *) 0;
+
+	for (b = bsn; b; prv = b, b = b->nxt)
+	{	if (strcmp(b->str, s) == 0)
+		{	b->cnt--;
+			if (b->cnt == 0)
+			{	if (prv)
+				{	prv->nxt = b->nxt;
+				} else
+				{	bsn = b->nxt;
+			}	}
+/*	printf("---------%s\n", s);	*/
+			break;
+	}	}
+}
+
+void
+checkindex(char *s, char *t)
+{	BaseName *b;
+
+/*	printf("xxx Check %s (%s)\n", s, t);	*/
+	for (b = bsn; b; b = b->nxt)
+	{
+/*		printf("	%s\n", b->str);	*/
+		if (strcmp(b->str, s) == 0)
+		{	non_fatal("do not index an array with itself (%s)", t);
+			break;
+	}	}
+}
+
+void
+scan_tree(Lextok *t, char *mn, char *mx)
+{	char sv[512];
+	char tmp[32];
+	int oln = lineno;
+
+	if (!t) return;
+
+	lineno = t->ln;
+
+	if (t->ntyp == NAME)
+	{	strcat(mn, t->sym->name);
+		strcat(mx, t->sym->name);
+		if (t->lft)		/* array index */
+		{	strcat(mn, "[]");
+			newbasename(mn);
+				strcpy(sv, mn);		/* save */
+				strcpy(mn, "");		/* clear */
+				strcat(mx, "[");
+				scan_tree(t->lft, mn, mx);	/* index */
+				strcat(mx, "]");
+				checkindex(mn, mx);	/* match against basenames */
+				strcpy(mn, sv);		/* restore */
+			delbasename(mn);
+		}
+		if (t->rgt)	/* structure element */
+		{	scan_tree(t->rgt, mn, mx);
+		}
+	} else if (t->ntyp == CONST)
+	{	strcat(mn, "1"); /* really: t->val */
+		sprintf(tmp, "%d", t->val);
+		strcat(mx, tmp);
+	} else if (t->ntyp == '.')
+	{	strcat(mn, ".");
+		strcat(mx, ".");
+		scan_tree(t->lft, mn, mx);
+	} else
+	{	strcat(mn, "??");
+		strcat(mx, "??");
+	}
+	lineno = oln;
+}
+
+void
+no_nested_array_refs(Lextok *n)	/* a [ a[1] ] with a[1] = 1, causes trouble in pan.b */
+{	char mn[512];
+	char mx[512];
+
+/*	printf("==================================ZAP\n");	*/
+	bsn = (BaseName *) 0;	/* start new list */
+	strcpy(mn, "");
+	strcpy(mx, "");
+
+	scan_tree(n, mn, mx);
+/*	printf("==> %s\n", mn);	*/
+}
+
+void
 no_internals(Lextok *n)
 {	char *sp;
 
@@ -638,7 +827,10 @@
 	sp = n->sym->name;
 
 	if ((strlen(sp) == strlen("_nr_pr") && strcmp(sp, "_nr_pr") == 0)
+	||  (strlen(sp) == strlen("_pid") && strcmp(sp, "_pid") == 0)
 	||  (strlen(sp) == strlen("_p") && strcmp(sp, "_p") == 0))
-	{	fatal("attempt to assign value to system variable %s", sp);
+	{	fatal("invalid assignment to %s", sp);
 	}
+
+	no_nested_array_refs(n);
 }
--- a/sys/src/cmd/spin/mkfile
+++ b/sys/src/cmd/spin/mkfile
@@ -8,6 +8,7 @@
 	guided.$O\
 	main.$O\
 	mesg.$O\
+	msc_tcl.$O\
 	pangen1.$O\
 	pangen2.$O\
 	pangen3.$O\
@@ -14,8 +15,7 @@
 	pangen4.$O\
 	pangen5.$O\
 	pangen6.$O\
-	pc_zpp.$O\
-	ps_msc.$O\
+	pangen7.$O\
 	reprosrc.$O\
 	run.$O\
 	sched.$O\
@@ -45,7 +45,7 @@
 </sys/src/cmd/mkone
 
 CC=pcc -c
-CFLAGS=-B -D_POSIX_SOURCE
+CFLAGS=-B -D_POSIX_SOURCE -D_PLAN9
 YFLAGS=-S -d
 
 $SPIN_OS:	spin.h
--- /dev/null
+++ b/sys/src/cmd/spin/msc_tcl.c
@@ -1,0 +1,376 @@
+/***** spin: msc_tcl.c *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+#include <stdlib.h>
+#include "spin.h"
+#include "version.h"
+
+#define MW	500	/* page width */
+#define RH	100	/* right margin */
+#define WW	 80	/* distance between process lines */
+#define HH	 12	/* vertical distance between steps */
+#define LW	  2	/* line width of message arrows */
+
+#define RVC	"darkred"	/* rendezvous arrows */
+#define MPC	"darkblue"	/* asynchronous message passing arrow */
+#define GRC	"lightgrey"	/* grid lines */
+
+static int	MH = 600;	/* anticipated page-length */
+static FILE	*pfd;
+static char	**I;		/* initial procs */
+static int	*D,*R;		/* maps between depth (stepnr) and ldepth (msc-step) */
+static short	*M;		/* x location of each box at index y */
+static short	*T;		/* y index of match for each box at index y */
+static char	**L;		/* text labels */
+static int	ProcLine[256];	/* active processes */
+static int	UsedLine[256];	/* process line has at least one entry */
+static int	ldepth = 1;
+static int	maxx, TotSteps = 2*4096; /* max nr of steps for simulation output */
+static float	Scaler = (float) 1.0;
+
+static int	xscale = 2;
+static int	yscale = 1;
+static int	no_box;
+
+extern int	ntrail, s_trail, pno, depth;
+extern Symbol	*oFname;
+
+extern void	exit(int);
+extern void	putpostlude(void);
+
+static void	putpages(void);
+
+static void
+psline(int x0, int y0, int x1, int y1, char *color)
+{	char *side = "last";
+
+	if (x0 == x1)	/* gridline */
+	{	fprintf(pfd, ".c create line %d %d %d %d -fill %s -tags grid -width 1 \n",
+			xscale*(x0+1)*WW-20, yscale*y0+20,
+			xscale*(x1+1)*WW-20, yscale*y1+20, color);
+		fprintf(pfd, ".c lower grid\n");
+	} else
+	{	int xm = xscale*(x0+1)*WW + (xscale*(x1 - x0)*WW)/2 - 20;	/* mid x */
+
+		if (y1 - y0  <= HH+20)
+		{	y1 = y0+20; /* close enough to horizontal - looks better */
+		}
+ 
+		fprintf(pfd, ".c create line %d %d %d %d -fill %s -tags mesg -width %d\n",
+			xscale*(x0+1)*WW-20, yscale*y0+20+10,
+			xm,                  yscale*y0+20+10, color, LW);
+
+		if (y1 != y0+20)
+		{	fprintf(pfd, ".c create line %d %d %d %d -fill %s -tags mesg -width %d\n",
+				xm, yscale*y0+20+10,
+				xm, yscale*y1+20-10, color, LW);
+		}
+
+		fprintf(pfd, ".c create line %d %d %d %d -fill %s -width %d ",
+			xm,                  yscale*y1+20-10,
+			xscale*(x1+1)*WW-20, yscale*y1+20-10, color, LW);
+
+		if (strcmp(color, RVC) == 0)
+		{	side = "both";
+		}
+		fprintf(pfd, "-arrow %s -arrowshape {5 5 5} -tags mesg\n", side);
+		fprintf(pfd, ".c raise mesg\n");
+	}
+}
+
+static void
+colbox(int ix, int iy, int w, int h_unused, char *color)
+{	int x = ix*WW;
+	int y = iy*HH;
+
+	if (ix < 0 || ix > 255)
+	{	fatal("msc_tcl: unexpected\n", (char *) 0);
+	}
+
+	if (ProcLine[ix] < iy)
+	{	/* if (ProcLine[ix] > 0) */
+		{	psline(ix-1, ProcLine[ix]*HH+HH+4,
+			       ix-1, iy*HH-HH, GRC);
+		}
+		fprintf(pfd, "# ProcLine[%d] from %d to %d (Used %d nobox %d)\n",
+			ix, ProcLine[ix], iy, UsedLine[ix], no_box);
+		ProcLine[ix] = iy;
+	} else
+	{	fprintf(pfd, "# ProcLine[%d] stays at %d (Used %d nobox %d)\n",
+			ix, ProcLine[ix], UsedLine[ix], no_box);
+	}
+
+	if (UsedLine[ix])
+	{	no_box = 2;
+	}
+
+	if (strcmp(color, "black") == 0)
+	{	if (no_box == 0)	/* shadow */
+		{	fprintf(pfd, ".c create rectangle %d %d %d %d -fill black\n",
+				xscale*x-(xscale*4*w/3)-20+4, (yscale*y-10)+20+2,
+				xscale*x+(xscale*4*w/3)-20,   (yscale*y+10)+20+2);
+		}
+	} else
+	{	if (no_box == 0)	/* box with outline */
+		{	fprintf(pfd, ".c create rectangle %d %d %d %d -fill ivory\n",
+				xscale*x-(xscale*4*w/3)-20, (yscale*y-10)+20,
+				xscale*x+(xscale*4*w/3)-20, (yscale*y+10)+20);
+			UsedLine[ix]++;
+		} else			/* no outline */
+		{	fprintf(pfd, ".c create rectangle %d %d %d %d -fill white -width 0\n",
+				xscale*x-(xscale*4*w/3)-20, (yscale*y-10)+20,
+				xscale*x+(xscale*4*w/3)-20, (yscale*y+10)+20);
+	}	}
+	if (no_box > 0)
+	{	no_box--;
+	}
+}
+
+static void
+stepnumber(int i)
+{	int y = (yscale*i*HH) + 20;
+
+	fprintf(pfd, ".c create text %d %d -fill #eef -text \"%d\"\n",
+		-10+(xscale*WW)/2, y, i);
+
+	/* horizontal dashed grid line */
+	fprintf(pfd, ".c create line %d %d %d %d -fill #eef -dash {6 4}\n",
+		-20+WW*xscale, y, (maxx+1)*WW*xscale-20, y);
+}
+
+static void
+spitbox(int ix, int y, char *s)
+{	float bw;	/* box width */
+	char d[256], *t, *z;
+	int a, i, x = ix+1;
+	char *color = "black";
+
+	if (y > 0)
+	{	stepnumber(y);
+	}
+
+	bw = (float)1.8*(float)strlen(s);	/* guess at default font width */
+	colbox(x, y, (int) (bw+1.0), 5, "black");
+	if (s[0] == '~')
+	{	switch (s[1]) {
+		default :
+		case 'R': color = "red";   break;
+		case 'B': color = "blue";  break;
+		case 'G': color = "green"; break;
+		}
+		s += 2;
+	} else if (strchr(s, '!'))
+	{	color = "ivory";
+	} else if (strchr(s, '?'))
+	{	color = "azure";
+	} else
+	{	color = "pink";
+		if (sscanf(s, "%d:%250s", &a, d) == 2
+		&&  a >= 0 && a < TotSteps)
+		{	if (!I[a]  || strlen(I[a]) <= strlen(s))
+			{	I[a] = (char *) emalloc((int) strlen(s)+1);
+			}
+			strcpy(I[a], s);
+	}	}
+
+	colbox(x, y, (int) bw, 4, color);
+
+	z = t = (char *) emalloc(2*strlen(s)+1);
+
+	for (i = 0; i < (int) strlen(s); i++)
+	{	if (s[i] == '\n')
+		{	continue;
+		}
+		if (s[i] == '[' || s[i] == ']')
+		{	*t++ = '\\';
+		}
+		*t++ = s[i];
+	}
+
+	fprintf(pfd, ".c create text %d %d -text \"%s\"\n",
+		xscale*x*WW-20, yscale*y*HH+20, z);
+}
+
+static void
+putpages(void)
+{	int i, lasti=0; float nmh;
+
+	if (maxx*xscale*WW > MW-RH/2)
+	{	Scaler = (float) (MW-RH/2) / (float) (maxx*xscale*WW);
+		nmh = (float) MH; nmh /= Scaler; MH = (int) nmh;
+		fprintf(pfd, "# Scaler %f, MH %d\n", Scaler, MH);
+	}
+	if (ldepth >= TotSteps)
+	{	ldepth = TotSteps-1;
+	}
+
+/* W: (maxx+2)*xscale*WW  */
+/* H: ldepth*HH*yscale+50 */
+	fprintf(pfd, "wm title . \"scenario\"\n");
+	fprintf(pfd, "wm geometry . %dx600+650+100\n", (maxx+2)*xscale*WW);
+
+	fprintf(pfd, "canvas .c -width 800 -height 800 \\\n");
+	fprintf(pfd, "	-scrollregion {0c -1c 30c 100c} \\\n");
+	fprintf(pfd, "	-xscrollcommand \".hscroll set\" \\\n");
+	fprintf(pfd, "	-yscrollcommand \".vscroll set\" \\\n");
+	fprintf(pfd, "	-bg white -relief raised -bd 2\n");
+
+	fprintf(pfd, "scrollbar .vscroll -relief sunken ");
+	fprintf(pfd, " -command \".c yview\"\n");
+	fprintf(pfd, "scrollbar .hscroll -relief sunken -orient horiz ");
+	fprintf(pfd, " -command \".c xview\"\n");
+
+	fprintf(pfd, "pack append . \\\n");
+	fprintf(pfd, "	.vscroll {right filly} \\\n");
+	fprintf(pfd, "	.hscroll {bottom fillx} \\\n");
+	fprintf(pfd, "	.c {top expand fill}\n");
+
+	fprintf(pfd, ".c yview moveto 0\n");
+
+	for (i = TotSteps-1; i >= 0; i--)
+	{	if (I[i])
+		{	spitbox(i, -1, I[i]);
+	}	}
+
+	for (i = 0; i <= ldepth; i++)
+	{	if (!M[i] && !L[i])
+		{	continue;	/* no box */
+		}
+		if (T[i] > 0)		/* arrow */
+		{	if (T[i] == i)	/* rv handshake */
+			{	psline(	M[lasti], lasti*HH,
+					M[i],     i*HH, RVC);
+			} else
+			{	psline(	M[i],     i*HH,
+					M[T[i]],  T[i]*HH, MPC);
+		}	}
+		if (L[i])
+		{	spitbox(M[i], i, L[i]);
+			lasti = i;
+	}	}
+}
+
+static void
+putbox(int x)
+{
+	if (ldepth >= TotSteps)
+	{	fprintf(stderr, "max length of %d steps exceeded - ps file truncated\n",
+			TotSteps);
+		putpostlude();
+	}
+	M[ldepth] = x;
+	if (x > maxx)
+	{	maxx = x;
+		fprintf(pfd, "# maxx %d\n", x);
+	}
+}
+
+/* functions called externally: */
+
+extern int WhatSeed(void);
+
+void
+putpostlude(void)
+{	char cmd[512];
+
+	putpages();
+	fprintf(pfd, ".c lower grid\n");
+	fprintf(pfd, ".c raise mesg\n");
+	fclose(pfd);
+
+	fprintf(stderr, "seed used: -n%d\n", WhatSeed());
+	sprintf(cmd, "wish -f %s.tcl &", oFname?oFname->name:"msc");
+	fprintf(stderr, "%s\n", cmd);
+	(void) unlink("pan.pre");
+	exit (system(cmd));
+}
+
+void
+putprelude(void)
+{	char snap[256]; FILE *fd;
+
+	sprintf(snap, "%s.tcl", oFname?oFname->name:"msc");
+	if (!(pfd = fopen(snap, MFLAGS)))
+	{	fatal("cannot create file '%s'", snap);
+	}
+	if (s_trail)
+	{	if (ntrail)
+		sprintf(snap, "%s%d.trail", oFname?oFname->name:"msc", ntrail);
+		else
+		sprintf(snap, "%s.trail", oFname?oFname->name:"msc");
+		if (!(fd = fopen(snap, "r")))
+		{	snap[strlen(snap)-2] = '\0';
+			if (!(fd = fopen(snap, "r")))
+				fatal("cannot open trail file", (char *) 0);
+		}
+		TotSteps = 1;
+		while (fgets(snap, 256, fd)) TotSteps++;
+		fclose(fd);
+	}
+	TotSteps *= 2;
+	R = (int   *) emalloc(TotSteps * sizeof(int));
+	D = (int   *) emalloc(TotSteps * sizeof(int));
+	M = (short *) emalloc(TotSteps * sizeof(short));
+	T = (short *) emalloc(TotSteps * sizeof(short));
+	L = (char **) emalloc(TotSteps * sizeof(char *));
+	I = (char **) emalloc(TotSteps * sizeof(char *));
+}
+
+void
+putarrow(int from, int to)
+{
+	/* from rv if from == to */
+	/* which means that D[from] == D[to] */
+	/* which means that T[x] == x */
+
+	if (from    < TotSteps
+	&&  to      < TotSteps
+	&&  D[from] < TotSteps)
+	{	T[D[from]] = D[to];
+	}
+}
+
+void
+pstext(int x, char *s)
+{	char *tmp = emalloc((int) strlen(s)+1);
+
+	strcpy(tmp, s);
+	if (depth == 0)
+	{	I[x] = tmp;
+	} else
+	{	if (depth >= TotSteps || ldepth >= TotSteps)
+		{	fprintf(stderr, "spin: error: max nr of %d steps exceeded\n",
+				TotSteps);
+			fatal("use -uN to limit steps", (char *) 0);
+		}
+		putbox(x);
+		D[depth] = ldepth;
+		R[ldepth] = depth;
+		L[ldepth] = tmp;
+		ldepth += 2;
+	}
+}
+
+void
+dotag(FILE *fd, char *s)
+{	extern int columns, notabs; extern RunList *X;
+	int i = (!strncmp(s, "MSC: ", 5))?5:0;
+	int pid = s_trail ? pno : (X?X->pid:0);
+
+	if (columns == 2)
+	{	pstext(pid, &s[i]);
+	} else
+	{	if (!notabs)
+		{	printf("  ");
+			for (i = 0; i <= pid; i++)
+			{	printf("    ");
+		}	}
+		fprintf(fd, "%s", s);
+		fflush(fd);
+	}
+}
--- a/sys/src/cmd/spin/pangen1.c
+++ b/sys/src/cmd/spin/pangen1.c
@@ -1,18 +1,22 @@
 /***** spin: pangen1.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include "y.tab.h"
 #include "pangen1.h"
 #include "pangen3.h"
+#include "pangen6.h"
+#include <assert.h>
+#ifdef SOLARIS
+#include <sys/int_limits.h>
+#else
+#include <stdint.h>
+#endif
 
 extern FILE	*tc, *th, *tt;
 extern Label	*labtab;
@@ -20,9 +24,10 @@
 extern ProcList	*rdy;
 extern Queue	*qtab;
 extern Symbol	*Fname;
-extern int	lineno, verbose, Pid, separate;
+extern int	lineno, verbose, Pid, separate, old_scope_rules, nclaims;
 extern int	nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
-extern short	has_sorted, has_random, has_provided;
+extern short	has_sorted, has_random, has_provided, has_priority;
+extern Queue	*ltab[];
 
 int	Npars=0, u_sync=0, u_async=0, hastrack = 1;
 short	has_io = 0;
@@ -36,9 +41,10 @@
 static void	dohidden(void);
 static void	do_init(FILE *, Symbol *);
 static void	end_labs(Symbol *, int);
-static void	put_ptype(char *, int, int, int);
+static void	put_ptype(char *, int, int, int, enum btypes);
 static void	tc_predef_np(void);
 static void	put_pinit(ProcList *);
+static void	multi_init(void);
        void	walk_struct(FILE *, int, char *, Symbol *, char *, char *, char *);
 
 static void
@@ -46,9 +52,24 @@
 {
 	if (!p) return;
 	reverse_names(p->nxt);
-	fprintf(th, "   \"%s\",\n", p->n->name);
+	fprintf(tc, "   \"%s\",\n", p->n->name);
 }
+static void
+reverse_types(ProcList *p)
+{
+	if (!p) return;
+	reverse_types(p->nxt);
+	fprintf(tc, "   %d,	/* %s */\n", p->b, p->n->name);
+}
 
+static int
+blog(int n)	/* for small log2 without rounding problems */
+{	int m=1, r=2;
+
+	while (r < n) { m++; r *= 2; }
+	return 1+m;
+}
+
 void
 genheader(void)
 {	ProcList *p; int i;
@@ -57,37 +78,129 @@
 	{	putunames(th);
 		goto here;
 	}
-
+	/* 5.2.3: gcc 3 no longer seems to compute sizeof at compile time */
+	fprintf(th, "#define WS		%d /* word size in bytes */\n", (int) sizeof(void *));
 	fprintf(th, "#define SYNC	%d\n", u_sync);
 	fprintf(th, "#define ASYNC	%d\n\n", u_async);
+	fprintf(th, "#ifndef NCORE\n");
+	fprintf(th, "	#ifdef DUAL_CORE\n");
+	fprintf(th, "		#define NCORE	2\n");
+	fprintf(th, "	#elif QUAD_CORE\n");
+	fprintf(th, "		#define NCORE	4\n");
+	fprintf(th, "	#else\n");
+	fprintf(th, "		#define NCORE	1\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "#endif\n\n");
 
 	putunames(th);
 
-	fprintf(tc, "short Air[] = { ");
+	fprintf(tc, "\nshort Air[] = { ");
 	for (p = rdy, i=0; p; p = p->nxt, i++)
 		fprintf(tc, "%s (short) Air%d", (p!=rdy)?",":"", i);
 	fprintf(tc, ", (short) Air%d", i);	/* np_ */
+	if (nclaims > 1)
+	{	fprintf(tc, "\n#ifndef NOCLAIM\n");
+		fprintf(tc, "	, (short) Air%d", i+1);	/* Multi */
+		fprintf(tc, "\n#endif\n\t");
+	}
 	fprintf(tc, " };\n");
 
-	fprintf(th, "char *procname[] = {\n");
+	fprintf(tc, "char *procname[] = {\n");
 		reverse_names(rdy);
-	fprintf(th, "   \":np_:\",\n");
-	fprintf(th, "};\n\n");
+	fprintf(tc, "   \":np_:\",\n");
+	fprintf(tc, "	0\n");
+	fprintf(tc, "};\n\n");
 
+	fprintf(tc, "enum btypes { NONE=%d, N_CLAIM=%d,", NONE, N_CLAIM);
+	fprintf(tc, " I_PROC=%d, A_PROC=%d,", I_PROC, A_PROC);
+	fprintf(tc, " P_PROC=%d, E_TRACE=%d, N_TRACE=%d };\n\n",
+		P_PROC, E_TRACE, N_TRACE);
+
+	fprintf(tc, "int Btypes[] = {\n");
+		reverse_types(rdy);
+	fprintf(tc, "   0	/* :np_: */\n");
+	fprintf(tc, "};\n\n");
+
 here:
 	for (p = rdy; p; p = p->nxt)
-		put_ptype(p->n->name, p->tn, mst, nrRdy+1);
+		put_ptype(p->n->name, p->tn, mst, nrRdy+1, p->b);
 		/* +1 for np_ */
-	put_ptype("np_", nrRdy, mst, nrRdy+1);
+	put_ptype("np_", nrRdy, mst, nrRdy+1, 0);
 
+	if (nclaims > 1)
+	{	/* this is the structure that goes into the state-vector
+		 * instead of the actual never claims
+		 * this assumes that the claims do not have any local variables
+		 * this claim records the types and states of all subclaims in an array
+		 * NB: not sure if we need the first 3 fields in this structure
+		 *     it's here for now to avoid breaking some possible dependence
+		 * in the calculations above, we were already taking into account
+		 * that there is one never-claim, which will now be this one
+		 */
+
+		i = blog(mst);
+		fprintf(th, "\n");
+
+		fprintf(th, "#ifndef NOCLAIM\n");
+		fprintf(th, "	#undef VERI\n");
+		fprintf(th, "	#define VERI	%d\n", nrRdy+1);
+		fprintf(th, "	#define Pclaim	P%d\n\n", nrRdy+1);
+		fprintf(th, "typedef struct P%d {\n", nrRdy+1);
+		fprintf(th, "	unsigned _pid : 8; /* always zero */\n");
+		fprintf(th, "	unsigned _t   : %d; /* active-claim type  */\n",
+			blog(nrRdy+1));
+		fprintf(th, "	unsigned _p   : %d; /* active-claim state */\n",
+			i);
+		fprintf(th, "	unsigned _n   : %d; /* active-claim index */\n",
+			blog(nclaims));
+		if (i <= UINT8_MAX)	/* in stdint.h = UCHAR_MAX from limits.h */
+		{	fprintf(th, "	uchar c_cur[NCLAIMS]; /* claim-states */\n");
+		} else if (i <= UINT16_MAX)	/* really USHRT_MAX from limits.h */
+		{	fprintf(th, "	ushort c_cur[NCLAIMS]; /* claim-states */\n");
+		} else	/* the most unlikely case */
+		{	fprintf(th, "	uint c_cur[NCLAIMS]; /* claim-states */\n");
+		}
+		fprintf(th, "} P%d;\n", nrRdy+1);
+
+		fprintf(tc, "#ifndef NOCLAIM\n");
+		fprintf(tc, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n");
+		fprintf(tc, "#endif\n");
+
+		fprintf(th, "	#define Air%d	(0)\n\n", nrRdy+1);
+		fprintf(th, "#endif\n");
+		/*
+		 * find special states as:
+		 *	stopstate [ claimnr ][ curstate ] == 1
+		 *	accpstate [ claimnr ][ curstate ]
+		 *	progstate [ claimnr ][ curstate ]
+		 *	reached   [ claimnr ][ curstate ]
+		 *	visstate  [ claimnr ][ curstate ]
+		 *	loopstate [ claimnr ][ curstate ]
+		 *	mapstate  [ claimnr ][ curstate ]
+		 */
+	} else
+	{	fprintf(th, "#define Pclaim	P0\n");
+		fprintf(th, "#ifndef NCLAIMS\n");
+		fprintf(th, "	#define NCLAIMS 1\n");
+		fprintf(th, "#endif\n");
+		fprintf(tc, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n");
+	}
+
 	ntimes(th, 0, 1, Head0);
 
 	if (separate != 2)
 	{	extern void c_add_stack(FILE *);
+		extern void c_stack_size(FILE *);
 
 		ntimes(th, 0, 1, Header);
+		fprintf(th, "#define StackSize	(");
+			c_stack_size(th);
+		fprintf(th, ")\n");
+
 		c_add_stack(th);
 		ntimes(th, 0, 1, Header0);
+	} else
+	{	fprintf(th, "extern char *emalloc(unsigned long);\n");
 	}
 	ntimes(th, 0, 1, Head1);
 
@@ -96,7 +209,13 @@
 
 	hastrack = c_add_sv(th);
 
+	fprintf(th, "#ifdef TRIX\n");
+	fprintf(th, "	/* room for 512 proc+chan ptrs, + safety margin */\n");
+	fprintf(th, "	char *_ids_[MAXPROC+MAXQ+4];\n");
+	fprintf(th, "#else\n");
 	fprintf(th, "	uchar sv[VECTORSZ];\n");
+	fprintf(th, "#endif\n");
+
 	fprintf(th, "} State");
 #ifdef SOLARIS
 	fprintf(th,"\n#ifdef GCC\n");
@@ -105,8 +224,24 @@
 #endif
 	fprintf(th, ";\n\n");
 
-	fprintf(th, "#define HAS_TRACK	%d\n", hastrack);
+	fprintf(th, "#ifdef TRIX\n");
+	fprintf(th, "typedef struct TRIX_v6 {\n");
+	fprintf(th, "	uchar *body; /* aligned */\n");
+	fprintf(th, "#ifndef BFS\n");
+	fprintf(th, "	short modified;\n");
+	fprintf(th, "#endif\n");
+	fprintf(th, "	short psize;\n");
+	fprintf(th, "	short parent_pid;\n");
+	fprintf(th, "	struct TRIX_v6 *nxt;\n");
+	fprintf(th, "} TRIX_v6;\n");
+	fprintf(th, "#endif\n\n");
 
+	fprintf(th, "#define HAS_TRACK	%d\n", hastrack);
+	if (0 && hastrack)	/* not really a problem */
+	{	fprintf(th, "#ifdef BFS_PAR\n");
+		fprintf(th, "	#error cannot use BFS_PAR on models with c_track stmnts\n");
+		fprintf(th, "#endif\n");
+	}
 	if (separate != 2)
 		dohidden();
 }
@@ -116,14 +251,36 @@
 {	ProcList *p;
 	int i = 0;
 
-	if (separate ==2) goto shortcut;
+	if (separate == 2) goto shortcut;
 
-	fprintf(tc, "int\naddproc(int n");
-	for (i = 0; i < Npars; i++)
+	ntimes(tc, nrRdy+1, nrRdy+2, R2); /* +1 for np_ -- was th */
+
+	fprintf(tc, "#ifdef TRIX\n");
+	fprintf(tc, "int what_p_size(int);\n");
+	fprintf(tc, "int what_q_size(int);\n\n");
+
+	/* the number of processes just changed by 1 (up or down) */
+	/* this means that the channel indices move up or down by one slot */
+	/* not all new channels may have a valid index yet, but we move */
+	/* all of them anyway, as if they existed */
+	ntimes(tc, 0, 1, R7a);
+	fprintf(tc, "#endif\n\n");
+
+	ntimes(tc, 0, 1, R7b);
+
+	fprintf(tc, "int\naddproc(int calling_pid, int priority, int n");
+	for (/* i = 0 */; i < Npars; i++)
 		fprintf(tc, ", int par%d", i);
 
 	ntimes(tc, 0, 1, Addp0);
 	ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
+
+	if (nclaims > 1)
+	{	fprintf(tc, "#ifndef NOCLAIM\n");
+		ntimes(tc, nrRdy+1, nrRdy+2, R5);
+		fprintf(tc, "#endif\n");
+	}
+
 	ntimes(tc, 0, 1, Addp1);
 
 	if (has_provided)
@@ -132,6 +289,9 @@
 		fprintf(tt, "{\n\tswitch(ot) {\n");
 	}
 shortcut:
+	if (nclaims > 1)
+	{	multi_init();
+	}
 	tc_predef_np();
 	for (p = rdy; p; p = p->nxt)
 	{	Pid = p->tn;
@@ -157,8 +317,17 @@
 do_locinits(FILE *fd)
 {	ProcList *p;
 
+	/* the locinit functions may refer to pptr or qptr */
+	fprintf(fd, "#if VECTORSZ>32000\n");
+	fprintf(fd, "	extern int \n");
+	fprintf(fd, "#else\n");
+	fprintf(fd, "	extern short \n");
+	fprintf(fd, "#endif\n");
+	fprintf(fd, "	*proc_offset, *q_offset;\n");
+
 	for (p = rdy; p; p = p->nxt)
-		c_add_locinit(fd, p->tn, p->n->name);
+	{	c_add_locinit(fd, p->tn, p->n->name);
+	}
 }
 
 void
@@ -167,33 +336,64 @@
 
 	switch (separate) {
 	case 2:
-		if (claimnr >= 0)
-		ntimes(tc, claimnr, claimnr+1, R0); /* claim only */
+		if (nclaims > 0)
+		{	for (p = rdy; p; p = p->nxt)
+			{	if (p->b == N_CLAIM)
+				{	ntimes(tc, p->tn, p->tn+1, R0); /* claims only */
+					fprintf(tc, "#ifdef HAS_CODE\n");
+					ntimes(tc, p->tn, p->tn+1, R00);
+					fprintf(tc, "#endif\n");
+		}	}	}
 		break;
 	case 1:
 		ntimes(tc,     0,    1, Code0);
-		ntimes(tc, 0, claimnr, R0);	/* all except claim */
-		ntimes(tc, claimnr+1, nrRdy, R0);
+		for (p = rdy; p; p = p->nxt)
+		{	if (p->b != N_CLAIM)
+			{	ntimes(tc, p->tn, p->tn+1, R0); /* all except claims */
+				fprintf(tc, "#ifdef HAS_CODE\n");
+				ntimes(tc, p->tn, p->tn+1, R00);
+				fprintf(tc, "#endif\n");
+		}	}
 		break;
 	case 0:
 		ntimes(tc,     0,    1, Code0);
 		ntimes(tc,     0, nrRdy+1, R0); /* +1 for np_ */
+		fprintf(tc, "#ifdef HAS_CODE\n");
+		ntimes(tc,     0, nrRdy+1, R00); /* +1 for np_ */
+		fprintf(tc, "#endif\n");
 		break;
 	}
+	/* new place, make sure Maxbody is set to its final value here */
+	fprintf(tc, "\n");
 
+	if (separate != 2)
+	{	ntimes(tc, 1, u_sync+u_async+1, R3); /* nqs is still 0 */
+		fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);\n");
+		fprintf(tc, "\tif ((Maxbody %% WS) != 0)\n");
+		fprintf(tc, "\t	Maxbody += WS - (Maxbody %% WS);\n\n");
+	}
+
 	for (p = rdy; p; p = p->nxt)
 		end_labs(p->n, p->tn);
 
 	switch (separate) {
 	case 2:
-		if (claimnr >= 0)
-		ntimes(tc, claimnr, claimnr+1, R0a); /* claim only */
+		if (nclaims > 0)
+		{	for (p = rdy; p; p = p->nxt)
+			{	if (p->b == N_CLAIM)
+				{	ntimes(tc, p->tn, p->tn+1, R0a); /* claims only */
+		}	}	}
 		return;
 	case 1:
-		ntimes(tc, 0, claimnr, R0a);	/* all except claim */
-		ntimes(tc, claimnr+1, nrRdy, R0a);
+		for (p = rdy; p; p = p->nxt)
+		{	if (p->b != N_CLAIM)
+			{	ntimes(tc, p->tn, p->tn+1, R0a); /* all except claims */
+		}	}
 		fprintf(tc, "	if (state_tables)\n");
-		fprintf(tc, "		ini_claim(%d, 0);\n", claimnr);
+		fprintf(tc, "		ini_claim(%d, 0);\n", claimnr);	/* the default claim */
+		if (acceptors == 0)
+		{	acceptors = 1;	/* assume at least 1 acceptstate */
+		}
 		break;
 	case 0:
 		ntimes(tc, 0, nrRdy, R0a);	/* all */
@@ -200,30 +400,25 @@
 		break;
 	}
 
-	ntimes(tc, 0,     1, R0b);
-	if (separate == 1 && acceptors == 0)
-		acceptors = 1;	/* assume at least 1 acceptstate */
 	ntimes(th, acceptors,   acceptors+1,   Code1);
 	ntimes(th, progressors, progressors+1, Code3);
-	ntimes(th, nrRdy+1, nrRdy+2, R2); /* +1 for np_ */
 
-	fprintf(tc, "	iniglobals();\n");
-	ntimes(tc, 0,     1, Code2a);
-	ntimes(tc, 0,     1, Code2b);	/* bfs option */
-	ntimes(tc, 0,     1, Code2c);
+	ntimes(tc, 0,     1, Code2a);	/* dfs, bfs */
+	ntimes(tc, 0,     1, Code2e);	/* multicore */
+	ntimes(tc, 0,     1, Code2c);	/* multicore */
+	ntimes(tc, 0,     1, Code2d);
+
+	fprintf(tc, "void\ndo_reach(void)\n{\n");
 	ntimes(tc, 0,     nrRdy, R4);
 	fprintf(tc, "}\n\n");
 
-	fprintf(tc, "void\n");
-	fprintf(tc, "iniglobals(void)\n{\n");
+	fprintf(tc, "void\niniglobals(int calling_pid)\n{\n");
 	if (doglobal("", INIV) > 0)
 	{	fprintf(tc, "#ifdef VAR_RANGES\n");
 		(void) doglobal("logval(\"", LOGV);
 		fprintf(tc, "#endif\n");
 	}
-	ntimes(tc, 1, nqs+1, R3);
-	fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);");
-	fprintf(tc, "\n}\n\n");
+	fprintf(tc, "}\n\n");
 }
 
 void
@@ -248,17 +443,17 @@
 	Label *l;
 	int j; char foo[128];
 
-	if ((i == claimnr && separate == 1)
-	||  (i != claimnr && separate == 2))
+	if ((pid_is_claim(i) && separate == 1)
+	|| (!pid_is_claim(i) && separate == 2))
 		return;
 
 	for (l = labtab; l; l = l->nxt)
 	for (j = 0; ln[j].n; j++)
-		if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0
+	{	if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0
 		&&  strcmp(l->c->name, s->name) == 0)
 		{	fprintf(tc, "\t%s[%d][%d] = 1;\n",
 				ln[j].t, i, l->e->seqno);
-			acceptors += ln[j].m;
+			acceptors   += ln[j].m;
 			progressors += ln[j].p;
 			if (l->e->status & D_ATOM)
 			{	sprintf(foo, "%s label inside d_step",
@@ -272,8 +467,7 @@
 				Fname  = l->e->n->fn;
 				printf("spin: %3d:%s, warning, %s - is invisible\n",
 					lineno, Fname?Fname->name:"-", foo);
-			}
-		}	
+	}	}	}	
 	/* visible states -- through remote refs: */
 	for (l = labtab; l; l = l->nxt)
 		if (l->visible
@@ -286,7 +480,7 @@
 }
 
 void
-ntimes(FILE *fd, int n, int m, char *c[])
+ntimes(FILE *fd, int n, int m, const char *c[])
 {
 	int i, j;
 	for (j = 0; c[j]; j++)
@@ -305,7 +499,7 @@
 
 	n = (s->context != ZS)?s->context->ini:s->ini;
 	if (n)
-	printf("line %3d %s, ", n->ln, n->fn->name);
+	printf("line %s:%d, ", n->fn->name, n->ln);
 }
 
 void
@@ -338,7 +532,7 @@
 	{	if (!(verbose&32)) return;
 		sputtype(buf, sp->type);
 		i = (int) strlen(buf);
-		while (buf[--i] == ' ') buf[i] = '\0';
+		while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
 		prehint(sp);
 		if (sp->context)
 			printf("proctype %s:", s);
@@ -361,12 +555,12 @@
 	}
 }
 
-int
-dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s)
+static int
+dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s, enum btypes b)
 {	int h, j, k=0; extern int nr_errs;
 	Ordered *walk;
 	Symbol *sp;
-	char buf[64], buf2[128], buf3[128];
+	char buf[128], buf2[128], buf3[128];
 
 	if (dowhat == INIV)
 	{	/* initialize in order of declaration */
@@ -390,7 +584,8 @@
 			if (sp->context
 			&& !sp->owner
 			&&  sp->type == Types[j]
-			&&  ((h == 0 && sp->nel == 1) || (h == 1 && sp->nel > 1))
+			&&  ((h == 0 && (sp->nel == 1 && sp->isarray == 0))
+			||   (h == 1 && (sp->nel  > 1 || sp->isarray == 1)))
 			&&  strcmp(s, sp->context->name) == 0)
 			{	switch (dowhat) {
 				case LOGV:
@@ -409,7 +604,7 @@
 					k++;
 					break;
 				}
-				if (strcmp(s, ":never:") == 0)
+				if (b == N_CLAIM)
 				{	printf("error: %s defines local %s\n",
 						s, sp->name);
 					nr_errs++;
@@ -425,8 +620,8 @@
 	int i;
 
 	if (!qtab)
-	{	fprintf(fd, "void\nc_chandump(int unused) ");
-		fprintf(fd, "{ unused = unused++; /* avoid complaints */ }\n");
+	{	fprintf(fd, "void\nc_chandump(int unused)\n");
+		fprintf(fd, "{\tunused++; /* avoid complaints */\n}\n");
 		return;
 	}
 
@@ -465,9 +660,19 @@
 
 void
 c_var(FILE *fd, char *pref, Symbol *sp)
-{	char buf[256];
+{	char *ptr, buf[256];
 	int i;
 
+	if (!sp)
+	{	fatal("cannot happen - c_var", 0);
+	}
+
+	ptr = sp->name;
+	if (!old_scope_rules)
+	{	while (*ptr == '_' || isdigit((int)*ptr))
+		{	ptr++;
+	}	}
+
 	switch (sp->type) {
 	case STRUCT:
 		/* c_struct(fd, pref, sp); */
@@ -476,27 +681,33 @@
 		sprintf(buf, "%s%s.", pref, sp->name);
 		c_struct(fd, buf, sp);
 		break;
+	case MTYPE:
 	case BIT:   case BYTE:
 	case SHORT: case INT:
 	case UNSIGNED:
 		sputtype(buf, sp->type);
-		if (sp->nel == 1)
-		{	fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
-				buf, sp->name, pref, sp->name);
+		if (sp->nel == 1 && sp->isarray == 0)
+		{
+			if (sp->type == MTYPE && ismtype(sp->name))
+			{	fprintf(fd, "\tprintf(\"\t%s %s:\t%d\\n\");\n",
+					buf, ptr, ismtype(sp->name));
+			} else
+			{	fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
+					buf, ptr, pref, sp->name);
+			}
 		} else
 		{	fprintf(fd, "\t{\tint l_in;\n");
 			fprintf(fd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
 			fprintf(fd, "\t\t{\n");
 			fprintf(fd, "\t\t\tprintf(\"\t%s %s[%%d]:\t%%d\\n\", l_in, %s%s[l_in]);\n",
-						buf, sp->name, pref, sp->name);
+						buf, ptr, pref, sp->name);
 			fprintf(fd, "\t\t}\n");
 			fprintf(fd, "\t}\n");
 		}
 		break;
 	case CHAN:
-		if (sp->nel == 1)
-		{  fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ",
-			sp->name);
+		if (sp->nel == 1 && sp->isarray == 0)
+		{  fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ", ptr);
 		   fprintf(fd, "%s%s, q_len(%s%s));\n",
 			pref, sp->name, pref, sp->name);
 		   fprintf(fd, "\tc_chandump(%s%s);\n", pref, sp->name);
@@ -503,7 +714,7 @@
 		} else
 		for (i = 0; i < sp->nel; i++)
 		{  fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ",
-			sp->name, i);
+			ptr, i);
 		   fprintf(fd, "%s%s[%d], q_len(%s%s[%d]));\n",
 			pref, sp->name, i, pref, sp->name, i);
 		   fprintf(fd, "\tc_chandump(%s%s[%d]);\n",
@@ -518,9 +729,7 @@
 {	Ordered *walk;
 	Symbol *sp;
 
-	if (strcmp(p->n->name, ":never:") != 0
-	&&  strcmp(p->n->name, ":trace:") != 0
-	&&  strcmp(p->n->name, ":notrace:") != 0)
+	if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
 	for (walk = all_names; walk; walk = walk->next)
 	{	sp = walk->entry;
 		if (!sp->context
@@ -541,9 +750,7 @@
 	Symbol *sp;
 	char pref[64];
 
-	if (strcmp(p->n->name, ":never:") != 0
-	&&  strcmp(p->n->name, ":trace:") != 0
-	&&  strcmp(p->n->name, ":notrace:") != 0)
+	if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
 	for (walk = all_names; walk; walk = walk->next)
 	{	sp = walk->entry;
 		if (!sp->context
@@ -571,10 +778,8 @@
 	fprintf(fd, "	printf(\"global vars:\\n\");\n");
 	for (walk = all_names; walk; walk = walk->next)
 	{	sp = walk->entry;
-		if (sp->context || sp->owner || (sp->hidden&1)
-		|| (sp->type == MTYPE && ismtype(sp->name)))
+		if (sp->context || sp->owner || (sp->hidden&1))
 			continue;
-
 		c_var(fd, "now.", sp);
 	}
 	fprintf(fd, "}\n");
@@ -583,8 +788,6 @@
 	fprintf(fd, "	switch(tp) {\n");
 	for (p = rdy; p; p = p->nxt)
 	{	fprintf(fd, "	case %d:\n", p->tn);
-		fprintf(fd, "	\tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
-			p->n->name);
 		if (c_splurge_any(p))
 		{	fprintf(fd, "	\tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
 				p->n->name);
@@ -633,8 +836,9 @@
 				checktype(sp, (char *) 0);
 				cnt++; /* fall through */
 			case PUTV:
-				do_var(tc, dowhat, (sp->hidden&1)?"":"now.", sp,
-				"", " = ", ";\n");
+				do_var(tc, dowhat,
+					(sp->hidden&1)?"":"now.", sp,
+					"", " = ", ";\n");
 				break;
 	}	}	}
 	return cnt;
@@ -652,13 +856,12 @@
 		if ((sp->hidden&1)
 		&&  sp->type == Types[j])
 		{	if (sp->context || sp->owner)
-			fatal("cannot hide non-globals (%s)", sp->name);
+			  fatal("cannot hide non-globals (%s)", sp->name);
 			if (sp->type == CHAN)
-			fatal("cannot hide channels (%s)", sp->name);
+			  fatal("cannot hide channels (%s)", sp->name);
 			fprintf(th, "/* hidden variable: */");
 			typ2c(sp);
 	}	}
-	fprintf(th, "int _; /* a predefined write-only variable */\n\n");
 }
 
 void
@@ -665,15 +868,25 @@
 do_var(FILE *ofd, int dowhat, char *s, Symbol *sp,
 	char *pre, char *sep, char *ter)
 {	int i;
+	char *ptr = sp?sp->name:"";
 
+	if (!sp)
+	{	fatal("cannot happen - do_var", 0);
+	}
+
 	switch(dowhat) {
 	case PUTV:
-
 		if (sp->hidden&1) break;
 
 		typ2c(sp);
 		break;
+
 	case LOGV:
+		if (!old_scope_rules)
+		{	while (*ptr == '_' || isdigit((int)*ptr))
+			{	ptr++;
+		}	}
+		/* fall thru */
 	case INIV:
 		if (sp->type == STRUCT)
 		{	/* struct may contain a chan */
@@ -682,13 +895,16 @@
 		}
 		if (!sp->ini && dowhat != LOGV)	/* it defaults to 0 */
 			break;
-		if (sp->nel == 1)
-		{	fprintf(ofd, "\t\t%s%s%s%s",
-				pre, s, sp->name, sep);
-			if (dowhat == LOGV)
+		if (sp->nel == 1 && sp->isarray == 0)
+		{	if (dowhat == LOGV)
+			{	fprintf(ofd, "\t\t%s%s%s%s",
+					pre, s, ptr, sep);
 				fprintf(ofd, "%s%s", s, sp->name);
-			else
+			} else
+			{	fprintf(ofd, "\t\t%s%s%s%s",
+					pre, s, sp->name, sep);
 				do_init(ofd, sp);
+			}
 			fprintf(ofd, "%s", ter);
 		} else
 		{	if (sp->ini && sp->ini->ntyp == CHAN)
@@ -702,20 +918,38 @@
 						do_init(ofd, sp);
 					fprintf(ofd, "%s", ter);
 				}
-			} else
-			{	fprintf(ofd, "\t{\tint l_in;\n");
-				fprintf(ofd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
-				fprintf(ofd, "\t\t{\n");
-				fprintf(ofd, "\t\t\t%s%s%s[l_in]%s",
+			} else if (sp->ini)
+			{	if (dowhat != LOGV && sp->isarray && sp->ini->ntyp == ',')
+				{	Lextok *z, *y;
+					z = sp->ini;
+					for (i = 0; i < sp->nel; i++)
+					{	if (z && z->ntyp == ',')
+						{	y = z->lft;
+							z = z->rgt;
+						} else
+						{	y = z;
+						}
+						fprintf(ofd, "\t\t%s%s%s[%d]%s",
+							pre, s, sp->name, i, sep);
+						putstmnt(ofd, y, 0);
+						fprintf(ofd, "%s", ter);
+					}
+				} else
+				{	fprintf(ofd, "\t{\tint l_in;\n");
+					fprintf(ofd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n",
+						sp->nel);
+					fprintf(ofd, "\t\t{\n");
+					fprintf(ofd, "\t\t\t%s%s%s[l_in]%s",
 						pre, s, sp->name, sep);
-				if (dowhat == LOGV)
-					fprintf(ofd, "%s%s[l_in]", s, sp->name);
-				else
-					putstmnt(ofd, sp->ini, 0);
-				fprintf(ofd, "%s", ter);
-				fprintf(ofd, "\t\t}\n");
-				fprintf(ofd, "\t}\n");
-		}	}
+					if (dowhat == LOGV)
+					{	fprintf(ofd, "%s%s[l_in]", s, sp->name);
+					} else
+					{	putstmnt(ofd, sp->ini, 0);
+					}
+					fprintf(ofd, "%s", ter);
+					fprintf(ofd, "\t\t}\n");
+					fprintf(ofd, "\t}\n");
+		}	}	}
 		break;
 	}
 }
@@ -722,57 +956,48 @@
 
 static void
 do_init(FILE *ofd, Symbol *sp)
-{	int i; extern Queue *ltab[];
+{	int i; 
 
 	if (sp->ini
 	&&  sp->type == CHAN
 	&& ((i = qmake(sp)) > 0))
 	{	if (sp->ini->ntyp == CHAN)
-			fprintf(ofd, "addqueue(%d, %d)",
-			i, ltab[i-1]->nslots == 0);
-		else
-			fprintf(ofd, "%d", i);
+		{	fprintf(ofd, "addqueue(calling_pid, %d, %d)",
+				i, ltab[i-1]->nslots == 0);
+		} else
+		{	fprintf(ofd, "%d", i);
+		}
 	} else
-		putstmnt(ofd, sp->ini, 0);
+	{	putstmnt(ofd, sp->ini, 0);
+	}
 }
 
-static int
-blog(int n)	/* for small log2 without rounding problems */
-{	int m=1, r=2;
-
-	while (r < n) { m++; r *= 2; }
-	return 1+m;
-}
-
 static void
-put_ptype(char *s, int i, int m0, int m1)
+put_ptype(char *s, int i, int m0, int m1, enum btypes b)
 {	int k;
 
-	if (strcmp(s, ":init:") == 0)
-		fprintf(th, "#define Pinit	((P%d *)this)\n", i);
+	if (b == I_PROC)
+	{	fprintf(th, "#define Pinit	((P%d *)this)\n", i);
+	} else if (b == P_PROC || b == A_PROC)
+	{	fprintf(th, "#define P%s	((P%d *)this)\n", s, i);
+	}
 
-	if (strcmp(s, ":never:") != 0
-	&&  strcmp(s, ":trace:") != 0
-	&&  strcmp(s, ":notrace:") != 0
-	&&  strcmp(s, ":init:")  != 0
-	&&  strcmp(s, "_:never_template:_") != 0
-	&&  strcmp(s, "np_")     != 0)
-		fprintf(th, "#define P%s	((P%d *)this)\n", s, i);
-
 	fprintf(th, "typedef struct P%d { /* %s */\n", i, s);
 	fprintf(th, "	unsigned _pid : 8;  /* 0..255 */\n");
 	fprintf(th, "	unsigned _t   : %d; /* proctype */\n", blog(m1));
 	fprintf(th, "	unsigned _p   : %d; /* state    */\n", blog(m0));
+	fprintf(th, "#ifdef HAS_PRIORITY\n");
+	fprintf(th, "	unsigned _priority : 8; /* 0..255 */\n");
+	fprintf(th, "#endif\n");
 	LstSet = ZS;
 	nBits = 8 + blog(m1) + blog(m0);
-	k = dolocal(tc, "", PUTV, i, s);	/* includes pars */
-
+	k = dolocal(tc, "", PUTV, i, s, b);	/* includes pars */
 	c_add_loc(th, s);
 
 	fprintf(th, "} P%d;\n", i);
 	if ((!LstSet && k > 0) || has_state)
-		fprintf(th, "#define Air%d	0\n", i);
-	else
+		fprintf(th, "#define Air%d	0\n\n", i);
+	else if (LstSet || k == 0)			/* 5.0, added condition */
 	{	fprintf(th, "#define Air%d	(sizeof(P%d) - ", i, i);
 		if (k == 0)
 		{	fprintf(th, "%d", (nBits+7)/8);
@@ -802,35 +1027,79 @@
 			fatal("cannot happen Air %s",
 				LstSet->name);
 		}
-done:		fprintf(th, ")\n");
+done:		fprintf(th, ")\n\n");
 	}
 }
 
 static void
 tc_predef_np(void)
-{	int i = nrRdy;	/* 1+ highest proctype nr */
+{
+	fprintf(th, "#define _NP_	%d\n", nrRdy);	/* 1+ highest proctype nr */
 
-	fprintf(th, "#define _NP_	%d\n", i);
-/*	if (separate == 2) fprintf(th, "extern ");	*/
-	fprintf(th, "uchar reached%d[3];  /* np_ */\n", i);
+	fprintf(th, "#define _nstates%d	3 /* np_ */\n", nrRdy);
+	fprintf(th, "#define _endstate%d	2 /* np_ */\n\n", nrRdy);
+	fprintf(th, "#define _start%d	0 /* np_ */\n", nrRdy);
 
-	fprintf(th, "#define nstates%d	3 /* np_ */\n", i);
-	fprintf(th, "#define endstate%d	2 /* np_ */\n\n", i);
-	fprintf(th, "#define start%d	0 /* np_ */\n", i);
-
-	fprintf(tc, "\tcase %d:	/* np_ */\n", i);
+	fprintf(tc, "\tcase %d:	/* np_ */\n", nrRdy);
 	if (separate == 1)
-	{	fprintf(tc, "\t\tini_claim(%d, h);\n", i);
+	{	fprintf(tc, "\t\tini_claim(%d, h);\n", nrRdy);
 	} else
-	{	fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
-		fprintf(tc, "\t\t((P%d *)pptr(h))->_p = 0;\n", i);
-		fprintf(tc, "\t\treached%d[0] = 1;\n", i);
-		fprintf(tc, "\t\taccpstate[%d][1] = 1;\n", i);
+	{	fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", nrRdy, nrRdy);
+		fprintf(tc, "\t\t((P%d *)pptr(h))->_p = 0;\n", nrRdy);
+
+		fprintf(tc, "#ifdef HAS_PRIORITY\n");
+		fprintf(tc, "\t\t((P%d *)pptr(h))->_priority = priority;\n", nrRdy);
+		fprintf(tc, "#endif\n");
+
+		fprintf(tc, "\t\treached%d[0] = 1;\n", nrRdy);
+		fprintf(tc, "\t\taccpstate[%d][1] = 1;\n", nrRdy);
 	}
 	fprintf(tc, "\t\tbreak;\n");
 }
 
 static void
+multi_init(void)
+{	ProcList *p;
+	Element	*e;
+	int i = nrRdy+1;
+	int ini, j;
+	int nrc = nclaims;
+
+	fprintf(tc, "#ifndef NOCLAIM\n");
+	fprintf(tc, "\tcase %d:	/* claim select */\n", i);
+	for (p = rdy, j = 0; p; p = p->nxt, j++)
+	{	if (p->b == N_CLAIM)
+		{	e = p->s->frst;
+			ini = huntele(e, e->status, -1)->seqno;
+
+			fprintf(tc, "\t\tspin_c_typ[%d] = %d; /* %s */\n",
+				j, p->tn, p->n->name);
+			fprintf(tc, "\t\t((P%d *)pptr(h))->c_cur[%d] = %d;\n",
+				i, j, ini);
+			fprintf(tc, "\t\treached%d[%d]=1;\n", p->tn, ini);
+
+			/* the default initial claim is first one in model */
+			if (--nrc == 0)	
+			{ fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, p->tn);
+			  fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini);
+			  fprintf(tc, "\t\t((P%d *)pptr(h))->_n = %d; /* %s */\n",
+				i, j, p->n->name);
+			  fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", p->tn);
+			  fprintf(tc, "#ifndef BFS\n");
+			  fprintf(tc, "\t\tif (whichclaim == -1 && claimname == NULL)\n");
+			  fprintf(tc, "\t\t\tprintf(\"0: Claim %s (%d), from state %d\\n\");\n",
+				p->n->name, p->tn, ini);
+			  fprintf(tc, "#endif\n");
+			}
+	}	}
+	fprintf(tc, "\t\tif (whichclaim != -1)\n");
+	fprintf(tc, "\t\t{	select_claim(whichclaim);\n");
+	fprintf(tc, "\t\t}\n");
+	fprintf(tc, "\t\tbreak;\n\n");
+	fprintf(tc, "#endif\n");
+}
+
+static void
 put_pinit(ProcList *P)
 {	Lextok	*fp, *fpt, *t;
 	Element	*e = P->s->frst;
@@ -839,7 +1108,7 @@
 	int	 i = P->tn;
 	int	ini, j, k;
 
-	if (i == claimnr
+	if (pid_is_claim(i)
 	&&  separate == 1)
 	{	fprintf(tc, "\tcase %d:	/* %s */\n", i, s->name);
 		fprintf(tc, "\t\tini_claim(%d, h);\n", i);
@@ -846,14 +1115,12 @@
 		fprintf(tc, "\t\tbreak;\n");
 		return;
 	}
-	if (i != claimnr
+	if (!pid_is_claim(i)
 	&&  separate == 2)
 		return;
 
 	ini = huntele(e, e->status, -1)->seqno;
-	fprintf(th, "#define start%d	%d\n", i, ini);
-	if (i == claimnr)
-	fprintf(th, "#define start_claim	%d\n", ini);
+	fprintf(th, "#define _start%d	%d\n", i, ini);
 	if (i == eventmapnr)
 	fprintf(th, "#define start_event	%d\n", ini);
 
@@ -860,9 +1127,18 @@
 	fprintf(tc, "\tcase %d:	/* %s */\n", i, s->name);
 
 	fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
-	fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;", i, ini);
-	fprintf(tc, " reached%d[%d]=1;\n", i, ini);
+	fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini);
+	fprintf(tc, "#ifdef HAS_PRIORITY\n");
 
+	fprintf(tc, "\t\t((P%d *)pptr(h))->_priority = priority; /* was: %d */\n",
+		i, (P->priority<1)? 1 : P->priority);
+
+	fprintf(tc, "#endif\n");
+	fprintf(tc, "\t\treached%d[%d]=1;\n", i, ini);
+	if (P->b == N_CLAIM)
+	{	fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", i);
+	}
+
 	if (has_provided)
 	{	fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name);
 		if (P->prov)
@@ -879,7 +1155,7 @@
 	for (fp  = p, j=0; fp; fp = fp->rgt)
 	for (fpt = fp->lft; fpt; fpt = fpt->rgt, j++)
 	{	t = (fpt->ntyp == ',') ? fpt->lft : fpt;
-		if (t->sym->nel != 1)
+		if (t->sym->nel > 1 || t->sym->isarray)
 		{	lineno = t->ln;
 			Fname  = t->fn;
 			fatal("array in parameter list, %s",
@@ -898,10 +1174,10 @@
 		fprintf(tc, " = par%d;\n", j);
 	}
 	fprintf(tc, "\t\t/* locals: */\n");
-	k = dolocal(tc, "", INIV, i, s->name);
+	k = dolocal(tc, "", INIV, i, s->name, P->b);
 	if (k > 0)
 	{	fprintf(tc, "#ifdef VAR_RANGES\n");
-		(void) dolocal(tc, "logval(\"", LOGV, i, s->name);
+		(void) dolocal(tc, "logval(\"", LOGV, i, s->name, P->b);
 		fprintf(tc, "#endif\n");
 	}
 
@@ -929,17 +1205,19 @@
 	}	}
 
 	if (cnt >= 200 || !e)
-		fatal("confusing control structure", (char *) 0);
+	{	lineno = (f && f->n)?f->n->ln:lineno;
+		fatal("confusing control. structure", (char *) 0);
+	}
 	return e;
 }
 
 Element *
-huntele(Element *f, int o, int stopat)
+huntele(Element *f, unsigned int o, int stopat)
 {	Element *g, *e = f;
 	int cnt=0; /* a precaution against loops */
 
 	if (e)
-	for (cnt = 0; cnt < 200 && e->n; cnt++)
+	for ( ; cnt < 500 && e->n; cnt++)
 	{
 		if (e->seqno == stopat)
 			break;
@@ -947,6 +1225,10 @@
 		switch (e->n->ntyp) {
 		case GOTO:
 			g = get_lab(e->n,1);
+			if (e == g)
+			{	lineno = (f && f->n)?f->n->ln:lineno;
+				fatal("infinite goto loop", (char *) 0);
+			}
 			cross_dsteps(e->n, g->n);
 			break;
 		case '.':
@@ -957,6 +1239,9 @@
 			break;
 		case UNLESS:
 			g = huntele(e->sub->this->frst, o, stopat);
+			if (!g)
+			{	fatal("unexpected error 1", (char *) 0);
+			}
 			break;
 		case D_STEP:
 		case ATOMIC:
@@ -968,8 +1253,10 @@
 			return e;
 		e = g;
 	}
-	if (cnt >= 200 || !e)
+	if (cnt >= 500 || !e)
+	{	lineno = (f && f->n)?f->n->ln:lineno;
 		fatal("confusing control structure", (char *) 0);
+	}
 	return e;
 }
 
@@ -992,7 +1279,7 @@
 		nBits += sp->nbits;
 		break;
 	case BIT:
-		if (sp->nel == 1 && !(sp->hidden&1))
+		if (sp->nel == 1 && sp->isarray == 0 && !(sp->hidden&1))
 		{	fprintf(th, "\tunsigned %s : 1", sp->name);
 			LstSet = sp; 
 			nBits++;
@@ -1031,13 +1318,13 @@
 		fatal("variable %s undeclared", sp->name);
 	}
 
-	if (sp->nel != 1)
+	if (sp->nel > 1 || sp->isarray)
 		fprintf(th, "[%d]", sp->nel);
 	fprintf(th, ";\n");
 }
 
 static void
-ncases(FILE *fd, int p, int n, int m, char *c[])
+ncases(FILE *fd, int p, int n, int m, const char *c[])
 {	int i, j;
 
 	for (j = 0; c[j]; j++)
@@ -1067,12 +1354,11 @@
 	Queue *q;
 
 	ntimes(tc, 0, 1, Addq0);
+
 	if (has_io && !nqs)
 		fprintf(th, "#define NQS	1 /* nqs=%d, but has_io */\n", nqs);
 	else
 		fprintf(th, "#define NQS	%d\n", nqs);
-	fprintf(th, "short q_flds[%d];\n", nqs+1);
-	fprintf(th, "short q_max[%d];\n", nqs+1);
 
 	for (q = qtab; q; q = q->nxt)
 		if (q->nslots > qmax)
@@ -1124,6 +1410,22 @@
 
 	ntimes(tc, 0, 1, Addq1);
 
+	fprintf(tc, "#ifdef TRIX\n");
+	fprintf(tc, "int\nwhat_p_size(int t)\n{\tint j;\n");
+	fprintf(tc, "	switch (t) {\n");
+	ntimes(tc, 0, nrRdy+1, R5); /* +1 for np_ */
+	fprintf(tc, "	default: Uerror(\"bad proctype\");\n");
+	fprintf(tc, "	}\n	return j;\n}\n\n");
+
+	fprintf(tc, "int\nwhat_q_size(int t)\n{\tint j;\n");
+	fprintf(tc, "	switch (t) {\n");
+	for (j = 0; j < nqs+1; j++)
+	{	fprintf(tc, "	case %d: j = sizeof(Q%d); break;\n", j, j);
+	}
+	fprintf(tc, "	default: Uerror(\"bad qtype\");\n");
+	fprintf(tc, "	}\n	return j;\n}\n");
+	fprintf(tc, "#endif\n\n");
+
 	if (has_random)
 	{	fprintf(th, "int Q_has(int");
 		for (j = 0; j < Mpars; j++)
@@ -1159,7 +1461,7 @@
 	fprintf(tc, "void\nqsend(int into, int sorted");
 	for (j = 0; j < Mpars; j++)
 		fprintf(tc, ", int fld%d", j);
-	fprintf(tc, ")\n");
+	fprintf(tc, ", int args_given)\n");
 	ntimes(tc, 0, 1, Addq11);
 
 	for (q = qtab; q; q = q->nxt)
@@ -1202,6 +1504,12 @@
 		sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
 		for (j = 0; j < q->nflds; j++)
 			fprintf(tc, "\t\t%s%d = fld%d;\n", buf0, j, j);
+		fprintf(tc, "\t\tif (args_given != %d)\n", q->nflds);
+		fprintf(tc, "\t\t{	if (args_given > %d)\n", q->nflds);
+		fprintf(tc, "\t\t		uerror(\"too many parameters in send stmnt\");\n");
+		fprintf(tc, "\t\t	else\n");
+		fprintf(tc, "\t\t		uerror(\"too few parameters in send stmnt\");\n");
+		fprintf(tc, "\t\t}\n");
 		fprintf(tc, "\t\tbreak;\n");
 	}
 	ntimes(tc, 0, 1, Addq2);
@@ -1261,14 +1569,15 @@
 	fprintf(tc, "	case %d: j = sizeof(Q%d); break;\n",
 		q->qid, q->qid);
 	ntimes(tc, 0, 1, R8b);
+	ntimes(th, 0, 1, Proto);	/* function prototypes */
 
-	ntimes(th, 0, 1, Proto);	/* tag on function prototypes */
 	fprintf(th, "void qsend(int, int");
 	for (j = 0; j < Mpars; j++)
 		fprintf(th, ", int");
-	fprintf(th, ");\n");
+	fprintf(th, ", int);\n\n");
 
-	fprintf(th, "#define Addproc(x)	addproc(x");
+	fprintf(th, "#define Addproc(x,y)	addproc(256, y, x");
+	/* 256 is param outside the range of valid pids */
 	for (j = 0; j < Npars; j++)
 		fprintf(th, ", 0");
 	fprintf(th, ")\n");
--- a/sys/src/cmd/spin/pangen1.h
+++ b/sys/src/cmd/spin/pangen1.h
@@ -1,20 +1,56 @@
 /***** spin: pangen1.h *****/
 
-/* Copyright (c) 1989-2005 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
-static char *Code2a[] = { /* the tail of procedure run() */
-	"#if defined(VERI) && !defined(NOREDUCE) && !defined(NP)",
+static const char *Code2a[] = { /* the tail of procedure run() */
+	"	if (state_tables)",
+	"	{ if (dodot) exit(0);",
+	"	  printf(\"\\nTransition Type: \");",
+	"	  printf(\"A=atomic; D=d_step; L=local; G=global\\n\");",
+	"	  printf(\"Source-State Labels: \");",
+	"	  printf(\"p=progress; e=end; a=accept;\\n\");",
+	"#ifdef MERGED",
+	"	  printf(\"Note: statement merging was used. Only the first\\n\");",
+	"	  printf(\"      stmnt executed in each merge sequence is shown\\n\");",
+	"	  printf(\"      (use spin -a -o3 to disable statement merging)\\n\");",
+	"#endif",
+	"	  pan_exit(0);",
+	"	}",
+	"#if defined(BFS) && defined(TRIX)", /* before iniglobals */
+	"	{ int i;",
+	"	  for (i = 0; i < MAXPROC+1; i++)",
+	"	  {	processes[i] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));",
+	"		processes[i]->body = (uchar *) emalloc(Maxbody * sizeof(char));",
+	"	  }",
+	"	  for (i = 0; i < MAXQ+1; i++)",
+	"	  {	channels[i] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));",
+	"		channels[i]->body = (uchar *) emalloc(Maxbody * sizeof(char));",
+	"	} }",
+	"#endif",
+	"#ifdef BFS_PAR",
+	"	bfs_setup_mem();",
+	"	#ifdef COLLAPSE",
+	"	/* this must be the very first allocation from the shared heap */",
+	"		#ifdef BFS_SEP_HASH",
+	"		ncomps = (ulong *) emalloc((ulong)((256+2) * sizeof(ulong)));",
+	"		#else",
+	"		ncomps = (ulong *) sh_pre_malloc((ulong)((256+2) * sizeof(ulong)));",
+	"		#endif",
+	"	#endif",
+	"#endif",
+	"	iniglobals(258); /* arg outside range of pids */",
+	"#if defined(VERI) && !defined(NOREDUCE) && !defined(NP) && !defined(BFS) && !defined(HAS_LTL)",
 	"	if (!state_tables",
-	"#ifdef HAS_CODE",
+	"	#ifdef HAS_CODE",
 	"	&& !readtrail",
-	"#endif",
+	"	#endif",
+	"	#if NCORE>1",
+	"	&& core_id == 0",
+	"	#endif",
 	"	)",
 	"	{ printf(\"warning: for p.o. reduction to be valid \");",
 	"	  printf(\"the never claim must be stutter-invariant\\n\");",
@@ -24,14 +60,7 @@
 	"#endif",
 	"	UnBlock;	/* disable rendez-vous */",
 	"#ifdef BITSTATE",
-#ifndef POWOW
-	"	if (udmem)",
-	"	{	udmem *= 1024L*1024L;",
-	"		SS = (uchar *) emalloc(udmem);",
-	"		bstore = bstore_mod;",
-	"	} else",
-#endif
-	"	SS = (uchar *) emalloc(1L<<(ssize-3));",
+	"	sinit();",
 	"#else",
 	"	hinit();",
 	"#endif",
@@ -39,18 +68,24 @@
 	"	onstack_init();",
 	"#endif",
 	"#if defined(CNTRSTACK) && !defined(BFS)",
-	"	LL = (uchar *) emalloc(1L<<(ssize-3));",
+	"	LL = (uchar *) emalloc(ONE_L<<(ssize-3));",
 	"#endif",
-	"	stack	= ( Stack *) emalloc(sizeof(Stack));",
+	"	stack	= (_Stack *) emalloc(sizeof(_Stack));",
 	"	svtack	= (Svtack *) emalloc(sizeof(Svtack));",
 	"	/* a place to point for Pptr of non-running procs: */",
-	"	noptr	= (uchar *) emalloc(Maxbody * sizeof(char));",
-	"#ifdef SVDUMP",
+	"	noqptr = noptr	= (uchar *) emalloc(Maxbody * sizeof(char));",
+	"#if defined(SVDUMP) && defined(VERBOSE)",
 	"	if (vprefix > 0)",
-	"		write(svfd, (uchar *) &vprefix, sizeof(int));",
+	"		(void) write(svfd, (uchar *) &vprefix, sizeof(int));",
 	"#endif",
 	"#ifdef VERI",
-	"	Addproc(VERI);	/* never - pid = 0 */",
+	"	Addproc(VERI,1);	/* pid = 0, priority 1 */",
+	"	#if NCLAIMS>1",
+	"	if (claimname != NULL)",
+	"	{	whichclaim = find_claim(claimname);",
+	"		select_claim(whichclaim);",
+	"	}",
+	"	#endif",
 	"#endif",
 	"	active_procs();	/* started after never */",
 	"#ifdef EVENT_TRACE",
@@ -66,17 +101,21 @@
 	"#endif",
 	"	do_the_search();",
 	"#ifdef BITSTATE",
-	"	if (--Nrun > 0 && HASH_CONST[++HASH_NR])",
+	"	if (--Nrun > 0 && HASH_CONST[++HASH_NR])", /* last entry is 0 */
 	"	{	printf(\"Run %%d:\\n\", HASH_NR);",
 	"		wrap_stats();",
 	"		printf(\"\\n\");",
-	"		memset(SS, 0, 1L<<(ssize-3));",
-		"#if defined(CNTRSTACK)",
-	"		memset(LL, 0, 1L<<(ssize-3));",
+	"		if (udmem)	/* Dillinger 3/2/09 */",
+	"		{	memset(SS, 0, udmem);",
+	"		} else",
+	"		{	memset(SS, 0, ONE_L<<(ssize-3));",
+	"		}",
+		"#ifdef CNTRSTACK",
+	"		memset(LL, 0, ONE_L<<(ssize-3));",
 		"#endif",
-		"#if defined(FULLSTACK)",
+		"#ifdef FULLSTACK",
 	"		memset((uchar *) S_Tab, 0, ",
-	"		maxdepth*sizeof(struct H_el *));",
+	"		maxdepth*sizeof(H_el *));",
 		"#endif",
 	"		nstates=nlinks=truncs=truncs2=ngrabs = 0;",
 	"		nlost=nShadow=hcmp = 0;",
@@ -86,10 +125,159 @@
 	"	}",
 	"#endif",
 	"}",
+	"#ifdef HAS_PRIORITY",
+	"extern int highest_priority(int, short, Trans *);",
+	"extern int get_priority(int);",
+	"extern int set_priority(int, int);",
+	"#endif",
+	"#ifdef SPIN_HEAP",
+	"void *",
+	"spin_malloc(int n)	/* reserved for use by Modex generated models */",
+	"{	char *spin_heap_ptr = &(now.spin_heap[now.spin_heap_n]);",
+	"	if (now.spin_heap_n + n >= sizeof(now.spin_heap))",
+	"	{	Uerror(\"spin_heap limit reached\");",
+	"	}",
+	"	now.spin_heap_n += n;",
+	"	return spin_heap_ptr;",
+	"}",
+	"void",
+	"spin_free(void *unused)",
+	"{	unused; /* ignore */",
+	"}",
+	"#endif",
+	"int",
+	"spin_join(int p, void **unused)",
+	"{	/* fprintf(stderr, \"join %%d when %%d\\n \", p, now._nr_pr); */",
+	"	return (now._nr_pr <= p);	/* process *p has stopped */",
+	"}",
+	"",
+	"int",
+	"spin_mutex_free(int *m)",
+	"{	return (*m == 0);",
+	"}",
+	"",
+	"int",
+	"spin_mutex_lock(int *m)",
+	"{	*m = 1;",
+	"	return 1;",
+	"}",
+	"void",
+	"spin_mutex_destroy(int *m)",
+	"{	*m = 0;",
+	"}",
+	"void",
+	"spin_mutex_unlock(int *m)",
+	"{	*m = 0;",
+	"}",
+	"void",
+	"spin_mutex_init(int *m, void *val)",
+	"{",
+	"	if (!val)", /* the 2nd arg must be NULL, for now */
+	"	{	*m = 0;",
+	"	} else",
+	"	{	Uerror(\"pthread_mutex_init: unsupported non-default init\");",
+	"	}",
+	"}",
+	"",
+	"int",
+	"spin_cond_wait(int *cond, int *lck)",	/*release and re-acquire lock *lck */
+	"{	/* this version does not scale very far alas */",
+	"	if (((P0 *)this)->_pid + 1 >= WS*8)", /* 32 or 64 */
+	"	{	Uerror(\"pid exceeds range supported by pthread_cond_wait\");",
+	"	}",
+	"	if (((*cond)&1) == 0)",		/* repeatedly tested, so: */
+	"	{	spin_mutex_unlock(lck);", /* avoid double counting */
+	"		*cond |= (1<<(((P0 *)this)->_pid + 1));",
+	"		return 0;",	/* blocked, must test again */
+	"	} else",
+	"	{	/* if other processes are already waiting */",
+	"		/* while our wait flag is 0, then they should go first */",
+	"		if (((*cond)&(~(1 | (1<<(((P0 *)this)->_pid + 1))))) != 0)",
+	"		{	spin_mutex_unlock(lck);",
+	"			return 0;", /* wait for the others to go first */
+	"		}",
+	"		*cond &= ~1;",	/* clear the 'go' bit andy wait flag */
+	"		*cond &= ~(1<<(((P0 *)this)->_pid + 1));",
+	"		return 1;",	/* okay to proceed */
+	"	}",
+	"}",
+	"void",
+	"spin_cond_signal(int *cond)",
+	"{",
+	"	if ( ((*cond)&(~1)) != 0 )", /* procs are waiting */
+	"	{	*cond |= 1;",	/* set the 'go' bit */
+	"	}",
+	"}",
+	"",
 	"#ifdef HAS_PROVIDED",
-	"int provided(int, uchar, int, Trans *);",
+	"	int provided(int, uchar, int, Trans *);",
 	"#endif",
+	"#ifdef BFS_PAR",
+	"	extern void bfs_shutdown(const char *);",
+	"#endif",
+	"",
+	"#if NCORE>1",
+	"	#define GLOBAL_LOCK	(0)",
+	"	#ifndef CS_N",
+	"		#define CS_N		(256*NCORE)", /* must be a power of 2 */
+	"	#endif",
 
+	"	#ifdef NGQ",	/* no global queue */
+	"		#define NR_QS		(NCORE)",
+	"		#define CS_NR		(CS_N+1)	/* 2^N + 1, nr critical sections */",
+	"		#define GQ_RD		GLOBAL_LOCK",	/* not really used in this mode */
+	"		#define GQ_WR		GLOBAL_LOCK",	/* but just in case... */
+	"		#define CS_ID		(1 + (int) (j1_spin & (CS_N-1))) /* mask: 2^N - 1, zero reserved */",
+	"		#define QLOCK(n)	(1+n)", /* overlaps first n zones of hashtable */
+	"	#else",
+	"		#define NR_QS		(NCORE+1)",	/* add a global queue */
+	"		#define CS_NR		(CS_N+3)",	/* 2 extra locks for global q */
+	"		#define GQ_RD		(1)",		/* read access to global q */
+	"		#define GQ_WR		(2)",		/* write access to global q */
+	"		#define CS_ID		(3 + (int) (j1_spin & (CS_N-1)))",
+	"		#define QLOCK(n)	(3+n)",/* overlaps first n zones of hashtable */
+	"	#endif",
+	"",
+	"	#ifndef SEP_STATE",
+	"		#define enter_critical(w)	e_critical(w)",
+	"		#define leave_critical(w)	x_critical(w)",
+	"	#else",
+	"		#ifdef NGQ",
+	"			#define enter_critical(w)	{ if (w < 1+NCORE) e_critical(w); }",
+	"			#define leave_critical(w)	{ if (w < 1+NCORE) x_critical(w); }",
+	"		#else",
+	"			#define enter_critical(w)	{ if (w < 3+NCORE) e_critical(w); }",
+	"			#define leave_critical(w)	{ if (w < 3+NCORE) x_critical(w); }",
+	"		#endif",
+	"	#endif",
+	"",
+	"	int",
+	"	cpu_printf(const char *fmt, ...)", /* only used with VERBOSE/CHECK/DEBUG */
+	"	{	va_list args;",
+	"		enter_critical(GLOBAL_LOCK);	/* printing */",
+	"		printf(\"cpu%%d: \", core_id);",
+	"		fflush(stdout);",
+	"		va_start(args, fmt);",
+	"		vprintf(fmt, args);",
+	"		va_end(args);",
+	"		fflush(stdout);",
+	"		leave_critical(GLOBAL_LOCK);",
+	"		return 1;",
+	"	}",
+	"#else",
+	"	#define enter_critical(w)	/* none */",
+	"	#define leave_critical(w)	/* none */",
+	"",
+	"	int",
+	"	cpu_printf(const char *fmt, ...)",
+	"	{	va_list args;",
+	"		va_start(args, fmt);",
+	"		vprintf(fmt, args);",
+	"		va_end(args);",
+	"		return 1;",
+	"	}",
+	"#endif",
+
 #ifndef PRINTF
 	"int",
 	"Printf(const char *fmt, ...)",
@@ -132,7 +320,7 @@
 	"static int stackread;",
 	"static Trail frameptr;",
 	"Trail *",
-	"getframe(int d)",
+	"getframe(long d)",
 	"{",
 	"	if (CNT1 == CNT2)",
 	"		return &trail[d];",
@@ -153,45 +341,85 @@
 	"	return &frameptr;",
 	"}",
 	"#endif",
-
-	"#if !defined(SAFETY) && !defined(BITSTATE)",
-	"#if !defined(FULLSTACK) || defined(MA)",
-	"#define depth_of(x)	A_depth /* an estimate */",
-	"#else",
-	"int",
-	"depth_of(struct H_el *s)",
-	"{	Trail *t; int d;",
-	"	for (d = 0; d <= A_depth; d++)",
-	"	{	t = getframe(d);",
-	"		if (s == t->ostate)",
-	"			return d;",
-	"	}",
-	"	printf(\"pan: cannot happen, depth_of\\n\");",
-	"	return depthfound;",
-	"}",
+	"#if NCORE>1",
+	"extern void cleanup_shm(int);",
+	"volatile uint	*search_terminated; /* to signal early termination */",
+	/*
+	 *	Meaning of bitflags in search_terminated:
+	 *	  1	set by pan_exit
+	 *	  2	set by wrapup
+	 *	  4	set by uerror
+	 *	  8	set by sudden_stop -- called after someone_crashed and [Uu]error
+	 *	 16	set by cleanup_shm
+	 *	 32	set by give_up	-- called on signal
+	 *	 64	set by proxy_exit
+	 *	128	set by proxy on write port failure
+	 *	256	set by proxy on someone_crashed
+	 *
+	 *	Flags 8|32|128|256 indicate abnormal termination
+	 *
+	 *	The flags are checked in 4 functions in the code:
+	 *		sudden_stop()
+	 *		someone_crashed() (proxy and pan version)
+	 *		mem_hand_off()
+	 */
 	"#endif",
-	"#endif",
-
 	"void",
 	"pan_exit(int val)",
-	"{	if (signoff) printf(\"--end of output--\\n\");",
+	"{	void stop_timer(int);",
+	"#ifdef BFS_PAR",
+	"	extern void bfs_mark_done(int);",
+	"	extern void bfs_drop_shared_memory(void);",
+	"#endif",
+	"	if (signoff)",
+	"	{	printf(\"--end of output--\\n\");",
+	"	}",
+	"#if NCORE>1",
+	"	if (search_terminated != NULL)",
+	"	{	*search_terminated |= 1;	/* pan_exit */",
+	"	}",
+		"#ifdef USE_DISK",
+	"	{ void	dsk_stats(void);",
+	"		dsk_stats();",
+	"	}",
+		"#endif",
+	"	if (!state_tables && !readtrail)",
+	"	{	cleanup_shm(1);",
+	"	}",
+	"#endif",
+	"#ifdef BFS_PAR",
+	"	if (who_am_i != 0)",
+	"	{	bfs_mark_done(3); /* stopped */",
+	"	}",
+	"	bfs_drop_shared_memory();",
+	"#endif",
+	"	if (val == 2)",
+	"	{	val = 0;",
+	"	}",
+	"#ifdef BFS_PAR",
+	"	if (who_am_i == 0)",
+	"#endif",
+	"	stop_timer(1);",
+	"",
+	"#ifdef C_EXIT",
+	"	C_EXIT; /* trust that it defines a fct */",
+	"#endif",
 	"	exit(val);",
 	"}",
-
 	"#ifdef HAS_CODE",
+	"static char tbuf[2][2048];",
+	"",
 	"char *",
 	"transmognify(char *s)",
 	"{	char *v, *w;",
-	"	static char buf[2][2048];",
 	"	int i, toggle = 0;",
-
 	"	if (!s || strlen(s) > 2047) return s;",
-	"	memset(buf[0], 0, 2048);",
-	"	memset(buf[1], 0, 2048);",
-	"	strcpy(buf[toggle], s);",
-	"	while ((v = strstr(buf[toggle], \"{c_code\")))",	/* assign v */
+	"	memset(tbuf[0], 0, 2048);",
+	"	memset(tbuf[1], 0, 2048);",
+	"	strcpy(tbuf[toggle], s);",
+	"	while ((v = strstr(tbuf[toggle], \"{c_code\")))",	/* assign v */
 	"	{	*v = '\\0'; v++;",
-	"		strcpy(buf[1-toggle], buf[toggle]);",
+	"		strcpy(tbuf[1-toggle], tbuf[toggle]);",
 	"		for (w = v; *w != '}' && *w != '\\0'; w++) /* skip */;",
 	"		if (*w != '}') return s;",
 	"		*w = '\\0'; w++;",
@@ -198,18 +426,18 @@
 	"		for (i = 0; code_lookup[i].c; i++)",
 	"			if (strcmp(v, code_lookup[i].c) == 0",
 	"			&&  strlen(v) == strlen(code_lookup[i].c))",
-	"			{	if (strlen(buf[1-toggle])",
+	"			{	if (strlen(tbuf[1-toggle])",
 	"				 +  strlen(code_lookup[i].t)",
 	"				 +  strlen(w) > 2047)",
 	"					return s;",
-	"				strcat(buf[1-toggle], code_lookup[i].t);",
+	"				strcat(tbuf[1-toggle], code_lookup[i].t);",
 	"				break;",
 	"			}",
-	"		strcat(buf[1-toggle], w);",
+	"		strcat(tbuf[1-toggle], w);",
 	"		toggle = 1 - toggle;",
 	"	}",
-	"	buf[toggle][2047] = '\\0';",
-	"	return buf[toggle];",
+	"	tbuf[toggle][2047] = '\\0';",
+	"	return tbuf[toggle];",
 	"}",
 	"#else",
 	"char * transmognify(char *s) { return s; }",
@@ -223,7 +451,6 @@
 	"",
 	"	for (t = trans[ot][tt]; t; t = t->nxt)",
 	"	{	printf(\"\\t\\t\");",
-
 	"		q = transmognify(t->tp);",
 	"		for ( ; q && *q; q++)",
 	"			if (*q == '\\n')",
@@ -233,6 +460,17 @@
 	"		printf(\"\\n\");",
 	"	}",
 	"}",
+	"",
+	"char *",
+	"find_source(int tp, int s)",
+	"{",
+	"	if (s >= flref[tp]->from",
+	"	&&  s <= flref[tp]->upto)",
+	"	{	return flref[tp]->fnm;",
+	"	}",
+	"	return PanSource; /* i.e., don't know */",
+	"}",
+	"",
 	"void",
 	"wrap_trail(void)",
 	"{	static int wrap_in_progress = 0;",
@@ -243,7 +481,7 @@
 	"",
 	"	printf(\"spin: trail ends after %%ld steps\\n\", depth);",
 	"	if (onlyproc >= 0)",
-	"	{	if (onlyproc >= now._nr_pr) pan_exit(0);",
+	"	{	if (onlyproc >= now._nr_pr) { pan_exit(0); }",
 	"		II = onlyproc;",
 	"		z = (P0 *)pptr(II);",
 	"		printf(\"%%3ld:\tproc %%d (%%s) \",",
@@ -250,7 +488,8 @@
 	"			depth, II, procname[z->_t]);",
 	"		for (i = 0; src_all[i].src; i++)",
 	"			if (src_all[i].tp == (int) z->_t)",
-	"			{	printf(\" line %%3d\",",
+	"			{	printf(\" %%s:%%d\",",
+	"					find_source((int) z->_t, (int) z->_p),",
 	"					src_all[i].src[z->_p]);",
 	"				break;",
 	"			}",
@@ -269,7 +508,8 @@
 	"			depth, II, procname[z->_t]);",
 	"		for (i = 0; src_all[i].src; i++)",
 	"			if (src_all[i].tp == (int) z->_t)",
-	"			{	printf(\" line %%3d\",",
+	"			{	printf(\" %%s:%%d\",",
+	"					find_source((int) z->_t, (int) z->_p),",
 	"					src_all[i].src[z->_p]);",
 	"				break;",
 	"			}",
@@ -293,23 +533,100 @@
 	"findtrail(void)",
 	"{	FILE *fd;",
 	"	char fnm[512], *q;",
-	"	char MyFile[512];",
+	"	char MyFile[512];",	/* avoid using a non-writable string */
+	"	char MySuffix[16];",
+	"	int  try_core;",
+	"	int  candidate_files;",
 	"",
-	"	strcpy(MyFile, TrailFile);",	/* avoid problem with non-writable strings */
+	"	if (trailfilename != NULL)",
+	"	{	fd = fopen(trailfilename, \"r\");",
+	"		if (fd == NULL)",
+	"		{	printf(\"pan: cannot find %%s\\n\", trailfilename);",
+	"			pan_exit(1);",
+	"		} /* else */",
+	"		goto success;",
+	"	}",
+	"talk:",
+	"	try_core = 1;",
+	"	candidate_files = 0;",
+	"	tprefix = \"trail\";",
+	"	strcpy(MyFile, TrailFile);",
+	"	do { /* see if there's more than one possible trailfile */",
+	"		if (whichtrail)",
+	"		{	sprintf(fnm, \"%%s%%d.%%s\",",
+	"				MyFile, whichtrail, tprefix);",
+	"			fd = fopen(fnm, \"r\");",
+	"			if (fd != NULL)",
+	"			{	candidate_files++;",
+	"				if (verbose==100)",
+	"					printf(\"trail%%d: %%s\\n\",",
+	"						candidate_files, fnm);",
+	"				fclose(fd);",
+	"			}",
+	"			if ((q = strchr(MyFile, \'.\')) != NULL)",
+	"			{	*q = \'\\0\';",	/* e.g., strip .pml */
+	"				sprintf(fnm, \"%%s%%d.%%s\",",
+	"					MyFile, whichtrail, tprefix);",
+	"				*q = \'.\';",
+	"				fd = fopen(fnm, \"r\");",
+	"				if (fd != NULL)",
+	"				{	candidate_files++;",
+	"					if (verbose==100)",
+	"						printf(\"trail%%d: %%s\\n\",",
+	"							candidate_files, fnm);",
+	"					fclose(fd);",
+	"			}	}",
+	"		} else",
+	"		{	sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
+	"			fd = fopen(fnm, \"r\");",
+	"			if (fd != NULL)",
+	"			{	candidate_files++;",
+	"				if (verbose==100)",
+	"					printf(\"trail%%d: %%s\\n\",",
+	"						candidate_files, fnm);",
+	"				fclose(fd);",
+	"			}",
+	"			if ((q = strchr(MyFile, \'.\')) != NULL)",
+	"			{	*q = \'\\0\';",	/* e.g., strip .pml */
+	"				sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
+	"				*q = \'.\';",
+	"				fd = fopen(fnm, \"r\");",
+	"				if (fd != NULL)",
+	"				{	candidate_files++;",
+	"					if (verbose==100)",
+	"						printf(\"trail%%d: %%s\\n\",",
+	"							candidate_files, fnm);",
+	"					fclose(fd);",
+	"		}	}	}",
+	"		tprefix = MySuffix;",
+	"		sprintf(tprefix, \"cpu%%d_trail\", try_core++);",
+	"	} while (try_core <= NCORE);",
 	"",
+	"	if (candidate_files != 1)",
+	"	{	if (verbose != 100)",
+	"		{	printf(\"error: there are %%d trail files:\\n\",",
+	"				candidate_files);",
+	"			verbose = 100;",
+	"			goto talk;",
+	"		} else",
+	"		{	printf(\"pan: rm or mv all except one\\n\");",
+	"			exit(1);",
+	"	}	}",
+
+	"	try_core = 1;",
+	"	strcpy(MyFile, TrailFile); /* restore */",
+	"	tprefix = \"trail\";",
+	"try_again:",
 	"	if (whichtrail)",
 	"	{	sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, tprefix);",
 	"		fd = fopen(fnm, \"r\");",
 	"		if (fd == NULL && (q = strchr(MyFile, \'.\')))",
 	"		{	*q = \'\\0\';",	/* e.g., strip .pml on original file */
-	"			sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, tprefix);",
+	"			sprintf(fnm, \"%%s%%d.%%s\",",
+	"				MyFile, whichtrail, tprefix);",
 	"			*q = \'.\';",
 	"			fd = fopen(fnm, \"r\");",
-	"			if (fd == NULL)",
-	"			{	printf(\"pan: cannot find %%s%%d.%%s or %%s\\n\", ",
-	"					MyFile, whichtrail, tprefix, fnm);",
-	"				pan_exit(1);",
-	"		}	}",
+	"		}",
 	"	} else",
 	"	{	sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
 	"		fd = fopen(fnm, \"r\");",
@@ -318,34 +635,99 @@
 	"			sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
 	"			*q = \'.\';",
 	"			fd = fopen(fnm, \"r\");",
-	"			if (fd == NULL)",
-	"			{	printf(\"pan: cannot find %%s.%%s or %%s\\n\", ",
-	"					MyFile, tprefix, fnm);",
-	"				pan_exit(1);",
-	"	}	}	}",
+	"	}	}",
 	"	if (fd == NULL)",
-	"	{	printf(\"pan: cannot find trailfile %%s\\n\", fnm);",
+	"	{	if (try_core < NCORE)",
+	"		{	tprefix = MySuffix;",
+	"			sprintf(tprefix, \"cpu%%d_trail\", try_core++);",
+	"			goto try_again;",
+	"		}",
+	"		printf(\"pan: cannot find trailfile %%s\\n\", fnm);",
 	"		pan_exit(1);",
 	"	}",
+	"success:",
+	"#if NCORE>1 && defined(SEP_STATE)",
+	"	{	void set_root(void); /* for partial traces from local root */",
+	"		set_root();",
+	"	}",
+	"#endif",
 	"	return fd;",
 	"}",
 	"",
 	"uchar do_transit(Trans *, short);",
+	"#ifdef PERMUTED",
+	"void set_permuted(int);",
+	"void set_reversed(int);",
+	"void set_rotated(int);",
+	"void set_randrot(int);",
+	"void (*p_reorder)(int) = set_permuted;",
+	"short p_rotate;",
+	"#endif",
 	"",
 	"void",
 	"getrail(void)",
 	"{	FILE *fd;",
-	"	char *q;",
-	"	int i, t_id, lastnever=-1; short II;",
+	"	char *q, *pnm;",
+	"	int i, t_id, lastnever = -1; short II;",
 	"	Trans *t;",
 	"	P0 *z;",
-	"",
+	"#ifdef PERMUTED",
+	"	char sbuf[128];",
+	"	memset(sbuf, 0, sizeof(sbuf));",
+	"#endif",
 	"	fd = findtrail();	/* exits if unsuccessful */",
 	"	while (fscanf(fd, \"%%ld:%%d:%%d\\n\", &depth, &i, &t_id) == 3)",
 	"	{	if (depth == -1)",
-	"			printf(\"<<<<<START OF CYCLE>>>>>\\n\");",
+	"		{	printf(\"<<<<<START OF CYCLE>>>>>\\n\");",
+	"		}",
+	"#ifdef PERMUTED",
 	"		if (depth < 0)",
-	"			continue;",
+	"		{	switch (depth) {",
+	"			case -5:",
+	"				if (i && !t_reverse)",
+	"				{	strcat(sbuf, \"-t_reverse \");",
+	"				}",
+	"				break;",
+	"			case -6:",
+	"				if (i && p_reorder != set_permuted)",
+	"				{	strcat(sbuf, \"-p_permute \");",
+	"				} else",
+	"				if (t_id && p_reorder != set_reversed)",
+	"				{	strcat(sbuf, \"-p_reverse \");",
+	"				}",
+	"				break;",
+	"			case -7:",
+	"				if (i",
+	"				&& (p_reorder != set_rotated || p_rotate != t_id))",
+	"				{	char tmp[32];",
+	"					sprintf(tmp, \"-p_rotate%%d \", t_id);",
+	"					strcat(sbuf, tmp);",
+	"				}",
+	"				break;",
+	"			case -8:",
+	"				if (i && p_reorder != set_randrot)",
+	"				{	strcat(sbuf, \"-p_randrot \");",
+	"				}",
+	"				if (s_rand != ++t_id)",
+	"				{	char tmp[32];",
+	"					sprintf(tmp, \"-RS%%u \", (uint) t_id-1);",
+	"					strcat(sbuf, tmp);",
+	"				}",
+	"				break;",
+	"			default:",
+	"				continue;",
+	"			}",
+	"		}",
+	"#endif",
+	"		if (depth < 0)",
+	"		{	continue;",
+	"		}",
+	"#ifdef PERMUTED",
+	"		if (strlen(sbuf) > 0)",
+	"		{	fprintf(efd, \"add: %%s\\n\", sbuf);",
+	"			exit(1);",
+	"		}",
+	"#endif",
 	"		if (i > now._nr_pr)",
 	"		{	printf(\"pan: Error, proc %%d invalid pid \", i);",
 	"			printf(\"transition %%d\\n\", t_id);",
@@ -352,16 +734,15 @@
 	"			break;",
 	"		}",
 	"		II = i;",
-	"",
 	"		z = (P0 *)pptr(II);",
 	"		for (t = trans[z->_t][z->_p]; t; t = t->nxt)",
-	"			if (t->t_id == t_id)",
+	"			if (t->t_id == (T_ID) t_id)",
 	"				break;",
 	"		if (!t)",
 	"		{	for (i = 0; i < NrStates[z->_t]; i++)",
 	"			{	t = trans[z->_t][i];",
-	"				if (t && t->t_id == t_id)",
-	"				{	printf(\"	Recovered at state %%d\\n\", i);",
+	"				if (t && t->t_id == (T_ID) t_id)",
+	"				{	printf(\"\\tRecovered at state %%d\\n\", i);",
 	"					z->_p = i;",
 	"					goto recovered;",
 	"			}	}",
@@ -368,6 +749,8 @@
 	"			printf(\"pan: Error, proc %%d type %%d state %%d: \",",
 	"				II, z->_t, z->_p);",
 	"			printf(\"transition %%d not found\\n\", t_id);",
+	"			printf(\"pan: list of possible transitions in this process:\\n\");",
+	"			if (z->_t >= 0 && z->_t <= _NP_)",
 	"			for (t = trans[z->_t][z->_p]; t; t = t->nxt)",
 	"				printf(\"	t_id %%d -- case %%d, [%%s]\\n\",",
 	"					t->t_id, t->forw, t->tp);",
@@ -377,11 +760,13 @@
 	"		q = transmognify(t->tp);",
 	"		if (gui) simvals[0] = \'\\0\';",
 
+	"		pnm = procname[z->_t];",
 	"		this = pptr(II);",
 	"		trpt->tau |= 1;",	/* timeout always possible */
 	"		if (!do_transit(t, II))",
 	"		{	if (onlyproc >= 0 && II != onlyproc)",
 	"				goto moveon;",
+	"			if (!verbose) break;",
 	"			printf(\"pan: error, next transition UNEXECUTABLE on replay\\n\");",
 	"			printf(\"     most likely causes: missing c_track statements\\n\");",
 	"			printf(\"       or illegal side-effects in c_expr statements\\n\");",
@@ -391,16 +776,24 @@
 	"			goto moveon;",
 
 	"		if (verbose)",
-	"		{	printf(\"depth: %%3ld proc: %%3d trans: %%3d (%%d procs)  \",",
-	"				depth, II, t_id, now._nr_pr);",
-	"			printf(\"forw=%%3d [%%s]\\n\", t->forw, q);",
-	"",
+	"		{	printf(\"%%3ld: proc %%2d (%%s) \", depth, II, pnm);",
+
+	"			for (i = 0; src_all[i].src; i++)",
+	"				if (src_all[i].tp == (int) z->_t)",
+	"				{	printf(\" %%s:%%d \",",
+	"						find_source((int) z->_t, (int) z->_p),",
+	"						src_all[i].src[z->_p]);",
+	"					break;",
+	"				}",
+
+	"			printf(\"(state %%d) trans {%%d,%%d} [%%s]\\n\",",
+	"				z->_p, t_id, t->forw, q?q:\"\");",
+
 	"			c_globals();",
 	"			for (i = 0; i < now._nr_pr; i++)",
 	"			{	c_locals(i, ((P0 *)pptr(i))->_t);",
 	"			}",
-	"		} else",
-	"		if (strcmp(procname[z->_t], \":never:\") == 0)",
+	"		} else if (Btypes[z->_t] == N_CLAIM)",
 	"		{	if (lastnever != (int) z->_p)",
 	"			{	for (i = 0; src_all[i].src; i++)",
 	"					if (src_all[i].tp == (int) z->_t)",
@@ -413,8 +806,7 @@
 	"			}",
 	"			lastnever = z->_p;",
 	"			goto sameas;",
-	"		} else",
-	"		if (strcmp(procname[z->_t], \":np_:\") != 0)",
+	"		} else if (Btypes[z->_t] != 0) /* not :np_: */",
 	"		{",
 	"sameas:		if (no_rck) goto moveon;",
 	"			if (coltrace)",
@@ -421,15 +813,16 @@
 	"			{	printf(\"%%ld: \", depth);",
 	"				for (i = 0; i < II; i++)",
 	"					printf(\"\\t\\t\");",
-	"				printf(\"%%s(%%d):\", procname[z->_t], II);",
+	"				printf(\"%%s(%%d):\", pnm, II);",
 	"				printf(\"[%%s]\\n\", q?q:\"\");",
 	"			} else if (!silent)",
 	"			{	if (strlen(simvals) > 0) {",
 	"				printf(\"%%3ld:	proc %%2d (%%s)\", ",
-	"					depth, II, procname[z->_t]);",
+	"					depth, II, pnm);",
 	"				for (i = 0; src_all[i].src; i++)",
 	"					if (src_all[i].tp == (int) z->_t)",
-	"					{	printf(\" line %%3d \\\"pan_in\\\" \",",
+	"					{	printf(\" %%s:%%d \",",
+	"							find_source((int) z->_t, (int) z->_p),",
 	"							src_all[i].src[z->_p]);",
 	"						break;",
 	"					}",
@@ -436,15 +829,16 @@
 	"				printf(\"(state %%d)\t[values: %%s]\\n\", z->_p, simvals);",
 	"				}",
 	"				printf(\"%%3ld:	proc %%2d (%%s)\", ",
-	"					depth, II, procname[z->_t]);",
+	"					depth, II, pnm);",
 	"				for (i = 0; src_all[i].src; i++)",
 	"					if (src_all[i].tp == (int) z->_t)",
-	"					{	printf(\" line %%3d \\\"pan_in\\\" \",",
+	"					{	printf(\" %%s:%%d \",",
+	"							find_source((int) z->_t, (int) z->_p),",
 	"							src_all[i].src[z->_p]);",
 	"						break;",
 	"					}",
 	"				printf(\"(state %%d)\t[%%s]\\n\", z->_p, q?q:\"\");",
-	"				printf(\"\\n\");",
+	"			/*	printf(\"\\n\");	*/",
 	"		}	}",
 	"moveon:	z->_p = t->st;",
 	"	}",
@@ -462,19 +856,22 @@
 	"	}",
 	"	return -1;",
 	"}",
-	"#ifdef VERI",
-	"void check_claim(int);",
+	"",
+	"#if NCORE>1 && !defined(GLOB_HEAP)",
+	"	#define SEP_HEAP /* version 5.1.2 */",
 	"#endif",
 	"",
 	"#ifdef BITSTATE",
-#ifndef POWOW
 	"int",
 	"bstore_mod(char *v, int n)	/* hasharray size not a power of two */",
-	"{	unsigned long x, y;",
-	"	unsigned int i = 1;",
-	"",
-	"	d_hash((uchar *) v, n); /* sets j3, j4, K1, K2 */",
-	"	x = K2; y = j3;",
+	"{	ulong x, y;",
+	"	uint i = 1;",
+	"#if defined(MURMUR) && (WS==8)",
+	"	m_hash((uchar *) v, n); /* bstore_mod - sets j3_spin, j4_spin, K1, K2 */",
+	"#else",
+	"	d_hash((uchar *) v, n); /* bstore_mod - sets j3_spin, j4_spin, K1, K2 */",
+	"#endif",
+	"	x = K1; y = j3_spin;",	/* was K2 before 5.1.1 */
 	"	for (;;)",
 	"	{	if (!(SS[x%%udmem]&(1<<y))) break;",	/* take the hit in speed */
 	"		if (i == hfns) {",
@@ -483,8 +880,8 @@
 				"#endif",
 	"			return 1;",
 	"		}",
-	"		x = (x + K1 + i);",	/* no mask, using mod */
-	"		y = (y + j4) & 7;",
+	"		x = (x + K2 + i);",	/* no mask, using mod - was K1 before 5.1.1 */
+	"		y = (y + j4_spin) & 7;",
 	"		i++;",
 	"	}",
 		"#ifdef RANDSTOR",
@@ -493,8 +890,8 @@
 	"	for (;;)",
 	"	{	SS[x%%udmem] |= (1<<y);",
 	"		if (i == hfns) break;",	/* done */
-	"		x = (x + K1 + i);",	/* no mask */
-	"		y = (y + j4) & 7;",
+	"		x = (x + K2 + i);",	/* no mask - was K1 before 5.1.1 */
+	"		y = (y + j4_spin) & 7;",
 	"		i++;",
 	"	}",
 		"#ifdef DEBUG",
@@ -505,14 +902,16 @@
 	"	}",
 	"	return 0;",
 	"}",
-#endif
 	"int",
 	"bstore_reg(char *v, int n)	/* extended hashing, Peter Dillinger, 2004 */",
-	"{	unsigned long x, y;",
-	"	unsigned int i = 1;",
-	"",
-	"	d_hash((uchar *) v, n); /* sets j1-j4 */",
-	"	x = j2; y = j3;",
+	"{	ulong x, y;",
+	"	uint i = 1;",
+	"#if defined(MURMUR) && (WS==8)",
+	"	m_hash((uchar *) v, n); /* bstore_reg - sets j1_spin-j4_spin */",
+	"#else",
+	"	d_hash((uchar *) v, n); /* bstore_reg - sets j1_spin-j4_spin */",
+	"#endif",
+	"	x = j2_spin; y = j3_spin;",
 	"	for (;;)",
 	"	{	if (!(SS[x]&(1<<y))) break;",	/* at least one bit not set */
 	"		if (i == hfns) {",
@@ -521,8 +920,8 @@
 				"#endif",
 	"			return 1;",
 	"		}",
-	"		x = (x + j1 + i) & nmask;",
-	"		y = (y + j4) & 7;",
+	"		x = (x + j1_spin + i) & nmask;",
+	"		y = (y + j4_spin) & 7;",
 	"		i++;",
 	"	}",
 		"#ifdef RANDSTOR",
@@ -531,8 +930,8 @@
 	"	for (;;)",
 	"	{	SS[x] |= (1<<y);",
 	"		if (i == hfns) break;",		/* done */
-	"		x = (x + j1 + i) & nmask;",
-	"		y = (y + j4) & 7;",
+	"		x = (x + j1_spin + i) & nmask;",
+	"		y = (y + j4_spin) & 7;",
 	"		i++;",
 	"	}",
 		"#ifdef DEBUG",
@@ -543,8 +942,8 @@
 	"	}",
 	"	return 0;",
 	"}",
-	"#endif",
-	"unsigned long TMODE = 0666; /* file permission bits for trail files */",
+	"#endif", /* BITSTATE */
+	"ulong TMODE = 0666; /* file permission bits for trail files */",
 	"",
 	"int trcnt=1;",
 	"char snap[64], fnm[512];",
@@ -554,18 +953,34 @@
 	"{	int fd;",
 	"	char *q;",
 	"	char MyFile[512];",
+	"	int w_flags = O_CREAT|O_WRONLY|O_TRUNC;",
 	"",
+	"	if (exclusive == 1 && iterative == 0)",
+	"	{	w_flags |= O_EXCL;",
+	"	}",
+	"",
 	"	q = strrchr(TrailFile, \'/\');",
 	"	if (q == NULL) q = TrailFile; else q++;",
 	"	strcpy(MyFile, q); /* TrailFile is not a writable string */",
 	"",
 	"	if (iterative == 0 && Nr_Trails++ > 0)",
+	"	{",
+	"#ifdef PUTPID",
+	"		sprintf(fnm, \"%%s_%%s_%%d_%%d.%%s\",",
+	"			MyFile, progname, getpid(), Nr_Trails-1, tprefix);",
+	"#else",
 	"		sprintf(fnm, \"%%s%%d.%%s\",",
 	"			MyFile, Nr_Trails-1, tprefix);",
-	"	else",
+	"#endif",
+	"	} else",
+	"	{",
+	"#ifdef PUTPID",
+	"		sprintf(fnm, \"%%s_%%s_%%d.%%s\", MyFile, progname, getpid(), tprefix);",
+	"#else",
 	"		sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
-	"",
-	"	if ((fd = creat(fnm, TMODE)) < 0)",
+	"#endif",
+	"	}",
+	"	if ((fd = open(fnm, w_flags, TMODE)) < 0)",
 	"	{	if ((q = strchr(MyFile, \'.\')))",
 	"		{	*q = \'\\0\';",		/* strip .pml */
 	"			if (iterative == 0 && Nr_Trails-1 > 0)",
@@ -574,91 +989,146 @@
 	"			else",
 	"				sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
 	"			*q = \'.\';",
-	"			fd = creat(fnm, TMODE);",
+	"			fd = open(fnm, w_flags, TMODE);",
 	"	}	}",
 	"	if (fd < 0)",
 	"	{	printf(\"pan: cannot create %%s\\n\", fnm);",
 	"		perror(\"cause\");",
 	"	} else",
-	"	{	printf(\"pan: wrote %%s\\n\", fnm);",
+	"	{",
+	"#if NCORE>1 && (defined(SEP_STATE) || !defined(FULL_TRAIL))",
+	"	void write_root(void); ",
+	"	write_root();",
+	"#else",
+	"		printf(\"pan: wrote %%s\\n\", fnm);",
+	"#endif",
 	"	}",
 	"	return fd;",
 	"}",
-	0
-};
-
-static char *Code2b[] = {	/* breadth-first search option */
-	"#ifdef BFS",
-	"#define Q_PROVISO",
-	"#ifndef INLINE_REV",
-	"#define INLINE_REV",
-	"#endif",
 	"",
-	"typedef struct SV_Hold {",
-	"	State *sv;",
-	"	int  sz;",
-	"	struct SV_Hold *nxt;",
-	"} SV_Hold;",
-	"",
-	"typedef struct EV_Hold {",
-	"	char *sv;",	/* Mask */
-	"	int  sz;",	/* vsize */
-	"	int nrpr;",
-	"	int nrqs;",
-	"#if VECTORSZ>32000",
-	"	int *po;",
-	"#else",
-	"	short *po;",
+	"#ifndef FREQ",
+	"#define FREQ	(1000000)",
 	"#endif",
-	"	int *qo;",
-	"	uchar *ps, *qs;",
-	"	struct EV_Hold *nxt;",
-	"} EV_Hold;",
+	"double freq = (double) FREQ;\n",
+
+	"#ifdef TRIX",
+	"void sv_populate(void);",
 	"",
-	"typedef struct BFS_Trail {",
-	"	Trail	*frame;",
-	"	SV_Hold *onow;",
-	"	EV_Hold *omask;",
-	"#ifdef Q_PROVISO",
-	"	struct H_el *lstate;",
+	"void",
+	"re_populate(void) /* restore procs and chans from now._ids_ */",
+	"{	int i, cnt = 0;",
+	"	char *b;",
+	"#ifdef V_TRIX",
+	"	printf(\"%%4d: re_populate\\n\", depth);",
 	"#endif",
-	"	short boq;",
-	"	struct BFS_Trail *nxt;",
-	"} BFS_Trail;",
+	"	for (i = 0; i < now._nr_pr; i++, cnt++)",
+	"	{	b = now._ids_[cnt];",
+	"		processes[i]->psize = what_p_size( ((P0 *)b)->_t );",
+	"		memcpy(processes[i]->body, b, processes[i]->psize);",
+	"#ifdef TRIX_RIX",
+	"		((P0 *)pptr(i))->_pid = i;",
+	"		if (BASE > 0 && h > 0)",
+	"		{	((P0 *)pptr(i))->_pid -= BASE;",
+	"		}",
+	"#endif",
+	"#ifndef BFS",
+	"		processes[i]->modified = 1; /* re-populate */",
+	"#endif",
+	"	}",
+	"	for (i = 0; i < now._nr_qs; i++, cnt++)",
+	"	{	b = now._ids_[cnt];",
+	"		channels[i]->psize = what_q_size( ((Q0 *)b)->_t );",
+	"		memcpy(channels[i]->body, b, channels[i]->psize);",
+	"#ifndef BFS",
+	"		channels[i]->modified = 1; /* re-populate */",
+	"#endif",
+	"	}",
+	"}",
+	"#endif\n",
+
+	"#ifdef BFS",	/* breadth-first search */
+	"	#ifndef BFS_PAR",
+	"		BFS_State *bfs_trail, *bfs_bot, *bfs_free;",
+	"		SV_Hold *svfree;",
+	"	#else",
+	"		static ulong	bfs_pre_allocated;",
+	"	#endif",
+	"	#ifdef BFS_DISK",
+	"		#ifndef BFS_LIMIT",
+	"			#define BFS_LIMIT	100000",
+	"		#endif",
+	"		#ifndef BFS_DSK_LIMIT",
+	"			#define BFS_DSK_LIMIT	1000000",
+	"		#endif",
+	"		#if defined(WIN32) || defined(WIN64)",
+	"			#define RFLAGS	(O_RDONLY|O_BINARY)",
+	"			#define WFLAGS	(O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)",
+	"			#define RWFLAGS	(O_RDWR|O_BINARY)",
+	"		#else",
+	"			#define RFLAGS	(O_RDONLY)",
+	"			#define WFLAGS	(O_CREAT|O_WRONLY|O_TRUNC)",
+	"			#define RWFLAGS	(O_RDWR)",
+	"		#endif",
 	"",
-	"BFS_Trail *bfs_trail, *bfs_bot, *bfs_free;",
+	"		long bfs_size_limit;",
+	"		int bfs_dsk_write = -1;",
+	"		int bfs_dsk_read = -1;",
+	"		long bfs_dsk_writes, bfs_dsk_reads;",
+	"		int bfs_dsk_seqno_w, bfs_dsk_seqno_r;",
+	"	#endif",
 	"",
-	"SV_Hold *svhold, *svfree;",
-	"",
 	"uchar do_reverse(Trans *, short, uchar);",
 	"void snapshot(void);",
+	"#if 0",
+	"void",
+	"select_claim(int x)	/* ignored in BFS mode */",
+	"{	if (verbose)",
+	"	{	printf(\"select %%d (ignored)\\n\", x);",
+	"	}",
+	"}",
+	"#endif",
+	"Trail *ntrpt;",
 	"",
+	"#ifndef BFS_PAR",
 	"SV_Hold *",
 	"getsv(int n)",
-	"{	SV_Hold *h = (SV_Hold *) 0, *oh;",
+	"{	SV_Hold *h;",
 	"",
-	"	oh = (SV_Hold *) 0;",
-	"	for (h = svfree; h; oh = h, h = h->nxt)",
-	"	{	if (n == h->sz)",
-	"		{	if (!oh)",
-	"				svfree = h->nxt;",
-	"			else",
-	"				oh->nxt = h->nxt;",
-	"			h->nxt = (SV_Hold *) 0;",
-	"			break;",
-	"		}",
-	"		if (n < h->sz)",
-	"		{	h = (SV_Hold *) 0;",
-	"			break;",
-	"		}",
-	"		/* else continue */",
-	"	}",
-	"",
-	"	if (!h)",
+	"	if (svfree && n <= svfree->sz)",
+	"	{	h = svfree;",
+	"		svfree = h->nxt;",
+	"		h->nxt = (SV_Hold *) 0;",
+	"	} else",
 	"	{	h = (SV_Hold *) emalloc(sizeof(SV_Hold));",
 	"		h->sz = n;",
+	"	#ifdef BFS_DISK",
+	"		if (bfs_size_limit >= BFS_LIMIT)",
+	"		{	h->sv = (State *) 0;	/* means: read disk */",
+	"			bfs_dsk_writes++;	/* count */",
+	"			if (bfs_dsk_write < 0	/* file descriptor */",
+	"			||  bfs_dsk_writes%%BFS_DSK_LIMIT == 0)",
+	"			{	char dsk_nm[32];",
+	"				if (bfs_dsk_write >= 0)",
+	"				{	(void) close(bfs_dsk_write);",
+	"				}",
+	"				sprintf(dsk_nm, \"pan_bfs_%%d.tmp\", bfs_dsk_seqno_w++);",
+	"				bfs_dsk_write = open(dsk_nm, WFLAGS, 0644);",
+	"				if (bfs_dsk_write < 0)",
+	"				{	Uerror(\"could not create tmp disk file\");",
+	"				}",
+	"				printf(\"pan: created disk file %%s\\n\", dsk_nm);",
+	"			}",
+	"			if (write(bfs_dsk_write, (char *) &now, n) != n)",
+	"			{	Uerror(\"aborting -- disk write failed (disk full?)\");",
+	"			}",
+	"			return h; /* no memcpy */",
+	"		}", /* else */
+	"		bfs_size_limit++;",
+	"	#endif",
 	"		h->sv = (State *) emalloc(sizeof(State) - VECTORSZ + n);",
 	"	}",
+	"",
+	"	memcpy((char *)h->sv, (char *)&now, n);",
 	"	return h;",
 	"}",
 	"",
@@ -669,18 +1139,24 @@
 	"",
 	"	for (h = kept; h; h = h->nxt)",
 	"		if (n == h->sz",
+	"#if !defined(NOCOMP) && !defined(HC)",
 	"		&&  (memcmp((char *) Mask, (char *) h->sv, n) == 0)",
+	"#endif",
 	"		&&  (now._nr_pr == h->nrpr)",
 	"		&&  (now._nr_qs == h->nrqs)",
-	"#if VECTORSZ>32000",
+	"	#ifdef TRIX",
+	"		)",
+	"	#else",
+	"		#if VECTORSZ>32000",
 	"		&&  (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(int)) == 0)",
 	"		&&  (memcmp((char *) q_offset, (char *) h->qo, now._nr_qs * sizeof(int)) == 0)",
-	"#else",
+	"		#else",
 	"		&&  (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(short)) == 0)",
 	"		&&  (memcmp((char *) q_offset, (char *) h->qo, now._nr_qs * sizeof(short)) == 0)",
-	"#endif",
-	"		&&  (memcmp((char *) proc_skip,   (char *) h->ps, now._nr_pr * sizeof(uchar)) == 0)",
-	"		&&  (memcmp((char *) q_skip,   (char *) h->qs, now._nr_qs * sizeof(uchar)) == 0))",
+	"		#endif",
+	"		&&  (memcmp((char *) proc_skip, (char *) h->ps, now._nr_pr * sizeof(uchar)) == 0)",
+	"		&&  (memcmp((char *) q_skip,    (char *) h->qs, now._nr_qs * sizeof(uchar)) == 0))",
+	"	#endif",
 	"			break;",
 	"	if (!h)",
 	"	{	h = (EV_Hold *) emalloc(sizeof(EV_Hold));",
@@ -689,29 +1165,33 @@
 	"		h->nrqs = now._nr_qs;",
 	"",
 	"		h->sv = (char *) emalloc(n * sizeof(char));",
+	"#if !defined(NOCOMP) && !defined(HC)",
 	"		memcpy((char *) h->sv, (char *) Mask, n);",
-	"",
+	"#endif",
+	"	#ifndef TRIX",
 	"		if (now._nr_pr > 0)",
-	"		{	h->po = (int *) emalloc(now._nr_pr * sizeof(int));",
-	"			h->ps = (int *) emalloc(now._nr_pr * sizeof(int));",
-	"#if VECTORSZ>32000",
+	"		{	h->ps = (char *) emalloc(now._nr_pr * sizeof(int));",
+	"			memcpy((char *) h->ps, (char *) proc_skip,   now._nr_pr * sizeof(uchar));",
+	"		#if VECTORSZ>32000",
+	"			h->po = (char *) emalloc(now._nr_pr * sizeof(int));",
 	"			memcpy((char *) h->po, (char *) proc_offset, now._nr_pr * sizeof(int));",
-	"#else",
+	"		#else",
+	"			h->po = (char *) emalloc(now._nr_pr * sizeof(short));",
 	"			memcpy((char *) h->po, (char *) proc_offset, now._nr_pr * sizeof(short));",
-	"#endif",
-	"			memcpy((char *) h->ps, (char *) proc_skip,   now._nr_pr * sizeof(uchar));",
+	"		#endif",
 	"		}",
 	"		if (now._nr_qs > 0)",
-	"		{	h->qo = (int *) emalloc(now._nr_qs * sizeof(int));",
-	"			h->qs = (int *) emalloc(now._nr_qs * sizeof(int));",
-	"#if VECTORSZ>32000",
+	"		{	h->qs = (char *) emalloc(now._nr_qs * sizeof(int));",
+	"			memcpy((char *) h->qs, (char *) q_skip,   now._nr_qs * sizeof(uchar));",
+	"		#if VECTORSZ>32000",
+	"			h->qo = (char *) emalloc(now._nr_qs * sizeof(int));",
 	"			memcpy((char *) h->qo, (char *) q_offset, now._nr_qs * sizeof(int));",
-	"#else",
+	"		#else",
+	"			h->qo = (char *) emalloc(now._nr_qs * sizeof(short));",
 	"			memcpy((char *) h->qo, (char *) q_offset, now._nr_qs * sizeof(short));",
-	"#endif",
-	"			memcpy((char *) h->qs, (char *) q_skip,   now._nr_qs * sizeof(uchar));",
+	"		#endif",
 	"		}",
-	"",
+	"	#endif",
 	"		h->nxt = kept;",
 	"		kept = h;",
 	"	}",
@@ -724,9 +1204,9 @@
 	"",
 	"	oh = (SV_Hold *) 0;",
 	"	for (h = svfree; h; oh = h, h = h->nxt)",
-	"		if (h->sz >= p->sz)",
+	"	{	if (p->sz >= h->sz)",
 	"			break;",
-	"",
+	"	}",
 	"	if (!oh)",
 	"	{	p->nxt = svfree;",
 	"		svfree = p;",
@@ -736,24 +1216,26 @@
 	"	}",
 	"}",
 	"",
-	"BFS_Trail *",
+	"BFS_State *",
 	"get_bfs_frame(void)",
-	"{	BFS_Trail *t;",
+	"{	BFS_State *t;",
 	"",
 	"	if (bfs_free)",
 	"	{	t = bfs_free;",
 	"		bfs_free = bfs_free->nxt;",
-	"		t->nxt = (BFS_Trail *) 0;",
+	"		t->nxt = (BFS_State *) 0;",
 	"	} else",
-	"	{	t = (BFS_Trail *) emalloc(sizeof(BFS_Trail));",
+	"	{	t = (BFS_State *) emalloc(sizeof(BFS_State));",
 	"	}",
 	"	t->frame = (Trail *) emalloc(sizeof(Trail));", /* always new */
+	"	/* new because we keep a ptr to the frame of parent states */",
+	"	/* used for reconstructing path and recovering failed rvs etc */",
 	"	return t;",
 	"}",
 	"",
 	"void",
 	"push_bfs(Trail *f, int d)",
-	"{	BFS_Trail *t;",
+	"{	BFS_State *t;",
 	"",
 	"	t = get_bfs_frame();",
 	"	memcpy((char *)t->frame, (char *)f, sizeof(Trail));",
@@ -760,12 +1242,14 @@
 	"	t->frame->o_tt = d;	/* depth */",
 	"",
 	"	t->boq = boq;",
+	"	#ifdef TRIX",
+	"	sv_populate();",
+	"	#endif",
 	"	t->onow = getsv(vsize);",
-	"	memcpy((char *)t->onow->sv, (char *)&now, vsize);",
 	"	t->omask = getsv_mask(vsize);",
-	"#if defined(FULLSTACK) && defined(Q_PROVISO)",
-	"	t->lstate = Lstate;",
-	"#endif",
+	"	#if defined(FULLSTACK) && defined(Q_PROVISO)",
+	"	t->lstate = Lstate;	/* bfs */",
+	"	#endif",
 	"	if (!bfs_bot)",
 	"	{	bfs_bot = bfs_trail = t;",
 	"	} else",
@@ -772,56 +1256,107 @@
 	"	{	bfs_bot->nxt = t;",
 	"		bfs_bot = t;",
 	"	}",
-	"#ifdef CHECK",
-	"	printf(\"PUSH %%u (%%d)\\n\", t->frame, d);",
-	"#endif",
+	"	#ifdef VERBOSE",
+	"	t->nr = nstates;",
+	"	#endif",
+	"	#ifdef CHECK",
+	"		#ifdef VERBOSE",
+	"	printf(\"PUSH %%lu (depth %%d, nr %%lu)\\n\", (ulong) t->frame, d, t->nr);",
+	"		#else",
+	"	printf(\"PUSH %%lu (depth %%d)\\n\", (ulong) t->frame, d);",
+	"		#endif",
+	"	#endif",
 	"}",
 	"",
 	"Trail *",
 	"pop_bfs(void)",
-	"{	BFS_Trail *t;",
+	"{	BFS_State *t;",
 	"",
 	"	if (!bfs_trail)",
-	"		return (Trail *) 0;",
-	"",
+	"	{	return (Trail *) 0;",
+	"	}",
 	"	t = bfs_trail;",
 	"	bfs_trail = t->nxt;",
 	"	if (!bfs_trail)",
-	"		bfs_bot = (BFS_Trail *) 0;",
-	"#if defined(Q_PROVISO) && !defined(BITSTATE) && !defined(NOREDUCE)",
-	"	if (t->lstate) t->lstate->tagged = 0;",
-	"#endif",
-	"",
+	"	{	bfs_bot = (BFS_State *) 0;",
+	"	}",
+	"	#if defined(Q_PROVISO) && !defined(BITSTATE) && !defined(NOREDUCE)",
+	"	if (t->lstate)			/* bfs */",
+	"	{	t->lstate->tagged = 0;	/* bfs */",
+	"	}",
+	"	#endif",
 	"	t->nxt = bfs_free;",
 	"	bfs_free = t;",
 	"",
 	"	vsize = t->onow->sz;",
 	"	boq = t->boq;",
-	"",
-	"	memcpy((uchar *) &now, (uchar *) t->onow->sv, vsize);",
+	"	#ifdef BFS_DISK",
+	"	if (t->onow->sv == (State *) 0)",
+	"	{	char dsk_nm[32];",
+	"		bfs_dsk_reads++;	/* count */",
+	"		if (bfs_dsk_read >= 0	/* file descriptor */",
+	"		&&  bfs_dsk_reads%%BFS_DSK_LIMIT == 0)",
+	"		{	(void) close(bfs_dsk_read);",
+	"			sprintf(dsk_nm, \"pan_bfs_%%d.tmp\", bfs_dsk_seqno_r-1);",
+	"			(void) unlink(dsk_nm);",
+	"			bfs_dsk_read = -1;",
+	"		}",
+	"		if (bfs_dsk_read < 0)",
+	"		{	sprintf(dsk_nm, \"pan_bfs_%%d.tmp\", bfs_dsk_seqno_r++);",
+	"			bfs_dsk_read = open(dsk_nm, RFLAGS);",
+	"			if (bfs_dsk_read < 0)",
+	"			{	Uerror(\"could not open temp disk file\");",
+	"		}	}",
+	"		if (read(bfs_dsk_read, (char *) &now, vsize) != vsize)",
+	"		{	Uerror(\"bad bfs disk file read\");",
+	"		}",
+	"		#ifndef NOVSZ",
+	"		if (now._vsz != vsize)",
+	"		{	Uerror(\"disk read vsz mismatch\");",
+	"		}",
+	"		#endif",
+	"	} else",
+	"	#endif",
+	"	{	memcpy((uchar *) &now, (uchar *) t->onow->sv, vsize);",
+	"	#ifndef NOVSZ",
+	"		vsize = now._vsz;",
+	"	#endif",
+	"	}",
+	"#if !defined(NOCOMP) && !defined(HC)",
 	"	memcpy((uchar *) Mask, (uchar *) t->omask->sv, vsize);",
-
+	"#endif",
+	"	#ifdef TRIX",
+	"	re_populate();",
+	"	#else",
 	"	if (now._nr_pr > 0)",
-	"#if VECTORSZ>32000",
+	"		#if VECTORSZ>32000",
 	"	{	memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(int));",
-	"#else",
+	"		#else",
 	"	{	memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(short));",
-	"#endif",
+	"		#endif",
 	"		memcpy((char *)proc_skip,   (char *)t->omask->ps, now._nr_pr * sizeof(uchar));",
 	"	}",
 	"	if (now._nr_qs > 0)",
-	"#if VECTORSZ>32000",
+	"		#if VECTORSZ>32000",
 	"	{	memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(int));",
-	"#else",
+	"		#else",
 	"	{	memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(short));",
-	"#endif",
+	"		#endif",
 	"		memcpy((uchar *)q_skip,   (uchar *)t->omask->qs, now._nr_qs * sizeof(uchar));",
 	"	}",
-
-	"	freesv(t->onow);	/* omask not freed */",
-	"#ifdef CHECK",
-	"	printf(\"POP %%u (%%d)\\n\", t->frame, t->frame->o_tt);",
-	"#endif",
+	"	#endif",
+	"	#ifdef BFS_DISK",
+	"	if (t->onow->sv != (State *) 0)",
+	"	#endif",
+	"	{	freesv(t->onow);	/* omask not freed */",
+	"	}",
+	"	#ifdef CHECK",
+	"		#ifdef VERBOSE",
+	"	printf(\"POP %%lu (depth %%d, nr %%lu)\\n\", (ulong) t->frame, t->frame->o_tt, t->nr);",
+	"		#else",
+	"	printf(\"POP %%lu (depth %%d)\\n\", (ulong) t->frame, t->frame->o_tt);",
+	"		#endif",
+	"	#endif",
 	"	return t->frame;",
 	"}",
 	"",
@@ -828,7 +1363,7 @@
 	"void",
 	"store_state(Trail *ntrpt, int shortcut, short oboq)",
 	"{",
-	"#ifdef VERI",
+	"	#ifdef VERI",
 	"	Trans *t2 = (Trans *) 0;",
 	"	uchar ot; int tt, E_state;",
 	"	uchar o_opm = trpt->o_pm, *othis = this;",
@@ -835,72 +1370,85 @@
 	"",
 	"	if (shortcut)",
 	"	{",
-	"#ifdef VERBOSE",
+	"		#ifdef VERBOSE",
 	"		printf(\"claim: shortcut\\n\");",
-	"#endif",
+	"		#endif",
 	"		goto store_it;	/* no claim move */",
 	"	}",
 	"",
-	"	this  = (((uchar *)&now)+proc_offset[0]); /* 0 = never claim */",
+	"	this  = pptr(0);	/* 0 = never claim */",
 	"	trpt->o_pm = 0;",	/* to interpret else in never claim */
 	"",
 	"	tt    = (int)   ((P0 *)this)->_p;",
 	"	ot    = (uchar) ((P0 *)this)->_t;",
 	"",
-		"#ifdef HAS_UNLESS",
+	"		#ifdef HAS_UNLESS",
 	"	E_state = 0;",
-		"#endif",
+	"		#endif",
 	"	for (t2 = trans[ot][tt]; t2; t2 = t2?t2->nxt:(Trans *)0)",
 	"	{",
-		"#ifdef HAS_UNLESS",
-	"		if (E_state > 0",
-	"		&&  E_state != t2->e_trans)",
-	"			break;",
-		"#endif",
+	"		#ifdef HAS_UNLESS",
+	"		if (E_state > 0 && E_state != t2->e_trans)",
+	"		{	break;",
+	"		}",
+	"		#endif",
 	"		if (do_transit(t2, 0))",
 	"		{",
-		"#ifdef VERBOSE",
+	"		#ifdef VERBOSE",
 	"			if (!reached[ot][t2->st])",
 	"			printf(\"depth: %%d -- claim move from %%d -> %%d\\n\",",
 	"				trpt->o_tt, ((P0 *)this)->_p, t2->st);",
-		"#endif",
-		"#ifdef HAS_UNLESS",
+	"		#endif",
+	"		#ifdef HAS_UNLESS",
 	"			E_state = t2->e_trans;",
-		"#endif",
+	"		#endif",
 	"			if (t2->st > 0)",
 	"			{	((P0 *)this)->_p = t2->st;",
 	"				reached[ot][t2->st] = 1;",
-		"#ifndef NOCLAIM",
-	"				check_claim(t2->st);",
-		"#endif",
+	"		#ifndef NOCLAIM",
+	"				if (stopstate[ot][t2->st])",
+	"				{	uerror(\"end state in claim reached\");",
+	"				}",
+	"		#endif",
 	"			}",
 	"			if (now._nr_pr == 0)	/* claim terminated */",
 	"				uerror(\"end state in claim reached\");",
 	"",
-		"#ifdef PEG",
+	"		#ifdef PEG",
 	"			peg[t2->forw]++;",
-		"#endif",
+	"		#endif",
 	"			trpt->o_pm |= 1;",
-	"			if (t2->atom&2)",	/* atomic in claim */
-	"			Uerror(\"atomic in claim not supported in BFS mode\");",
+	"			if (t2->atom&2)",
+	"			{ Uerror(\"atomic in claim not supported in BFS\");",
+	"			}",
 	"store_it:",
 	"",
-	"#endif",	/* VERI */
+	"	#endif",	/* VERI */
 	"",
-	"#ifdef BITSTATE",
-	"			if (!bstore((char *)&now, vsize))",
-	"#else",
-		"#ifdef MA",
-	"			if (!gstore((char *)&now, vsize, 0))",
-		"#else",
-	"			if (!hstore((char *)&now, vsize))",
-		"#endif",
-	"#endif",
-	"			{	nstates++;",
-	"#ifndef NOREDUCE",
-	"				trpt->tau |= 64;", /* succ definitely outside stack */
-	"#endif",
-	"#if SYNC",
+	"	#if defined(BITSTATE)",
+	"			if (!b_store((char *)&now, vsize))",
+	"	#elif defined(MA)",
+	"			if (!g_store((char *)&now, vsize, 0))",
+	"	#else",
+	"			if (!h_store((char *)&now, vsize))",
+	"	#endif",
+	"			{	static long sdone = (long) 0; long ndone;",
+	"				nstates++;",
+	"	#ifndef NOREDUCE",
+	"				trpt->tau |= 64;", /* bfs: succ definitely outside stack */
+	"	#endif",
+	"				ndone = (ulong) (nstates/(freq));",
+	"				if (ndone != sdone && mreached%%10 != 0)",
+	"				{	snapshot();",
+	"					sdone = ndone;",
+	"	#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)",
+	"					if (nstates > ((double)(1<<(ssize+1))))",
+	"					{	void resize_hashtable(void);",
+	"						resize_hashtable();",
+	"					}",
+	"	#endif",
+	"				}",
+	"	#if SYNC",
 	"				if (boq != -1)",
 	"					midrv++;",
 	"				else if (oboq != -1)",
@@ -908,26 +1456,29 @@
 	"					x = (Trail *) trpt->ostate; /* pre-rv state */",
 	"					if (x) x->o_pm |= 4; /* mark success */",
 	"				}",
-	"#endif",
+	"	#endif",
 	"				push_bfs(ntrpt, trpt->o_tt+1);",
 	"			} else",
 	"			{	truncs++;",
 
-	"#if !defined(NOREDUCE) && defined(FULLSTACK) && defined(Q_PROVISO)",
-		"#if !defined(QLIST) && !defined(BITSTATE)",
-	"				if (Lstate && Lstate->tagged) trpt->tau |= 64;",
-		"#else",
+	"	#if defined(Q_PROVISO) && !defined(NOREDUCE) && defined(FULLSTACK)",
+	"		#if !defined(BITSTATE)",
+	"				if (Lstate && Lstate->tagged)",
+	"				{  trpt->tau |= 64;",
+	"				}",
+	"		#else",
 	"				if (trpt->tau&32)",
-	"				{  BFS_Trail *tprov;",
+	"				{  BFS_State *tprov;",
 	"				   for (tprov = bfs_trail; tprov; tprov = tprov->nxt)",
-	"					if (!memcmp((uchar *)&now, (uchar *)tprov->onow->sv, vsize))",
+	"					if (tprov->onow->sv != (State *) 0",
+	"					&&  memcmp((uchar *)&now, (uchar *)tprov->onow->sv, vsize) == 0)",
 	"					{	trpt->tau |= 64;",
 	"						break;	/* state is in queue */",
 	"				}	}",
-		"#endif",
-	"#endif",
+	"		#endif",
+	"	#endif",
 	"			}",
-	"#ifdef VERI",
+	"	#ifdef VERI",
 	"			((P0 *)this)->_p = tt;	/* reset claim */",
 	"			if (t2)",
 	"				do_reverse(t2, 0, 0);",
@@ -936,11 +1487,9 @@
 	"	}	}",
 	"	this = othis;",
 	"	trpt->o_pm = o_opm;",
-	"#endif",
+	"	#endif",
 	"}",
 	"",
-	"Trail *ntrpt;",	/* 4.2.8 */
-	"",
 	"void",
 	"bfs(void)",
 	"{	Trans *t; Trail *otrpt, *x;",
@@ -950,7 +1499,7 @@
 	"	short oboq = boq;",
 	"",
 	"	ntrpt = (Trail *) emalloc(sizeof(Trail));",
-	"	trpt->ostate = (struct H_el *) 0;",
+	"	trpt->ostate = (H_el *) 0;",
 	"	trpt->tau = 0;",
 	"",
 	"	trpt->o_tt = -1;",
@@ -958,65 +1507,59 @@
 	"",
 	"	while ((otrpt = pop_bfs()))	/* also restores now */",
 	"	{	memcpy((char *) trpt, (char *) otrpt, sizeof(Trail));",
-	"#if defined(C_States) && (HAS_TRACK==1)",
+	"	#if defined(C_States) && (HAS_TRACK==1)",
 	"		c_revert((uchar *) &(now.c_state[0]));",
-	"#endif",
+	"	#endif",
 	"		if (trpt->o_pm & 4)",
 	"		{",
-	"#ifdef VERBOSE",
+	"	#ifdef VERBOSE",
 	"			printf(\"Revisit of atomic not needed (%%d)\\n\",",
 	"				trpt->o_pm);",	/* at least 1 rv succeeded */
-	"#endif",
+	"	#endif",
 	"			continue;",
 	"		}",
-	"#ifndef NOREDUCE",
+	"	#ifndef NOREDUCE",
 	"		nps = 0;",
-	"#endif",
+	"	#endif",
 	"		if (trpt->o_pm == 8)",
 	"		{	revrv++;",
 	"			if (trpt->tau&8)",
 	"			{",
-		"#ifdef VERBOSE",
+	"	#ifdef VERBOSE",
 	"				printf(\"Break atomic (pm:%%d,tau:%%d)\\n\",",
 	"					trpt->o_pm, trpt->tau);",
-		"#endif",
+	"	#endif",
 	"				trpt->tau &= ~8;",
 	"			}",
-	"#ifndef NOREDUCE",
+	"	#ifndef NOREDUCE",
 	"			else if (trpt->tau&32)",	/* was a preselected move */
 	"			{",
-		"#ifdef VERBOSE",
+	"		#ifdef VERBOSE",
 	"				printf(\"Void preselection (pm:%%d,tau:%%d)\\n\",",
 	"					trpt->o_pm, trpt->tau);",
-		"#endif",
+	"		#endif",
 	"				trpt->tau &= ~32;",
 	"				nps = 1; /* no preselection in repeat */",
 	"			}",
-	"#endif",
+	"	#endif",
 	"		}",
 	"		trpt->o_pm &= ~(4|8);",
 	"		if (trpt->o_tt > mreached)",
 	"		{	mreached = trpt->o_tt;",
 	"			if (mreached%%10 == 0)",
-	"			{	printf(\"Depth= %%7d States= %%7g \", mreached, nstates);",
-	"				printf(\"Transitions= %%7g \", nstates+truncs);",
-	"#ifdef MA",
-	"				printf(\"Nodes= %%7d \", nr_states);",
-	"#endif",
-	"				printf(\"Memory= %%-6.3f\\n\", memcnt/1000000.);",
-	"				fflush(stdout);",
+	"			{	snapshot();",
 	"		}	}",
 	"		depth = trpt->o_tt;",
 
 	"		if (depth >= maxdepth)",
 	"		{",
-	"#if SYNC",
+	"	#if SYNC",
 	"			Trail *x;",
 	"			if (boq != -1)",
 	"			{	x = (Trail *) trpt->ostate;",
 	"				if (x) x->o_pm |= 4; /* not failing */",
 	"			}",
-	"#endif",
+	"	#endif",
 	"			truncs++;",
 	"			if (!warned)",
 	"			{	warned = 1;",
@@ -1023,16 +1566,15 @@
 	"		  		printf(\"error: max search depth too small\\n\");",
 	"			}",
 	"			if (bounded)",
-	"				uerror(\"depth limit reached\");",
+	"			{	uerror(\"depth limit reached\");",
+	"			}",
 	"			continue;",
 	"		}",
-
-/* PO */
-	"#ifndef NOREDUCE",
+	"	#ifndef NOREDUCE",
 	"		if (boq == -1 && !(trpt->tau&8) && nps == 0)",
 	"		for (II = now._nr_pr-1; II >= BASE; II -= 1)",
 	"		{",
-	"Pickup:			this = pptr(II);",
+	"Pickup:		this = pptr(II);",
 	"			tt = (int) ((P0 *)this)->_p;",
 	"			ot = (uchar) ((P0 *)this)->_t;",
 	"			if (trans[ot][tt]->atom & 8)",	/* safe */
@@ -1045,15 +1587,14 @@
 	"				}",
 	"				From = To = II;",
 	"				trpt->tau |= 32; /* preselect marker */",
-		"#ifdef DEBUG",
-	"				printf(\"%%3d: proc %%d PreSelected (tau=%%d)\\n\", ",
+	"		#ifdef DEBUG",
+	"				printf(\"%%3ld: proc %%d PreSelected (tau=%%d)\\n\", ",
 	"					depth, II, trpt->tau);",
-		"#endif",
+	"		#endif",
 	"				goto MainLoop;",
 	"		}	}",
 	"		trpt->tau &= ~32;",	/* not preselected */
-	"#endif",
-/* PO */
+	"	#endif",	/* if !NOREDUCE */
 	"Repeat:",
 	"		if (trpt->tau&8)		/* atomic */",
 	"		{	From = To = (short ) trpt->pr;",
@@ -1066,32 +1607,44 @@
 	"		_n = _m = 0;",
 	"		for (II = From; II >= To; II -= 1)",
 	"		{",
-	"			this = (((uchar *)&now)+proc_offset[II]);",
+	"			this = pptr(II);",
 	"			tt = (int) ((P0 *)this)->_p;",
 	"			ot = (uchar) ((P0 *)this)->_t;",
-	"#if SYNC",
+	"	#if SYNC",
 	"			/* no rendezvous with same proc */",
-	"			if (boq != -1 && trpt->pr == II) continue;",
-	"#endif",
+	"			if (boq != -1 && trpt->pr == II)",
+	"			{	continue;",
+	"			}",
+	"	#endif",
 	"			ntrpt->pr = (uchar) II;",
 	"			ntrpt->st = tt;	",
-	"			trpt->o_pm &= ~1;		/* no move yet */",
-	"#ifdef EVENT_TRACE",
+	"			trpt->o_pm &= ~1; /* no move yet */",
+	"	#ifdef EVENT_TRACE",
 	"			trpt->o_event = now._event;",
-	"#endif",
-	"#ifdef HAS_PROVIDED",
-	"			if (!provided(II, ot, tt, t)) continue;",
-	"#endif",
-	"#ifdef HAS_UNLESS",
+	"	#endif",
+
+	"	#ifdef HAS_PRIORITY",
+	"			if (!highest_priority(((P0 *)this)->_pid, II, t))",
+	"			{	continue;",
+	"			}",
+	"	#else",
+	"		#ifdef HAS_PROVIDED",
+	"			if (!provided(II, ot, tt, t))",
+	"			{	continue;",
+	"			}",
+	"		#endif",
+	"	#endif",
+
+	"	#ifdef HAS_UNLESS",
 	"			E_state = 0;",
-	"#endif",
+	"	#endif",
 	"			for (t = trans[ot][tt]; t; t = t->nxt)",
 	"			{",
-	"#ifdef HAS_UNLESS",
+	"	#ifdef HAS_UNLESS",
 	"				if (E_state > 0",
 	"				&&  E_state != t->e_trans)",
 	"					break;",
-	"#endif",
+	"	#endif",
 	"				ntrpt->o_t = t;",
 	"",
 	"				oboq = boq;",
@@ -1101,136 +1654,147 @@
 	"",
 	"				trpt->o_pm |= 1;	/* we moved */",
 	"				(trpt+1)->o_m = _m;	/* for unsend */",
-		"#ifdef PEG",
+	"	#ifdef PEG",
 	"				peg[t->forw]++;",
-		"#endif",
-	"#ifdef CHECK",
-	"				printf(\"%%3d: proc %%d exec %%d, \",",
+	"	#endif",
+	"	#ifdef CHECK",
+	"				printf(\"%%3ld: proc %%d exec %%d, \",",
 	"					depth, II, t->forw);",
 	"				printf(\"%%d to %%d, %%s %%s %%s\",",
 	"					tt, t->st, t->tp,",
 	"					(t->atom&2)?\"atomic\":\"\",",
 	"					(boq != -1)?\"rendez-vous\":\"\");",
-		"#ifdef HAS_UNLESS",
+	"		#ifdef HAS_UNLESS",
 	"				if (t->e_trans)",
 	"					printf(\" (escapes to state %%d)\", t->st);",
-		"#endif",
+	"		#endif",
 	"				printf(\" %%saccepting [tau=%%d]\\n\",",
 	"					(trpt->o_pm&2)?\"\":\"non-\", trpt->tau);",
-	"#endif",
-	"#ifdef HAS_UNLESS",
+	"	#endif",
+	"	#ifdef HAS_UNLESS",
 	"				E_state = t->e_trans;",
-		"#if SYNC>0",
+	"		#if SYNC>0",
 	"				if (t->e_trans > 0 && (boq != -1 /* || oboq != -1 */))",
-	"				{ fprintf(efd, \"error:\tthe use of rendezvous stmnt in the escape clause\\n\");",
+	"				{ fprintf(efd, \"error:\ta rendezvous stmnt in the escape clause\\n\");",
 	"				  fprintf(efd, \"\tof an unless stmnt is not compatible with -DBFS\\n\");",
 	"				  pan_exit(1);",
 	"				}",
-		"#endif",
-	"#endif",
-	"				if (t->st > 0) ((P0 *)this)->_p = t->st;",
+	"		#endif",
+	"	#endif",
+	"				if (t->st > 0)",
+	"				{	((P0 *)this)->_p = t->st;",
+	"				}",
 	"",
-	"	/* ptr to pred: */	ntrpt->ostate = (struct H_el *) otrpt;",
+	"	/* ptr to pred: */	ntrpt->ostate = (H_el *) otrpt;",
 	"				ntrpt->st = tt;",
 	"				if (boq == -1 && (t->atom&2))	/* atomic */",
 	"					ntrpt->tau = 8;	/* record for next move */",
 	"				else",
 	"					ntrpt->tau = 0;",
-	"",
 	"				store_state(ntrpt, (boq != -1 || (t->atom&2)), oboq);",
-	"#ifdef EVENT_TRACE",
+	"	#ifdef EVENT_TRACE",
 	"				now._event = trpt->o_event;",
-	"#endif",
-	"",
+	"	#endif",
 	"				/* undo move and continue */",
 	"				trpt++;	/* this is where ovals and ipt are set */",
 	"				do_reverse(t, II, _m);	/* restore now. */",
 	"				trpt--;",
-	"#ifdef CHECK",
-	"				printf(\"%%3d: proc %%d \", depth, II);",
+	"	#ifdef CHECK",
+	"				enter_critical(GLOBAL_LOCK);	/* verbose mode */",
+	"		#if NCORE>1",
+	"				printf(\"cpu%%d: \", core_id);",
+	"		#endif",
+	"				printf(\"%%3lu: proc %%d \", depth, II);",
 	"				printf(\"reverses %%d, %%d to %%d,\",",
 	"					t->forw, tt, t->st);",
-	"				printf(\" %%s [abit=%%d,adepth=%%d,\",",
+	"				printf(\" %%s [abit=%%d,adepth=%%ld,\",",
 	"					t->tp, now._a_t, A_depth);",
 	"				printf(\"tau=%%d,%%d]\\n\",",
 	"					trpt->tau, (trpt-1)->tau);",
-	"#endif",
+	"				leave_critical(GLOBAL_LOCK);",
+	"	#endif",
 	"				reached[ot][t->st] = 1;",
-	"				reached[ot][tt] = 1;",
+	"				reached[ot][tt]    = 1;",
 	"",
 	"				((P0 *)this)->_p = tt;",
 	"				_n |= _m;",
 	"		}	}",
-/* PO */
-	"#ifndef NOREDUCE",
+	"	#ifndef NOREDUCE",	/* with PO */
 	"		/* preselected - no succ definitely outside stack */",
 	"		if ((trpt->tau&32) && !(trpt->tau&64))",
 	"		{	From = now._nr_pr-1; To = BASE;",
-	"#ifdef DEBUG",
-	"			printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
+	"		#ifdef DEBUG",
+	"			cpu_printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
 	"				depth, II+1, (int) _n, trpt->tau);",
-	"#endif",
+	"		#endif",
 	"			_n = 0; trpt->tau &= ~32;",
 	"			if (II >= BASE)",
-	"				goto Pickup;",
+	"			{	goto Pickup;",
+	"			}",
 	"			goto MainLoop;",
 	"		}",
 	"		trpt->tau &= ~(32|64);",
-	"#endif",
-/* PO */
+	"	#endif",	/* PO */
 	"		if (_n != 0)",
-	"			continue;",
-	"#ifdef DEBUG",
-	"		printf(\"%%3d: no move [II=%%d, tau=%%d, boq=%%d, _nr_pr=%%d]\\n\",",
+	"		{	continue;",
+	"		}",
+	"	#ifdef DEBUG",
+	"		printf(\"%%3ld: no move [II=%%d, tau=%%d, boq=%%d, _nr_pr=%%d]\\n\",",
 	"			depth, II, trpt->tau, boq, now._nr_pr);",
-	"#endif",
+	"	#endif",
 	"		if (boq != -1)",
 	"		{	failedrv++;",
-	"			x = (Trail *) trpt->ostate; /* pre-rv state */",
-	"			if (!x) continue; /* root state */",
+	"			x = (Trail *) trpt->ostate;	/* pre-rv state */",
+	"			if (!x)",
+	"			{	continue;		/* root state */",
+	"			}",
 	"			if ((x->tau&8) || (x->tau&32)) /* break atomic or preselect at parent */",
 	"			{	x->o_pm |= 8; /* mark failure */",
-	"				this = (((uchar *)&now)+proc_offset[otrpt->pr]);",
-	"#ifdef VERBOSE",
+	"				this = pptr(otrpt->pr);",
+	"	#ifdef VERBOSE",
 	"				printf(\"\\treset state of %%d from %%d to %%d\\n\",",
 	"					otrpt->pr, ((P0 *)this)->_p, otrpt->st);",
-	"#endif",
+	"	#endif",
 	"				((P0 *)this)->_p = otrpt->st;",
 	"				unsend(boq);	/* retract rv offer */",
 	"				boq = -1;",
 
 	"				push_bfs(x, x->o_tt);",
-	"#ifdef VERBOSE",
+	"	#ifdef VERBOSE",
 	"				printf(\"failed rv, repush with %%d\\n\", x->o_pm);",
-	"#endif",
+	"	#endif",
 	"			}",
-	"#ifdef VERBOSE",
-	"			else printf(\"failed rv, tau at parent: %%d\\n\", x->tau);",
-	"#endif",
+	"	#ifdef VERBOSE",
+	"			else",
+	"			{	printf(\"failed rv, tau at parent: %%d\\n\", x->tau);",
+	"			}",
+	"	#endif",
 	"		} else if (now._nr_pr > 0)",
 	"		{",
 	"			if ((trpt->tau&8))		/* atomic */",
 	"			{	trpt->tau &= ~(1|8);	/* 1=timeout, 8=atomic */",
-	"#ifdef DEBUG",
-	"				printf(\"%%3d: atomic step proc %%d blocks\\n\",",
+	"	#ifdef DEBUG",
+	"				printf(\"%%3ld: atomic step proc %%d blocks\\n\",",
 	"					depth, II+1);",
-	"#endif",
+	"	#endif",
 	"				goto Repeat;",
 	"			}",
 	"",
 	"			if (!(trpt->tau&1)) /* didn't try timeout yet */",
 	"			{	trpt->tau |=  1;",
-	"#ifdef DEBUG",
-	"				printf(\"%%d: timeout\\n\", depth);",
-	"#endif",
+	"	#ifdef DEBUG",
+	"				printf(\"%%ld: timeout\\n\", depth);",
+	"	#endif",
 	"				goto MainLoop;",
 	"			}",
-	"#ifndef VERI",
+	"	#ifndef VERI",
 	"			if (!noends && !a_cycles && !endstate())",
-	"				uerror(\"invalid end state\");",
-	"#endif",
+	"			{	uerror(\"invalid end state\");",
+	"			}",
+	"	#endif",
 	"	}	}",
 	"}",
+	"#endif",	/* !BFS_PAR */
 	"",
 	"void",
 	"putter(Trail *trpt, int fd)",
@@ -1252,19 +1816,27 @@
 	"}",
 	"",
 	"void",
-	"nuerror(char *str)",
+	"n_ewrite(int fd, char *s, int n)",
+	"{	if (write(fd, s, strlen(s)) != strlen(s))",
+	"	{       printf(\"pan: error writing %%s\\n\", fnm);",
+	"		pan_exit(1);",
+	"	}",
+	"}",
+	"",
+	"void",
+	"nuerror(void)",
 	"{	int fd = make_trail();",
 	"	int j;",
 	"",
 	"	if (fd < 0) return;",
-	"#ifdef VERI",
-	"	sprintf(snap, \"-2:%%d:-2\\n\", VERI);",
-	"	write(fd, snap, strlen(snap));",
-	"#endif",
-	"#ifdef MERGED",
-	"	sprintf(snap, \"-4:-4:-4\\n\");",
-	"	write(fd, snap, strlen(snap));",
-	"#endif",
+	"	#ifdef VERI",
+	"		sprintf(snap, \"-2:%%d:-2\\n\", (uchar) ((P0 *)pptr(0))->_t);",
+	"		n_ewrite(fd, snap, strlen(snap));",
+	"	#endif",
+	"	#ifdef MERGED",
+	"		sprintf(snap, \"-4:-4:-4\\n\");",
+	"		n_ewrite(fd, snap, strlen(snap));",
+	"	#endif",
 	"	trcnt = 1;",
 	"	putter(trpt, fd);",
 	"	if (ntrpt->o_t)",	/* 4.2.8 -- Alex example, missing last transition */
@@ -1271,14 +1843,11 @@
 	"	{	sprintf(snap, \"%%d:%%d:%%d\\n\",",
 	"			trcnt++, ntrpt->pr, ntrpt->o_t->t_id);",
 	"		j = strlen(snap);",
-	"		if (write(fd, snap, j) != j)",
-	"		{       printf(\"pan: error writing %%s\\n\", fnm);",
-	"			pan_exit(1);",
-	"	}	}",
+	"		n_ewrite(fd, snap, j);",
+	"	}",
 	"	close(fd);",
 	"	if (errors >= upto && upto != 0)",
-	"	{",
-	"		wrapup();",
+	"	{	wrapup();",
 	"	}",
 	"}",
 	"#endif",	/* BFS */
@@ -1285,8 +1854,141 @@
 	0,
 };
 
-static char *Code2c[] = {
+static const char *Code2d[] = {
+	"clock_t start_time;",
+	"#if NCORE>1",
+	"clock_t crash_stamp;",
+	"#endif",
+	"#if !defined(WIN32) && !defined(WIN64)",
+	"struct tms start_tm;",
+	"#endif",
+	"",
+	"#if SYNC",
+	"extern int q_zero(int);",
+	"extern int not_RV(int);",
+	"#endif",
+	"",
 	"void",
+	"start_timer(void)",
+	"{",
+	"#if defined(WIN32) || defined(WIN64)",
+	"	start_time = clock();",
+	"#else",
+	"	start_time = times(&start_tm);",
+	"#endif",
+	"}",
+	"",
+	"double delta_time;",
+	"",
+	"void",
+	"report_time(void)",
+	"{",
+	"	printf(\"\\npan: elapsed time %%.3g seconds\\n\", delta_time);",
+	"	if (delta_time > 0.01)",
+	"	{	printf(\"pan: rate %%9.8g states/second\\n\", nstates/delta_time);",
+	"		if (verbose)",
+	"		{	printf(\"pan: avg transition delay %%.5g usec\\n\",",
+	"				delta_time/(nstates+truncs));",
+	"	}	}",
+	"}",
+	"",
+	"void",
+	"stop_timer(int report)",
+	"{	clock_t stop_time;",
+	"#if !defined(WIN32) && !defined(WIN64)",
+	"	struct tms stop_tm;",
+	"	stop_time = times(&stop_tm);",
+	"	delta_time = ((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK));",
+	"#else",
+	"	stop_time = clock();",
+	"	delta_time = ((double) (stop_time - start_time)) / ((double) CLOCKS_PER_SEC);",
+	"#endif",
+	"	if (readtrail || delta_time < 0.00) return;",
+	"#if NCORE>1",
+	"	if (core_id == 0 && nstates > (double) 0)",
+	"	{	printf(\"\\ncpu%%d: elapsed time %%.3g seconds (%%g states visited)\\n\",",
+	"			core_id, delta_time, nstates);",
+	"		if (delta_time > 0.01)",
+	"		{	printf(\"cpu%%d: rate %%g states/second\\n\", core_id, nstates/delta_time);",
+	"		}",
+	"		{ void check_overkill(void);",
+	"	 	  check_overkill();",
+	"	}	}",
+	"#else",
+	"	if (report)",
+	"	{	report_time();",
+	"	}",
+	"#endif",
+	"}",
+	"",
+	"#if NCORE>1",
+	"#ifdef T_ALERT",
+	"double t_alerts[17];",
+	"",
+	"void",
+	"crash_report(void)",
+	"{	int i;",
+	"	printf(\"crash alert intervals:\\n\");",
+	"	for (i = 0; i < 17; i++)",
+	"	{	printf(\"%%d\\t%%g\\n\", i, t_alerts[i]);",
+	"}	}",
+	"#endif",
+	"",
+	"void",
+	"crash_reset(void)",
+	"{	/* false alarm */",
+	"	if (crash_stamp != (clock_t) 0)",
+	"	{",
+	"#ifdef T_ALERT",
+	"		double delta_time;",
+	"		int i;",
+		"#if defined(WIN32) || defined(WIN64)",
+	"		delta_time = ((double) (clock() - crash_stamp)) / ((double) CLOCKS_PER_SEC);",
+		"#else",
+	"		delta_time = ((double) (times(&start_tm) - crash_stamp)) / ((double) sysconf(_SC_CLK_TCK));",
+		"#endif",
+	"		for (i = 0; i < 16; i++)",
+	"		{	if (delta_time <= (i*30))",
+	"			{	t_alerts[i] = delta_time;",
+	"				break;",
+	"		}	}",
+	"		if (i == 16) t_alerts[i] = delta_time;",
+	"#endif",
+	"		if (verbose)",
+	"		printf(\"cpu%%d: crash alert off\\n\", core_id);",
+	"	}",
+	"	crash_stamp = (clock_t) 0;",
+	"}",
+	"",
+	"int",
+	"crash_test(double maxtime)",
+	"{	double delta_time;",
+	"	if (crash_stamp == (clock_t) 0)",
+	"	{	/* start timing */",
+	"#if defined(WIN32) || defined(WIN64)",
+	"		crash_stamp = clock();",
+	"#else",
+	"		crash_stamp = times(&start_tm);",
+	"#endif",
+	"		if (verbose)",
+	"		{	printf(\"cpu%%d: crash detection\\n\", core_id);",
+	"		}",
+	"		return 0;",
+	"	}",
+	"#if defined(WIN32) || defined(WIN64)",
+	"	delta_time = ((double) (clock() - crash_stamp)) / ((double) CLOCKS_PER_SEC);",
+	"#else",
+	"	delta_time = ((double) (times(&start_tm) - crash_stamp)) / ((double) sysconf(_SC_CLK_TCK));",
+	"#endif",
+	"	return (delta_time >= maxtime);",
+	"}",
+	"#endif",
+	"",
+	"#ifdef BFS_PAR",
+	"int ncores = 0;",
+	"#endif",
+	"",
+	"void",
 	"do_the_search(void)",
 	"{	int i;",
 	"	depth = mreached = 0;",
@@ -1300,11 +2002,13 @@
 	"		if (!(trpt->o_pm&2)",
 	"		&&  accpstate[ptr->_t][ptr->_p])",
 	"		{	trpt->o_pm |= 2;",
+	"			break;",
 	"		}",
 	"#else",
 	"		if (!(trpt->o_pm&4)",
 	"		&&  progstate[ptr->_t][ptr->_p])",
 	"		{	trpt->o_pm |= 4;",
+	"			break;",
 	"		}",
 	"#endif",
 	"	}",
@@ -1319,21 +2023,21 @@
 	"	}",
 	"#endif",
 	"#endif",
-	"#ifndef NOCOMP",
+	"#if !defined(NOCOMP) && !defined(HC)",
 	"	Mask[0] = Mask[1] = 1;	/* _nr_pr, _nr_qs */",
 	"	if (!a_cycles)",
 	"	{	i = &(now._a_t) - (uchar *) &now;",
 	"		Mask[i] = 1; /* _a_t */",
 	"	}",
-	"#ifndef NOFAIR",
-	"	if (!fairness)",
-	"	{	int j = 0;",
-	"		i = &(now._cnt[0]) - (uchar *) &now;",
-	"		while (j++ < NFAIR)",
-	"			Mask[i++] = 1; /* _cnt[] */",
-	"	}",
+	"	#ifndef NOFAIR",
+	"		if (!fairness)",
+	"		{	int j = 0;",
+	"			i = &(now._cnt[0]) - (uchar *) &now;",
+	"			while (j++ < NFAIR)",
+	"				Mask[i++] = 1; /* _cnt[] */",
+	"		}",
+	"	#endif",
 	"#endif",
-	"#endif",
 	"#ifndef NOFAIR",
 	"	if (fairness",
 	"	&&  (a_cycles && (trpt->o_pm&2)))",
@@ -1340,12 +2044,19 @@
 	"	{	now._a_t = 2;	/* set the A-bit */",
 	"		now._cnt[0] = now._nr_pr + 1;",	/* NEW: +1 */
 		"#ifdef VERBOSE",
-	"	printf(\"%%3d: fairness Rule 1, cnt=%%d, _a_t=%%d\\n\",",
+	"	printf(\"%%3ld: fairness Rule 1, cnt=%%d, _a_t=%%d\\n\",",
 	"		depth, now._cnt[now._a_t&1], now._a_t);",
 		"#endif",
 	"	}",
 	"#endif",
 
+	"	c_stack_start = (char *) &i; /* meant to be read-only */",
+
+	"#if defined(HAS_CODE) && defined (C_INIT)",
+	"	C_INIT; /* initialization of data that must precede fork() */",
+	"	c_init_done++;",
+	"#endif",
+
 	"#if defined(C_States) && (HAS_TRACK==1)",
 	"	/* capture initial state of tracked C objects */",
 	"	c_update((uchar *) &(now.c_state[0]));",
@@ -1354,17 +2065,30 @@
 	"#ifdef HAS_CODE",
 	"	if (readtrail) getrail(); /* no return */",
 	"#endif",
+	"#ifndef BFS_PAR",
+	"	start_timer();",
+	"#endif",
 	"#ifdef BFS",
-	"	bfs();",
+	"	#ifdef BFS_PAR",
+	"		bfs_main(ncores,0);",
+	"	#else",
+	"		bfs();",
+	"	#endif",
 	"#else",
-		"#if defined(C_States) && defined(HAS_STACK) && (HAS_TRACK==1)",
-		"	/* initial state of tracked & unmatched objects */",
-		"	c_stack((uchar *) &(svtack->c_stack[0]));",
-		"#endif",
-		"#ifdef RANDOMIZE",
-	"	srand(123);",
-		"#endif",
-	"	new_state();	/* start 1st DFS */",
+	"	#if defined(C_States) && defined(HAS_STACK) && (HAS_TRACK==1)",
+	"		/* initial state of tracked & unmatched objects */",
+	"		c_stack((uchar *) &(svtack->c_stack[0]));",
+	"	#endif",
+
+	"	#if defined(P_RAND) || defined(T_RAND)",
+	"		srand(s_rand+HASH_NR);", /* do_the_search */
+	"	#endif",
+
+	"	#if NCORE>1",
+	"		mem_get();",
+	"	#else",
+	"		new_state();	/* start 1st DFS */",
+	"	#endif",
 	"#endif",
 	"}",
 
@@ -1373,42 +2097,41 @@
 	"do_reverse(Trans *t, short II, uchar M)",
 	"{	uchar _m = M;",
 	"	int  tt = (int) ((P0 *)this)->_p;",
-	"#include REVERSE_MOVES",
+	"#include BACKWARD_MOVES",
 	"R999:	return _m;",
 	"}",
 	"#endif",
 
 	"#ifndef INLINE",
-	"#ifdef EVENT_TRACE",
+	"	#ifdef EVENT_TRACE",
 	"static char _tp = 'n'; static int _qid = 0;",
-	"#endif",
+	"	#endif",
 	"uchar",
 	"do_transit(Trans *t, short II)",
 	"{	uchar _m = 0;",
 	"	int  tt = (int) ((P0 *)this)->_p;",
-	"#ifdef M_LOSS",
+	"	#ifdef M_LOSS",
 	"	uchar delta_m = 0;",
-	"#endif",
-	"#ifdef EVENT_TRACE",
+	"	#endif",
+	"	#ifdef EVENT_TRACE",
 	"	short oboq = boq;",
 	"	uchar ot = (uchar)  ((P0 *)this)->_t;",
-	"	if (ot == EVENT_TRACE) boq = -1;",
+	"	if (II == -EVENT_TRACE) boq = -1;",
 		"#define continue	{ boq = oboq; return 0; }",
-	"#else",
+	"	#else",
 		"#define continue	return 0",
 		"#ifdef SEPARATE",
 	"	uchar ot = (uchar)  ((P0 *)this)->_t;",
 		"#endif",
-	"#endif",
+	"	#endif",
 	"#include FORWARD_MOVES",
 	"P999:",
-	"#ifdef EVENT_TRACE",
-	"	if (ot == EVENT_TRACE) boq = oboq;",
-	"#endif",
+	"	#ifdef EVENT_TRACE",
+	"	if (II == -EVENT_TRACE) boq = oboq;",
+	"	#endif",
 	"	return _m;",
-	"#undef continue",
+	"	#undef continue",
 	"}",
-
 	"#ifdef EVENT_TRACE",
 	"void",
 	"require(char tp, int qid)",
@@ -1417,67 +2140,65 @@
 	"",
 	"	if (now._event != endevent)",
 	"	for (t = trans[EVENT_TRACE][now._event]; t; t = t->nxt)",
-	"	{	if (do_transit(t, EVENT_TRACE))",
+	"	{	if (do_transit(t, -EVENT_TRACE))",
 	"		{	now._event = t->st;",
 	"			reached[EVENT_TRACE][t->st] = 1;",
-	"#ifdef VERBOSE",
+	"	#ifdef VERBOSE",
 	"	printf(\"	event_trace move to -> %%d\\n\", t->st);",
-	"#endif",
-	"#ifndef BFS",
-		"#ifndef NP",
+	"	#endif",
+	"	#ifndef BFS",
+		"	#ifndef NP",
 	"			if (accpstate[EVENT_TRACE][now._event])",
 	"				(trpt+1)->o_pm |= 2;",
-		"#else",
+		"	#else",
 	"			if (progstate[EVENT_TRACE][now._event])",
 	"				(trpt+1)->o_pm |= 4;",
-		"#endif",
-	"#endif",
-	"#ifdef NEGATED_TRACE",
+		"	#endif",
+	"	#endif",
+	"	#ifdef NEGATED_TRACE",
 	"			if (now._event == endevent)",
 	"			{",
-		"#ifndef BFS",
+		"	#ifndef BFS",
 	"				depth++; trpt++;",
-		"#endif",
+		"	#endif",
 	"				uerror(\"event_trace error (all events matched)\");",
-		"#ifndef BFS",
+		"	#ifndef BFS",
 	"				trpt--; depth--;",
-		"#endif",
+		"	#endif",
 	"				break;",
 	"			}",
-	"#endif",
+	"	#endif",
 	"			for (t = t->nxt; t; t = t->nxt)",
-	"			{	if (do_transit(t, EVENT_TRACE))",
+	"			{	if (do_transit(t, -EVENT_TRACE))",
 	"				 Uerror(\"non-determinism in event-trace\");",
 	"			}",
 	"			return;",
 	"		}",
-	"#ifdef VERBOSE",
+	"	#ifdef VERBOSE",
 	"		 else",
 	"	printf(\"	event_trace miss '%%c' -- %%d, %%d, %%d\\n\",",
 	"			tp, qid, now._event, t->forw);",
-	"#endif",
+	"	#endif",
 	"	}",
-	"#ifdef NEGATED_TRACE",
+	"	#ifdef NEGATED_TRACE",
 	"	now._event = endevent; /* only 1st try will count -- fixed 4.2.6 */",
-	"#else",	
-		"#ifndef BFS",
+	"	#else",	
+	"		#ifndef BFS",
 	"	depth++; trpt++;",
-		"#endif",
+	"		#endif",
 	"	uerror(\"event_trace error (no matching event)\");",
-		"#ifndef BFS",
+	"		#ifndef BFS",
 	"	trpt--; depth--;",
-		"#endif",
-	"#endif",
+	"		#endif",
+	"	#endif",
 	"}",
 	"#endif",
-
 	"int",
 	"enabled(int iam, int pid)",
 	"{	Trans *t; uchar *othis = this;",
 	"	int res = 0; int tt; uchar ot;",
-	"#ifdef VERI",
-	"	/* if (pid > 0) */ pid++;",
-	"#endif",
+	"",
+	"	pid += BASE;",
 	"	if (pid == iam)",
 	"		Uerror(\"used: enabled(pid=thisproc)\");",
 	"	if (pid < 0 || pid >= (int) now._nr_pr)",
@@ -1496,21 +2217,132 @@
 	"	return res;",
 	"}",
 	"#endif",
+	"",
+	"#ifdef HAS_PRIORITY",
+	"int",
+	"highest_priority(int pid, short nII, Trans *t)",
+	"{	int i = pid; uchar *othis = this;",
+	"",
+	"#ifdef VERI",
+	"	if (nII == 0)",
+	"	{	return 1;", /* never claim */
+	"	}",
+	"#endif",
+	"#ifdef HAS_PROVIDED",
+	"	i = pid+BASE;",	 /* uncorrected process number */
+	"#endif",
+	"	if (i < 0",
+	"	||  i >= (int) now._nr_pr",
+	"#ifdef HAS_PROVIDED",
+	"	|| !provided(i, (uchar) ((P0 *)this)->_t, (int) ((P0 *)this)->_p, t)",
+	"#endif",
+	"	)",
+	"	{	return 0;",
+	"	}",
+	"",
+	"	for (i = BASE; i < now._nr_pr; i++)",	/* all except never, if present */
+	"	{	this = pptr(i);",
+	"		if (i != pid+BASE",
+	"		&&  ((P0 *)this)->_priority > ((P0 *)pptr(pid+BASE))->_priority",
+	"#ifdef HAS_PROVIDED",
+	"		&&  provided(i, (uchar) ((P0 *)this)->_t, (int) ((P0 *)this)->_p, 0)",
+	"#endif",
+	"		&&  enabled(i+1, i-BASE))", /* enabled adds back BASE in 2nd arg */
+	"		{	this = othis;",
+	"			return 0;",
+	"	}	}",
+	"	this = othis;",
+	"	return 1;",
+	"}",
+	"int",
+	"get_priority(int pid)",
+	"{	pid += BASE;	/* 6.2.7 */",
+	"	if (pid < 0 || pid >= (int) now._nr_pr)",
+	"		return 0;",
+	"	return ((P0 *)pptr(pid))->_priority;",
+	"}",
+	"int",
+	"set_priority(int pid, int pr)",
+	"{	pid += BASE;	/* 6.2.7 */",
+	"	if (pid < 0 || pid >= (int) now._nr_pr)",
+	"	{",
+	"	#ifdef VERBOSE",
+	"		printf(\"warning: bad pid %%d, no such process (set_priority)\\n\", pid);",
+	"	#endif",
+	"		return 1;",
+	"	}",
+	"	if (pr < 1 || pr > 255)",
+	"	{	Uerror(\"priority is out of range\");",
+	"	}",
+
+	"	if (!TstOnly)",
+	"	{	(trpt+1)->o_priority = ",
+	"		(((P0 *)pptr(pid))->_priority & 255) | (pid << 8);",
+	"		((P0 *)pptr(pid))->_priority = pr;",
+	"	}",
+
+	"	return 1;", /* always executable */
+	"}",
+	"#endif",
+	"",
 	"void",
+	"snap_time(void)",
+	"{	clock_t stop_time;",
+	"	double delta_time;",
+	"#if !defined(WIN32) && !defined(WIN64)",
+	"	struct tms stop_tm;",
+	"	stop_time  = times(&stop_tm);",
+	"	delta_time = ((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK));",
+	"#else",
+	"	stop_time  = clock();",
+	"	delta_time = ((double) (stop_time - start_time)) / ((double) CLOCKS_PER_SEC);",
+	"#endif",
+	"	if (delta_time > 0.01)",
+	"	{	printf(\"t= %%8.3g \", delta_time);",
+	"		printf(\"R= %%7.0g\", nstates/delta_time);",
+	"	}",
+	"	printf(\"\\n\");",
+	"	if (quota > 0.1 && delta_time > quota)",
+	"	{	printf(\"Time limit of %%6.3g minutes exceeded\\n\", quota/60.0);",
+	"#if NCORE>1",
+	"		fflush(stdout);",
+	"		leave_critical(GLOBAL_LOCK);",
+	"		sudden_stop(\"time-limit\");",
+	"		exit(1);",
+	"#endif",
+	"		wrapup();",
+	"	}",
+	"}",
+	"void",
 	"snapshot(void)",
-	"{	static long sdone = (long) 0;",
-	"	long ndone = (unsigned long) nstates/1000000;",
-	"	if (ndone == sdone) return;",
-	"	sdone = ndone;",
-	"	printf(\"Depth= %%7d States= %%7g \", mreached, nstates);",
-	"	printf(\"Transitions= %%7g \", nstates+truncs);",
+	"{",
+	"#ifdef BFS_PAR",
+	"	e_critical(BFS_GLOB);		/* bfs_par / snapshot */",
+	"	printf(\"cpu%%d: \", who_am_i);",
+	"#endif",
+	"#if NCORE>1",
+	"	enter_critical(GLOBAL_LOCK);	/* ncore / snapshot */",
+	"	printf(\"cpu%%d: \", core_id);",
+	"#endif",
+	"	printf(\"Depth= %%7ld States= %%8.3g \",",
+	"#if NCORE>1",
+	"		(long) (nr_handoffs * z_handoff) +",
+	"#endif",
+	"		mreached, nstates);",
+	"	printf(\"Transitions= %%8.3g \", nstates+truncs);",
 	"#ifdef MA",
-	"	printf(\"Nodes= %%7d \", nr_states);",
+	"	printf(\"Nodes= %%7lu \", nr_states);",
 	"#endif",
-	"	printf(\"Memory= %%-6.3f\\n\", memcnt/1000000.);",
+	"	printf(\"Memory= %%9.3f\\t\", memcnt/1048576.);",
+	"	snap_time();",
 	"	fflush(stdout);",
+	"#if NCORE>1",
+	"	leave_critical(GLOBAL_LOCK);",
+	"#endif",
+	"#ifdef BFS_PAR",
+	"	x_critical(BFS_GLOB);",
+	"#endif",
 	"}",
-
 	"#ifdef SC",
 	"void",
 	"stack2disk(void)",
@@ -1552,46 +2384,246 @@
 	"#endif",
 
 	"uchar *",
-	"Pptr(int x)",	/* as a fct, to avoid a problem with the p9 compiler */
-	"{	if (x < 0 || x >= MAXPROC || !proc_offset[x])",	/* does not exist */
+	"Pptr(int x)",
+	"{	if (x < 0 || x >= MAXPROC",	/* does not exist */
+	"#ifdef TRIX",
+	"	|| !processes[x])",
+	"#else",
+	"	|| !proc_offset[x])",
+	"#endif",
 	"		return noptr;",
 	"	else",
 	"		return (uchar *) pptr(x);",
+	"}\n",
+	"uchar *",
+	"Qptr(int x)",
+	"{	if (x < 0 || x >= MAXQ",
+	"#ifdef TRIX",
+	"	|| !channels[x])",
+	"#else",
+	"	|| !q_offset[x])",
+	"#endif",
+	"		return noqptr;",
+	"	else",
+	"		return (uchar *) qptr(x);",
+	"}\n",
+	"",
+	"#if NCLAIMS>1",
+	"void",
+	"select_claim(int n)",
+	"{	int m, i;",
+	"	if (n < 0 || n >= NCLAIMS)",
+	"	{	uerror(\"non-existing claim\");",
+	"	} else",
+	"	{	m = ((Pclaim *)pptr(0))->_n;",
+	"		if (verbose)",
+	"		{	printf(\"%%d: Claim %%s (%%d), from state %%d\\n\",",
+	"				(int) depth, procname[spin_c_typ[n]],",
+	"				n, ((Pclaim *)pptr(0))->c_cur[n]);",
+	"		} else",
+	"		{	printf(\"pan: ltl formula %%s\\n\",",
+	"				procname[spin_c_typ[n]]);",
+	"		}",
+	"		((Pclaim *)pptr(0))->c_cur[m] = ((Pclaim *)pptr(0))->_p;",
+	"		((Pclaim *)pptr(0))->_t = spin_c_typ[n];",
+	"		((Pclaim *)pptr(0))->_p = ((Pclaim *)pptr(0))->c_cur[n];",
+	"		((Pclaim *)pptr(0))->_n = n;",
+	"		for (i = 0; src_all[i].src != (short *) 0; i++)",
+	"		{	if (src_all[i].tp == spin_c_typ[n])",
+	"			{	src_claim = src_all[i].src;",
+	"				break;",
+	"		}	}", 
+	"		if (src_all[i].src == (short *) 0)",
+	"		{	uerror(\"cannot happen: src_ln ref\");",
+	"	}	}",
 	"}",
+	"#else",
+	"void",
+	"select_claim(int n)",
+	"{	if (n != 0) uerror(\"non-existing claim\");",
+	"}",
+	"#endif",
+
 	"int qs_empty(void);",
+	"#if !defined(BFS) && (!defined(BITSTATE) || !defined(MA))",
+	"#ifdef NSUCC",
+	"int N_succ[512];",
+	"void",
+	"tally_succ(int cnt)",
+	"{	if (cnt < 512) N_succ[cnt]++;",
+	"	else printf(\"tally_succ: cnt %%d exceeds range\\n\", cnt);",
+	"}",
+	"",
+	"void",
+	"dump_succ(void)",
+	"{	int i; double sum = 0.0;",
+	"	double w_avg = 0.0;",
+	"	printf(\"Successor counts:\\n\");",
+	"	for (i = 0; i < 512; i++)",
+	"	{	sum += (double) N_succ[i];",
+	"	}",
+	"	for (i = 0; i < 512; i++)",
+	"	{	if (N_succ[i] > 0)",
+	"		{	printf(\"%%3d\t%%10d\t(%%.4g %%%% of total)\\n\",",
+	"				i, N_succ[i], (100.0 * (double) N_succ[i])/sum);",
+	"			w_avg += (double) i * (double) N_succ[i];",
+	"	}	}",
+	"	if (sum > N_succ[0])",
+	"	printf(\"mean %%.4g (without 0: %%.4g)\\n\", w_avg / sum, w_avg / (sum - (double) N_succ[0]));",
+	"}",
+	"#endif",
+	"",
+	"#ifdef P_REVERSE",
+	"	#define FROM_P	(BASE)",
+	"	#define UPTO_P	(now._nr_pr-1)",
+	"	#define MORE_P	(II <= To)",		/* p.o. only */
+	"	#define INI_P	(From-1)",		/* fairness only */
+	"	#define CNT_P	(1 + (To - From))",	/* P_RAND start */
+	"	#define NDONE_P	(From <= To)",		/* P_RAND continue */
+	"	#define ALL_P	(II = From; II <= To; II++)",
+	"#else",
+	"	#define FROM_P	(now._nr_pr-1)",
+	"	#define UPTO_P	(BASE)",
+	"	#define MORE_P	(II >= BASE)",
+	"	#define INI_P	(From+1)",
+	"	#define CNT_P	(1 + (From - To))",
+	"	#define NDONE_P	(From >= To)",
+	"	#define ALL_P	(II = From; II >= To; II--)",
+	"#endif",
+	"",
+	"#ifdef PERMUTED",
+	"	#define CONTINUE0 { if (reversing&2) { II = oII; } continue; }",
+	"	#define CONTINUE  { if (reversing&2) { p_reorder(seed); II = oII; } continue; }",
+	"#else",
+	"	#define CONTINUE0 { continue; }",
+	"	#define CONTINUE  { continue; }",
+	"#endif",
 
+	"#ifdef PERMUTED",
+	"uchar _permutation_[256];",
+	"void",
+	"set_reversed(int unused)",
+	"{	int i, n = now._nr_pr;",
+	"  #ifdef VERBOSE",
+	"	printf(\"%%ld: Set_reversed\\n\", depth);",
+	"  #endif",
+	"  #if defined(VERI) && !defined(NOCLAIM)",
+	"	for (i = 1; i < n; i++)",
+	"	{	_permutation_[i] = n-i;",
+	"	}",
+	"  #else",
+	"	for (i = 0; i < n; i++)",
+	"	{	_permutation_[i] = n-1-i;",
+	"	}",
+	"  #endif",
+	"}",
+	"void",
+	"set_rotated(int unused)",
+	"{	int i, n = now._nr_pr;",
+	"  #ifdef VERBOSE",
+	"	printf(\"%%ld: Set_rotated %%d\\n\", depth, p_rotate);",
+	"  #endif",
+	"  #if defined(VERI) && !defined(NOCLAIM)",
+	"	for (i = 1; i < n; i++)",
+	"	{	_permutation_[i] = 1+(i-1+p_rotate)%%(n-1);",
+	"	}",
+	"  #else",
+	"	for (i = 0; i < n; i++)",
+	"	{	_permutation_[i] = (i+p_rotate)%%n;",
+	"	}",
+	"  #endif",
+	"}",
+	"void",
+	"set_randrot(int unused)",
+	"{",
+	"	if (now._nr_pr > 1)",
+	"	{	p_rotate = 1+rand()%%(now._nr_pr-1);",
+	"	} else",
+	"	{	p_rotate = 0;",
+	"	}",
+	"	set_rotated(0);",
+	"}",
+	"void",
+	"set_permuted(int T)",
+	"{	/* permute nrs 1..n-1, leave 0 in place */",
+	"	int i, j, k, n = now._nr_pr;",
+	"	char tmp, *in = &(_permutation_[0]);",
+	"  #ifdef VERBOSE",
+	"	printf(\"%%ld: Set_permuted %%d\\n\", depth, T);",
+	"  #endif",
+	"	srand(T);",	/* set_permuted */
+	"	for (i = 0; i < n; i++)",
+	"	{	in[i] = i;",
+	"	}",
+	"	if (n > 1)",
+	"	{  for (i = 0; i < n; i++)",
+	"	   {",
+	"  #if defined(VERI) && !defined(NOCLAIM)",
+	"		j = 1 + rand()%%(n-1);",
+	"		k = 1 + rand()%%(n-1);",
+	"  #else",
+	"		j = rand()%%(n);",
+	"		k = rand()%%(n);",
+	"  #endif",
+	"		tmp   = in[j];",
+	"		in[j] = in[k];",
+	"		in[k] = tmp;",
+	"	}  }",
+	"}",
+	"",
+	"  #ifdef VERBOSE",
+	"	short",
+	"	get_permuted(int x)",
+	"	{	printf(\"%%ld: Get_permuted %%d -> %%d\\n\",",
+	"			depth, x, _permutation_[x]);",
+	"		return (short) _permutation_[x];",
+	"	}",
+	"  #else",
+	"	#define get_permuted(x)  (short) _permutation_[x]",
+	"  #endif",
+	"",
+	"#endif",
 	"/*",
 	" * new_state() is the main DFS search routine in the verifier",
 	" * it has a lot of code ifdef-ed together to support",
 	" * different search modes, which makes it quite unreadable.",
-	" * if you are studying the code, first use the C preprocessor",
+	" * if you are studying the code, use the C preprocessor",
 	" * to generate a specific version from the pan.c source,",
 	" * e.g. by saying:",
 	" *	gcc -E -DNOREDUCE -DBITSTATE pan.c > ppan.c",
-	" * and then study the resulting file, rather than this one",
+	" * and then study the resulting file, instead of this version",
 	" */",
-	"#if !defined(BFS) && (!defined(BITSTATE) || !defined(MA))",
+	"",
 	"void",
 	"new_state(void)",
 	"{	Trans *t;",
 	"	uchar _n, _m, ot;",
-	"#ifdef RANDOMIZE",
+	"#ifdef T_RAND",
 	"	short ooi, eoi;",
 	"#endif",
+	"#ifdef PERMUTED",
+	"	short oII; uint seed;",
+	"#endif",
 	"#ifdef M_LOSS",
 	"	uchar delta_m = 0;",
 	"#endif",
 	"	short II, JJ = 0, kk;",
 	"	int tt;",
-	"	short From = now._nr_pr-1, To = BASE;",
+	"	short From = FROM_P, To = UPTO_P;",
+	"#ifdef BCS",
+	"	trpt->sched_limit = 0; /* at depth=0 only */",
+	"#endif",
 	"Down:",
 	"#ifdef CHECK",
-	"	printf(\"%%d: Down - %%s\",",
-	"		depth, (trpt->tau&4)?\"claim\":\"program\");",
-	"	printf(\" %%saccepting [pids %%d-%%d]\\n\",",
+	"	cpu_printf(\"%%d: Down - %%s %%saccepting [pids %%d-%%d]\\n\",",
+	"		depth, (trpt->tau&4)?\"claim\":\"program\",",
 	"		(trpt->o_pm&2)?\"\":\"non-\", From, To);",
 	"#endif",
 
+	"#ifdef P_RAND",
+	"	trpt->p_skip = -1;",
+	"#endif",
+
 	"#ifdef SC",
 	"	if (depth > hiwater)",
 	"	{	stack2disk();",
@@ -1599,7 +2631,7 @@
 	"		hiwater += DDD;",
 	"		trpt -= DDD;",
 	"		if(verbose)",
-	"		printf(\"zap %%d: %%d (maxdepth now %%d)\\n\",",
+	"		printf(\"zap %%ld: %%ld (maxdepth now %%ld)\\n\",",
 	"			CNT1, hiwater, maxdepth);",
 	"	}",
 	"#endif",
@@ -1608,23 +2640,54 @@
 	"#if defined(FULLSTACK) && defined(MA)",
 	"	trpt->proviso = 0;",
 	"#endif",
-	"	if (depth >= maxdepth)",
-	"	{	truncs++;",
+	"#ifdef NSUCC",
+	"	trpt->n_succ = 0;",
+	"#endif",
+	"#if NCORE>1",
+	"	if (mem_hand_off())",
+	"	{",
 	"#if SYNC",
-	"		(trpt+1)->o_n = 1; /* not a deadlock */",
+	"		(trpt+1)->o_n = 1;	/* not a deadlock: as below  */",
 	"#endif",
-	"		if (!warned)",
+	"#ifndef LOOPSTATE",
+	"		(trpt-1)->tau |= 16;	/* worstcase guess: as below */",
+	"#endif",
+	"#if NCORE>1 && defined(FULL_TRAIL)",
+	"		if (upto > 0)",
+	"		{	Pop_Stack_Tree();",
+	"		}",
+	"#endif",
+	"		goto Up;",
+	"	}",
+	"#endif",
+
+	"	if (depth >= maxdepth)",
+	"	{	if (!warned)",
 	"		{ warned = 1;",
 	"		  printf(\"error: max search depth too small\\n\");",
 	"		}",
-	"		if (bounded) uerror(\"depth limit reached\");",
-	"		(trpt-1)->tau |= 16; /* worstcase guess */",
+	"		if (bounded)",
+	"		{	uerror(\"depth limit reached\");",
+	"		}",
+	"		truncs++;",
+	"#if SYNC",
+	"		(trpt+1)->o_n = 1; /* not a deadlock */",
+	"#endif",
+	"#ifndef LOOPSTATE",
+	"		(trpt-1)->tau |= 16;	/* worstcase guess */",
+	"#endif",
+
+	"#if NCORE>1 && defined(FULL_TRAIL)",
+	"		if (upto > 0)",
+	"		{	Pop_Stack_Tree();",
+	"		}",
+	"#endif",
 	"		goto Up;",
 	"	}",
 	"AllOver:",
-	"#if defined(FULLSTACK) && !defined(MA)",
+	"#if (defined(FULLSTACK) && !defined(MA)) || NCORE>1",
 	"	/* if atomic or rv move, carry forward previous state */",
-	"	trpt->ostate = (trpt-1)->ostate;",	/* was: = (struct H_el *) 0;*/
+	"	trpt->ostate = (trpt-1)->ostate;",
 	"#endif",
 	"#ifdef VERI",
 	"	if ((trpt->tau&4) || ((trpt-1)->tau&128))",
@@ -1631,51 +2694,115 @@
 	"#endif",
 	"	if (boq == -1) {	/* if not mid-rv */",
 	"#ifndef SAFETY",
-	"		/* this check should now be redundant",
-	"		 * because the seed state also appears",
-	"		 * on the 1st dfs stack and would be",
-	"		 * matched in hstore below",
-	"		 */",
+#if 0
+	we want to skip nrpr, nrqs, _a_t and cnt[NFAIR] (in the case of fairness)
+	this is calculated in S_A, but S_A subtracts 2 bytes,
+	because nrpr and nrqs are masked in the default state comparisons
+	so we add those two bytes back here
+	-- in default comparisons (h_store) we skip _a_t and cnt in the
+	-- first comparison to find a match on the base-state
+	-- the _a_t and cnt fields are then separately updated if there was
+	-- a match on the base state
+#endif
 	"		if ((now._a_t&1) && depth > A_depth)",
-	"		{	if (!memcmp((char *)&A_Root, ",
-	"				(char *)&now, vsize))",
+	"		{	int delta = S_A + 2;",
+	"			if (!memcmp((char *)&A_Root + delta, ",
+	"				(char *)&now + delta, vsize - delta))",
 	"			{",
-	"				depthfound = A_depth;",
-		"#ifdef CHECK",
-	"			  printf(\"matches seed\\n\");",
-		"#endif",
-		"#ifdef NP",
-	"			  uerror(\"non-progress cycle\");",
-		"#else",
-	"			  uerror(\"acceptance cycle\");",
-		"#endif",
-	"			  goto Up;",
+	"#ifndef NOFAIR",
+	"			   if (fairness && now._cnt[1] != 1) /* was > 1 */",
+	"			   {",
+	"	#ifdef CHECK",
+	"				printf(\"\tfairness count non-zero\\n\");",
+	"	#endif",
+	"				/* treat as new state */",
+	"			   } else",
+	"#endif",
+	"			   {	depthfound = A_depth;",
+	"	#ifdef CHECK",
+	"				printf(\"matches seed\\n\");",
+	"	#endif",
+	"	#ifdef NP",
+	"				uerror(\"non-progress cycle\");",
+	"	#else",
+	"				uerror(\"acceptance cycle\");",
+	"	#endif",
+	"	#if NCORE>1 && defined(FULL_TRAIL)",
+	"				if (upto > 0)",
+	"				{	Pop_Stack_Tree();",
+	"				}",
+	"	#endif",
+	"				goto Up;",
+	"			}  }",
+	"	#ifdef CHECK",
+	"			else",
+	"			{",
+	"			   printf(\"not seed\\n\");",
 	"			}",
-		"#ifdef CHECK",
-	"			printf(\"not seed\\n\");",
-		"#endif",
+	"	#endif",
 	"		}",
 	"#endif",
 	"		if (!(trpt->tau&8)) /* if no atomic move */",
 	"		{",
+	"#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+	"			uchar was_last = now._last;",
+	"			now._last = 0;	/* value not stored */",
+	"#endif",
 	"#ifdef BITSTATE",
 		"#ifdef CNTRSTACK",	/* -> bitstate, reduced, safety */
-	"			II = bstore((char *)&now, vsize);",
-	"			trpt->j6 = j1; trpt->j7 = j2;",
-	"			JJ = LL[j1] && LL[j2];",
+	"		#if defined(BCS) && defined(STORE_CTX)",
+	"		{ int xj;",
+	"			for (xj = trpt->sched_limit; xj <= sched_max; xj++)",
+	"			{	now._ctx = xj;",
+	"				II = b_store((char *)&now, vsize);",
+	"				trpt->j6 = j1_spin; trpt->j7 = j2_spin;",
+	"				JJ = LL[j1_spin] && LL[j2_spin];",
+	"				if (II != 0) { break; }",
+	"			}",
+	"			now._ctx = 0; /* just in case */",
+	"		}",
+	"		#else",
+	"			II = b_store((char *)&now, vsize);",
+	"			trpt->j6 = j1_spin; trpt->j7 = j2_spin;",
+	"			JJ = LL[j1_spin] && LL[j2_spin];",
+	"		#endif",
 		"#else",
-			"#ifdef FULLSTACK",
-	"			JJ = onstack_now();",		    /* sets j1 */
-			"#else",
-				"#ifndef NOREDUCE",
-	"			JJ = II; /* worstcase guess for p.o. */",
-				"#endif",
-			"#endif",
-	"			II = bstore((char *)&now, vsize);", /* sets j1-j4 */
+	"		#ifdef FULLSTACK", /* b_store after onstack_now, to preserve j1-j4 */
+	"		   #if defined(BCS) && defined(STORE_CTX)",
+	"		   { int xj;",
+	"			now._ctx = 0;",
+	"			JJ = onstack_now();",		    /* mangles j1 */
+	"			for (xj = trpt->sched_limit; xj <= sched_max; xj++)",
+	"			{	now._ctx = xj;",
+	"				II = b_store((char *)&now, vsize);", /* sets j1-j4 */
+	"				if (II != 0) { break; }",
+	"			}",
+	"			now._ctx = 0;",
+	"		   }",
+	"		   #else",
+	"			JJ = onstack_now();",		    /* mangles j1 */
+	"			II = b_store((char *)&now, vsize);", /* sets j1-j4 */
+	"		   #endif",
+	"		#else",
+	"		   #if defined(BCS) && defined(STORE_CTX)",
+	"		   { int xj;",
+	"			for (xj = trpt->sched_limit; xj <= sched_max; xj++)",
+	"			{	now._ctx = xj;",
+	"				II = b_store((char *)&now, vsize);", /* sets j1-j4 */
+	"				JJ = II; /* worstcase guess for p.o. - order corrected in 5.2.1 */",
+	"				if (II != 0) { break; }",
+	"			}",
+	"			now._ctx = 0;",
+	"		   }",
+	"		   #else",
+	"			II = b_store((char *)&now, vsize);", /* sets j1-j4 */
+	"			JJ = II; /* worstcase guess for p.o. - order corrected in 5.2.1 */",
+	"		   #endif",
+	"		#endif",
 		"#endif",
 	"#else",
 		"#ifdef MA",
-	"			II = gstore((char *)&now, vsize, 0);",
+	"			II = g_store((char *)&now, vsize, 0);",
 			"#ifndef FULLSTACK",
 	"			JJ = II;",
 			"#else",
@@ -1682,7 +2809,8 @@
 	"			JJ = (II == 2)?1:0;",
 			"#endif",
 		"#else",
-	"			II = hstore((char *)&now, vsize);",
+	"			II = h_store((char *)&now, vsize);",
+	"			/* @hash j1_spin II */",
 			"#ifdef FULLSTACK",
 	"			JJ = (II == 2)?1:0;",
 			"#endif",
@@ -1689,28 +2817,39 @@
 		"#endif",
 	"#endif",
 	"			kk = (II == 1 || II == 2);",
+	/* actually, BCS implies HAS_LAST */
+	"#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+	"			now._last = was_last;	/* restore value */",
+	"#endif",
+
 				/* II==0 new state */
 				/* II==1 old state */
 				/* II==2 on current dfs stack */
 				/* II==3 on 1st dfs stack */
 	"#ifndef SAFETY",
-
-	"			if (!fairness && a_cycles)",
+		/* with multicore we don't know which stack its on */
+		/* with HC there's a small chance of a false match - example fifoq 2012 */
+		"#if !defined(HC) && (NCORE==1 || defined (SEP_STATE))",
 	"			if (II == 2 && ((trpt->o_pm&2) || ((trpt-1)->o_pm&2)))",
-	"			{	II = 3; /* Schwoon & Esparza 2005, Gastin&Moro 2004 */",
-		"#ifdef VERBOSE",
+	"		#ifndef NOFAIR",
+	"			if (a_cycles && !fairness) /* 5.1.6 -- example by Hirofumi Watanabe */",
+	"		#endif",
+	"			if (depth > A_depth) /* forum example by adl */",
+	"			{",
+	"				II = 3; /* Schwoon & Esparza 2005, Gastin&Moro 2004 */",
+			"#ifdef VERBOSE",
 	"				printf(\"state match on dfs stack\\n\");",
-		"#endif",
+			"#endif",
 	"				goto same_case;",
 	"			}",
+		"#endif",
 
-
 		"#if defined(FULLSTACK) && defined(BITSTATE)",
 	"			if (!JJ && (now._a_t&1) && depth > A_depth)",
-	"			{	int oj1 = j1;",
+	"			{	int oj1 = j1_spin;",
 	"				uchar o_a_t = now._a_t;",
 	"				now._a_t &= ~(1|16|32);", /* 1st stack  */
-	"				if (onstack_now())",	  /* changes j1 */
+	"				if (onstack_now())",	  /* changes j1_spin */
 	"				{	II = 3;",
 		"#ifdef VERBOSE",
 	"					printf(\"state match on 1st dfs stack\\n\");",
@@ -1717,17 +2856,17 @@
 		"#endif",
 	"				}",
 	"				now._a_t = o_a_t;",	/* restore */
-	"				j1 = oj1;",
+	"				j1_spin = oj1;",
 	"			}",
 		"#endif",
 	"			if (II == 3 && a_cycles && (now._a_t&1))",
 	"			{",
 		"#ifndef NOFAIR",
-	"			   if (fairness && now._cnt[1] > 1)	/* was != 0 */",
+	"			   if (fairness && now._cnt[1] != 1)	/* was > 1 */",
 	"			   {",
-		"#ifdef VERBOSE",
+		"	#ifdef CHECK",
 	"				printf(\"\tfairness count non-zero\\n\");",
-		"#endif",
+		"	#endif",
 	"				II = 0;", /* treat as new state */
 	"			   } else",
 		"#endif",
@@ -1741,6 +2880,11 @@
 		"#else",
 	"				uerror(\"acceptance cycle\");",
 		"#endif",
+	"#if NCORE>1 && defined(FULL_TRAIL)",
+	"				if (upto > 0)",
+	"				{	Pop_Stack_Tree();",
+	"				}",
+	"#endif",
 	"				goto Up;",
 	"			   }",
 	"			}",
@@ -1747,41 +2891,103 @@
 	"#endif",
 
 	"#ifndef NOREDUCE",
-		"#ifndef SAFETY",
+	"	#ifndef SAFETY",
+	"		#if NCORE>1 && !defined(SEP_STATE) && defined(V_PROVISO)",
+	"			if (II != 0 && (!Lstate || Lstate->cpu_id < core_id))",
+	"			{	(trpt-1)->tau |= 16;",	/* treat as a stack state */
+	"			}",
+	"		#endif",
 	"			if ((II && JJ) || (II == 3))",
 	"			{	/* marker for liveness proviso */",
-	"				(trpt-1)->tau |= 16;",
+	"		#ifndef LOOPSTATE",
+	"				(trpt-1)->tau |= 16;",	/* truncated on stack */
+	"		#endif",
 	"				truncs2++;",
 	"			}",
 		"#else",
+	"		#if NCORE>1 && !defined(SEP_STATE) && defined(V_PROVISO)",
+	"			if (!(II != 0 && (!Lstate || Lstate->cpu_id < core_id)))",
+	"			{	/* treat as stack state */",
+	"				(trpt-1)->tau |= 16;",
+	"			} else",
+	"			{	/* treat as non-stack state */",
+	"				(trpt-1)->tau |= 64;",
+	"			}",
+	"		#endif",
 	"			if (!II || !JJ)",
 	"			{	/* successor outside stack */",
 	"				(trpt-1)->tau |= 64;",
 	"			}",
-		"#endif",
+	"	#endif",
 	"#endif",
+	"#if defined(BCS) && (defined(NOREDUCE) || !defined(SAFETY))",
+	/* needed for BCS - cover cases where it would not otherwise be set */
+	"			if (!II || !JJ)",
+	"			{	(trpt-1)->tau |= 64;",
+	"			}",
+	"#endif",
 	"			if (II)",
 	"			{	truncs++;",
+	"#if NCORE>1 && defined(FULL_TRAIL)",
+	"				if (upto > 0)",
+	"				{	Pop_Stack_Tree();",
+	"					if (depth == 0)",
+	"					{	return;",
+	"				}	}",
+	"#endif",
 	"				goto Up;",
 	"			}",
 	"			if (!kk)",
-	"			{	nstates++;",
-	"				if ((unsigned long) nstates%%1000000 == 0)",
-	"					snapshot();",
+	"			{	static long sdone = (long) 0; long ndone;",
+	"				nstates++;",
+	"#if defined(ZAPH) && defined(BITSTATE)",
+	"				zstates += (double) hfns;",
+	"#endif",
+	"				ndone = (ulong) (nstates/(freq));",
+	"				if (ndone != sdone)",
+	"				{	snapshot();",
+	"					sdone = ndone;",
+	"#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)",
+	"					if (nstates > ((double)(ONE_L<<(ssize+1))))",
+	"					{	void resize_hashtable(void);",
+	"						resize_hashtable();",
+	"					}",
+	"#endif",
+	"#if defined(ZAPH) && defined(BITSTATE)",
+	"					if (zstates > ((double)(ONE_L<<(ssize-2))))",
+	"					{	/* more than half the bits set */",
+	"						void zap_hashtable(void);",
+	"						zap_hashtable();",
+	"						zstates = 0;",
+	"					}",
+	"#endif",
+	"				}",
 	"#ifdef SVDUMP",
 	"				if (vprefix > 0)",
+	"	#ifdef SHO",	/* Store Hash Only */
+	"			/* always use the same hashfunction, for consistency across runs */",
+	"				if (HASH_NR != 0)",
+	"				{	int oh = HASH_NR;",
+	"					HASH_NR = 0;",
+	"					d_hash((uchar *) &now, vsize); /* SHO - set K1 */",
+	"					HASH_NR = oh;",
+	"				}",
+	"				if (write(svfd, (uchar *) &K1, sizeof(ulong)) != sizeof(ulong))",
+	"	#else",
 	"				if (write(svfd, (uchar *) &now, vprefix) != vprefix)",
-	"				{	fprintf(efd, \"writing %%s.svd failed\\n\", Source);",
+	"	#endif",
+	"				{	fprintf(efd, \"writing %%s.svd failed\\n\", PanSource);",
 	"					wrapup();",
 	"				}",
 	"#endif",
 	"#if defined(MA) && defined(W_XPT)",
-	"				if ((unsigned long) nstates%%W_XPT == 0)",
+	"				if ((ulong) nstates%%W_XPT == 0)",
 	"				{	void w_xpoint(void);",
 	"					w_xpoint();",
 	"				}",
 	"#endif",
 	"			}",
+
 	"#if defined(FULLSTACK) || defined(CNTRSTACK)",
 	"			onstack_put();",
 		"#ifdef DEBUG2",
@@ -1793,10 +2999,13 @@
 	"			printf(\"%%d: putting\\n\", depth);",
 		"#endif",
 		"#endif",
+	"#else",
+	"	#if NCORE>1",
+	"			trpt->ostate = Lstate;",
+	"	#endif",
 	"#endif",
 	"	}	}",
 
-
 	"	if (depth > mreached)",
 	"		mreached = depth;",
 	"#ifdef VERI",
@@ -1809,40 +3018,56 @@
 	"#endif",
 	"#ifdef VERI",
 	"	if (now._nr_pr == 0)	/* claim terminated */",
-	"		uerror(\"end state in claim reached\");",
-	"	check_claim(((P0 *)pptr(0))->_p);",
+	"	{	uerror(\"end state in claim reached\");",
+	"	}",
+	"	if (stopstate[((Pclaim *)pptr(0))->_t][((Pclaim *)pptr(0))->_p])",
+	"	{	uerror(\"end state in claim reached\");",
+	"	}",
 	"Stutter:",
 	"	if (trpt->tau&4)	/* must make a claimmove */",
 	"	{",
-
-	"#ifndef NOFAIR",
+	"	#ifndef NOFAIR",
 	"		if ((now._a_t&2)	/* A-bit set */",
 	"		&&   now._cnt[now._a_t&1] == 1)",
 	"		{	now._a_t &= ~2;",
 	"			now._cnt[now._a_t&1] = 0;",
 	"			trpt->o_pm |= 16;",
-		"#ifdef DEBUG",
+			"#ifdef DEBUG",
 	"	printf(\"%%3d: fairness Rule 3.: _a_t = %%d\\n\",",
-	"		depth, now._a_t);",
-		"#endif",
+	"		(int) depth, now._a_t);",
+			"#endif",
 	"		}",
-	"#endif",
-
+	"	#endif",
 	"		II = 0;		/* never */",
 	"		goto Veri0;",
 	"	}",
 	"#endif",
+	"#ifdef PERMUTED",
+	"	if (reversing&2)",
+	"	{	seed = rand();",
+	"		p_reorder(seed);",
+	"	}",
+	"#endif",
 	"#ifndef NOREDUCE",
 	"	/* Look for a process with only safe transitions */",
 	"	/* (special rules apply in the 2nd dfs) */",
-"#ifdef SAFETY",
-	"	if (boq == -1 && From != To)",
-"#else",
-	"/* implied: #ifdef FULLSTACK */",
 	"	if (boq == -1 && From != To",
+	"",
+	"#ifdef SAFETY",
+	" #if NCORE>1",
+	"	&& (depth < z_handoff)", /* not for border states */
+	" #endif",
+	"	)",
+	"#else",
+	" #if NCORE>1",
+	"	&& ((a_cycles) || (!a_cycles && depth < z_handoff))",
+	" #endif",
+	" #ifdef BCS",
+	"	&& (sched_max > 0 || depth > BASE)", /* no po in initial state if -L0 */
+	" #endif",
 	"	&&  (!(now._a_t&1)",
 	"	    ||	(a_cycles &&",
-	"#ifndef BITSTATE",
+	" #ifndef BITSTATE",
 		"#ifdef MA",
 			"#ifdef VERI",
 	"		 !((trpt-1)->proviso))",
@@ -1852,12 +3077,12 @@
 		"#else",
 			"#ifdef VERI",
 	"		 (trpt-1)->ostate &&",
-	"		!(((char *)&((trpt-1)->ostate->state))[0] & 128))",
+	"		!(((char *)&((trpt-1)->ostate->state))[0] & 128))", /* proviso bit in _a_t */
 			"#else",
 	"		!(((char *)&(trpt->ostate->state))[0] & 128))",
 			"#endif",
 		"#endif",
-	"#else",
+	" #else",
 		"#ifdef VERI",
 	"		(trpt-1)->ostate &&",
 	"		(trpt-1)->ostate->proviso == 0)",
@@ -1864,51 +3089,46 @@
 		"#else",
 	"		trpt->ostate->proviso == 0)",
 		"#endif",
-	"#endif",
+	" #endif",
 	"	   ))",
-	"/* #endif */",
-"#endif",
-	"	for (II = From; II >= To; II -= 1)",
-	"	{",
-	"Resume:	/* pick up here if preselect fails */",
-	"		this = pptr(II);",
-	"		tt = (int) ((P0 *)this)->_p;",
-	"		ot = (uchar) ((P0 *)this)->_t;",
-	"		if (trans[ot][tt]->atom & 8)",
-	"		{	t = trans[ot][tt];",
-	"			if (t->qu[0] != 0)",
-	"			{	Ccheck++;",
-	"				if (!q_cond(II, t))",
-	"					continue;",
-	"				Cholds++;",
-	"			}",
-	"			From = To = II;",
+	"#endif", /* SAFETY */
+	"	/* attempt Partial Order Reduction as preselect moves */",
+	"#ifdef BCS",
+	"	if (trpt->sched_limit < sched_max)",	/* po only if we can switch */
+	"#endif",
+	"	{	for ALL_P {",	/* PO preselect */
+	"Resume:		/* pick up here if preselect fails */",
+	"			this = pptr(II);",
+	"			tt = (int) ((P0 *)this)->_p;",
+	"			ot = (uchar) ((P0 *)this)->_t;",
+	"			if (trans[ot][tt]->atom & 8)",
+	"			{	t = trans[ot][tt];",
+	"				if (t->qu[0] != 0)",
+	"				{	Ccheck++;",
+	"					if (!q_cond(II, t))",
+	"					{	continue;",
+	"					}",
+	"					Cholds++;",
+	"				}",
+	"				From = To = II; /* preselect process */",
 	"#ifdef NIBIS",
-	"			t->om = 0;",
+	"				t->om = 0;",
 	"#endif",
-	"			trpt->tau |= 32; /* preselect marker */",
-		"#ifdef DEBUG",
-		"#ifdef NIBIS",
-	"			printf(\"%%3d: proc %%d Pre\", depth, II);",
-	"			printf(\"Selected (om=%%d, tau=%%d)\\n\", ",
-	"				t->om, trpt->tau);",
-		"#else",
-	"	printf(\"%%3d: proc %%d PreSelected (tau=%%d)\\n\", ",
-	"		depth, II, trpt->tau);",
-		"#endif",
-		"#endif",
-	"			goto Again;",
-	"		}",
-	"	}",
+	"				trpt->tau |= 32; /* preselect marker */",
+	"#ifdef DEBUG",
+	"				printf(\"%%3ld: proc %%d PreSelected (tau=%%d)\\n\", ",
+	"					depth, II, trpt->tau);",
+	"#endif",
+	"				goto Again;",
+	"			} else",
+	"			{	continue;",
+	"	}	}	}",
 	"	trpt->tau &= ~32;",
 	"#endif",
 	"#if !defined(NOREDUCE) || (defined(ETIM) && !defined(VERI))",
 	"Again:",
 	"#endif",
-	"	/* The Main Expansion Loop over Processes */",
-
-	"	trpt->o_pm &= ~(8|16|32|64); /* fairness-marks */",
-
+	"	trpt->o_pm &= ~(8|16|32|64); /* clear fairness-marks */",
 	"#ifndef NOFAIR",
 	"	if (fairness && boq == -1",
 		"#ifdef VERI",
@@ -1917,36 +3137,136 @@
 	"	&& !(trpt->tau&8))",
 	"	{	/* A_bit = 1; Cnt = N in acc states with A_bit 0 */",
 	"		if (!(now._a_t&2))",	/* A-bit not set */
-	"		{",
-	"			if (a_cycles && (trpt->o_pm&2))",
+	"		{	if (a_cycles && (trpt->o_pm&2))",
 	"			{	/* Accepting state */",
 	"				now._a_t |= 2;",
-	"				now._cnt[now._a_t&1] = now._nr_pr + 1;", /* NEW +1 */
+	"				now._cnt[now._a_t&1] = now._nr_pr + 1;",
 	"				trpt->o_pm |= 8;",
 		"#ifdef DEBUG",
-	"	printf(\"%%3d: fairness Rule 1: cnt=%%d, _a_t=%%d\\n\",",
+	"	printf(\"%%3ld: fairness Rule 1: cnt=%%d, _a_t=%%d\\n\",",
 	"			depth, now._cnt[now._a_t&1], now._a_t);",
 		"#endif",
 	"			}",
 	"		} else",		/* A-bit set */
 	"		{	/* A_bit = 0 when Cnt 0 */",
-	"			if (now._cnt[now._a_t&1] == 1)",	/* NEW: 1 iso 0 */
-	"			{	now._a_t &= ~2;",		/* reset a-bit */
-	"				now._cnt[now._a_t&1] = 0;",	/* NEW: reset cnt */
+	"			if (now._cnt[now._a_t&1] == 1)",
+	"			{	now._a_t &= ~2;",	/* reset a-bit */
+	"				now._cnt[now._a_t&1] = 0;",
 	"				trpt->o_pm |= 16;",
 		"#ifdef DEBUG",
-	"	printf(\"%%3d: fairness Rule 3: _a_t = %%d\\n\",",
+	"	printf(\"%%3ld: fairness Rule 3: _a_t = %%d\\n\",",
 	"		depth, now._a_t);",
 		"#endif",
 	"	}	}	}",
 	"#endif",
 
-	"	for (II = From; II >= To; II -= 1)",
-	"	{",
+	"#ifdef BCS",	/* bounded context switching */
+	"	trpt->bcs = trpt->b_pno = 0;	/* initial */",
+	"	if (From != To		/* not a PO or atomic move */",
+	"	&&  depth > BASE)	/* there is a prior move */",
+	"	{	trpt->b_pno = now._last + BASE;",
+	"		trpt->bcs = B_PHASE1;",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: BCS phase 1 proc %%d limit %%d\\n\",",
+	"			depth, trpt->b_pno, trpt->sched_limit);",
+	"	#endif",
+	"		/* allow only process b_pno to move in this phase */",
+	"	}",
+	"c_switch:	/* jumps here with bcs == B_PHASE2 with or wo B_FORCED added */",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: BCS c_switch phase=%%d pno=%%d [forced %%d]\\n\",",
+	"			depth, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+	"	#endif",
+	"#endif",
+
+	"#ifdef P_RAND",
+	"	trpt->p_left = CNT_P;",
+	"	if (trpt->p_left > 1)",
+	"	{	trpt->p_skip = rand() %% (trpt->p_left);",
+	"	} else",
+	"	{	trpt->p_skip = -1;",
+	"	}",
+	"r_switch:",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: P_RAND r_switch p_skip=%%d p_left=%%d\\n\",",
+	"			depth, trpt->p_skip, trpt->p_left);",
+	"	#endif",
+	"#endif",
+
+	"	for ALL_P {",	/* Main Loop */
+	"#ifdef PERMUTED",
+	"		if (reversing&2)",
+	"		{	oII = II;",
+	"			if (From != To)", /* not atomic or preselected */
+	"			{	II = get_permuted(II);",
+	"		}	}",
+	"#endif",
+	"#ifdef P_RAND",
+	"		if (trpt->p_skip >= 0)",
+	"		{	trpt->p_skip--; /* skip random nr of procs */",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: P_RAND skipping %%d [new p_skip=%%d p_left=%%d]\\n\",",
+	"			depth, II, trpt->p_skip, trpt->p_left);",
+	"	#endif",
+	"			CONTINUE0;",
+	"		}",
+	"		if (trpt->p_left == 0)",
+	"		{",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: P_RAND done at %%d\\n\", depth, II);",
+	"	#endif",
+	"			break;	/* done */",
+	"		}",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: P_RAND explore %%d [p_left=%%d]\\n\",",
+	"			depth, II, trpt->p_left);",
+	"	#endif",
+	"		trpt->p_left--;",
+	"#endif",
+
 	"#if SYNC",
 	"		/* no rendezvous with same proc */",
-	"		if (boq != -1 && trpt->pr == II) continue;",
+	"		if (boq != -1 && trpt->pr == II)",
+	"		{	CONTINUE0;",
+	"		}",
 	"#endif",
+
+	"#ifdef BCS",	/* never claim with II==0 cannot get here */
+	"		if ((trpt->bcs & B_PHASE1)",
+	"		&&  trpt->b_pno != II)",
+	"		{",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: BCS NotPre II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",",
+	"			depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+	"	#endif",
+	"			CONTINUE0;",	/* avoid context switch */
+	"		}",
+	"	#ifdef VERBOSE",
+	"		else if ((trpt->bcs & B_PHASE1) && trpt->b_pno == II)",
+	"		printf(\"%%3ld: BCS IsPre II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",",
+	"			depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+	"	#endif",
+
+	"		if (trpt->bcs & B_PHASE2)	/* 2nd phase */",
+	"		{	if (trpt->b_pno == II)	/* was already done in phase 1 */",
+	"			{",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: BCS NoRepeat II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",",
+	"			depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+	"	#endif",
+	"				CONTINUE0;",
+	"			}",
+	"			if (!(trpt->bcs & B_FORCED)	/* unless forced */",
+	"			&&  trpt->sched_limit >= sched_max)",
+	"			{",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: BCS Bound II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",",
+	"			depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+	"	#endif",
+	"				CONTINUE0;	/* enforce bound */",
+	"		}	}",
+	"#endif",
+
 	"#ifdef VERI",
 	"Veri0:",
 	"#endif",
@@ -1967,8 +3287,10 @@
 	"		{	if (t->qu[0] == 0",	/* unconditional */
 	"			||  q_cond(II, t))",	/* true condition */
 	"			{	_m = t->om;",
-	"				if (_m>_n||(_n>3&&_m!=0)) _n=_m;",
-	"				continue; /* did it before */",
+	"				if (_m>_n||(_n>3&&_m!=0))",
+	"				{	_n=_m;",
+	"				}",
+	"				CONTINUE0; /* did it before */",
 	"		}	}",
 	"#endif",
 	"		trpt->o_pm &=  ~1; /* no move in this pid yet */",
@@ -1990,7 +3312,7 @@
 	"				now._cnt[now._a_t&1] = 1;",
 		"#endif",
 		"#ifdef DEBUG",
-	"		printf(\"%%3d: proc %%d fairness \", depth, II);",
+	"		printf(\"%%3ld: proc %%d fairness \", depth, II);",
 	"		printf(\"Rule 2: --cnt to %%d (%%d)\\n\",",
 	"			now._cnt[now._a_t&1], now._a_t);",
 		"#endif",
@@ -1997,9 +3319,19 @@
 	"			trpt->o_pm |= (32|64);",
 	"		}",
 	"#endif",
-	"#ifdef HAS_PROVIDED",
-	"		if (!provided(II, ot, tt, t)) continue;",
+
+	"#ifdef HAS_PRIORITY",
+	"		if (!highest_priority(((P0 *)this)->_pid, II, t))",
+	"		{	CONTINUE0;",
+	"		}",
+	"#else",
+	"	#ifdef HAS_PROVIDED",
+	"		if (!provided(II, ot, tt, t))",
+	"		{	CONTINUE0;",
+	"		}",
+	"	#endif",
 	"#endif",
+
 	"		/* check all trans of proc II - escapes first */",
 	"#ifdef HAS_UNLESS",
 	"		trpt->e_state = 0;",
@@ -2007,27 +3339,31 @@
 	"		(trpt+1)->pr = (uchar) II;",	/* for uerror */
 	"		(trpt+1)->st = tt;",
 
-	"#ifdef RANDOMIZE",
+	"#ifdef T_RAND",
 	"		for (ooi = eoi = 0, t = trans[ot][tt]; t; t = t->nxt, ooi++)",
-	"			if (strcmp(t->tp, \"else\") == 0)",
-	"				eoi++;",
-	"",
-	"		if (eoi)",
+	"		{	if (strcmp(t->tp, \"else\") == 0",
+	"	#ifdef HAS_UNLESS",
+	"			||  t->e_trans != 0",
+	"	#endif",
+	"			)",
+	"			{	eoi++;", /* no break, must count ooi */
+	"		}	}",
+	"		if (eoi > 0)",
 	"		{	t = trans[ot][tt];",
-	"#ifdef VERBOSE",
-	"			printf(\"randomizer: suppressed, saw else\\n\");",
-	"#endif",
-	"		} else",
+	"	#ifdef VERBOSE",
+	"			printf(\"randomizer: suppressed, saw else or escape\\n\");",
+	"	#endif",
+	"		} else if (ooi > 0)",
 	"		{	eoi = rand()%%ooi;",
-	"#ifdef VERBOSE",
+	"	#ifdef VERBOSE",
 	"			printf(\"randomizer: skip %%d in %%d\\n\", eoi, ooi);",
-	"#endif",
+	"	#endif",
 	"			for (t = trans[ot][tt]; t; t = t->nxt)",
 	"				if (eoi-- <= 0) break;",
 	"		}",
-	"DOMORE:",
+	"domore:",
 	"		for ( ; t && ooi > 0; t = t->nxt, ooi--)",
-	"#else",
+	"#else", /* ie dont randomize */
 	"		for (t = trans[ot][tt]; t; t = t->nxt)",
 	"#endif",
 	"		{",
@@ -2045,50 +3381,84 @@
 	"				break;",
 	"			}",
 	"#endif",
+	"	#if defined(TRIX) && !defined(TRIX_ORIG) && !defined(BFS)",
+	"			(trpt+1)->p_bup = now._ids_[II];",
+	"	#endif",
 	"			(trpt+1)->o_t = t;",	/* for uerror */
 	"#ifdef INLINE",
 	"#include FORWARD_MOVES",
 	"P999:			/* jumps here when move succeeds */",
 	"#else",
-	"			if (!(_m = do_transit(t, II))) continue;",
+	"			if (!(_m = do_transit(t, II)))",
+	"			{	continue;",
+	"			}",
 	"#endif",
+	"#ifdef BCS",
+	"			if (depth > BASE",	/* has prior move */
+	"			&& II >= BASE",		/* not claim */
+	"			&& From != To",		/* not atomic or po */
+	"	#ifndef BCS_NOFIX",
+	"			/* added 5.2.5: prior move was not po */",
+	"			&& !((trpt-(BASE+1))->tau & 32)",
+	"	#endif",
+	"			&& boq == -1",		/* not rv */
+	"			&& (trpt->bcs & B_PHASE2)",
+	"			&&  trpt->b_pno != II	/* context switch */", /* redundant */
+	"			&& !(trpt->bcs & B_FORCED))	/* unless forced */",
+	"			{	(trpt+1)->sched_limit = 1 + trpt->sched_limit;",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: up sched count to %%d\\n\", depth, (trpt+1)->sched_limit);",
+	"	#endif",
+	"			} else",
+	"			{	(trpt+1)->sched_limit = trpt->sched_limit;",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: keep sched count at %%d\\n\", depth, (trpt+1)->sched_limit);",
+	"	#endif",
+	"			}",
+	"#endif",
 	"			if (boq == -1)",
-"#ifdef CTL",
+		"#ifdef CTL",
 	"	/* for branching-time, can accept reduction only if */",
 	"	/* the persistent set contains just 1 transition */",
 	"			{	if ((trpt->tau&32) && (trpt->o_pm&1))",
-	"					trpt->tau |= 16;",
+	"					trpt->tau |= 16;",	/* CTL */
 	"				trpt->o_pm |= 1; /* we moved */",
 	"			}",
-"#else",
+		"#else",
 	"				trpt->o_pm |= 1; /* we moved */",
-"#endif",
+		"#endif",
+
+	"#ifdef LOOPSTATE",
+	"			if (loopstate[ot][tt])",
+	"			{",
+		"#ifdef VERBOSE",
+	"				printf(\"exiting from loopstate:\\n\");",
+		"#endif",
+	"				trpt->tau |= 16;",	/* exiting loopstate */
+	"				cnt_loops++;",
+	"			}",
+	"#endif",
+
 	"#ifdef PEG",
 	"			peg[t->forw]++;",
 	"#endif",
-
 	"#if defined(VERBOSE) || defined(CHECK)",
 		"#if defined(SVDUMP)",
-	"			printf(\"%%3d: proc %%d exec %%d \\n\", ",
-	"				depth, II, t->t_id);",
+	"	cpu_printf(\"%%3ld: proc %%d exec %%d \\n\", depth, II, t->t_id);",
 		"#else",
-	"			printf(\"%%3d: proc %%d exec %%d, \", ",
-	"				depth, II, t->forw);",
-	"			printf(\"%%d to %%d, %%s %%s %%s\", ",
-	"				tt, t->st, t->tp,",
+	"	cpu_printf(\"%%3ld: proc %%d exec %%d, %%d to %%d, %%s %%s %%s %%saccepting [tau=%%d]\\n\", ",
+	"				depth, II, t->forw, tt, t->st, t->tp,",
 	"				(t->atom&2)?\"atomic\":\"\",",
-	"				(boq != -1)?\"rendez-vous\":\"\");",
-			"#ifdef HAS_UNLESS",
-	"			if (t->e_trans)",
-	"				printf(\" (escapes to state %%d)\",",
-	"					t->st);",
-			"#endif",
-	"			printf(\" %%saccepting [tau=%%d]\\n\",",
+	"				(boq != -1)?\"rendez-vous\":\"\",",
 	"				(trpt->o_pm&2)?\"\":\"non-\", trpt->tau);",
+		"#ifdef HAS_UNLESS",
+	"			if (t->e_trans)",
+	"			cpu_printf(\"\\t(escape to state %%d)\\n\", t->st);",
 		"#endif",
-		"#ifdef RANDOMIZE",
-	"			printf(\"	randomizer %%d\\n\", ooi);",
 		"#endif",
+		"#ifdef T_RAND",
+	"			cpu_printf(\"\\t(randomizer %%d)\\n\", ooi);",
+		"#endif",
 	"#endif",
 
 	"#ifdef HAS_LAST",
@@ -2143,9 +3513,16 @@
 	"			trpt->o_ot = ot; trpt->o_tt = tt;",
 	"			trpt->o_To = To; trpt->o_m  = _m;",
 	"			trpt->tau = 0;",
-"#ifdef RANDOMIZE",
+	"#ifdef PERMUTED",
+	"			if (reversing&2)",
+	"			{	trpt->seed = seed;",
+	"				trpt->oII  = oII;",
+	"			}",
+	"#endif",
+
+	"#if defined(T_RAND) && !defined(BFS)",
 	"			trpt->oo_i = ooi;",
-"#endif",
+	"#endif",
 	"			if (boq != -1 || (t->atom&2))",
 	"			{	trpt->tau |= 8;",
 	"#ifdef VERI",
@@ -2171,32 +3548,78 @@
 	"			if (boq == -1 && (t->atom&2))",
 	"			{	From = To = II; nlinks++;",
 	"			} else",
-	"			{	From = now._nr_pr-1; To = BASE;",
+	"			{	From = FROM_P; To = UPTO_P;",
 	"			}",
+	"#if NCORE>1 && defined(FULL_TRAIL)",
+	"			if (upto > 0)",
+	"			{	Push_Stack_Tree(II, t->t_id);",
+	"			}",
+	"#endif",
+	"#ifdef TRIX",
+	"			if (processes[II])", /* last move could have been a delproc */
+	"			{	processes[II]->modified = 1; /* transition in II */",
+	"	#ifdef V_TRIX",
+	"				printf(\"%%4d: process %%d modified\\n\", depth, II);",
+	"			} else",
+	"			{	printf(\"%%4d: process %%d modified but gone (%%p)\\n\",",
+	"					depth, II, trpt);",
+	"	#endif",
+	"			}",
+	"#endif",
 	"			goto Down;	/* pseudo-recursion */",
 	"Up:",
+	"#ifdef TRIX",
+	"	#ifndef TRIX_ORIG",
+	"		#ifndef BFS",
+	"			now._ids_[trpt->pr] = trpt->p_bup;",
+	"		#endif",
+	"	#else",
+	"			if (processes[trpt->pr])",
+	"			{",
+	"				processes[trpt->pr]->modified = 1; /* reverse move */",
+	"		#ifdef V_TRIX",
+	"				printf(\"%%4d: unmodify pr %%d (%%p)\\n\",",
+	"					depth, trpt->pr, trpt);",
+	"			} else",
+	"			{	printf(\"%%4d: unmodify pr %%d (gone) (%%p)\\n\",",
+	"					depth, trpt->pr, trpt);",
+	"		#endif",
+	"			}",
+	"	#endif",
+	"#endif",
 	"#ifdef CHECK",
-	"	printf(\"%%d: Up - %%s\\n\", depth,",
-	"		(trpt->tau&4)?\"claim\":\"program\");",
+	"			cpu_printf(\"%%d: Up - %%s\\n\", depth,",
+	"				(trpt->tau&4)?\"claim\":\"program\");",
 	"#endif",
-	"#ifdef MA",
-	"	if (depth <= 0) return;",
-	"	/* e.g., if first state is old, after a restart */",
+	"#if NCORE>1",
+	"			iam_alive();",
+	"	#ifdef USE_DISK",
+	"			mem_drain();",
+	"	#endif",
 	"#endif",
+	"#if defined(MA) || NCORE>1",
+	"			if (depth <= 0) return;",
+	"			/* e.g., if first state is old, after a restart */",
+	"#endif",
 
 	"#ifdef SC",
-	"	if (CNT1 > CNT2",
-	"		&& depth < hiwater - (HHH-DDD) + 2)",
-	"	{",
-	" 		trpt += DDD;",
-	"		disk2stack();",
-	"		maxdepth -= DDD;",
-	"		hiwater -= DDD;",
-	"if(verbose)",
-	"printf(\"unzap %%d: %%d\\n\", CNT2, hiwater);",
-	"	}",
+	"			if (CNT1 > CNT2",
+	"			&& depth < hiwater - (HHH-DDD) - 2)",	/* 5.1.6: was + 2 */
+	"			{",
+	" 				trpt += DDD;",
+	"				disk2stack();",
+	"				maxdepth -= DDD;",
+	"				hiwater -= DDD;",
+	"				if(verbose)",
+	"				printf(\"unzap %%ld: %%ld\\n\", CNT2, hiwater);",
+	"			}",
 	"#endif",
 
+	"#ifndef SAFETY",	/* moved earlier in version 5.2.5 */
+	"			if ((now._a_t&1) && depth <= A_depth)",
+	"				return;	/* to checkcycles() */",
+	"#endif",
+
 	"#ifndef NOFAIR",
 	"			if (trpt->o_pm&128)	/* fairness alg */",
 	"			{	now._cnt[now._a_t&1] = trpt->bup.oval;",
@@ -2203,7 +3626,7 @@
 	"				_n = 1; trpt->o_pm &= ~128;",
 	"				depth--; trpt--;",
 		"#if defined(VERBOSE) || defined(CHECK)",
-	"	printf(\"%%3d: reversed fairness default move\\n\", depth);",
+	"	printf(\"%%3ld: reversed fairness default move\\n\", depth);",
 		"#endif",
 	"				goto Q999;",
 	"			}",
@@ -2211,7 +3634,7 @@
 
 	"#ifdef HAS_LAST",
 	"#ifdef VERI",
-	"			{ int d; Trail *trl;",
+	"			{ long d; Trail *trl;",
 	"			  now._last = 0;",
 	"			  for (d = 1; d < depth; d++)",
 	"			  {	trl = getframe(depth-d); /* was (trpt-d) */",
@@ -2226,45 +3649,56 @@
 	"#ifdef EVENT_TRACE",
 	"			now._event = trpt->o_event;",
 	"#endif",
-	"#ifndef SAFETY",
-	"			if ((now._a_t&1) && depth <= A_depth)",
-	"				return;	/* to checkcycles() */",
-	"#endif",
 	"			t  = trpt->o_t;  _n = trpt->o_n;",
 	"			ot = trpt->o_ot; II = trpt->pr;",
-	"			tt = trpt->o_tt; this = pptr(II);",
+	"			tt = trpt->o_tt; this = Pptr(II);",
 	"			To = trpt->o_To; _m  = trpt->o_m;",
-"#ifdef RANDOMIZE",
+	"#ifdef PERMUTED",
+	"			if (reversing&2)",
+	"			{	seed = trpt->seed;",
+	"				oII  = trpt->oII;",
+	"			}",
+	"#endif",
+	"#if defined(T_RAND) && !defined(BFS)",
 	"			ooi = trpt->oo_i;",
-"#endif",
+	"#endif",
 	"#ifdef INLINE_REV",
 	"			_m = do_reverse(t, II, _m);",
 	"#else",
-	"#include REVERSE_MOVES",
+	"#include BACKWARD_MOVES",
 	"R999:			/* jumps here when done */",
 	"#endif",
 
 	"#ifdef VERBOSE",
-	"			printf(\"%%3d: proc %%d \", depth, II);",
-	"			printf(\"reverses %%d, %%d to %%d,\",",
-	"				t->forw, tt, t->st);",
-	"			printf(\" %%s [abit=%%d,adepth=%%d,\", ",
-	"				t->tp, now._a_t, A_depth);",
-	"			printf(\"tau=%%d,%%d]\\n\", ",
-	"				trpt->tau, (trpt-1)->tau);",
+	"			cpu_printf(\"%%3ld: proc %%d reverses %%d, %%d to %%d\\n\",",
+	"				depth, II, t->forw, tt, t->st);",
+	"			cpu_printf(\"\\t%%s [abit=%%d,adepth=%%ld,tau=%%d,%%d]\\n\", ",
+	"				t->tp, now._a_t, A_depth, trpt->tau, (trpt-1)->tau);",
 	"#endif",
 	"#ifndef NOREDUCE",
 	"			/* pass the proviso tags */",
 	"			if ((trpt->tau&8)	/* rv or atomic */",
 	"			&&  (trpt->tau&16))",
-	"				(trpt-1)->tau |= 16;",
-	"#ifdef SAFETY",
+	"				(trpt-1)->tau |= 16;",	/* pass upward */
+	"	#ifdef SAFETY",
 	"			if ((trpt->tau&8)	/* rv or atomic */",
 	"			&&  (trpt->tau&64))",
 	"				(trpt-1)->tau |= 64;",
+	"	#endif",
 	"#endif",
+
+	"#if defined(BCS) && (defined(NOREDUCE) || !defined(SAFETY))",
+	/* for BCS, cover cases where 64 is otherwise not handled */
+	"			if ((trpt->tau&8)",
+	"			&&  (trpt->tau&64))",
+	"				(trpt-1)->tau |= 64;",
 	"#endif",
+
 	"			depth--; trpt--;",
+	"",
+	"#ifdef NSUCC",
+	"			trpt->n_succ++;",
+	"#endif",
 	"#ifdef NIBIS",
 	"			(trans[ot][tt])->om = _m; /* head of list */",
 	"#endif",
@@ -2271,16 +3705,7 @@
 
 	"			/* i.e., not set if rv fails */",
 	"			if (_m)",
-	"			{",
-	"#if defined(VERI) && !defined(NP)",
-	"				if (II == 0 && verbose && !reached[ot][t->st])",
-	"				{",
-	"			printf(\"depth %%d: Claim reached state %%d (line %%d)\\n\",",
-	"					depth, t->st, src_claim [t->st]);",
-	"					fflush(stdout);",
-	"				}",
-	"#endif",
-	"				reached[ot][t->st] = 1;",
+	"			{	reached[ot][t->st] = 1;",
 	"				reached[ot][tt] = 1;",
 	"			}",
 	"#ifdef HAS_UNLESS",
@@ -2291,19 +3716,19 @@
 	"			((P0 *)this)->_p = tt;",
 	"		} /* all options */",
 
-	"#ifdef RANDOMIZE",
+	"#ifdef T_RAND",
 	"		if (!t && ooi > 0)",	/* means we skipped some initial options */
 	"		{	t = trans[ot][tt];",
-	"#ifdef VERBOSE",
+	"	#ifdef VERBOSE",
 	"			printf(\"randomizer: continue for %%d more\\n\", ooi);",
-	"#endif",
-	"			goto DOMORE;",
+	"	#endif",
+	"			goto domore;",
 	"		}",
-	"#ifdef VERBOSE",
+	"	#ifdef VERBOSE",
 	"		  else",
 	"			printf(\"randomizer: done\\n\");",
+	"	#endif",
 	"#endif",
-	"#endif",
 
 	"#ifndef NOFAIR",
 	"		/* Fairness: undo Rule 2 */",
@@ -2312,12 +3737,12 @@
 	"		{	if (trpt->o_pm&1)",/* it didn't block */
 	"			{",
 		"#ifdef VERI",
-	"				if (now._cnt[now._a_t&1] == 1)",	/* NEW: 1 iso 0 */
-	"					now._cnt[now._a_t&1] = 2;",	/* NEW: 2 iso 1*/
+	"				if (now._cnt[now._a_t&1] == 1)",
+	"					now._cnt[now._a_t&1] = 2;",
 		"#endif",
 	"				now._cnt[now._a_t&1] += 1;",
 		"#ifdef VERBOSE",
-	"		printf(\"%%3d: proc %%d fairness \", depth, II);",
+	"		printf(\"%%3ld: proc %%d fairness \", depth, II);",
 	"		printf(\"undo Rule 2, cnt=%%d, _a_t=%%d\\n\",",
 	"			now._cnt[now._a_t&1], now._a_t);",
 		"#endif",
@@ -2326,32 +3751,77 @@
 	"			{	if (_n > 0)", /* a prev proc didn't */
 	"				{",	/* start over */
 	"					trpt->o_pm &= ~64;",
-	"					II = From+1;",
+	"					II = INI_P;", /* after loop incr II == From */
 	"		}	}	}",
 	"#endif",
-
 	"#ifdef VERI",
-	"		if (II == 0) break;	/* never claim */",
+	"		if (II == 0)",
+	"		{	break;	/* never claim */",
+	"		}",
 	"#endif",
-	"	} /* all processes */",
+	"		CONTINUE;",
+	"	} /* ALL_P */",
 
+	"#ifdef NSUCC",
+	"	tally_succ(trpt->n_succ);",
+	"#endif",
+
+	"#ifdef P_RAND",
+	"	if (trpt->p_left > 0 && NDONE_P)",
+	"	{	trpt->p_skip = -1; /* probably rendundant */",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: P_RAND -- explore remainder\\n\", depth);",
+	"	#endif",
+	"		goto r_switch; /* explore the remaining procs */",
+	"	} else",
+	"	{",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: P_RAND -- none left\\n\", depth);",
+	"	#endif",
+	"	}",
+	"#endif",
+
+	"#ifdef BCS",
+	"	if (trpt->bcs & B_PHASE1)",
+	"	{	trpt->bcs = B_PHASE2;	/* start 2nd phase */",
+	"		if (_n == 0 || !(trpt->tau&64))	/* pre-move unexecutable or led to stackstate */",
+	"		{	trpt->bcs |= B_FORCED; /* forced switch */",
+	"		}",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: BCS move to phase 2, _n=%%d %%s\\n\", depth, _n,",
+	"			(trpt->bcs & B_FORCED)?\"forced\":\"free\");",
+	"	#endif",
+	"		From = FROM_P; To = UPTO_P;",
+	"		goto c_switch;",
+	"	}",
+	"",
+	"	if (_n == 0	/* no process could move */",
+	"	&&  II >= BASE	/* not the never claim */",
+	"	&&  trpt->sched_limit >= sched_max)",
+	"	{	_n = 1;",
+	"	#ifdef VERBOSE",
+	"		printf(\"%%3ld: BCS not a deadlock\\n\", depth);",
+	"	#endif",
+	"	}",
+	"#endif",
+
 	"#ifndef NOFAIR",
 	"	/* Fairness: undo Rule 2 */",
 	"	if (trpt->o_pm&32)	/* remains if proc blocked */",
 	"	{",
 		"#ifdef VERI",
-	"		if (now._cnt[now._a_t&1] == 1)",	/* NEW: 1 iso 0 */
-	"			now._cnt[now._a_t&1] = 2;",	/* NEW: 2 iso 1 */
+	"		if (now._cnt[now._a_t&1] == 1)",
+	"			now._cnt[now._a_t&1] = 2;",
 		"#endif",
 	"		now._cnt[now._a_t&1] += 1;",
 		"#ifdef VERBOSE",
-	"		printf(\"%%3d: proc -- fairness \", depth);",
+	"		printf(\"%%3ld: proc -- fairness \", depth);",
 	"		printf(\"undo Rule 2, cnt=%%d, _a_t=%%d\\n\",",
 	"			now._cnt[now._a_t&1], now._a_t);",
 		"#endif",
 	"		trpt->o_pm &= ~32;",
 	"	}",
-"#ifndef NP",
+	"#ifndef NP",
 	/* 12/97 non-progress cycles cannot be created
 	 * by stuttering extension, here or elsewhere
 	 */
@@ -2361,12 +3831,8 @@
 		"	&& !(trpt->tau&4)	/* in program move */",
 		"#endif",
 	"	&& !(trpt->tau&8)	/* not an atomic one */",
-		"#ifdef OTIM",
-		"	&& ((trpt->tau&1) || endstate())",
-		"#else",
-			"#ifdef ETIM",
-			"	&&  (trpt->tau&1)	/* already tried timeout */",
-			"#endif",
+		"#ifdef ETIM",
+		"	&&  (trpt->tau&1)	/* already tried timeout */",
 		"#endif",
 		"#ifndef NOREDUCE",
 		"	/* see below  */",
@@ -2382,14 +3848,14 @@
 		"#else",
 	"		trpt->tau = 0;",
 		"#endif",
-	"		From = now._nr_pr-1; To = BASE;",
+	"		From = FROM_P; To = UPTO_P;",
 		"#if defined(VERBOSE) || defined(CHECK)",
-	"		printf(\"%%3d: fairness default move \", depth);",
+	"		printf(\"%%3ld: fairness default move \", depth);",
 	"		printf(\"(all procs block)\\n\");",
 		"#endif",
 	"		goto Down;",
 	"	}",
-"#endif",
+	"#endif",
 	"Q999:	/* returns here with _n>0 when done */;",
 
 	"	if (trpt->o_pm&8)",
@@ -2397,7 +3863,7 @@
 	"		now._cnt[now._a_t&1] = 0;",
 	"		trpt->o_pm &= ~8;",
 		"#ifdef VERBOSE",
-	"		printf(\"%%3d: fairness undo Rule 1, _a_t=%%d\\n\",",
+	"		printf(\"%%3ld: fairness undo Rule 1, _a_t=%%d\\n\",",
 	"			depth, now._a_t);",
 		"#endif",
 	"	}",
@@ -2406,7 +3872,7 @@
 	"		now._cnt[now._a_t&1] = 1;",	/* NEW: restore cnt */
 	"		trpt->o_pm &= ~16;",
 		"#ifdef VERBOSE",
-	"		printf(\"%%3d: fairness undo Rule 3, _a_t=%%d\\n\",",
+	"		printf(\"%%3ld: fairness undo Rule 3, _a_t=%%d\\n\",",
 	"			depth, now._a_t);",
 		"#endif",
 	"	}",
@@ -2414,35 +3880,41 @@
 
 	"#ifndef NOREDUCE",
 "#ifdef SAFETY",
-	"	/* preselected move - no successors outside stack */",
-	"	if ((trpt->tau&32) && !(trpt->tau&64))",
-	"	{	From = now._nr_pr-1; To = BASE;",
-		"#ifdef DEBUG",
-	"	printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
-	"	depth, II+1, _n, trpt->tau);",
-		"#endif",
+	"	#ifdef LOOPSTATE",
+	"	  /* at least one move that was preselected at this */",
+	"	  /* level, blocked or was a loop control flow point */",
+	"	  if ((trpt->tau&32) && (_n == 0 || (trpt->tau&16)))",
+	"	#else",
+	"	  /* preselected move - no successors outside stack */",
+	"	  if ((trpt->tau&32) && !(trpt->tau&64))",
+	"	#endif",
+	"	  {	From = FROM_P; To = UPTO_P; /* undo From == To */",
+	"	#ifdef DEBUG",
+	"		printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
+	"			depth, II+1, _n, trpt->tau);",
+	"	#endif",
 	"		_n = 0; trpt->tau &= ~(16|32|64);",
-	"		if (II >= BASE)	/* II already decremented */",
-	"			goto Resume;",
-	"		else",
-	"			goto Again;",
-	"	}",
+
+	"		if (MORE_P)	/* II already restored and updated */",
+	"		{	goto Resume;",
+	"		} else",
+	"		{	goto Again;",
+	"	  }	}",
 "#else",
 	"	/* at least one move that was preselected at this */",
 	"	/* level, blocked or truncated at the next level  */",
-	"/* implied: #ifdef FULLSTACK */",
 	"	if ((trpt->tau&32) && (_n == 0 || (trpt->tau&16)))",
 	"	{",
-		"#ifdef DEBUG",
-	"	printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
-	"	depth, II+1, (int) _n, trpt->tau);",
-		"#endif",
+	"	#ifdef DEBUG",
+	"		printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
+	"		depth, II+1, (int) _n, trpt->tau);",
+	"	#endif",
 	"		if (a_cycles && (trpt->tau&16))",
 	"		{	if (!(now._a_t&1))",
 	"			{",
-		"#ifdef DEBUG",
-	"	printf(\"%%3d: setting proviso bit\\n\", depth);",
-		"#endif",
+	"	#ifdef DEBUG",
+	"			printf(\"%%3ld: setting proviso bit\\n\", depth);",
+	"	#endif",
 	"#ifndef BITSTATE",
 		"#ifdef MA",
 			"#ifdef VERI",
@@ -2466,19 +3938,18 @@
 	"			trpt->ostate->proviso = 1;",
 		"#endif",
 	"#endif",
-	"				From = now._nr_pr-1; To = BASE;",
+	"				From = FROM_P; To = UPTO_P;",
 	"				_n = 0; trpt->tau &= ~(16|32|64);",
 	"				goto Again; /* do full search */",
 	"			} /* else accept reduction */",
 	"		} else",
-	"		{	From = now._nr_pr-1; To = BASE;",
+	"		{	From = FROM_P; To = UPTO_P;",
 	"			_n = 0; trpt->tau &= ~(16|32|64);",
-	"			if (II >= BASE)	/* already decremented */",
-	"				goto Resume;",
-	"			else",
-	"				goto Again;",
-	"	}	}",
-	"/* #endif */",
+	"			if (MORE_P)	/* II already updated */",
+	"			{	goto Resume;",
+	"			} else",
+	"			{	goto Again;",
+	"	}	}	}",
 "#endif",
 	"#endif",
 
@@ -2485,8 +3956,8 @@
 	"	if (_n == 0 || ((trpt->tau&4) && (trpt->tau&2)))",
 	"	{",
 		"#ifdef DEBUG",
-	"	printf(\"%%3d: no move [II=%%d, tau=%%d, boq=%%d]\\n\",",
-	"		 depth, II, trpt->tau, boq);",
+	"		cpu_printf(\"%%3ld: no move [II=%%d, tau=%%d, boq=%%d]\\n\",",
+	"			depth, II, trpt->tau, boq);",
 		"#endif",
 	"#if SYNC",
 	"		/* ok if a rendez-vous fails: */",
@@ -2494,18 +3965,14 @@
 	"#endif",
 	"		/* ok if no procs or we're at maxdepth */",
 	"		if ((now._nr_pr == 0 && (!strict || qs_empty()))",
-	"#ifdef OTIM",
-	"		||  endstate()",
-	"#endif",
-	"		||  depth >= maxdepth-1) goto Done;",
+	"		||  depth >= maxdepth-1) goto Done;	/* undo change from 5.2.3 */",
 
 	"		if ((trpt->tau&8) && !(trpt->tau&4))",
 	"		{	trpt->tau &= ~(1|8);",
 	"			/* 1=timeout, 8=atomic */",
-	"			From = now._nr_pr-1; To = BASE;",
+	"			From = FROM_P; To = UPTO_P;",
 		"#ifdef DEBUG",
-	"		printf(\"%%3d: atomic step proc %%d \", depth, II+1);",
-	"		printf(\"unexecutable\\n\");",
+	"		cpu_printf(\"%%3ld: atomic step proc %%d unexecutable\\n\", depth, II+1);",
 		"#endif",
 	"#ifdef VERI",
 	"			trpt->tau |= 4;	/* switch to claim */",
@@ -2524,9 +3991,9 @@
 		"#endif",
 	"				{	trpt->tau |=  1;",
 	"					trpt->tau &= ~2;",
-				"#ifdef DEBUG",
-	"				printf(\"%%d: timeout\\n\", depth);",
-				"#endif",
+	"	#ifdef DEBUG",
+	"				cpu_printf(\"%%d: timeout\\n\", depth);",
+	"	#endif",
 	"					goto Stutter;",
 	"			}	}",
 	"			else",
@@ -2534,18 +4001,22 @@
 	"				if ((trpt->tau&8)",
 	"				&&  !((trpt-1)->tau&4))",
 	"/* blocks inside an atomic */		goto BreakOut;",
-				"#ifdef DEBUG",
-	"				printf(\"%%d: req timeout\\n\",",
+	"	#ifdef DEBUG",
+	"				cpu_printf(\"%%d: req timeout\\n\",",
 	"					depth);",
-				"#endif",
+	"	#endif",
 	"				(trpt-1)->tau |= 2; /* request */",
+	"	#if NCORE>1 && defined(FULL_TRAIL)",
+	"				if (upto > 0)",
+	"				{	Pop_Stack_Tree();",
+	"				}",
+	"	#endif",
 	"				goto Up;",
 	"			}",
 	"#else",
-
-				"#ifdef DEBUG",
-	"			printf(\"%%d: timeout\\n\", depth);",
-				"#endif",
+	"	#ifdef DEBUG",
+	"			cpu_printf(\"%%d: timeout\\n\", depth);",
+	"	#endif",
 	"			trpt->tau |=  1;",
 	"			goto Again;",
 	"#endif",
@@ -2560,7 +4031,7 @@
 	"		{	trpt->tau |= 4;   /* claim stuttering */",
 	"			trpt->tau |= 128; /* stutter mark */",
 				"#ifdef DEBUG",
-	"			printf(\"%%d: claim stutter\\n\", depth);",
+	"			cpu_printf(\"%%d: claim stutter\\n\", depth);",
 				"#endif",
 	"			goto Stutter;",
 	"		}",
@@ -2585,6 +4056,47 @@
 	"Done:",
 	"	if (!(trpt->tau&8))	/* not in atomic seqs */",
 	"	{",
+
+"#ifndef MA",
+	"#if defined(FULLSTACK) || defined(CNTRSTACK)",
+	"#ifdef VERI",
+	"		if (boq == -1",
+	"		&&  (((trpt->tau&4) && !(trpt->tau&128))",
+	"		||  ( (trpt-1)->tau&128)))",
+	"#else",
+	"		if (boq == -1)",
+	"#endif",
+	"		{",
+		"#ifdef DEBUG2",
+		"#if defined(FULLSTACK)",
+	"			printf(\"%%ld: zapping %%u (%%d)\\n\",",
+	"				depth, trpt->ostate,",
+	"			(trpt->ostate)?trpt->ostate->tagged:0);",
+		"#endif",
+		"#endif",
+	"			onstack_zap();",
+	"		}",
+	"#endif",
+"#else",
+	"#ifdef VERI",
+	"		if (boq == -1",
+	"		&&  (((trpt->tau&4) && !(trpt->tau&128))",
+	"		||  ( (trpt-1)->tau&128)))",
+	"#else",
+	"		if (boq == -1)",
+	"#endif",
+	"		{",
+		"#ifdef DEBUG",
+	"			printf(\"%%ld: zapping\\n\", depth);",
+		"#endif",
+	"			onstack_zap();",
+		"#ifndef NOREDUCE",
+	"			if (trpt->proviso)",
+	"			g_store((char *) &now, vsize, 1);",
+		"#endif",
+	"		}",
+"#endif",
+
 	"#ifndef SAFETY",
 	"		if (_n != 0",		/* we made a move */
 		"#ifdef VERI",
@@ -2601,7 +4113,7 @@
 	"			if (fairness)",	/* implies a_cycles */
 	"			{",
 			"#ifdef VERBOSE",
-	"			printf(\"Consider check %%d %%d...\\n\",",
+	"			cpu_printf(\"Consider check %%d %%d...\\n\",",
 	"				now._a_t, now._cnt[0]);",
 			"#endif",
 #if 0
@@ -2624,47 +4136,16 @@
 	"				checkcycles();",
 	"		}",
 	"#endif",
-"#ifndef MA",
-	"#if defined(FULLSTACK) || defined(CNTRSTACK)",
-	"#ifdef VERI",
-	"		if (boq == -1",
-	"		&&  (((trpt->tau&4) && !(trpt->tau&128))",
-	"		||  ( (trpt-1)->tau&128)))",
-	"#else",
-	"		if (boq == -1)",
-	"#endif",
-	"		{",
-		"#ifdef DEBUG2",
-		"#if defined(FULLSTACK)",
-	"			printf(\"%%d: zapping %%u (%%d)\\n\",",
-	"				depth, trpt->ostate,",
-	"			(trpt->ostate)?trpt->ostate->tagged:0);",
-		"#endif",
-		"#endif",
-	"			onstack_zap();",
+	"	}",
+	"	if (depth > 0)",
+	"	{",
+	"#if NCORE>1 && defined(FULL_TRAIL)",
+	"		if (upto > 0)",
+	"		{	Pop_Stack_Tree();",
 	"		}",
 	"#endif",
-"#else",
-	"#ifdef VERI",
-	"		if (boq == -1",
-	"		&&  (((trpt->tau&4) && !(trpt->tau&128))",
-	"		||  ( (trpt-1)->tau&128)))",
-	"#else",
-	"		if (boq == -1)",
-	"#endif",
-	"		{",
-		"#ifdef DEBUG",
-	"			printf(\"%%d: zapping\\n\", depth);",
-		"#endif",
-	"			onstack_zap();",
-		"#ifndef NOREDUCE",
-	"			if (trpt->proviso)",
-	"			gstore((char *) &now, vsize, 1);",
-		"#endif",
-	"		}",
-"#endif",
+	"		goto Up;",
 	"	}",
-	"	if (depth > 0) goto Up;",
 	"}\n",
 	"#else",
 	"void new_state(void) { /* place holder */ }",
@@ -2671,7 +4152,7 @@
 	"#endif",	/* BFS */
 	"",
 	"void",
-	"assert(int a, char *s, int ii, int tt, Trans *t)",
+	"spin_assert(int a, char *s, int ii, int tt, Trans *t)",
 	"{",
 	"	if (!a && !noasserts)",
 	"	{	char bad[1024];",
@@ -2688,169 +4169,214 @@
 	"int",
 	"Boundcheck(int x, int y, int a1, int a2, Trans *a3)",
 	"{",
-	"	assert((x >= 0 && x < y), \"- invalid array index\",",
+	"	spin_assert((x >= 0 && x < y), \"- invalid array index\",",
 	"		a1, a2, a3);",
 	"	return x;",
 	"}",
 	"#endif",
+	"int do_hashgen = 0;",
 	"void",
 	"wrap_stats(void)",
 	"{",
 	"	if (nShadow>0)",
-	"	  printf(\"%%8g states, stored (%%g visited)\\n\",",
+	"	  printf(\"%%9.8g states, stored (%%g visited)\\n\",",
 	"			nstates - nShadow, nstates);",
 	"	else",
-	"	  printf(\"%%8g states, stored\\n\", nstates);",
+	"	  printf(\"%%9.8g states, stored\\n\", nstates);",
+	"#ifdef BFS_PAR",
+	"	if (bfs_punt > 0)",
+	"	printf(\"%%9.8g states lost (lack of queue memory)\\n\", (double) bfs_punt);",
+	"#endif",
 	"#ifdef BFS",
-	"#if SYNC",
+	"	#if SYNC",
 	"	printf(\"	%%8g nominal states (- rv and atomic)\\n\", nstates-midrv-nlinks+revrv);",
 	"	printf(\"	%%8g rvs succeeded\\n\", midrv-failedrv);",
-	"#else",
+	"	#else",
 	"	printf(\"	%%8g nominal states (stored-atomic)\\n\", nstates-nlinks);",
-	"#endif",
-	"#ifdef DEBUG",
+	"	#endif",
+	"	#ifdef DEBUG",
 	"	printf(\"	%%8g midrv\\n\", midrv);",
 	"	printf(\"	%%8g failedrv\\n\", failedrv);",
 	"	printf(\"	%%8g revrv\\n\", revrv);",
+	"	#endif",
 	"#endif",
-	"#endif",
-	"	printf(\"%%8g states, matched\\n\", truncs);",
+	"	printf(\"%%9.8g states, matched\\n\", truncs);",
 	"#ifdef CHECK",
-	"	printf(\"%%8g matches within stack\\n\",truncs2);",
+	"	printf(\"%%9.8g matches within stack\\n\",truncs2);",
 	"#endif",
 	"	if (nShadow>0)",
-	"	printf(\"%%8g transitions (= visited+matched)\\n\",",
+	"	printf(\"%%9.8g transitions (= visited+matched)\\n\",",
 	"		nstates+truncs);",
 	"	else",
-	"	printf(\"%%8g transitions (= stored+matched)\\n\",",
+	"	printf(\"%%9.8g transitions (= stored+matched)\\n\",",
 	"		nstates+truncs);",
-	"	printf(\"%%8g atomic steps\\n\", nlinks);",
+	"	printf(\"%%9.8g atomic steps\\n\", nlinks);",
 	"	if (nlost) printf(\"%%g lost messages\\n\", (double) nlost);",
 	"",
 	"#ifndef BITSTATE",
-	"	printf(\"hash conflicts: %%g (resolved)\\n\", hcmp);",
+	"	#ifndef MA",
+	"	printf(\"hash conflicts: %%9.8g (resolved)\\n\", hcmp);",
+	"		#if !defined(AUTO_RESIZE) && !defined(BFS_PAR)",
+	"	if (hcmp > (double) (1<<ssize))",
+	"	{  printf(\"hint: increase hashtable-size (-w) to reduce runtime\\n\");",
+	"	}",
+	"		#endif",
+	"		#if defined(BFS_PAR) && defined(HC)",
+	"	{ double fp = (100. * (double) nstates)/((double) ((ulong) (1<<ssize)));",
+	"	  int fi = 0;",
+	"		printf(\"the hash table is %%3.3g %%%% filled\", fp);",
+	"		if (fp > 1.0)",
+	"		{	fp = 100. / fp;",
+	"			while (fp > 2.) { fi++; fp /= 2.; }",
+	"			if (fi > 0)",
+	"			{	printf(\" (hint: rerun with -w%%d to reduce runtime)\",",
+	"				ssize-fi);",
+	"		}	}",
+	"		printf(\"\\n\");",
+	"	}",
+	"		#endif",
+	"	#endif",
 	"#else",
 		"#ifdef CHECK",
 		"	printf(\"%%8g states allocated for dfs stack\\n\", ngrabs);",
 		"#endif",
-	"	printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",",
-	"		(double)(1<<(ssize-8)) / (double) nstates * 256.0);",
-	"       printf(\"bits set per state: %%u (-k%%u)\\n\", hfns, hfns);",
-	"#if 0",
-#ifndef POWOW
 	"	if (udmem)",
-	"	printf(\"total bits available: %%8g (-M%%ld)\\n\",",
-	"		((double) udmem) * 8.0, udmem/(1024L*1024L));",
+	"	printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",",
+	"		(double)(((double) udmem) * 8.0) / (double) nstates);",
 	"	else",
-#endif
-	"	printf(\"total bits available: %%8g (-w%%d)\\n\",",
-	"		((double) (1L << (ssize-4)) * 16.0), ssize);",
+	"	printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",",
+	"		((double)(((ulong)1)<<(ssize-10)) / (double) nstates) * 1024.0);",
+			/* the -10 and *1024 stuff is to avoid overflow */
+	"       printf(\"bits set per state: %%u (-k%%u)\\n\", hfns, hfns);",
+	"	if (do_hashgen)",
+	"	printf(\"hash polynomial used: 0x%%.8x\\n\", HASH_CONST[HASH_NR]);",
+	"	if (s_rand != 12345)",
+	"	printf(\"random seed used: %%u\\n\", (uint) (s_rand-1));",
 	"#endif",
-"#ifdef COVEST",
-	"	/* this code requires compilation with -lm on some systems */",
-	"	{	double pow(double, double);",
-	"		double log(double);",
-	"               unsigned int best_k;",
-	"               double i, n = 30000.0L;",
-	"               double f, p, q, m, c, est = 0.0L, k = (double)hfns;",
-	"               c = (double) nstates / n;",
-	"               m = (double) (1<<(ssize-8)) * 256.0L / c;",
-	"               p = 1.0L - (k / m);  q = 1.0L;",
-	"               for (i = 0.0L; i - est < n; i += 1.0L)",
-	"		{	q *= p;",
-	"			est += pow(1.0L - q, k);",
-	"		}",
-	"		f = m/i;",
-	"		est *= c;",
-	"		i *= c;",
-	"		/* account for loss from enhanced double hashing */",
-        "		if (hfns > 2) est += i * pow(0.5, (double) ssize * 2.0);",
-	"",
-	"               if (f < 1.134) best_k = 1;",
-	"               else if (f < 2.348) best_k = 2;",
-	"               else if (f < 3.644) best_k = 3;",
-	"		else best_k = (unsigned int) (pow(3.8L,1.0L/(f+4.2L))*f*.69315L + 0.99999999L);",
-	"",
-	"		if (best_k != hfns && best_k > ssize)",
-	"			best_k = (unsigned int) 1.0 + ssize/log((double)best_k / (double)ssize + 3.0);",
-	"",
-	"		if (best_k > 32)",
-	"			best_k = 1 + (unsigned int) (32.0/log((double)best_k/35.0));",
-	"",
-	"		if (est * (double) nstates < 1.0)",
-	"		{	printf(\"prob. of omissions: negligible\\n\");",
-	"			return;	/* no hints needed */",
-	"		}",
-	"",
-	"		if (best_k != hfns)",
-	"		{	printf(\"hint: repeating the search with -k%%u \", best_k);",
-	"			printf(\"may increase accuracy\\n\");",
-	"		} else",
-	"		{	printf(\"hint: the current setting for -k (-k%%d) \", hfns);",
-	"			printf(\"is likely to be optimal for -w%%d\\n\", ssize);",
-	"		}",
-	"		if (ssize < 32)",
-	"		{	printf(\"hint: increasing -w above -w%%d \", ssize);",
-	"			printf(\"will increase accuracy (max is -w34)\\n\");",
-	"			printf(\"(in xspin, increase Estimated State Space Size)\\n\");",
-	"	}	}",
-"#endif",
+	"#if defined(BFS_DISK) && !defined(BFS_PAR)",
+	"	printf(\"bfs disk reads: %%ld writes %%ld -- diff %%ld\\n\",",
+	"		bfs_dsk_reads, bfs_dsk_writes, bfs_dsk_writes-bfs_dsk_reads);",
+	"	if (bfs_dsk_read  >= 0) (void) close(bfs_dsk_read);",
+	"	if (bfs_dsk_write >= 0) (void) close(bfs_dsk_write);",
+	"	(void) unlink(\"pan_bfs_dsk.tmp\");",
 	"#endif",
 	"}",
+	"",
 	"void",
 	"wrapup(void)",
-	"{",
-	"#if defined(BITSTATE) || !defined(NOCOMP)",
-	"	double nr1, nr2, nr3 = 0.0, nr4, nr5 = 0.0;",
-	"#if !defined(MA) && (defined(MEMCNT) || defined(MEMLIM))",
-	"	int mverbose = 1;",
-	"#else",
-	"	int mverbose = verbose;",
+	"{	double nr1, nr2, nr3 = 0.0, nr4, nr5 = 0.0;",
+	"#ifdef BFS_PAR",
+	"	if (who_am_i != 0)",
+	"	{	pan_exit(0);",
+	"	}",
 	"#endif",
+	"#if NCORE>1",
+	"	if (verbose) cpu_printf(\"wrapup -- %%d error(s)\\n\", errors);",
+	"	if (core_id != 0)",
+	"	{",
+	"	#ifdef USE_DISK",
+	"		void	dsk_stats(void);",
+	"		dsk_stats();",
+	"	#endif",
+	"		if (search_terminated != NULL)",
+	"		{	*search_terminated |= 2;	/* wrapup */",
+	"		}",
+	"		exit(0); /* normal termination, not an error */",
+	"	}",
 	"#endif",
-
+	"#if !defined(WIN32) && !defined(WIN64)",
 	"	signal(SIGINT, SIG_DFL);",
-	"	printf(\"(%%s)\\n\", Version);",
+	"#endif",
+	"	printf(\"\\n(%%s)\\n\", SpinVersion);",
 	"	if (!done) printf(\"Warning: Search not completed\\n\");",
+	"#if defined(BFS_PAR) && !defined(BITSTATE)",
+	"	if (bfs_punt > 0) printf(\"Warning: Search incomplete\\n\");",
+	"#endif",
 	"#ifdef SC",
 	"	(void) unlink((const char *)stackfile);",
 	"#endif",
+	"#ifdef BFS_PAR",
+	"	printf(\"	+ Multi-Core (using %%d cores)\\n\", Cores);",
+	"	#ifdef BFS_SEP_HASH",
+	"	printf(\"	+ Separate Hash Tables\\n\");",
+	"	#endif",
+	"	#ifdef BFS_DISK",
+	"	printf(\"	+ Disk storage\\n\");",
+	"	#endif",
+	"#endif",
+	"#if NCORE>1",
+	"	if (a_cycles)",
+	"	{	printf(\"	+ Multi-Core (NCORE=%%d)\\n\", NCORE);",
+	"	} else",
+	"	{	printf(\"	+ Multi-Core (NCORE=%%d -z%%ld)\\n\", NCORE, z_handoff);",
+	"	}",
+	"#endif",
 	"#ifdef BFS",
-	"	printf(\"	+ Using Breadth-First Search\\n\");",
+	"	printf(\"	+ Breadth-First Search\\n\");",
 	"#endif",
 	"#ifndef NOREDUCE",
 	"	printf(\"	+ Partial Order Reduction\\n\");",
 	"#endif",
-#if 0
-	"#ifdef Q_PROVISO",
-	"	printf(\"	+ Queue Proviso\\n\");",
+	"#ifdef PERMUTED",
+	"	printf(\"	+ Process Scheduling Permutation\\n\");",
 	"#endif",
-#endif
+	"#ifdef P_REVERSE",
+	"	printf(\"	+ Reverse Depth-First Search Order\\n\");",
+	"#endif",
+	"	if (t_reverse)",
+	"	printf(\"	+ Reverse Transition Ordering\\n\");",
+	"#ifdef T_RAND",
+	"	printf(\"	+ Randomized Transition Ordering\\n\");",
+	"#endif",
+	"#ifdef P_RAND",
+	"	printf(\"	+ Randomized Process Ordering\\n\");",
+	"#endif",
+	"#ifdef BCS",
+	"	printf(\"	+ Scheduling Restriction (-L%%d)\\n\", sched_max);",
+	"#endif",
+	"#ifdef TRIX",
+	"	printf(\"	+ Tree Index Compression\\n\");",
+	"#endif",
 	"#ifdef COLLAPSE",
 	"	printf(\"	+ Compression\\n\");",
 	"#endif",
 	"#ifdef MA",
 	"	printf(\"	+ Graph Encoding (-DMA=%%d)\\n\", MA);",
-	"#ifdef R_XPT",
-	"	printf(\"	  Restarted from checkpoint %%s.xpt\\n\", Source);",
+	"  #ifdef R_XPT",
+	"	printf(\"	  Restarted from checkpoint %%s.xpt\\n\", PanSource);",
+	"  #endif",
 	"#endif",
-	"#endif",
 	"#ifdef CHECK",
-		"#ifdef FULLSTACK",
+	"  #ifdef FULLSTACK",
 	"	printf(\"	+ FullStack Matching\\n\");",
-		"#endif",
-		"#ifdef CNTRSTACK",
+	"  #endif",
+	"  #ifdef CNTRSTACK",
 	"	printf(\"	+ CntrStack Matching\\n\");",
-		"#endif",
+	"  #endif",
 	"#endif",
+	"#ifdef PERMUTED",
+	"	if (reversing & 2)",
+	"	{	if (p_reorder == set_permuted)",
+	"		{	printf(\"	+ Permuted\\n\");",
+	"		}",
+	"		if (p_reorder == set_reversed)",
+	"		{	printf(\"	+ Reversed\\n\");",
+	"		}",
+	"		if (p_reorder == set_rotated)",
+	"		{	printf(\"	+ Rotated %%d\\n\", p_rotate);",
+	"		}",
+	"		if (p_reorder == set_randrot)",
+	"		{	printf(\"	+ RandRotated\\n\");",
+	"	}	}",
+	"#endif",
 	"#ifdef BITSTATE",
 	"	printf(\"\\nBit statespace search for:\\n\");",
 	"#else",
-		"#ifdef HC",
+	"  #ifdef HC",
 	"	printf(\"\\nHash-Compact %%d search for:\\n\", HC);",
-		"#else",
+	"  #else",
 	"	printf(\"\\nFull statespace search for:\\n\");",
-		"#endif",
+	"  #endif",
 	"#endif",
 	"#ifdef EVENT_TRACE",
 	"#ifdef NEGATED_TRACE",
@@ -2860,7 +4386,8 @@
 	"#endif",
 	"#endif",
 	"#ifdef VERI",
-	"	printf(\"\tnever claim         \t+\\n\");",
+	"	printf(\"\tnever claim         \t+\");",
+	"	printf(\" (%%s)\\n\", procname[((Pclaim *)pptr(0))->_t]);",
 	"	printf(\"\tassertion violations\t\");",
 	"	if (noasserts)",
 	"		printf(\"- (disabled by -A flag)\\n\");",
@@ -2889,7 +4416,11 @@
 	"			fairness?\"en\":\"dis\");",
 	"	else printf(\"- (not selected)\\n\");",
 	"#else",
+	"	#if !defined(BFS_PAR) || !defined(L_BOUND)",
 	"	printf(\"\tcycle checks       \t- (disabled by -DSAFETY)\\n\");",
+	"	#else",
+	"	printf(\"\tcycle checks       \t+ (bound %%d)\\n\", L_bound);",
+	"	#endif",
 	"#endif",
 	"#ifdef VERI",
 	"	printf(\"\tinvalid end states\t- \");",
@@ -2905,9 +4436,13 @@
 	"	else",
 	"		printf(\"+\\n\\n\");",
 	"#endif",
-	"	printf(\"State-vector %%d byte, depth reached %%d\", ",
-	"					hmax, mreached);",
+	"	printf(\"State-vector %%d byte, depth reached %%ld\", hmax,",
+	"#if NCORE>1",
+	"					(nr_handoffs * z_handoff) +",
+	"#endif",
+	"					mreached);",
 	"	printf(\", errors: %%d\\n\", errors);",
+	"	fflush(stdout);",
 	"#ifdef MA",
 	"	if (done)",
 	"	{	extern void dfa_stats(void);",
@@ -2920,124 +4455,196 @@
 	"	wrap_stats();",
 	"#ifdef CHECK",
 	"	printf(\"stackframes: %%d/%%d\\n\\n\", smax, svmax);",
-	"	printf(\"stats: fa %%d, fh %%d, zh %%d, zn %%d - \",",
+	"	printf(\"stats: fa %%ld, fh %%ld, zh %%ld, zn %%ld - \",",
 	"		Fa, Fh, Zh, Zn);",
-	"	printf(\"check %%d holds %%d\\n\", Ccheck, Cholds);",
-	"	printf(\"stack stats: puts %%d, probes %%d, zaps %%d\\n\",",
+	"	printf(\"check %%ld holds %%ld\\n\", Ccheck, Cholds);",
+	"	printf(\"stack stats: puts %%ld, probes %%ld, zaps %%ld\\n\",",
 	"		PUT, PROBE, ZAPS);",
 	"#else",
 	"	printf(\"\\n\");",
 	"#endif",
 	"",
-	"#if defined(BITSTATE) || !defined(NOCOMP)",
+	"#if !defined(BITSTATE) && defined(NOCOMP)",
+	"	if (!verbose) { goto jump_here; }",	/* added 5.2.0 */
+	"#endif",
+	"",
+	"#if 1",	/* omitted 5.2.0:  defined(BITSTATE) || !defined(NOCOMP) */
 	"	nr1 = (nstates-nShadow)*",
-	"	      (double)(hmax+sizeof(struct H_el)-sizeof(unsigned));",
-		"#ifdef BFS",
+	"	      (double)(hmax+sizeof(H_el)-sizeof(unsigned));",
+	"	#ifdef BFS",
 	"	nr2 = 0.0;",
-		"#else",
+	"	#else",
 	"	nr2 = (double) ((maxdepth+3)*sizeof(Trail));",
-		"#endif",
+	"	#endif",
 
-		"#ifndef BITSTATE",
+	"	#ifndef BITSTATE",
 			"#if !defined(MA) || defined(COLLAPSE)",
-	"	nr3 = (double) (1L<<ssize)*sizeof(struct H_el *);",
+	"	nr3 = (double) (ONE_L<<ssize)*sizeof(H_el *);",
 			"#endif",
-		"#else",
-#ifndef POWOW
+	"	#else",
 	"	if (udmem)",
 	"		nr3 = (double) (udmem);",
 	"	else",
-#endif
-	"	nr3 = (double) (1L<<(ssize-3));",
+	"		nr3 = (double) (ONE_L<<(ssize-3));",
 			"#ifdef CNTRSTACK",
-	"	nr3 += (double) (1L<<(ssize-3));",
+	"	nr5 = (double) (ONE_L<<(ssize-3));",
 			"#endif",
 			"#ifdef FULLSTACK",
-	"	nr5 = (double) (maxdepth*sizeof(struct H_el *));",
+	"	nr5 = (double) (maxdepth*sizeof(H_el *));",
 			"#endif",
-		"#endif",
+	"	#endif",
+
 	"	nr4 = (double) (svmax * (sizeof(Svtack) + hmax))",
-	"	    + (double) (smax * (sizeof(Stack) + Maxbody));",
+	"	    + (double) (smax  * (sizeof(_Stack) + Maxbody * sizeof(char)));",
 		"#ifndef MA",
-	"	if (mverbose || memcnt < nr1+nr2+nr3+nr4+nr5)",
+	"	if (1 /* verbose || memcnt < nr1+nr2+nr3+nr4+nr5 */)",
 		"#endif",
 	"	{ double remainder = memcnt;",
 	"	  double tmp_nr = memcnt-nr3-nr4-(nr2-fragment)-nr5;",
+	"",
+	"	#if NCORE>1 && !defined(SEP_STATE)",
+	"		tmp_nr -= ((double) NCORE * LWQ_SIZE) + GWQ_SIZE;",
+	"	#endif",
 	"		if (tmp_nr < 0.0) tmp_nr = 0.;",
 	"		printf(\"Stats on memory usage (in Megabytes):\\n\");",
-	"		printf(\"%%-6.3f\tequivalent memory usage for states\",",
-	"			nr1/1000000.);",
+	"		printf(\"%%9.3f\tequivalent memory usage for states\",",
+	"			nr1/1048576.); /* 1024*1024=1048576 */",
 	"		printf(\" (stored*(State-vector + overhead))\\n\");",
-		"#ifdef BITSTATE",
-#ifndef POWOW
+	"	#if NCORE>1 && !defined(WIN32) && !defined(WIN64)",
+	"		printf(\"%%9.3f\tshared memory reserved for state storage\\n\",",
+	"			mem_reserved/1048576.);",
+	"		#ifdef SEP_HEAP",
+	"		printf(\"\t\tin %%d local heaps of %%7.3f MB each\\n\",",
+	"			NCORE, mem_reserved/(NCORE*1048576.));",
+	"		#endif",
+	"		printf(\"\\n\");",
+	"	#endif",
+	"	#ifdef BITSTATE",
 	"		if (udmem)",
-	"		printf(\"%%-6.3f\tmemory used for hash array (-M%%ld)\\n\",",
-	"			nr3/1000000., udmem/(1024L*1024L));",
+	"			printf(\"%%9.3f\tmemory used for hash array (-M%%ld)\\n\",",
+	"			nr3/1048576., udmem/(1024L*1024L));",
 	"		else",
-#endif
-	"		printf(\"%%-6.3f\tmemory used for hash array (-w%%d)\\n\",",
-	"			nr3/1000000., ssize);",
+	"			printf(\"%%9.3f\tmemory used for hash array (-w%%d)\\n\",",
+	"			nr3/1048576., ssize);",
 	"		if (nr5 > 0.0)",
-	"		printf(\"%%-6.3f\tmemory used for bit stack\\n\",",
-	"			nr5/1000000.);",
+	"		printf(\"%%9.3f\tmemory used for bit stack\\n\",",
+	"			nr5/1048576.);",
 	"		remainder = remainder - nr3 - nr5;",
-		"#else",
-	"		printf(\"%%-6.3f\tactual memory usage for states\",",
-	"			tmp_nr/1000000.);",
-	"		remainder = remainder - tmp_nr;",
-	"		printf(\" (\");",
-	"		if (tmp_nr > 0.)",
-	"		{	if (tmp_nr > nr1) printf(\"unsuccessful \");",
-	"			printf(\"compression: %%.2f%%%%)\\n\",",
-	"				(100.0*tmp_nr)/nr1);",
-	"		} else",
-	"			printf(\"less than 1k)\\n\");",
-			"#ifndef MA",
-	"		if (tmp_nr > 0.)",
-	"		{	printf(\"\tState-vector as stored = %%.0f byte\",",
-	"			(tmp_nr)/(nstates-nShadow) -",
-	"			(double) (sizeof(struct H_el) - sizeof(unsigned)));",
-	"			printf(\" + %%ld byte overhead\\n\",",
-	"			sizeof(struct H_el)-sizeof(unsigned));",
+	"	#else",
+	"		#ifndef USE_TDH",
+	"			printf(\"%%9.3f\tactual memory usage for states\",",
+	"				tmp_nr/1048576.);",
+	"			remainder -= tmp_nr;",
+	"			if (tmp_nr > 0.)",
+	"			{	if (tmp_nr < nr1) ",
+	"				{	printf(\" (compression: %%.2f%%%%)\\n\",",
+	"						(100.0*tmp_nr)/nr1);",
+	"				} else",
+	"				{	printf(\"\\n\");",
+	"				}",
+	"			} else",
+	"			{	printf(\" (less than 1k)\\n\");",
+	"			}",
+	"			#ifndef MA",
+	"			if (tmp_nr > 0. && tmp_nr < nr1)",
+	"			{	printf(\"         \tstate-vector as stored = %%.0f byte\",",
+	"				(tmp_nr)/(nstates-nShadow) -",
+	"				(double) (sizeof(H_el) - sizeof(unsigned)));",
+	"				printf(\" + %%ld byte overhead\\n\",",
+	"				(long int) sizeof(H_el)-sizeof(unsigned));",
+	"			}",
+	"			#endif",
+	"		#endif",
+	"		#if !defined(MA) || defined(COLLAPSE)",
+	"			#ifdef BFS_PAR",
+	"				printf(\"%%9.3f\tshared memory used for hash table (-w%%d)\\n\",",
+	"				((double) bfs_pre_allocated)/1048576., ssize);",
+	"			#else",
+	"				printf(\"%%9.3f\tmemory used for hash table (-w%%d)\\n\",",
+	"					nr3/1048576., ssize);",
+	"				remainder -= nr3;",
+	"			#endif",
+	"		#endif",
+	"	#endif",
+	"	#ifndef BFS",
+	"		printf(\"%%9.3f\tmemory used for DFS stack (-m%%ld)\\n\",",
+	"			nr2/1048576., maxdepth);",
+	"		remainder -= nr2;",
+	"	#endif",
+	"	#if NCORE>1",
+	"		remainder -= ((double) NCORE * LWQ_SIZE) + GWQ_SIZE;",
+	"		printf(\"%%9.3f\tshared memory used for work-queues\\n\",",
+	"			(GWQ_SIZE + (double) NCORE * LWQ_SIZE) /1048576.);",
+	"		printf(\"\t\tin %%d queues of %%7.3f MB each\",",
+	"			NCORE, (double) LWQ_SIZE /1048576.);",
+	"		#ifndef NGQ",
+	"		printf(\" + a global q of %%7.3f MB\\n\",",
+	"			(double) GWQ_SIZE / 1048576.);",
+	"		#else",
+	"		printf(\"\\n\");",
+	"		#endif",
+	"	#endif",
+	"		if (remainder - fragment > 1048576.)",
+	"		{	printf(\"%%9.3f\tother (proc and chan stacks)\\n\",",
+	"			(remainder-fragment)/1048576.);",
 	"		}",
-			"#endif",
-			"#if !defined(MA) || defined(COLLAPSE)",
-	"		printf(\"%%-6.3f\tmemory used for hash table (-w%%d)\\n\",",
-	"			nr3/1000000., ssize);",
-	"		remainder = remainder - nr3;",
-			"#endif",
-		"#endif",
-		"#ifndef BFS",
-	"		printf(\"%%-6.3f\tmemory used for DFS stack (-m%%ld)\\n\",",
-	"			nr2/1000000., maxdepth);",
-	"		remainder = remainder - nr2;",
-		"#endif",
-	"		if (remainder - fragment > 0.0)",
-	"		printf(\"%%-6.3f\tother (proc and chan stacks)\\n\",",
-	"			(remainder-fragment)/1000000.);",
-	"		if (fragment > 0.0)",
-	"		printf(\"%%-6.3f\tmemory lost to fragmentation\\n\",",
-	"			fragment/1000000.);",
-	"		printf(\"%%-6.3f\ttotal actual memory usage\\n\\n\",",
-	"			memcnt/1000000.);",
+	"		if (fragment > 1048576.)",
+	"		{	printf(\"%%9.3f\tmemory lost to fragmentation\\n\",",
+	"			fragment/1048576.);",
+	"		}",
+	"	#ifdef BFS_PAR",
+	"		printf(\"%%9.3f\ttotal non-shared memory usage\\n\\n\",",
+	"			memcnt/1048576.);",
+	"	#else",
+	"		printf(\"%%9.3f\ttotal actual memory usage\\n\\n\",",
+	"			memcnt/1048576.);",
+	"	#endif",
 	"	}",
-		"#ifndef MA",
+	"	#ifndef MA",
 	"	else",
-		"#endif",
+	"	#endif",
 	"#endif",
-		"#ifndef MA",
-	"		printf(\"%%-6.3f\tmemory usage (Mbyte)\\n\\n\",",
-	"			memcnt/1000000.);",
-		"#endif",
+
+	"#if !defined(BITSTATE) && defined(NOCOMP)",
+	"jump_here:",
+	"#endif",
+	"#ifndef MA",
+	"	printf(\"%%9.3f\tmemory usage (Mbyte)\\n\",",
+	"		memcnt/1048576.);",
+	"#endif",
+	"#ifdef BFS_PAR",
+	"	bfs_report_mem();",
+	"#else",
+	"	printf(\"\\n\");",
+	"#endif",
 	"#ifdef COLLAPSE",
-	"	printf(\"nr of templates: [ globals chans procs ]\\n\");",
+	"	printf(\"nr of templates: [ 0:globals 1:chans 2:procs ]\\n\");",
 	"	printf(\"collapse counts: [ \");",
 	"	{ int i; for (i = 0; i < 256+2; i++)",
 	"		if (ncomps[i] != 0)",
-	"			printf(\"%%d \", ncomps[i]);",
+	"			printf(\"%%d:%%lu \", i, ncomps[i]);",
 	"		printf(\"]\\n\");",
 	"	}",
 	"#endif",
+	"	#ifdef TRIX",
+	"	if (verbose)",
+	"	{	int i;",
+	"		printf(\"TRIX counts:\\n\");",
+	"		printf(\"  processes: \");",
+	"		for (i = 0; i < MAXPROC; i++)",
+	"			if (_p_count[i] != 0)",
+	"			{	printf(\"%%3d:%%ld \",",
+	"					i, _p_count[i]);",
+	"			}",
+	"		printf(\"\\n  channels : \");",
+	"		for (i = 0; i < MAXQ; i++)",
+	"			if (_c_count[i] != 0)",
+	"			{	printf(\"%%3d:%%ld \",",
+	"					i, _c_count[i]);",
+	"			}",
+	"		printf(\"\\n\\n\");",
+	"	}",
+	"	#endif",
 
 	"	if ((done || verbose) && !no_rck) do_reach();",
 	"#ifdef PEG",
@@ -3053,21 +4660,90 @@
 	"#ifdef SVDUMP",
 	"	if (vprefix > 0) close(svfd);",
 	"#endif",
+	"#ifdef LOOPSTATE",
+	"	printf(\"%%g loopstates hit\\n\", cnt_loops);",
+	"#endif",
+	"#ifdef NSUCC",
+	"	dump_succ();",
+	"#endif",
+	"#if NCORE>1 && defined(T_ALERT)",
+	"	crash_report();",
+	"#endif",
+	"#ifndef BFS_PAR",
 	"	pan_exit(0);",
+	"#endif",
 	"}\n",
 	"void",
 	"stopped(int arg)",
-	"{	printf(\"Interrupted\\n\");",
+	"{",
+	"#ifdef BFS_PAR",
+	"	bfs_shutdown(\"interrupted\");",
+	"#endif",
+	"	printf(\"Interrupted\\n\");",
+	"#if NCORE>1",
+	"	was_interrupted = 1;",
+	"#endif",
 	"	wrapup();",
 	"	pan_exit(0);",
 	"}",
+	"",
 	"/*",
-	" * based on Bob Jenkins hash-function from 1996",
-	" * see: http://www.burtleburtle.net/bob/",
+	" * super fast hash, based on Paul Hsieh's function",
+	" * http://www.azillionmonkeys.com/qed/hash.html",
 	" */",
+	"#include <stdint.h>",	/* for uint32_t etc */
+	" #undef get16bits",
+	" #if defined(__GNUC__) && defined(__i386__)",
+	"	#define get16bits(d) (*((const uint16_t *) (d)))",
+	" #else",
+	"	#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\\",
+	"                              +(uint32_t)(((const uint8_t *)(d))[0]) )",
+	" #endif",
 	"",
-"#if defined(HASH64) || defined(WIN64)",
-	/* 64-bit Jenkins hash: http://burtleburtle.net/bob/c/lookup8.c */
+	"void",
+	"d_sfh(uchar *s, int len)",	/* sets one 32-bit number, in K1 */
+	"{	uint32_t h = len, tmp;",
+	"	int rem;",
+	"",
+	"	rem = len & 3;",
+	"	len >>= 2;",
+	"",
+	"	for ( ; len > 0; len--)",
+	"	{	h  += get16bits(s);",
+	"        	tmp = (get16bits(s+2) << 11) ^ h;",
+	"        	h   = (h << 16) ^ tmp;",
+	"        	s  += 2*sizeof(uint16_t);",
+	"		h  += h >> 11;",
+	"	}",
+	"	switch (rem) {",
+	"	case 3: h += get16bits(s);",
+	"		h ^= h << 16;",
+	"		h ^= s[sizeof(uint16_t)] << 18;",
+	"		h += h >> 11;",
+	"		break;",
+	"	case 2: h += get16bits(s);",
+	"		h ^= h << 11;",
+	"		h += h >> 17;",
+	"		break;",
+	"	case 1: h += *s;",
+	"		h ^= h << 10;",
+	"		h += h >> 1;",
+	"		break;",
+	"	}",
+	"	h ^= h << 3;",
+	"	h += h >> 5;",
+	"	h ^= h << 4;",
+	"	h += h >> 17;",
+	"	h ^= h << 25;",
+	"	h += h >> 6;",
+	"",
+	"	K1 = h;",
+	"}",
+	"",
+	"#if WS>4",
+	"/* 64-bit Jenkins hash, 1997",
+	" * http://burtleburtle.net/bob/c/lookup8.c",
+	" */",
 	"#define mix(a,b,c) \\",
 	"{ a -= b; a -= c; a ^= (c>>43); \\",
 	"  b -= c; b -= a; b ^= (a<<9);  \\",
@@ -3082,56 +4758,231 @@
 	"  b -= c; b -= a; b ^= (a<<18); \\",
 	"  c -= a; c -= b; c ^= (b>>22); \\",
 	"}",
-"#else",
+	"#else",
+	"/* 32-bit Jenkins hash, 2006",
+	" * http://burtleburtle.net/bob/c/lookup3.c",
+	" */",
+	"#define rot(x,k)	(((x)<<(k))|((x)>>(32-(k))))",
+	"",
 	"#define mix(a,b,c) \\",
-	"{ a -= b; a -= c; a ^= (c>>13); \\",
-	"  b -= c; b -= a; b ^= (a<<8);  \\",
-	"  c -= a; c -= b; c ^= (b>>13); \\",
-	"  a -= b; a -= c; a ^= (c>>12); \\",
-	"  b -= c; b -= a; b ^= (a<<16); \\",
-	"  c -= a; c -= b; c ^= (b>>5);  \\",
-	"  a -= b; a -= c; a ^= (c>>3);  \\",
-	"  b -= c; b -= a; b ^= (a<<10); \\",
-	"  c -= a; c -= b; c ^= (b>>15); \\",
+	"{ a -= c;  a ^= rot(c, 4);  c += b; \\",
+	"  b -= a;  b ^= rot(a, 6);  a += c; \\",
+	"  c -= b;  c ^= rot(b, 8);  b += a; \\",
+	"  a -= c;  a ^= rot(c,16);  c += b; \\",
+	"  b -= a;  b ^= rot(a,19);  a += c; \\",
+	"  c -= b;  c ^= rot(b, 4);  b += a; \\",
 	"}",
-"#endif",
-	"void",
-	"d_hash(uchar *Cp, int Om)	/* double bit hash - Jenkins */",
-	"{	unsigned long a = 0x9e3779b9, b, c = 0, len, length;",
-	"	unsigned long *k = (unsigned long *) Cp;",
 	"",
-	"	length = len = (unsigned long) ((unsigned long) Om + WS-1)/WS;",
+	"#define final(a,b,c) \\",
+	"{ c ^= b; c -= rot(b,14); \\",
+	"  a ^= c; a -= rot(c,11); \\",
+	"  b ^= a; b -= rot(a,25); \\",
+	"  c ^= b; c -= rot(b,16); \\",
+	"  a ^= c; a -= rot(c,4);  \\",
+	"  b ^= a; b -= rot(a,14); \\",
+	"  c ^= b; c -= rot(b,24); \\",
+	"}",
+	"#endif",
 	"",
+	"void",
+	"d_hash(uchar *kb, int nbytes)", /* sets two 64-bit or 32-bit nrs, depending on WS */
+	"{	uint8_t  *bp;",
+	"#if WS>4",
+	"	uint64_t a = 0, b, c, n;",
+	"	const uint64_t *k = (uint64_t *) kb;",
+	"#else",
+	"	uint32_t a = 0, b, c, n;",
+	"	const uint32_t *k = (uint32_t *) kb;",
+	"#endif",
+	"	n = nbytes/WS;	/* nr of words */",
+	"	/* extend to multiple of words, if needed */",
+	"	a = WS - (nbytes %% WS);",
+	"	if (a > 0 && a < WS)",
+	"	{	n++;",
+	"		bp = kb + nbytes;",
+	"		switch (a) {",
+	"#if WS>4",
+	"		case 7: *bp++ = 0; /* fall thru */",
+	"		case 6: *bp++ = 0; /* fall thru */",
+	"		case 5: *bp++ = 0; /* fall thru */",
+	"		case 4: *bp++ = 0; /* fall thru */",
+	"#endif",
+	"		case 3: *bp++ = 0; /* fall thru */",
+	"		case 2: *bp++ = 0; /* fall thru */",
+	"		case 1: *bp   = 0;",
+	"		case 0: break;",
+	"	}	}",
+	"#if WS>4",
 	"	b = HASH_CONST[HASH_NR];",
-	"	while (len >= 3)",
+	"	c = 0x9e3779b97f4a7c13LL; /* arbitrary value */",
+	"	while (n >= 3)",
 	"	{	a += k[0];",
 	"		b += k[1];",
 	"		c += k[2];",
 	"		mix(a,b,c);",
-	"		k += 3; len -= 3;",
+	"		n -= 3;",
+	"		k += 3;",
 	"	}",
-	"	c += length;",
-	"	switch (len) {",
+	"	c += (((uint64_t) nbytes)<<3);",
+	"	switch (n) {",
 	"	case 2: b += k[1];",
 	"	case 1: a += k[0];",
+	"	case 0: break;",
 	"	}",
 	"	mix(a,b,c);",
-	"	j1 = c&nmask; j3 = a&7;",	/* 1st bit */
-	"	j2 = b&nmask; j4 = (a>>3)&7;",	/* 2nd bit */
-	"	K1 = c; K2 = b;",		/* no nmask */
+	"#else", /* 32 bit version: */
+	"	a = c = 0xdeadbeef + (n<<2);",
+	"	b = HASH_CONST[HASH_NR];",
+	"	while (n > 3)",
+	"	{	a += k[0];",
+	"		b += k[1];",
+	"		c += k[2];",
+	"		mix(a,b,c);",
+	"		n -= 3;",
+	"		k += 3;",
+	"	}",
+	"	switch (n) { ",
+	"	case 3: c += k[2];",
+	"	case 2: b += k[1];",
+	"	case 1: a += k[0];",
+	"		final(a,b,c);",
+	"	case 0: break;",
+	"	}",
+	"#endif",
+	"	j1_spin = c&nmask; j3_spin = a&7; /* 1st bit */",
+	"	j2_spin = b&nmask; j4_spin = (a>>3)&7; /* 2nd bit */",
+	"	K1 = c; K2 = b;",
 	"}",
+	"",
+	"#if defined(MURMUR) && (WS==8)",
+	"/* public-domain, 64-bit MurmurHash3, by Austin Appleby */",
+	"/*  https://code.google.com/p/smhasher/wiki/MurmurHash3 */",
 	"void",
-	"s_hash(uchar *cp, int om)",
-	"{	d_hash(cp, om);	/* sets K1 and K2 */",
+	"m_hash(uchar *v, int len)",
+	"{	uint8_t *bp, *data = (uint8_t*) v;",
+	"	int i, nblocks = len / 16;",
+	"",
+	"	uint64_t h1 = HASH_CONST[HASH_NR];",
+	"	uint64_t h2 = 0x9e3779b97f4a7c13LL;",
+	"",
+	"	uint64_t c1 = 0x87c37b91114253d5;",
+	"	uint64_t c2 = 0x4cf5ad432745937f;",
+	"",
+	"	uint64_t *blocks = (uint64_t *)(data);",
+	"",
+	"	/* guarantee a multiple of 16 bytes */",
+	"	i = 16 - (len %% 16);",
+	"	if (i > 0 && i < 16)",
+	"	{	nblocks++;",
+	"		bp = v + len;",
+	"		switch (i) {",
+	"		case 15: *bp++ = 0; /* fall thru */",
+	"		case 14: *bp++ = 0;",
+	"		case 13: *bp++ = 0;",
+	"		case 12: *bp++ = 0;",
+	"		case 11: *bp++ = 0;",
+	"		case 10: *bp++ = 0;",
+	"		case  9: *bp++ = 0;",
+	"		case  8: *bp++ = 0;",
+	"		case  7: *bp++ = 0;",
+	"		case  6: *bp++ = 0;",
+	"		case  5: *bp++ = 0;",
+	"		case  4: *bp++ = 0;",
+	"		case  3: *bp++ = 0;",
+	"		case  2: *bp++ = 0;",
+	"		case  1: *bp   = 0;",
+	"		case  0: break;",
+	"       }       }",
+	"",
+	"	for (i = 0; i < nblocks; i++)",
+	"	{	uint64_t k1 = blocks[i*2];",
+	"		uint64_t k2 = blocks[i*2+1];",
+	"",
+	"		k1 *= c1;",
+	"		k1 = (k1 << 31) | (k1 >> 33);",
+	"		k1 *= c2;",
+	"		h1 ^= k1;",
+	"",
+	"		h1 = (h1 << 27) | (h1 >> 37);",
+	"		h1 += h2;",
+	"		h1 = h1 * 5 + 0x52dce729;",
+	"",
+	"		k2 *= c2;",
+	"		k2 = (k2 << 33) | (k2 >> 31);",
+	"		k2 *= c1;",
+	"		h2 ^= k2;",
+	"",
+	"		h2 = (h2 << 31) | (h2 >> 33);",
+	"		h2 += h1;",
+	"		h2 = h2 * 5 + 0x38495ab5;",
+	"	}",
+	"",
+	"	uint8_t *tail = (uint8_t*)(data + (nblocks * 16));",
+	"",
+	"	uint64_t k1 = 0;",
+	"	uint64_t k2 = 0;",
+	"",
+	"	switch(len & 15) {",
+	"	case 15: k2 ^= ((uint64_t) tail[14]) << 48; break;",
+	"	case 14: k2 ^= ((uint64_t) tail[13]) << 40; break;",
+	"	case 13: k2 ^= ((uint64_t) tail[12]) << 32; break;",
+	"	case 12: k2 ^= ((uint64_t) tail[11]) << 24; break;",
+	"	case 11: k2 ^= ((uint64_t) tail[10]) << 16; break;",
+	"	case 10: k2 ^= ((uint64_t) tail[ 9]) << 8; break;",
+	"	case  9: k2 ^= ((uint64_t) tail[ 8]) << 0; break;",
+	"		 k2 *= c2;",
+	"		 k2 = (k2 << 33) | (k2 >> 31);",
+	"		 k2 *= c1;",
+	"		 h2 ^= k2; break;",
+	"	case  8: k1 ^= ((uint64_t) tail[7]) << 56; break;",
+	"	case  7: k1 ^= ((uint64_t) tail[6]) << 48; break;",
+	"	case  6: k1 ^= ((uint64_t) tail[5]) << 40; break;",
+	"	case  5: k1 ^= ((uint64_t) tail[4]) << 32; break;",
+	"	case  4: k1 ^= ((uint64_t) tail[3]) << 24; break;",
+	"	case  3: k1 ^= ((uint64_t) tail[2]) << 16; break;",
+	"	case  2: k1 ^= ((uint64_t) tail[1]) << 8; break;",
+	"	case  1: k1 ^= ((uint64_t) tail[0]) << 0; break;",
+	"		 k1 *= c1;",
+	"		 k1 = (k1 << 31) | (k1 >> 33);",
+	"		 k1 *= c2;",
+	"		 h1 ^= k1;",
+	"	};",
+	"",
+	"	h1 ^= len; h2 ^= len;",
+	"	h1 += h2;",
+	"	h2 += h1;",
+	"	h1 ^= h1 >> 33;",
+	"	h1 *= 0xff51afd7ed558ccd;",
+	"	h1 ^= h1 >> 33;",
+	"	h1 *= 0xc4ceb9fe1a85ec53;",
+	"	h1 ^= h1 >> 33;",
+	"	h2 ^= h2 >> 33;",
+	"	h2 *= 0xff51afd7ed558ccd;",
+	"	h2 ^= h2 >> 33;",
+	"	h2 *= 0xc4ceb9fe1a85ec53;",
+	"	h2 ^= h2 >> 33;",
+	"	h1 += h2;",
+	"	h2 += h1;",
+	"",
+	"	j1_spin = h1&nmask; j3_spin = (h1>>48)&7;",
+	"	j2_spin = h2&nmask; j4_spin = (h2>>48)&7;",
+	"	K1 = h1; K2 = h2;",
+	"}",
+	"#endif",
+	"",
+	"void",
+	"s_hash(uchar *cp, int om)",	/* uses either d_sfh (1x32bit), or d_hash (2x64bit) */
+	"{",				/* depending on ssize ie the -w parameter */
+	"	hasher(cp, om);		/* sets K1 */",
 	"#ifdef BITSTATE",
 	"	if (S_Tab == H_tab)",	/* state stack in bitstate search */
-	"		j1 = K1 %% omaxdepth;",
+	"		j1_spin = K1 %% omaxdepth;",
 	"	else",
-	"#endif", /* if (S_Tab != H_Tab) */
-	"		if (ssize < 8*WS)",
-	"			j1 = K1&mask;",
-	"		else",
-	"			j1 = K1;",
+	"#endif",
+	"	if (ssize < 8*WS)",
+	"		j1_spin = K1&mask;",
+	"	else",
+	"		j1_spin = K1;",
 	"}",
 	"#ifndef RANDSTOR",
 	"int *prerand;",
@@ -3138,10 +4989,11 @@
 	"void",
 	"inirand(void)",
 	"{	int i;",
-	"	srand(123);	/* fixed startpoint */",
+	"	srand(s_rand+HASH_NR);",	/* inirand */
 	"	prerand = (int *) emalloc((omaxdepth+3)*sizeof(int));",
 	"	for (i = 0; i < omaxdepth+3; i++)",
-	"		prerand[i] = rand();",
+	"	{	prerand[i] = rand();",
+	"	}",
 	"}",
 	"int",
 	"pan_rand(void)",
@@ -3150,28 +5002,271 @@
 	"}",
 	"#endif",
 	"",
+	"void",
+	"set_masks(void)",
+	"{",
+	"	if (WS == 4 && ssize >= 32)",
+	"	{	mask = 0xffffffff;",
+	"#ifdef BITSTATE",
+	"		switch (ssize) {",
+	"		case 34: nmask = (mask>>1); break;",
+	"		case 33: nmask = (mask>>2); break;",
+	"		default: nmask = (mask>>3); break;",
+	"		}",
+	"#else",
+	"		nmask = mask;",
+	"#endif",
+	"	} else if (WS == 8)",
+	"	{	mask = ((ONE_L<<ssize)-1);	/* hash init */",
+	"#ifdef BITSTATE",
+	"		nmask = mask>>3;",
+	"#else",
+	"		nmask = mask;",
+	"#endif",
+	"	} else if (WS != 4)",
+	"	{	fprintf(stderr, \"pan: wordsize %%ld not supported\\n\", (long int) WS);",
+	"		exit(1);",
+	"	} else	/* WS == 4 and ssize < 32 */",
+	"	{	mask = ((ONE_L<<ssize)-1);	/* hash init */",
+	"		nmask = (mask>>3);",
+	"	}",
+	"}",
+	"",
+	"#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)",
+	"#if NCORE>1",
+	"	#error cannot combine AUTO_RESIZE with NCORE>1",
+	"#endif",
+	"static long reclaim_size;",
+	"static char *reclaim_mem;",
+	"static H_el **N_tab;",
+	"void",
+	"reverse_capture(H_el *p)",
+	"{	if (!p) return;",
+	"	reverse_capture(p->nxt);",
+	"	/* last element of list moves first */",
+	"	/* to preserve list-order */",
+	"	j2_spin = p->m_K1;",
+	"	if (ssize < 8*WS) /* probably always true */",
+	"	{	j2_spin &= mask;",
+	"	}",
+	"	p->nxt = N_tab[j2_spin];",
+	"	N_tab[j2_spin] = p;",
+	"}",
+	"void",
+	"resize_hashtable(void)",
+	"{",
+	"#ifndef BFS_PAR",	/* ssize and mask/nmask are not in shared mem */
+	"	if (WS == 4 && ssize >= 27 - 1)",
+	"#endif",
+	"	{	return;	/* cannot increase further */",
+	"	}",
+	"",
+	"	ssize += 2; /* 4x size @htable ssize */",
+	"",
+	"	printf(\"pan: resizing hashtable to -w%%d.. \", ssize);",
+	"",
+	"	N_tab = (H_el **) emalloc((ONE_L<<ssize)*sizeof(H_el *));",
+	"	set_masks();	/* they changed */",
+	"",
+	"	for (j1_spin = 0; j1_spin < (ONE_L << (ssize - 2)); j1_spin++)",
+	"	{	reverse_capture(H_tab[j1_spin]);",
+	"	}",
+	"	reclaim_mem = (char *) H_tab;",
+	"	reclaim_size = (ONE_L << (ssize - 2));",
+	"	H_tab = N_tab;",
+	"",
+	"	printf(\" done\\n\");",
+	"}",
+	"#endif",
+	"#if defined(ZAPH) && defined(BITSTATE)",
+	"void",
+	"zap_hashtable(void)",
+	"{	cpu_printf(\"pan: resetting hashtable\\n\");",
+	"	if (udmem)",
+	"	{	memset(SS, 0, udmem);",
+	"	} else",
+	"	{	memset(SS, 0, ONE_L<<(ssize-3));",
+	"	}",
+	"}",
+	"#endif",
+	"",
+	"#if NCLAIMS>1",
 	"int",
+	"find_claim(char *s)",
+	"{	int i, j;",
+	"	for (i = 0; strncmp(procname[i], \":np_:\", 5) != 0; i++)",
+	"	{	if (strcmp(s, procname[i]) == 0)",
+	"		{	for (j = 0; j < NCLAIMS; j++)",
+	"			{	if (spin_c_typ[j] == i)",
+	"				{	return j;",
+	"			}	}",
+	"			break;",
+	"	}	}",
+	"	printf(\"pan: error: cannot find claim '%%s'\\n\", s);",
+	"	exit(1);",
+	"	return -1; /* unreachable */",
+	"}",
+	"#endif",
+	"",
+	"#if defined(BFS_PAR) && defined(BFS_SEP_HASH)",
+	"int	/* to avoid having to include <math.h> and compile with -lm */",
+	"blog2(int n)	/* n >= 1 */",
+	"{	int m=1, r=2;",
+	"	if (n == 1) { return 0; }",
+	"	if (n == 2) { return 1; }",
+	"	while (n > r) { m++; r *= 2; }",
+	"	return m;",
+	"}",
+	"#endif",
+	"",
+	"uint pp[33];",
+	"",
+	"uint ",
+	"mul(uint a, uint b, uint p)",
+	"{	int c = 0;",
+	"	while (a)",
+	"	{	if (a&1)",
+	"		{	a ^= 1;",
+	"			c ^= b;",
+	"		}",
+	"		a = (a>>1);",
+	"		if (b & 0x80000000)",
+	"		{	b += b;",
+	"			b ^= p;",
+	"		} else",
+	"		{	b += b;",
+	"	}	}",
+	"	return c;",
+	"}",
+	"",
+	"uint",
+	"ppow(int n, uint p)",
+	"{	uint t = 1; int i;",
+	"	for (i = 0; i < 32; i++)",
+	"	{	if (n & (1<<i))",
+	"		{	t = mul(t, pp[i], p);",
+	"	}	}",
+	"	return t;",
+	"}",
+	"",
+	"void",
+	"hashgen(void)	/* courtesy Jim Reeds, 1995 */",
+	"{	uint x, y, p; int i, cnt;",
+	"	int ff[5] = { 3, 5, 17, 257, 65537 };",
+	"	int nn[5];",
+	"",
+	"	srand(s_rand);	/* was: srandom(s_rand) */",
+	"	nn[0] = ff[1]*ff[2]*ff[3]*ff[4];",
+	"	nn[1] = ff[0]*ff[2]*ff[3]*ff[4];",
+	"	nn[2] = ff[0]*ff[1]*ff[3]*ff[4];",
+	"	nn[3] = ff[0]*ff[1]*ff[2]*ff[4];",
+	"	nn[4] = ff[0]*ff[1]*ff[2]*ff[3];",
+	"	for (cnt = 0; cnt < 5000; cnt++)",
+	"	{	x = 2;",
+	"		p = ((rand()<<13)^rand()) | 1; /* used random() before */",
+	"		pp[0] = x;",
+	"		for (i = 0; i < 32; i++)",
+	"		{	pp[i+1] = mul(pp[i], pp[i], p);",
+	"		}",
+	"		if (pp[32] == x)",
+	"		{	for (i = 0; i < 5; i++)",
+	"			{	y = ppow(nn[i], p);",
+	"				if (y == 1)",
+	"				{	break;",
+	"			}	}",
+	"			if (y != 1)",
+	"			{	HASH_CONST[0] = p;", /* 32 bit */
+	"				if (verbose)",
+	"				{	printf(\"polynomial: 0x%%.8x (%%d tries)\\n\",",
+	"						p, cnt);",
+	"				}",
+	"				return;", /* success */
+	"	}	}	}",
+	"	fprintf(efd, \"pan: could not find a polynomial in %%d tries\\n\", cnt);",
+	"	fprintf(efd, \"pan: try a different seed with -RSn\\n\");",
+	"	exit(1);",
+	"}",
+	"",
+	"int",
 	"main(int argc, char *argv[])",
 	"{	void to_compile(void);\n",
 	"	efd = stderr;	/* default */",
+	"#if defined(BFS_PAR) && defined(BFS_SEP_HASH)",
+	"	uchar used_w = 0;",
+	"#endif",
+	"	if (G_long != sizeof(long)",
+	"	||  G_int  != sizeof(int))",
+	"	{	printf(\"spin: error, the version of spin \");",
+	"		printf(\"that generated this pan.c assumed a different \");",
+	"		printf(\"wordsize (%%d iso %%d)\\n\", G_long, (int) sizeof(long));",
+	"		exit(1);",
+	"	}",
+	"",
+	"#if defined(T_RAND) && (T_RAND>0)",
+	"	s_rand = T_RAND;", /* so that -RS can override */
+	"#elif defined(P_RAND) && (P_RAND>0)",
+	"	s_rand = P_RAND;",
+	"#endif",
+	"",
+	"#ifdef PUTPID",
+	"	{	char *ptr = strrchr(argv[0], '/');",
+	"		if (ptr == NULL)",
+	"		{	ptr = argv[0];",
+	"		} else",
+	"		{	ptr++;",
+	"		}",
+	"		progname = emalloc(strlen(ptr));",
+	"		strcpy(progname, ptr);",
+	"		/* printf(\"progname: %%s\\n\", progname); */",
+	"	}",
+	"#endif",
+	"",
 	"#ifdef BITSTATE",
-	"	bstore = bstore_reg; /* default */",
+	"	b_store = bstore_reg; /* default */",
 	"#endif",
+	"#if NCORE>1",
+	"	{	int i, j;",
+	"		strcpy(o_cmdline, \"\");",
+	"		for (j = 1; j < argc; j++)",
+	"		{	strcat(o_cmdline, argv[j]);",
+	"			strcat(o_cmdline, \" \");",
+	"		}",
+	"		/* printf(\"Command Line: %%s\\n\", o_cmdline); */",
+	"		if (strlen(o_cmdline) >= sizeof(o_cmdline))",
+	"		{	Uerror(\"option list too long\");",
+	"	}	}",
+	"#endif",
 	"	while (argc > 1 && argv[1][0] == '-')",
 	"	{	switch (argv[1][1]) {",
 	"#ifndef SAFETY",
-		"#ifdef NP",
-	"		case 'a': fprintf(efd, \"error: -a disabled\");",
-	"			  usage(efd); break;",
-		"#else",
+	"	#ifdef NP",
+	"		case 'a': fprintf(efd, \"warning: -a is disabled by -DNP, ignored\");",
+	"			  break;",
+	"	#else",
 	"		case 'a': a_cycles = 1; break;",
-		"#endif",
+	"	#endif",
+	"#else",
+	"	#if defined(BFS_PAR) && defined(L_BOUND)",
+	"		case 'a': if (isdigit(argv[1][2]))",
+	"			  {	L_bound = atoi(&argv[1][2]);",
+	"				if (L_bound < 1 || L_bound > 255)",
+	"				{	printf(\"usage: -aN with 0<N<256\\n\");",
+	"					exit(1);",
+	"			  }	}",
+	"			  break;",
+	"	#endif",
 	"#endif",
 	"		case 'A': noasserts = 1; break;",
 	"		case 'b': bounded = 1; break;",
-	"		case 'c': upto  = atoi(&argv[1][2]); break;",
+	"#ifdef HAS_CODE",
+	"	#if HAS_CODE>0",
+	"		case 'C': coltrace = 1; goto samething;",
+	"	#endif",
+	"#endif",
+	"		case 'c': upto = atoi(&argv[1][2]); break;",
+	"		case 'D': dodot++; state_tables++; break;",
 	"		case 'd': state_tables++; break;",
-	"		case 'e': every_error = 1; Nr_Trails = 1; break;",
+	"		case 'e': every_error = 1; upto = 0; Nr_Trails = 1; break;",
 	"		case 'E': noends = 1; break;",
 	"#ifdef SC",
 	"		case 'F': if (strlen(argv[1]) > 2)",
@@ -3181,23 +5276,57 @@
 	"#if !defined(SAFETY) && !defined(NOFAIR)",
 	"		case 'f': fairness = 1; break;",
 	"#endif",
-	"		case 'h': if (!argv[1][2]) usage(efd); else",
-	"			  HASH_NR = atoi(&argv[1][2])%%33; break;",
+	"#ifdef HAS_CODE",
+	"	#if HAS_CODE>0",
+	"		case 'g': gui = 1; goto samething;",
+	"	#endif",
+	"#endif",
+	"		case 'h':",
+	"			  if (strncmp(&argv[1][1], \"hash\", strlen(\"hash\")) == 0)",
+	"			  {	do_hashgen = 1;",
+	"				break;",
+	"			  }",
+	"			  if (!argv[1][2] || !isdigit((int) argv[1][2]))",
+	"			  {	usage(efd);	/* exits */",
+	"			  }",
+	"			  HASH_NR = atoi(&argv[1][2])%%(sizeof(HASH_CONST)/sizeof(uint));",
+	"			  break;",
 	"		case 'I': iterative = 2; every_error = 1; break;",
-	"		case 'i': iterative = 1; every_error = 1; break;",
+	"		case 'i':",
+	"			  if (strncmp(&argv[1][1], \"i_reverse\", strlen(\"i_reverse\")) == 0)",
+	"			  {	reversing |= 1;",
+	"			  } else",
+	"			  {	iterative   = 1;",
+	"			  	every_error = 1;",
+	"			  }",
+	"			  break;",
 	"		case 'J': like_java = 1; break; /* Klaus Havelund */",
 	"#ifdef BITSTATE",
 	"		case 'k': hfns = atoi(&argv[1][2]); break;",
 	"#endif",
+	"#ifdef BCS",
+	"		case 'L':",
+	"			sched_max = atoi(&argv[1][2]);",
+	"			if (sched_max > 255)	/* stored as one byte */",
+	"			{	fprintf(efd, \"warning: using max bound (255)\\n\");",
+	"				sched_max = 255;",
+	"			}",
+	"	#ifndef NOREDUCE",
+	"			if (sched_max == 0)",
+	"			{	fprintf(efd, \"warning: with (default) bound -L0, \");",
+	"				fprintf(efd, \"using -DNOREDUCE performs better\\n\");",
+	"			}",
+	"	#endif",
+	"			break;",
+	"#endif",
 	"#ifndef SAFETY",
 		"#ifdef NP",
 	"		case 'l': a_cycles = 1; break;",
 		"#else",
-	"		case 'l': fprintf(efd, \"error: -l disabled\");",
+	"		case 'l': fprintf(efd, \"error: -l not available (compile with -DNP)\");",
 	"			  usage(efd); break;",
 		"#endif",
 	"#endif",
-#ifndef POWOW
 	"#ifdef BITSTATE",
 	"		case 'M': udmem = atoi(&argv[1][2]); break;",
 	"		case 'G': udmem = atoi(&argv[1][2]); udmem *= 1024; break;",
@@ -3206,66 +5335,344 @@
 	"			  fprintf(stderr, \"-M and -G affect only -DBITSTATE\\n\");",
 	"			  break;",
 	"#endif",
-#endif
 	"		case 'm': maxdepth = atoi(&argv[1][2]); break;",
+	"#ifndef NOCLAIM",
+	"		case 'N':",
+	"	#if NCLAIMS>1",
+	"			  if (isdigit((int)argv[1][2]))",
+	"			  {	whichclaim = atoi(&argv[1][2]);",
+	"			  } else if (isalpha((int)argv[1][2]))",
+	"			  {     claimname = &argv[1][2];",
+	"			  } else if (argc > 2 && argv[2][0] != '-') /* check next arg */",
+	"			  {	claimname = argv[2];",
+	"				argc--; argv++; /* skip next arg */",
+	"			  }",
+	"	#else",
+	"		#if NCLAIMS==1",
+	"			  fprintf(stderr, \"warning: only one claim defined, -N ignored\\n\");",
+	"		#else",
+	"			  fprintf(stderr, \"warning: no claims defined, -N ignored\\n\");",
+	"		#endif",
+	"			  if (!isdigit((int)argv[1][2]) && argc > 2 && argv[2][0] != '-')",
+	"			  {	argc--; argv++;",
+	"			  }",
+	"	#endif",
+	"#endif",
+	"			  break;\n",
 	"		case 'n': no_rck = 1; break;",
+	"",
+	"		case 'P':",
+	"			  if (!readtrail",
+	"			  &&  isdigit((int) argv[1][2]))", /* was argv[1][2] == '_' */
+	"			  {	int x = atoi(&argv[1][2]);",
+	"				if (x != 0 && x != 1)",
+	"				{	fprintf(efd, \"pan: bad option -P[01], ignored\\n\");",
+	"				}",
+	"				if (x == 0)",
+	"				{	reversing &= ~1;",
+	"					break;",
+	"				}",
+	"				if (x == 1)",
+	"				{	reversing |= 1;",
+	"					break;",
+	"				}",
+	"				if (verbose)",
+	"				fprintf(efd, \"pan: reversed *active* process creation %%s\\n\",",
+	"					reversing&1?\"on\":\"off\");",
+	"				break;",
+	"			  } /* else */",
+	"#ifdef HAS_CODE",
+	"	#if HAS_CODE>0",
+	"			  readtrail = 1; onlyproc = atoi(&argv[1][2]);",
+	"			  if (argc > 2 && argv[2][0] != '-') /* check next arg */",
+	"			  {	trailfilename = argv[2];",
+	"				argc--; argv++; /* skip next arg */",
+	"			  }",
+	"	#else",
+	"			  fprintf(efd, \"pan: option -P not recognized, ignored\\n\");",
+	"	#endif",
+	"#else",
+	"			  fprintf(efd, \"pan: option -P not recognized, ignored\\n\");",
+	"#endif",
+	"			  break;",
+	"",
+	"		case 'p':",
+	"	#if !defined(BFS) && !defined(BFS_PAR)",
+	"	#ifdef PERMUTED",
+	"			  if (strncmp(&argv[1][1], \"p_normal\", strlen(\"p_normal\")) == 0)",
+	"			  {	reversing &= ~2;",
+	"				break;",
+	"			  }",
+	"			  reversing |=2;",
+	"			  if (strncmp(&argv[1][1], \"p_permute\", strlen(\"p_permute\")) == 0)",
+	"			  {	p_reorder = set_permuted;",
+	"				break;",
+	"			  }",
+	"			  if (strncmp(&argv[1][1], \"p_rotate\", strlen(\"p_rotate\")) == 0)",
+	"			  {	p_reorder = set_rotated;",
+	"				if (isdigit((int) argv[1][9]))",
+	"				{	p_rotate = atoi(&argv[1][9]);",
+	"				} else",
+	"				{	p_rotate = 1;",
+	"				}",
+	"				break;",
+	"			  }",
+	"			  if (strncmp(&argv[1][1], \"p_randrot\", strlen(\"p_randrot\")) == 0)",
+	"			  {	p_reorder = set_randrot;",
+	"				break;",
+	"			  }",
+	"			  if (strncmp(&argv[1][1], \"p_reverse\", strlen(\"p_reverse\")) == 0)",
+	"			  {	p_reorder = set_reversed;",
+	"				break;",
+	"			  }",
+	"	#else",
+	"			  if (strncmp(&argv[1][1], \"p_permute\", strlen(\"p_permute\")) == 0",
+	"			  ||  strncmp(&argv[1][1], \"p_rotate\",  strlen(\"p_rotate\")) == 0",
+	"			  ||  strncmp(&argv[1][1], \"p_randrot\",  strlen(\"p_randrot\")) == 0",
+	"			  ||  strncmp(&argv[1][1], \"p_reverse\", strlen(\"p_reverse\")) == 0)",
+	"			  {	fprintf(efd, \"option %%s required compilation with -DPERMUTED\\n\",",
+	"					argv[1]);",
+	"				exit(1);",
+	"			  }",
+	"	#endif",
+	"	#endif",
 	"#ifdef SVDUMP",
-	"		case 'p': vprefix = atoi(&argv[1][2]); break;",
+	"			  vprefix = atoi(&argv[1][2]);",
+	"#else",
+	"			  fprintf(efd, \"invalid option '%%s' -- ignored\\n\", argv[1]);",
 	"#endif",
+	"			  break;",
+	"#if NCORE==1",
+	"		case 'Q': quota = (double) 60.0 * (double) atoi(&argv[1][2]);",
+	"	#ifndef FREQ",
+	"			  freq /= 10.; /* for better resolution */",
+	"	#endif",
+	"			  break;",
+	"#endif",
 	"		case 'q': strict = 1; break;",
-	"#ifdef HAS_CODE",
+	"		case 'R':",
+	"			if (argv[1][2] == 'S') /* e.g., -RS76842 */",
+	"			{	s_rand = atoi(&argv[1][3]);", /* RS */
+	"				break;",
+	"			}",
+	"#ifdef BITSTATE",
+	"			Nrun = atoi(&argv[1][2]);",
+	"			if (Nrun > 100)",
+	"			{	Nrun = 100;",
+	"			} else if (Nrun < 1)",
+	"			{	Nrun = 1;",
+	"			}",
+	"#else",
+	"			usage(efd);",
+	"			break;",
+	"#endif",
 	"		case 'r':",
+	"			  if (strncmp(&argv[1][1], \"rhash\", strlen(\"rhash\")) == 0)",
+	"			  {	if (s_rand == 12345)	/* default seed */",
+	"				{",
+	"#if defined(WIN32) || defined(WIN64)",
+	"					s_rand = (uint) clock();",
+	"#else",
+	"					struct tms dummy_tm;",
+	"					s_rand = (uint) times(&dummy_tm);",
+	"#endif",
+	"				}",
+	"				srand(s_rand++);",
+	"	#ifdef PERMUTED",
+	"			  	do_hashgen = 1;",	/* + randomize p_rotate, p_reverse, p_permute */
+	"			  	switch (rand()%%5) {",
+	"				case 0:	p_reorder = set_permuted;",
+	"					reversing |=2;",
+	"					break;",
+	"			  	case 1:	p_reorder = set_reversed;",
+	"					reversing |=2;",
+	"					break;",
+	"					/* fully randomize p_rotate: */",
+	"				case 2:	p_reorder = set_randrot;",
+	"					reversing |=2;",
+	"					break;",
+	"					/* choose once, then keep p_rotate fixed: */",
+	"				case 3: p_reorder = set_rotated;",
+	"					p_rotate = rand()%%3;",
+	"					reversing |=2;",
+	"					break;",
+	"				default: /* standard search */ break;",
+	"				}",
+	"				if (rand()%%2 == 0)",
+	"			 	{	t_reverse = 1;",
+	"				}",
+	"				break;",
+	"	#else",
+	"				fprintf(efd, \"option -rhash requires compilation with -DPERMUTED\\n\");",
+	"				exit(1);",
+	"	#endif",
+	"			  }",
+	"#if defined(HAS_CODE) && HAS_CODE>0",
 	"samething:		  readtrail = 1;",
-	"			  if (isdigit(argv[1][2]))",
+	"			  if (isdigit((int)argv[1][2]))",
 	"				whichtrail = atoi(&argv[1][2]);",
+	"			  else if (argc > 2 && argv[2][0] != '-') /* check next arg */",
+	"			  {	trailfilename = argv[2];",
+	"				argc--; argv++; /* skip next arg */",
+	"			  }",
 	"			  break;",
-	"		case 'P': readtrail = 1; onlyproc = atoi(&argv[1][2]); break;",
-	"		case 'C': coltrace = 1; goto samething;",
-	"		case 'g': gui = 1; goto samething;",
-	"		case 'S': silent = 1; break;",
+	"		case 'S': silent = 1; goto samething;",
+	"#else",
+	"			  fprintf(efd, \"options -r is for models with embedded C code\\n\");",
+	"			  break;",
 	"#endif",
-	"		case 'R': Nrun = atoi(&argv[1][2]); break;",
-	"#ifdef BITSTATE",
-	"		case 's': hfns = 1; break;",
-	"#endif",
-	"		case 'T': TMODE = 0444; break;",
-	"		case 't': if (argv[1][2]) tprefix = &argv[1][2]; break;",
-	"		case 'V': printf(\"Generated by %%s\\n\", Version);",
-	"			  to_compile(); pan_exit(0); break;",
-	"		case 'v': verbose = 1; break;",
-	"		case 'w': ssize = atoi(&argv[1][2]); break;",
+	"		case 'T':",
+	"			  if (isdigit((int) argv[1][2]))", /* was argv[1][2] == '_' */
+	"			  {	t_reverse = atoi(&argv[1][2]);",
+	"				if (verbose)",
+	"				printf(\"pan: reverse transition ordering %%s\\n\",",
+	"					t_reverse?\"on\":\"off\");",
+	"				break;",
+	"			  }",
+	"			  TMODE = 0444;",
+	"			  break;",
+	"		case 't':",
+	"			  if (strncmp(&argv[1][1], \"t_reverse\", strlen(\"t_reverse\")) == 0)",
+	"			  {	t_reverse = 1;",
+	"				break;",
+	"			  }", /* i.e., a trail prefix cannot be '_reverse' */
+	"			  if (argv[1][2])",
+	"			  {	tprefix = &argv[1][2];",
+	"			  }",
+	"			  break;",
+	"		case 'u':",
+	"	#ifdef BFS_PAR",
+	"			  ncores = atoi(&argv[1][2]);",
+	"	#endif",
+	"			  break;",
+	"		case 'V': start_timer(); printf(\"Generated by %%s\\n\", SpinVersion);",
+	"			  to_compile(); pan_exit(2); break;",
+	"		case 'v': verbose++; break;",
+	"		case 'w': ssize = atoi(&argv[1][2]);",
+	"	#if defined(BFS_PAR) && defined(BFS_SEP_HASH)",
+	"			  used_w = 1;",
+	"	#endif",
+	"			  break;",
 	"		case 'Y': signoff = 1; break;",
 	"		case 'X': efd = stdout; break;",
-	"		default : fprintf(efd, \"saw option -%%c\\n\", argv[1][1]); usage(efd); break;",
+	"		case 'x': exclusive = 1; break;",
+	"	#if NCORE>1",
+	"		/* -B ip is passthru to proxy of remote ip address: */",
+	"		case 'B': argc--; argv++; break;",
+	"		case 'Q': worker_pids[0] = atoi(&argv[1][2]); break;",
+	"		/* -Un means that the nth worker should be instantiated as a proxy */",
+	"		case 'U': proxy_pid = atoi(&argv[1][2]); break;",
+	"		/* -W means this copy is started by a cluster-server as a remote */",
+	"		/* this flag is passed to ./pan_proxy, which interprets it */",
+	"		case 'W': remote_party++; break;",
+	"		case 'Z': core_id = atoi(&argv[1][2]);",
+	"			  if (verbose)",
+	"			  { printf(\"cpu%%d: pid %%d parent %%d\\n\",",
+	"				core_id, getpid(), worker_pids[0]);",
+	"			  }",
+	"			  break;",
+	"		case 'z': z_handoff = atoi(&argv[1][2]); break;",
+	"	#else",
+	"		case 'z': break; /* ignored for single-core */",
+	"	#endif",
+	"		default : fprintf(efd, \"saw option -%%c\\n\",",
+	"				argv[1][1]); usage(efd); break;",
 	"		}",
 	"		argc--; argv++;",
 	"	}",
+	"#if defined(BFS_PAR) && defined(BFS_SEP_HASH)",
+	"	if (used_w == 0)",
+	"	{	if (ncores == 0) /* all cores used, by default */",
+	"		{	ssize -= blog2(BFS_MAXPROCS - 1);",
+	"		} else",
+	"		{	ssize -= blog2(ncores);",
+	"	}	}",
+	"#endif",
+	"	if (do_hashgen)",
+	"	{	hashgen();", /* placed here so that -RSn can appear after -hash */
+	"	}",
+	"#ifndef SAFETY",
+	"	if (fairness && !a_cycles)",
+	"	{	fprintf(efd, \"error: -f requires the use of -a or -l\\n\");", 
+	"		usage(efd);",
+	"	}",
+	"	#if ACCEPT_LAB==0",
+	"	if (a_cycles)",
+	"	{	fprintf(efd, \"warning: no accept labels are defined, \");",
+	"		fprintf(efd, \"so option -a has no effect (ignored)\\n\");",
+	"		a_cycles = 0;",
+	"	}",
+	"	#endif",
+	"#endif",
+	"",
+	"#ifdef BFS_PAR",
+	"	uerror = bfs_uerror;",
+	"	Uerror = bfs_Uerror;",
+	"#else",
+	"	uerror = dfs_uerror;",
+	"	Uerror = dfs_Uerror;",
+	"#endif",
+	"	if (ssize <= 32)	/* 6.2.0 */",
+	"	{	hasher = d_sfh;",
+	"#if !defined(BITSTATE) && defined(USE_TDH)",
+	"		o_hash = o_hash32;",
+	"#endif",
+	"	} else",
+	"	{	hasher = d_hash;",
+	"#if !defined(BITSTATE) && defined(USE_TDH)",
+	"		o_hash = o_hash64;",
+	"#endif",
+	"	}",
 	"	if (iterative && TMODE != 0666)",
 	"	{	TMODE = 0666;",
 	"		fprintf(efd, \"warning: -T ignored when -i or -I is used\\n\");",
 	"	}",
 	"#if defined(WIN32) || defined(WIN64)",
+	"	#ifndef _S_IWRITE",
+	"		#define	S_IWRITE 0000200  /* write permission, owner */",
+	"	#endif",
+	"	#ifndef _S_IREAD",
+	"		#define	S_IREAD  0000400  /* read permission, owner */",
+	"	#endif",
 	"	if (TMODE == 0666)",
-	"		TMODE = _S_IWRITE | _S_IREAD;",
+	"		TMODE = S_IWRITE | S_IREAD;",
 	"	else",
-	"		TMODE = _S_IREAD;",
+	"		TMODE = S_IREAD;",
 	"#endif",
-	"#ifdef OHASH",
-	"	fprintf(efd, \"warning: -DOHASH no longer supported (directive ignored)\\n\");",
+	"#if NCORE>1",
+	"	store_proxy_pid = proxy_pid; /* for checks in mem_file() and someone_crashed() */",
+	"	if (core_id != 0) { proxy_pid = 0; }",
+	"	#ifndef SEP_STATE",
+	"	if (core_id == 0 && a_cycles)",
+	"	{	fprintf(efd, \"hint: this search may be more efficient \");",
+	"		fprintf(efd, \"if pan.c is compiled -DSEP_STATE\\n\");",
+	"	}",
+	"	#endif",
+	"	if (z_handoff < 0)",
+	"	{	z_handoff =  20; /* conservative default - for non-liveness checks */",
+	"	}",
+	"#if defined(NGQ) || defined(LWQ_FIXED)",
+	"	LWQ_SIZE = (double) (128.*1048576.);",
+	"#else",
+	"	LWQ_SIZE = (double) ( z_handoff + 2.) * (double) sizeof(SM_frame);",
+		/* the added margin of +2 is not really necessary */
 	"#endif",
-	"#ifdef JHASH",
-	"	fprintf(efd, \"warning: -DJHASH no longer supported (directive ignored)\\n\");",
+	"	#if NCORE>2",
+	"	if (a_cycles)",
+	"	{	fprintf(efd, \"warning: the intended nr of cores to be used in liveness mode is 2\\n\");",
+	"		#ifndef SEP_STATE",
+	"		fprintf(efd, \"warning: without -DSEP_STATE there is no guarantee that all liveness violations are found\\n\");",
+	"		#endif",
+	"	}",	/* it still works though, the later cores get states from the global q */
+	"	#endif",
+	"	#ifdef HAS_HIDDEN",
+	"	#error cannot use hidden variables when compiling multi-core",
+	"	#endif",
 	"#endif",
-	"#ifdef HYBRID_HASH",
-	"	fprintf(efd, \"warning: -DHYBRID_HASH no longer supported (directive ignored)\\n\");",
+	"#if defined(T_RAND) && defined(ELSE_IN_GUARD)",
+	"	#error cannot hide 'else' as guard in d_step, when using -DT_RAND",
 	"#endif",
-	"#ifdef NOCOVEST",
-	"	fprintf(efd, \"warning: -DNOCOVEST no longer supported (directive ignored)\\n\");",
-	"#endif",
 	"#ifdef BITSTATE",
-	"#ifdef BCOMP",
-	"	fprintf(efd, \"warning: -DBCOMP no longer supported (directive ignored)\\n\");",
-	"#endif",
 	"	if (hfns <= 0)",
 	"	{	hfns = 1;",
 	"		fprintf(efd, \"warning: using -k%%d as minimal usable value\\n\", hfns);",
@@ -3278,7 +5685,7 @@
 	"		fprintf(efd, \"warning: using -w%%d as max usable value\\n\", ssize);",
 	"/*",
 	" *	-w35 would not work: 35-3 = 32 but 1^31 is the largest",
-	" *	power of 2 that can be represented in an unsigned long",
+	" *	power of 2 that can be represented in an ulong",
 	" */",
 	"	}",
 	"#else",
@@ -3297,8 +5704,8 @@
 	"	hiwater = HHH = maxdepth-10;",
 	"	DDD = HHH/2;",
 	"	if (!stackfile)",
-	"	{	stackfile = (char *) emalloc(strlen(Source)+4+1);",
-	"		sprintf(stackfile, \"%%s._s_\", Source);",
+	"	{	stackfile = (char *) emalloc(strlen(PanSource)+4+1);",
+	"		sprintf(stackfile, \"%%s._s_\", PanSource);",
 	"	}",
 	"	if (iterative)",
 	"	{	fprintf(efd, \"error: cannot use -i or -I with -DSC\\n\");",
@@ -3307,8 +5714,7 @@
 	"#endif",
 
 	"#if (defined(R_XPT) || defined(W_XPT)) && !defined(MA)",
-	"	fprintf(efd, \"error: -D?_XPT requires -DMA\\n\");",
-	"	exit(1);",
+	"	#warning -DR_XPT and -DW_XPT assume -DMA (ignored)",
 	"#endif",
 
 	"	if (iterative && a_cycles)",
@@ -3315,61 +5721,90 @@
 	"	fprintf(efd, \"warning: -i or -I work for safety properties only\\n\");",
 
 	"#ifdef BFS",
-	"#if defined(SC)",
-	"	fprintf(efd, \"error: -DBFS not compatible with -DSC\\n\");",
-	"	exit(1);",
+	"	#ifdef SC",
+	"		#error -DBFS not compatible with -DSC",
+	"	#endif",
+	"	#ifdef HAS_LAST",
+	"		#error -DBFS not compatible with _last",
+	"	#endif",
+	"	#ifdef HAS_STACK",
+	"		#error cannot use c_track UnMatched with BFS",
+	"	#endif",
+	"	#ifdef BCS",
+	"		#error -DBFS not compatible with -DBCS",
+	"	#endif",
+	"	#ifdef REACH",
+	"		#warning -DREACH is redundant when -DBFS is used",
+	"	#endif",
 	"#endif",
-	"#if defined(HAS_LAST)",
-	"	fprintf(efd, \"error: -DBFS not compatible with _last\\n\");",
-	"	exit(1);",
+
+	"#ifdef TRIX",
+	"	#ifdef BITSTATE",
+	"		#error cannot combine -DTRIX and -DBITSTATE",
+	"	#endif",
+	"	#ifdef COLLAPSE",
+	"		#error cannot combine -DTRIX and -DCOLLAPSE",
+	"	#endif",
+	"	#ifdef MA",
+	"		#error cannot combine -DTRIX and -DMA",
+	"	#endif",
+	"	#if defined(BFS_PAR) && defined(BFS_SEP_HEAP)",
+	"		#error cannot combined -DBFS_SEP_HEAP with -DTRIX",
+	"	#endif",
 	"#endif",
-	"#if defined(REACH)",
-	"	fprintf(efd, \"warning: -DREACH redundant when -DBFS is used\\n\");",
+
+	"#ifdef BFS_PAR",
+	"	#ifdef NP",
+	"	#error cannot combine -DBFS_PAR and -DNP",
+	"	#undef NP",
+	"	#endif",
 	"#endif",
-	"#if defined(HAS_STACK)",
-	"	fprintf(efd, \"error: cannot use UnMatched qualifier on c_track with BFS\\n\");",
-	"	exit(1);",
+
+	"#ifdef NOCLAIM",
+	"	#ifdef NP",
+	"	#warning using -DNP overrides -DNOCLAIM",
+	"	#undef NOCLAIM",
+	"	#endif",
 	"#endif",
+
+	"#ifdef BCS",
+	"	#ifdef P_RAND",
+	"		#error cannot combine -DBCS and -DP_RAND",
+	"	#endif",
+	"	#ifdef BFS",
+	"		#error cannot combine -DBCS and -DBFS",
+	"	#endif",
 	"#endif",
 
 	"#if defined(MERGED) && defined(PEG)",
-	"	fprintf(efd, \"error: to allow -DPEG use: spin -o3 -a %%s\\n\", Source);",
-	"	fprintf(efd, \"       to turn off transition merge optimization\\n\");",
-	"	pan_exit(1);",
+	"	#error to use -DPEG use: spin -o3 -a",
 	"#endif",
-	"#ifdef HC",
-		"#ifdef NOCOMP",
-	"	fprintf(efd, \"error: cannot combine -DHC and -DNOCOMP\\n\");",
-	"	pan_exit(1);",
-		"#endif",
-		"#ifdef BITSTATE",
-	"	fprintf(efd, \"error: cannot combine -DHC and -DBITSTATE\\n\");",
-	"	pan_exit(1);",
-		"#endif",
+	"#if defined(HC) && !defined(BFS_PAR)",
+	"	#ifdef NOCOMP",
+	"		#error cannot combine -DHC and -DNOCOMP",
+	"	#endif",
+	"	#ifdef BITSTATE",
+	"		#error cannot combine -DHC and -DBITSTATE",
+	"	#endif",
 	"#endif",
 	"#if defined(SAFETY) && defined(NP)",
-	"	fprintf(efd, \"error: cannot combine -DNP and -DSAFETY\\n\");",
-	"	pan_exit(1);",
+	"	#error cannot combine -DNP and -DBFS or -DSAFETY",
 	"#endif",
 	"#ifdef MA",
-	"#ifdef BITSTATE",
-	"	fprintf(efd, \"error: cannot combine -DMA and -DBITSTATE\\n\");",
-	"	pan_exit(1);",
+	"	#ifdef BITSTATE",
+	"		#error cannot combine -DMA and -DBITSTATE",
+	"	#endif",
+	"	#if MA <= 0",
+	"		#error usage: -DMA=N with N > 0 and N < VECTORSZ",
+	"	#endif",
 	"#endif",
-	"	if (MA <= 0)",
-	"	{	fprintf(efd, \"usage: -DMA=N with N > 0 and < VECTORSZ\\n\");",
-	"		pan_exit(1);",
-	"	}",
-	"#endif",
 	"#ifdef COLLAPSE",
-		"#if defined(BITSTATE)",
-	"	fprintf(efd, \"error: cannot combine -DBITSTATE and -DCOLLAPSE\\n\");",
-	"	pan_exit(1);",
-		"#endif",
-		"#if defined(NOCOMP)",
-	"	fprintf(efd, \"error: cannot combine -DNOCOMP and -DCOLLAPSE\\n\");",
-	"	pan_exit(1);",
-		"#endif",
+	"	#ifdef BITSTATE",
+	"		#error cannot combine -DBITSTATE and -DCOLLAPSE",
+	"	#endif",
+	"	#ifdef NOCOMP",
+	"		#error cannot combine -DCOLLAPSE and -DNOCOMP",
+	"	#endif",
 	"#endif",
 	"	if (maxdepth <= 0 || ssize <= 1) usage(efd);",
 	"#if SYNC>0 && !defined(NOREDUCE)",
@@ -3382,185 +5817,126 @@
 	"	}",
 	"#endif",
 	"#if defined(REM_VARS) && !defined(NOREDUCE)",
-	"	{ fprintf(efd, \"warning: p.o. reduction not compatible with \");",
-	"	  fprintf(efd, \"remote varrefs (use -DNOREDUCE)\\n\");",
-	"	}",
+	"	#warning p.o. reduction not compatible with remote varrefs (use -DNOREDUCE)",
 	"#endif",
 	"#if defined(NOCOMP) && !defined(BITSTATE)",
 	"	if (a_cycles)",
-	"	{ fprintf(efd, \"error: -DNOCOMP voids -l and -a\\n\");",
+	"	{ fprintf(efd, \"error: use of -DNOCOMP voids -l and -a\\n\");",
 	"	  pan_exit(1);",
 	"	}",
 	"#endif",
-
-	"#ifdef MEMLIM",	/* MEMLIM setting takes precedence */
-		"	memlim = (double) MEMLIM * (double) (1<<20);	/* size in Mbyte */",
-	"#else",
-		"#ifdef MEMCNT",
-		"#if MEMCNT<31",
-		"	memlim  = (double) (1<<MEMCNT);",
-		"#else",
-		"	memlim  = (double) (1<<30);",
-		"	memlim *= (double) (1<<(MEMCNT-30));",
-		"#endif",
-		"#endif",
+	"#ifdef MEMLIM",
+	"	memlim = ((double) MEMLIM) * (double) (1<<20);	/* size in Mbyte */",
 	"#endif",
-
-	"#ifndef BITSTATE",
-	"	if (Nrun > 1) HASH_NR = Nrun - 1;",
+	"#if SYNC>0",
+	"	#ifdef HAS_PRIORITY",
+	"		#error use of priorities cannot be combined with rendezvous",
+	"	#elif HAS_ENABLED",
+	"		#error use of enabled() cannot be combined with rendezvous",
+	"	#endif",
 	"#endif",
-	"	if (Nrun < 1 || Nrun > 32)",
-	"	{	fprintf(efd, \"error: invalid arg for -R\\n\");",
-	"		usage(efd);",
-	"	}",
-	"#ifndef SAFETY",
-	"	if (fairness && !a_cycles)",
-	"	{	fprintf(efd, \"error: -f requires -a or -l\\n\");", 
-	"		usage(efd);",
-	"	}",
-		"#if ACCEPT_LAB==0",
-	"	if (a_cycles)",
-		"#ifndef VERI",
-	"	{	fprintf(efd, \"error: no accept labels defined \");",
-	"		fprintf(efd, \"in model (for option -a)\\n\");",
-	"		usage(efd);",
-	"	}",
-		"#else",
-	"	{	fprintf(efd, \"warning: no explicit accept labels \");",
-	"		fprintf(efd, \"defined in model (for -a)\\n\");",
-	"	}",
-		"#endif",
-		"#endif",
+	"#ifndef NOREDUCE",
+	"	#ifdef HAS_PRIORITY",
+	"		#warning use of priorities requires -DNOREDUCE",
+	"	#elif HAS_ENABLED",
+	"		#error use of enabled() requires -DNOREDUCE",
+	"	#endif",
+	"	#ifdef HAS_PCVALUE",
+	"		#error use of pcvalue() requires -DNOREDUCE",
+	"	#endif",
+	"	#ifdef HAS_BADELSE",
+	"		#error use of 'else' combined with i/o stmnts requires -DNOREDUCE",
+	"	#endif",
+	"	#if defined(HAS_LAST) && !defined(BCS)",
+	"		#error use of _last requires -DNOREDUCE",
+	"	#endif",
 	"#endif",
-	"#if !defined(NOREDUCE)",
-		"#if defined(HAS_ENABLED)",
-	"	fprintf(efd, \"error: reduced search precludes \");",
-	"	fprintf(efd, \"use of 'enabled()'\\n\");",
-	"	pan_exit(1);",
-		"#endif",
-		"#if defined(HAS_PCVALUE)",
-	"	fprintf(efd, \"error: reduced search precludes \");",
-	"	fprintf(efd, \"use of 'pcvalue()'\\n\");",
-	"	pan_exit(1);",
-		"#endif",
-		"#if defined(HAS_BADELSE)",
-	"	fprintf(efd, \"error: reduced search precludes \");",
-	"	fprintf(efd, \"using 'else' combined with i/o stmnts\\n\");",
-	"	pan_exit(1);",
-		"#endif",
-		"#if defined(HAS_LAST)",
-	"	fprintf(efd, \"error: reduced search precludes \");",
-	"	fprintf(efd, \"use of _last\\n\");",
-	"	pan_exit(1);",
-		"#endif",
-	"#endif",
 
 	"#if SYNC>0 && !defined(NOREDUCE)",
-		"#ifdef HAS_UNLESS",
+	"	#ifdef HAS_UNLESS",
 	"	fprintf(efd, \"warning: use of a rendezvous stmnts in the escape\\n\");",
 	"	fprintf(efd, \"\tof an unless clause, if present, could make p.o. reduction\\n\");",
 	"	fprintf(efd, \"\tinvalid (use -DNOREDUCE to avoid this)\\n\");",
-			"#ifdef BFS",
-	"	fprintf(efd, \"\t(this type of rv is also not compatible with -DBFS)\\n\");",
-			"#endif",
-		"#endif",
+	"		#ifdef BFS",
+	"		fprintf(efd, \"\t(this type of rv is also not compatible with -DBFS)\\n\");",
+	"		#endif",
+	"	#endif",
 	"#endif",
 	"#if SYNC>0 && defined(BFS)",
-	"	fprintf(efd, \"warning: use of rendezvous in BFS mode \");",
-	"	fprintf(efd, \"does not preserve all invalid endstates\\n\");",
+	"	if (!noends)",
+	"	fprintf(efd, \"warning: use of rendezvous with BFS does not preserve all invalid endstates\\n\");",
 	"#endif",
 	"#if !defined(REACH) && !defined(BITSTATE)",
 	"	if (iterative != 0 && a_cycles == 0)",
-	"	fprintf(efd, \"warning: -i and -I need -DREACH to work accurately\\n\");",
+	"	{	fprintf(efd, \"warning: -i and -I need -DREACH to work accurately\\n\");",
+	"	}",
 	"#endif",
 	"#if defined(BITSTATE) && defined(REACH)",
-	"	fprintf(efd, \"warning: -DREACH voided by -DBITSTATE\\n\");",
+	"	#warning -DREACH is voided by -DBITSTATE",
 	"#endif",
 	"#if defined(MA) && defined(REACH)",
-	"	fprintf(efd, \"warning: -DREACH voided by -DMA\\n\");",
+	"	#warning -DREACH is voided by -DMA",
 	"#endif",
 	"#if defined(FULLSTACK) && defined(CNTRSTACK)",
-	"	fprintf(efd, \"error: cannot combine\");",
-	"	fprintf(efd, \" -DFULLSTACK and -DCNTRSTACK\\n\");",
-	"	pan_exit(1);",
+	"	#error cannot combine -DFULLSTACK and -DCNTRSTACK",
 	"#endif",
 	"#if defined(VERI)",
-		"#if ACCEPT_LAB>0",
-	"#ifndef BFS",
-	"	if (!a_cycles",
-		"#ifdef HAS_CODE",
-	"	&& !readtrail",
-		"#endif",
-	"	&& !state_tables)",
-	"	{ fprintf(efd, \"warning: never claim + accept labels \");",
-	"	  fprintf(efd, \"requires -a flag to fully verify\\n\");",
-	"	}",
-	"#else",
-	"	if (",
-		"#ifdef HAS_CODE",
-	"	!readtrail",
-		"#endif",
-	"	&& !state_tables)",
-	"	{ fprintf(efd, \"warning: verification in BFS mode \");",
-	"	  fprintf(efd, \"is restricted to safety properties\\n\");",
-	"	}",
+	"	#if ACCEPT_LAB>0",
+	"		#ifndef BFS",
+	"			if (!a_cycles",
+	"			#ifdef HAS_CODE",
+	"			&& !readtrail",
+	"			#endif",
+	"			#if NCORE>1",
+	"			&& core_id == 0",
+	"			#endif",
+	"			&& !state_tables)",
+	"			{ fprintf(efd, \"warning: never claim + accept labels \");",
+	"			  fprintf(efd, \"requires -a flag to fully verify\\n\");",
+	"			}",
+	"		#else",
+	"			if (verbose && !state_tables",
+	"			#ifdef HAS_CODE",
+	"			&& !readtrail",
+	"			#endif",
+	"			)",
+	"			{ fprintf(efd, \"warning: verification in BFS mode \");",
+	"			  fprintf(efd, \"is restricted to safety properties\\n\");",
+	"			}",
+	"		#endif",
+	"	#endif",
 	"#endif",
-		"#endif",
-	"#endif",
 	"#ifndef SAFETY",
+	"  #if 0",
 	"	if (!a_cycles",
-	"#ifdef HAS_CODE",
+	"	#ifdef HAS_CODE",
 	"	&& !readtrail",
-	"#endif",
-	"	&&  !state_tables)",
+	"	#endif",
+	"	#if NCORE>1",
+	"	&& core_id == 0",
+	"	#endif",
+	"	&& !state_tables)",
 	"	{ fprintf(efd, \"hint: this search is more efficient \");",
 	"	  fprintf(efd, \"if pan.c is compiled -DSAFETY\\n\");",
 	"	}",
-		"#ifndef NOCOMP",
+	"  #endif",
+	"	#ifndef NOCOMP",
 	"	if (!a_cycles)",
-	"		S_A = 0;",
-	"	else",
+	"	{	S_A = 0;",
+	"	} else",
 	"	{	if (!fairness)",
-	"			S_A = 1; /* _a_t */",
-		"#ifndef NOFAIR",
-	"		else /* _a_t and _cnt[NFAIR] */",
-	"		  S_A = (&(now._cnt[0]) - (uchar *) &now) + NFAIR - 2;",
+	"		{	S_A = 1; /* _a_t */",
+	"		#ifndef NOFAIR",
+	"		} else /* _a_t and _cnt[NFAIR] */",
+	"		{  S_A = (&(now._cnt[0]) - (uchar *) &now) + NFAIR - 2;",
 	"		/* -2 because first two uchars in now are masked */",
-		"#endif",
-	"	}",
-		"#endif",
+	"		#endif",
+	"	}	}",
+	"	#endif",
 	"#endif",
 	"	signal(SIGINT, stopped);",
-
-	/******************* 4.2.5 ********************/
-	"	if (WS == 4 && ssize >= 32)",
-	"	{	mask = 0xffffffff;",
-	"#ifdef BITSTATE",
-	"		switch (ssize) {",
-	"		case 34: nmask = (mask>>1); break;",
-	"		case 33: nmask = (mask>>2); break;",
-	"		default: nmask = (mask>>3); break;",
-	"		}",
-	"#else",
-	"		nmask = mask;",
-	"#endif",
-	"	} else if (WS == 8)",
-	"	{	mask = ((1L<<ssize)-1);	/* hash init */",
-	"#ifdef BITSTATE",
-	"		nmask = mask>>3;",
-	"#else",
-	"		nmask = mask;",
-	"#endif",
-	"	} else if (WS != 4)",
-	"	{	fprintf(stderr, \"pan: wordsize %%ld not supported\\n\", WS);",
-	"		exit(1);",
-	"	} else	/* WS == 4 and ssize < 32 */",
-	"	{	mask = ((1L<<ssize)-1);	/* hash init */",
-	"		nmask = (mask>>3);",
-	"	}",
-	/****************** end **********************/
-
-	"#ifdef BFS",
+	"	set_masks();",
+	"#if defined(BFS) || defined(BFS_PAR)",
 	"	trail = (Trail *) emalloc(6*sizeof(Trail));",
 	"	trail += 3;",
 	"#else",
@@ -3567,17 +5943,21 @@
 	"	trail = (Trail *) emalloc((maxdepth+3)*sizeof(Trail));",
 	"	trail++;	/* protect trpt-1 refs at depth 0 */",
 	"#endif",
+	"	trpt = &trail[0]; /* precaution -- in case uerror is called early */",
+	"#ifdef BFS",
+	"	ntrpt = trpt;",
+	"#endif",
 	"#ifdef SVDUMP",
 	"	if (vprefix > 0)",
 	"	{	char nm[64];",
-	"		sprintf(nm, \"%%s.svd\", Source);",
-	"		if ((svfd = creat(nm, 0666)) < 0)",
+	"		sprintf(nm, \"%%s.svd\", PanSource);",
+	"		if ((svfd = creat(nm, TMODE)) < 0)",
 	"		{	fprintf(efd, \"couldn't create %%s\\n\", nm);",
 	"			vprefix = 0;",
 	"	}	}",
 	"#endif",
 	"#ifdef RANDSTOR",
-	"	srand(123);",
+	"	srand(s_rand+HASH_NR);", /* main - RANDSTOR */
 	"#endif",
 	"#if SYNC>0 && ASYNC==0",
 	"	set_recvs();",
@@ -3591,6 +5971,7 @@
 	"void",
 	"usage(FILE *fd)",
 	"{",
+	"	fprintf(fd, \"%%s\\n\", SpinVersion);",
 	"	fprintf(fd, \"Valid Options are:\\n\");",
 	"#ifndef SAFETY",
 		"#ifdef NP",
@@ -3606,6 +5987,7 @@
 	"	fprintf(fd, \"\t-b  consider it an error to exceed the depth-limit\\n\");",
 	"	fprintf(fd, \"\t-cN stop at Nth error \");",
 	"	fprintf(fd, \"(defaults to -c1)\\n\");",
+	"	fprintf(fd, \"\t-D  print state tables in dot-format and stop\\n\");",
 	"	fprintf(fd, \"\t-d  print state tables and stop\\n\");",
 	"	fprintf(fd, \"\t-e  create trails for all errors\\n\");",
 	"	fprintf(fd, \"\t-E  ignore invalid end states\\n\");",
@@ -3615,7 +5997,9 @@
 	"#ifndef NOFAIR",
 	"	fprintf(fd, \"\t-f  add weak fairness (to -a or -l)\\n\");",
 	"#endif",
-	"	fprintf(fd, \"\t-hN use different hash-seed N:1..32\\n\");",
+	"	fprintf(fd, \"\t-hN use different hash-seed N:0..499 (defaults to -h0)\\n\");",
+	"	fprintf(fd, \"\t-hash generate a random hash-polynomial for -h0 (see also -rhash)\\n\");",
+	"	fprintf(fd, \"\t      using a seed set with -RSn (default %%u)\\n\", s_rand);",
 	"	fprintf(fd, \"\t-i  search for shortest path to error\\n\");",
 	"	fprintf(fd, \"\t-I  like -i, but approximate and faster\\n\");",
 	"	fprintf(fd, \"\t-J  reverse eval order of nested unlesses\\n\");",
@@ -3622,6 +6006,9 @@
 	"#ifdef BITSTATE",
 	"	fprintf(fd, \"\t-kN set N bits per state (defaults to 3)\\n\");",
 	"#endif",
+	"#ifdef BCS",
+	"	fprintf(fd, \"\t-LN set scheduling restriction to N (default 0)\\n\");",
+	"#endif",
 	"#ifndef SAFETY",
 		"#ifdef NP",
 	"	fprintf(fd, \"\t-l  find non-progress cycles\\n\");",
@@ -3631,69 +6018,83 @@
 	"	fprintf(fd, \"compilation with -DNP\\n\");",
 		"#endif",
 	"#endif",
-#ifndef POWOW
 	"#ifdef BITSTATE",
 	"	fprintf(fd, \"\t-MN use N Megabytes for bitstate hash array\\n\");",
 	"	fprintf(fd, \"\t-GN use N Gigabytes for bitstate hash array\\n\");",
 	"#endif",
-#endif
 	"	fprintf(fd, \"\t-mN max depth N steps (default=10k)\\n\");",
+	"#if NCLAIMS>1",
+	"	fprintf(fd, \"\t-N cn -- use the claim named cn\\n\");",
+	"	fprintf(fd, \"\t-Nn   -- use claim number n\\n\");",
+	"#endif",
 	"	fprintf(fd, \"\t-n  no listing of unreached states\\n\");",
+	"#ifdef PERMUTED",
+	"	fprintf(fd, \"\t-p_permute randomize order in which processes are scheduled (see also -rhash)\\n\");",
+	"	fprintf(fd, \"\t-p_reverse reverse order in which processes are scheduled (see also -rhash)\\n\");",
+	"	fprintf(fd, \"\t-p_rotateN rotate by N the process scheduling order (see also -rhash)\\n\");",
+	"#endif",
 	"#ifdef SVDUMP",
 	"	fprintf(fd, \"\t-pN create svfile (save N bytes per state)\\n\");",
 	"#endif",
+	"	fprintf(fd, \"\t-QN set time-limit on execution of N minutes\\n\");",
 	"	fprintf(fd, \"\t-q  require empty chans in valid end states\\n\");",
 	"#ifdef HAS_CODE",
 	"	fprintf(fd, \"\t-r  read and execute trail - can add -v,-n,-PN,-g,-C\\n\");",
+	"	fprintf(fd, \"\t-r trailfilename  read and execute trail in file\\n\");",
 	"	fprintf(fd, \"\t-rN read and execute N-th error trail\\n\");",
 	"	fprintf(fd, \"\t-C  read and execute trail - columnated output (can add -v,-n)\\n\");",
-	"	fprintf(fd, \"\t-PN read and execute trail - restrict trail output to proc N\\n\");",
+	"	fprintf(fd, \"\t-r -PN read and execute trail - restrict trail output to proc N\\n\");",
 	"	fprintf(fd, \"\t-g  read and execute trail + msc gui support\\n\");",
 	"	fprintf(fd, \"\t-S  silent replay: only user defined printfs show\\n\");",
 	"#endif",
+	"	fprintf(fd, \"\t-RSn use randomization seed n\\n\");",
+	"	fprintf(fd, \"\t-rhash use random hash-polynomial and randomly choose -p_rotateN, -p_permute, or p_reverse\\n\");",
 	"#ifdef BITSTATE",
-	"	fprintf(fd, \"\t-RN repeat run Nx with N \");",
-	"	fprintf(fd, \"[1..32] independent hash functions\\n\");",
-	"	fprintf(fd, \"\t-s  same as -k1 (single bit per state)\\n\");",
+	"	fprintf(fd, \"\t-Rn run n times n: [1..100] using n \");",
+	"	fprintf(fd, \" different hash functions\\n\");",
 	"#endif",
 	"	fprintf(fd, \"\t-T  create trail files in read-only mode\\n\");",
+	"	fprintf(fd, \"\t-t_reverse  reverse order in which transitions are explored\\n\");",
 	"	fprintf(fd, \"\t-tsuf replace .trail with .suf on trailfiles\\n\");",
 	"	fprintf(fd, \"\t-V  print SPIN version number\\n\");",
 	"	fprintf(fd, \"\t-v  verbose -- filenames in unreached state listing\\n\");",
 	"	fprintf(fd, \"\t-wN hashtable of 2^N entries \");",
 	"	fprintf(fd, \"(defaults to -w%%d)\\n\", ssize);",
+	"	fprintf(fd, \"\t-x  do not overwrite an existing trail file\\n\");",
+	"#if NCORE>1",
+	"	fprintf(fd, \"\t-zN handoff states below depth N to 2nd cpu (multi_core)\\n\");",
+	"#endif",
+	"#ifdef HAS_CODE",
+	"	fprintf(fd, \"\\n\toptions -r, -C, -PN, -g, and -S can optionally be followed by\\n\");",
+	"	fprintf(fd, \"\ta filename argument, as in \'-r filename\', naming the trailfile\\n\");",
+	"#endif",
+	"#if NCORE>1",
+	"	multi_usage(fd);",
+	"#endif",
 	"	exit(1);",
 	"}",
 	"",
 	"char *",
-	"Malloc(unsigned long n)",
+	"Malloc(ulong n)",
 	"{	char *tmp;",
-	"#if defined(MEMCNT) || defined(MEMLIM)",
-	"	if (memcnt+ (double) n > memlim) goto err;",
+	"#ifdef MEMLIM",
+	"	if (memcnt + (double) n > memlim)",
+	"	{	printf(\"pan: reached -DMEMLIM bound\\n\");",
+	"		goto err;",
+	"	}",
 	"#endif",
-"#if 1",
 	"	tmp = (char *) malloc(n);",
 	"	if (!tmp)",
-"#else",
-	/* on linux machines, a large amount of memory is set aside
-	 * for malloc, whether it is used or not
-	 * using sbrk would make this memory arena inaccessible
-	 * the reason for using sbrk was originally to provide a
-	 * small additional speedup (since this memory is never released)
-	 */
-	"	tmp = (char *) sbrk(n);",
-	"	if (tmp == (char *) -1L)",
-"#endif",
 	"	{",
-	"#if defined(MEMCNT) || defined(MEMLIM)",
-	"err:",
+	"#ifdef BFS_PAR",
+	"		Uerror(\"out of non-shared memory\");",
 	"#endif",
 	"		printf(\"pan: out of memory\\n\");",
-	"#if defined(MEMCNT) || defined(MEMLIM)",
+	"#ifdef MEMLIM",
+	"err:",
 	"		printf(\"\t%%g bytes used\\n\", memcnt);",
 	"		printf(\"\t%%g bytes more needed\\n\", (double) n);",
-	"		printf(\"\t%%g bytes limit\\n\",",
-	"			memlim);",
+	"		printf(\"\t%%g bytes limit\\n\", memlim);",
 	"#endif",
 	"#ifdef COLLAPSE",
 	"		printf(\"hint: to reduce memory, recompile with\\n\");",
@@ -3714,6 +6115,15 @@
 	"		printf(\"  -DBITSTATE # supertrace, approximation\\n\");",
 	"#endif",
 	"#endif",
+	"#if NCORE>1",
+	"	#ifdef FULL_TRAIL",
+	"		printf(\"  omit -DFULL_TRAIL or use pan -c0 to reduce memory\\n\");",
+	"	#endif",
+	"	#ifdef SEP_STATE",
+	"		printf(\"hint: to reduce memory, recompile without\\n\");",
+	"		printf(\"  -DSEP_STATE # may be faster, but uses more memory\\n\");",
+	"	#endif",
+	"#endif",
 	"		wrapup();",
 	"	}",
 	"	memcnt += (double) n;",
@@ -3723,13 +6133,13 @@
 	"#define CHUNK	(100*VECTORSZ)",
 	"",
 	"char *",
-	"emalloc(unsigned long n) /* never released or reallocated */",
+	"emalloc(ulong n) /* never released or reallocated */",
 	"{	char *tmp;",
 	"	if (n == 0)",
 	"	        return (char *) NULL;",
 	"	if (n&(sizeof(void *)-1)) /* for proper alignment */",
 	"	        n += sizeof(void *)-(n&(sizeof(void *)-1));",
-	"	if ((unsigned long) left < n)",	/* was: (left < (long)n) */
+	"	if ((ulong) left < n)",	/* was: (left < (long)n) */
 	"	{       grow = (n < CHUNK) ? CHUNK : n;",
 #if 1
 	"	        have = Malloc(grow);",
@@ -3754,9 +6164,15 @@
 	"}",
 
 	"void",
-	"Uerror(char *str)",
+	"dfs_Uerror(char *str)",
 	"{	/* always fatal */",
 	"	uerror(str);",
+	"#if NCORE>1",
+	"	sudden_stop(\"Uerror\");",
+	"#endif",
+	"#ifdef BFS_PAR",
+	"	bfs_shutdown(\"Uerror\");",
+	"#endif",
 	"	wrapup();",
 	"}\n",
 	"#if defined(MA) && !defined(SAFETY)",
@@ -3775,9 +6191,14 @@
 	"	trpt = getframe(depth);",
 	"#endif",
 	"#ifdef VERBOSE",
-	"	printf(\"%%d	 State: \", depth);",
+	"	printf(\"%%ld	 State: \", depth);",
+	"#if !defined(NOCOMP) && !defined(HC)",
 	"	for (i = 0; i < vsize; i++) printf(\"%%d%%s,\",",
 	"		((char *)&now)[i], Mask[i]?\"*\":\"\");",
+	"#else",
+	"	for (i = 0; i < vsize; i++)",
+	"		printf(\"%%d,\", ((char *)&now)[i]);",
+	"#endif",
 	"	printf(\"\\n\");",
 	"#endif",
 	"#ifndef NOFAIR",
@@ -3794,7 +6215,7 @@
 	"#endif",
 	"#ifdef HAS_LAST",
 	"#ifdef VERI",
-	"	{ int d; Trail *trl;",
+	"	{ long d; Trail *trl;",
 	"	  now._last = 0;",
 	"	  for (d = 1; d < depth; d++)",
 	"	  {	trl = getframe(depth-d); /* was trl = (trpt-d); */",
@@ -3820,10 +6241,10 @@
 	"	tt = trpt->o_tt; this = pptr(II);",
 	"	_m = do_reverse(t, II, trpt->o_m);",
 	"#ifdef VERBOSE",
-	"	printf(\"%%3d: proc %%d \", depth, II);",
+	"	printf(\"%%3ld: proc %%d \", depth, II);",
 	"	printf(\"reverses %%d, %%d to %%d,\",",
 	"		t->forw, tt, t->st);",
-	"	printf(\" %%s [abit=%%d,adepth=%%d,\", ",
+	"	printf(\" %%s [abit=%%d,adepth=%%ld,\", ",
 	"		t->tp, now._a_t, A_depth);",
 	"	printf(\"tau=%%d,%%d] <unwind>\\n\", ",
 	"		trpt->tau, (trpt-1)->tau);",
@@ -3862,14 +6283,21 @@
 	"#endif",
 	"static char unwinding;",
 	"void",
-	"uerror(char *str)",
+	"dfs_uerror(char *str)",
 	"{	static char laststr[256];",
 	"	int is_cycle;",
 	"",
 	"	if (unwinding) return; /* 1.4.2 */",
 	"	if (strncmp(str, laststr, 254))",
-	"	printf(\"pan: %%s (at depth %%ld)\\n\", str,",
-	"		(depthfound==-1)?depth:depthfound);",
+	"#if NCORE>1",
+	"	cpu_printf(\"pan:%%d: %%s (at depth %%ld)\\n\", errors+1, str,",
+	"#else",
+	"	printf(\"pan:%%d: %%s (at depth %%ld)\\n\", errors+1, str,",
+	"#endif",
+	"#if NCORE>1",
+	"		(nr_handoffs * z_handoff) + ",
+	"#endif",
+	"		((depthfound == -1)?depth:depthfound));",
 	"	strncpy(laststr, str, 254);",
 	"	errors++;",
 	"#ifdef HAS_CODE",
@@ -3891,13 +6319,16 @@
 	"			depth = od;",
 	"		}",
 	"#endif",
-"#ifdef BFS",
+	"#if NCORE>1",
+	"		writing_trail = 1;",
+	"#endif",
+	"#ifdef BFS",
 	"		if (depth > 1) trpt--;",
-	"		nuerror(str);",
+	"		nuerror();",
 	"		if (depth > 1) trpt++;",
-"#else",
+	"#else",
 	"		putrail();",
-"#endif",
+	"#endif",
 	"#if defined(MA) && !defined(SAFETY)",
 	"		if (strstr(str, \" cycle\"))",
 	"		{	if (every_error)",
@@ -3905,20 +6336,36 @@
 	"			wrapup(); /* no recovery from unwind */",
 	"		}",
 	"#endif",
+	"#if NCORE>1",
+	"		if (search_terminated != NULL)",
+	"		{	*search_terminated |= 4; /* uerror */",
+	"		}",
+	"		writing_trail = 0;",
+	"#endif",
 	"	}",
 	"	if (!is_cycle)",
 	"	{	depth--; trpt--;	/* undo */",
 	"	}",
-"#ifndef BFS",
+	"#ifndef BFS",
 	"	if (iterative != 0 && maxdepth > 0)",
-	"	{	maxdepth = (iterative == 1)?(depth-1):(depth/2);",
+	"	{	if (maxdepth > depth)",
+	"		{	maxdepth = (iterative == 1)?(depth+1):(depth/2);",
+	"		}",
 	"		warned = 1;",
 	"		printf(\"pan: reducing search depth to %%ld\\n\",",
 	"			maxdepth);",
 	"	} else",
-"#endif",
+	"#endif",
 	"	if (errors >= upto && upto != 0)",
+	"	{",
+	"#ifdef BFS_PAR",
+	"		bfs_shutdown(\"uerror\"); /* no return */",
+	"#endif",
+	"#if NCORE>1",
+	"		sudden_stop(\"uerror\");",
+	"#endif",
 	"		wrapup();",
+	"	}",
 	"	depthfound = -1;",
 	"}\n",
 	"int",
@@ -3930,13 +6377,14 @@
 	"		||  strncmp(T->tp, \"goto :\", 6) == 0)",
 	"			return 1; /* not reported */",
 	"",
-	"		printf(\"\\tline %%d\", lno);",
-	"		if (verbose)",
 	"		for (j = 0; j < sizeof(mp); j++)",
 	"			if (i >= mp[j].from && i <= mp[j].upto)",
-	"			{	printf(\", \\\"%%s\\\"\", mp[j].fnm);",
+	"			{	printf(\"\\t%%s:%%d\", mp[j].fnm, lno);",
 	"				break;",
 	"			}",
+	"		if (j >= sizeof(mp))	/* fnm not found in list */",
+	"		{	printf(\"\\t%%s:%%d\", PanSource, lno); /* use default */",
+	"		}",
 	"		printf(\", state %%d\", i);",
 	"		if (strcmp(T->tp, \"\") != 0)",
 	"		{	char *q;",
@@ -3951,45 +6399,120 @@
 	"}\n",
 	"void",
 	"r_ck(uchar *which, int N, int M, short *src, S_F_MAP *mp)",
-	"{	int i, m=0;\n",
-	"#ifdef VERI",
-	"	if (M == VERI && !verbose) return;",
-	"#endif",
-	"	printf(\"unreached in proctype %%s\\n\", procname[M]);",
+	"{	int i, m=0;",
+	"",
+	"	if ((enum btypes) Btypes[M] == N_CLAIM",
+	"	&& claimname != NULL && strcmp(claimname, procname[M]) != 0)",
+	"	{	return;",
+	"	}",
+	"",
+	"	switch ((enum btypes) Btypes[M]) {",
+	"	case P_PROC:",
+	"	case A_PROC:",
+	"		printf(\"unreached in proctype %%s\\n\", procname[M]);",
+	"		break;",
+	"	case I_PROC:",
+	"		printf(\"unreached in init\\n\");",
+	"		break;",
+	"	case E_TRACE:",
+	"	case N_TRACE:",
+	"	case N_CLAIM:",
+	"	default:",
+	"		printf(\"unreached in claim %%s\\n\", procname[M]);",
+	"		break;",
+	"	}",
 	"	for (i = 1; i < N; i++)",
-#if 0
-	"	  if (which[i] == 0 /* && trans[M][i] */)",
-#else
-	"	  if (which[i] == 0",
-	"	  &&  (mapstate[M][i] == 0",
-	"	  ||   which[mapstate[M][i]] == 0))",
-#endif
-	"	  	m += xrefsrc((int) src[i], mp, M, i);",
-	"	  else",
-	"		m++;",
+	"	{	if (which[i] == 0",
+	"		&&  (mapstate[M][i] == 0",
+	"		||   which[mapstate[M][i]] == 0))",
+	"		{	m += xrefsrc((int) src[i], mp, M, i);",
+	"		} else",
+	"		{	m++;",
+	"	}	}",
 	"	printf(\"\t(%%d of %%d states)\\n\", N-1-m, N-1);",
-	"}\n",
+	"}",
+	"#if NCORE>1 && !defined(SEP_STATE)",
+	"static long rev_trail_cnt;",
+	"",
+	"#ifdef FULL_TRAIL",
 	"void",
+	"rev_trail(int fd, volatile Stack_Tree *st_tr)",
+	"{	long j; char snap[64];",
+	"",
+	"	if (!st_tr)",
+	"	{	return;",
+	"	}",
+	"	rev_trail(fd, st_tr->prv);",
+	"#ifdef VERBOSE",
+	"	printf(\"%%d (%%d) LRT [%%d,%%d] -- %%9u (root %%9u)\\n\",",
+	"		depth, rev_trail_cnt, st_tr->pr, st_tr->t_id, st_tr, stack_last[core_id]);",
+	"#endif",
+	"	if (st_tr->pr != 255)", /* still needed? */
+	"	{	sprintf(snap, \"%%ld:%%d:%%d\\n\", ",
+	"			rev_trail_cnt++, st_tr->pr, st_tr->t_id);",
+	"		j = strlen(snap);",
+	"		if (write(fd, snap, j) != j)",
+	"		{	printf(\"pan: error writing trailfile\\n\");",
+	"			close(fd);",
+	"			wrapup();",
+	"			return;",
+	"		}",
+	"	} else  /* handoff point */",
+	"	{	if (a_cycles)",
+	"		{	(void) write(fd, \"-1:-1:-1\\n\", 9);",
+	"	}	}",
+	"}",
+	"#endif", /* FULL_TRAIL */
+	"#endif", /* NCORE>1 */
+	"",
+	"void",
 	"putrail(void)",
-	"{	int fd; long i, j;",
-	"	Trail *trl;",
+	"{	int fd;",
 	"#if defined VERI || defined(MERGED)",
 	"	char snap[64];",
 	"#endif",
-	"",
+	"#if NCORE==1 || defined(SEP_STATE) || !defined(FULL_TRAIL)",
+	"	long i, j;",
+	"	Trail *trl;",
+	"#endif",
 	"	fd = make_trail();",
 	"	if (fd < 0) return;",
 	"#ifdef VERI",
-	"	sprintf(snap, \"-2:%%d:-2\\n\", VERI);",
-	"	write(fd, snap, strlen(snap));",
+	"	sprintf(snap, \"-2:%%d:-2\\n\", (uchar) ((P0 *)pptr(0))->_t);",
+	"	if (write(fd, snap, strlen(snap)) < 0) return;",
 	"#endif",
 	"#ifdef MERGED",
 	"	sprintf(snap, \"-4:-4:-4\\n\");",
-	"	write(fd, snap, strlen(snap));",
+	"	if (write(fd, snap, strlen(snap)) < 0) return;",
 	"#endif",
-	"	for (i = 1; i <= depth; i++)",
+	"#ifdef PERMUTED",
+	"	sprintf(snap, \"-5:%%d:%%d\\n\", t_reverse, reversing&2);",
+	"	if (write(fd, snap, strlen(snap)) < 0) return;",
+	"",
+	"	sprintf(snap, \"-6:%%d:%%d\\n\", p_reorder==set_permuted, p_reorder==set_reversed);",
+	"	if (write(fd, snap, strlen(snap)) < 0) return;",
+	"",
+	"	sprintf(snap, \"-7:%%d:%%d\\n\", p_reorder==set_rotated, p_rotate);",
+	"	if (write(fd, snap, strlen(snap)) < 0) return;",
+	"",
+	"	sprintf(snap, \"-8:%%d:%%d\\n\", p_reorder==set_randrot, --s_rand);",
+	"	if (write(fd, snap, strlen(snap)) < 0) return;",
+	"#endif",
+	"#if NCORE>1 && !defined(SEP_STATE) && defined(FULL_TRAIL)",
+	"	rev_trail_cnt = 1;",
+	"	enter_critical(GLOBAL_LOCK);",
+	"	 rev_trail(fd, stack_last[core_id]);",
+	"	leave_critical(GLOBAL_LOCK);",
+	"#else",
+	"	i = 1; /* trail starts at position 1 */",
+	"	#if NCORE>1 && defined(SEP_STATE)",
+	"	if (cur_Root.m_vsize > 0) { i++; depth++; }",
+	"	#endif",
+	"	for ( ; i <= depth; i++)",
 	"	{	if (i == depthfound+1)",
-	"			write(fd, \"-1:-1:-1\\n\", 9);",
+	"		{	if (write(fd, \"-1:-1:-1\\n\", 9) != 9)",
+	"			{	goto notgood;",
+	"		}	}",
 	"		trl = getframe(i);",
 	"		if (!trl->o_t) continue;",
 	"		if (trl->o_pm&128) continue;",
@@ -3997,12 +6520,16 @@
 	"			i, trl->pr, trl->o_t->t_id);",
 	"		j = strlen(snap);",
 	"		if (write(fd, snap, j) != j)",
-	"		{	printf(\"pan: error writing trailfile\\n\");",
+	"		{",
+	"notgood:		printf(\"pan: error writing trailfile\\n\");",
 	"			close(fd);",
 	"			wrapup();",
-	"		}",
-	"	}",
+	"	}	}",
+	"#endif",
 	"	close(fd);",
+	"#if NCORE>1",
+	"	cpu_printf(\"pan: wrote trailfile\\n\");",
+	"#endif",
 	"}\n",
 	"void",
 	"sv_save(void)	/* push state vector onto save stack */",
@@ -4022,6 +6549,9 @@
 	"#if SYNC",
 	"	svtack->o_boq = boq;",
 	"#endif",
+	"#ifdef TRIX",
+	"	sv_populate();",
+	"#endif",
 	"	svtack->o_delta = vsize; /* don't compress */",
 	"	memcpy((char *)(svtack->body), (char *) &now, vsize);",
 	"#if defined(C_States) && defined(HAS_STACK) && (HAS_TRACK==1)",
@@ -4028,7 +6558,7 @@
 	"	c_stack((uchar *) &(svtack->c_stack[0]));",
 	"#endif",
 	"#ifdef DEBUG",
-	"	printf(\"%%d:	sv_save\\n\", depth);",
+	"	cpu_printf(\"%%d:	sv_save\\n\", depth);",
 	"#endif",
 	"}\n",
 	"void",
@@ -4038,7 +6568,9 @@
 	"#if SYNC",
 	"	boq = svtack->o_boq;",
 	"#endif",
-
+	"#ifdef TRIX",
+	"	re_populate();",
+	"#endif",
 	"#if defined(C_States) && (HAS_TRACK==1)",
 	"#ifdef HAS_STACK",
 	"	c_unstack((uchar *) &(svtack->c_stack[0]));",
@@ -4049,78 +6581,144 @@
 	"	if (vsize != svtack->o_delta)",
 	"		Uerror(\"sv_restor\");",
 	"	if (!svtack->lst)",
-	"		Uerror(\"error: v_restor\");",
+	"		Uerror(\"error: sv_restor\");",
 	"	svtack  = svtack->lst;",
 	"#ifdef DEBUG",
-	"	printf(\"	sv_restor\\n\");",
+	"	cpu_printf(\"	sv_restor\\n\");",
 	"#endif",
-	"}\n",
+	"}",
+	"",
 	"void",
 	"p_restor(int h)",
-	"{	int i; char *z = (char *) &now;\n",
+	"{	int i;",
+	"	char *z = (char *) &now;\n",
+	"",
+	"#ifdef BFS_PAR",
+	"	bfs_prepmask(1);	/* p_restor */",
+	"#endif",
+	"#ifndef TRIX",
 	"	proc_offset[h] = stack->o_offset;",
 	"	proc_skip[h]   = (uchar) stack->o_skip;",
+	"#else",
+	"	char *oi;",
+	"	#ifdef V_TRIX",
+	"		printf(\"%%4d: p_restor %%d\\n\", depth, h);",
+	"	#endif",
+	"#endif",
 	"#ifndef XUSAFE",
 	"	p_name[h] = stack->o_name;",
 	"#endif",
-	"#ifndef NOCOMP",
+	"#ifdef TRIX",
+	"	vsize += sizeof(char *);",
+	"	#ifndef BFS",
+	"		if (processes[h] != NULL || freebodies == NULL)",
+	"		{	Uerror(\"processes error\");",
+	"		}",
+	"		processes[h] = freebodies;",
+	"		freebodies = freebodies->nxt;",
+	"		processes[h]->nxt = (TRIX_v6 *) 0;",
+	"		processes[h]->modified = 1;	/* p_restor */",
+	"	#endif",
+	"	processes[h]->parent_pid = stack->parent;",
+	"	processes[h]->psize = stack->o_delta;",
+	"	memcpy((char *)pptr(h), stack->b_ptr, stack->o_delta);",
+	"	oi = stack->b_ptr;",
+	"#else",
+	"	#if !defined(NOCOMP) && !defined(HC)",
 	"	for (i = vsize + stack->o_skip; i > vsize; i--)",
 	"		Mask[i-1] = 1; /* align */",
-	"#endif",
+	"	#endif",
 	"	vsize += stack->o_skip;",
 	"	memcpy(z+vsize, stack->body, stack->o_delta);",
 	"	vsize += stack->o_delta;",
-	"#ifndef NOVSZ",
-	"	now._vsz = vsize;",
-	"#endif",
-	"#ifndef NOCOMP",
-	"	for (i = 1; i <= Air[((P0 *)pptr(h))->_t]; i++)",
-	"		Mask[vsize - i] = 1; /* pad */",
-	"	Mask[proc_offset[h]] = 1;	/* _pid */",
-	"#endif",
+	"	#if !defined(NOCOMP) && !defined(HC)",
+	"		for (i = 1; i <= Air[((P0 *)pptr(h))->_t]; i++)",
+	"			Mask[vsize - i] = 1;	/* pad */",
+	"		Mask[proc_offset[h]] = 1;	/* _pid */",
+	"	#endif",
 	"	if (BASE > 0 && h > 0)",
 	"		((P0 *)pptr(h))->_pid = h-BASE;",
 	"	else",
 	"		((P0 *)pptr(h))->_pid = h;",
-	"	i = stack->o_delqs;",
+	"	#ifdef BFS_PAR",
+	"		bfs_fixmask(1);	/* p_restor */",
+	"	#endif",
+	"#endif",
 	"	now._nr_pr += 1;",
-	"	if (!stack->lst)	/* debugging */",
+	"#ifndef NOVSZ",
+	"	now._vsz = vsize;",
+	"#endif",
+	"	i = stack->o_delqs;",
+	"	if (!stack->lst)",
 	"		Uerror(\"error: p_restor\");",
 	"	stack = stack->lst;",
 	"	this = pptr(h);",
 	"	while (i-- > 0)",
 	"		q_restor();",
+	"#ifdef TRIX",
+	"	re_mark_all(1);	/* p_restor - all chans move up in _ids_ */",
+	"	now._ids_[h] = oi; /* restor the original contents */",
+	"#endif",
 	"}\n",
 	"void",
 	"q_restor(void)",
-	"{	char *z = (char *) &now;",
-	"#ifndef NOCOMP",
-	"	int k, k_end;",
-	"#endif",
-	"	q_offset[now._nr_qs] = stack->o_offset;",
-	"	q_skip[now._nr_qs]   = (uchar) stack->o_skip;",
-	"#ifndef XUSAFE",
-	"	q_name[now._nr_qs]   = stack->o_name;",
-	"#endif",
+	"{	int h = now._nr_qs;",
+	"#ifdef TRIX",
+	"	#ifdef V_TRIX",
+	"		printf(\"%%4d: q_restor %%d\\n\", depth, h);",
+	"	#endif",
+	"	vsize += sizeof(char *);",
+	"	#ifndef BFS",
+	"		if (channels[h] != NULL || freebodies == NULL)",
+	"		{	Uerror(\"channels error\");",
+	"		}",
+	"		channels[h] = freebodies;",
+	"		freebodies = freebodies->nxt;",
+	"		channels[h]->nxt = (TRIX_v6 *) 0;",
+	"		channels[h]->modified = 1;	/* q_restor */",
+	"	#endif",
+	"	channels[h]->parent_pid = stack->parent;",
+	"	channels[h]->psize = stack->o_delta;",
+	"	memcpy((char *)qptr(h), stack->b_ptr, stack->o_delta);",
+	"	now._ids_[now._nr_pr + h] = stack->b_ptr;",
+	"#else",
+	"	char *z = (char *) &now;",
+	"	#ifndef NOCOMP",
+	"		int k, k_end;",
+	"	#endif",
+	"	#ifdef BFS_PAR",
+	"		bfs_prepmask(2);	/* q_restor */",
+	"	#endif",
+	"	q_offset[h] = stack->o_offset;",
+	"	q_skip[h]   = (uchar) stack->o_skip;",
 	"	vsize += stack->o_skip;",
 	"	memcpy(z+vsize, stack->body, stack->o_delta);",
 	"	vsize += stack->o_delta;",
+	"#endif",
+	"#ifndef XUSAFE",
+	"	q_name[h] = stack->o_name;",
+	"#endif",
 	"#ifndef NOVSZ",
 	"	now._vsz = vsize;",
 	"#endif",
 	"	now._nr_qs += 1;",
-	"#ifndef NOCOMP",
-	"	k_end = stack->o_offset;",
-	"	k = k_end - stack->o_skip;",
-	"#if SYNC",
-	"#ifndef BFS",
-	"	if (q_zero(now._nr_qs)) k_end += stack->o_delta;",
+	"#ifndef TRIX",
+	"	#if !defined(NOCOMP) && !defined(HC)",
+	"		k_end = stack->o_offset;",
+	"		k = k_end - stack->o_skip;",
+	"		#if SYNC",
+	"			#ifndef BFS",
+	"			if (q_zero(now._nr_qs)) k_end += stack->o_delta;",
+	"			#endif",
+	"		#endif",
+	"		for ( ; k < k_end; k++)",
+	"			Mask[k] = 1;",
+	"	#endif",
+	"	#ifdef BFS_PAR",
+	"		bfs_fixmask(2);	/* q_restor */",
+	"	#endif",
 	"#endif",
-	"#endif",
-	"	for ( ; k < k_end; k++)",
-	"		Mask[k] = 1;",
-	"#endif",
-	"	if (!stack->lst)	/* debugging */",
+	"	if (!stack->lst)",
 	"		Uerror(\"error: q_restor\");",
 	"	stack = stack->lst;",
 	"}",
@@ -4163,7 +6761,46 @@
 	"#ifndef NOCOMP",
 	"	int o_vsize = vsize;",
 	"#endif",
-	"	if (h+1 != (int) now._nr_pr) return 0;\n",
+	"	if (h+1 != (int) now._nr_pr)",
+	"	{	return 0;",
+	"	}",
+	"#ifdef TRIX",
+	"	#ifdef V_TRIX",
+	"		printf(\"%%4d: delproc %%d -- parent %%d\\n\", depth, h, processes[h]->parent_pid);",
+	"		if (now._nr_qs > 0)",
+	"		printf(\"	top channel: %%d -- parent %%d\\n\", now._nr_qs-1, channels[now._nr_qs-1]->parent_pid);",
+	"	#endif",
+	"	while (now._nr_qs > 0",
+	"	&&     channels[now._nr_qs-1]->parent_pid == processes[h]->parent_pid)",
+	"	{	delq(sav);",
+	"		i++;",
+	"	}",
+	"	d = processes[h]->psize;",
+	"	if (sav)",
+	"	{	if (!stack->nxt)",
+	"		{	stack->nxt = (_Stack *) emalloc(sizeof(_Stack));",
+	"			stack->nxt->lst = stack;",
+	"			smax++;",
+	"		}",
+	"		stack = stack->nxt;",
+	"	#ifndef XUSAFE",
+	"		stack->o_name   = p_name[h];",
+	"	#endif",
+	"		stack->parent   = processes[h]->parent_pid;",
+	"		stack->o_delta  = d;",
+	"		stack->o_delqs  = i;",
+	"		stack->b_ptr = now._ids_[h];", /* new 6.1 */
+	"	}",
+	"	memset((char *)pptr(h), 0, d);",
+	"	#ifndef BFS",
+	"		processes[h]->nxt = freebodies;",
+	"		freebodies = processes[h];",
+	"		processes[h] = (TRIX_v6 *) 0;",
+	"	#endif",
+	"	vsize -= sizeof(char *);",
+	"	now._nr_pr -= 1;",
+	"	re_mark_all(-1); /* delproc - all chans move down in _ids_ */",
+	"#else",
 	"	while (now._nr_qs",
 	"	&&     q_offset[now._nr_qs-1] > proc_offset[h])",
 	"	{	delq(sav);",
@@ -4172,80 +6809,116 @@
 	"	d = vsize - proc_offset[h];",
 	"	if (sav)",
 	"	{	if (!stack->nxt)",
-	"		{	stack->nxt = (Stack *)",
-	"				emalloc(sizeof(Stack));",
-	"			stack->nxt->body = ",
-	"				emalloc(Maxbody*sizeof(char));",
+	"		{	stack->nxt = (_Stack *) emalloc(sizeof(_Stack));",
+	"			stack->nxt->body = emalloc(Maxbody * sizeof(char));",
 	"			stack->nxt->lst = stack;",
 	"			smax++;",
 	"		}",
 	"		stack = stack->nxt;",
 	"		stack->o_offset = proc_offset[h];",
-	"#if VECTORSZ>32000",
+	"	#if VECTORSZ>32000",
 	"		stack->o_skip   = (int) proc_skip[h];",
-	"#else",
+	"	#else",
 	"		stack->o_skip   = (short) proc_skip[h];",
-	"#endif",
-	"#ifndef XUSAFE",
+	"	#endif",
+	"	#ifndef XUSAFE",
 	"		stack->o_name   = p_name[h];",
-	"#endif",
+	"	#endif",
 	"		stack->o_delta  = d;",
 	"		stack->o_delqs  = i;",
 	"		memcpy(stack->body, (char *)pptr(h), d);",
 	"	}",
 	"	vsize = proc_offset[h];",
-	"	now._nr_pr = now._nr_pr - 1;",
+	"	now._nr_pr -= 1;",
 	"	memset((char *)pptr(h), 0, d);",
 	"	vsize -= (int) proc_skip[h];",
+	"	#if !defined(NOCOMP) && !defined(HC)",
+	"		#ifdef BFS_PAR",
+	"			bfs_prepmask(3); /* delproc - no chance in proc_offset or proc_skip */",
+	"		#endif",
+	"		for (i = vsize; i < o_vsize; i++)",
+	"			Mask[i] = 0; /* reset */",
+	"		#ifdef BFS_PAR",
+	"			bfs_fixmask(3);	/* delproc */",
+	"		#endif",
+	"	#endif",
+	"#endif",
 	"#ifndef NOVSZ",
 	"	now._vsz = vsize;",
 	"#endif",
-	"#ifndef NOCOMP",
-	"	for (i = vsize; i < o_vsize; i++)",
-	"		Mask[i] = 0; /* reset */",
-	"#endif",
 	"	return 1;",
 	"}\n",
 	"void",
 	"delq(int sav)",
 	"{	int h = now._nr_qs - 1;",
+	"#ifdef TRIX",
+	"	int d = channels[now._nr_qs - 1]->psize;",
+	"#else",
 	"	int d = vsize - q_offset[now._nr_qs - 1];",
+	"#endif",
 	"#ifndef NOCOMP",
 	"	int k, o_vsize = vsize;",
 	"#endif",
 	"	if (sav)",
 	"	{	if (!stack->nxt)",
-	"		{	stack->nxt = (Stack *)",
-	"				emalloc(sizeof(Stack));",
-	"			stack->nxt->body = ",
-	"				emalloc(Maxbody*sizeof(char));",
+	"		{	stack->nxt = (_Stack *) emalloc(sizeof(_Stack));",
+	"#ifndef TRIX",
+	"			stack->nxt->body = emalloc(Maxbody * sizeof(char));",
+	"#endif",
 	"			stack->nxt->lst = stack;",
 	"			smax++;",
 	"		}",
 	"		stack = stack->nxt;",
+	"#ifdef TRIX",
+	"		stack->parent = channels[h]->parent_pid;",
+	"		stack->b_ptr = now._ids_[h];", /* new 6.1 */
+	"#else",
 	"		stack->o_offset = q_offset[h];",
-	"#if VECTORSZ>32000",
+	"	#if VECTORSZ>32000",
 	"		stack->o_skip   = (int) q_skip[h];",
-	"#else",
+	"	#else",
 	"		stack->o_skip   = (short) q_skip[h];",
+	"	#endif",
 	"#endif",
-	"#ifndef XUSAFE",
+	"	#ifndef XUSAFE",
 	"		stack->o_name   = q_name[h];",
-	"#endif",
+	"	#endif",
 	"		stack->o_delta  = d;",
+	"#ifndef TRIX",
 	"		memcpy(stack->body, (char *)qptr(h), d);",
+	"#endif",
 	"	}",
+	"#ifdef TRIX",
+	"	vsize -= sizeof(char *);",
+	"	#ifdef V_TRIX",
+	"		printf(\"%%4d: delq %%d parent %%d\\n\", depth, h, channels[h]->parent_pid);",
+	"	#endif",
+	"#else",
 	"	vsize = q_offset[h];",
-	"	now._nr_qs = now._nr_qs - 1;",
-	"	memset((char *)qptr(h), 0, d);",
 	"	vsize -= (int) q_skip[h];",
+	"	#if !defined(NOCOMP) && !defined(HC)",
+	"		#ifdef BFS_PAR",
+	"			bfs_prepmask(3); /* delq - no change in q_offset or q_skip */",
+	"		#endif",
+	"		for (k = vsize; k < o_vsize; k++)",
+	"			Mask[k] = 0; /* reset */",
+	"		#ifdef BFS_PAR",
+	"			bfs_fixmask(3);	/* delq */",
+	"		#endif",
+	"	#endif",
+	"#endif",
+	"	now._nr_qs -= 1;",
+	"	memset((char *)qptr(h), 0, d);",
+	"#ifdef TRIX",
+	"	#ifndef BFS",
+	"		channels[h]->nxt = freebodies;",
+	"		freebodies = channels[h];",
+	"		channels[h] = (TRIX_v6 *) 0;",
+	"	#endif",
+	"#endif",
 	"#ifndef NOVSZ",
 	"	now._vsz = vsize;",
 	"#endif",
-	"#ifndef NOCOMP",
-	"	for (k = vsize; k < o_vsize; k++)",
-	"		Mask[k] = 0; /* reset */",
-	"#endif",
 	"}\n",
 	"int",
 	"qs_empty(void)",
@@ -4265,7 +6938,7 @@
 	"			return 0;",
 	"	}",
 	"	if (strict) return qs_empty();",
-	"#if defined(EVENT_TRACE) && !defined(OTIM)",
+	"#if defined(EVENT_TRACE)",
 	"	if (!stopstate[EVENT_TRACE][now._event] && !a_cycles)",
 	"	{	printf(\"pan: event_trace not completed\\n\");",
 	"		return 0;",
@@ -4273,55 +6946,54 @@
 	"#endif",
 	"	return 1;",
 	"}\n",
-	"#ifndef SAFETY",
+	"#if !defined(SAFETY) && !defined(BFS)",
 	"void",
 	"checkcycles(void)",
 	"{	uchar o_a_t = now._a_t;",
-	"#ifndef NOFAIR",
-	"	uchar o_cnt = now._cnt[1];",
-	"#endif",
-		"#ifdef FULLSTACK",
-		"#ifndef MA",
-	"	struct H_el *sv = trpt->ostate; /* save */",
-		"#else",
-	"	uchar prov = trpt->proviso; /* save */",
-		"#endif",
-		"#endif",
-		"#ifdef DEBUG",
-	"	{ int i; uchar *v = (uchar *) &now;",
-	"	  printf(\"	set Seed state \");",
-	"#ifndef NOFAIR",
-	"	  if (fairness) printf(\"(cnt = %%d:%%d, nrpr=%%d) \",",
-	"		now._cnt[0], now._cnt[1], now._nr_pr);",
-	"#endif",
-	"	/* for (i = 0; i < n; i++) printf(\"%%d,\", v[i]);	*/",
-	"	  printf(\"\\n\");",
-	"	}",
-	"	printf(\"%%d: cycle check starts\\n\", depth);",
-		"#endif",
+	"	#ifndef NOFAIR",
+	"		uchar o_cnt = now._cnt[1];",
+	"	#endif",
+	"	#ifdef FULLSTACK",
+	"		#ifndef MA",
+	"			H_el *sv = trpt->ostate; /* save */",
+	"		#else",
+	"			uchar prov = trpt->proviso; /* save */",
+	"		#endif",
+	"	#endif",
+	"	#ifdef DEBUG",
+	"	 {	int i; uchar *v = (uchar *) &now;",
+	"		printf(\"	set Seed state \");",
+	"		#ifndef NOFAIR",
+	"	  		if (fairness)",
+	"				printf(\"(cnt = %%d:%%d, nrpr=%%d) \",",
+	"				now._cnt[0], now._cnt[1], now._nr_pr);",
+	"		#endif",
+	"		/* for (i = 0; i < n; i++) printf(\"%%d,\", v[i]); */",
+	"		printf(\"\\n\");",
+	"	 }",
+	"	 printf(\"%%ld: cycle check starts\\n\", depth);",
+	"	#endif",
 	"	now._a_t |= (1|16|32);",
-	"	/* 1 = 2nd DFS; (16|32) to help hasher */",
-		"#ifndef NOFAIR",
-#if 0
-	"	if (fairness)",
-	"	{	now._a_t &= ~2;   /* pre-apply Rule 3 */",
-	"		now._cnt[1] = 0;", /* reset both a-bit and cnt=0 */
-	"	/* avoid matching seed on claim stutter on this state */",
-	"	}",
-#else
-	"	now._cnt[1] = now._cnt[0];",
-#endif
-		"#endif",
+	"	/* 1 = 2nd DFS; (16|32) to improve hashing */",
+	"	#ifndef NOFAIR",
+	"		now._cnt[1] = now._cnt[0];",
+	"	#endif",
 	"	memcpy((char *)&A_Root, (char *)&now, vsize);",
 	"	A_depth = depthfound = depth;",
-	"	new_state();	/* start 2nd DFS */",
+
+	"	#if NCORE>1",
+	"		mem_put_acc();", /* handoff accept states */
+	"	#else",
+	"		new_state();	/* start 2nd DFS */",
+	"	#endif",
+
 	"	now._a_t = o_a_t;",
-	"#ifndef NOFAIR",
-	"	now._cnt[1] = o_cnt;",
-	"#endif",
+	"	#ifndef NOFAIR",
+	"		now._cnt[1] = o_cnt;",
+	"	#endif",
 	"	A_depth = 0; depthfound = -1;",
 		"#ifdef DEBUG",
-	"	printf(\"%%d: cycle check returns\\n\", depth);",
+	"	printf(\"%%ld: cycle check returns\\n\", depth);",
 		"#endif",
 		"#ifdef FULLSTACK",
 		"#ifndef MA",
@@ -4331,60 +7003,120 @@
 		"#endif",
 		"#endif",
 	"}",
-	"#endif\n",
+	"#endif",
+	"",
 	"#if defined(FULLSTACK) && defined(BITSTATE)",
-	"struct H_el *Free_list = (struct H_el *) 0;",
+	"H_el *Free_list = (H_el *) 0;",
 	"void",
 	"onstack_init(void)	/* to store stack states in a bitstate search */",
-	"{	S_Tab = (struct H_el **) emalloc(maxdepth*sizeof(struct H_el *));",
+	"{	S_Tab = (H_el **) emalloc(maxdepth*sizeof(H_el *));",
 	"}",
-	"struct H_el *",
-	"grab_state(int n)",
-	"{	struct H_el *v, *last = 0;",
-	"	if (H_tab == S_Tab)",
-	"	{	for (v = Free_list; v && ((int) v->tagged >= n); v=v->nxt)",
-	"		{	if ((int) v->tagged == n)",
-	"			{	if (last)",
-	"					last->nxt = v->nxt;",
-	"				else",
-	"gotcha:				Free_list = v->nxt;",
-	"				v->tagged = 0;",
-	"				v->nxt = 0;",
-		"#ifdef COLLAPSE",
-	"				v->ln = 0;",
-		"#endif",
-	"				return v;",
-	"			}",
-	"			Fh++; last=v;",
-	"		}",
-	"		/* new: second try */",
-	"		v = Free_list;", /* try to avoid emalloc */
-	"		if (v && ((int) v->tagged >= n))",
-	"			goto gotcha;",
-	"		ngrabs++;",
-	"	}",
-	"	return (struct H_el *)",
-	"	      emalloc(sizeof(struct H_el)+n-sizeof(unsigned));",
-	"}\n",
-	"#else",
-	"#define grab_state(n) (struct H_el *) \\",
-	"		emalloc(sizeof(struct H_el)+n-sizeof(unsigned));",
 	"#endif",
+
+	"#if !defined(BFS_PAR)",
+	" #if defined(FULLSTACK) && defined(BITSTATE)",
+		"H_el *",
+		"grab_state(int n)",
+		"{	H_el *v, *last = 0;",
+		"	if (H_tab == S_Tab)",
+		"	{	for (v = Free_list; v && ((int) v->tagged >= n); v=v->nxt)",
+		"		{	if ((int) v->tagged == n)",
+		"			{	if (last)",
+		"					last->nxt = v->nxt;",
+		"				else",
+		"gotcha:				Free_list = v->nxt;",
+		"				v->tagged = 0;",
+		"				v->nxt = 0;",
+		"	#ifdef COLLAPSE",
+		"				v->ln = 0;",
+		"	#endif",
+		"				return v;",
+		"			}",
+		"			Fh++; last=v;",
+		"		}",
+		"		/* new: second try */",
+		"		v = Free_list;", /* try to avoid emalloc */
+		"		if (v && ((int) v->tagged >= n))",
+		"			goto gotcha;",
+		"		ngrabs++;",
+		"	}",
+		"	return (H_el *) emalloc(sizeof(H_el)+n-sizeof(unsigned));",
+		"}",
+	" #else",		/* !FULLSTACK || !BITSTATE */
+		"#if NCORE>1",
+			"H_el *",
+			"grab_state(int n)",
+			"{	H_el *grab_shared(int);",
+			"	return grab_shared(sizeof(H_el)+n-sizeof(unsigned));",
+			"}",
+		"#else", /* ! NCORE>1 */
+			"#ifndef AUTO_RESIZE",
+			"	#define grab_state(n) (H_el *) \\",
+			"		emalloc(sizeof(H_el)+n-sizeof(ulong));",
+			"#else",	/* AUTO_RESIZE */
+			"H_el *",
+			"grab_state(int n)",
+			"{	H_el *p;",
+			"	int cnt = sizeof(H_el)+n-sizeof(ulong);",
+			"#ifndef MA",
+			"	if (reclaim_size >= cnt+WS)",
+			"	{	if ((cnt & (WS-1)) != 0) /* alignment */",
+			"		{	cnt += WS - (cnt & (WS-1));",
+			"		}",
+			"		p = (H_el *) reclaim_mem;",
+			"		reclaim_mem  += cnt;",
+			"		reclaim_size -= cnt;",
+			"		memset(p, 0, cnt);",
+			"	} else",
+			"#endif",
+			"	{	p = (H_el *) emalloc(cnt);",
+			"	}",
+			"	return p;",
+			"}",
+			"#endif",	/* AUTO_RESIZE */
+		"#endif", 		/* NCORE>1 */
+	" #endif",			/* FULLSTACK && !BITSTATE */
+	"#else", /* BFS_PAR */
+	"	extern volatile uchar *sh_pre_malloc(ulong);",
+	"	extern volatile uchar *sh_malloc(ulong);",
+	"	H_el *",
+	"	grab_state(int n)	/* bfs_par */",
+	"	{	volatile uchar *rval = NULL;",
+	"		int m = sizeof(H_el) + n - sizeof(unsigned);",
+	"",
+	"		if (n == 0) m = m/n;",
+	"	#ifdef BFS_SEP_HASH",
+	"		rval = emalloc((ulong) m);",
+	"	#else",
+	"		rval = sh_malloc((ulong) m);",
+	"	#endif",
+	"		memset((void *) rval, 0, (size_t) m);",
+	"",
+	"		return (H_el *) rval;",
+	"	}",
+	"#endif", /* BFS_PAR */
+
 "#ifdef COLLAPSE",
-	"unsigned long",
+	"ulong",
 	"ordinal(char *v, long n, short tp)",
-	"{	struct H_el *tmp, *ntmp; long m;",
-	"	struct H_el *olst = (struct H_el *) 0;",
+	"{	H_el *tmp, *ntmp; long m;",
+	"	H_el *olst = (H_el *) 0;",
 	"	s_hash((uchar *)v, n);",
-	"	tmp = H_tab[j1];",
+
+	"#if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"	e_critical(BFS_ID);	/* bfs_par / collapse */",
+	"#endif",
+	"#if NCORE>1 && !defined(SEP_STATE)",
+	"	enter_critical(CS_ID);	/* uses spinlock - 1..128 */",
+	"#endif",
+	"	tmp = H_tab[j1_spin];",
 	"	if (!tmp)",
 	"	{	tmp = grab_state(n);",
-	"		H_tab[j1] = tmp;",
+	"		H_tab[j1_spin] = tmp;",
 	"	} else",
 	"	for ( ;; olst = tmp, tmp = tmp->nxt)",
-	"	{	m = memcmp(((char *)&(tmp->state)), v, n);",
-	"		if (n == tmp->ln)",
-	"		{",
+	"	{	if (n == tmp->ln)",
+	"		{	m = memcmp(((char *)&(tmp->state)), v, n);",
 	"			if (m == 0)",
 	"				goto done;",
 	"			if (m < 0)",
@@ -4392,7 +7124,7 @@
 	"Insert:			ntmp = grab_state(n);",
 	"				ntmp->nxt = tmp;",
 	"				if (!olst)",
-	"					H_tab[j1] = ntmp;",
+	"					H_tab[j1_spin] = ntmp;",
 	"				else",
 	"					olst->nxt = ntmp;",
 	"				tmp = ntmp;",
@@ -4410,15 +7142,38 @@
 	"		else if (!tmp->nxt)",
 	"			goto Append;",
 	"	}",
+	"#if NCORE>1 && !defined(SEP_STATE)",
+	"	enter_critical(GLOBAL_LOCK);",
+	"#endif",
+	"#ifdef BFS_PAR",
+	"	e_critical(BFS_ORD);	/* bfs_par */",
+	"#endif",
 	"	m = ++ncomps[tp];",
+	"#ifdef BFS_PAR",
+	"	x_critical(BFS_ORD);",
+	"#endif",
+	"#if NCORE>1 && !defined(SEP_STATE)",
+	"	leave_critical(GLOBAL_LOCK);",
+	"#endif",
 	"#ifdef FULLSTACK",
 	"	tmp->tagged = m;",
 	"#else",
 	"	tmp->st_id  = m;",
 	"#endif",
+	"#if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+	"	tmp->m_K1 = K1;",
+	"#endif",
 	"	memcpy(((char *)&(tmp->state)), v, n);",
 	"	tmp->ln = n;",
 	"done:",
+
+	"#if NCORE>1 && !defined(SEP_STATE)",
+	"	leave_critical(CS_ID);",
+	"#endif",
+	"#if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"	x_critical(BFS_ID);",
+	"#endif",
+
 	"#ifdef FULLSTACK",
 	"	return tmp->tagged;",
 	"#else",
@@ -4430,7 +7185,7 @@
 	"compress(char *vin, int nin)	/* collapse compression */",
 	"{	char	*w, *v = (char *) &comp_now;",
 	"	int	i, j;",
-	"	unsigned long	n;",
+	"	ulong	n;",
 	"	static char	*x;",
 	"	static uchar	nbytes[513]; /* 1 + 256 + 256 */",
 	"	static unsigned	short nbytelen;",
@@ -4523,7 +7278,7 @@
 		"#if VECTORSZ<65536",
 		"	w = (char *) &(now._vsz) + sizeof(unsigned short);",
 		"#else",
-		"	w = (char *) &(now._vsz) + sizeof(unsigned long);",
+		"	w = (char *) &(now._vsz) + sizeof(ulong);",
 		"#endif",
 	"#endif",
 	"	x = scratch;",
@@ -4535,8 +7290,14 @@
 	"	else",
 	"		n = pptr(0) - (uchar *) w;",
 	"	j = w - (char *) &now;",
+	"",
+	"#if !defined(NOCOMP) && !defined(HC)",
 	"	for (i = 0; i < (int) n; i++, w++)",
 	"		if (!Mask[j++]) *x++ = *w;",
+	"#else",
+	"	memcpy(x, w, n); x += n;",
+	"#endif",
+	"",
 	"#ifndef SEPQS",
 	"	for (i = 0; i < (int) now._nr_qs; i++)",
 	"		x += col_q(i, x);",
@@ -4572,7 +7333,7 @@
 	"	return v - (char *)&comp_now;",
 	"}",
 
-"#else",
+"#else",	/* !COLLAPSE */
 "#if !defined(NOCOMP)",
 	"int",
 	"compress(char *vin, int n)	/* default compression */",
@@ -4600,11 +7361,56 @@
 	"	char *vv = vin;",
 	"	char *v = (char *) &comp_now;",
 	"	int i;",
-	"	for (i = 0; i < n; i++, vv++)",
-	"		if (!Mask[i]) *v++ = *vv;",
-	"	for (i = 0; i < WS-1; i++)",
-	"		*v++ = 0;",
-	"	v -= i;",
+	"  #ifndef NO_FAST_C", /* disable faster compress */
+	"	int r = 0, unroll = n/8;", /* most sv are much longer */
+	"	if (unroll > 0)",
+	"	{	i = 0;",
+	"		while (r++ < unroll)",
+	"		{	/* unroll 8 times, avoid ifs */",
+	"	/* 1 */		*v = *vv++; v += 1 - Mask[i++];",
+	"	/* 2 */		*v = *vv++; v += 1 - Mask[i++];",
+	"	/* 3 */		*v = *vv++; v += 1 - Mask[i++];",
+	"	/* 4 */		*v = *vv++; v += 1 - Mask[i++];",
+	"	/* 5 */		*v = *vv++; v += 1 - Mask[i++];",
+	"	/* 6 */		*v = *vv++; v += 1 - Mask[i++];",
+	"	/* 7 */		*v = *vv++; v += 1 - Mask[i++];",
+	"	/* 8 */		*v = *vv++; v += 1 - Mask[i++];",
+	"		}",
+	"		r = n - i; /* the rest, at most 7 */",
+	"		switch (r) {",
+	"		case 7: *v = *vv++; v += 1 - Mask[i++];",
+	"		case 6: *v = *vv++; v += 1 - Mask[i++];",
+	"		case 5: *v = *vv++; v += 1 - Mask[i++];",
+	"		case 4: *v = *vv++; v += 1 - Mask[i++];",
+	"		case 3: *v = *vv++; v += 1 - Mask[i++];",
+	"		case 2: *v = *vv++; v += 1 - Mask[i++];",
+	"		case 1: *v = *vv++; v += 1 - Mask[i++];",
+	"		case 0: break;",
+	"		}",
+	"		n = i = v - (char *)&comp_now; /* bytes written so far */",
+	"		r = (n+WS-1)/WS; /* in words, rounded up */",
+	"		r *= WS;	 /* total bytes to fill  */",
+	"		i = r - i;	 /* remaining bytes      */",
+	"		switch (i) {",   /* fill word */
+	"		case 7: *v++ = 0;    /* fall thru */",
+	"		case 6: *v++ = 0;",
+	"		case 5: *v++ = 0;",
+	"		case 4: *v++ = 0;",
+	"		case 3: *v++ = 0;",
+	"		case 2: *v++ = 0;",
+	"		case 1: *v++ = 0;",
+	"		case 0: break;",
+	"		default: Uerror(\"unexpected wordsize\");",
+	"		}",
+	"		v -= i;",
+	"	} else",
+	"  #endif",
+	"	{	for (i = 0; i < n; i++, vv++)",
+	"			if (!Mask[i]) *v++ = *vv;",
+	"		for (i = 0; i < WS-1; i++)",
+	"			*v++ = 0;",
+	"		v -= i;",
+	"	}",
 		"#if 0",
 	"	printf(\"compress %%d -> %%d\\n\",",
 	"		n, v - (char *)&comp_now);",
@@ -4613,7 +7419,7 @@
 	"#endif",
 	"}",
 "#endif",
-"#endif",
+"#endif",	/* COLLAPSE */
 	"#if defined(FULLSTACK) && defined(BITSTATE)",
 "#if defined(MA)",
 	"#if !defined(onstack_now)",
@@ -4628,9 +7434,15 @@
 "#else",
 	"void",
 	"onstack_zap(void)",
-	"{	struct H_el *v, *w, *last = 0;",
-	"	struct H_el **tmp = H_tab;",
-	"	char *nv; int n, m;\n",
+	"{	H_el *v, *w, *last = 0;",
+	"	H_el **tmp = H_tab;",
+	"	char *nv; int n, m;",
+	"	static char warned = 0;",
+	"#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+	"	uchar was_last = now._last;",
+	"	now._last = 0;",
+	"#endif",
+	"",
 	"	H_tab = S_Tab;",
 	"#ifndef NOCOMP",
 	"	nv = (char *) &comp_now;",
@@ -4648,7 +7460,7 @@
 	"	s_hash((uchar *)nv, n);",
 	"#endif",
 	"	H_tab = tmp;",
-	"	for (v = S_Tab[j1]; v; Zh++, last=v, v=v->nxt)",
+	"	for (v = S_Tab[j1_spin]; v; Zh++, last=v, v=v->nxt)",
 	"	{	m = memcmp(&(v->state), nv, n);",
 	"		if (m == 0)",
 	"			goto Found;",
@@ -4656,101 +7468,190 @@
 	"			break;",
 	"	}",
 	"/* NotFound: */",
-	"	Uerror(\"stack out of wack - zap\");",
-	"	return;",
+	"#ifndef ZAPH",
+	"	/* seen this happen, likely harmless in multicore */",
+	"	if (warned == 0)",
+	"	{	/* Uerror(\"stack out of wack - zap\"); */",
+	"		cpu_printf(\"pan: warning, stack incomplete\\n\");",
+	"		warned = 1;",
+	"	}",
+	"#endif",
+	"	goto done;",
 	"Found:",
 	"	ZAPS++;",
 	"	if (last)",
 	"		last->nxt = v->nxt;",
 	"	else",
-	"		S_Tab[j1] = v->nxt;",
+	"		S_Tab[j1_spin] = v->nxt;",
 	"	v->tagged = (unsigned) n;",
 	"#if !defined(NOREDUCE) && !defined(SAFETY)",
 	"	v->proviso = 0;",
 	"#endif",
-	"	v->nxt = last = (struct H_el *) 0;",
+	"	v->nxt = last = (H_el *) 0;",
 	"	for (w = Free_list; w; Fa++, last=w, w = w->nxt)",
 	"	{	if ((int) w->tagged <= n)",
 	"		{	if (last)",
-	"			{	v->nxt = w; /* was: v->nxt = w->nxt; */",
+	"			{	v->nxt = w;",
 	"				last->nxt = v;",
 	"			} else",
 	"			{	v->nxt = Free_list;",
 	"				Free_list = v;",
 	"			}",
-	"			return;",
+	"			goto done;",
 	"		}",
 	"		if (!w->nxt)",
 	"		{	w->nxt = v;",
-	"			return;",
+	"			goto done;",
 	"	}	}",
 	"	Free_list = v;",
-	"}",
-	"void",
-	"onstack_put(void)",
-	"{	struct H_el **tmp = H_tab;",
-	"	H_tab = S_Tab;",
-	"	if (hstore((char *)&now, vsize) != 0)",
-	"#if defined(BITSTATE) && defined(LC)",
-	"		printf(\"pan: warning, double stack entry\\n\");",
-	"#else",
-	"		Uerror(\"cannot happen - unstack_put\");",
+	"done:",
+	"#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+	"	now._last = was_last;",
 	"#endif",
-	"	H_tab = tmp;",
-	"	trpt->ostate = Lstate;",
-	"	PUT++;",
+	"	return;",
 	"}",
-	"int",
-	"onstack_now(void)",
-	"{	struct H_el *tmp;",
-	"	struct H_el **tmp2 = H_tab;",
-	"	char *v; int n, m = 1;\n",
-	"	H_tab = S_Tab;",
-	"#ifdef NOCOMP",
-		"#if defined(BITSTATE) && defined(LC)",
-	"	v = (char *) &comp_now;",
-	"	n = compact_stack((char *)&now, vsize);",
-		"#else",
-	"	v = (char *) &now;",
-	"	n = vsize;",
-		"#endif",
-	"#else",
-	"	v = (char *) &comp_now;",
-	"	n = compress((char *)&now, vsize);",
-	"#endif",
-	"#if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
-	"	s_hash((uchar *)v, n);",
-	"#endif",
-	"	H_tab = tmp2;",
-	"	for (tmp = S_Tab[j1]; tmp; Zn++, tmp = tmp->nxt)",
-	"	{	m = memcmp(((char *)&(tmp->state)),v,n);",
-	"		if (m <= 0)",
-	"		{	Lstate = (struct H_el *) tmp;",
-	"			break;",
-	"	}	}",
-	"	PROBE++;",
-	"	return (m == 0);",
-	"}",
-	"#endif",
-"#endif",
+	"",
+	"#ifndef BFS_PAR",
+	"	void",
+	"	onstack_put(void)",
+	"	{	H_el **tmp = H_tab;",
+	"	#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+	"		uchar was_last = now._last;",
+	"		now._last = 0;",
+	"	#endif",
+	"		H_tab = S_Tab;",
+	"		if (h_store((char *)&now, vsize) != 0)",
+	"	#if defined(BITSTATE) && defined(LC)",
+	"			printf(\"pan: warning, double stack entry\\n\");",
+	"	#else",
+	"		#ifndef ZAPH",
+	"			Uerror(\"cannot happen - unstack_put\");",
+	"		#endif",
+	"	#endif",
+	"		H_tab = tmp;",
+	"		trpt->ostate = Lstate;",
+	"		PUT++;",
+	"	#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+	"		now._last = was_last;",
+	"	#endif",
+	"	}",
+	"	int",
+	"	onstack_now(void)",
+	"	{	H_el *tmp;",
+	"		H_el **tmp2 = H_tab;",
+	"		char *v; int n, m = 1;\n",
+	"	#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+	"		uchar was_last = now._last;",
+	"		now._last = 0;",
+	"	#endif",
+	"		H_tab = S_Tab;",
+	"	#ifdef NOCOMP",
+	"		#if defined(BITSTATE) && defined(LC)",
+	"			v = (char *) &comp_now;",
+	"			n = compact_stack((char *)&now, vsize);",
+	"		#else",
+	"			v = (char *) &now;",
+	"			n = vsize;",
+	"		#endif",
+	"	#else",
+	"		v = (char *) &comp_now;",
+	"		n = compress((char *)&now, vsize);",
+	"	#endif",
+	"	#if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
+	"		s_hash((uchar *)v, n);",
+	"	#endif",
+	"		H_tab = tmp2;",
+	"		for (tmp = S_Tab[j1_spin]; tmp; Zn++, tmp = tmp->nxt)",
+	"		{	m = memcmp(((char *)&(tmp->state)),v,n);",
+	"			if (m <= 0)",
+	"			{	Lstate = (H_el *) tmp;	/* onstack_now */",
+	"				break;",
+	"		}	}",
+	"		PROBE++;",
+	"	#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+	"		now._last = was_last;",
+	"	#endif",
+	"		return (m == 0);",
+	"	}",
+	"#endif",	/* !BFS_PAR */
+"#endif",		/* !MA */
+	"#endif",	/* FULLSTACK && BITSTATE */
 
-	"#ifndef BITSTATE",
+	"#ifdef BITSTATE",
+	"void init_SS(ulong);",
+	"",
 	"void",
-	"hinit(void)",
+	"sinit(void)",
 	"{",
-"#ifdef MA",
-	"#ifdef R_XPT",
-	"	{	void r_xpoint(void);",
-	"		r_xpoint();",
+	"	if (udmem)",
+	"	{	udmem *= 1024L*1024L;",
+	"	#if NCORE>1",
+	"		if (!readtrail)",
+	"		{	init_SS((ulong) udmem);",
+	"		} else",
+	"	#endif",
+	"	#if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"		SS = (uchar *) sh_pre_malloc((ulong) udmem);",
+	"	#else",
+	"		SS = (uchar *) emalloc(udmem);",
+	"	#endif",
+	"		b_store = bstore_mod;",
+	"	} else",
+	"	{",
+	"	#if NCORE>1",
+	"		init_SS(ONE_L<<(ssize-3));",
+	"	#else",
+	"		#if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"			SS = (uchar *) sh_pre_malloc((ulong)(ONE_L<<(ssize-3)));",
+	"		#else",
+	"			SS = (uchar *) emalloc(ONE_L<<(ssize-3));",
+	"		#endif",
+	"	#endif",
 	"	}",
+	"}",
 	"#else",
-	"	dfa_init((unsigned short) (MA+a_cycles));",
-	"#endif",
-"#endif",
-"#if !defined(MA) || defined(COLLAPSE)",
-	"	H_tab = (struct H_el **)",
-	"		emalloc((1L<<ssize)*sizeof(struct H_el *));",
-"#endif",
+	" #if !defined(MA) || defined(COLLAPSE)",
+	" void",
+	" set_H_tab(void)",
+	" {",
+	"  #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"	H_tab = (H_el **) sh_pre_malloc((ulong)((ONE_L<<ssize)*sizeof(H_el *)));",
+	"  #else",
+	"	H_tab = (H_el **) emalloc((ONE_L<<ssize)*sizeof(H_el *));",
+	"  #endif",
+	" }",
+	" #endif",
+	"void",
+	"hinit(void)",
+	"{",
+	"	#ifdef MA",
+	"		#ifdef R_XPT",
+	"			{	void r_xpoint(void);",
+	"				r_xpoint();",
+	"			}",
+	"		#else",
+	"			dfa_init((unsigned short) (MA+a_cycles));",
+	"			#if NCORE>1 && !defined(COLLAPSE)",
+	"			if (!readtrail)",
+	"			{	void init_HT(ulong);",
+	"				init_HT(0L);",
+	"			}",
+	"			#endif",
+	"		#endif",
+	"	#endif",
+	"	#if !defined(MA) || defined(COLLAPSE)",
+	"		#if NCORE>1 || (defined(BFS_PAR) && defined(USE_TDH) && !defined(WIN32) && !defined(WIN64))",
+	"			if (!readtrail)",
+	"			{	void init_HT(ulong);",
+	"				init_HT((ulong) (ONE_L<<ssize)*sizeof(H_el *));",
+	"			#if defined(TRIX) || (defined(BFS_PAR) && defined(COLLAPSE))",
+	"				set_H_tab(); /* need both */",
+	"			#endif",
+	"			} else",
+	"		#endif",
+	"			{	set_H_tab(); /* @htable ssize */",
+	"			}",
+	"	#endif", /* !defined(MA) || defined(COLLAPSE) */
 	"}",
 	"#endif\n",
 
@@ -4771,13 +7672,17 @@
 	"	}",
 	"#endif",
 	"#ifdef SDUMP",
-	"#ifndef NOCOMP",
 	"	printf(\"\t State: \");",
+	"#if !defined(NOCOMP) && !defined(HC)",
 	"	for (i = 0; i < vsize; i++) printf(\"%%d%%s,\",",
 	"		((char *)&now)[i], Mask[i]?\"*\":\"\");",
+	"#else",
+	"	for (i = 0; i < vsize; i++)",
+	"		printf(\"%%d,\", ((char *)&now)[i]);",
 	"#endif",
 	"	printf(\"\\n\tVector: \");",
-	"	for (i = 0; i < n; i++) printf(\"%%d,\", v[i]);",
+	"	for (i = 0; i < n; i++)",
+	"		printf(\"%%d,\", v[i]);",
 	"	printf(\"\\n\");",
 	"#endif",
 	"}",
@@ -4785,8 +7690,9 @@
 
 "#ifdef MA",
 	"int",
-	"gstore(char *vin, int nin, uchar pbit)",
+	"g_store(char *vin, int nin, uchar pbit)",
 	"{	int n, i;",
+	"	int ret_val = 1;",
 	"	uchar *v;",
 	"	static uchar Info[MA+1];",
 	"#ifndef NOCOMP",
@@ -4794,7 +7700,7 @@
 	"	v = (uchar *) &comp_now;",
 	"#else",
 	"	n = nin;",
-	"	v = vin;",
+	"	v = (uchar *) vin;",
 	"#endif",
 	"	if (n >= MA)",
 	"	{	printf(\"pan: error, MA too small, recompile pan.c\");",
@@ -4801,15 +7707,29 @@
 	"		printf(\" with -DMA=N with N>%%d\\n\", n);",
 	"		Uerror(\"aborting\");",
 	"	}",
-	"	if (n > (int) maxgs) maxgs = (unsigned int) n;",
-
+	"	if (n > (int) maxgs)",
+	"	{	maxgs = (uint) n;",
+	"	}",
 	"	for (i = 0; i < n; i++)",
-	"		Info[i] = v[i];",
+	"	{	Info[i] = v[i];",
+	"	}",
 	"	for ( ; i < MA-1; i++)",
-	"		Info[i] = 0;",
+	"	{	Info[i] = 0;",
+	"	}",
 	"	Info[MA-1] = pbit;",
 	"	if (a_cycles)	/* place _a_t at the end */",
-	"	{	Info[MA] = Info[0]; Info[0] = 0;  }",
+	"	{	Info[MA] = Info[0];",
+	"		Info[0]  = 0;",
+	"	}",
+	"",
+	"#ifdef BFS_PAR",
+	"	e_critical(BFS_STATE);	/* bfs_par / g_store */",
+	"#endif",
+	"#if NCORE>1 && !defined(SEP_STATE)",
+	"	enter_critical(GLOBAL_LOCK); /* crude, but necessary */",
+	"	/* to make this mode work, also replace emalloc with grab_shared inside store MA routines */",
+	"#endif",
+	"",
 	"	if (!dfa_store(Info))",
 	"	{	if (pbit == 0",
 	"		&& (now._a_t&1)",
@@ -4819,16 +7739,17 @@
 	"			{	Info[MA-1] = 4; /* off-stack bit */",
 	"				nShadow++;",
 	"				if (!dfa_member(MA-1))",
-	"				{",
-	"#ifdef VERBOSE",
-	"		printf(\"intersected 1st dfs stack\\n\");",
-	"#endif",
-	"					return 3;",
+	"				{	ret_val = 3;",
+	"			#ifdef VERBOSE",
+	"					printf(\"intersected 1st dfs stack\\n\");",
+	"			#endif",
+	"					goto done;",
 	"		}	}	}",
-	"#ifdef VERBOSE",
+	"		ret_val = 0;",
+	"	#ifdef VERBOSE",
 	"		printf(\"new state\\n\");",
-	"#endif",
-	"		return 0;	/* new state */",
+	"	#endif",
+	"		goto done;",
 	"	}",
 	"#ifdef FULLSTACK",
 	"	if (pbit == 0)",
@@ -4837,23 +7758,32 @@
 	"		trpt->proviso = dfa_member(MA-1);",
 	"#endif",
 	"		Info[MA-1] = 4;	/* off-stack bit */",
-	"		if (dfa_member(MA-1)) {",
-	"#ifdef VERBOSE",
+	"		if (dfa_member(MA-1))",
+	"		{	ret_val = 1; /* off-stack */",
+	"	#ifdef VERBOSE",
 	"			printf(\"old state\\n\");",
-	"#endif",
-	"			return 1; /* off-stack */",
-	"		} else {",
-	"#ifdef VERBOSE",
+	"	#endif",
+	"		} else",
+	"		{	ret_val = 2; /* on-stack */",
+	"	#ifdef VERBOSE",
 	"			printf(\"on-stack\\n\");",
-	"#endif",
-	"			return 2; /* on-stack */",
+	"	#endif",
 	"		}",
+	"		goto done;",
 	"	}",
 	"#endif",
+	"	ret_val = 1;",
 	"#ifdef VERBOSE",
-	"		printf(\"old state\\n\");",
+	"	printf(\"old state\\n\");",
 	"#endif",
-	"	return 1;	/* old state */",
+	"done:",
+	"#ifdef BFS_PAR",
+	"	x_critical(BFS_STATE);",
+	"#endif",
+	"#if NCORE>1 && !defined(SEP_STATE)",
+	"	leave_critical(GLOBAL_LOCK);",
+	"#endif",
+	"	return ret_val;	/* old state */",
 	"}",
 "#endif",
 
@@ -4873,15 +7803,120 @@
 	"}",
 	"#endif",
 
+	"#ifdef TRIX",
+	"void",
+	"sv_populate(void)",
+	"{	int i, cnt = 0;",
+	"	TRIX_v6 **base = processes;",
+	"	int bound = now._nr_pr; /* MAXPROC+1; */",
+	"#ifdef V_TRIX",
+	"	printf(\"%%4d: sv_populate\\n\", depth);",
+	"#endif",
+	"again:",
+	"	for (i = 0; i < bound; i++)",
+	"	{	if (base[i] != NULL)",
+	"		{	H_el *tmp;",
+	"			int m, n; uchar *v;",
+	"#ifndef BFS",
+	"			if (base[i]->modified == 0)",
+	"			{	cnt++;",
+	"	#ifdef V_TRIX",
+	"				printf(\"%%4d: %%s %%d not modified\\n\",",
+	"				depth, (base == processes)?\"proc\":\"chan\", i);",
+	"	#endif",
+	"				continue;",
+	"			}",
+	"	#ifndef V_MOD",
+	"			base[i]->modified = 0;",
+	"	#endif",
+	"#endif",
+	"#ifdef TRIX_RIX",
+	"			if (base == processes)",
+	"			{	((P0 *)pptr(i))->_pid = 0;",
+	"			}",
+	"#endif",
+	"			n = base[i]->psize;",
+	"			v = base[i]->body;",
+	"			s_hash(v, n); /* sets j1_spin */",
+	"			tmp = H_tab[j1_spin];",
+	"			if (!tmp)	/* new */",
+	"			{	tmp = grab_state(n);",
+	"				H_tab[j1_spin] = tmp;",
+	"				m = 1; /* non-zero */",
+	"			} else",
+	"			{  H_el *ntmp, *olst = (H_el *) 0;",
+	"			   for (;; hcmp++, olst = tmp, tmp = tmp->nxt)",
+	"			   { 	m = memcmp(((char *)&(tmp->state)), v, n);",
+	"				if (m == 0)	/* match */",
+	"				{	break;",
+	"				} else if (m < 0) /* insert */",
+	"				{	ntmp = grab_state(n);",
+	"					ntmp->nxt = tmp;",
+	"					if (!olst)",
+	"						H_tab[j1_spin] = ntmp;",
+	"					else",
+	"						olst->nxt = ntmp;",
+	"					tmp = ntmp;",
+	"					break;",
+	"				} else if (!tmp->nxt)	/* append */",
+	"				{	tmp->nxt = grab_state(n);",
+	"					tmp = tmp->nxt;",
+	"					break;",
+	"			}  }	}",
+	"			if (m != 0)",
+	"			{	memcpy((char *)&(tmp->state), v, n);",
+	"#if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+	"				tmp->m_K1 = K1; /* set via s_hash */",
+	"#endif",
+	"				if (verbose)",
+	"				{	if (base == processes)",
+	"					{	_p_count[i]++;",
+	"					} else",
+	"					{	_c_count[i]++;",
+	"			}	}	}",
+	"			now._ids_[cnt++] = (char *)&(tmp->state);",
+	"#ifdef TRIX_RIX",
+	"			if (base == processes)",
+	"			{	((P0 *)pptr(i))->_pid = i;",
+	"				if (BASE > 0 && i > 0)",
+	"				{	((P0 *)pptr(i))->_pid -= BASE;",
+	"			}	}",
+	"#endif",
+	"	}	}",
+#if 0
+	if a process appears or disappears: always secure a full sv_populate
+	(channels come and go only with a process)
+
+	only one process can disappear per step
+	but any nr of channels can be removed at the same time
+		if a process disappears, all subsequent entries
+		are then in the wrong place in the _ids_ list
+		and need to be recomputed
+	but we do not need to fill out with zeros
+		because vsize prevents them being used
+#endif
+	"	/* do the same for all channels */",
+	"	if (base == processes)",
+	"	{	base = channels;",
+	"		bound = now._nr_qs; /* MAXQ+1; */",
+	"		goto again;",
+	"	}",
+	"}",
+	"#endif\n",
+	"#if !defined(BFS_PAR) || (!defined(BITSTATE) && !defined(USE_TDH))",
 	"int",
-	"hstore(char *vin, int nin)	/* hash table storage */",
-	"{	struct H_el *tmp, *ntmp, *olst = (struct H_el *) 0;",
+	"h_store(char *vin, int nin)	/* hash table storage */",
+	"{	H_el *ntmp;",
+	"	H_el *tmp, *olst = (H_el *) 0;",
 	"	char *v; int n, m=0;",
-	"#ifdef HC",
+	" #ifdef HC",
 	"	uchar rem_a;",
-	"#endif",
-	"#ifdef NOCOMP",	/* defined by BITSTATE */
-		"#if defined(BITSTATE) && defined(LC)",
+	" #endif",
+	" #ifdef TRIX",
+	"	sv_populate();	/* update proc and chan ids */",
+	" #endif",
+	" #ifdef NOCOMP",	/* defined by BITSTATE */
+	"	#if defined(BITSTATE) && defined(LC)",
 	"	if (S_Tab == H_tab)",
 	"	{	v = (char *) &comp_now;",
 	"		n = compact_stack(vin, nin);",
@@ -4888,19 +7923,20 @@
 	"	} else",
 	"	{	v = vin; n = nin;",
 	"	}",
-		"#else",
+	"	#else",
 	"	v = vin; n = nin;",
-		"#endif",
-	"#else",
+	"	#endif",
+	" #else",
 	"	v = (char *) &comp_now;",
 	"	#ifdef HC",
-	"	rem_a = now._a_t;",	/* 4.3.0 */
+	"	rem_a = now._a_t;",	/* new 5.0 */
 	"	now._a_t = 0;",	/* for hashing/state matching to work right */
 	"	#endif",
-	"	n = compress(vin, nin);", /* with HC, this calls s_hash */
+	"	n = compress(vin, nin);", /* with HC, this calls s_hash -- but on vin, not on v... */
 	"	#ifdef HC",
-	"	now._a_t = rem_a;",	/* 4.3.0 */
+	"	now._a_t = rem_a;",	/* new 5.0 */
 	"	#endif",
+		/* with HC4 -a, compress copies K1 and K2 into v[], leaving v[0] free for the a-bit */
 		"#ifndef SAFETY",
 	"	if (S_A)",
 	"	{	v[0] = 0;	/* _a_t  */",
@@ -4911,35 +7947,53 @@
 			"#endif",
 	"		m = 0;",
 	"	}",
-		"#endif",
-	"#endif",
-	"#if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
+	"	#endif",
+	" #endif",
+	" #if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
 	"	s_hash((uchar *)v, n);",
-	"#endif",
-	"	tmp = H_tab[j1];",
+	" #endif",
+	"	/* for BFS_PAR we can only get here in BITSTATE mode */",
+	"	/* and in that case we don't use locks */",
+	" #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"	e_critical(BFS_ID);	/* bfs_par / h_store */",
+	" #endif",
+	" #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+	"	enter_critical(CS_ID);",
+	" #endif",
+	"	tmp = H_tab[j1_spin];",
 	"	if (!tmp)",
-	"	{  tmp = grab_state(n);",
-	"	   H_tab[j1] = tmp;",
+	"	{  tmp = grab_state(n);", /* no zero-returns with bfs_par */
+	" #if NCORE>1",
+	"	   if (!tmp)",
+	"	   {	/* if we get here -- we've already issued a warning */",
+	"		/* but we want to allow the normal distributed termination */",
+	"		/* to collect the stats on all cpus in the wrapup */",
+	"	#if !defined(SEP_STATE) && !defined(BITSTATE)",
+	"		leave_critical(CS_ID);",
+	"	#endif",
+	"		return 1; /* allow normal termination */",
+	"	   }",
+	" #endif",
+	"	   H_tab[j1_spin] = tmp;",
 	"	} else",
 	"	{  for (;; hcmp++, olst = tmp, tmp = tmp->nxt)",
 	"	   {   /* skip the _a_t and the _cnt bytes */",
-	"#ifdef COLLAPSE",
+	" #ifdef COLLAPSE",
 	"		if (tmp->ln != 0)",
 	"		{	if (!tmp->nxt) goto Append;",
 	"			continue;",
 	"		}",
-	"#endif",
+	" #endif",
 	"		m = memcmp(((char *)&(tmp->state)) + S_A, ",
 	"			v + S_A, n - S_A);",
 	"		if (m == 0) {",
-	"#ifdef SAFETY",
+	" #ifdef SAFETY",
 			"#define wasnew	0",
-	"#else",
+	" #else",
 	"		int wasnew = 0;",
-	"#endif",
+	" #endif",
 
-	"#ifndef SAFETY",
-	"#ifndef NOCOMP",
+	" #if !defined(SAFETY) && !defined(NOCOMP)",
 	"		if (S_A)",
 	"		{ if ((((char *)&(tmp->state))[0] & V_A) != V_A)",
 	"		  {	wasnew = 1; nShadow++;",
@@ -4948,7 +8002,7 @@
 		"#ifndef NOFAIR",
 	"		  if (S_A > NFAIR)",
 	"		  {	/* 0 <= now._cnt[now._a_t&1] < MAXPROC */",
-	"			unsigned ci, bp; /* index, bit pos */",
+	"			uint ci, bp; /* index, bit pos */",
 	"			ci = (now._cnt[now._a_t&1] / 8);",
 	"			bp = (now._cnt[now._a_t&1] - 8*ci);",
 	"			if (now._a_t&1)	/* use tail-bits in _cnt */",
@@ -4968,13 +8022,16 @@
 	"		   /* else: wasnew == 0, i.e., old state */",
 		"#endif",
 	"		}",
-	"#endif",
-	"#endif",
+	" #endif",
 
+	" #if NCORE>1",
+	"		Lstate = (H_el *) tmp;	/* h_store */",
+	" #endif",
+
 	"#ifdef FULLSTACK",
 		"#ifndef SAFETY",	/* or else wasnew == 0 */
 	"		if (wasnew)",
-	"		{	Lstate = (struct H_el *) tmp;",
+	"		{	Lstate = (H_el *) tmp;	/* h_store */",
 	"			tmp->tagged |= V_A;",
 	"			if ((now._a_t&1)",
 	"			&& (tmp->tagged&A_V)",
@@ -4982,22 +8039,42 @@
 	"			{",
 	"intersect:",
 		"#ifdef CHECK",
+	" #if NCORE>1",
+	"	printf(\"cpu%%d: \", core_id);",
+	" #endif",
 	"	printf(\"1st dfs-stack intersected on state %%d+\\n\",",
 	"		(int) tmp->st_id);",
 		"#endif",
+
+	" #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"				x_critical(BFS_ID);",
+	" #endif",
+	" #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+	"				leave_critical(CS_ID);",
+	" #endif",
+
 	"				return 3;",
 	"			}",
 		"#ifdef CHECK",
+	" #if NCORE>1",
+	"	printf(\"cpu%%d: \", core_id);",
+	" #endif",
 	"	printf(\"\tNew state %%d+\\n\", (int) tmp->st_id);",
 		"#endif",
 		"#ifdef DEBUG",
 	"	dumpstate(1, (char *)&(tmp->state),n,tmp->tagged);",
 		"#endif",
+	" #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"			x_critical(BFS_ID);",
+	" #endif",
+	" #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+	"			leave_critical(CS_ID);",
+	" #endif",
 	"			return 0;",
 	"		} else",
 		"#endif",
 	"		if ((S_A)?(tmp->tagged&V_A):tmp->tagged)",
-	"		{	Lstate = (struct H_el *) tmp;",
+	"		{	Lstate = (H_el *) tmp;	/* h_store */",
 		"#ifndef SAFETY",
 	"			/* already on current dfs stack */",
 	"			/* but may also be on 1st dfs stack */",
@@ -5014,11 +8091,20 @@
 	"				goto intersect;",
 		"#endif",
 		"#ifdef CHECK",
+	" #if NCORE>1",
+	"	printf(\"cpu%%d: \", core_id);",
+	" #endif",
 	"	printf(\"\tStack state %%d\\n\", (int) tmp->st_id);",
 		"#endif",
 		"#ifdef DEBUG",
 	"	dumpstate(0, (char *)&(tmp->state),n,tmp->tagged);",
 		"#endif",
+	" #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"			x_critical(BFS_ID);",
+	" #endif",
+	" #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+	"			leave_critical(CS_ID);",
+	" #endif",
 	"			return 2; /* match on stack */",
 	"		}",
 	"#else",
@@ -5025,30 +8111,90 @@
 	"		if (wasnew)",
 	"		{",
 		"#ifdef CHECK",
+	" #if NCORE>1",
+	"	printf(\"cpu%%d: \", core_id);",
+	" #endif",
 	"	printf(\"\tNew state %%d+\\n\", (int) tmp->st_id);",
 		"#endif",
 		"#ifdef DEBUG",
 	"	dumpstate(1, (char *)&(tmp->state), n, 0);",
 		"#endif",
+	" #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"			x_critical(BFS_ID);",
+	" #endif",
+	" #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+	"			leave_critical(CS_ID);",
+	" #endif",
 	"			return 0;",
 	"		}",
 	"#endif",
 		"#ifdef CHECK",
+	"#if NCORE>1",
+	"	printf(\"cpu%%d: \", core_id);",
+	"#endif",
 	"	printf(\"\tOld state %%d\\n\", (int) tmp->st_id);",
 		"#endif",
 		"#ifdef DEBUG",
 	"	dumpstate(0, (char *)&(tmp->state), n, 0);",
 		"#endif",
-	"#ifdef REACH",
-	"		if (tmp->D > depth)",
-	"		{	tmp->D = depth;",
-		"#ifdef CHECK",
-	"	printf(\"\t\tReVisiting (from smaller depth)\\n\");",
-		"#endif",
-	"			nstates--;",
+	"#if defined(BCS)",
+	"  #ifdef CONSERVATIVE",
+	"	if (tmp->ctx_low > trpt->sched_limit)",
+	"	{	tmp->ctx_low = trpt->sched_limit;",
+	"		tmp->ctx_pid[(now._last)/8] = 1 << ((now._last)%%8); /* new */",
+	"	#ifdef CHECK",
+	"		#if NCORE>1",
+	"		printf(\"cpu%%d: \", core_id);",
+	"		#endif",
+	"		printf(\"\t\tRevisit with fewer context switches\\n\");",
+	"	#endif",
+	"		nstates--;",
+	"		#if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"		x_critical(BFS_ID);",
+	"		#endif",
+	"		#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+	"		leave_critical(CS_ID);",
+	"		#endif",
+	"		return 0;",
+	"	} else if ((tmp->ctx_low == trpt->sched_limit",
+	"	&&   (tmp->ctx_pid[(now._last)/8] & ( 1 << ((now._last)%%8) )) == 0 ))",
+	"	{	tmp->ctx_pid[(now._last)/8] |= 1 << ((now._last)%%8); /* add */",
+	"	#ifdef CHECK",
+	"		#if NCORE>1",
+	"		printf(\"cpu%%d: \", core_id);",
+	"		#endif",
+	"		printf(\"\t\tRevisit with same nr of context switches\\n\");",
+	"	#endif",
+	"		nstates--;",
+	"		#if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"		x_critical(BFS_ID);",
+	"		#endif",
+	"		#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+	"		leave_critical(CS_ID);",
+	"		#endif",
+	"		return 0;",
+	"	}",
+	"  #endif",
+	"#endif",
+	" #ifdef REACH",
+	"	if (tmp->D > depth)",
+	"	{	tmp->D = depth;",
+	"	#ifdef CHECK",
+	"		#if NCORE>1",
+	"		printf(\"cpu%%d: \", core_id);",
+	"		#endif",
+	"		printf(\"\t\tReVisiting (from smaller depth)\\n\");",
+	"	#endif",
+	"		nstates--;",
+	"	#if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"		x_critical(BFS_ID);",
+	"	#endif",
+	"	#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+	"		leave_critical(CS_ID);",
+	"	#endif",
 #if 0
-  possible variation of iterative search for shortest counter-example (pan -i
-  and pan -I) suggested by Pierre Moro (for safety properties):
+  a possible variation of iterative search for shortest counter-example
+  (pan -i and pan -I) suggested by Pierre Moro (for safety properties):
   state revisits on shorter depths do not start until after
   the first counter-example is found.  this assumes that the max search
   depth is set large enough that a first (possibly long) counter-example
@@ -5056,22 +8202,37 @@
   if set too short, this variant can miss the counter-example, even if
   it would otherwise be shorter than the depth-limit.
   (p.m. unsure if this preserves the guarantee of finding the
-   shortest counter-example - so not enabled yet)
-	"			if (errors > 0 && iterative)", /* Moro */
+   shortest counter-example - so not enabled by default)
+	"		if (errors > 0 && iterative)", /* Moro */
 #endif
-	"			return 0;",
-	"		}",
-	"#endif",
-	"#if defined(BFS) && defined(Q_PROVISO)",
-	"		Lstate = (struct H_el *) tmp;",
-	"#endif",
+	"		return 0;",
+	"	}",
+	" #endif",
+	" #if (defined(BFS) && defined(Q_PROVISO)) || NCORE>1",
+	"		Lstate = (H_el *) tmp;	/* h_store */",
+	" #endif",
+	" #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"		x_critical(BFS_ID);",
+	" #endif",
+	" #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+	"		leave_critical(CS_ID);",
+	" #endif",
 	"		return 1; /* match outside stack */",
 	"	       } else if (m < 0)",
 	"	       {	/* insert state before tmp */",
 	"			ntmp = grab_state(n);",
+	" #if NCORE>1",
+	"			if (!ntmp)",
+	"			{",
+	"	#if !defined(SEP_STATE) && !defined(BITSTATE)",
+	"				leave_critical(CS_ID);",
+	"	#endif",
+	"				return 1;  /* allow normal termination */",
+	"			}",
+	" #endif",
 	"			ntmp->nxt = tmp;",
 	"			if (!olst)",
-	"				H_tab[j1] = ntmp;",
+	"				H_tab[j1_spin] = ntmp;",
 	"			else",
 	"				olst->nxt = ntmp;",
 	"			tmp = ntmp;",
@@ -5078,16 +8239,28 @@
 	"			break;",
 	"	       } else if (!tmp->nxt)",
 	"	       {	/* append after tmp */",
-	"#ifdef COLLAPSE",
+	" #ifdef COLLAPSE",
 	"Append:",
-	"#endif",
+	" #endif",
 	"			tmp->nxt = grab_state(n);",
+	" #if NCORE>1",
+	"			if (!tmp->nxt)",
+	"			{",
+	"	#if !defined(SEP_STATE) && !defined(BITSTATE)",
+	"				leave_critical(CS_ID);",
+	"	#endif",
+	"				return 1;  /* allow normal termination */",
+	"			}",
+	" #endif",
 	"			tmp = tmp->nxt;",
 	"			break;",
 	"	   }   }",
 	"	}",
-	"#ifdef CHECK",
+	" #ifdef CHECK",
 	"	tmp->st_id = (unsigned) nstates;",
+	" #if NCORE>1",
+	"	printf(\"cpu%%d: \", core_id);",
+	" #endif",
 		"#ifdef BITSTATE",
 	"	printf(\"	Push state %%d\\n\", ((int) nstates) - 1);",
 		"#else",
@@ -5094,16 +8267,21 @@
 	"	printf(\"	New state %%d\\n\", (int) nstates);",
 		"#endif",
 	"#endif",
-	"#if !defined(SAFETY) || defined(REACH)",
+	" #if defined(BCS)",
+	"	tmp->ctx_low = trpt->sched_limit;",
+	"	#ifdef CONSERVATIVE",
+	"	tmp->ctx_pid[(now._last)/8] = 1 << ((now._last)%%8); /* new limit */",
+	"	#endif",
+	" #endif",
+	" #if !defined(SAFETY) || defined(REACH)",
 	"	tmp->D = depth;",
-	"#endif",
-	"#ifndef SAFETY",
-	"#ifndef NOCOMP",
+	" #endif",
+	" #if !defined(SAFETY) && !defined(NOCOMP)",
 	"	if (S_A)",
 	"	{	v[0] = V_A;",
 		"#ifndef NOFAIR",
 	"		if (S_A > NFAIR)",
-	"		{	unsigned ci, bp; /* as above */",
+	"		{	uint ci, bp; /* as above */",
 	"			ci = (now._cnt[now._a_t&1] / 8);",
 	"			bp = (now._cnt[now._a_t&1] - 8*ci);",
 	"			if (now._a_t&1)",
@@ -5114,26 +8292,409 @@
 	"		}",
 		"#endif",
 	"	}",
-	"#endif",
-	"#endif",
+	" #endif",
+	" #if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+	"	tmp->m_K1 = K1;",
+	" #endif",
 	"	memcpy(((char *)&(tmp->state)), v, n);",
-	"#ifdef FULLSTACK",
+	" #ifdef FULLSTACK",
 	"	tmp->tagged = (S_A)?V_A:(depth+1);",
 		"#ifdef DEBUG",
-	"	dumpstate(-1, v, n, tmp->tagged);",
+	"		dumpstate(-1, v, n, tmp->tagged);",
 		"#endif",
-	"	Lstate = (struct H_el *) tmp;",
+	"	Lstate = (H_el *) tmp;	/* end of h_store */",
+	" #else",
+	"	#ifdef DEBUG",
+	"		dumpstate(-1, v, n, 0);",
+	"	#endif",
+	"	#if NCORE>1",
+	"		Lstate = (H_el *) tmp;	/* end of h_store */",
+	"	#endif",
+	" #endif",
+
+	" #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+	"		x_critical(BFS_ID);",
+	" #endif",
+	" #if NCORE>1",
+	"	#ifdef V_PROVISO",
+	"		tmp->cpu_id = core_id;",
+	"	#endif",
+	"	#if !defined(SEP_STATE) && !defined(BITSTATE)",
+	"		leave_critical(CS_ID);",
+	"	#endif",
+	" #endif",
+
+	"	return 0;",
+	"}",	/* end of h_store */
+	"#endif", /* !BFS_PAR || !USE_TDH */
+	"",
+	"void",
+	"o_hash32(uchar *s, int len, int h) /* 32-bit, like d_sfh, but with seed */",
+	"{       uint32_t tmp;",
+	"        int rem;",
+	"",
+	"        rem = len & 3;",
+	"        len >>= 2;",
+	"",
+	"        for ( ; len > 0; len--)",
+	"        {       h  += get16bits(s);",
+	"                tmp = (get16bits(s+2) << 11) ^ h;",
+	"                h   = (h << 16) ^ tmp;",
+	"                s  += 2*sizeof(uint16_t);",
+	"                h  += h >> 11;",
+	"        }",
+	"        switch (rem) {",
+	"        case 3: h += get16bits(s);",
+	"                h ^= h << 16;",
+	"                h ^= s[sizeof(uint16_t)] << 18;",
+	"                h += h >> 11;",
+	"                break;",
+	"        case 2: h += get16bits(s);",
+	"                h ^= h << 11;",
+	"                h += h >> 17;",
+	"                break;",
+	"        case 1: h += *s;",
+	"                h ^= h << 10;",
+	"                h += h >> 1;",
+	"                break;",
+	"        }",
+	"        h ^= h << 3;",
+	"        h += h >> 5;",
+	"        h ^= h << 4;",
+	"        h += h >> 17;",
+	"        h ^= h << 25;",
+	"        h += h >> 6;",
+	"",
+	"        K1 = h;",
+	"}",
+	"void",
+	"o_hash64(uchar *kb, int nbytes, int seed)", /* 64-bit hash */
+	"{	uint8_t  *bp;",
+	"	uint64_t a, b, c, n;",
+	"	const uint64_t *k = (uint64_t *) kb;",
+	"	n = nbytes/WS;	/* nr of 8-byte chunks */",
+	"	/* extend to multiple of words, if needed */",
+	"	a = WS - (nbytes %% WS);",
+	"	if (a > 0 && a < WS)",
+	"	{	n++;",
+	"		bp = kb + nbytes;",
+	"		switch (a) {",
+	"		case 7: *bp++ = 0; /* fall thru */",
+	"		case 6: *bp++ = 0; /* fall thru */",
+	"		case 5: *bp++ = 0; /* fall thru */",
+	"		case 4: *bp++ = 0; /* fall thru */",
+	"		case 3: *bp++ = 0; /* fall thru */",
+	"		case 2: *bp++ = 0; /* fall thru */",
+	"		case 1: *bp   = 0;",
+	"		case 0: break;",
+	"	}	}",
+	"	a = (uint64_t) seed;",
+	"	b = HASH_CONST[HASH_NR];",
+	"	c = 0x9e3779b97f4a7c13LL; /* arbitrary */",
+	"	while (n >= 3)",
+	"	{	a += k[0];",
+	"		b += k[1];",
+	"		c += k[2];",
+	"		mix(a,b,c);",
+	"		n -= 3;",
+	"		k += 3;",
+	"	}",
+	"	c += (((uint64_t) nbytes)<<3);",
+	"	switch (n) {",
+	"	case 2: b += k[1];",
+	"	case 1: a += k[0];",
+	"	case 0: break;",
+	"	}",
+	"	mix(a,b,c);",
+	"",
+	"	K1 = a;",
+	"}",
+	"",
+	"#if defined(USE_TDH) && !defined(WIN32) && !defined(WIN64)",
+#if 0
+	some problems with this storage mode:
+
+	0. pre-allocates full hash-table with slots equal to max statevector size
+	    e.g. with -w26 we allocate 2^26 (64 M) slots of VECTORSZ large
+	   which can accomodate up to 64 M states
+	   once you get close to or exceed the max, the search aborts
+	   with a 'hashtable full' message
+	   in HC mode the max storage needed per state is more modest and independent
+	   of the maximum vectorsize; which makes this mode attractive as a default
+
+	1. does not support PO reduction through the Lstate->ostate->tagged
+	   to distinguish open from closed states - this can reduce states by 50%
+	   could add this as another bit from the hash value
+	   e.g., could add it in HC mode to the first hash?
+
+	2. the same state may be stored multiple times
+#endif
+	"#ifdef HC",
+	"	#ifndef T_HC",
+	"		#ifdef BFS_HC",
+	"			#define T_HC	BFS_HC",
+	"		#else",
+	"			#define T_HC	2",
+	"		#endif",
+	"	#endif",
+	"	#if T_HC<1 || T_HC>4",
+	"		#error \"BFS_HC must be 1, 2, 3, or 4 (default is 2)\"",
+	"	#endif",
+	"#endif",
+	"",
+	"#define T_ROW     	 6", /* related to cache line size */
+	"#define T_ROW_SIZE	 (1<<T_ROW)",
+	"#define T_ROW_MASK	-(1<<T_ROW)",
+	"#define T_FREE    	 0",
+	"#define T_STAT    	 1	/* status bit */",
+	"#ifndef T_VSZ",
+	"	#define T_VSZ	VECTORSZ/4	/* compressed vectorsize */",
+	"#endif",
+	"",
+	"static volatile char     *ohash_sd;	/* state data  */",
+	"static volatile uint32_t *ohash_hv;	/* hash values */",
+	"static ulong     	   ohash_max;",
+	"static ulong    	   ohash_mask;",
+	"",
+	"#if defined(USE_TDH) && defined(Q_PROVISO)",
+	"  static volatile uchar    *ohash_inq;	/* open/closed flag BFS_INQ */",
+	"#endif",
+	"#ifdef HC",
+	"  static uint32_t	   ohash_hc[T_HC];",
+	"  static ulong		   ohash_hc_sz;",
+	"#endif",
+	"",
+	"void",
+	"init_HT(ulong x)		/* USE_TDH cygwin/linux */",
+	"{	x = x / (ulong) sizeof(H_el *);	/* room for x pointers */",
+	"	#ifdef DEBUG",
+	"	printf(\"prealloc x %%lu v %%d  x*v %%lu\\n\",",
+	"		x, T_VSZ, (ulong) (x * (ulong)T_VSZ));",
+	"	#endif",
+	"#ifndef HC",
+	"	if (!(x * (ulong) T_VSZ > x))",
+	"	{	Uerror(\"assertion x * (ulong) T_VSZ > x fails\");",
+	"	}",
+	"	#ifdef BFS_SEP_HASH",
+	"		ohash_sd   = (char *) emalloc(x * (ulong) T_VSZ);",
+	"	#else",
+	"		ohash_sd   = (volatile char *) sh_pre_malloc(x * (ulong) T_VSZ);",
+	"	#endif",
+	"#else", /* assume T_HC >= 1, and normally 2 */
+	"	ohash_hc_sz = (ulong) (T_HC * (ulong) sizeof(uint32_t));",
+	"	if (!(x * ohash_hc_sz > x))",	/* watch for overflow */
+	"	{	Uerror(\"assertion x * ohash_hc_sz > x fails\");",
+	"	}",
+	"	#ifdef BFS_SEP_HASH",
+	"		ohash_sd   = (char *) emalloc(x * ohash_hc_sz);",
+	"	#else",
+	"		ohash_sd   = (volatile char *) sh_pre_malloc(x * ohash_hc_sz);",
+	"	#endif",
+	"#endif",
+	"#ifdef BFS_SEP_HASH",
+	"	ohash_hv = (uint32_t *) emalloc(x * (ulong) sizeof(uint32_t));",
 	"#else",
-		"#ifdef DEBUG",
-	"	dumpstate(-1, v, n, 0);",
-		"#endif",
+	"	ohash_hv = (volatile uint32_t *) sh_pre_malloc(x * (ulong) sizeof(uint32_t));",
 	"#endif",
-	"	return 0;",
+	"	ohash_mask = (((ulong)1)<<ssize)-1;",
+	"	ohash_max  = (((ulong)1)<<ssize)/100;",
+	"#if defined(USE_TDH) && defined(Q_PROVISO)",
+	"	#ifdef BFS_SEP_HASH",
+	"	ohash_inq  = (uchar *) emalloc(x * (ulong) sizeof(uchar));",
+	"	#else",
+	"	ohash_inq  = (volatile uchar *) sh_pre_malloc(x * (ulong) sizeof(uchar));",
+	"	#endif",
+	"#endif",
 	"}",
+	"",
+	"static int h_table_full;",
+	"#ifdef L_BOUND",
+	"void",
+	"bfs_mark_live(void)",
+	"{	int i;",
+	"",
+	"	trpt->o_pm &= ~2;",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"check to mark\\n\");",
 	"#endif",
-	"#include TRANSITIONS",
+	"	for (i = 0; i < (int) now._nr_pr; i++)",
+	"	{	P0 *ptr = (P0 *) pptr(i);",
+	"		if (accpstate[ptr->_t][ptr->_p])",
+	"		{	trpt->o_pm |= 2;",
+	"			now._l_bnd = L_bound;",
+	"			now._l_sds = (uchar *) 0;",
+	"#ifdef VERBOSE",
+	"			bfs_printf(\"mark state live\\n\");",
+	"#endif",
+	"			break;",
+	"	}	}",
+	"}",
 	"void",
-	"do_reach(void)",
-	"{",
+	"bfs_check_live(uchar b, uchar *s)",
+	"{	/* assert(b>0); */",
+	"	now._l_bnd = b-1;	/* decrease bound */",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"check live %%d\\n\", b);",
+	"#endif",
+	"	if (b == L_bound && boq == -1)", /* never mid rv */
+	"	{	now._l_sds = (uchar *) Lstate;	/* new target */",
+	"	} else",
+	"	{	now._l_sds = s;		/* restore target */",
+	"		if (s == (uchar *) Lstate)",
+	"		{	depthfound = depth - (BASE+1)*(L_bound - now._l_bnd - 1);",
+	"			uerror(\"accept cycle found\");",
+	"			depthfound = -1;",
+	"			now._l_bnd = 0;",
+	"			now._l_sds = (uchar *) 0;",
+	"	}	}",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"set l_bound to %%d -- sds %%p\\n\", b-1, (void *) now._l_sds);",
+	"#endif",
+	"}",
+	"#endif",
+	"/* closed hashing with locality - similar to ltsmin */",
+	"int",
+	"o_store(const char *vin, int nin)",
+	"{	int i, seed = 0;",
+	"	ulong hash_v, ix, ex;",
+	"	uint32_t T_BUSY, T_DONE;",
+	"	volatile uint32_t *t_entry;",
+	"#ifdef HC",
+	"	ulong vs = ohash_hc_sz;",
+	"#else",
+	"	ulong vs = (ulong) T_VSZ;",
+	"#endif",
+	"#ifdef L_BOUND",
+	"	uchar o_bnd, *o_sds;",
+	"#endif",
+	"#ifndef STOP_ON_FULL",
+	"	if (h_table_full)",
+	"	{	goto done;",
+	"	}",
+	"#endif",
+	"#ifdef L_BOUND",
+	"	if (now._l_bnd == 0)",
+	"	{	bfs_mark_live();",
+	"	}",
+	"	#ifdef VERBOSE",
+	"	  else",
+	"	{	bfs_printf(\"non-markable state %%d\\n\", now._l_bnd);",
+	"	}",
+	"	#endif",
+	"	o_bnd = now._l_bnd;",
+	"	o_sds = now._l_sds;",
+	"	now._l_bnd = (o_bnd)?1:0;  /* mark nested phase of bounded search */",
+	"	now._l_sds = (uchar *) 0;",
+	"#endif",
+	"#if !defined(HC) && !defined(T_NOCOMP)",
+	"	nin = compress((char *)vin, nin);",
+	"	vin = (char *) &comp_now;",
+	"#endif",
+	"	do {	o_hash((uchar *)vin, nin, seed++);",
+	"		hash_v = K1;",
+	"	} while (hash_v == T_FREE || hash_v == T_STAT);	/* unlikely, hash_v 0 or 1 */",
+	"",
+	"	T_BUSY = ((uint32_t) hash_v & ~((uint32_t) T_STAT));	/* hash with status bit 0 */",
+	"	T_DONE = ((uint32_t) hash_v |  ((uint32_t) T_STAT));	/* hash with status bit 1 */",
+	"#ifdef HC",
+	"	d_hash((uchar *)vin, nin);",			/* HC */
+	"	ohash_hc[0] = (uint32_t) K1;",
+	"	#if T_HC>1",
+	"	ohash_hc[1] = (uint32_t) (K1>>32);",		/* assumes ulong = 64 bits */
+	"	#endif",
+	"	#if T_HC>2",
+	"	ohash_hc[2] = (uint32_t) K2;",
+	"	#endif",
+	"	#if T_HC>3",
+	"	ohash_hc[3] = (uint32_t) (K2>>32);",
+	"	#endif",
+	"#endif",
+	"	while (seed < ohash_max)",
+	"	{	ix = hash_v & ohash_mask;",
+	"		ex = (ix & T_ROW_MASK) + T_ROW_SIZE;",
+	"		for (i = 0; i < T_ROW_SIZE; i++)",
+	"		{	t_entry = (uint32_t *) &ohash_hv[ix];",
+	"			if (*t_entry == T_FREE && cas(t_entry, T_FREE, T_BUSY))",
+	"			{",
+	"#ifndef HC",
+	"				memcpy((char *) &ohash_sd[ix * vs], vin, nin);",
+	"#else",
+	"				memcpy((char *) &ohash_sd[ix * vs], (char *) ohash_hc, vs);",
+	"#endif",
+	"#if defined(USE_TDH) && defined(Q_PROVISO)",
+	"				ohash_inq[ix] = (uchar) BFS_INQ;",
+	"				Lstate = (H_el *) &ohash_inq[ix];",
+	"#endif",
+	"				*t_entry = T_DONE;",
+	"#ifdef VERBOSE",
+	"	#ifdef L_BOUND",
+	"				bfs_printf(\"New state %%p [%%p]\\n\",",
+	"					(void *) Lstate, (void *) o_sds);",
+	"	#else",
+	"				bfs_printf(\"New state %%p\\n\", (void *) Lstate);",
+	"	#endif",
+	"#endif",
+	"#ifdef L_BOUND",
+	"				if (o_bnd) { bfs_check_live(o_bnd, o_sds); }",
+	"#endif",
+	"				return 0;	/* New State */",
+	"			}",
+	"			while (*t_entry == T_BUSY)",
+	"			{	usleep(2);	/* wait */",
+	"			}",
+	"			if (*t_entry == T_DONE /* (first) hash matches, check data */",
+	"#ifndef HC",
+	"			&&   memcmp((char *) &ohash_sd[ix * vs], vin, nin) == 0)",
+	"#else",
+	"			&&   memcmp((char *) &ohash_sd[ix * vs], (char *) ohash_hc, vs) == 0)",
+	"#endif",
+	"			{",
+	"#if defined(USE_TDH) && defined(Q_PROVISO)",
+	"				Lstate = (H_el *) &ohash_inq[ix];",
+	"#endif",
+	"#ifdef VERBOSE",
+	"	#ifdef L_BOUND",
+	"				bfs_printf(\"Old state %%p [%%p]\\n\",",
+	"					(void *) Lstate, (void *) o_sds);",
+	"	#else",
+	"				bfs_printf(\"Old state %%p\\n\", (void *) Lstate);",
+	"	#endif",
+	"#endif",
+	"#ifdef L_BOUND",
+	"				if (o_bnd) { bfs_check_live(o_bnd, o_sds); }",
+	"#endif",
+	"				return 1;	/* Old State */",
+	"			}",
+	"			hcmp++; ix++;",
+	"			ix = (ix==ex) ? ex - T_ROW_SIZE : ix;",
+	"		}",
+	"		/* find a new slot: */",
+	"		do {	o_hash((uchar *)vin, nin, (int) (hash_v + seed++));",
+	"			hash_v = K1;",
+	"		} while (hash_v == T_FREE || hash_v == T_STAT);",
+	"		T_BUSY = ((uint32_t) hash_v & ~((uint32_t) T_STAT));",
+	"		T_DONE = ((uint32_t) hash_v |  ((uint32_t) T_STAT));",
+	"	}",
+	"#ifdef STOP_ON_FULL",
+	"	Uerror(\"hash table full\");",
+	"	/* no return from Uerror */",
+	"#else",
+	"	if (!h_table_full)",
+	"	{	h_table_full++;",
+	"		if (who_am_i == 0)",
+	"		{	bfs_printf(\"hash table is full\\n\");",
+	"	}	}",
+	"done:",
+	"	bfs_punt++;	/* counts this as a lost state */",
+	"#endif",
+	"#ifdef L_BOUND",
+	"	now._l_bnd = 0; /* no more checking */",
+	"	now._l_sds = (uchar *) 0;",
+	"#endif",
+	"	return 1; /* technically should be 0, but we want to throttle down */",
+	"}",
+	"#endif", /* USE_TDH && !WIN32 && !WIN64 */
+	"#endif", /* !BITSTATE || FULLSTACK */
+	"#include TRANSITIONS",
 	0,
 };
--- a/sys/src/cmd/spin/pangen2.c
+++ b/sys/src/cmd/spin/pangen2.c
@@ -1,13 +1,10 @@
 /***** spin: pangen2.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include "version.h"
@@ -15,33 +12,40 @@
 #include "pangen2.h"
 #include "pangen4.h"
 #include "pangen5.h"
+#include "pangen7.h"
 
 #define DELTA	500	/* sets an upperbound on nr of chan names */
 
 #define blurb(fd, e)	{ fprintf(fd, "\n"); if (!merger) fprintf(fd, "\t\t/* %s:%d */\n", \
 				e->n->fn->name, e->n->ln); }
-#define tr_map(m, e)	{ if (!merger) fprintf(tt, "\t\ttr_2_src(%d, %s, %d);\n", \
+#define tr_map(m, e)	{ if (!merger) fprintf(tt, "\t\ttr_2_src(%d, \"%s\", %d);\n", \
 				m, e->n->fn->name, e->n->ln); }
 
 extern ProcList	*rdy;
 extern RunList	*run;
+extern Lextok	*runstmnts;
 extern Symbol	*Fname, *oFname, *context;
 extern char	*claimproc, *eventmap;
-extern int	lineno, verbose, Npars, Mpars;
+extern int	lineno, verbose, Npars, Mpars, nclaims;
 extern int	m_loss, has_remote, has_remvar, merger, rvopt, separate;
-extern int	Ntimeouts, Etimeouts, deadvar;
-extern int	u_sync, u_async, nrRdy;
+extern int	Ntimeouts, Etimeouts, deadvar, old_scope_rules, old_priority_rules;
+extern int	u_sync, u_async, nrRdy, Unique;
 extern int	GenCode, IsGuard, Level, TestOnly;
+extern int	globmin, globmax, ltl_mode, dont_simplify;
+
 extern short	has_stack;
-extern char	*NextLab[];
+extern char	*NextLab[64];	/* must match value in dstep.c:18 */
 
-FILE	*tc, *th, *tt, *tm, *tb;
+int	 	 buzzed;
+FILE		*tc, *th, *tt, *tb;
+static FILE	*tm;
 
-int	OkBreak = -1;
+int	OkBreak = -1, has_hidden = 0; /* has_hidden set in sym.c and structs.c */
 short	nocast=0;	/* to turn off casts in lvalues */
 short	terse=0;	/* terse printing of varnames */
 short	no_arrays=0;
 short	has_last=0;	/* spec refers to _last */
+short	has_priority=0;	/* spec refers to _priority */
 short	has_badelse=0;	/* spec contains else combined with chan refs */
 short	has_enabled=0;	/* spec contains enabled() */
 short	has_pcvalue=0;	/* spec contains pc_value() */
@@ -52,9 +56,7 @@
 short	has_unless=0;	/* spec contains unless statements */
 short	has_provided=0;	/* spec contains PROVIDED clauses on procs */
 short	has_code=0;	/* spec contains c_code, c_expr, c_state */
-short	_isok=0;	/* checks usage of predefined variable _ */
-short	evalindex=0;	/* evaluate index of var names */
-short	withprocname=0;	/* prefix local varnames with procname */
+short	has_ltl=0;	/* has inline ltl formulae */
 int	mst=0;		/* max nr of state/process */
 int	claimnr = -1;	/* claim process, if any */
 int	eventmapnr = -1; /* event trace, if any */
@@ -74,6 +76,9 @@
 static int	uniq=1;
 static int	multi_needed, multi_undo;
 static short	AllGlobal=0;	/* set if process has provided clause */
+static short	withprocname=0;	/* prefix local varnames with procname */
+static short	_isok=0;	/* checks usage of predefined variable _ */
+static short	evalindex=0;	/* evaluate index of var names */
 
 int	has_global(Lextok *);
 static int	getweight(Lextok *);
@@ -86,6 +91,29 @@
 static void	Tpe(Lextok *);
 extern void	spit_recvs(FILE *, FILE*);
 
+static L_List *keep_track;
+
+void
+keep_track_off(Lextok *n)
+{	L_List *p;
+
+	p = (L_List *) emalloc(sizeof(L_List));
+	p->n = n;
+	p->nxt = keep_track;
+	keep_track = p;
+}
+
+int
+check_track(Lextok *n)
+{	L_List *p;
+
+	for (p = keep_track; p; p = p->nxt)
+	{	if (p->n == n)
+		{	return n->sym?n->sym->type:0;
+	}	}
+	return 0;
+}
+
 static int
 fproc(char *s)
 {	ProcList *p;
@@ -98,26 +126,48 @@
 	return -1;
 }
 
+int
+pid_is_claim(int p)	/* Pid (p->tn) to type (p->b) */
+{	ProcList *r;
+
+	for (r = rdy; r; r = r->nxt)
+	{	if (r->tn == p) return (r->b == N_CLAIM);
+	}
+	printf("spin: error, cannot find pid %d\n", p);
+	return 0;
+}
+
 static void
 reverse_procs(RunList *q)
 {
 	if (!q) return;
 	reverse_procs(q->nxt);
-	fprintf(tc, "	Addproc(%d);\n", q->tn);
+	fprintf(tc, "		Addproc(%d, %d);\n",
+		q->tn, q->priority < 1 ? 1 : q->priority);
 }
 
 static void
+forward_procs(RunList *q)
+{
+	if (!q) return;
+	fprintf(tc, "		Addproc(%d, %d);\n",
+		q->tn, q->priority < 1 ? 1 : q->priority);
+	forward_procs(q->nxt);
+}
+
+static void
 tm_predef_np(void)
 {
 	fprintf(th, "#define _T5	%d\n", uniq++);
 	fprintf(th, "#define _T2	%d\n", uniq++);
+
 	fprintf(tm, "\tcase  _T5:\t/* np_ */\n");
 
 	if (separate == 2)
-	fprintf(tm, "\t\tif (!((!(o_pm&4) && !(tau&128))))\n");
-	else
-	fprintf(tm, "\t\tif (!((!(trpt->o_pm&4) && !(trpt->tau&128))))\n");
-
+	{	fprintf(tm, "\t\tif (!((!(o_pm&4) && !(tau&128))))\n");
+	} else
+	{	fprintf(tm, "\t\tif (!((!(trpt->o_pm&4) && !(trpt->tau&128))))\n");
+	}
 	fprintf(tm, "\t\t\tcontinue;\n");
 	fprintf(tm, "\t\t/* else fall through */\n");
 	fprintf(tm, "\tcase  _T2:\t/* true */\n");
@@ -151,51 +201,120 @@
 void
 gensrc(void)
 {	ProcList *p;
+	int i;
 
-	if (!(tc = fopen(Cfile[0].nm[separate], "w"))		/* main routines */
-	||  !(th = fopen(Cfile[1].nm[separate], "w"))		/* header file   */
-	||  !(tt = fopen(Cfile[2].nm[separate], "w"))		/* transition matrix */
-	||  !(tm = fopen(Cfile[3].nm[separate], "w"))		/* forward  moves */
-	||  !(tb = fopen(Cfile[4].nm[separate], "w")))	/* backward moves */
+	disambiguate();		/* avoid name-clashes between scopes */
+
+	if (!(tc = fopen(Cfile[0].nm[separate], MFLAGS))		/* main routines */
+	||  !(th = fopen(Cfile[1].nm[separate], MFLAGS))		/* header file   */
+	||  !(tt = fopen(Cfile[2].nm[separate], MFLAGS))		/* transition matrix */
+	||  !(tm = fopen(Cfile[3].nm[separate], MFLAGS))		/* forward  moves */
+	||  !(tb = fopen(Cfile[4].nm[separate], MFLAGS)))	/* backward moves */
 	{	printf("spin: cannot create pan.[chtmfb]\n");
 		alldone(1);
 	}
 
-	fprintf(th, "#define Version	\"%s\"\n", Version);
-	fprintf(th, "#define Source	\"%s\"\n\n", oFname->name);
-	if (separate != 2)
-	fprintf(th, "char *TrailFile = Source; /* default */\n");
+	fprintf(th, "#ifndef PAN_H\n");
+	fprintf(th, "#define PAN_H\n\n");
 
+	fprintf(th, "#define SpinVersion	\"%s\"\n", SpinVersion);
+	fprintf(th, "#define PanSource	\"");
+	for (i = 0; oFname->name[i] != '\0'; i++)
+	{	char c = oFname->name[i];
+		if (c == '\\' || c == ' ') /* Windows path */
+		{	fprintf(th, "\\");
+		}
+		fprintf(th, "%c", c);
+	}
+	fprintf(th, "\"\n\n");
+
+	fprintf(th, "#define G_long	%d\n", (int) sizeof(long));
+	fprintf(th, "#define G_int	%d\n\n", (int) sizeof(int));
+	fprintf(th, "#define ulong	unsigned long\n");
+	fprintf(th, "#define ushort	unsigned short\n");
+
+	fprintf(th, "#ifdef WIN64\n");
+	fprintf(th, "	#define ONE_L	(1L)\n");
+	fprintf(th, "/*	#define long	long long */\n");
+	fprintf(th, "#else\n");
+	fprintf(th, "	#define ONE_L	(1L)\n");
+	fprintf(th, "#endif\n\n");
+
+	fprintf(th, "#ifdef BFS_PAR\n");
+	fprintf(th, "	#define NRUNS	%d\n", (runstmnts)?1:0);
+	fprintf(th, "	#ifndef BFS\n");
+	fprintf(th, "		#define BFS\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "	#ifndef PUTPID\n");
+	fprintf(th, "		#define PUTPID\n");
+	fprintf(th, "	#endif\n\n");
+	fprintf(th, "	#if !defined(USE_TDH) && !defined(NO_TDH)\n");
+	fprintf(th, "		#define USE_TDH\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "	#if defined(USE_TDH) && !defined(NO_HC)\n");
+	fprintf(th, "		#define HC /* default for USE_TDH */\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "	#ifndef BFS_MAXPROCS\n");
+	fprintf(th, "		#define BFS_MAXPROCS	64	/* max nr of cores to use */\n");
+	fprintf(th, "	#endif\n");
+
+	fprintf(th, "	#define BFS_GLOB	0	/* global lock */\n");
+	fprintf(th, "	#define BFS_ORD		1	/* used with -DCOLLAPSE */\n");
+	fprintf(th, "	#define BFS_MEM		2	/* malloc from shared heap */\n");
+	fprintf(th, "	#define BFS_PRINT	3	/* protect printfs */\n");
+	fprintf(th, "	#define BFS_STATE	4	/* hashtable */\n\n");
+	fprintf(th, "	#define BFS_INQ 	2	/* state is in q */\n\n");
+
+	fprintf(th, "	#ifdef BFS_FIFO\n");	/* queue access */
+	fprintf(th, "	  #define BFS_ID(a,b)	(BFS_STATE + (int) ((a)*BFS_MAXPROCS+(b)))\n");
+	fprintf(th, "	  #define BFS_MAXLOCKS	(BFS_STATE + (BFS_MAXPROCS*BFS_MAXPROCS))\n");
+	fprintf(th, "	#else\n");		/* h_store access (not needed for o_store) */
+	fprintf(th, "	  #ifndef BFS_W\n");
+	fprintf(th, "		#define BFS_W	10\n");	/* 1<<BFS_W locks */
+	fprintf(th, "	  #endif\n");
+	fprintf(th, "	  #define BFS_MASK	((1<<BFS_W) - 1)\n");
+	fprintf(th, "	  #define BFS_ID	(BFS_STATE + (int) (j1_spin & (BFS_MASK)))\n");
+	fprintf(th, "	  #define BFS_MAXLOCKS	(BFS_STATE + (1<<BFS_W))\n"); /* 4+1024 */
+	fprintf(th, "	#endif\n");
+
+	fprintf(th, "	#undef NCORE\n");
+	fprintf(th, "	extern int Cores, who_am_i;\n");
+	fprintf(th, "	#ifndef SAFETY\n");
+	fprintf(th, "	  #if !defined(BFS_STAGGER) && !defined(BFS_DISK)\n");
+	fprintf(th, "		#define BFS_STAGGER	64 /* randomizer, was 16 */\n");
+	fprintf(th, "	  #endif\n");
+	fprintf(th, "	  #ifndef L_BOUND\n");
+	fprintf(th, "		#define L_BOUND 	10 /* default */\n");
+	fprintf(th, "	  #endif\n");
+	fprintf(th, "	  extern int L_bound;\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "	#if defined(BFS_DISK) && defined(BFS_STAGGER)\n");
+	fprintf(th, "		#error BFS_DISK and BFS_STAGGER are not compatible\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "#endif\n\n");
+
 	fprintf(th, "#if defined(BFS)\n");
-	fprintf(th, "#ifndef SAFETY\n");
-	fprintf(th, "#define SAFETY\n");
+	fprintf(th, "	#ifndef SAFETY\n");
+	fprintf(th, "		#define SAFETY\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "	#ifndef XUSAFE\n");
+	fprintf(th, "		#define XUSAFE\n");
+	fprintf(th, "	#endif\n");
 	fprintf(th, "#endif\n");
-	fprintf(th, "#ifndef XUSAFE\n");
-	fprintf(th, "#define XUSAFE\n");
-	fprintf(th, "#endif\n");
-	fprintf(th, "#endif\n");
 
 	fprintf(th, "#ifndef uchar\n");
-	fprintf(th, "#define uchar	unsigned char\n");
+	fprintf(th, "	#define uchar	unsigned char\n");
 	fprintf(th, "#endif\n");
 	fprintf(th, "#ifndef uint\n");
-	fprintf(th, "#define uint	unsigned int\n");
+	fprintf(th, "	#define uint	unsigned int\n");
 	fprintf(th, "#endif\n");
 
-	if (sizeof(void *) > 4)	/* 64 bit machine */
-	{	fprintf(th, "#ifndef HASH32\n");
-		fprintf(th, "#define HASH64\n");
-		fprintf(th, "#endif\n");
-	}
-#if 0
-	if (sizeof(long)==sizeof(int))
-		fprintf(th, "#define long	int\n");
-#endif
 	if (separate == 1 && !claimproc)
 	{	Symbol *n = (Symbol *) emalloc(sizeof(Symbol));
 		Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
+		s->minel = -1;
 		claimproc = n->name = "_:never_template:_";
-		ready(n, ZN, s, 0, ZN);
+		ready(n, ZN, s, 0, ZN, N_CLAIM);
 	}
 	if (separate == 2)
 	{	if (has_remote)
@@ -207,20 +326,29 @@
 		fprintf(th, "#endif\n");
 		if (has_last)
 		fprintf(th, "#define HAS_LAST	%d\n", has_last);
+		if (has_priority && !old_priority_rules)
+		fprintf(th, "#define HAS_PRIORITY	%d\n", has_priority);
 		goto doless;
 	}
 
 	fprintf(th, "#define DELTA	%d\n", DELTA);
 	fprintf(th, "#ifdef MA\n");
-	fprintf(th, "#if MA==1\n"); /* user typed -DMA without size */
-	fprintf(th, "#undef MA\n#define MA	100\n");
-	fprintf(th, "#endif\n#endif\n");
+	fprintf(th, "	#if NCORE>1 && !defined(SEP_STATE)\n");
+	fprintf(th, "		#define SEP_STATE\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "	#if MA==1\n"); /* user typed -DMA without size */
+	fprintf(th, "		#undef MA\n");
+	fprintf(th, "		#define MA	100\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "#endif\n");
 	fprintf(th, "#ifdef W_XPT\n");
-	fprintf(th, "#if W_XPT==1\n"); /* user typed -DW_XPT without size */
-	fprintf(th, "#undef W_XPT\n#define W_XPT 1000000\n");
-	fprintf(th, "#endif\n#endif\n");
+	fprintf(th, "	#if W_XPT==1\n"); /* user typed -DW_XPT without size */
+	fprintf(th, "		#undef W_XPT\n");
+	fprintf(th, "		#define W_XPT 1000000\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "#endif\n");
 	fprintf(th, "#ifndef NFAIR\n");
-	fprintf(th, "#define NFAIR	2	/* must be >= 2 */\n");
+	fprintf(th, "	#define NFAIR	2	/* must be >= 2 */\n");
 	fprintf(th, "#endif\n");
 	if (Ntimeouts)
 	fprintf(th, "#define NTIM	%d\n", Ntimeouts);
@@ -230,8 +358,16 @@
 	fprintf(th, "#define REM_VARS	1\n");
 	if (has_remote)
 	fprintf(th, "#define REM_REFS	%d\n", has_remote); /* not yet used */
+	if (has_hidden)
+	{	fprintf(th, "#define HAS_HIDDEN	%d\n", has_hidden);
+		fprintf(th, "#if defined(BFS_PAR) || defined(BFS)\n");
+		fprintf(th, "	#error cannot use BFS on models with variables declared hidden\n");
+		fprintf(th, "#endif\n");
+	}
 	if (has_last)
 	fprintf(th, "#define HAS_LAST	%d\n", has_last);
+	if (has_priority && !old_priority_rules)
+	fprintf(th, "#define HAS_PRIORITY	%d\n", has_priority);
 	if (has_sorted)
 	fprintf(th, "#define HAS_SORTED	%d\n", has_sorted);
 	if (m_loss)
@@ -238,10 +374,17 @@
 	fprintf(th, "#define M_LOSS\n");
 	if (has_random)
 	fprintf(th, "#define HAS_RANDOM	%d\n", has_random);
-	fprintf(th, "#define HAS_CODE\n");	/* doesn't seem to cause measurable overhead */
+	if (has_ltl)
+	fprintf(th, "#define HAS_LTL	1\n");
+	fprintf(th, "#define HAS_CODE	1\n");	/* could also be set to has_code */
+		/* always defining it doesn't seem to cause measurable overhead though */
+		/* and allows for pan -r etc to work for non-embedded code as well */
+	fprintf(th, "#if defined(RANDSTORE) && !defined(RANDSTOR)\n");
+	fprintf(th, "	#define RANDSTOR	RANDSTORE\n"); /* xspin uses RANDSTORE... */
+	fprintf(th, "#endif\n");
 	if (has_stack)
-	fprintf(th, "#define HAS_STACK\n");
-	if (has_enabled)
+	fprintf(th, "#define HAS_STACK	%d\n", has_stack);
+	if (has_enabled || (has_priority && !old_priority_rules))
 	fprintf(th, "#define HAS_ENABLED	1\n");
 	if (has_unless)
 	fprintf(th, "#define HAS_UNLESS	%d\n", has_unless);
@@ -252,11 +395,12 @@
 	if (has_badelse)
 	fprintf(th, "#define HAS_BADELSE	%d\n", has_badelse);
 	if (has_enabled
+	|| (has_priority && !old_priority_rules)
 	||  has_pcvalue
 	||  has_badelse
 	||  has_last)
 	{	fprintf(th, "#ifndef NOREDUCE\n");
-		fprintf(th, "#define NOREDUCE	1\n");
+		fprintf(th, "	#define NOREDUCE	1\n");
 		fprintf(th, "#endif\n");
 	}
 	if (has_np)
@@ -265,33 +409,46 @@
 	fprintf(th, "#define MERGED	1\n");
 
 doless:
-	fprintf(th, "#ifdef NP	/* includes np_ demon */\n");
+	fprintf(th, "#if !defined(HAS_LAST) && defined(BCS)\n");
+	fprintf(th, "	#define HAS_LAST	1 /* use it, but */\n");
+	fprintf(th, "	#ifndef STORE_LAST\n"); /* unless the user insists */
+	fprintf(th, "		#define NO_LAST	1 /* dont store it */\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "#endif\n");
+
+	fprintf(th, "#if defined(BCS) && defined(BITSTATE)\n");
+	fprintf(th, "	#ifndef NO_CTX\n");
+	fprintf(th, "		#define STORE_CTX	1\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "#endif\n");
+
+	fprintf(th, "#ifdef NP\n");
 	if (!has_np)
-	fprintf(th, "#define HAS_NP	2\n");
-	fprintf(th, "#define VERI	%d\n",	nrRdy);
-	fprintf(th, "#define endclaim	3 /* none */\n");
+	fprintf(th, "	#define HAS_NP	2\n");
+	fprintf(th, "	#define VERI	%d	/* np_ */\n",	nrRdy);
 	fprintf(th, "#endif\n");
 	if (claimproc)
-	{	claimnr = fproc(claimproc);
-		/* NP overrides claimproc */
-		fprintf(th, "#if !defined(NOCLAIM) && !defined NP\n");
-		fprintf(th, "#define VERI	%d\n",	claimnr);
-		fprintf(th, "#define endclaim	endstate%d\n",	claimnr);
+	{	claimnr = fproc(claimproc);	/* the default claim */
+		fprintf(th, "#ifndef NOCLAIM\n");
+		fprintf(th, "	#define NCLAIMS	%d\n", nclaims);
+		fprintf(th, "	#ifndef NP\n");
+		fprintf(th, "		#define VERI	%d\n", claimnr);
+		fprintf(th, "	#endif\n");
 		fprintf(th, "#endif\n");
 	}
 	if (eventmap)
 	{	eventmapnr = fproc(eventmap);
 		fprintf(th, "#define EVENT_TRACE	%d\n",	eventmapnr);
-		fprintf(th, "#define endevent	endstate%d\n",	eventmapnr);
+		fprintf(th, "#define endevent	_endstate%d\n",	eventmapnr);
 		if (eventmap[2] == 'o')	/* ":notrace:" */
 		fprintf(th, "#define NEGATED_TRACE	1\n");
 	}
 
-	fprintf(th, "typedef struct S_F_MAP {\n");
-	fprintf(th, "	char *fnm; int from; int upto;\n");
+	fprintf(th, "\ntypedef struct S_F_MAP {\n");
+	fprintf(th, "	char *fnm;\n\tint from;\n\tint upto;\n");
 	fprintf(th, "} S_F_MAP;\n");
 
-	fprintf(tc, "/*** Generated by %s ***/\n", Version);
+	fprintf(tc, "/*** Generated by %s ***/\n", SpinVersion);
 	fprintf(tc, "/*** From source: %s ***/\n\n", oFname->name);
 
 	ntimes(tc, 0, 1, Pre0);
@@ -304,19 +461,36 @@
 	case 2:	fprintf(tc, "#include \"pan_t.h\"\n"); break;
 	}
 
+	if (separate != 2)
+	{	fprintf(tc, "char *TrailFile = PanSource; /* default */\n");
+		fprintf(tc, "char *trailfilename;\n");
+	}
+
+	fprintf(tc, "#ifdef LOOPSTATE\n");
+	fprintf(tc, "double cnt_loops;\n");
+	fprintf(tc, "#endif\n");
+
 	fprintf(tc, "State	A_Root;	/* seed-state for cycles */\n");
 	fprintf(tc, "State	now;	/* the full state-vector */\n");
+	fprintf(tc, "#if NQS > 0\n");
+	fprintf(tc, "short q_flds[NQS+1];\n");
+	fprintf(tc, "short q_max[NQS+1];\n");
+	fprintf(tc, "#endif\n");
+
 	plunk_c_fcts(tc);	/* State can be used in fcts */
 
 	if (separate != 2)
-		ntimes(tc, 0, 1, Preamble);
-	else
-		fprintf(tc, "extern int verbose; extern long depth;\n");
+	{	ntimes(tc, 0, 1, Preamble);
+		ntimes(tc, 0, 1, Separate); /* things that moved out of pan.h */
+	} else
+	{	fprintf(tc, "extern int verbose;\n");
+		fprintf(tc, "extern long depth, depthfound;\n");
+	}
 
 	fprintf(tc, "#ifndef NOBOUNDCHECK\n");
-	fprintf(tc, "#define Index(x, y)\tBoundcheck(x, y, II, tt, t)\n");
+	fprintf(tc, "	#define Index(x, y)\tBoundcheck(x, y, II, tt, t)\n");
 	fprintf(tc, "#else\n");
-	fprintf(tc, "#define Index(x, y)\tx\n");
+	fprintf(tc, "	#define Index(x, y)\tx\n");
 	fprintf(tc, "#endif\n");
 
 	c_preview();	/* sets hastrack */
@@ -335,7 +509,7 @@
 		fprintf(tt, "}\n\n");
 		fprintf(tt, "void\nputpeg(int n, int m)\n");
 		fprintf(tt, "{	printf(\"%%5d\ttrans %%4d \", m, n);\n");
-		fprintf(tt, "	printf(\"file %%s line %%3d\\n\",\n");
+		fprintf(tt, "	printf(\"%%s:%%d\\n\",\n");
 		fprintf(tt, "		T_SRC[n].fl, T_SRC[n].ln);\n");
 		fprintf(tt, "}\n");
 		if (!merger)
@@ -359,13 +533,18 @@
 		}
 
 		fprintf(tm, "#define rand	pan_rand\n");
+		fprintf(tm, "#define pthread_equal(a,b)	((a)==(b))\n");
 		fprintf(tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
-		fprintf(tm, "	printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
+		fprintf(tm, "	#ifdef BFS_PAR\n");
+		fprintf(tm, "		bfs_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
+		fprintf(tm, "	#else\n");
+		fprintf(tm, "		cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
+		fprintf(tm, "	#endif\n");
 		fprintf(tm, "#endif\n");
 		fprintf(tm, "	switch (t->forw) {\n");
 	} else
 	{	fprintf(tt, "#ifndef PEG\n");
-		fprintf(tt, "#define tr_2_src(m,f,l)\n");
+		fprintf(tt, "	#define tr_2_src(m,f,l)\n");
 		fprintf(tt, "#endif\n");
 		fprintf(tt, "void\nset_claim(void)\n{\tTrans *T;\n");
 		fprintf(tt, "\textern Trans ***trans;\n");
@@ -373,8 +552,9 @@
 		fprintf(tt, " char *, int, int, int);\n\n");
 
 		fprintf(tm, "#define rand	pan_rand\n");
+		fprintf(tm, "#define pthread_equal(a,b)	((a)==(b))\n");
 		fprintf(tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
-		fprintf(tm, "	printf(\"Pr: %%d Tr: %%d\\n\", II, forw);\n");
+		fprintf(tm, "	cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, forw);\n");
 		fprintf(tm, "#endif\n");
 		fprintf(tm, "	switch (forw) {\n");
 	}
@@ -404,25 +584,48 @@
 	fprintf(tb, "	case  0: goto R999; /* nothing to undo */\n");
 
 	for (p = rdy; p; p = p->nxt)
-		putproc(p);
+	{	putproc(p);
+	}
 
-
 	if (separate != 2)
-	{	fprintf(th, "struct {\n");
-		fprintf(th, "	int tp; short *src;\n");
-		fprintf(th, "} src_all[] = {\n");
+	{	fprintf(th, "\n");
 		for (p = rdy; p; p = p->nxt)
-			fprintf(th, "	{ %d, &src_ln%d[0] },\n",
+			fprintf(th, "extern short src_ln%d[];\n", p->tn);
+		for (p = rdy; p; p = p->nxt)
+			fprintf(th, "extern S_F_MAP src_file%d[];\n", p->tn);
+		fprintf(th, "\n");
+
+		fprintf(tc, "uchar reached%d[3];  /* np_ */\n", nrRdy);	
+		fprintf(tc, "uchar *loopstate%d;  /* np_ */\n", nrRdy);
+
+		fprintf(tc, "struct {\n");
+		fprintf(tc, "	int tp; short *src;\n");
+		fprintf(tc, "} src_all[] = {\n");
+		for (p = rdy; p; p = p->nxt)
+			fprintf(tc, "	{ %d, &src_ln%d[0] },\n",
 				p->tn, p->tn);
-		fprintf(th, "	{ 0, (short *) 0 }\n");
-		fprintf(th, "};\n");
-		fprintf(th, "short *frm_st0;\n");	/* records src states for transitions in never claim */
+		fprintf(tc, "	{ 0, (short *) 0 }\n");
+		fprintf(tc, "};\n");
+
+		fprintf(tc, "S_F_MAP *flref[] = {\n");	/* 5.3.0 */
+		for (p = rdy; p; p = p->nxt)
+		{	fprintf(tc, "	src_file%d%c\n", p->tn, p->nxt?',':' ');
+		}
+		fprintf(tc, "};\n\n");
 	} else
-	{	fprintf(th, "extern short *frm_st0;\n");
+	{	fprintf(tc, "extern uchar reached%d[3];  /* np_ */\n", nrRdy);	
 	}
 
-	gencodetable(th);
+	gencodetable(tc);	/* was th */
 
+	if (Unique < (1 << (8*sizeof(unsigned char)) ))	/* was uniq before */
+	{	fprintf(th, "#define T_ID	unsigned char\n");
+	} else if (Unique < (1 << (8*sizeof(unsigned short)) ))
+	{	fprintf(th, "#define T_ID	unsigned short\n");
+	} else
+	{	fprintf(th, "#define T_ID	unsigned int\n");
+	}
+
 	if (separate != 1)
 	{	tm_predef_np();
 		tt_predef_np();
@@ -438,13 +641,13 @@
 		genheader();
 		if (separate == 1)
 		{	fprintf(th, "#define FORWARD_MOVES\t\"pan_s.m\"\n");
-			fprintf(th, "#define REVERSE_MOVES\t\"pan_s.b\"\n");
+			fprintf(th, "#define BACKWARD_MOVES\t\"pan_s.b\"\n");
 			fprintf(th, "#define SEPARATE\n");
 			fprintf(th, "#define TRANSITIONS\t\"pan_s.t\"\n");
 			fprintf(th, "extern void ini_claim(int, int);\n");
 		} else
 		{	fprintf(th, "#define FORWARD_MOVES\t\"pan.m\"\n");
-			fprintf(th, "#define REVERSE_MOVES\t\"pan.b\"\n");
+			fprintf(th, "#define BACKWARD_MOVES\t\"pan.b\"\n");
 			fprintf(th, "#define TRANSITIONS\t\"pan.t\"\n");
 		}
 		genaddproc();
@@ -456,33 +659,37 @@
 		if (!run) fatal("no runable process", (char *)0);
 		fprintf(tc, "void\n");
 		fprintf(tc, "active_procs(void)\n{\n");
+
+		fprintf(tc, "	if (reversing == 0) {\n");
 			reverse_procs(run);
+		fprintf(tc, "	} else {\n");
+			forward_procs(run);
+		fprintf(tc, "	}\n");
+
 		fprintf(tc, "}\n");
 		ntimes(tc, 0, 1, Dfa);
 		ntimes(tc, 0, 1, Xpt);
 
 		fprintf(th, "#define NTRANS	%d\n", uniq);
-		fprintf(th, "#ifdef PEG\n");
-		fprintf(th, "long peg[NTRANS];\n");
-		fprintf(th, "#endif\n");
-
 		if (u_sync && !u_async)
-			spit_recvs(th, tc);
+		{	spit_recvs(th, tc);
+		}
 	} else
 	{	genheader();
 		fprintf(th, "#define FORWARD_MOVES\t\"pan_t.m\"\n");
-		fprintf(th, "#define REVERSE_MOVES\t\"pan_t.b\"\n");
+		fprintf(th, "#define BACKWARD_MOVES\t\"pan_t.b\"\n");
 		fprintf(th, "#define TRANSITIONS\t\"pan_t.t\"\n");
 		fprintf(tc, "extern int Maxbody;\n");
 		fprintf(tc, "#if VECTORSZ>32000\n");
-		fprintf(tc, "extern int proc_offset[];\n");
+		fprintf(tc, "	extern int *proc_offset;\n");
 		fprintf(tc, "#else\n");
-		fprintf(tc, "extern short proc_offset[];\n");
+		fprintf(tc, "	extern short *proc_offset;\n");
 		fprintf(tc, "#endif\n");
-		fprintf(tc, "extern uchar proc_skip[];\n");
+		fprintf(tc, "extern uchar *proc_skip;\n");
 		fprintf(tc, "extern uchar *reached[];\n");
 		fprintf(tc, "extern uchar *accpstate[];\n");
 		fprintf(tc, "extern uchar *progstate[];\n");
+		fprintf(tc, "extern uchar *loopstate[];\n");
 		fprintf(tc, "extern uchar *stopstate[];\n");
 		fprintf(tc, "extern uchar *visstate[];\n\n");
 		fprintf(tc, "extern short *mapstate[];\n");
@@ -491,7 +698,7 @@
 		fprintf(tc, "\textern State now;\n");
 		fprintf(tc, "\textern void set_claim(void);\n\n");
 		fprintf(tc, "#ifdef PROV\n");
-		fprintf(tc, "#include PROV\n");
+		fprintf(tc, "	#include PROV\n");
 		fprintf(tc, "#endif\n");
 		fprintf(tc, "\tset_claim();\n");
 		genother();
@@ -509,13 +716,42 @@
 		fprintf(tc, "int\nrev_claim(int backw)\n{ return 0; }\n");
 		fprintf(tc, "#include TRANSITIONS\n");
 	}
-	if (separate != 1)
-		ntimes(tc, 0, 1, Nvr1);
 
 	if (separate != 2)
 	{	c_wrapper(tc);
 		c_chandump(tc);
 	}
+
+	fprintf(th, "#if defined(BFS_PAR) || NCORE>1\n");
+	fprintf(th, "	void e_critical(int);\n");
+	fprintf(th, "	void x_critical(int);\n");
+	fprintf(th, "	#ifdef BFS_PAR\n");
+	fprintf(th, "		void bfs_main(int, int);\n");
+	fprintf(th, "		void bfs_report_mem(void);\n");
+	fprintf(th, "	#endif\n");
+	fprintf(th, "#endif\n");
+
+	fprintf(th, "\n\n/* end of PAN_H */\n#endif\n");
+	fclose(th);
+	fclose(tt);
+	fclose(tm);
+	fclose(tb);
+
+	if (!(th = fopen("pan.p", MFLAGS)))
+	{	printf("spin: cannot create pan.p for -DBFS_PAR\n");
+		return; 	/* we're done anyway */
+	}
+
+	ntimes(th, 0, 1, pan_par);	/* BFS_PAR */
+	fclose(th);
+
+	fprintf(tc, "\nTrans *t_id_lkup[%d];\n\n", globmax+1); 
+
+	if (separate != 2)
+	{	fprintf(tc, "\n#ifdef BFS_PAR\n\t#include \"pan.p\"\n#endif\n");
+	}
+	fprintf(tc, "\n/* end of pan.c */\n");
+	fclose(tc);
 }
 
 static int
@@ -537,13 +773,13 @@
 	fprintf(tc, "%s(", pre);
 	if (!(s->hidden&1))
 	{	if (s->context)
-			fprintf(tc, "((P%d *)this)->", pid);
+			fprintf(tc, "(int) ( ((P%d *)this)->", pid);
 		else
-			fprintf(tc, "now.");
+			fprintf(tc, "(int) ( now.");
 	}
 	fprintf(tc, "%s", s->name);
-	if (qln > 1) fprintf(tc, "[%d]", ai);
-	fprintf(tc, ")");
+	if (qln > 1 || s->isarray) fprintf(tc, "[%d]", ai);
+	fprintf(tc, ") )");
 }
 
 struct AA {	char TT[9];	char CC[8]; };
@@ -712,47 +948,60 @@
 	fprintf(tc, "}\n");
 }
 
+extern int find_min(Sequence *);
+extern int find_max(Sequence *);
+
 static void
 putproc(ProcList *p)
 {	Pid = p->tn;
 	Det = p->det;
 
-	if (Pid == claimnr
+	if (pid_is_claim(Pid)
 	&&  separate == 1)
 	{	fprintf(th, "extern uchar reached%d[];\n", Pid);
 #if 0
-		fprintf(th, "extern short nstates%d;\n", Pid);
+		fprintf(th, "extern short _nstates%d;\n", Pid);
 #else
-		fprintf(th, "\n#define nstates%d	%d\t/* %s */\n",
+		fprintf(th, "\n#define _nstates%d	%d\t/* %s */\n",
 			Pid, p->s->maxel, p->n->name);
 #endif
 		fprintf(th, "extern short src_ln%d[];\n", Pid);
+		fprintf(th, "extern uchar *loopstate%d;\n", Pid);
 		fprintf(th, "extern S_F_MAP src_file%d[];\n", Pid);
-		fprintf(th, "#define endstate%d	%d\n",
+		fprintf(th, "#define _endstate%d	%d\n",
 			Pid, p->s->last?p->s->last->seqno:0);
-		fprintf(th, "#define src_claim	src_ln%d\n", claimnr);
-
 		return;
 	}
-	if (Pid != claimnr
+	if (!pid_is_claim(Pid)
 	&&  separate == 2)
 	{	fprintf(th, "extern short src_ln%d[];\n", Pid);
+		fprintf(th, "extern uchar *loopstate%d;\n", Pid);
 		return;
 	}
 
 	AllGlobal = (p->prov)?1:0;	/* process has provided clause */
 
-	fprintf(th, "\n#define nstates%d	%d\t/* %s */\n",
+	fprintf(th, "\n#define _nstates%d	%d\t/* %s */\n",
 		Pid, p->s->maxel, p->n->name);
-	if (Pid == claimnr)
-	fprintf(th, "#define nstates_claim	nstates%d\n", Pid);
+/* new */
+	fprintf(th, "#define minseq%d	%d\n", Pid, find_min(p->s));
+	fprintf(th, "#define maxseq%d	%d\n", Pid, find_max(p->s));
+
+/* end */
+
 	if (Pid == eventmapnr)
-	fprintf(th, "#define nstates_event	nstates%d\n", Pid);
+	fprintf(th, "#define nstates_event	_nstates%d\n", Pid);
 
-	fprintf(th, "#define endstate%d	%d\n",
-		Pid, p->s->last->seqno);
-	fprintf(tm, "\n		 /* PROC %s */\n", p->n->name);
-	fprintf(tb, "\n		 /* PROC %s */\n", p->n->name);
+	fprintf(th, "#define _endstate%d	%d\n", Pid, p->s->last?p->s->last->seqno:0);
+
+	if (p->b == N_CLAIM || p->b == E_TRACE || p->b == N_TRACE)
+	{	fprintf(tm, "\n		 /* CLAIM %s */\n", p->n->name);
+		fprintf(tb, "\n		 /* CLAIM %s */\n", p->n->name);
+	}
+	else
+	{	fprintf(tm, "\n		 /* PROC %s */\n", p->n->name);
+		fprintf(tb, "\n		 /* PROC %s */\n", p->n->name);
+	}
 	fprintf(tt, "\n	/* proctype %d: %s */\n", Pid, p->n->name);
 	fprintf(tt, "\n	trans[%d] = (Trans **)", Pid);
 	fprintf(tt, " emalloc(%d*sizeof(Trans *));\n\n", p->s->maxel);
@@ -761,7 +1010,6 @@
 	{	fprintf(th, "\n#define in_s_scope(x_y3_)	0");
 		fprintf(tc, "\n#define in_r_scope(x_y3_)	0");
 	}
-
 	put_seq(p->s, 2, 0);
 	if (Pid == eventmapnr)
 	{	fprintf(th, "\n\n");
@@ -947,10 +1195,10 @@
 	if (e->n->ntyp == D_STEP)
 	{	int inherit = (e->status&(ATOM|L_ATOM));
 		fprintf(tm, "\tcase %d: ", uniq++);
-		fprintf(tm, "/* STATE %d - line %d %s - [",
-			e->seqno, e->n->ln, e->n->fn->name);
+		fprintf(tm, "// STATE %d - %s:%d - [",
+			e->seqno, e->n->fn->name, e->n->ln);
 		comment(tm, e->n, 0);
-		fprintf(tm, "] */\n\t\t");
+		fprintf(tm, "]\n\t\t");
 
 		if (s->last->n->ntyp == BREAK)
 			OkBreak = target(huntele(s->last->nxt,
@@ -971,7 +1219,7 @@
 		}
 	
 		fprintf(tb, "\tcase %d: ", uniq-1);
-		fprintf(tb, "/* STATE %d */\n", e->seqno);
+		fprintf(tb, "// STATE %d\n", e->seqno);
 		fprintf(tb, "\t\tsv_restor();\n");
 		fprintf(tb, "\t\tgoto R999;\n");
 		if (e->nxt)
@@ -1024,7 +1272,7 @@
 	struct CaseCache *nxt;
 } CaseCache;
 
-CaseCache *casing[6];
+static CaseCache *casing[6];
 
 static int
 identical(Lextok *p, Lextok *q)
@@ -1076,6 +1324,9 @@
 	if (stopat)
 	while (f && f->seqno != stopat)
 	{	f = findnext(f);
+		if (!f)
+		{	break;
+		}
 		switch (f->n->ntyp) {
 		case GOTO:
 		case '.':
@@ -1084,8 +1335,7 @@
 			break;
 		default:
 			return f;
-		}
-	}
+	}	}
 	return (Element *) 0;
 }
 
@@ -1107,18 +1357,16 @@
 	if (!stopat_a && !stopat_b)
 		return 1;
 
-	for (;;)
-	{
-		f = advance(a, stopat_a);
-		g = advance(b, stopat_b);
-		if (!f && !g)
-			return 1;
-		if (f && g)
-			return identical(f->n, g->n);
-		else
-			return 0;
-	}
-	return 1;
+	f = advance(a, stopat_a);
+	g = advance(b, stopat_b);
+
+	if (!f && !g)
+		return 1;
+
+	if (f && g)
+		return identical(f->n, g->n);
+
+	return 0;
 }
 
 static CaseCache *
@@ -1174,6 +1422,7 @@
 
 	switch (e->n->ntyp) {
 	case ASGN:
+		if (check_track(e->n) == STRUCT) { break; }
 		nr++;
 		break;
 	case  'r':
@@ -1234,10 +1483,10 @@
 		}
 
 		if (f && !f->merge && !f->merge_single && f->seqno != stopat)
-		{	fprintf(tm, "\n\t\tbad hop %s:%d -- at %d, <",
+		{	fprintf(tm, "\n\t\t// bad hop %s:%d -- at %d, <",
 				f->n->fn->name,f->n->ln, f->seqno);
 			comment(tm, f->n, 0);
-			fprintf(tm, "> looking for %d -- merge %d:%d:%d\n\t\t",
+			fprintf(tm, "> looking for %d -- merge %d:%d:%d ",
 				stopat, f->merge, f->merge_start, f->merge_single);
 		 	break;
 		}
@@ -1258,18 +1507,20 @@
 }
 
 static void
-doforward(FILE *tm, Element *e)
+doforward(FILE *tm_fd, Element *e)
 {	FSM_use *u;
 
-	putstmnt(tm, e->n, e->seqno);
+	putstmnt(tm_fd, e->n, e->seqno);
 
 	if (e->n->ntyp != ELSE && Det)
-	{	fprintf(tm, ";\n\t\tif (trpt->o_pm&1)\n\t\t");
-		fprintf(tm, "\tuerror(\"non-determinism in D_proctype\")");
+	{	fprintf(tm_fd, ";\n\t\tif (trpt->o_pm&1)\n\t\t");
+		fprintf(tm_fd, "\tuerror(\"non-determinism in D_proctype\")");
 	}
 	if (deadvar && !has_code)
 	for (u = e->dead; u; u = u->nxt)
-	{	fprintf(tm, ";\n\t\t/* dead %d: %s */  ",
+	{	fprintf(tm_fd, ";\n\t\t");
+		fprintf(tm_fd, "if (TstOnly) return 1; /* TT */\n");
+		fprintf(tm_fd, "\t\t/* dead %d: %s */  ",
 			u->special, u->var->name);
 
 		switch (u->special) {
@@ -1281,10 +1532,10 @@
 			}
 			if (e->n->ntyp != 'r')
 			{	XZ.sym = u->var;
-				fprintf(tm, "\n#ifdef HAS_CODE\n");
-				fprintf(tm, "\t\tif (!readtrail)\n");
-				fprintf(tm, "#endif\n\t\t\t");
-				putname(tm, "", &XZ, 0, " = 0");
+				fprintf(tm_fd, "\n#ifdef HAS_CODE\n");
+				fprintf(tm_fd, "\t\tif (!readtrail)\n");
+				fprintf(tm_fd, "#endif\n\t\t\t");
+				putname(tm_fd, "", &XZ, 0, " = 0");
 				break;
 			} /* else fall through */
 		case 1:		/* dead after read -- add asgn of rval -- needs bup */
@@ -1292,20 +1543,20 @@
 			CnT[YZcnt]++;		/* this step added bups */
 			if (multi_oval)
 			{	check_needed();
-				fprintf(tm, "(trpt+1)->bup.ovals[%d] = ",
+				fprintf(tm_fd, "(trpt+1)->bup.ovals[%d] = ",
 					multi_oval-1);
 				multi_oval++;
 			} else
-				fprintf(tm, "(trpt+1)->bup.oval = ");
-			putname(tm, "", &YZ[YZmax], 0, ";\n");
-			fprintf(tm, "#ifdef HAS_CODE\n");
-			fprintf(tm, "\t\tif (!readtrail)\n");
-			fprintf(tm, "#endif\n\t\t\t");
-			putname(tm, "", &YZ[YZmax], 0, " = 0");
+				fprintf(tm_fd, "(trpt+1)->bup.oval = ");
+			putname(tm_fd, "", &YZ[YZmax], 0, ";\n");
+			fprintf(tm_fd, "#ifdef HAS_CODE\n");
+			fprintf(tm_fd, "\t\tif (!readtrail)\n");
+			fprintf(tm_fd, "#endif\n\t\t\t");
+			putname(tm_fd, "", &YZ[YZmax], 0, " = 0");
 			YZmax++;
 			break;
 	}	}
-	fprintf(tm, ";\n\t\t");
+	fprintf(tm_fd, ";\n\t\t");
 }
 
 static int
@@ -1318,7 +1569,7 @@
 
 	if (!didcase)
 	{	fprintf(tb, "\n\tcase %d: ", casenr);
-		fprintf(tb, "/* STATE %d */\n\t\t", e->seqno);
+		fprintf(tb, "// STATE %d\n\t\t", e->seqno);
 		didcase++;
 	}
 
@@ -1412,7 +1663,7 @@
 {	int bupcase = 0, casenr = uniq, fromcache = 0;
 	CaseCache *Cached = (CaseCache *) 0;
 	Element *f, *g;
-	int j, nrbups, mark, target;
+	int j, nrbups, mark, ntarget;
 	extern int ccache;
 
 	mark = (e->status&ATOM); /* could lose atomicity in a merge chain */
@@ -1439,7 +1690,7 @@
 	fprintf(tt, "\ttrans[%d][%d]\t= ", Pid, e->seqno);
 
 	if (ccache
-	&&  Pid != claimnr
+	&&  !pid_is_claim(Pid)
 	&&  Pid != eventmapnr
 	&& (Cached = prev_case(e, Pid)))
 	{	bupcase = Cached->b;
@@ -1446,10 +1697,10 @@
 		casenr  = Cached->m;
 		fromcache = 1;
 
-		fprintf(tm, "/* STATE %d - line %d %s - [",
-			e->seqno, e->n->ln, e->n->fn->name);
+		fprintf(tm, "// STATE %d - %s:%d - [",
+			e->seqno, e->n->fn->name, e->n->ln);
 		comment(tm, e->n, 0);
-		fprintf(tm, "] (%d:%d - %d) same as %d (%d:%d - %d) */\n",
+		fprintf(tm, "] (%d:%d - %d) same as %d (%d:%d - %d)\n",
 			e->merge_start, e->merge, e->merge_in,
 			casenr,
 			Cached->e->merge_start, Cached->e->merge, Cached->e->merge_in);
@@ -1457,17 +1708,17 @@
 		goto gotit;
 	}
 
-	fprintf(tm, "\tcase %d: /* STATE %d - line %d %s - [",
-		uniq++, e->seqno, e->n->ln, e->n->fn->name);
+	fprintf(tm, "\tcase %d: // STATE %d - %s:%d - [",
+		uniq++, e->seqno, e->n->fn->name, e->n->ln);
 	comment(tm, e->n, 0);
 	nrbups = (e->merge || e->merge_start) ? nrhops(e) : nr_bup(e);
-	fprintf(tm, "] (%d:%d:%d - %d) */\n\t\t",
+	fprintf(tm, "] (%d:%d:%d - %d)\n\t\t",
 		e->merge_start, e->merge, nrbups, e->merge_in);
 
 	if (nrbups > MAXMERGE-1)
 		fatal("merge requires more than 256 bups", (char *)0);
 
-	if (e->n->ntyp != 'r' && Pid != claimnr && Pid != eventmapnr)
+	if (e->n->ntyp != 'r' && !pid_is_claim(Pid) && Pid != eventmapnr)
 		fprintf(tm, "IfNotBlocked\n\t\t");
 
 	if (multi_needed != 0 || multi_undo != 0)
@@ -1482,18 +1733,29 @@
 	memset(CnT, 0, sizeof(CnT));
 	YZmax = YZcnt = 0;
 
-/* NEW 4.2.6 */
-	if (Pid == claimnr)
-	{
-		fprintf(tm, "\n#if defined(VERI) && !defined(NP)\n\t\t");
-		fprintf(tm, "{	static int reported%d = 0;\n\t\t", e->seqno);
-		/* source state changes in retrans and must be looked up in frm_st0[t->forw] */
-		fprintf(tm, "	if (verbose && !reported%d)\n\t\t", e->seqno);
-		fprintf(tm, "	{	printf(\"depth %%d: Claim reached state %%d (line %%d)\\n\",\n\t\t");
-		fprintf(tm, "			depth, frm_st0[t->forw], src_claim[%d]);\n\t\t", e->seqno);
-		fprintf(tm, "		reported%d = 1;\n\t\t", e->seqno);
-		fprintf(tm, "		fflush(stdout);\n\t\t");
-		fprintf(tm, "}	}\n");
+/* new 4.2.6, revised 6.0.0 */
+	if (pid_is_claim(Pid))
+	{	fprintf(tm, "\n#if defined(VERI) && !defined(NP)\n");
+		fprintf(tm, "#if NCLAIMS>1\n\t\t");
+		 fprintf(tm, "{	static int reported%d = 0;\n\t\t", e->seqno);
+		 fprintf(tm, "	if (verbose && !reported%d)\n\t\t", e->seqno);
+		 fprintf(tm, "	{	int nn = (int) ((Pclaim *)pptr(0))->_n;\n\t\t");
+		 fprintf(tm, "		printf(\"depth %%ld: Claim %%s (%%d), state %%d (line %%d)\\n\",\n\t\t");
+		 fprintf(tm, "			depth, procname[spin_c_typ[nn]], nn, ");
+		 fprintf(tm, "(int) ((Pclaim *)pptr(0))->_p, src_claim[ (int) ((Pclaim *)pptr(0))->_p ]);\n\t\t");
+		 fprintf(tm, "		reported%d = 1;\n\t\t", e->seqno);
+		 fprintf(tm, "		fflush(stdout);\n\t\t");
+		 fprintf(tm, "}	}\n");
+		fprintf(tm, "#else\n\t\t");
+		 fprintf(tm, "{	static int reported%d = 0;\n\t\t", e->seqno);
+		 fprintf(tm, "	if (verbose && !reported%d)\n\t\t", e->seqno);
+		 fprintf(tm, "	{	printf(\"depth %%d: Claim, state %%d (line %%d)\\n\",\n\t\t");
+		 fprintf(tm, "			(int) depth, (int) ((Pclaim *)pptr(0))->_p, ");
+		 fprintf(tm, "src_claim[ (int) ((Pclaim *)pptr(0))->_p ]);\n\t\t");
+		 fprintf(tm, "		reported%d = 1;\n\t\t", e->seqno);
+		 fprintf(tm, "		fflush(stdout);\n\t\t");
+		 fprintf(tm, "}	}\n");
+		fprintf(tm, "#endif\n");
 		fprintf(tm, "#endif\n\t\t");
 	}
 /* end */
@@ -1504,32 +1766,32 @@
 	doforward(tm, e);
 
 	if (e->merge_start)
-		target = e->merge_start;
+		ntarget = e->merge_start;
 	else
-		target = e->merge;
+		ntarget = e->merge;
 
-	if (target)
+	if (ntarget)
 	{	f = e;
 
 more:		if (f->n->ntyp == GOTO)
 		{	g = get_lab(f->n, 1);
-			if (g->seqno == target)
+			if (g->seqno == ntarget)
 				f = g;
 			else
-				f = huntele(g, f->status, target);
+				f = huntele(g, f->status, ntarget);
 		} else
 			f = f->nxt;
 
 
-		if (f && f->seqno != target)
+		if (f && f->seqno != ntarget)
 		{	if (!f->merge && !f->merge_single)
 			{	fprintf(tm, "/* stop at bad hop %d, %d */\n\t\t",
-					f->seqno, target);
+					f->seqno, ntarget);
 				goto out;
 			}
 			fprintf(tm, "/* merge: ");
 			comment(tm, f->n, 0);
-			fprintf(tm,  "(%d, %d, %d) */\n\t\t", f->merge, f->seqno, target);
+			fprintf(tm,  "(%d, %d, %d) */\n\t\t", f->merge, f->seqno, ntarget);
 			fprintf(tm, "reached[%d][%d] = 1;\n\t\t", Pid, f->seqno);
 			YZcnt++;
 			lab_transfer(e, f);
@@ -1547,8 +1809,8 @@
 	multi_needed = 0;
 	didcase = 0;
 
-	if (target)
-		lastfirst(target, e, casenr); /* mergesteps only */
+	if (ntarget)
+		lastfirst(ntarget, e, casenr); /* mergesteps only */
 
 	dobackward(e, casenr);			/* the original step */
 
@@ -1557,7 +1819,7 @@
 	if (e->merge || e->merge_start)
 	{	if (!didcase)
 		{	fprintf(tb, "\n\tcase %d: ", casenr);
-			fprintf(tb, "/* STATE %d */", e->seqno);
+			fprintf(tb, "// STATE %d", e->seqno);
 			didcase++;
 		} else
 			fprintf(tb, ";");
@@ -1607,8 +1869,8 @@
 	} else
 		a = 0;
 	if (g
-	&&  (g->status&CHECK2	/* entering remotely ref'd state */
-	||   e->status&CHECK2))	/* leaving  remotely ref'd state */
+	&&  ((g->status&CHECK2)		/* entering remotely ref'd state */
+	||   (e->status&CHECK2)))	/* leaving  remotely ref'd state */
 		e->status |= I_GLOB;
 
 	/* don't remove dead edges in here, to preserve structure of fsm */
@@ -1758,8 +2020,8 @@
 				{	fprintf(tt, "#if 0\n\t/* dead link: */\n");
 					deadlink = 1;
 					if (verbose&32)
-					printf("spin: line %3d  %s, Warning: condition is always false\n",
-						g->n->ln, g->n->fn?g->n->fn->name:"");
+					printf("spin: %s:%d, warning, condition is always false\n",
+						g->n->fn?g->n->fn->name:"", g->n->ln);
 				} else
 					deadlink = 0;
 				if (0) printf("			settr %d %d\n", a, 0);
@@ -1867,7 +2129,7 @@
 	case BREAK:
 		if (e->nxt)
 		{	f = find_target(huntele(e->nxt, e->status, -1));
-			break;	/* 4.3.0 -- was missing */
+			break;	/* new 5.0 -- was missing */
 		}
 		/* else fall through */
 	default:
@@ -1888,6 +2150,26 @@
 }
 
 static int
+seq_has_el(Sequence *s, Element *g)		/* new to version 5.0 */
+{	Element *f;
+	SeqList *h;
+
+	for (f = s->frst; f; f = f->nxt)	/* g in same atomic? */
+	{	if (f == g)
+		{	return 1;
+		}
+		if (f->status & CHECK3)
+		{	continue;
+		}
+		f->status |= CHECK3; /* protect against cycles */
+		for (h = f->sub; h; h = h->nxt)
+		{	if (h->this && seq_has_el(h->this, g))
+			{	return 1;
+	}	}	}
+	return 0;
+}
+
+static int
 scan_seq(Sequence *s)
 {	Element *f, *g;
 	SeqList *h;
@@ -1896,20 +2178,22 @@
 	{	if ((f->status&CHECK2)
 		||  has_global(f->n))
 			return 1;
-		if (f->n->ntyp == GOTO)	/* may reach other atomic */
-		{
-#if 0
-			/* if jumping from an atomic without globals into
-			 * one with globals, this does the wrong thing
+		if  (f->n->ntyp == GOTO	/* may exit or reach other atomic */
+		&& !(f->status & D_ATOM))	/* cannot jump from d_step */
+		{	/* consider jump from an atomic without globals into
+			 * an atomic with globals
 			 * example by Claus Traulsen, 22 June 2007
 			 */
 			g = target(f);
+#if 1
+			if (g && !seq_has_el(s, g)) /* not internal to this atomic/dstep */
+
+#else
 			if (g
 			&& !(f->status & L_ATOM)
 			&& !(g->status & (ATOM|L_ATOM)))
 #endif
-			{	fprintf(tt, "	/* mark-down line %d */\n",
-					f->n->ln);
+			{	fprintf(tt, "\t/* mark-down line %d status %d = %d */\n", f->n->ln, f->status, (f->status & D_ATOM));
 				return 1; /* assume worst case */
 		}	}
 		for (h = f->sub; h; h = h->nxt)
@@ -1937,9 +2221,26 @@
 	return result;
 }
 
+static int
+proc_is_safe(const Lextok *n)
+{	ProcList *p;
+	/* not safe unless no local var inits are used */
+	/* note that a local variable init could refer to a global */
+
+	for (p = rdy; p; p = p->nxt)
+	{	if (strcmp(n->sym->name, p->n->name) == 0)
+		{	/* printf("proc %s safety: %d\n", p->n->name, p->unsafe); */
+			return (p->unsafe != 0);
+	}	}
+/*	non_fatal("bad call to proc_is_safe", (char *) 0);	*/
+	/* cannot happen */
+	return 0;
+}
+
 int
 has_global(Lextok *n)
-{	Lextok *v; extern int runsafe;
+{	Lextok *v;
+	static Symbol *n_seen = (Symbol *) 0;
 
 	if (!n) return 0;
 	if (AllGlobal) return 1;	/* global provided clause */
@@ -1968,6 +2269,14 @@
 	case  LEN:   return (((n->sym->xu)&(XR|XS|XX)) != (XR|XS));
 
 	case   NAME:
+		if (strcmp(n->sym->name, "_priority") == 0)
+		{	if (old_priority_rules)
+			{	if (n_seen != n->sym)
+					fatal("cannot refer to _priority with -o6", (char *) 0);
+				n_seen = n->sym;
+			}
+			return 0;
+		}
 		if (n->sym->context
 		|| (n->sym->hidden&64)
 		||  strcmp(n->sym->name, "_pid") == 0
@@ -1975,14 +2284,15 @@
 			return 0;
 		return 1;
 
-	case RUN: return 1-runsafe;
+	case RUN:
+		return proc_is_safe(n);
 
 	case C_CODE: case C_EXPR:
 		return glob_inline(n->sym->name);
 
 	case ENABLED: case PC_VAL: case NONPROGRESS:
-	case 'p': case 'q':
-	case TIMEOUT:
+	case 'p':    case 'q':
+	case TIMEOUT: case SET_P:  case GET_P:
 		return 1;
 
 	/* 	@ was 1 (global) since 2.8.5
@@ -2017,11 +2327,12 @@
 Bailout(FILE *fd, char *str)
 {
 	if (!GenCode)
-		fprintf(fd, "continue%s", str);
-	else if (IsGuard)
-		fprintf(fd, "%s%s", NextLab[Level], str);
-	else
-		fprintf(fd, "Uerror(\"block in step seq\")%s", str);
+	{	fprintf(fd, "continue%s", str);
+	} else if (IsGuard)
+	{	fprintf(fd, "%s%s", NextLab[Level], str);
+	} else
+	{	fprintf(fd, "Uerror(\"block in d_step seq\")%s", str);
+	}
 }
 
 #define cat0(x)   	putstmnt(fd,now->lft,m); fprintf(fd, x); \
@@ -2029,6 +2340,7 @@
 #define cat1(x)		fprintf(fd,"("); cat0(x); fprintf(fd,")")
 #define cat2(x,y)  	fprintf(fd,x); putstmnt(fd,y,m)
 #define cat3(x,y,z)	fprintf(fd,x); putstmnt(fd,y,m); fprintf(fd,z)
+#define cat30(x,y,z)	fprintf(fd,x,0); putstmnt(fd,y,m); fprintf(fd,z)
 
 void
 putstmnt(FILE *fd, Lextok *now, int m)
@@ -2070,12 +2382,14 @@
 		else
 			fprintf(fd, "((trpt->tau)&1)");
 		if (GenCode)
-		 printf("spin: line %3d, warning: 'timeout' in d_step sequence\n",
-			lineno);
+		 printf("spin: %s:%d, warning, 'timeout' in d_step sequence\n",
+			Fname->name, lineno);
 		/* is okay as a guard */
 		break;
 
 	case RUN:
+		if (now->sym == NULL)
+			fatal("internal error pangen2.c", (char *) 0);
 		if (claimproc
 		&&  strcmp(now->sym->name, claimproc) == 0)
 			fatal("claim %s, (not runnable)", claimproc);
@@ -2084,10 +2398,11 @@
 			fatal("eventmap %s, (not runnable)", eventmap);
 
 		if (GenCode)
-		  fatal("'run' in d_step sequence (use atomic)",
-			(char *)0);
+			fatal("'run' in d_step sequence (use atomic)", (char *)0);
 
-		fprintf(fd,"addproc(%d", fproc(now->sym->name));
+		fprintf(fd,"addproc(II, %d, %d",
+			(now->val > 0 && !old_priority_rules) ? now->val : 1,
+			fproc(now->sym->name));
 		for (v = now->lft, i = 0; v; v = v->rgt, i++)
 		{	cat2(", ", v->lft);
 		}
@@ -2094,13 +2409,21 @@
 		check_param_count(i, now);
 
 		if (i > Npars)
-		{	printf("\t%d parameters used, max %d expected\n", i, Npars);
-			fatal("too many parameters in run %s(...)",
-			now->sym->name);
+		{	/* printf("\t%d parameters used, max %d expected\n", i, Npars); */
+			fatal("too many parameters in run %s(...)", now->sym->name);
 		}
 		for ( ; i < Npars; i++)
 			fprintf(fd, ", 0");
 		fprintf(fd, ")");
+#if 0
+		/* process now->sym->name has run priority now->val */
+		if (now->val > 0 && now->val < 256 && !old_priority_rules)
+		{	fprintf(fd, " && (((P0 *)pptr(now._nr_pr - 1))->_priority = %d)", now->val);
+		}
+#endif
+		if (now->val < 0 || now->val > 255)	/* 0 itself is allowed */
+		{	fatal("bad process in run %s, valid range: 1..255", now->sym->name);
+		}
 		break;
 
 	case ENABLED:
@@ -2107,6 +2430,25 @@
 		cat3("enabled(II, ", now->lft, ")");
 		break;
 
+	case GET_P:
+		if (old_priority_rules)
+		{	fprintf(fd, "1");
+		} else
+		{	cat3("get_priority(", now->lft, ")");
+		}
+		break;
+
+	case SET_P:
+		if (!old_priority_rules)
+		{	fprintf(fd, "if (TstOnly) return 1; /* T30 */\n\t\t");
+			fprintf(fd, "set_priority(");
+			putstmnt(fd, now->lft->lft, m);
+			fprintf(fd, ", ");
+			putstmnt(fd, now->lft->rgt, m);
+			fprintf(fd, ")");
+		}
+		break;
+
 	case NONPROGRESS:
 		/* o_pm&4=progress, tau&128=claim stutter */
 		if (separate == 2)
@@ -2180,7 +2522,7 @@
 
 	case 's':
 		if (Pid == eventmapnr)
-		{	fprintf(fd, "if ((ot == EVENT_TRACE && _tp != 's') ");
+		{	fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 's') ");
 			putname(fd, "|| _qid+1 != ", now->lft, m, "");
 			for (v = now->rgt, i=0; v; v = v->rgt, i++)
 			{	if (v->lft->ntyp != CONST
@@ -2208,10 +2550,16 @@
 			break;
 		}
 		if (has_xu)
-		{	fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
-			putname(fd, "if (q_claim[", now->lft, m, "]&2) ");
-			putname(fd, "q_S_check(", now->lft, m, ", II);");
-			fprintf(fd, "\n#endif\n\t\t");
+		{	fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t");
+			putname(fd, "if (q_claim[", now->lft, m, "]&2)\n\t\t");
+			putname(fd, "{	q_S_check(", now->lft, m, ", II);\n\t\t");
+			fprintf(fd, "}\n");
+			if (has_sorted && now->val == 1)
+			{	putname(fd, "\t\tif (q_claim[", now->lft, m, "]&1)\n\t\t"); /* &1 iso &2 */
+				fprintf(fd, "{	uerror(\"sorted send on xr channel violates po reduction\");\n\t\t");
+				fprintf(fd, "}\n");
+			}
+			fprintf(fd, "#endif\n\t\t");
 		}
 		fprintf(fd, "if (q_%s",
 			(u_sync > 0 && u_async == 0)?"len":"full");
@@ -2218,14 +2566,14 @@
 		putname(fd, "(", now->lft, m, "))\n");
 
 		if (m_loss)
-			fprintf(fd, "\t\t{ nlost++; delta_m = 1; } else {");
-		else
+		{	fprintf(fd, "\t\t{ nlost++; delta_m = 1; } else {");
+		} else
 		{	fprintf(fd, "\t\t\t");
 			Bailout(fd, ";");
 		}
 
-		if (has_enabled)
-			fprintf(fd, "\n\t\tif (TstOnly) return 1;");
+		if (has_enabled || has_priority)
+			fprintf(fd, "\n\t\tif (TstOnly) return 1; /* T1 */");
 
 		if (u_sync && !u_async && rvopt)
 			fprintf(fd, "\n\n\t\tif (no_recvs(II)) continue;\n");
@@ -2232,7 +2580,7 @@
 
 		fprintf(fd, "\n#ifdef HAS_CODE\n");
 		fprintf(fd, "\t\tif (readtrail && gui) {\n");
-		fprintf(fd, "\t\t\tchar simtmp[32];\n");
+		fprintf(fd, "\t\t\tchar simtmp[64];\n");
 		putname(fd, "\t\t\tsprintf(simvals, \"%%d!\", ", now->lft, m, ");\n");
 		_isok++;
 		for (v = now->rgt, i = 0; v; v = v->rgt, i++)
@@ -2256,9 +2604,9 @@
 			printf("	%d msg parameters sent, %d expected\n", i, Mpars);
 			fatal("too many pars in send", "");
 		}
-		for ( ; i < Mpars; i++)
+		for (j = i; i < Mpars; i++)
 			fprintf(fd, ", 0");
-		fprintf(fd, ")");
+		fprintf(fd, ", %d)", j);
 		if (u_sync)
 		{	fprintf(fd, ";\n\t\t");
 			if (u_async)
@@ -2274,7 +2622,7 @@
 
 	case 'r':
 		if (Pid == eventmapnr)
-		{	fprintf(fd, "if ((ot == EVENT_TRACE && _tp != 'r') ");
+		{	fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 'r') ");
 			putname(fd, "|| _qid+1 != ", now->lft, m, "");
 			for (v = now->rgt, i=0; v; v = v->rgt, i++)
 			{	if (v->lft->ntyp != CONST
@@ -2342,10 +2690,13 @@
 			break;
 		}
 		if (has_xu)
-		{	fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
-			putname(fd, "if (q_claim[", now->lft, m, "]&1) ");
-			putname(fd, "q_R_check(", now->lft, m, ", II);");
-			fprintf(fd, "\n#endif\n\t\t");
+		{	fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t");
+			putname(fd, "if (q_claim[", now->lft, m, "]&1)\n\t\t");
+			putname(fd, "{	q_R_check(", now->lft, m, ", II);\n\t\t");
+			if (has_random && now->val != 0)
+			fprintf(fd, "	uerror(\"rand receive on xr channel violates po reduction\");\n\t\t");
+			fprintf(fd, "}\n");
+			fprintf(fd, "#endif\n\t\t");
 		}
 		if (u_sync)
 		{	if (now->val >= 2)
@@ -2398,6 +2749,8 @@
 				  fprintf(fd, "0, %d, 0)) ", i);
 				  Bailout(fd, "");
 			}	}
+			if (has_enabled || has_priority)
+				fprintf(fd, ";\n\t\tif (TstOnly) return 1 /* T2 */");
 		} else	/* random receive: val 1 or 3 */
 		{	fprintf(fd, ";\n\t\tif (!(XX = Q_has(");
 			putname(fd, "", now->lft, m, "");
@@ -2415,19 +2768,21 @@
 				fprintf(fd, ", 0, 0");
 			fprintf(fd, "))) ");
 			Bailout(fd, "");
-			fprintf(fd, ";\n\t\t");
-			if (multi_oval)
-			{	check_needed();
-				fprintf(fd, "(trpt+1)->bup.ovals[%d] = ",
-					multi_oval-1);
-				multi_oval++;
-			} else
-				fprintf(fd, "(trpt+1)->bup.oval = ");
-			fprintf(fd, "XX");
-		}
 
-		if (has_enabled)
-			fprintf(fd, ";\n\t\tif (TstOnly) return 1");
+			if (has_enabled || has_priority)
+				fprintf(fd, ";\n\t\tif (TstOnly) return 1 /* T2 */");
+			if (!GenCode) {
+				fprintf(fd, ";\n\t\t");
+				if (multi_oval)
+				{	check_needed();
+					fprintf(fd, "(trpt+1)->bup.ovals[%d] = ",
+						multi_oval-1);
+					multi_oval++;
+				} else
+				{	fprintf(fd, "(trpt+1)->bup.oval = ");
+				}
+				fprintf(fd, "XX");
+		}	}
 
 		if (j == 0 && now->val >= 2)
 		{	fprintf(fd, ";\n\t\t");
@@ -2439,16 +2794,20 @@
 			fprintf(fd, ";\n\t\t");
 			/* no variables modified */
 			if (j == 0 && now->val == 0)
-			{	fprintf(fd, "if (q_flds[((Q0 *)qptr(");
+			{	fprintf(fd, "\n#ifndef BFS_PAR\n\t\t");
+				/* q_flds values are not shared among cores */
+				fprintf(fd, "if (q_flds[((Q0 *)qptr(");
 				putname(fd, "", now->lft, m, "-1))->_t]");
-				fprintf(fd, " != %d)\n\t", i);
-				fprintf(fd, "\t\tUerror(\"wrong nr of msg fields in rcv\");\n\t\t");
+				fprintf(fd, " != %d)\n\t\t\t", i);
+				fprintf(fd, "Uerror(\"wrong nr of msg fields in rcv\");\n");
+				fprintf(fd, "#endif\n\t\t");
 			}
 
 			for (v = now->rgt; v; v = v->rgt)
-				if ((v->lft->ntyp != CONST
+			{	if ((v->lft->ntyp != CONST
 				&&   v->lft->ntyp != EVAL))
-					jj++;	/* nr of vars needing bup */
+				{	jj++;	/* nr of vars needing bup */
+			}	}
 
 			if (jj)
 			for (v = now->rgt, i = 0; v; v = v->rgt, i++)
@@ -2467,12 +2826,12 @@
 					sprintf(tempbuf, "(trpt+1)->bup.oval = ");
 
 				if (v->lft->sym && !strcmp(v->lft->sym->name, "_"))
-				{	fprintf(fd, tempbuf);
+				{	fprintf(fd, tempbuf, (char *) 0);
 					putname(fd, "qrecv(", now->lft, m, "");
 					fprintf(fd, ", XX-1, %d, 0);\n\t\t", i);
 				} else
 				{	_isok++;
-					cat3(tempbuf, v->lft, ";\n\t\t");
+					cat30(tempbuf, v->lft, ";\n\t\t");
 					_isok--;
 				}
 			}
@@ -2485,7 +2844,7 @@
 					&&  v->lft->ntyp != EVAL
 					&&  v->lft->sym
 					&&  v->lft->sym->type != STRUCT	/* not a struct */
-					&&  v->lft->sym->nel == 1	/* not an array */
+					&&  (v->lft->sym->nel == 1 && v->lft->sym->isarray == 0) /* not array */
 					&&  strcmp(v->lft->sym->name, "_") != 0)
 					for (w = v->rgt; w; w = w->rgt)
 						if (v->lft->sym == w->lft->sym)
@@ -2501,6 +2860,7 @@
 
 			if (v->lft->ntyp != CONST
 			&&  v->lft->ntyp != EVAL
+			&&  v->lft->sym != NULL
 			&&  strcmp(v->lft->sym->name, "_") != 0)
 			{	nocast=1;
 				_isok++;
@@ -2515,6 +2875,7 @@
 
 			if (v->lft->ntyp != CONST
 			&&  v->lft->ntyp != EVAL
+			&&  v->lft->sym != NULL
 			&& strcmp(v->lft->sym->name, "_") != 0
 			&&  (v->lft->ntyp != NAME
 			||   v->lft->sym->type != CHAN))
@@ -2658,8 +3019,10 @@
 		break;
 
 	case ASGN:
-		if (has_enabled)
-		fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+		if (check_track(now) == STRUCT) { break; }
+
+		if (has_enabled || has_priority)
+		fprintf(fd, "if (TstOnly) return 1; /* T3 */\n\t\t");
 		_isok++;
 
 		if (!GenCode)
@@ -2669,14 +3032,27 @@
 				sprintf(tempbuf, "(trpt+1)->bup.ovals[%d] = ",
 					multi_oval-1);
 				multi_oval++;
-				cat3(tempbuf, now->lft, ";\n\t\t");
+				cat30(tempbuf, now->lft, ";\n\t\t");
 			} else
 			{	cat3("(trpt+1)->bup.oval = ", now->lft, ";\n\t\t");
 		}	}
+		if (now->lft->sym
+		&&  now->lft->sym->type == PREDEF
+		&&  strcmp(now->lft->sym->name, "_") != 0
+		&&  strcmp(now->lft->sym->name, "_priority") != 0)
+		{	fatal("invalid assignment to %s", now->lft->sym->name);
+		}
+
 		nocast = 1; putstmnt(fd,now->lft,m); nocast = 0;
 		fprintf(fd," = ");
 		_isok--;
-		putstmnt(fd,now->rgt,m);
+		if (now->lft->sym->isarray
+		&&  now->rgt->ntyp == ',')	/* array initializer */
+		{	putstmnt(fd, now->rgt->lft, m);
+			non_fatal("cannot use an array list initializer here", (char *) 0);
+		} else
+		{	putstmnt(fd, now->rgt, m);
+		}
 
 		if (now->sym->type != CHAN
 		||  verbose > 0)
@@ -2695,8 +3071,8 @@
 		break;
 
 	case PRINT:
-		if (has_enabled)
-		fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+		if (has_enabled || has_priority)
+			fprintf(fd, "if (TstOnly) return 1; /* T4 */\n\t\t");
 #ifdef PRINTF
 		fprintf(fd, "printf(%s", now->sym->name);
 #else
@@ -2709,8 +3085,8 @@
 		break;
 
 	case PRINTM:
-		if (has_enabled)
-		fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+		if (has_enabled || has_priority)
+			fprintf(fd, "if (TstOnly) return 1; /* T5 */\n\t\t");
 		fprintf(fd, "printm(");
 		if (now->lft && now->lft->ismtyp)
 			fprintf(fd, "%d", now->lft->val);
@@ -2732,7 +3108,7 @@
 
 	case   'q':
 		if (terse)
-			fprintf(fd, "%s", now->sym->name);
+			fprintf(fd, "%s", now->sym?now->sym->name:"?");
 		else
 			fprintf(fd, "%d", remotelab(now));
 		break;
@@ -2748,14 +3124,16 @@
 		break;
 
 	case C_CODE:
-		fprintf(fd, "/* %s */\n\t\t", now->sym->name);
-		if (has_enabled)
-			fprintf(fd, "if (TstOnly) return 1;\n\t\t");
-		if (!GenCode)	/* not in d_step */
-		{	fprintf(fd, "sv_save();\n\t\t");
-			/* store the old values for reverse moves */
-		}
-		plunk_inline(fd, now->sym->name, 1);
+		if (now->sym)
+			fprintf(fd, "/* %s */\n\t\t", now->sym->name);
+		if (has_enabled || has_priority)
+			fprintf(fd, "if (TstOnly) return 1; /* T6 */\n\t\t");
+
+		if (now->sym)
+			plunk_inline(fd, now->sym->name, 1, GenCode);
+		else
+			fatal("internal error pangen2.c", (char *) 0);
+
 		if (!GenCode)
 		{	fprintf(fd, "\n");	/* state changed, capture it */
 			fprintf(fd, "#if defined(C_States) && (HAS_TRACK==1)\n");
@@ -2765,10 +3143,10 @@
 		break;
 
 	case ASSERT:
-		if (has_enabled)
-			fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+		if (has_enabled || has_priority)
+			fprintf(fd, "if (TstOnly) return 1; /* T7 */\n\t\t");
 
-		cat3("assert(", now->lft, ", ");
+		cat3("spin_assert(", now->lft, ", ");
 		terse = nocast = 1;
 		cat3("\"", now->lft, "\", II, tt, t)");
 		terse = nocast = 0;
@@ -2788,7 +3166,7 @@
 			break;
 		}
 
-		if (has_enabled)
+		if (has_enabled || has_priority)
 		{	fprintf(fd, "if (TstOnly)\n\t\t\t");
 			fprintf(fd, "return (II+1 == now._nr_pr);\n\t\t");
 		}
@@ -2797,16 +3175,30 @@
 		break;
 
 	default:
-		printf("spin: bad node type %d (.m) - line %d\n",
-			now->ntyp, now->ln);
-		fflush(tm);
+		printf("spin: error, %s:%d, bad node type %d (.m)\n",
+			now->fn->name, now->ln, now->ntyp);
+		fflush(fd);
 		alldone(1);
 	}
 }
 
+char *
+simplify_name(char *s)
+{	char *t = s;
+
+	if (!old_scope_rules)
+	{	while (*t == '_' || isdigit((int)*t))
+		{	t++;
+	}	}
+
+	return t;
+}
+
 void
 putname(FILE *fd, char *pre, Lextok *n, int m, char *suff) /* varref */
 {	Symbol *s = n->sym;
+	char *ptr;
+
 	lineno = n->ln; Fname = n->fn;
 
 	if (!s)
@@ -2819,12 +3211,13 @@
 	{	fprintf(fd, "%s%s%s", pre, n->sym->name, suff);
 		return;
 	}
+
 	if (!s->type)	/* not a local name */
 		s = lookup(s->name);	/* must be a global */
 
 	if (!s->type)
 	{	if (strcmp(pre, ".") != 0)
-		non_fatal("undeclared variable '%s'", s->name);
+			fatal("undeclared variable '%s'", s->name);
 		s->type = INT;
 	}
 
@@ -2831,36 +3224,54 @@
 	if (s->type == PROCTYPE)
 		fatal("proctype-name '%s' used as array-name", s->name);
 
-	fprintf(fd, pre);
+	fprintf(fd, pre, 0);
 	if (!terse && !s->owner && evalindex != 1)
-	{	if (s->context
-		||  strcmp(s->name, "_p") == 0
-		||  strcmp(s->name, "_pid") == 0)
-		{	fprintf(fd, "((P%d *)this)->", Pid);
+	{	if (old_priority_rules
+		&&  strcmp(s->name, "_priority") == 0)
+		{	fprintf(fd, "1");	
+			goto shortcut;
 		} else
-		{	int x = strcmp(s->name, "_");
-			if (!(s->hidden&1) && x != 0)
-				fprintf(fd, "now.");
-			if (x == 0 && _isok == 0)
-				fatal("attempt to read value of '_'", 0);
-	}	}
+		{	if (s->context
+			||  strcmp(s->name, "_p") == 0
+			||  strcmp(s->name, "_pid") == 0
+			||  strcmp(s->name, "_priority") == 0)
+			{	fprintf(fd, "((P%d *)this)->", Pid);
+			} else
+			{	int x = strcmp(s->name, "_");
+				if (!(s->hidden&1) && x != 0)
+					fprintf(fd, "now.");
+				if (x == 0 && _isok == 0)
+					fatal("attempt to read value of '_'", 0);
+	}	}	}
 
-	if (withprocname
-	&&  s->context
-	&&  strcmp(pre, "."))
-		fprintf(fd, "%s:", s->context->name);
+	if (terse && buzzed == 1)
+	{	fprintf(fd, "B_state.%s", (s->context)?"local[B_pid].":"");
+	}
 
+	ptr = s->name;
+
+	if (!dont_simplify	/* new 6.4.3 */
+	&&  s->type != PREDEF)	/* new 6.0.2 */
+	{	if (withprocname
+		&&  s->context
+		&&  strcmp(pre, "."))
+		{	fprintf(fd, "%s:", s->context->name);
+			ptr = simplify_name(ptr);
+		} else
+		{	if (terse)
+			{	ptr = simplify_name(ptr);
+	}	}	}
+
 	if (evalindex != 1)
-		fprintf(fd, "%s", s->name);
+		fprintf(fd, "%s", ptr);
 
-	if (s->nel != 1)
+	if (s->nel > 1 || s->isarray == 1)
 	{	if (no_arrays)
-		{
-		non_fatal("ref to array element invalid in this context",
-			(char *)0);
-		printf("\thint: instead of, e.g., x[rs] qu[3], use\n");
-		printf("\tchan nm_3 = qu[3]; x[rs] nm_3;\n");
-		printf("\tand use nm_3 in sends/recvs instead of qu[3]\n");
+		{	non_fatal("ref to array element invalid in this context",
+				(char *)0);
+			printf("\thint: instead of, e.g., x[rs] qu[3], use\n");
+			printf("\tchan nm_3 = qu[3]; x[rs] nm_3;\n");
+			printf("\tand use nm_3 in sends/recvs instead of qu[3]\n");
 		}
 		/* an xr or xs reference to an array element
 		 * becomes an exclusion tag on the array itself -
@@ -2885,15 +3296,32 @@
 			|| (!n->lft && s->nel > 0))
 			{	cat3("[", n->lft, "]");
 			} else
-			{	cat3("[ Index(", n->lft, ", ");
+			{	/* attempt to catch arrays that are indexed with an array element in the same array
+				 * this causes trouble in the verifier in the backtracking
+				 * e.g., restoring a[?] in the assignment: a [a[1]] = x where a[1] == 1
+				 * but it is hard when the array is inside a structure, so the names dont match
+				 */
+#if 0
+				if (n->lft->ntyp == NAME)
+				{	printf("%4d: Basename %s	index %s\n",
+						n->lft->ln, s->name, n->lft->sym->name);
+				}
+#endif
+				cat3("[ Index(", n->lft, ", ");
 				fprintf(fd, "%d) ]", s->nel);
-			}
-		}
-	}
+		}	}
+	} else
+	{	if (n->lft	/* effectively a scalar, but with an index */
+		&& (n->lft->ntyp != CONST
+		||  n->lft->val != 0))
+		{	fatal("ref to scalar '%s' using array index", (char *) ptr);
+	}	}
+
 	if (s->type == STRUCT && n->rgt && n->rgt->lft)
 	{	putname(fd, ".", n->rgt->lft, m, "");
 	}
-	fprintf(fd, suff);
+shortcut:
+	fprintf(fd, suff, 0);
 }
 
 void
@@ -2908,7 +3336,11 @@
 			putstmnt(fd, n->lft->lft, m);	/* pid */
 			fprintf(fd, "]");
 		}
-		fprintf(fd, ".%s", n->sym->name);
+		if (ltl_mode)
+		{	fprintf(fd, ":%s", n->sym->name);
+		} else
+		{	fprintf(fd, ".%s", n->sym->name);
+		}
 	} else
 	{	if (Sym_typ(n) < SHORT)
 		{	promoted = 1;
--- a/sys/src/cmd/spin/pangen2.h
+++ b/sys/src/cmd/spin/pangen2.h
@@ -1,32 +1,15 @@
 /***** spin: pangen2.h *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
-static char *Nvr1[] = {		/* allow separate compilation */
-	"#ifdef VERI",
-	"void",
-	"check_claim(int st)",
-	"{",
-	"	if (st == endclaim)",
-	"		uerror(\"claim violated!\");",
-	"	if (stopstate[VERI][st])",
-	"		uerror(\"end state in claim reached\");",
-	"}",
+static const char *Pre0[] = {
+	"#ifdef SC",
+	"	#define _FILE_OFFSET_BITS	64",	/* allows file sizes greater than 2Gb */
 	"#endif",
-	0,
-};
-
-static char *Pre0[] = {
-"#ifdef SC",
-	"#define _FILE_OFFSET_BITS	64",	/* to allow file sizes greater than 2Gb */
-"#endif",
 	"#include <stdio.h>",
 	"#include <signal.h>",
 	"#include <stdlib.h>",
@@ -38,12 +21,14 @@
 		"#include <time.h>",
 	"#else",
 		"#include <unistd.h>",
-		"#include <sys/times.h>",	/* new 4.3.0 */
+		"#include <sys/times.h>",
 	"#endif",
 	"#include <sys/types.h>",	/* defines off_t */
 	"#include <sys/stat.h>",
+	"#include <limits.h>",
 	"#include <fcntl.h>",
-	"#define Offsetof(X, Y)	((unsigned long)(&(((X *)0)->Y)))",
+
+	"#define Offsetof(X, Y)	((ulong)(&(((X *)0)->Y)))",
 	"#ifndef max",
 	"#define max(a,b) (((a)<(b)) ? (b) : (a))",
 	"#endif",
@@ -53,12 +38,62 @@
 	0,
 };
 
-static char *Preamble[] = {
+static const char *Separate[] = {
+	"#ifdef COLLAPSE",
+	"	#if (NCORE>1 && !defined(SEP_STATE)) || defined(BFS_PAR)",
+	"		volatile ulong *ncomps;	/* in shared memory */",
+	"	#else",
+	"		ulong ncomps[256+2];",
+	"	#endif",
+	"#endif",
+	"Trans ***trans;	/* 1 ptr per state per proctype */\n",
+	"",
+	"#if VECTORSZ>32000",
+	"	int P_o[MAXPROC], P_o_tmp[MAXPROC+1];",
+	"	int Q_o[MAXQ],    Q_o_tmp[MAXPROC+1];",
+	"",
+	"	int *proc_offset = (int *) P_o;",
+	"	int *q_offset    = (int *) Q_o;",
+	"#else",
+	"	short P_o[MAXPROC], P_o_tmp[MAXPROC+1];",
+	"	short Q_o[MAXQ],    Q_o_tmp[MAXPROC+1];",
+	"",
+	"	short *proc_offset = (short *) P_o;",
+	"	short *q_offset    = (short *) Q_o;",
+	"#endif",
+	"uchar P_s[MAXPROC+1], P_s_tmp[MAXPROC+1];",
+	"uchar Q_s[MAXQ+1],    Q_s_tmp[MAXQ+1];",
+	"uchar *proc_skip = (uchar *) P_s;",
+	"uchar *q_skip    = (uchar *) Q_s;",
+	"",
+	"#ifdef TRIX",
+	"	TRIX_v6 *freebodies;",
+	"	TRIX_v6 *processes[MAXPROC+1];",
+	"	TRIX_v6 *channels[MAXQ+1];",
+	"	long _p_count[MAXPROC];",
+	"	long _c_count[MAXPROC];",
+	"#endif\n",
+	"ulong  vsize;	/* vector size in bytes */",
+	"#ifdef SVDUMP",
+	"	int vprefix=0, svfd;	/* runtime option -pN */",
+	"#endif",
+	"char *tprefix = \"trail\";	/* runtime option -tsuffix */",
+	"short boq = -1;		/* blocked_on_queue status */",
+	"int _;	/* predefined write-only variable */",
+	"#ifdef PEG",
+	"	long peg[NTRANS];",
+	"#endif",
+	0,
+};
 
+static const char *Preamble[] = {
+	"#ifdef RANDOMIZE",
+	"	#define T_RAND  RANDOMIZE",
+	"#endif",
 	"#ifdef CNTRSTACK",
-	"#define onstack_now()	(LL[trpt->j6] && LL[trpt->j7])",
-	"#define onstack_put()	 LL[trpt->j6]++; LL[trpt->j7]++",
-	"#define onstack_zap()	 LL[trpt->j6]--; LL[trpt->j7]--",
+	"	#define onstack_now()	(LL[trpt->j6] && LL[trpt->j7])",
+	"	#define onstack_put()	 LL[trpt->j6]++; LL[trpt->j7]++",
+	"	#define onstack_zap()	 LL[trpt->j6]--; LL[trpt->j7]--",
 	"#endif",
 
 	"#if !defined(SAFETY) && !defined(NOCOMP)",
@@ -68,13 +103,13 @@
 		 * S_A remembers how many leading bytes in the sv
 		 * are used for these markers + fairness bits
 		 */
-		"#define V_A	(((now._a_t&1)?2:1) << (now._a_t&2))",
-		"#define A_V	(((now._a_t&1)?1:2) << (now._a_t&2))",
-		"int	S_A = 0;",
+	"	#define V_A	(((now._a_t&1)?2:1) << (now._a_t&2))",
+	"	#define A_V	(((now._a_t&1)?1:2) << (now._a_t&2))",
+	"	int	S_A = 0;",
 	"#else",
-		"#define V_A	0",
-		"#define A_V	0",
-		"#define S_A	0",
+	"	#define V_A	0",
+	"	#define A_V	0",
+	"	#define S_A	0",
 	"#endif",
 
 "#ifdef MA",
@@ -82,7 +117,7 @@
 	"#undef onstack_put",
 	"#undef onstack_zap",
 	"#define onstack_put()	;",
-	"#define onstack_zap()	gstore((char *) &now, vsize, 4)",
+	"#define onstack_zap()	g_store((char *) &now, vsize, 4)",
 "#else",
 	"#if defined(FULLSTACK) && !defined(BITSTATE)",
 	"#define onstack_put()	trpt->ostate = Lstate",
@@ -93,165 +128,284 @@
 	"	}",
 	"#endif",
 "#endif",
-	"struct H_el {",
-	"	struct H_el *nxt;",
-	"#ifdef FULLSTACK",
-	"	unsigned int tagged;",
-		"#if defined(BITSTATE) && !defined(NOREDUCE) && !defined(SAFETY)",
-		"	unsigned int proviso;", /* uses just 1 bit 0/1 */
-		"#endif",
-	"#endif",
-	"#if defined(CHECK) || (defined(COLLAPSE) && !defined(FULLSTACK))",
-	"	unsigned long st_id;",
-	"#endif",
-	"#ifdef COLLAPSE",
-		"#if VECTORSZ<65536",
-	"	unsigned short ln;",	/* length of vector */
-		"#else",
-	"	unsigned long ln;",	/* length of vector */
-		"#endif",
-	"#endif",
-	"#if !defined(SAFETY) || defined(REACH)",
-	"	unsigned int D;",
-	"#endif",
-	"	unsigned state;",
-	"} **H_tab, **S_Tab;\n",
-
-	"typedef struct Trail {",
-	"	int   st;	/* current state */",
-	"	uchar pr;	/* process id */",
-	"	uchar tau;	/* 8 bit-flags */",
-	"	uchar o_pm;	/* 8 more bit-flags */",
-	"#if 0",
-	"	Meaning of bit-flags:",
-	"	tau&1   -> timeout enabled",
-	"	tau&2   -> request to enable timeout 1 level up (in claim)",
-	"	tau&4   -> current transition is a  claim move",
-	"	tau&8   -> current transition is an atomic move",
-	"	tau&16  -> last move was truncated on stack",
-	"	tau&32  -> current transition is a preselected move",
-	"	tau&64  -> at least one next state is not on the stack",
-	"	tau&128 -> current transition is a stutter move",
-
-	"	o_pm&1	-> the current pid moved -- implements else",
-	"	o_pm&2	-> this is an acceptance state",
-	"	o_pm&4	-> this is a  progress state",
-	"	o_pm&8	-> fairness alg rule 1 undo mark",
-	"	o_pm&16	-> fairness alg rule 3 undo mark",
-	"	o_pm&32	-> fairness alg rule 2 undo mark",
-	"	o_pm&64 -> the current proc applied rule2",
-	"	o_pm&128 -> a fairness, dummy move - all procs blocked",
-	"#endif",
-	"#if defined(FULLSTACK) && defined(MA) && !defined(BFS)",
-	"	uchar proviso;",
-	"#endif",
-	"#ifndef BFS",
-	"	uchar  o_n, o_ot;	/* to save locals */",
-	"#endif",
-	"	uchar  o_m;",
-	"#ifdef EVENT_TRACE",
-		"#if nstates_event<256",
-	"	uchar o_event;",
-		"#else",
-	"	unsigned short o_event;",
-		"#endif",
-	"#endif",
-	"	int o_tt;",
-	"#ifndef BFS",
-	"	short o_To;",
-		"#ifdef RANDOMIZE",
-	"	short oo_i;",
-		"#endif",
-	"#endif",
-	"#if defined(HAS_UNLESS) && !defined(BFS)",
-	"	int e_state;	/* if escape trans - state of origin */",
-	"#endif",
-	"#if (defined(FULLSTACK) && !defined(MA)) || defined(BFS)",
-	"	struct H_el *ostate;	/* pointer to stored state */",
-	"#endif",
-	/* CNTRSTACK when !NOREDUCE && BITSTATE && SAFETY, uses LL[] */
-	"#if defined(CNTRSTACK) && !defined(BFS)",
-	"	long	j6, j7;",
-	"#endif",
-	"	Trans *o_t;",	/* transition fct, next state   */
-	"#ifdef HAS_SORTED",
-	"	short ipt;",	/* insertion slot in q */
-	"#endif",
-	"	union {",
-	"		int oval;",	/* single backup value of variable */
-	"		int *ovals;",	/* ptr to multiple values */
-	"	} bup;",
-	"} Trail;",
+	"H_el	**H_tab, **S_Tab;",
+	"/* #ifndef BFS_PAR */",
+	"	H_el   *Lstate;",
+	"/* #endif */",
 	"Trail	*trail, *trpt;",
-
 	"FILE	*efd;",
 	"uchar	*this;",
 	"long	maxdepth=10000;",
 	"long	omaxdepth=10000;",
+	"#ifdef BCS",
+	"	/* bitflags in trpt->bcs */",
+	"	#define B_PHASE1	1",
+	"	#define B_PHASE2	2",
+	"	#define B_FORCED	4",
+	"int	sched_max = 0;",
+	"#endif",
+	"",
+	"double	quota;	/* time limit */",
+	"#if NCORE>1",
+	"	long	z_handoff = -1;",
+	"#endif",
 	"#ifdef SC",	/* stack cycling */
-	"char	*stackfile;",
+	"	char	*stackfile;",
  	"#endif",
 	"uchar	*SS, *LL;",
+	"",
+	"uchar	reversing = 0;",
 	"uchar	HASH_NR = 0;",
 	"",
 	"double memcnt = (double) 0;",
-	"double memlim = (double) (1<<30);",
+	"double memlim = (double) (1<<30); /* 1 GB */",
+	"#if NCORE>1",
+	"double mem_reserved = (double) 0;",
+	"#endif",
 	"",
 	"/* for emalloc: */",
 	"static char *have;",
 	"static long left = 0L;",
 	"static double fragment = (double) 0;",
-	"static unsigned long grow;",
+	"static ulong grow;",
 	"",
+#if 1
 	"unsigned int HASH_CONST[] = {",
+	"	/* generated by hashgen 421 -- assumes 4 bytes per int */",
+	"	0x100d4e63,	0x0fc22f87,	0xa7155c77,	0x78f2c3b9,",
+	"	0xde32d207,	0xc27d305b,	0x1bb3fb2b,	0x2798c7a5,",
+	"	0x9c675ffd,	0x777d9081,	0x07aef2f1,	0xae08922f,",
+	"	0x5bd365b7,	0xed51c47b,	0x9b5aeea1,	0xbcc9d431,",
+	"	0x396d8fff,	0xa2fd1367,	0x08616521,	0x5e84991f,",
+	"	0x87495bc5,	0x2930039b,	0xceb6a593,	0xfe522d63,",
+	"	0x7ff60baf,	0xf89b1fbf,	0x74c01755,	0xe0c559bf,",
+	"	0x3669fc47,	0x8756d3bf,	0x14f78445,	0x24c41779,",
+	"	0x0af7b129,	0xde22368d,	0x3e1c01e3,	0xaf773e49,",
+	"	0x5b762459,	0x86d12911,	0x0953a3af,	0xb66dc23d,",
+	"	0x96b3bd4f,	0x19b1dd51,	0xd886fbc3,	0xa7f3a025,",
+	"	0xccb48e63,	0x87d8f027,	0x2bea270d,	0xdb0e9379,",
+	"	0x78c09f21,	0x0cbbfe07,	0xea4bc7c3,	0x5bfbc3c9,",
+	"	0x3c6e53fd,	0xab320cdd,	0x31041409,	0x416e7485,",
+	"	0xe41d75fd,	0xc3c5060f,	0x201a9dc1,	0x93dee72b,",
+	"	0x6461305f,	0xc571dec5,	0xa1fd21c5,	0xfb421ce1,",
+	"	0x7f024b05,	0xfa518819,	0x6c9777fb,	0x0d4d9351,",
+	"	0x08b33861,	0xccb9d0f3,	0x34112791,	0xe962d7c9,",
+	"	0x8d742211,	0xcd9c47a1,	0x64437b69,	0x5fe40feb,",
+	"	0x806113cb,	0x10e1d593,	0x821851b3,	0x057a1ff3,",
+	"	0x8ededc0b,	0x90dd5b31,	0x635ff359,	0x68dbcd35,",
+	"	0x1050ff4f,	0xdbb07257,	0x486336db,	0x83af1e75,",
+	"	0x432f1799,	0xc1d0e7e7,	0x21f4eb5b,	0x881ec2c1,",
+	"	0x23f3b539,	0x6cdfb80d,	0x71d474cf,	0x97d5d4a9,",
+	"	0xf721d2e5,	0xb5ff3711,	0x3f2e58cd,	0x4e06e3d9,",
+	"	0x7d711739,	0x927887df,	0x7d57ad71,	0x232eb767,",
+	"	0xe3f5cc51,	0x6576b443,	0xed17bf1f,	0x8828b637,",
+	"	0xc940f6ab,	0xc7b830ef,	0x11ed8a13,	0xaff20949,",
+	"	0xf28a8465,	0x0da10cf9,	0xb512497d,	0x44accae1,",
+	"	0x95e0929f,	0xe08c8901,	0xfd22d6c9,	0xb6a5c029,",
+	"	0xaadb428d,	0x6e8a453d,	0x3d5c0195,	0x8bf4ae39,",
+	"	0xbf83ab19,	0x3e9dac33,	0xc4df075d,	0x39472d71,",
+	"	0xb8647725,	0x1a6d4887,	0x78a03577,	0xafd76ef7,",
+	"	0xc1a1d6b3,	0x1afb33c5,	0x87896299,	0x5cc992ef,",
+	"	0x7f805d0d,	0x089a039b,	0xa353cc27,	0x57b296b3,",
+	"	0x52badec9,	0xc916e431,	0x09171957,	0x14996d51,",
+	"	0xe87e32c7,	0xb4fdbb5d,	0xdd216a03,	0x4ddd3fff,",
+	"	0x767d5c57,	0x79c97509,	0xab70543b,	0xc5feca4f,",
+	"	0x8eb37b89,	0x20a2cefd,	0xf4b00b91,	0xf166593d,",
+	"	0x7bf50f65,	0x753e6c8b,	0xfb5b81dd,	0xf2d45ef5,",
+	"	0x9741c04f,	0x300da48d,	0x01dc4121,	0xa112cd47,",
+	"	0x0223b24b,	0xa89fbce7,	0x681e1f7b,	0xe7c6aedf,",
+	"	0x1fd3d523,	0x561ba723,	0xf54042fb,	0x1a516751,",
+	"	0xcd085bd5,	0xe74246d5,	0x8b170b5d,	0x249985e9,",
+	"	0x5b4d9cf7,	0xe9912323,	0x5fc0f339,	0x41f8f051,",
+	"	0x8a296fb1,	0x62909f51,	0x2c05d695,	0x095efccb,",
+	"	0xa91574f1,	0x0f5cc6c3,	0x23a2ca2b,	0xc6053ec1,",
+	"	0xeb19e081,	0x3d1b3997,	0xb0c5f3cd,	0xe5d85b35,",
+	"	0x1cb1bdf1,	0x0c8f278f,	0x518249c3,	0x9f61b68d,",
+	"	0xade0919d,	0x779e29c3,	0xdbac9485,	0x2ce149a9,",
+	"	0x254c2409,	0x205b34fb,	0xc8ab1a89,	0x6b4a2585,",
+	"	0x2303d94b,	0x8fa186b9,	0x49826da5,	0xd23a37ad,",
+	"	0x680b18c9,	0xa46fbd7f,	0xe42c2cf9,	0xf7cfcb5f,",
+	"	0xb4842b8b,	0xe483780d,	0x66cf756b,	0x3eb73781,",
+	"	0x41ca17a5,	0x59f91b0f,	0x92fb67d9,	0x0a5c330f,",
+	"	0x46013fdb,	0x3b0634af,	0x9024f533,	0x96a001a7,",
+	"	0x15bcd793,	0x3a311fb1,	0x78913b8b,	0x9d4a5ddf,",
+	"	0x33189b31,	0xa99e8283,	0xf7cb29e9,	0x12d64a27,",
+	"	0xeda770ff,	0xa7320297,	0xbd3c14a5,	0x96d0156f,",
+	"	0x0115db95,	0x7f79f52b,	0xa6d52521,	0xa063d4bd,",
+	"	0x9cb5e039,	0x42cf8195,	0xcb716835,	0x1bc21273,",
+	"	0x5a67ad27,	0x4b3b0545,	0x162cda67,	0x0489166b,",
+	"	0x85fd06a9,	0x562b037d,	0x995bc1f3,	0xe144e78b,",
+	"	0x1e749f69,	0xa36df057,	0xcfee1667,	0x8c4116b7,",
+	"	0x94647fe3,	0xe6899df7,	0x6d218981,	0xf1069079,",
+	"	0xd1851a33,	0xf424fc83,	0x24467005,	0xad8caf59,",
+	"	0x1ae5da13,	0x497612f9,	0x10f6d1ef,	0xeaf4ff05,",
+	"	0x405f030b,	0x693b041d,	0x2065a645,	0x9fec71b3,",
+	"	0xc3bd1b0f,	0xf29217a3,	0x0f25e15d,	0xd48c2b97,",
+	"	0xce8acf2d,	0x0629489b,	0x1a5b0e01,	0x32d0c059,",
+	"	0x2d3664bf,	0xc45f3833,	0xd57f551b,	0xbdd991c5,",
+	"	0x9f97da9f,	0xa029c2a9,	0x5dd0cbdf,	0xe237ba41,",
+	"	0x62bb0b59,	0x93e7d037,	0x7e495619,	0x51b8282f,",
+	"	0x853e8ef3,	0x9b8abbeb,	0x055f66f9,	0x2736f7e5,",
+	"	0x8d7e6353,	0x143abb65,	0x4e2bb5b3,	0x872e1adf,",
+	"	0x8fcac853,	0xb7cf6e57,	0x12177f3d,	0x1d2da641,",
+	"	0x07856425,	0xc0ed53dd,	0x252271d9,	0x79874843,",
+	"	0x0aa8c9b5,	0x7e804f93,	0x2d080e09,	0x3929ddfd,",
+	"	0x36433dbd,	0xd6568c17,	0xe624e939,	0xb33189ef,",
+	"	0x29e68bff,	0x8aae2433,	0xe6335499,	0xc5facd9d,",
+	"	0xbd5afc65,	0x7a584fa7,	0xab191435,	0x64bbdeef,",
+	"	0x9f5cd8e1,	0xb3a1be05,	0xbd0c1753,	0xb00e2c7f,",
+	"	0x6a96e315,	0x96a31589,	0x660af5af,	0xc0438d43,",
+	"	0x17637373,	0x6460e8df,	0x7d458de9,	0xd76b923f,",
+	"	0x316f045f,	0x3ccbd035,	0x63f64d81,	0xd990d969,",
+	"	0x7c860a93,	0x99269ff7,	0x6fbcac8f,	0xd8cc562b,",
+	"	0x67141071,	0x09f85ea3,	0x1298f2dd,	0x41fa86e5,",
+	"	0xce1d7cf5,	0x6b232c9d,	0x8f093d4b,	0x3203ad4b,",
+	"	0x07d70d5f,	0x38c44c75,	0x0887c9ef,	0x1833acf5,",
+	"	0xa3607f85,	0x7d367573,	0x0ea4ffc3,	0xad2d09c1,",
+	"	0x7a1e664f,	0xef41dff5,	0x03563491,	0x67f30a1f,",
+	"	0x5ce5f9ef,	0xa2487a27,	0xe5077957,	0x9beb36fd,",
+	"	0x16e41251,	0x216799ef,	0x07181f8d,	0xc191c3cf,",
+	"	0xba21cab5,	0x73944eb7,	0xdf9eb69d,	0x5fef6cfd,",
+	"	0xd750a6f5,	0x04f3fa43,	0x7cb2d063,	0xd3bdb369,",
+	"	0x35f35981,	0x9f294633,	0x5e293517,	0x70e51d05,",
+	"	0xf8db618d,	0x66ee05db,	0x835eaa77,	0x166a02c3,",
+	"	0xb516f283,	0x94102293,	0x1ace50a5,	0x64072651,",
+	"	0x66df7b75,	0x02e1b261,	0x8e6a73b9,	0x19dddfe7,",
+	"	0xd551cf39,	0x391c17cb,	0xf4304de5,	0xcd67b8d1,",
+	"	0x25873e8d,	0x115b4c71,	0x36e062f3,	0xaec0c7c9,",
+	"	0xd929f79d,	0x935a661b,	0xda762b47,	0x170bd76b,",
+	"	0x1a955cb5,	0x341fb0ef,	0x7f366cef,	0xc98f60c7,",
+	"	0xa4181af3,	0xa94a8837,	0x5fa3bc43,	0x11c638c1,",
+	"	0x4e66fabb,	0x30ab85cf,	0x250704ef,	0x8bf3bc07,",
+	"	0x6d2cd5ab,	0x613ef9c3,	0xb8e62149,	0x0404fd91,",
+	"	0xa04fd9b1,	0xa5e389eb,	0x9543bd23,	0xad6ca1f9,",
+	"	0x210c49ab,	0xf8e9532b,	0x854fba89,	0xdc7fc6bb,",
+	"	0x48a051a7,	0x6b2f383b,	0x61a4b433,	0xd3af231b,",
+	"	0xc5023fc7,	0xa5aa85df,	0xa0cd1157,	0x4206f64d,",
+	"	0x3fea31c3,	0x62d510a1,	0x13988957,	0x6a11a033,",
+	"	0x46f2a3b7,	0x2784ef85,	0x229eb9eb,	0x9c0c3053,",
+	"	0x5b7ead39,	0x82ae9afb,	0xf99e9fb3,	0x914b6459,",
+	"	0xaf05edd7,	0xc82710dd,	0x8fc1ea1f,	0x7e0d7a8d,",
+	"	0x7c7592e9,	0x65321017,	0xea57553f,	0x4aeb49ff,",
+	"	0x5239ae4d,	0x4b4b4585,	0x94091c21,	0x7eaaf4cb,",
+	"	0x6b489d6f,	0xecb9c0c3,	0x29a7af63,	0xaf117a0d,",
+	"	0x969ea6cd,	0x7658a34d,	0x5fc0bba9,	0x26e99b7f,",
+	"	0x7a6f260f,	0xe37c34f1,	0x1a1569bb,	0xc3bc7371,",
+	"	0x8567543d,	0xad0c46a9,	0xa1264fd9,	0x16f10b29,",
+	"	0x5e00dd3b,	0xf85b6bcd,	0xa2d32d8b,	0x4a3c8d43,",
+	"	0x6b33b959,	0x4fd1e6c9,	0x7938b8a9,	0x1ec795c7,",
+	"	0xe2ef3409,	0x83c16b9d,	0x0d3fd9eb,	0xeb461ad7,",
+	"	0xb09c831d,	0xaf052001,	0x7911164d,	0x1a9dc191,",
+	"	0xb52a0815,	0x0f732157,	0xc68c4831,	0x12cf3cbb };",
+#else
+	"unsigned int HASH_CONST[] = {",
 	"	/* asuming 4 bytes per int */",
-	"	0x88888EEF,	0x00400007,",
-	"	0x04c11db7,	0x100d4e63,",
-	"	0x0fc22f87,	0x3ff0c3ff,",
-	"	0x38e84cd7,	0x02b148e9,",
-	"	0x98b2e49d,	0xb616d379,",
-	"	0xa5247fd9,	0xbae92a15,",
-	"	0xb91c8bc5,	0x8e5880f3,",
-	"	0xacd7c069,	0xb4c44bb3,",
-	"	0x2ead1fb7,	0x8e428171,",
-	"	0xdbebd459,	0x828ae611,",
-	"	0x6cb25933,	0x86cdd651,",
-	"	0x9e8f5f21,	0xd5f8d8e7,",
-	"	0x9c4e956f,	0xb5cf2c71,",
-	"	0x2e805a6d,	0x33fc3a55,",
-	"	0xaf203ed1,	0xe31f5909,",
-	"	0x5276db35,	0x0c565ef7,",
-	"	0x273d1aa5,	0x8923b1dd,",
-	"	0",
-	"};",
-	"int	mreached=0, done=0, errors=0, Nrun=1;",
+	"	0x100d4e63,	0x0fc22f87,",
+	"	0x3ff0c3ff,	0x38e84cd7,",
+	"	0x02b148e9,	0x98b2e49d,",
+	"	0xb616d379,	0xa5247fd9,",
+	"	0xbae92a15,	0xb91c8bc5,",
+	"	0x8e5880f3,	0xacd7c069,",
+	"	0xb4c44bb3,	0x2ead1fb7,",
+	"	0x8e428171,	0xdbebd459,",
+	"	0x00400007,	0x04c11db7,",
+	"	0x828ae611,	0x6cb25933,",
+	"	0x86cdd651,	0x9e8f5f21,",
+	"	0xd5f8d8e7,	0x9c4e956f,",
+	"	0xb5cf2c71,	0x2e805a6d,",
+	"	0x33fc3a55,	0xaf203ed1,",
+	"	0xe31f5909,	0x5276db35,",
+	"	0x0c565ef7,	0x273d1aa5,",
+	"	0x8923b1dd,	0xa9acaac5,",
+	"	0xd1f69207,	0xedfd944b,",
+	"	0x9a68e46b,	0x5355e13f,",
+	"	0x7eeb44f9,	0x932beea9,",
+	"	0x330c4cd3,	0x87f34e5f,",
+	"	0x1b5851b7,	0xb9ca6447,",
+	"	0x58f96a8f,	0x1b3b5307,",
+	"	0x31c387b3,	0xf35f0f35,",
+	"	0xa0acc4df,	0xf3140303,",
+	"	0x2446245d,	0xe4b8f4ef,",
+	"	0x5c007383,	0x68e648af,",
+	"	0x1814fba7,	0xcdf731b5,",
+	"	0xd09ccb4b,	0xb92d0eff,",
+	"	0xcc3c6b67,	0xd3af6a57,",
+	"	0xf44fc3f5,	0x5bb67623,",
+	"	0xaeb9c953,	0x5e0ac739,",
+	"	0x3a7fda09,	0x5edf39eb,",
+	"	0x661eefd9,	0x6423f0d1,",
+	"	0x910fe413,	0x9ec92297,",
+	"	0x4bd8159d,	0xa7b16ee1,",
+	"	0x89d484e9,	0x7f305cb3,",
+	"	0xc5f303e7,	0x415deeef,",
+	"	0x09986f89,	0x7e9c4117,",
+	"	0x0b7cbedb,	0xf9ed7561,",
+	"	0x7a20ac99,	0xf05adef3,",
+	"	0x5893d75b,	0x44d73327,",
+	"	0xb583c873,	0x324d2145,",
+	"	0x7fa3829b,	0xe4b47a23,",
+	"	0xe256d94f,	0xb1fd8959,",
+	"	0xe561a321,	0x1435ac09,",
+	"	0xdd62408b,	0x02ec0bcb,",
+	"	0x5469b785,	0x2f4f50bb,",
+	"	0x20f19395,	0xf96ba085,",
+	"	0x2381f937,	0x768e2a11 };",
+#endif
+	"",
+	"#if NCORE>1",
+	"extern int core_id;",
+	"#endif",
+	"long	mreached=0;",
+	"int done=0, errors=0, Nrun=1;",
+	"int	c_init_done=0;",
+	"char	*c_stack_start = (char *) 0;",
 	"double	nstates=0, nlinks=0, truncs=0, truncs2=0;",
 	"double	nlost=0, nShadow=0, hcmp=0, ngrabs=0;",
+	"#ifdef BFS_PAR",
+	"extern ulong bfs_punt;",
+	"#endif",
+	"#ifdef PUTPID",
+	"char *progname;",
+	"#endif",
+	"#if defined(ZAPH) && defined(BITSTATE)",
+	"double zstates = 0;",
+	"#endif",
+	"/* int	c_init_run; */",
+	"#ifdef REVERSE",
+	"	#define P_REVERSE",
+	"#endif",
+	"#ifdef T_REVERSE",
+	"	int	t_reverse = 1;", /* can be modified with a parameter */
+	"#else",
+	"	int	t_reverse = 0;",
+	"#endif",
 	"#ifdef BFS",
 	"double midrv=0, failedrv=0, revrv=0;",
 	"#endif",
-	"unsigned long	nr_states=0; /* nodes in DFA */",
+	"ulong	nr_states=0; /* nodes in DFA */",
 	"long	Fa=0, Fh=0, Zh=0, Zn=0;",
 	"long	PUT=0, PROBE=0, ZAPS=0;",
 	"long	Ccheck=0, Cholds=0;",
 	"int	a_cycles=0, upto=1, strict=0, verbose = 0, signoff = 0;",
 	"#ifdef HAS_CODE",
-	"int	gui = 0, coltrace = 0, readtrail = 0, whichtrail = 0, onlyproc = -1, silent = 0;",
+	"int	gui = 0, coltrace = 0, readtrail = 0;",
+	"int	whichtrail = 0, whichclaim = -1, onlyproc = -1, silent = 0;",
+	"char	*claimname;",
 	"#endif",
-	"int	state_tables=0, fairness=0, no_rck=0, Nr_Trails=0;",
-	"char	simvals[128];",
+	"int	state_tables=0, fairness=0, no_rck=0, Nr_Trails=0, dodot=0;",
+	"char	simvals[256];",
 	"#ifndef INLINE",
 	"int	TstOnly=0;",
 	"#endif",
-	"unsigned long mask, nmask;",
+	"ulong mask, nmask;",
 	"#ifdef BITSTATE",
-	"int	ssize=23;	/* 1 Mb */",
+	"int	ssize=27;	/* 16 Mb */",
 	"#else",
-	"int	ssize=19;	/* 512K slots */",
+	"int	ssize=24;	/* 16M slots */",
 	"#endif",
 	"int	hmax=0, svmax=0, smax=0;",
 	"int	Maxbody=0, XX;",
-	"uchar	*noptr;	/* used by macro Pptr(x) */",
+	"uchar	*noptr, *noqptr;	/* used by Pptr(x) and Qptr(x) */",
 	"#ifdef VAR_RANGES",
 	"void logval(char *, int);",
 	"void dumpranges(void);",
@@ -260,36 +414,55 @@
 	"#ifdef MA",
 	"#define INLINE_REV",
 	"extern void dfa_init(unsigned short);",
-	"extern int  dfa_member(unsigned long);",
+	"extern int  dfa_member(ulong);",
 	"extern int  dfa_store(uchar *);",
 	"unsigned int	maxgs = 0;",
 	"#endif",
-
-	"State	comp_now;	/* compressed state vector */",
-	"State	comp_msk;",
-	"uchar	*Mask = (uchar *) &comp_msk;",
+	"",
+	"#ifdef ALIGNED",
+	"	State	comp_now __attribute__ ((aligned (8)));",
+	"	/* gcc 64-bit aligned for Itanium2 systems */",
+	"	/* MAJOR runtime penalty if not used on those systems */",
+	"#else",
+	"	State	comp_now;	/* compressed state vector */",
+	"#endif",
+	"",
+	"#ifndef HC",
+	"	#ifdef BFS_PAR",
+	"		State tmp_msk;",
+	"	#endif",
+	"	State	comp_msk;",
+	"	uchar	*Mask = (uchar *) &comp_msk;",
+	"#endif",
 	"#ifdef COLLAPSE",
-	"State	comp_tmp;",
-	"static char	*scratch = (char *) &comp_tmp;",
+	"	State	comp_tmp;",
+	"	static char	*scratch = (char *) &comp_tmp;",
 	"#endif",
-
-	"Stack	*stack; 	/* for queues, processes */",
+	"",
+	"_Stack	*stack; 	/* for queues, processes */",
 	"Svtack	*svtack;	/* for old state vectors */",
 	"#ifdef BITSTATE",
-	"static unsigned hfns = 3;	/* new default */",
+	"static unsigned int hfns = 3;	/* new default */",
 	"#endif",
-	"static unsigned long j1;",
-	"static unsigned long K1, K2;",
-	"static unsigned long j2, j3, j4;",
+	"static ulong j1_spin, j2_spin; /* 5.2.1: avoid nameclash with math.h */",
+	"static ulong j3_spin, j4_spin;",
+	"ulong K1, K2;",
 	"#ifdef BITSTATE",
-#ifndef POWOW
-	"static long udmem;",
-#endif
+	"long udmem;",
 	"#endif",
+	"#ifndef BFS_PAR",
 	"static long	A_depth = 0;",
-	"long	depth = 0;",	/* not static to support -S2 option, but possible clash with embedded code */
-	"static uchar	warned = 0, iterative = 0, like_java = 0, every_error = 0;",
-	"static uchar	noasserts = 0, noends = 0, bounded = 0;",
+	"#endif",
+	"long	depth = 0;",
+	"long depthfound = -1;	/* loop detection */",
+	/* depth: not static to support -S2, but possible clash with embedded code */
+	"#if NCORE>1",
+	"long nr_handoffs = 0;",
+	"#endif",
+	"uchar	warned = 0, iterative = 0, exclusive = 0, like_java = 0, every_error = 0;",
+	"uchar	noasserts = 0, noends = 0, bounded = 0;",
+	"uint	s_rand = 12345;	/* default seed */",
+
 	"#if SYNC>0 && ASYNC==0",
 	"void set_recvs(void);",
 	"int  no_recvs(int);",
@@ -302,17 +475,32 @@
 	"#define UnBlock     	/* don't bother */",
 	"#endif\n",
 	"#ifdef BITSTATE",
-	"int (*bstore)(char *, int);",
+	"int (*b_store)(char *, int);",
 	"int bstore_reg(char *, int);",
-#ifndef POWOW
 	"int bstore_mod(char *, int);",
-#endif
 	"#endif",
+	"",
+	"void dfs_uerror(char *);",
+	"void dfs_Uerror(char *);",
+	"#ifdef BFS_PAR",
+	"void bfs_uerror(char *);",
+	"void bfs_Uerror(char *);",
+	"#endif",
+	"void (*uerror)(char *);",
+	"void (*Uerror)(char *);",
+	"void (*hasher)(uchar *, int);",
+	"void (*o_hash)(uchar *, int, int);",
+	"void d_hash(uchar *, int);",
+	"void m_hash(uchar *, int);",
+	"void d_sfh(uchar *, int);",
+	"void o_hash32(uchar *, int, int);",
+	"void o_hash64(uchar *, int, int);",
+	"",
 	"void active_procs(void);",
 	"void cleanup(void);",
 	"void do_the_search(void);",
 	"void find_shorter(int);",
-	"void iniglobals(void);",
+	"void iniglobals(int);",
 	"void stopped(int);",
 	"void wrapup(void);",
 	"int *grab_ints(int);",
@@ -320,7 +508,7 @@
 	0,
 };
 
-static char *Tail[] = {
+static const char *Tail[] = {
 	"Trans *",
 	"settr(	int t_id, int a, int b, int c, int d,",
 	"	char *t, int g, int tpe0, int tpe1)",
@@ -425,10 +613,14 @@
 	"}",
 	"#endif",
 	"void",
-	"retrans(int n, int m, int is, short srcln[], uchar reach[])",
+	"retrans(int n, int m, int is, short srcln[], uchar reach[], uchar lpstate[])",
 	"	/* process n, with m states, is=initial state */",
 	"{	Trans *T0, *T1, *T2, *T3;",
-	"	int i, k;",
+	"	Trans *T4, *T5; /* t_reverse or has_unless */",
+	"	int i;",
+	"#if defined(HAS_UNLESS) || !defined(NOREDUCE)",
+	"	int k;",
+	"#endif",
 	"#ifndef NOREDUCE",
 	"	int g, h, j, aa;",
 	"#endif",
@@ -436,7 +628,7 @@
 	"	int p;",
 	"#endif",
 	"	if (state_tables >= 4)",
-	"	{	printf(\"STEP 1 proctype %%s\\n\", ",
+	"	{	printf(\"STEP 1 %%s\\n\", ",
 	"			procname[n]);",
 	"		for (i = 1; i < m; i++)",
 	"		for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
@@ -477,7 +669,7 @@
 	"	} while (cnt);",
 
 	"	if (state_tables >= 3)",
-	"	{	printf(\"STEP 2 proctype %%s\\n\", ",
+	"	{	printf(\"STEP 2 %%s\\n\", ",
 	"			procname[n]);",
 	"		for (i = 1; i < m; i++)",
 	"		for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
@@ -490,7 +682,9 @@
 	"#if 0",
 	"			printf(\"\\t\\tpull %%d (%%d) to %%d\\n\",",
 	"			T1->st, T1->forw, i);",
-	"#endif",
+	"#endif",		/* pull linenumber ref as well: */
+	"			srcln[i] = srcln[T1->st];	/* Oyvind Teig, 5.2.0 */",
+	"",
 	"			if (!trans[n][T1->st]) continue;",
 	"			T0 = cpytr(trans[n][T1->st]);",
 	"			trans[n][i] = T0;",
@@ -502,6 +696,7 @@
 	"			printf(\"\\t\\tpull %%d (%%d) to %%d\\n\",",
 	"				T1->st, T1->forw, i);",
 	"#endif",
+	"		/*		srcln[i] = srcln[T1->st];  gh: not useful */",
 	"				if (!trans[n][T1->st]) continue;",
 	"				T0->nxt = cpytr(trans[n][T1->st]);",
 	"				T0 = T0->nxt;",
@@ -509,7 +704,7 @@
 	"				imed(T0, T1->st, n, i);",
 	"	}	}	}",
 	"	if (state_tables >= 2)",
-	"	{	printf(\"STEP 3 proctype %%s\\n\", ",
+	"	{	printf(\"STEP 3 %%s\\n\", ",
 	"			procname[n]);",
 	"		for (i = 1; i < m; i++)",
 	"		for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
@@ -525,8 +720,8 @@
 	"		 * and prepend them to the transition-",
 	"		 * list of state i",
 	"		 */",
-	" if (!like_java) /* the default */",
-	" {		for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
+	"	 if (!like_java) /* the default */",
+	"	 {	for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
 	"		for (k = HAS_UNLESS-1; k >= 0; k--)",
 	"		{	if (p = T0->escp[k])",
 	"			for (T1 = trans[n][p]; T1; T1 = T1->nxt)",
@@ -537,9 +732,8 @@
 	"				T2->nxt = trans[n][i];",
 	"				trans[n][i] = T2;",
 	"		}	}",
-	" } else /* outermost unless checked first */",
-	" {		Trans *T4;",
-	"		T4 = T3 = (Trans *) 0;",
+	"	 } else /* outermost unless checked first */",
+	"	 {	T4 = T3 = (Trans *) 0;",
 	"		for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
 	"		for (k = HAS_UNLESS-1; k >= 0; k--)",
 	"		{	if (p = T0->escp[k])",
@@ -557,22 +751,21 @@
 	"		{	T3->nxt = trans[n][i];",
 	"			trans[n][i] = T4;",
 	"		}",
-	" }",
+	"	 }",
 	"	}",
 	"#endif",
 
 	"#ifndef NOREDUCE",
 	"	for (i = 1; i < m; i++)",
-	"	{",
-	"		if (a_cycles)",
+	"	{	if (a_cycles)",
 	"		{ /* moves through these states are visible */",
-	"#if PROG_LAB>0 && defined(HAS_NP)",
+	"	#if PROG_LAB>0 && defined(HAS_NP)",
 	"			if (progstate[n][i])",
 	"				goto degrade;",
 	"			for (T1 = trans[n][i]; T1; T1 = T1->nxt)",
 	"				if (progstate[n][T1->st])",
 	"					goto degrade;",
-	"#endif",
+	"	#endif",
 	"			if (accpstate[n][i] || visstate[n][i])",
 	"				goto degrade;",
 	"			for (T1 = trans[n][i]; T1; T1 = T1->nxt)",
@@ -668,19 +861,44 @@
 	"			continue;",
 	"		stopstate[n][T2->st] = 1;",
 	"	}",
-	"	if (state_tables)",
-	"	{	printf(\"proctype \");",
-	"		if (!strcmp(procname[n], \":init:\"))",
-	"			printf(\"init\\n\");",
-	"		else",
-	"			printf(\"%%s\\n\", procname[n]);",
+	"	if (state_tables && !verbose)",
+	"	{	if (dodot)",
+	"		{	char buf[256], *q = buf, *p = procname[n];",
+	"			while (*p != '\\0')",
+	"			{	if (*p != ':')",
+	"				{	*q++ = *p;",
+	"				}",
+	"				p++;",
+	"			}",
+	"			*q = '\\0';",
+	"			printf(\"digraph \");",
+	"			switch (Btypes[n]) {",
+	"			case I_PROC:  printf(\"init {\\n\"); break;",
+	"			case N_CLAIM: printf(\"claim_%%s {\\n\", buf); break;",
+	"			case E_TRACE: printf(\"notrace {\\n\"); break;",
+	"			case N_TRACE: printf(\"trace {\\n\"); break;",
+	"			default:      printf(\"p_%%s {\\n\", buf); break;",
+	"			}",
+	"			printf(\"size=\\\"8,10\\\";\\n\");",
+	"			printf(\"  GT [shape=box,style=dotted,label=\\\"%%s\\\"];\\n\", buf);",
+	"			printf(\"  GT -> S%%d;\\n\", is);",
+	"		} else",
+	"		{	switch (Btypes[n]) {",
+	"			case I_PROC:  printf(\"init\\n\"); break;",
+	"			case N_CLAIM: printf(\"claim %%s\\n\", procname[n]); break;",
+	"			case E_TRACE: printf(\"notrace assertion\\n\"); break;",
+	"			case N_TRACE: printf(\"trace assertion\\n\"); break;",
+	"			default:      printf(\"proctype %%s\\n\", procname[n]); break;",
+	"		}	}",
 	"		for (i = 1; i < m; i++)",
-	"			reach[i] = 1;",
+	"		{	reach[i] = 1;",
+	"		}",
 	"		tagtable(n, m, is, srcln, reach);",
+	"		if (dodot) printf(\"}\\n\");",
 	"	} else",
 	"	for (i = 1; i < m; i++)",
 	"	{	int nrelse;",
-	"		if (strcmp(procname[n], \":never:\") != 0)",
+	"		if (Btypes[n] != N_CLAIM)",
 	"		{	for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
 	"			{	if (T0->st == i",
 	"				&& strcmp(T0->tp, \"(1)\") == 0)",
@@ -703,16 +921,84 @@
 	"		  	printf(\" 'else' stmnts\\n\");",
 	"			pan_exit(1);",
 	"	}	}",
-	"	if (!state_tables && strcmp(procname[n], \":never:\") == 0)",
-	"	{	int h = 0;",
+	"#if !defined(LOOPSTATE) && !defined(BFS_PAR)",
+	"	if (state_tables)",
+	"#endif",
+	"	do_dfs(n, m, is, srcln, reach, lpstate);",
+	"",
+	"	if (!t_reverse)",
+	"	{	return;",
+	"	}",
+	"	/* process n, with m states, is=initial state -- reverse list */",
+	"	if (!state_tables && Btypes[n] != N_CLAIM)",
+	"	{	for (i = 1; i < m; i++)", /* for each state */
+	"		{	Trans *Tx = (Trans *) 0; /* list of escapes */",
+	"			Trans *Ty = (Trans *) 0; /* its tail element */",
+	"			T1 = (Trans *) 0; /* reversed list */",
+	"			T2 = (Trans *) 0; /* its tail */",
+	"			T3 = (Trans *) 0; /* remembers possible 'else' */",
+	"",
+	"			/* find unless-escapes, they should go first */",
+	"			T4 = T5 = T0 = trans[n][i];",
+	"	#ifdef HAS_UNLESS",
+	"			while (T4 && T4->e_trans) /* escapes are first in orig list */",
+	"			{	T5 = T4;	  /* remember predecessor */",
+	"				T4 = T4->nxt;",
+	"			}",
+	"	#endif",
+	"			/* T4 points to first non-escape, T5 to its parent, T0 to original list */",
+	"			if (T4 != T0)		 /* there was at least one escape */",	
+	"			{	T3 = T5->nxt;		 /* start of non-escapes */",
+	"				T5->nxt = (Trans *) 0;	 /* separate */",
+	"				Tx = T0;		 /* start of the escapes */",
+	"				Ty = T5;		 /* its tail */",
+	"				T0 = T3;		 /* the rest, to be reversed */",
+	"			}",
+	"			/* T0 points to first non-escape, Tx to the list of escapes, Ty to its tail */",
+	"",
+	"			/* first tail-add non-escape transitions, reversed */",
+	"			T3 = (Trans *) 0;", /* remember a possible 'else' */
+	"			for (T5 = T0; T5; T5 = T4)",
+	"			{	T4 = T5->nxt;",
+	"	#ifdef HAS_UNLESS",
+	"				if (T5->e_trans)",
+	"				{	printf(\"error: cannot happen!\\n\");",
+	"					continue;",
+	"				}",
+	"	#endif",
+	"				if (strcmp(T5->tp, \"else\") == 0)",
+	"				{	T3 = T5;",
+	"					T5->nxt = (Trans *) 0;",
+	"				} else",
+	"				{	T5->nxt = T1;",
+	"					if (!T1) { T2 = T5; }",
+	"					T1 = T5;",
+	"			}	}",
+	"			/* T3 points to a possible else, which is removed from the list */",
+	"			/* T1 points to the reversed list so far (without escapes) */",
+	"			/* T2 points to the tail element -- where the else should go */",
+	"			if (T2 && T3)",
+	"			{	T2->nxt = T3;	/* add else */",
+	"			} else",
+	"			{	if (T3) /* there was an else, but there's no tail */",
+	"				{	if (!T1)	/* and no reversed list */",
+	"					{	T1 = T3; /* odd, but possible */",
+	"					} else		/* even stranger */",
+	"					{	T1->nxt = T3;",
+	"			}	}	}",
+	"",
+	"			/* add in the escapes, to that they appear at the front */",
+	"			if (Tx && Ty) { Ty->nxt = T1; T1 = Tx; }",
+	"",
+	"			trans[n][i] = T1;",
+	"			/* reversed, with escapes first and else last */",
+	"	}	}",
+	"	if (state_tables && verbose)",
+	"	{	printf(\"FINAL proctype %%s\\n\", ",
+	"			procname[n]);",
 	"		for (i = 1; i < m; i++)",
 	"		for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
-	"			if (T0->forw > h) h = T0->forw;",
-	"		h++;",
-	"		frm_st0 = (short *) emalloc(h * sizeof(short));",
-	"		for (i = 1; i < m; i++)",
-	"		for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
-	"			frm_st0[T0->forw] = i;",
+	"			crack(n, i, T0, srcln);",
 	"	}",
 	"}",
 	"void",
@@ -731,7 +1017,12 @@
 	"	reach[is] = 0;",
 	"	if (state_tables)",
 	"	for (z = trans[n][is]; z; z = z->nxt)",
-	"		crack(n, is, z, srcln);",
+	"	{	if (dodot)",
+	"			dot_crack(n, is, z);",
+	"		else",
+	"			crack(n, is, z, srcln);",
+	"	}",
+	"",
 	"	for (z = trans[n][is]; z; z = z->nxt)",
 	"	{",
 	"#ifdef HAS_UNLESS",
@@ -747,7 +1038,48 @@
 	"#endif",
 	"	}",
 	"}",
+	"",
+	"extern Trans *t_id_lkup[];",	/* needed by BFS_PAR */
+	"",
 	"void",
+	"dfs_table(int n, int m, int is, short srcln[], uchar reach[], uchar lpstate[])",
+	"{	Trans *z;\n",
+	"	if (is >= m || is <= 0 || !trans[n][is])",
+	"		return;",
+	"	if ((reach[is] & (4|8|16)) != 0)",
+	"	{	if ((reach[is] & (8|16)) == 16)	/* on stack, not yet recorded */",
+	"		{	lpstate[is] = 1;",
+	"			reach[is] |= 8; /* recorded */",
+	"			if (state_tables && verbose)",
+	"			{	printf(\"state %%d line %%d is a loopstate\\n\", is, srcln[is]);",
+	"		}	}",
+	"		return;",
+	"	}",
+	"	reach[is] |= (4|16);	/* visited | onstack */",
+	"	for (z = trans[n][is]; z; z = z->nxt)",
+	"	{	t_id_lkup[z->t_id] = z;",	/* needed by BFS_PAR */
+	"#ifdef HAS_UNLESS",
+	"		int i, j;",
+	"#endif",
+	"		dfs_table(n, m, z->st, srcln, reach, lpstate);",
+	"#ifdef HAS_UNLESS",
+	"		for (i = 0; i < HAS_UNLESS; i++)",
+	"		{	j = trans[n][is]->escp[i];",
+	"			if (!j) break;",
+	"			dfs_table(n, m, j, srcln, reach, lpstate);",
+	"		}",
+	"#endif",
+	"	}",
+	"	reach[is] &= ~16; /* no longer on stack */",
+	"}",
+	"void",
+	"do_dfs(int n, int m, int is, short srcln[], uchar reach[], uchar lpstate[])",
+	"{	int i;",
+	"	dfs_table(n, m, is, srcln, reach, lpstate);",
+	"	for (i = 0; i < m; i++)",
+	"		reach[i] &= ~(4|8|16);",
+	"}",
+	"void",
 	"crack(int n, int j, Trans *z, short srcln[])",
 	"{	int i;\n",
 	"	if (!z) return;",
@@ -765,19 +1097,19 @@
 	"	}",
 	"#endif",
 	"	printf(\"]\");",
-	"	printf(\" [%%s%%s%%s%%s%%s] line %%d => \",",
+	"	printf(\" [%%s%%s%%s%%s%%s] %%s:%%d => \",",
 	"		z->atom&6?\"A\":z->atom&32?\"D\":\"-\",",
 	"		accpstate[n][j]?\"a\" :\"-\",",
 	"		stopstate[n][j]?\"e\" : \"-\",",
 	"		progstate[n][j]?\"p\" : \"-\",",
 	"		z->atom & 8 ?\"L\":\"G\",",
-	"		srcln[j]);",
+	"		PanSource, srcln[j]);",
 	"	for (i = 0; z->tp[i]; i++)",
 	"		if (z->tp[i] == \'\\n\')",
 	"			printf(\"\\\\n\");",
 	"		else",
 	"			putchar(z->tp[i]);",
-	"	if (z->qu[0])",
+	"	if (verbose && z->qu[0])",
 	"	{	printf(\"\\t[\");",
 	"		for (i = 0; i < 6; i++)",
 	"			if (z->qu[i])",
@@ -787,6 +1119,32 @@
 	"	}",
 	"	printf(\"\\n\");",
 	"	fflush(stdout);",
+	"}",
+	"/* spin -a m.pml; cc -o pan pan.c; ./pan -D | dot -Tps > foo.ps; ps2pdf foo.ps */",
+	"void",
+	"dot_crack(int n, int j, Trans *z)",
+	"{	int i;\n",
+	"	if (!z) return;",
+	"	printf(\"\tS%%d -> S%%d  [color=black\", j, z->st);",
+	"",
+	"	if (z->atom&6) printf(\",style=dashed\");",		/* A */
+	"	else if (z->atom&32) printf(\",style=dotted\");",	/* D */
+	"	else if (z->atom&8) printf(\",style=solid\");",		/* L */
+	"	else printf(\",style=bold\");",				/* G */
+		/* other styles: filled dotted */
+	"",
+	"	printf(\",label=\\\"\");",
+	"	for (i = 0; z->tp[i]; i++)",
+	"	{	if (z->tp[i] == \'\\\\\'",
+	"		&&  z->tp[i+1] == \'n\')",
+	"		{	i++; printf(\" \");",
+	"		} else",
+	"		{	putchar(z->tp[i]);",
+	"	}	}",
+	"	printf(\"\\\"];\\n\");",
+	"	if (accpstate[n][j]) printf(\"  S%%d [color=red,style=bold];\\n\", j);",
+	"	else if (progstate[n][j]) printf(\"  S%%d [color=green,style=bold];\\n\", j);",
+	"	if (stopstate[n][j]) printf(\"  S%%d [color=blue,style=bold,shape=box];\\n\", j);",
 	"}",
 	"",
 	"#ifdef VAR_RANGES",
--- a/sys/src/cmd/spin/pangen3.c
+++ b/sys/src/cmd/spin/pangen3.c
@@ -1,22 +1,20 @@
 /***** spin: pangen3.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include "y.tab.h"
+#include <assert.h>
 
-extern FILE	*th;
-extern int	claimnr, eventmapnr;
+extern FILE	*th, *tc;
+extern int	eventmapnr, old_priority_rules;
 
 typedef struct SRC {
-	short ln, st;	/* linenr, statenr */
+	int ln, st;	/* linenr, statenr */
 	Symbol *fn;	/* filename */
 	struct SRC *nxt;
 } SRC;
@@ -28,6 +26,8 @@
 static SRC	*frst = (SRC *) 0;
 static SRC	*skip = (SRC *) 0;
 
+extern int	ltl_mode;
+
 extern void	sr_mesg(FILE *, int, int);
 
 static void
@@ -34,10 +34,10 @@
 putnr(int n)
 {
 	if (col++ == 8)
-	{	fprintf(th, "\n\t");
+	{	fprintf(tc, "\n\t");	/* was th */
 		col = 1;
 	}
-	fprintf(th, "%3d, ", n);
+	fprintf(tc, "%3d, ", n);	/* was th */
 }
 
 static void
@@ -47,7 +47,7 @@
 		return;
 
 	if (lastfnm)
-		fprintf(th, "{ %s, %d, %d },\n\t",
+		fprintf(tc, "{ \"%s\", %d, %d },\n\t",	/* was th */
 			lastfnm->name,
 			lastfrom,
 			j-1);
@@ -59,41 +59,67 @@
 putfnm_flush(int j)
 {
 	if (lastfnm)
-		fprintf(th, "{ %s, %d, %d }\n",
+		fprintf(tc, "{ \"%s\", %d, %d }\n",	/* was th */
 			lastfnm->name,
 			lastfrom, j);
 }
 
-void
-putskip(int m)	/* states that need not be reached */
+static SRC *
+newsrc(int m, SRC *n)
 {	SRC *tmp;
-
-	for (tmp = skip; tmp; tmp = tmp->nxt)
-		if (tmp->st == m)
-			return;
 	tmp = (SRC *) emalloc(sizeof(SRC));
-	tmp->st = (short) m;
-	tmp->nxt = skip;
-	skip = tmp;
+	tmp->st  = m;
+	tmp->nxt = n;
+	return tmp;
 }
 
 void
+putskip(int m)	/* states that need not be reached */
+{	SRC *tmp, *lst = (SRC *)0;
+	/* 6.4.0: now an ordered list */
+	for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
+	{	if (tmp->st == m)
+		{	return;
+		}
+		if (tmp->st > m)	/* insert before */
+		{	if (tmp == skip)
+			{	tmp = newsrc(m, skip);
+				skip = tmp;
+			} else
+			{	assert(lst);
+				tmp = newsrc(m, lst->nxt);
+				lst->nxt = tmp;
+			}
+			return;	
+	}	}
+	/* insert at the end */
+	if (lst)
+	{	lst->nxt = newsrc(m, 0);
+	} else	/* empty list */
+	{	skip = newsrc(m, 0);
+	}
+}
+
+void
 unskip(int m)	/* a state that needs to be reached after all */
-{	SRC *tmp, *lst=(SRC *)0;
+{	SRC *tmp, *lst = (SRC *)0;
 
 	for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
-		if (tmp->st == m)
+	{	if (tmp->st == m)
 		{	if (tmp == skip)
 				skip = skip->nxt;
-			else
+			else if (lst)	/* always true, but helps coverity */
 				lst->nxt = tmp->nxt;
 			break;
 		}
+		if (tmp->st > m)
+		{	break;	/* m is not in list */
+	}	}
 }
 
 void
 putsrc(Element *e)	/* match states to source lines */
-{	SRC *tmp;
+{	SRC *tmp, *lst = (SRC *)0;
 	int n, m;
 
 	if (!e || !e->n) return;
@@ -100,32 +126,51 @@
 
 	n = e->n->ln;
 	m = e->seqno;
-
-	for (tmp = frst; tmp; tmp = tmp->nxt)
-		if (tmp->st == m)
+	/* 6.4.0: now an ordered list */
+	for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
+	{	if (tmp->st == m)
 		{	if (tmp->ln != n || tmp->fn != e->n->fn)
-			printf("putsrc mismatch %d - %d, file %s\n", n,
+			printf("putsrc mismatch seqno %d, line %d - %d, file %s\n", m, n,
 				tmp->ln, tmp->fn->name);
 			return;
 		}
-	tmp = (SRC *) emalloc(sizeof(SRC));
-	tmp->ln = (short) n;
-	tmp->st = (short) m;
+		if (tmp->st > m) /* insert before */
+		{	if (tmp == frst)
+			{	tmp = newsrc(m, frst);
+				frst = tmp;
+			} else
+			{	assert(lst);
+				tmp = newsrc(m, lst->nxt);
+				lst->nxt = tmp;
+			}
+			tmp->ln = n;
+			tmp->fn = e->n->fn;
+			return;
+	}	}
+	/* insert at the end */
+	tmp = newsrc(m, lst?lst->nxt:0);
+	tmp->ln = n;
 	tmp->fn = e->n->fn;
-	tmp->nxt = frst;
-	frst = tmp;
+	if (lst)
+	{	lst->nxt = tmp;
+	} else
+	{	frst = tmp;
+	}
 }
 
 static void
 dumpskip(int n, int m)
 {	SRC *tmp, *lst;
+	FILE *tz = tc;	/* was th */
 	int j;
 
-	fprintf(th, "uchar reached%d [] = {\n\t", m);
+	fprintf(tz, "uchar reached%d [] = {\n\t", m);
+	tmp = skip;
+	lst = (SRC *) 0;
 	for (j = 0, col = 0; j <= n; j++)
-	{	lst = (SRC *) 0;
-		for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
-			if (tmp->st == j)
+	{	/* find j in the sorted list */
+		for ( ; tmp; lst = tmp, tmp = tmp->nxt)
+		{	if (tmp->st == j)
 			{	putnr(1);
 				if (lst)
 					lst->nxt = tmp->nxt;
@@ -133,12 +178,17 @@
 					skip = tmp->nxt;
 				break;
 			}
+			if (tmp->st > j)
+			{	putnr(0);
+				break;	/* j is not in the list */
+		}	}
+
 		if (!tmp)
-			putnr(0);
-	}
-	fprintf(th, "};\n");
-	if (m == claimnr)
-		fprintf(th, "#define reached_claim	reached%d\n", m);
+		{	putnr(0);
+	}	}
+	fprintf(tz, "};\n");
+	fprintf(tz, "uchar *loopstate%d;\n", m);
+
 	if (m == eventmapnr)
 		fprintf(th, "#define reached_event	reached%d\n", m);
 
@@ -149,27 +199,34 @@
 dumpsrc(int n, int m)
 {	SRC *tmp, *lst;
 	int j;
+	static int did_claim = 0;
+	FILE *tz = tc;	/* was th */
 
-	fprintf(th, "short src_ln%d [] = {\n\t", m);
+	fprintf(tz, "\nshort src_ln%d [] = {\n\t", m);
+	tmp = frst;
 	for (j = 0, col = 0; j <= n; j++)
-	{	lst = (SRC *) 0;
-		for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
-			if (tmp->st == j)
+	{	for ( ; tmp; tmp = tmp->nxt)
+		{	if (tmp->st == j)
 			{	putnr(tmp->ln);
 				break;
 			}
+			if (tmp->st > j)
+			{	putnr(0);
+				break;
+		}	}
 		if (!tmp)
-			putnr(0);
-	}
-	fprintf(th, "};\n");
+		{	putnr(0);
+	}	}
+	fprintf(tz, "};\n");
 
 	lastfnm = (Symbol *) 0;
-	lastdef.name = "\"-\"";
-	fprintf(th, "S_F_MAP src_file%d [] = {\n\t", m);
+	lastdef.name = "-";
+	fprintf(tz, "S_F_MAP src_file%d [] = {\n\t", m);
+	tmp = frst;
+	lst = (SRC *) 0;
 	for (j = 0, col = 0; j <= n; j++)
-	{	lst = (SRC *) 0;
-		for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
-			if (tmp->st == j)
+	{	for ( ; tmp; lst = tmp, tmp = tmp->nxt)
+		{	if (tmp->st == j)
 			{	putfnm(j, tmp->fn);
 				if (lst)
 					lst->nxt = tmp->nxt;
@@ -177,14 +234,20 @@
 					frst = tmp->nxt;
 				break;
 			}
+			if (tmp->st > j)
+			{	putfnm(j, &lastdef);
+				break;
+		}	}
 		if (!tmp)
-			putfnm(j, &lastdef);
-	}
+		{	putfnm(j, &lastdef);
+	}	}
 	putfnm_flush(j);
-	fprintf(th, "};\n");
+	fprintf(tz, "};\n");
 
-	if (m == claimnr)
-		fprintf(th, "#define src_claim	src_ln%d\n", m);
+	if (pid_is_claim(m) && !did_claim)
+	{	fprintf(tz, "short *src_claim;\n");
+		did_claim++;
+	}
 	if (m == eventmapnr)
 		fprintf(th, "#define src_event	src_ln%d\n", m);
 
@@ -237,7 +300,27 @@
 	case GT:	Cat1(">"); break;
 	case LT:	Cat1("<"); break;
 	case NE:	Cat1("!="); break;
-	case EQ:	Cat1("=="); break;
+	case EQ:
+			if (ltl_mode
+			&&  now->lft->ntyp == 'p'
+			&&  now->rgt->ntyp == 'q')	/* remote ref */
+			{	Lextok *p = now->lft->lft;
+
+				fprintf(fd, "(");
+				fprintf(fd, "%s", p->sym->name);
+				if (p->lft)
+				{	fprintf(fd, "[");
+					putstmnt(fd, p->lft, 0); /* pid */
+					fprintf(fd, "]");
+				}
+				fprintf(fd, "@");
+				fprintf(fd, "%s", now->rgt->sym->name);
+				fprintf(fd, ")");
+				break;
+			}
+			Cat1("==");
+			break;
+
 	case OR:	Cat1("||"); break;
 	case AND:	Cat1("&&"); break;
 	case LSHIFT:	Cat1("<<"); break;
@@ -298,6 +381,22 @@
 	case ENABLED:	Cat3("enabled(", now->lft, ")");
 			break;
 
+	case GET_P:	if (old_priority_rules)
+			{	fprintf(fd, "1");
+			} else
+			{	Cat3("get_priority(", now->lft, ")");
+			}
+			break;
+
+	case SET_P:	if (!old_priority_rules)
+			{	fprintf(fd, "set_priority(");
+				comwork(fd, now->lft->lft, m);
+				fprintf(fd, ", ");
+				comwork(fd, now->lft->rgt, m);
+				fprintf(fd, ")");
+			}
+			break;
+
 	case EVAL:	Cat3("eval(", now->lft, ")");
 			break;
 
@@ -320,12 +419,14 @@
 			}
 			break;	
 
-	case ASGN:	comwork(fd,now->lft,m);
+	case ASGN:
+			if (check_track(now) == STRUCT) { break; }
+			comwork(fd,now->lft,m);
 			fprintf(fd," = ");
 			comwork(fd,now->rgt,m);
 			break;
 
-	case PRINT:	{	char c, buf[512];
+	case PRINT:	{	char c, buf[1024];
 				strncpy(buf, now->sym->name, 510);
 				for (i = j = 0; i < 510; i++, j++)
 				{	c = now->sym->name[i];
@@ -349,9 +450,23 @@
 			comwork(fd, now->lft, m);
 			fprintf(fd, ")");
 			break;
-	case NAME:	putname(fd, "", now, m, "");
+	case NAME:
+			putname(fd, "", now, m, "");
 			break;
-	case   'p':	putremote(fd, now, m);
+
+	case   'p':
+			if (ltl_mode)
+			{	fprintf(fd, "%s", now->lft->sym->name); /* proctype */
+				if (now->lft->lft)
+				{	fprintf(fd, "[");
+					putstmnt(fd, now->lft->lft, 0); /* pid */
+					fprintf(fd, "]");
+				}
+				fprintf(fd, ":");	/* remote varref */
+				fprintf(fd, "%s", now->sym->name);	/* varname */
+				break;
+			}
+			putremote(fd, now, m);
 			break;
 	case   'q':	fprintf(fd, "%s", now->sym->name);
 			break;
@@ -366,7 +481,7 @@
 	case  ELSE:	fprintf(fd, "else"); break;
 	case   '@':	fprintf(fd, "-end-"); break;
 
-	case D_STEP:	fprintf(fd, "D_STEP"); break;
+	case D_STEP:	fprintf(fd, "D_STEP%d", now->ln); break;
 	case ATOMIC:	fprintf(fd, "ATOMIC"); break;
 	case NON_ATOMIC: fprintf(fd, "sub-sequence"); break;
 	case IF:	fprintf(fd, "IF"); break;
--- a/sys/src/cmd/spin/pangen3.h
+++ b/sys/src/cmd/spin/pangen3.h
@@ -1,22 +1,19 @@
 /***** spin: pangen3.h *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
-static char *Head0[] = {
+static const char *Head0[] = {
 	"#if defined(BFS) && defined(REACH)",
-	"#undef REACH",	/* redundant with bfs */
+	"	#undef REACH",	/* redundant with bfs */
 	"#endif",
 	"#ifdef VERI",
-		"#define BASE	1",
+	"	#define BASE	1",
 	"#else",
-		"#define BASE	0",
+	"	#define BASE	0",
 	"#endif",
 	"typedef struct Trans {",
 	"	short atom;	/* if &2 = atomic trans; if &8 local */",
@@ -37,108 +34,131 @@
 	"	int back;	/* index return  transition */",
 	"	struct Trans *nxt;",
 	"} Trans;\n",
-	"#define qptr(x)	(((uchar *)&now)+(int)q_offset[x])",
-	"#define pptr(x)	(((uchar *)&now)+(int)proc_offset[x])",
-/*	"#define Pptr(x)	((proc_offset[x])?pptr(x):noptr)",	*/
+
+	"#ifdef TRIX",
+	"	#define qptr(x)	(channels[x]->body)",
+	"	#define pptr(x)	(processes[x]->body)",
+	"#else",
+	"	#define qptr(x)	(((uchar *)&now)+(int)q_offset[x])",
+	"	#define pptr(x)	(((uchar *)&now)+(int)proc_offset[x])",
+/*	"	#define Pptr(x)	((proc_offset[x])?pptr(x):noptr)",	*/
+	"#endif",
 	"extern uchar *Pptr(int);",
+	"extern uchar *Qptr(int);",
 
-	"#define q_sz(x)	(((Q0 *)qptr(x))->Qlen)\n",
-	"#ifndef VECTORSZ",
-	"#define VECTORSZ	1024           /* sv   size in bytes */",
+	"#define q_sz(x)	(((Q0 *)qptr(x))->Qlen)",
+	"",
+	"#ifdef TRIX",
+	"	#ifdef VECTORSZ",
+	"		#undef VECTORSZ",	/* backward compatibility */
+	"	#endif",
+	"	#if WS==4",
+	"		#define VECTORSZ	2056	/* ((MAXPROC+MAXQ+4)*sizeof(uchar *)) */",
+	"	#else",
+	"		#define VECTORSZ	4112	/* the formula causes probs in preprocessing */",
+	"	#endif",
+	"#else",
+	"	#ifndef VECTORSZ",
+	"		#define VECTORSZ	1024	/* sv size in bytes */",
+	"	#endif",
 	"#endif\n",
+	"#define MAXQ   	255",
+	"#define MAXPROC	255",
+	"",
 	0,
 };
 
-static char *Header[] = {
+static const char *Header[] = {
 	"#ifdef VERBOSE",
-		"#ifndef CHECK",
-		"#define CHECK",
-		"#endif",
-		"#ifndef DEBUG",
-		"#define DEBUG",
-		"#endif",
+	"	#ifndef CHECK",
+	"		#define CHECK",
+	"	#endif",
+	"	#ifndef DEBUG",
+	"		#define DEBUG",
+	"	#endif",
 	"#endif",
 	"#ifdef SAFETY",
-		"#ifndef NOFAIR",
-			"#define NOFAIR",
-		"#endif",
+	"	#ifndef NOFAIR",
+	"		#define NOFAIR",
+	"	#endif",
 	"#endif",
+#if 0
+                 NOREDUCE BITSTATE SAFETY  MA   WS>4
+     CNTRSTACK:     -        +       +     d     -
+     FULLSTACK:     +        d       -     -     d
+                    -        +       d     d     d
+                    -        +       +     d     +
+                    -        -       d     d     d
+     Neither:       +        d       +     d     d
+                    +        d       d     +     d
+#endif
 	"#ifdef NOREDUCE",
-		"#ifndef XUSAFE",
-		"#define XUSAFE",
-		"#endif",
-		"#if !defined(SAFETY) && !defined(MA)",
-			"#define FULLSTACK",
-		"#endif",
+	"	#ifndef XUSAFE",
+	"		#define XUSAFE",
+	"	#endif",
+	"	#if !defined(SAFETY) && !defined(MA)",
+	"		#define FULLSTACK",		/* => NOREDUCE && !SAFETY && !MA */
+	"	#endif",
 	"#else",
-		"#ifdef BITSTATE",
-			"#ifdef SAFETY && !defined(HASH64)",
-				"#define CNTRSTACK",
-			"#else",
-				"#define FULLSTACK",
-			"#endif",
-		"#else",
-			"#define FULLSTACK",
-		"#endif",
+	"	#ifdef BITSTATE",
+	"		#if defined(SAFETY) && WS<=4",
+	"			#define CNTRSTACK",	/* => !NOREDUCE && BITSTATE && SAFETY && WS<=4 */
+	"		#else",
+	"			#define FULLSTACK",	/* => !NOREDUCE && BITSTATE && (!SAFETY || WS>4) */
+	"		#endif",
+	"	#else",
+	"		#define FULLSTACK",		/* => !NOREDUCE && !BITSTATE */
+	"	#endif",
 	"#endif",
 	"#ifdef BITSTATE",
-		"#ifndef NOCOMP",
-		"#define NOCOMP",
-		"#endif",
-		"#if !defined(LC) && defined(SC)",
-		"#define LC",
-		"#endif",
+	"	#ifndef NOCOMP",
+	"		#define NOCOMP",
+	"	#endif",
+	"	#if !defined(LC) && defined(SC)",
+	"		#define LC",
+	"	#endif",
 	"#endif",
 	"#if defined(COLLAPSE2) || defined(COLLAPSE3) || defined(COLLAPSE4)",
-		"/* accept the above for backward compatibility */",
-		"#define COLLAPSE",
+	"	/* accept the above for backward compatibility */",
+	"	#define COLLAPSE",
 	"#endif",
 	"#ifdef HC",
-	"#undef HC",
-	"#define HC4",
+	"	#undef HC",
+	"	#define HC4",
 	"#endif",
-	"#ifdef HC0",	/* 32 bits */
-	"#define HC	0",
-	"#endif",
-	"#ifdef HC1",	/* 32+8 bits */
-	"#define HC	1",
-	"#endif",
-	"#ifdef HC2",	/* 32+16 bits */
-	"#define HC	2",
-	"#endif",
-	"#ifdef HC3",	/* 32+24 bits */
-	"#define HC	3",
-	"#endif",
-	"#ifdef HC4",	/* 32+32 bits - combine with -DMA=8 */
-	"#define HC	4",
-	"#endif",
-	"#ifdef COLLAPSE",
-	"unsigned long ncomps[256+2];",
-	"#endif",
-
-	"#define MAXQ   	255",
-	"#define MAXPROC	255",
-	"#define WS		sizeof(long)   /* word size in bytes */",
-	"typedef struct Stack  {	 /* for queues and processes */",
+	"#if defined(HC0) || defined(HC1) || defined(HC2) || defined(HC3) || defined(HC4)",
+	"	#define HC	4",	/* 2x32 bits */
+	"#endif",	/* really only one hashcompact mode, not 5 */
+	"",
+	"typedef struct _Stack  {	 /* for queues and processes */",
 	"#if VECTORSZ>32000",
 	"	int o_delta;",
-	"	int o_offset;",
-	"	int o_skip;",
+	"	#ifndef TRIX",
+	"		int o_offset;",
+	"		int o_skip;",
+	"	#endif",
 	"	int o_delqs;",
 	"#else",
 	"	short o_delta;",
-	"	short o_offset;",
-	"	short o_skip;",
+	"	#ifndef TRIX",
+	"		short o_offset;",
+	"		short o_skip;",
+	"	#endif",
 	"	short o_delqs;",
 	"#endif",
 	"	short o_boq;",
+	"#ifdef TRIX",
+	"	short parent;",
+	"	char *b_ptr;",	/* used in delq/q_restor and delproc/p_restor */
+	"#else",
+	"	char *body;",	/* full copy of state vector in non-trix mode */
+	"#endif",
 	"#ifndef XUSAFE",
 	"	char *o_name;",
 	"#endif",
-	"	char *body;",
-	"	struct Stack *nxt;",
-	"	struct Stack *lst;",
-	"} Stack;\n",
+	"	struct _Stack *nxt;",
+	"	struct _Stack *lst;",
+	"} _Stack;\n",
 	"typedef struct Svtack { /* for complete state vector */",
 	"#if VECTORSZ>32000",
 	"	int o_delta;",
@@ -153,35 +173,15 @@
 	0,
 };
 
-static char *Header0[] = {
+static const char *Header0[] = {
 	"	char *body;",
 	"	struct Svtack *nxt;",
 	"	struct Svtack *lst;",
 	"} Svtack;\n",
-	"Trans ***trans;	/* 1 ptr per state per proctype */\n",
-	"#if defined(FULLSTACK) || defined(BFS)",
-	"struct H_el *Lstate;",
-	"#endif",
-	"int depthfound = -1;	/* loop detection */",
-	"#if VECTORSZ>32000",
-	"int proc_offset[MAXPROC];",
-	"int q_offset[MAXQ];",
-	"#else",
-	"short proc_offset[MAXPROC];",
-	"short q_offset[MAXQ];",
-	"#endif",
-	"uchar proc_skip[MAXPROC];",
-	"uchar q_skip[MAXQ];",
-	"unsigned long  vsize;	/* vector size in bytes */",
-	"#ifdef SVDUMP",
-	"int vprefix=0, svfd;		/* runtime option -pN */",
-	"#endif",
-	"char *tprefix = \"trail\";	/* runtime option -tsuffix */",
-	"short boq = -1;		/* blocked_on_queue status */",
 	0,
 };
 
-static char *Head1[] = {
+static const char *Head1[] = {
 	"typedef struct State {",
 	"	uchar _nr_pr;",
 	"	uchar _nr_qs;",
@@ -207,24 +207,32 @@
 #endif
 		"	unsigned short _vsz;",
 		"#else",
-		"	unsigned long  _vsz;",
+		"	ulong  _vsz;",
 		"#endif",
 	"#endif",
 
-	"#ifdef HAS_LAST",	/* cannot go before _cnt - see hstore() */
+	"#ifdef HAS_LAST",	/* cannot go before _cnt - see h_store() */
 	"	uchar  _last;	/* pid executed in last step */",
 	"#endif",
+
+	"#if defined(BITSTATE) && defined(BCS) && defined(STORE_CTX)",
+	"	uchar  _ctx;	/* nr of context switches so far */",
+	"#endif",
+	"#if defined(BFS_PAR) && defined(L_BOUND)",
+	"	uchar  _l_bnd;	/* bounded liveness */",
+	"	uchar *_l_sds;	/* seed state */",
+	"#endif",
 	"#ifdef EVENT_TRACE",
-		"#if nstates_event<256",
-	"	uchar _event;",
-		"#else",
-	"	unsigned short _event;",
-		"#endif",
+	"	#if nstates_event<256",
+	"		uchar _event;",
+	"	#else",
+	"		unsigned short _event;",
+	"	#endif",
 	"#endif",
 	0,
 };
 
-static char *Addp0[] = {
+static const char *Addp0[] = {
 	/* addproc(....parlist... */ ")",
 	"{	int j, h = now._nr_pr;",
 	"#ifndef NOCOMP",
@@ -235,45 +243,66 @@
 	"	if (TstOnly) return (h < MAXPROC);",
 	"#endif",
 	"#ifndef NOBOUNDCHECK",
-	"/* redefine Index only within this procedure */",
-	"#undef Index",
-	"#define Index(x, y)	Boundcheck(x, y, 0, 0, 0)",
+	"	/* redefine Index only within this procedure */",
+	"	#undef Index",
+	"	#define Index(x, y)	Boundcheck(x, y, 0, 0, 0)",
 	"#endif",
 	"	if (h >= MAXPROC)",
 	"		Uerror(\"too many processes\");",
+	"#ifdef V_TRIX",
+	"	printf(\"%%4d: add process %%d\\n\", depth, h);",
+	"#endif",
 	"	switch (n) {",
 	"	case 0: j = sizeof(P0); break;",
 	0,
 };
 
-static char *Addp1[] = {
+static const char *Addp1[] = {
 	"	default: Uerror(\"bad proc - addproc\");",
 	"	}",
+	"	#ifdef BFS_PAR",
+	"		bfs_prepmask(1);	/* addproc */",
+	"	#endif",
+
+	"#ifdef TRIX",
+	"	vsize += sizeof(H_el *);",
+	"#else",
 	"	if (vsize%%WS)",
 	"		proc_skip[h] = WS-(vsize%%WS);",
 	"	else",
 	"		proc_skip[h] = 0;",
-	"#ifndef NOCOMP",
-	"	for (k = vsize + (int) proc_skip[h]; k > vsize; k--)",
-	"		Mask[k-1] = 1; /* align */",
-	"#endif",
+	"	#if !defined(NOCOMP) && !defined(HC)",
+	"		for (k = vsize + (int) proc_skip[h]; k > vsize; k--)",
+	"			Mask[k-1] = 1; /* align */",
+	"	#endif",
 	"	vsize += (int) proc_skip[h];",
 	"	proc_offset[h] = vsize;",
-	"#ifdef SVDUMP",
+	"	vsize += j;",
+	"	#if defined(SVDUMP) && defined(VERBOSE)",
 	"	if (vprefix > 0)",
 	"	{	int dummy = 0;",
 	"		write(svfd, (uchar *) &dummy, sizeof(int)); /* mark */",
 	"		write(svfd, (uchar *) &h, sizeof(int));",
 	"		write(svfd, (uchar *) &n, sizeof(int));",
-	"#if VECTORSZ>32000",
+	"	#if VECTORSZ>32000",
 	"		write(svfd, (uchar *) &proc_offset[h], sizeof(int));",
-	"#else",
-	"		write(svfd, (uchar *) &proc_offset[h], sizeof(short));",
-	"#endif",
 	"		write(svfd, (uchar *) &now, vprefix-4*sizeof(int)); /* padd */",
+	"	#else",
+	"		write(svfd, (uchar *) &proc_offset[h], sizeof(short));",
+	"		write(svfd, (uchar *) &now, vprefix-3*sizeof(int)-sizeof(short)); /* padd */",
+	"	#endif",
 	"	}",
+	"	#endif",
 	"#endif",
+
 	"	now._nr_pr += 1;",
+	"#if defined(BCS) && defined(CONSERVATIVE)",
+	"	if (now._nr_pr >= CONSERVATIVE*8)",
+	"	{	printf(\"pan: error: too many processes -- recompile with \");",
+	"		printf(\"-DCONSERVATIVE=%%d\\n\", CONSERVATIVE+1);",
+	"		pan_exit(1);",
+	"	}",
+	"#endif",
 	"	if (fairness && ((int) now._nr_pr + 1 >= (8*NFAIR)/2))",
 	"	{	printf(\"pan: error: too many processes -- current\");",
 	"		printf(\" max is %%d procs (-DNFAIR=%%d)\\n\",",
@@ -282,71 +311,127 @@
 	"			NFAIR+1);",
 	"		pan_exit(1);",
 	"	}",
-
-	"	vsize += j;",
 	"#ifndef NOVSZ",
 	"	now._vsz = vsize;",
 	"#endif",
-	"#ifndef NOCOMP",
-	"	for (k = 1; k <= Air[n]; k++)",
-	"		Mask[vsize - k] = 1; /* pad */",
-	"	Mask[vsize-j] = 1; /* _pid */",
-	"#endif",
 	"	hmax = max(hmax, vsize);",
+
+	"#ifdef TRIX",
+	"	#ifndef BFS",
+	"		if (freebodies)",
+	"		{	processes[h] = freebodies;",
+	"			freebodies = freebodies->nxt;",
+	"		} else",
+	"		{	processes[h] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));",
+	"			processes[h]->body = (uchar *) emalloc(Maxbody * sizeof(char));",
+	"		}",
+	"		processes[h]->modified = 1;	/* addproc */",
+	"	#endif",
+	"	processes[h]->psize = j;",
+	"	processes[h]->parent_pid = calling_pid;",
+	"	processes[h]->nxt = (TRIX_v6 *) 0;",
+	"#else",
+	"	#if !defined(NOCOMP) && !defined(HC)",
+	"		for (k = 1; k <= Air[n]; k++)",
+	"			Mask[vsize - k] = 1; /* pad */",
+	"		Mask[vsize-j] = 1; /* _pid */",
+	"	#endif",
+	"	#ifdef BFS_PAR",
+	"		bfs_fixmask(1);	/* addproc */",
+	"	#endif",
 	"	if (vsize >= VECTORSZ)",
 	"	{	printf(\"pan: error, VECTORSZ too small, recompile pan.c\");",
-	"		printf(\" with -DVECTORSZ=N with N>%%d\\n\", vsize);",
+	"		printf(\" with -DVECTORSZ=N with N>%%d\\n\", (int) vsize);",
 	"		Uerror(\"aborting\");",
 	"	}",
+	"#endif",
+
 	"	memset((char *)pptr(h), 0, j);",
 	"	this = pptr(h);",
 	"	if (BASE > 0 && h > 0)",
-	"		((P0 *)this)->_pid = h-BASE;",
-	"	else",
-	"		((P0 *)this)->_pid = h;",
+	"	{	((P0 *)this)->_pid = h-BASE;",
+	"	} else",
+	"	{	((P0 *)this)->_pid = h;",
+	"	}",
 	"	switch (n) {",
 	0,
 };
 
-static char *Addq0[] = {
+static const char *Addq0[] = {
+	"",
 	"int",
-	"addqueue(int n, int is_rv)",
+	"addqueue(int calling_pid, int n, int is_rv)",
 	"{	int j=0, i = now._nr_qs;",
-	"#ifndef NOCOMP",
+	"#if !defined(NOCOMP) && !defined(TRIX)",
 	"	int k;",
 	"#endif",
 	"	if (i >= MAXQ)",
 	"		Uerror(\"too many queues\");",
+	"#ifdef V_TRIX",
+	"	printf(\"%%4d: add queue %%d\\n\", depth, i);",
+	"#endif",
 	"	switch (n) {",
 	0,
 };
 
-static char *Addq1[] = {
+static const char *Addq1[] = {
 	"	default: Uerror(\"bad queue - addqueue\");",
 	"	}",
+	"	#ifdef BFS_PAR",
+	"		bfs_prepmask(2);	/* addqueue */",
+	"	#endif",
+
+	"#ifdef TRIX",
+	"	vsize += sizeof(H_el *);",
+	"#else",
 	"	if (vsize%%WS)",
 	"		q_skip[i] = WS-(vsize%%WS);",
 	"	else",
 	"		q_skip[i] = 0;",
-	"#ifndef NOCOMP",
-	"	k = vsize;",
-	"#ifndef BFS",
-	"	if (is_rv) k += j;",
-	"#endif",
-	"	for (k += (int) q_skip[i]; k > vsize; k--)",
-	"		Mask[k-1] = 1;",
-	"#endif",
+	"	#if !defined(NOCOMP) && !defined(HC)",
+	"		k = vsize;",
+	"		#ifndef BFS",
+	"			if (is_rv) k += j;",
+	"		#endif",
+	"		for (k += (int) q_skip[i]; k > vsize; k--)",
+	"			Mask[k-1] = 1;",
+	"	#endif",
 	"	vsize += (int) q_skip[i];",
 	"	q_offset[i] = vsize;",
-	"	now._nr_qs += 1;",
 	"	vsize += j;",
+	"	#ifdef BFS_PAR",
+	"		bfs_fixmask(2);	/* addqueue */",
+	"	#endif",
+	"#endif",
+
+	"	now._nr_qs += 1;",
 	"#ifndef NOVSZ",
 	"	now._vsz = vsize;",
 	"#endif",
 	"	hmax = max(hmax, vsize);",
+
+	"#ifdef TRIX",
+	"	#ifndef BFS",
+	"		if (freebodies)",
+	"		{	channels[i] = freebodies;",
+	"			freebodies = freebodies->nxt;",
+	"		} else",
+	"		{	channels[i] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));",
+	"			channels[i]->body = (uchar *) emalloc(Maxbody * sizeof(char));",
+	"		}",
+	"		channels[i]->modified = 1;	/* addq */",
+	"	#endif",
+	"	channels[i]->psize = j;",
+	"	channels[i]->parent_pid = calling_pid;",
+	"	channels[i]->nxt = (TRIX_v6 *) 0;",
+	"#else",
 	"	if (vsize >= VECTORSZ)",
 	"		Uerror(\"VECTORSZ is too small, edit pan.h\");",
-	"	memset((char *)qptr(i), 0, j);",
+	"#endif",
+
+	"	if (j > 0)", /* zero if there are no queues */
+	"	{	memset((char *)qptr(i), 0, j);",
+	"	}",
 	"	((Q0 *)qptr(i))->_t = n;",
 	"	return i+1;",
 	"}\n",
@@ -353,7 +438,7 @@
 	0,
 };
 
-static char *Addq11[] = {
+static const char *Addq11[] = {
 	"{	int j; uchar *z;\n",
 	"#ifdef HAS_SORTED",
 	"	int k;",
@@ -362,6 +447,19 @@
 	"	uerror(\"ref to uninitialized chan name (sending)\");",
 	"	if (into >= (int) now._nr_qs || into < 0)",
 	"		Uerror(\"qsend bad queue#\");",
+	"#if defined(TRIX) && !defined(BFS)",
+	"	#ifndef TRIX_ORIG",
+	"		(trpt+1)->q_bup = now._ids_[now._nr_pr+into];",
+	"		#ifdef V_TRIX",
+	"			printf(\"%%4d: channel %%d s save %%p from %%d\\n\",",
+	"			depth, into, (trpt+1)->q_bup, now._nr_pr+into);",
+	"		#endif",
+	"	#endif",
+	"	channels[into]->modified = 1;	/* qsend */",
+	"	#ifdef V_TRIX",
+	"		printf(\"%%4d: channel %%d modified\\n\", depth, into);",
+	"	#endif",
+	"#endif",
 	"	z = qptr(into);",
 	"	j = ((Q0 *)qptr(into))->Qlen;",
 	"	switch (((Q0 *)qptr(into))->_t) {",
@@ -368,7 +466,7 @@
 	0,
 };
 
-static char *Addq2[] = {
+static const char *Addq2[] = {
 	"	case 0: printf(\"queue %%d was deleted\\n\", into+1);",
 	"	default: Uerror(\"bad queue - qsend\");",
 	"	}",
@@ -389,7 +487,7 @@
 	0,
 };
 
-static char *Addq3[] = {
+static const char *Addq3[] = {
 	"	case 0: printf(\"queue %%d was deleted\\n\", from+1);",
 	"	}",
 	"	Uerror(\"bad queue q-zero\");",
@@ -449,7 +547,11 @@
 	"short q_recver[MAXQ+1];",
 	"int",
 	"q_R_check(int x, int who)",
-	"{	if (!q_recver[x])",
+	"{",
+	"#ifdef VERBOSE",
+	"	printf(\"q_R_check x=%%d who=%%d\\n\", x, who);",
+	"#endif",
+	"	if (!q_recver[x])",
 	"	{	q_recver[x] = who+1;",
 	"#if SYNC",
 	"		if (q_zero(x))",
@@ -489,7 +591,7 @@
 	0,
 };
 
-static char *Addq4[] = {
+static const char *Addq4[] = {
 	"	case 0: printf(\"queue %%d was deleted\\n\", from+1);",
 	"	}",
 	"	Uerror(\"bad queue - q_full\");",
@@ -509,6 +611,19 @@
 	"	int j, k, r=0;\n",
 	"	if (!from--)",
 	"	uerror(\"ref to uninitialized chan name (receiving)\");",
+	"#if defined(TRIX) && !defined(BFS)",
+	"	#ifndef TRIX_ORIG",
+	"		(trpt+1)->q_bup = now._ids_[now._nr_pr+from];",
+	"		#ifdef V_TRIX",
+	"			printf(\"%%4d: channel %%d r save %%p from %%d\\n\",",
+	"			depth, from, (trpt+1)->q_bup, now._nr_pr+from);",
+	"		#endif",
+	"	#endif",
+	"	channels[from]->modified = 1;	/* qrecv */",
+	"	#ifdef V_TRIX",
+	"		printf(\"%%4d: channel %%d modified\\n\", depth, from);",
+	"	#endif",
+	"#endif",
 	"	if (from >= (int) now._nr_qs || from < 0)",
 	"		Uerror(\"qrecv bad queue#\");",
 	"	z = qptr(from);",
@@ -520,7 +635,7 @@
 	0,
 };
 
-static char *Addq5[] = {
+static const char *Addq5[] = {
 	"	case 0: printf(\"queue %%d was deleted\\n\", from+1);",
 	"	default: Uerror(\"bad queue - qrecv\");",
 	"	}",
@@ -528,7 +643,7 @@
 	"}",
 	"#endif\n",
 	"#ifndef BITSTATE",
-	"#ifdef COLLAPSE",
+	"	#ifdef COLLAPSE",
 	"long",
 	"col_q(int i, char *z)",
 	"{	int j=0, k;",
@@ -538,15 +653,22 @@
 	0,
 };
 
-static char *Code0[] = {
+static const char *Code0[] = {
 	"void",
 	"run(void)",
 	"{	/* int i; */",
 	"	memset((char *)&now, 0, sizeof(State));",
-	"	vsize = (unsigned long) (sizeof(State) - VECTORSZ);",
+	"	vsize = (ulong) (sizeof(State) - VECTORSZ);",
 	"#ifndef NOVSZ",
 	"	now._vsz = vsize;",
 	"#endif",
+	"#ifdef TRIX",
+	"	if (VECTORSZ != sizeof(now._ids_))",
+	"	{	printf(\"VECTORSZ is %%d, but should be %%d in this mode\\n\",",
+	"			VECTORSZ, (int) sizeof(now._ids_));",
+	"		Uerror(\"VECTORSZ set incorrectly, recompile Spin (not pan.c)\");",
+	"	}",
+	"#endif",
 	"/* optional provisioning statements, e.g. to */",
 	"/* set hidden variables, used as constants */",
 	"#ifdef PROV",
@@ -556,98 +678,117 @@
 	0,
 };
 
-static char *R0[] = {
-	"	Maxbody = max(Maxbody, sizeof(P%d));",
+static const char *R0[] = {
+	"	Maxbody = max(Maxbody, ((int) sizeof(P%d)));",
 	"	reached[%d] = reached%d;",
-	"	accpstate[%d] = (uchar *) emalloc(nstates%d);",
-	"	progstate[%d] = (uchar *) emalloc(nstates%d);",
-	"	stopstate[%d] = (uchar *) emalloc(nstates%d);",
-	"	visstate[%d] = (uchar *) emalloc(nstates%d);",
-	"	mapstate[%d] = (short *) emalloc(nstates%d * sizeof(short));",
-	"#ifdef HAS_CODE",
-	"	NrStates[%d] = nstates%d;",
-	"#endif",
-	"	stopstate[%d][endstate%d] = 1;",
+	"	accpstate[%d] = (uchar *) emalloc(_nstates%d);",
+	"	progstate[%d] = (uchar *) emalloc(_nstates%d);",
+	"	loopstate%d = loopstate[%d] = (uchar *) emalloc(_nstates%d);",
+	"	stopstate[%d] = (uchar *) emalloc(_nstates%d);",
+	"	visstate[%d] = (uchar *) emalloc(_nstates%d);",
+	"	mapstate[%d] = (short *) emalloc(_nstates%d * sizeof(short));",
+	"	stopstate[%d][_endstate%d] = 1;",
 	0,
 };
 
-static char *R0a[] = {
-	"	retrans(%d, nstates%d, start%d, src_ln%d, reached%d);",
+static const char *R00[] = {
+	"	NrStates[%d] = _nstates%d;",
 	0,
 };
-static char *R0b[] = {
-	"	if (state_tables)",
-	"	{ printf(\"\\nTransition Type: \");",
-	"	  printf(\"A=atomic; D=d_step; L=local; G=global\\n\");",
-	"	  printf(\"Source-State Labels: \");",
-	"	  printf(\"p=progress; e=end; a=accept;\\n\");",
-	"#ifdef MERGED",
-	"	  printf(\"Note: statement merging was used. Only the first\\n\");",
-	"	  printf(\"      stmnt executed in each merge sequence is shown\\n\");",
-	"	  printf(\"      (use spin -a -o3 to disable statement merging)\\n\");",
-	"#endif",
-	"	  pan_exit(0);",
-	"	}",
+
+static const char *R0a[] = {
+	"	retrans(%d, _nstates%d, _start%d, src_ln%d, reached%d, loopstate%d);",
 	0,
 };
 
-static char *Code1[] = {
+static const char *Code1[] = {
 	"#ifdef NP",
-	"#define ACCEPT_LAB	1 /* at least 1 in np_ */",
+	"	#define ACCEPT_LAB	1 /* at least 1 in np_ */",
 	"#else",
-	"#define ACCEPT_LAB	%d /* user-defined accept labels */",
+	"	#define ACCEPT_LAB	%d /* user-defined accept labels */",
 	"#endif",
+	"#ifdef MEMCNT",
+	"	#ifdef MEMLIM",
+	"		#warning -DMEMLIM takes precedence over -DMEMCNT",
+	"		#undef MEMCNT",
+	"	#else",
+	"		#if MEMCNT<20",
+	"			#warning using minimal value -DMEMCNT=20 (=1MB)",
+	"			#define MEMLIM	(1)",
+	"			#undef MEMCNT",
+	"		#else",
+	"			#if MEMCNT==20",
+	"				#define MEMLIM	(1)",
+	"				#undef MEMCNT",
+	"			#else",
+	"			 #if MEMCNT>=50",
+	"				#error excessive value for MEMCNT",
+	"			 #else",
+	"				#define MEMLIM	(1<<(MEMCNT-20))",
+	"			 #endif",
+	"			#endif",
+	"		#endif",
+	"	#endif",
+	"#endif",
+
+	"#if NCORE>1 && !defined(MEMLIM)",
+	"	#define MEMLIM	(2048)	/* need a default, using 2 GB */",
+	"#endif",
 	0,
 };
 
-static char *Code3[] = {
+static const char *Code3[] = {
 	"#define PROG_LAB	%d /* progress labels */",
 	0,
 };
 
-static char *R2[] = {
+static const char *R2[] = {
 	"uchar *accpstate[%d];",
 	"uchar *progstate[%d];",
+	"uchar *loopstate[%d];",
 	"uchar *reached[%d];",
 	"uchar *stopstate[%d];",
 	"uchar *visstate[%d];",
 	"short *mapstate[%d];",
 	"#ifdef HAS_CODE",
-	"int NrStates[%d];",
+	"	int NrStates[%d];",
 	"#endif",
 	0,
 };
-static char *R3[] = {
-	"	Maxbody = max(Maxbody, sizeof(Q%d));",
+static const char *R3[] = {
+	"	Maxbody = max(Maxbody, ((int) sizeof(Q%d)));",
 	0,
 };
-static char *R4[] = {
-	"	r_ck(reached%d, nstates%d, %d, src_ln%d, src_file%d);",
+static const char *R4[] = {
+	"	r_ck(reached%d, _nstates%d, %d, src_ln%d, src_file%d);",
 	0,
 };
-static char *R5[] = {
+static const char *R5[] = {
 	"	case %d: j = sizeof(P%d); break;",
 	0,
 };
-static char *R6[] = {
+static const char *R6[] = {
 	"	}",
 	"	this = o_this;",
+	"#ifdef TRIX",
+	"	re_mark_all(1); /* addproc */",
+	"#endif",
 	"	return h-BASE;",
 	"#ifndef NOBOUNDCHECK",
-	"#undef Index",
-	"#define Index(x, y)	Boundcheck(x, y, II, tt, t)",
+	"	#undef Index",
+	"	#define Index(x, y)	Boundcheck(x, y, II, tt, t)",
 	"#endif",
 	"}\n",
 	"#if defined(BITSTATE) && defined(COLLAPSE)",
-	"/* just to allow compilation, to generate the error */",
-	"long col_p(int i, char *z) { return 0; }",
-	"long col_q(int i, char *z) { return 0; }",
+	"	/* just to allow compilation, to generate the error */",
+	"	long col_p(int i, char *z) { return 0; }",
+	"	long col_q(int i, char *z) { return 0; }",
 	"#endif",
 	"#ifndef BITSTATE",
-	"#ifdef COLLAPSE",
+	"	#ifdef COLLAPSE",
 	"long",
 	"col_p(int i, char *z)",
-	"{	int j, k; unsigned long ordinal(char *, long, short);",
+	"{	int j, k; ulong ordinal(char *, long, short);",
 	"	char *x, *y;",
 	"	P0 *ptr = (P0 *) pptr(i);",
 	"	switch (ptr->_t) {",
@@ -654,15 +795,150 @@
 	"	case 0: j = sizeof(P0); break;",
 	0,
 };
-static char *R8a[] = {
+static const char *R7a[] = {
+	"void\nre_mark_all(int whichway)",
+	"{	int j;",
+	"	#ifdef V_TRIX",
+	"		printf(\"%%d: re_mark_all channels %%d\\n\", depth, whichway);",
+	"	#endif",
+	"	#ifndef BFS",
+	"	for (j = 0; j < now._nr_qs; j++)",
+	"		channels[j]->modified = 1; /* channel index moved */",
+	"	#endif",
+	"	#ifndef TRIX_ORIG",
+	"	if (whichway > 0)",
+	"	{	for (j = now._nr_pr + now._nr_qs - 1; j >= now._nr_pr; j--)",
+	"			now._ids_[j] = now._ids_[j-1];",
+	"	} else",
+	"	{	for (j = now._nr_pr; j < now._nr_pr + now._nr_qs; j++)",
+	"			now._ids_[j] = now._ids_[j+1];",
+	"	}",
+	"	#endif",
+	"}",
+	0,
+};
+
+static const char *R7b[] = {
+	"#ifdef BFS_PAR",
+	"inline void",
+	"bfs_prepmask(int caller)",
+	"{",
+	"#if !defined(NOCOMP) && !defined(HC)",
+	"	memcpy((char *) &tmp_msk, (const char *) Mask, sizeof(State));",
+	"	Mask = (uchar *) &tmp_msk;",
+	"#endif",
+	"	switch (caller) {",
+	"	case 1:	/* addproc */",
+	"#if VECTORSZ>32000",
+	"		memcpy((char *) P_o_tmp, (const char *) proc_offset, MAXPROC*sizeof(int));",
+	"#else",
+	"		memcpy((char *) P_o_tmp, (const char *) proc_offset, MAXPROC*sizeof(short));",
+	"#endif",
+	"		memcpy((char *) P_s_tmp, (const char *) proc_skip, MAXPROC*sizeof(uchar));",
+	"		proc_offset = P_o_tmp;",
+	"		proc_skip   = (uchar *) &P_s_tmp[0];",
+	"		break;",
+	"	case 2: /* addqueue */",
+	"#if VECTORSZ>32000",
+	"		memcpy((char *) Q_o_tmp, (const char *) q_offset, MAXQ*sizeof(int));",
+	"#else",
+	"		memcpy((char *) Q_o_tmp, (const char *) q_offset, MAXQ*sizeof(short));",
+	"#endif",
+	"		memcpy((char *) Q_s_tmp, (const char *) q_skip, MAXQ*sizeof(uchar));",
+	"		q_offset = Q_o_tmp;",
+	"		q_skip   = (uchar *) &Q_s_tmp[0];",
+	"		break;",
+	"	case 3: /* no nothing */",
+	"		break;",
+	"	default: /* cannot happen */",
+	"		Uerror(\"no good\");",
+	"		break;",
+	"	}",
+	"}",
+	"",
+	"typedef struct BFS_saves BFS_saves;",
+	"struct BFS_saves {",
+	"	char *m;",
+	"	BFS_saves *nxt;",
+	"} *bfs_save_po,",
+	"  *bfs_save_ps,",
+	"#if !defined(NOCOMP) && !defined(HC)",
+	"  *bfs_save_mask,",
+	"#endif",
+	"  *bfs_save_qo,",
+	"  *bfs_save_qs;",
+	"",
+	"extern volatile uchar *sh_malloc(ulong);",
+	"static int bfs_runs; /* 0 before local heaps are initialized */",
+	"",
+	"void",
+	"bfs_swoosh(BFS_saves **where, char **what, int howmuch)",
+	"{	BFS_saves *m;",
+	"	for (m = *where; m; m = m->nxt)",
+	"	{	if (memcmp(m->m, *what, howmuch) == 0)",
+	"		{	*what = m->m;",
+	"			return;",
+	"	}	}",
+	"	m = (BFS_saves *) emalloc(sizeof(BFS_saves));",
+	"	if (bfs_runs)",
+	"	{	m->m = (char *) sh_malloc(howmuch);",
+	"	} else",
+	"	{	m->m = (char *) sh_pre_malloc(howmuch);",
+	"	}",
+	"	memcpy(m->m, *what, howmuch);",
+	"	m->nxt = *where;",
+	"	*where = m;",
+	"	*what = m->m;",
+	"}",
+	"",
+	"void",
+	"bfs_fixmask(int caller)",	/* 1=addproc, 2=addqueue */
+	"{",
+	"#if !defined(NOCOMP) && !defined(HC)",
+	"	bfs_swoosh(&bfs_save_mask, (char **) &Mask, sizeof(State));",
+	"#endif",
+	"#ifndef TRIX",
+	"	switch (caller) {",
+	"	case 1: /* addproc */",
+	"	#if VECTORSZ>32000",
+	"		bfs_swoosh(&bfs_save_po, (char **) &proc_offset, MAXPROC*sizeof(int));",
+	"	#else",
+	"		bfs_swoosh(&bfs_save_po, (char **) &proc_offset, MAXPROC*sizeof(short));",
+	"	#endif",
+	"		bfs_swoosh(&bfs_save_ps, (char **) &proc_skip, MAXPROC*sizeof(uchar));",
+	"		break;",
+	"	case 2: /* addqueue */",
+	"	#if VECTORSZ>32000",
+	"		bfs_swoosh(&bfs_save_qo, (char **) &q_offset, MAXQ*sizeof(int));",
+	"	#else",
+	"		bfs_swoosh(&bfs_save_qo, (char **) &q_offset, MAXQ*sizeof(short));",
+	"	#endif",
+	"		bfs_swoosh(&bfs_save_qs, (char **) &q_skip, MAXQ*sizeof(uchar));",
+	"		break;",
+	"	case 3: /* do nothing */",
+	"		break;",
+	"	default:",
+	"		Uerror(\"double plus ungood\");",
+	"		break;",
+	"	}",
+	"#endif",
+	"}",
+	"#endif",
+	0,
+};
+static const char *R8a[] = {
 	"	default: Uerror(\"bad proctype - collapse\");",
 	"	}",
 	"	if (z) x = z; else x = scratch;",
 	"	y = (char *) ptr; k = proc_offset[i];",
-
+	"",
+	"#if !defined(NOCOMP) && !defined(HC)",
 	"	for ( ; j > 0; j--, y++)",
 	"		if (!Mask[k++]) *x++ = *y;",
-
+	"#else",
+	"	memcpy(x, y, j);",
+	"	x += j;",
+	"#endif",
 	"	for (j = 0; j < WS-1; j++)",
 	"		*x++ = 0;",
 	"	x -= j;",
@@ -669,22 +945,28 @@
 	"	if (z) return (long) (x - z);",
 	"	return ordinal(scratch, x-scratch, (short) (2+ptr->_t));",
 	"}",
+	"	#endif",
 	"#endif",
-	"#endif",
 	0,
 };
-static char *R8b[] = {
+static const char *R8b[] = {
 	"	default: Uerror(\"bad qtype - collapse\");",
 	"	}",
 	"	if (z) x = z; else x = scratch;",
 	"	y = (char *) ptr; k = q_offset[i];",
 
+	"#if NQS > 0",
 	"	/* no need to store the empty slots at the end */",
 	"	j -= (q_max[ptr->_t] - ptr->Qlen) * ((j - 2)/q_max[ptr->_t]);",
-
+	"#endif",
+	"",
+	"#if !defined(NOCOMP) && !defined(HC)",
 	"	for ( ; j > 0; j--, y++)",
 	"		if (!Mask[k++]) *x++ = *y;",
-
+	"#else",
+	"	memcpy(x, y, j);",
+	"	x += j;",
+	"#endif",
 	"	for (j = 0; j < WS-1; j++)",
 	"		*x++ = 0;",
 	"	x -= j;",
@@ -691,16 +973,16 @@
 	"	if (z) return (long) (x - z);",
 	"	return ordinal(scratch, x-scratch, 1); /* chan */",
 	"}",
+	"	#endif",
 	"#endif",
-	"#endif",
 	0,
 };
 
-static char *R12[] = {
+static const char *R12[] = {
 	"\t\tcase %d: r = ((Q%d *)z)->contents[slot].fld%d; break;",
 	0,
 };
-char *R13[] = {
+const char *R13[] = {
 	"int ",
 	"unsend(int into)",
 	"{	int _m=0, j; uchar *z;\n",
@@ -709,6 +991,20 @@
 	"#endif",
 	"	if (!into--)",
 	"		uerror(\"ref to uninitialized chan (unsend)\");",
+	"#if defined(TRIX) && !defined(BFS)",
+	"	#ifndef TRIX_ORIG",
+	"		now._ids_[now._nr_pr+into] = trpt->q_bup;",
+	"		#ifdef V_TRIX",
+	"			printf(\"%%4d: channel %%d s restore %%p into %%d\\n\",",
+	"				depth, into, trpt->q_bup, now._nr_pr+into);",
+	"		#endif",
+	"	#else",
+	"		channels[into]->modified = 1;	/* unsend */",
+	"		#ifdef V_TRIX",
+	"			printf(\"%%4d: channel %%d unmodify\\n\", depth, into);",
+	"		#endif",
+	"	#endif",
+	"#endif",
 	"	z = qptr(into);",
 	"	j = ((Q0 *)z)->Qlen;",
 	"	((Q0 *)z)->Qlen = --j;",
@@ -715,7 +1011,7 @@
 	"	switch (((Q0 *)qptr(into))->_t) {",
 	0,
 };
-char *R14[] = {
+const char *R14[] = {
 	"	default: Uerror(\"bad queue - unsend\");",
 	"	}",
 	"	return _m;",
@@ -725,6 +1021,20 @@
 	"{	int j; uchar *z;\n",
 	"	if (!from--)",
 	"		uerror(\"ref to uninitialized chan (unrecv)\");",
+	"#if defined(TRIX) && !defined(BFS)",
+	"	#ifndef TRIX_ORIG",
+	"		now._ids_[now._nr_pr+from] = trpt->q_bup;",
+	"		#ifdef V_TRIX",
+	"			printf(\"%%4d: channel %%d r restore %%p into %%d\\n\",",
+	"				depth, from, trpt->q_bup, now._nr_pr+from);",
+	"		#endif",
+	"	#else",
+	"		channels[from]->modified = 1;	/* unrecv */",
+	"		#ifdef V_TRIX",
+	"			printf(\"%%4d: channel %%d unmodify\\n\", depth, from);",
+	"		#endif",
+	"	#endif",
+	"#endif",
 	"	z = qptr(from);",
 	"	j = ((Q0 *)z)->Qlen;",
 	"	if (strt) ((Q0 *)z)->Qlen = j+1;",
@@ -731,34 +1041,33 @@
 	"	switch (((Q0 *)qptr(from))->_t) {",
 	0,
 };
-char *R15[] = {
+const char *R15[] = {
 	"	default: Uerror(\"bad queue - qrecv\");",
 	"	}",
 	"}",
 	0,
 };
-static char *Proto[] = {
+static const char *Proto[] = {
 	"",
 	"/** function prototypes **/",
-	"char *emalloc(unsigned long);",
-	"char *Malloc(unsigned long);",
+	"char *emalloc(ulong);",
+	"char *Malloc(ulong);",
 	"int Boundcheck(int, int, int, int, Trans *);",
-	"int addqueue(int, int);",
+	"int addqueue(int, int, int);",
 	"/* int atoi(char *); */",
 	"/* int abort(void); */",
 	"int close(int);",	/* should probably remove this */
 #if 0
 	"#ifndef SC",
-	"int creat(char *, unsigned short);",
-	"int write(int, void *, unsigned);",
+	"	int creat(char *, unsigned short);",
+	"	int write(int, void *, unsigned);",
 	"#endif",
 #endif
 	"int delproc(int, int);",
 	"int endstate(void);",
-	"int hstore(char *, int);",
-"#ifdef MA",
-	"int gstore(char *, int, uchar);",
-"#endif",
+	"int find_claim(char *);",
+	"int h_store(char *, int);",
+	"int pan_rand(void);",
 	"int q_cond(short, Trans *);",
 	"int q_full(int);",
 	"int q_len(int);",
@@ -766,21 +1075,33 @@
 	"int qrecv(int, int, int, int);",
 	"int unsend(int);",
 	"/* void *sbrk(int); */",
-	"void Uerror(char *);",
-	"void assert(int, char *, int, int, Trans *);",
+	"void spin_assert(int, char *, int, int, Trans *);",
+	"#ifdef BFS_PAR",
+	"void bfs_printf(const char *, ...);",
+	"volatile uchar *sh_pre_malloc(ulong);",
+	"#endif",
 	"void c_chandump(int);",
 	"void c_globals(void);",
 	"void c_locals(int, int);",
 	"void checkcycles(void);",
 	"void crack(int, int, Trans *, short *);",
+	"void d_sfh(uchar *, int);",
 	"void d_hash(uchar *, int);",
+	"void m_hash(uchar *, int);",
 	"void s_hash(uchar *, int);",
-	"void r_hash(uchar *, int);",
 	"void delq(int);",
+	"void dot_crack(int, int, Trans *);",
 	"void do_reach(void);",
 	"void pan_exit(int);",
 	"void exit(int);",
-	"void hinit(void);",
+	"#ifdef BFS_PAR",
+	"	void bfs_setup_mem(void);",
+	"#endif",
+	"#ifdef BITSTATE",
+	"	void sinit(void);",
+	"#else",
+	"	void hinit(void);",
+	"#endif",
 	"void imed(Trans *, int, int, int);",
 	"void new_state(void);",
 	"void p_restor(int);",
@@ -787,44 +1108,320 @@
 	"void putpeg(int, int);",
 	"void putrail(void);",
 	"void q_restor(void);",
-	"void retrans(int, int, int, short *, uchar *);",
+	"void retrans(int, int, int, short *, uchar *, uchar *);",
+	"void select_claim(int);",
 	"void settable(void);",
 	"void setq_claim(int, int, char *, int, char *);",
 	"void sv_restor(void);",
 	"void sv_save(void);",
 	"void tagtable(int, int, int, short *, uchar *);",
-	"void uerror(char *);",
+	"void do_dfs(int, int, int, short *, uchar *, uchar *);",
 	"void unrecv(int, int, int, int, int);",
 	"void usage(FILE *);",
-	"void wrap_stats(void);",
+	"void wrap_stats(void);\n",
+	"#ifdef MA",
+	"	int g_store(char *, int, uchar);",
+	"#endif",
 	"#if defined(FULLSTACK) && defined(BITSTATE)",
-	"int  onstack_now(void);",
-	"void onstack_init(void);",
-	"void onstack_put(void);",
-	"void onstack_zap(void);",
+	"	int  onstack_now(void);",
+	"	void onstack_init(void);",
+	"	void onstack_put(void);",
+	"	void onstack_zap(void);",
 	"#endif",
 	"#ifndef XUSAFE",
-	"int q_S_check(int, int);",
-	"int q_R_check(int, int);",
-	"uchar q_claim[MAXQ+1];",
-	"char *q_name[MAXQ+1];",
-	"char *p_name[MAXPROC+1];",
+	"	int q_S_check(int, int);",
+	"	int q_R_check(int, int);",
+	"	uchar q_claim[MAXQ+1];",
+	"	char *q_name[MAXQ+1];",
+	"	char *p_name[MAXPROC+1];",
 	"#endif",
+	"",
+	"#ifndef NO_V_PROVISO",
+	"	#define V_PROVISO",
+	"#endif",
+	"#if !defined(NO_RESIZE) && !defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(SPACE) && !defined(USE_TDH) && NCORE==1",
+	"	#define AUTO_RESIZE",
+	"#endif",
+	"",
+	"typedef struct Trail Trail;",
+	"typedef struct H_el  H_el;",
+	"",
+	"struct H_el {",
+	"	H_el *nxt;",
+	"	#ifdef FULLSTACK",
+	"		unsigned int tagged;",
+	"		#if defined(BITSTATE) && !defined(NOREDUCE) && !defined(SAFETY)",
+	"			unsigned int proviso;", /* uses just 1 bit 0/1 */
+	"		#endif",
+	"	#endif",
+	"	#if defined(CHECK) || (defined(COLLAPSE) && !defined(FULLSTACK))",
+	"		ulong st_id;",
+	"	#endif",
+	"	#if !defined(SAFETY) || defined(REACH)",
+	"		uint D;",
+	"	#endif",
+	"	#ifdef BCS",
+	"		#ifndef CONSERVATIVE",
+	"			#define CONSERVATIVE	1 /* good for up to 8 processes */",
+	"		#endif",
+	"		#ifdef CONSERVATIVE",
+	"			#if CONSERVATIVE <= 0 || CONSERVATIVE>32",
+	"			#error sensible values for CONSERVATIVE are 1..32 (256/8 = 32)",
+	"			#endif",
+	"			uchar ctx_pid[CONSERVATIVE];", /* pids setting lowest value */
+	"		#endif",
+	"		uchar ctx_low;", /* lowest nr of context switches seen so far */
+	"	#endif",
+	"	#if NCORE>1",
+	"		/* could cost 1 extra word: 4 bytes if 32-bit and 8 bytes if 64-bit */",
+	"		#ifdef V_PROVISO",
+	"			uchar	cpu_id;		/* id of cpu that created the state */",
+	"		#endif",
+	"	#endif",
+	"	#ifdef COLLAPSE",
+	"		#if VECTORSZ<65536",
+	"			ushort ln;",	/* length of vector */
+	"		#else",
+	"			ulong ln;",	/* length of vector */
+	"		#endif",
+	"	#endif",
+	"	#if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+	"		ulong m_K1;",
+	"	#endif",
+	"	ulong state;",
+	"};",
+	"",
+	"#ifdef BFS_PAR",
+	"typedef struct BFS_Trail BFS_Trail;",
+	"struct BFS_Trail {",
+	"	H_el *ostate;",
+	"	int   st;",
+	"	int   o_tt;",
+	"	T_ID  t_id;", /* could be uint, ushort, or uchar */
+	"	uchar pr;",
+	"	uchar o_pm;",
+	"	uchar tau;",
+	"};",
+	"	#if SYNC>0",
+	"		#undef BFS_NOTRAIL", /* just in case it was used */
+	"	#endif",
+	"#endif",
+	"",
+	"#ifdef RHASH",
+	"	#ifndef PERMUTED",
+	"	#define PERMUTED",
+	"	#endif",
+	"#endif",
+	"",
+	"struct Trail {",
+	"	int   st;	/* current state */",
+	"	int   o_tt;",
+	"#ifdef PERMUTED",
+	"	uint  seed;",
+	"	uchar oII;",
+	"#endif",
+	"	uchar pr;	/* process id */",
+	"	uchar tau;	/* 8 bit-flags */",
+	"	uchar o_pm;	/* 8 more bit-flags */",
+	"",
+	"	#if 0",
+	"	Meaning of bit-flags on tau and o_pm:",
+	"	tau&1   -> timeout enabled",
+	"	tau&2   -> request to enable timeout 1 level up (in claim)",
+	"	tau&4   -> current transition is a  claim move",
+	"	tau&8   -> current transition is an atomic move",
+	"	tau&16  -> last move was truncated on stack",
+	"	tau&32  -> current transition is a preselected move",
+	"	tau&64  -> at least one next state is not on the stack",
+	"	tau&128 -> current transition is a stutter move",
+
+	"	o_pm&1	-> the current pid moved -- implements else",
+	"	o_pm&2	-> this is an acceptance state",
+	"	o_pm&4	-> this is a  progress state",
+	"	o_pm&8	-> fairness alg rule 1 undo mark",
+	"	o_pm&16	-> fairness alg rule 3 undo mark",
+	"	o_pm&32	-> fairness alg rule 2 undo mark",
+	"	o_pm&64 -> the current proc applied rule2",
+	"	o_pm&128 -> a fairness, dummy move - all procs blocked",
+	"	#endif",
+	"",
+	"	#ifdef NSUCC",
+	"	 uchar n_succ;	/* nr of successor states */",
+	"	#endif",
+	"	#if defined(FULLSTACK) && defined(MA) && !defined(BFS)",
+	"	 uchar proviso;",
+	"	#endif",
+	"	#ifndef BFS",
+	"	 uchar  o_n, o_ot;	/* to save locals */",
+	"	#endif",
+	"	uchar  o_m;",
+	"	#ifdef EVENT_TRACE",
+	"		#if nstates_event<256",
+	"		 uchar o_event;",
+	"		#else",
+	"		 unsigned short o_event;",
+	"		#endif",
+	"	#endif",
+	"	#ifndef BFS",
+	"		short o_To;",
+	"		#if defined(T_RAND) || defined(RANDOMIZE)",
+	"		 short oo_i;",
+	"		#endif",
+	"	#endif",
+	"	#if defined(HAS_UNLESS) && !defined(BFS)",
+	"	 int e_state;	/* if escape trans - state of origin */",
+	"	#endif",
+	"	#if (defined(FULLSTACK) && !defined(MA)) || defined(BFS) || (NCORE>1)",
+	"	 H_el *ostate;	/* pointer to stored state */",
+	"	#endif",
+	/* CNTRSTACK when !NOREDUCE && BITSTATE && SAFETY && WS<=4, uses LL[] */
+	"	#if defined(CNTRSTACK) && !defined(BFS)",
+	"	 long	j6, j7;",
+	"	#endif",
+	"	Trans *o_t;",	/* transition fct, next state   */
+
+	"	#if !defined(BFS) && !defined(TRIX_ORIG)",
+	"	 char *p_bup;",
+	"	 char *q_bup;",
+	"	#endif",
+
+	"	#ifdef BCS",
+	"	 unsigned short sched_limit;",
+	"	 unsigned char  bcs; /* phase 1 or 2, or forced 4 */",
+	"	 unsigned char  b_pno; /* preferred pid */",
+	"	#endif",
+
+	"	#ifdef P_RAND",	/* process scheduling randomization */
+	"	 unsigned char p_left;	/* nr of procs left to explore */",
+	"	 short p_skip;	/* to find starting point in list */",
+	"	#endif",
+
+	"	#ifdef HAS_SORTED",
+	"	 short ipt;",	/* insertion slot in q */
+	"	#endif",
+	"	#ifdef HAS_PRIORITY",
+	"	 short o_priority;",
+	"	#endif",
+	"	union {",
+	"	 int oval;",	/* single backup value of variable */
+	"	 int *ovals;",	/* ptr to multiple values */
+	"	} bup;",
+	"}; /* end of struct Trail */",
+	"",
+	"#ifdef BFS",	/* breadth-first search */
+	"	#define Q_PROVISO",
+	"	#ifndef INLINE_REV",
+	"		#define INLINE_REV",
+	"	#endif",
+	"",
+	"typedef struct SV_Hold {",
+	"	State *sv;",
+	" #ifndef BFS_PAR",
+	"	int  sz;",
+	" #endif",
+	"	struct SV_Hold *nxt;",
+	"} SV_Hold;",
+	"#if !defined(BFS_PAR) || NRUNS>0",
+	"	typedef struct EV_Hold {",
+	"	 #if !defined(BFS_PAR) || (!defined(NOCOMP) && !defined(HC) && NRUNS>0)",
+	"		char *sv;	/* Mask */",
+	"	 #endif",
+	"	 #if VECTORSZ<65536",
+	"		ushort sz;	/* vsize */",
+	"	 #else",
+	"		ulong  sz;",
+	"	 #endif",
+	"	 #ifdef BFS_PAR",
+	"		uchar owner;",
+	"	 #endif",
+	"		uchar nrpr;",
+	"		uchar nrqs;",
+	"		#if !defined(BFS_PAR) || (!defined(TRIX) && NRUNS>0)",
+	"			char *po, *qo;",
+	"			char *ps, *qs;",
+	"		#endif",
+	"		struct EV_Hold *nxt;",
+	"	} EV_Hold;",
+	"#endif",
+	"typedef struct BFS_State {",
+	" #ifdef BFS_PAR",
+	"	BFS_Trail *t_info;",
+	"	State	*osv;",
+	" #else",
+	"	Trail	*frame;",
+	"	SV_Hold *onow;",
+	" #endif",
+	" #if !defined(BFS_PAR) || NRUNS>0",
+	"	EV_Hold *omask;",
+	" #endif",
+	" #if defined(Q_PROVISO) && !defined(NOREDUCE)",
+	"	H_el *lstate;",
+	" #endif",
+	" #if !defined(BFS_PAR) || SYNC>0",
+	"	short boq;",
+	" #endif",
+	" #ifdef VERBOSE",
+	"	ulong nr;",
+	" #endif",
+	" #ifndef BFS_PAR",	/* new 6.2.4, 3 dec 2012 */
+	"	struct BFS_State *nxt;",
+	" #endif",
+	"} BFS_State;",
+	"#endif\n",
 	0,
 };
 
-static char *SvMap[] = {
+static const char *SvMap[] = {
 	"void",
 	"to_compile(void)",
-	"{	char ctd[1024], carg[64];",
+	"{	char ctd[2048], carg[128];",
 	"#ifdef BITSTATE",
 	"	strcpy(ctd, \"-DBITSTATE \");",
 	"#else",
 	"	strcpy(ctd, \"\");",
 	"#endif",
+	"#ifdef BFS_PAR",
+	"	strcat(ctd, \"-DBFS_PAR \");",
+	"#endif",
 	"#ifdef NOVSZ",
 	"	strcat(ctd, \"-DNOVSZ \");",
 	"#endif",
+	"#ifdef RHASH",
+	"	strcat(ctd, \"-DRHASH \");",
+	"#else",
+	"	#ifdef PERMUTED",
+	"		strcat(ctd, \"-DPERMUTED \");",
+	"	#endif",
+	"#endif",
+	"#ifdef P_REVERSE",
+	"	strcat(ctd, \"-DP_REVERSE \");",
+	"#endif",
+	"#ifdef T_REVERSE",
+	"	strcat(ctd, \"-DT_REVERSE \");",
+	"#endif",
+	"#ifdef T_RAND",
+	"	#if T_RAND>0",
+	"	sprintf(carg, \"-DT_RAND=%%d \", T_RAND);",
+	"	strcat(ctd, carg);",
+	"	#else",
+	"	strcat(ctd, \"-DT_RAND \");",
+	"	#endif",
+	"#endif",
+	"#ifdef P_RAND",
+	"	#if P_RAND>0",
+	"	sprintf(carg, \"-DP_RAND=%%d \", P_RAND);",
+	"	strcat(ctd, carg);",
+	"	#else",
+	"	strcat(ctd, \"-DP_RAND \");",
+	"	#endif",
+	"#endif",
+	"#ifdef BCS",
+	"	sprintf(carg, \"-DBCS=%%d \", BCS);",
+	"	strcat(ctd, carg);",
+	"#endif",
+	"#ifdef BFS",
+	"	strcat(ctd, \"-DBFS \");",
+	"#endif",
 	"#ifdef MEMLIM",
 	"	sprintf(carg, \"-DMEMLIM=%%d \", MEMLIM);",
 	"	strcat(ctd, carg);",
@@ -867,21 +1464,9 @@
 	"#ifdef VAR_RANGES",
 	"	strcat(ctd, \"-DVAR_RANGES \");",
 	"#endif",
-	"#ifdef HC0",
-	"	strcat(ctd, \"-DHC0 \");",
+	"#ifdef HC",
+	"	strcat(ctd, \"-DHC \");",
 	"#endif",
-	"#ifdef HC1",
-	"	strcat(ctd, \"-DHC1 \");",
-	"#endif",
-	"#ifdef HC2",
-	"	strcat(ctd, \"-DHC2 \");",
-	"#endif",
-	"#ifdef HC3",
-	"	strcat(ctd, \"-DHC3 \");",
-	"#endif",
-	"#ifdef HC4",
-	"	strcat(ctd, \"-DHC4 \");",
-	"#endif",
 	"#ifdef CHECK",
 	"	strcat(ctd, \"-DCHECK \");",
 	"#endif",
@@ -888,6 +1473,9 @@
 	"#ifdef CTL",
 	"	strcat(ctd, \"-DCTL \");",
 	"#endif",
+	"#ifdef TRIX",
+	"	strcat(ctd, \"-DTRIX \");",
+	"#endif",
 	"#ifdef NIBIS",
 	"	strcat(ctd, \"-DNIBIS \");",
 	"#endif",
@@ -903,9 +1491,6 @@
 	"#ifdef PRINTF",
 	"	strcat(ctd, \"-DPRINTF \");",
 	"#endif",
-	"#ifdef OTIM",
-	"	strcat(ctd, \"-DOTIM \");",
-	"#endif",
 	"#ifdef COLLAPSE",
 	"	strcat(ctd, \"-DCOLLAPSE \");",
 	"#endif",
@@ -916,7 +1501,7 @@
 	"#ifdef SVDUMP",
 	"	strcat(ctd, \"-DSVDUMP \");",
 	"#endif",
-	"#ifdef VECTORSZ",
+	"#if defined(VECTORSZ) && !defined(TRIX)",
 	"	if (VECTORSZ != 1024)",
 	"	{	sprintf(carg, \"-DVECTORSZ=%%d \", VECTORSZ);",
 	"		strcat(ctd, carg);",
@@ -931,8 +1516,31 @@
 	"#ifdef SDUMP",
 	"	strcat(ctd, \"-DSDUMP \");",
 	"#endif",
-	"#ifdef COVEST",
-	"	strcat(ctd, \"-DCOVEST \");",
+	"#if NCORE>1",
+	"	sprintf(carg, \"-DNCORE=%%d \", NCORE);",
+	"	strcat(ctd, carg);",
+	"#endif",
+	"#ifdef VMAX",
+	"	if (VMAX != 256)",
+	"	{	sprintf(carg, \"-DVMAX=%%d \", VMAX);",
+	"		strcat(ctd, carg);",
+	"	}",
+	"#endif",
+	"#ifdef PMAX",
+	"	if (PMAX != 16)",
+	"	{	sprintf(carg, \"-DPMAX=%%d \", PMAX);",
+	"		strcat(ctd, carg);",
+	"	}",
+	"#endif",
+	"#ifdef QMAX",
+	"	if (QMAX != 16)",
+	"	{	sprintf(carg, \"-DQMAX=%%d \", QMAX);",
+	"		strcat(ctd, carg);",
+	"	}",
+	"#endif",
+	"#ifdef SET_WQ_SIZE",
+	"	sprintf(carg, \"-DSET_WQ_SIZE=%%d \", SET_WQ_SIZE);",
+	"	strcat(ctd, carg);",
 	"#endif",
 	"	printf(\"Compiled as: cc -o pan %%span.c\\n\", ctd);",
 	"}",
--- a/sys/src/cmd/spin/pangen4.c
+++ b/sys/src/cmd/spin/pangen4.c
@@ -1,13 +1,10 @@
 /***** spin: pangen4.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include "y.tab.h"
@@ -17,7 +14,7 @@
 extern Symbol	*Fname;
 extern int	lineno, m_loss, Pid, eventmapnr, multi_oval;
 extern short	nocast, has_provided, has_sorted;
-extern char	*R13[], *R14[], *R15[];
+extern const char *R13[], *R14[], *R15[];
 
 static void	check_proc(Lextok *, int);
 
@@ -44,7 +41,7 @@
 	case FULL:	case EMPTY:	case 'R':
 	case NFULL:	case NEMPTY:	case ENABLED:
 	case '?':	case PC_VAL:	case '^':
-	case C_EXPR:
+	case C_EXPR:	case GET_P:
 	case NONPROGRESS:
 		putstmnt(tb, now, m);
 		break;
@@ -153,7 +150,14 @@
 		fprintf(tb, "p_restor(II);\n\t\t");
 		break;
 
+	case SET_P:
+		fprintf(tb, "((P0 *)pptr((trpt->o_priority >> 8)))");
+		fprintf(tb, "->_priority = trpt->o_priority & 255");
+		break;
+
 	case ASGN:
+		if (check_track(now) == STRUCT) { break; }
+
 		nocast=1; putstmnt(tb,now->lft,m);
 		nocast=0; fprintf(tb, " = trpt->bup.oval");
 		if (multi_oval > 0)
@@ -307,6 +311,8 @@
 	ntimes(tc, 0, 1, R15);
 }
 
+extern void explain(int);
+
 int
 proper_enabler(Lextok *n)
 {
@@ -317,15 +323,19 @@
 	case LEN:	case 'R':
 	case NAME:
 		has_provided = 1;
-		if (strcmp(n->sym->name, "_pid") == 0)
+		if (strcmp(n->sym->name, "_pid") == 0
+		||  strcmp(n->sym->name, "_priority") == 0)
 			return 1;
 		return (!(n->sym->context));
 
-	case CONST:	case TIMEOUT:
+	case C_EXPR:
+	case CONST:
+	case TIMEOUT:
 		has_provided = 1;
 		return 1;
 
 	case ENABLED:	case PC_VAL:
+	case GET_P:	/* not SET_P */
 		return proper_enabler(n->lft);
 
 	case '!': case UMIN: case '~':
@@ -335,10 +345,14 @@
 	case '%': case LT:  case GT: case '&': case '^':
 	case '|': case LE:  case GE:  case NE: case '?':
 	case EQ:  case OR:  case AND: case LSHIFT:
-	case RSHIFT: case 'c':
+	case RSHIFT: case 'c': /* case ',': */
 		return proper_enabler(n->lft) && proper_enabler(n->rgt);
+
 	default:
 		break;
 	}
+	printf("spin: saw ");
+	explain(n->ntyp);
+	printf("\n");
 	return 0;
 }
--- a/sys/src/cmd/spin/pangen4.h
+++ b/sys/src/cmd/spin/pangen4.h
@@ -1,24 +1,21 @@
 /***** spin: pangen4.h *****/
 
-/* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * The DFA code below was written by Anuj Puri and Gerard J. Holzmann in
+ * May 1997, and was inspired by earlier work on data compression using
+ * sharing tree data structures and graph-encoded sets by J-Ch. Gregoire
+ * (INRS Telecom, Quebec, Canada) and D.Zampunieris (Univ.Namur, Belgium)
+ * The splay routine code included here is based on the public domain
+ * version written by D. Sleator <sleator@cs.cmu.edu> in 1992.
+ */
 
-/* The DFA code below was written by Anuj Puri and Gerard J. Holzmann in  */
-/* May 1997, and was inspired by earlier work on data compression using   */
-/* sharing tree data structures and graph-encoded sets by J-Ch. Gregoire  */
-/* (INRS Telecom, Quebec, Canada) and D.Zampunieris (Univ.Namur, Belgium) */
-
-/* The splay routine code included here is based on the public domain     */
-/* version written by D. Sleator <sleator@cs.cmu.edu> in 1992.            */
-
-static char *Dfa[] = {
+static const char *Dfa[] = {
 	"#ifdef MA",
+#if 0
 	"/*",
 	"#include <stdio.h>",
 	"#define uchar	unsigned char",
@@ -26,6 +23,7 @@
 	"#define ulong	unsigned long",
 	"#define ushort	unsigned short",
 	"",
+#endif
 	"#define TWIDTH		256",
 	"#define HASH(y,n)	(n)*(((long)y))",
 	"#define INRANGE(e,h)	((h>=e->From && h<=e->To)||(e->s==1 && e->S==h))",
@@ -466,7 +464,7 @@
 	"	for (j = 0; j < TWIDTH; j++)",
 	"	for (i = 0; i < dfa_depth+1; i++)",
 	"		cnt += tree_stats(layers[i*TWIDTH+j]);",
-	"	printf(\"Minimized Automaton:\t%%6d nodes and %%6g edges\\n\",",
+	"	printf(\"Minimized Automaton:\t%%6lu nodes and %%6g edges\\n\",",
 	"		nr_states, cnt);",
 	"}",
 	"",
--- a/sys/src/cmd/spin/pangen5.c
+++ b/sys/src/cmd/spin/pangen5.c
@@ -1,13 +1,10 @@
 /***** spin: pangen5.c *****/
 
-/* Copyright (c) 1999-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include "y.tab.h"
@@ -140,6 +137,7 @@
 	||  lt->ntyp == C_CODE
 	||  lt->ntyp == C_EXPR
 	||  has_lab(el, 0)		/* any label at all */
+	||  lt->ntyp == SET_P		/* to prevent multiple set_p merges */
 
 	||  lt->ntyp == DO
 	||  lt->ntyp == UNLESS
@@ -211,13 +209,18 @@
 static int
 build_step(FSM_trans *v)
 {	FSM_state *f;
-	Element	*el = v->step;
+	Element	*el;
 #if 0
 	Lextok	*lt = ZN;
 #endif
-	int	st  = v->to;
+	int	st;
 	int	r;
 
+	if (!v) return -1;
+
+	el = v->step;
+	st = v->to;
+
 	if (!el) return -1;
 
 	if (v->step->merge)
@@ -234,9 +237,7 @@
 	lt = v->step->n;
 	if (verbose&32)
 	{	if (++howdeep == 1)
-			printf("spin: %s, line %3d, merge:\n",
-				lt->fn->name,
-				lt->ln);
+			printf("spin: %s:%d, merge:\n", lt->fn->name, lt->ln);
 		printf("\t[%d] <seqno %d>\t", howdeep, el->seqno);
 		comment(stdout, lt, 0);
 		printf(";\n");
@@ -257,7 +258,7 @@
 }
 
 static void
-FSM_MERGER(char *pname_unused)	/* find candidates for safely merging steps */
+FSM_MERGER(/* char *pname */ void)	/* find candidates for safely merging steps */
 {	FSM_state *f, *g;
 	FSM_trans *t;
 	Lextok	*lt;
@@ -281,7 +282,7 @@
 			continue;
 
 		g = fsm_tbl[t->to];
-		if (!eligible(g->t))
+		if (!g || !eligible(g->t))
 		{
 #define SINGLES
 #ifdef SINGLES
@@ -288,7 +289,7 @@
 			t->step->merge_single = t->to;
 #if 0
 			if ((verbose&32))
-			{	printf("spin: %s, line %3d, merge_single:\n\t<seqno %d>\t",
+			{	printf("spin: %s:%d, merge_single:\n\t<seqno %d>\t",
 					t->step->n->fn->name,
 					t->step->n->ln,
 					t->step->seqno);
@@ -321,14 +322,17 @@
 		lt = t->step->n;
 #if 0
 	4.1.3:
-	an rv send operation inside an atomic, *loses* atomicity
-	when executed
-	and should therefore never be merged with a subsequent
+	an rv send operation ('s') inside an atomic, *loses* atomicity
+	when executed, and should therefore never be merged with a subsequent
 	statement within the atomic sequence
-	the same is not true for non-rv send operations
+	the same is not true for non-rv send operations;
+	6.2.2:
+	RUN statements can start a new process at a higher priority level
+	which interferes with statement merging, so it too is not a suitable
+	merge target
 #endif
 
-		if (lt->ntyp == 'c'	/* potentially blocking stmnts */
+		if ((lt->ntyp == 'c' && !any_oper(lt->lft, RUN)) /* 2nd clause 6.2.2 */
 		||  lt->ntyp == 'r'
 		||  (lt->ntyp == 's' && u_sync == 0))	/* added !u_sync in 4.1.3 */
 		{	if (!canfill_in(t))		/* atomic, non-global, etc. */
@@ -346,9 +350,8 @@
 #if 0
 			if ((verbose&32)
 			&& t->step->merge_start)
-			{	printf("spin: %s, line %3d, merge_START:\n\t<seqno %d>\t",
-						lt->fn->name,
-						lt->ln,
+			{	printf("spin: %s:%d, merge_START:\n\t<seqno %d>\t",
+						lt->fn->name, lt->ln,
 						t->step->seqno);
 				comment(stdout, lt, 0);
 				printf(";\n");
@@ -532,6 +535,7 @@
 	if (now->sym->name[0] == '_'
 	&&  (strcmp(now->sym->name, "_") == 0
 	||   strcmp(now->sym->name, "_pid") == 0
+	||   strcmp(now->sym->name, "_priority") == 0
 	||   strcmp(now->sym->name, "_last") == 0))
 		return;
 
@@ -588,10 +592,17 @@
 	case C_EXPR:
 		break;
 
+	case ',': /* reached with SET_P and array initializers */
+		if (now->lft && now->lft->rgt)
+		{	ana_stmnt(t, now->lft->rgt, RVAL);
+		}
+		break;
+
 	case '!':	
 	case UMIN:
 	case '~':
 	case ENABLED:
+	case GET_P:
 	case PC_VAL:
 	case LEN:
 	case FULL:
@@ -603,6 +614,11 @@
 		ana_stmnt(t, now->lft, RVAL);
 		break;
 
+	case SET_P:
+		ana_stmnt(t, now->lft, RVAL); /* ',' */
+		ana_stmnt(t, now->lft->rgt, RVAL);
+		break;
+
 	case '/':
 	case '*':
 	case '-':
@@ -626,8 +642,11 @@
 		break;
 
 	case ASGN:
+		if (check_track(now) == STRUCT) { break; }
+
 		ana_stmnt(t, now->lft, LVAL);
-		ana_stmnt(t, now->rgt, RVAL);
+		if (now->rgt->ntyp)
+			ana_stmnt(t, now->rgt, RVAL);
 		break;
 
 	case PRINT:
@@ -679,7 +698,8 @@
 		break;
 
 	default:
-		printf("spin: bad node type %d line %d (ana_stmnt)\n", now->ntyp, now->ln);
+		printf("spin: %s:%d, bad node type %d (ana_stmnt)\n",
+			now->fn->name, now->ln, now->ntyp);
 		fatal("aborting", (char *) 0);
 	}
 }
@@ -692,10 +712,7 @@
 	int counter = 1;
 #endif
 	for (p = rdy; p; p = p->nxt)
-	{	if (p->tn == eventmapnr
-		||  p->tn == claimnr)
-			continue;
-
+	{
 		ana_seq(p->s);
 		fsm_table();
 
@@ -711,7 +728,7 @@
 		{	FSM_ANA();
 		}
 		if (merger)
-		{	FSM_MERGER(p->n->name);
+		{	FSM_MERGER(/* p->n->name */);
 			huntele(e, e->status, -1)->merge_in = 1; /* start-state */
 #if 0
 			printf("\n");
@@ -726,8 +743,7 @@
 	{
 		if (!(e->status&DONE) && (verbose&32))
 		{	printf("unreachable code: ");
-			printf("%s, line %3d:  ",
-				e->n->fn->name, e->n->ln);
+			printf("%s:%3d  ", e->n->fn->name, e->n->ln);
 			comment(stdout, e->n, 0);
 			printf("\n");
 		}
@@ -735,7 +751,7 @@
 	}
 	if (export_ast)
 	{	AST_slice();
-		exit(0);
+		alldone(0);	/* changed in 5.3.0: was exit(0) */
 	}
 }
 
@@ -831,9 +847,15 @@
 		{	if (e->n->ntyp == GOTO)
 			{	g = get_lab(e->n, 1);
 				g = huntele(g, e->status, -1);
+				if (!g)
+				{	fatal("unexpected error 2", (char *) 0);
+				}
 				To = g->seqno;
 			} else if (e->nxt)
 			{	g = huntele(e->nxt, e->status, -1);
+				if (!g)
+				{	fatal("unexpected error 3", (char *) 0);
+				}
 				To = g->seqno;
 			} else
 				To = 0;
--- a/sys/src/cmd/spin/pangen5.h
+++ b/sys/src/cmd/spin/pangen5.h
@@ -1,15 +1,12 @@
 /***** spin: pangen5.h *****/
 
-/* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
-static char *Xpt[] = {
+static const char *Xpt[] = {
 	"#if defined(MA) && (defined(W_XPT) || defined(R_XPT))",
 	"static Vertex	**temptree;",
 	"static char	wbuf[4096];",
@@ -80,7 +77,7 @@
 	"	int i, j;  uchar c;",
 	"	static uchar xwarned = 0;",
 	"",
-	"	sprintf(nm, \"%%s.xpt\", Source);",
+	"	sprintf(nm, \"%%s.xpt\", PanSource);",
 	"	if ((fd = creat(nm, 0666)) <= 0)",
 	"	if (!xwarned)",
 	"	{	xwarned = 1;",
@@ -136,7 +133,7 @@
 	"	stacker[dfa_depth-1] = 0; r = dfa_store(stacker);",
 	"	stacker[dfa_depth-1] = 4; j = dfa_member(dfa_depth-1);",
 	"	if (r != 1 || j != 0)",
-	"	{	printf(\"%%d: \", stackcnt);",
+	"	{	printf(\"%%lu: \", stackcnt);",
 	"		for (i = 0; i < dfa_depth; i++)",
 	"			printf(\"%%d,\", stacker[i]);",
 	"		printf(\" -- not a stackstate <o:%%d,4:%%d>\\n\", r, j);",
@@ -372,7 +369,7 @@
 	"	int i, j;",
 	"",
 	"	wcnt = 0;",
-	"	sprintf(nm, \"%%s.xpt\", Source);",
+	"	sprintf(nm, \"%%s.xpt\", PanSource);",
 	"	if ((fd = open(nm, 0)) < 0)	/* O_RDONLY */",
 	"		Uerror(\"cannot open checkpoint file\");",
 	"",
@@ -416,7 +413,7 @@
 	"	x_cleanup(d);",
 	"	close(fd);",
 	"",
-	"	printf(\"pan: removed %%d stackstates\\n\", stackcnt);",
+	"	printf(\"pan: removed %%lu stackstates\\n\", stackcnt);",
 	"	nstates -= (double) stackcnt;",
 	"}",
 	"#endif",
--- a/sys/src/cmd/spin/pangen6.c
+++ b/sys/src/cmd/spin/pangen6.c
@@ -1,21 +1,11 @@
 /***** spin: pangen6.c *****/
 
-/* Copyright (c) 2000-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
-/* Abstract syntax tree analysis / slicing (spin option -A) */
-/* AST_store stores the fsms's for each proctype            */
-/* AST_track keeps track of variables used in properties    */
-/* AST_slice starts the slicing algorithm                   */
-/*      it first collects more info and then calls          */
-/*      AST_criteria to process the slice criteria          */
-
 #include "spin.h"
 #include "y.tab.h"
 
@@ -90,7 +80,6 @@
 static Slicer	*rel_vars;	/* all relevant variables */
 static int	AST_Changes;
 static int	AST_Round;
-static FSM_state no_state;
 static RPN	*rpn;
 static int	in_recv = 0;
 
@@ -145,7 +134,7 @@
 {
 	if (!n || !n->sym) return;
 
-	if (n->sym->nel != 1)
+	if (n->sym->nel > 1 || n->sym->isarray)
 		def_use(n->lft, code);		/* process the index */
 
 	if (n->sym->type == STRUCT		/* and possible deeper ones */
@@ -202,6 +191,8 @@
 	case '~':
 	case 'c':
 	case ENABLED:
+	case SET_P:
+	case GET_P:
 	case ASSERT:
 	case EVAL:
 		def_use(now->lft, USE|code);
@@ -503,7 +494,7 @@
 	if (strcmp(as->name, bs->name) != 0)
 		return 0;
 
-	if (as->type == STRUCT && a->rgt && b->rgt)
+	if (as->type == STRUCT && a->rgt && b->rgt)	/* we know that a and b are not null */
 		return AST_mutual(a->rgt->lft, b->rgt->lft, 0);
 
 	return 1;
@@ -545,14 +536,14 @@
 			case 'r':
 				/* guess sends where name may originate */
 				for (cl = chanlist; cl; cl = cl->nxt)	/* all sends */
-				{	int a = AST_nrpar(cl->s);
-					int b = AST_nrpar(t->step->n);
-					if (a != b)	/* matching nrs of params */
+				{	int aa = AST_nrpar(cl->s);
+					int bb = AST_nrpar(t->step->n);
+					if (aa != bb)	/* matching nrs of params */
 						continue;
 
-					a = AST_ord(cl->s, cl->n);
-					b = AST_ord(t->step->n, u->n);
-					if (a != b)	/* same position in parlist */
+					aa = AST_ord(cl->s, cl->n);
+					bb = AST_ord(t->step->n, u->n);
+					if (aa != bb)	/* same position in parlist */
 						continue;
 
 					AST_add_alias(cl->n, 4); /* RCV assume possible match */
@@ -692,9 +683,7 @@
 	}
 
 	for (a = ast; a; a = a->nxt)		/* all other stmnts */
-	{	if (strcmp(a->p->n->name, ":never:") != 0
-		&&  strcmp(a->p->n->name, ":trace:") != 0
-		&&  strcmp(a->p->n->name, ":notrace:") != 0)
+	{	if (a->p->b != N_CLAIM && a->p->b != E_TRACE && a->p->b != N_TRACE)
 		for (f = a->fsm; f; f = f->nxt)
 		for (t = f->t; t; t = t->nxt)
 		{	if (!(t->relevant&1))
@@ -786,10 +775,8 @@
 	 */
 
 	for (a = ast; a; a = a->nxt)
-	{	if (strcmp(a->p->n->name, ":never:") == 0
-		||  strcmp(a->p->n->name, ":trace:") == 0
-		||  strcmp(a->p->n->name, ":notrace:") == 0
-		||  strcmp(a->p->n->name, ":init:") == 0)
+	{	if (a->p->b == N_CLAIM || a->p->b == I_PROC
+		||  a->p->b == E_TRACE || a->p->b == N_TRACE)
 		{	a->relevant |= 1;	/* the proctype is relevant */
 			continue;
 		}
@@ -823,9 +810,9 @@
 		printf("spin: redundant in proctype %s (for given property):\n",
 			a->p->n->name);
 	}
-	printf("      line %3d %s (state %d)",
-		e->n?e->n->ln:-1,
+	printf("      %s:%d (state %d)",
 		e->n?e->n->fn->name:"-",
+		e->n?e->n->ln:-1,
 		e->seqno);
 	printf("	[");
 	comment(stdout, e->n, 0);
@@ -1016,7 +1003,8 @@
 	printf(" -- %d\n", code);
 #endif
 	if (in_recv && (code&DEF) && (code&USE))
-	{	printf("spin: error: DEF and USE of same var in rcv stmnt: ");
+	{	printf("spin: %s:%d, error: DEF and USE of same var in rcv stmnt: ",
+			n->fn->name, n->ln);
 		AST_var(n, n->sym, 1);
 		printf(" -- %d\n", code);
 		nr_errs++;
@@ -1065,6 +1053,8 @@
 	case '~':
 	case 'c':
 	case ENABLED:
+	case SET_P:
+	case GET_P:
 	case ASSERT:
 		AST_track(now->lft, USE|code);
 		break;
@@ -1075,8 +1065,8 @@
 
 	case NAME:
 		name_AST_track(now, code);
-		if (now->sym->nel != 1)
-			AST_track(now->lft, USE|code);	/* index */
+		if (now->sym->nel > 1 || now->sym->isarray)
+			AST_track(now->lft, USE);	/* index, was USE|code */
 		break;
 
 	case 'R':
@@ -1569,7 +1559,8 @@
 			{	t->relevant &= ~2;	/* clear mark */
 				if (verbose&32)
 				{	printf("\t\tnomark ");
-					comment(stdout, t->step->n, 0);
+					if (t->step && t->step->n)
+						comment(stdout, t->step->n, 0);
 					printf("\n");
 	}		}	}
 
@@ -1601,7 +1592,8 @@
 			t->relevant |= 2;	/* lift */
 			if (verbose&32)
 			{	printf("\t\t\tliftmark ");
-				comment(stdout, t->step->n, 0);
+				if (t->step && t->step->n)
+					comment(stdout, t->step->n, 0);
 				printf("\n");
 			}
 			AST_spread(a, t->to);	/* and spread to all guards */
@@ -1621,10 +1613,9 @@
 {	AST *a;
 
 	for (a = ast; a; a = a->nxt)
-		if (strcmp(a->p->n->name, ":never:") != 0
-		&&  strcmp(a->p->n->name, ":trace:") != 0
-		&&  strcmp(a->p->n->name, ":notrace:") != 0)
-			AST_ctrl(a);
+	{	if (a->p->b != N_CLAIM && a->p->b != E_TRACE && a->p->b != N_TRACE)
+		{	AST_ctrl(a);
+	}	}
 }
 
 static void
@@ -1634,9 +1625,7 @@
 	FSM_trans *t;
 
 	for (a = ast; a; a = a->nxt)
-	{	if (strcmp(a->p->n->name, ":never:") != 0
-		&&  strcmp(a->p->n->name, ":trace:") != 0
-		&&  strcmp(a->p->n->name, ":notrace:") != 0)
+	{	if (a->p->b != N_CLAIM && a->p->b != E_TRACE && a->p->b != N_TRACE)
 		for (f = a->fsm; f; f = f->nxt)
 		for (t = f->t; t; t = t->nxt)
 		{	if (t->step
@@ -1692,8 +1681,7 @@
 	int spurious = 0;
 
 	if (!slicer)
-	{	non_fatal("no slice criteria (or no claim) specified",
-		(char *) 0);
+	{	printf("spin: warning: no slice criteria found (no assertions and no claim)\n");
 		spurious = 1;
 	}
 	AST_dorelevant();		/* mark procs refered to in remote refs */
@@ -1730,9 +1718,7 @@
 AST_store(ProcList *p, int start_state)
 {	AST *n_ast;
 
-	if (strcmp(p->n->name, ":never:") != 0
-	&&  strcmp(p->n->name, ":trace:") != 0
-	&&  strcmp(p->n->name, ":notrace:") != 0)
+	if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
 	{	n_ast = (AST *) emalloc(sizeof(AST));
 		n_ast->p = p;
 		n_ast->i_st = start_state;
@@ -1809,12 +1795,10 @@
 	int cnt;
 
 	for (a = ast; a; a = a->nxt)
-	{	if (strcmp(a->p->n->name, ":never:") == 0
-		||  strcmp(a->p->n->name, ":trace:") == 0
-		||  strcmp(a->p->n->name, ":notrace:") == 0
-		||  strcmp(a->p->n->name, ":init:") == 0)
-			continue;			/* have no params */
-
+	{	if (a->p->b == N_CLAIM || a->p->b == I_PROC
+		||  a->p->b == E_TRACE || a->p->b == N_TRACE)
+		{	continue;			/* has no params */
+		}
 		cnt = 0;
 		for (f = a->p->p; f; f = f->rgt)	/* types */
 		for (t = f->lft; t; t = t->rgt)		/* formals */
@@ -1845,9 +1829,8 @@
 	}	}
 
 	for (a = ast; a; a = a->nxt)
-	{	if (strcmp(a->p->n->name, ":never:") != 0
-		&&  strcmp(a->p->n->name, ":trace:") != 0
-		&&  strcmp(a->p->n->name, ":notrace:") != 0)	/* claim has no locals */
+	{	if (a->p->b != N_CLAIM
+		&&  a->p->b != E_TRACE && a->p->b != N_TRACE)	/* has no locals */
 		for (walk = all_names; walk; walk = walk->next)	
 		{	sp = walk->entry;
 			if (sp
@@ -1995,7 +1978,7 @@
 	h = fsm_tbl[out];
 
 	i = f->from / BPW;
-	j = f->from % BPW;
+	j = f->from % BPW; /* assert(j <= 32); else lshift undefined? */
 	g = h->mod;
 
 	if (verbose&32)
@@ -2023,28 +2006,30 @@
 		d. the dominator is reachable, and not equal to this node
 #endif
 		for (t = f->p, i = 0; t; t = t->nxt)
-			i += fsm_tbl[t->to]->seen;
-		if (i <= 1) continue;					/* a. */
-
+		{	i += fsm_tbl[t->to]->seen;
+		}
+		if (i <= 1)
+		{	continue;					/* a. */
+		}
 		for (cnt = 1; cnt < a->nstates; cnt++)	/* 0 is endstate */
 		{	if (cnt == f->from
 			||  !fsm_tbl[cnt]->seen)
-				continue;				/* c. */
-
+			{	continue;				/* c. */
+			}
 			i = cnt / BPW;
-			j = cnt % BPW;
+			j = cnt % BPW;	/* assert(j <= 32); */
 			if (!(f->dom[i]&(1<<j)))
-				continue;
-
+			{	continue;
+			}
 			for (t = fsm_tbl[cnt]->t, i = 0; t; t = t->nxt)
-				i += fsm_tbl[t->to]->seen;
+			{	i += fsm_tbl[t->to]->seen;
+			}
 			if (i <= 1)
-				continue;				/* b. */
-
+			{	continue;				/* b. */
+			}
 			if (f->mod)			/* final check in 2nd phase */
-				subgraph(a, f, cnt);	/* possible entry-exit pair */
-		}
-	}
+			{	subgraph(a, f, cnt);	/* possible entry-exit pair */
+	}	}	}
 }
 
 static void
@@ -2178,27 +2163,26 @@
 	for (f = a->fsm; f; f = f->nxt)
 	{	if (!f->seen) continue;
 
-		f->dom = (ulong *)
-			emalloc(a->nwords * sizeof(ulong));
+		f->dom = (ulong *) emalloc(a->nwords * sizeof(ulong));
 
 		if (f->from == a->i_st)
 		{	i = a->i_st / BPW;
-			j = a->i_st % BPW;
+			j = a->i_st % BPW; /* assert(j <= 32); */
 			f->dom[i] = (1<<j);			/* (1) */
 		} else						/* (2) */
 		{	for (i = 0; i < a->nwords; i++)
-				f->dom[i] = (ulong) ~0;			/* all 1's */
-
+			{	f->dom[i] = (ulong) ~0;		/* all 1's */
+			}
 			if (a->nstates % BPW)
 			for (i = (a->nstates % BPW); i < (int) BPW; i++)
-				f->dom[a->nwords-1] &= ~(1<<i);	/* clear tail */
-
+			{	f->dom[a->nwords-1] &= ~(1<< ((ulong) i)); /* clear tail */
+			}
 			for (cnt = 0; cnt < a->nstates; cnt++)
-				if (!fsm_tbl[cnt]->seen)
+			{	if (!fsm_tbl[cnt]->seen)
 				{	i = cnt / BPW;
-					j = cnt % BPW;
-					f->dom[i] &= ~(1<<j);
-	}	}		}
+					j = cnt % BPW; /* assert(j <= 32); */
+					f->dom[i] &= ~(1<< ((ulong) j));
+	}	}	}	}
 }
 
 static int
@@ -2226,7 +2210,7 @@
 	}
 
 	i = f->from / BPW;
-	j = f->from % BPW;
+	j = f->from % BPW;	/* assert(j <= 32); */
 	ndom[i] |= (1<<j);			/* (5a) */
 
 	for (i = 0; i < a->nwords; i++)
@@ -2261,6 +2245,7 @@
 	FSM_trans *t;
 	AST *a;
 	int oi;
+	static FSM_state no_state;
 #if 0
 	find dominators
 	Aho, Sethi, & Ullman, Compilers - principles, techniques, and tools
--- /dev/null
+++ b/sys/src/cmd/spin/pangen6.h
@@ -1,0 +1,2878 @@
+/***** spin: pangen6.h *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+static const char *Code2e[] = {
+	"#if (NCORE>1 || defined(BFS_PAR)) && !defined(WIN32) && !defined(WIN64)",
+	"	/* Test and Set assembly code */",
+	"	#if defined(i386) || defined(__i386__) || defined(__x86_64__)",
+	"		int",
+	"		tas(volatile int *s)	/* tested */",
+	"		{	int r;",
+	"			__asm__ __volatile__(",
+	"				\"xchgl %%0, %%1 \\n\\t\"",
+	"		       		: \"=r\"(r), \"=m\"(*s)",
+	"				: \"0\"(1), \"m\"(*s)",
+	"				: \"memory\");",
+	"		",
+	"			return r;",
+	"		}",
+	"	#elif defined(__arm__)",
+	"		int",
+	"		tas(volatile int *s)	/* not tested */",
+	"		{	int r = 1;",
+	"			__asm__ __volatile__(",
+	"				\"swpb %%0, %%0, [%%3] \\n\"",
+	"				: \"=r\"(r), \"=m\"(*s)",
+	"				: \"0\"(r), \"r\"(s));",
+	"",
+	"			return r;",
+	"		}",
+	"	#elif defined(sparc) || defined(__sparc__)",
+	"		int",
+	"		tas(volatile int *s)	/* not tested */",
+	"		{	int r = 1;",
+	"			__asm__ __volatile__(",
+	"				\" ldstub [%%2], %%0 \\n\"",
+	"				: \"=r\"(r), \"=m\"(*s)",
+	"				: \"r\"(s));",
+	"",
+	"			return r;",
+	"		}",
+	"	#elif defined(ia64) || defined(__ia64__)",
+	"		/* Intel Itanium */",
+	"		int",
+	"		tas(volatile int *s)	/* tested */",
+	"		{	long int r;",
+	"			__asm__ __volatile__(",
+	"				\"	xchg4 	%%0=%%1,%%2	\\n\"",
+	"		:		\"=r\"(r), \"+m\"(*s)",
+	"		:		\"r\"(1)",
+	"		:		\"memory\");",
+	"			return (int) r;",
+	"		}",
+	"	#elif defined(__powerpc64__)",
+	"		int",
+	"		tas(volatile int *s)	/* courtesy srirajpaul */",
+	"		{	int r;",
+	" #if 1",
+	"			r = __sync_lock_test_and_set();",
+	" #else",
+	"			/* xlc compiler only */",
+	"			r = __fetch_and_or(s, 1);",
+	"			__isync();",
+	" #endif",
+	"			return r;",
+	"		}",
+	"	#else",
+	"		#error missing definition of test and set operation for this platform",
+	"	#endif",
+	"",
+	"	#ifndef NO_CAS", /* linux, windows */
+	"		#define cas(a,b,c) __sync_bool_compare_and_swap(a,b,c)",
+	"	#else",
+	"	int", /* workaround if the above is not available */
+	"	cas(volatile uint32_t *a, uint32_t b, uint32_t c)",
+	"	{	static volatile int cas_lock;",
+	"		while (tas(&cas_lock) != 0) { ; }",
+	"		if (*a == b)",
+	"		{	*a = c;",
+	"			cas_lock = 0;",
+	"			return 1;",
+	"		}",
+	"		cas_lock = 0;",
+	"		return 0;",
+	"	}",
+	"	#endif",
+	"#endif",
+	0,
+};
+
+static const char *Code2c[] = { /* multi-core option - Spin 5.0 and later */
+	"#if NCORE>1",
+	"#if defined(WIN32) || defined(WIN64)",
+	"	#ifndef _CONSOLE",
+	"		#define _CONSOLE",
+	"	#endif",
+	"	#ifdef WIN64",
+	"		#undef long",
+	"	#endif",
+	"	#include <windows.h>",
+	"/*",
+	"	#ifdef WIN64",
+	"		#define long	long long",
+	"	#endif",
+	"*/",
+	"#else",
+	"	#include <sys/ipc.h>",
+	"	#include <sys/sem.h>",
+	"	#include <sys/shm.h>",
+	"#endif",
+	"",
+	"/* code common to cygwin/linux and win32/win64: */",
+	"",
+	"#ifdef VERBOSE",
+	"	#define VVERBOSE	(1)",
+	"#else",
+	"	#define VVERBOSE	(0)",
+	"#endif",
+	"",
+	"/* the following values must be larger than 256 and must fit in an int */",
+	"#define QUIT		1024	/* terminate now command */",
+	"#define QUERY		 512	/* termination status query message */",
+	"#define QUERY_F	 513	/* query failed, cannot quit */",
+	"",
+	"#define GN_FRAMES	(int) (GWQ_SIZE / (double) sizeof(SM_frame))",
+	"#define LN_FRAMES	(int) (LWQ_SIZE / (double) sizeof(SM_frame))",
+	"",
+	"#ifndef VMAX",
+	"	#define VMAX	VECTORSZ",
+	"#endif",
+	"#ifndef PMAX",
+	"	#define PMAX	64",
+	"#endif",
+	"#ifndef QMAX",
+	"	#define QMAX	64",
+	"#endif",
+	"",
+	"#if VECTORSZ>32000",
+	"	#define OFFT	int",
+	"#else",
+	"	#define OFFT	short",
+	"#endif",
+	"",
+	"#ifdef SET_SEG_SIZE",
+	"	/* no longer useful -- being recomputed for local heap size anyway */",
+	"	double SEG_SIZE = (((double) SET_SEG_SIZE) * 1048576.);",
+	"#else",
+	"	double SEG_SIZE = (1048576.*1024.);	/* 1GB default shared memory pool segments */",
+	"#endif",
+	"",
+	"double LWQ_SIZE = 0.; /* initialized in main */",
+	"",
+	"#ifdef SET_WQ_SIZE",
+	"	#ifdef NGQ",
+	"	#warning SET_WQ_SIZE applies to global queue -- ignored",
+	"	double GWQ_SIZE = 0.;",
+	"	#else",
+	"	double GWQ_SIZE = (((double) SET_WQ_SIZE) * 1048576.);",
+	"	/* must match the value in pan_proxy.c, if used */",
+	"	#endif",
+	"#else",
+	"	#ifdef NGQ",
+	"	double GWQ_SIZE = 0.;",
+	"	#else",
+	"	double GWQ_SIZE = (128.*1048576.);	/* 128 MB default queue sizes */",
+	"	#endif",
+	"#endif",
+	"",
+	"/* Crash Detection Parameters */",
+	"#ifndef ONESECOND",
+	"	#define ONESECOND	(1<<25)", /* name is somewhat of a misnomer */
+	"#endif",
+	"#ifndef SHORT_T",
+	"	#define SHORT_T	(0.1)",
+	"#endif",
+	"#ifndef LONG_T",
+	"	#define LONG_T	(600)",
+	"#endif",
+	"",
+	"double OneSecond   = (double) (ONESECOND); /* waiting for a free slot -- checks crash */",
+	"double TenSeconds  = 10. * (ONESECOND);    /* waiting for a lock -- check for a crash */",
+	"",
+	"/* Termination Detection Params -- waiting for new state input in Get_Full_Frame */",
+	"double Delay       = ((double) SHORT_T) * (ONESECOND);	/* termination detection trigger */",
+	"double OneHour     = ((double) LONG_T) * (ONESECOND);	/* timeout termination detection */",
+	"",
+	"typedef struct SM_frame     SM_frame;",
+	"typedef struct SM_results   SM_results;",
+	"typedef struct sh_Allocater sh_Allocater;",
+	"",
+	"struct SM_frame {			/* about 6K per slot */",
+	"	volatile int	m_vsize;	/* 0 means free slot */",
+	"	volatile int	m_boq;		/* >500 is a control message */",
+	"#ifdef FULL_TRAIL",
+	"	volatile struct Stack_Tree *m_stack;	/* ptr to previous state */",
+	"#endif",
+	"	volatile uchar	m_tau;",
+	"	volatile uchar	m_o_pm;",
+	"	volatile int	nr_handoffs;	/* to compute real_depth */",
+	"	volatile char	m_now     [VMAX];",
+	"#if !defined(NOCOMP) && !defined(HC)",
+	"	volatile char	m_mask    [(VMAX + 7)/8];",
+	"#endif",
+	"	volatile OFFT	m_p_offset[PMAX];",
+	"	volatile OFFT	m_q_offset[QMAX];",
+	"	volatile uchar	m_p_skip  [PMAX];",
+	"	volatile uchar	m_q_skip  [QMAX];",
+	"#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)",
+	"	volatile uchar	m_c_stack [StackSize];",
+		 /* captures contents of c_stack[] for unmatched objects */
+	"#endif",
+	"};",
+	"",
+	"int	proxy_pid;		/* id of proxy if nonzero -- receive half */",
+	"int	store_proxy_pid;",
+	"short	remote_party;",
+	"int	proxy_pid_snd;		/* id of proxy if nonzero -- send half */",
+	"char	o_cmdline[512];		/* to pass options to children */",
+	"",
+	"int	iamin[CS_NR+NCORE];		/* non-shared */",
+	"",
+"#if defined(WIN32) || defined(WIN64)",
+	"int tas(volatile LONG *);",
+	"",
+	"HANDLE		proxy_handle_snd;	/* for Windows Create and Terminate */",
+	"",
+	"struct sh_Allocater {			/* shared memory for states */",
+	"	volatile char	*dc_arena;	/* to allocate states from */",
+	"	volatile long	 pattern;	/* to detect overruns */",
+	"	volatile long	 dc_size;	/* nr of bytes left */",
+	"	volatile void	*dc_start;	/* where memory segment starts */",
+	"	volatile void	*dc_id;		/* to attach, detach, remove shared memory segments */",
+	"	volatile sh_Allocater *nxt;	/* linked list of pools */",
+	"};",
+	"DWORD		worker_pids[NCORE];	/* root mem of pids of all workers created */",
+	"HANDLE		worker_handles[NCORE];	/* for windows Create and Terminate */",
+	"void *		shmid      [NR_QS];	/* return value from CreateFileMapping */",
+	"void *		shmid_M;		/* shared mem for state allocation in hashtable */",
+	"",
+	"#ifdef SEP_STATE",
+	"	void *shmid_X;",
+	"#else",
+	"	void *shmid_S;			/* shared bitstate arena or hashtable */",
+	"#endif",
+"#else",
+	"int tas(volatile int *);",
+	"",
+	"struct sh_Allocater {			/* shared memory for states */",
+	"	volatile char	*dc_arena;	/* to allocate states from */",
+	"	volatile long	 pattern;	/* to detect overruns */",
+	"	volatile long	 dc_size;	/* nr of bytes left */",
+	"	volatile char	*dc_start;	/* where memory segment starts */",
+	"	volatile int	dc_id;		/* to attach, detach, remove shared memory segments */",
+	"	volatile sh_Allocater *nxt;	/* linked list of pools */",
+	"};",
+	"",
+	"int	worker_pids[NCORE];	/* root mem of pids of all workers created */",
+	"int	shmid      [NR_QS];	/* return value from shmget */",
+	"int	nibis = 0;		/* set after shared mem has been released */",
+	"int	shmid_M;		/* shared mem for state allocation in hashtable */",
+	"#ifdef SEP_STATE",
+	"	long	shmid_X;",
+	"#else",
+	"	int	shmid_S;	/* shared bitstate arena or hashtable */",
+	"	volatile sh_Allocater	*first_pool;	/* of shared state memory */",
+	"	volatile sh_Allocater	*last_pool;",
+	"#endif", /* SEP_STATE */
+"#endif", /* WIN32 || WIN64 */
+	"",
+	"struct SM_results {			/* for shuttling back final stats */",
+	"	volatile int	m_vsize;	/* avoid conflicts with frames */",
+	"	volatile int	m_boq;		/* these 2 fields are not written in record_info */",
+	"	/* probably not all fields really need to be volatile */",
+	"	volatile double	m_memcnt;",
+	"	volatile double	m_nstates;",
+	"	volatile double	m_truncs;",
+	"	volatile double	m_truncs2;",
+	"	volatile double	m_nShadow;",
+	"	volatile double	m_nlinks;",
+	"	volatile double	m_ngrabs;",
+	"	volatile double	m_nlost;",
+	"	volatile double	m_hcmp;",
+	"	volatile double	m_frame_wait;",
+	"	volatile int	m_hmax;",
+	"	volatile int	m_svmax;",
+	"	volatile int	m_smax;",
+	"	volatile int	m_mreached;",
+	"	volatile int	m_errors;",
+	"	volatile int	m_VMAX;",
+	"	volatile short	m_PMAX;",
+	"	volatile short	m_QMAX;",
+	"	volatile uchar	m_R;		/* reached info for all proctypes */",
+	"};",
+	"",
+	"int		core_id = 0;		/* internal process nr, to know which q to use */",
+	"unsigned long	nstates_put = 0;	/* statistics */",
+	"unsigned long	nstates_get = 0;",
+	"int		query_in_progress = 0;	/* termination detection */",
+	"",
+	"double		free_wait  = 0.;	/* waiting for a free frame */",
+	"double		frame_wait = 0.;	/* waiting for a full frame */",
+	"double		lock_wait  = 0.;	/* waiting for access to cs */",
+	"double		glock_wait[3];	/* waiting for access to global lock */",
+	"",
+	"char		*sprefix = \"rst\";",
+	"uchar		was_interrupted, issued_kill, writing_trail;",
+	"",
+	"static SM_frame cur_Root;		/* current root, to be safe with error trails */",
+	"",
+	"SM_frame	*m_workq   [NR_QS];	/* per cpu work queues + global q */",
+	"char		*shared_mem[NR_QS];	/* return value from shmat */",
+	"#ifdef SEP_HEAP",
+	"char		*my_heap;",
+	"long		 my_size;",
+	"#endif",
+	"volatile sh_Allocater	*dc_shared;	/* assigned at initialization */",
+	"",
+	"static int	vmax_seen, pmax_seen, qmax_seen;",
+	"static double	gq_tries, gq_hasroom, gq_hasnoroom;",
+	"",
+	"volatile int *prfree;",	/* [NCORE] */
+	"volatile int *prfull;",	/* [NCORE] */
+	"volatile int *prcnt;",		/* [NCORE] */
+	"volatile int *prmax;",		/* [NCORE] */
+	"",
+	"volatile int	*sh_lock;	/* mutual exclusion locks - in shared memory */",
+	"volatile double *is_alive;	/* to detect when processes crash */",
+	"volatile int    *grfree, *grfull, *grcnt, *grmax;	/* access to shared global q */",
+	"volatile double *gr_readmiss, *gr_writemiss;",
+	"static   int	lrfree;		/* used for temporary recording of slot */",
+	"static   int dfs_phase2;",
+	"",
+	"void mem_put(int);		/* handoff state to other cpu */",
+	"void mem_put_acc(void);	/* liveness mode */",
+	"void mem_get(void);		/* get state from work queue  */",
+	"void sudden_stop(char *);",
+	"",
+	"void",
+	"record_info(SM_results *r)",
+	"{	int i;",
+	"	uchar *ptr;",
+	"",
+	"#ifdef SEP_STATE",
+	"	if (0)",
+	"	{	cpu_printf(\"nstates %%g nshadow %%g -- memory %%-6.3f Mb\\n\",",
+	"			nstates, nShadow, memcnt/(1048576.));",
+	"	}",
+	"	r->m_memcnt = 0;",
+	"#else",
+	"	#ifdef BITSTATE",
+		"	r->m_memcnt = 0; /* it's shared */",
+	"	#endif",
+	"	r->m_memcnt = memcnt;",
+	"#endif",
+	"	if (a_cycles && core_id == 1)",
+	"	{	r->m_nstates  = nstates;",
+	"		r->m_nShadow  = nstates;",
+	"	} else",
+	"	{	r->m_nstates  = nstates;",
+	"		r->m_nShadow  = nShadow;",
+	"	}",
+	"	r->m_truncs   = truncs;",
+	"	r->m_truncs2  = truncs2;",
+	"	r->m_nlinks   = nlinks;",
+	"	r->m_ngrabs   = ngrabs;",
+	"	r->m_nlost    = nlost;",
+	"	r->m_hcmp     = hcmp;",
+	"	r->m_frame_wait = frame_wait;",
+	"	r->m_hmax     = hmax;",
+	"	r->m_svmax    = svmax;",
+	"	r->m_smax     = smax;",
+	"	r->m_mreached = mreached;",
+	"	r->m_errors   = errors;",
+	"	r->m_VMAX     = vmax_seen;",
+	"	r->m_PMAX     = (short) pmax_seen;",
+	"	r->m_QMAX     = (short) qmax_seen;",
+	"	ptr = (uchar *) &(r->m_R);",
+	"	for (i = 0; i <= _NP_; i++)	/* all proctypes */",
+	"	{	memcpy(ptr, reached[i], NrStates[i]*sizeof(uchar));",
+	"		ptr += NrStates[i]*sizeof(uchar);",
+	"	}",
+	"	if (verbose>1)",
+	"	{	cpu_printf(\"Put Results nstates %%g (sz %%d)\\n\", nstates, ptr - &(r->m_R));",
+	"	}",
+	"}",
+	"",
+	"void snapshot(void);",
+	"",
+	"void",
+	"retrieve_info(SM_results *r)",
+	"{	int i, j;",
+	"	volatile uchar *ptr;",
+	"",
+	"	snapshot();	/* for a final report */",
+	"",
+	"	enter_critical(GLOBAL_LOCK);",
+	"#ifdef SEP_HEAP",
+	"	if (verbose)",
+	"	{	printf(\"cpu%%d: local heap-left %%ld KB (%%d MB)\\n\",",
+	"			core_id, (long) (my_size/1024), (int) (my_size/1048576));",
+	"	}",
+	"#endif",
+	"	if (verbose && core_id == 0)",
+	"	{	printf(\"qmax: \");",
+	"		for (i = 0; i < NCORE; i++)",
+	"		{	printf(\"%%d \", prmax[i]);",
+	"		}",
+	"#ifndef NGQ",
+	"		printf(\"G: %%d\", *grmax);",
+	"#endif",
+	"		printf(\"\\n\");",
+	"	}",
+	"	leave_critical(GLOBAL_LOCK);",
+	"",
+	"	memcnt  += r->m_memcnt;",
+	"	nstates += r->m_nstates;",
+	"	nShadow += r->m_nShadow;",
+	"	truncs  += r->m_truncs;",
+	"	truncs2 += r->m_truncs2;",
+	"	nlinks  += r->m_nlinks;",
+	"	ngrabs  += r->m_ngrabs;",
+	"	nlost   += r->m_nlost;",
+	"	hcmp    += r->m_hcmp;",
+	"	/* frame_wait += r->m_frame_wait; */",
+	"	errors  += r->m_errors;",
+	"",
+	"	if (hmax  < r->m_hmax)  hmax  = r->m_hmax;",
+	"	if (svmax < r->m_svmax) svmax = r->m_svmax;",
+	"	if (smax  < r->m_smax)  smax  = r->m_smax;",
+	"	if (mreached < r->m_mreached) mreached = r->m_mreached;",
+	"",
+	"	if (vmax_seen < r->m_VMAX) vmax_seen = r->m_VMAX;",
+	"	if (pmax_seen < (int) r->m_PMAX) pmax_seen = (int) r->m_PMAX;",
+	"	if (qmax_seen < (int) r->m_QMAX) qmax_seen = (int) r->m_QMAX;",
+	"",
+	"	ptr = &(r->m_R);",
+	"	for (i = 0; i <= _NP_; i++)	/* all proctypes */",
+	"	{	for (j = 0; j < NrStates[i]; j++)",
+	"		{	if (*(ptr + j) != 0)",
+	"			{	reached[i][j] = 1;",
+	"		}	}",
+	"		ptr += NrStates[i]*sizeof(uchar);",
+	"	}",
+	"	if (verbose>1)",
+	"	{	cpu_printf(\"Got Results (%%d)\\n\", (int) (ptr - &(r->m_R)));",
+	"		snapshot();",
+	"	}",
+	"}",
+	"",
+	"#if !defined(WIN32) && !defined(WIN64)",
+	"static void",
+	"rm_shared_segments(void)",
+	"{	int m;",
+	"	volatile sh_Allocater *nxt_pool;",
+	"	/*",
+	"	 * mark all shared memory segments for removal ",
+	"	 * the actual removes wont happen intil last process dies or detaches",
+	"	 * the shmctl calls can return -1 if not all procs have detached yet",
+	"	 */",
+	"	for (m = 0; m < NR_QS; m++)	/* +1 for global q */",
+	"	{	if (shmid[m] != -1)",
+	"		{	(void) shmctl(shmid[m], IPC_RMID, NULL);",
+	"	}	}",
+	"#ifdef SEP_STATE",
+	"	if (shmid_M != -1)",
+	"	{	(void) shmctl(shmid_M, IPC_RMID, NULL);",
+	"	}",
+	"#else",
+	"	if (shmid_S != -1)",
+	"	{	(void) shmctl(shmid_S, IPC_RMID, NULL);",
+	"	}",
+	"	for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)",
+	"	{	shmid_M = (int) (last_pool->dc_id);",
+	"		nxt_pool = last_pool->nxt;	/* as a pre-caution only */",
+	"		if (shmid_M != -1)",
+	"		{	(void) shmctl(shmid_M, IPC_RMID, NULL);",
+	"	}	}",
+	"#endif",
+	"}",
+	"#endif",
+	"",
+	"void",
+	"sudden_stop(char *s)",
+	"{	char b[64];",
+	"	int i;",
+	"",
+	"	printf(\"cpu%%d: stop - %%s\\n\", core_id, s);",
+	"#if !defined(WIN32) && !defined(WIN64)",
+	"	if (proxy_pid != 0)",
+	"	{	rm_shared_segments();",
+	"	}",
+	"#endif",
+	"	if (search_terminated != NULL)",
+	"	{	if (*search_terminated != 0)",
+	"		{	if (verbose)",
+	"			{	printf(\"cpu%%d: termination initiated (%%d)\\n\",",
+	"					core_id, (int) *search_terminated);",
+	"			}",
+	"		} else",
+	"		{	if (verbose)",
+	"			{	printf(\"cpu%%d: initiated termination\\n\", core_id);",
+	"			}",
+	"			*search_terminated |= 8;	/* sudden_stop */",
+	"		}",
+	"		if (core_id == 0)",
+	"		{	if (((*search_terminated) & 4)	/* uerror in one of the cpus */",
+	"			&& !((*search_terminated) & (8|32|128|256))) /* abnormal stop */",
+	"			{	if (errors == 0) errors++; /* we know there is at least 1 */",
+	"			}",
+	"			wrapup(); /* incomplete stats, but at least something */",
+	"		}",
+	"		return;",
+	"	} /* else: should rarely happen, take more drastic measures */",
+	"",
+	"	if (core_id == 0)	/* local root process */",
+	"	{	for (i = 1; i < NCORE; i++)	/* not for 0 of course */",
+	"		{	int ignore;",
+	"#if defined(WIN32) || defined(WIN64)",
+	"				DWORD dwExitCode = 0;",
+	"				GetExitCodeProcess(worker_handles[i], &dwExitCode);",
+	"				if (dwExitCode == STILL_ACTIVE)",
+	"				{	TerminateProcess(worker_handles[i], 0);",
+	"				}",
+	"				printf(\"cpu0: terminate %%d %%d\\n\",",
+	"					(int) worker_pids[i], (dwExitCode == STILL_ACTIVE));",
+	"#else",
+	"				sprintf(b, \"kill -%%d %%d\", (int) SIGKILL, (int) worker_pids[i]);",
+	"				ignore = system(b);	/* if this is a proxy: receive half */",
+	"				printf(\"cpu0: %%s\\n\", b);",
+	"#endif",
+	"		}",
+	"		issued_kill++;",
+	"	} else",
+	"	{	/* on WIN32/WIN64 -- these merely kills the root process... */",
+	"		if (was_interrupted == 0)",	/* 2=SIGINT to root to trigger stop */
+	"		{	int ignore;",
+	"			sprintf(b, \"kill -%%d %%d\", (int) SIGINT, (int) worker_pids[0]);",
+	"			ignore = system(b);	/* warn the root process */",
+	"			printf(\"cpu%%d: %%s\\n\", core_id, b);",
+	"			issued_kill++;",
+	"	}	}",
+	"}",
+	"",
+	"#define iam_alive()	is_alive[core_id]++",	/* for crash detection */
+	"",
+	"extern int crash_test(double);",
+	"extern void crash_reset(void);",
+	"",
+	"int",
+	"someone_crashed(int wait_type)",
+	"{	static double last_value = 0.0;",
+	"	static int count = 0;",
+	"",
+	"	if (search_terminated == NULL",
+	"	|| *search_terminated != 0)",
+	"	{",
+	"		if (!(*search_terminated & (8|32|128|256)))",
+	"		{	if (count++ < 100*NCORE)",
+	"			{	return 0;",
+	"		}	}",
+	"		return 1;",
+	"	}",
+	"	/* check left neighbor only */",
+	"	if (last_value == is_alive[(core_id + NCORE - 1) %% NCORE])",
+	"	{	if (count++ >= 100)	/* to avoid unnecessary checks */",
+	"		{	return 1;",
+	"		}",
+	"		return 0;",
+	"	}",
+	"	last_value = is_alive[(core_id + NCORE - 1) %% NCORE];",
+	"	count = 0;",
+	"	crash_reset();",
+	"	return 0;",
+	"}",
+	"",
+	"void",
+	"sleep_report(void)",
+	"{",
+	"	enter_critical(GLOBAL_LOCK);",
+	"	if (verbose)",
+	"	{",
+	"#ifdef NGQ",
+	"		printf(\"cpu%%d: locks: global %%g\\tother %%g\\t\",",
+	"			core_id, glock_wait[0], lock_wait - glock_wait[0]);",
+	"#else",
+	"		printf(\"cpu%%d: locks: GL %%g, RQ %%g, WQ %%g, HT %%g\\t\",",
+	"			core_id, glock_wait[0], glock_wait[1], glock_wait[2],",
+	"			lock_wait - glock_wait[0] - glock_wait[1] - glock_wait[2]);",
+	"#endif",
+	"		printf(\"waits: states %%g slots %%g\\n\", frame_wait, free_wait);",
+	"#ifndef NGQ",
+	"		printf(\"cpu%%d: gq [tries %%g, room %%g, noroom %%g]\\n\", core_id, gq_tries, gq_hasroom, gq_hasnoroom);",
+	"		if (core_id == 0 && (*gr_readmiss >= 1.0 || *gr_readmiss >= 1.0 || *grcnt != 0))",
+	"		printf(\"cpu0: gq [readmiss: %%g, writemiss: %%g cnt %%d]\\n\", *gr_readmiss, *gr_writemiss, *grcnt);",
+	"#endif",
+	"	}",
+	"	if (free_wait > 1000000.)",
+	"	#ifndef NGQ",
+	"	if (!a_cycles)",
+	"	{	printf(\"hint: this search may be faster with a larger work-queue\\n\");",
+	"		printf(\"	(-DSET_WQ_SIZE=N with N>%%g), and/or with -DUSE_DISK\\n\",",
+	"			GWQ_SIZE/sizeof(SM_frame));",
+	"		printf(\"      or with a larger value for -zN (N>%%ld)\\n\", z_handoff);",
+	"	#else",
+	"	{	printf(\"hint: this search may be faster if compiled without -DNGQ, with -DUSE_DISK, \");",
+	"		printf(\"or with a larger -zN (N>%%d)\\n\", z_handoff);",
+	"	#endif",
+	"	}",
+	"	leave_critical(GLOBAL_LOCK);",
+	"}",
+	"",
+	"#ifndef MAX_DSK_FILE",
+	"	#define MAX_DSK_FILE	1000000	/* default is max 1M states per file */",
+	"#endif",
+	"",
+	"void",
+	"multi_usage(FILE *fd)",
+	"{	static int warned = 0;",
+	"	if (warned > 0) { return; } else { warned++; }",
+	"	fprintf(fd, \"\\n\");",
+	"	fprintf(fd, \"Defining multi-core mode:\\n\\n\");",
+	"	fprintf(fd, \"        -DDUAL_CORE --> same as -DNCORE=2\\n\");",
+	"	fprintf(fd, \"        -DQUAD_CORE --> same as -DNCORE=4\\n\");",
+	"	fprintf(fd, \"        -DNCORE=N   --> enables multi_core verification if N>1\\n\");",
+	"	fprintf(fd, \"\\n\");",
+	"	fprintf(fd, \"Additional directives supported in multi-core mode:\\n\\n\");",
+	"	fprintf(fd, \"        -DSEP_STATE --> forces separate statespaces instead of a single shared state space\\n\");",
+	"	fprintf(fd, \"        -DNUSE_DISK --> use disk for storing states when a work queue overflows\\n\");",
+	"	fprintf(fd, \"        -DMAX_DSK_FILE --> max nr of states per diskfile (%%d)\\n\", MAX_DSK_FILE);",
+	"	fprintf(fd, \"        -DFULL_TRAIL --> support full error trails (increases memory use)\\n\");",
+	"	fprintf(fd, \"\\n\");",
+	"	fprintf(fd, \"More advanced use (should rarely need changing):\\n\\n\");",
+	"	fprintf(fd, \"     To change the nr of states that can be stored in the global queue\\n\");",
+	"	fprintf(fd, \"     (lower numbers allow for more states to be stored, prefer multiples of 8):\\n\");",
+	"	fprintf(fd, \"        -DVMAX=N    --> upperbound on statevector for handoffs (N=%%d)\\n\", VMAX);",
+	"	fprintf(fd, \"        -DPMAX=N    --> upperbound on nr of procs (default: N=%%d)\\n\", PMAX);",
+	"	fprintf(fd, \"        -DQMAX=N    --> upperbound on nr of channels (default: N=%%d)\\n\", QMAX);",
+	"	fprintf(fd, \"\\n\");",
+#if 0
+	"#if !defined(WIN32) && !defined(WIN64)",
+	"	fprintf(fd, \"     To change the size of spin's individual shared memory segments for cygwin/linux:\\n\");",
+	"	fprintf(fd, \"        -DSET_SEG_SIZE=N --> default %%g (Mbytes)\\n\", SEG_SIZE/(1048576.));",
+	"	fprintf(fd, \"\\n\");",
+	"#endif",
+#endif
+	"	fprintf(fd, \"     To set the total amount of memory reserved for the global workqueue:\\n\");",
+	"	fprintf(fd, \"        -DSET_WQ_SIZE=N --> default: N=128 (defined in MBytes)\\n\\n\");",
+#if 0
+	"	fprintf(fd, \"     To omit the global workqueue completely (bad idea):\\n\");",
+	"	fprintf(fd, \"        -DNGQ\\n\\n\");",
+#endif
+	"	fprintf(fd, \"     To force the use of a single global heap, instead of separate heaps:\\n\");",
+	"	fprintf(fd, \"        -DGLOB_HEAP\\n\");",
+	"	fprintf(fd, \"\\n\");",
+	"	fprintf(fd, \"     To define a fct to initialize data before spawning processes (use quotes):\\n\");",
+	"	fprintf(fd, \"        \\\"-DC_INIT=fct()\\\"\\n\");",
+	"	fprintf(fd, \"\\n\");",
+	"	fprintf(fd, \"     Timer settings for termination and crash detection:\\n\");",
+	"	fprintf(fd, \"        -DSHORT_T=N --> timeout for termination detection trigger (N=%%g)\\n\", (double) SHORT_T);",
+	"	fprintf(fd, \"        -DLONG_T=N  --> timeout for giving up on termination detection (N=%%g)\\n\", (double) LONG_T);",
+	"	fprintf(fd, \"        -DONESECOND --> (1<<29) --> timeout waiting for a free slot -- to check for crash\\n\");",
+	"	fprintf(fd, \"        -DT_ALERT   --> collect stats on crash alert timeouts\\n\\n\");",
+	"	fprintf(fd, \"Help with Linux/Windows/Cygwin configuration for multi-core:\\n\");",
+	"	fprintf(fd, \"	http://spinroot.com/spin/multicore/V5_Readme.html\\n\");",
+	"	fprintf(fd, \"\\n\");",
+	"}",
+	"#if NCORE>1 && defined(FULL_TRAIL)",
+	"typedef struct Stack_Tree {",
+	"	uchar	      pr;	/* process that made transition */",
+	"	T_ID	    t_id;	/* id of transition */",
+	"	volatile struct Stack_Tree *prv; /* backward link towards root */",
+	"} Stack_Tree;",
+	"",
+	"H_el *grab_shared(int);",
+	"volatile Stack_Tree **stack_last; /* in shared memory */",
+	"char *stack_cache = NULL;	/* local */",
+	"int  nr_cached = 0;		/* local */",
+	"",
+	"#ifndef CACHE_NR",
+	"	#define CACHE_NR	1024",
+	"#endif",
+	"",
+	"volatile Stack_Tree *",
+	"stack_prefetch(void)",
+	"{	volatile Stack_Tree *st;",
+	"",
+	"	if (nr_cached == 0)",
+	"	{	stack_cache = (char *) grab_shared(CACHE_NR * sizeof(Stack_Tree));",
+	"		nr_cached = CACHE_NR;",
+	"	}",
+	"	st = (volatile Stack_Tree *) stack_cache;",
+	"	stack_cache += sizeof(Stack_Tree);",
+	"	nr_cached--;",
+	"	return st;",
+	"}",
+	"",
+	"void",
+	"Push_Stack_Tree(short II, T_ID t_id)",
+	"{	volatile Stack_Tree *st;",
+	"",
+	"	st = (volatile Stack_Tree *) stack_prefetch();",
+	"	st->pr = II;",
+	"	st->t_id = t_id;",
+	"	st->prv = (Stack_Tree *) stack_last[core_id];",
+	"	stack_last[core_id] = st;",
+	"}",
+	"",
+	"void",
+	"Pop_Stack_Tree(void)",
+	"{	volatile Stack_Tree *cf = stack_last[core_id];",
+	"",
+	"	if (cf)",
+	"	{	stack_last[core_id] = cf->prv;",
+	"	} else if (nr_handoffs * z_handoff + depth > 0)",
+	"	{	printf(\"cpu%%d: error pop_stack_tree (depth %%ld)\\n\",",
+	"			core_id, depth);",
+	"	}",
+	"}",
+	"#endif", /* NCORE>1 && FULL_TRAIL */
+	"",
+	"void",
+	"e_critical(int which)",
+	"{	double cnt_start;",
+	"",
+	"	if (readtrail || iamin[which] > 0)",
+	"	{	if (!readtrail && verbose)",
+	"		{	printf(\"cpu%%d: Double Lock on %%d (now %%d)\\n\",",
+	"				core_id, which, iamin[which]+1);",
+	"			fflush(stdout);",
+	"		}",
+	"		iamin[which]++;	/* local variable */",
+	"		return;",
+	"	}",
+	"",
+	"	cnt_start = lock_wait;",
+	"",
+	"	while (sh_lock != NULL)	/* as long as we have shared memory */",
+	"	{	int r = tas(&sh_lock[which]);",
+	"		if (r == 0)",
+	"		{	iamin[which] = 1;",
+	"			return;		/* locked */",
+	"		}",
+	"",
+	"		lock_wait++;",
+	"#ifndef NGQ",
+	"		if (which < 3) { glock_wait[which]++; }",
+	"#else",
+	"		if (which == 0) { glock_wait[which]++; }",
+	"#endif",
+	"		iam_alive();",
+	"",
+	"		if (lock_wait - cnt_start > TenSeconds)",
+	"		{	printf(\"cpu%%d: lock timeout on %%d\\n\", core_id, which);",
+	"			cnt_start = lock_wait;",
+	"			if (someone_crashed(1))",
+	"			{	sudden_stop(\"lock timeout\");",
+	"				pan_exit(1);",
+	"	}	}	}",
+	"}",
+	"",
+	"void",
+	"x_critical(int which)",
+	"{",
+	"	if (iamin[which] != 1)",
+	"	{	if (iamin[which] > 1)",
+	"		{	iamin[which]--;	/* this is thread-local - no races on this one */",
+	"			if (!readtrail && verbose)",
+	"			{	printf(\"cpu%%d: Partial Unlock on %%d (%%d more needed)\\n\",",
+	"					core_id, which, iamin[which]);",
+	"				fflush(stdout);",
+	"			}",
+	"			return;",
+	"		} else /* iamin[which] <= 0 */",
+	"		{	if (!readtrail)",
+	"			{	printf(\"cpu%%d: Invalid Unlock iamin[%%d] = %%d\\n\",",
+	"					core_id, which, iamin[which]);",
+	"				fflush(stdout);",
+	"			}",
+	"			return;",
+	"	}	}",
+	"",
+	"	if (sh_lock != NULL)",
+	"	{	iamin[which]   = 0;",
+	"#if defined(__powerpc64__)",
+	"	#if 1",
+	"		__sync_synchronize();	/* srirajpaul */",
+	"	#else",
+	"		__lwsync();		/* xlc compiler only */",
+	"	#endif",
+	"#endif",
+	"		sh_lock[which] = 0;	/* unlock */",
+	"	}",
+	"}",
+	"",
+	"void",
+	"#if defined(WIN32) || defined(WIN64)",
+	"start_proxy(char *s, DWORD r_pid)",
+	"#else",
+	"start_proxy(char *s, int r_pid)",
+	"#endif",
+	"{	char  Q_arg[16], Z_arg[16], Y_arg[16];",
+	"	char *args[32], *ptr;",
+	"	int   argcnt = 0;",
+	"",
+	"	sprintf(Q_arg, \"-Q%%d\", getpid());",
+	"	sprintf(Y_arg, \"-Y%%d\", r_pid);",
+	"	sprintf(Z_arg, \"-Z%%d\", proxy_pid /* core_id */);",
+	"",
+	"	args[argcnt++] = \"proxy\";",
+	"	args[argcnt++] = s; /* -r or -s */",
+	"	args[argcnt++] = Q_arg;",
+	"	args[argcnt++] = Z_arg;",
+	"	args[argcnt++] = Y_arg;",
+	"",
+	"	if (strlen(o_cmdline) > 0)",
+	"	{	ptr = o_cmdline; /* assume args separated by spaces */",
+	"		do {	args[argcnt++] = ptr++;",
+	"			if ((ptr = strchr(ptr, ' ')) != NULL)",
+	"			{	while (*ptr == ' ')",
+	"				{	*ptr++ = '\\0';",
+	"				}",
+	"			} else",
+	"			{	break;",
+	"			}",
+	"		} while (argcnt < 31);",
+	"	}",
+	"	args[argcnt] = NULL;",
+	"#if defined(WIN32) || defined(WIN64)",
+	"	execvp(\"pan_proxy\", args); /* no return */",
+	"#else",
+	"	execvp(\"./pan_proxy\", args); /* no return */",
+	"#endif",
+	"	Uerror(\"pan_proxy exec failed\");",
+	"}",
+	"/*** end of common code fragment ***/",
+	"",
+	"#if !defined(WIN32) && !defined(WIN64)",
+	"void",
+	"init_shm(void)		/* initialize shared work-queues - linux/cygwin */",
+	"{	key_t	key[NR_QS];",
+	"	int	n, m;",
+	"	int	must_exit = 0;",
+	"",
+	"	if (core_id == 0 && verbose)",
+	"	{	printf(\"cpu0: step 3: allocate shared workqueues %%g MB\\n\",",
+	"			((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.) );",
+	"	}",
+	"	for (m = 0; m < NR_QS; m++)		/* last q is the global q */",
+	"	{	double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;",
+	"		key[m] = ftok(PanSource, m+1);", /* m must be nonzero, 1..NCORE */
+	"		if (key[m] == -1)",
+	"		{	perror(\"ftok shared queues\"); must_exit = 1; break;",
+	"		}",
+	"",
+	"		if (core_id == 0)	/* root creates */",
+	"		{	/* check for stale copy */",
+	"			shmid[m] = shmget(key[m], (size_t) qsize, 0600);",
+	"			if (shmid[m] != -1)	/* yes there is one; remove it */",
+	"			{	printf(\"cpu0: removing stale q%%d, status: %%d\\n\",",
+	"					m, shmctl(shmid[m], IPC_RMID, NULL));",
+	"			}",
+	"			shmid[m] = shmget(key[m], (size_t) qsize, 0600|IPC_CREAT|IPC_EXCL);",
+	"			memcnt += qsize;",
+	"		} else			/* workers attach */",
+	"		{	shmid[m] = shmget(key[m], (size_t) qsize, 0600);",
+	"			/* never called, since we create shm *before* we fork */",
+	"		}",
+	"		if (shmid[m] == -1)",
+	"		{	perror(\"shmget shared queues\"); must_exit = 1; break;",
+	"		}",
+	"",
+	"		shared_mem[m] = (char *) shmat(shmid[m], (void *) 0, 0);	/* attach */",
+	"		if (shared_mem[m] == (char *) -1)",
+	"		{ fprintf(stderr, \"error: cannot attach shared wq %%d (%%d Mb)\\n\",",
+	"				m+1, (int) (qsize/(1048576.)));",
+	"		  perror(\"shmat shared queues\"); must_exit = 1; break;",
+	"		}",
+	"",
+	"		m_workq[m] = (SM_frame *) shared_mem[m];",
+	"		if (core_id == 0)",
+	"		{	int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;",
+	"			for (n = 0; n < nframes; n++)",
+	"			{	m_workq[m][n].m_vsize = 0;",
+	"				m_workq[m][n].m_boq = 0;",
+	"	}	}	}",
+	"",
+	"	if (must_exit)",
+	"	{	rm_shared_segments();",
+	"		fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+	"		pan_exit(1);	/* calls cleanup_shm */",
+	"	}",
+	"}",
+	"",
+	"static uchar *",
+	"prep_shmid_S(size_t n)		/* either sets SS or H_tab, linux/cygwin */",
+	"{	char	*rval;",
+	"#ifndef SEP_STATE",
+	"	key_t	key;",
+	"",
+	"	if (verbose && core_id == 0)",
+	"	{",
+	"	#ifdef BITSTATE",
+	"		printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",",
+	"			(double) n / (1048576.));",
+	"	#else",
+	"		printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",",
+	"			(double) n / (1048576.));",
+	"	#endif",
+	"	}",
+	"	#ifdef MEMLIM", /* memlim has a value */
+	"	if (memcnt + (double) n > memlim)",
+	"	{	printf(\"cpu0: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",",
+	"			memcnt/1024., (int) (n/1024), memlim/(1048576.));",
+	"		printf(\"cpu0: insufficient memory -- aborting\\n\");",
+	"		exit(1);",
+	"	}",
+	"	#endif",
+	"",
+	"	key = ftok(PanSource, NCORE+2);	/* different from queues */",
+	"	if (key == -1)",
+	"	{	perror(\"ftok shared bitstate or hashtable\");",
+	"		fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+	"		pan_exit(1);",
+	"	}",
+	"",
+	"	if (core_id == 0)	/* root */",
+	"	{	shmid_S = shmget(key, n, 0600);",
+	"		if (shmid_S != -1)",
+	"		{	printf(\"cpu0: removing stale segment, status: %%d\\n\",",
+	"				(int) shmctl(shmid_S, IPC_RMID, NULL));",
+	"		}",
+	"		shmid_S = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);",
+	"		memcnt += (double) n;",
+	"	} else			/* worker */",
+	"	{	shmid_S = shmget(key, n, 0600);",
+	"	}",
+	"	if (shmid_S == -1)",
+	"	{	perror(\"shmget shared bitstate or hashtable too large?\");",
+	"		fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+	"		pan_exit(1);",
+	"	}",
+	"",
+	"	rval = (char *) shmat(shmid_S, (void *) 0, 0);	/* attach */",
+	"	if ((char *) rval == (char *) -1)",
+	"	{	perror(\"shmat shared bitstate or hashtable\");",
+	"		fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+	"		pan_exit(1);",
+	"	}",
+	"#else",
+	"	rval = (char *) emalloc(n);",
+	"#endif",
+	"	return (uchar *) rval;",
+	"}",
+	"",
+	"#define TRY_AGAIN	1",
+	"#define NOT_AGAIN	0",
+	"",
+	"static char shm_prep_result;",
+	"",
+	"static uchar *",
+	"prep_state_mem(size_t n)		/* sets memory arena for states linux/cygwin */",
+	"{	char	*rval;",
+	"	key_t	key;",
+	"	static int cnt = 3;		/* start larger than earlier ftok calls */",
+	"",
+	"	shm_prep_result = NOT_AGAIN;	/* default */",
+	"	if (verbose && core_id == 0)",
+	"	{	printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%6.2g Mb\\n\",",
+	"			cnt-3, (double) n / (1048576.));",
+	"	}",
+	"	#ifdef MEMLIM",
+	"	if (memcnt + (double) n > memlim)",
+	"	{	printf(\"cpu0: error: M %%.0f + %%.0f Kb exceeds memory limit of %%.0f Mb\\n\",",
+	"			memcnt/1024.0, (double) n/1024.0, memlim/(1048576.));",
+	"		return NULL;",
+	"	}",
+	"	#endif",
+	"",
+	"	key = ftok(PanSource, NCORE+cnt); cnt++;", /* starts at NCORE+3 */
+	"	if (key == -1)",
+	"	{	perror(\"ftok T\");",
+	"		printf(\"pan: check './pan --' for usage details\\n\");",
+	"		pan_exit(1);",
+	"	}",
+	"",
+	"	if (core_id == 0)",
+	"	{	shmid_M = shmget(key, n, 0600);",
+	"		if (shmid_M != -1)",
+	"		{	printf(\"cpu0: removing stale memory segment %%d, status: %%d\\n\",",
+	"				cnt-3, shmctl(shmid_M, IPC_RMID, NULL));",
+	"		}",
+	"		shmid_M = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);",
+	"		/* memcnt += (double) n; -- only amount actually used is counted */",
+	"	} else",
+	"	{	shmid_M = shmget(key, n, 0600);",
+	"	",
+	"	}",
+	"	if (shmid_M == -1)",
+	"	{	if (verbose)",
+	"		{	printf(\"error: failed to get pool of shared memory %%d of %%.0f Mb\\n\",",
+	"				cnt-3, ((double)n)/(1048576.));",
+	"			perror(\"state mem\");",
+	"			printf(\"pan: check './pan --' for usage details\\n\");",
+	"		}",
+	"		shm_prep_result = TRY_AGAIN;",
+	"		return NULL;",
+	"	}",
+	"	rval = (char *) shmat(shmid_M, (void *) 0, 0);	/* attach */",
+	"",
+	"	if ((char *) rval == (char *) -1)",
+	"	{	printf(\"cpu%%d error: failed to attach pool of shared memory %%d of %%.0f Mb\\n\",",
+	"			 core_id, cnt-3, ((double)n)/(1048576.));",
+	"		perror(\"state mem\");",
+	"		return NULL;",
+	"	}",
+	"	return (uchar *) rval;",
+	"}",
+	"",
+	"void",
+	"init_HT(unsigned long n)	/* cygwin/linux version */",
+	"{	volatile char	*x;",
+	"	double  get_mem;",
+	"#ifndef SEP_STATE",
+	"	volatile char	*dc_mem_start;",
+	"	double  need_mem, got_mem = 0.;",
+	"#endif",
+	"",
+"#ifdef SEP_STATE",
+	" #ifndef MEMLIM",
+	"	if (verbose)",
+	"	{	printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");", /* cannot happen */
+	"	}",
+	" #else",
+	"	if (verbose)",
+	"	{	printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",",
+	"		MEMLIM, ((double)n/(1048576.)), (((double) NCORE * LWQ_SIZE) + GWQ_SIZE) /(1048576.) );",
+	"	}",
+	" #endif",
+	"	get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *) + 4*sizeof(void *) + 2*sizeof(double);",
+	"	/* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */",
+	"	get_mem += 4 * NCORE * sizeof(void *); /* prfree, prfull, prcnt, prmax */",
+	" #ifdef FULL_TRAIL",
+	"	get_mem += (NCORE) * sizeof(Stack_Tree *); /* NCORE * stack_last */",
+	" #endif",
+	"	x = (volatile char *) prep_state_mem((size_t) get_mem); /* work queues and basic structs */",
+	"	shmid_X = (long) x;",
+	"	if (x == NULL)", /* do not repeat for smaller sizes */
+	"	{	printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");",
+	"		exit(1);",
+	"	}",
+	"	search_terminated = (volatile unsigned int *) x; /* comes first */",
+	"	x += sizeof(void *); /* maintain alignment */",
+	"",
+	"	is_alive   = (volatile double *) x;",
+	"	x += NCORE * sizeof(double);",
+	"",
+	"	sh_lock   = (volatile int *) x;",
+	"	x += CS_NR * sizeof(void *);", /* allow 1 word per entry */
+	"",
+	"	grfree    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	grfull    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	grcnt    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	grmax    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	prfree = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	prfull = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	prcnt = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	prmax = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	gr_readmiss    = (volatile double *) x;",
+	"	x += sizeof(double);",
+	"	gr_writemiss    = (volatile double *) x;",
+	"	x += sizeof(double);",
+	"",
+	"	#ifdef FULL_TRAIL",
+	"		stack_last = (volatile Stack_Tree **) x;",
+	"		x += NCORE * sizeof(Stack_Tree *);",
+	"	#endif",
+	"",
+	"	#ifndef BITSTATE",
+	"		H_tab = (H_el **) emalloc(n);",
+	"	#endif",
+"#else",
+	"	#ifndef MEMLIM",
+	"		#warning MEMLIM not set", /* cannot happen */
+	"		#define MEMLIM	(2048)",
+	"	#endif",
+	"",
+	"	if (core_id == 0 && verbose)",
+	"	{	printf(\"cpu0: step 0: -DMEMLIM=%%d Mb minus hashtable+workqs (%%g + %%g Mb) leaves %%g Mb\\n\",",
+	"			MEMLIM, ((double)n/(1048576.)), (NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),",
+	"			(memlim - memcnt - (double) n - (NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));",
+	"	}",
+	"	#ifndef BITSTATE",
+	"		H_tab = (H_el **) prep_shmid_S((size_t) n);	/* hash_table */",
+	"	#endif",
+	"	need_mem = memlim - memcnt - ((double) NCORE * LWQ_SIZE) - GWQ_SIZE;",
+	"	if (need_mem <= 0.)",
+	"	{	Uerror(\"internal error -- shared state memory\");",
+	"	}",
+	"",
+	"	if (core_id == 0 && verbose)",
+	"	{	printf(\"cpu0: step 2: pre-allocate shared state memory %%g Mb\\n\",",
+	"			need_mem/(1048576.));",
+	"	}",
+	"#ifdef SEP_HEAP",
+	"	SEG_SIZE = need_mem / NCORE;",
+	"	if (verbose && core_id == 0)",
+	"	{	printf(\"cpu0: setting segsize to %%6g MB\\n\",",
+	"			SEG_SIZE/(1048576.));",
+	"	}",
+	"	#if defined(CYGWIN) || defined(__CYGWIN__)",
+	"	if (SEG_SIZE > 512.*1024.*1024.)",
+	"	{	printf(\"warning: reducing SEG_SIZE of %%g MB to 512MB (exceeds max for Cygwin)\\n\",",
+	"			SEG_SIZE/(1024.*1024.));",
+	"		SEG_SIZE = 512.*1024.*1024.;",
+	"	}",
+	"	#endif",
+	"#endif",
+	"	mem_reserved = need_mem;",
+	"	while (need_mem > 1024.)",
+	"	{	get_mem = need_mem;",
+	"shm_more:",
+	"		if (get_mem > (double) SEG_SIZE)",
+	"		{	get_mem = (double) SEG_SIZE;",
+	"		}",
+	"		if (get_mem <= 0.0) break;",
+	"",
+	"		/* for allocating states: */",
+	"		x = dc_mem_start = (volatile char *) prep_state_mem((size_t) get_mem);",
+	"		if (x == NULL)",
+	"		{	if (shm_prep_result == NOT_AGAIN",
+	"			||  first_pool != NULL",
+	"			||  SEG_SIZE < (16. * 1048576.))",
+	"			{	break;",
+	"			}",
+	"			SEG_SIZE /= 2.;",
+	"			if (verbose)",
+	"			{	printf(\"pan: lowered segsize to %%f\\n\", SEG_SIZE);",
+	"			}",
+	"			if (SEG_SIZE >= 1024.)",
+	"			{	goto shm_more;", /* always terminates */
+	"			}",
+	"			break;",
+	"		}",
+	"",
+	"		need_mem -= get_mem;",
+	"		got_mem  += get_mem;",
+	"		if (first_pool == NULL)",
+	"		{	search_terminated = (volatile unsigned int *) x; /* comes first */",
+	"			x += sizeof(void *); /* maintain alignment */",
+	"",
+	"			is_alive   = (volatile double *) x;",
+	"			x += NCORE * sizeof(double);",
+	"",
+	"			sh_lock   = (volatile int *) x;",
+	"			x += CS_NR * sizeof(void *);", /* allow 1 word per entry */
+	"",
+	"			grfree    = (volatile int *) x;",
+	"			x += sizeof(void *);",
+	"			grfull    = (volatile int *) x;",
+	"			x += sizeof(void *);",
+	"			grcnt    = (volatile int *) x;",
+	"			x += sizeof(void *);",
+	"			grmax    = (volatile int *) x;",
+	"			x += sizeof(void *);",
+	"			prfree = (volatile int *) x;",
+	"			x += NCORE * sizeof(void *);",
+	"			prfull = (volatile int *) x;",
+	"			x += NCORE * sizeof(void *);",
+	"			prcnt = (volatile int *) x;",
+	"			x += NCORE * sizeof(void *);",
+	"			prmax = (volatile int *) x;",
+	"			x += NCORE * sizeof(void *);",
+	"			gr_readmiss  = (volatile double *) x;",
+	"			x += sizeof(double);",
+	"			gr_writemiss = (volatile double *) x;",
+	"			x += sizeof(double);",
+	" #ifdef FULL_TRAIL",
+	"			stack_last = (volatile Stack_Tree **) x;",
+	"			x += NCORE * sizeof(Stack_Tree *);",
+	" #endif",
+	"			if (((long)x)&(sizeof(void *)-1)) /* 64-bit word alignment */",
+	"			{	x += sizeof(void *)-(((long)x)&(sizeof(void *)-1));",
+	"			}",
+	"",
+	"			#ifdef COLLAPSE",
+	"			ncomps = (unsigned long *) x;",
+	"			x += (256+2) * sizeof(unsigned long);",
+	"			#endif",
+	"		}",
+	"",
+	"		dc_shared = (sh_Allocater *) x; /* must be in shared memory */",
+	"		x += sizeof(sh_Allocater);",
+	"",
+	"		if (core_id == 0)	/* root only */",
+	"		{	dc_shared->dc_id     = shmid_M;",
+	"			dc_shared->dc_start  = dc_mem_start;",
+	"			dc_shared->dc_arena  = x;",
+	"			dc_shared->pattern   = 1234567; /* protection */",
+	"			dc_shared->dc_size   = (long) get_mem - (long) (x - dc_mem_start);",
+	"			dc_shared->nxt       = (long) 0;",
+	"",
+	"			if (last_pool == NULL)",
+	"			{	first_pool = last_pool = dc_shared;",
+	"			} else",
+	"			{	last_pool->nxt = dc_shared;",
+	"				last_pool = dc_shared;",
+	"			}",
+	"		} else if (first_pool == NULL)",
+	"		{	first_pool = dc_shared;",
+	"	}	}",
+	"",
+	"	if (need_mem > 1024.)",
+	"	{	printf(\"cpu0: could allocate only %%g Mb of shared memory (wanted %%g more)\\n\",",
+	"			got_mem/(1048576.), need_mem/(1048576.));",
+	"	}",
+	"",
+	"	if (!first_pool)",
+	"	{	printf(\"cpu0: insufficient memory -- aborting.\\n\");",
+	"		exit(1);",
+	"	}",
+	"	/* we are still single-threaded at this point, with core_id 0 */",
+	"	dc_shared = first_pool;",
+	"",
+"#endif", /* !SEP_STATE */
+	"}",
+	"",
+	"void",
+	"cleanup_shm(int val)",
+	"{	volatile sh_Allocater *nxt_pool;",
+	"	unsigned long cnt = 0;",
+	"	int m;",
+	"",
+	"	if (nibis != 0)",
+	"	{	printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);",
+	"		return;",
+	"	} else",
+	"	{	nibis = 1;",
+	"	}",
+	"	if (search_terminated != NULL)",
+	"	{	*search_terminated |= 16; /* cleanup_shm */",
+	"	}",
+	"",
+	"	for (m = 0; m < NR_QS; m++)",
+	"	{	if (shmdt((void *) shared_mem[m]) > 0)",
+	"		{	perror(\"shmdt detaching from shared queues\");",
+	"	}	}",
+	"",
+	"#ifdef SEP_STATE",
+	"	if (shmdt((void *) shmid_X) != 0)",
+	"	{	perror(\"shmdt detaching from shared state memory\");",
+	"	}",
+	"#else",
+	"	#ifdef BITSTATE",
+	"		if (SS > 0 && shmdt((void *) SS) != 0)",
+	"		{	if (verbose)",
+	"			{	perror(\"shmdt detaching from shared bitstate arena\");",
+	"		}	}",
+	"	#else",
+	"		if (core_id == 0)",
+	"		{	/* before detaching: */",
+	"			for (nxt_pool = dc_shared; nxt_pool != NULL; nxt_pool = nxt_pool->nxt)",
+	"			{	cnt += nxt_pool->dc_size;",
+	"			}",
+	"			if (verbose)",
+	"			{	printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",",
+	"					cnt / (long)(1048576));",
+	"		}	}",
+	"",
+	"		if (shmdt((void *) H_tab) != 0)",
+	"		{	perror(\"shmdt detaching from shared hashtable\");",
+	"		}",
+	"",
+	"		for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)",
+	"		{	nxt_pool = last_pool->nxt;",
+	"			if (shmdt((void *) last_pool->dc_start) != 0)",
+	"			{	perror(\"shmdt detaching from shared state memory\");",
+	"		}	}",
+	"		first_pool = last_pool = NULL;	/* precaution */",
+	"	#endif",
+	"#endif",
+	"	/* detached from shared memory - so cannot use cpu_printf */",
+	"	if (verbose)",
+	"	{	printf(\"cpu%%d: done -- got %%ld states from queue\\n\",",
+	"			core_id, nstates_get);",
+	"	}",
+	"}",
+	"",
+	"extern void give_up(int);",
+	"extern void Read_Queue(int);",
+	"",
+	"void",
+	"mem_get(void)",
+	"{	SM_frame   *f;",
+	"	int is_parent;",
+	"",
+	"#if defined(MA) && !defined(SEP_STATE)",
+	"	#error MA without SEP_STATE is not supported with multi-core",
+	"#endif",
+	"#ifdef BFS",
+	"	#error instead of -DNCORE -DBFS use -DBFS_PAR",
+	"#endif",
+	"#ifdef SC",
+	"	#error SC is not supported with multi-core",
+	"#endif",
+	"	init_shm();	/* we are single threaded when this starts */",
+	"",
+	"	if (core_id == 0 && verbose)",
+	"	{	printf(\"cpu0: step 4: calling fork()\\n\");",
+	"	}",
+	"	fflush(stdout);",
+	"",
+	"/*	if NCORE > 1 the child or the parent should fork N-1 more times",
+	" *	the parent is the only process with core_id == 0 and is_parent > 0",
+	" *	the workers have is_parent = 0 and core_id = 1..NCORE-1",
+	" */",
+	"	if (core_id == 0)",
+	"	{	worker_pids[0] = getpid();	/* for completeness */",
+	"		while (++core_id < NCORE)	/* first worker sees core_id = 1 */",
+	"		{	is_parent = fork();",
+	"			if (is_parent == -1)",
+	"			{	Uerror(\"fork failed\");",
+	"			}",
+	"			if (is_parent == 0)	/* this is a worker process */",
+	"			{	if (proxy_pid == core_id)	/* always non-zero */",
+	"				{	start_proxy(\"-r\", 0);	/* no return */",
+	"				}",
+	"				goto adapt;	/* root process continues spawning */",
+	"			}",
+	"			worker_pids[core_id] = is_parent;",
+	"		}",
+	"		/* note that core_id is now NCORE */",
+	"		if (proxy_pid > 0 && proxy_pid < NCORE)", /* add send-half of proxy */
+	"		{	proxy_pid_snd = fork();",
+	"			if (proxy_pid_snd == -1)",
+	"			{	Uerror(\"proxy fork failed\");",
+	"			}",
+	"			if (proxy_pid_snd == 0)",
+	"			{	start_proxy(\"-s\", worker_pids[proxy_pid]); /* no return */",
+	"		}	} /* else continue */",
+
+	"		if (is_parent > 0)",
+	"		{	core_id = 0;	/* reset core_id for root process */",
+	"		}",
+	"	} else	/* worker */",
+	"	{	static char db0[16];	/* good for up to 10^6 cores */",
+	"		static char db1[16];",
+	"adapt:		tprefix = db0; sprefix = db1;",
+	"		sprintf(tprefix, \"cpu%%d_trail\", core_id);",
+	"		sprintf(sprefix, \"cpu%%d_rst\", core_id);",
+	"		memcnt = 0;	/* count only additionally allocated memory */",
+	"	}",
+	"	signal(SIGINT, give_up);",
+	"",
+	"	if (proxy_pid == 0)		/* not in a cluster setup, pan_proxy must attach */",
+	"	{	rm_shared_segments();	/* mark all shared segments for removal on exit */",
+	"	}", /* doing it early means less chance of being unable to do this */
+	"	if (verbose)",
+	"	{	cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());",
+	"	}",
+
+	"#if defined(SEP_HEAP) && !defined(SEP_STATE)",	/* set my_heap and adjust dc_shared */
+	"	{	int i;",
+	"		volatile sh_Allocater *ptr;",
+	"		ptr = first_pool;",
+	"		for (i = 0; i < NCORE  && ptr != NULL; i++)",
+	"		{	if (i == core_id)",
+	"			{	my_heap = (char *) ptr->dc_arena;",
+	"				my_size = (long) ptr->dc_size;",
+	"				if (verbose)",
+	"				cpu_printf(\"local heap %%ld MB\\n\", my_size/(1048576));",
+	"				break;",
+	"			}",
+	"			ptr = ptr->nxt; /* local */",
+	"		}",
+	"		if (my_heap == NULL)",
+	"		{	printf(\"cpu%%d: no local heap\\n\", core_id);",
+	"			pan_exit(1);",
+	"		} /* else */",
+	"	#if defined(CYGWIN) || defined(__CYGWIN__)",
+	"		ptr = first_pool;",
+	"		for (i = 0; i < NCORE  && ptr != NULL; i++)",
+	"		{	ptr = ptr->nxt; /* local */",
+	"		}",
+	"		dc_shared = ptr; /* any remainder */",
+	"	#else",
+	"		dc_shared = NULL; /* used all mem for local heaps */",
+	"	#endif",
+	"	}",
+	"#endif",
+
+	"	if (core_id == 0 && !remote_party)",
+	"	{	new_state();		/* cpu0 explores root */",
+	"		if (verbose)",
+	"		cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), read q\\n\",",
+	"			nstates, nstates_put);",
+	"		dfs_phase2 = 1;",
+	"	}",
+	"	Read_Queue(core_id);	/* all cores */",
+	"",
+	"	if (verbose)",
+	"	{	cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",",
+	"			nstates_put, nstates_get);",
+	"	}",
+	"	if (proxy_pid != 0)",
+	"	{	rm_shared_segments();",
+	"	}",
+	"	done = 1;",
+	"	wrapup();",
+	"	exit(0);",
+	"}",
+	"",
+	"#else",
+	"int unpack_state(SM_frame *, int);",
+	"#endif",
+	"",
+	"H_el *",
+	"grab_shared(int n)",
+	"{",
+	"#ifndef SEP_STATE",
+	"	char *rval = (char *) 0;",
+	"",
+	"	if (n == 0)",
+	"	{	printf(\"cpu%%d: grab shared zero\\n\", core_id); fflush(stdout);",
+	"		return (H_el *) rval;",
+	"	} else if (n&(sizeof(void *)-1))",
+	"	{	n += sizeof(void *)-(n&(sizeof(void *)-1)); /* alignment */",
+	"	}",
+	"",
+	"#ifdef SEP_HEAP",
+	"	/* no locking */",
+	"	if (my_heap != NULL && my_size > n)",
+	"	{	rval = my_heap;",
+	"		my_heap += n;",
+	"		my_size -= n;",
+	"		goto done;",
+	"	}",
+	"#endif",
+	"",
+	"	if (!dc_shared)",
+	"	{	sudden_stop(\"pan: out of memory\");",
+	"	}",
+	"",
+	"	/* another lock is always already in effect when this is called */",
+	"	/* but not always the same lock -- i.e., on different parts of the hashtable */",
+	"	enter_critical(GLOBAL_LOCK);	/* this must be independently mutex */",
+	"#if defined(SEP_HEAP) && !defined(WIN32) && !defined(WIN64)",
+	"	{	static int noted = 0;",
+	"		if (!noted)",
+	"		{	noted = 1;",
+	"			printf(\"cpu%%d: global heap has %%ld bytes left, needed %%d\\n\",",
+	"				core_id, dc_shared?dc_shared->dc_size:0, n);",
+	"	}	}",
+	"#endif",
+	"#if 0",	/* for debugging */
+	"		if (dc_shared->pattern != 1234567)",
+	"		{	leave_critical(GLOBAL_LOCK);",
+	"			Uerror(\"overrun -- memory corruption\");",
+	"		}",
+	"#endif",
+	"		if (dc_shared->dc_size < n)",
+	"		{	if (verbose)",
+	"			{ printf(\"Next Pool %%g Mb + %%d\\n\", memcnt/(1048576.), n);",
+	"			}",
+	"			if (dc_shared->nxt == NULL",
+	"			||  dc_shared->nxt->dc_arena == NULL",
+	"			||  dc_shared->nxt->dc_size < n)",
+	"			{	printf(\"cpu%%d: memcnt %%g Mb + wanted %%d bytes more\\n\",",
+	"					core_id, memcnt / (1048576.), n);",
+	"				leave_critical(GLOBAL_LOCK);",
+	"				sudden_stop(\"out of memory -- aborting\");",
+	"				wrapup();	/* exits */",
+	"			} else",
+	"			{	dc_shared = (sh_Allocater *) dc_shared->nxt;",
+	"		}	}",
+	"",
+	"		rval = (char *) dc_shared->dc_arena;",
+	"		dc_shared->dc_arena += n;",
+	"		dc_shared->dc_size  -= (long) n;",
+	"#if 0",
+	"		if (VVERBOSE)",
+	"		printf(\"cpu%%d grab shared (%%d bytes) -- %%ld left\\n\",",
+	"			core_id, n, dc_shared->dc_size);",
+	"#endif",
+	"	leave_critical(GLOBAL_LOCK);",
+	"done:",
+	"	memset(rval, 0, n);",
+	"	memcnt += (double) n;",
+	"",
+	"	return (H_el *) rval;",
+	"#else",
+	"	return (H_el *) emalloc(n);",
+	"#endif",
+	"}",
+	"",
+	"SM_frame *",
+	"Get_Full_Frame(int n)",
+	"{	SM_frame *f;",
+	"	double cnt_start = frame_wait;",
+	"",
+	"	f = &m_workq[n][prfull[n]];",
+	"	while (f->m_vsize == 0)	/* await full slot LOCK : full frame */",
+	"	{	iam_alive();",
+	"#ifndef NGQ",
+	"	#ifndef SAFETY",
+	"		if (!a_cycles || core_id != 0)",
+	"	#endif",
+	"		if (*grcnt > 0)	/* accessed outside lock, but safe even if wrong */",
+	"		{	enter_critical(GQ_RD);	/* gq - read access */",
+	"			if (*grcnt > 0)		/* could have changed */",
+	"			{	f = &m_workq[NCORE][*grfull];	/* global q */",
+	"				if (f->m_vsize == 0)",
+	"				{	/* writer is still filling the slot */",
+	"					*gr_writemiss++;",
+	"					f = &m_workq[n][prfull[n]]; /* reset */",
+	"				} else",
+	"				{	*grfull = (*grfull+1) %% (GN_FRAMES);",
+	"						enter_critical(GQ_WR);",
+	"						*grcnt = *grcnt - 1;",
+	"						leave_critical(GQ_WR);",
+	"					leave_critical(GQ_RD);",
+	"					return f;",
+	"			}	}",
+	"			leave_critical(GQ_RD);",
+	"		}",
+	"#endif",
+	"		if (frame_wait++ - cnt_start > Delay)",
+	"		{	if (0)", /* too frequent to enable this one */
+	"			{	cpu_printf(\"timeout on q%%d -- %%u -- query %%d\\n\",",
+	"					n, f, query_in_progress);",
+	"			}",
+	"			return (SM_frame *) 0;	/* timeout */",
+	"	}	}",
+	"	iam_alive();",
+	"	if (VVERBOSE) cpu_printf(\"got frame from q%%d\\n\", n);",
+	"	prfull[n] = (prfull[n] + 1) %% (LN_FRAMES);",
+	"	enter_critical(QLOCK(n));",
+	"		prcnt[n]--; /* lock out increments */",
+	"	leave_critical(QLOCK(n));",
+	"	return f;",
+	"}",
+	"",
+	"SM_frame *",
+	"Get_Free_Frame(int n)",
+	"{	SM_frame *f;",
+	"	double cnt_start = free_wait;",
+	"",
+	"	if (VVERBOSE) { cpu_printf(\"get free frame from q%%d\\n\", n); }",
+	"",
+	"	if (n == NCORE)	/* global q */",
+	"	{	f = &(m_workq[n][lrfree]);",
+	"	} else",
+	"	{	f = &(m_workq[n][prfree[n]]);",
+	"	}",
+	"	while (f->m_vsize != 0)	/* await free slot LOCK : free slot */",
+	"	{	iam_alive();",
+	"		if (free_wait++ - cnt_start > OneSecond)",
+	"		{	if (verbose)",
+	"			{	cpu_printf(\"timeout waiting for free slot q%%d\\n\", n);",
+	"			}",
+	"			cnt_start = free_wait;",
+	"			if (someone_crashed(1))",
+	"			{	printf(\"cpu%%d: search terminated\\n\", core_id);",
+	"				sudden_stop(\"get free frame\");",
+	"				pan_exit(1);",
+	"	}	}	}",
+	"	if (n != NCORE)",
+	"	{	prfree[n] = (prfree[n] + 1) %% (LN_FRAMES);",
+	"		enter_critical(QLOCK(n));",
+	"			prcnt[n]++; /* lock out decrements */",
+	"			if (prmax[n] < prcnt[n])",
+	"			{	prmax[n] = prcnt[n];",
+	"			}",
+	"		leave_critical(QLOCK(n));",
+	"	}",
+	"	return f;",
+	"}",
+	"",
+	"#ifndef NGQ",
+	"int",
+	"GlobalQ_HasRoom(void)",
+	"{	int rval = 0;",
+	"",
+	"	gq_tries++;",
+	"	if (*grcnt < GN_FRAMES) /* there seems to be room */",
+	"	{	enter_critical(GQ_WR);	/* gq write access */",
+	"		if (*grcnt < GN_FRAMES)",
+	"		{	if (m_workq[NCORE][*grfree].m_vsize != 0)",
+	"			{	/* can happen if reader is slow emptying slot */",
+	"				*gr_readmiss++;",
+	"				goto out; /* dont wait: release lock and return */",
+	"			}",
+	"			lrfree = *grfree;	/* Get_Free_Frame use lrfree in this mode */",
+	"			*grfree = (*grfree + 1) %% GN_FRAMES;",	/* next process looks at next slot */
+	"			*grcnt = *grcnt + 1;	/* count nr of slots filled -- no additional lock needed */",
+	"			if (*grmax < *grcnt) *grmax = *grcnt;",
+	"			leave_critical(GQ_WR);	/* for short lock duration */",
+	"			gq_hasroom++;",
+	"			mem_put(NCORE);		/* copy state into reserved slot */",
+	"			rval = 1;		/* successfull handoff */",
+	"		} else",
+	"		{	gq_hasnoroom++;",
+	"out:			leave_critical(GQ_WR);",	/* should be rare */
+	"	}	}",
+	"	return rval;",
+	"}",
+	"#endif",
+	"",
+	"int",
+	"unpack_state(SM_frame *f, int from_q)",
+	"{	int i, j;",
+	"	static H_el D_State;",
+	"",
+	"	if (f->m_vsize > 0)",
+	"	{	boq   = f->m_boq;",
+	"		if (boq > 256)",
+	"		{	cpu_printf(\"saw control %%d, expected state\\n\", boq);",
+	"			return 0;",
+	"		}",
+	"		vsize = f->m_vsize;",
+	"correct:",
+	"		memcpy((uchar *) &now, (uchar *) f->m_now, vsize);",
+	"	#if !defined(NOCOMP) && !defined(HC)",
+	"		for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
+	"		{	Mask[i] = (f->m_mask[i/8] & (1<<j)) ? 1 : 0;",
+	"		}",
+	"	#endif",
+	"		if (now._nr_pr > 0)",
+	"		{	memcpy((uchar *) proc_offset, (uchar *) f->m_p_offset, now._nr_pr * sizeof(OFFT));",
+	"			memcpy((uchar *) proc_skip,   (uchar *) f->m_p_skip,   now._nr_pr * sizeof(uchar));",
+	"		}",
+	"		if (now._nr_qs > 0)",
+	"		{	memcpy((uchar *) q_offset,    (uchar *) f->m_q_offset, now._nr_qs * sizeof(OFFT));",
+	"			memcpy((uchar *) q_skip,      (uchar *) f->m_q_skip,   now._nr_qs * sizeof(uchar));",
+	"		}",
+	"#ifndef NOVSZ",
+	"		if (vsize != now._vsz)",
+	"		{	cpu_printf(\"vsize %%d != now._vsz %%d (type %%d) %%d\\n\",",
+	"				vsize, now._vsz, f->m_boq, f->m_vsize);",
+	"			vsize = now._vsz;",
+	"			goto correct;	/* rare event: a race */",
+	"		}",
+	"#endif",
+	"		hmax = max(hmax, vsize);",
+	"",
+	"		if (f != &cur_Root)",
+	"		{	memcpy((uchar *) &cur_Root, (uchar *) f, sizeof(SM_frame));",
+	"		}",
+	"",
+	"		if (((now._a_t) & 1) == 1)	/* i.e., when starting nested DFS */",
+	"		{	A_depth = depthfound = 0;",
+	"			memcpy((uchar *)&A_Root, (uchar *)&now, vsize);",
+	"		}",
+	"		nr_handoffs = f->nr_handoffs;",
+	"	} else",
+	"	{	cpu_printf(\"pan: state empty\\n\");",
+	"	}",
+	"",
+	"	depth = 0;",
+	"	trpt = &trail[1];",
+	"	trpt->tau    = f->m_tau;",
+	"	trpt->o_pm   = f->m_o_pm;",
+	"",
+	"	(trpt-1)->ostate = &D_State; /* stub */",
+	"	trpt->ostate = &D_State;",
+	"",
+	"#ifdef FULL_TRAIL",
+	"	if (upto > 0)",
+	"	{	stack_last[core_id] = (Stack_Tree *) f->m_stack;",
+	"	}",
+	"	#if defined(VERBOSE)",
+	"	if (stack_last[core_id])",
+	"	{	cpu_printf(\"%%d: UNPACK -- SET m_stack %%u (%%d,%%d)\\n\",",
+	"			depth, stack_last[core_id], stack_last[core_id]->pr,",
+	"			stack_last[core_id]->t_id);",
+	"	}",
+	"	#endif",
+	"#endif",
+	"",
+	"	if (!trpt->o_t)",
+	"	{	static Trans D_Trans;",
+	"		trpt->o_t = &D_Trans;",
+	"	}",
+	"",
+	"	#ifdef VERI",
+	"	if ((trpt->tau & 4) != 4)",
+	"	{	trpt->tau |= 4;	/* the claim moves first */",
+	"		cpu_printf(\"warning: trpt was not up to date\\n\");",
+	"	}",
+	"	#endif",
+	"",
+	"	for (i = 0; i < (int) now._nr_pr; i++)",
+	"	{	P0 *ptr = (P0 *) pptr(i);",
+	"	#ifndef NP",
+	"		if (accpstate[ptr->_t][ptr->_p])",
+	"		{	trpt->o_pm |= 2;",
+	"		}",
+	"	#else",
+	"		if (progstate[ptr->_t][ptr->_p])",
+	"		{	trpt->o_pm |= 4;",
+	"		}",
+	"	#endif",
+	"	}",
+	"",
+	"	#ifdef EVENT_TRACE",
+	"		#ifndef NP",
+	"			if (accpstate[EVENT_TRACE][now._event])",
+	"			{	trpt->o_pm |= 2;",
+	"			}",
+	"		#else",
+	"			if (progstate[EVENT_TRACE][now._event])",
+	"			{	trpt->o_pm |= 4;",
+	"			}",
+	"		#endif",
+	"	#endif",
+	"",
+	"	#if defined(C_States) && (HAS_TRACK==1)",
+	"		/* restore state of tracked C objects */",
+	"		c_revert((uchar *) &(now.c_state[0]));",
+	"		#if (HAS_STACK==1)",
+	"		c_unstack((uchar *) f->m_c_stack); /* unmatched tracked data */",
+	"		#endif",
+	"	#endif",
+	"	return 1;",
+	"}",
+	"",
+	"void",
+	"write_root(void)	/* for trail file */",
+	"{	int fd;",
+	"",
+	"	if (iterative == 0 && Nr_Trails > 1)",
+	"		sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);",
+	"	else",
+	"		sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);",
+	"",
+	"	if (cur_Root.m_vsize == 0)",
+	"	{	(void) unlink(fnm); /* remove possible old copy */",
+	"		return;	/* its the default initial state */",
+	"	}",
+	"",
+	"	if ((fd = creat(fnm, TMODE)) < 0)",
+	"	{	char *q;",
+	"		if ((q = strchr(TrailFile, \'.\')))",
+	"		{	*q = \'\\0\';		/* strip .pml */",
+	"			if (iterative == 0 && Nr_Trails-1 > 0)",
+	"				sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);",
+	"			else",
+	"				sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);",
+	"			*q = \'.\';",
+	"			fd = creat(fnm, TMODE);",
+	"		}",
+	"		if (fd < 0)",
+	"		{	cpu_printf(\"pan: cannot create %%s\\n\", fnm);",
+	"			perror(\"cause\");",
+	"			return;",
+	"	}	}",
+	"",
+	"	if (write(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))",
+	"	{	cpu_printf(\"pan: error writing %%s\\n\", fnm);",
+	"	} else",
+	"	{	cpu_printf(\"pan: wrote %%s\\n\", fnm);",
+	"	}",
+	"	close(fd);",
+	"}",
+	"",
+	"void",
+	"set_root(void)",
+	"{	int fd;",
+	"	char *q;",
+	"	char MyFile[512];",	/* enough to hold a reasonable pathname */
+	"	char MySuffix[16];",
+	"	char *ssuffix = \"rst\";",
+	"	int  try_core = 1;",
+	"",
+	"	strcpy(MyFile, TrailFile);",
+	"try_again:",
+	"	if (whichtrail > 0)",
+	"	{	sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);",
+	"		fd = open(fnm, O_RDONLY, 0);",
+	"		if (fd < 0 && (q = strchr(MyFile, \'.\')))",
+	"		{	*q = \'\\0\';	/* strip .pml */",
+	"			sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);",
+	"			*q = \'.\';",
+	"			fd = open(fnm, O_RDONLY, 0);",
+	"		}",
+	"	} else",
+	"	{	sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);",
+	"		fd = open(fnm, O_RDONLY, 0);",
+	"		if (fd < 0 && (q = strchr(MyFile, \'.\')))",
+	"		{	*q = \'\\0\';	/* strip .pml */",
+	"			sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);",
+	"			*q = \'.\';",
+	"			fd = open(fnm, O_RDONLY, 0);",
+	"	}	}",
+	"",
+	"	if (fd < 0)",
+	"	{	if (try_core < NCORE)",
+	"		{	ssuffix = MySuffix;",
+	"			sprintf(ssuffix, \"cpu%%d_rst\", try_core++);",
+	"			goto try_again;",
+	"		}",
+	"		cpu_printf(\"no file '%%s.rst' or '%%s' (not an error)\\n\", MyFile, fnm);",
+	"	} else",
+	"	{	if (read(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))",
+	"		{	cpu_printf(\"read error %%s\\n\", fnm);",
+	"			close(fd);",
+	"			pan_exit(1);",
+	"		}",
+	"		close(fd);",
+	"		(void) unpack_state(&cur_Root, -2);",
+	"#ifdef SEP_STATE",
+	"		cpu_printf(\"partial trail -- last few steps only\\n\");",
+	"#endif",
+	"		cpu_printf(\"restored root from '%%s'\\n\", fnm);",
+	"		printf(\"=====State:=====\\n\");",
+	"		{	int i, j; P0 *z;",
+	"			for (i = 0; i < now._nr_pr; i++)",
+	"			{	z = (P0 *)pptr(i);",
+	"				printf(\"proc %%2d (%%s) \", i, procname[z->_t]);",
+
+	"				for (j = 0; src_all[j].src; j++)",
+	"				if (src_all[j].tp == (int) z->_t)",
+	"				{	printf(\" %%s:%%d \",",
+	"						PanSource, src_all[j].src[z->_p]);",
+	"					break;",
+	"				}",
+	"				printf(\"(state %%d)\\n\", z->_p);",
+	"				c_locals(i, z->_t);",
+	"			}",
+	"			c_globals();",
+	"		}",
+	"		printf(\"================\\n\");",
+	"	}",
+	"}",
+	"",
+	"#ifdef USE_DISK",
+	"unsigned long dsk_written, dsk_drained;",
+	"void mem_drain(void);",
+	"#endif",
+	"",
+	"void",
+	"m_clear_frame(SM_frame *f)", /* clear room for stats */
+	"{	int i, clr_sz = sizeof(SM_results);",
+	"",
+	"	for (i = 0; i <= _NP_; i++)	/* all proctypes */",
+	"	{	clr_sz += NrStates[i]*sizeof(uchar);",
+	"	}",
+	"	memset(f, 0, clr_sz);",
+	"	/* caution if sizeof(SM_results) > sizeof(SM_frame) */",
+	"}",
+	"",
+	"#define TargetQ_Full(n)	(m_workq[n][prfree[n]].m_vsize != 0)", /* no free slot */
+	"#define TargetQ_NotFull(n)	(m_workq[n][prfree[n]].m_vsize == 0)", /* avoiding prcnt */
+	"",
+	"int",
+	"AllQueuesEmpty(void)",
+	"{	int q;",
+	"#ifndef NGQ",
+	"	if (*grcnt != 0)",
+	"	{	return 0;",
+	"	}",
+	"#endif",
+	"	for (q = 0; q < NCORE; q++)",
+	"	{	if (prcnt[q] != 0)", /* not locked, ok if race */
+	"		{	return 0;",
+	"	}	}",
+	"	return 1;",
+	"}",
+	"",
+	"void",
+	"Read_Queue(int q)",
+	"{	SM_frame   *f, *of;",
+	"	int	remember, target_q;",
+	"	SM_results *r;",
+	"	double patience = 0.0;",
+	"",
+	"	target_q = (q + 1) %% NCORE;",
+	"",
+	"	for (;;)",
+	"	{	f = Get_Full_Frame(q);",
+	"		if (!f)	/* 1 second timeout -- and trigger for Query */",
+	"		{	if (someone_crashed(2))",
+	"			{	printf(\"cpu%%d: search terminated [code %%d]\\n\",",
+	"					core_id, search_terminated?*search_terminated:-1);",
+	"				sudden_stop(\"\");",
+	"				pan_exit(1);",
+	"			}",
+	"#ifdef TESTING",
+	"	/* to profile with cc -pg and gprof pan.exe -- set handoff depth beyond maxdepth */",
+	"			exit(0);",
+	"#endif",
+	"			remember = *grfree;",
+	"			if (core_id == 0		/* root can initiate termination */",
+	"			&& remote_party == 0		/* and only the original root */",
+	"			&& query_in_progress == 0	/* unless its already in progress */",
+	"			&& AllQueuesEmpty())",
+	"			{	f = Get_Free_Frame(target_q);",
+	"				query_in_progress = 1;	/* only root process can do this */",
+	"				if (!f) { Uerror(\"Fatal1: no free slot\"); }",
+	"				f->m_boq = QUERY;	/* initiate Query */",
+	"				if (verbose)",
+	"				{  cpu_printf(\"snd QUERY to q%%d (%%d) into slot %%d\\n\",",
+	"					target_q, nstates_get + 1, prfree[target_q]-1);",
+	"				}",
+	"				f->m_vsize = remember + 1;",
+	"				/* number will not change unless we receive more states */",
+	"			} else if (patience++ > OneHour) /* one hour watchdog timer */",
+	"			{	cpu_printf(\"timeout -- giving up\\n\");",
+	"				sudden_stop(\"queue timeout\");",
+	"				pan_exit(1);",
+	"			}",
+	"			if (0) cpu_printf(\"timed out -- try again\\n\");",
+	"			continue;	",
+	"		}",
+	"		patience = 0.0; /* reset watchdog */",
+	"",
+	"		if (f->m_boq == QUERY)",
+	"		{	if (verbose)",
+	"			{	cpu_printf(\"got QUERY on q%%d (%%d <> %%d) from slot %%d\\n\",",
+	"					q, f->m_vsize, nstates_put + 1, prfull[q]-1);",
+	"				snapshot();",
+	"			}",
+	"			remember = f->m_vsize;",
+	"			f->m_vsize = 0;	/* release slot */",
+	"",
+	"			if (core_id == 0 && remote_party == 0)	/* original root cpu0 */",
+	"			{	if (query_in_progress == 1	/* didn't send more states in the interim */",
+	"				&&  *grfree + 1 == remember)	/* no action on global queue meanwhile */",
+	"				{	if (verbose) cpu_printf(\"Termination detected\\n\");",
+	"					if (TargetQ_Full(target_q))",
+	"					{	if (verbose)",
+	"						cpu_printf(\"warning: target q is full\\n\");",
+	"					}",
+	"					f = Get_Free_Frame(target_q);",
+	"					if (!f) { Uerror(\"Fatal2: no free slot\"); }",
+	"					m_clear_frame(f);",
+	"					f->m_boq = QUIT; /* send final Quit, collect stats */",
+	"					f->m_vsize = 111; /* anything non-zero will do */",
+	"					if (verbose)",
+	"					cpu_printf(\"put QUIT on q%%d\\n\", target_q);",
+	"				} else",
+	"				{	if (verbose) cpu_printf(\"Stale Query\\n\");",
+	"#ifdef USE_DISK",
+	"					mem_drain();",
+	"#endif",
+	"				}",
+	"				query_in_progress = 0;",
+	"			} else",
+	"			{	if (TargetQ_Full(target_q))",
+	"				{	if (verbose)",
+	"					cpu_printf(\"warning: forward query - target q full\\n\");",
+	"				}",
+	"				f = Get_Free_Frame(target_q);",
+	"				if (verbose)",
+	"				cpu_printf(\"snd QUERY response to q%%d (%%d <> %%d) in slot %%d\\n\",",
+	"					target_q, remember, *grfree + 1, prfree[target_q]-1);",
+	"				if (!f) { Uerror(\"Fatal4: no free slot\"); }",
+	"",
+	"				if (*grfree + 1 == remember)	/* no action on global queue */",
+	"				{	f->m_boq = QUERY;	/* forward query, to root */",
+	"					f->m_vsize = remember;",
+	"				} else",
+	"				{	f->m_boq = QUERY_F;	/* no match -- busy */",
+	"					f->m_vsize = 112;	/* anything non-zero */",
+	"#ifdef USE_DISK",
+	"					if (dsk_written != dsk_drained)",
+	"					{	mem_drain();",
+	"					}",
+	"#endif",
+	"			}	}",
+	"			continue;",
+	"		}",
+	"",
+	"		if (f->m_boq == QUERY_F)",
+	"		{	if (verbose)",
+	"			{	cpu_printf(\"got QUERY_F on q%%d from slot %%d\\n\", q, prfull[q]-1);",
+	"			}",
+	"			f->m_vsize = 0;	/* release slot */",
+	"",
+	"			if (core_id == 0 && remote_party == 0)		/* original root cpu0 */",
+	"			{	if (verbose) cpu_printf(\"No Match on Query\\n\");",
+	"				query_in_progress = 0;",
+	"			} else",
+	"			{	if (TargetQ_Full(target_q))",
+	"				{	if (verbose) cpu_printf(\"warning: forwarding query_f, target queue full\\n\");",
+	"				}",
+	"				f = Get_Free_Frame(target_q);",
+	"				if (verbose) cpu_printf(\"forward QUERY_F to q%%d into slot %%d\\n\",",
+	"						target_q, prfree[target_q]-1);",
+	"				if (!f) { Uerror(\"Fatal5: no free slot\"); }",
+	"				f->m_boq = QUERY_F;		/* cannot terminate yet */",
+	"				f->m_vsize = 113;		/* anything non-zero */",
+	"			}",
+	"#ifdef USE_DISK",
+	"			if (dsk_written != dsk_drained)",
+	"			{	mem_drain();",
+	"			}",
+	"#endif",
+	"			continue;",
+	"		}",
+	"",
+	"		if (f->m_boq == QUIT)",
+	"		{	if (0) cpu_printf(\"done -- local memcnt %%g Mb\\n\", memcnt/(1048576.));",
+	"			retrieve_info((SM_results *) f); /* collect and combine stats */",
+	"			if (verbose)",
+	"			{	cpu_printf(\"received Quit\\n\");",
+	"				snapshot();",
+	"			}",
+	"			f->m_vsize = 0;	/* release incoming slot */",
+	"			if (core_id != 0)",
+	"			{	f = Get_Free_Frame(target_q); /* new outgoing slot */",
+	"				if (!f) { Uerror(\"Fatal6: no free slot\"); }",
+	"				m_clear_frame(f);	/* start with zeroed stats */",
+	"				record_info((SM_results *) f);",
+	"				f->m_boq = QUIT;	/* forward combined results */",
+	"				f->m_vsize = 114;	/* anything non-zero */",
+	"				if (verbose>1)",
+	"				cpu_printf(\"fwd Results to q%%d\\n\", target_q);",
+	"			}",
+	"			break;			/* successful termination */",
+	"		}",
+	"",
+	"		/* else: 0<= boq <= 255, means STATE transfer */",
+	"		if (unpack_state(f, q) != 0)",
+	"		{	nstates_get++;",
+	"			f->m_vsize = 0;	/* release slot */",
+	"			if (VVERBOSE) cpu_printf(\"Got state\\n\");",
+	"",
+	"			if (search_terminated != NULL",
+	"			&&  *search_terminated == 0)",
+	"			{	new_state();	/* explore successors */",
+	"				memset((uchar *) &cur_Root, 0, sizeof(SM_frame));	/* avoid confusion */",
+	"			} else",
+	"			{	pan_exit(0);",
+	"			}",
+	"		} else",
+	"		{	pan_exit(0);",
+	"	}	}",
+	"	if (verbose) cpu_printf(\"done got %%d put %%d\\n\", nstates_get, nstates_put);",
+	"	sleep_report();",
+	"}",
+	"",
+	"void",
+	"give_up(int unused_x)",
+	"{",
+	"	if (search_terminated != NULL)",
+	"	{	*search_terminated |= 32;	/* give_up */",
+	"	}",
+	"	if (!writing_trail)",
+	"	{	was_interrupted = 1;",
+	"		snapshot();",
+	"		cpu_printf(\"Give Up\\n\");",
+	"		sleep_report();",
+	"		pan_exit(1);",
+	"	} else /* we are already terminating */",
+	"	{	cpu_printf(\"SIGINT\\n\");",
+	"	}",
+	"}",
+	"",
+	"void",
+	"check_overkill(void)",
+	"{",
+	"	vmax_seen = (vmax_seen + 7)/ 8;",
+	"	vmax_seen *= 8;	/* round up to a multiple of 8 */",
+	"",
+	"	if (core_id == 0",
+	"	&&  !remote_party",
+	"	&&  nstates_put > 0",
+	"	&&  VMAX - vmax_seen > 8)",
+	"	{",
+	"#ifdef BITSTATE",
+	"		printf(\"cpu0: max VMAX value seen in this run: \");",
+	"#else",
+	"		printf(\"cpu0: recommend recompiling with \");",
+	"#endif",
+	"		printf(\"-DVMAX=%%d\\n\", vmax_seen);",
+	"	}",
+	"}",
+	"",
+	"void",
+	"mem_put(int q)	/* handoff state to other cpu, workq q */",
+	"{	SM_frame *f;",
+	"	int i, j;",
+	"",
+	"	if (vsize > VMAX)",
+	"	{	vsize = (vsize + 7)/8; vsize *= 8; /* round up */",
+	"		printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", (int) vsize);",
+	"		Uerror(\"aborting\");",
+	"	}",
+	"	if (now._nr_pr > PMAX)",
+	"	{	printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);",
+	"		Uerror(\"aborting\");",
+	"	}",
+	"	if (now._nr_qs > QMAX)",
+	"	{	printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);",
+	"		Uerror(\"aborting\");",
+	"	}",
+	"	if (vsize > vmax_seen) vmax_seen = vsize;",
+	"	if (now._nr_pr > pmax_seen) pmax_seen = now._nr_pr;",
+	"	if (now._nr_qs > qmax_seen) qmax_seen = now._nr_qs;",
+	"",
+	"	f = Get_Free_Frame(q);	/* not called in likely deadlock states */",
+	"	if (!f) { Uerror(\"Fatal3: no free slot\"); }",
+	"",
+	"	if (VVERBOSE) cpu_printf(\"putting state into q%%d\\n\", q);",
+	"",
+	"	memcpy((uchar *) f->m_now,  (uchar *) &now, vsize);",
+	"#if !defined(NOCOMP) && !defined(HC)",
+	"	memset((uchar *) f->m_mask, 0, (VMAX+7)/8 * sizeof(char));",
+	"	for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
+	"	{	if (Mask[i])",
+	"		{	f->m_mask[i/8] |= (1<<j);",
+	"	}	}",
+	"#endif",
+	"	if (now._nr_pr > 0)",
+	"	{ memcpy((uchar *) f->m_p_offset, (uchar *) proc_offset, now._nr_pr * sizeof(OFFT));",
+	"	  memcpy((uchar *) f->m_p_skip,   (uchar *) proc_skip,   now._nr_pr * sizeof(uchar));",
+	"	}",
+	"	if (now._nr_qs > 0)",
+	"	{ memcpy((uchar *) f->m_q_offset, (uchar *) q_offset, now._nr_qs * sizeof(OFFT));",
+	"	  memcpy((uchar *) f->m_q_skip,   (uchar *) q_skip,   now._nr_qs * sizeof(uchar));",
+	"	}",
+	"#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)",
+	"	c_stack((uchar *) f->m_c_stack); /* save unmatched tracked data */",
+	"#endif",
+	"#ifdef FULL_TRAIL",
+	"	f->m_stack = stack_last[core_id];",
+	"#endif",
+	"	f->nr_handoffs = nr_handoffs+1;",
+	"	f->m_tau    = trpt->tau;",
+	"	f->m_o_pm   = trpt->o_pm;",
+	"	f->m_boq    = boq;",
+	"	f->m_vsize  = vsize;	/* must come last - now the other cpu can see it */",
+	"",
+	"	if (query_in_progress == 1)",
+	"		query_in_progress = 2;	/* make sure we know, if a query makes the rounds */",
+	"	nstates_put++;",
+	"}",
+	"",
+	"#ifdef USE_DISK",
+	"int Dsk_W_Nr, Dsk_R_Nr;",
+	"int dsk_file = -1, dsk_read = -1;",
+	"unsigned long dsk_written, dsk_drained;",
+	"char dsk_name[512];",
+	"",
+	"#ifndef BFS_DISK",
+	"#if defined(WIN32) || defined(WIN64)",
+	"	#define RFLAGS	(O_RDONLY|O_BINARY)",
+	"	#define WFLAGS	(O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)",
+	"#else",
+	"	#define RFLAGS	(O_RDONLY)",
+	"	#define WFLAGS	(O_CREAT|O_WRONLY|O_TRUNC)",
+	"#endif",
+	"#endif",
+	"",
+	"void",
+	"dsk_stats(void)",
+	"{	int i;",
+	"",
+	"	if (dsk_written > 0)",
+	"	{	cpu_printf(\"dsk_written %%d states in %%d files\\ncpu%%d: dsk_drained %%6d states\\n\",",
+	"			dsk_written, Dsk_W_Nr, core_id, dsk_drained);",
+	"		close(dsk_read);",
+	"		close(dsk_file);",
+	"		for (i = 0; i < Dsk_W_Nr; i++)",
+	"		{	sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", i, core_id);",
+	"			unlink(dsk_name);",
+	"	}	}",
+	"}",
+	"",
+	"void",
+	"mem_drain(void)",
+	"{	SM_frame *f, g;",
+	"	int q = (core_id + 1) %% NCORE;	/* target q */",
+	"	int sz;",
+	"",
+	"	if (dsk_read < 0",
+	"	||  dsk_written <= dsk_drained)",
+	"	{	return;",
+	"	}",
+	"",
+	"	while (dsk_written > dsk_drained",
+	"	&& TargetQ_NotFull(q))",
+	"	{	f = Get_Free_Frame(q);",
+	"		if (!f) { Uerror(\"Fatal: unhandled condition\"); }",
+	"",
+	"		if ((dsk_drained+1)%%MAX_DSK_FILE == 0)	/* 100K states max per file */",
+	"		{	(void) close(dsk_read); 	/* close current read handle */",
+	"			sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr++, core_id);",
+	"			(void) unlink(dsk_name);	/* remove current file */",
+	"			sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr, core_id);",
+	"			cpu_printf(\"reading %%s\\n\", dsk_name);",
+	"			dsk_read = open(dsk_name, RFLAGS); /* open next file */",
+	"			if (dsk_read < 0)",
+	"			{	Uerror(\"could not open dsk file\");",
+	"		}	}",
+	"		if (read(dsk_read, &g, sizeof(SM_frame)) != sizeof(SM_frame))",
+	"		{	Uerror(\"bad dsk file read\");",
+	"		}",
+	"		sz = g.m_vsize;",
+	"		g.m_vsize = 0;",
+	"		memcpy(f, &g, sizeof(SM_frame));",
+	"		f->m_vsize = sz;	/* last */",
+	"",
+	"		dsk_drained++;",
+	"	}",
+	"}",
+	"",
+	"void",
+	"mem_file(void)",
+	"{	SM_frame f;",
+	"	int i, j, q = (core_id + 1) %% NCORE;	/* target q */",
+	"",
+	"	if (vsize > VMAX)",
+	"	{	printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", vsize);",
+	"		Uerror(\"aborting\");",
+	"	}",
+	"	if (now._nr_pr > PMAX)",
+	"	{	printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);",
+	"		Uerror(\"aborting\");",
+	"	}",
+	"	if (now._nr_qs > QMAX)",
+	"	{	printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);",
+	"		Uerror(\"aborting\");",
+	"	}",
+	"",
+	"	if (VVERBOSE) cpu_printf(\"filing state for q%%d\\n\", q);",
+	"",
+	"	memcpy((uchar *) f.m_now,  (uchar *) &now, vsize);",
+	"#if !defined(NOCOMP) && !defined(HC)",
+	"	memset((uchar *) f.m_mask, 0, (VMAX+7)/8 * sizeof(char));",
+	"	for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
+	"	{	if (Mask[i])",
+	"		{	f.m_mask[i/8] |= (1<<j);",
+	"	}	}",
+	"#endif",
+	"	if (now._nr_pr > 0)",
+	"	{	memcpy((uchar *)f.m_p_offset, (uchar *)proc_offset, now._nr_pr*sizeof(OFFT));",
+	"		memcpy((uchar *)f.m_p_skip,   (uchar *)proc_skip,   now._nr_pr*sizeof(uchar));",
+	"	}",
+	"	if (now._nr_qs > 0)",
+	"	{	memcpy((uchar *) f.m_q_offset, (uchar *) q_offset, now._nr_qs*sizeof(OFFT));",
+	"		memcpy((uchar *) f.m_q_skip,   (uchar *) q_skip,   now._nr_qs*sizeof(uchar));",
+	"	}",
+	"#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)",
+	"	c_stack((uchar *) f.m_c_stack); /* save unmatched tracked data */",
+	"#endif",
+	"#ifdef FULL_TRAIL",
+	"	f.m_stack  = stack_last[core_id];",
+	"#endif",
+	"	f.nr_handoffs = nr_handoffs+1;",
+	"	f.m_tau    = trpt->tau;",
+	"	f.m_o_pm   = trpt->o_pm;",
+	"	f.m_boq    = boq;",
+	"	f.m_vsize  = vsize;",
+	"",
+	"	if (query_in_progress == 1)",
+	"	{	query_in_progress = 2;",
+	"	}",
+	"	if (dsk_file < 0)",
+	"	{	sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr, core_id);",
+	"		dsk_file = open(dsk_name, WFLAGS, 0644);",
+	"		dsk_read = open(dsk_name, RFLAGS);",
+	"		if (dsk_file < 0 || dsk_read < 0)",
+	"		{	cpu_printf(\"File: <%%s>\\n\", dsk_name);",
+	"			Uerror(\"cannot open diskfile\");",
+	"		}",
+	"		Dsk_W_Nr++; /* nr of next file to open */",
+	"		cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);",
+	"	} else if ((dsk_written+1)%%MAX_DSK_FILE == 0)",
+	"	{	close(dsk_file); /* close write handle */",
+	"		sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr++, core_id);",
+	"		dsk_file = open(dsk_name, WFLAGS, 0644);",
+	"		if (dsk_file < 0)",
+	"		{	cpu_printf(\"File: <%%s>\\n\", dsk_name);",
+	"			Uerror(\"aborting: cannot open new diskfile\");",
+	"		}",
+	"		cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);",
+	"	}",
+	"	if (write(dsk_file, &f, sizeof(SM_frame)) != sizeof(SM_frame))",
+	"	{	Uerror(\"aborting -- disk write failed (disk full?)\");",
+	"	}",
+	"	nstates_put++;",
+	"	dsk_written++;",
+	"}",
+	"#endif",
+	"",
+	"int",
+	"mem_hand_off(void)",
+	"{",
+	"	if (search_terminated == NULL",
+	"	||  *search_terminated != 0)	/* not a full crash check */",
+	"	{	pan_exit(0);",
+	"	}",
+	"	iam_alive();		/* on every transition of Down */",
+	"#ifdef USE_DISK",
+	"	mem_drain();		/* maybe call this also on every Up */",
+	"#endif",
+	"	if (depth > z_handoff	/* above handoff limit */",
+	"#ifndef SAFETY",
+	"	&&  !a_cycles		/* not in liveness mode */",
+	"#endif",
+	"#if SYNC",
+	"	&&  boq == -1		/* not mid-rv */",
+	"#endif",
+	"#ifdef VERI",
+	"	&&  (trpt->tau&4)	 /* claim moves first  */",
+	"	&&  !((trpt-1)->tau&128) /* not a stutter move */",
+	"#endif",
+	"	&&  !(trpt->tau&8))	/* not an atomic move */",
+	"	{	int q = (core_id + 1) %% NCORE;	/* circular handoff */",
+	"	#ifdef GENEROUS",
+	"		if (prcnt[q] < LN_FRAMES)", /* not the best strategy */
+	"	#else",
+	"		if (TargetQ_NotFull(q)",
+	"		&& (dfs_phase2 == 0 || prcnt[core_id] > 0))", /* not locked, ok if race */
+	"	#endif",
+	"		{	mem_put(q);",	/* only 1 writer: lock-free */
+	"			return 1;",
+	"		}",
+	"		{	int rval;",
+	"	#ifndef NGQ",
+	"			rval = GlobalQ_HasRoom();",
+	"	#else",
+	"			rval = 0;",
+	"	#endif",
+	"	#ifdef USE_DISK",
+	"			if (rval == 0)",
+	"			{	void mem_file(void);",
+	"				mem_file();",
+	"				rval = 1;",
+	"			}",
+	"	#endif",
+	"			return rval;",
+	"		}",
+	"	}",
+	"	return 0; /* i.e., no handoff */",
+	"}",
+	"",
+	"void",
+	"mem_put_acc(void)	/* liveness mode */",
+	"{	int q = (core_id + 1) %% NCORE;",
+	"",
+	"	if (search_terminated == NULL",
+	"	||  *search_terminated != 0)",
+	"	{	pan_exit(0);",
+	"	}",
+	"#ifdef USE_DISK",
+	"	mem_drain();",
+	"#endif",
+	"	/* some tortured use of preprocessing: */",
+	"#if !defined(NGQ) || defined(USE_DISK)",
+	"	if (TargetQ_Full(q))",
+	"	{",
+	"#endif",
+	"#ifndef NGQ",
+	"		if (GlobalQ_HasRoom())",
+	"		{	return;",
+	"		}",
+	"#endif",
+	"#ifdef USE_DISK",
+	"		mem_file();",
+	"	} else",
+	"#else",
+	"	#if !defined(NGQ) || defined(USE_DISK)",
+	"	}",
+	"	#endif",
+	"#endif",
+	"	{	mem_put(q);",
+	"	}",
+	"}",
+	"",
+	"#if defined(WIN32) || defined(WIN64)", /* visual studio */
+	"void",
+	"init_shm(void)		/* initialize shared work-queues */",
+	"{	char	key[512];",
+	"	int	n, m;",
+	"	int	must_exit = 0;",
+	"",
+	"	if (core_id == 0 && verbose)",
+	"	{	printf(\"cpu0: step 3: allocate shared work-queues %%g Mb\\n\",",
+	"			((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.));",
+	"	}",
+	"	for (m = 0; m < NR_QS; m++)	/* last q is global 1 */",
+	"	{	double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;",
+	"		sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, m);",
+	"		if (core_id == 0)",	/* root process creates shared memory segments */
+	"		{	shmid[m] = CreateFileMapping(",
+	"				INVALID_HANDLE_VALUE,	/* use paging file */",
+	"				NULL,			/* default security */",
+	"				PAGE_READWRITE,		/* access permissions */",
+	"				0,			/* high-order 4 bytes */",
+	"				qsize,			/* low-order bytes, size in bytes */",
+	"				key);			/* name */",
+	"		} else			/* worker nodes just open these segments */",
+	"		{	shmid[m] = OpenFileMapping(",
+	"				FILE_MAP_ALL_ACCESS,	/* read/write access */",
+	"				FALSE,			/* children do not inherit handle */",
+	"				key);",
+	"		}",
+	"		if (shmid[m] == NULL)",
+	"		{	fprintf(stderr, \"cpu%%d: could not create or open shared queues\\n\",",
+	"				core_id);",
+	"			must_exit = 1;",
+	"			break;",
+	"		}",
+	"		/* attach: */",
+	"		shared_mem[m] = (char *) MapViewOfFile(shmid[m], FILE_MAP_ALL_ACCESS, 0, 0, 0);",
+	"		if (shared_mem[m] == NULL)",
+	"		{ fprintf(stderr, \"cpu%%d: cannot attach shared q%%d (%%d Mb)\\n\",",
+	"			core_id, m+1, (int) (qsize/(1048576.)));",
+	"		  must_exit = 1;",
+	"		  break;",
+	"		}",
+	"",
+	"		memcnt += qsize;",
+	"",
+	"		m_workq[m] = (SM_frame *) shared_mem[m];",
+	"		if (core_id == 0)",
+	"		{	int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;",
+	"			for (n = 0; n < nframes; n++)",
+	"			{	m_workq[m][n].m_vsize = 0;",
+	"				m_workq[m][n].m_boq = 0;",
+	"	}	}	}",
+	"",
+	"	if (must_exit)",
+	"	{	fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+	"		pan_exit(1);	/* calls cleanup_shm */",
+	"	}",
+	"}",
+	"",
+	"static uchar *",
+	"prep_shmid_S(size_t n)		/* either sets SS or H_tab, WIN32/WIN64 */",
+	"{	char	*rval;",
+	"#ifndef SEP_STATE",
+	"	char	key[512];",
+	"",
+	"	if (verbose && core_id == 0)",
+	"	{",
+	"	#ifdef BITSTATE",
+	"		printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",",
+	"			(double) n / (1048576.));",
+	"	#else",
+	"		printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",",
+	"			(double) n / (1048576.));",
+	"	#endif",
+	"	}",
+	"	#ifdef MEMLIM",
+	"	if (memcnt + (double) n > memlim)",
+	"	{	printf(\"cpu%%d: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",",
+	"			core_id, memcnt/1024., n/1024, memlim/(1048576.));",
+	"		printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);",
+	"		exit(1);",
+	"	}",
+	"	#endif",
+	"",
+	"	/* make key different from queues: */",
+	"	sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+2); /* different from qs */",
+	"",
+	"	if (core_id == 0)	/* root */",
+	"	{	shmid_S = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,",
+	"#ifdef WIN64",
+	"			PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);",
+	"#else",
+	"			PAGE_READWRITE, 0, n, key);",
+	"#endif",
+	"		memcnt += (double) n;",
+	"	} else			/* worker */",
+	"	{	shmid_S = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);",
+	"	}",
+
+	"	if (shmid_S == NULL)",
+	"	{",
+	"	#ifdef BITSTATE",
+	"		fprintf(stderr, \"cpu%%d: cannot %%s shared bitstate\",",
+	"			core_id, core_id?\"open\":\"create\");",
+	"	#else",
+	"		fprintf(stderr, \"cpu%%d: cannot %%s shared hashtable\",",
+	"			core_id, core_id?\"open\":\"create\");",
+	"	#endif",
+	"		fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+	"		pan_exit(1);",
+	"	}",
+	"",
+	"	rval = (char *) MapViewOfFile(shmid_S, FILE_MAP_ALL_ACCESS, 0, 0, 0);	/* attach */",
+	"	if ((char *) rval == NULL)",
+	"	{ fprintf(stderr, \"cpu%%d: cannot attach shared bitstate or hashtable\\n\", core_id);",
+	"	  fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+	"	  pan_exit(1);",
+	"	}",
+	"#else",
+	"	rval = (char *) emalloc(n);",
+	"#endif",
+	"	return (uchar *) rval;",
+	"}",
+	"",
+	"static uchar *",
+	"prep_state_mem(size_t n)		/* WIN32/WIN64 sets memory arena for states */",
+	"{	char	*rval;",
+	"	char	key[512];",
+	"	static int cnt = 3;		/* start larger than earlier ftok calls */",
+	"",
+	"	if (verbose && core_id == 0)",
+	"	{	printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%g Mb\\n\",",
+	"			cnt-3, (double) n / (1048576.));",
+	"	}",
+	"	#ifdef MEMLIM",
+	"	if (memcnt + (double) n > memlim)",
+	"	{	printf(\"cpu%%d: error: M %%.0f + %%.0f exceeds memory limit of %%.0f Kb\\n\",",
+	"			core_id, memcnt/1024.0, (double) n/1024.0, memlim/1024.0);",
+	"		return NULL;",
+	"	}",
+	"	#endif",
+	"",
+	"	sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+cnt); cnt++;",
+	"",
+	"	if (core_id == 0)",
+	"	{	shmid_M = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,",
+	"#ifdef WIN64",
+	"			PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);",
+	"#else",
+	"			PAGE_READWRITE, 0, n, key);",
+	"#endif",
+	"	} else",
+	"	{	shmid_M = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);",
+	"	}",
+	"	if (shmid_M == NULL)",
+	"	{	printf(\"cpu%%d: failed to get pool of shared memory nr %%d of size %%d\\n\",",
+	"			core_id, cnt-3, n);",
+	"		printf(\"pan: check './pan --' for usage details\\n\");",
+	"		return NULL;",
+	"	}",
+	"	rval = (char *) MapViewOfFile(shmid_M, FILE_MAP_ALL_ACCESS, 0, 0, 0);	/* attach */",
+	"",
+	"	if (rval == NULL)",
+	"	{ printf(\"cpu%%d: failed to attach pool of shared memory nr %%d of size %%d\\n\",",
+	"		core_id, cnt-3, n);",
+	"	  return NULL;",
+	"	}",
+	"	return (uchar *) rval;",
+	"}",
+	"",
+	"void",
+	"init_HT(unsigned long n)	/* WIN32/WIN64 version */",
+	"{	volatile char	*x;",
+	"	double  get_mem;",
+	"#ifndef SEP_STATE",
+	"	char	*dc_mem_start;",
+	"#endif",
+	"	if (verbose) printf(\"cpu%%d: initialization for Windows\\n\", core_id);",
+	"",
+"#ifdef SEP_STATE",
+	" #ifndef MEMLIM",
+	"	if (verbose)",
+	"	{	printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");",
+	"	}",
+	" #else",
+	"	if (verbose)",
+	"	printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",",
+	"		MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.));",
+	"#endif",
+	"	get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *)+ 4*sizeof(void *) + 2*sizeof(double);",
+	"	/* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */",
+	"	get_mem += 4 * NCORE * sizeof(void *);", /* prfree, prfull, prcnt, prmax */
+	" #ifdef FULL_TRAIL",
+	"	get_mem += (NCORE) * sizeof(Stack_Tree *);",
+	"	/* NCORE * stack_last */",
+	" #endif",
+	"	x = (volatile char *) prep_state_mem((size_t) get_mem);",
+	"	shmid_X = (void *) x;",
+	"	if (x == NULL)",
+	"	{	printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");",
+	"		exit(1);",
+	"	}",
+	"	search_terminated = (volatile unsigned int *) x; /* comes first */",
+	"	x += sizeof(void *); /* maintain alignment */",
+	"",
+	"	is_alive   = (volatile double *) x;",
+	"	x += NCORE * sizeof(double);",
+	"",
+	"	sh_lock   = (volatile int *) x;",
+	"	x += CS_NR * sizeof(void *); /* allow 1 word per entry */",
+	"",
+	"	grfree    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	grfull    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	grcnt    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	grmax    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	prfree = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	prfull = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	prcnt = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	prmax = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	gr_readmiss    = (volatile double *) x;",
+	"	x += sizeof(double);",
+	"	gr_writemiss    = (volatile double *) x;",
+	"	x += sizeof(double);",
+	"",
+	"	#ifdef FULL_TRAIL",
+	"		stack_last = (volatile Stack_Tree **) x;",
+	"		x += NCORE * sizeof(Stack_Tree *);",
+	"	#endif",
+	"",
+	"	#ifndef BITSTATE",
+	"		H_tab = (H_el **) emalloc(n);",
+	"	#endif",
+"#else",
+	"	#ifndef MEMLIM",
+	"		#warning MEMLIM not set",	/* cannot happen */
+	"		#define MEMLIM	(2048)",
+	"	#endif",
+	"",
+	"	if (core_id == 0 && verbose)",
+	"		printf(\"cpu0: step 0: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb) = %%g Mb for state storage\\n\",",
+	"		MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),",
+	"		(memlim - memcnt - (double) n - ((double) NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));",
+	"	#ifndef BITSTATE",
+	"		H_tab = (H_el **) prep_shmid_S((size_t) n);	/* hash_table */",
+	"	#endif",
+	"	get_mem = memlim - memcnt - ((double) NCORE) * LWQ_SIZE - GWQ_SIZE;",
+	"	if (get_mem <= 0)",
+	"	{	Uerror(\"internal error -- shared state memory\");",
+	"	}",
+	"",
+	"	if (core_id == 0 && verbose)",
+	"	{	printf(\"cpu0: step 2: shared state memory %%g Mb\\n\",",
+	"			get_mem/(1048576.));",
+	"	}",
+	"	x = dc_mem_start = (char *) prep_state_mem((size_t) get_mem);	/* for states */",
+	"	if (x == NULL)",
+	"	{	printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);",
+	"		exit(1);",
+	"	}",
+	"",
+	"	search_terminated = (volatile unsigned int *) x; /* comes first */",
+	"	x += sizeof(void *); /* maintain alignment */",
+	"",
+	"	is_alive   = (volatile double *) x;",
+	"	x += NCORE * sizeof(double);",
+	"",
+	"	sh_lock   = (volatile int *) x;",
+	"	x += CS_NR * sizeof(int);",
+	"",
+	"	grfree    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	grfull    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	grcnt    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	grmax    = (volatile int *) x;",
+	"	x += sizeof(void *);",
+	"	prfree = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	prfull = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	prcnt = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	prmax = (volatile int *) x;",
+	"	x += NCORE * sizeof(void *);",
+	"	gr_readmiss = (volatile double *) x;",
+	"	x += sizeof(double);",
+	"	gr_writemiss = (volatile double *) x;",
+	"	x += sizeof(double);",
+	"",
+	" #ifdef FULL_TRAIL",
+	"	stack_last = (volatile Stack_Tree **) x;",
+	"	x += NCORE * sizeof(Stack_Tree *);",
+	" #endif",
+	"	if (((long)x)&(sizeof(void *)-1))	/* word alignment */",
+	"	{	x += sizeof(void *)-(((long)x)&(sizeof(void *)-1)); /* 64-bit align */",
+	"	}",
+	"",
+	"	#ifdef COLLAPSE",
+	"	ncomps = (unsigned long *) x;",
+	"	x += (256+2) * sizeof(unsigned long);",
+	"	#endif",
+	"",
+	"	dc_shared = (sh_Allocater *) x; /* in shared memory */",
+	"	x += sizeof(sh_Allocater);",
+	"",
+	"	if (core_id == 0)	/* root only */",
+	"	{	dc_shared->dc_id     = shmid_M;",
+	"		dc_shared->dc_start  = (void *) dc_mem_start;",
+	"		dc_shared->dc_arena  = x;",
+	"		dc_shared->pattern   = 1234567;",
+	"		dc_shared->dc_size   = (long) get_mem - (long) (x - dc_mem_start);",
+	"		dc_shared->nxt       = NULL;",
+	"	}",
+"#endif",
+	"}",
+	"",
+	"#if defined(WIN32) || defined(WIN64) || defined(__i386__) || defined(__x86_64__)",
+	"extern BOOLEAN InterlockedBitTestAndSet(LONG volatile* Base, LONG Bit);",
+	"int",
+	"tas(volatile LONG *s)", /* atomic test and set */
+	"{	return InterlockedBitTestAndSet(s, 1);",
+	"}",
+	"#else",
+	"	#error missing definition of test and set operation for this platform",
+	"#endif",
+	"",
+	"void",
+	"cleanup_shm(int val)",
+	"{	int m;",
+	"	static int nibis = 0;",
+	"",
+	"	if (nibis != 0)",
+	"	{	printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);",
+	"		return;",
+	"	} else",
+	"	{	nibis = 1;",
+	"	}",
+	"	if (search_terminated != NULL)",
+	"	{	*search_terminated |= 16; /* cleanup_shm */",
+	"	}",
+	"",
+	"	for (m = 0; m < NR_QS; m++)",
+	"	{	if (shmid[m] != NULL)",
+	"		{	UnmapViewOfFile((char *) shared_mem[m]);",
+	"			CloseHandle(shmid[m]);",
+	"	}	}",
+	"#ifdef SEP_STATE",
+	"	UnmapViewOfFile((void *) shmid_X);",
+	"	CloseHandle((void *) shmid_M);",
+	"#else",
+	"	#ifdef BITSTATE",
+	"		if (shmid_S != NULL)",
+	"		{	UnmapViewOfFile(SS);",
+	"			CloseHandle(shmid_S);",
+	"		}",
+	"	#else",
+	"		if (core_id == 0 && verbose)",
+	"		{	printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",",
+	"				dc_shared->dc_size / (long)(1048576));",
+	"		}",
+	"		if (shmid_S != NULL)",
+	"		{	UnmapViewOfFile(H_tab);",
+	"			CloseHandle(shmid_S);",
+	"		}",
+	"		shmid_M = (void *) (dc_shared->dc_id);",
+	"		UnmapViewOfFile((char *) dc_shared->dc_start);",
+	"		CloseHandle(shmid_M);",
+	"	#endif",
+	"#endif",
+	"	/* detached from shared memory - so cannot use cpu_printf */",
+	"	if (verbose)",
+	"	{	printf(\"cpu%%d: done -- got %%d states from queue\\n\",",
+	"			core_id, nstates_get);",
+	"	}",
+	"}",
+	"",
+	"void",
+	"mem_get(void)",
+	"{	SM_frame   *f;",
+	"	int is_parent;",
+	"",
+	"#if defined(MA) && !defined(SEP_STATE)",
+	"	#error MA requires SEP_STATE in multi-core mode",
+	"#endif",
+	"#ifdef BFS",
+	"	#error instead of -DNCORE -DBFS use -DBFS_PAR",
+	"#endif",
+	"#ifdef SC",
+	"	#error SC is not supported in multi-core mode",
+	"#endif",
+	"	init_shm();	/* we are single threaded when this starts */",
+	"	signal(SIGINT, give_up);	/* windows control-c interrupt */",
+	"",
+	"	if (core_id == 0 && verbose)",
+	"	{	printf(\"cpu0: step 4: creating additional workers (proxy %%d)\\n\",",
+	"			proxy_pid);",
+	"	}",
+	"#if 0",
+	"	if NCORE > 1 the child or the parent should fork N-1 more times",
+	"	the parent is the only process with core_id == 0 and is_parent > 0",
+	"	the others (workers) have is_parent = 0 and core_id = 1..NCORE-1",
+	"#endif",
+	"	if (core_id == 0)			/* root starts up the workers */",
+	"	{	worker_pids[0] = (DWORD) getpid();	/* for completeness */",
+	"		while (++core_id < NCORE)	/* first worker sees core_id = 1 */",
+	"		{	char cmdline[64];",
+	"			STARTUPINFO si = { sizeof(si) };",
+	"			PROCESS_INFORMATION pi;",
+	"",
+	"			if (proxy_pid == core_id)	/* always non-zero */",
+	"			{	sprintf(cmdline, \"pan_proxy.exe -r %%s-Q%%d -Z%%d\",",
+	"					o_cmdline, getpid(), core_id);",
+	"			} else",
+	"			{	sprintf(cmdline, \"pan.exe %%s-Q%%d -Z%%d\",",
+	"					o_cmdline, getpid(), core_id);",
+	"			}",
+	"			if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);",
+	"",
+	"			is_parent = CreateProcess(0, cmdline, 0, 0, FALSE, 0, 0, 0, &si, &pi);",
+	"			if (is_parent == 0)",
+	"			{	Uerror(\"fork failed\");",
+	"			}",
+	"			worker_pids[core_id] = pi.dwProcessId;",
+	"			worker_handles[core_id] = pi.hProcess;",
+	"			if (verbose)",
+	"			{	cpu_printf(\"created core %%d, pid %%d\\n\",",
+	"					core_id, pi.dwProcessId);",
+	"			}",
+	"			if (proxy_pid == core_id)	/* we just created the receive half */",
+	"			{	/* add proxy send, store pid in proxy_pid_snd */",
+	"				sprintf(cmdline, \"pan_proxy.exe -s %%s-Q%%d -Z%%d -Y%%d\",",
+	"					o_cmdline, getpid(), core_id, worker_pids[proxy_pid]);",
+	"				if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);",
+	"				is_parent = CreateProcess(0, cmdline, 0,0, FALSE, 0,0,0, &si, &pi);",
+	"				if (is_parent == 0)",
+	"				{	Uerror(\"fork failed\");",
+	"				}",
+	"				proxy_pid_snd = pi.dwProcessId;",
+	"				proxy_handle_snd = pi.hProcess;",
+	"				if (verbose)",
+	"				{	cpu_printf(\"created core %%d, pid %%d (send proxy)\\n\",",
+	"						core_id, pi.dwProcessId);",
+	"		}	}	}",
+	"		core_id = 0;		/* reset core_id for root process */",
+	"	} else	/* worker */",
+	"	{	static char db0[16];	/* good for up to 10^6 cores */",
+	"		static char db1[16];",
+	"		tprefix = db0; sprefix = db1;",
+	"		sprintf(tprefix, \"cpu%%d_trail\", core_id);	/* avoid conflicts on file access */",
+	"		sprintf(sprefix, \"cpu%%d_rst\", core_id);",
+	"		memcnt = 0;	/* count only additionally allocated memory */",
+	"	}",
+	"	if (verbose)",
+	"	{	cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());",
+	"	}",
+	"	if (core_id == 0 && !remote_party)",
+	"	{	new_state();	/* root starts the search */",
+	"		if (verbose)",
+	"		cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), start reading q\\n\",",
+	"			nstates, nstates_put);",
+	"		dfs_phase2 = 1;",
+	"	}",
+	"	Read_Queue(core_id);	/* all cores */",
+	"",
+	"	if (verbose)",
+	"	{	cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",",
+	"			nstates_put, nstates_get);",
+	"	}",
+	"	done = 1;",
+	"	wrapup();",
+	"	exit(0);",
+	"}",
+	"#endif", /* WIN32 || WIN64 */
+	"",
+	"#ifdef BITSTATE",
+	"void",
+	"init_SS(unsigned long n)",
+	"{",
+	"	SS = (uchar *) prep_shmid_S((size_t) n);",
+	"	init_HT(0L);", /* locks and shared memory for Stack_Tree allocations */
+	"}",
+	"#endif", /* BITSTATE */
+	"",
+	"#endif", /* NCORE>1 */
+	0,
+};
--- /dev/null
+++ b/sys/src/cmd/spin/pangen7.c
@@ -1,0 +1,923 @@
+/***** spin: pangen7.c *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include "spin.h"
+#include "y.tab.h"
+#include <assert.h>
+#ifndef PC
+#include <unistd.h>
+#endif
+
+extern ProcList	*rdy;
+extern Element *Al_El;
+extern int nclaims, verbose, Strict;
+extern short has_accept;
+
+typedef struct Succ_List Succ_List;
+typedef struct SQueue SQueue;
+typedef struct OneState OneState;
+typedef struct State_Stack State_Stack;
+typedef struct Guard Guard;
+
+struct Succ_List {
+	SQueue	*s;
+	Succ_List *nxt;
+};
+
+struct OneState {
+	int	*combo;	/* the combination of claim states */
+	Succ_List	*succ;	/* list of ptrs to immediate successor states */
+};
+
+struct SQueue {
+	OneState	state;
+	SQueue	*nxt;
+};
+
+struct State_Stack {
+	int *n;
+	State_Stack *nxt;
+};
+
+struct Guard {
+	Lextok *t;
+	Guard *nxt;
+};
+
+static SQueue	*sq, *sd, *render;	/* states move from sq to sd to render to holding */
+static SQueue	*holding, *lasthold;
+static State_Stack *dsts;
+
+static int nst;		/* max nr of states in claims */
+static int *Ist;	/* initial states */
+static int *Nacc;	/* number of accept states in claim */
+static int *Nst;	/* next states */
+static int **reached;	/* n claims x states */
+static int unfolding;	/* to make sure all accept states are reached */
+static int is_accept;	/* remember if the current state is accepting in any claim */
+static int not_printing; /* set during explore_product */
+
+static Element ****matrix;	/* n x two-dimensional arrays state x state */
+static Element **Selfs;	/* self-loop states at end of claims */
+
+static void get_seq(int, Sequence *);
+static void set_el(int n, Element *e);
+static void gen_product(void);
+static void print_state_nm(char *, int *, char *);
+static SQueue *find_state(int *);
+static SQueue *retrieve_state(int *);
+
+static int
+same_state(int *a, int *b)
+{	int i;
+
+	for (i = 0; i < nclaims; i++)
+	{	if (a[i] != b[i])
+		{	return 0;
+	}	}
+	return 1;
+}
+
+static int
+in_stack(SQueue *s, SQueue *in)
+{	SQueue *q;
+
+	for (q = in; q; q = q->nxt)
+	{	if (same_state(q->state.combo, s->state.combo))
+		{	return 1;
+	}	}
+	return 0;
+}
+
+static void
+to_render(SQueue *s)
+{	SQueue *a, *q, *last; /* find in sd/sq and move to render, if not already there */
+	int n;
+
+	for (n = 0; n < nclaims; n++)
+	{	reached[n][ s->state.combo[n] ] |= 2;
+	}
+
+	for (q = render; q; q = q->nxt)
+	{	if (same_state(q->state.combo, s->state.combo))
+		{	return;
+	}	}
+	for (q = holding; q; q = q->nxt)
+	{	if (same_state(q->state.combo, s->state.combo))
+		{	return;
+	}	}
+
+	a = sd;
+more:
+	for (q = a, last = 0; q; last = q, q = q->nxt)
+	{	if (same_state(q->state.combo, s->state.combo))
+		{	if (!last)
+			{	if (a == sd)
+				{	sd = q->nxt;
+				} else if (a == sq)
+				{	sq = q->nxt;
+				} else
+				{	holding = q->nxt;
+				}
+			} else
+			{	last->nxt = q->nxt;
+			}
+			q->nxt = render;
+			render = q;
+			return;
+	}	}
+	if (verbose)
+	{	print_state_nm("looking for: ", s->state.combo, "\n");
+	}
+	(void) find_state(s->state.combo);	/* creates it in sq */
+	if (a != sq)
+	{	a = sq;
+		goto more;
+	}
+	fatal("cannot happen, to_render", 0);
+}
+
+static void
+wrap_text(char *pre, Lextok *t, char *post)
+{
+	printf(pre, (char *) 0);
+	comment(stdout, t, 0);
+	printf(post, (char *) 0);
+}
+
+static State_Stack *
+push_dsts(int *n)
+{	State_Stack *s;
+	int i;
+
+	for (s = dsts; s; s = s->nxt)
+	{	if (same_state(s->n, n))
+		{	if (verbose&64)
+			{	printf("\n");
+				for (s = dsts; s; s = s->nxt)
+				{	print_state_nm("\t", s->n, "\n");
+				}
+				print_state_nm("\t", n, "\n");
+			}
+			return s;
+	}	}
+
+	s = (State_Stack *) emalloc(sizeof(State_Stack));
+	s->n = (int *) emalloc(nclaims * sizeof(int));
+	for (i = 0; i < nclaims; i++)
+		s->n[i] = n[i];
+	s->nxt = dsts;
+	dsts = s;
+	return 0;
+}
+
+static void
+pop_dsts(void)
+{
+	assert(dsts != NULL);
+	dsts = dsts->nxt;
+}
+
+static void
+complete_transition(Succ_List *sl, Guard *g)
+{	Guard *w;
+	int cnt = 0;
+
+	printf("	:: ");
+	for (w = g; w; w = w->nxt)
+	{	if (w->t->ntyp == CONST
+		&&  w->t->val == 1)
+		{	continue;
+		} else if (w->t->ntyp == 'c'
+		&&  w->t->lft->ntyp == CONST
+		&&  w->t->lft->val == 1)
+		{	continue; /* 'true' */
+		}
+
+		if (cnt > 0)
+		{	printf(" && ");
+		}
+		wrap_text("", w->t, "");
+		cnt++;
+	}
+	if (cnt == 0)
+	{	printf("true");
+	}
+	print_state_nm(" -> goto ", sl->s->state.combo, "");
+
+	if (is_accept > 0)
+	{	printf("_U%d\n", (unfolding+1)%nclaims);
+	} else
+	{	printf("_U%d\n", unfolding);
+	}
+}
+
+static void
+state_body(OneState *s, Guard *guard)
+{	Succ_List *sl;
+	State_Stack *y;
+	Guard *g;
+	int i, once;
+
+	for (sl = s->succ; sl; sl = sl->nxt)
+	{	once = 0;
+
+		for (i = 0; i < nclaims; i++)
+		{	Element *e;
+			e = matrix[i][s->combo[i]][sl->s->state.combo[i]];
+
+			/* if one of the claims has a DO or IF move
+			   then pull its target state forward, once
+			 */
+
+			if (!e
+			|| e->n->ntyp == NON_ATOMIC
+			||  e->n->ntyp == DO
+			||  e->n->ntyp == IF)
+			{	s = &(sl->s->state);
+				y = push_dsts(s->combo);
+				if (!y)
+				{	if (once++ == 0)
+					{	assert(s->succ != NULL);
+						state_body(s, guard);
+					}
+					pop_dsts();
+				} else if (!y->nxt)	/* self-loop transition */
+				{	if (!not_printing) printf(" /* self-loop */\n");
+				} else
+				{	/* non_fatal("loop in state body", 0); ** maybe ok */
+				}
+				continue;
+			} else
+			{	g = (Guard *) emalloc(sizeof(Guard));
+				g->t = e->n;
+				g->nxt = guard;
+				guard = g;
+		}	}
+
+		if (guard && !once)
+		{	if (!not_printing) complete_transition(sl, guard);
+			to_render(sl->s);
+	}	}
+}
+
+static struct X {
+	char *s;	int n;
+} spl[] = {
+	{"end",		3 },
+	{"accept",	6 },
+	{0,		0 },
+};
+
+static int slcnt;
+extern Label *labtab;
+
+static ProcList *
+locate_claim(int n)
+{	ProcList *p;
+	int i;
+
+	for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */
+	{	if (i == n)
+		{	break;
+	}	}
+	assert(p && p->b == N_CLAIM);
+
+	return p;
+}
+
+static void
+elim_lab(Element *e)
+{	Label *l, *lst;
+
+	for (l = labtab, lst = NULL; l; lst = l, l = l->nxt)
+	{	if (l->e == e)
+		{	if (lst)
+			{	lst->nxt = l->nxt;
+			} else
+			{	labtab = l->nxt;
+			}
+			break;
+	}	}
+}
+
+static int
+claim_has_accept(ProcList *p)
+{	Label *l;
+
+	for (l = labtab; l; l = l->nxt)
+	{	if (strcmp(l->c->name, p->n->name) == 0
+		&&  strncmp(l->s->name, "accept", 6) == 0)
+		{	return 1;
+	}	}
+	return 0;
+}
+
+static void
+prune_accept(void)
+{	int n;
+
+	for (n = 0; n < nclaims; n++)
+	{	if ((reached[n][Selfs[n]->seqno] & 2) == 0)
+		{	if (verbose)
+			{	printf("claim %d: selfloop not reachable\n", n);
+			}
+			elim_lab(Selfs[n]);
+			Nacc[n] = claim_has_accept(locate_claim(n));
+	}	}
+}
+
+static void
+mk_accepting(int n, Element *e)
+{	ProcList *p;
+	Label *l;
+	int i;
+
+	assert(!Selfs[n]);
+	Selfs[n] = e;
+
+	l = (Label *) emalloc(sizeof(Label));
+	l->s = (Symbol *) emalloc(sizeof(Symbol));
+	l->s->name = "accept00";
+	l->c = (Symbol *) emalloc(sizeof(Symbol));
+	l->uiid = 0;	/* this is not in an inline */
+
+	for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */
+	{	if (i == n)
+		{	l->c->name = p->n->name;
+			break;
+	}	}
+	assert(p && p->b == N_CLAIM);
+	Nacc[n] = 1;
+	has_accept = 1;
+
+	l->e = e;
+	l->nxt = labtab;
+	labtab = l;
+}
+
+static void
+check_special(int *nrs)
+{	ProcList *p;
+	Label *l;
+	int i, j, nmatches;
+	int any_accepts = 0;
+
+	for (i = 0; i < nclaims; i++)
+	{	any_accepts += Nacc[i];
+	}
+
+	is_accept = 0;
+	for (j = 0; spl[j].n; j++) /* 2 special label prefixes */
+	{	nmatches = 0;
+		for (p = rdy, i = 0; p; p = p->nxt, i++) /* check each claim */
+		{	if (p->b != N_CLAIM)
+			{	continue;
+			}
+			/* claim i in state nrs[i], type p->tn, name p->n->name
+			 * either the state has an accept label, or the claim has none,
+			 * so that all its states should be considered accepting
+			 * --- but only if other claims do have accept states!
+			 */
+			if (Strict == 0 && j == 1 && Nacc[i] == 0 && any_accepts > 0)
+			{	if ((verbose&32) && i == unfolding)
+				{	printf("	/* claim %d pseudo-accept */\n", i);
+				}
+				goto is_accepting;
+			}
+			for (l = labtab; l; l = l->nxt)	/* check its labels */
+			{	if (strcmp(l->c->name, p->n->name) == 0  /* right claim */
+				&&  l->e->seqno == nrs[i]		 /* right state */
+				&&  strncmp(l->s->name, spl[j].s, spl[j].n) == 0)
+				{	if (j == 1)	/* accept state */
+					{	char buf[32];
+is_accepting:					if (strchr(p->n->name, ':'))
+						{	sprintf(buf, "N%d", i);
+						} else
+						{	assert(strlen(p->n->name) < sizeof(buf));
+							strcpy(buf, p->n->name);
+						}
+						if (unfolding == 0 && i == 0)
+						{	if (!not_printing)
+							printf("%s_%s_%d:\n",	/* true accept */
+								spl[j].s, buf, slcnt++);
+						} else if (verbose&32)
+						{	if (!not_printing)
+							printf("%s_%s%d:\n",
+								buf, spl[j].s, slcnt++);
+						}
+						if (i == unfolding)
+						{	is_accept++; /* move to next unfolding */
+						}
+					} else
+					{	nmatches++;
+					}
+					break;
+		}	}	}
+		if (j == 0 && nmatches == nclaims)	/* end-state */
+		{	if (!not_printing)
+			{	printf("%s%d:\n", spl[j].s, slcnt++);
+	}	}	}
+}
+
+static int
+render_state(SQueue *q)
+{
+	if (!q || !q->state.succ)
+	{	if (verbose&64)
+		{	printf("	no exit\n");
+		}
+		return 0;
+	}
+
+	check_special(q->state.combo); /* accept or end-state labels */
+
+	dsts = (State_Stack *) 0;
+	push_dsts(q->state.combo);	/* to detect loops */
+
+	if (!not_printing)
+	{	print_state_nm("", q->state.combo, "");	/* the name */
+		printf("_U%d:\n\tdo\n", unfolding);
+	}
+
+	state_body(&(q->state), (Guard *) 0);
+
+	if (!not_printing)
+	{	printf("\tod;\n");
+	}
+	pop_dsts();
+	return 1;
+}
+
+static void
+explore_product(void)
+{	SQueue *q;
+
+	/* all states are in the sd queue */
+
+	q = retrieve_state(Ist);	/* retrieve from the sd q */
+	q->nxt = render;		/* put in render q */
+	render = q;
+	do {
+		q = render;
+		render = render->nxt;
+		q->nxt = 0;		/* remove from render q */
+
+		if (verbose&64)
+		{	print_state_nm("explore: ", q->state.combo, "\n");
+		}
+
+		not_printing = 1;
+		render_state(q);	/* may add new states */
+		not_printing = 0;
+
+		if (lasthold)
+		{	lasthold->nxt = q;
+			lasthold = q;
+		} else
+		{	holding = lasthold = q;
+		}
+	} while (render);
+	assert(!dsts);
+	
+}
+
+static void
+print_product(void)
+{	SQueue *q;
+	int cnt;
+
+	if (unfolding == 0)
+	{	printf("never Product {\n");	/* name expected by iSpin */
+		q = find_state(Ist);	/* should find it in the holding q */
+		assert(q != NULL);
+		q->nxt = holding;	/* put it at the front */
+		holding = q;
+	}
+	render = holding;
+	holding = lasthold = 0;
+
+	printf("/* ============= U%d ============= */\n", unfolding);
+	cnt = 0;
+	do {
+		q = render;
+		render = render->nxt;
+		q->nxt = 0;
+		if (verbose&64)
+		{	print_state_nm("print: ", q->state.combo, "\n");
+		}
+		cnt += render_state(q);
+
+		if (lasthold)
+		{	lasthold->nxt = q;
+			lasthold = q;
+		} else
+		{	holding = lasthold = q;
+		}
+	} while (render);
+	assert(!dsts);
+
+	if (cnt == 0)
+	{	printf("	0;\n");
+	}
+
+	if (unfolding == nclaims-1)
+	{	printf("}\n");
+	}
+}
+
+static void
+prune_dead(void)
+{	Succ_List *sl, *last;
+	SQueue *q;
+	int cnt;
+
+	do {	cnt = 0;
+		for (q = sd; q; q = q->nxt)
+		{	/* if successor is deadend, remove it
+			 * unless it's a move to the end-state of the claim
+			 */
+			last = (Succ_List *) 0;
+			for (sl = q->state.succ; sl; last = sl, sl = sl->nxt)
+			{	if (!sl->s->state.succ)	/* no successor */
+				{	if (!last)
+					{	q->state.succ = sl->nxt;
+					} else
+					{	last->nxt = sl->nxt;
+					}
+					cnt++;
+		}	}	}
+	} while (cnt > 0);
+}
+
+static void
+print_raw(void)
+{	int i, j, n;
+
+	printf("#if 0\n");
+	for (n = 0; n < nclaims; n++)
+	{	printf("C%d:\n", n);
+		for (i = 0; i < nst; i++)
+		{	if (reached[n][i])
+			for (j = 0; j < nst; j++)
+			{	if (matrix[n][i][j])
+				{	if (reached[n][i] & 2) printf("+");
+					if (i == Ist[n]) printf("*");
+					printf("\t%d", i);
+					wrap_text(" -[", matrix[n][i][j]->n, "]->\t");
+					printf("%d\n", j);
+	}	}	}	}
+	printf("#endif\n\n");
+	fflush(stdout);
+}
+
+void
+sync_product(void)
+{	ProcList *p;
+	Element *e;
+	int n, i;
+
+	if (nclaims <= 1) return;
+
+	(void) unlink("pan.pre");
+
+	Ist  = (int *) emalloc(sizeof(int) * nclaims);
+	Nacc = (int *) emalloc(sizeof(int) * nclaims);
+	Nst  = (int *) emalloc(sizeof(int) * nclaims);
+	reached = (int **) emalloc(sizeof(int *) * nclaims);
+	Selfs   = (Element **) emalloc(sizeof(Element *) * nclaims);
+	matrix  = (Element ****) emalloc(sizeof(Element ***) * nclaims); /* claims */
+
+	for (p = rdy, i = 0; p; p = p->nxt, i++)
+	{	if (p->b == N_CLAIM)
+		{	nst = max(p->s->maxel, nst);
+			Nacc[i] = claim_has_accept(p);
+	}	}
+
+	for (n = 0; n < nclaims; n++)
+	{	reached[n] = (int *) emalloc(sizeof(int) * nst);
+		matrix[n] = (Element ***) emalloc(sizeof(Element **) * nst);	/* rows */
+		for (i = 0; i < nst; i++)					/* cols */
+		{	matrix[n][i] = (Element **) emalloc(sizeof(Element *) * nst);
+	}	}
+
+	for (e = Al_El; e; e = e->Nxt)
+	{	e->status &= ~DONE;
+	}
+
+	for (p = rdy, n=0; p; p = p->nxt, n++)
+	{	if (p->b == N_CLAIM)
+		{	/* fill in matrix[n] */
+			e = p->s->frst;
+			Ist[n] = huntele(e, e->status, -1)->seqno;
+
+			reached[n][Ist[n]] = 1|2;
+			get_seq(n, p->s);
+	}	}
+
+	if (verbose)	/* show only the input automata */
+	{	print_raw();
+	}
+
+	gen_product();	/* create product automaton */
+}
+
+static int
+nxt_trans(int n, int cs, int frst)
+{	int j;
+
+	for (j = frst; j < nst; j++)
+	{	if (reached[n][cs]
+		&&  matrix[n][cs][j])
+		{	return j;
+	}	}
+	return -1;
+}
+
+static void
+print_state_nm(char *p, int *s, char *a)
+{	int i;
+	printf("%sP", p);
+	for (i = 0; i < nclaims; i++)
+	{	printf("_%d", s[i]);
+	}
+	printf("%s", a);
+}
+
+static void
+create_transition(OneState *s, SQueue *it)
+{	int n, from, upto;
+	int *F = s->combo;
+	int *T = it->state.combo;
+	Succ_List *sl;
+	Lextok *t;
+
+	if (verbose&64)
+	{	print_state_nm("", F, " ");
+		print_state_nm("-> ", T, "\t");
+	}
+
+	/* check if any of the claims is blocked */
+	/* which makes the state a dead-end */
+	for (n = 0; n < nclaims; n++)
+	{	from = F[n];
+		upto = T[n];
+		t = matrix[n][from][upto]->n;
+		if (verbose&64)
+		{	wrap_text("", t, " ");
+		}
+		if (t->ntyp == 'c'
+		&&  t->lft->ntyp == CONST)
+		{	if (t->lft->val == 0)	/* i.e., false */
+			{	goto done;
+	}	}	}
+
+	sl = (Succ_List *) emalloc(sizeof(Succ_List));
+	sl->s = it;
+	sl->nxt = s->succ;
+	s->succ = sl;
+done:
+	if (verbose&64)
+	{	printf("\n");
+	}
+}
+
+static SQueue *
+find_state(int *cs)
+{	SQueue *nq, *a = sq;
+	int i;
+
+again:	/* check in nq, sq, and then in the render q */
+	for (nq = a; nq; nq = nq->nxt)
+	{	if (same_state(nq->state.combo, cs))
+		{	return nq;	/* found */
+	}	}
+	if (a == sq && sd)
+	{	a = sd;
+		goto again; /* check the other stack too */
+	} else if (a == sd && render)
+	{	a = render;
+		goto again;
+	}
+
+	nq = (SQueue *) emalloc(sizeof(SQueue));
+	nq->state.combo = (int *) emalloc(nclaims * sizeof(int));
+	for (i = 0; i < nclaims; i++)
+	{	nq->state.combo[i] = cs[i];
+	}
+	nq->nxt = sq;	/* add to sq stack */
+	sq = nq;
+
+	return nq;
+}
+
+static SQueue *
+retrieve_state(int *s)
+{	SQueue *nq, *last = NULL;
+
+	for (nq = sd; nq; last = nq, nq = nq->nxt)
+	{	if (same_state(nq->state.combo, s))
+		{	if (last)
+			{	last->nxt = nq->nxt;
+			} else
+			{	sd = nq->nxt;	/* 6.4.0: was sd = nq */
+			}
+			return nq;	/* found */
+	}	}
+
+	fatal("cannot happen: retrieve_state", 0);
+	return (SQueue *) 0;
+}
+
+static void
+all_successors(int n, OneState *cur)
+{	int i, j = 0;
+
+	if (n >= nclaims)
+	{	create_transition(cur, find_state(Nst));
+	} else
+	{	i = cur->combo[n];
+		for (;;)
+		{	j = nxt_trans(n, i, j);
+			if (j < 0) break;
+			Nst[n] = j;
+			all_successors(n+1, cur);
+			j++;
+	}	}
+}
+
+static void
+gen_product(void)
+{	OneState *cur_st;
+	SQueue *q;
+
+	find_state(Ist);	/* create initial state */
+
+	while (sq)
+	{	if (in_stack(sq, sd))
+		{	sq = sq->nxt;
+			continue;
+		}
+		cur_st = &(sq->state);
+
+		q = sq;
+		sq = sq->nxt;	/* delete from sq stack */
+		q->nxt = sd;	/* and move to done stack */
+		sd = q;
+
+		all_successors(0, cur_st);
+	}
+	/* all states are in the sd queue now */
+	prune_dead();
+	explore_product();	/* check if added accept-self-loops are reachable */
+	prune_accept();
+
+	if (verbose)
+	{	print_raw();
+	}
+
+	/* PM: merge states with identical successor lists */
+
+	/* all outgoing transitions from accept-states
+	   from claim n in copy n connect to states in copy (n+1)%nclaims
+	   only accept states from claim 0 in copy 0 are true accept states
+	   in the product
+
+	   PM: what about claims that have no accept states (e.g., restrictions)
+	*/
+
+	for (unfolding = 0; unfolding < nclaims; unfolding++)
+	{	print_product();
+	}
+}
+
+static void
+t_record(int n, Element *e, Element *g)
+{	int from = e->seqno, upto = g?g->seqno:0;
+
+	assert(from >= 0 && from < nst);
+	assert(upto >= 0 && upto < nst);
+
+	matrix[n][from][upto] = e;
+	reached[n][upto] |= 1;
+}
+
+static void
+get_sub(int n, Element *e)
+{
+	if (e->n->ntyp == D_STEP
+	||  e->n->ntyp == ATOMIC)
+	{	fatal("atomic or d_step in never claim product", 0);
+	} 
+	/* NON_ATOMIC */
+	e->n->sl->this->last->nxt = e->nxt;
+	get_seq(n, e->n->sl->this);
+
+	t_record(n, e, e->n->sl->this->frst);
+
+}
+
+static void
+set_el(int n, Element *e)
+{	Element *g;
+
+	if (e->n->ntyp == '@')	/* change to self-loop */
+	{	e->n->ntyp = CONST;
+		e->n->val = 1;	/* true */
+		e->nxt = e;
+		g = e;
+		mk_accepting(n, e);
+	} else
+
+	if (e->n->ntyp == GOTO)
+	{	g = get_lab(e->n, 1);
+		g = huntele(g, e->status, -1);
+	} else if (e->nxt)
+	{	g = huntele(e->nxt, e->status, -1);
+	} else
+	{	g = NULL;
+	}
+
+	t_record(n, e, g);
+}
+
+static void
+get_seq(int n, Sequence *s)
+{	SeqList *h;
+	Element *e;
+
+	e = huntele(s->frst, s->frst->status, -1);
+	for ( ; e; e = e->nxt)
+	{	if (e->status & DONE)
+		{	goto checklast;
+		}
+		e->status |= DONE;
+
+		if (e->n->ntyp == UNLESS)
+		{	fatal("unless stmnt in never claim product", 0);
+		}
+
+		if (e->sub)	/* IF or DO */
+		{	Lextok *x = NULL;
+			Lextok *y = NULL;
+			Lextok *haselse = NULL;
+
+			for (h = e->sub; h; h = h->nxt)
+			{	Lextok *t = h->this->frst->n;
+				if (t->ntyp == ELSE)
+				{	if (verbose&64) printf("else at line %d\n", t->ln);
+					haselse = t;
+					continue;
+				}
+				if (t->ntyp != 'c')
+				{	fatal("product, 'else' combined with non-condition", 0);
+				}
+
+				if (t->lft->ntyp == CONST	/* true */
+				&&  t->lft->val == 1
+				&&  y == NULL)
+				{	y = nn(ZN, CONST, ZN, ZN);
+					y->val = 0;
+				} else
+				{	if (!x)
+						x = t;
+					else
+						x = nn(ZN, OR, x, t);
+					if (verbose&64)
+					{	wrap_text(" [", x, "]\n");
+			}	}	}
+			if (haselse)
+			{	if (!y)
+				{	y = nn(ZN, '!', x, ZN);
+				}
+				if (verbose&64)
+				{	wrap_text(" [else: ", y, "]\n");
+				}
+				haselse->ntyp = 'c';	/* replace else */
+				haselse->lft = y;
+			}
+
+			for (h = e->sub; h; h = h->nxt)
+			{	t_record(n, e, h->this->frst);
+				get_seq(n, h->this);
+			}
+		} else
+		{	if (e->n->ntyp == ATOMIC
+			||  e->n->ntyp == D_STEP
+			||  e->n->ntyp == NON_ATOMIC)
+			{	get_sub(n, e);
+			} else 
+			{	set_el(n, e);
+			}
+		}
+checklast:	if (e == s->last)
+			break;
+	}
+}
--- /dev/null
+++ b/sys/src/cmd/spin/pangen7.h
@@ -1,0 +1,2413 @@
+/***** spin: pangen7.h *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+static const char *pan_par[] = {	/* generates pan.p */
+	"#include <sys/ipc.h>",
+	"#include <sys/shm.h>",
+	"#include <time.h>",	/* for nanosleep */
+	"#include <assert.h>",
+	"#include <limits.h>",
+	"#ifdef BFS_DISK",
+	"#include <unistd.h>",		/* for rmdir */
+	"#include <sys/stat.h>",	/* for mkdir */
+	"#include <sys/types.h>",
+	"#include <fcntl.h>",		/* for open */
+	"#endif",
+	"",
+	"#define Max(a,b)	(((a)>(b))?(a):(b))",
+	"#ifndef WAIT_MAX",
+	"	#define WAIT_MAX	2	/* seconds */",
+	"#endif",
+	"#define BFS_GEN 	2	/* current and next generation */",
+	"",
+	"typedef struct BFS_Slot BFS_Slot;",
+	"typedef struct BFS_shared BFS_shared;",
+	"typedef struct BFS_data BFS_data;",
+	"",
+	"struct BFS_Slot {",
+	" #ifdef BFS_FIFO",
+	"	enum bfs_types	type;		/* message type */",
+	" #endif",
+	"	BFS_State	*s_data;	/* state data */",
+	" #ifndef BFS_QSZ",
+	"	BFS_Slot	*nxt;		/* linked list */",
+	" #endif",
+	"};",
+	"",
+	"struct BFS_data {",
+	"	double memcnt;",
+	"	double nstates;",
+	"	double nlinks;",
+	"	double truncs;",
+	"	ulong mreached;",
+	"	ulong vsize;",
+	"	ulong memory_left;",
+	"	ulong punted;",
+	"	ulong errors;",
+	"	int   override;	/* after crash, if another proc clears locks */",
+	"};",
+	"",
+	"struct BFS_shared {	/* about 13K for BFS_MAXPROCS=16 and BFS_MAXLOCKS=1028 */",
+	"	volatile ulong	quit;	/* set to signal termination -- one word */",
+	"	volatile ulong	started;",
+	"",
+	"	volatile uchar	sh_owner[BFS_MAXLOCKS];		/* optional */",
+	"#ifdef BFS_CHECK",
+	"	volatile uchar	in_count[BFS_MAXLOCKS];		/* optional */",
+	"#endif",
+	"	volatile int	sh_locks[BFS_MAXLOCKS];",
+	"	volatile ulong	wait_count[BFS_MAXLOCKS];	/* optional */",
+	"",
+	"	volatile BFS_data bfs_data[BFS_MAXPROCS];",
+	"	volatile uchar	bfs_flag[BFS_MAXPROCS]; /* running 0, normal exit 1, abnormal 2 */",
+	"	volatile uchar	bfs_idle[BFS_MAXPROCS]; /* set when all input queues are empty */",
+	"#ifdef BFS_DISK",
+	"	volatile uchar	bfs_out_cnt[BFS_MAXPROCS]; /* set when core writes a state */",
+	"#endif",
+	"",
+	"#ifdef BFS_QSZ",
+	"	#define BFS_NORECYCLE",
+	"	#if BFS_QSZ<=0",
+	"		#error BFS_QSZ must be positive",
+	"	#endif",
+	"	#ifdef BFS_FIFO",
+	"		#error BFS_QSZ cannot be combined with BFS_FIFO",
+	"	#endif",
+	"	#ifdef BFS_DISK",
+	"		#error BFS_QSZ cannot be combined with BFS_DISK",
+	"	#endif",
+	"	volatile BFS_Slot bfsq[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS][BFS_QSZ];",
+	"	volatile uint bfs_ix[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS];",
+	"#else",
+	"	volatile BFS_Slot *head[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS];",
+	"#endif",
+	"",
+	"#ifdef BFS_FIFO",
+	"	volatile BFS_Slot *tail[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS];",
+	"	volatile BFS_Slot *dels[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS];",
+	"#endif",
+	"#ifdef BFS_LOGMEM",
+	"	volatile ulong logmem[1024];",
+	"#endif",
+	"	volatile ulong mem_left;",
+	"	volatile uchar *allocator;	/* start of shared heap, must be last */",
+	"};",
+	"",
+	"enum bfs_types { EMPTY = 0, STATE, DELETED };",
+	"",
+	"extern volatile uchar *bfs_get_shared_mem(key_t, size_t);",
+	"extern BFS_Slot  * bfs_new_slot(BFS_Trail *);",
+	"extern BFS_Slot  * bfs_prep_slot(BFS_Trail *, BFS_Slot *);",
+	"extern BFS_Slot  * bfs_next(void);",
+	"extern BFS_Slot  * bfs_pack_state(Trail *, BFS_Trail *, int, BFS_Slot *);",
+	"extern SV_Hold   * bfs_new_sv(int);",
+	"#if NRUNS>0",
+	"extern EV_Hold   * bfs_new_sv_mask(int);",
+	"#endif",
+	"extern BFS_Trail * bfs_grab_trail(void);",
+	"extern BFS_Trail * bfs_unpack_state(BFS_Slot *);",
+	"extern int         bfs_all_empty(void);",
+	"extern int         bfs_all_idle(void);",
+	"extern int         bfs_all_running(void);",
+	"extern int         bfs_idle_and_empty(void);",
+	"extern size_t	    bfs_find_largest(key_t);",
+	"",
+	"extern void	bfs_clear_locks(void);",
+	"extern void	bfs_drop_shared_memory(void);",
+	"extern void	bfs_explore_state(BFS_Slot *);",
+	"extern void	bfs_initial_state(void);",
+	"extern void	bfs_mark_done(int);",
+	"extern void	bfs_printf(const char *fmt, ...);",
+	"extern void	bfs_push_state(Trail *, BFS_Trail *, int);",
+	"extern void	bfs_recycle(BFS_Slot *);",
+	"extern void	bfs_release_trail(BFS_Trail *);",
+	"extern void	bfs_run(void);",
+	"extern void	bfs_setup_mem(void);",
+	"extern void	bfs_setup(void);",
+	"extern void	bfs_shutdown(const char *);",
+	"extern void	bfs_statistics(void);",
+	"extern void	bfs_store_state(Trail *, short);",
+	"extern void	bfs_set_toggle(void);",
+	"extern void	bfs_update(void);",
+	"",
+	"#ifdef MA",
+	"	#error cannot combine -DMA with -DBFS_PAR",
+	"	/* would require us to parallelize g_store */",
+	"#endif",
+	"#ifdef BCS",
+	"	#error cannot combine -DBCS with -DBFS_PAR",
+	"#endif",
+	"#ifdef BFS_DISK",
+	"	#ifdef BFS_FIFO",
+	"		#error cannot combine BFS_DISK and BFS_FIFO",
+	"	#endif",
+	"	extern void bfs_disk_start(void);",
+	"	extern void bfs_disk_stop(void);",
+	"	extern void bfs_disk_out(void);",
+	"	extern void bfs_disk_inp(void);",
+	"	extern void bfs_disk_iclose(void);",
+	"	extern void bfs_disk_oclose(void);",
+	"	int bfs_out_fd[BFS_MAXPROCS];",
+	"	int bfs_inp_fd[BFS_MAXPROCS];",
+	"#endif",
+	"",
+	"static BFS_shared *shared_memory;",
+	"#ifndef BFS_QSZ",
+	"static BFS_Slot   *bfs_free_slot; /* local free list */",
+	"#endif",
+	"static BFS_Slot    bfs_null;",
+	"static SV_Hold    *bfs_svfree[VECTORSZ];",
+	"static uchar	*bfs_heap;	/* local pointer into heap */",
+	"static ulong	bfs_left;	/* local part of shared heap */",
+	"#if NRUNS>0",
+	"static void	bfs_keep(EV_Hold *);",
+	"#endif",
+	"static long	bfs_sent;	/* nr msgs sent -- local to each process */",
+	"static long	bfs_rcvd;	/* nr msgs rcvd */",
+	"static long	bfs_sleep_cnt;	/* stats */",
+	"static long	bfs_wcount;",
+	"static long	bfs_gcount;",
+	"static ulong	bfs_total_shared;",
+	"#ifdef BFS_STAGGER",
+	" static int	bfs_stage_cnt = 0;",
+	" static void	bfs_stagger_flush(void);",
+	"#endif",
+	"static int	bfs_toggle;	/* local variable, 0 or 1 */",
+	"static int	bfs_qscan;	/* scan input queues in order */",
+	"static ulong	bfs_snapped;",
+	"static int	shared_mem_id;",
+	"#ifndef NOREDUCE",
+	"static int	bfs_nps;	/* no preselection */",
+	"#endif",
+	"ulong	bfs_punt;	/* states dropped for lack of memory */",
+	"#if defined(VERBOSE) || defined(BFS_CHECK)",
+	"static const char *bfs_sname[] = {",
+	"	\"EMPTY\",	/* 0 */",
+	"	\"STATE\",	/* 1 */",
+	"	\"STATE\",	/* 2 = DELETED */",
+	"	0",
+	"};",
+	"#endif",
+	"static const char *bfs_lname[] = { /* match values defined in pangen2.c */",
+	"	\"global lock\",	/* BFS_GLOB  */",
+	"	\"ordinal\",		/* BFS_ORD  */",
+	"	\"shared memory\",	/* BFS_MEM   */",
+	"	\"print to stdout\",	/* BFS_PRINT */",
+	"	\"hashtable\",		/* BFS_STATE */",
+	"	0",
+	"};",
+	"",
+	"static ulong bfs_count[DELETED+1];	/* indexed with bfs_types: EMPTY=0, STATE=1, DELETED=2 */",
+	"",
+	"static int bfs_keep_state;",
+	"",
+	"int Cores = 1;",
+	"int who_am_i = 0;	/* root */",
+	"",
+	"#ifdef L_BOUND",
+	"	int L_bound = L_BOUND;",
+	"#endif",
+	"",
+	"#ifdef BFS_CHECK",
+	"void",
+	"bfs_dump_now(char *s)",
+	"{	int i; char *p = (char *) &now;",
+	"",
+	"	e_critical(BFS_PRINT);",
+	"	printf(\"%%s\\t\", s);",
+	"	printf(\"%%3lu: \", vsize);",
+	"	for (i = 0; i < vsize; i++)",
+	"	{	printf(\"%%3d \", *p++);",
+	"	}",
+	"	printf(\"	%%s\\noffsets:\\t\", s);",
+	"	for (i = 0; i < now._nr_pr; i++)",
+	"	{	printf(\"%%3d \", proc_offset[i]);",
+	"	}",
+	"	printf(\"\\n\");",
+	"	x_critical(BFS_PRINT);",
+	"}",
+	"",
+	"void",
+	"view_state(char *s)	/* debugging */",
+	"{	int i;",
+	"	char *p;",
+	"	e_critical(BFS_PRINT);",
+	"	printf(\"cpu%%02d %%s: \", who_am_i, s);",
+	"	p = (char *)&now;",
+	"	for (i = 0; i < vsize; i++)",
+	"		printf(\"%%3d, \", *p++);",
+	"	printf(\"\\n\"); fflush(stdout);",
+	"	x_critical(BFS_PRINT);",
+	"}",
+	"#endif",
+	"",
+	"void",
+	"bfs_main(int ncores, int cycles)",
+	"{",
+	"	if (cycles)",
+	"	{	fprintf(stderr, \"pan: cycle detection is not supported in this mode\\n\");",
+	"		exit(1);",
+	"	}",
+	"",
+	"	if (ncores == 0)	/* i.e., find out */",
+	"	{	FILE *fd;",
+	"		char buf[512];",
+	"		if ((fd = fopen(\"/proc/cpuinfo\", \"r\")) == NULL)",
+	"		{	/* cannot tell */",
+	"			ncores = Cores; /* use the default */",
+	"		} else",
+	"		{	while (fgets(buf, sizeof(buf), fd))",
+	"			{	if (strncmp(buf, \"processor\", strlen(\"processor\")) == 0)",
+	"				{	ncores++;",
+	"			}	}",
+	"			fclose(fd);",
+	"			ncores--;",
+	"			if (verbose)",
+	"			{	printf(\"pan: %%d available cores\\n\", ncores+1);",
+	"	}	}	}",
+	"	if (ncores >= BFS_MAXPROCS)",
+	"	{	Cores = BFS_MAXPROCS-1; /* why -1? */",
+	"	} else if (ncores <  1)",
+	"	{	Cores = 1;",
+	"	} else",
+	"	{	Cores = ncores;",
+	"	}",
+	"	printf(\"pan: using %%d core%%s\\n\", Cores, (Cores>1)?\"s\":\"\");",
+	"	fflush(stdout);",
+	"#ifdef BFS_DISK",
+	"	bfs_disk_start();",	/* create .spin */
+	"#endif",
+	"	bfs_setup();	/* shared memory segments and fork */",
+	"	bfs_run();",
+	"	if (who_am_i == 0)",
+	"	{	stop_timer(0);",
+	"	}",
+	"	bfs_statistics();",
+	"	bfs_mark_done(1);",
+	"	if (who_am_i == 0)",
+	"	{	report_time();",
+	"#ifdef BFS_DISK",
+	"		bfs_disk_stop();",
+	"#endif",
+	"	}",
+	"#ifdef C_EXIT",
+	"	C_EXIT; /* trust that it defines a fct */",
+	"#endif",
+	"	bfs_drop_shared_memory();",
+	"	exit(0);",
+	"}",
+	"",
+	"void",
+	"bfs_setup_mem(void)",
+	"{	size_t n;",
+	"	key_t key;",
+	"#ifdef BFS_FIFO",
+	"	bfs_null.type = EMPTY;",
+	"#endif",
+	"	ntrpt = (Trail *) emalloc(sizeof(Trail));", /* just once */
+	"",
+	"	if ((key = ftok(\".\", (int) 'L')) == -1)",
+	"	{	perror(\"ftok shared memory\");",
+	"		exit(1);",
+	"	}",
+	"	n = bfs_find_largest(key);",
+	"	bfs_total_shared = (ulong) n;",
+	"",
+	"	shared_memory            = (BFS_shared *) bfs_get_shared_mem(key, n);	/* root */",
+	"	shared_memory->allocator = (uchar *) shared_memory + sizeof(BFS_shared);",
+	"	shared_memory->mem_left  = (ulong) (n - sizeof(BFS_shared));",
+	"}",
+	"",
+	"ulong bfs_LowLim;",
+	"#ifndef BFS_RESERVE",
+	"	#define BFS_RESERVE 5",
+	/* keep memory on global heap in reserve for first few cores */
+	/* that run out of their local allocation of shared mem */
+	/* 1~50 percent, 2~30 percent, 5~20 percent, >Cores=none */
+	"#else",
+	"	#if BFS_RESERVE<1",
+	"	#error BFS_RESERVE must be at least 1",
+	"	#endif",
+	"#endif",
+	"",
+	"void",
+	"bfs_setup(void)	/* executed by root */",
+	"{	int i, j;",
+	"	ulong n;	/* share of shared memory allocated to each core */",
+	"",
+	"	n = shared_memory->mem_left / (Cores + Cores/(BFS_RESERVE)); /* keep some reserve */",
+	"",
+	"	if ((n%%sizeof(void *)) != 0)",
+	"	{       n -= (n%%sizeof(void *)); /* align, without exceeding total */",
+	"	}",
+	"	for (i = 0; i < Cores-1; i++)",
+	"	{	j = fork();",
+	"		if (j == -1)",
+	"		{	bfs_printf(\"fork failed\\n\");",
+	"			exit(1);",
+	"		}",
+	"		if (j == 0)",
+	"		{	who_am_i = i+1;	/* 1..Cores-1 */",
+	"			break;",
+	"	}	}",
+	"",
+	"	e_critical(BFS_MEM);",
+	"	 bfs_heap = (uchar *) shared_memory->allocator;",
+	"	 shared_memory->allocator += n;",
+	"	 shared_memory->mem_left  -= n;",
+	"	x_critical(BFS_MEM);",
+	"",
+	"	bfs_left = n;",
+	"	bfs_runs = 1;",
+	"	bfs_LowLim = n / (2 * (ulong) Cores);", /* 50% */
+	"}",
+	"",
+	"void",
+	"bfs_run(void)",
+	"{	BFS_Slot *v;",
+	"",
+	"#ifdef BFS_DISK",
+	"	bfs_disk_out();",	/* create outqs */
+	"#endif",
+	"	if (who_am_i == 0)",
+	"	{	bfs_initial_state();",
+	"	}",
+	"#ifdef BFS_DISK",
+	"	#ifdef BFS_STAGGER",
+	"	bfs_stagger_flush();",
+	"	#endif",
+	"	bfs_disk_oclose();",	/* sync and close outqs */
+	"#endif",
+	"#ifdef BFS_FIFO",
+	"	static int i_count;",
+	"#endif",
+	"",
+	"	srand(s_rand+HASH_NR);",
+	"	bfs_qscan = 0;",
+	"	bfs_toggle = 1 - bfs_toggle; /* after initial state */",
+	"	e_critical(BFS_GLOB);",
+	"	 shared_memory->started++;",
+	"	x_critical(BFS_GLOB);",
+	"",
+	"	while (shared_memory->started != Cores)	/* wait for all cores to connect */",
+	"	{	usleep(1);",
+	"	}",
+	"",
+	"#ifdef BFS_DISK",
+	"	bfs_disk_out();",
+	"	bfs_disk_inp();",
+	"#endif",
+	"",
+	"	start_timer();",
+	"	while (shared_memory->quit == 0)",
+	"	{	v = bfs_next(); /* get next message from current generation */",
+	"		if (v->s_data) /* v->type == STATE || v->type == DELETED */",
+	"		{	bfs_count[STATE]++;",
+	"#ifdef VERBOSE",
+	"			bfs_printf(\"GOT STATE (depth %%d, nr %%u)\\n\",",
+	"				v->s_data->t_info->o_tt, v->s_data->nr);",
+	"#endif",
+	"			/* last resort: start dropping states when out of memory */",
+	"			if (bfs_left > 1024 || shared_memory->mem_left > 1024)",
+	"			{	bfs_explore_state(v);",
+	"			} else",
+	"			{	static int warned_loss = 0;",
+	"				if (warned_loss == 0 && who_am_i == 0)",
+	"				{	warned_loss++;",
+	"					bfs_printf(\"out of shared memory - losing states\\n\");",
+	"				}",
+	"				bfs_punt++;",
+	"			}",
+	"#if !defined(BFS_FIFO) && !defined(BFS_NORECYCLE)",
+	"			bfs_recycle(v);",
+	"#endif",
+	"#ifdef BFS_FIFO",
+	"			i_count = 0;",
+	"#endif",
+	"		} else",
+	"		{	bfs_count[EMPTY]++;",
+	"#if defined(BFS_FIFO) && defined(BFS_CHECK)",
+	"			assert(v->type == EMPTY);",
+	"#endif",
+	"#ifdef BFS_FIFO",
+	"			if (who_am_i == 0)",
+	"			{	if (bfs_idle_and_empty())",
+	"				{	if (i_count++ > 10)",
+	"					{	shared_memory->quit = 1;",
+	"					}",
+	"					else usleep(1);",
+	"				}",
+	"			} else if (!bfs_all_running())",
+	"			{	bfs_shutdown(\"early termination\");",
+	"			}",
+	"#else",
+	"			if (who_am_i == 0)",
+	"			{	if (bfs_all_idle())		/* wait for it */",
+	"				{	if (!bfs_all_empty())	/* more states to process */",
+	"					{	bfs_set_toggle();",
+	"						goto do_toggle;",
+	"					} else			/* done */",
+	"					{	shared_memory->quit = 1; /* step 4 */",
+	"					}",
+	"				} else",
+	"				{	bfs_sleep_cnt++;",
+	"				}",
+	"			} else",
+	"			{	/* wait for quit or idle bit to be reset by root */",
+	"				while (shared_memory->bfs_idle[who_am_i] == 1",
+	"				&&     shared_memory->quit == 0)",
+	"				{	if (bfs_all_running())",
+	"					{	bfs_sleep_cnt++;",
+	"						usleep(10);	/* new 6.2.3 */",
+	"					} else",
+	"					{	bfs_shutdown(\"early termination\");",
+	"						/* no return */",
+	"				}	}",
+	"do_toggle:			bfs_qscan = 0;",
+	"#ifdef BFS_DISK",
+	"				bfs_disk_iclose();",
+	"				bfs_disk_oclose();",
+	"#endif",
+	"				bfs_toggle = 1 - bfs_toggle;",
+	"#ifdef BFS_DISK",
+	"				bfs_disk_out();",
+	"				bfs_disk_inp();",
+	"#endif",
+	"	#ifdef BFS_CHECK",
+	"				bfs_printf(\"toggle: recv from %%d, send to %%d\\n\",",
+	"					bfs_toggle, 1 - bfs_toggle);",
+	"	#endif",
+	"			}",
+	"#endif",
+	"	}	}",
+	"#ifdef BFS_CHECK",
+	"	bfs_printf(\"done, sent %%5ld recvd %%5ld punt %%5lu sleep: %%ld\\n\",",
+	"		bfs_sent, bfs_rcvd, bfs_punt, bfs_sleep_cnt);",
+	"#endif",
+	"}",
+	"",
+	"void",
+	"bfs_report_mem(void)	/* called from within wrapup() */",
+	"{",
+	"	printf(\"%%9.3f	total shared memory usage\\n\\n\",",
+	"		((double) bfs_total_shared - (double) bfs_left)/(1024.*1024.));",
+	"}",
+	"",
+	"void",
+	"bfs_statistics(void)",
+	"{",
+	"	#ifdef VERBOSE",
+	"	enum bfs_types i;",
+	"	#endif",
+	"	if (verbose)",
+	"		bfs_printf(\"states sent %%7ld recvd %%7ld stored %%8g sleeps: %%4ld, %%4ld, %%ld\\n\",",
+	"			bfs_sent, bfs_rcvd, nstates, bfs_wcount, bfs_gcount, bfs_sleep_cnt);",
+	"	if (0) bfs_printf(\"states punted %%7lu\\n\", bfs_punt);",
+	"	#ifdef VERBOSE",
+	"	for (i = EMPTY; i <= DELETED; i++)",
+	"	{	if (bfs_count[i] > 0)",
+	"		{	bfs_printf(\"%%6s	%%8lu\\n\",",
+	"				bfs_sname[i], bfs_count[i]);",
+	"	}	}",
+	"	#endif",
+	"	bfs_update();",
+	"",
+	"	if (who_am_i == 0 && shared_memory)",
+	"	{	int i; ulong count = 0L;",
+	"		done = 1;",
+	"",
+	"		e_critical(BFS_PRINT);",
+	"		  wrapup();",
+	"		  if (verbose)",
+	"		  {	  printf(\"\\nlock-wait counts:\\n\");",
+	"	 	  	for (i = 0; i < BFS_STATE; i++)",
+	"	 			printf(\"%%16s  %%9lu\\n\",",
+	"					bfs_lname[i], shared_memory->wait_count[i]);",
+	"#ifndef BITSTATE",
+	"		  	for (i = BFS_STATE; i < BFS_MAXLOCKS; i++)",
+	"		  	{	if (0)",
+	"				printf(\"	[%%6d]  %%9lu\\n\",",
+	"					i, shared_memory->wait_count[i]);",
+	"				count += shared_memory->wait_count[i];",
+	"		  	}",
+	"	 	  	printf(\"%%16s  %%9lu (avg per region)\\n\",",
+	"				bfs_lname[BFS_STATE], count/(BFS_MAXLOCKS - BFS_STATE));",
+	"#endif",
+	"		  }",
+	"		  fflush(stdout);",
+	"		x_critical(BFS_PRINT);",
+	"	}",
+	"}",
+	"",
+	"void",
+	"bfs_snapshot(void)",
+	"{	clock_t stop_time;",
+	"	double delta_time;",
+	"	struct tms stop_tm;",
+	"	volatile BFS_data *s;",
+	"",
+	"	e_critical(BFS_PRINT);",
+	"	 printf(\"cpu%%02d Depth= %%7lu States= %%8.3g Transitions= %%8.3g \",",
+	"		who_am_i, mreached, nstates, nstates+truncs);",
+	"	 printf(\"Memory= %%9.3f\\t\", memcnt/1048576.);",
+	"	 printf(\"SharedMLeft= %%4lu \", bfs_left/1048576);",
+	"	 stop_time  = times(&stop_tm);",
+	"	 delta_time = ((double) (stop_time - start_time))/((double) sysconf(_SC_CLK_TCK));",
+	"	 if (delta_time > 0.01)",
+	"	 {	printf(\"t= %%6.3g R= %%6.0g\\n\", delta_time, nstates/delta_time);",
+	"	 } else",
+	"	 {	printf(\"t= %%6.3g R= %%6.0g\\n\", 0., 0.);",
+	"	 }",
+	"	 fflush(stdout);",
+	"	x_critical(BFS_PRINT);",
+	"",
+	"	s = &shared_memory->bfs_data[who_am_i];",
+	"	s->mreached = (ulong) mreached;",
+	"	s->vsize    = (ulong) vsize;",
+	"	s->errors   = (int) errors;",
+	"	s->memcnt   = (double) memcnt;",
+	"	s->nstates  = (double) nstates;",
+	"	s->nlinks   = (double) nlinks;",
+	"	s->truncs   = (double) truncs;",
+	"	s->memory_left = (ulong) bfs_left;",
+	"	s->punted      = (ulong) bfs_punt;",
+	"	bfs_snapped++; /* for bfs_best */",
+	"}",
+	"",
+	"void",
+	"bfs_shutdown(const char *s)",
+	"{",
+	"	bfs_clear_locks(); /* in case we interrupted at a bad point */",
+	"	if (!strstr(s, \"early \") || verbose)",
+	"	{	bfs_printf(\"stop (%%s)\\n\", s);",
+	"	}",
+	"	bfs_update();",
+	"	if (who_am_i == 0)",
+	"	{	wrapup();",
+	"#ifdef BFS_DISK",
+	"		bfs_disk_stop();",
+	"#endif",
+	"	}",
+	"	bfs_mark_done(2);",
+	"	pan_exit(2);",
+	"}",
+	"",
+	"SV_Hold *bfs_free_hold;",
+	"",
+	"SV_Hold *",
+	"bfs_get_hold(void)",
+	"{	SV_Hold *x;",
+	"	if (bfs_free_hold)",
+	"	{	x = bfs_free_hold;",
+	"		bfs_free_hold = bfs_free_hold->nxt;",
+	"	} else",
+	"	{	x = (SV_Hold *) sh_malloc((ulong) sizeof(SV_Hold));",
+	"	}",
+	"	return x;",
+	"}",
+	"",
+	"BFS_Trail *",
+	"bfs_unpack_state(BFS_Slot *n)		/* called in bfs_explore_state */",
+	"{	BFS_Trail *otrpt;",
+	"	BFS_State *bfs_t;",
+	"	int vecsz;",
+	"",
+	"	if (!n || !n->s_data || !n->s_data->t_info)",
+	"	{	bfs_Uerror(\"internal error\");",
+	"	}",
+	"	otrpt = (BFS_Trail *) ((BFS_State *) n->s_data)->t_info;",
+	"",
+	"	trpt->ostate = otrpt->ostate;",
+	"	trpt->st     = otrpt->st;",
+	"	trpt->o_tt   = otrpt->o_tt;",
+	"	trpt->pr     = otrpt->pr;",
+	"	trpt->tau    = otrpt->tau;",
+	"	trpt->o_pm   = otrpt->o_pm;",
+	"	if (trpt->ostate)",
+	"	trpt->o_t    = t_id_lkup[otrpt->t_id];",
+	"#if defined(C_States) && (HAS_TRACK==1)",
+	"	c_revert((uchar *) &(now.c_state[0]));",
+	"#endif",
+	"	if (trpt->o_pm & 4)			/* rv succeeded */",
+	"	{	return (BFS_Trail *) 0;		/* revisit not needed */",
+	"	}",
+	"#ifndef NOREDUCE",
+	"	bfs_nps = 0;",
+	"#endif",
+	"	if (trpt->o_pm & 8)			/* rv attempt failed */",
+	"	{	revrv++;",
+	"		if (trpt->tau&8)",
+	"		{	trpt->tau &= ~8;	/* break atomic */",
+	"#ifndef NOREDUCE",
+	"		} else if (trpt->tau&32)	/* void preselection */",
+	"		{	trpt->tau &= ~32;",
+	"			bfs_nps = 1;		/* no preselection in repeat */",
+	"#endif",
+	"	}	}",
+	"	trpt->o_pm &= ~(4|8);",
+	"	if (trpt->o_tt > mreached)",
+	"	{	static ulong nr = 0L, nc;",
+	"		mreached = trpt->o_tt;",
+	"		nc = (long) nstates/FREQ;",
+	"		if (nc > nr)",
+	"		{	nr = nc;",
+	"			bfs_snapshot();",
+	"	}	}",
+	"	depth = trpt->o_tt;",
+	"	if (depth >= maxdepth)",
+	"	{",
+	"#if SYNC",
+	"		if (boq != -1)",
+	"		{	BFS_Trail *x = (BFS_Trail *) trpt->ostate;",
+	"			if (x) x->o_pm |= 4; /* rv not failing */",
+	"		}",
+	"#endif",
+	"		truncs++;",
+	"		if (!warned)",
+	"		{	warned = 1;",
+	"			bfs_printf(\"error: max search depth too small\\n\");",
+	"		}",
+	"		if (bounded)",
+	"		{	bfs_uerror(\"depth limit reached\");",
+	"		}",
+	"		return (BFS_Trail *) 0;",
+	"	}",
+	"",
+	"	bfs_t = n->s_data;",
+	"#if NRUNS>0",
+	"	vsize = bfs_t->omask->sz;",
+	"#else",
+	"	vsize = ((State *) (bfs_t->osv))->_vsz;",
+	"#endif",
+	"#if SYNC",
+	"	boq   = bfs_t->boq;",
+	"#endif",
+	"",
+	"#if defined(Q_PROVISO) && !defined(BITSTATE) && defined(FULLSTACK)",
+	"	#ifdef USE_TDH",
+	"		if (((uchar *)(bfs_t->lstate)))		/* if BFS_INQ is set */",
+	"		{	*((uchar *) bfs_t->lstate) = 0;	/* turn it off */",
+	"		}",
+	"	#else",
+	"		if (bfs_t->lstate)			/* bfs_par */",
+	"		{	bfs_t->lstate->tagged = 0;	/* bfs_par state removed from q */",
+	"		}",
+	"	#endif",
+	"#endif",
+	"	memcpy((char *) &now, (uchar *) bfs_t->osv, vsize);",
+	"#if !defined(NOCOMP) && !defined(HC) && NRUNS>0",
+	"	Mask = (uchar *) bfs_t->omask->sv;	/* in shared memory */",
+	"#endif",
+	"#ifdef BFS_CHECK",
+	"	if (0) bfs_dump_now(\"got1\");",
+	"#endif",
+	"#ifdef TRIX",
+	"	re_populate();",
+	"#else",
+	"	#if NRUNS>0",
+	"		if (now._nr_pr > 0)",
+	"		{",
+	"		#if VECTORSZ>32000",
+	"			proc_offset = (int *) bfs_t->omask->po;",
+	"		#else",
+	"			proc_offset = (short *) bfs_t->omask->po;",
+	"		#endif",
+	"			proc_skip   = (uchar *) bfs_t->omask->ps;",
+	"		}",
+	"		if (now._nr_qs > 0)",
+	"		{",
+	"		#if VECTORSZ>32000",
+	"			q_offset = (int *) bfs_t->omask->qo;",
+	"		#else",
+	"			q_offset = (short *) bfs_t->omask->qo;",
+	"		#endif",
+	"			q_skip   = (uchar *) bfs_t->omask->qs;",
+	"		}",
+	"	#endif",
+	"#endif",
+	"	vecsz = ((State *) bfs_t->osv)->_vsz;",
+	"#ifdef BFS_CHECK",
+	"	assert(vecsz > 0 && vecsz < VECTORSZ);",
+	"#endif",
+	"	{ SV_Hold *x = bfs_get_hold();",
+	"		x->sv  = bfs_t->osv;",
+	"		x->nxt = bfs_svfree[vecsz];",
+	"		bfs_svfree[vecsz] = x;",
+	"		bfs_t->osv = (State *) 0;",
+	"	}",
+	"#if NRUNS>0",
+	"	bfs_keep(bfs_t->omask);",
+	"#endif",
+	"",
+	"#ifdef BFS_CHECK",
+	"	if (0) bfs_dump_now(\"got2\");",
+	"	if (0) view_state(\"after\");",
+	"#endif",
+	"	return (BFS_Trail *) bfs_t->t_info;",
+	"}",
+	"void",
+	"bfs_initial_state(void)",
+	"{",
+	"#ifdef BFS_CHECK",
+	"	assert(trpt != NULL);",
+	"#endif",
+	"	trpt->ostate = (H_el *) 0;",
+	"	trpt->o_tt   = -1;",
+	"	trpt->tau    = 0;",
+	"#ifdef VERI",
+	"	trpt->tau |= 4;	/* claim moves first */",
+	"#endif",
+	"	bfs_store_state(trpt, boq);	/* initial state : bfs_lib.c */",
+	"}",
+	"",
+	"#ifdef BITSTATE",
+	"		#define bfs_do_store(v, n) b_store(v, n)",
+	"#else",
+	"	#ifdef USE_TDH",
+	"		#define bfs_do_store(v, n) o_store(v, n)",
+	"	#else",
+	"		#define bfs_do_store(v, n) h_store(v, n)",
+	"	#endif",
+	"#endif",
+	"",
+	"#ifdef BFS_SEP_HASH",
+	"int",
+	"bfs_seen_before(void)",
+	"{	/* cannot set trpt->tau |= 64 to mark successors outside stack */",
+	"	/* since the check is done remotely and the trpt value is gone */",
+	" #ifdef VERI",
+	"	if (!trpt->ostate		/* initial state */",
+	"	|| ((trpt->tau&4)		/* starting claim moves(s) */",
+	"	&& !(((BFS_Trail *)trpt->ostate)->tau&4))) /* prev move: prog */",
+	"	{	return 0; /* claim move: mid-state not stored */",
+	"	} /* else */",
+	" #endif",
+	"	if (!bfs_do_store((char *)&now, vsize))	/* sep_hash */",
+	"	{	nstates++;		/* local count */",
+	"		return 0;		/* new state */",
+	"	}",
+	" #ifdef BFS_CHECK",
+	"	bfs_printf(\"seen before\\n\");",
+	" #endif",
+	"	truncs++;",
+	"	return 1;			/* old state */",
+	"}",
+	"#endif",
+	"",
+	"void",
+	"bfs_explore_state(BFS_Slot *v)		/* generate all successors of v */",
+	"{	BFS_Trail *otrpt;",
+	"	Trans *t;",
+	"#ifdef HAS_UNLESS",
+	"	int E_state;",
+	"#endif",
+	"	int tt;",
+	"	short II, To = BASE, From = (short) (now._nr_pr-1);",
+	"	short oboq = boq;",
+	"	uchar _n, _m, ot;",
+	"",
+	"	memset(ntrpt, 0, sizeof(Trail));",
+	"	otrpt = bfs_unpack_state(v); /* BFS_Trail */",
+	"",
+	"	if (!otrpt) { return; } /* e.g., depth limit reached */",
+	"#ifdef L_BOUND",
+	"	#if defined(VERBOSE)",
+	"	bfs_printf(\"Unpacked state with l_bound %%d -- sds %%p\\n\",",
+	"		now._l_bnd, now._l_sds);",
+	"	#endif",
+	"#endif",
+	"",
+	"#if defined(C_States) && (HAS_TRACK==1)",
+	"	c_revert((uchar *) &(now.c_state[0]));",
+	"#endif",
+	"",
+	"#ifdef BFS_SEP_HASH",
+	"	if (bfs_seen_before()) return;",
+	"#endif",
+	"",
+	"#ifdef VERI",	/* could move to just before store_state */
+	"	if (now._nr_pr == 0	/* claim terminated */",
+	"	||  stopstate[((Pclaim *)pptr(0))->_t][((Pclaim *)pptr(0))->_p])",
+	"	{	bfs_uerror(\"end state in claim reached\");",
+	"	}",
+	"#endif",
+	"	trpt->tau &= ~1;	/* timeout off */",
+	"#ifdef VERI",
+	"	if (trpt->tau&4)	/* claim move */",
+	"	{	trpt->tau |= (otrpt->tau)&1; /* inherit from prog move */",
+	"		From = To = 0;	/* claim */",
+	"		goto Repeat_two;",
+	"	}",
+	"#endif",
+	"#ifndef NOREDUCE",
+	"	if (boq == -1 && !(trpt->tau&8) && bfs_nps == 0)",
+	"	for (II = now._nr_pr-1; II >= BASE; II -= 1)",
+	"	{",
+	"Pickup:	this = pptr(II);",
+	"		tt = (int) ((P0 *)this)->_p;",
+	"		ot = (uchar) ((P0 *)this)->_t;",
+	"		if (trans[ot][tt]->atom & 8)",
+	"		{	t = trans[ot][tt];",
+	"			if (t->qu[0] != 0)",
+	"			{	if (!q_cond(II, t))",
+	"					continue;",
+	"			}",
+	"			From = To = II;",
+	"			trpt->tau |= 32; /* preselect marker */",
+	"	#ifdef VERBOSE",
+	"			bfs_printf(\"%%3ld: proc %%d PreSelected (tau=%%d)\\n\", ",
+	"				depth, II, trpt->tau);",
+	"	#endif",
+	"			goto Repeat_two;",
+	"	}	}",
+	"	trpt->tau &= ~32;",
+	"#endif",
+	"",
+	"Repeat_one:",
+	"	if (trpt->tau&8)",
+	"	{	From = To = (short ) trpt->pr;	/* atomic */",
+	"	} else",
+	"	{	From = now._nr_pr-1;",
+	"		To = BASE;",
+	"	}",
+	"#if defined(VERI) || !defined(NOREDUCE) || defined(ETIM)",
+	"Repeat_two: /* MainLoop */",
+	"#endif",
+	"	_n = _m = 0;",
+	"	for (II = From; II >= To; II -= 1)	/* all processes */",
+	"	{",
+	"#ifdef BFS_CHECK",
+	"		bfs_printf(\"proc %%d (%%d - %%d)\\n\", II, From, To);",
+	"#endif",
+	"#if SYNC	",
+	"		if (boq != -1 && trpt->pr == II)",
+	"		{	continue;	/* no rendezvous with same proc */",
+	"		}",
+	"#endif",
+	"		this = pptr(II);",
+	"		tt = (int) ((P0 *)this)->_p;",
+	"		ot = (uchar) ((P0 *)this)->_t;",
+	"		ntrpt->pr = (uchar) II;",
+	"		ntrpt->st = tt;	",
+	"		trpt->o_pm &= ~1; /* no move yet */",
+	"#ifdef EVENT_TRACE",
+	"		trpt->o_event = now._event;",
+	"#endif",
+	"#ifdef HAS_PRIORITY",
+	"		if (!highest_priority(((P0 *)this)->_pid, II, t))",
+	"		{	continue;",
+	"		}",
+	"#else",
+	"	#ifdef HAS_PROVIDED",
+	"		if (!provided(II, ot, tt, t))",
+	"		{	continue;",
+	"		}",
+	"	#endif",
+	"#endif",
+	"#ifdef HAS_UNLESS",
+	"		E_state = 0;",
+	"#endif",
+	"		for (t = trans[ot][tt]; t; t = t->nxt)	/* all process transitions */",
+	"		{",
+	"#ifdef BFS_CHECK",
+	"			assert(t_id_lkup[t->t_id] == t); /* for reverse lookup in bfs_unpack_state */",
+	"#endif",
+	"#ifdef VERBOSE",
+	"			if (0) bfs_printf(\"\\tproc %%d tr %%d\\n\", II, t->forw);",
+	"#endif",
+	"#ifdef HAS_UNLESS",
+	"			if (E_state > 0",
+	"			&&  E_state != t->e_trans)",
+	"				break;",
+	"#endif",
+	"			/* trpt->o_t = */ ntrpt->o_t = t;",
+	"			oboq = boq;",
+	"",
+	"			if (!(_m = do_transit(t, II)))",
+	"				continue;",
+	"",
+	"			trpt->o_pm |= 1;		/* we moved */",
+	"			(trpt+1)->o_m = _m;		/* for unsend */",
+	"#ifdef PEG",
+	"			peg[t->forw]++;",
+	"#endif",
+	"#ifdef VERBOSE",
+	"			e_critical(BFS_PRINT);",
+	"			printf(\"%%3ld: proc %%d exec %%d, \",",
+	"				depth, II, t->forw);",
+	"			printf(\"%%d to %%d, %%s %%s %%s\",",
+	"				tt, t->st, t->tp,",
+	"				(t->atom&2)?\"atomic\":\"\",",
+	"				(boq != -1)?\"rendez-vous\":\"\");",
+	"	#ifdef HAS_UNLESS",
+	"			if (t->e_trans)",
+	"				printf(\" (escapes to state %%d)\", t->st);",
+	"	#endif",
+	"			printf(\" %%saccepting [tau=%%d]\\n\",",
+	"				(trpt->o_pm&2)?\"\":\"non-\", trpt->tau);",
+	"			x_critical(BFS_PRINT);",
+	"#endif",
+	"#ifdef HAS_UNLESS",
+	"			E_state = t->e_trans;",
+	"	#if SYNC>0",
+	"			if (t->e_trans > 0 && boq != -1)",
+	"			{ fprintf(efd, \"error:	rendezvous stmnt in the escape clause\\n\");",
+	"			  fprintf(efd, \"	of unless stmnt not compatible with -DBFS\\n\");",
+	"			  pan_exit(1);",
+	"			}",
+	"	#endif",
+	"#endif",
+	"			if (t->st > 0)",
+	"			{	((P0 *)this)->_p = t->st;",
+	"			}",
+	"			/* use the ostate ptr, with type *H_el, to temporarily store *BFS_Trail */",
+	"#ifdef BFS_NOTRAIL",
+	"			ntrpt->ostate = (H_el *) 0;	/* no error-traces in this mode */",
+	"#else",
+	"			ntrpt->ostate = (H_el *) otrpt;	/* parent stackframe */",
+	"#endif",
+	"		/*	ntrpt->st = tt;		* was already set above */",
+	"",
+	"			if (boq == -1 && (t->atom&2))	/* atomic */",
+	"			{	ntrpt->tau = 8;		/* record for next move */",
+	"			} else",
+	"			{	ntrpt->tau = 0;		/* no timeout or preselect etc */",
+	"			}",
+	"#ifdef VERI",
+	"			ntrpt->tau |= trpt->tau&4;	/* if claim, inherit */",
+	"			if (boq == -1 && !(ntrpt->tau&8))	/* unless rv or atomic */",
+	"			{	if (ntrpt->tau&4)	/* claim */",
+	"				{	ntrpt->tau &= ~4; /* switch to prog */",
+	"				} else",
+	"				{	ntrpt->tau |=  4; /* switch to claim */",
+	"			}	}",
+	"#endif",
+	"#ifdef L_BOUND",
+	"			{  uchar obnd = now._l_bnd;",
+	"			   uchar *os  = now._l_sds;",
+	"	#ifdef VERBOSE",
+	"			   bfs_printf(\"saving bound %%d -- sds %%p\\n\", obnd, (void *) os);",
+	"	#endif",
+	"#endif",
+	"",
+	"			   bfs_store_state(ntrpt, oboq);",
+	"#ifdef EVENT_TRACE",
+	"			   now._event = trpt->o_event;",
+	"#endif",
+	"			   /* undo move and generate other successor states */",
+	"			   trpt++;	/* this is where ovals and ipt are set */",
+	"			   do_reverse(t, II, _m);	/* restore now. */",
+	"#ifdef L_BOUND",
+	"	#ifdef VERBOSE",
+	"			   bfs_printf(\"restoring bound %%d -- sds %%p\\n\", obnd, (void *) os);",
+	"	#endif",
+	"			   now._l_bnd = obnd;",
+	"			   now._l_sds = os;",
+	"			}",
+	"#endif",
+	"			trpt--;",
+	"#ifdef VERBOSE",
+	"			e_critical(BFS_PRINT);",
+	"			printf(\"%%3ld: proc %%d \",  depth, II);",
+	"			printf(\"reverses %%d, %%d to %%d,\", t->forw, tt, t->st);",
+	"			printf(\" %%s [abit=%%d,adepth=%%d,\", t->tp, now._a_t, 0);",
+	"			printf(\"tau=%%d,%%d]\\n\", trpt->tau, (trpt-1)->tau);",
+	"			x_critical(BFS_PRINT);",
+	"#endif",
+	"			reached[ot][t->st] = 1;",
+	"			reached[ot][tt]    = 1;",
+	"",
+	"			((P0 *)this)->_p = tt;",
+	"			_n |= _m;",
+	"	}	}",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"done _n = %%d\\n\", _n);",
+	"#endif",
+	"",
+	"#ifndef NOREDUCE",
+	"	/* preselected - no succ definitely outside stack */",
+	"	if ((trpt->tau&32) && !(trpt->tau&64))",
+	"	{	From = now._nr_pr-1; To = BASE;",
+	"	#ifdef VERBOSE",
+	"		bfs_printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
+	"			depth, II+1, (int) _n, trpt->tau);",
+	"	#endif",
+	"		_n = 0; trpt->tau &= ~32;",
+	"		if (II >= BASE)",
+	"		{	goto Pickup;",
+	"		}",
+	"		goto Repeat_two;",
+	"	}",
+	"	trpt->tau &= ~(32|64);",
+	"#endif",
+	"	if (_n == 0",
+	"#ifdef VERI",
+	"	&& !(trpt->tau&4)",
+	"#endif",
+	"	)",
+	"	{	/* no successor states generated */",
+	"		if (boq != -1)				/* was rv move */",
+	"		{	BFS_Trail *x = (BFS_Trail *) trpt->ostate; /* pre-rv state */",
+	"			if (x && ((x->tau&8) || (x->tau&32))) /* break atomic or preselect */",
+	"			{	x->o_pm |= 8;		/* mark failure */",
+	"				this = pptr(otrpt->pr);",
+	"				((P0 *) this)->_p = otrpt->st;	/* reset state */",
+	"				unsend(boq);		/* retract rv offer */",
+	"				boq = -1;",
+	"#ifdef VERBOSE",
+	"				printf(\"repush state\\n\");",
+	"#endif",
+	"				bfs_push_state(NULL, x, x->o_tt); /* repush rv fail */",
+	"			} /* else the rv need not be retried */",
+	"		} else if (now._nr_pr > BASE)		/* possible deadlock */",
+	"		{	if ((trpt->tau&8))		/* atomic step blocked */",
+	"			{	trpt->tau &= ~(1|8);	/* 1=timeout, 8=atomic */",
+	"				goto Repeat_one;",
+	"			}",
+	"#ifdef ETIM",
+	"			/* if timeouts were used in the model */",
+	"			if (!(trpt->tau&1))",
+	"			{	trpt->tau |= 1;		/* enable timeout */",
+	"				goto Repeat_two;",
+	"			}",
+	"#endif",
+	"			if (!noends && !endstate())",
+	"			{	bfs_uerror(\"invalid end state.\");",
+	"			}",
+	"		}",
+	"#ifdef VERI",
+	"		else /* boq == -1 && now._nr_pr == BASE && trpt->tau != 4 */",
+	"		{	trpt->tau |= 4; /* switch to claim for stutter moves */",
+	"	#ifdef VERBOSE",
+	"			printf(\"%%3ld: proc -1 exec -1, (stutter move)\\n\", depth, II);",
+	"	#endif",
+	"			bfs_store_state(trpt, boq);", /* doesn't store it but queues it */
+	"	#ifdef VERBOSE",
+	"			printf(\"%%3ld: proc -1 reverses -1, (stutter move)\\n\", depth, II);",
+	"	#endif",
+	"			trpt->tau &= ~4; /* undo, probably not needed */",
+	"		}",
+	"#endif",
+	"	}",
+	"#ifdef BFS_NOTRAIL",
+	"	bfs_release_trail(otrpt);",
+	"#endif",
+	"}",
+	"#if !defined(BFS_FIFO) && !defined(BFS_NORECYCLE)",
+	"void",
+	"bfs_recycle(BFS_Slot *n)",
+	"{",
+	"	#ifdef BFS_CHECK",
+	"	 assert(n != &bfs_null);",
+	"	#endif",
+	"	n->nxt = bfs_free_slot;",
+	"	bfs_free_slot = n;",
+	"",
+	"	#ifdef BFS_CHECK",
+	"	 bfs_printf(\"recycles %%s -- %%p\\n\",",
+	"		n->s_data?\"STATE\":\"EMPTY\", (void *) n);",
+	"	#endif",
+	"}",
+	"#endif",
+	"#ifdef BFS_FIFO",
+	"int",
+	"bfs_empty(int p)",	/* return Cores if all empty or index of first non-empty q of p */
+	"{	int i;",
+	"	const int dst = 0;",
+	"	for (i = 0; i < Cores; i++)",
+	"	{	if (shared_memory->head[dst][p][i] != (BFS_Slot *) 0)",
+	"		{",
+	"			volatile BFS_Slot *x = shared_memory->head[dst][p][i];",
+	"			while (x && x->type == DELETED)",
+	"			{	x = x->nxt;",
+	"			}",
+	"			if (!x)",
+	"			{	continue;",
+	"			}",
+	"			if (p == who_am_i)",
+	"			{	shared_memory->head[dst][p][i] = x;",
+	"			}",
+	"	#ifdef BFS_CHECK",
+	"			bfs_printf(\"input q [%%d][%%d][%%d] !empty\\n\",",
+	"				dst, p, i);",
+	"	#endif",
+	"			return i;",
+	"	}	}",
+	"	#ifdef BFS_CHECK",
+	"	 bfs_printf(\"all input qs [%%d][%%d][0..max] empty\\n\",",
+	"		dst, p);",
+	"	#endif		",
+	"	return Cores;",
+	"}",
+	"#endif",
+	"#ifdef BFS_DISK",
+	"void",
+	"bfs_ewrite(int fd, const void *p, size_t count)",
+	"{",
+	"	if (write(fd, p, count) != count)",
+	"	{	perror(\"diskwrite\");",
+	"		Uerror(\"aborting\");",
+	"	}",
+	"}",
+	"",
+	"void",
+	"bfs_eread(int fd, void *p, size_t count)",
+	"{",
+	"	if (read(fd, p, count) != count)",
+	"	{	perror(\"diskread\");",
+	"		Uerror(\"aborting\");",
+	"	}",
+	"}",
+	"",
+	"void",
+	"bfs_sink_disk(int who_are_you, BFS_Slot *n)",
+	"{	SV_Hold *x;",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"sink_disk -> %%d\\n\", who_are_you);",
+	"#endif",
+	"	bfs_ewrite(bfs_out_fd[who_are_you], (const void *) n->s_data->t_info, sizeof(BFS_Trail));",
+	"	bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &vsize, sizeof(ulong));",
+	"	bfs_ewrite(bfs_out_fd[who_are_you], &now, vsize);",
+	"",
+	"	bfs_release_trail(n->s_data->t_info);",
+	"	n->s_data->t_info = (BFS_Trail *) 0;",
+	"",
+	"#if NRUNS>0",
+	"	bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &(n->s_data->omask), sizeof(EV_Hold *));",
+	"#endif",
+	"#ifdef Q_PROVISO",
+	"	bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &(n->s_data->lstate), sizeof(H_el *));",
+	"#endif",
+	"#if SYNC>0",
+	"	bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &(n->s_data->boq), sizeof(short));",
+	"#endif",
+	"#if VERBOSE",
+	"	bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &(n->s_data->nr), sizeof(ulong));",
+	"#endif",
+	"	shared_memory->bfs_out_cnt[who_am_i] = 1;", /* wrote at least one state */
+	"}",
+	"void",
+	"bfs_source_disk(int fd, volatile BFS_Slot *n)",
+	"{	ulong	  nb; /* local temporary */",
+	"	SV_Hold  *x;",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"source_disk <- %%d\\n\", who_am_i);",
+	"#endif",
+	"	n->s_data->t_info = bfs_grab_trail();",
+	"	bfs_eread(fd, (void *) n->s_data->t_info, sizeof(BFS_Trail));",
+	"	bfs_eread(fd, (void *) &nb, sizeof(ulong));",
+	"",
+	"	x = bfs_new_sv(nb);	/* space for osv isn't already allocated */",
+	"	n->s_data->osv = x->sv;",
+	"	x->sv = (State *) 0;",
+	"	x->nxt = bfs_free_hold;",
+	"	bfs_free_hold = x;",
+	"",
+	"	bfs_eread(fd, (void *) n->s_data->osv, (size_t) nb);",
+	"#if NRUNS>0",
+	"	bfs_eread(fd, (void *) &(n->s_data->omask), sizeof(EV_Hold *));",
+	"#endif",
+	"#ifdef Q_PROVISO",
+	"	bfs_eread(fd, (void *) &(n->s_data->lstate), sizeof(H_el *));",
+	"#endif",
+	"#if SYNC>0",
+	"	bfs_eread(fd, (void *) &(n->s_data->boq), sizeof(short));",
+	"#endif",
+	"#if VERBOSE",
+	"	bfs_eread(fd, (void *) &(n->s_data->nr), sizeof(ulong));",
+	"#endif",
+	"}",
+	"#endif",
+	"",
+	"#ifndef BFS_QSZ",
+	" #ifdef BFS_STAGGER",
+	"static BFS_Slot *bfs_stage[BFS_STAGGER];",
+	"",
+	"static void",
+	"bfs_stagger_flush(void)",
+	"{	int i, who_are_you;",
+	"	int dst = 1 - bfs_toggle;",
+	"	BFS_Slot *n;",
+	"	who_are_you = (rand()%%Cores);", /* important: all to the same cpu, but reversed */
+	"	for (i = bfs_stage_cnt-1; i >= 0; i--)",
+	"	{	n = bfs_stage[i];",
+	" #ifdef BFS_DISK",
+	"		bfs_sink_disk(who_are_you, n);",
+	"		bfs_stage[i] = (BFS_Slot *) 0;",
+	" #endif",
+	"		n->nxt = (BFS_Slot *) shared_memory->head[dst][who_are_you][who_am_i];",
+	"		shared_memory->head[dst][who_are_you][who_am_i] = n;",
+	"		/* bfs_sent++; */",
+	"	}",
+	"	#ifdef VERBOSE",
+	"		bfs_printf(\"stagger flush %%d states to %%d\\n\",",
+	"			bfs_stage_cnt, who_are_you);",
+	"	#endif",
+	"	bfs_stage_cnt = 0;",
+	"}",
+	"",
+	"void",
+	"bfs_stagger_add(BFS_Slot *n)",
+	"{",
+	"	if (bfs_stage_cnt == BFS_STAGGER)",
+	"	{	bfs_stagger_flush();",
+	"	}",
+	"	bfs_stage[bfs_stage_cnt++] = n;",
+	"}",
+	" #endif",
+	"#endif",
+	"",
+	"void",
+	"bfs_push_state(Trail *x, BFS_Trail *y, int tt)",
+	"{	int who_are_you;",
+	"#ifdef BFS_FIFO",
+	"	const int dst = 0;",
+	"#else",
+	"	int dst = 1 - bfs_toggle;",
+	"#endif",
+	"#ifdef BFS_QSZ",
+	"	uint z;",
+	"	if (bfs_keep_state > 0)",
+	"	{	who_are_you = bfs_keep_state - 1;",
+	"	} else",
+	"	{	who_are_you = (rand()%%Cores);",
+	"	}",
+	"	z = shared_memory->bfs_ix[dst][who_are_you][who_am_i];",
+	"	if (z >= BFS_QSZ)",
+	"	{	static int warned_qloss = 0;",
+	"		if (warned_qloss == 0 && who_am_i == 0)",
+	"		{	warned_qloss++;",
+	"			bfs_printf(\"BFS_QSZ too small - losing states\\n\");",
+	"		}",
+	"		bfs_punt++;",
+	"		return;",
+	"	}",
+	"	shared_memory->bfs_ix[dst][who_are_you][who_am_i] = z+1;",
+	"	BFS_Slot *n = bfs_pack_state(x, y, tt, bfs_prep_slot(y, ",
+	"		(BFS_Slot *) &(shared_memory->bfsq[dst][who_are_you][who_am_i][z])));",
+	"#else",
+	"	BFS_Slot *n = bfs_pack_state(x, y, tt, bfs_new_slot(y));",
+	"",
+	" #ifdef BFS_GREEDY",
+	"	who_are_you = who_am_i; /* for testing only */",
+	" #else",
+	"	if (bfs_keep_state > 0)",
+	"	{	who_are_you = bfs_keep_state - 1;",
+	"	} else",
+	"	{",
+	"	#ifdef BFS_STAGGER",
+	"		who_are_you = -1;",
+	"		bfs_stagger_add(n);",
+	"		goto done;",
+	"	#else",
+	"		who_are_you = (rand()%%Cores);",
+	"	#endif",
+	"	}",
+	" #endif",
+	" #ifdef BFS_FIFO",
+	"	  if (!shared_memory->tail[dst][who_are_you][who_am_i])",
+	"	  {	shared_memory->dels[dst][who_are_you][who_am_i] =",
+	"		shared_memory->tail[dst][who_are_you][who_am_i] =",
+	"		shared_memory->head[dst][who_are_you][who_am_i] = n;",
+	"	  } else",
+	"	  {	shared_memory->tail[dst][who_are_you][who_am_i]->nxt = n;",
+	"		shared_memory->tail[dst][who_are_you][who_am_i] = n;",
+	"	  }",
+	"	  shared_memory->bfs_idle[who_are_you] = 0;",
+	" #else",
+	"  #ifdef BFS_DISK",
+	"	  bfs_sink_disk(who_are_you, n);",
+	"  #endif",
+	"	  n->nxt = (BFS_Slot *) shared_memory->head[dst][who_are_you][who_am_i];",
+	"	  shared_memory->head[dst][who_are_you][who_am_i] = n;",
+	" #endif",
+	" #ifdef BFS_STAGGER",
+	"done:",
+	" #endif",
+	"#endif", /* BFS_QSZ */
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"PUT STATE (depth %%ld, nr %%u) to %%d -- s_data: %%p\\n\",",
+	"		tt, n->s_data->nr, who_are_you, n->s_data);",
+	"#endif",
+	"	bfs_sent++;",
+	"}",
+	"",
+	"BFS_Slot *",
+	"bfs_next(void)",
+	"{	volatile BFS_Slot *n = &bfs_null;",
+	" #ifdef BFS_FIFO",
+	"	const int src = 0;",
+	"	bfs_qscan = bfs_empty(who_am_i);",
+	" #else",
+	"	const int src = bfs_toggle;",
+	"  #ifdef BFS_QSZ",
+	"	while (bfs_qscan < Cores",
+	"	&& shared_memory->bfs_ix[src][who_am_i][bfs_qscan] == 0)",
+	"	{	bfs_qscan++;",
+	"	}",
+	"  #else",
+	"	while (bfs_qscan < Cores",
+	"	&& shared_memory->head[src][who_am_i][bfs_qscan] == (BFS_Slot *) 0)",
+	"	{	bfs_qscan++;",
+	"	}",
+	"  #endif",
+	" #endif",
+	"	if (bfs_qscan < Cores)",
+	"	{",
+	" #ifdef BFS_FIFO",			/* no wait for toggles */
+	"		shared_memory->bfs_idle[who_am_i] = 0;",
+	"		for (n = shared_memory->head[src][who_am_i][bfs_qscan]; n; n = n->nxt)",
+	"		{	if (n->type != DELETED)",
+	"			{	break;",
+	"		}	}",
+	"	#ifdef BFS_CHECK",
+	"		assert(n && n->type == STATE); /* q cannot be empty */",
+	"	#endif",
+	"		if (n->nxt)",
+	"		{	shared_memory->head[src][who_am_i][bfs_qscan] = n->nxt;",
+	"		}",	/* else, do not remove it - yet - avoid empty queues */
+	"		n->type = DELETED;",
+	" #else",
+	"	#ifdef BFS_QSZ",
+	"		uint x = --shared_memory->bfs_ix[src][who_am_i][bfs_qscan];",
+	"		n = &(shared_memory->bfsq[src][who_am_i][bfs_qscan][x]);",
+	"	#else",
+	"		n = shared_memory->head[src][who_am_i][bfs_qscan];",
+	"		shared_memory->head[src][who_am_i][bfs_qscan] = n->nxt;",
+	"		#if defined(BFS_FIFO) && defined(BFS_CHECK)",
+	"			assert(n->type == STATE);",
+	"		#endif",
+	"		n->nxt = (BFS_Slot *) 0;",
+	"	#endif",
+	"	#ifdef BFS_DISK",
+	"		/* the states actually show up in reverse order (FIFO iso LIFO) here */",
+	"		/* but that doesnt really matter as long as the count is right */",
+	"		bfs_source_disk(bfs_inp_fd[bfs_qscan], n); /* get the data */",
+	"	#endif",
+
+	" #endif",
+	" #ifdef BFS_CHECK",
+	"		bfs_printf(\"rcv STATE from [%%d][%%d][%%d]\\n\",",
+	"			src, who_am_i, bfs_qscan);",
+	" #endif",
+	"		bfs_rcvd++;",
+	"	} else",
+	"	{",
+	" #if defined(BFS_STAGGER) && !defined(BFS_QSZ)",
+	"		if (bfs_stage_cnt > 0)",
+	"		{	bfs_stagger_flush();",
+	"		}",
+	" #endif",
+	"		shared_memory->bfs_idle[who_am_i] = 1;",
+	" #if defined(BFS_FIFO) && defined(BFS_CHECK)",
+	"		assert(n->type == EMPTY);",
+	" #endif",
+	"	}",
+	"	return (BFS_Slot *) n;",
+	"}",
+	"",
+	"int",
+	"bfs_all_empty(void)",
+	"{	int i;",
+	"#ifdef BFS_DISK",
+	"	for (i = 0; i < Cores; i++)",
+	"	{	if (shared_memory->bfs_out_cnt[i] != 0)",
+	"		{",
+	"  #ifdef VERBOSE",
+	"			bfs_printf(\"bfs_all_empty %%d not empty\\n\", i);",
+	"  #endif",
+	"			return 0;",
+	"	}	}",
+	"#else",
+	"	int p;",
+	"  #ifdef BFS_FIFO",
+	"	const int dst = 0;",
+	"  #else",
+	"	int dst = 1 - bfs_toggle; /* next generation */",
+	"  #endif",
+	"	for (p = 0; p < Cores; p++)",
+	"	for (i = 0; i < Cores; i++)",
+	"  #ifdef BFS_QSZ",
+	"	{	if (shared_memory->bfs_ix[dst][p][i] > 0)",
+	"  #else",
+	"	{	if (shared_memory->head[dst][p][i] != (BFS_Slot *) 0)",
+	"  #endif",
+	"		{	return 0;",
+	"	}	}",
+	"#endif",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"bfs_all_empty\\n\");",
+	"#endif",
+	"	return 1;",
+	"}",
+	"",
+	"#ifdef BFS_FIFO",
+	"BFS_Slot *",
+	"bfs_sweep(void)",
+	"{	BFS_Slot *n;",
+	"	int i;",
+	"	for (i = 0; i < Cores; i++)",
+	"	for (n = (BFS_Slot *) shared_memory->dels[0][who_am_i][i];",
+	"		n && n != shared_memory->head[0][who_am_i][i];",
+	"		n = n->nxt)",
+	"	{	if (n->type == DELETED && n->nxt)",
+	"		{	shared_memory->dels[0][who_am_i][i] = n->nxt;",
+	"			n->nxt = (BFS_Slot *) 0;",
+	"			return n;",
+	"	}	}",
+	"	return (BFS_Slot *) sh_malloc((ulong) sizeof(BFS_Slot));",
+	"}",
+	"#endif",
+	"",
+	"typedef struct BFS_T_Hold BFS_T_Hold;",
+	"struct BFS_T_Hold {",
+	"	volatile BFS_Trail *t;",
+	"	BFS_T_Hold *nxt;",
+	"};",
+	"BFS_T_Hold *bfs_t_held, *bfs_t_free;",
+	"",
+	"BFS_Trail *",
+	"bfs_grab_trail(void)",			/* call in bfs_source_disk and bfs_new_slot */
+	"{	BFS_Trail *t;",
+	"	BFS_T_Hold *h;",
+	"",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"grab trail - bfs_t_held %%p\\n\", (void *) bfs_t_held);",
+	"#endif",
+	"	if (bfs_t_held)",
+	"	{	h = bfs_t_held;",
+	"		bfs_t_held = bfs_t_held->nxt;",
+	"		t = (BFS_Trail *) h->t;",
+	"		h->t = (BFS_Trail *) 0; /* make sure it cannot be reused */",
+	"		h->nxt = bfs_t_free;",
+	"		bfs_t_free = h;",
+	"",
+	"	} else",
+	"	{	t = (BFS_Trail *) sh_malloc((ulong) sizeof(BFS_Trail));",
+	"	}",
+	"#ifdef BFS_CHECK",
+	"	assert(t);",
+	"#endif",
+	"	t->ostate = (H_el *) 0;",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"grab trail %%p\\n\", (void *) t);",
+	"#endif",
+	"	return t;",
+	"}",
+	"",
+	"#if defined(BFS_DISK) || defined(BFS_NOTRAIL)",
+	"void",
+	"bfs_release_trail(BFS_Trail *t)",	/* call in bfs_sink_disk (not bfs_recycle) */
+	"{	BFS_T_Hold *h;",
+	" #ifdef BFS_CHECK",
+	"	assert(t);",
+	" #endif",
+	" #ifdef VERBOSE",
+	"	bfs_printf(\"release trail %%p\\n\", (void *) t);",
+	"	#endif",
+	"	if (bfs_t_free)",
+	"	{	h = bfs_t_free;",
+	"		bfs_t_free = bfs_t_free->nxt;",
+	"	} else",
+	"	{	h = (BFS_T_Hold *) emalloc(sizeof(BFS_T_Hold));",
+	"	}",
+	"	h->t = t;",
+	"	h->nxt = bfs_t_held;",
+	"	bfs_t_held = h;",
+	" #ifdef VERBOSE",
+	"	bfs_printf(\"release trail - bfs_t_held %%p\\n\", (void *) bfs_t_held);",
+	" #endif",
+	"}",
+	"#endif",
+	"",
+	"#ifndef BFS_QSZ",
+	"BFS_Slot *",
+	"bfs_new_slot(BFS_Trail *f)",
+	"{	BFS_Slot *t;",
+	"",
+	"#ifdef BFS_FIFO",
+	"	t = bfs_sweep();",
+	"#else",
+	"	if (bfs_free_slot)	/* local */",
+	"	{	t = bfs_free_slot;",
+	"		bfs_free_slot = bfs_free_slot->nxt;",
+	"		t->nxt = (BFS_Slot *) 0;",
+	"	} else",
+	"	{	t = (BFS_Slot *) sh_malloc((ulong) sizeof(BFS_Slot));",
+	"	}",
+	"#endif",
+	"	if (t->s_data)",
+	"	{	memset(t->s_data, 0, sizeof(BFS_State));",
+	"	} else",
+	"	{	t->s_data = (BFS_State *) sh_malloc((ulong) sizeof(BFS_State));",
+	"	}",
+	"",
+	"	/* we keep a ptr to the frame of parent states, which is */",
+	"	/* used for reconstructing path and recovering failed rvs etc */",
+	"	/* we should not overwrite the data at this address with a memset */",
+	"",
+	"	if (f)",
+	"	{	t->s_data->t_info = f;",
+	"	} else",
+	"	{	t->s_data->t_info = bfs_grab_trail();",
+	"	}",
+	"	return t;",
+	"}",
+	"#else",
+	"BFS_Slot *",
+	"bfs_prep_slot(BFS_Trail *f, BFS_Slot *t)",
+	"{",
+	"	if (t->s_data)",
+	"	{	memset(t->s_data, 0, sizeof(BFS_State));",
+	"	} else",
+	"	{	t->s_data = (BFS_State *) sh_malloc((ulong) sizeof(BFS_State));",
+	"	}",
+	"	if (f)",
+	"	{	t->s_data->t_info = f;",
+	"	} else",
+	"	{	t->s_data->t_info = bfs_grab_trail();",
+	"	}",
+	"	return t;",
+	"}",
+	"#endif",
+	"",
+	"SV_Hold *",
+	"bfs_new_sv(int n)",
+	"{	SV_Hold *h;",
+	"",
+	"	if (bfs_svfree[n])",
+	"	{	h = bfs_svfree[n];",
+	"		bfs_svfree[n] = h->nxt;",
+	"		h->nxt = (SV_Hold *) 0;",
+	"	} else",
+	"	{	h = (SV_Hold *) sh_malloc((ulong) sizeof(SV_Hold));",
+	"#if 0",
+	"		h->sz = n;",
+	"#endif",
+	"		h->sv = (State *) sh_malloc((ulong)(sizeof(State) - VECTORSZ + n));",
+	"	}",
+	"	memcpy((char *)h->sv, (char *)&now, n);",
+	"	return h;",
+	"}",
+	"#if NRUNS>0",
+	"static EV_Hold *kept[VECTORSZ];	/* local */",
+	"",
+	"static void",
+	"bfs_keep(EV_Hold *v)",
+	"{	EV_Hold *h;",
+	"",
+	"	for (h = kept[v->sz]; h; h = h->nxt) /* check local list */",
+	"	{	if (v->nrpr == h->nrpr",
+	"		&&  v->nrqs == h->nrqs",
+	"#if !defined(NOCOMP) && !defined(HC)",
+	"		&&  (v->sv == h->sv || memcmp((char *) v->sv, (char *) h->sv, v->sz) == 0)",
+	"#endif",
+	"#ifdef TRIX",
+	"		)",
+	"#else",
+	"	#if NRUNS>0",
+	"		#if VECTORSZ>32000",
+	"		&&  (memcmp((char *) v->po, (char *) h->po, v->nrpr * sizeof(int)) == 0)",
+	"		&&  (memcmp((char *) v->qo, (char *) h->qo, v->nrqs * sizeof(int)) == 0)",
+	"		#else",
+	"		&&  (memcmp((char *) v->po, (char *) h->po, v->nrpr * sizeof(short)) == 0)",
+	"		&&  (memcmp((char *) v->qo, (char *) h->qo, v->nrqs * sizeof(short)) == 0)",
+	"		#endif",
+	"		&&  (memcmp((char *) v->ps, (char *) h->ps, v->nrpr * sizeof(uchar)) == 0)",
+	"		&&  (memcmp((char *) v->qs, (char *) h->qs, v->nrqs * sizeof(uchar)) == 0))",
+	"	#else",
+	"		)",
+	"	#endif",
+	"#endif",
+	"		{	break;",
+	"	}	}",
+	"",
+	"	if (!h)	/* we don't have one like it yet */",
+	"	{	v->nxt = kept[v->sz];	/* keep the original owner field */",
+	"		kept[v->sz] = v;",
+	"		/* all ptrs inside are to shared memory, but nxt is local */",
+	"	}",
+	"}",
+	"",
+	"EV_Hold *",
+	"bfs_new_sv_mask(int n)",
+	"{	EV_Hold *h;",
+	"",
+	"	for (h = kept[n]; h; h = h->nxt)",
+	"	{	if ((now._nr_pr == h->nrpr)",
+	"		&&  (now._nr_qs == h->nrqs)",
+	"#if !defined(NOCOMP) && !defined(HC) && NRUNS>0",
+	"		&& ((char *) Mask == h->sv || (memcmp((char *) Mask, h->sv, n) == 0))",
+	"#endif",
+	"#ifdef TRIX",
+	"		)",
+	"#else",
+	"	#if NRUNS>0",
+	"		#if VECTORSZ>32000",
+	"		&&  (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(int)) == 0)",
+	"		&&  (memcmp((char *) q_offset,    (char *) h->qo, now._nr_qs * sizeof(int)) == 0)",
+	"		#else",
+	"		&&  (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(short)) == 0)",
+	"		&&  (memcmp((char *) q_offset,    (char *) h->qo, now._nr_qs * sizeof(short)) == 0)",
+	"		#endif",
+	"		&&  (memcmp((char *) proc_skip, (char *) h->ps, now._nr_pr * sizeof(uchar)) == 0)",
+	"		&&  (memcmp((char *) q_skip,    (char *) h->qs, now._nr_qs * sizeof(uchar)) == 0))",
+	"	#else",
+	"		)",
+	"	#endif",
+	"#endif",
+	"		{	break;",
+	"	}	}",
+	"",
+	"	if (!h)",
+	"	{	/* once created, the contents are never modified */",
+	"		h = (EV_Hold *) sh_malloc((ulong)sizeof(EV_Hold));",
+	"		h->owner = who_am_i;",
+	"		h->sz = n;",
+	"		h->nrpr = now._nr_pr;",
+	"		h->nrqs = now._nr_qs;",
+	"#if !defined(NOCOMP) && !defined(HC) && NRUNS>0",
+	"		h->sv = (char *) Mask;	/* in shared memory, and never modified */",
+	"#endif",
+	"#if NRUNS>0 && !defined(TRIX)",
+	"		if (now._nr_pr > 0)",
+	"		{	h->ps = (char *) proc_skip;",
+	"			h->po = (char *) proc_offset;",
+	"		}",
+	"		if (now._nr_qs > 0)",
+	"		{	h->qs = (char *) q_skip;",
+	"			h->qo = (char *) q_offset;",
+	"		}",
+	"#endif",
+	"		h->nxt = kept[n];",
+	"		kept[n] = h;",
+	"	}",
+	"	return h;",
+	"}",
+	"#endif", /* NRUNS>0 */
+	"BFS_Slot *",
+	"bfs_pack_state(Trail *f, BFS_Trail *g, int search_depth, BFS_Slot *t)",
+	"{",
+	"#ifdef BFS_CHECK",
+	"	assert(t->s_data != NULL);",
+	"	assert(t->s_data->t_info != NULL);",
+	"	assert(f || g);",
+	"#endif",
+	"	if (!g)",
+	"	{	t->s_data->t_info->ostate = f->ostate;",
+	"		t->s_data->t_info->st   = f->st;",
+	"		t->s_data->t_info->o_tt = search_depth;",
+	"		t->s_data->t_info->pr   = f->pr;",
+	"		t->s_data->t_info->tau  = f->tau;",
+	"		t->s_data->t_info->o_pm = f->o_pm;",
+	"		if (f->o_t)",
+	"		{	t->s_data->t_info->t_id = f->o_t->t_id;",
+	"		} else",
+	"		{	t->s_data->t_info->t_id = -1;",
+	"			t->s_data->t_info->ostate = NULL;",
+	"		}",
+	"	} /* else t->s_data->t_info == g */",
+	"#if SYNC",
+	"	t->s_data->boq = boq;",
+	"#endif",
+	"#ifdef VERBOSE",
+	"	{	static ulong u_cnt;",
+	"		t->s_data->nr = u_cnt++;",
+	"	}",
+	"#endif",
+	"#ifdef TRIX",
+	"	sv_populate(); /* make sure now is up to date */",
+	"#endif",
+	"#ifndef BFS_DISK",
+	"	{ 	SV_Hold *x = bfs_new_sv(vsize);",
+	"		t->s_data->osv = x->sv;",
+	"		x->sv = (State *) 0;",
+	"		x->nxt = bfs_free_hold;",
+	"		bfs_free_hold = x;",
+	"	}",
+	"#endif",
+	"#if NRUNS>0",
+	"	t->s_data->omask = bfs_new_sv_mask(vsize);",
+	"#endif",
+	"",
+	"#if defined(Q_PROVISO) && !defined(BITSTATE) && !defined(NOREDUCE)",
+	"	t->s_data->lstate = Lstate;	/* Lstate is set in o_store or h_store */",
+	"#endif",
+	"#ifdef BFS_FIFO",
+	"	t->type = STATE;",
+	"#endif",
+	"	return t;",
+	"}",
+	"",
+	"void",
+	"bfs_store_state(Trail *t, short oboq)",
+	"{",
+	"#ifdef TRIX",
+	"	sv_populate();",
+	"#endif",
+	"#if defined(VERI) && defined(Q_PROVISO) && !defined(BITSTATE) && defined(FULLSTACK)",
+	"	if (!(t->tau&4)",	/* prog move */
+	"	&&    t->ostate)",	/* not initial state */
+	"	{	t->tau |= ((BFS_Trail *) t->ostate)->tau&64;",
+	"	}	/* lift 64 across claim moves */",
+	"#endif",	
+	"",
+	"#ifdef BFS_SEP_HASH",
+	"	#if SYNC",
+	"	if (boq == -1 && oboq != -1)	/* post-rv */",
+	"	{	BFS_Trail *x =  (BFS_Trail *) trpt->ostate; /* pre-rv state */",
+	"	 	if (x)",
+	"		{	x->o_pm |= 4;	/* rv complete */",
+	"	}	}",
+	"	#endif",
+	"	d_sfh((uchar *)&now, (int) vsize); /* sep-hash -- sets K1 -- overkill */",
+	"	bfs_keep_state = K1%%Cores + 1;",
+	"	bfs_push_state(t, NULL, trpt->o_tt+1);	/* bfs_store_state - sep_hash */",
+	"	bfs_keep_state = 0;",
+	"#else",
+	"	#ifdef VERI",
+#if 0
+		in VERI mode store the state when
+		(!t->ostate || (t->tau&4)) in initial state and after each program move
+
+		i.e., dont store when !(!t->ostate || (t->tau&4)) = (t->ostate && !(t->tau&4))
+		the *first* time that the tau flag is not set:
+		possibly after a series of claim moves in an atomic sequence
+#endif
+	"		if (!(t->tau&4) && t->ostate && (((BFS_Trail *)t->ostate)->tau&4))",
+	"		{	/* do not store intermediate state */",
+	"		#if defined(VERBOSE) && defined(L_BOUND)",
+	"			bfs_printf(\"Un-Stored state bnd %%d -- sds %%p\\n\",",
+	"				now._l_bnd, now._l_sds);",
+	"		#endif",
+	"			bfs_push_state(t, NULL, trpt->o_tt+1);	/* claim move */",
+	"		} else",
+	"	#endif",
+	"		if (!bfs_do_store((char *)&now, vsize))	/* includes bfs_visited */",
+	"		{	nstates++;			/* local count */",
+	"			trpt->tau |= 64;		/* bfs: succ outside stack */",
+	"	#if SYNC",
+	"			if (boq == -1 && oboq != -1)	/* post-rv */",
+	"			{	BFS_Trail *x = ",
+	"			  	(BFS_Trail *) trpt->ostate; /* pre-rv state */",
+	"			  	if (x)",
+	"				{	x->o_pm |= 4;	/* rv complete */",
+	"			}	}",
+	"	#endif",
+	"			bfs_push_state(t, NULL, trpt->o_tt+1);	/* successor */",
+	"		} else",
+	"		{	truncs++;",
+	"	#ifdef BFS_CHECK",
+	"			bfs_printf(\"seen before\\n\");",
+	"	#endif",
+	"	#if defined(Q_PROVISO) && !defined(BITSTATE) && defined(FULLSTACK)",
+	"		#ifdef USE_TDH",
+	"			if (Lstate)",	/* if BFS_INQ is set */
+	"			{	trpt->tau |= 64;",
+	"			}",
+	"		#else",
+	"			if (Lstate && Lstate->tagged)	/* bfs_store_state */",
+	"			{	trpt->tau |= 64;",
+	"			}",
+	"		#endif",
+	"	#endif",
+	"		}",
+	"#endif",
+	"}",
+	"",
+	"/*** support routines ***/",
+	"",
+	"void",
+	"bfs_clear_locks(void)",
+	"{	int i;",
+	"",
+	"	/* clear any locks held by this process only */",
+	"	if (shared_memory)",
+	"	for (i = 0; i < BFS_MAXLOCKS; i++)",
+	"	{	if (shared_memory->sh_owner[i] == who_am_i + 1)",
+	"		{	shared_memory->sh_locks[i] = 0;",
+	"#ifdef BFS_CHECK",
+	"			shared_memory->in_count[i] = 0;",
+	"#endif",
+	"			shared_memory->sh_owner[i] = 0;",
+	"	}	}",
+	"}",
+	"",
+	"void",
+	"e_critical(int which)",
+	"{	int w;",
+	"#ifdef BFS_CHECK",
+	"	assert(which >= 0 && which < BFS_MAXLOCKS);",
+	"#endif",
+	"	if (shared_memory == NULL) return;",
+	"	while (tas(&(shared_memory->sh_locks[which])) != 0)",
+	"	{	w = shared_memory->sh_owner[which]; /* sh_locks[which] could be 0 by now */",
+	"		assert(w >= 0 && w <= BFS_MAXPROCS);",
+	"		if (w > 0 && shared_memory->bfs_flag[w-1] == 2)",
+	"		{	/* multiple processes can get here; only one should do this: */",
+	"			if (tas(&(shared_memory->bfs_data[w - 1].override)) == 0)",
+	"			{	fprintf(stderr, \"cpu%%02d: override lock %%d - held by %%d\\n\",",
+	"				who_am_i, which, shared_memory->sh_owner[which]);",
+	"#ifdef BFS_CHECK",
+	"				shared_memory->in_count[which] = 0;",
+	"#endif",
+	"				shared_memory->sh_locks[which] = 0;",
+	"				shared_memory->sh_owner[which] = 0;",
+	"		}	}",
+	"		shared_memory->wait_count[which]++; /* not atomic of course */",
+	"	}",
+	"#ifdef BFS_CHECK",
+	"	if (shared_memory->in_count[which] != 0)",
+	"	{	fprintf(stderr, \"cpu%%02d: cannot happen lock %%d count %%d\\n\", who_am_i,",
+	"			which, shared_memory->in_count[which]);",
+	"	}",
+	"	shared_memory->in_count[which]++;",
+	"#endif",
+	"	shared_memory->sh_owner[which] = who_am_i+1;",
+	"}",
+	"",
+	"void",
+	"x_critical(int which)",
+	"{",
+	"	if (shared_memory == NULL) return;",
+	"#ifdef BFS_CHECK",
+	"	assert(shared_memory->in_count[which] == 1);",
+	"	shared_memory->in_count[which] = 0;",
+	"#endif",
+	"	shared_memory->sh_locks[which] = 0;",
+	"	shared_memory->sh_owner[which] = 0;",
+	"}",
+	"",
+	"void",
+	"bfs_printf(const char *fmt, ...)",
+	"{	va_list args;",
+	"",
+	"	e_critical(BFS_PRINT);",
+	"#ifdef BFS_CHECK",
+	"	if (1) { int i=who_am_i; while (i-- > 0) printf(\"  \"); }",
+	"#endif",
+	"	printf(\"cpu%%02d: \", who_am_i);",
+	"	va_start(args, fmt);",
+	"	vprintf(fmt, args);",
+	"	va_end(args);",
+	"	fflush(stdout);",
+	"	x_critical(BFS_PRINT);",
+	"}",
+	"",
+	"int",
+	"bfs_all_idle(void)",
+	"{	int i;",
+	"",
+	"	if (shared_memory)",
+	"	for (i = 0; i < Cores; i++)",
+	"	{	if (shared_memory->bfs_flag[i] == 0",
+	"		&&  shared_memory->bfs_idle[i] == 0)",
+	"		{	return 0;",
+	"	}	}",
+	"	return 1;",
+	"}",
+	"",
+	"#ifdef BFS_FIFO",
+	"int",
+	"bfs_idle_and_empty(void)",
+	"{	int p;	/* read-only */",
+	"	for (p = 0; p < Cores; p++)",
+	"	{	if (shared_memory->bfs_flag[p] == 0",
+	"		&&  shared_memory->bfs_idle[p] == 0)",
+	"		{	return 0;",
+	"	}	}",
+	"	for (p = 0; p < Cores; p++)",
+	"	{	if (bfs_empty(p) < Cores)",
+	"		{	return 0;",
+	"	}	}",
+	"	return 1;",
+	"}",
+	"#endif",
+	"",
+	"void",
+	"bfs_set_toggle(void)	/* executed by root */",
+	"{	int i;",
+	"",
+	"	if (shared_memory)",
+	"	for (i = 0; i < Cores; i++)",
+	"	{	shared_memory->bfs_idle[i] = 0;",
+	"	}",
+	"}",
+	"",
+	"int",
+	"bfs_all_running(void)	/* crash detection */",
+	"{	int i;",
+	"	for (i = 0; i < Cores; i++)",
+	"	{	if (!shared_memory || shared_memory->bfs_flag[i] > 1)",
+	"		{	return 0;",
+	"	}	}",
+	"	return 1;",
+	"}",
+	"",
+	"void",
+	"bfs_mark_done(int code)",
+	"{",
+	"	if (shared_memory)",
+	"	{	shared_memory->bfs_flag[who_am_i] = (int) code;",
+	"		shared_memory->quit = 1;",
+	"	}",
+	"}",
+	"",
+	"static uchar *",
+	"bfs_offset(int c)",
+	"{	int   p, N;",
+	"#ifdef COLLAPSE",
+	"	uchar *q = (uchar *) ncomps; /* it is the first object allocated */",
+	"	q += (256+2) * sizeof(ulong); /* preserve contents of ncomps */",
+	"#else",
+	"	uchar *q = (uchar *) &(shared_memory->allocator);",
+	"#endif",
+	"	/* _NP_+1 proctypes, reachability info:",
+	"	 * reached[x : 0 .. _NP_+1][ 0 .. NrStates[x] ]",
+	"	 */",
+	"	for (p = N = 0; p <= _NP_; p++)",
+	"	{	N += NrStates[p];	/* sum for all proctypes */",
+	"	}",
+	"",
+	"	/* space needed per proctype: N bytes */",
+	"	/* rounded up to a multiple of the word size */",
+	"	if ((N%%sizeof(void *)) != 0)	/* aligned */",
+	"	{	N += sizeof(void *) - (N%%sizeof(void *));",
+	"	}",
+	"",
+	"	q += ((c - 1) * (_NP_ + 1) * N);",
+	"	return q;",
+	"}",
+	"",
+	"static void",
+	"bfs_putreached(void)",
+	"{	uchar *q;",
+	"	int p;",
+	"",
+	"	assert(who_am_i > 0);",
+	"",
+	"	q = bfs_offset(who_am_i);",
+	"	for (p = 0; p <= _NP_; p++)",
+	"	{	memcpy((void *) q, (const void *) reached[p], (size_t) NrStates[p]);",
+	"		q += NrStates[p];",
+	"	}",
+	"}",
+	"",
+	"static void",
+	"bfs_getreached(int c)",
+	"{	uchar *q;",
+	"	int p, i;",
+	"",
+	"	assert(who_am_i == 0 && c >= 1 && c < Cores);",
+	"",
+	"	q = (uchar *) bfs_offset(c);",
+	"	for (p = 0; p <= _NP_; p++)",
+	"	for (i = 0; i < NrStates[p]; i++)",
+	"	{	reached[p][i] += *q++; /* update local copy */",
+	"	}",
+	"}",
+	"",
+	"void",
+	"bfs_update(void)",
+	"{	int i;",
+	"	volatile BFS_data *s;",
+	"",
+	"	if (!shared_memory) return;",
+	"",
+	"	s = &shared_memory->bfs_data[who_am_i];",
+	"	if (who_am_i == 0)",
+	"	{	shared_memory->bfs_flag[who_am_i] = 3; /* or else others dont stop */",
+	"		bfs_gcount = 0;",
+	"		for (i = 1; i < Cores; i++) /* start at 1 not 0 */",
+	"		{	while (shared_memory->bfs_flag[i] == 0)",
+	"			{	sleep(1);",
+	"				if (bfs_gcount++ > WAIT_MAX)	/* excessively long wait */",
+	"				{	printf(\"cpu00: give up waiting for cpu%%2d (%%d cores)\\n\", i, Cores);",
+	"					bfs_gcount = 0;",
+	"					break;",
+	"			}	}",
+	"			s = &shared_memory->bfs_data[i];",
+	"			mreached     = Max(mreached, s->mreached);",
+	"			hmax = vsize = Max(vsize,    s->vsize);",
+	"			errors   += s->errors;",
+	"			memcnt   += s->memcnt;",
+	"			nstates  += s->nstates;",
+	"			nlinks   += s->nlinks;",
+	"			truncs   += s->truncs;",
+	"			bfs_left += s->memory_left;",
+	"			bfs_punt += s->punted;",
+	"			bfs_getreached(i);",
+	"		}",
+	"	} else",
+	"	{	s->mreached = (ulong) mreached;",
+	"		s->vsize    = (ulong) vsize;",
+	"		s->errors   = (int) errors;",
+	"		s->memcnt   = (double) memcnt;",
+	"		s->nstates  = (double) nstates;",
+	"		s->nlinks   = (double) nlinks;",
+	"		s->truncs   = (double) truncs;",
+	"		s->memory_left = (ulong) bfs_left;",
+	"		s->punted      = (ulong) bfs_punt;",
+	"		bfs_putreached();",
+	"	}",
+	"}",
+	"",
+	"volatile uchar *",
+	"sh_pre_malloc(ulong n)	/* used before the local heaps are populated */",
+	"{	volatile uchar *ptr = NULL;",
+	"",
+	"	assert(!bfs_runs);",
+	"	if ((n%%sizeof(void *)) != 0)",
+	"	{	n += sizeof(void *) - (n%%sizeof(void *));",
+	"		assert((n%%sizeof(void *)) == 0);",
+	"	}",
+	"",
+	"	e_critical(BFS_MEM);	/* needed? */",
+	"		if (shared_memory->mem_left < n + 7)", /* 7 for possible alignment */
+	"		{	x_critical(BFS_MEM);",
+	"			bfs_printf(\"want %%lu, have %%lu\\n\",",
+	"				n, shared_memory->mem_left);",
+	"			bfs_shutdown(\"out of shared memory\");",
+	"			assert(0); /* should be unreachable */",
+	"		}",
+	"		ptr = shared_memory->allocator;",
+	"#if WS>4", /* align to 8 byte boundary */
+	"		{	int b = (int) ((uint64_t) ptr)&7;",
+	"			if (b != 0)",
+	"			{	ptr += (8-b);",
+	"				shared_memory->allocator = ptr;",
+	"		}	}",
+	"#endif",
+	"		shared_memory->allocator += n;",
+	"		shared_memory->mem_left -= n;",
+	"	x_critical(BFS_MEM);",
+	"",
+	"	bfs_pre_allocated += n;",
+	"",
+	"	return ptr;",
+	"}",
+	"",
+	"volatile uchar *",
+	"sh_malloc(ulong n)",
+	"{	volatile uchar *ptr = NULL;",
+	"#ifdef BFS_CHECK",
+	"	assert(bfs_runs);",
+	"#endif",
+	"	if ((n%%sizeof(void *)) != 0)",
+	"	{	n += sizeof(void *) - (n%%sizeof(void *));",
+	"#ifdef BFS_CHECK",
+	"		assert((n%%sizeof(void *)) == 0);",
+	"#endif",
+	"	}",
+	"",
+	"	/* local heap -- no locks needed */",
+	"	if (bfs_left < n)",
+	"	{	e_critical(BFS_MEM);",
+	"		if (shared_memory->mem_left >= n)",
+	"		{	ptr = (uchar *) shared_memory->allocator;",
+	"			shared_memory->allocator += n;",
+	"			shared_memory->mem_left  -= n;",
+	"			x_critical(BFS_MEM);",
+	"			return ptr;",
+	"		}",
+	"		x_critical(BFS_MEM);",
+	"#ifdef BFS_LOGMEM",
+	"		int i;",
+	"		e_critical(BFS_MEM);",
+	"		for (i = 0; i < 1024; i++)",
+	"		{	if (shared_memory->logmem[i] > 0)",
+	"			{	bfs_printf(\"\tlog[%%d]\t%%d\\n\", i, shared_memory->logmem[i]);",
+	"		}	}",
+	"		x_critical(BFS_MEM);",
+	"#endif",
+	"		bfs_shutdown(\"out of shared memory\"); /* no return */",
+	"	}",
+	"#ifdef BFS_LOGMEM",
+	"	e_critical(BFS_MEM);",
+	"	if (n < 1023)",
+	"	{	shared_memory->logmem[n]++;",
+	"	} else",
+	"	{	shared_memory->logmem[1023]++;",
+	"	}",
+	"	x_critical(BFS_MEM);",
+	"#endif",
+	"	ptr = (uchar *) bfs_heap;",
+	"	bfs_heap += n;",
+	"	bfs_left -= n;",
+	"",
+	"	if (0) printf(\"sh_malloc %%ld\\n\", n);",
+	"	return ptr;",
+	"}",
+	"",
+	"volatile uchar *",
+	"bfs_get_shared_mem(key_t key, size_t n)",
+	"{	char *rval;",
+	"",
+	"	assert(who_am_i == 0);",
+	"",
+	"	shared_mem_id = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);	/* create */",
+	"	if (shared_mem_id == -1)",
+	"	{	fprintf(stderr, \"cpu%%02d: tried to get %%d MB of shared memory\\n\",",
+	"			who_am_i, (int) n/(1024*1024));",
+	"		perror(\"shmget\");",
+	"		exit(1);",
+	"	}",
+	"	if ((rval = (char *) shmat(shared_mem_id, (void *) 0, 0)) == (char *) -1) /* attach */",
+	"	{	perror(\"shmat\");",
+	"		exit(1);",
+	"	}",
+	"	return (uchar *) rval;",
+	"}",
+	"",
+	"void",
+	"bfs_drop_shared_memory(void)",
+	"{",
+	"	if (who_am_i == 0)",
+	"	{	printf(\"pan: releasing shared memory...\");",
+	"		fflush(stdout);",
+	"	}",
+	"	if (shared_memory)",
+	"	{	shmdt(shared_memory);					/* detach */",
+	"		if (who_am_i == 0)",
+	"		{	shmctl(shared_mem_id, IPC_RMID, (void *) 0);	/* remove */",
+	"	}	}",
+	"	if (who_am_i == 0)",
+	"	{	printf(\"done\\n\");",
+	"		fflush(stdout);",
+	"	}",
+	"}",
+	"",
+	"size_t",
+	"bfs_find_largest(key_t key)",
+	"{	size_t n;",
+	"	const size_t delta = 32*1024*1024;",
+	"	int temp_id = -1;",
+	"	int atleastonce = 0;",
+	"",
+	"	for (n = delta; ; n += delta)",
+	"	{	if (WS <= 4 && n >= 1024*1024*1024)", /* was n >= INT_MAX */
+	"		{	n = 1024*1024*1024;",
+	"			break;",
+	"		}",
+	"#ifdef MEMLIM",
+	"		if ((double) n > memlim)",
+	"		{	n = (size_t) memlim;",
+	"			break;",
+	"		}",
+	"#endif",
+	"		temp_id = shmget(key, n, 0600);		/* check for stale copy */",
+	"		if (temp_id != -1)",
+	"		{	if (shmctl(temp_id, IPC_RMID, ((void *) 0)) < 0) /* remove */",
+	"			{	perror(\"remove_segment_fails 2\");",
+	"				exit(1);",
+	"		}	}",
+	"",
+	"		temp_id = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);	/* create new */",
+	"		if (temp_id == -1)",
+	"		{	n -= delta;",
+	"			break;",
+	"		} else",
+	"		{	atleastonce++;",
+	"			if (shmctl(temp_id, IPC_RMID, ((void *) 0)) < 0)",
+	"			{	perror(\"remove_segment_fails 0\");",
+	"				exit(1);",
+	"	}	}	}",
+	"",
+	"	if (!atleastonce)",
+	"	{	printf(\"cpu%%02d: no shared memory n=%%d\\n\", who_am_i, (int) n);",
+	"		exit(1);",
+	"	}",
+	"",
+	"	printf(\"cpu%%02d: largest shared memory segment: %%lu MB\\n\",",
+	"		who_am_i, (ulong) n/(1024*1024));",
+	"#if 0",
+	"	#ifdef BFS_SEP_HASH",
+	"	n /= 2;	/* not n /= Cores because the queues take most memory */",
+	"	printf(\"cpu%%02d: using %%lu MB\\n\", who_am_i, (ulong) n/(1024*1024));",
+	"	#endif",
+	"#endif",
+	"	fflush(stdout);",
+	"",
+	"	if ((n/(1024*1024)) == 32)",
+	"	{ if (sizeof(void *) == 4) 	/* a 32 bit machine */",
+	"	  { fprintf(stderr, \"\\t32MB is the default; increase it to 1 GB with:\\n\");",
+	"	    fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmmax=%%d\\n\", (1<<30));",
+	"	    fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmall=%%d\\n\", (1<<30)/8192);",
+	"	  } else if (sizeof(void *) == 8)	/* a 64 bit machine */",
+	"	  { fprintf(stderr, \"\\t32MB is the default; increase it to 30 GB with:\\n\");",
+	"	    fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmmax=32212254720\\n\");",
+	"	    fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmall=7864320\\n\");",
+	"	    fprintf(stderr, \"\\tor for 60 GB:\\n\");",
+	"	    fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmmax=60000000000\\n\");",
+	"	    fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmall=30000000\\n\");",
+	"	  } else",
+	"	  { fprintf(stderr, \"\\tweird wordsize %%d\\n\", (int) sizeof(void *));",
+	"	} }",
+	"",
+	"	return n;",
+	"}",
+	"#ifdef BFS_DISK",
+	"void",
+	"bfs_disk_start(void)",	/* setup .spin*/
+	"{	int unused = system(\"rm -fr .spin\");",
+	"	if (mkdir(\".spin\", 0777) != 0)",
+	"	{	perror(\"mkdir\");",
+	"		Uerror(\"aborting\");",
+	"	}",
+	"}",
+	"void",
+	"bfs_disk_stop(void)",	/* remove .spin */
+	"{",
+	"	if (system(\"rm -fr .spin\") < 0)",
+	"	{	perror(\"rm -fr .spin/\");",
+	"	}",
+	"}",
+	"void",
+	"bfs_disk_inp(void)", /* this core only */
+	"{	int i; char fnm[16];",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"inp %%d %%d 0..%%d\\n\", bfs_toggle, who_am_i, Cores);",
+	"#endif",
+	"	for (i = 0; i < Cores; i++)",
+	"	{	sprintf(fnm, \".spin/q%%d_%%d_%%d\", bfs_toggle, who_am_i, i);",
+	"		if ((bfs_inp_fd[i] = open(fnm, 0444)) < 0)",
+	"		{	perror(\"open\");",
+	"			Uerror(fnm);",
+	"	}	}",
+	"}",
+	"void",
+	"bfs_disk_out(void)", /* this core only */
+	"{	int i; char fnm[16];",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"out %%d 0..%%d %%d\\n\", 1-bfs_toggle, Cores, who_am_i);",
+	"#endif",
+	"	shared_memory->bfs_out_cnt[who_am_i] = 0;",
+	"	for (i = 0; i < Cores; i++)",
+	"	{	sprintf(fnm, \".spin/q%%d_%%d_%%d\", 1-bfs_toggle, i, who_am_i);",
+	"		if ((bfs_out_fd[i] = creat(fnm, 0666)) < 0)",
+	"		{	perror(\"creat\");",
+	"			Uerror(fnm);",
+	"	}	}",
+	"}",
+	"void",
+	"bfs_disk_iclose(void)",
+	"{	int i;",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"close_inp\\n\");",
+	"#endif",
+	"	for (i = 0; i < Cores; i++)",
+	"	{	if (close(bfs_inp_fd[i]) < 0)",
+	"		{	perror(\"iclose\");",
+	"	}	}",
+	"}",
+	"void",
+	"bfs_disk_oclose(void)",
+	"{	int i;",
+	"#ifdef VERBOSE",
+	"	bfs_printf(\"close_out\\n\");",
+	"#endif",
+	"	for (i = 0; i < Cores; i++)",
+	"	{	if (fsync(bfs_out_fd[i]) < 0)",
+	"		{	perror(\"fsync\");",
+	"		}",
+	"		if (close(bfs_out_fd[i]) < 0)",
+	"		{	perror(\"oclose\");",
+	"	}	}",
+	"}",
+	"#endif",
+	"void",
+	"bfs_write_snap(int fd)",
+	"{	if (write(fd, snap, strlen(snap)) != strlen(snap))",
+	"	{       printf(\"pan: error writing %%s\\n\", fnm);",
+	"		bfs_shutdown(\"file system error\");",
+	"	}",
+	"}",
+	"",
+	"void",
+	"bfs_one_step(BFS_Trail *t, int fd)",
+	"{	if (t && t->t_id != (T_ID) -1)",
+	"	{	sprintf(snap, \"%%d:%%d:%%d\\n\",",
+	"			trcnt++, t->pr, t->t_id);",
+	"		bfs_write_snap(fd);",
+	"	}",
+	"}",
+	"",
+	"void",
+	"bfs_putter(BFS_Trail *t, int fd)",
+	"{	if (t && t != (BFS_Trail *) t->ostate)",
+	"		bfs_putter((BFS_Trail *) t->ostate, fd);",
+	"#ifdef L_BOUND",
+	"	if (depthfound == trcnt)",
+	"	{	strcpy(snap, \"-1:-1:-1\\n\");",
+	"		bfs_write_snap(fd);",
+	"		depthfound = -1;",
+	"	}",
+	"#endif",
+	"	bfs_one_step(t, fd);",
+	"}",
+	"",
+	"void",
+	"bfs_nuerror(char *str)",
+	"{	int fd = make_trail();",
+	"",
+	"	if (fd < 0) return;",
+	"#ifdef VERI",
+	"	sprintf(snap, \"-2:%%d:-2\\n\", (uchar) ((P0 *)pptr(0))->_t);",
+	"	bfs_write_snap(fd);",
+	"#endif",
+	"#ifdef MERGED",
+	"	sprintf(snap, \"-4:-4:-4\\n\");",
+	"	bfs_write_snap(fd);",
+	"#endif",
+	"	trcnt = 1;",
+	"	if (strstr(str, \"invalid\"))",
+	"	{	bfs_putter((BFS_Trail *) trpt->ostate, fd);",
+	"	} else",
+	"	{	BFS_Trail x;",
+	"		memset((char *) &x, 0, sizeof(BFS_Trail));",
+	"		x.pr = trpt->pr;",
+	"		x.t_id = (trpt->o_t)?trpt->o_t->t_id:0;",
+	"		x.ostate = trpt->ostate;",
+	"		bfs_putter(&x, fd);",
+	"	}",
+	"	close(fd);",
+	"	if (errors >= upto && upto != 0)",
+	"	{	bfs_shutdown(str);",
+	"	}",
+	"}",
+	"",
+	"void",
+	"bfs_uerror(char *str)",
+	"{	static char laststr[256];",
+	"",
+	"	errors++;",
+	"	if (strncmp(str, laststr, 254) != 0)",
+	"	{	bfs_printf(\"pan:%%d: %%s (at depth %%ld)\\n\",",
+	"			errors, str, ((depthfound == -1)?depth:depthfound));",
+	"		strncpy(laststr, str, 254);",
+	"	}",
+	"#ifdef HAS_CODE",
+	"	if (readtrail) { wrap_trail(); return; }",
+	"#endif",
+	"	if (every_error != 0 || errors == upto)",
+	"	{	bfs_nuerror(str);",
+	"	}",
+	"	if (errors >= upto && upto != 0)",
+	"	{	bfs_shutdown(\"bfs_uerror\");",
+	"	}",
+	"	depthfound = -1;",
+	"}\n",
+	"void",
+	"bfs_Uerror(char *str)",
+	"{	/* bfs_uerror(str); */",
+	"	bfs_printf(\"pan:%%d: %%s (at depth %%ld)\\n\", ++errors, str,",
+	"		((depthfound == -1)?depth:depthfound));",
+	"	bfs_shutdown(\"bfs_Uerror\");",
+	"}",
+	0,
+};
--- a/sys/src/cmd/spin/reprosrc.c
+++ b/sys/src/cmd/spin/reprosrc.c
@@ -1,22 +1,21 @@
 /***** spin: reprosrc.c *****/
 
-/* Copyright (c) 2002-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include <stdio.h>
+#include <assert.h>
 #include "spin.h"
 #include "y.tab.h"
 
 static int indent = 1;
 
+extern YYSTYPE yylval;
 extern ProcList	*rdy;
-void repro_seq(Sequence *);
+static void repro_seq(Sequence *);
 
 void
 doindent(void)
@@ -48,7 +47,7 @@
 	printf(" };\n");
 }
 
-void
+static void
 repro_seq(Sequence *s)
 {	Element *e;
 	Symbol *v;
@@ -96,7 +95,7 @@
 				doindent();
 				if (e->n->ntyp == C_CODE)
 				{	printf("c_code ");
-					plunk_inline(stdout, e->n->sym->name, 1);
+					plunk_inline(stdout, e->n->sym->name, 1, 1);
 				} else if (e->n->ntyp == 'c'
 				       &&  e->n->lft->ntyp == C_EXPR)
 				{	printf("c_expr { ");
@@ -133,4 +132,253 @@
 repro_src(void)
 {
 	repro_proc(rdy);
+}
+
+static int in_decl;
+static int in_c_decl;
+static int in_c_code;
+
+void
+blip(int n, char *b)
+{	char mtxt[1024];
+
+	strcpy(mtxt, "");
+
+	switch (n) {
+	default:	if (n > 0 && n < 256)
+				sprintf(mtxt, "%c", n);
+			else
+				sprintf(mtxt, "<%d?>", n);
+
+			break;
+	case '(':	strcpy(mtxt, "("); in_decl++; break;
+	case ')':	strcpy(mtxt, ")"); in_decl--; break;
+	case '{':	strcpy(mtxt, "{"); break;
+	case '}':	strcpy(mtxt, "}"); break;
+	case '\t':	sprintf(mtxt, "\\t"); break;
+	case '\f':	sprintf(mtxt, "\\f"); break;
+	case '\n':	sprintf(mtxt, "\\n"); break;
+	case '\r':	sprintf(mtxt, "\\r"); break;
+	case 'c':	sprintf(mtxt, "condition"); break;
+	case 's':	sprintf(mtxt, "send"); break;
+	case 'r':	sprintf(mtxt, "recv"); break;
+	case 'R':	sprintf(mtxt, "recv poll"); break;
+	case '@':	sprintf(mtxt, "@"); break;
+	case '?':	sprintf(mtxt, "(x->y:z)"); break;
+	case NEXT:	sprintf(mtxt, "X"); break;
+	case ALWAYS:	sprintf(mtxt, "[]"); break;
+	case EVENTUALLY: sprintf(mtxt, "<>"); break;
+	case IMPLIES:	sprintf(mtxt, "->"); break;
+	case EQUIV:	sprintf(mtxt, "<->"); break;
+	case UNTIL:	sprintf(mtxt, "U"); break;
+	case WEAK_UNTIL: sprintf(mtxt, "W"); break;
+	case IN: sprintf(mtxt, "in"); break;
+	case ACTIVE:	sprintf(mtxt, "active"); break;
+	case AND:	sprintf(mtxt, "&&"); break;
+	case ARROW:	sprintf(mtxt, "->"); break;
+	case ASGN:	sprintf(mtxt, "="); break;
+	case ASSERT:	sprintf(mtxt, "assert"); break;
+	case ATOMIC:	sprintf(mtxt, "atomic"); break;
+	case BREAK:	sprintf(mtxt, "break"); break;
+	case C_CODE:	sprintf(mtxt, "c_code"); in_c_code++; break;
+	case C_DECL:	sprintf(mtxt, "c_decl"); in_c_decl++; break;
+	case C_EXPR:	sprintf(mtxt, "c_expr"); break;
+	case C_STATE:	sprintf(mtxt, "c_state"); break;
+	case C_TRACK:	sprintf(mtxt, "c_track"); break;
+	case CLAIM:	sprintf(mtxt, "never"); break;
+	case CONST:	sprintf(mtxt, "%d", yylval->val); break;
+	case DECR:	sprintf(mtxt, "--"); break;
+	case D_STEP:	sprintf(mtxt, "d_step"); break;
+	case D_PROCTYPE: sprintf(mtxt, "d_proctype"); break;
+	case DO:	sprintf(mtxt, "do"); break;
+	case DOT:	sprintf(mtxt, "."); break;
+	case ELSE:	sprintf(mtxt, "else"); break;
+	case EMPTY:	sprintf(mtxt, "empty"); break;
+	case ENABLED:	sprintf(mtxt, "enabled"); break;
+	case EQ:	sprintf(mtxt, "=="); break;
+	case EVAL:	sprintf(mtxt, "eval"); break;
+	case FI:	sprintf(mtxt, "fi"); break;
+	case FULL:	sprintf(mtxt, "full"); break;
+	case GE:	sprintf(mtxt, ">="); break;
+	case GET_P:	sprintf(mtxt, "get_priority"); break;
+	case GOTO:	sprintf(mtxt, "goto"); break;
+	case GT:	sprintf(mtxt, ">"); break;
+	case HIDDEN:	sprintf(mtxt, "hidden"); break;
+	case IF:	sprintf(mtxt, "if"); break;
+	case INCR:	sprintf(mtxt, "++"); break;
+
+	case INLINE:	sprintf(mtxt, "inline"); break;
+	case INIT:	sprintf(mtxt, "init"); break;
+	case ISLOCAL:	sprintf(mtxt, "local"); break;
+
+	case LABEL:	sprintf(mtxt, "<label-name>"); break;
+
+	case LE:	sprintf(mtxt, "<="); break;
+	case LEN:	sprintf(mtxt, "len"); break;
+	case LSHIFT:	sprintf(mtxt, "<<"); break;
+	case LT:	sprintf(mtxt, "<"); break;
+	case LTL:	sprintf(mtxt, "ltl"); break;
+
+	case NAME:	sprintf(mtxt, "%s", yylval->sym->name); break;
+
+	case XU:	switch (yylval->val) {
+			case XR:	sprintf(mtxt, "xr"); break;
+			case XS:	sprintf(mtxt, "xs"); break;
+			default:	sprintf(mtxt, "<?>"); break;
+			}
+			break;
+
+	case TYPE:	switch (yylval->val) {
+			case BIT:	sprintf(mtxt, "bit"); break;
+			case BYTE:	sprintf(mtxt, "byte"); break;
+			case CHAN:	sprintf(mtxt, "chan"); in_decl++; break;
+			case INT:	sprintf(mtxt, "int"); break;
+			case MTYPE:	sprintf(mtxt, "mtype"); break;
+			case SHORT:	sprintf(mtxt, "short"); break;
+			case UNSIGNED:	sprintf(mtxt, "unsigned"); break;
+			default:	sprintf(mtxt, "<unknown type>"); break;
+			}
+			break;
+
+	case NE:	sprintf(mtxt, "!="); break;
+	case NEG:	sprintf(mtxt, "!"); break;
+	case NEMPTY:	sprintf(mtxt, "nempty"); break;
+	case NFULL:	sprintf(mtxt, "nfull"); break;
+
+	case NON_ATOMIC: sprintf(mtxt, "<sub-sequence>"); break;
+
+	case NONPROGRESS: sprintf(mtxt, "np_"); break;
+	case OD:	sprintf(mtxt, "od"); break;
+	case OF:	sprintf(mtxt, "of"); break;
+	case OR:	sprintf(mtxt, "||"); break;
+	case O_SND:	sprintf(mtxt, "!!"); break;
+	case PC_VAL:	sprintf(mtxt, "pc_value"); break;
+	case PRINT:	sprintf(mtxt, "printf"); break;
+	case PRINTM:	sprintf(mtxt, "printm"); break;
+	case PRIORITY:	sprintf(mtxt, "priority"); break;
+	case PROCTYPE:	sprintf(mtxt, "proctype"); break;
+	case PROVIDED:	sprintf(mtxt, "provided"); break;
+	case RCV:	sprintf(mtxt, "?"); break;
+	case R_RCV:	sprintf(mtxt, "??"); break;
+	case RSHIFT:	sprintf(mtxt, ">>"); break;
+	case RUN:	sprintf(mtxt, "run"); break;
+	case SEP:	sprintf(mtxt, "::"); break;
+	case SEMI:	sprintf(mtxt, ";"); break;
+	case SET_P:	sprintf(mtxt, "set_priority"); break;
+	case SHOW:	sprintf(mtxt, "show"); break;
+	case SND:	sprintf(mtxt, "!"); break;
+
+	case INAME:
+	case UNAME:
+	case PNAME:
+	case STRING:	sprintf(mtxt, "%s", yylval->sym->name); break;
+
+	case TRACE:	sprintf(mtxt, "trace"); break;
+	case TIMEOUT:	sprintf(mtxt, "timeout"); break;
+	case TYPEDEF:	sprintf(mtxt, "typedef"); break;
+	case UMIN:	sprintf(mtxt, "-"); break;
+	case UNLESS:	sprintf(mtxt, "unless"); break;
+	}
+	strcat(b, mtxt);
+}
+
+void
+purge(char *b)
+{
+	if (strlen(b) == 0) return;
+
+	if (b[strlen(b)-1] != ':')	/* label? */
+	{	if (b[0] == ':' && b[1] == ':')
+		{	indent--;
+			doindent();
+			indent++;
+		} else
+		{	doindent();
+		}
+	}
+	printf("%s\n", b);
+	strcpy(b, "");
+
+	in_decl = 0;
+	in_c_code = 0;
+	in_c_decl = 0;
+}
+
+int pp_mode;
+extern int lex(void);
+
+void
+pretty_print(void)
+{	int c, lastc = 0;
+	char buf[1024];
+
+	pp_mode = 1;
+	indent = 0;
+	strcpy(buf, "");
+	while ((c = lex()) != EOF)
+	{
+		if ((lastc == IF || lastc == DO) && c != SEP)
+		{	indent--;	/* c_code if */
+		}
+		if (c == C_DECL  || c == C_STATE
+		||  c == C_TRACK || c == SEP
+		||  c == DO      || c == IF
+		|| (c == TYPE && !in_decl))
+		{	purge(buf); /* start on new line */
+		}
+
+		if (c == '{'
+		&& lastc != OF && lastc != IN
+		&& lastc != ATOMIC && lastc != D_STEP
+		&& lastc != C_CODE && lastc != C_DECL && lastc != C_EXPR)
+		{	purge(buf);
+		}
+
+		if (c == PREPROC)
+		{	int oi = indent;
+			purge(buf);
+			assert(strlen(yylval->sym->name) < sizeof(buf));
+			strcpy(buf, yylval->sym->name);
+			indent = 0;
+			purge(buf);
+			indent = oi;
+			continue;
+		}
+
+		if (c != ':' && c != SEMI
+		&&  c != ',' && c != '('
+		&&  c != '#' && lastc != '#'
+		&&  c != ARROW && lastc != ARROW
+		&&  c != '.' && lastc != '.'
+		&&  c != '!' && lastc != '!'
+		&&  c != SND && lastc != SND
+		&&  c != RCV && lastc != RCV
+		&&  c != O_SND && lastc != O_SND
+		&&  c != R_RCV && lastc != R_RCV
+		&&  (c != ']' || lastc != '[')
+		&&  (c != '>' || lastc != '<')
+		&&  (c != GT || lastc != LT)
+		&&  c != '@' && lastc != '@'
+		&&  c != DO && c != OD && c != IF && c != FI
+		&&  c != SEP && strlen(buf) > 0)
+			strcat(buf, " ");
+
+		if (c == '}' || c == OD || c == FI)
+		{	purge(buf);
+			indent--;
+		}
+		blip(c, buf);
+
+		if (c == '{' || c == DO || c == IF)
+		{	purge(buf);
+			indent++;
+		}
+
+		if (c == '}' || c == BREAK || c == SEMI
+		|| (c == ':' && lastc == NAME))
+		{	purge(buf);
+		}
+		lastc = c;
+	}
+	purge(buf);
 }
--- a/sys/src/cmd/spin/run.c
+++ b/sys/src/cmd/spin/run.c
@@ -1,13 +1,10 @@
 /***** spin: run.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include <stdlib.h>
 #include "spin.h"
@@ -16,9 +13,10 @@
 extern RunList	*X, *run;
 extern Symbol	*Fname;
 extern Element	*LastStep;
-extern int	Rvous, lineno, Tval, interactive, MadeChoice;
+extern int	Rvous, lineno, Tval, interactive, MadeChoice, Priority_Sum;
 extern int	TstOnly, verbose, s_trail, xspin, jumpsteps, depth;
-extern int	nproc, nstop, no_print, like_java;
+extern int	analyze, nproc, nstop, no_print, like_java, old_priority_rules;
+extern short	Have_claim;
 
 static long	Seed = 1;
 static int	E_Check = 0, Escape_Check = 0;
@@ -25,6 +23,8 @@
 
 static int	eval_sync(Element *);
 static int	pc_enabled(Lextok *n);
+static int	get_priority(Lextok *n);
+static void	set_priority(Lextok *n, Lextok *m);
 extern void	sr_buf(int, int);
 
 void
@@ -42,15 +42,14 @@
 
 Element *
 rev_escape(SeqList *e)
-{	Element *r;
+{	Element *r = (Element *) 0;
 
-	if (!e)
-		return (Element *) 0;
+	if (e)
+	{	if ((r = rev_escape(e->nxt)) == ZE) /* reversed order */
+		{	r = eval_sub(e->this->frst);
+	}	}
 
-	if ((r = rev_escape(e->nxt)) != ZE) /* reversed order */
-		return r;
-
-	return eval_sub(e->this->frst);		
+	return r;		
 }
 
 Element *
@@ -57,9 +56,9 @@
 eval_sub(Element *e)
 {	Element *f, *g;
 	SeqList *z;
-	int i, j, k;
+	int i, j, k, only_pos;
 
-	if (!e->n)
+	if (!e || !e->n)
 		return ZE;
 #ifdef DEBUG
 	printf("\n\teval_sub(%d %s: line %d) ",
@@ -69,8 +68,13 @@
 #endif
 	if (e->n->ntyp == GOTO)
 	{	if (Rvous) return ZE;
-		LastStep = e; f = get_lab(e->n, 1);
+		LastStep = e;
+		f = get_lab(e->n, 1);
+		f = huntele(f, e->status, -1); /* 5.2.3: was missing */
 		cross_dsteps(e->n, f->n);
+#ifdef DEBUG
+		printf("GOTO leads to %d\n", f->seqno);
+#endif
 		return f;
 	}
 	if (e->n->ntyp == UNLESS)
@@ -80,6 +84,7 @@
 	{	Element *has_else = ZE;
 		Element *bas_else = ZE;
 		int nr_else = 0, nr_choices = 0;
+		only_pos = -1;
 
 		if (interactive
 		&& !MadeChoice && !E_Check
@@ -89,8 +94,10 @@
 		{	printf("Select stmnt (");
 			whoruns(0); printf(")\n");
 			if (nproc-nstop > 1)
-			printf("\tchoice 0: other process\n");
-		}
+			{	printf("\tchoice 0: other process\n");
+				nr_choices++;
+				only_pos = 0;
+		}	}
 		for (z = e->sub, j=0; z; z = z->nxt)
 		{	j++;
 			if (interactive
@@ -113,14 +120,22 @@
 				if (!Enabled0(z->this->frst))
 					printf("unexecutable, ");
 				else
-					nr_choices++;
+				{	nr_choices++;
+					only_pos = j;
+				}
 				comment(stdout, z->this->frst->n, 0);
 				printf("\n");
 		}	}
 
 		if (nr_choices == 0 && has_else)
-			printf("\tchoice %d: (else)\n", nr_else);
+		{	printf("\tchoice %d: (else)\n", nr_else);
+			only_pos = nr_else;
+		}
 
+		if (nr_choices <= 1 && only_pos != -1 && !MadeChoice)
+		{	MadeChoice = only_pos;
+		}
+
 		if (interactive && depth >= jumpsteps
 		&& !Escape_Check
 		&& !(e->status&(D_ATOM))
@@ -132,8 +147,11 @@
 				else
 					printf("Select [0-%d]: ", j);
 				fflush(stdout);
-				scanf("%s", buf);
-				if (isdigit(buf[0]))
+				if (scanf("%64s", buf) <= 0)
+				{	printf("no input\n");
+					return ZE;
+				}
+				if (isdigit((int)buf[0]))
 					k = atoi(buf);
 				else
 				{	if (buf[0] == 'q')
@@ -155,6 +173,7 @@
 			else
 				k = Rand()%j;	/* nondeterminism */
 		}
+
 		has_else = ZE;
 		bas_else = ZE;
 		for (i = 0, z = e->sub; i < j+k; i++)
@@ -215,7 +234,7 @@
 		} else
 		{	SeqList *x;
 			if (!(e->status & (D_ATOM))
-			&&  e->esc && verbose&32)
+			&&  e->esc && (verbose&32))
 			{	printf("Stmnt [");
 				comment(stdout, e->n, 0);
 				printf("] has escape(s): ");
@@ -234,11 +253,18 @@
 			if (!(e->status & D_ATOM))	/* escapes don't reach inside d_steps */
 			/* 4.2.4: only the guard of a d_step can have an escape */
 #endif
+#if 1
+			if (!s_trail)	/* trail determines selections, new 5.2.5 */
+#endif
 			{	Escape_Check++;
 				if (like_java)
 				{	if ((g = rev_escape(e->esc)) != ZE)
 					{	if (verbose&4)
-							printf("\tEscape taken\n");
+						{	printf("\tEscape taken (-J) ");
+							if (g->n && g->n->fn)
+								printf("%s:%d", g->n->fn->name, g->n->ln);
+							printf("\n");
+						}
 						Escape_Check--;
 						return g;
 					}
@@ -246,18 +272,24 @@
 				{	for (x = e->esc; x; x = x->nxt)
 					{	if ((g = eval_sub(x->this->frst)) != ZE)
 						{	if (verbose&4)
-								printf("\tEscape taken\n");
+							{	printf("\tEscape taken ");
+								if (g->n && g->n->fn)
+									printf("%s:%d", g->n->fn->name, g->n->ln);
+								printf("\n");
+							}
 							Escape_Check--;
 							return g;
 				}	}	}
 				Escape_Check--;
 			}
-		
 			switch (e->n->ntyp) {
+			case ASGN:
+				if (check_track(e->n) == STRUCT) { break; }
+				/* else fall thru */
 			case TIMEOUT: case RUN:
 			case PRINT: case PRINTM:
 			case C_CODE: case C_EXPR:
-			case ASGN: case ASSERT:
+			case ASSERT:
 			case 's': case 'r': case 'c':
 				/* toplevel statements only */
 				LastStep = e;
@@ -308,7 +340,8 @@
 		t = Sym_typ(now->rgt);
 		break;
 	}
-	typ_ck(Sym_typ(now->lft), t, "assignment"); 
+	typ_ck(Sym_typ(now->lft), t, "assignment");
+
 	return setval(now->lft, eval(now->rgt));
 }
 
@@ -371,6 +404,10 @@
 	case  NEMPTY: return (qlen(now)>0);
 	case ENABLED: if (s_trail) return 1;
 		      return pc_enabled(now->lft);
+
+	case GET_P: return get_priority(now->lft);
+	case SET_P: set_priority(now->lft->lft, now->lft->rgt); return 1;
+
 	case    EVAL: return eval(now->lft);
 	case  PC_VAL: return pc_value(now->lft);
 	case NONPROGRESS: return nonprogress();
@@ -384,15 +421,21 @@
 	case   'c': return eval(now->lft);	/* condition    */
 	case PRINT: return TstOnly?1:interprint(stdout, now);
 	case PRINTM: return TstOnly?1:printm(stdout, now);
-	case  ASGN: return assign(now);
+	case  ASGN:
+		if (check_track(now) == STRUCT) { return 1; }
+		return assign(now);
 
-	case C_CODE: printf("%s:\t", now->sym->name);
-		     plunk_inline(stdout, now->sym->name, 0);
+	case C_CODE: if (!analyze)
+		     {	printf("%s:\t", now->sym->name);
+		     	plunk_inline(stdout, now->sym->name, 0, 1);
+		     }
 		     return 1; /* uninterpreted */
 
-	case C_EXPR: printf("%s:\t", now->sym->name);
-		     plunk_expr(stdout, now->sym->name);
-		     printf("\n");
+	case C_EXPR: if (!analyze)
+		     {	printf("%s:\t", now->sym->name);
+		     	plunk_expr(stdout, now->sym->name);
+		     	printf("\n");
+		     }
 		     return 1; /* uninterpreted */
 
 	case ASSERT: if (TstOnly || eval(now->lft)) return 1;
@@ -407,6 +450,11 @@
 	case   '.': return 1;	/* return label for compound */
 	case   '@': return 0;	/* stop state */
 	case  ELSE: return 1;	/* only hit here in guided trails */
+
+	case ',':	/* reached through option -A with array initializer */
+	case 0:
+		    return 0;	/* not great, but safe */
+
 	default   : printf("spin: bad node type %d (run)\n", now->ntyp);
 		    if (s_trail) printf("spin: trail file doesn't match spec?\n");
 		    fatal("aborting", 0);
@@ -426,7 +474,6 @@
 			j = n->lft->val;
 		else
 			j = eval(n->lft);
-		Buf[0] = '\0';
 		sr_buf(j, 1);
 		dotag(fd, Buf);
 	}
@@ -437,9 +484,9 @@
 interprint(FILE *fd, Lextok *n)
 {	Lextok *tmp = n->lft;
 	char c, *s = n->sym->name;
-	int i, j; char lbuf[512];
-	extern char Buf[];
-	char tBuf[4096];
+	int i, j; char lbuf[512]; /* matches value in sr_buf() */
+	extern char Buf[];	/* global, size 4096 */
+	char tBuf[4096];	/* match size of global Buf[] */
 
 	Buf[0] = '\0';
 	if (!no_print)
@@ -490,7 +537,7 @@
 		}
 		dotag(fd, Buf);
 	}
-	if (strlen(Buf) > 4096) fatal("printf string too long", 0);
+	if (strlen(Buf) >= 4096) fatal("printf string too long", 0);
 	return 1;
 }
 
@@ -512,6 +559,7 @@
 		verbose = v;
 		return i;
 
+	case SET_P:
 	case C_CODE: case C_EXPR:
 	case PRINT: case PRINTM:
 	case   ASGN: case ASSERT:
@@ -552,6 +600,7 @@
 	case '@':
 		return X->pid == (nproc-nstop-1);
 	case '.':
+	case SET_P:
 		return 1;
 	case GOTO:
 		if (Rvous) return 0;
@@ -594,9 +643,91 @@
 	for (Y = run; Y; Y = Y->nxt)
 		if (--i == pid)
 		{	oX = X; X = Y;
-			result = Enabled0(Y->pc);
+			result = Enabled0(X->pc);
 			X = oX;
 			break;
 		}
 	return result;
+}
+
+int
+pc_highest(Lextok *n)
+{	int i = nproc - nstop;
+	int pid = eval(n);
+	int target = 0, result = 1;
+	RunList *Y, *oX;
+
+	if (X->prov && !eval(X->prov)) return 0; /* can't be highest unless fully enabled */
+
+	for (Y = run; Y; Y = Y->nxt)
+	{	if (--i == pid)
+		{	target = Y->priority;
+			break;
+	}	}
+if (0) printf("highest for pid %d @ priority = %d\n", pid, target);
+
+	oX = X;
+	i = nproc - nstop;
+	for (Y = run; Y; Y = Y->nxt)
+	{	i--;
+if (0) printf("	pid %d @ priority %d\t", Y->pid, Y->priority);
+		if (Y->priority > target)
+		{	X = Y;
+if (0) printf("enabled: %s\n", Enabled0(X->pc)?"yes":"nope");
+if (0) printf("provided: %s\n", eval(X->prov)?"yes":"nope");
+			if (Enabled0(X->pc) && (!X->prov || eval(X->prov)))
+			{	result = 0;
+				break;
+		}	}
+else
+if (0) printf("\n");
+	}
+	X = oX;
+
+	return result;
+}
+
+int
+get_priority(Lextok *n)
+{	int i = nproc - nstop;
+	int pid = eval(n);
+	RunList *Y;
+
+	if (old_priority_rules)
+	{	return 1;
+	}
+
+	for (Y = run; Y; Y = Y->nxt)
+	{	if (--i == pid)
+		{	return Y->priority;
+	}	}
+	return 0;
+}
+
+void
+set_priority(Lextok *n, Lextok *p)
+{	int i = nproc - nstop - Have_claim;
+	int pid = eval(n);
+	RunList *Y;
+
+	if (old_priority_rules)
+	{	return;
+	}
+	for (Y = run; Y; Y = Y->nxt)
+	{	if (--i == pid)
+		{	Priority_Sum -= Y->priority;
+			Y->priority = eval(p);
+			Priority_Sum += Y->priority;
+			if (1)
+			{	printf("%3d: setting priority of proc %d (%s) to %d\n",
+					depth, pid, Y->n->name, Y->priority);
+	}	}	}
+	if (verbose&32)
+	{	printf("\tPid\tName\tPriority\n");
+		for (Y = run; Y; Y = Y->nxt)
+		{	printf("\t%d\t%s\t%d\n",
+				Y->pid,
+				Y->n->name,
+				Y->priority);
+	}	}
 }
--- a/sys/src/cmd/spin/sched.c
+++ b/sys/src/cmd/spin/sched.c
@@ -1,13 +1,10 @@
 /***** spin: sched.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include <stdlib.h>
 #include "spin.h"
@@ -19,19 +16,21 @@
 extern Symbol	*Fname, *context;
 extern int	lineno, nr_errs, dumptab, xspin, jumpsteps, columns;
 extern int	u_sync, Elcnt, interactive, TstOnly, cutoff;
-extern short	has_enabled;
-extern int	limited_vis;
+extern short	has_enabled, has_priority, has_code, replay;
+extern int	limited_vis, product, nclaims, old_priority_rules;
+extern int	old_scope_rules, scope_seq[128], scope_level, has_stdin;
 
+extern int	pc_highest(Lextok *n);
+
 RunList		*X   = (RunList  *) 0;
 RunList		*run = (RunList  *) 0;
 RunList		*LastX  = (RunList  *) 0; /* previous executing proc */
 ProcList	*rdy = (ProcList *) 0;
 Element		*LastStep = ZE;
-int		nproc=0, nstop=0, Tval=0;
+int		nproc=0, nstop=0, Tval=0, Priority_Sum = 0;
 int		Rvous=0, depth=0, nrRdy=0, MadeChoice;
 short		Have_claim=0, Skip_claim=0;
 
-static int	Priority_Sum = 0;
 static void	setlocals(RunList *);
 static void	setparams(RunList *, ProcList *, Lextok *);
 static void	talk(RunList *);
@@ -42,13 +41,20 @@
 
 	r->n  = p->n;
 	r->tn = p->tn;
+	r->b  = p->b;
 	r->pid = nproc++ - nstop + Skip_claim;
+	r->priority = weight;
+	p->priority = (unsigned char) weight; /* not quite the best place of course */
 
-	if ((verbose&4) || (verbose&32))
-		printf("Starting %s with pid %d\n", p->n->name, r->pid);
-
+	if (!noparams && ((verbose&4) || (verbose&32)))
+	{	printf("Starting %s with pid %d",
+			p->n?p->n->name:"--", r->pid);
+		if (has_priority) printf(" priority %d", r->priority);
+		printf("\n");
+	}
 	if (!p->s)
-		fatal("parsing error, no sequence %s", p->n?p->n->name:"--");
+		fatal("parsing error, no sequence %s",
+			p->n?p->n->name:"--");
 
 	r->pc = huntele(p->s->frst, p->s->frst->status, -1);
 	r->ps = p->s;
@@ -58,14 +64,18 @@
 
 	r->nxt = run;
 	r->prov = p->prov;
-	r->priority = weight;
+	if (weight < 1 || weight > 255)
+	{	fatal("bad process priority, valid range: 1..255", (char *) 0);
+	}
+
 	if (noparams) setlocals(r);
 	Priority_Sum += weight;
+
 	run = r;
 }
 
 ProcList *
-ready(Symbol *n, Lextok *p, Sequence *s, int det, Lextok *prov)
+ready(Symbol *n, Lextok *p, Sequence *s, int det, Lextok *prov, enum btypes b)
 	/* n=name, p=formals, s=body det=deterministic prov=provided */
 {	ProcList *r = (ProcList *) emalloc(sizeof(ProcList));
 	Lextok *fp, *fpt; int j; extern int Npars;
@@ -73,9 +83,15 @@
 	r->n = n;
 	r->p = p;
 	r->s = s;
+	r->b = b;
 	r->prov = prov;
-	r->tn = nrRdy++;
-	r->det = (short) det;
+	r->tn = (short) nrRdy++;
+	n->sc = scope_seq[scope_level];	/* scope_level should be 0 */
+
+	if (det != 0 && det != 1)
+	{	fprintf(stderr, "spin: bad value for det (cannot happen)\n");
+	}
+	r->det = (unsigned char) det;
 	r->nxt = rdy;
 	rdy = r;
 
@@ -128,13 +144,15 @@
 			run->pid - Have_claim, run->n->name);
 			pstext(run->pid - Have_claim, Buf);
 		} else
-			printf("proc %d = %s\n",
-			run->pid - Have_claim, run->n->name);
+		{	printf("proc %d = %s\n",
+				run->pid - Have_claim, run->n->name);
+		}
 		return;
 	}
 
 	if (dumptab
 	||  analyze
+	||  product
 	||  s_trail
 	|| !(verbose&4))
 		return;
@@ -161,9 +179,11 @@
 	Symbol *s = m->sym;	/* proctype name */
 	Lextok *n = m->lft;	/* actual parameters */
 
-	if (m->val < 1) m->val = 1;	/* minimum priority */
+	if (m->val < 1)
+	{	m->val = 1;	/* minimum priority */
+	}
 	for (p = rdy; p; p = p->nxt)
-		if (strcmp(s->name, p->n->name) == 0)
+	{	if (strcmp(s->name, p->n->name) == 0)
 		{	if (nproc-nstop >= MAXP)
 			{	printf("spin: too many processes (%d max)\n", MAXP);
 				break;
@@ -173,7 +193,7 @@
 			setparams(run, p, n);
 			setlocals(run); /* after setparams */
 			return run->pid - Have_claim + Skip_claim; /* effective simu pid */
-		}
+	}	}
 	return 0; /* process not found */
 }
 
@@ -208,26 +228,29 @@
 	RunList  *r, *q = (RunList *) 0;
 
 	for (p = rdy; p; p = p->nxt)
-		if (p->tn == n
-		&&  strcmp(p->n->name, ":never:") == 0)
+		if (p->tn == n && p->b == N_CLAIM)
 		{	runnable(p, 1, 1);
 			goto found;
 		}
-	printf("spin: couldn't find claim (ignored)\n");
+	printf("spin: couldn't find claim %d (ignored)\n", n);
+	if (verbose&32)
+	for (p = rdy; p; p = p->nxt)
+		printf("\t%d = %s\n", p->tn, p->n->name);
+
 	Skip_claim = 1;
 	goto done;
 found:
 	/* move claim to far end of runlist, and reassign it pid 0 */
 	if (columns == 2)
-	{	depth = 0;
-		pstext(0, "0::never:");
+	{	extern char Buf[];
+		depth = 0;
+		sprintf(Buf, "%d:%s", 0, p->n->name);
+		pstext(0, Buf);
 		for (r = run; r; r = r->nxt)
-		{	if (!strcmp(r->n->name, ":never:"))
-				continue;
-			sprintf(Buf, "%d:%s",
-				r->pid+1, r->n->name);
-			pstext(r->pid+1, Buf);
-	}	}
+		{	if (r->b != N_CLAIM)
+			{	sprintf(Buf, "%d:%s", r->pid+1, r->n->name);
+				pstext(r->pid+1, Buf);
+	}	}	}
 
 	if (run->pid == 0) return; /* it is the first process started */
 
@@ -288,7 +311,7 @@
 		nproc - Have_claim + Skip_claim,
 		(xspin || nproc!=1)?"es":"");
 short_cut:
-	if (xspin) alldone(0);	/* avoid an abort from xspin */
+	if (s_trail || xspin) alldone(0);	/* avoid an abort from xspin */
 	if (fini)  alldone(1);
 }
 
@@ -332,6 +355,24 @@
 	return e;
 }
 
+static int
+x_can_run(void)	/* the currently selected process in X can run */
+{
+	if (X->prov && !eval(X->prov))
+	{
+if (0) printf("pid %d cannot run: not provided\n", X->pid);
+		return 0;
+	}
+	if (has_priority && !old_priority_rules)
+	{	Lextok *n = nn(ZN, CONST, ZN, ZN);
+		n->val = X->pid;
+if (0) printf("pid %d %s run (priority)\n", X->pid, pc_highest(n)?"can":"cannot");
+		return pc_highest(n);
+	}
+if (0) printf("pid %d can run\n", X->pid);
+	return 1;
+}
+
 static RunList *
 pickproc(RunList *Y)
 {	SeqList *z; Element *has_else;
@@ -343,7 +384,25 @@
 		return NULL;
 	}
 	if (!interactive || depth < jumpsteps)
-	{	/* was: j = (int) Rand()%(nproc-nstop); */
+	{	if (has_priority && !old_priority_rules)	/* new 6.3.2 */
+		{	j = Rand()%(nproc-nstop);
+			for (X = run; X; X = X->nxt)
+			{	if (j-- <= 0)
+					break;
+			}
+			if (X == NULL)
+			{	fatal("unexpected, pickproc", (char *)0);
+			}
+			j = nproc - nstop;
+			while (j-- > 0)
+			{	if (x_can_run())
+				{	Y = X;
+					break;
+				}
+				X = (X->nxt)?X->nxt:run;
+			}
+			return Y;
+		}
 		if (Priority_Sum < nproc-nstop)
 			fatal("cannot happen - weights", (char *)0);
 		j = (int) Rand()%Priority_Sum;
@@ -354,6 +413,7 @@
 			X = X->nxt;
 			if (!X) { Y = NULL; X = run; }
 		}
+
 	} else
 	{	int only_choice = -1;
 		int no_choice = 0, proc_no_ch, proc_k;
@@ -365,8 +425,7 @@
 
 			Choices[X->pid] = (short) k;
 
-			if (!X->pc
-			||  (X->prov && !eval(X->prov)))
+			if (!X->pc || !x_can_run())
 			{	if (X == run)
 					Choices[X->pid] = 0;
 				continue;
@@ -457,9 +516,12 @@
 		} else
 		{	char buf[256];
 			fflush(stdout);
-			scanf("%s", buf);
+			if (scanf("%64s", buf) == 0)
+			{	printf("\tno input\n");
+				goto try_again;
+			}
 			j = -1;
-			if (isdigit(buf[0]))
+			if (isdigit((int) buf[0]))
 				j = atoi(buf);
 			else
 			{	if (buf[0] == 'q')
@@ -484,6 +546,26 @@
 }
 
 void
+multi_claims(void)
+{	ProcList *p, *q = NULL;
+
+	if (nclaims > 1)
+	{	printf("  the model contains %d never claims:", nclaims);
+		for (p = rdy; p; p = p->nxt)
+		{	if (p->b == N_CLAIM)
+			{	printf("%s%s", q?", ":" ", p->n->name);
+				q = p;
+		}	}
+		printf("\n");
+		printf("  only one claim is used in a verification run\n");
+		printf("  choose which one with ./pan -a -N name (defaults to -N %s)\n",
+			q?q->n->name:"--");
+		printf("  or use e.g.: spin -search -ltl %s %s\n",
+			q?q->n->name:"--", Fname?Fname->name:"filename");
+	}
+}
+
+void
 sched(void)
 {	Element *e;
 	RunList *Y = NULL;	/* previous process in run queue */
@@ -498,6 +580,10 @@
 		dumplabels();
 		return;
 	}
+	if (has_code && !analyze)
+	{	printf("spin: warning: c_code fragments remain uninterpreted\n");
+		printf("      in random simulations with spin; use ./pan -r instead\n");
+	}
 
 	if (has_enabled && u_sync > 0)
 	{	printf("spin: error, cannot use 'enabled()' in ");
@@ -504,13 +590,23 @@
 		printf("models with synchronous channels.\n");
 		nr_errs++;
 	}
-	if (analyze)
+	if (product)
+	{	sync_product();
+		alldone(0);
+	}
+	if (analyze && (!replay || has_code))
 	{	gensrc();
+		multi_claims();
 		return;
-	} else if (s_trail)
+	}
+	if (replay && !has_code)
+	{	return;
+	}
+	if (s_trail)
 	{	match_trail();
 		return;
 	}
+
 	if (claimproc)
 	printf("warning: never claim not used in random simulation\n");
 	if (eventmap)
@@ -543,9 +639,9 @@
 		depth++; LastStep = ZE;
 		oX = X;	/* a rendezvous could change it */
 		go = 1;
-		if (X && X->prov && X->pc
+		if (X->pc
 		&& !(X->pc->status & D_ATOM)
-		&& !eval(X->prov))
+		&& !x_can_run())
 		{	if (!xspin && ((verbose&32) || (verbose&4)))
 			{	p_talk(X->pc, 1);
 				printf("\t<<Not Enabled>>\n");
@@ -557,9 +653,10 @@
 			&& ((verbose&32) || (verbose&4)))
 			{	if (X == oX)
 				if (!(e->status & D_ATOM) || (verbose&32)) /* no talking in d_steps */
-				{	p_talk(X->pc, 1);
+				{	if (!LastStep) LastStep = X->pc;
+					/* A. Tanaka, changed order */
+					p_talk(LastStep, 1);
 					printf("	[");
-					if (!LastStep) LastStep = X->pc;
 					comment(stdout, LastStep->n, 0);
 					printf("]\n");
 				}
@@ -570,7 +667,8 @@
 				if (xspin)
 					printf("\n");
 			}
-			if (oX != X)
+			if (oX != X
+			||  (X->pc->status & (ATOM|D_ATOM)))		/* new 5.0 */
 			{	e = silent_moves(e);
 				notbeyond = 0;
 			}
@@ -587,10 +685,12 @@
 			}
 		} else
 		{	depth--;
-			if (oX->pc->status & D_ATOM)
-			 non_fatal("stmnt in d_step blocks", (char *)0);
-
-			if (X->pc->n->ntyp == '@'
+			if (oX->pc && (oX->pc->status & D_ATOM))
+			{	non_fatal("stmnt in d_step blocks", (char *)0);
+			}
+			if (X->pc
+			&&  X->pc->n
+			&&  X->pc->n->ntyp == '@'
 			&&  X->pid == (nproc-nstop-1))
 			{	if (X != run && Y != NULL)
 					Y->nxt = X->nxt;
@@ -610,14 +710,19 @@
 				X = (X->nxt) ? X->nxt : run;
 			} else
 			{	if (p_blocked(X->pid))
-				{	if (Tval) break;
-					Tval = 1;
-					if (depth >= jumpsteps)
+				{	if (Tval && !has_stdin)
+					{	break;
+					}
+					if (!Tval && depth >= jumpsteps)
 					{	oX = X;
 						X = (RunList *) 0; /* to suppress indent */
 						dotag(stdout, "timeout\n");
 						X = oX;
+						Tval = 1;
 		}	}	}	}
+
+		if (!run || !X) break;	/* new 5.0 */
+
 		Y = pickproc(X);
 		notbeyond = 0;
 	}
@@ -662,7 +767,7 @@
 				printf("	[");
 				comment(stdout, s_was->n, 0);
 				printf("]\n");
-				tmp = orun; orun = X; X = tmp;
+				tmp = orun; /* orun = X; */ X = tmp;
 				if (!LastStep) LastStep = X->pc;
 				p_talk(LastStep, 1);
 				printf("	[");
@@ -692,7 +797,9 @@
 	int i;
 
 	for (t = r->symtab; t; t = t->next)
-		if (strcmp(t->name, s->name) == 0)
+		if (strcmp(t->name, s->name) == 0
+		&& (old_scope_rules
+		 || strcmp((const char *)t->bscp, (const char *)s->bscp) == 0))
 			return;		/* it's already there */
 
 	t = (Symbol *) emalloc(sizeof(Symbol));
@@ -699,11 +806,16 @@
 	t->name = s->name;
 	t->type = s->type;
 	t->hidden = s->hidden;
+	t->isarray = s->isarray;
 	t->nbits  = s->nbits;
 	t->nel  = s->nel;
 	t->ini  = s->ini;
 	t->setat = depth;
 	t->context = r->n;
+
+	t->bscp  = (unsigned char *) emalloc(strlen((const char *)s->bscp)+1);
+	strcpy((char *)t->bscp, (const char *)s->bscp);
+
 	if (s->type != STRUCT)
 	{	if (s->val)	/* if already initialized, copy info */
 		{	t->val = (int *) emalloc(s->nel*sizeof(int));
@@ -710,7 +822,8 @@
 			for (i = 0; i < s->nel; i++)
 				t->val[i] = s->val[i];
 		} else
-			(void) checkvar(t, 0);	/* initialize it */
+		{	(void) checkvar(t, 0);	/* initialize it */
+		}
 	} else
 	{	if (s->Sval)
 			fatal("saw preinitialized struct %s", s->name);
@@ -759,7 +872,7 @@
 
 	if (!a)
 		fatal("missing actual parameters: '%s'", p->n->name);
-	if (t->sym->nel != 1)
+	if (t->sym->nel > 1 || t->sym->isarray)
 		fatal("array in parameter list, %s", t->sym->name);
 	k = eval(a->lft);
 
@@ -768,7 +881,7 @@
 	ft = Sym_typ(t);
 
 	if (at != ft && (at == CHAN || ft == CHAN))
-	{	char buf[128], tag1[64], tag2[64];
+	{	char buf[256], tag1[64], tag2[64];
 		(void) sputtype(tag1, ft);
 		(void) sputtype(tag2, at);
 		sprintf(buf, "type-clash in params of %s(..), (%s<-> %s)",
@@ -809,8 +922,11 @@
 		return ZS;
 	}
 	for (r = X->symtab; r; r = r->next)
-		if (strcmp(r->name, s->name) == 0)
-			break;
+	{	if (strcmp(r->name, s->name) == 0
+		&& (old_scope_rules
+		 || strcmp((const char *)r->bscp, (const char *)s->bscp) == 0))
+		{	break;
+	}	}
 	if (!r)
 	{	addsymbol(X, s);
 		r = X->symtab;
@@ -878,7 +994,11 @@
 		printf(" -");
 	else
 		printf("%2d", X->pid - Have_claim);
-	printf(" (%s) ", X->n->name);
+	if (old_priority_rules)
+	{	printf(" (%s) ", X->n->name);
+	} else
+	{	printf(" (%s:%d) ", X->n->name, X->priority);
+	}
 }
 
 static void
@@ -895,6 +1015,7 @@
 void
 p_talk(Element *e, int lnr)
 {	static int lastnever = -1;
+	static char nbuf[128];
 	int newnever = -1;
 
 	if (e && e->n)
@@ -918,9 +1039,22 @@
 
 	whoruns(lnr);
 	if (e)
-	{	printf("line %3d %s (state %d)",
+	{	if (e->n)
+		{	char *ptr = e->n->fn->name;
+			char *qtr = nbuf;
+			while (*ptr != '\0')
+			{	if (*ptr != '"')
+				{	*qtr++ = *ptr;
+				}
+				ptr++;
+			}
+			*qtr = '\0';
+		} else
+		{	strcpy(nbuf, "-");
+		}
+		printf("%s:%d (state %d)",
+			nbuf,
 			e->n?e->n->ln:-1,
-			e->n?e->n->fn->name:"-",
 			e->seqno);
 		if (!xspin
 		&&  ((e->status&ENDSTATE) || has_lab(e, 2)))	/* 2=end */
@@ -943,8 +1077,9 @@
 	{	fatal("remote ref to label '%s' inside d_step",
 			n->sym->name);
 	}
-	if ((i = find_lab(n->sym, n->lft->sym, 1)) == 0)
-		fatal("unknown labelname: %s", n->sym->name);
+	if ((i = find_lab(n->sym, n->lft->sym, 1)) == 0)	/* remotelab */
+	{	fatal("unknown labelname: %s", n->sym->name);
+	}
 	return i;
 }
 
@@ -970,7 +1105,8 @@
 	}	}
 
 	if (prno < 0)
-		return 0;	/* non-existing process */
+	{	return 0;	/* non-existing process */
+	}
 #if 0
 	i = nproc - nstop;
 	for (Y = run; Y; Y = Y->nxt)
@@ -978,7 +1114,7 @@
 		printf("	%s: i=%d, prno=%d, ->pid=%d\n", Y->n->name, i, prno, Y->pid);
 	}
 #endif
-	i = nproc - nstop;
+	i = nproc - nstop + Skip_claim;	/* 6.0: added Skip_claim */
 	for (Y = run; Y; Y = Y->nxt)
 	if (--i == prno)
 	{	if (strcmp(Y->n->name, n->lft->sym->name) != 0)
@@ -988,12 +1124,13 @@
 		}
 		if (strcmp(n->sym->name, "_p") == 0)
 		{	if (Y->pc)
-				return Y->pc->seqno;
+			{	return Y->pc->seqno;
+			}
 			/* harmless, can only happen with -t */
 			return 0;
 		}
-#if 1
-		/* new 4.0 allow remote variables */
+
+		/* check remote variables */
 		oX = X;
 		X = Y;
 
@@ -1001,8 +1138,14 @@
 		n->lft = n->rgt;
 
 		os = n->sym;
-		n->sym = findloc(n->sym);
-
+		if (!n->sym->context)
+		{	n->sym->context = Y->n;
+		}
+		{ int rs = old_scope_rules;
+		  old_scope_rules = 1; /* 6.4.0 */
+		  n->sym = findloc(n->sym);
+		  old_scope_rules = rs;
+		}
 		i = getval(n);
 
 		n->sym = os;
@@ -1009,9 +1152,6 @@
 		n->lft = onl;
 		X = oX;
 		return i;
-#else
-		break;
-#endif
 	}
 	printf("remote ref: %s[%d] ", n->lft->sym->name, prno-added);
 	non_fatal("%s not found", n->sym->name);
--- a/sys/src/cmd/spin/spin.h
+++ b/sys/src/cmd/spin/spin.h
@@ -1,13 +1,10 @@
 /***** spin: spin.h *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #ifndef SEEN_SPIN_H
 #define SEEN_SPIN_H
@@ -15,7 +12,16 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#if !defined(WIN32) && !defined(WIN64)
+ #include <unistd.h>
+#endif
+#if !defined(PC) && !defined(_PLAN9)
+ #include <memory.h>
+#endif
 
+enum	    { INIV, PUTV, LOGV }; /* used in pangen1.c */
+enum btypes { NONE, N_CLAIM, I_PROC, A_PROC, P_PROC, E_TRACE, N_TRACE };
+
 typedef struct Lextok {
 	unsigned short	ntyp;	/* node type */
 	short	ismtyp;		/* CONST derived from MTYP */
@@ -22,6 +28,7 @@
 	int	val;		/* value attribute */
 	int	ln;		/* line number */
 	int	indstep;	/* part of d_step sequence */
+	int	uiid;		/* inline id, if non-zero */
 	struct Symbol	*fn;	/* file name */
 	struct Symbol	*sym;	/* symbol reference */
         struct Sequence *sq;	/* sequence */
@@ -54,6 +61,9 @@
 				  64=treat as if local; 128=read at least once
 				 */
 	unsigned char	colnr;	/* for use with xspin during simulation */
+	unsigned char	isarray; /* set if decl specifies array bound */
+	unsigned char	*bscp;	/* block scope */
+	int	sc;		/* scope seq no -- set only for proctypes */
 	int	nbits;		/* optional width specifier */
 	int	nel;		/* 1 if scalar, >1 if array   */
 	int	setat;		/* last depth value changed   */
@@ -124,7 +134,7 @@
 	int	merge_single;
 	short	merge_in;	/* nr of incoming edges */
 	short	merge_mark;	/* state was generated in merge sequence */
-	unsigned char	status;	/* used by analyzer generator  */
+	unsigned int	status;	/* used by analyzer generator  */
 	struct FSM_use	*dead;	/* optional dead variable list */
 	struct SeqList	*sub;	/* subsequences, for compounds */
 	struct SeqList	*esc;	/* zero or more escape sequences */
@@ -136,6 +146,7 @@
 	Element	*frst;
 	Element	*last;		/* links onto continuations */
 	Element *extent;	/* last element in original */
+	int	minel;		/* minimum Seqno, set and used only in guided.c */
 	int	maxel;		/* 1+largest id in sequence */
 } Sequence;
 
@@ -148,6 +159,7 @@
 	Symbol	*s;
 	Symbol	*c;
 	Element	*e;
+	int	uiid;		/* non-zero if label appears in an inline */
 	int	visible;	/* label referenced in claim (slice relevant) */
 	struct Label	*nxt;
 } Label;
@@ -157,11 +169,17 @@
 	struct Lbreak	*nxt;
 } Lbreak;
 
+typedef struct L_List {
+	Lextok *n;
+	struct L_List	*nxt;
+} L_List;
+
 typedef struct RunList {
 	Symbol	*n;		/* name            */
 	int	tn;		/* ordinal of type */
 	int	pid;		/* process id      */
 	int	priority;	/* for simulations only */
+	enum btypes b;		/* the type of process */
 	Element	*pc;		/* current stmnt   */
 	Sequence *ps;		/* used by analyzer generator */
 	Lextok	*prov;		/* provided clause */
@@ -174,11 +192,19 @@
 	Lextok	*p;		/* parameters */
 	Sequence *s;		/* body       */
 	Lextok	*prov;		/* provided clause */
+	enum btypes b;		/* e.g., claim, trace, proc */
 	short	tn;		/* ordinal number */
-	short	det;		/* deterministic */
+	unsigned char	det;	/* deterministic */
+	unsigned char   unsafe;	/* contains global var inits */
+	unsigned char	priority; /* process priority, if any */
 	struct ProcList	*nxt;	/* linked list */
 } ProcList;
 
+typedef struct QH {
+	int	n;
+	struct	QH *nxt;
+} QH;
+
 typedef	Lextok *Lexptr;
 
 #define YYSTYPE	Lexptr
@@ -194,7 +220,8 @@
 #define DONE2	 16		/* used in putcode and main*/
 #define D_ATOM	 32		/* deterministic atomic    */
 #define ENDSTATE 64		/* normal endstate         */
-#define CHECK2	128
+#define CHECK2	128		/* status bits for remote ref check */
+#define CHECK3	256		/* status bits for atomic jump check */
 
 #define Nhash	255    		/* slots in symbol hash-table */
 
@@ -216,18 +243,24 @@
 
 #define SOMETHINGBIG	65536
 #define RATHERSMALL	512
+#define MAXSCOPESZ	1024
 
 #ifndef max
-#define max(a,b) (((a)<(b)) ? (b) : (a))
+ #define max(a,b) (((a)<(b)) ? (b) : (a))
 #endif
 
-enum	{ INIV, PUTV, LOGV };	/* for pangen[14].c */
+#ifdef PC
+ #define MFLAGS	"wb"
+#else
+ #define MFLAGS	"w"
+#endif
 
 /***** prototype definitions *****/
 Element	*eval_sub(Element *);
 Element	*get_lab(Lextok *, int);
-Element	*huntele(Element *, int, int);
+Element	*huntele(Element *, unsigned int, int);
 Element	*huntstart(Element *);
+Element *mk_skip(void);
 Element	*target(Element *);
 
 Lextok	*do_unless(Lextok *, Lextok *);
@@ -238,8 +271,9 @@
 Lextok	*rem_lab(Symbol *, Lextok *, Symbol *);
 Lextok	*rem_var(Symbol *, Lextok *, Symbol *, Lextok *);
 Lextok	*tail_add(Lextok *, Lextok *);
+Lextok	*return_statement(Lextok *);
 
-ProcList *ready(Symbol *, Lextok *, Sequence *, int, Lextok *);
+ProcList *ready(Symbol *, Lextok *, Sequence *, int, Lextok *, enum btypes);
 
 SeqList	*seqlist(Sequence *, SeqList *);
 Sequence *close_seq(int);
@@ -250,7 +284,8 @@
 Symbol	*lookup(char *);
 Symbol	*prep_inline(Symbol *, Lextok *);
 
-char	*emalloc(int);
+char	*put_inline(FILE *, char *);
+char	*emalloc(size_t);
 long	Rand(void);
 
 int	any_oper(Lextok *, int);
@@ -258,6 +293,7 @@
 int	c_add_sv(FILE *);
 int	cast_val(int, int, int);
 int	checkvar(Symbol *, int);
+int	check_track(Lextok *);
 int	Cnt_flds(Lextok *);
 int	cnt_mpars(Lextok *);
 int	complete_rendez(void);
@@ -274,6 +310,7 @@
 int	in_bound(Symbol *, int);
 int	interprint(FILE *, Lextok *);
 int	printm(FILE *, Lextok *);
+int	is_inline(void);
 int	ismtype(char *);
 int	isproctype(char *);
 int	isutype(char *);
@@ -280,6 +317,7 @@
 int	Lval_struct(Lextok *, Symbol *, int, int);
 int	main(int, char **);
 int	pc_value(Lextok *);
+int	pid_is_claim(int);
 int	proper_enabler(Lextok *);
 int	putcode(FILE *, Sequence *, Element *, int, int, int);
 int	q_is_sync(Lextok *);
@@ -298,7 +336,6 @@
 int	tl_main(int, char *[]);
 int	Width_set(int *, int, Lextok *);
 int	yyparse(void);
-int	yywrap(void);
 int	yylex(void);
 
 void	AST_track(Lextok *, int);
@@ -309,7 +346,6 @@
 void	c_add_def(FILE *);
 void	c_add_loc(FILE *, char *);
 void	c_add_locinit(FILE *, int, char *);
-void	c_add_use(FILE *);
 void	c_chandump(FILE *);
 void	c_preview(void);
 void	c_struct(FILE *, char *, Symbol *);
@@ -321,6 +357,7 @@
 void	checkrun(Symbol *, int);
 void	comment(FILE *, Lextok *, int);
 void	cross_dsteps(Lextok *, Lextok *);
+void	disambiguate(void);
 void	doq(Symbol *, int, RunList *);
 void	dotag(FILE *, char *);
 void	do_locinits(FILE *);
@@ -344,20 +381,22 @@
 void	ini_struct(Symbol *);
 void	loose_ends(void);
 void	make_atomic(Sequence *, int);
+void	mark_last(void);
 void	match_trail(void);
 void	no_side_effects(char *);
 void	nochan_manip(Lextok *, Lextok *, int);
 void	non_fatal(char *, char *);
-void	ntimes(FILE *, int, int, char *c[]);
+void	ntimes(FILE *, int, int, const char *c[]);
 void	open_seq(int);
 void	p_talk(Element *, int);
-void	pickup_inline(Symbol *, Lextok *);
+void	pickup_inline(Symbol *, Lextok *, Lextok *);
 void	plunk_c_decls(FILE *);
 void	plunk_c_fcts(FILE *);
 void	plunk_expr(FILE *, char *);
-void	plunk_inline(FILE *, char *, int);
+void	plunk_inline(FILE *, char *, int, int);
 void	prehint(Symbol *);
 void	preruse(FILE *, Lextok *);
+void	pretty_print(void);
 void	prune_opts(Lextok *);
 void	pstext(int, char *);
 void	pushbreak(void);
@@ -383,17 +422,23 @@
 void	struct_name(Lextok *, Symbol *, int, char *);
 void	symdump(void);
 void	symvar(Symbol *);
+void	sync_product(void);
 void	trackchanuse(Lextok *, Lextok *, int);
 void	trackvar(Lextok *, Lextok *);
 void	trackrun(Lextok *);
-void	trapwonly(Lextok *, char *);	/* spin.y and main.c */
+void	trapwonly(Lextok * /* , char * */);	/* spin.y and main.c */
 void	typ2c(Symbol *);
 void	typ_ck(int, int, char *);
 void	undostmnt(Lextok *, int);
 void	unrem_Seq(void);
 void	unskip(int);
-void	varcheck(Element *, Element *);
 void	whoruns(int);
 void	wrapup(int);
 void	yyerror(char *, ...);
+
+extern	int unlink(const char *);
+
+#define TMP_FILE1 "._s_p_i_n_"
+#define TMP_FILE2 "._n_i_p_s_"
+
 #endif
--- a/sys/src/cmd/spin/spin.y
+++ b/sys/src/cmd/spin/spin.y
@@ -1,47 +1,69 @@
 /***** spin: spin.y *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 %{
 #include "spin.h"
+#include <sys/types.h>
+#ifndef PC
+#include <unistd.h>
+#endif
 #include <stdarg.h>
 
-#define YYDEBUG	0
+#define YYMAXDEPTH	20000	/* default is 10000 */
+#define YYDEBUG		0
 #define Stop	nn(ZN,'@',ZN,ZN)
+#define PART0	"place initialized declaration of "
+#define PART1	"place initialized chan decl of "
+#define PART2	" at start of proctype "
 
+static	Lextok *ltl_to_string(Lextok *);
+
 extern  Symbol	*context, *owner;
-extern  int	u_sync, u_async, dumptab;
-extern	short	has_sorted, has_random, has_enabled, has_pcvalue, has_np;
-extern	short	has_code, has_state, has_io;
+extern	Lextok *for_body(Lextok *, int);
+extern	void for_setup(Lextok *, Lextok *, Lextok *);
+extern	Lextok *for_index(Lextok *, Lextok *);
+extern	Lextok *sel_index(Lextok *, Lextok *, Lextok *);
+extern  void    keep_track_off(Lextok *);
+extern	void	safe_break(void);
+extern	void	restore_break(void);
+extern  int	u_sync, u_async, dumptab, scope_level;
+extern	int	initialization_ok;
+extern	short	has_sorted, has_random, has_enabled, has_pcvalue, has_np, has_priority;
+extern	short	has_code, has_state, has_ltl, has_io;
 extern	void	count_runs(Lextok *);
 extern	void	no_internals(Lextok *);
 extern	void	any_runs(Lextok *);
+extern	void	explain(int);
+extern	void	ltl_list(char *, char *);
 extern	void	validref(Lextok *, Lextok *);
+extern  void	sanity_check(Lextok *);
 extern	char	yytext[];
 
 int	Mpars = 0;	/* max nr of message parameters  */
-int	runsafe = 1;	/* 1 if all run stmnts are in init */
+int	nclaims = 0;	/* nr of never claims */
+int	ltl_mode = 0;	/* set when parsing an ltl formula */
 int	Expand_Ok = 0, realread = 1, IArgs = 0, NamesNotAdded = 0;
+int	in_for = 0, in_seq = 0, par_cnt = 0;
+int	dont_simplify = 0;
 char	*claimproc = (char *) 0;
 char	*eventmap = (char *) 0;
 
-static	int	Embedded = 0, inEventMap = 0, has_ini = 0;
+static	char *ltl_name;
+static	int  Embedded = 0, inEventMap = 0, has_ini = 0;
 
 %}
 
-%token	ASSERT PRINT PRINTM
+%token	ASSERT PRINT PRINTM PREPROC
 %token	C_CODE C_DECL C_EXPR C_STATE C_TRACK
-%token	RUN LEN ENABLED EVAL PC_VAL
-%token	TYPEDEF MTYPE INLINE LABEL OF
-%token	GOTO BREAK ELSE SEMI
-%token	IF FI DO OD SEP
+%token	RUN LEN ENABLED SET_P GET_P EVAL PC_VAL
+%token	TYPEDEF MTYPE INLINE RETURN LABEL OF
+%token	GOTO BREAK ELSE SEMI ARROW
+%token	IF FI DO OD FOR SELECT IN SEP DOTDOT
 %token	ATOMIC NON_ATOMIC D_STEP UNLESS
 %token  TIMEOUT NONPROGRESS
 %token	ACTIVE PROCTYPE D_PROCTYPE
@@ -50,12 +72,16 @@
 %token	FULL EMPTY NFULL NEMPTY
 %token	CONST TYPE XU			/* val */
 %token	NAME UNAME PNAME INAME		/* sym */
-%token	STRING CLAIM TRACE INIT		/* sym */
+%token	STRING CLAIM TRACE INIT	LTL	/* sym */
 
 %right	ASGN
 %left	SND O_SND RCV R_RCV /* SND doubles as boolean negation */
+%left	IMPLIES EQUIV			/* ltl */
 %left	OR
 %left	AND
+%left	ALWAYS EVENTUALLY		/* ltl */
+%left	UNTIL WEAK_UNTIL RELEASE	/* ltl */
+%right	NEXT				/* ltl */
 %left	'|'
 %left	'^'
 %left	'&'
@@ -81,17 +107,25 @@
 unit	: proc		/* proctype { }       */
 	| init		/* init { }           */
 	| claim		/* never claim        */
+	| ltl		/* ltl formula        */
 	| events	/* event assertions   */
 	| one_decl	/* variables, chans   */
 	| utype		/* user defined types */
 	| c_fcts	/* c functions etc.   */
 	| ns		/* named sequence     */
-	| SEMI		/* optional separator */
+	| semi		/* optional separator */
 	| error
 	;
 
+l_par	: '('		{ par_cnt++; }
+	;
+
+r_par	: ')'		{ par_cnt--; }
+	;
+
+
 proc	: inst		/* optional instantiator */
-	  proctype NAME	{
+	  proctype NAME	{ 
 			  setptype($3, PROCTYPE, ZN);
 			  setpname($3);
 			  context = $3->sym;
@@ -99,7 +133,7 @@
 			  Expand_Ok++; /* expand struct names in decl */
 			  has_ini = 0;
 			}
-	  '(' decl ')'	{ Expand_Ok--;
+	  l_par decl r_par	{ Expand_Ok--;
 			  if (has_ini)
 			  fatal("initializer in parameter list", (char *) 0);
 			}
@@ -106,14 +140,23 @@
 	  Opt_priority
 	  Opt_enabler
 	  body		{ ProcList *rl;
-			  rl = ready($3->sym, $6, $11->sq, $2->val, $10);
 			  if ($1 != ZN && $1->val > 0)
 			  {	int j;
+				rl = ready($3->sym, $6, $11->sq, $2->val, $10, A_PROC);
 			  	for (j = 0; j < $1->val; j++)
-				runnable(rl, $9?$9->val:1, 1);
+				{	runnable(rl, $9?$9->val:1, 1);
 				announce(":root:");
+				}
 				if (dumptab) $3->sym->ini = $1;
+			  } else
+			  {	rl = ready($3->sym, $6, $11->sq, $2->val, $10, P_PROC);
 			  }
+			  if (rl && has_ini == 1)	/* global initializations, unsafe */
+			  {	/* printf("proctype %s has initialized data\n",
+					$3->sym->name);
+				 */
+				rl->unsafe = 1;
+			  }
 			  context = ZS;
 			}
 	;
@@ -124,7 +167,7 @@
 
 inst	: /* empty */	{ $$ = ZN; }
 	| ACTIVE	{ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
-	| ACTIVE '[' CONST ']' {
+	| ACTIVE '[' const_expr ']' {
 			  $$ = nn(ZN,CONST,ZN,ZN); $$->val = $3->val;
 			  if ($3->val > 255)
 				non_fatal("max nr of processes is 255\n", "");
@@ -133,10 +176,10 @@
 			  $$ = nn(ZN,CONST,ZN,ZN);
 			  $$->val = 0;
 			  if (!$3->sym->type)
-				non_fatal("undeclared variable %s",
+				fatal("undeclared variable %s",
 					$3->sym->name);
 			  else if ($3->sym->ini->ntyp != CONST)
-				non_fatal("need constant initializer for %s\n",
+				fatal("need constant initializer for %s\n",
 					$3->sym->name);
 			  else
 				$$->val = $3->sym->ini->val;
@@ -146,7 +189,7 @@
 init	: INIT		{ context = $1->sym; }
 	  Opt_priority
 	  body		{ ProcList *rl;
-			  rl = ready(context, ZN, $4->sq, 0, ZN);
+			  rl = ready(context, ZN, $4->sq, 0, ZN, I_PROC);
 			  runnable(rl, $3?$3->val:1, 1);
 			  announce(":root:");
 			  context = ZS;
@@ -153,16 +196,49 @@
         		}
 	;
 
-claim	: CLAIM		{ context = $1->sym;
-			  if (claimproc)
-				non_fatal("claim %s redefined", claimproc);
+ltl	: LTL optname2	{ ltl_mode = 1; ltl_name = $2->sym->name; }
+	  ltl_body	{ if ($4) ltl_list($2->sym->name, $4->sym->name);
+			  ltl_mode = 0; has_ltl = 1;
+			}
+	;
+
+ltl_body: '{' full_expr OS '}' { $$ = ltl_to_string($2); }
+	| error		{ $$ = NULL; }
+	;
+
+claim	: CLAIM	optname	{ if ($2 != ZN)
+			  {	$1->sym = $2->sym;	/* new 5.3.0 */
+			  }
+			  nclaims++;
+			  context = $1->sym;
+			  if (claimproc && !strcmp(claimproc, $1->sym->name))
+			  {	fatal("claim %s redefined", claimproc);
+			  }
 			  claimproc = $1->sym->name;
 			}
-	  body		{ (void) ready($1->sym, ZN, $3->sq, 0, ZN);
+	  body		{ (void) ready($1->sym, ZN, $4->sq, 0, ZN, N_CLAIM);
         		  context = ZS;
         		}
 	;
 
+optname : /* empty */	{ char tb[32];
+			  memset(tb, 0, 32);
+			  sprintf(tb, "never_%d", nclaims);
+			  $$ = nn(ZN, NAME, ZN, ZN);
+			  $$->sym = lookup(tb);
+			}
+	| NAME		{ $$ = $1; }
+	;
+
+optname2 : /* empty */ { char tb[32]; static int nltl = 0;
+			  memset(tb, 0, 32);
+			  sprintf(tb, "ltl_%d", nltl++);
+			  $$ = nn(ZN, NAME, ZN, ZN);
+			  $$->sym = lookup(tb);
+			}
+	| NAME		{ $$ = $1; }
+	;
+
 events : TRACE		{ context = $1->sym;
 			  if (eventmap)
 				non_fatal("trace %s redefined", eventmap);
@@ -169,18 +245,28 @@
 			  eventmap = $1->sym->name;
 			  inEventMap++;
 			}
-	  body		{ (void) ready($1->sym, ZN, $3->sq, 0, ZN);
+	  body		{
+			  if (strcmp($1->sym->name, ":trace:") == 0)
+			  {	(void) ready($1->sym, ZN, $3->sq, 0, ZN, E_TRACE);
+			  } else
+			  {	(void) ready($1->sym, ZN, $3->sq, 0, ZN, N_TRACE);
+			  }
         		  context = ZS;
 			  inEventMap--;
 			}
 	;
 
-utype	: TYPEDEF NAME		{ if (context)
-				   fatal("typedef %s must be global",
-						$2->sym->name);
+utype	: TYPEDEF NAME '{' 	{  if (context)
+				   { fatal("typedef %s must be global",
+					$2->sym->name);
+				   }
 				   owner = $2->sym;
+				   in_seq = $1->ln;
 				}
-	  '{' decl_lst '}'	{ setuname($5); owner = ZS; }
+	  decl_lst '}'		{ setuname($5);
+				  owner = ZS;
+				  in_seq = 0;
+				}
 	;
 
 nm	: NAME			{ $$ = $1; }
@@ -190,8 +276,8 @@
 				}
 	;
 
-ns	: INLINE nm '('		{ NamesNotAdded++; }
-	  args ')'		{ prep_inline($2->sym, $5);
+ns	: INLINE nm l_par		{ NamesNotAdded++; }
+	  args r_par		{ prep_inline($2->sym, $5);
 				  NamesNotAdded--;
 				}
 	;
@@ -227,6 +313,8 @@
 				  NamesNotAdded--;
 				  $$ = nn(ZN, C_CODE, ZN, ZN);
 				  $$->sym = s;
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
 				  has_code = 1;
 				}
 	| C_DECL		{ Symbol *s;
@@ -236,6 +324,8 @@
 				  s->type = CODE_DECL;
 				  $$ = nn(ZN, C_CODE, ZN, ZN);
 				  $$->sym = s;
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
 				  has_code = 1;
 				}
 	;
@@ -242,17 +332,29 @@
 cexpr	: C_EXPR		{ Symbol *s;
 				  NamesNotAdded++;
 				  s = prep_inline(ZS, ZN);
+/* if context is 0 this was inside an ltl formula
+   mark the last inline added to seqnames */
+				  if (!context)
+				  {	mark_last();
+				  }
 				  NamesNotAdded--;
 				  $$ = nn(ZN, C_EXPR, ZN, ZN);
 				  $$->sym = s;
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
 				  no_side_effects(s->name);
 				  has_code = 1;
 				}
 	;
 
-body	: '{'			{ open_seq(1); }
+body	: '{'			{ open_seq(1); in_seq = $1->ln; }
           sequence OS		{ add_seq(Stop); }
-          '}'			{ $$->sq = close_seq(0); }
+          '}'			{ $$->sq = close_seq(0); in_seq = 0;
+				  if (scope_level != 0)
+				  {	non_fatal("missing '}' ?", 0);
+					scope_level = 0;
+				  }
+				}
 	;
 
 sequence: step			{ if ($1) add_seq($1); }
@@ -264,7 +366,11 @@
 	| NAME ':' one_decl	{ fatal("label preceding declaration,", (char *)0); }
 	| NAME ':' XU		{ fatal("label predecing xr/xs claim,", 0); }
 	| stmnt			{ $$ = $1; }
-	| stmnt UNLESS stmnt	{ $$ = do_unless($1, $3); }
+	| stmnt UNLESS		{ if ($1->ntyp == DO) { safe_break(); } }
+	  stmnt			{ if ($1->ntyp == DO) { restore_break(); }
+				  $$ = do_unless($1, $4);
+				}
+	| error			{ printf("Not a Step\n"); }
 	;
 
 vis	: /* empty */		{ $$ = ZN; }
@@ -277,7 +383,9 @@
 	| ASGN
 	;
 
-one_decl: vis TYPE var_list	{ setptype($3, $2->val, $1); $$ = $3; }
+one_decl: vis TYPE var_list	{ setptype($3, $2->val, $1);
+				  $$ = $3;
+				}
 	| vis UNAME var_list	{ setutype($3, $2->sym, $1);
 				  $$ = expand($3, Expand_Ok);
 				}
@@ -310,26 +418,76 @@
 	| ivar ',' var_list	{ $$ = nn($1, TYPE, ZN, $3); }
 	;
 
+c_list	: CONST			{ $1->ntyp = CONST; $$ = $1; }
+	| CONST ',' c_list	{ $1->ntyp = CONST; $$ = nn($1, ',', $1, $3); }
+	;
+
 ivar    : vardcl           	{ $$ = $1;
 				  $1->sym->ini = nn(ZN,CONST,ZN,ZN);
 				  $1->sym->ini->val = 0;
+				  if (!initialization_ok)
+				  {	Lextok *zx, *xz;
+					zx = nn(ZN, NAME, ZN, ZN);
+					zx->sym = $1->sym;
+					xz = nn(zx, ASGN, zx, $1->sym->ini);
+					keep_track_off(xz);
+					/* make sure zx doesnt turn out to be a STRUCT later */
+					add_seq(xz);
+				  }
 				}
-	| vardcl ASGN expr   	{ $1->sym->ini = $3; $$ = $1;
-				  trackvar($1,$3); has_ini = 1;
+	| vardcl ASGN '{' c_list '}'	{
+				  if (!$1->sym->isarray)
+					fatal("%s must be an array", $1->sym->name);
+				  $$ = $1;
+				  $1->sym->ini = $4;
+				  has_ini = 1;
+				  $1->sym->hidden |= (4|8);	/* conservative */
+				  if (!initialization_ok)
+				  {	Lextok *zx = nn(ZN, NAME, ZN, ZN);
+					zx->sym = $1->sym;
+					add_seq(nn(zx, ASGN, zx, $4));
+				  }
 				}
+	| vardcl ASGN expr   	{ $$ = $1;
+				  $1->sym->ini = $3;
+				  if ($3->ntyp == CONST
+				  || ($3->ntyp == NAME && $3->sym->context))
+				  {	has_ini = 2; /* local init */
+				  } else
+				  {	has_ini = 1; /* possibly global */
+				  }
+				  trackvar($1, $3);
+				  if (any_oper($3, RUN))
+				  {	fatal("cannot use 'run' in var init, saw", (char *) 0);
+				  }
+				  nochan_manip($1, $3, 0);
+				  no_internals($1);
+				  if (!initialization_ok)
+				  {	Lextok *zx = nn(ZN, NAME, ZN, ZN);
+					zx->sym = $1->sym;
+					add_seq(nn(zx, ASGN, zx, $3));
+				  }
+				}
 	| vardcl ASGN ch_init	{ $1->sym->ini = $3;
 				  $$ = $1; has_ini = 1;
+				  if (!initialization_ok)
+				  {	non_fatal(PART1 "'%s'" PART2, $1->sym->name);
+				  }
 				}
 	;
 
-ch_init : '[' CONST ']' OF
-	  '{' typ_list '}'	{ if ($2->val) u_async++;
-				  else u_sync++;
+ch_init : '[' const_expr ']' OF
+	  '{' typ_list '}'	{ if ($2->val)
+					u_async++;
+				  else
+					u_sync++;
         			  {	int i = cnt_mpars($6);
 					Mpars = max(Mpars, i);
 				  }
         			  $$ = nn(ZN, CHAN, ZN, $6);
 				  $$->val = $2->val;
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
         			}
 	;
 
@@ -342,13 +500,33 @@
 				  }
 				  $1->sym->nel = 1; $$ = $1;
 				}
-	| NAME '[' CONST ']'	{ $1->sym->nel = $3->val; $$ = $1; }
+	| NAME '[' const_expr ']'	{ $1->sym->nel = $3->val; $1->sym->isarray = 1; $$ = $1; }
+	| NAME '[' NAME ']'	{	/* make an exception for an initialized scalars */
+					$$ = nn(ZN, CONST, ZN, ZN);
+					fprintf(stderr, "spin: %s:%d, warning: '%s' in array bound ",
+						$1->fn->name, $1->ln, $3->sym->name);
+					if ($3->sym->ini->val > 0)
+					{	fprintf(stderr, "evaluated as %d\n", $3->sym->ini->val);
+						$$->val = $3->sym->ini->val;
+					} else
+					{	fprintf(stderr, "evaluated as 8 by default (to avoid zero)\n");
+						$$->val = 8;
+					}
+					$1->sym->nel = $$->val;
+					$1->sym->isarray = 1;
+					$$ = $1;
+				}
 	;
 
 varref	: cmpnd			{ $$ = mk_explicit($1, Expand_Ok, NAME); }
 	;
 
-pfld	: NAME			{ $$ = nn($1, NAME, ZN, ZN); }
+pfld	: NAME			{ $$ = nn($1, NAME, ZN, ZN);
+				  if ($1->sym->isarray && !in_for)
+				  {	non_fatal("missing array index for '%s'",
+						$1->sym->name);
+				  }
+				}
 	| NAME			{ owner = ZS; }
 	  '[' expr ']'		{ $$ = nn($1, NAME, $4, ZN); }
 	;
@@ -363,7 +541,7 @@
 				  Embedded--;
 				  if (!Embedded && !NamesNotAdded
 				  &&  !$1->sym->type)
-				   non_fatal("undeclared variable: %s",
+				   fatal("undeclared variable: %s",
 						$1->sym->name);
 				  if ($3) validref($1, $3->lft);
 				  owner = ZS;
@@ -374,13 +552,21 @@
 	| '.' cmpnd %prec DOT	{ $$ = nn(ZN, '.', $2, ZN); }
 	;
 
-stmnt	: Special		{ $$ = $1; }
-	| Stmnt			{ $$ = $1;
-				  if (inEventMap)
-				   non_fatal("not an event", (char *)0);
+stmnt	: Special		{ $$ = $1; initialization_ok = 0; }
+	| Stmnt			{ $$ = $1; initialization_ok = 0;
+				  if (inEventMap) non_fatal("not an event", (char *)0);
 				}
 	;
 
+for_pre : FOR l_par		{ in_for = 1; }
+	  varref		{ trapwonly($4 /*, "for" */);
+				  pushbreak(); /* moved up */
+				  $$ = $4;
+				}
+	;
+
+for_post: '{' sequence OS '}' ;
+
 Special : varref RCV		{ Expand_Ok++; }
 	  rargs			{ Expand_Ok--; has_io++;
 				  $$ = nn($1,  'r', $1, $4);
@@ -392,13 +578,30 @@
 				  $$->val=0; trackchanuse($4, ZN, 'S');
 				  any_runs($4);
 				}
+	| for_pre ':' expr DOTDOT expr r_par	{
+				  for_setup($1, $3, $5); in_for = 0;
+				}
+	  for_post		{ $$ = for_body($1, 1);
+				}
+	| for_pre IN varref r_par	{ $$ = for_index($1, $3); in_for = 0;
+				}
+	  for_post		{ $$ = for_body($5, 1);
+				}
+	| SELECT l_par varref ':' expr DOTDOT expr r_par {
+				  trapwonly($3 /*, "select" */);
+				  $$ = sel_index($3, $5, $7);
+				}
 	| IF options FI 	{ $$ = nn($1, IF, ZN, ZN);
         			  $$->sl = $2->sl;
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
 				  prune_opts($$);
         			}
 	| DO    		{ pushbreak(); }
           options OD    	{ $$ = nn($1, DO, ZN, ZN);
         			  $$->sl = $3->sl;
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
 				  prune_opts($$);
         			}
 	| BREAK  		{ $$ = nn(ZN, GOTO, ZN, ZN);
@@ -420,9 +623,22 @@
 				  }
 				  $1->sym->type = LABEL;
 				}
+	| NAME ':'		{ $$ = nn($1, ':',ZN,ZN);
+				  if ($1->sym->type != 0
+				  &&  $1->sym->type != LABEL) {
+				  	non_fatal("bad label-name %s",
+					$1->sym->name);
+				  }
+				  $$->lft = nn(ZN, 'c', nn(ZN,CONST,ZN,ZN), ZN);
+				  $$->lft->lft->val = 1; /* skip */
+				  $1->sym->type = LABEL;
+				}
+	| error			{ $$ = nn(ZN, 'c', nn(ZN,CONST,ZN,ZN), ZN);
+				  $$->lft->val = 1; /* skip */
+				}
 	;
 
-Stmnt	: varref ASGN expr	{ $$ = nn($1, ASGN, $1, $3);
+Stmnt	: varref ASGN full_expr	{ $$ = nn($1, ASGN, $1, $3);
 				  trackvar($1, $3);
 				  nochan_manip($1, $3, 0);
 				  no_internals($1);
@@ -443,10 +659,11 @@
 				  if ($1->sym->type == CHAN)
 				   fatal("arithmetic on chan id's", (char *)0);
 				}
-	| PRINT	'(' STRING	{ realread = 0; }
-	  prargs ')'		{ $$ = nn($3, PRINT, $5, ZN); realread = 1; }
-	| PRINTM '(' varref ')'	{ $$ = nn(ZN, PRINTM, $3, ZN); }
-	| PRINTM '(' CONST ')'	{ $$ = nn(ZN, PRINTM, $3, ZN); }
+	| SET_P l_par two_args r_par	{ $$ = nn(ZN, SET_P, $3, ZN); has_priority++; }
+	| PRINT	l_par STRING	{ realread = 0; }
+	  prargs r_par		{ $$ = nn($3, PRINT, $5, ZN); realread = 1; }
+	| PRINTM l_par varref r_par	{ $$ = nn(ZN, PRINTM, $3, ZN); }
+	| PRINTM l_par CONST r_par	{ $$ = nn(ZN, PRINTM, $3, ZN); }
 	| ASSERT full_expr    	{ $$ = nn(ZN, ASSERT, $2, ZN); AST_track($2, 0); }
 	| ccode			{ $$ = $1; }
 	| varref R_RCV		{ Expand_Ok++; }
@@ -480,11 +697,17 @@
 	| ATOMIC   '{'   	{ open_seq(0); }
           sequence OS '}'   	{ $$ = nn($1, ATOMIC, ZN, ZN);
         			  $$->sl = seqlist(close_seq(3), 0);
-        			  make_atomic($$->sl->this, 0);
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
+				  make_atomic($$->sl->this, 0);
         			}
-	| D_STEP '{'		{ open_seq(0); rem_Seq(); }
+	| D_STEP '{'		{ open_seq(0);
+				  rem_Seq();
+				}
           sequence OS '}'   	{ $$ = nn($1, D_STEP, ZN, ZN);
         			  $$->sl = seqlist(close_seq(4), 0);
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
         			  make_atomic($$->sl->this, D_ATOM);
 				  unrem_Seq();
         			}
@@ -491,10 +714,23 @@
 	| '{'			{ open_seq(0); }
 	  sequence OS '}'	{ $$ = nn(ZN, NON_ATOMIC, ZN, ZN);
         			  $$->sl = seqlist(close_seq(5), 0);
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
         			}
 	| INAME			{ IArgs++; }
-	  '(' args ')'		{ pickup_inline($1->sym, $4); IArgs--; }
+	  l_par args r_par	{ initialization_ok = 0;
+				  pickup_inline($1->sym, $4, ZN);
+				  IArgs--;
+				}
 	  Stmnt			{ $$ = $7; }
+
+	| varref ASGN INAME	{ IArgs++; }
+	  l_par args r_par	{ initialization_ok = 0;
+				  pickup_inline($3->sym, $6, $1);
+				  IArgs--;
+				}
+	  Stmnt			{ $$ = $9; }
+	| RETURN full_expr	{ $$ = return_statement($2); }	
 	;
 
 options : option		{ $$->sl = seqlist($1->sq, 0); }
@@ -503,22 +739,39 @@
 
 option  : SEP   		{ open_seq(0); }
           sequence OS		{ $$ = nn(ZN,0,ZN,ZN);
-				  $$->sq = close_seq(6); }
+				  $$->sq = close_seq(6);
+				  $$->ln = $1->ln;
+				  $$->fn = $1->fn;
+				}
 	;
 
 OS	: /* empty */
-	| SEMI			{ /* redundant semi at end of sequence */ }
+	| semi			{ /* redundant semi at end of sequence */ }
 	;
 
-MS	: SEMI			{ /* at least one semi-colon */ }
-	| MS SEMI		{ /* but more are okay too   */ }
+semi	: SEMI
+	| ARROW
 	;
 
+MS	: semi			{ /* at least one semi-colon */ }
+	| MS semi		{ /* but more are okay too   */ }
+	;
+
 aname	: NAME			{ $$ = $1; }
 	| PNAME			{ $$ = $1; }
 	;
 
-expr    : '(' expr ')'		{ $$ = $2; }
+const_expr:	CONST			{ $$ = $1; }
+	| '-' const_expr %prec UMIN	{ $$ = $2; $$->val = -($2->val); }
+	| l_par const_expr r_par		{ $$ = $2; }
+	| const_expr '+' const_expr	{ $$ = $1; $$->val = $1->val + $3->val; }
+	| const_expr '-' const_expr	{ $$ = $1; $$->val = $1->val - $3->val; }
+	| const_expr '*' const_expr	{ $$ = $1; $$->val = $1->val * $3->val; }
+	| const_expr '/' const_expr	{ $$ = $1; $$->val = $1->val / $3->val; }
+	| const_expr '%' const_expr	{ $$ = $1; $$->val = $1->val % $3->val; }
+	;
+
+expr    : l_par expr r_par		{ $$ = $2; }
 	| expr '+' expr		{ $$ = nn(ZN, '+', $1, $3); }
 	| expr '-' expr		{ $$ = nn(ZN, '-', $1, $3); }
 	| expr '*' expr		{ $$ = nn(ZN, '*', $1, $3); }
@@ -541,7 +794,7 @@
 	| '-' expr %prec UMIN	{ $$ = nn(ZN, UMIN, $2, ZN); }
 	| SND expr %prec NEG	{ $$ = nn(ZN, '!', $2, ZN); }
 
-	| '(' expr SEMI expr ':' expr ')' {
+	| l_par expr ARROW expr ':' expr r_par {
 				  $$ = nn(ZN,  OR, $4, $6);
 				  $$ = nn(ZN, '?', $2, $$);
 				}
@@ -548,21 +801,18 @@
 
 	| RUN aname		{ Expand_Ok++;
 				  if (!context)
-				  fatal("used 'run' outside proctype",
+				   fatal("used 'run' outside proctype",
 					(char *) 0);
-				  if (strcmp(context->name, ":init:") != 0)
-					runsafe = 0;
 				}
-	  '(' args ')'
+	  l_par args r_par
 	  Opt_priority		{ Expand_Ok--;
 				  $$ = nn($2, RUN, $5, ZN);
-				  $$->val = ($7) ? $7->val : 1;
+				  $$->val = ($7) ? $7->val : 0;
 				  trackchanuse($5, $2, 'A'); trackrun($$);
 				}
-	| LEN '(' varref ')'	{ $$ = nn($3, LEN, $3, ZN); }
-	| ENABLED '(' expr ')'	{ $$ = nn(ZN, ENABLED, $3, ZN);
-				  has_enabled++;
-				}
+	| LEN l_par varref r_par	{ $$ = nn($3, LEN, $3, ZN); }
+	| ENABLED l_par expr r_par	{ $$ = nn(ZN, ENABLED, $3, ZN); has_enabled++; }
+	| GET_P l_par expr r_par	{ $$ = nn(ZN, GET_P, $3, ZN); has_priority++; }
 	| varref RCV		{ Expand_Ok++; }
 	  '[' rargs ']'		{ Expand_Ok--; has_io++;
 				  $$ = nn($1, 'R', $1, $5);
@@ -572,7 +822,7 @@
 				  $$ = nn($1, 'R', $1, $5);
 				  $$->val = has_random = 1;
 				}
-	| varref		{ $$ = $1; trapwonly($1, "varref"); }
+	| varref		{ $$ = $1; trapwonly($1 /*, "varref" */); }
 	| cexpr			{ $$ = $1; }
 	| CONST 		{ $$ = nn(ZN,CONST,ZN,ZN);
 				  $$->ismtyp = $1->ismtyp;
@@ -582,7 +832,7 @@
 	| NONPROGRESS		{ $$ = nn(ZN,NONPROGRESS, ZN, ZN);
 				  has_np++;
 				}
-	| PC_VAL '(' expr ')'	{ $$ = nn(ZN, PC_VAL, $3, ZN);
+	| PC_VAL l_par expr r_par	{ $$ = nn(ZN, PC_VAL, $3, ZN);
 				  has_pcvalue++;
 				}
 	| PNAME '[' expr ']' '@' NAME
@@ -591,47 +841,63 @@
 	  			{ $$ = rem_var($1->sym, $3, $6->sym, $6->lft); }
 	| PNAME '@' NAME	{ $$ = rem_lab($1->sym, ZN, $3->sym); }
 	| PNAME ':' pfld	{ $$ = rem_var($1->sym, ZN, $3->sym, $3->lft); }
+	| ltl_expr		{ $$ = $1; /* sanity_check($1); */ }
 	;
 
 Opt_priority:	/* none */	{ $$ = ZN; }
-	| PRIORITY CONST	{ $$ = $2; }
+	| PRIORITY CONST	{ $$ = $2; has_priority++; }
 	;
 
 full_expr:	expr		{ $$ = $1; }
-	|	Expr		{ $$ = $1; }
+	| Expr		{ $$ = $1; }
 	;
 
-Opt_enabler:	/* none */	{ $$ = ZN; }
-	| PROVIDED '(' full_expr ')'	{ if (!proper_enabler($3))
-				  {	non_fatal("invalid PROVIDED clause",
-						(char *)0);
-					$$ = ZN;
-				  } else
-					$$ = $3;
-				 }
-	| PROVIDED error	{ $$ = ZN;
-				  non_fatal("usage: provided ( ..expr.. )",
-					(char *)0);
+ltl_expr: expr UNTIL expr	{ $$ = nn(ZN, UNTIL,   $1, $3); }
+	| expr RELEASE expr	{ $$ = nn(ZN, RELEASE, $1, $3); }
+	| expr WEAK_UNTIL expr	{ $$ = nn(ZN, ALWAYS, $1, ZN);
+				  $$ = nn(ZN, OR, $$, nn(ZN, UNTIL, $1, $3));
 				}
+	| expr IMPLIES expr	{
+				$$ = nn(ZN, '!', $1, ZN);
+				$$ = nn(ZN, OR,  $$, $3);
+				}
+	| expr EQUIV expr	{ $$ = nn(ZN, EQUIV,   $1, $3); }
+	| NEXT expr       %prec NEG { $$ = nn(ZN, NEXT,  $2, ZN); }
+	| ALWAYS expr     %prec NEG { $$ = nn(ZN, ALWAYS,$2, ZN); }
+	| EVENTUALLY expr %prec NEG { $$ = nn(ZN, EVENTUALLY, $2, ZN); }
 	;
 
 	/* an Expr cannot be negated - to protect Probe expressions */
 Expr	: Probe			{ $$ = $1; }
-	| '(' Expr ')'		{ $$ = $2; }
+	| l_par Expr r_par		{ $$ = $2; }
 	| Expr AND Expr		{ $$ = nn(ZN, AND, $1, $3); }
 	| Expr AND expr		{ $$ = nn(ZN, AND, $1, $3); }
+	| expr AND Expr		{ $$ = nn(ZN, AND, $1, $3); }
 	| Expr OR  Expr		{ $$ = nn(ZN,  OR, $1, $3); }
 	| Expr OR  expr		{ $$ = nn(ZN,  OR, $1, $3); }
-	| expr AND Expr		{ $$ = nn(ZN, AND, $1, $3); }
 	| expr OR  Expr		{ $$ = nn(ZN,  OR, $1, $3); }
 	;
 
-Probe	: FULL '(' varref ')'	{ $$ = nn($3,  FULL, $3, ZN); }
-	| NFULL '(' varref ')'	{ $$ = nn($3, NFULL, $3, ZN); }
-	| EMPTY '(' varref ')'	{ $$ = nn($3, EMPTY, $3, ZN); }
-	| NEMPTY '(' varref ')'	{ $$ = nn($3,NEMPTY, $3, ZN); }
+Probe	: FULL l_par varref r_par	{ $$ = nn($3,  FULL, $3, ZN); }
+	| NFULL l_par varref r_par	{ $$ = nn($3, NFULL, $3, ZN); }
+	| EMPTY l_par varref r_par	{ $$ = nn($3, EMPTY, $3, ZN); }
+	| NEMPTY l_par varref r_par	{ $$ = nn($3,NEMPTY, $3, ZN); }
 	;
 
+Opt_enabler:	/* none */	{ $$ = ZN; }
+	| PROVIDED l_par full_expr r_par	{ if (!proper_enabler($3))
+				  {	non_fatal("invalid PROVIDED clause",
+						(char *)0);
+					$$ = ZN;
+				  } else
+					$$ = $3;
+				 }
+	| PROVIDED error	{ $$ = ZN;
+				  non_fatal("usage: provided ( ..expr.. )",
+					(char *)0);
+				}
+	;
+
 basetype: TYPE			{ $$->sym = ZS;
 				  $$->val = $1->val;
 				  if ($$->val == UNSIGNED)
@@ -647,6 +913,9 @@
 	| basetype ',' typ_list	{ $$ = nn($1, $1->val, ZN, $3); }
 	;
 
+two_args:	expr ',' expr	{ $$ = nn(ZN, ',', $1, $3); }
+	;
+
 args    : /* empty */		{ $$ = ZN; }
 	| arg			{ $$ = $1; }
 	;
@@ -656,7 +925,7 @@
 	;
 
 margs   : arg			{ $$ = $1; }
-	| expr '(' arg ')'	{ if ($1->ntyp == ',')
+	| expr l_par arg r_par	{ if ($1->ntyp == ',')
 					$$ = tail_add($1, $3);
 				  else
 				  	$$ = nn(ZN, ',', $1, $3);
@@ -676,9 +945,9 @@
 	;
 
 rarg	: varref		{ $$ = $1; trackvar($1, $1);
-				  trapwonly($1, "rarg"); }
-	| EVAL '(' expr ')'	{ $$ = nn(ZN,EVAL,$3,ZN);
-				  trapwonly($1, "eval rarg"); }
+				  trapwonly($1 /*, "rarg" */); }
+	| EVAL l_par expr r_par	{ $$ = nn(ZN,EVAL,$3,ZN);
+				  trapwonly($1 /*, "eval rarg" */); }
 	| CONST 		{ $$ = nn(ZN,CONST,ZN,ZN);
 				  $$->ismtyp = $1->ismtyp;
 				  $$->val = $1->val;
@@ -698,12 +967,12 @@
 				  else
 				  	$$ = nn(ZN, ',', $1, $3);
 				}
-	| rarg '(' rargs ')'	{ if ($1->ntyp == ',')
+	| rarg l_par rargs r_par	{ if ($1->ntyp == ',')
 					$$ = tail_add($1, $3);
 				  else
 				  	$$ = nn(ZN, ',', $1, $3);
 				}
-	| '(' rargs ')'		{ $$ = $2; }
+	| l_par rargs r_par		{ $$ = $2; }
 	;
 
 nlst	: NAME			{ $$ = nn($1, NAME, ZN, ZN);
@@ -714,6 +983,138 @@
 	| nlst ','		{ $$ = $1; /* commas optional */ }
 	;
 %%
+
+#define binop(n, sop)	fprintf(fd, "("); recursive(fd, n->lft); \
+			fprintf(fd, ") %s (", sop); recursive(fd, n->rgt); \
+			fprintf(fd, ")");
+#define unop(n, sop)	fprintf(fd, "%s (", sop); recursive(fd, n->lft); \
+			fprintf(fd, ")");
+
+static void
+recursive(FILE *fd, Lextok *n)
+{
+	if (n)
+	switch (n->ntyp) {
+	case NEXT:
+		unop(n, "X");
+		break;
+	case ALWAYS:
+		unop(n, "[]");
+		break;
+	case EVENTUALLY:
+		unop(n, "<>");
+		break;
+	case '!':
+		unop(n, "!");
+		break;
+	case UNTIL:
+		binop(n, "U");
+		break;
+	case WEAK_UNTIL:
+		binop(n, "W");
+		break;
+	case RELEASE: /* see http://en.wikipedia.org/wiki/Linear_temporal_logic */
+		binop(n, "V");
+		break;
+	case OR:
+		binop(n, "||");
+		break;
+	case AND:
+		binop(n, "&&");
+		break;
+	case IMPLIES:
+		binop(n, "->");
+		break;
+	case EQUIV:
+		binop(n, "<->");
+		break;
+	case C_EXPR:
+		fprintf(fd, "c_expr { %s }", put_inline(fd, n->sym->name));
+		break;
+	default:
+		comment(fd, n, 0);
+		break;
+	}
+}
+
+static Lextok *
+ltl_to_string(Lextok *n)
+{	Lextok *m = nn(ZN, 0, ZN, ZN);
+	char *retval;
+	char ltl_formula[2048];
+	FILE *tf = fopen(TMP_FILE1, "w+"); /* tmpfile() fails on Windows 7 */
+
+	/* convert the parsed ltl to a string
+	   by writing into a file, using existing functions,
+	   and then passing it to the existing interface for
+	   conversion into a never claim
+	  (this means parsing everything twice, which is
+	   a little redundant, but adds only miniscule overhead)
+	 */
+
+	if (!tf)
+	{	fatal("cannot create temporary file", (char *) 0);
+	}
+	dont_simplify = 1;
+	recursive(tf, n);
+	dont_simplify = 0;
+	(void) fseek(tf, 0L, SEEK_SET);
+
+	memset(ltl_formula, 0, sizeof(ltl_formula));
+	retval = fgets(ltl_formula, sizeof(ltl_formula), tf);
+	fclose(tf);
+
+	(void) unlink(TMP_FILE1);
+
+	if (!retval)
+	{	printf("%p\n", retval);
+		fatal("could not translate ltl ltl_formula", 0);
+	}
+
+	if (1) printf("ltl %s: %s\n", ltl_name, ltl_formula);
+
+	m->sym = lookup(ltl_formula);
+
+	return m;
+}
+
+int
+is_temporal(int t)
+{
+	return (t == EVENTUALLY || t == ALWAYS || t == UNTIL
+	     || t == WEAK_UNTIL || t == RELEASE);
+}
+
+int
+is_boolean(int t)
+{
+	return (t == AND || t == OR || t == IMPLIES || t == EQUIV);
+}
+
+#if 0
+/* flags correct formula like: ltl { true U (true U true) } */
+void
+sanity_check(Lextok *t)	/* check proper embedding of ltl_expr */
+{
+	if (!t) return;
+	sanity_check(t->lft);
+	sanity_check(t->rgt);
+
+	if (t->lft && t->rgt)
+	{	if (!is_boolean(t->ntyp)
+		&&  (is_temporal(t->lft->ntyp)
+		||   is_temporal(t->rgt->ntyp)))
+		{	printf("spin: attempt to apply '");
+			explain(t->ntyp);
+			printf("' to '");
+			explain(t->lft->ntyp);
+			printf("' and '");
+			explain(t->rgt->ntyp);
+			printf("'\n");
+	/*		non_fatal("missing parentheses?", (char *)0); */
+	}	}
+}
+#endif
 
 void
 yyerror(char *fmt, ...)
--- a/sys/src/cmd/spin/spinlex.c
+++ b/sys/src/cmd/spin/spinlex.c
@@ -1,15 +1,15 @@
 /***** spin: spinlex.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
 #include "spin.h"
 #include "y.tab.h"
 
@@ -21,8 +21,11 @@
 	Symbol *nm;		/* name of the type */
 	Lextok *cn;		/* contents */
 	Lextok *params;		/* formal pars if any */
+	Lextok *rval;		/* variable to assign return value, if any */
 	char   **anms;		/* literal text for actual pars */
 	char   *prec;		/* precondition for c_code or c_expr */
+	int    uiid;		/* unique inline id */
+	int    is_expr;		/* c_expr in an ltl formula */
 	int    dln, cln;	/* def and call linenr */
 	Symbol *dfn, *cfn;	/* def and call filename */
 	struct IType *nxt;	/* linked list */
@@ -32,19 +35,24 @@
 	Symbol *s;
 	Symbol *t;
 	Symbol *ival;
+	Symbol *fnm;
+	int	lno;
 	struct C_Added *nxt;
 } C_Added;
 
 extern RunList	*X;
 extern ProcList	*rdy;
-extern Symbol	*Fname;
+extern Symbol	*Fname, *oFname;
 extern Symbol	*context, *owner;
 extern YYSTYPE	yylval;
-extern short	has_last, has_code;
-extern int	verbose, IArgs, hastrack, separate;
+extern short	has_last, has_code, has_priority;
+extern int	verbose, IArgs, hastrack, separate, in_for;
+extern int	implied_semis, ltl_mode, in_seq, par_cnt;
 
 short	has_stack = 0;
 int	lineno  = 1;
+int	scope_seq[128], scope_level = 0;
+char	CurScope[MAXSCOPESZ];
 char	yytext[2048];
 FILE	*yyin, *yyout;
 
@@ -55,45 +63,62 @@
 static unsigned char	in_comment=0;
 static int	IArgno = 0, Inlining = -1;
 static int	check_name(char *);
+static int	last_token = 0;
 
-#if 1
-#define Token(y)	{ if (in_comment) goto again; \
-			yylval = nn(ZN,0,ZN,ZN); return y; }
-
 #define ValToken(x, y)	{ if (in_comment) goto again; \
-			yylval = nn(ZN,0,ZN,ZN); yylval->val = x; return y; }
+			yylval = nn(ZN,0,ZN,ZN); \
+			yylval->val = x; \
+			last_token = y; \
+			return y; \
+			}
 
 #define SymToken(x, y)	{ if (in_comment) goto again; \
-			yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; return y; }
-#else
-#define Token(y)	{ yylval = nn(ZN,0,ZN,ZN); \
-			if (!in_comment) return y; else goto again; }
+			yylval = nn(ZN,0,ZN,ZN); \
+			yylval->sym = x; \
+			last_token = y; \
+			return y; \
+			}
 
-#define ValToken(x, y)	{ yylval = nn(ZN,0,ZN,ZN); yylval->val = x; \
-			if (!in_comment) return y; else goto again; }
+static int  getinline(void);
+static void uninline(void);
 
-#define SymToken(x, y)	{ yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; \
-			if (!in_comment) return y; else goto again; }
-#endif
+static int PushBack;
+static int PushedBack;
+static char pushedback[4096];
 
-static int	getinline(void);
-static void	uninline(void);
+static void
+push_back(char *s)
+{
+	if (PushedBack + strlen(s) > 4094)
+	{	fatal("select statement too large", 0);
+	}
+	strcat(pushedback, s);
+	PushedBack += strlen(s);
+}
 
-#if 1
-#define Getchar()	((Inlining<0)?getc(yyin):getinline())
-#define Ungetch(c)	{if (Inlining<0) ungetc(c,yyin); else uninline(); }
-
-#else
-
 static int
 Getchar(void)
 {	int c;
+
+	if (PushedBack > 0 && PushBack < PushedBack)
+	{	c = pushedback[PushBack++];
+		if (PushBack == PushedBack)
+		{	pushedback[0] = '\0';
+			PushBack = PushedBack = 0;
+		}
+		return c;	/* expanded select statement */
+	}
 	if (Inlining<0)
-		c = getc(yyin);
-	else
-		c = getinline();
-#if 1
-	printf("<%c>", c);
+	{	c = getc(yyin);
+	} else
+	{	c = getinline();
+	}
+#if 0
+	if (0)
+	{	printf("<%c:%d>[%d] ", c, c, Inlining);
+	} else
+	{	printf("%c", c);
+	}
 #endif
 	return c;
 }
@@ -101,17 +126,27 @@
 static void
 Ungetch(int c)
 {
+	if (PushedBack > 0 && PushBack > 0)
+	{	PushBack--;
+		return;
+	}
+
 	if (Inlining<0)
-		ungetc(c,yyin);
-	else
-		uninline();
-#if 1
-	printf("<bs>");
-#endif
+	{	ungetc(c,yyin);
+	} else
+	{	uninline();
+	}
+	if (0)
+	{	printf("\n<bs{%d}bs>\n", c);
+	}
 }
-#endif
 
 static int
+notdollar(int c)
+{	return (c != '$' && c != '\n');
+}
+
+static int
 notquote(int c)
 {	return (c != '\"' && c != '\n');
 }
@@ -133,15 +168,17 @@
 
 static void
 getword(int first, int (*tst)(int))
-{	int i=0; char c;
+{	int i=0, c;
 
 	yytext[i++]= (char) first;
 	while (tst(c = Getchar()))
-	{	yytext[i++] = c;
+	{	yytext[i++] = (char) c;
 		if (c == '\\')
-			yytext[i++] = Getchar();	/* no tst */
-	}
+		{	c = Getchar();
+			yytext[i++] = (char) c;	/* no tst */
+	}	}
 	yytext[i] = '\0';
+
 	Ungetch(c);
 }
 
@@ -150,7 +187,8 @@
 {	int c;
 
 	if ((c = Getchar()) == tok)
-		return ifyes;
+	{	return ifyes;
+	}
 	Ungetch(c);
 
 	return ifno;
@@ -161,10 +199,11 @@
 static void
 def_inline(Symbol *s, int ln, char *ptr, char *prc, Lextok *nms)
 {	IType *tmp;
-	char *nw = (char *) emalloc((int) strlen(ptr)+1);
+	int  cnt = 0;
+	char *nw = (char *) emalloc(strlen(ptr)+1);
 	strcpy(nw, ptr);
 
-	for (tmp = seqnames; tmp; tmp = tmp->nxt)
+	for (tmp = seqnames; tmp; cnt++, tmp = tmp->nxt)
 		if (!strcmp(s->name, tmp->nm->name))
 		{	non_fatal("procedure name %s redefined",
 				tmp->nm->name);
@@ -179,11 +218,12 @@
 	tmp->cn = (Lextok *) nw;
 	tmp->params = nms;
 	if (strlen(prc) > 0)
-	{	tmp->prec = (char *) emalloc((int) strlen(prc)+1);
+	{	tmp->prec = (char *) emalloc(strlen(prc)+1);
 		strcpy(tmp->prec, prc);
 	}
 	tmp->dln = ln;
 	tmp->dfn = Fname;
+	tmp->uiid = cnt+1;	/* so that 0 means: not an inline */
 	tmp->nxt = seqnames;
 	seqnames = tmp;
 }
@@ -250,6 +290,20 @@
 	return 0;
 }
 
+Lextok *
+return_statement(Lextok *n)
+{
+	if (Inline_stub[Inlining]->rval)
+	{	Lextok *g = nn(ZN, NAME, ZN, ZN);
+		Lextok *h = Inline_stub[Inlining]->rval;
+		g->sym = lookup("rv_");
+		return nn(h, ASGN, h, n);
+	} else
+	{	fatal("return statement outside inline", (char *) 0);
+	}
+	return ZN;
+}
+
 static int
 getinline(void)
 {	int c;
@@ -261,16 +315,20 @@
 			c = *Inliner[Inlining]++;
 		}
 	} else
+	{
 		c = *Inliner[Inlining]++;
+	}
 
 	if (c == '\0')
-	{	lineno = Inline_stub[Inlining]->cln;
+	{
+		lineno = Inline_stub[Inlining]->cln;
 		Fname  = Inline_stub[Inlining]->cfn;
 		Inlining--;
+
 #if 0
 		if (verbose&32)
-		printf("spin: line %d, done inlining %s\n",
-			lineno, Inline_stub[Inlining+1]->nm->name);
+		printf("spin: %s:%d, done inlining %s\n",
+			Fname, lineno, Inline_stub[Inlining+1]->nm->name);
 #endif
 		return Getchar();
 	}
@@ -286,6 +344,16 @@
 		Inliner[Inlining]--;
 }
 
+int
+is_inline(void)
+{
+	if (Inlining < 0)
+		return 0;	/* i.e., not an inline */
+	if (Inline_stub[Inlining] == NULL)
+		fatal("unexpected, inline_stub not set", 0);
+	return Inline_stub[Inlining]->uiid;
+}
+
 IType *
 find_inline(char *s)
 {	IType *tmp;
@@ -295,6 +363,7 @@
 			break;
 	if (!tmp)
 		fatal("cannot happen, missing inline def %s", s);
+
 	return tmp;
 }
 
@@ -306,7 +375,17 @@
 	r->s = s;	/* pointer to a data object */
 	r->t = t;	/* size of object, or "global", or "local proctype_name"  */
 	r->ival = ival;
+	r->lno = lineno;
+	r->fnm = Fname;
 	r->nxt = c_added;
+
+	if(strncmp(r->s->name, "\"unsigned unsigned", 18) == 0)
+	{	int i;
+		for (i = 10; i < 18; i++)
+		{	r->s->name[i] = ' ';
+		}
+	/*	printf("corrected <%s>\n", r->s->name);	*/
+	}
 	c_added = r;
 }
 
@@ -319,6 +398,8 @@
 	r->t = t;
 	r->ival = stackonly;	/* abuse of name */
 	r->nxt = c_tracked;
+	r->fnm = Fname;
+	r->lno = lineno;
 	c_tracked = r;
 
 	if (stackonly != ZS)
@@ -329,36 +410,76 @@
 		     &&  strcmp(stackonly->name, "\"StackOnly\"") != 0)
 			non_fatal("expecting '[Un]Matched', saw %s", stackonly->name);
 		else
-			has_stack = 1;
+			has_stack = 1;	/* unmatched stack */
 	}
 }
 
 char *
-jump_etc(char *op)
-{	char *p = op;
+skip_white(char *p)
+{
+	if (p != NULL)
+	{	while (*p == ' ' || *p == '\t')
+			p++;
+	} else
+	{	fatal("bad format - 1", (char *) 0);
+	}
+	return p;
+}
 
-	/* kludgy - try to get the type separated from the name */
+char *
+skip_nonwhite(char *p)
+{
+	if (p != NULL)
+	{	while (*p != ' ' && *p != '\t')
+			p++;
+	} else
+	{	fatal("bad format - 2", (char *) 0);
+	}
+	return p;
+}
 
-	while (*p == ' ' || *p == '\t')
-		p++;	/* initial white space */
-	while (*p != ' ' && *p != '\t')
-		p++;	/* type name */
-	while (*p == ' ' || *p == '\t')
-		p++;	/* white space */
-	while (*p == '*')
-		p++;	/* decorations */
-	while (*p == ' ' || *p == '\t')
-		p++;	/* white space */
+static char *
+jump_etc(C_Added *r)
+{	char *op = r->s->name;
+	char *p = op;
+	char *q = (char *) 0;
+	int oln = lineno;
+	Symbol *ofnm = Fname;
 
+	/* try to get the type separated from the name */
+	lineno = r->lno;
+	Fname  = r->fnm;
+
+	p = skip_white(p);	/* initial white space */
+
+	if (strncmp(p, "enum", strlen("enum")) == 0) /* special case: a two-part typename */
+	{	p += strlen("enum")+1;
+		p = skip_white(p);
+	}
+	if (strncmp(p, "unsigned", strlen("unsigned")) == 0) /* possibly a two-part typename */
+	{	p += strlen("unsigned")+1;
+		q = p = skip_white(p);
+	}
+	p = skip_nonwhite(p);	/* type name */
+	p = skip_white(p);	/* white space */
+	while (*p == '*') p++;	/* decorations */
+	p = skip_white(p);	/* white space */
+
 	if (*p == '\0')
-		fatal("c_state format (%s)", op);
+	{	if (q)
+		{	p = q;	/* unsigned with implied 'int' */
+		} else
+		{	fatal("c_state format (%s)", op);
+	}	}
 
-	if (strchr(p, '[')
-	&&  !strchr(p, '{'))
+	if (strchr(p, '[') && !strchr(p, '{'))
 	{	non_fatal("array initialization error, c_state (%s)", p);
-		return (char *) 0;
+		p = (char *) 0;
 	}
 
+	lineno = oln;
+	Fname = ofnm;
+
 	return p;
 }
 
@@ -379,7 +500,7 @@
 				if (*q == '\\')
 					*q++ = ' '; /* skip over the next */
 			}
-			p = jump_etc(r->s->name);	/* e.g., "int **q" */
+			p = jump_etc(r);	/* e.g., "int **q" */
 			if (p)
 			fprintf(fd, "	now.%s = %s;\n", p, r->ival->name);
 
@@ -391,7 +512,7 @@
 				if (*q == '\\')
 					*q++ = ' '; /* skip over the next */
 			}
-			p = jump_etc(r->s->name);	/* e.g., "int **q" */
+			p = jump_etc(r);	/* e.g., "int **q" */
 			if (p)
 			fprintf(fd, "	%s = %s;\n", p, r->ival->name);	/* no now. prefix */
 
@@ -413,7 +534,7 @@
 				if (*q == '\"')
 					*q = ' ';
 			
-			p = jump_etc(r->s->name);	/* e.g., "int **q" */
+			p = jump_etc(r);	/* e.g., "int **q" */
 
 			q = r->t->name + strlen(" Local");
 			while (*q == ' ' || *q == '\t')
@@ -435,9 +556,9 @@
 			}
 
 			if (p)
-			fprintf(fd, "		((P%d *)this)->%s = %s;\n",
-				tpnr, p, r->ival->name);
-
+			{	fprintf(fd, "\t\t((P%d *)this)->%s = %s;\n",
+					tpnr, p, r->ival->name);
+			}
 		}
 	fprintf(fd, "}\n");
 }
@@ -514,32 +635,38 @@
 }
 
 void
-c_add_stack(FILE *fd)
+c_stack_size(FILE *fd)
 {	C_Added *r;
 	int cnt = 0;
 
-	if ((!c_added && !c_tracked) || !has_stack) return;
-
-
 	for (r = c_tracked; r; r = r->nxt)
 		if (r->ival != ZS)
+		{	fprintf(fd, "%s%s",
+				(cnt==0)?"":"+", r->t->name);
 			cnt++;
+		}
+	if (cnt == 0)
+	{	fprintf(fd, "WS");
+	}
+}
 
-	if (cnt == 0) return;
+void
+c_add_stack(FILE *fd)
+{	C_Added *r;
+	int cnt = 0;
 
-	fprintf(fd, "	uchar c_stack[");
+	if ((!c_added && !c_tracked) || !has_stack)
+	{	return;
+	}
 
-	cnt = 0;
 	for (r = c_tracked; r; r = r->nxt)
-	{	if (r->ival == ZS) continue;
+		if (r->ival != ZS)
+		{	cnt++;
+		}
 
-		fprintf(fd, "%s%s",
-			(cnt==0)?"":"+", r->t->name);
-		cnt++;
+	if (cnt > 0)
+	{	fprintf(fd, "	uchar c_stack[StackSize];\n");
 	}
-
-	if (cnt == 0) fprintf(fd, "WS"); /* can't happen */
-	fprintf(fd, "];\n");
 }
 
 void
@@ -568,6 +695,7 @@
 	for (r = c_added; r; r = r->nxt)	/* pickup local decls */
 		if (strncmp(r->t->name, " Local", strlen(" Local")) == 0)
 		{	p = r->t->name + strlen(" Local");
+fprintf(fd, "/* XXX p=<%s>, s=<%s>, buf=<%s> r->s->name=<%s>XXX */\n", p, s, buf, r->s->name);
 			while (*p == ' ' || *p == '\t')
 				p++;
 			if (strcmp(p, buf) == 0)
@@ -578,7 +706,7 @@
 c_add_def(FILE *fd)	/* 3 - called in plunk_c_fcts() */
 {	C_Added *r;
 
-	fprintf(fd, "#if defined(C_States) && defined(HAS_TRACK)\n");
+	fprintf(fd, "#if defined(C_States) && (HAS_TRACK==1)\n");
 	for (r = c_added; r; r = r->nxt)
 	{	r->s->name[strlen(r->s->name)-1] = ' ';
 		r->s->name[0] = ' '; /* remove the "s */
@@ -610,9 +738,10 @@
 	}
 
 	if (has_stack)
-	{	fprintf(fd, "void\nc_stack(uchar *p_t_r)\n{\n");
+	{	fprintf(fd, "int cpu_printf(const char *, ...);\n");
+		fprintf(fd, "void\nc_stack(uchar *p_t_r)\n{\n");
 		fprintf(fd, "#ifdef VERBOSE\n");
-		fprintf(fd, "	printf(\"c_stack %%u\\n\", p_t_r);\n");
+		fprintf(fd, "	cpu_printf(\"c_stack %%u\\n\", p_t_r);\n");
 		fprintf(fd, "#endif\n");
 		for (r = c_tracked; r; r = r->nxt)
 		{	if (r->ival == ZS) continue;
@@ -630,7 +759,7 @@
 
 	fprintf(fd, "void\nc_update(uchar *p_t_r)\n{\n");
 	fprintf(fd, "#ifdef VERBOSE\n");
-	fprintf(fd, "	printf(\"c_update %%u\\n\", p_t_r);\n");
+	fprintf(fd, "	printf(\"c_update %%p\\n\", p_t_r);\n");
 	fprintf(fd, "#endif\n");
 	for (r = c_added; r; r = r->nxt)
 	{	if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
@@ -660,7 +789,7 @@
 	if (has_stack)
 	{	fprintf(fd, "void\nc_unstack(uchar *p_t_r)\n{\n");
 		fprintf(fd, "#ifdef VERBOSE\n");
-		fprintf(fd, "	printf(\"c_unstack %%u\\n\", p_t_r);\n");
+		fprintf(fd, "	cpu_printf(\"c_unstack %%u\\n\", p_t_r);\n");
 		fprintf(fd, "#endif\n");
 		for (r = c_tracked; r; r = r->nxt)
 		{	if (r->ival == ZS) continue;
@@ -675,7 +804,7 @@
 
 	fprintf(fd, "void\nc_revert(uchar *p_t_r)\n{\n");
 	fprintf(fd, "#ifdef VERBOSE\n");
-	fprintf(fd, "	printf(\"c_revert %%u\\n\", p_t_r);\n");
+	fprintf(fd, "	printf(\"c_revert %%p\\n\", p_t_r);\n");
 	fprintf(fd, "#endif\n");
 	for (r = c_added; r; r = r->nxt)
 	{	if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
@@ -708,11 +837,13 @@
 	plunk_reverse(fd, p->nxt, matchthis);
 
 	if (!p->nm->context
-	&&   p->nm->type == matchthis)
+	&&   p->nm->type == matchthis
+	&&   p->is_expr == 0)
 	{	fprintf(fd, "\n/* start of %s */\n", p->nm->name);
 		z = (char *) p->cn;
 		while (*z == '\n' || *z == '\r' || *z == '\\')
-			z++;
+		{	z++;
+		}
 		/* e.g.: \#include "..." */
 
 		y = z;
@@ -772,14 +903,28 @@
 	}	}
 }
 
+extern short terse;
+extern short nocast;
+
 void
 plunk_expr(FILE *fd, char *s)
 {	IType *tmp;
+	char *q;
 
 	tmp = find_inline(s);
 	check_inline(tmp);
 
-	fprintf(fd, "%s", (char *) tmp->cn);
+	if (terse && nocast)
+	{	for (q = (char *) tmp->cn; q && *q != '\0'; q++)
+		{	fflush(fd);
+			if (*q == '"')
+			{	fprintf(fd, "\\");
+			}
+			fprintf(fd, "%c", *q);
+		}
+	} else
+	{	fprintf(fd, "%s", (char *) tmp->cn);
+	}
 }
 
 void
@@ -791,9 +936,11 @@
 	{	tmp = find_inline(n->sym->name);
 		if (tmp->prec)
 		{	fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec);
-			fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t;");
-			fprintf(fd, "trpt->st = tt; Uerror(\"%s\"); } ", tmp->prec);
-			fprintf(fd, "else { printf(\"pan: precondition false: %s\\n\"); ", tmp->prec);
+			fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t; trpt->st = tt; ");
+			fprintf(fd, "uerror(\"c_expr line %d precondition false: %s\"); continue;",
+				tmp->dln, tmp->prec);
+			fprintf(fd, " } else { printf(\"pan: precondition false: %s\\n\"); ",
+				tmp->prec);
 			fprintf(fd, "_m = 3; goto P999; } } \n\t\t");
 		}
 	} else
@@ -813,8 +960,25 @@
 	||      strchr(bdy, '(') > bdy);	/* possible C-function call */
 }
 
+char *
+put_inline(FILE *fd, char *s)
+{	IType *tmp;
+
+	tmp = find_inline(s);
+	check_inline(tmp);
+	return (char *) tmp->cn;
+}
+
 void
-plunk_inline(FILE *fd, char *s, int how)	/* c_code with precondition */
+mark_last(void)
+{
+	if (seqnames)
+	{	seqnames->is_expr = 1;
+	}
+}
+
+void
+plunk_inline(FILE *fd, char *s, int how, int gencode)	/* c_code with precondition */
 {	IType *tmp;
 
 	tmp = find_inline(s);
@@ -822,16 +986,32 @@
 
 	fprintf(fd, "{ ");
 	if (how && tmp->prec)
-	{	fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec);
-		fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t;");
-		fprintf(fd, "trpt->st = tt; Uerror(\"%s\"); } ", tmp->prec);
-		fprintf(fd, "else { printf(\"pan: precondition false: %s\\n\"); ", tmp->prec);
-		fprintf(fd, "_m = 3; goto P999; } } ");
+	{	fprintf(fd, "if (!(%s)) { if (!readtrail) {",
+			tmp->prec);
+		fprintf(fd, " uerror(\"c_code line %d precondition false: %s\"); continue; ",
+			tmp->dln,
+			tmp->prec);
+		fprintf(fd, "} else { ");
+		fprintf(fd, "printf(\"pan: precondition false: %s\\n\"); _m = 3; goto P999; } } ",
+			tmp->prec);
 	}
+
+	if (!gencode)	/* not in d_step */
+	{	fprintf(fd, "\n\t\tsv_save();");
+	}
+
 	fprintf(fd, "%s", (char *) tmp->cn);
 	fprintf(fd, " }\n");
 }
 
+int
+side_scan(char *t, char *pat)
+{	char *r = strstr(t, pat);
+	return (r
+		&& *(r-1) != '"'
+		&& *(r-1) != '\'');
+}
+
 void
 no_side_effects(char *s)
 {	IType *tmp;
@@ -845,9 +1025,9 @@
 	tmp = find_inline(s);
 	t = (char *) tmp->cn;
 
-	if (strchr(t, ';')
-	||  strstr(t, "++")
-	||  strstr(t, "--"))
+	if (side_scan(t, ";")
+	||  side_scan(t, "++")
+	||  side_scan(t, "--"))
 	{
 bad:		lineno = tmp->dln;
 		Fname = tmp->dfn;
@@ -857,8 +1037,10 @@
 	while ((t = strchr(t, '=')) != NULL)
 	{	if (*(t-1) == '!'
 		||  *(t-1) == '>'
-		||  *(t-1) == '<')
-		{	t++;
+		||  *(t-1) == '<'
+		||  *(t-1) == '"'
+		||  *(t-1) == '\'')
+		{	t += 2;
 			continue;
 		}
 		t++;
@@ -869,16 +1051,16 @@
 }
 
 void
-pickup_inline(Symbol *t, Lextok *apars)
+pickup_inline(Symbol *t, Lextok *apars, Lextok *rval)
 {	IType *tmp; Lextok *p, *q; int j;
 
 	tmp = find_inline(t->name);
 
 	if (++Inlining >= MAXINL)
-		fatal("inline fcts too deeply nested", 0);
-
+		fatal("inlines nested too deeply", 0);
 	tmp->cln = lineno;	/* remember calling point */
 	tmp->cfn = Fname;	/* and filename */
+	tmp->rval = rval;
 
 	for (p = apars, q = tmp->params, j = 0; p && q; p = p->rgt, q = q->rgt)
 		j++; /* count them */
@@ -887,7 +1069,7 @@
 
 	tmp->anms  = (char **) emalloc(j * sizeof(char *));
 	for (p = apars, j = 0; p; p = p->rgt, j++)
-	{	tmp->anms[j] = (char *) emalloc((int) strlen(IArg_cont[j])+1);
+	{	tmp->anms[j] = (char *) emalloc(strlen(IArg_cont[j])+1);
 		strcpy(tmp->anms[j], IArg_cont[j]);
 	}
 
@@ -897,14 +1079,18 @@
 	Inline_stub[Inlining] = tmp;
 #if 0
 	if (verbose&32)
-	printf("spin: line %d, file %s, inlining '%s' (from line %d, file %s)\n",
-		tmp->cln, tmp->cfn->name, t->name, tmp->dln, tmp->dfn->name);
+	printf("spin: %s:%d, inlining '%s' (from %s:%d)\n",
+		tmp->cfn->name, tmp->cln, t->name, tmp->dfn->name, tmp->dln);
 #endif
 	for (j = 0; j < Inlining; j++)
-		if (Inline_stub[j] == Inline_stub[Inlining])
-		fatal("cyclic inline attempt on: %s", t->name);
+	{	if (Inline_stub[j] == Inline_stub[Inlining])
+		{	fatal("cyclic inline attempt on: %s", t->name);
+	}	}
+	last_token = SEMI;	/* avoid insertion of extra semi */
 }
 
+extern int pp_mode;
+
 static void
 do_directive(int first)
 {	int c = first;	/* handles lines starting with pound */
@@ -930,13 +1116,15 @@
 		fatal("malformed preprocessor directive - .fname", 0);
 
 	if ((c = Getchar()) != '\"')
-		fatal("malformed preprocessor directive - .fname", 0);
+	{	printf("got %c, expected \" -- lineno %d\n", c, lineno);
+		fatal("malformed preprocessor directive - .fname (%s)", yytext);
+	}
 
-	getword(c, notquote);
+	getword(Getchar(), notquote);	/* was getword(c, notquote); */
 	if (Getchar() != '\"')
 		fatal("malformed preprocessor directive - fname.", 0);
 
-	strcat(yytext, "\"");
+	/* strcat(yytext, "\""); */
 	Fname = lookup(yytext);
 done:
 	while (Getchar() != '\n')
@@ -965,34 +1153,37 @@
 			break;
 		}
 	}
-	fatal("cannot happen", (char *) 0);			
+	fatal("cannot happen", (char *) 0); /* unreachable */
 }
 
+
 Symbol *
 prep_inline(Symbol *s, Lextok *nms)
 {	int c, nest = 1, dln, firstchar, cnr;
-	char *p, buf[SOMETHINGBIG], buf2[RATHERSMALL];
+	char *p;
 	Lextok *t;
+	static char Buf1[SOMETHINGBIG], Buf2[RATHERSMALL];
 	static int c_code = 1;
 
 	for (t = nms; t; t = t->rgt)
 		if (t->lft)
 		{	if (t->lft->ntyp != NAME)
-			fatal("bad param to inline %s", s->name);
+			fatal("bad param to inline %s", s?s->name:"--");
 			t->lft->sym->hidden |= 32;
 		}
 
 	if (!s)	/* C_Code fragment */
 	{	s = (Symbol *) emalloc(sizeof(Symbol));
-		s->name = (char *) emalloc((int) strlen("c_code")+26);
+		s->name = (char *) emalloc(strlen("c_code")+26);
 		sprintf(s->name, "c_code%d", c_code++);
 		s->context = context;
 		s->type = CODE_FRAG;
 	} else
-		s->type = PREDEF;
+	{	s->type = PREDEF;
+	}
 
-	p = &buf[0];
-	buf2[0] = '\0';
+	p = &Buf1[0];
+	Buf2[0] = '\0';
 	for (;;)
 	{	c = Getchar();
 		switch (c) {
@@ -999,7 +1190,7 @@
 		case '[':
 			if (s->type != CODE_FRAG)
 				goto bad;
-			precondition(&buf2[0]);	/* e.g., c_code [p] { r = p-r; } */
+			precondition(&Buf2[0]);	/* e.g., c_code [p] { r = p-r; } */
 			continue;
 		case '{':
 			break;
@@ -1017,19 +1208,22 @@
 	dln = lineno;
 	if (s->type == CODE_FRAG)
 	{	if (verbose&32)
-			sprintf(buf, "\t/* line %d %s */\n\t\t",
+		{	sprintf(Buf1, "\t/* line %d %s */\n\t\t",
 				lineno, Fname->name);
-		else
-			strcpy(buf, "");
+		} else
+		{	strcpy(Buf1, "");
+		}
 	} else
-		sprintf(buf, "\n#line %d %s\n{", lineno, Fname->name);
-	p += strlen(buf);
+	{	sprintf(Buf1, "\n#line %d \"%s\"\n{", lineno, Fname->name);
+	}
+	p += strlen(Buf1);
 	firstchar = 1;
 
 	cnr = 1; /* not zero */
 more:
-	*p++ = c = Getchar();
-	if (p - buf >= SOMETHINGBIG)
+	c = Getchar();
+	*p++ = (char) c;
+	if (p - Buf1 >= SOMETHINGBIG)
 		fatal("inline text too long", 0);
 	switch (c) {
 	case '\n':
@@ -1045,11 +1239,13 @@
 		if (--nest <= 0)
 		{	*p = '\0';
 			if (s->type == CODE_FRAG)
-				*--p = '\0';	/* remove trailing '}' */	
-			def_inline(s, dln, &buf[0], &buf2[0], nms);
-			if (firstchar && s)
-				printf("%3d: %s, warning: empty inline definition (%s)\n",
+			{	*--p = '\0';	/* remove trailing '}' */
+			}	
+			def_inline(s, dln, &Buf1[0], &Buf2[0], nms);
+			if (firstchar)
+			{	printf("%3d: %s, warning: empty inline definition (%s)\n",
 					dln, Fname->name, s->name);
+			}
 			return s;	/* normal return */
 		}
 		break;
@@ -1057,30 +1253,240 @@
 		if (cnr == 0)
 		{	p--;
 			do_directive(c); /* reads to newline */
-			break;
-		} /* else fall through */
-	default:
-		firstchar = 0;
+		} else
+		{	firstchar = 0;
+			cnr++;
+		}
+		break;
 	case '\t':
 	case ' ':
 	case '\f':
 		cnr++;
 		break;
+	case '"':
+		do {
+			c = Getchar();
+			*p++ = (char) c;
+			if (c == '\\')
+			{	*p++ = (char) Getchar();
+			}
+			if (p - Buf1 >= SOMETHINGBIG)
+			{	fatal("inline text too long", 0);
+			}
+		} while (c != '"');	/* end of string */
+		/* *p = '\0'; */
+		break;
+	case '\'':
+		c = Getchar();
+		*p++ = (char) c;
+		if (c == '\\')
+		{	*p++ = (char) Getchar();
+		}
+		c = Getchar();
+		*p++ = (char) c;
+		assert(c == '\'');
+		break;
+	default:
+		firstchar = 0;
+		cnr++;
+		break;
 	}
 	goto more;
 }
 
+static void
+set_cur_scope(void)
+{	int i;
+	char tmpbuf[256];
+
+	strcpy(CurScope, "_");
+
+	if (context)
+	for (i = 0; i < scope_level; i++)
+	{	sprintf(tmpbuf, "%d_", scope_seq[i]);
+		strcat(CurScope, tmpbuf);
+	}
+}
+
 static int
+pre_proc(void)
+{	char b[512];
+	int c, i = 0;
+
+	b[i++] = '#';
+	while ((c = Getchar()) != '\n' && c != EOF)
+	{	b[i++] = (char) c;
+	}
+	b[i] = '\0';
+	yylval = nn(ZN, 0, ZN, ZN);
+	yylval->sym = lookup(b);
+	return PREPROC;
+}
+
+static int specials[] = {
+	'}', ')', ']',
+	OD, FI, ELSE, BREAK,
+	C_CODE, C_EXPR, C_DECL,
+	NAME, CONST, INCR, DECR, 0
+};
+
+int
+follows_token(int c)
+{	int i;
+
+	for (i = 0; specials[i]; i++)
+	{	if (c == specials[i])
+		{	return 1;
+	}	}
+	return 0;
+}
+#define DEFER_LTL
+#ifdef DEFER_LTL
+/* defer ltl formula to the end of the spec
+ * no matter where they appear in the original
+ */
+
+static int deferred = 0;
+static FILE *defer_fd;
+
+int
+get_deferred(void)
+{
+	if (!defer_fd)
+	{	return 0;	/* nothing was deferred */
+	}
+	fclose(defer_fd);
+
+	defer_fd = fopen(TMP_FILE2, "r");
+	if (!defer_fd)
+	{	non_fatal("cannot retrieve deferred ltl formula", (char *) 0);
+		return 0;
+	}
+	fclose(yyin);
+	yyin = defer_fd;
+	return 1;
+}
+
+void
+zap_deferred(void)
+{
+	(void) unlink(TMP_FILE2);
+}
+
+int
+put_deferred(void)
+{	int c, cnt;
+	if (!defer_fd)
+	{	defer_fd = fopen(TMP_FILE2, "w+");
+		if (!defer_fd)
+		{	non_fatal("cannot defer ltl expansion", (char *) 0);
+			return 0;
+	}	}
+	fprintf(defer_fd, "ltl ");
+	cnt = 0;
+	while ((c = getc(yyin)) != EOF)
+	{	if (c == '{')
+		{	cnt++;
+		}
+		if (c == '}')
+		{	cnt--;
+			if (cnt == 0)
+			{	break;
+		}	}
+		fprintf(defer_fd, "%c", c);
+	}
+	fprintf(defer_fd, "}\n");
+	fflush(defer_fd);
+	return 1;
+}
+#endif
+
+#define EXPAND_SELECT
+#ifdef EXPAND_SELECT
+static char tmp_hold[256];
+static int  tmp_has;
+
+void
+new_select(void)
+{	tmp_hold[0] = '\0';
+	tmp_has = 0;
+}
+
+int
+scan_to(int stop, int (*tst)(int), char *buf)
+{	int c, i = 0;
+
+	do {	c = Getchar();
+		if (tmp_has < sizeof(tmp_hold))
+		{	tmp_hold[tmp_has++] = c;
+		}
+		if (c == '\n')
+		{	lineno++;
+		} else if (buf)
+		{	buf[i++] = c;
+		}
+		if (tst && !tst(c) && c != ' ' && c != '\t')
+		{	break;
+		}
+	} while (c != stop && c != EOF);
+
+	if (buf)
+	{	buf[i-1] = '\0';
+	}
+
+	if (c != stop)
+	{	if (0)
+		{	printf("saw: '%c', expected '%c'\n", c, stop);
+		}
+		if (tmp_has < sizeof(tmp_hold))
+		{	tmp_hold[tmp_has] = '\0';
+			push_back(tmp_hold);
+			if (0)
+			{	printf("pushed back: <'%s'>\n", tmp_hold);
+			}
+			return 0; /* internal expansion fails */
+		} else
+		{	fatal("expecting select ( name : constant .. constant )", 0);
+	}	}
+	return 1;		/* success */
+}
+#endif
+
+int
 lex(void)
 {	int c;
-
 again:
 	c = Getchar();
 	yytext[0] = (char) c;
 	yytext[1] = '\0';
 	switch (c) {
+	case EOF:
+#ifdef DEFER_LTL
+		if (!deferred)
+		{	deferred = 1;
+			if (get_deferred())
+			{	goto again;
+			}
+		} else
+		{	zap_deferred();
+		}
+#endif
+		return c;
 	case '\n':		/* newline */
 		lineno++;
+		/* make most semi-colons optional */
+		if (implied_semis
+	/*	&&  context	*/
+		&&  in_seq
+		&&  par_cnt == 0
+		&&  follows_token(last_token))
+		{	if (0)
+			{	printf("insert ; line %d, last_token %d in_seq %d\n",
+				 lineno-1, last_token, in_seq);
+			}
+			ValToken(1, SEMI);
+		}
+		/* else fall thru */
 	case '\r':		/* carriage return */
 		goto again;
 
@@ -1089,6 +1495,10 @@
 
 	case '#':		/* preprocessor directive */
 		if (in_comment) goto again;
+		if (pp_mode)
+		{	last_token = PREPROC;
+			return pre_proc();
+		}
 		do_directive(c);
 		goto again;
 
@@ -1099,6 +1509,13 @@
 		strcat(yytext, "\"");
 		SymToken(lookup(yytext), STRING)
 
+	case '$':
+		getword('\"', notdollar);
+		if (Getchar() != '$')
+			fatal("ltl definition not terminated", yytext);
+		strcat(yytext, "\""); 
+		SymToken(lookup(yytext), STRING)
+
 	case '\'':	/* new 3.0.9 */
 		c = Getchar();
 		if (c == '\\')
@@ -1117,8 +1534,15 @@
 	}
 
 	if (isdigit_(c))
-	{	getword(c, isdigit_);
-		ValToken(atoi(yytext), CONST)
+	{	long int nr;
+		getword(c, isdigit_);
+		errno = 0;
+		nr = strtol(yytext, NULL, 10);
+		if (errno != 0)
+		{	fprintf(stderr, "spin: value out of range: '%s' read as '%d'\n",
+				yytext, (int) nr);
+		}
+		ValToken((int)nr, CONST)
 	}
 
 	if (isalpha_(c) || c == '_')
@@ -1125,12 +1549,89 @@
 	{	getword(c, isalnum_);
 		if (!in_comment)
 		{	c = check_name(yytext);
-			if (c) return c;
+
+#ifdef EXPAND_SELECT
+			if (c == SELECT && Inlining < 0)
+			{	char name[64], from[32], upto[32];
+				int i, a, b;
+				new_select();
+				if (!scan_to('(', 0, 0)
+				||  !scan_to(':', isalnum, name)
+				||  !scan_to('.', isdigit, from)
+				||  !scan_to('.', 0, 0)
+				||  !scan_to(')', isdigit, upto))
+				{	goto not_expanded;
+				}
+				a = atoi(from);
+				b = atoi(upto);
+				if (0)
+				{	printf("Select %s from %d to %d\n",
+						name, a, b);
+				}
+				if (a > b)
+				{	non_fatal("bad range in select statement", 0);
+					goto again;
+				}
+				if (b - a <= 32)
+				{	push_back("if ");
+					for (i = a; i <= b; i++)
+					{	char buf[128];
+						push_back(":: ");
+						sprintf(buf, "%s = %d ",
+							name, i);
+						push_back(buf);
+					}
+					push_back("fi ");
+				} else
+				{	char buf[128];
+					sprintf(buf, "%s = %d; do ",
+						name, a);
+					push_back(buf);
+					sprintf(buf, ":: (%s < %d) -> %s++ ",
+						name, b, name);
+					push_back(buf);
+					push_back(":: break od; ");
+				}
+				goto again;
+			}
+not_expanded:
+#endif
+
+#ifdef DEFER_LTL
+			if (c == LTL && !deferred)
+			{	if (put_deferred())
+				{	goto again;
+			}	}
+#endif
+			if (c)
+			{	last_token = c;
+				return c;
+			}
 			/* else fall through */
 		}
 		goto again;
 	}
 
+	if (ltl_mode)
+	{	switch (c) {
+		case '-': c = follow('>', IMPLIES,    '-'); break;
+		case '[': c = follow(']', ALWAYS,     '['); break;
+		case '<': c = follow('>', EVENTUALLY, '<');
+			  if (c == '<')
+			  {	c = Getchar();
+				if (c == '-')
+				{	c = follow('>', EQUIV, '-');
+					if (c == '-')
+					{	Ungetch(c);
+						c = '<';
+					}
+				} else
+				{	Ungetch(c);
+					c = '<';
+			  }	}
+		default:  break;
+	}	}
+
 	switch (c) {
 	case '/': c = follow('*', 0, '/');
 		  if (!c) { in_comment = 1; goto again; }
@@ -1139,7 +1640,7 @@
 		  if (!c) { in_comment = 0; goto again; }
 		  break;
 	case ':': c = follow(':', SEP, ':'); break;
-	case '-': c = follow('>', SEMI, follow('-', DECR, '-')); break;
+	case '-': c = follow('>', ARROW, follow('-', DECR, '-')); break;
 	case '+': c = follow('+', INCR, '+'); break;
 	case '<': c = follow('<', LSHIFT, follow('=', LE, LT)); break;
 	case '>': c = follow('>', RSHIFT, follow('=', GE, GT)); break;
@@ -1149,12 +1650,35 @@
 	case '&': c = follow('&', AND, '&'); break;
 	case '|': c = follow('|', OR, '|'); break;
 	case ';': c = SEMI; break;
+	case '.': c = follow('.', DOTDOT, '.'); break;
+	case '{': scope_seq[scope_level++]++; set_cur_scope(); break;
+	case '}': scope_level--; set_cur_scope(); break;
 	default : break;
 	}
-	Token(c)
+	ValToken(0, c)
 }
 
 static struct {
+	char *s;	int tok;
+} LTL_syms[] = {
+	/* [], <>, ->, and <-> are intercepted in lex() */
+	{ "U",		UNTIL   },
+	{ "V",		RELEASE },
+	{ "W",		WEAK_UNTIL },
+	{ "X",		NEXT    },
+	{ "always",	ALWAYS  },
+	{ "eventually",	EVENTUALLY },
+	{ "until",	UNTIL   },
+	{ "stronguntil",UNTIL   },
+	{ "weakuntil",	WEAK_UNTIL   },
+	{ "release",	RELEASE },
+	{ "next",	NEXT    },
+	{ "implies",	IMPLIES },
+	{ "equivalent",	EQUIV   },
+	{ 0, 		0       },
+};
+
+static struct {
 	char *s;	int tok;	int val;	char *sym;
 } Names[] = {
 	{"active",	ACTIVE,		0,		0},
@@ -1178,14 +1702,19 @@
 	{"eval",	EVAL,		0,		0},
 	{"false",	CONST,		0,		0},
 	{"fi",		FI,		0,		0},
+	{"for",		FOR,		0,		0},
 	{"full",	FULL,		0,		0},
+	{"get_priority", GET_P,		0,		0},
 	{"goto",	GOTO,		0,		0},
 	{"hidden",	HIDDEN,		0,		":hide:"},
 	{"if",		IF,		0,		0},
+	{"in",		IN,		0,		0},
 	{"init",	INIT,		0,		":init:"},
+	{"inline",	INLINE,		0,		0},
 	{"int",		TYPE,		INT,		0},
 	{"len",		LEN,		0,		0},
 	{"local",	ISLOCAL,	0,		":local:"},
+	{"ltl",		LTL,		0,		":ltl:"},
 	{"mtype",	TYPE,		MTYPE,		0},
 	{"nempty",	NEMPTY,		0,		0},
 	{"never",	CLAIM,		0,		":never:"},
@@ -1201,9 +1730,11 @@
 	{"priority",	PRIORITY,	0,		0},
 	{"proctype",	PROCTYPE,	0,		0},
 	{"provided",	PROVIDED,	0,		0},
+	{"return",	RETURN,		0,		0},
 	{"run",		RUN,		0,		0},
 	{"d_step",	D_STEP,		0,		0},
-	{"inline",	INLINE,		0,		0},
+	{"select",	SELECT,		0,		0},
+	{"set_priority", SET_P,		0,		0},
 	{"short",	TYPE,		SHORT,		0},
 	{"skip",	CONST,		1,		0},
 	{"timeout",	TIMEOUT,	0,		0},
@@ -1223,13 +1754,23 @@
 {	int i;
 
 	yylval = nn(ZN, 0, ZN, ZN);
+
+	if (ltl_mode)
+	{	for (i = 0; LTL_syms[i].s; i++)
+		{	if (strcmp(s, LTL_syms[i].s) == 0)
+			{	return LTL_syms[i].tok;
+	}	}	}
+
 	for (i = 0; Names[i].s; i++)
-		if (strcmp(s, Names[i].s) == 0)
+	{	if (strcmp(s, Names[i].s) == 0)
 		{	yylval->val = Names[i].val;
 			if (Names[i].sym)
 				yylval->sym = lookup(Names[i].sym);
+			if (Names[i].tok == IN && !in_for)
+			{	continue;
+			}
 			return Names[i].tok;
-		}
+	}	}
 
 	if ((yylval->val = ismtype(s)) != 0)
 	{	yylval->ismtyp = 1;
@@ -1239,6 +1780,9 @@
 	if (strcmp(s, "_last") == 0)
 		has_last++;
 
+	if (strcmp(s, "_priority") == 0)
+		has_priority++;
+
 	if (Inlining >= 0 && !ReDiRect)
 	{	Lextok *tt, *t = Inline_stub[Inlining]->params;
 
@@ -1253,19 +1797,29 @@
 				Inline_stub[Inlining]->nm->name,
 				Inline_stub[Inlining]->anms[i]);
 #endif
-			
 			for (tt = Inline_stub[Inlining]->params; tt; tt = tt->rgt)
 				if (!strcmp(Inline_stub[Inlining]->anms[i],
 					tt->lft->sym->name))
 				{	/* would be cyclic if not caught */
-					printf("spin: line %d replacement value: %s\n",
-						lineno, tt->lft->sym->name);
-					fatal("formal par of %s matches replacement value",
+					printf("spin: %s:%d replacement value: %s\n",
+						oFname->name?oFname->name:"--", lineno, tt->lft->sym->name);
+					fatal("formal par of %s contains replacement value",
 						Inline_stub[Inlining]->nm->name);
 					yylval->ntyp = tt->lft->ntyp;
 					yylval->sym = lookup(tt->lft->sym->name);
 					return NAME;
 				}
+
+			/* check for occurrence of param as field of struct */
+			{ char *ptr = Inline_stub[Inlining]->anms[i];
+				while ((ptr = strstr(ptr, s)) != NULL)
+				{	if (*(ptr-1) == '.'
+					||  *(ptr+strlen(s)) == '.')
+					{	fatal("formal par of %s used in structure name",
+						Inline_stub[Inlining]->nm->name);
+					}
+					ptr++;
+			}	}
 			ReDiRect = Inline_stub[Inlining]->anms[i];
 			return 0;
 	}	 }
@@ -1293,13 +1847,16 @@
 	if (hold)
 	{	c = hold;
 		hold = 0;
+		last_token = c;
 	} else
 	{	c = lex();
 		if (last == ELSE
 		&&  c != SEMI
+		&&  c != ARROW
 		&&  c != FI)
 		{	hold = c;
 			last = 0;
+			last_token = SEMI;
 			return SEMI;
 		}
 		if (last == '}'
@@ -1312,12 +1869,14 @@
 		&&  c != '}'
 		&&  c != UNLESS
 		&&  c != SEMI
+		&&  c != ARROW
 		&&  c != EOF)
 		{	hold = c;
 			last = 0;
+			last_token = SEMI;
 			return SEMI;	/* insert ';' */
 		}
-		if (c == SEMI)
+		if (c == SEMI || c == ARROW)
 		{	/* if context, we're not in a typedef
 			 * because they're global.
 			 * if owner, we're at the end of a ref
@@ -1328,6 +1887,7 @@
 			if (context) owner = ZS;
 			hold = lex();	/* look ahead */
 			if (hold == '}'
+			||  hold == ARROW
 			||  hold == SEMI)
 			{	c = hold; /* omit ';' */
 				hold = 0;
@@ -1346,16 +1906,26 @@
 			{	IArgno = 0;
 				IArg_cont[0][0] = '\0';
 			} else
+			{	assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
 				strcat(IArg_cont[IArgno], yytext);
+			}
 		} else if (strcmp(yytext, ")") == 0)
 		{	if (--IArg_nst > 0)
+			{	assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
 				strcat(IArg_cont[IArgno], yytext);
+			}
 		} else if (c == CONST && yytext[0] == '\'')
 		{	sprintf(yytext, "'%c'", yylval->val);
+			assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
 			strcat(IArg_cont[IArgno], yytext);
+		} else if (c == CONST)
+		{	sprintf(yytext, "%d", yylval->val);
+			assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
+			strcat(IArg_cont[IArgno], yytext);
 		} else
 		{
 			switch (c) {
+			case ARROW:	strcpy(yytext, "->"); break; /* NEW */
 			case SEP:	strcpy(yytext, "::"); break;
 			case SEMI:	strcpy(yytext, ";"); break;
 			case DECR:	strcpy(yytext, "--"); break;
@@ -1376,9 +1946,9 @@
 			case AND: 	strcpy(yytext, "&&"); break;
 			case OR:	strcpy(yytext, "||"); break;
 			}
+			assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
 			strcat(IArg_cont[IArgno], yytext);
 		}
 	}
-
 	return c;
 }
--- a/sys/src/cmd/spin/structs.c
+++ b/sys/src/cmd/spin/structs.c
@@ -1,13 +1,10 @@
 /***** spin: structs.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include "y.tab.h"
@@ -19,7 +16,7 @@
 } UType;
 
 extern	Symbol	*Fname;
-extern	int	lineno, depth, Expand_Ok;
+extern	int	lineno, depth, Expand_Ok, has_hidden, in_for;
 
 Symbol	*owner;
 
@@ -33,6 +30,9 @@
 setuname(Lextok *n)
 {	UType *tmp;
 
+	if (!owner)
+		fatal("illegal reference inside typedef", (char *) 0);
+
 	for (tmp = Unames; tmp; tmp = tmp->nxt)
 		if (!strcmp(owner->name, tmp->nm->name))
 		{	non_fatal("typename %s was defined before",
@@ -39,8 +39,7 @@
 				tmp->nm->name);
 			return;
 		}
-	if (!owner) fatal("illegal reference inside typedef",
-		(char *) 0);
+
 	tmp = (UType *) emalloc(sizeof(UType));
 	tmp->nm = owner;
 	tmp->cn = n;
@@ -102,21 +101,22 @@
 	{	lineno = n->ln;
 		Fname = n->fn;
 		if (n->sym->type)
-		non_fatal("redeclaration of '%s'", n->sym->name);
+			fatal("redeclaration of '%s'", n->sym->name);
 
 		if (n->sym->nbits > 0)
-		non_fatal("(%s) only an unsigned can have width-field",
-			n->sym->name);
+			non_fatal("(%s) only an unsigned can have width-field",
+				n->sym->name);
 
 		if (Expand_Ok)
 			n->sym->hidden |= (4|8|16); /* formal par */
 
 		if (vis)
-		{	if (strncmp(vis->sym->name, ":hide:", 6) == 0)
-				n->sym->hidden |= 1;
-			else if (strncmp(vis->sym->name, ":show:", 6) == 0)
+		{	if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
+			{	n->sym->hidden |= 1;
+				has_hidden++;
+			} else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
 				n->sym->hidden |= 2;
-			else if (strncmp(vis->sym->name, ":local:", 7) == 0)
+			else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
 				n->sym->hidden |= 64;
 		}
 		n->sym->type = STRUCT;	/* classification   */
@@ -196,6 +196,7 @@
 		fatal("non-zero 'rgt' on non-structure", 0);
 
 	ix = eval(tmp->lft);
+/*	printf("%d: ix: %d (%d) %d\n", depth, ix, tl->nel, tl->val[ix]); */
 	if (ix >= tl->nel || ix < 0)
 		fatal("indexing error \'%s\'", tl->name);
 
@@ -222,10 +223,12 @@
 		fatal("indexing error \'%s\'", tl->name);
 
 	if (tl->nbits > 0)
-		a = (a & ((1<<tl->nbits)-1));	
-	tl->val[ix] = a;
-	tl->setat = depth;
+		a = (a & ((1<<tl->nbits)-1));
 
+	if (a != tl->val[ix])
+	{	tl->val[ix] = a;
+		tl->setat = depth;
+	}
 	return 1;
 }
 
@@ -246,7 +249,7 @@
 	for (fp = n; fp; fp = fp->rgt)
 	for (tl = fp->lft; tl; tl = tl->rgt)
 	{	if (tl->sym->type == STRUCT)
-		{	if (tl->sym->nel != 1)
+		{	if (tl->sym->nel > 1 || tl->sym->isarray)
 				fatal("array of structures in param list, %s",
 					tl->sym->name);
 			cnt += Cnt_flds(tl->sym->Slst);
@@ -266,9 +269,9 @@
 		return s->type;
 
 	if (!t->rgt
-	||  !t->rgt->ntyp == '.'
+	||   t->rgt->ntyp != '.'	/* gh: had ! in wrong place */
 	||  !t->rgt->lft)
-		return STRUCT;	/* not a field reference */
+		return STRUCT;		/* not a field reference */
 
 	return Sym_typ(t->rgt->lft);
 }
@@ -315,6 +318,7 @@
 	if (!s) return ZN;
 
 	d = (Lextok *) emalloc(sizeof(Lextok));
+	d->uiid = s->uiid;
 	d->ntyp = s->ntyp;
 	d->val  = s->val;
 	d->ln   = s->ln;
@@ -353,7 +357,7 @@
 		goto out;
 	}
 	fprintf(fd, ".%s", tl->name);
-out:	if (tmp->sym->nel > 1)
+out:	if (tmp->sym->nel > 1 || tmp->sym->isarray == 1)
 	{	fprintf(fd, "[%d]", eval(tmp->lft));
 		hiddenarrays = 1;
 	}
@@ -391,7 +395,7 @@
 	}
 	sprintf(lbuf, ".%s", tl->name);
 	strcat(buf, lbuf);
-	if (tmp->sym->nel > 1)
+	if (tmp->sym->nel > 1 || tmp->sym->isarray == 1)
 	{	sprintf(lbuf, "[%d]", eval(tmp->lft));
 		strcat(buf, lbuf);
 	}
@@ -405,10 +409,10 @@
 	extern void Done_case(char *, Symbol *);
 
 	ini_struct(z);
-	if (z->nel == 1)
+	if (z->nel == 1 && z->isarray == 0)
 		sprintf(eprefix, "%s%s.", s, z->name);
 	for (ix = 0; ix < z->nel; ix++)
-	{	if (z->nel > 1)
+	{	if (z->nel > 1 || z->isarray == 1)
 			sprintf(eprefix, "%s%s[%d].", s, z->name, ix);
 		for (fp = z->Sval[ix]; fp; fp = fp->rgt)
 		for (tl = fp->lft; tl; tl = tl->rgt)
@@ -426,10 +430,10 @@
 	int ix;
 
 	ini_struct(z);
-	if (z->nel == 1)
+	if (z->nel == 1 && z->isarray == 0)
 		sprintf(eprefix, "%s%s.", s, z->name);
 	for (ix = 0; ix < z->nel; ix++)
-	{	if (z->nel > 1)
+	{	if (z->nel > 1 || z->isarray == 1)
 			sprintf(eprefix, "%s%s[%d].", s, z->name, ix);
 		for (fp = z->Sval[ix]; fp; fp = fp->rgt)
 		for (tl = fp->lft; tl; tl = tl->rgt)
@@ -443,7 +447,7 @@
 void
 c_struct(FILE *fd, char *ipref, Symbol *z)
 {	Lextok *fp, *tl;
-	char pref[256], eprefix[256];
+	char pref[256], eprefix[300];
 	int ix;
 
 	ini_struct(z);
@@ -452,7 +456,7 @@
 	for (fp = z->Sval[ix]; fp; fp = fp->rgt)
 	for (tl = fp->lft; tl; tl = tl->rgt)
 	{	strcpy(eprefix, ipref);
-		if (z->nel > 1)
+		if (z->nel > 1 || z->isarray == 1)
 		{	/* insert index before last '.' */
 			eprefix[strlen(eprefix)-1] = '\0';
 			sprintf(pref, "[ %d ].", ix);
@@ -476,7 +480,7 @@
 	ini_struct(z);
 
 	for (ix = 0; ix < z->nel; ix++)
-	{	if (z->nel > 1)
+	{	if (z->nel > 1 || z->isarray == 1)
 			sprintf(eprefix, "%s[%d]", prefix, ix);
 		else
 			strcpy(eprefix, prefix);
@@ -484,7 +488,7 @@
 		for (fp = z->Sval[ix]; fp; fp = fp->rgt)
 		for (tl = fp->lft; tl; tl = tl->rgt)
 		{	if (tl->sym->type == STRUCT)
-			{	char pref[256];
+			{	char pref[300];
 				strcpy(pref, eprefix);
 				strcat(pref, ".");
 				strcat(pref, tl->sym->name);
@@ -498,7 +502,7 @@
 					if (r)
 					printf("%s(%d):", r->n->name, r->pid);
 					printf("%s.%s", eprefix, tl->sym->name);
-					if (tl->sym->nel > 1)
+					if (tl->sym->nel > 1 || tl->sym->isarray == 1)
 						printf("[%d]", jx);
 					printf(" = ");
 					sr_mesg(stdout, tl->sym->val[jx],
@@ -579,8 +583,10 @@
 	int i, cnt; extern int IArgs;
 
 	if (n->sym->type != STRUCT
+	||  in_for
 	||  is_explicit(n))
 		return n;
+
 
 	if (n->rgt
 	&&  n->rgt->ntyp == '.'
--- a/sys/src/cmd/spin/sym.c
+++ b/sys/src/cmd/spin/sym.c
@@ -1,13 +1,10 @@
 /***** spin: sym.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include "y.tab.h"
@@ -14,12 +11,17 @@
 
 extern Symbol	*Fname, *owner;
 extern int	lineno, depth, verbose, NamesNotAdded, deadvar;
+extern int	has_hidden, m_loss, old_scope_rules;
 extern short	has_xu;
+extern char	CurScope[MAXSCOPESZ];
 
 Symbol	*context = ZS;
 Ordered	*all_names = (Ordered *)0;
 int	Nid = 0;
 
+Lextok *Mtype = (Lextok *) 0;
+Lextok *runstmnts = ZN;
+
 static Ordered	*last_name = (Ordered *)0;
 static Symbol	*symtab[Nhash+1];
 
@@ -31,12 +33,12 @@
 	return !strcmp(a->name, b->name);
 }
 
-int
-hash(char *s)
-{	int h=0;
+unsigned int
+hash(const char *s)
+{	unsigned int h = 0;
 
 	while (*s)
-	{	h += *s++;
+	{	h += (unsigned int) *s++;
 		h <<= 1;
 		if (h&(Nhash+1))
 			h |= 1;
@@ -44,31 +46,89 @@
 	return h&Nhash;
 }
 
+void
+disambiguate(void)
+{	Ordered *walk;
+	Symbol *sp;
+	char *n, *m;
+
+	if (old_scope_rules)
+		return;
+
+	/* prepend the scope_prefix to the names */
+
+	for (walk = all_names; walk; walk = walk->next)
+	{	sp = walk->entry;
+		if (sp->type != 0
+		&&  sp->type != LABEL
+		&&  strlen((const char *)sp->bscp) > 1)
+		{	if (sp->context)
+			{	m = (char *) emalloc(strlen((const char *)sp->bscp) + 1);
+				sprintf(m, "_%d_", sp->context->sc);
+				if (strcmp((const char *) m, (const char *) sp->bscp) == 0)
+				{	continue;
+				/* 6.2.0: only prepend scope for inner-blocks,
+				   not for top-level locals within a proctype
+				   this means that you can no longer use the same name
+				   for a global and a (top-level) local variable
+				 */
+			}	}
+
+			n = (char *) emalloc(strlen((const char *)sp->name)
+				+ strlen((const char *)sp->bscp) + 1);
+			sprintf(n, "%s%s", sp->bscp, sp->name);
+			sp->name = n;	/* discard the old memory */
+	}	}
+}
+
 Symbol *
 lookup(char *s)
 {	Symbol *sp; Ordered *no;
-	int h = hash(s);
+	unsigned int h = hash(s);
 
-	for (sp = symtab[h]; sp; sp = sp->next)
-		if (strcmp(sp->name, s) == 0
-		&&  samename(sp->context, context)
-		&&  samename(sp->owner, owner))
-			return sp;		/* found */
+	if (old_scope_rules)
+	{	/* same scope - global refering to global or local to local */
+		for (sp = symtab[h]; sp; sp = sp->next)
+		{	if (strcmp(sp->name, s) == 0
+			&&  samename(sp->context, context)
+			&&  samename(sp->owner, owner))
+			{	return sp;		/* found */
+		}	}
+	} else
+	{	/* added 6.0.0: more traditional, scope rule */
+		for (sp = symtab[h]; sp; sp = sp->next)
+		{	if (strcmp(sp->name, s) == 0
+			&&  samename(sp->context, context)
+			&&  (strcmp((const char *)sp->bscp, CurScope) == 0
+			||   strncmp((const char *)sp->bscp, CurScope, strlen((const char *)sp->bscp)) == 0)
+			&&  samename(sp->owner, owner))
+			{
+				if (!samename(sp->owner, owner))
+				{	printf("spin: different container %s\n", sp->name);
+					printf("	old: %s\n", sp->owner?sp->owner->name:"--");
+					printf("	new: %s\n", owner?owner->name:"--");
+				/*	alldone(1);	*/
+				}
+				return sp;		/* found */
+	}	}	}
 
-	if (context)				/* in proctype */
+	if (context)				/* in proctype, refers to global */
 	for (sp = symtab[h]; sp; sp = sp->next)
-		if (strcmp(sp->name, s) == 0
+	{	if (strcmp(sp->name, s) == 0
 		&& !sp->context
 		&&  samename(sp->owner, owner))
-			return sp;		/* global */
+		{	return sp;		/* global */
+	}	}
 
 	sp = (Symbol *) emalloc(sizeof(Symbol));
-	sp->name = (char *) emalloc((int) strlen(s) + 1);
+	sp->name = (char *) emalloc(strlen(s) + 1);
 	strcpy(sp->name, s);
 	sp->nel = 1;
 	sp->setat = depth;
 	sp->context = context;
 	sp->owner = owner;			/* if fld in struct */
+	sp->bscp = (unsigned char *) emalloc(strlen((const char *)CurScope)+1);
+	strcpy((char *)sp->bscp, CurScope);
 
 	if (NamesNotAdded == 0)
 	{	sp->next = symtab[h];
@@ -109,8 +169,6 @@
 	}
 }
 
-Lextok *runstmnts = ZN;
-
 void
 trackrun(Lextok *n)
 {
@@ -151,11 +209,11 @@
 		strcpy(buf2, (!(res&4))?"bit":"byte");
 		sputtype(buf, parnm->type);
 		i = (int) strlen(buf);
-		while (buf[--i] == ' ') buf[i] = '\0';
-		if (strcmp(buf, buf2) == 0) return;
+		while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
+		if (i == 0 || strcmp(buf, buf2) == 0) return;
 		prehint(parnm);
 		printf("proctype %s, '%s %s' could be declared",
-			parnm->context->name, buf, parnm->name);
+			parnm->context?parnm->context->name:"", buf, parnm->name);
 		printf(" '%s %s'\n", buf2, parnm->name);
 	}
 }
@@ -178,9 +236,9 @@
 
 	while (n)
 	{	if (n->sym->type && !(n->sym->hidden&32))
-		{ lineno = n->ln; Fname = n->fn;
-		  non_fatal("redeclaration of '%s'", n->sym->name);
-		  lineno = oln;
+		{	lineno = n->ln; Fname = n->fn;
+			fatal("redeclaration of '%s'", n->sym->name);
+			lineno = oln;
 		}
 		n->sym->type = (short) t;
 
@@ -201,14 +259,15 @@
 				n->sym->name);
 		}
 		if (vis)
-		{	if (strncmp(vis->sym->name, ":hide:", 6) == 0)
+		{	if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
 			{	n->sym->hidden |= 1;
+				has_hidden++;
 				if (t == BIT)
 				fatal("bit variable (%s) cannot be hidden",
 					n->sym->name);
-			} else if (strncmp(vis->sym->name, ":show:", 6) == 0)
+			} else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
 			{	n->sym->hidden |= 2;
-			} else if (strncmp(vis->sym->name, ":local:", 7) == 0)
+			} else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
 			{	n->sym->hidden |= 64;
 			}
 		}
@@ -268,7 +327,13 @@
 setxus(Lextok *p, int t)
 {	Lextok *m, *n;
 
-	has_xu = 1; 
+	has_xu = 1;
+
+	if (m_loss && t == XS)
+	{	printf("spin: %s:%d, warning, xs tag not compatible with -m (message loss)\n",
+			(p->fn != NULL) ? p->fn->name : "stdin", p->ln);
+	}
+
 	if (!context)
 	{	lineno = p->ln;
 		Fname = p->fn;
@@ -276,6 +341,7 @@
 	}
 	for (m = p; m; m = m->rgt)
 	{	Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok));
+		Xu_new->uiid = p->uiid;
 		Xu_new->val = t;
 		Xu_new->lft = m->lft;
 		Xu_new->sym = context;
@@ -297,8 +363,6 @@
 	}
 }
 
-Lextok *Mtype = (Lextok *) 0;
-
 void
 setmtype(Lextok *m)
 {	Lextok *n;
@@ -332,7 +396,7 @@
 	}
 	lineno = oln;
 	if (cnt > 256)
-	fatal("too many mtype elements (>255)", (char *)0);
+		fatal("too many mtype elements (>255)", (char *)0);
 }
 
 int
@@ -389,11 +453,11 @@
 	printf("\t");
 	if (sp->owner) printf("%s.", sp->owner->name);
 	printf("%s", sp->name);
-	if (sp->nel > 1) printf("[%d]", sp->nel);
+	if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
 
 	if (sp->type == CHAN)
 		printf("\t%d", (sp->ini)?sp->ini->val:0);
-	else if (sp->type == STRUCT) /* Frank Weil, 2.9.8 */
+	else if (sp->type == STRUCT && sp->Snm != NULL) /* Frank Weil, 2.9.8 */
 		printf("\t%s", sp->Snm->name);
 	else
 		printf("\t%d", eval(sp->ini));
@@ -408,8 +472,13 @@
 
 	if (sp->Nid < 0)	/* formal parameter */
 		printf("\t<parameter %d>", -(sp->Nid));
+	else if (sp->type == MTYPE)
+		printf("\t<constant>");
+	else if (sp->isarray)
+		printf("\t<array>");
 	else
 		printf("\t<variable>");
+
 	if (sp->type == CHAN && sp->ini)
 	{	int i;
 		for (m = sp->ini->rgt, i = 0; m; m = m->rgt)
@@ -423,6 +492,11 @@
 			if (m->rgt) printf("\t");
 		}
 	}
+
+	if (!old_scope_rules)
+	{	printf("\t{scope %s}", sp->bscp);
+	}
+
 	printf("\n");
 }
 
@@ -440,11 +514,10 @@
 	if (sp->context) printf("%s-", sp->context->name);
 	if (sp->owner) printf("%s.", sp->owner->name);
 	printf("%s", sp->name);
-	if (sp->nel > 1) printf("[%d]", sp->nel);
+	if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
 	printf("\t");
 }
 
-
 static struct X {
 	int typ; char *nm;
 } xx[] = {
@@ -521,7 +594,7 @@
 
 			if (!(verbose&32) || has_code) continue;
 
-			printf("spin: warning, %s, ", Fname->name);
+			printf("spin: %s:0, warning, ", Fname->name);
 			sputtype(buf, walk->entry->type);
 			if (walk->entry->context)
 				printf("proctype %s",
@@ -528,7 +601,7 @@
 					walk->entry->context->name);
 			else
 				printf("global");
-			printf(", '%s%s' variable is never used\n",
+			printf(", '%s%s' variable is never used (other than in print stmnts)\n",
 				buf, walk->entry->name);
 	}	}
 }
--- a/sys/src/cmd/spin/tl.h
+++ b/sys/src/cmd/spin/tl.h
@@ -1,17 +1,14 @@
 /***** tl_spin: tl.h *****/
 
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
 
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-
 #include <stdio.h>
 #include <string.h>
 
@@ -66,6 +63,7 @@
 #ifdef NXT
 	, NEXT		/* 269 */
 #endif
+	, CEXPR		/* 270 */
 };
 
 Node	*Canonical(Node *);
@@ -82,11 +80,12 @@
 Symbol	*getsym(Symbol *);
 Symbol	*DoDump(Node *);
 
-char	*emalloc(int);	/* in main.c */
+extern char	*emalloc(size_t);	/* in main.c */
 
+extern unsigned int	hash(const char *);	/* in sym.c */
+
 int	anywhere(int, Node *, Node *);
 int	dump_cond(Node *, Node *, int);
-int	hash(char *);	/* in sym.c */
 int	isalnum_(int);	/* in spinlex.c */
 int	isequal(Node *, Node *);
 int	tl_Getchar(void);
@@ -100,6 +99,10 @@
 void	Fatal(char *, char *);
 void	fatal(char *, char *);
 void	fsm_print(void);
+void	ini_buchi(void);
+void	ini_cache(void);
+void	ini_rewrt(void);
+void	ini_trans(void);
 void	releasenode(int, Node *);
 void	tfree(void *);
 void	tl_explain(int);
--- a/sys/src/cmd/spin/tl_buchi.c
+++ b/sys/src/cmd/spin/tl_buchi.c
@@ -1,20 +1,18 @@
 /***** tl_spin: tl_buchi.c *****/
 
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
 
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-
 #include "tl.h"
 
 extern int tl_verbose, tl_clutter, Total, Max_Red;
+extern char *claim_name;
 
 FILE	*tl_out;	/* if standalone: = stdout; */
 
@@ -38,6 +36,13 @@
 static State *never = (State *) 0;
 static int hitsall;
 
+void
+ini_buchi(void)
+{
+	never = (State *) 0;
+	hitsall = 0;
+}
+
 static int
 sametrans(Transition *s, Transition *t)
 {
@@ -58,6 +63,7 @@
 #ifdef NXT
 	case NEXT:
 #endif
+	case CEXPR:
 		return p;
 	case OR:
 		p->lft = Prune(p->lft);
@@ -545,10 +551,22 @@
 	rev_trans(t->nxt);
 
 	if (t->redundant && !tl_verbose) return;
-	fprintf(tl_out, "\t:: (");
-	if (dump_cond(t->cond, t->cond, 1))
-		fprintf(tl_out, "1");
-	fprintf(tl_out, ") -> goto %s\n", t->name->name);
+
+	if (strcmp(t->name->name, "accept_all") == 0)	/* 6.2.4 */
+	{	/* not d_step because there may be remote refs */
+		fprintf(tl_out, "\t:: atomic { (");
+		if (dump_cond(t->cond, t->cond, 1))
+			fprintf(tl_out, "1");
+		fprintf(tl_out, ") -> assert(!(");
+		if (dump_cond(t->cond, t->cond, 1))
+			fprintf(tl_out, "1");
+		fprintf(tl_out, ")) }\n");
+	} else
+	{	fprintf(tl_out, "\t:: (");
+		if (dump_cond(t->cond, t->cond, 1))
+			fprintf(tl_out, "1");
+		fprintf(tl_out, ") -> goto %s\n", t->name->name);
+	}
 	tcnt++;
 }
 
@@ -570,11 +588,11 @@
 	&&  Max_Red == 0)
 		fprintf(tl_out, "T0%s:\n", &(b->name->name[6]));
 
-	fprintf(tl_out, "\tif\n");
+	fprintf(tl_out, "\tdo\n");
 	tcnt = 0;
 	rev_trans(b->trans);
 	if (!tcnt) fprintf(tl_out, "\t:: false\n");
-	fprintf(tl_out, "\tfi;\n");
+	fprintf(tl_out, "\tod;\n");
 	Total++;
 }
 
@@ -626,13 +644,13 @@
 	if (tl_clutter) clutter();
 
 	b = findstate("T0_init");
-	if (Max_Red == 0)
+	if (b && (Max_Red == 0))
 		b->accepting = 1;
 
 	mergestates(0); 
 	b = findstate("T0_init");
 
-	fprintf(tl_out, "never {    /* ");
+	fprintf(tl_out, "never %s {    /* ", claim_name?claim_name:"");
 		put_uform();
 	fprintf(tl_out, " */\n");
 
--- a/sys/src/cmd/spin/tl_cache.c
+++ b/sys/src/cmd/spin/tl_cache.c
@@ -1,17 +1,14 @@
 /***** tl_spin: tl_cache.c *****/
 
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
 
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-
 #include "tl.h"
 
 typedef struct Cache {
@@ -24,10 +21,19 @@
 static Cache	*stored = (Cache *) 0;
 static unsigned long	Caches, CacheHits;
 
-static int	ismatch(Node *, Node *);
+static int ismatch(Node *, Node *);
+static int sameform(Node *, Node *);
+
 extern void fatal(char *, char *);
-int	sameform(Node *, Node *);
 
+void
+ini_cache(void)
+{
+	stored = (Cache *) 0;
+	Caches = 0;
+	CacheHits = 0;
+}
+
 #if 0
 void
 cache_dump(void)
@@ -182,7 +188,7 @@
 	return all_lfts(ntyp, b, a);
 }
 
-int	/* a better isequal() */
+static int	/* a better isequal() */
 sameform(Node *a, Node *b)
 {
 	if (!a && !b) return 1;
@@ -206,6 +212,7 @@
 #ifdef NXT
 	case NEXT:
 #endif
+	case CEXPR:
 		return sameform(a->lft, b->lft);
 	case U_OPER:
 	case V_OPER:
--- a/sys/src/cmd/spin/tl_lex.c
+++ b/sys/src/cmd/spin/tl_lex.c
@@ -1,17 +1,14 @@
 /***** tl_spin: tl_lex.c *****/
 
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
 
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-
 #include <stdlib.h>
 #include <ctype.h>
 #include "tl.h"
@@ -18,6 +15,7 @@
 
 static Symbol	*symtab[Nhash+1];
 static int	tl_lex(void);
+extern int tl_peek(int);
 
 extern YYSTYPE	tl_yylval;
 extern char	yytext[];
@@ -26,11 +24,19 @@
 
 static void
 tl_getword(int first, int (*tst)(int))
-{	int i=0; char c;
+{	int i=0; int c;
 
 	yytext[i++] = (char ) first;
-	while (tst(c = tl_Getchar()))
-		yytext[i++] = c;
+
+	c = tl_Getchar();
+	while (c != -1 && tst(c))
+	{	yytext[i++] = (char) c;
+		c = tl_Getchar();
+	}
+
+/*	while (tst(c = tl_Getchar()))
+ *		yytext[i++] = c;
+ */
 	yytext[i] = '\0';
 	tl_UnGetchar();
 }
@@ -54,12 +60,86 @@
 tl_yylex(void)
 {	int c = tl_lex();
 #if 0
-	printf("c = %d\n", c);
+	printf("c = %c (%d)\n", c, c);
 #endif
 	return c;
 }
 
 static int
+is_predicate(int z)
+{	char c, c_prev = z;
+	char want = (z == '{') ? '}' : ')';
+	int i = 0, j, nesting = 0;
+	char peek_buf[512];
+
+	c = tl_peek(i++);	/* look ahead without changing position */
+	while ((c != want || nesting > 0) && c != -1 && i < 2047)
+	{	if (islower((int) c) || c == '_')
+		{	peek_buf[0] = c;
+			j = 1;
+			while (j < (int) sizeof(peek_buf)
+			&&    (isalnum((int)(c = tl_peek(i))) || c == '_'))
+			{	peek_buf[j++] = c;
+				i++;
+			}
+			c = 0;	/* make sure we don't match on z or want on the peekahead */
+			if (j >= (int) sizeof(peek_buf))
+			{	peek_buf[j-1] = '\0';
+				fatal("name '%s' in ltl formula too long", peek_buf);
+			}
+			peek_buf[j] = '\0';
+			if (strcmp(peek_buf, "always") == 0
+			||  strcmp(peek_buf, "equivalent") == 0
+			||  strcmp(peek_buf, "eventually") == 0
+			||  strcmp(peek_buf, "until") == 0
+			||  strcmp(peek_buf, "next") == 0
+			||  strcmp(peek_buf, "c_expr") == 0)
+			{	return 0;
+			}
+		} else
+		{	int c_nxt = tl_peek(i);
+			if (((c == 'U' || c == 'V' || c == 'X')
+			&& !isalnum_(c_prev)
+			&& (c_nxt == -1 || !isalnum_(c_nxt)))
+			||  (c == '<' && c_nxt == '>')
+			||  (c == '<' && c_nxt == '-')
+			||  (c == '-' && c_nxt == '>')
+			||  (c == '[' && c_nxt == ']'))
+			{	return 0;
+		}	}
+
+		if (c == z)
+		{	nesting++;
+		}
+		if (c == want)
+		{	nesting--;
+		}
+		c_prev = c;
+		c = tl_peek(i++);
+	}
+	return 1;
+}
+
+static void
+read_upto_closing(int z)
+{	char c, want = (z == '{') ? '}' : ')';
+	int i = 0, nesting = 0;
+
+	c = tl_Getchar();
+	while ((c != want || nesting > 0) && c != -1 && i < 2047) /* yytext is 2048 */
+	{	yytext[i++] = c;
+		if (c == z)
+		{	nesting++;
+		}
+		if (c == want)
+		{	nesting--;
+		}
+		c = tl_Getchar();
+	}
+	yytext[i] = '\0';
+}
+
+static int
 tl_lex(void)
 {	int c;
 
@@ -74,6 +154,20 @@
 
 	} while (c == ' ');	/* '\t' is removed in tl_main.c */
 
+	if (c == '{' || c == '(')	/* new 6.0.0 */
+	{	if (is_predicate(c))
+		{	read_upto_closing(c);
+			tl_yylval = tl_nn(PREDICATE,ZN,ZN);
+			if (!tl_yylval)
+			{	fatal("unexpected error 4", (char *) 0);
+			}
+			tl_yylval->sym = tl_lookup(yytext);
+			return PREDICATE;
+	}	}
+
+	if (c == '}')
+	{	tl_yyerror("unexpected '}'");
+	}
 	if (islower(c))
 	{	tl_getword(c, isalnum_);
 		if (strcmp("true", yytext) == 0)
@@ -82,10 +176,34 @@
 		if (strcmp("false", yytext) == 0)
 		{	Token(FALSE);
 		}
+		if (strcmp("always", yytext) == 0)
+		{	Token(ALWAYS);
+		}
+		if (strcmp("eventually", yytext) == 0)
+		{	Token(EVENTUALLY);
+		}
+		if (strcmp("until", yytext) == 0)
+		{	Token(U_OPER);
+		}
+#ifdef NXT
+		if (strcmp("next", yytext) == 0)
+		{	Token(NEXT);
+		}
+#endif
+		if (strcmp("c_expr", yytext) == 0)
+		{	Token(CEXPR);
+		}
+		if (strcmp("not", yytext) == 0)
+		{	Token(NOT);
+		}
 		tl_yylval = tl_nn(PREDICATE,ZN,ZN);
+		if (!tl_yylval)
+		{	fatal("unexpected error 5", (char *) 0);
+		}
 		tl_yylval->sym = tl_lookup(yytext);
 		return PREDICATE;
 	}
+
 	if (c == '<')
 	{	c = tl_Getchar();
 		if (c == '>')
@@ -124,7 +242,7 @@
 Symbol *
 tl_lookup(char *s)
 {	Symbol *sp;
-	int h = hash(s);
+	unsigned int h = hash(s);
 
 	for (sp = symtab[h]; sp; sp = sp->next)
 		if (strcmp(sp->name, s) == 0)
--- a/sys/src/cmd/spin/tl_main.c
+++ b/sys/src/cmd/spin/tl_main.c
@@ -1,17 +1,14 @@
 /***** tl_spin: tl_main.c *****/
 
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
 
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-
 #include "tl.h"
 
 extern FILE	*tl_out;
@@ -21,7 +18,10 @@
 int	tl_verbose = 0;
 int	tl_terse   = 0;
 int	tl_clutter = 0;
+int	state_cnt = 0;
+
 unsigned long	All_Mem = 0;
+char	*claim_name;
 
 static char	uform[4096];
 static int	hasuform=0, cnt=0;
@@ -38,6 +38,15 @@
 	return -1;
 }
 
+int
+tl_peek(int n)
+{
+	if (cnt+n < hasuform)
+	{	return uform[cnt+n];
+	}
+	return -1;
+}
+
 void
 tl_balanced(void)
 {	int i;
@@ -45,10 +54,21 @@
 
 	for (i = 0; i < hasuform; i++)
 	{	if (uform[i] == '(')
-		{	k++;
+		{	if (i > 0
+			&& ((uform[i-1] == '"'  && uform[i+1] == '"')
+			||  (uform[i-1] == '\'' && uform[i+1] == '\'')))
+			{	continue;
+			}
+			k++;
 		} else if (uform[i] == ')')
-		{	k--;
+		{	if (i > 0
+			&& ((uform[i-1] == '"'  && uform[i+1] == '"')
+			||  (uform[i-1] == '\'' && uform[i+1] == '\'')))
+			{	continue;
+			}
+			k--;
 	}	}
+
 	if (k != 0)
 	{	tl_errs++;
 		tl_yyerror("parentheses not balanced");
@@ -79,18 +99,40 @@
 int
 tl_main(int argc, char *argv[])
 {	int i;
-	extern int verbose, xspin;
-	tl_verbose = verbose;
-	tl_clutter = 1-xspin;	/* use -X -f to turn off uncluttering */
+	extern int xspin, s_trail;
 
+	tl_verbose = 0; /* was: tl_verbose = verbose; */
+	if (xspin && s_trail)
+	{	tl_clutter = 1;
+		/* generating claims for a replay should
+		   be done the same as when generating the
+		   pan.c that produced the error-trail */
+	} else
+	{	tl_clutter = 1-xspin;	/* use -X -f to turn off uncluttering */
+	}
+	newstates  = 0;
+	state_cnt  = 0;
+	tl_errs    = 0;
+	tl_terse   = 0;
+	All_Mem = 0;
+	memset(uform, 0, sizeof(uform));
+	hasuform=0;
+	cnt=0;
+	claim_name = (char *) 0;
+
+	ini_buchi();
+	ini_cache();
+	ini_rewrt();
+	ini_trans();
+
 	while (argc > 1 && argv[1][0] == '-')
-	{	switch (argv[1][1]) {
+	{
+		switch (argv[1][1]) {
 		case 'd':	newstates = 1;	/* debugging mode */
 				break;
 		case 'f':	argc--; argv++;
-				for (i = 0; i < argv[1][i]; i++)
+				for (i = 0; argv[1][i]; i++)
 				{	if (argv[1][i] == '\t'
-					||  argv[1][i] == '\"'
 					||  argv[1][i] == '\n')
 						argv[1][i] = ' ';
 				}
@@ -101,6 +143,10 @@
 				break;
 		case 'n':	tl_terse = 1;
 				break;
+		case 'c':	argc--; argv++;
+				claim_name = (char *) emalloc(strlen(argv[1])+1);
+				strcpy(claim_name, argv[1]);
+				break;
 		default :	printf("spin -f: saw '-%c'\n", argv[1][1]);
 				goto nogood;
 		}
@@ -162,6 +208,12 @@
 	case PREDICATE:
 		fprintf(tl_out, "(%s)", n->sym->name);
 		break;
+	case CEXPR:
+		fprintf(tl_out, "c_expr");
+		fprintf(tl_out, " {");
+		dump(n->lft);
+		fprintf(tl_out, "}");
+		break;
 	case -1:
 		fprintf(tl_out, " D ");
 		break;
@@ -189,6 +241,7 @@
 #ifdef NXT
 	case NEXT:	printf("X"); break;
 #endif
+	case CEXPR:	printf("c_expr"); break;
 	case TRUE:	printf("true"); break;
 	case FALSE:	printf("false"); break;
 	case ';':	printf("end of formula"); break;
@@ -202,10 +255,14 @@
 	int i;
 
 	printf("tl_spin: ");
+#if 1
+	printf(s1, s2);	/* prevent a compiler warning */
+#else
 	if (s2)
 		printf(s1, s2);
 	else
 		printf(s1);
+#endif
 	if (tl_yychar != -1 && tl_yychar != 0)
 	{	printf(", saw '");
 		tl_explain(tl_yychar);
--- a/sys/src/cmd/spin/tl_mem.c
+++ b/sys/src/cmd/spin/tl_mem.c
@@ -1,16 +1,13 @@
 /***** tl_spin: tl_mem.c *****/
 
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
-
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
 
 #include "tl.h"
 
--- a/sys/src/cmd/spin/tl_parse.c
+++ b/sys/src/cmd/spin/tl_parse.c
@@ -1,17 +1,14 @@
 /***** tl_spin: tl_parse.c *****/
 
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
 
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-
 #include "tl.h"
 
 extern int	tl_yylex(void);
@@ -44,11 +41,13 @@
 		ptr = tl_yylval;
 		tl_yychar = tl_yylex();
 		ptr->lft = tl_factor();
+		if (!ptr->lft)
+		{	fatal("malformed expression", (char *) 0);
+		}
 		ptr = push_negation(ptr);
 		break;
 	case ALWAYS:
 		tl_yychar = tl_yylex();
-
 		ptr = tl_factor();
 #ifndef NO_OPT
 		if (ptr->ntyp == FALSE
@@ -73,6 +72,14 @@
 		ptr = tl_nn(NEXT, ptr, ZN);
 		break;
 #endif
+	case CEXPR:
+		tl_yychar = tl_yylex();
+		ptr = tl_factor();
+		if (ptr->ntyp != PREDICATE)
+		{	tl_yyerror("expected {...} after c_expr");
+		}
+		ptr = tl_nn(CEXPR, ptr, ZN);
+		break;
 	case EVENTUALLY:
 		tl_yychar = tl_yylex();
 
@@ -385,7 +392,10 @@
 
 void
 tl_parse(void)
-{	Node *n = tl_formula();
+{	Node *n;
+
+	/* tl_verbose = 1; */
+	n = tl_formula();
 	if (tl_verbose)
 	{	printf("formula: ");
 		dump(n);
--- a/sys/src/cmd/spin/tl_rewrt.c
+++ b/sys/src/cmd/spin/tl_rewrt.c
@@ -1,17 +1,14 @@
 /***** tl_spin: tl_rewrt.c *****/
 
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
 
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-
 #include "tl.h"
 
 extern int	tl_verbose;
@@ -18,6 +15,12 @@
 
 static Node	*can = ZN;
 
+void
+ini_rewrt(void)
+{
+	can = ZN;
+}
+
 Node *
 right_linked(Node *n)
 {
@@ -137,6 +140,9 @@
 	}
 
 	s = DoDump(N);
+	if (!s)
+	{	fatal("unexpected error 6", (char *) 0);
+	}
 	if (can->ntyp != tok)	/* only one element in list so far */
 	{	ptr = &can;
 		goto insert;
@@ -146,7 +152,10 @@
 	prev = ZN;
 	for (m = can; m->ntyp == tok && m->rgt; prev = m, m = m->rgt)
 	{	t = DoDump(m->lft);
-		cmp = strcmp(s->name, t->name);
+		if (t != ZS)
+			cmp = strcmp(s->name, t->name);
+		else
+			cmp = 0;
 		if (cmp == 0)	/* duplicate */
 			return;
 		if (cmp < 0)
--- a/sys/src/cmd/spin/tl_trans.c
+++ b/sys/src/cmd/spin/tl_trans.c
@@ -1,21 +1,18 @@
 /***** tl_spin: tl_trans.c *****/
 
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
 
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-
 #include "tl.h"
 
 extern FILE	*tl_out;
-extern int	tl_errs, tl_verbose, tl_terse, newstates;
+extern int	tl_errs, tl_verbose, tl_terse, newstates, state_cnt;
 
 int	Stack_mx=0, Max_Red=0, Total=0;
 
@@ -23,7 +20,7 @@
 static Graph	*Nodes_Set = (Graph *) 0;
 static Graph	*Nodes_Stack = (Graph *) 0;
 
-static char	dumpbuf[2048];
+static char	dumpbuf[4096];
 static int	Red_cnt  = 0;
 static int	Lab_cnt  = 0;
 static int	Base     = 0;
@@ -51,6 +48,24 @@
 static void	push_stack(Graph *);
 static void	sdump(Node *);
 
+void
+ini_trans(void)
+{
+	Stack_mx = 0;
+	Max_Red = 0;
+	Total = 0;
+
+	Mapped = (Mapping *) 0;
+	Nodes_Set = (Graph *) 0;
+	Nodes_Stack = (Graph *) 0;
+
+	memset(dumpbuf, 0, sizeof(dumpbuf));
+	Red_cnt  = 0;
+	Lab_cnt  = 0;
+	Base     = 0;
+	Stack_sz = 0;
+}
+
 static void
 dump_graph(Graph *g)
 {	Node *n1;
@@ -101,9 +116,8 @@
 
 static char *
 newname(void)
-{	static int cnt = 0;
-	static char buf[32];
-	sprintf(buf, "S%d", cnt++);
+{	static char buf[32];
+	sprintf(buf, "S%d", state_cnt++);
 	return buf;
 }
 
@@ -132,6 +146,8 @@
 mk_grn(Node *n)
 {	Graph *p;
 
+	if (!n) return;
+
 	n = right_linked(n);
 more:
 	for (p = Nodes_Set; p; p = p->nxt)
@@ -152,6 +168,8 @@
 mk_red(Node *n)
 {	Graph *p;
 
+	if (!n) return;
+
 	n = right_linked(n);
 	for (p = Nodes_Set; p; p = p->nxt)
 	{	if (p->outgoing
@@ -240,6 +258,15 @@
 	q = dupnode(pp);
 	q = rewrite(q);
 
+	if (q->ntyp == CEXPR)
+	{	if (!frst) fprintf(tl_out, " && ");
+		fprintf(tl_out, "c_expr { ");
+		dump_cond(q->lft, r, 1);
+		fprintf(tl_out, " } ");
+		frst = 0;
+		return frst;
+	}
+
 	if (q->ntyp == PREDICATE
 	||  q->ntyp == NOT
 #ifndef NXT
@@ -342,7 +369,7 @@
 fsm_trans(Graph *p, int count, char *curnm)
 {	Graph	*r;
 	Symbol	*s;
-	char	prefix[128], nwnm[128];
+	char	prefix[128], nwnm[256];
 
 	if (!p->outgoing)
 		addtrans(p, curnm, False, "accept_all");
@@ -452,9 +479,11 @@
 
 	ng(tl_lookup("init"), ZS, ZN, ZN, ZN);
 	p1 = pop_stack();
-	p1->nxt = Nodes_Set;
-	p1->Other = p1->Old = orig;
-	Nodes_Set = p1;
+	if (p1)
+	{	p1->nxt = Nodes_Set;
+		p1->Other = p1->Old = orig;
+		Nodes_Set = p1;
+	}
 
 	for (g = Nodes_Set; g; g = g->nxt)
 	{	for (q1 = g->incoming; q1; q1 = q2)
@@ -532,6 +561,10 @@
 	case NEXT:	strcat(dumpbuf, "X");
 			goto common1;
 #endif
+	case CEXPR:	strcat(dumpbuf, "c_expr {");
+			sdump(n->lft);
+			strcat(dumpbuf, "}");
+			break;
 	case NOT:	strcat(dumpbuf, "!");
 			goto common1;
 	case TRUE:	strcat(dumpbuf, "T");
@@ -718,10 +751,13 @@
 		break;
 	case PREDICATE:
 	case NOT:
+	case CEXPR:
 		if (can_release) releasenode(1, now);
 		push_stack(g);
 		break;
 	case V_OPER:
+		Assert(now->rgt != ZN, now->ntyp);
+		Assert(now->lft != ZN, now->ntyp);
 		Assert(now->rgt->nxt == ZN, now->ntyp);
 		Assert(now->lft->nxt == ZN, now->ntyp);
 		n1 = now->rgt;
@@ -759,6 +795,7 @@
 
 #ifdef NXT
 	case NEXT:
+		Assert(now->lft != ZN, now->ntyp);
 		nx = dupnode(now->lft);
 		nx->nxt = g->Next;
 		g->Next = nx;
--- a/sys/src/cmd/spin/vars.c
+++ b/sys/src/cmd/spin/vars.c
@@ -1,13 +1,10 @@
 /***** spin: vars.c *****/
 
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
-/* All Rights Reserved.  This software is for educational purposes only.  */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code.  Permission is given to distribute this code provided that  */
-/* this introductory message is not removed and no monies are exchanged.  */
-/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
-/*             http://spinroot.com/                                       */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
 
 #include "spin.h"
 #include "y.tab.h"
@@ -17,7 +14,7 @@
 extern Symbol	*Fname;
 extern char	Buf[];
 extern int	lineno, depth, verbose, xspin, limited_vis;
-extern int	analyze, jumpsteps, nproc, nstop, columns;
+extern int	analyze, jumpsteps, nproc, nstop, columns, old_priority_rules;
 extern short	no_arrays, Have_claim;
 extern void	sr_mesg(FILE *, int, int);
 extern void	sr_buf(int, int);
@@ -42,16 +39,29 @@
 	{	if (!X) return 0;
 		return X->pid - Have_claim;
 	}
+	if (strcmp(s->name, "_priority") == 0)
+	{	if (!X) return 0;
+
+		if (old_priority_rules)
+		{	non_fatal("cannot refer to _priority with -o6", (char *) 0);
+			return 1;
+		}
+		return X->priority;
+	}
+
 	if (strcmp(s->name, "_nr_pr") == 0)
-		return nproc-nstop;	/* new 3.3.10 */
+	{	return nproc-nstop;	/* new 3.3.10 */
+	}
 
 	if (s->context && s->type)
-		return getlocal(sn);
+	{	return getlocal(sn);
+	}
 
 	if (!s->type)	/* not declared locally */
 	{	s = lookup(s->name); /* try global */
 		sn->sym = s;	/* fix it */
 	}
+
 	return getglobal(sn);
 }
 
@@ -58,6 +68,25 @@
 int
 setval(Lextok *v, int n)
 {
+	if (strcmp(v->sym->name, "_last") == 0
+	||  strcmp(v->sym->name, "_p") == 0
+	||  strcmp(v->sym->name, "_pid") == 0
+	||  strcmp(v->sym->name, "_nr_qs") == 0
+	||  strcmp(v->sym->name, "_nr_pr") == 0)
+	{	non_fatal("illegal assignment to %s", v->sym->name);
+	}
+	if (strcmp(v->sym->name, "_priority") == 0)
+	{	if (old_priority_rules)
+		{	non_fatal("cannot refer to _priority with -o6", (char *) 0);
+			return 1;
+		}
+		if (!X)
+		{	non_fatal("no context for _priority", (char *) 0);
+			return 1;
+		}
+		X->priority = n;
+	}
+
 	if (v->sym->context && v->sym->type)
 		return setlocal(v, n);
 	if (!v->sym->type)
@@ -90,6 +119,7 @@
 checkvar(Symbol *s, int n)
 {	int	i, oln = lineno;	/* calls on eval() change it */
 	Symbol	*ofnm = Fname;
+	Lextok  *z, *y;
 
 	if (!in_bound(s, n))
 		return 0;
@@ -101,15 +131,23 @@
 	/* not a STRUCT */
 	if (s->val == (int *) 0)	/* uninitialized */
 	{	s->val = (int *) emalloc(s->nel*sizeof(int));
+		z = s->ini;
 		for (i = 0; i < s->nel; i++)
-		{	if (s->type != CHAN)
-			{	rm_selfrefs(s, s->ini);
-				s->val[i] = eval(s->ini);
+		{	if (z && z->ntyp == ',')
+			{	y = z->lft;
+				z = z->rgt;
+			} else
+			{	y = z;
+			}
+			if (s->type != CHAN)
+			{	rm_selfrefs(s, y);
+				s->val[i] = eval(y);
 			} else if (!analyze)
-				s->val[i] = qmake(s);
-	}	}
+			{	s->val[i] = qmake(s);
+	}	}	}
 	lineno = oln;
 	Fname  = ofnm;
+
 	return 1;
 }
 
@@ -118,14 +156,16 @@
 {	Symbol *s = sn->sym;
 	int i, n = eval(sn->lft);
 
-	if (s->type == 0 && X && (i = find_lab(s, X->n, 0)))
+	if (s->type == 0 && X && (i = find_lab(s, X->n, 0)))	/* getglobal */
 	{	printf("findlab through getglobal on %s\n", s->name);
 		return i;	/* can this happen? */
 	}
 	if (s->type == STRUCT)
-		return Rval_struct(sn, s, 1); /* 1 = check init */
+	{	return Rval_struct(sn, s, 1); /* 1 = check init */
+	}
 	if (checkvar(s, n))
-		return cast_val(s->type, s->val[n], s->nbits);
+	{	return cast_val(s->type, s->val[n], s->nbits);
+	}
 	return 0;
 }
 
@@ -145,10 +185,10 @@
 	}
 
 	if (v != i+s+ (int) u)
-	{	char buf[32]; sprintf(buf, "%d->%d (%d)", v, i+s+u, t);
+	{	char buf[64]; sprintf(buf, "%d->%d (%d)", v, i+s+(int)u, t);
 		non_fatal("value (%s) truncated in assignment", buf);
 	}
-	return (int)(i+s+u);
+	return (int)(i+s+(int)u);
 }
 
 static int
@@ -155,13 +195,16 @@
 setglobal(Lextok *v, int m)
 {
 	if (v->sym->type == STRUCT)
-		(void) Lval_struct(v, v->sym, 1, m);
-	else
+	{	(void) Lval_struct(v, v->sym, 1, m);
+	} else
 	{	int n = eval(v->lft);
 		if (checkvar(v->sym, n))
-		{	v->sym->val[n] = cast_val(v->sym->type, m, v->sym->nbits);
-			v->sym->setat = depth;
-	}	}
+		{	int oval = v->sym->val[n];
+			int nval = cast_val(v->sym->type, m, v->sym->nbits);
+			v->sym->val[n] = nval;
+			if (oval != nval)
+			{	v->sym->setat = depth;
+	}	}	}
 	return 1;
 }
 
@@ -215,7 +258,12 @@
 			continue;
 
 		if (sp->type == STRUCT)
-		{	dump_struct(sp, sp->name, 0);
+		{	if ((verbose&4) && !(verbose&64)
+			&&  (sp->setat < depth
+			&&   jumpsteps != depth))
+			{	continue;
+			}
+			dump_struct(sp, sp->name, 0);
 			continue;
 		}
 		for (j = 0; j < sp->nel; j++)
@@ -227,13 +275,15 @@
 			if ((verbose&4) && !(verbose&64)
 			&&  (sp->setat < depth
 			&&   jumpsteps != depth))
-				continue;
+			{	continue;
+			}
+
 			dummy->sym = sp;
 			dummy->lft->val = j;
 			/* in case of cast_val warnings, do this first: */
 			prefetch = getglobal(dummy);
 			printf("\t\t%s", sp->name);
-			if (sp->nel > 1) printf("[%d]", j);
+			if (sp->nel > 1 || sp->isarray) printf("[%d]", j);
 			printf(" = ");
 			sr_mesg(stdout, prefetch,
 				sp->type == MTYPE);
@@ -249,7 +299,7 @@
 				}
 				sr_buf(prefetch, sp->type == MTYPE);
 				if (sp->colnr == 0)
-				{	sp->colnr = maxcolnr;
+				{	sp->colnr = (unsigned char) maxcolnr;
 					maxcolnr = 1+(maxcolnr%10);
 				}
 				colpos = nproc+sp->colnr-1;
@@ -266,7 +316,7 @@
 					depth, colpos);
 				printf("(state 0)\t[printf('MSC: globvar\\\\n')]\n");
 				printf("\t\t%s", sp->name);
-				if (sp->nel > 1) printf("[%d]", j);
+				if (sp->nel > 1 || sp->isarray) printf("[%d]", j);
 				printf(" = %s\n", Buf);
 	}	}	}
 }
@@ -303,8 +353,8 @@
 			dummy->lft->val = i;
 
 			printf("\t\t%s(%d):%s",
-				r->n->name, r->pid, z->name);
-			if (z->nel > 1) printf("[%d]", i);
+				r->n->name, r->pid - Have_claim, z->name);
+			if (z->nel > 1 || z->isarray) printf("[%d]", i);
 			printf(" = ");
 			sr_mesg(stdout, getval(dummy), z->type == MTYPE);
 			printf("\n");
@@ -321,7 +371,7 @@
 				}
 				sr_buf(getval(dummy), z->type==MTYPE);
 				if (z->colnr == 0)
-				{	z->colnr = maxcolnr;
+				{	z->colnr = (unsigned char) maxcolnr;
 					maxcolnr = 1+(maxcolnr%10);
 				}
 				colpos = nproc+z->colnr-1;
@@ -341,7 +391,7 @@
 				printf("(state 0)\t[printf('MSC: locvar\\\\n')]\n");
 				printf("\t\t%s(%d):%s",
 					r->n->name, r->pid, z->name);
-				if (z->nel > 1) printf("[%d]", i);
+				if (z->nel > 1 || z->isarray) printf("[%d]", i);
 				printf(" = %s\n", Buf);
 	}	}	}
 }
--- a/sys/src/cmd/spin/version.h
+++ b/sys/src/cmd/spin/version.h
@@ -1,1 +1,9 @@
-#define Version	"Spin Version 4.3.0 -- 22 June 2007"
+/***** spin: version.h *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+#define SpinVersion	"Spin Version 6.4.7 -- 19 August 2017"